From 46e398b69c0f68ade36b2a3e224a9ce3908eb26e Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Wed, 3 Mar 2021 15:15:59 +0900 Subject: [PATCH] Imported Upstream version 2.11.0 --- Documentation/RelNotes/2.10.3.txt | 55 - Documentation/RelNotes/2.10.4.txt | 4 - Documentation/RelNotes/2.10.5.txt | 17 - Documentation/RelNotes/2.11.0.txt | 593 ++ Documentation/RelNotes/2.4.12.txt | 12 - Documentation/RelNotes/2.5.6.txt | 12 - Documentation/RelNotes/2.6.7.txt | 12 - Documentation/RelNotes/2.7.5.txt | 14 - Documentation/RelNotes/2.7.6.txt | 25 - Documentation/RelNotes/2.8.5.txt | 12 - Documentation/RelNotes/2.8.6.txt | 4 - Documentation/RelNotes/2.9.4.txt | 7 - Documentation/RelNotes/2.9.5.txt | 4 - Documentation/blame-options.txt | 5 +- Documentation/config.txt | 32 + Documentation/diff-config.txt | 22 +- Documentation/diff-heuristic-options.txt | 7 + Documentation/diff-options.txt | 37 +- Documentation/fetch-options.txt | 14 + Documentation/git-annotate.txt | 1 + Documentation/git-blame.txt | 4 +- Documentation/git-cat-file.txt | 40 +- Documentation/git-clone.txt | 13 +- Documentation/git-count-objects.txt | 5 + Documentation/git-fetch-pack.txt | 14 + Documentation/git-format-patch.txt | 8 +- Documentation/git-index-pack.txt | 2 + Documentation/git-interpret-trailers.txt | 15 +- Documentation/git-ls-files.txt | 7 +- Documentation/git-mergetool.txt | 7 + Documentation/git-receive-pack.txt | 3 + Documentation/git-shell.txt | 16 - Documentation/git-stash.txt | 3 +- Documentation/git-status.txt | 133 +- Documentation/git-unpack-objects.txt | 3 + Documentation/git.txt | 33 +- Documentation/gitattributes.txt | 157 +- Documentation/gitremote-helpers.txt | 11 + Documentation/gitweb.conf.txt | 21 +- Documentation/pretty-formats.txt | 10 +- Documentation/revisions.txt | 17 +- Documentation/technical/api-sha1-array.txt | 8 +- Documentation/technical/pack-protocol.txt | 4 +- Documentation/technical/protocol-capabilities.txt | 25 + GIT-VERSION-GEN | 2 +- Makefile | 5 +- RelNotes | 2 +- apply.c | 4988 ++++++++++ apply.h | 137 + archive.c | 8 +- archive.h | 2 +- attr.c | 6 +- bisect.c | 2 +- builtin.h | 2 +- builtin/am.c | 205 +- builtin/apply.c | 4873 +--------- builtin/archive.c | 10 +- builtin/blame.c | 148 +- builtin/branch.c | 2 +- builtin/cat-file.c | 178 +- builtin/checkout-index.c | 2 +- builtin/checkout.c | 73 +- builtin/clone.c | 137 +- builtin/commit-tree.c | 20 +- builtin/commit.c | 93 +- builtin/config.c | 4 +- builtin/count-objects.c | 12 + builtin/describe.c | 2 +- builtin/diff.c | 27 +- builtin/fast-export.c | 2 +- builtin/fetch-pack.c | 27 +- builtin/fetch.c | 84 +- builtin/fmt-merge-msg.c | 12 +- builtin/fsck.c | 14 +- builtin/grep.c | 3 +- builtin/hash-object.c | 13 +- builtin/help.c | 30 +- builtin/index-pack.c | 16 +- builtin/init-db.c | 109 +- builtin/log.c | 62 +- builtin/ls-files.c | 181 +- builtin/mailinfo.c | 19 +- builtin/merge-index.c | 2 +- builtin/merge-recursive.c | 19 +- builtin/merge.c | 11 +- builtin/mktree.c | 2 +- builtin/name-rev.c | 3 +- builtin/notes.c | 66 +- builtin/pack-objects.c | 229 +- builtin/pull.c | 71 +- builtin/read-tree.c | 2 +- builtin/receive-pack.c | 134 +- builtin/remote-ext.c | 4 +- builtin/remote.c | 3 +- builtin/reset.c | 52 +- builtin/rev-list.c | 74 +- builtin/rev-parse.c | 59 +- builtin/revert.c | 46 +- builtin/rm.c | 18 +- builtin/shortlog.c | 2 +- builtin/show-branch.c | 36 +- builtin/stripspace.c | 4 +- builtin/submodule--helper.c | 156 +- builtin/unpack-objects.c | 7 + builtin/update-index.c | 79 +- builtin/upload-archive.c | 6 +- cache-tree.c | 4 +- cache.h | 131 +- combine-diff.c | 6 +- commit.c | 8 +- commit.h | 2 + config.c | 8 +- connect.c | 53 +- connected.c | 1 + connected.h | 5 + contrib/coccinelle/qsort.cocci | 37 + contrib/credential/libsecret/Makefile | 25 + .../libsecret/git-credential-libsecret.c | 370 + contrib/long-running-filter/example.pl | 128 + convert.c | 388 +- credential-cache--daemon.c | 6 +- daemon.c | 2 +- diff-lib.c | 49 +- diff-no-index.c | 3 + diff.c | 267 +- diff.h | 21 +- diffcore-delta.c | 5 +- diffcore-order.c | 2 +- diffcore-rename.c | 2 +- dir.c | 69 +- dir.h | 4 + entry.c | 9 +- environment.c | 28 +- fast-import.c | 4 +- fetch-pack.c | 171 +- fetch-pack.h | 4 + fsck.c | 18 +- git-add--interactive.perl | 5 +- git-archimport.perl | 4 +- git-compat-util.h | 11 + git-cvsimport.perl | 1 - git-cvsserver.perl | 77 +- git-gui/GIT-VERSION-GEN | 2 +- git-gui/Makefile | 2 +- git-gui/git-gui.sh | 154 +- git-gui/lib/blame.tcl | 2 +- git-gui/lib/branch_checkout.tcl | 2 +- git-gui/lib/branch_create.tcl | 2 +- git-gui/lib/branch_delete.tcl | 4 +- git-gui/lib/branch_rename.tcl | 2 +- git-gui/lib/browser.tcl | 6 +- git-gui/lib/commit.tcl | 36 +- git-gui/lib/database.tcl | 4 +- git-gui/lib/diff.tcl | 14 +- git-gui/lib/error.tcl | 8 +- git-gui/lib/index.tcl | 12 +- git-gui/lib/merge.tcl | 13 +- git-gui/lib/option.tcl | 8 +- git-gui/lib/remote.tcl | 8 +- git-gui/lib/remote_add.tcl | 2 +- git-gui/lib/remote_branch_delete.tcl | 2 +- git-gui/lib/shortcut.tcl | 17 +- git-gui/lib/themed.tcl | 87 +- git-gui/lib/tools.tcl | 3 + git-gui/lib/tools_dlg.tcl | 6 +- git-gui/lib/transport.tcl | 2 +- git-gui/po/bg.po | 3543 ++++---- git-gui/po/glossary/pt_pt.po | 293 + git-gui/po/pt_pt.po | 2716 ++++++ git-gui/po/ru.po | 680 +- git-mergetool.sh | 184 +- git-rebase--interactive.sh | 13 +- git-stash.sh | 21 +- git-submodule.sh | 7 +- git-svn.perl | 13 +- git.c | 48 +- gitweb/gitweb.perl | 34 +- gpg-interface.c | 13 +- graph.c | 100 +- graph.h | 22 +- help.c | 15 +- http-backend.c | 2 +- http.c | 37 + ident.c | 32 +- line-log.c | 2 +- log-tree.c | 5 +- mailinfo.c | 116 +- mailinfo.h | 1 + merge-recursive.c | 8 +- merge.c | 9 +- notes-merge.c | 135 +- notes.c | 12 +- object.h | 2 +- pack-bitmap-write.c | 3 +- pack-bitmap.c | 2 +- pack-check.c | 2 +- pack-objects.h | 9 + pack-write.c | 3 +- pager.c | 93 +- parse-options-cb.c | 12 + parse-options.h | 1 + path.c | 44 +- pathspec.c | 14 +- perl/Git.pm | 16 +- perl/Git/SVN.pm | 36 +- perl/Git/SVN/Editor.pm | 12 +- perl/Git/SVN/Fetcher.pm | 15 +- perl/Git/SVN/Migration.pm | 37 +- pkt-line.c | 152 +- pkt-line.h | 12 +- po/ca.po | 8907 ++++++++++-------- po/de.po | 9112 ++++++++++--------- po/fr.po | 8916 ++++++++++-------- po/git.pot | 6732 ++++++++------ po/ko.po | 8729 ++++++++++-------- po/pt_PT.po | 8794 ++++++++++-------- po/ru.po | 9575 ++++++++++++-------- po/sv.po | 8709 ++++++++++-------- po/vi.po | 8697 ++++++++++-------- po/zh_CN.po | 8689 ++++++++++-------- pretty.c | 4 + read-cache.c | 33 +- ref-filter.c | 4 +- refs.c | 325 +- refs.h | 17 +- refs/files-backend.c | 574 +- refs/refs-internal.h | 220 +- remote-curl.c | 80 +- rerere.c | 3 +- resolve-undo.c | 2 +- revision.c | 36 +- run-command.c | 39 +- run-command.h | 4 +- sequencer.c | 797 +- sequencer.h | 23 +- server-info.c | 2 +- sh-i18n--envsubst.c | 3 +- sha1-array.c | 10 +- sha1-array.h | 8 +- sha1_file.c | 513 +- sha1_name.c | 275 +- shallow.c | 80 +- shell.c | 16 +- split-index.c | 2 +- strbuf.c | 20 + strbuf.h | 8 + streaming.c | 6 +- streaming.h | 2 +- string-list.c | 2 +- submodule.c | 216 +- submodule.h | 8 +- t/helper/test-config.c | 3 + t/helper/test-dump-cache-tree.c | 1 + t/helper/test-dump-split-index.c | 2 +- t/helper/test-dump-untracked-cache.c | 6 +- t/helper/test-scrap-cache-tree.c | 1 + t/helper/test-sha1-array.c | 3 +- t/perf/p0003-delta-base-cache.sh | 31 + t/perf/p5310-pack-bitmaps.sh | 14 +- t/t0001-init.sh | 26 + t/t0012-help.sh | 52 + t/t0020-crlf.sh | 6 +- t/t0021-conversion.sh | 504 +- t/t0021/rot13-filter.pl | 192 + t/t0030-stripspace.sh | 9 + t/t0060-path-utils.sh | 29 +- t/t1007-hash-object.sh | 68 +- t/t1301-shared-repo.sh | 41 + t/t1302-repo-version.sh | 32 +- t/t1450-fsck.sh | 16 +- t/t1512-rev-parse-disambiguation.sh | 72 +- t/t2203-add-intent.sh | 41 +- t/t3007-ls-files-recurse-submodules.sh | 210 + t/t3310-notes-merge-manual-resolve.sh | 2 +- t/t3320-notes-merge-worktrees.sh | 2 +- t/t3404-rebase-interactive.sh | 11 + t/t3501-revert-cherry-pick.sh | 2 +- t/t3600-rm.sh | 5 + t/t3700-add.sh | 5 + t/t3900-i18n-commit.sh | 8 +- t/t3901-i18n-patch.sh | 2 +- t/t3903-stash.sh | 35 + t/t4012-diff-binary.sh | 4 +- t/t4013-diff-various.sh | 6 + ...diff.diff_--line-prefix=abc_master_master^_side | 29 + t/t4013/diff.diff_--line-prefix_--cached_--_file0 | 15 + t/t4014-format-patch.sh | 9 + t/t4015-diff-whitespace.sh | 74 +- t/t4021-format-patch-numbered.sh | 17 + t/t4053-diff-no-index.sh | 38 + t/t4059-diff-submodule-not-initialized.sh | 127 + t/t4060-diff-submodule-option-diff-format.sh | 749 ++ t/t4061-diff-indent.sh | 216 + t/t4150-am.sh | 23 + t/t4202-log.sh | 323 + t/t4204-patch-id.sh | 14 + t/t4254-am-corrupt.sh | 4 +- t/t5000-tar-tree.sh | 35 +- t/t5100-mailinfo.sh | 15 +- t/t5100/info0018 | 5 + t/t5100/info0018--no-inbody-headers | 5 + t/t5100/msg0015 | 2 - t/t5100/msg0018 | 2 + t/t5100/msg0018--no-inbody-headers | 8 + t/t5100/patch0018 | 6 + t/t5100/patch0018--no-inbody-headers | 6 + t/t5100/sample.mbox | 19 + t/t5310-pack-bitmaps.sh | 108 +- t/t5314-pack-cycle-detection.sh | 113 + t/t5500-fetch-pack.sh | 68 + t/t5512-ls-remote.sh | 42 +- t/t5532-fetch-proxy.sh | 5 - t/t5539-fetch-http-shallow.sh | 73 + t/t5546-receive-limits.sh | 55 + t/t5547-push-quarantine.sh | 36 + t/t5613-info-alternate.sh | 205 +- t/t5615-alternate-env.sh | 71 + t/t5810-proto-disable-local.sh | 23 - t/t5813-proto-disable-ssh.sh | 23 - t/t6000-rev-list-misc.sh | 14 + t/t6101-rev-parse-parents.sh | 94 + t/t6300-for-each-ref.sh | 10 + t/t7060-wtstatus.sh | 21 + t/t7064-wtstatus-pv2.sh | 593 ++ t/t7408-submodule-reference.sh | 185 +- t/t7510-signed-commit.sh | 13 +- t/t7513-interpret-trailers.sh | 299 + t/t7610-mergetool.sh | 60 + t/t8003-blame-corner-cases.sh | 4 +- t/t8010-cat-file-filters.sh | 64 + t/t9400-git-cvsserver-server.sh | 48 - t/t9500-gitweb-standalone-no-errors.sh | 8 + t/test-lib-functions.sh | 4 + t/test-lib.sh | 4 + tmp-objdir.c | 275 + tmp-objdir.h | 54 + trailer.c | 620 +- transport-helper.c | 62 +- transport.c | 100 +- transport.h | 17 +- tree-walk.c | 83 +- tree-walk.h | 8 + tree.c | 5 +- unpack-trees.c | 12 +- upload-pack.c | 403 +- usage.c | 15 + write_or_die.c | 13 - wt-status.c | 653 +- wt-status.h | 25 +- xdiff-interface.c | 8 +- xdiff-interface.h | 3 +- xdiff/xdiff.h | 1 + xdiff/xdiffi.c | 635 +- 353 files changed, 73767 insertions(+), 49739 deletions(-) delete mode 100644 Documentation/RelNotes/2.10.3.txt delete mode 100644 Documentation/RelNotes/2.10.4.txt delete mode 100644 Documentation/RelNotes/2.10.5.txt create mode 100644 Documentation/RelNotes/2.11.0.txt delete mode 100644 Documentation/RelNotes/2.4.12.txt delete mode 100644 Documentation/RelNotes/2.5.6.txt delete mode 100644 Documentation/RelNotes/2.6.7.txt delete mode 100644 Documentation/RelNotes/2.7.5.txt delete mode 100644 Documentation/RelNotes/2.7.6.txt delete mode 100644 Documentation/RelNotes/2.8.5.txt delete mode 100644 Documentation/RelNotes/2.8.6.txt delete mode 100644 Documentation/RelNotes/2.9.5.txt create mode 100644 Documentation/diff-heuristic-options.txt create mode 100644 apply.c create mode 100644 apply.h create mode 100644 contrib/coccinelle/qsort.cocci create mode 100644 contrib/credential/libsecret/Makefile create mode 100644 contrib/credential/libsecret/git-credential-libsecret.c create mode 100755 contrib/long-running-filter/example.pl create mode 100644 git-gui/po/glossary/pt_pt.po create mode 100644 git-gui/po/pt_pt.po create mode 100755 t/perf/p0003-delta-base-cache.sh create mode 100755 t/t0012-help.sh create mode 100644 t/t0021/rot13-filter.pl create mode 100755 t/t3007-ls-files-recurse-submodules.sh create mode 100644 t/t4013/diff.diff_--line-prefix=abc_master_master^_side create mode 100644 t/t4013/diff.diff_--line-prefix_--cached_--_file0 create mode 100755 t/t4059-diff-submodule-not-initialized.sh create mode 100755 t/t4060-diff-submodule-option-diff-format.sh create mode 100755 t/t4061-diff-indent.sh create mode 100644 t/t5100/info0018 create mode 100644 t/t5100/info0018--no-inbody-headers create mode 100644 t/t5100/msg0018 create mode 100644 t/t5100/msg0018--no-inbody-headers create mode 100644 t/t5100/patch0018 create mode 100644 t/t5100/patch0018--no-inbody-headers create mode 100755 t/t5314-pack-cycle-detection.sh create mode 100755 t/t5546-receive-limits.sh create mode 100755 t/t5547-push-quarantine.sh create mode 100755 t/t5615-alternate-env.sh create mode 100755 t/t7064-wtstatus-pv2.sh create mode 100755 t/t8010-cat-file-filters.sh create mode 100644 tmp-objdir.c create mode 100644 tmp-objdir.h diff --git a/Documentation/RelNotes/2.10.3.txt b/Documentation/RelNotes/2.10.3.txt deleted file mode 100644 index ad6a01b..0000000 --- a/Documentation/RelNotes/2.10.3.txt +++ /dev/null @@ -1,55 +0,0 @@ -Git v2.10.3 Release Notes -========================= - -Fixes since v2.10.2 -------------------- - - * Extract a small helper out of the function that reads the authors - script file "git am" internally uses. - This by itself is not useful until a second caller appears in the - future for "rebase -i" helper. - - * The command-line completion script (in contrib/) learned to - complete "git cmd ^mas" to complete the negative end of - reference to "git cmd ^master". - - * "git send-email" attempts to pick up valid e-mails from the - trailers, but people in real world write non-addresses there, like - "Cc: Stable # 4.8+", which broke the output depending - on the availability and vintage of Mail::Address perl module. - - * The code that we have used for the past 10+ years to cycle - 4-element ring buffers turns out to be not quite portable in - theoretical world. - - * "git daemon" used fixed-length buffers to turn URL to the - repository the client asked for into the server side directory - path, using snprintf() to avoid overflowing these buffers, but - allowed possibly truncated paths to the directory. This has been - tightened to reject such a request that causes overlong path to be - required to serve. - - * Recent update to git-sh-setup (a library of shell functions that - are used by our in-tree scripted Porcelain commands) included - another shell library git-sh-i18n without specifying where it is, - relying on the $PATH. This has been fixed to be more explicit by - prefixing $(git --exec-path) output in front. - - * Fix for a racy false-positive test failure. - - * Portability update and workaround for builds on recent Mac OS X. - - * Update to the test framework made in 2.9 timeframe broke running - the tests under valgrind, which has been fixed. - - * Improve the rule to convert "unsigned char [20]" into "struct - object_id *" in contrib/coccinelle/ - - * "git-shell" rejects a request to serve a repository whose name - begins with a dash, which makes it no longer possible to get it - confused into spawning service programs like "git-upload-pack" with - an option like "--help", which in turn would spawn an interactive - pager, instead of working with the repository user asked to access - (i.e. the one whose name is "--help"). - -Also contains minor documentation updates and code clean-ups. diff --git a/Documentation/RelNotes/2.10.4.txt b/Documentation/RelNotes/2.10.4.txt deleted file mode 100644 index ee8142a..0000000 --- a/Documentation/RelNotes/2.10.4.txt +++ /dev/null @@ -1,4 +0,0 @@ -Git v2.10.4 Release Notes -========================= - -This release forward-ports the fix for "ssh://..." URL from Git v2.7.6 diff --git a/Documentation/RelNotes/2.10.5.txt b/Documentation/RelNotes/2.10.5.txt deleted file mode 100644 index a498fd6..0000000 --- a/Documentation/RelNotes/2.10.5.txt +++ /dev/null @@ -1,17 +0,0 @@ -Git v2.10.5 Release Notes -========================= - -Fixes since v2.10.4 -------------------- - - * "git cvsserver" no longer is invoked by "git daemon" by default, - as it is old and largely unmaintained. - - * Various Perl scripts did not use safe_pipe_capture() instead of - backticks, leaving them susceptible to end-user input. They have - been corrected. - -Credits go to joernchen for finding the -unsafe constructs in "git cvsserver", and to Jeff King at GitHub for -finding and fixing instances of the same issue in other scripts. - diff --git a/Documentation/RelNotes/2.11.0.txt b/Documentation/RelNotes/2.11.0.txt new file mode 100644 index 0000000..b7b7dd3 --- /dev/null +++ b/Documentation/RelNotes/2.11.0.txt @@ -0,0 +1,593 @@ +Git 2.11 Release Notes +====================== + +Backward compatibility notes. + + * An empty string used as a pathspec element has always meant + 'everything matches', but it is too easy to write a script that + finds a path to remove in $path and run 'git rm "$paht"' by + mistake (when the user meant to give "$path"), which ends up + removing everything. This release starts warning about the + use of an empty string that is used for 'everything matches' and + asks users to use a more explicit '.' for that instead. + + The hope is that existing users will not mind this change, and + eventually the warning can be turned into a hard error, upgrading + the deprecation into removal of this (mis)feature. + + * The historical argument order "git merge HEAD ..." + has been deprecated for quite some time, and will be removed in the + next release (not this one). + + * The default abbreviation length, which has historically been 7, now + scales as the repository grows, using the approximate number of + objects in the repository and a bit of math around the birthday + paradox. The logic suggests to use 12 hexdigits for the Linux + kernel, and 9 to 10 for Git itself. + + +Updates since v2.10 +------------------- + +UI, Workflows & Features + + * Comes with new version of git-gui, now at its 0.21.0 tag. + + * "git format-patch --cover-letter HEAD^" to format a single patch + with a separate cover letter now numbers the output as [PATCH 0/1] + and [PATCH 1/1] by default. + + * An incoming "git push" that attempts to push too many bytes can now + be rejected by setting a new configuration variable at the receiving + end. + + * "git nosuchcommand --help" said "No manual entry for gitnosuchcommand", + which was not intuitive, given that "git nosuchcommand" said "git: + 'nosuchcommand' is not a git command". + + * "git clone --recurse-submodules --reference $path $URL" is a way to + reduce network transfer cost by borrowing objects in an existing + $path repository when cloning the superproject from $URL; it + learned to also peek into $path for presence of corresponding + repositories of submodules and borrow objects from there when able. + + * The "git diff --submodule={short,log}" mechanism has been enhanced + to allow "--submodule=diff" to show the patch between the submodule + commits bound to the superproject. + + * Even though "git hash-objects", which is a tool to take an + on-filesystem data stream and put it into the Git object store, + can perform "outside-world-to-Git" conversions (e.g. + end-of-line conversions and application of the clean-filter), and + it has had this feature on by default from very early days, its reverse + operation "git cat-file", which takes an object from the Git object + store and externalizes it for consumption by the outside world, + lacked an equivalent mechanism to run the "Git-to-outside-world" + conversion. The command learned the "--filters" option to do so. + + * Output from "git diff" can be made easier to read by intelligently selecting + which lines are common and which lines are added/deleted + when the lines before and after the changed section + are the same. A command line option (--indent-heuristic) and a + configuration variable (diff.indentHeuristic) are added to help with the + experiment to find good heuristics. + + * In some projects, it is common to use "[RFC PATCH]" as the subject + prefix for a patch meant for discussion rather than application. A + new format-patch option "--rfc" is a short-hand for "--subject-prefix=RFC PATCH" + to help the participants of such projects. + + * "git add --chmod={+,-}x " only changed the + executable bit for paths that are either new or modified. This has + been corrected to change the executable bit for all paths that match + the given pathspec. + + * When "git format-patch --stdout" output is placed as an in-body + header and it uses RFC2822 header folding, "git am" fails to + put the header line back into a single logical line. The + underlying "git mailinfo" was taught to handle this properly. + + * "gitweb" can spawn "highlight" to show blob contents with + (programming) language-specific syntax highlighting, but only + when the language is known. "highlight" can however be told + to guess the language itself by giving it "--force" option, which + has been enabled. + + * "git gui" l10n to Portuguese. + + * When given an abbreviated object name that is not (or more + realistically, "no longer") unique, we gave a fatal error + "ambiguous argument". This error is now accompanied by a hint that + lists the objects beginning with the given prefix. During the + course of development of this new feature, numerous minor bugs were + uncovered and corrected, the most notable one of which is that we + gave "short SHA1 xxxx is ambiguous." twice without good reason. + + * "git log rev^..rev" is an often-used revision range specification + to show what was done on a side branch merged at rev. This has + gained a short-hand "rev^-1". In general "rev^-$n" is the same as + "^rev^$n rev", i.e. what has happened on other branches while the + history leading to nth parent was looking the other way. + + * In recent versions of cURL, GSSAPI credential delegation is + disabled by default due to CVE-2011-2192; introduce a http.delegation + configuration variable to selectively allow enabling this. + (merge 26a7b23429 ps/http-gssapi-cred-delegation later to maint). + + * "git mergetool" learned to honor "-O" to control the + order of paths to present to the end user. + + * "git diff/log --ws-error-highlight=" lacked the corresponding + configuration variable (diff.wsErrorHighlight) to set it by default. + + * "git ls-files" learned the "--recurse-submodules" option + to get a listing of tracked files across submodules (i.e. this + only works with the "--cached" option, not for listing untracked or + ignored files). This would be a useful tool to sit on the upstream + side of a pipe that is read with xargs to work on all working tree + files from the top-level superproject. + + * A new credential helper that talks via "libsecret" with + implementations of XDG Secret Service API has been added to + contrib/credential/. + + * The GPG verification status shown by the "%G?" pretty format specifier + was not rich enough to differentiate a signature made by an expired + key, a signature made by a revoked key, etc. New output letters + have been assigned to express them. + + * In addition to purely abbreviated commit object names, "gitweb" + learned to turn "git describe" output (e.g. v2.9.3-599-g2376d31787) + into clickable links in its output. + + * "git commit" created an empty commit when invoked with an index + consisting solely of intend-to-add paths (added with "git add -N"). + It now requires the "--allow-empty" option to create such a commit. + The same logic prevented "git status" from showing such paths as "new files" in the + "Changes not staged for commit" section. + + * The smudge/clean filter API spawns an external process + to filter the contents of each path that has a filter defined. A + new type of "process" filter API has been added to allow the first + request to run the filter for a path to spawn a single process, and + all filtering is served by this single process for multiple + paths, reducing the process creation overhead. + + * The user always has to say "stash@{$N}" when naming a single + element in the default location of the stash, i.e. reflogs in + refs/stash. The "git stash" command learned to accept "git stash + apply 4" as a short-hand for "git stash apply stash@{4}". + + +Performance, Internal Implementation, Development Support etc. + + * The delta-base-cache mechanism has been a key to the performance in + a repository with a tightly packed packfile, but it did not scale + well even with a larger value of core.deltaBaseCacheLimit. + + * Enhance "git status --porcelain" output by collecting more data on + the state of the index and the working tree files, which may + further be used to teach git-prompt (in contrib/) to make fewer + calls to git. + + * Extract a small helper out of the function that reads the authors + script file "git am" internally uses. + (merge a77598e jc/am-read-author-file later to maint). + + * Lift calls to exit(2) and die() higher in the callchain in + sequencer.c files so that more helper functions in it can be used + by callers that want to handle error conditions themselves. + + * "git am" has been taught to make an internal call to "git apply"'s + innards without spawning the latter as a separate process. + + * The ref-store abstraction was introduced to the refs API so that we + can plug in different backends to store references. + + * The "unsigned char sha1[20]" to "struct object_id" conversion + continues. Notable changes in this round includes that ce->sha1, + i.e. the object name recorded in the cache_entry, turns into an + object_id. + + * JGit can show a fake ref "capabilities^{}" to "git fetch" when it + does not advertise any refs, but "git fetch" was not prepared to + see such an advertisement. When the other side disconnects without + giving any ref advertisement, we used to say "there may not be a + repository at that URL", but we may have seen other advertisements + like "shallow" and ".have" in which case we definitely know that a + repository is there. The code to detect this case has also been + updated. + + * Some codepaths in "git pack-objects" were not ready to use an + existing pack bitmap; now they are and as a result they have + become faster. + + * The codepath in "git fsck" to detect malformed tree objects has + been updated not to die but keep going after detecting them. + + * We call "qsort(array, nelem, sizeof(array[0]), fn)", and most of + the time third parameter is redundant. A new QSORT() macro lets us + omit it. + + * "git pack-objects" in a repository with many packfiles used to + spend a lot of time looking for/at objects in them; the accesses to + the packfiles are now optimized by checking the most-recently-used + packfile first. + (merge c9af708b1a jk/pack-objects-optim-mru later to maint). + + * Codepaths involved in interacting alternate object stores have + been cleaned up. + + * In order for the receiving end of "git push" to inspect the + received history and decide to reject the push, the objects sent + from the sending end need to be made available to the hook and + the mechanism for the connectivity check, and this was done + traditionally by storing the objects in the receiving repository + and letting "git gc" expire them. Instead, store the newly + received objects in a temporary area, and make them available by + reusing the alternate object store mechanism to them only while we + decide if we accept the check, and once we decide, either migrate + them to the repository or purge them immediately. + + * The require_clean_work_tree() helper was recreated in C when "git + pull" was rewritten from shell; the helper is now made available to + other callers in preparation for upcoming "rebase -i" work. + + * "git upload-pack" had its code cleaned-up and performance improved + by reducing use of timestamp-ordered commit-list, which was + replaced with a priority queue. + + * "git diff --no-index" codepath has been updated not to try to peek + into a .git/ directory that happens to be under the current + directory, when we know we are operating outside any repository. + + * Update of the sequencer codebase to make it reusable to reimplement + "rebase -i" continues. + + * Git generally does not explicitly close file descriptors that were + open in the parent process when spawning a child process, but most + of the time the child does not want to access them. As Windows does + not allow removing or renaming a file that has a file descriptor + open, a slow-to-exit child can even break the parent process by + holding onto them. Use O_CLOEXEC flag to open files in various + codepaths. + + * Update "interpret-trailers" machinery and teach it that people in + the real world write all sorts of cruft in the "trailer" that was + originally designed to have the neat-o "Mail-Header: like thing" + and nothing else. + + +Also contains various documentation updates and code clean-ups. + + +Fixes since v2.10 +----------------- + +Unless otherwise noted, all the fixes since v2.9 in the maintenance +track are contained in this release (see the maintenance releases' +notes for details). + + * Clarify various ways to specify the "revision ranges" in the + documentation. + + * "diff-highlight" script (in contrib/) learned to work better with + "git log -p --graph" output. + + * The test framework left the number of tests and success/failure + count in the t/test-results directory, keyed by the name of the + test script plus the process ID. The latter however turned out not + to serve any useful purpose. The process ID part of the filename + has been removed. + + * Having a submodule whose ".git" repository is somehow corrupt + caused a few commands that recurse into submodules to loop forever. + + * "git symbolic-ref -d HEAD" happily removes the symbolic ref, but + the resulting repository becomes an invalid one. Teach the command + to forbid removal of HEAD. + + * A test spawned a short-lived background process, which sometimes + prevented the test directory from getting removed at the end of the + script on some platforms. + + * Update a few tests that used to use GIT_CURL_VERBOSE to use the + newer GIT_TRACE_CURL. + + * "git pack-objects --include-tag" was taught that when we know that + we are sending an object C, we want a tag B that directly points at + C but also a tag A that points at the tag B. We used to miss the + intermediate tag B in some cases. + + * Update Japanese translation for "git-gui". + + * "git fetch http::/site/path" did not die correctly and segfaulted + instead. + + * "git commit-tree" stopped reading commit.gpgsign configuration + variable that was meant for Porcelain "git commit" in Git 2.9; we + forgot to update "git gui" to look at the configuration to match + this change. + + * "git add --chmod={+,-}x" added recently lacked documentation, which has + been corrected. + + * "git log --cherry-pick" used to include merge commits as candidates + to be matched up with other commits, resulting a lot of wasted time. + The patch-id generation logic has been updated to ignore merges and + avoid the wastage. + + * The http transport (with curl-multi option, which is the default + these days) failed to remove curl-easy handle from a curlm session, + which led to unnecessary API failures. + + * There were numerous corner cases in which the configuration files + are read and used or not read at all depending on the directory a + Git command was run, leading to inconsistent behaviour. The code + to set-up repository access at the beginning of a Git process has + been updated to fix them. + (merge 4d0efa1 jk/setup-sequence-update later to maint). + + * "git diff -W" output needs to extend the context backward to + include the header line of the current function and also forward to + include the body of the entire current function up to the header + line of the next one. This process may have to merge two adjacent + hunks, but the code forgot to do so in some cases. + + * Performance tests done via "t/perf" did not use the right + build configuration if the user relied on autoconf generated + configuration. + + * "git format-patch --base=..." feature that was recently added + showed the base commit information after the "-- " e-mail signature + line, which turned out to be inconvenient. The base information + has been moved above the signature line. + + * More i18n. + + * Even when "git pull --rebase=preserve" (and the underlying "git + rebase --preserve") can complete without creating any new commits + (i.e. fast-forwards), it still insisted on having usable ident + information (read: user.email is set correctly), which was less + than nice. As the underlying commands used inside "git rebase" + would fail with a more meaningful error message and advice text + when the bogus ident matters, this extra check was removed. + + * "git gc --aggressive" used to limit the delta-chain length to 250, + which is way too deep for gaining additional space savings and is + detrimental for runtime performance. The limit has been reduced to + 50. + + * Documentation for individual configuration variables to control use + of color (like `color.grep`) said that their default value is + 'false', instead of saying their default is taken from `color.ui`. + When we updated the default value for color.ui from 'false' to + 'auto' quite a while ago, all of them broke. This has been + corrected. + + * The pretty-format specifier "%C(auto)" used by the "log" family of + commands to enable coloring of the output is taught to also issue a + color-reset sequence to the output. + + * A shell script example in check-ref-format documentation has been + fixed. + + * "git checkout " does not follow the usual disambiguation + rules when the can be both a rev and a path, to allow + checking out a branch 'foo' in a project that happens to have a + file 'foo' in the working tree without having to disambiguate. + This was poorly documented and the check was incorrect when the + command was run from a subdirectory. + + * Some codepaths in "git diff" used regexec(3) on a buffer that was + mmap(2)ed, which may not have a terminating NUL, leading to a read + beyond the end of the mapped region. This was fixed by introducing + a regexec_buf() helper that takes a pair with REG_STARTEND + extension. + + * The procedure to build Git on Mac OS X for Travis CI hardcoded the + internal directory structure we assumed HomeBrew uses, which was a + no-no. The procedure has been updated to ask HomeBrew things we + need to know to fix this. + + * When "git rebase -i" is given a broken instruction, it told the + user to fix it with "--edit-todo", but didn't say what the step + after that was (i.e. "--continue"). + + * Documentation around tools to import from CVS was fairly outdated. + + * "git clone --recurse-submodules" lost the progress eye-candy in + a recent update, which has been corrected. + + * A low-level function verify_packfile() was meant to show errors + that were detected without dying itself, but under some conditions + it didn't and died instead, which has been fixed. + + * When "git fetch" tries to find where the history of the repository + it runs in has diverged from what the other side has, it has a + mechanism to avoid digging too deep into irrelevant side branches. + This however did not work well over the "smart-http" transport due + to a design bug, which has been fixed. + + * In the codepath that comes up with the hostname to be used in an + e-mail when the user didn't tell us, we looked at the ai_canonname + field in struct addrinfo without making sure it is not NULL first. + + * "git worktree", even though it used the default_abbrev setting that + ought to be affected by the core.abbrev configuration variable, ignored + the variable setting. The command has been taught to read the + default set of configuration variables to correct this. + + * "git init" tried to record core.worktree in the repository's + 'config' file when the GIT_WORK_TREE environment variable was set and + it was different from where GIT_DIR appears as ".git" at its top, + but the logic was faulty when .git is a "gitdir:" file that points + at the real place, causing trouble in working trees that are + managed by "git worktree". This has been corrected. + + * Codepaths that read from an on-disk loose object were too loose in + validating that they are reading a proper object file and + sometimes read past the data they read from the disk, which has + been corrected. H/t to Gustavo Grieco for reporting. + + * The original command line syntax for "git merge", which was "git + merge HEAD ...", has been deprecated for quite some + time, and "git gui" was the last in-tree user of the syntax. This + is finally fixed, so that we can move forward with the deprecation. + + * An author name that has a backslash-quoted double quote in the + human readable part ("My \"double quoted\" name"), was not unquoted + correctly while applying a patch from a piece of e-mail. + + * Doc update to clarify what "log -3 --reverse" does. + + * Almost everybody uses DEFAULT_ABBREV to refer to the default + setting for the abbreviation, but "git blame" peeked into + underlying variable bypassing the macro for no good reason. + + * The "graph" API used in "git log --graph" miscounted the number of + output columns consumed so far when drawing a padding line, which + has been fixed; this did not affect any existing code as nobody + tried to write anything after the padding on such a line, though. + + * The code that parses the format parameter of the for-each-ref command + has seen a micro-optimization. + + * When we started to use cURL to talk to an imap server, we forgot to explicitly add + imap(s):// before the destination. To some folks, that didn't work + and the library tried to make HTTP(s) requests instead. + + * The ./configure script generated from configure.ac was taught how + to detect support of SSL by libcurl better. + + * The command-line completion script (in contrib/) learned to + complete "git cmd ^mas" to complete the negative end of + reference to "git cmd ^master". + (merge 49416ad22a cp/completion-negative-refs later to maint). + + * The existing "git fetch --depth=" option was hard to use + correctly when making the history of an existing shallow clone + deeper. A new option, "--deepen=", has been added to make this + easier to use. "git clone" also learned "--shallow-since=" + and "--shallow-exclude=" options to make it easier to specify + "I am interested only in the recent N months worth of history" and + "Give me only the history since that version". + (merge cccf74e2da nd/shallow-deepen later to maint). + + * "git blame --reverse OLD path" is now DWIMmed to show how lines + in path in an old revision OLD have survived up to the current + commit. + (merge e1d09701a4 jc/blame-reverse later to maint). + + * The http.emptyauth configuration variable is a way to allow an empty username to + pass when attempting to authenticate using mechanisms like + Kerberos. We took an unspecified (NULL) username and sent ":" + (i.e. no username, no password) to CURLOPT_USERPWD, but did not do + the same when the username is explicitly set to an empty string. + + * "git clone" of a local repository can be done at the filesystem + level, but the codepath did not check errors while copying and + adjusting the file that lists alternate object stores. + + * Documentation for "git commit" was updated to clarify that "commit + -p " adds to the current contents of the index to come up + with what to commit. + + * A stray symbolic link in the $GIT_DIR/refs/ directory could make name + resolution loop forever, which has been corrected. + + * The "submodule..path" stored in .gitmodules is never copied + to .git/config and such a key in .git/config has no meaning, but + the documentation described it next to submodule..url + as if both belong to .git/config. This has been fixed. + + * In a worktree created via "git + worktree", "git checkout" attempts to protect users from confusion + by refusing to check out a branch that is already checked out in + another worktree. However, this also prevented checking out a + branch which is designated as the primary branch of a bare + repository, in a worktree that is connected to the bare + repository. The check has been corrected to allow it. + + * "git rebase" immediately after "git clone" failed to find the fork + point from the upstream. + + * When fetching from a remote that has many tags that are irrelevant + to branches we are following, we used to waste way too many cycles + checking if the object pointed at by a tag (that we are not + going to fetch!) exists in our repository too carefully. + + * Protect our code from over-eager compilers. + + * Recent git allows submodule..branch to use a special token + "." instead of the branch name; the documentation has been updated + to describe it. + + * "git send-email" attempts to pick up valid e-mails from the + trailers, but people in the real world write non-addresses there, like + "Cc: Stable # 4.8+", which broke the output depending + on the availability and vintage of the Mail::Address perl module. + (merge dcfafc5214 mm/send-email-cc-cruft-after-address later to maint). + + * The Travis CI configuration we ship ran the tests with the --verbose + option but this risks non-TAP output that happens to be "ok" to be + misinterpreted as TAP signalling a test that passed. This resulted + in unnecessary failures. This has been corrected by introducing a + new mode to run our tests in the test harness to send the verbose + output separately to the log file. + + * Some AsciiDoc formatters mishandle a displayed illustration with + tabs in it. Adjust a few of them in merge-base documentation to + work around them. + + * Fixed a minor regression in "git submodule" that was introduced + when more helper functions were reimplemented in C. + (merge 77b63ac31e sb/submodule-ignore-trailing-slash later to maint). + + * The code that we have used for the past 10+ years to cycle + 4-element ring buffers turns out to be not quite portable in + theoretical world. + (merge bb84735c80 rs/ring-buffer-wraparound later to maint). + + * "git daemon" used fixed-length buffers to turn URLs to the + repository the client asked for into the server side directory + paths, using snprintf() to avoid overflowing these buffers, but + allowed possibly truncated paths to the directory. This has been + tightened to reject such a request that causes an overlong path to be + served. + (merge 6bdb0083be jk/daemon-path-ok-check-truncation later to maint). + + * Recent update to git-sh-setup (a library of shell functions that + are used by our in-tree scripted Porcelain commands) included + another shell library git-sh-i18n without specifying where it is, + relying on the $PATH. This has been fixed to be more explicit by + prefixing with $(git --exec-path) output. + (merge 1073094f30 ak/sh-setup-dot-source-i18n-fix later to maint). + + * Fix for a racy false-positive test failure. + (merge fdf4f6c79b as/merge-attr-sleep later to maint). + + * Portability update and workaround for builds on recent Mac OS X. + (merge a296bc0132 ls/macos-update later to maint). + + * Using a %(HEAD) placeholder in "for-each-ref --format=" option + caused the command to segfault when on an unborn branch. + (merge 84679d470d jc/for-each-ref-head-segfault-fix later to maint). + + * "git rebase -i" did not work well with the core.commentchar + configuration variable for two reasons, both of which have been + fixed. + (merge 882cd23777 js/rebase-i-commentchar-fix later to maint). + + * Other minor doc, test and build updates and code cleanups. + (merge 5c238e29a8 jk/common-main later to maint). + (merge 5a5749e45b ak/pre-receive-hook-template-modefix later to maint). + (merge 6d834ac8f1 jk/rebase-config-insn-fmt-docfix later to maint). + (merge de9f7fa3b0 rs/commit-pptr-simplify later to maint). + (merge 4259d693fc sc/fmt-merge-msg-doc-markup-fix later to maint). + (merge 28fab7b23d nd/test-helpers later to maint). + (merge c2bb0c1d1e rs/cocci later to maint). + (merge 3285b7badb ps/common-info-doc later to maint). + (merge 2b090822e8 nd/worktree-lock later to maint). + (merge 4bd488ea7c jk/create-branch-remove-unused-param later to maint). + (merge 974e0044d6 tk/diffcore-delta-remove-unused later to maint). diff --git a/Documentation/RelNotes/2.4.12.txt b/Documentation/RelNotes/2.4.12.txt deleted file mode 100644 index 7d15f94..0000000 --- a/Documentation/RelNotes/2.4.12.txt +++ /dev/null @@ -1,12 +0,0 @@ -Git v2.4.12 Release Notes -========================= - -Fixes since v2.4.11 -------------------- - - * "git-shell" rejects a request to serve a repository whose name - begins with a dash, which makes it no longer possible to get it - confused into spawning service programs like "git-upload-pack" with - an option like "--help", which in turn would spawn an interactive - pager, instead of working with the repository user asked to access - (i.e. the one whose name is "--help"). diff --git a/Documentation/RelNotes/2.5.6.txt b/Documentation/RelNotes/2.5.6.txt deleted file mode 100644 index 9cd025b..0000000 --- a/Documentation/RelNotes/2.5.6.txt +++ /dev/null @@ -1,12 +0,0 @@ -Git v2.5.6 Release Notes -======================== - -Fixes since v2.5.5 ------------------- - - * "git-shell" rejects a request to serve a repository whose name - begins with a dash, which makes it no longer possible to get it - confused into spawning service programs like "git-upload-pack" with - an option like "--help", which in turn would spawn an interactive - pager, instead of working with the repository user asked to access - (i.e. the one whose name is "--help"). diff --git a/Documentation/RelNotes/2.6.7.txt b/Documentation/RelNotes/2.6.7.txt deleted file mode 100644 index 1335de4..0000000 --- a/Documentation/RelNotes/2.6.7.txt +++ /dev/null @@ -1,12 +0,0 @@ -Git v2.6.7 Release Notes -======================== - -Fixes since v2.6.6 ------------------- - - * "git-shell" rejects a request to serve a repository whose name - begins with a dash, which makes it no longer possible to get it - confused into spawning service programs like "git-upload-pack" with - an option like "--help", which in turn would spawn an interactive - pager, instead of working with the repository user asked to access - (i.e. the one whose name is "--help"). diff --git a/Documentation/RelNotes/2.7.5.txt b/Documentation/RelNotes/2.7.5.txt deleted file mode 100644 index 83559ce..0000000 --- a/Documentation/RelNotes/2.7.5.txt +++ /dev/null @@ -1,14 +0,0 @@ -Git v2.7.5 Release Notes -======================== - -Fixes since v2.7.4 ------------------- - - * "git-shell" rejects a request to serve a repository whose name - begins with a dash, which makes it no longer possible to get it - confused into spawning service programs like "git-upload-pack" with - an option like "--help", which in turn would spawn an interactive - pager, instead of working with the repository user asked to access - (i.e. the one whose name is "--help"). - -Also contains a few fixes backported from later development tracks. diff --git a/Documentation/RelNotes/2.7.6.txt b/Documentation/RelNotes/2.7.6.txt deleted file mode 100644 index 4c6d1dc..0000000 --- a/Documentation/RelNotes/2.7.6.txt +++ /dev/null @@ -1,25 +0,0 @@ -Git v2.7.6 Release Notes -======================== - -Fixes since v2.7.5 ------------------- - - * A "ssh://..." URL can result in a "ssh" command line with a - hostname that begins with a dash "-", which would cause the "ssh" - command to instead (mis)treat it as an option. This is now - prevented by forbidding such a hostname (which will not be - necessary in the real world). - - * Similarly, when GIT_PROXY_COMMAND is configured, the command is - run with host and port that are parsed out from "ssh://..." URL; - a poorly written GIT_PROXY_COMMAND could be tricked into treating - a string that begins with a dash "-". This is now prevented by - forbidding such a hostname and port number (again, which will not - be necessary in the real world). - - * In the same spirit, a repository name that begins with a dash "-" - is also forbidden now. - -Credits go to Brian Neel at GitLab, Joern Schneeweisz of Recurity -Labs and Jeff King at GitHub. - diff --git a/Documentation/RelNotes/2.8.5.txt b/Documentation/RelNotes/2.8.5.txt deleted file mode 100644 index 7bd179f..0000000 --- a/Documentation/RelNotes/2.8.5.txt +++ /dev/null @@ -1,12 +0,0 @@ -Git v2.8.5 Release Notes -======================== - -Fixes since v2.8.4 ------------------- - - * "git-shell" rejects a request to serve a repository whose name - begins with a dash, which makes it no longer possible to get it - confused into spawning service programs like "git-upload-pack" with - an option like "--help", which in turn would spawn an interactive - pager, instead of working with the repository user asked to access - (i.e. the one whose name is "--help"). diff --git a/Documentation/RelNotes/2.8.6.txt b/Documentation/RelNotes/2.8.6.txt deleted file mode 100644 index d8db55d..0000000 --- a/Documentation/RelNotes/2.8.6.txt +++ /dev/null @@ -1,4 +0,0 @@ -Git v2.8.6 Release Notes -======================== - -This release forward-ports the fix for "ssh://..." URL from Git v2.7.6 diff --git a/Documentation/RelNotes/2.9.4.txt b/Documentation/RelNotes/2.9.4.txt index 9768293..01e8642 100644 --- a/Documentation/RelNotes/2.9.4.txt +++ b/Documentation/RelNotes/2.9.4.txt @@ -80,11 +80,4 @@ Fixes since v2.9.3 the file descriptor still open. Open tempfile with O_CLOEXEC flag to avoid this (on Windows, this is mapped to O_NOINHERIT). - * "git-shell" rejects a request to serve a repository whose name - begins with a dash, which makes it no longer possible to get it - confused into spawning service programs like "git-upload-pack" with - an option like "--help", which in turn would spawn an interactive - pager, instead of working with the repository user asked to access - (i.e. the one whose name is "--help"). - Also contains minor documentation updates and code clean-ups. diff --git a/Documentation/RelNotes/2.9.5.txt b/Documentation/RelNotes/2.9.5.txt deleted file mode 100644 index 668313a..0000000 --- a/Documentation/RelNotes/2.9.5.txt +++ /dev/null @@ -1,4 +0,0 @@ -Git v2.9.5 Release Notes -======================== - -This release forward-ports the fix for "ssh://..." URL from Git v2.7.6 diff --git a/Documentation/blame-options.txt b/Documentation/blame-options.txt index 02cb684..2669b87 100644 --- a/Documentation/blame-options.txt +++ b/Documentation/blame-options.txt @@ -28,12 +28,13 @@ include::line-range-format.txt[] -S :: Use revisions from revs-file instead of calling linkgit:git-rev-list[1]. ---reverse:: +--reverse ..:: Walk history forward instead of backward. Instead of showing the revision in which a line appeared, this shows the last revision in which a line has existed. This requires a range of revision like START..END where the path to blame exists in - START. + START. `git blame --reverse START` is taken as `git blame + --reverse START..HEAD` for convenience. -p:: --porcelain:: diff --git a/Documentation/config.txt b/Documentation/config.txt index cbae7a6..a0ab66a 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1736,6 +1736,20 @@ http.emptyAuth:: a username in the URL, as libcurl normally requires a username for authentication. +http.delegation:: + Control GSSAPI credential delegation. The delegation is disabled + by default in libcurl since version 7.21.7. Set parameter to tell + the server what it is allowed to delegate when it comes to user + credentials. Used with GSS/kerberos. Possible values are: ++ +-- +* `none` - Don't allow any delegation. +* `policy` - Delegates if and only if the OK-AS-DELEGATE flag is set in the + Kerberos service ticket, which is a matter of realm policy. +* `always` - Unconditionally allow the server to delegate. +-- + + 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 @@ -2523,6 +2537,12 @@ receive.unpackLimit:: especially on slow filesystems. If not set, the value of `transfer.unpackLimit` is used instead. +receive.maxInputSize:: + If the size of the incoming pack stream is larger than this + limit, then git-receive-pack will error out, instead of + accepting the pack file. If not set or set to 0, then the size + is unlimited. + receive.denyDeletes:: If set to true, git-receive-pack will deny a ref update that deletes the ref. Use this to prevent such a ref deletion via a push. @@ -2854,6 +2874,18 @@ submodule.fetchJobs:: in parallel. A value of 0 will give some reasonable default. If unset, it defaults to 1. +submodule.alternateLocation:: + Specifies how the submodules obtain alternates when submodules are + cloned. Possible values are `no`, `superproject`. + By default `no` is assumed, which doesn't add references. When the + value is set to `superproject` the submodule to be cloned computes + its alternates location relative to the superprojects alternate. + +submodule.alternateErrorStrategy + Specifies how to treat errors with the alternates for a submodule + as computed via `submodule.alternateLocation`. Possible values are + `ignore`, `info`, `die`. Default is `die`. + tag.forceSignAnnotated:: A boolean to specify whether annotated tags created should be GPG signed. If `--annotate` is specified on the command line, it takes diff --git a/Documentation/diff-config.txt b/Documentation/diff-config.txt index d5a5b17..58f4bd6 100644 --- a/Documentation/diff-config.txt +++ b/Documentation/diff-config.txt @@ -122,10 +122,11 @@ diff.suppressBlankEmpty:: diff.submodule:: Specify the format in which differences in submodules are - shown. The "log" format lists the commits in the range like - linkgit:git-submodule[1] `summary` does. The "short" format - format just shows the names of the commits at the beginning - and end of the range. Defaults to short. + shown. The "short" format just shows the names of the commits + at the beginning and end of the range. The "log" format lists + the commits in the range like linkgit:git-submodule[1] `summary` + does. The "diff" format shows an inline diff of the changed + contents of the submodule. Defaults to "short". diff.wordRegex:: A POSIX Extended Regular Expression used to determine what is a "word" @@ -170,10 +171,11 @@ diff.tool:: include::mergetools-diff.txt[] +diff.indentHeuristic:: 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. + Set one of these options to `true` to enable one of two + experimental heuristics that shift diff hunk boundaries to + make patches easier to read. diff.algorithm:: Choose a diff algorithm. The variants are as follows: @@ -191,3 +193,9 @@ diff.algorithm:: low-occurrence common elements". -- + + +diff.wsErrorHighlight:: + A comma separated list of `old`, `new`, `context`, that + specifies how whitespace errors on lines are highlighted + with `color.diff.whitespace`. Can be overridden by the + command line option `--ws-error-highlight=` diff --git a/Documentation/diff-heuristic-options.txt b/Documentation/diff-heuristic-options.txt new file mode 100644 index 0000000..36cb549 --- /dev/null +++ b/Documentation/diff-heuristic-options.txt @@ -0,0 +1,7 @@ +--indent-heuristic:: +--no-indent-heuristic:: +--compaction-heuristic:: +--no-compaction-heuristic:: + These are to help debugging and tuning experimental heuristics + (which are off by default) that shift diff hunk boundaries to + make patches easier to read. diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 705a873..e6215c3 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -63,12 +63,7 @@ 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. +include::diff-heuristic-options.txt[] --minimal:: Spend extra time to make sure the smallest possible @@ -210,13 +205,16 @@ any of those replacements occurred. of the `--diff-filter` option on what the status letters mean. --submodule[=]:: - Specify how differences in submodules are shown. When `--submodule` - or `--submodule=log` is given, the 'log' format is used. This format lists - the commits in the range like linkgit:git-submodule[1] `summary` does. - Omitting the `--submodule` option or specifying `--submodule=short`, - uses the 'short' format. This format just shows the names of the commits - at the beginning and end of the range. Can be tweaked via the - `diff.submodule` configuration variable. + Specify how differences in submodules are shown. When specifying + `--submodule=short` the 'short' format is used. This format just + shows the names of the commits at the beginning and end of the range. + When `--submodule` or `--submodule=log` is specified, the 'log' + format is used. This format lists the commits in the range like + linkgit:git-submodule[1] `summary` does. When `--submodule=diff` + is specified, the 'diff' format is used. This format shows an + inline diff of the changes in the submodule contents between the + commit range. Defaults to `diff.submodule` or the 'short' format + if the config option is unset. --color[=]:: Show colored diff. @@ -310,6 +308,8 @@ ifndef::git-format-patch[] lines are highlighted. E.g. `--ws-error-highlight=new,old` highlights whitespace errors on both deleted and added lines. `all` can be used as a short-hand for `old,new,context`. + The `diff.wsErrorHighlight` configuration variable can be + used to specify the default behaviour. endif::git-format-patch[] @@ -569,5 +569,16 @@ endif::git-format-patch[] --no-prefix:: Do not show any source or destination prefix. +--line-prefix=:: + Prepend an additional prefix to every line of output. + +--ita-invisible-in-index:: + By default entries added by "git add -N" appear as an existing + empty file in "git diff" and a new file in "git diff --cached". + This option makes the entry appear as a new file in "git diff" + and non-existent in "git diff --cached". This option could be + reverted with `--ita-visible-in-index`. Both options are + experimental and could be removed in future. + For more detailed explanation on these common options, see also linkgit:gitdiffcore[7]. diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index 9eab1f5..fb6bebb 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -14,6 +14,20 @@ linkgit:git-clone[1]), deepen or shorten the history to the specified number of commits. Tags for the deepened commits are not fetched. +--deepen=:: + Similar to --depth, except it specifies the number of commits + from the current shallow boundary instead of from the tip of + each remote branch history. + +--shallow-since=:: + Deepen or shorten the history of a shallow repository to + include all reachable commits after . + +--shallow-exclude=:: + Deepen or shorten the history of a shallow repository to + exclude commits reachable from a specified remote branch or tag. + This option can be specified multiple times. + --unshallow:: If the source repository is complete, convert a shallow repository to a complete one, removing all the limitations diff --git a/Documentation/git-annotate.txt b/Documentation/git-annotate.txt index 05fd482..94be4b8 100644 --- a/Documentation/git-annotate.txt +++ b/Documentation/git-annotate.txt @@ -23,6 +23,7 @@ familiar command name for people coming from other SCM systems. OPTIONS ------- include::blame-options.txt[] +include::diff-heuristic-options.txt[] SEE ALSO -------- diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt index ba54175..fdc3aea 100644 --- a/Documentation/git-blame.txt +++ b/Documentation/git-blame.txt @@ -10,7 +10,7 @@ SYNOPSIS [verse] 'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental] [-L ] [-S ] [-M] [-C] [-C] [-C] [--since=] - [--progress] [--abbrev=] [ | --contents | --reverse ] + [--progress] [--abbrev=] [ | --contents | --reverse ..] [--] DESCRIPTION @@ -89,6 +89,8 @@ include::blame-options.txt[] abbreviated object name, use +1 digits. Note that 1 column is used for a caret to mark the boundary commit. +include::diff-heuristic-options.txt[] + THE PORCELAIN FORMAT -------------------- diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index 18d03d8..204541c 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -9,18 +9,22 @@ git-cat-file - Provide content or type and size information for repository objec SYNOPSIS -------- [verse] -'git cat-file' (-t [--allow-unknown-type]| -s [--allow-unknown-type]| -e | -p | | --textconv ) -'git cat-file' (--batch | --batch-check) [--follow-symlinks] +'git cat-file' (-t [--allow-unknown-type]| -s [--allow-unknown-type]| -e | -p | | --textconv | --filters ) [--path=] +'git cat-file' (--batch | --batch-check) [ --textconv | --filters ] [--follow-symlinks] DESCRIPTION ----------- In its first form, the command provides the content or the type of an object in the repository. The type is required unless `-t` or `-p` is used to find the -object type, or `-s` is used to find the object size, or `--textconv` is used -(which implies type "blob"). +object type, or `-s` is used to find the object size, or `--textconv` or +`--filters` is used (which imply type "blob"). In the second form, a list of objects (separated by linefeeds) is provided on -stdin, and the SHA-1, type, and size of each object is printed on stdout. +stdin, and the SHA-1, type, and size of each object is printed on stdout. The +output format can be overridden using the optional `` argument. If +either `--textconv` or `--filters` was specified, the input is expected to +list the object names followed by the path name, separated by a single white +space, so that the appropriate drivers can be determined. OPTIONS ------- @@ -54,19 +58,35 @@ OPTIONS --textconv:: Show the content as transformed by a textconv filter. In this case, - has be of the form :, or : in order - to apply the filter to the content recorded in the index at . + has to be of the form :, or : in + order to apply the filter to the content recorded in the index at + . + +--filters:: + Show the content as converted by the filters configured in + the current working tree for the given (i.e. smudge filters, + end-of-line conversion, etc). In this case, has to be of + the form :, or :. + +--path=:: + For use with --textconv or --filters, to allow specifying an object + name and a path separately, e.g. when it is difficult to figure out + the revision from which the blob came. --batch:: --batch=:: Print object information and contents for each object provided - on stdin. May not be combined with any other options or arguments. - See the section `BATCH OUTPUT` below for details. + on stdin. May not be combined with any other options or arguments + except `--textconv` or `--filters`, in which case the input lines + also need to specify the path, separated by white space. See the + section `BATCH OUTPUT` below for details. --batch-check:: --batch-check=:: Print object information for each object provided on stdin. May - not be combined with any other options or arguments. See the + not be combined with any other options or arguments except + `--textconv` or `--filters`, in which case the input lines also + need to specify the path, separated by white space. See the section `BATCH OUTPUT` below for details. --batch-all-objects:: diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index ec41d3d..35cc34b 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -90,13 +90,16 @@ If you want to break the dependency of a repository cloned with `-s` on its source repository, you can simply run `git repack -a` to copy all objects from the source repository into a pack in the cloned repository. ---reference :: +--reference[-if-able] :: If the reference repository is on the local machine, automatically setup `.git/objects/info/alternates` to obtain objects from the reference repository. Using an already existing repository as an alternate will require fewer objects to be copied from the repository being cloned, reducing network and local storage costs. + When using the `--reference-if-able`, a non existing + directory is skipped with a warning instead of aborting + the clone. + *NOTE*: see the NOTE for the `--shared` option, and also the `--dissociate` option. @@ -194,6 +197,14 @@ objects from the source repository into a pack in the cloned repository. tips of all branches. If you want to clone submodules shallowly, also pass `--shallow-submodules`. +--shallow-since=:: + Create a shallow clone with a history after the specified time. + +--shallow-exclude=:: + Create a shallow clone with a history, excluding commits + reachable from a specified remote branch or tag. This option + can be specified multiple times. + --[no-]single-branch:: Clone only the history leading to the tip of a single branch, either specified by the `--branch` option or the primary diff --git a/Documentation/git-count-objects.txt b/Documentation/git-count-objects.txt index 2ff3568..cb9b4d2 100644 --- a/Documentation/git-count-objects.txt +++ b/Documentation/git-count-objects.txt @@ -38,6 +38,11 @@ objects nor valid packs + size-garbage: disk space consumed by garbage files, in KiB (unless -H is specified) ++ +alternate: absolute path of alternate object databases; may appear +multiple times, one line per path. Note that if the path contains +non-printable characters, it may be surrounded by double-quotes and +contain C-style backslashed escape sequences. -H:: --human-readable:: diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index 24417ee..d45f6ad 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@ -87,6 +87,20 @@ be in a separate packet, and the list must end with a flush packet. 'git-upload-pack' treats the special depth 2147483647 as infinite even if there is an ancestor-chain that long. +--shallow-since=:: + Deepen or shorten the history of a shallow'repository to + include all reachable commits after . + +--shallow-exclude=:: + Deepen or shorten the history of a shallow repository to + exclude commits reachable from a specified remote branch or tag. + This option can be specified multiple times. + +--deepen-relative:: + Argument --depth specifies the number of commits from the + current shallow boundary instead of from the tip of each + remote branch history. + --no-progress:: Do not show the progress. diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 9624c84..9b200b3 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -19,7 +19,8 @@ SYNOPSIS [--start-number ] [--numbered-files] [--in-reply-to=Message-Id] [--suffix=.] [--ignore-if-in-upstream] - [--subject-prefix=Subject-Prefix] [(--reroll-count|-v) ] + [--rfc] [--subject-prefix=Subject-Prefix] + [(--reroll-count|-v) ] [--to=] [--cc=] [--[no-]cover-letter] [--quiet] [--notes[=]] [] @@ -172,6 +173,11 @@ will want to ensure that threading is disabled for `git send-email`. allows for useful naming of a patch series, and can be combined with the `--numbered` option. +--rfc:: + Alias for `--subject-prefix="RFC PATCH"`. RFC means "Request For + Comments"; use this when sending an experimental patch for + discussion rather than application. + -v :: --reroll-count=:: Mark the series as the -th iteration of the topic. The diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt index 7a4e055..1b4b65d 100644 --- a/Documentation/git-index-pack.txt +++ b/Documentation/git-index-pack.txt @@ -87,6 +87,8 @@ OPTIONS Specifying 0 will cause Git to auto-detect the number of CPU's and use maximum 3 threads. +--max-input-size=:: + Die, if the pack is larger than . Note ---- diff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt index 93d1db6..09074c7 100644 --- a/Documentation/git-interpret-trailers.txt +++ b/Documentation/git-interpret-trailers.txt @@ -48,19 +48,22 @@ with only spaces at the end of the commit message part, one blank line will be added before the new trailer. Existing trailers are extracted from the input message by looking for -a group of one or more lines that contain a colon (by default), where -the group is preceded by one or more empty (or whitespace-only) lines. +a group of one or more lines that (i) are all trailers, or (ii) contains at +least one Git-generated or user-configured trailer and consists of at +least 25% trailers. +The group must be preceded by one or more empty (or whitespace-only) lines. The group must either be at the end of the message or be the last non-whitespace lines before a line that starts with '---'. Such three minus signs start the patch part of the message. -When reading trailers, there can be whitespaces before and after the +When reading trailers, there can be whitespaces after the token, the separator and the value. There can also be whitespaces -inside the token and the value. +inside the token and the value. The value may be split over multiple lines with +each subsequent line starting with whitespace, like the "folding" in RFC 822. Note that 'trailers' do not follow and are not intended to follow many -rules for RFC 822 headers. For example they do not follow the line -folding rules, the encoding rules and probably many other rules. +rules for RFC 822 headers. For example they do not follow +the encoding rules and probably many other rules. OPTIONS ------- diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt index 0d933ac..446209e 100644 --- a/Documentation/git-ls-files.txt +++ b/Documentation/git-ls-files.txt @@ -18,7 +18,8 @@ SYNOPSIS [--exclude-per-directory=] [--exclude-standard] [--error-unmatch] [--with-tree=] - [--full-name] [--abbrev] [--] [...] + [--full-name] [--recurse-submodules] + [--abbrev] [--] [...] DESCRIPTION ----------- @@ -137,6 +138,10 @@ a space) at the start of each line: option forces paths to be output relative to the project top directory. +--recurse-submodules:: + Recursively calls ls-files on each submodule in the repository. + Currently there is only support for the --cached mode. + --abbrev[=]:: Instead of showing the full 40-byte hexadecimal object lines, show only a partial prefix. diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt index e846c2e..3622d66 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.txt @@ -79,6 +79,13 @@ success of the resolution after the custom tool has exited. Prompt before each invocation of the merge resolution program to give the user a chance to skip the path. +-O:: + Process files in the order specified in the + , which has one shell glob pattern per line. + This overrides the `diff.orderFile` configuration variable + (see linkgit:git-config[1]). To cancel `diff.orderFile`, + use `-O/dev/null`. + TEMPORARY FILES --------------- `git mergetool` creates `*.orig` backup files while resolving merges. diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt index 000ee8d..0ccd5fb 100644 --- a/Documentation/git-receive-pack.txt +++ b/Documentation/git-receive-pack.txt @@ -33,6 +33,9 @@ post-update hooks found in the Documentation/howto directory. option, which tells it if updates to a ref should be denied if they are not fast-forwards. +A number of other receive.* config options are available to tweak +its behavior, see linkgit:git-config[1]. + OPTIONS ------- :: diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt index 54cf256..2e30a3e 100644 --- a/Documentation/git-shell.txt +++ b/Documentation/git-shell.txt @@ -79,22 +79,6 @@ EOF $ chmod +x $HOME/git-shell-commands/no-interactive-login ---------------- -To enable git-cvsserver access (which should generally have the -`no-interactive-login` example above as a prerequisite, as creating -the git-shell-commands directory allows interactive logins): - ----------------- -$ cat >$HOME/git-shell-commands/cvs <<\EOF -if ! test $# = 1 && test "$1" = "server" -then - echo >&2 "git-cvsserver only handles \"server\"" - exit 1 -fi -exec git cvsserver server -EOF -$ chmod +x $HOME/git-shell-commands/cvs ----------------- - SEE ALSO -------- ssh(1), diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt index 92df596..2e9cef0 100644 --- a/Documentation/git-stash.txt +++ b/Documentation/git-stash.txt @@ -39,7 +39,8 @@ The latest stash you created is stored in `refs/stash`; older stashes are found in the reflog of this reference and can be named using the usual reflog syntax (e.g. `stash@{0}` is the most recently created stash, `stash@{1}` is the one before it, `stash@{2.hours.ago}` -is also possible). +is also possible). Stashes may also be referenced by specifying just the +stash index (e.g. the integer `n` is equivalent to `stash@{n}`). OPTIONS ------- diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt index e1e8f57..725065e 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.txt @@ -32,11 +32,14 @@ OPTIONS --branch:: Show the branch and tracking info even in short-format. ---porcelain:: +--porcelain[=]:: Give the output in an easy-to-parse format for scripts. This is similar to the short output, but will remain stable across Git versions and regardless of user configuration. See below for details. ++ +The version parameter is used to specify the format version. +This is optional and defaults to the original version 'v1' format. --long:: Give the output in the long-format. This is the default. @@ -96,7 +99,7 @@ configuration variable documented in linkgit:git-config[1]. -z:: Terminate entries with NUL, instead of LF. This implies - the `--porcelain` output format if no other format is given. + the `--porcelain=v1` output format if no other format is given. --column[=]:: --no-column:: @@ -180,12 +183,12 @@ in which case `XY` are `!!`. If -b is used the short-format status is preceded by a line -## branchname tracking info + ## branchname tracking info -Porcelain Format -~~~~~~~~~~~~~~~~ +Porcelain Format Version 1 +~~~~~~~~~~~~~~~~~~~~~~~~~~ -The porcelain format is similar to the short format, but is guaranteed +Version 1 porcelain format is similar to the short format, but is guaranteed not to change in a backwards-incompatible way between Git versions or based on user configuration. This makes it ideal for parsing by scripts. The description of the short format above also describes the porcelain @@ -207,6 +210,124 @@ field from the first filename). Third, filenames containing special characters are not specially formatted; no quoting or backslash-escaping is performed. +Porcelain Format Version 2 +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Version 2 format adds more detailed information about the state of +the worktree and changed items. Version 2 also defines an extensible +set of easy to parse optional headers. + +Header lines start with "#" and are added in response to specific +command line arguments. Parsers should ignore headers they +don't recognize. + +### Branch Headers + +If `--branch` is given, a series of header lines are printed with +information about the current branch. + + Line Notes + ------------------------------------------------------------ + # branch.oid | (initial) Current commit. + # branch.head | (detached) Current branch. + # branch.upstream If upstream is set. + # branch.ab + - If upstream is set and + the commit is present. + ------------------------------------------------------------ + +### Changed Tracked Entries + +Following the headers, a series of lines are printed for tracked +entries. One of three different line formats may be used to describe +an entry depending on the type of change. Tracked entries are printed +in an undefined order; parsers should allow for a mixture of the 3 +line types in any order. + +Ordinary changed entries have the following format: + + 1 + +Renamed or copied entries have the following format: + + 2 + + Field Meaning + -------------------------------------------------------- + A 2 character field containing the staged and + unstaged XY values described in the short format, + with unchanged indicated by a "." rather than + a space. + A 4 character field describing the submodule state. + "N..." when the entry is not a submodule. + "S" when the entry is a submodule. + is "C" if the commit changed; otherwise ".". + is "M" if it has tracked changes; otherwise ".". + is "U" if there are untracked changes; otherwise ".". + The octal file mode in HEAD. + The octal file mode in the index. + The octal file mode in the worktree. + The object name in HEAD. + The object name in the index. + The rename or copy score (denoting the percentage + of similarity between the source and target of the + move or copy). For example "R100" or "C75". + The pathname. In a renamed/copied entry, this + is the path in the index and in the working tree. + When the `-z` option is used, the 2 pathnames are separated + with a NUL (ASCII 0x00) byte; otherwise, a tab (ASCII 0x09) + byte separates them. + The pathname in the commit at HEAD. This is only + present in a renamed/copied entry, and tells + where the renamed/copied contents came from. + -------------------------------------------------------- + +Unmerged entries have the following format; the first character is +a "u" to distinguish from ordinary changed entries. + + u

+ + Field Meaning + -------------------------------------------------------- + A 2 character field describing the conflict type + as described in the short format. + A 4 character field describing the submodule state + as described above. + The octal file mode in stage 1. + The octal file mode in stage 2. + The octal file mode in stage 3. + The octal file mode in the worktree. +

The object name in stage 1. +

The object name in stage 2. +

The object name in stage 3. + The pathname. + -------------------------------------------------------- + +### Other Items + +Following the tracked entries (and if requested), a series of +lines will be printed for untracked and then ignored items +found in the worktree. + +Untracked items have the following format: + + ? + +Ignored items have the following format: + + ! + +### Pathname Format Notes and -z + +When the `-z` option is given, pathnames are printed as is and +without any quoting and lines are terminated with a NUL (ASCII 0x00) +byte. + +Otherwise, all pathnames will be "C-quoted" if they contain any tab, +linefeed, double quote, or backslash characters. In C-quoting, these +characters will be replaced with the corresponding C-style escape +sequences and the resulting pathname will be double quoted. + + CONFIGURATION ------------- diff --git a/Documentation/git-unpack-objects.txt b/Documentation/git-unpack-objects.txt index 3e887d1..b3de50d 100644 --- a/Documentation/git-unpack-objects.txt +++ b/Documentation/git-unpack-objects.txt @@ -44,6 +44,9 @@ OPTIONS --strict:: Don't write objects with broken content or links. +--max-input-size=:: + Die, if the pack is larger than . + GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/git.txt b/Documentation/git.txt index 89157e2..af191c5 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -13,6 +13,7 @@ SYNOPSIS [--exec-path[=]] [--html-path] [--man-path] [--info-path] [-p|--paginate|--no-pager] [--no-replace-objects] [--bare] [--git-dir=] [--work-tree=] [--namespace=] + [--super-prefix=] [] DESCRIPTION @@ -43,47 +44,46 @@ 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.10.3/git.html[documentation for release 2.10.3] +* link:v2.11.0/git.html[documentation for release 2.11] + +* release notes for + link:RelNotes/2.11.0.txt[2.11]. + +* link:v2.10.2/git.html[documentation for release 2.10.2] * release notes for - link:RelNotes/2.10.3.txt[2.10.3], link:RelNotes/2.10.2.txt[2.10.2], link:RelNotes/2.10.1.txt[2.10.1], link:RelNotes/2.10.0.txt[2.10]. -* link:v2.9.4/git.html[documentation for release 2.9.4] +* link:v2.9.3/git.html[documentation for release 2.9.3] * release notes for - link:RelNotes/2.9.4.txt[2.9.4], link:RelNotes/2.9.3.txt[2.9.3], link:RelNotes/2.9.2.txt[2.9.2], link:RelNotes/2.9.1.txt[2.9.1], link:RelNotes/2.9.0.txt[2.9]. -* link:v2.8.5/git.html[documentation for release 2.8.5] +* link:v2.8.4/git.html[documentation for release 2.8.4] * release notes for - link:RelNotes/2.8.5.txt[2.8.5], 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.5/git.html[documentation for release 2.7.5] +* link:v2.7.3/git.html[documentation for release 2.7.3] * release notes for - link:RelNotes/2.7.5.txt[2.7.5], - link:RelNotes/2.7.4.txt[2.7.4], link:RelNotes/2.7.3.txt[2.7.3], link:RelNotes/2.7.2.txt[2.7.2], link:RelNotes/2.7.1.txt[2.7.1], link:RelNotes/2.7.0.txt[2.7]. -* link:v2.6.7/git.html[documentation for release 2.6.7] +* link:v2.6.6/git.html[documentation for release 2.6.6] * release notes for - link:RelNotes/2.6.7.txt[2.6.7], link:RelNotes/2.6.6.txt[2.6.6], link:RelNotes/2.6.5.txt[2.6.5], link:RelNotes/2.6.4.txt[2.6.4], @@ -92,10 +92,9 @@ Documentation for older releases are available here: link:RelNotes/2.6.1.txt[2.6.1], link:RelNotes/2.6.0.txt[2.6]. -* link:v2.5.6/git.html[documentation for release 2.5.6] +* link:v2.5.5/git.html[documentation for release 2.5.5] * release notes for - link:RelNotes/2.5.6.txt[2.5.6], link:RelNotes/2.5.5.txt[2.5.5], link:RelNotes/2.5.4.txt[2.5.4], link:RelNotes/2.5.3.txt[2.5.3], @@ -103,10 +102,9 @@ Documentation for older releases are available here: link:RelNotes/2.5.1.txt[2.5.1], link:RelNotes/2.5.0.txt[2.5]. -* link:v2.4.12/git.html[documentation for release 2.4.12] +* link:v2.4.11/git.html[documentation for release 2.4.11] * release notes for - link:RelNotes/2.4.12.txt[2.4.12], link:RelNotes/2.4.11.txt[2.4.11], link:RelNotes/2.4.10.txt[2.4.10], link:RelNotes/2.4.9.txt[2.4.9], @@ -611,6 +609,11 @@ foo.bar= ...`) sets `foo.bar` to the empty string. details. Equivalent to setting the `GIT_NAMESPACE` environment variable. +--super-prefix=:: + Currently for internal use only. Set a prefix which gives a path from + above a repository down to its root. One use is to give submodules + context about the superproject that invoked it. + --bare:: Treat the repository as a bare repository. If GIT_DIR environment is not set, it is set to the current working diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 7aff940..976243a 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -293,7 +293,15 @@ checkout, when the `smudge` command is specified, the command is fed the blob object from its standard input, and its standard output is used to update the worktree file. Similarly, the `clean` command is used to convert the contents of worktree file -upon checkin. +upon checkin. By default these commands process only a single +blob and terminate. If a long running `process` filter is used +in place of `clean` and/or `smudge` filters, then Git can process +all blobs with a single filter command invocation for the entire +life of a single Git command, for example `git add --all`. If a +long running `process` filter is configured then it always takes +precedence over a configured single blob filter. See section +below for the description of the protocol used to communicate with +a `process` filter. One use of the content filtering is to massage the content into a shape that is more convenient for the platform, filesystem, and the user to use. @@ -373,6 +381,153 @@ not exist, or may have different contents. So, smudge and clean commands should not try to access the file on disk, but only act as filters on the content provided to them on standard input. +Long Running Filter Process +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the filter command (a string value) is defined via +`filter..process` then Git can process all blobs with a +single filter invocation for the entire life of a single Git +command. This is achieved by using a packet format (pkt-line, +see technical/protocol-common.txt) based protocol over standard +input and standard output as follows. All packets, except for the +"*CONTENT" packets and the "0000" flush packet, are considered +text and therefore are terminated by a LF. + +Git starts the filter when it encounters the first file +that needs to be cleaned or smudged. After the filter started +Git sends a welcome message ("git-filter-client"), a list of supported +protocol version numbers, and a flush packet. Git expects to read a welcome +response message ("git-filter-server"), exactly one protocol version number +from the previously sent list, and a flush packet. All further +communication will be based on the selected version. The remaining +protocol description below documents "version=2". Please note that +"version=42" in the example below does not exist and is only there +to illustrate how the protocol would look like with more than one +version. + +After the version negotiation Git sends a list of all capabilities that +it supports and a flush packet. Git expects to read a list of desired +capabilities, which must be a subset of the supported capabilities list, +and a flush packet as response: +------------------------ +packet: git> git-filter-client +packet: git> version=2 +packet: git> version=42 +packet: git> 0000 +packet: git< git-filter-server +packet: git< version=2 +packet: git< 0000 +packet: git> capability=clean +packet: git> capability=smudge +packet: git> capability=not-yet-invented +packet: git> 0000 +packet: git< capability=clean +packet: git< capability=smudge +packet: git< 0000 +------------------------ +Supported filter capabilities in version 2 are "clean" and +"smudge". + +Afterwards Git sends a list of "key=value" pairs terminated with +a flush packet. The list will contain at least the filter command +(based on the supported capabilities) and the pathname of the file +to filter relative to the repository root. Right after the flush packet +Git sends the content split in zero or more pkt-line packets and a +flush packet to terminate content. Please note, that the filter +must not send any response before it received the content and the +final flush packet. +------------------------ +packet: git> command=smudge +packet: git> pathname=path/testfile.dat +packet: git> 0000 +packet: git> CONTENT +packet: git> 0000 +------------------------ + +The filter is expected to respond with a list of "key=value" pairs +terminated with a flush packet. If the filter does not experience +problems then the list must contain a "success" status. Right after +these packets the filter is expected to send the content in zero +or more pkt-line packets and a flush packet at the end. Finally, a +second list of "key=value" pairs terminated with a flush packet +is expected. The filter can change the status in the second list +or keep the status as is with an empty list. Please note that the +empty list must be terminated with a flush packet regardless. + +------------------------ +packet: git< status=success +packet: git< 0000 +packet: git< SMUDGED_CONTENT +packet: git< 0000 +packet: git< 0000 # empty list, keep "status=success" unchanged! +------------------------ + +If the result content is empty then the filter is expected to respond +with a "success" status and a flush packet to signal the empty content. +------------------------ +packet: git< status=success +packet: git< 0000 +packet: git< 0000 # empty content! +packet: git< 0000 # empty list, keep "status=success" unchanged! +------------------------ + +In case the filter cannot or does not want to process the content, +it is expected to respond with an "error" status. +------------------------ +packet: git< status=error +packet: git< 0000 +------------------------ + +If the filter experiences an error during processing, then it can +send the status "error" after the content was (partially or +completely) sent. +------------------------ +packet: git< status=success +packet: git< 0000 +packet: git< HALF_WRITTEN_ERRONEOUS_CONTENT +packet: git< 0000 +packet: git< status=error +packet: git< 0000 +------------------------ + +In case the filter cannot or does not want to process the content +as well as any future content for the lifetime of the Git process, +then it is expected to respond with an "abort" status at any point +in the protocol. +------------------------ +packet: git< status=abort +packet: git< 0000 +------------------------ + +Git neither stops nor restarts the filter process in case the +"error"/"abort" status is set. However, Git sets its exit code +according to the `filter..required` flag, mimicking the +behavior of the `filter..clean` / `filter..smudge` +mechanism. + +If the filter dies during the communication or does not adhere to +the protocol then Git will stop the filter process and restart it +with the next file that needs to be processed. Depending on the +`filter..required` flag Git will interpret that as error. + +After the filter has processed a blob it is expected to wait for +the next "key=value" list containing a command. Git will close +the command pipe on exit. The filter is expected to detect EOF +and exit gracefully on its own. Git will wait until the filter +process has stopped. + +A long running filter demo implementation can be found in +`contrib/long-running-filter/example.pl` located in the Git +core repository. If you develop your own long running filter +process then the `GIT_TRACE_PACKET` environment variables can be +very helpful for debugging (see linkgit:git[1]). + +Please note that you cannot use an existing `filter..clean` +or `filter..smudge` command with `filter..process` +because the former two use a different inter process communication +protocol than the latter one. + + Interaction between checkin/checkout attributes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt index a4de50a..9e8681f 100644 --- a/Documentation/gitremote-helpers.txt +++ b/Documentation/gitremote-helpers.txt @@ -415,6 +415,17 @@ set by Git if the remote helper has the 'option' capability. 'option depth' :: Deepens the history of a shallow repository. +'option deepen-since :: + Deepens the history of a shallow repository based on time. + +'option deepen-not :: + Deepens the history of a shallow repository excluding ref. + Multiple options add up. + +'option deepen-relative {'true'|'false'}:: + Deepens the history of a shallow repository relative to + current boundary. Only valid when used with "option depth". + 'option followtags' {'true'|'false'}:: If enabled the helper should automatically fetch annotated tag objects if the object the tag points at was transferred diff --git a/Documentation/gitweb.conf.txt b/Documentation/gitweb.conf.txt index a79e350..e632089 100644 --- a/Documentation/gitweb.conf.txt +++ b/Documentation/gitweb.conf.txt @@ -246,13 +246,20 @@ $highlight_bin:: Note that 'highlight' feature must be set for gitweb to actually use syntax highlighting. + -*NOTE*: if you want to add support for new file type (supported by -"highlight" but not used by gitweb), you need to modify `%highlight_ext` -or `%highlight_basename`, depending on whether you detect type of file -based on extension (for example "sh") or on its basename (for example -"Makefile"). The keys of these hashes are extension and basename, -respectively, and value for given key is name of syntax to be passed via -`--syntax ` to highlighter. +*NOTE*: for a file to be highlighted, its syntax type must be detected +and that syntax must be supported by "highlight". The default syntax +detection is minimal, and there are many supported syntax types with no +detection by default. There are three options for adding syntax +detection. The first and second priority are `%highlight_basename` and +`%highlight_ext`, which detect based on basename (the full filename, for +example "Makefile") and extension (for example "sh"). The keys of these +hashes are the basename and extension, respectively, and the value for a +given key is the name of the syntax to be passed via `--syntax ` +to "highlight". The last priority is the "highlight" configuration of +`Shebang` regular expressions to detect the language based on the first +line in the file, (for example, matching the line "#!/bin/bash"). See +the highlight documentation and the default config at +/etc/highlight/filetypes.conf for more details. + For example if repositories you are hosting use "phtml" extension for PHP files, and you want to have correct syntax-highlighting for those diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index 69c289d..3bcee2d 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -143,8 +143,14 @@ 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 (valid) signature, "B" for a bad signature, - "U" for a good signature with unknown validity 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, + "X" for a good signature that has expired, + "Y" for a good signature made by an expired key, + "R" for a good signature made by a revoked key, + "E" if the signature cannot be checked (e.g. missing key) + 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}` or diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt index 4bed5b1..ba11b9c 100644 --- a/Documentation/revisions.txt +++ b/Documentation/revisions.txt @@ -283,7 +283,7 @@ empty range that is both reachable and unreachable from HEAD. Other {caret} Parent Shorthand Notations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Two other shorthands exist, particularly useful for merge commits, +Three other shorthands exist, particularly useful for merge commits, for naming a set that is formed by a commit and its parent commits. The 'r1{caret}@' notation means all parents of 'r1'. @@ -291,8 +291,15 @@ The 'r1{caret}@' notation means all parents of 'r1'. The 'r1{caret}!' notation includes commit 'r1' but excludes all of its parents. By itself, this notation denotes the single commit 'r1'. +The '{caret}-{}' notation includes '' but excludes the th +parent (i.e. a shorthand for '{caret}..'), with '' = 1 if +not given. This is typically useful for merge commits where you +can just pass '{caret}-' to get all the commits in the branch +that was merged in merge commit '' (including '' +itself). + While '{caret}' was about specifying a single commit parent, these -two notations consider all its parents. For example you can say +three notations also consider its parents. For example you can say 'HEAD{caret}2{caret}@', however you cannot say 'HEAD{caret}@{caret}2'. Revision Range Summary @@ -326,6 +333,10 @@ Revision Range Summary as giving commit '' and then all its parents prefixed with '{caret}' to exclude them (and their ancestors). +'{caret}-{}', e.g. 'HEAD{caret}-, HEAD{caret}-2':: + Equivalent to '{caret}..', with '' = 1 if not + given. + Here are a handful of examples using the Loeliger illustration above, with each step in the notation's expansion and selection carefully spelt out: @@ -339,6 +350,8 @@ spelt out: C I J F C B..C = ^B C C B...C = B ^F C G H D E B C + B^- = B^..B + = ^B^1 B E I J F B C^@ = C^1 = F I J F B^@ = B^1 B^2 B^3 diff --git a/Documentation/technical/api-sha1-array.txt b/Documentation/technical/api-sha1-array.txt index 3e75497..dcc5294 100644 --- a/Documentation/technical/api-sha1-array.txt +++ b/Documentation/technical/api-sha1-array.txt @@ -38,16 +38,20 @@ Functions `sha1_array_for_each_unique`:: Efficiently iterate over each unique element of the list, executing the callback function for each one. If the array is - not sorted, this function has the side effect of sorting it. + not sorted, this function has the side effect of sorting it. If + the callback returns a non-zero value, the iteration ends + immediately and the callback's return is propagated; otherwise, + 0 is returned. Examples -------- ----------------------------------------- -void print_callback(const unsigned char sha1[20], +int print_callback(const unsigned char sha1[20], void *data) { printf("%s\n", sha1_to_hex(sha1)); + return 0; /* always continue */ } void some_func(void) diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt index 736f389..c59ac99 100644 --- a/Documentation/technical/pack-protocol.txt +++ b/Documentation/technical/pack-protocol.txt @@ -219,7 +219,9 @@ out of what the server said it could do with the first 'want' line. shallow-line = PKT-LINE("shallow" SP obj-id) - depth-request = PKT-LINE("deepen" SP depth) + depth-request = PKT-LINE("deepen" SP depth) / + PKT-LINE("deepen-since" SP timestamp) / + PKT-LINE("deepen-not" SP ref) first-want = PKT-LINE("want" SP obj-id SP capability-list) additional-want = PKT-LINE("want" SP obj-id) diff --git a/Documentation/technical/protocol-capabilities.txt b/Documentation/technical/protocol-capabilities.txt index 4c28d3a..26dcc6f 100644 --- a/Documentation/technical/protocol-capabilities.txt +++ b/Documentation/technical/protocol-capabilities.txt @@ -179,6 +179,31 @@ This capability adds "deepen", "shallow" and "unshallow" commands to the fetch-pack/upload-pack protocol so clients can request shallow clones. +deepen-since +------------ + +This capability adds "deepen-since" command to fetch-pack/upload-pack +protocol so the client can request shallow clones that are cut at a +specific time, instead of depth. Internally it's equivalent of doing +"rev-list --max-age=" on the server side. "deepen-since" +cannot be used with "deepen". + +deepen-not +---------- + +This capability adds "deepen-not" command to fetch-pack/upload-pack +protocol so the client can request shallow clones that are cut at a +specific revision, instead of depth. Internally it's equivalent of +doing "rev-list --not " on the server side. "deepen-not" +cannot be used with "deepen", but can be used with "deepen-since". + +deepen-relative +--------------- + +If this capability is requested by the client, the semantics of +"deepen" command is changed. The "depth" argument is the depth from +the current shallow boundary, instead of the depth from remote refs. + no-progress ----------- diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 5f32268..520d6e6 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.10.5 +DEF_VER=v2.11.0 LF=' ' diff --git a/Makefile b/Makefile index 46ad908..f53fcc9 100644 --- a/Makefile +++ b/Makefile @@ -467,6 +467,7 @@ SPATCH = spatch export TCL_PATH TCLTK_PATH SPARSE_FLAGS = +SPATCH_FLAGS = --all-includes @@ -698,6 +699,7 @@ LIB_OBJS += abspath.o LIB_OBJS += advice.o LIB_OBJS += alias.o LIB_OBJS += alloc.o +LIB_OBJS += apply.o LIB_OBJS += archive.o LIB_OBJS += archive-tar.o LIB_OBJS += archive-zip.o @@ -830,6 +832,7 @@ LIB_OBJS += submodule-config.o LIB_OBJS += symlinks.o LIB_OBJS += tag.o LIB_OBJS += tempfile.o +LIB_OBJS += tmp-objdir.o LIB_OBJS += trace.o LIB_OBJS += trailer.o LIB_OBJS += transport.o @@ -2314,7 +2317,7 @@ C_SOURCES = $(patsubst %.o,%.c,$(C_OBJ)) %.cocci.patch: %.cocci $(C_SOURCES) @echo ' ' SPATCH $<; \ for f in $(C_SOURCES); do \ - $(SPATCH) --sp-file $< $$f; \ + $(SPATCH) --sp-file $< $$f $(SPATCH_FLAGS); \ done >$@ 2>$@.log; \ if test -s $@; \ then \ diff --git a/RelNotes b/RelNotes index 0afb154..b54330f 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.10.5.txt \ No newline at end of file +Documentation/RelNotes/2.11.0.txt \ No newline at end of file diff --git a/apply.c b/apply.c new file mode 100644 index 0000000..705cf56 --- /dev/null +++ b/apply.c @@ -0,0 +1,4988 @@ +/* + * apply.c + * + * Copyright (C) Linus Torvalds, 2005 + * + * This applies patches on top of some (arbitrary) version of the SCM. + * + */ + +#include "cache.h" +#include "blob.h" +#include "delta.h" +#include "diff.h" +#include "dir.h" +#include "xdiff-interface.h" +#include "ll-merge.h" +#include "lockfile.h" +#include "parse-options.h" +#include "quote.h" +#include "rerere.h" +#include "apply.h" + +static void git_apply_config(void) +{ + git_config_get_string_const("apply.whitespace", &apply_default_whitespace); + git_config_get_string_const("apply.ignorewhitespace", &apply_default_ignorewhitespace); + git_config(git_default_config, NULL); +} + +static int parse_whitespace_option(struct apply_state *state, const char *option) +{ + if (!option) { + state->ws_error_action = warn_on_ws_error; + return 0; + } + if (!strcmp(option, "warn")) { + state->ws_error_action = warn_on_ws_error; + return 0; + } + if (!strcmp(option, "nowarn")) { + state->ws_error_action = nowarn_ws_error; + return 0; + } + if (!strcmp(option, "error")) { + state->ws_error_action = die_on_ws_error; + return 0; + } + if (!strcmp(option, "error-all")) { + state->ws_error_action = die_on_ws_error; + state->squelch_whitespace_errors = 0; + return 0; + } + if (!strcmp(option, "strip") || !strcmp(option, "fix")) { + state->ws_error_action = correct_ws_error; + return 0; + } + return error(_("unrecognized whitespace option '%s'"), option); +} + +static int parse_ignorewhitespace_option(struct apply_state *state, + const char *option) +{ + if (!option || !strcmp(option, "no") || + !strcmp(option, "false") || !strcmp(option, "never") || + !strcmp(option, "none")) { + state->ws_ignore_action = ignore_ws_none; + return 0; + } + if (!strcmp(option, "change")) { + state->ws_ignore_action = ignore_ws_change; + return 0; + } + return error(_("unrecognized whitespace ignore option '%s'"), option); +} + +int init_apply_state(struct apply_state *state, + const char *prefix, + struct lock_file *lock_file) +{ + memset(state, 0, sizeof(*state)); + state->prefix = prefix; + state->prefix_length = state->prefix ? strlen(state->prefix) : 0; + state->lock_file = lock_file; + state->newfd = -1; + state->apply = 1; + state->line_termination = '\n'; + state->p_value = 1; + state->p_context = UINT_MAX; + state->squelch_whitespace_errors = 5; + state->ws_error_action = warn_on_ws_error; + state->ws_ignore_action = ignore_ws_none; + state->linenr = 1; + string_list_init(&state->fn_table, 0); + string_list_init(&state->limit_by_name, 0); + string_list_init(&state->symlink_changes, 0); + strbuf_init(&state->root, 0); + + git_apply_config(); + if (apply_default_whitespace && parse_whitespace_option(state, apply_default_whitespace)) + return -1; + if (apply_default_ignorewhitespace && parse_ignorewhitespace_option(state, apply_default_ignorewhitespace)) + return -1; + return 0; +} + +void clear_apply_state(struct apply_state *state) +{ + string_list_clear(&state->limit_by_name, 0); + string_list_clear(&state->symlink_changes, 0); + strbuf_release(&state->root); + + /* &state->fn_table is cleared at the end of apply_patch() */ +} + +static void mute_routine(const char *msg, va_list params) +{ + /* do nothing */ +} + +int check_apply_state(struct apply_state *state, int force_apply) +{ + int is_not_gitdir = !startup_info->have_repository; + + if (state->apply_with_reject && state->threeway) + return error(_("--reject and --3way cannot be used together.")); + if (state->cached && state->threeway) + return error(_("--cached and --3way cannot be used together.")); + if (state->threeway) { + if (is_not_gitdir) + return error(_("--3way outside a repository")); + state->check_index = 1; + } + if (state->apply_with_reject) { + state->apply = 1; + if (state->apply_verbosity == verbosity_normal) + state->apply_verbosity = verbosity_verbose; + } + if (!force_apply && (state->diffstat || state->numstat || state->summary || state->check || state->fake_ancestor)) + state->apply = 0; + if (state->check_index && is_not_gitdir) + return error(_("--index outside a repository")); + if (state->cached) { + if (is_not_gitdir) + return error(_("--cached outside a repository")); + state->check_index = 1; + } + if (state->check_index) + state->unsafe_paths = 0; + if (!state->lock_file) + return error("BUG: state->lock_file should not be NULL"); + + if (state->apply_verbosity <= verbosity_silent) { + state->saved_error_routine = get_error_routine(); + state->saved_warn_routine = get_warn_routine(); + set_error_routine(mute_routine); + set_warn_routine(mute_routine); + } + + return 0; +} + +static void set_default_whitespace_mode(struct apply_state *state) +{ + if (!state->whitespace_option && !apply_default_whitespace) + state->ws_error_action = (state->apply ? warn_on_ws_error : nowarn_ws_error); +} + +/* + * This represents one "hunk" from a patch, starting with + * "@@ -oldpos,oldlines +newpos,newlines @@" marker. The + * patch text is pointed at by patch, and its byte length + * is stored in size. leading and trailing are the number + * of context lines. + */ +struct fragment { + unsigned long leading, trailing; + unsigned long oldpos, oldlines; + unsigned long newpos, newlines; + /* + * 'patch' is usually borrowed from buf in apply_patch(), + * but some codepaths store an allocated buffer. + */ + const char *patch; + unsigned free_patch:1, + rejected:1; + int size; + int linenr; + struct fragment *next; +}; + +/* + * When dealing with a binary patch, we reuse "leading" field + * to store the type of the binary hunk, either deflated "delta" + * or deflated "literal". + */ +#define binary_patch_method leading +#define BINARY_DELTA_DEFLATED 1 +#define BINARY_LITERAL_DEFLATED 2 + +/* + * This represents a "patch" to a file, both metainfo changes + * such as creation/deletion, filemode and content changes represented + * as a series of fragments. + */ +struct patch { + char *new_name, *old_name, *def_name; + unsigned int old_mode, new_mode; + int is_new, is_delete; /* -1 = unknown, 0 = false, 1 = true */ + int rejected; + unsigned ws_rule; + int lines_added, lines_deleted; + int score; + unsigned int is_toplevel_relative:1; + unsigned int inaccurate_eof:1; + unsigned int is_binary:1; + unsigned int is_copy:1; + unsigned int is_rename:1; + unsigned int recount:1; + unsigned int conflicted_threeway:1; + unsigned int direct_to_threeway:1; + struct fragment *fragments; + char *result; + size_t resultsize; + char old_sha1_prefix[41]; + char new_sha1_prefix[41]; + struct patch *next; + + /* three-way fallback result */ + struct object_id threeway_stage[3]; +}; + +static void free_fragment_list(struct fragment *list) +{ + while (list) { + struct fragment *next = list->next; + if (list->free_patch) + free((char *)list->patch); + free(list); + list = next; + } +} + +static void free_patch(struct patch *patch) +{ + free_fragment_list(patch->fragments); + free(patch->def_name); + free(patch->old_name); + free(patch->new_name); + free(patch->result); + free(patch); +} + +static void free_patch_list(struct patch *list) +{ + while (list) { + struct patch *next = list->next; + free_patch(list); + list = next; + } +} + +/* + * A line in a file, len-bytes long (includes the terminating LF, + * except for an incomplete line at the end if the file ends with + * one), and its contents hashes to 'hash'. + */ +struct line { + size_t len; + unsigned hash : 24; + unsigned flag : 8; +#define LINE_COMMON 1 +#define LINE_PATCHED 2 +}; + +/* + * This represents a "file", which is an array of "lines". + */ +struct image { + char *buf; + size_t len; + size_t nr; + size_t alloc; + struct line *line_allocated; + struct line *line; +}; + +static uint32_t hash_line(const char *cp, size_t len) +{ + size_t i; + uint32_t h; + for (i = 0, h = 0; i < len; i++) { + if (!isspace(cp[i])) { + h = h * 3 + (cp[i] & 0xff); + } + } + return h; +} + +/* + * Compare lines s1 of length n1 and s2 of length n2, ignoring + * whitespace difference. Returns 1 if they match, 0 otherwise + */ +static int fuzzy_matchlines(const char *s1, size_t n1, + const char *s2, size_t n2) +{ + const char *last1 = s1 + n1 - 1; + const char *last2 = s2 + n2 - 1; + int result = 0; + + /* ignore line endings */ + while ((*last1 == '\r') || (*last1 == '\n')) + last1--; + while ((*last2 == '\r') || (*last2 == '\n')) + last2--; + + /* skip leading whitespaces, if both begin with whitespace */ + if (s1 <= last1 && s2 <= last2 && isspace(*s1) && isspace(*s2)) { + while (isspace(*s1) && (s1 <= last1)) + s1++; + while (isspace(*s2) && (s2 <= last2)) + s2++; + } + /* early return if both lines are empty */ + if ((s1 > last1) && (s2 > last2)) + return 1; + while (!result) { + result = *s1++ - *s2++; + /* + * Skip whitespace inside. We check for whitespace on + * both buffers because we don't want "a b" to match + * "ab" + */ + if (isspace(*s1) && isspace(*s2)) { + while (isspace(*s1) && s1 <= last1) + s1++; + while (isspace(*s2) && s2 <= last2) + s2++; + } + /* + * If we reached the end on one side only, + * lines don't match + */ + if ( + ((s2 > last2) && (s1 <= last1)) || + ((s1 > last1) && (s2 <= last2))) + return 0; + if ((s1 > last1) && (s2 > last2)) + break; + } + + return !result; +} + +static void add_line_info(struct image *img, const char *bol, size_t len, unsigned flag) +{ + ALLOC_GROW(img->line_allocated, img->nr + 1, img->alloc); + img->line_allocated[img->nr].len = len; + img->line_allocated[img->nr].hash = hash_line(bol, len); + img->line_allocated[img->nr].flag = flag; + img->nr++; +} + +/* + * "buf" has the file contents to be patched (read from various sources). + * attach it to "image" and add line-based index to it. + * "image" now owns the "buf". + */ +static void prepare_image(struct image *image, char *buf, size_t len, + int prepare_linetable) +{ + const char *cp, *ep; + + memset(image, 0, sizeof(*image)); + image->buf = buf; + image->len = len; + + if (!prepare_linetable) + return; + + ep = image->buf + image->len; + cp = image->buf; + while (cp < ep) { + const char *next; + for (next = cp; next < ep && *next != '\n'; next++) + ; + if (next < ep) + next++; + add_line_info(image, cp, next - cp, 0); + cp = next; + } + image->line = image->line_allocated; +} + +static void clear_image(struct image *image) +{ + free(image->buf); + free(image->line_allocated); + memset(image, 0, sizeof(*image)); +} + +/* fmt must contain _one_ %s and no other substitution */ +static void say_patch_name(FILE *output, const char *fmt, struct patch *patch) +{ + struct strbuf sb = STRBUF_INIT; + + if (patch->old_name && patch->new_name && + strcmp(patch->old_name, patch->new_name)) { + quote_c_style(patch->old_name, &sb, NULL, 0); + strbuf_addstr(&sb, " => "); + quote_c_style(patch->new_name, &sb, NULL, 0); + } else { + const char *n = patch->new_name; + if (!n) + n = patch->old_name; + quote_c_style(n, &sb, NULL, 0); + } + fprintf(output, fmt, sb.buf); + fputc('\n', output); + strbuf_release(&sb); +} + +#define SLOP (16) + +static int read_patch_file(struct strbuf *sb, int fd) +{ + if (strbuf_read(sb, fd, 0) < 0) + return error_errno("git apply: failed to read"); + + /* + * Make sure that we have some slop in the buffer + * so that we can do speculative "memcmp" etc, and + * see to it that it is NUL-filled. + */ + strbuf_grow(sb, SLOP); + memset(sb->buf + sb->len, 0, SLOP); + return 0; +} + +static unsigned long linelen(const char *buffer, unsigned long size) +{ + unsigned long len = 0; + while (size--) { + len++; + if (*buffer++ == '\n') + break; + } + return len; +} + +static int is_dev_null(const char *str) +{ + return skip_prefix(str, "/dev/null", &str) && isspace(*str); +} + +#define TERM_SPACE 1 +#define TERM_TAB 2 + +static int name_terminate(int c, int terminate) +{ + if (c == ' ' && !(terminate & TERM_SPACE)) + return 0; + if (c == '\t' && !(terminate & TERM_TAB)) + return 0; + + return 1; +} + +/* remove double slashes to make --index work with such filenames */ +static char *squash_slash(char *name) +{ + int i = 0, j = 0; + + if (!name) + return NULL; + + while (name[i]) { + if ((name[j++] = name[i++]) == '/') + while (name[i] == '/') + i++; + } + name[j] = '\0'; + return name; +} + +static char *find_name_gnu(struct apply_state *state, + const char *line, + const char *def, + int p_value) +{ + struct strbuf name = STRBUF_INIT; + char *cp; + + /* + * Proposed "new-style" GNU patch/diff format; see + * http://marc.info/?l=git&m=112927316408690&w=2 + */ + if (unquote_c_style(&name, line, NULL)) { + strbuf_release(&name); + return NULL; + } + + for (cp = name.buf; p_value; p_value--) { + cp = strchr(cp, '/'); + if (!cp) { + strbuf_release(&name); + return NULL; + } + cp++; + } + + strbuf_remove(&name, 0, cp - name.buf); + if (state->root.len) + strbuf_insert(&name, 0, state->root.buf, state->root.len); + return squash_slash(strbuf_detach(&name, NULL)); +} + +static size_t sane_tz_len(const char *line, size_t len) +{ + const char *tz, *p; + + if (len < strlen(" +0500") || line[len-strlen(" +0500")] != ' ') + return 0; + tz = line + len - strlen(" +0500"); + + if (tz[1] != '+' && tz[1] != '-') + return 0; + + for (p = tz + 2; p != line + len; p++) + if (!isdigit(*p)) + return 0; + + return line + len - tz; +} + +static size_t tz_with_colon_len(const char *line, size_t len) +{ + const char *tz, *p; + + if (len < strlen(" +08:00") || line[len - strlen(":00")] != ':') + return 0; + tz = line + len - strlen(" +08:00"); + + if (tz[0] != ' ' || (tz[1] != '+' && tz[1] != '-')) + return 0; + p = tz + 2; + if (!isdigit(*p++) || !isdigit(*p++) || *p++ != ':' || + !isdigit(*p++) || !isdigit(*p++)) + return 0; + + return line + len - tz; +} + +static size_t date_len(const char *line, size_t len) +{ + const char *date, *p; + + if (len < strlen("72-02-05") || line[len-strlen("-05")] != '-') + return 0; + p = date = line + len - strlen("72-02-05"); + + if (!isdigit(*p++) || !isdigit(*p++) || *p++ != '-' || + !isdigit(*p++) || !isdigit(*p++) || *p++ != '-' || + !isdigit(*p++) || !isdigit(*p++)) /* Not a date. */ + return 0; + + if (date - line >= strlen("19") && + isdigit(date[-1]) && isdigit(date[-2])) /* 4-digit year */ + date -= strlen("19"); + + return line + len - date; +} + +static size_t short_time_len(const char *line, size_t len) +{ + const char *time, *p; + + if (len < strlen(" 07:01:32") || line[len-strlen(":32")] != ':') + return 0; + p = time = line + len - strlen(" 07:01:32"); + + /* Permit 1-digit hours? */ + if (*p++ != ' ' || + !isdigit(*p++) || !isdigit(*p++) || *p++ != ':' || + !isdigit(*p++) || !isdigit(*p++) || *p++ != ':' || + !isdigit(*p++) || !isdigit(*p++)) /* Not a time. */ + return 0; + + return line + len - time; +} + +static size_t fractional_time_len(const char *line, size_t len) +{ + const char *p; + size_t n; + + /* Expected format: 19:41:17.620000023 */ + if (!len || !isdigit(line[len - 1])) + return 0; + p = line + len - 1; + + /* Fractional seconds. */ + while (p > line && isdigit(*p)) + p--; + if (*p != '.') + return 0; + + /* Hours, minutes, and whole seconds. */ + n = short_time_len(line, p - line); + if (!n) + return 0; + + return line + len - p + n; +} + +static size_t trailing_spaces_len(const char *line, size_t len) +{ + const char *p; + + /* Expected format: ' ' x (1 or more) */ + if (!len || line[len - 1] != ' ') + return 0; + + p = line + len; + while (p != line) { + p--; + if (*p != ' ') + return line + len - (p + 1); + } + + /* All spaces! */ + return len; +} + +static size_t diff_timestamp_len(const char *line, size_t len) +{ + const char *end = line + len; + size_t n; + + /* + * Posix: 2010-07-05 19:41:17 + * GNU: 2010-07-05 19:41:17.620000023 -0500 + */ + + if (!isdigit(end[-1])) + return 0; + + n = sane_tz_len(line, end - line); + if (!n) + n = tz_with_colon_len(line, end - line); + end -= n; + + n = short_time_len(line, end - line); + if (!n) + n = fractional_time_len(line, end - line); + end -= n; + + n = date_len(line, end - line); + if (!n) /* No date. Too bad. */ + return 0; + end -= n; + + if (end == line) /* No space before date. */ + return 0; + if (end[-1] == '\t') { /* Success! */ + end--; + return line + len - end; + } + if (end[-1] != ' ') /* No space before date. */ + return 0; + + /* Whitespace damage. */ + end -= trailing_spaces_len(line, end - line); + return line + len - end; +} + +static char *find_name_common(struct apply_state *state, + const char *line, + const char *def, + int p_value, + const char *end, + int terminate) +{ + int len; + const char *start = NULL; + + if (p_value == 0) + start = line; + while (line != end) { + char c = *line; + + if (!end && isspace(c)) { + if (c == '\n') + break; + if (name_terminate(c, terminate)) + break; + } + line++; + if (c == '/' && !--p_value) + start = line; + } + if (!start) + return squash_slash(xstrdup_or_null(def)); + len = line - start; + if (!len) + return squash_slash(xstrdup_or_null(def)); + + /* + * Generally we prefer the shorter name, especially + * if the other one is just a variation of that with + * something else tacked on to the end (ie "file.orig" + * or "file~"). + */ + if (def) { + int deflen = strlen(def); + if (deflen < len && !strncmp(start, def, deflen)) + return squash_slash(xstrdup(def)); + } + + if (state->root.len) { + char *ret = xstrfmt("%s%.*s", state->root.buf, len, start); + return squash_slash(ret); + } + + return squash_slash(xmemdupz(start, len)); +} + +static char *find_name(struct apply_state *state, + const char *line, + char *def, + int p_value, + int terminate) +{ + if (*line == '"') { + char *name = find_name_gnu(state, line, def, p_value); + if (name) + return name; + } + + return find_name_common(state, line, def, p_value, NULL, terminate); +} + +static char *find_name_traditional(struct apply_state *state, + const char *line, + char *def, + int p_value) +{ + size_t len; + size_t date_len; + + if (*line == '"') { + char *name = find_name_gnu(state, line, def, p_value); + if (name) + return name; + } + + len = strchrnul(line, '\n') - line; + date_len = diff_timestamp_len(line, len); + if (!date_len) + return find_name_common(state, line, def, p_value, NULL, TERM_TAB); + len -= date_len; + + return find_name_common(state, line, def, p_value, line + len, 0); +} + +static int count_slashes(const char *cp) +{ + int cnt = 0; + char ch; + + while ((ch = *cp++)) + if (ch == '/') + cnt++; + return cnt; +} + +/* + * Given the string after "--- " or "+++ ", guess the appropriate + * p_value for the given patch. + */ +static int guess_p_value(struct apply_state *state, const char *nameline) +{ + char *name, *cp; + int val = -1; + + if (is_dev_null(nameline)) + return -1; + name = find_name_traditional(state, nameline, NULL, 0); + if (!name) + return -1; + cp = strchr(name, '/'); + if (!cp) + val = 0; + else if (state->prefix) { + /* + * Does it begin with "a/$our-prefix" and such? Then this is + * very likely to apply to our directory. + */ + if (!strncmp(name, state->prefix, state->prefix_length)) + val = count_slashes(state->prefix); + else { + cp++; + if (!strncmp(cp, state->prefix, state->prefix_length)) + val = count_slashes(state->prefix) + 1; + } + } + free(name); + return val; +} + +/* + * Does the ---/+++ line have the POSIX timestamp after the last HT? + * GNU diff puts epoch there to signal a creation/deletion event. Is + * this such a timestamp? + */ +static int has_epoch_timestamp(const char *nameline) +{ + /* + * We are only interested in epoch timestamp; any non-zero + * fraction cannot be one, hence "(\.0+)?" in the regexp below. + * For the same reason, the date must be either 1969-12-31 or + * 1970-01-01, and the seconds part must be "00". + */ + const char stamp_regexp[] = + "^(1969-12-31|1970-01-01)" + " " + "[0-2][0-9]:[0-5][0-9]:00(\\.0+)?" + " " + "([-+][0-2][0-9]:?[0-5][0-9])\n"; + const char *timestamp = NULL, *cp, *colon; + static regex_t *stamp; + regmatch_t m[10]; + int zoneoffset; + int hourminute; + int status; + + for (cp = nameline; *cp != '\n'; cp++) { + if (*cp == '\t') + timestamp = cp + 1; + } + if (!timestamp) + return 0; + if (!stamp) { + stamp = xmalloc(sizeof(*stamp)); + if (regcomp(stamp, stamp_regexp, REG_EXTENDED)) { + warning(_("Cannot prepare timestamp regexp %s"), + stamp_regexp); + return 0; + } + } + + status = regexec(stamp, timestamp, ARRAY_SIZE(m), m, 0); + if (status) { + if (status != REG_NOMATCH) + warning(_("regexec returned %d for input: %s"), + status, timestamp); + return 0; + } + + zoneoffset = strtol(timestamp + m[3].rm_so + 1, (char **) &colon, 10); + if (*colon == ':') + zoneoffset = zoneoffset * 60 + strtol(colon + 1, NULL, 10); + else + zoneoffset = (zoneoffset / 100) * 60 + (zoneoffset % 100); + if (timestamp[m[3].rm_so] == '-') + zoneoffset = -zoneoffset; + + /* + * YYYY-MM-DD hh:mm:ss must be from either 1969-12-31 + * (west of GMT) or 1970-01-01 (east of GMT) + */ + if ((zoneoffset < 0 && memcmp(timestamp, "1969-12-31", 10)) || + (0 <= zoneoffset && memcmp(timestamp, "1970-01-01", 10))) + return 0; + + hourminute = (strtol(timestamp + 11, NULL, 10) * 60 + + strtol(timestamp + 14, NULL, 10) - + zoneoffset); + + return ((zoneoffset < 0 && hourminute == 1440) || + (0 <= zoneoffset && !hourminute)); +} + +/* + * Get the name etc info from the ---/+++ lines of a traditional patch header + * + * FIXME! The end-of-filename heuristics are kind of screwy. For existing + * files, we can happily check the index for a match, but for creating a + * new file we should try to match whatever "patch" does. I have no idea. + */ +static int parse_traditional_patch(struct apply_state *state, + const char *first, + const char *second, + struct patch *patch) +{ + char *name; + + first += 4; /* skip "--- " */ + second += 4; /* skip "+++ " */ + if (!state->p_value_known) { + int p, q; + p = guess_p_value(state, first); + q = guess_p_value(state, second); + if (p < 0) p = q; + if (0 <= p && p == q) { + state->p_value = p; + state->p_value_known = 1; + } + } + if (is_dev_null(first)) { + patch->is_new = 1; + patch->is_delete = 0; + name = find_name_traditional(state, second, NULL, state->p_value); + patch->new_name = name; + } else if (is_dev_null(second)) { + patch->is_new = 0; + patch->is_delete = 1; + name = find_name_traditional(state, first, NULL, state->p_value); + patch->old_name = name; + } else { + char *first_name; + first_name = find_name_traditional(state, first, NULL, state->p_value); + name = find_name_traditional(state, second, first_name, state->p_value); + free(first_name); + if (has_epoch_timestamp(first)) { + patch->is_new = 1; + patch->is_delete = 0; + patch->new_name = name; + } else if (has_epoch_timestamp(second)) { + patch->is_new = 0; + patch->is_delete = 1; + patch->old_name = name; + } else { + patch->old_name = name; + patch->new_name = xstrdup_or_null(name); + } + } + if (!name) + return error(_("unable to find filename in patch at line %d"), state->linenr); + + return 0; +} + +static int gitdiff_hdrend(struct apply_state *state, + const char *line, + struct patch *patch) +{ + return 1; +} + +/* + * We're anal about diff header consistency, to make + * sure that we don't end up having strange ambiguous + * patches floating around. + * + * As a result, gitdiff_{old|new}name() will check + * their names against any previous information, just + * to make sure.. + */ +#define DIFF_OLD_NAME 0 +#define DIFF_NEW_NAME 1 + +static int gitdiff_verify_name(struct apply_state *state, + const char *line, + int isnull, + char **name, + int side) +{ + if (!*name && !isnull) { + *name = find_name(state, line, NULL, state->p_value, TERM_TAB); + return 0; + } + + if (*name) { + int len = strlen(*name); + char *another; + if (isnull) + return error(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), + *name, state->linenr); + another = find_name(state, line, NULL, state->p_value, TERM_TAB); + if (!another || memcmp(another, *name, len + 1)) { + free(another); + return error((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"), state->linenr); + } + free(another); + } else { + /* expect "/dev/null" */ + if (memcmp("/dev/null", line, 9) || line[9] != '\n') + return error(_("git apply: bad git-diff - expected /dev/null on line %d"), state->linenr); + } + + return 0; +} + +static int gitdiff_oldname(struct apply_state *state, + const char *line, + struct patch *patch) +{ + return gitdiff_verify_name(state, line, + patch->is_new, &patch->old_name, + DIFF_OLD_NAME); +} + +static int gitdiff_newname(struct apply_state *state, + const char *line, + struct patch *patch) +{ + return gitdiff_verify_name(state, line, + patch->is_delete, &patch->new_name, + DIFF_NEW_NAME); +} + +static int gitdiff_oldmode(struct apply_state *state, + const char *line, + struct patch *patch) +{ + patch->old_mode = strtoul(line, NULL, 8); + return 0; +} + +static int gitdiff_newmode(struct apply_state *state, + const char *line, + struct patch *patch) +{ + patch->new_mode = strtoul(line, NULL, 8); + return 0; +} + +static int gitdiff_delete(struct apply_state *state, + const char *line, + struct patch *patch) +{ + patch->is_delete = 1; + free(patch->old_name); + patch->old_name = xstrdup_or_null(patch->def_name); + return gitdiff_oldmode(state, line, patch); +} + +static int gitdiff_newfile(struct apply_state *state, + const char *line, + struct patch *patch) +{ + patch->is_new = 1; + free(patch->new_name); + patch->new_name = xstrdup_or_null(patch->def_name); + return gitdiff_newmode(state, line, patch); +} + +static int gitdiff_copysrc(struct apply_state *state, + const char *line, + struct patch *patch) +{ + patch->is_copy = 1; + free(patch->old_name); + patch->old_name = find_name(state, line, NULL, state->p_value ? state->p_value - 1 : 0, 0); + return 0; +} + +static int gitdiff_copydst(struct apply_state *state, + const char *line, + struct patch *patch) +{ + patch->is_copy = 1; + free(patch->new_name); + patch->new_name = find_name(state, line, NULL, state->p_value ? state->p_value - 1 : 0, 0); + return 0; +} + +static int gitdiff_renamesrc(struct apply_state *state, + const char *line, + struct patch *patch) +{ + patch->is_rename = 1; + free(patch->old_name); + patch->old_name = find_name(state, line, NULL, state->p_value ? state->p_value - 1 : 0, 0); + return 0; +} + +static int gitdiff_renamedst(struct apply_state *state, + const char *line, + struct patch *patch) +{ + patch->is_rename = 1; + free(patch->new_name); + patch->new_name = find_name(state, line, NULL, state->p_value ? state->p_value - 1 : 0, 0); + return 0; +} + +static int gitdiff_similarity(struct apply_state *state, + const char *line, + struct patch *patch) +{ + unsigned long val = strtoul(line, NULL, 10); + if (val <= 100) + patch->score = val; + return 0; +} + +static int gitdiff_dissimilarity(struct apply_state *state, + const char *line, + struct patch *patch) +{ + unsigned long val = strtoul(line, NULL, 10); + if (val <= 100) + patch->score = val; + return 0; +} + +static int gitdiff_index(struct apply_state *state, + const char *line, + struct patch *patch) +{ + /* + * index line is N hexadecimal, "..", N hexadecimal, + * and optional space with octal mode. + */ + const char *ptr, *eol; + int len; + + ptr = strchr(line, '.'); + if (!ptr || ptr[1] != '.' || 40 < ptr - line) + return 0; + len = ptr - line; + memcpy(patch->old_sha1_prefix, line, len); + patch->old_sha1_prefix[len] = 0; + + line = ptr + 2; + ptr = strchr(line, ' '); + eol = strchrnul(line, '\n'); + + if (!ptr || eol < ptr) + ptr = eol; + len = ptr - line; + + if (40 < len) + return 0; + memcpy(patch->new_sha1_prefix, line, len); + patch->new_sha1_prefix[len] = 0; + if (*ptr == ' ') + patch->old_mode = strtoul(ptr+1, NULL, 8); + return 0; +} + +/* + * This is normal for a diff that doesn't change anything: we'll fall through + * into the next diff. Tell the parser to break out. + */ +static int gitdiff_unrecognized(struct apply_state *state, + const char *line, + struct patch *patch) +{ + return 1; +} + +/* + * Skip p_value leading components from "line"; as we do not accept + * absolute paths, return NULL in that case. + */ +static const char *skip_tree_prefix(struct apply_state *state, + const char *line, + int llen) +{ + int nslash; + int i; + + if (!state->p_value) + return (llen && line[0] == '/') ? NULL : line; + + nslash = state->p_value; + for (i = 0; i < llen; i++) { + int ch = line[i]; + if (ch == '/' && --nslash <= 0) + return (i == 0) ? NULL : &line[i + 1]; + } + return NULL; +} + +/* + * This is to extract the same name that appears on "diff --git" + * line. We do not find and return anything if it is a rename + * patch, and it is OK because we will find the name elsewhere. + * We need to reliably find name only when it is mode-change only, + * creation or deletion of an empty file. In any of these cases, + * both sides are the same name under a/ and b/ respectively. + */ +static char *git_header_name(struct apply_state *state, + const char *line, + int llen) +{ + const char *name; + const char *second = NULL; + size_t len, line_len; + + line += strlen("diff --git "); + llen -= strlen("diff --git "); + + if (*line == '"') { + const char *cp; + struct strbuf first = STRBUF_INIT; + struct strbuf sp = STRBUF_INIT; + + if (unquote_c_style(&first, line, &second)) + goto free_and_fail1; + + /* strip the a/b prefix including trailing slash */ + cp = skip_tree_prefix(state, first.buf, first.len); + if (!cp) + goto free_and_fail1; + strbuf_remove(&first, 0, cp - first.buf); + + /* + * second points at one past closing dq of name. + * find the second name. + */ + while ((second < line + llen) && isspace(*second)) + second++; + + if (line + llen <= second) + goto free_and_fail1; + if (*second == '"') { + if (unquote_c_style(&sp, second, NULL)) + goto free_and_fail1; + cp = skip_tree_prefix(state, sp.buf, sp.len); + if (!cp) + goto free_and_fail1; + /* They must match, otherwise ignore */ + if (strcmp(cp, first.buf)) + goto free_and_fail1; + strbuf_release(&sp); + return strbuf_detach(&first, NULL); + } + + /* unquoted second */ + cp = skip_tree_prefix(state, second, line + llen - second); + if (!cp) + goto free_and_fail1; + if (line + llen - cp != first.len || + memcmp(first.buf, cp, first.len)) + goto free_and_fail1; + return strbuf_detach(&first, NULL); + + free_and_fail1: + strbuf_release(&first); + strbuf_release(&sp); + return NULL; + } + + /* unquoted first name */ + name = skip_tree_prefix(state, line, llen); + if (!name) + return NULL; + + /* + * since the first name is unquoted, a dq if exists must be + * the beginning of the second name. + */ + for (second = name; second < line + llen; second++) { + if (*second == '"') { + struct strbuf sp = STRBUF_INIT; + const char *np; + + if (unquote_c_style(&sp, second, NULL)) + goto free_and_fail2; + + np = skip_tree_prefix(state, sp.buf, sp.len); + if (!np) + goto free_and_fail2; + + len = sp.buf + sp.len - np; + if (len < second - name && + !strncmp(np, name, len) && + isspace(name[len])) { + /* Good */ + strbuf_remove(&sp, 0, np - sp.buf); + return strbuf_detach(&sp, NULL); + } + + free_and_fail2: + strbuf_release(&sp); + return NULL; + } + } + + /* + * Accept a name only if it shows up twice, exactly the same + * form. + */ + second = strchr(name, '\n'); + if (!second) + return NULL; + line_len = second - name; + for (len = 0 ; ; len++) { + switch (name[len]) { + default: + continue; + case '\n': + return NULL; + case '\t': case ' ': + /* + * Is this the separator between the preimage + * and the postimage pathname? Again, we are + * only interested in the case where there is + * no rename, as this is only to set def_name + * and a rename patch has the names elsewhere + * in an unambiguous form. + */ + if (!name[len + 1]) + return NULL; /* no postimage name */ + second = skip_tree_prefix(state, name + len + 1, + line_len - (len + 1)); + if (!second) + return NULL; + /* + * Does len bytes starting at "name" and "second" + * (that are separated by one HT or SP we just + * found) exactly match? + */ + if (second[len] == '\n' && !strncmp(name, second, len)) + return xmemdupz(name, len); + } + } +} + +/* Verify that we recognize the lines following a git header */ +static int parse_git_header(struct apply_state *state, + const char *line, + int len, + unsigned int size, + struct patch *patch) +{ + unsigned long offset; + + /* A git diff has explicit new/delete information, so we don't guess */ + patch->is_new = 0; + patch->is_delete = 0; + + /* + * Some things may not have the old name in the + * rest of the headers anywhere (pure mode changes, + * or removing or adding empty files), so we get + * the default name from the header. + */ + patch->def_name = git_header_name(state, line, len); + if (patch->def_name && state->root.len) { + char *s = xstrfmt("%s%s", state->root.buf, patch->def_name); + free(patch->def_name); + patch->def_name = s; + } + + line += len; + size -= len; + state->linenr++; + for (offset = len ; size > 0 ; offset += len, size -= len, line += len, state->linenr++) { + static const struct opentry { + const char *str; + int (*fn)(struct apply_state *, const char *, struct patch *); + } optable[] = { + { "@@ -", gitdiff_hdrend }, + { "--- ", gitdiff_oldname }, + { "+++ ", gitdiff_newname }, + { "old mode ", gitdiff_oldmode }, + { "new mode ", gitdiff_newmode }, + { "deleted file mode ", gitdiff_delete }, + { "new file mode ", gitdiff_newfile }, + { "copy from ", gitdiff_copysrc }, + { "copy to ", gitdiff_copydst }, + { "rename old ", gitdiff_renamesrc }, + { "rename new ", gitdiff_renamedst }, + { "rename from ", gitdiff_renamesrc }, + { "rename to ", gitdiff_renamedst }, + { "similarity index ", gitdiff_similarity }, + { "dissimilarity index ", gitdiff_dissimilarity }, + { "index ", gitdiff_index }, + { "", gitdiff_unrecognized }, + }; + int i; + + len = linelen(line, size); + if (!len || line[len-1] != '\n') + break; + for (i = 0; i < ARRAY_SIZE(optable); i++) { + const struct opentry *p = optable + i; + int oplen = strlen(p->str); + int res; + if (len < oplen || memcmp(p->str, line, oplen)) + continue; + res = p->fn(state, line + oplen, patch); + if (res < 0) + return -1; + if (res > 0) + return offset; + break; + } + } + + return offset; +} + +static int parse_num(const char *line, unsigned long *p) +{ + char *ptr; + + if (!isdigit(*line)) + return 0; + *p = strtoul(line, &ptr, 10); + return ptr - line; +} + +static int parse_range(const char *line, int len, int offset, const char *expect, + unsigned long *p1, unsigned long *p2) +{ + int digits, ex; + + if (offset < 0 || offset >= len) + return -1; + line += offset; + len -= offset; + + digits = parse_num(line, p1); + if (!digits) + return -1; + + offset += digits; + line += digits; + len -= digits; + + *p2 = 1; + if (*line == ',') { + digits = parse_num(line+1, p2); + if (!digits) + return -1; + + offset += digits+1; + line += digits+1; + len -= digits+1; + } + + ex = strlen(expect); + if (ex > len) + return -1; + if (memcmp(line, expect, ex)) + return -1; + + return offset + ex; +} + +static void recount_diff(const char *line, int size, struct fragment *fragment) +{ + int oldlines = 0, newlines = 0, ret = 0; + + if (size < 1) { + warning("recount: ignore empty hunk"); + return; + } + + for (;;) { + int len = linelen(line, size); + size -= len; + line += len; + + if (size < 1) + break; + + switch (*line) { + case ' ': case '\n': + newlines++; + /* fall through */ + case '-': + oldlines++; + continue; + case '+': + newlines++; + continue; + case '\\': + continue; + case '@': + ret = size < 3 || !starts_with(line, "@@ "); + break; + case 'd': + ret = size < 5 || !starts_with(line, "diff "); + break; + default: + ret = -1; + break; + } + if (ret) { + warning(_("recount: unexpected line: %.*s"), + (int)linelen(line, size), line); + return; + } + break; + } + fragment->oldlines = oldlines; + fragment->newlines = newlines; +} + +/* + * Parse a unified diff fragment header of the + * form "@@ -a,b +c,d @@" + */ +static int parse_fragment_header(const char *line, int len, struct fragment *fragment) +{ + int offset; + + if (!len || line[len-1] != '\n') + return -1; + + /* Figure out the number of lines in a fragment */ + offset = parse_range(line, len, 4, " +", &fragment->oldpos, &fragment->oldlines); + offset = parse_range(line, len, offset, " @@", &fragment->newpos, &fragment->newlines); + + return offset; +} + +/* + * Find file diff header + * + * Returns: + * -1 if no header was found + * -128 in case of error + * the size of the header in bytes (called "offset") otherwise + */ +static int find_header(struct apply_state *state, + const char *line, + unsigned long size, + int *hdrsize, + struct patch *patch) +{ + unsigned long offset, len; + + patch->is_toplevel_relative = 0; + patch->is_rename = patch->is_copy = 0; + patch->is_new = patch->is_delete = -1; + patch->old_mode = patch->new_mode = 0; + patch->old_name = patch->new_name = NULL; + for (offset = 0; size > 0; offset += len, size -= len, line += len, state->linenr++) { + unsigned long nextlen; + + len = linelen(line, size); + if (!len) + break; + + /* Testing this early allows us to take a few shortcuts.. */ + if (len < 6) + continue; + + /* + * Make sure we don't find any unconnected patch fragments. + * That's a sign that we didn't find a header, and that a + * patch has become corrupted/broken up. + */ + if (!memcmp("@@ -", line, 4)) { + struct fragment dummy; + if (parse_fragment_header(line, len, &dummy) < 0) + continue; + error(_("patch fragment without header at line %d: %.*s"), + state->linenr, (int)len-1, line); + return -128; + } + + if (size < len + 6) + break; + + /* + * Git patch? It might not have a real patch, just a rename + * or mode change, so we handle that specially + */ + if (!memcmp("diff --git ", line, 11)) { + int git_hdr_len = parse_git_header(state, line, len, size, patch); + if (git_hdr_len < 0) + return -128; + if (git_hdr_len <= len) + continue; + if (!patch->old_name && !patch->new_name) { + if (!patch->def_name) { + error(Q_("git diff header lacks filename information when removing " + "%d leading pathname component (line %d)", + "git diff header lacks filename information when removing " + "%d leading pathname components (line %d)", + state->p_value), + state->p_value, state->linenr); + return -128; + } + patch->old_name = xstrdup(patch->def_name); + patch->new_name = xstrdup(patch->def_name); + } + if (!patch->is_delete && !patch->new_name) { + error(_("git diff header lacks filename information " + "(line %d)"), state->linenr); + return -128; + } + patch->is_toplevel_relative = 1; + *hdrsize = git_hdr_len; + return offset; + } + + /* --- followed by +++ ? */ + if (memcmp("--- ", line, 4) || memcmp("+++ ", line + len, 4)) + continue; + + /* + * We only accept unified patches, so we want it to + * at least have "@@ -a,b +c,d @@\n", which is 14 chars + * minimum ("@@ -0,0 +1 @@\n" is the shortest). + */ + nextlen = linelen(line + len, size - len); + if (size < nextlen + 14 || memcmp("@@ -", line + len + nextlen, 4)) + continue; + + /* Ok, we'll consider it a patch */ + if (parse_traditional_patch(state, line, line+len, patch)) + return -128; + *hdrsize = len + nextlen; + state->linenr += 2; + return offset; + } + return -1; +} + +static void record_ws_error(struct apply_state *state, + unsigned result, + const char *line, + int len, + int linenr) +{ + char *err; + + if (!result) + return; + + state->whitespace_error++; + if (state->squelch_whitespace_errors && + state->squelch_whitespace_errors < state->whitespace_error) + return; + + err = whitespace_error_string(result); + if (state->apply_verbosity > verbosity_silent) + fprintf(stderr, "%s:%d: %s.\n%.*s\n", + state->patch_input_file, linenr, err, len, line); + free(err); +} + +static void check_whitespace(struct apply_state *state, + const char *line, + int len, + unsigned ws_rule) +{ + unsigned result = ws_check(line + 1, len - 1, ws_rule); + + record_ws_error(state, result, line + 1, len - 2, state->linenr); +} + +/* + * Parse a unified diff. Note that this really needs to parse each + * fragment separately, since the only way to know the difference + * between a "---" that is part of a patch, and a "---" that starts + * the next patch is to look at the line counts.. + */ +static int parse_fragment(struct apply_state *state, + const char *line, + unsigned long size, + struct patch *patch, + struct fragment *fragment) +{ + int added, deleted; + int len = linelen(line, size), offset; + unsigned long oldlines, newlines; + unsigned long leading, trailing; + + offset = parse_fragment_header(line, len, fragment); + if (offset < 0) + return -1; + if (offset > 0 && patch->recount) + recount_diff(line + offset, size - offset, fragment); + oldlines = fragment->oldlines; + newlines = fragment->newlines; + leading = 0; + trailing = 0; + + /* Parse the thing.. */ + line += len; + size -= len; + state->linenr++; + added = deleted = 0; + for (offset = len; + 0 < size; + offset += len, size -= len, line += len, state->linenr++) { + if (!oldlines && !newlines) + break; + len = linelen(line, size); + if (!len || line[len-1] != '\n') + return -1; + switch (*line) { + default: + return -1; + case '\n': /* newer GNU diff, an empty context line */ + case ' ': + oldlines--; + newlines--; + if (!deleted && !added) + leading++; + trailing++; + if (!state->apply_in_reverse && + state->ws_error_action == correct_ws_error) + check_whitespace(state, line, len, patch->ws_rule); + break; + case '-': + if (state->apply_in_reverse && + state->ws_error_action != nowarn_ws_error) + check_whitespace(state, line, len, patch->ws_rule); + deleted++; + oldlines--; + trailing = 0; + break; + case '+': + if (!state->apply_in_reverse && + state->ws_error_action != nowarn_ws_error) + check_whitespace(state, line, len, patch->ws_rule); + added++; + newlines--; + trailing = 0; + break; + + /* + * We allow "\ No newline at end of file". Depending + * on locale settings when the patch was produced we + * don't know what this line looks like. The only + * thing we do know is that it begins with "\ ". + * Checking for 12 is just for sanity check -- any + * l10n of "\ No newline..." is at least that long. + */ + case '\\': + if (len < 12 || memcmp(line, "\\ ", 2)) + return -1; + break; + } + } + if (oldlines || newlines) + return -1; + if (!deleted && !added) + return -1; + + fragment->leading = leading; + fragment->trailing = trailing; + + /* + * If a fragment ends with an incomplete line, we failed to include + * it in the above loop because we hit oldlines == newlines == 0 + * before seeing it. + */ + if (12 < size && !memcmp(line, "\\ ", 2)) + offset += linelen(line, size); + + patch->lines_added += added; + patch->lines_deleted += deleted; + + if (0 < patch->is_new && oldlines) + return error(_("new file depends on old contents")); + if (0 < patch->is_delete && newlines) + return error(_("deleted file still has contents")); + return offset; +} + +/* + * We have seen "diff --git a/... b/..." header (or a traditional patch + * header). Read hunks that belong to this patch into fragments and hang + * them to the given patch structure. + * + * The (fragment->patch, fragment->size) pair points into the memory given + * by the caller, not a copy, when we return. + * + * Returns: + * -1 in case of error, + * the number of bytes in the patch otherwise. + */ +static int parse_single_patch(struct apply_state *state, + const char *line, + unsigned long size, + struct patch *patch) +{ + unsigned long offset = 0; + unsigned long oldlines = 0, newlines = 0, context = 0; + struct fragment **fragp = &patch->fragments; + + while (size > 4 && !memcmp(line, "@@ -", 4)) { + struct fragment *fragment; + int len; + + fragment = xcalloc(1, sizeof(*fragment)); + fragment->linenr = state->linenr; + len = parse_fragment(state, line, size, patch, fragment); + if (len <= 0) { + free(fragment); + return error(_("corrupt patch at line %d"), state->linenr); + } + fragment->patch = line; + fragment->size = len; + oldlines += fragment->oldlines; + newlines += fragment->newlines; + context += fragment->leading + fragment->trailing; + + *fragp = fragment; + fragp = &fragment->next; + + offset += len; + line += len; + size -= len; + } + + /* + * If something was removed (i.e. we have old-lines) it cannot + * be creation, and if something was added it cannot be + * deletion. However, the reverse is not true; --unified=0 + * patches that only add are not necessarily creation even + * though they do not have any old lines, and ones that only + * delete are not necessarily deletion. + * + * Unfortunately, a real creation/deletion patch do _not_ have + * any context line by definition, so we cannot safely tell it + * apart with --unified=0 insanity. At least if the patch has + * more than one hunk it is not creation or deletion. + */ + if (patch->is_new < 0 && + (oldlines || (patch->fragments && patch->fragments->next))) + patch->is_new = 0; + if (patch->is_delete < 0 && + (newlines || (patch->fragments && patch->fragments->next))) + patch->is_delete = 0; + + if (0 < patch->is_new && oldlines) + return error(_("new file %s depends on old contents"), patch->new_name); + if (0 < patch->is_delete && newlines) + return error(_("deleted file %s still has contents"), patch->old_name); + if (!patch->is_delete && !newlines && context && state->apply_verbosity > verbosity_silent) + fprintf_ln(stderr, + _("** warning: " + "file %s becomes empty but is not deleted"), + patch->new_name); + + return offset; +} + +static inline int metadata_changes(struct patch *patch) +{ + return patch->is_rename > 0 || + patch->is_copy > 0 || + patch->is_new > 0 || + patch->is_delete || + (patch->old_mode && patch->new_mode && + patch->old_mode != patch->new_mode); +} + +static char *inflate_it(const void *data, unsigned long size, + unsigned long inflated_size) +{ + git_zstream stream; + void *out; + int st; + + memset(&stream, 0, sizeof(stream)); + + stream.next_in = (unsigned char *)data; + stream.avail_in = size; + stream.next_out = out = xmalloc(inflated_size); + stream.avail_out = inflated_size; + git_inflate_init(&stream); + st = git_inflate(&stream, Z_FINISH); + git_inflate_end(&stream); + if ((st != Z_STREAM_END) || stream.total_out != inflated_size) { + free(out); + return NULL; + } + return out; +} + +/* + * Read a binary hunk and return a new fragment; fragment->patch + * points at an allocated memory that the caller must free, so + * it is marked as "->free_patch = 1". + */ +static struct fragment *parse_binary_hunk(struct apply_state *state, + char **buf_p, + unsigned long *sz_p, + int *status_p, + int *used_p) +{ + /* + * Expect a line that begins with binary patch method ("literal" + * or "delta"), followed by the length of data before deflating. + * a sequence of 'length-byte' followed by base-85 encoded data + * should follow, terminated by a newline. + * + * Each 5-byte sequence of base-85 encodes up to 4 bytes, + * and we would limit the patch line to 66 characters, + * so one line can fit up to 13 groups that would decode + * to 52 bytes max. The length byte 'A'-'Z' corresponds + * to 1-26 bytes, and 'a'-'z' corresponds to 27-52 bytes. + */ + int llen, used; + unsigned long size = *sz_p; + char *buffer = *buf_p; + int patch_method; + unsigned long origlen; + char *data = NULL; + int hunk_size = 0; + struct fragment *frag; + + llen = linelen(buffer, size); + used = llen; + + *status_p = 0; + + if (starts_with(buffer, "delta ")) { + patch_method = BINARY_DELTA_DEFLATED; + origlen = strtoul(buffer + 6, NULL, 10); + } + else if (starts_with(buffer, "literal ")) { + patch_method = BINARY_LITERAL_DEFLATED; + origlen = strtoul(buffer + 8, NULL, 10); + } + else + return NULL; + + state->linenr++; + buffer += llen; + while (1) { + int byte_length, max_byte_length, newsize; + llen = linelen(buffer, size); + used += llen; + state->linenr++; + if (llen == 1) { + /* consume the blank line */ + buffer++; + size--; + break; + } + /* + * Minimum line is "A00000\n" which is 7-byte long, + * and the line length must be multiple of 5 plus 2. + */ + if ((llen < 7) || (llen-2) % 5) + goto corrupt; + max_byte_length = (llen - 2) / 5 * 4; + byte_length = *buffer; + if ('A' <= byte_length && byte_length <= 'Z') + byte_length = byte_length - 'A' + 1; + else if ('a' <= byte_length && byte_length <= 'z') + byte_length = byte_length - 'a' + 27; + else + goto corrupt; + /* if the input length was not multiple of 4, we would + * have filler at the end but the filler should never + * exceed 3 bytes + */ + if (max_byte_length < byte_length || + byte_length <= max_byte_length - 4) + goto corrupt; + newsize = hunk_size + byte_length; + data = xrealloc(data, newsize); + if (decode_85(data + hunk_size, buffer + 1, byte_length)) + goto corrupt; + hunk_size = newsize; + buffer += llen; + size -= llen; + } + + frag = xcalloc(1, sizeof(*frag)); + frag->patch = inflate_it(data, hunk_size, origlen); + frag->free_patch = 1; + if (!frag->patch) + goto corrupt; + free(data); + frag->size = origlen; + *buf_p = buffer; + *sz_p = size; + *used_p = used; + frag->binary_patch_method = patch_method; + return frag; + + corrupt: + free(data); + *status_p = -1; + error(_("corrupt binary patch at line %d: %.*s"), + state->linenr-1, llen-1, buffer); + return NULL; +} + +/* + * Returns: + * -1 in case of error, + * the length of the parsed binary patch otherwise + */ +static int parse_binary(struct apply_state *state, + char *buffer, + unsigned long size, + struct patch *patch) +{ + /* + * We have read "GIT binary patch\n"; what follows is a line + * that says the patch method (currently, either "literal" or + * "delta") and the length of data before deflating; a + * sequence of 'length-byte' followed by base-85 encoded data + * follows. + * + * When a binary patch is reversible, there is another binary + * hunk in the same format, starting with patch method (either + * "literal" or "delta") with the length of data, and a sequence + * of length-byte + base-85 encoded data, terminated with another + * empty line. This data, when applied to the postimage, produces + * the preimage. + */ + struct fragment *forward; + struct fragment *reverse; + int status; + int used, used_1; + + forward = parse_binary_hunk(state, &buffer, &size, &status, &used); + if (!forward && !status) + /* there has to be one hunk (forward hunk) */ + return error(_("unrecognized binary patch at line %d"), state->linenr-1); + if (status) + /* otherwise we already gave an error message */ + return status; + + reverse = parse_binary_hunk(state, &buffer, &size, &status, &used_1); + if (reverse) + used += used_1; + else if (status) { + /* + * Not having reverse hunk is not an error, but having + * a corrupt reverse hunk is. + */ + free((void*) forward->patch); + free(forward); + return status; + } + forward->next = reverse; + patch->fragments = forward; + patch->is_binary = 1; + return used; +} + +static void prefix_one(struct apply_state *state, char **name) +{ + char *old_name = *name; + if (!old_name) + return; + *name = xstrdup(prefix_filename(state->prefix, state->prefix_length, *name)); + free(old_name); +} + +static void prefix_patch(struct apply_state *state, struct patch *p) +{ + if (!state->prefix || p->is_toplevel_relative) + return; + prefix_one(state, &p->new_name); + prefix_one(state, &p->old_name); +} + +/* + * include/exclude + */ + +static void add_name_limit(struct apply_state *state, + const char *name, + int exclude) +{ + struct string_list_item *it; + + it = string_list_append(&state->limit_by_name, name); + it->util = exclude ? NULL : (void *) 1; +} + +static int use_patch(struct apply_state *state, struct patch *p) +{ + const char *pathname = p->new_name ? p->new_name : p->old_name; + int i; + + /* Paths outside are not touched regardless of "--include" */ + if (0 < state->prefix_length) { + int pathlen = strlen(pathname); + if (pathlen <= state->prefix_length || + memcmp(state->prefix, pathname, state->prefix_length)) + return 0; + } + + /* See if it matches any of exclude/include rule */ + for (i = 0; i < state->limit_by_name.nr; i++) { + struct string_list_item *it = &state->limit_by_name.items[i]; + if (!wildmatch(it->string, pathname, 0, NULL)) + return (it->util != NULL); + } + + /* + * If we had any include, a path that does not match any rule is + * not used. Otherwise, we saw bunch of exclude rules (or none) + * and such a path is used. + */ + return !state->has_include; +} + +/* + * Read the patch text in "buffer" that extends for "size" bytes; stop + * reading after seeing a single patch (i.e. changes to a single file). + * Create fragments (i.e. patch hunks) and hang them to the given patch. + * + * Returns: + * -1 if no header was found or parse_binary() failed, + * -128 on another error, + * the number of bytes consumed otherwise, + * so that the caller can call us again for the next patch. + */ +static int parse_chunk(struct apply_state *state, char *buffer, unsigned long size, struct patch *patch) +{ + int hdrsize, patchsize; + int offset = find_header(state, buffer, size, &hdrsize, patch); + + if (offset < 0) + return offset; + + prefix_patch(state, patch); + + if (!use_patch(state, patch)) + patch->ws_rule = 0; + else + patch->ws_rule = whitespace_rule(patch->new_name + ? patch->new_name + : patch->old_name); + + patchsize = parse_single_patch(state, + buffer + offset + hdrsize, + size - offset - hdrsize, + patch); + + if (patchsize < 0) + return -128; + + if (!patchsize) { + static const char git_binary[] = "GIT binary patch\n"; + int hd = hdrsize + offset; + unsigned long llen = linelen(buffer + hd, size - hd); + + if (llen == sizeof(git_binary) - 1 && + !memcmp(git_binary, buffer + hd, llen)) { + int used; + state->linenr++; + used = parse_binary(state, buffer + hd + llen, + size - hd - llen, patch); + if (used < 0) + return -1; + if (used) + patchsize = used + llen; + else + patchsize = 0; + } + else if (!memcmp(" differ\n", buffer + hd + llen - 8, 8)) { + static const char *binhdr[] = { + "Binary files ", + "Files ", + NULL, + }; + int i; + for (i = 0; binhdr[i]; i++) { + int len = strlen(binhdr[i]); + if (len < size - hd && + !memcmp(binhdr[i], buffer + hd, len)) { + state->linenr++; + patch->is_binary = 1; + patchsize = llen; + break; + } + } + } + + /* Empty patch cannot be applied if it is a text patch + * without metadata change. A binary patch appears + * empty to us here. + */ + if ((state->apply || state->check) && + (!patch->is_binary && !metadata_changes(patch))) { + error(_("patch with only garbage at line %d"), state->linenr); + return -128; + } + } + + return offset + hdrsize + patchsize; +} + +#define swap(a,b) myswap((a),(b),sizeof(a)) + +#define myswap(a, b, size) do { \ + unsigned char mytmp[size]; \ + memcpy(mytmp, &a, size); \ + memcpy(&a, &b, size); \ + memcpy(&b, mytmp, size); \ +} while (0) + +static void reverse_patches(struct patch *p) +{ + for (; p; p = p->next) { + struct fragment *frag = p->fragments; + + swap(p->new_name, p->old_name); + swap(p->new_mode, p->old_mode); + swap(p->is_new, p->is_delete); + swap(p->lines_added, p->lines_deleted); + swap(p->old_sha1_prefix, p->new_sha1_prefix); + + for (; frag; frag = frag->next) { + swap(frag->newpos, frag->oldpos); + swap(frag->newlines, frag->oldlines); + } + } +} + +static const char pluses[] = +"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; +static const char minuses[]= +"----------------------------------------------------------------------"; + +static void show_stats(struct apply_state *state, struct patch *patch) +{ + struct strbuf qname = STRBUF_INIT; + char *cp = patch->new_name ? patch->new_name : patch->old_name; + int max, add, del; + + quote_c_style(cp, &qname, NULL, 0); + + /* + * "scale" the filename + */ + max = state->max_len; + if (max > 50) + max = 50; + + if (qname.len > max) { + cp = strchr(qname.buf + qname.len + 3 - max, '/'); + if (!cp) + cp = qname.buf + qname.len + 3 - max; + strbuf_splice(&qname, 0, cp - qname.buf, "...", 3); + } + + if (patch->is_binary) { + printf(" %-*s | Bin\n", max, qname.buf); + strbuf_release(&qname); + return; + } + + printf(" %-*s |", max, qname.buf); + strbuf_release(&qname); + + /* + * scale the add/delete + */ + max = max + state->max_change > 70 ? 70 - max : state->max_change; + add = patch->lines_added; + del = patch->lines_deleted; + + if (state->max_change > 0) { + int total = ((add + del) * max + state->max_change / 2) / state->max_change; + add = (add * max + state->max_change / 2) / state->max_change; + del = total - add; + } + printf("%5d %.*s%.*s\n", patch->lines_added + patch->lines_deleted, + add, pluses, del, minuses); +} + +static int read_old_data(struct stat *st, const char *path, struct strbuf *buf) +{ + switch (st->st_mode & S_IFMT) { + case S_IFLNK: + if (strbuf_readlink(buf, path, st->st_size) < 0) + return error(_("unable to read symlink %s"), path); + return 0; + case S_IFREG: + if (strbuf_read_file(buf, path, st->st_size) != st->st_size) + return error(_("unable to open or read %s"), path); + convert_to_git(path, buf->buf, buf->len, buf, 0); + return 0; + default: + return -1; + } +} + +/* + * Update the preimage, and the common lines in postimage, + * from buffer buf of length len. If postlen is 0 the postimage + * is updated in place, otherwise it's updated on a new buffer + * of length postlen + */ + +static void update_pre_post_images(struct image *preimage, + struct image *postimage, + char *buf, + size_t len, size_t postlen) +{ + int i, ctx, reduced; + char *new, *old, *fixed; + struct image fixed_preimage; + + /* + * Update the preimage with whitespace fixes. Note that we + * are not losing preimage->buf -- apply_one_fragment() will + * free "oldlines". + */ + prepare_image(&fixed_preimage, buf, len, 1); + assert(postlen + ? fixed_preimage.nr == preimage->nr + : fixed_preimage.nr <= preimage->nr); + for (i = 0; i < fixed_preimage.nr; i++) + fixed_preimage.line[i].flag = preimage->line[i].flag; + free(preimage->line_allocated); + *preimage = fixed_preimage; + + /* + * Adjust the common context lines in postimage. This can be + * done in-place when we are shrinking it with whitespace + * fixing, but needs a new buffer when ignoring whitespace or + * expanding leading tabs to spaces. + * + * We trust the caller to tell us if the update can be done + * in place (postlen==0) or not. + */ + old = postimage->buf; + if (postlen) + new = postimage->buf = xmalloc(postlen); + else + new = old; + fixed = preimage->buf; + + for (i = reduced = ctx = 0; i < postimage->nr; i++) { + size_t l_len = postimage->line[i].len; + if (!(postimage->line[i].flag & LINE_COMMON)) { + /* an added line -- no counterparts in preimage */ + memmove(new, old, l_len); + old += l_len; + new += l_len; + continue; + } + + /* a common context -- skip it in the original postimage */ + old += l_len; + + /* and find the corresponding one in the fixed preimage */ + while (ctx < preimage->nr && + !(preimage->line[ctx].flag & LINE_COMMON)) { + fixed += preimage->line[ctx].len; + ctx++; + } + + /* + * preimage is expected to run out, if the caller + * fixed addition of trailing blank lines. + */ + if (preimage->nr <= ctx) { + reduced++; + continue; + } + + /* and copy it in, while fixing the line length */ + l_len = preimage->line[ctx].len; + memcpy(new, fixed, l_len); + new += l_len; + fixed += l_len; + postimage->line[i].len = l_len; + ctx++; + } + + if (postlen + ? postlen < new - postimage->buf + : postimage->len < new - postimage->buf) + die("BUG: caller miscounted postlen: asked %d, orig = %d, used = %d", + (int)postlen, (int) postimage->len, (int)(new - postimage->buf)); + + /* Fix the length of the whole thing */ + postimage->len = new - postimage->buf; + postimage->nr -= reduced; +} + +static int line_by_line_fuzzy_match(struct image *img, + struct image *preimage, + struct image *postimage, + unsigned long try, + int try_lno, + int preimage_limit) +{ + int i; + size_t imgoff = 0; + size_t preoff = 0; + size_t postlen = postimage->len; + size_t extra_chars; + char *buf; + char *preimage_eof; + char *preimage_end; + struct strbuf fixed; + char *fixed_buf; + size_t fixed_len; + + for (i = 0; i < preimage_limit; i++) { + size_t prelen = preimage->line[i].len; + size_t imglen = img->line[try_lno+i].len; + + if (!fuzzy_matchlines(img->buf + try + imgoff, imglen, + preimage->buf + preoff, prelen)) + return 0; + if (preimage->line[i].flag & LINE_COMMON) + postlen += imglen - prelen; + imgoff += imglen; + preoff += prelen; + } + + /* + * Ok, the preimage matches with whitespace fuzz. + * + * imgoff now holds the true length of the target that + * matches the preimage before the end of the file. + * + * Count the number of characters in the preimage that fall + * beyond the end of the file and make sure that all of them + * are whitespace characters. (This can only happen if + * we are removing blank lines at the end of the file.) + */ + buf = preimage_eof = preimage->buf + preoff; + for ( ; i < preimage->nr; i++) + preoff += preimage->line[i].len; + preimage_end = preimage->buf + preoff; + for ( ; buf < preimage_end; buf++) + if (!isspace(*buf)) + return 0; + + /* + * Update the preimage and the common postimage context + * lines to use the same whitespace as the target. + * If whitespace is missing in the target (i.e. + * if the preimage extends beyond the end of the file), + * use the whitespace from the preimage. + */ + extra_chars = preimage_end - preimage_eof; + strbuf_init(&fixed, imgoff + extra_chars); + strbuf_add(&fixed, img->buf + try, imgoff); + strbuf_add(&fixed, preimage_eof, extra_chars); + fixed_buf = strbuf_detach(&fixed, &fixed_len); + update_pre_post_images(preimage, postimage, + fixed_buf, fixed_len, postlen); + return 1; +} + +static int match_fragment(struct apply_state *state, + struct image *img, + struct image *preimage, + struct image *postimage, + unsigned long try, + int try_lno, + unsigned ws_rule, + int match_beginning, int match_end) +{ + int i; + char *fixed_buf, *buf, *orig, *target; + struct strbuf fixed; + size_t fixed_len, postlen; + int preimage_limit; + + if (preimage->nr + try_lno <= img->nr) { + /* + * The hunk falls within the boundaries of img. + */ + preimage_limit = preimage->nr; + if (match_end && (preimage->nr + try_lno != img->nr)) + return 0; + } else if (state->ws_error_action == correct_ws_error && + (ws_rule & WS_BLANK_AT_EOF)) { + /* + * This hunk extends beyond the end of img, and we are + * removing blank lines at the end of the file. This + * many lines from the beginning of the preimage must + * match with img, and the remainder of the preimage + * must be blank. + */ + preimage_limit = img->nr - try_lno; + } else { + /* + * The hunk extends beyond the end of the img and + * we are not removing blanks at the end, so we + * should reject the hunk at this position. + */ + return 0; + } + + if (match_beginning && try_lno) + return 0; + + /* Quick hash check */ + for (i = 0; i < preimage_limit; i++) + if ((img->line[try_lno + i].flag & LINE_PATCHED) || + (preimage->line[i].hash != img->line[try_lno + i].hash)) + return 0; + + if (preimage_limit == preimage->nr) { + /* + * Do we have an exact match? If we were told to match + * at the end, size must be exactly at try+fragsize, + * otherwise try+fragsize must be still within the preimage, + * and either case, the old piece should match the preimage + * exactly. + */ + if ((match_end + ? (try + preimage->len == img->len) + : (try + preimage->len <= img->len)) && + !memcmp(img->buf + try, preimage->buf, preimage->len)) + return 1; + } else { + /* + * The preimage extends beyond the end of img, so + * there cannot be an exact match. + * + * There must be one non-blank context line that match + * a line before the end of img. + */ + char *buf_end; + + buf = preimage->buf; + buf_end = buf; + for (i = 0; i < preimage_limit; i++) + buf_end += preimage->line[i].len; + + for ( ; buf < buf_end; buf++) + if (!isspace(*buf)) + break; + if (buf == buf_end) + return 0; + } + + /* + * No exact match. If we are ignoring whitespace, run a line-by-line + * fuzzy matching. We collect all the line length information because + * we need it to adjust whitespace if we match. + */ + if (state->ws_ignore_action == ignore_ws_change) + return line_by_line_fuzzy_match(img, preimage, postimage, + try, try_lno, preimage_limit); + + if (state->ws_error_action != correct_ws_error) + return 0; + + /* + * The hunk does not apply byte-by-byte, but the hash says + * it might with whitespace fuzz. We weren't asked to + * ignore whitespace, we were asked to correct whitespace + * errors, so let's try matching after whitespace correction. + * + * While checking the preimage against the target, whitespace + * errors in both fixed, we count how large the corresponding + * postimage needs to be. The postimage prepared by + * apply_one_fragment() has whitespace errors fixed on added + * lines already, but the common lines were propagated as-is, + * which may become longer when their whitespace errors are + * fixed. + */ + + /* First count added lines in postimage */ + postlen = 0; + for (i = 0; i < postimage->nr; i++) { + if (!(postimage->line[i].flag & LINE_COMMON)) + postlen += postimage->line[i].len; + } + + /* + * The preimage may extend beyond the end of the file, + * but in this loop we will only handle the part of the + * preimage that falls within the file. + */ + strbuf_init(&fixed, preimage->len + 1); + orig = preimage->buf; + target = img->buf + try; + for (i = 0; i < preimage_limit; i++) { + size_t oldlen = preimage->line[i].len; + size_t tgtlen = img->line[try_lno + i].len; + size_t fixstart = fixed.len; + struct strbuf tgtfix; + int match; + + /* Try fixing the line in the preimage */ + ws_fix_copy(&fixed, orig, oldlen, ws_rule, NULL); + + /* Try fixing the line in the target */ + strbuf_init(&tgtfix, tgtlen); + ws_fix_copy(&tgtfix, target, tgtlen, ws_rule, NULL); + + /* + * If they match, either the preimage was based on + * a version before our tree fixed whitespace breakage, + * or we are lacking a whitespace-fix patch the tree + * the preimage was based on already had (i.e. target + * has whitespace breakage, the preimage doesn't). + * In either case, we are fixing the whitespace breakages + * so we might as well take the fix together with their + * real change. + */ + match = (tgtfix.len == fixed.len - fixstart && + !memcmp(tgtfix.buf, fixed.buf + fixstart, + fixed.len - fixstart)); + + /* Add the length if this is common with the postimage */ + if (preimage->line[i].flag & LINE_COMMON) + postlen += tgtfix.len; + + strbuf_release(&tgtfix); + if (!match) + goto unmatch_exit; + + orig += oldlen; + target += tgtlen; + } + + + /* + * Now handle the lines in the preimage that falls beyond the + * end of the file (if any). They will only match if they are + * empty or only contain whitespace (if WS_BLANK_AT_EOL is + * false). + */ + for ( ; i < preimage->nr; i++) { + size_t fixstart = fixed.len; /* start of the fixed preimage */ + size_t oldlen = preimage->line[i].len; + int j; + + /* Try fixing the line in the preimage */ + ws_fix_copy(&fixed, orig, oldlen, ws_rule, NULL); + + for (j = fixstart; j < fixed.len; j++) + if (!isspace(fixed.buf[j])) + goto unmatch_exit; + + orig += oldlen; + } + + /* + * Yes, the preimage is based on an older version that still + * has whitespace breakages unfixed, and fixing them makes the + * hunk match. Update the context lines in the postimage. + */ + fixed_buf = strbuf_detach(&fixed, &fixed_len); + if (postlen < postimage->len) + postlen = 0; + update_pre_post_images(preimage, postimage, + fixed_buf, fixed_len, postlen); + return 1; + + unmatch_exit: + strbuf_release(&fixed); + return 0; +} + +static int find_pos(struct apply_state *state, + struct image *img, + struct image *preimage, + struct image *postimage, + int line, + unsigned ws_rule, + int match_beginning, int match_end) +{ + int i; + unsigned long backwards, forwards, try; + int backwards_lno, forwards_lno, try_lno; + + /* + * If match_beginning or match_end is specified, there is no + * point starting from a wrong line that will never match and + * wander around and wait for a match at the specified end. + */ + if (match_beginning) + line = 0; + else if (match_end) + line = img->nr - preimage->nr; + + /* + * Because the comparison is unsigned, the following test + * will also take care of a negative line number that can + * result when match_end and preimage is larger than the target. + */ + if ((size_t) line > img->nr) + line = img->nr; + + try = 0; + for (i = 0; i < line; i++) + try += img->line[i].len; + + /* + * There's probably some smart way to do this, but I'll leave + * that to the smart and beautiful people. I'm simple and stupid. + */ + backwards = try; + backwards_lno = line; + forwards = try; + forwards_lno = line; + try_lno = line; + + for (i = 0; ; i++) { + if (match_fragment(state, img, preimage, postimage, + try, try_lno, ws_rule, + match_beginning, match_end)) + return try_lno; + + again: + if (backwards_lno == 0 && forwards_lno == img->nr) + break; + + if (i & 1) { + if (backwards_lno == 0) { + i++; + goto again; + } + backwards_lno--; + backwards -= img->line[backwards_lno].len; + try = backwards; + try_lno = backwards_lno; + } else { + if (forwards_lno == img->nr) { + i++; + goto again; + } + forwards += img->line[forwards_lno].len; + forwards_lno++; + try = forwards; + try_lno = forwards_lno; + } + + } + return -1; +} + +static void remove_first_line(struct image *img) +{ + img->buf += img->line[0].len; + img->len -= img->line[0].len; + img->line++; + img->nr--; +} + +static void remove_last_line(struct image *img) +{ + img->len -= img->line[--img->nr].len; +} + +/* + * The change from "preimage" and "postimage" has been found to + * apply at applied_pos (counts in line numbers) in "img". + * Update "img" to remove "preimage" and replace it with "postimage". + */ +static void update_image(struct apply_state *state, + struct image *img, + int applied_pos, + struct image *preimage, + struct image *postimage) +{ + /* + * remove the copy of preimage at offset in img + * and replace it with postimage + */ + int i, nr; + size_t remove_count, insert_count, applied_at = 0; + char *result; + int preimage_limit; + + /* + * If we are removing blank lines at the end of img, + * the preimage may extend beyond the end. + * If that is the case, we must be careful only to + * remove the part of the preimage that falls within + * the boundaries of img. Initialize preimage_limit + * to the number of lines in the preimage that falls + * within the boundaries. + */ + preimage_limit = preimage->nr; + if (preimage_limit > img->nr - applied_pos) + preimage_limit = img->nr - applied_pos; + + for (i = 0; i < applied_pos; i++) + applied_at += img->line[i].len; + + remove_count = 0; + for (i = 0; i < preimage_limit; i++) + remove_count += img->line[applied_pos + i].len; + insert_count = postimage->len; + + /* Adjust the contents */ + result = xmalloc(st_add3(st_sub(img->len, remove_count), insert_count, 1)); + memcpy(result, img->buf, applied_at); + memcpy(result + applied_at, postimage->buf, postimage->len); + memcpy(result + applied_at + postimage->len, + img->buf + (applied_at + remove_count), + img->len - (applied_at + remove_count)); + free(img->buf); + img->buf = result; + img->len += insert_count - remove_count; + result[img->len] = '\0'; + + /* Adjust the line table */ + nr = img->nr + postimage->nr - preimage_limit; + if (preimage_limit < postimage->nr) { + /* + * NOTE: this knows that we never call remove_first_line() + * on anything other than pre/post image. + */ + REALLOC_ARRAY(img->line, nr); + img->line_allocated = img->line; + } + if (preimage_limit != postimage->nr) + memmove(img->line + applied_pos + postimage->nr, + img->line + applied_pos + preimage_limit, + (img->nr - (applied_pos + preimage_limit)) * + sizeof(*img->line)); + memcpy(img->line + applied_pos, + postimage->line, + postimage->nr * sizeof(*img->line)); + if (!state->allow_overlap) + for (i = 0; i < postimage->nr; i++) + img->line[applied_pos + i].flag |= LINE_PATCHED; + img->nr = nr; +} + +/* + * Use the patch-hunk text in "frag" to prepare two images (preimage and + * postimage) for the hunk. Find lines that match "preimage" in "img" and + * replace the part of "img" with "postimage" text. + */ +static int apply_one_fragment(struct apply_state *state, + struct image *img, struct fragment *frag, + int inaccurate_eof, unsigned ws_rule, + int nth_fragment) +{ + int match_beginning, match_end; + const char *patch = frag->patch; + int size = frag->size; + char *old, *oldlines; + struct strbuf newlines; + int new_blank_lines_at_end = 0; + int found_new_blank_lines_at_end = 0; + int hunk_linenr = frag->linenr; + unsigned long leading, trailing; + int pos, applied_pos; + struct image preimage; + struct image postimage; + + memset(&preimage, 0, sizeof(preimage)); + memset(&postimage, 0, sizeof(postimage)); + oldlines = xmalloc(size); + strbuf_init(&newlines, size); + + old = oldlines; + while (size > 0) { + char first; + int len = linelen(patch, size); + int plen; + int added_blank_line = 0; + int is_blank_context = 0; + size_t start; + + if (!len) + break; + + /* + * "plen" is how much of the line we should use for + * the actual patch data. Normally we just remove the + * first character on the line, but if the line is + * followed by "\ No newline", then we also remove the + * last one (which is the newline, of course). + */ + plen = len - 1; + if (len < size && patch[len] == '\\') + plen--; + first = *patch; + if (state->apply_in_reverse) { + if (first == '-') + first = '+'; + else if (first == '+') + first = '-'; + } + + switch (first) { + case '\n': + /* Newer GNU diff, empty context line */ + if (plen < 0) + /* ... followed by '\No newline'; nothing */ + break; + *old++ = '\n'; + strbuf_addch(&newlines, '\n'); + add_line_info(&preimage, "\n", 1, LINE_COMMON); + add_line_info(&postimage, "\n", 1, LINE_COMMON); + is_blank_context = 1; + break; + case ' ': + if (plen && (ws_rule & WS_BLANK_AT_EOF) && + ws_blank_line(patch + 1, plen, ws_rule)) + is_blank_context = 1; + case '-': + memcpy(old, patch + 1, plen); + add_line_info(&preimage, old, plen, + (first == ' ' ? LINE_COMMON : 0)); + old += plen; + if (first == '-') + break; + /* Fall-through for ' ' */ + case '+': + /* --no-add does not add new lines */ + if (first == '+' && state->no_add) + break; + + start = newlines.len; + if (first != '+' || + !state->whitespace_error || + state->ws_error_action != correct_ws_error) { + strbuf_add(&newlines, patch + 1, plen); + } + else { + ws_fix_copy(&newlines, patch + 1, plen, ws_rule, &state->applied_after_fixing_ws); + } + add_line_info(&postimage, newlines.buf + start, newlines.len - start, + (first == '+' ? 0 : LINE_COMMON)); + if (first == '+' && + (ws_rule & WS_BLANK_AT_EOF) && + ws_blank_line(patch + 1, plen, ws_rule)) + added_blank_line = 1; + break; + case '@': case '\\': + /* Ignore it, we already handled it */ + break; + default: + if (state->apply_verbosity > verbosity_normal) + error(_("invalid start of line: '%c'"), first); + applied_pos = -1; + goto out; + } + if (added_blank_line) { + if (!new_blank_lines_at_end) + found_new_blank_lines_at_end = hunk_linenr; + new_blank_lines_at_end++; + } + else if (is_blank_context) + ; + else + new_blank_lines_at_end = 0; + patch += len; + size -= len; + hunk_linenr++; + } + if (inaccurate_eof && + old > oldlines && old[-1] == '\n' && + newlines.len > 0 && newlines.buf[newlines.len - 1] == '\n') { + old--; + strbuf_setlen(&newlines, newlines.len - 1); + } + + leading = frag->leading; + trailing = frag->trailing; + + /* + * A hunk to change lines at the beginning would begin with + * @@ -1,L +N,M @@ + * but we need to be careful. -U0 that inserts before the second + * line also has this pattern. + * + * And a hunk to add to an empty file would begin with + * @@ -0,0 +N,M @@ + * + * In other words, a hunk that is (frag->oldpos <= 1) with or + * without leading context must match at the beginning. + */ + match_beginning = (!frag->oldpos || + (frag->oldpos == 1 && !state->unidiff_zero)); + + /* + * A hunk without trailing lines must match at the end. + * However, we simply cannot tell if a hunk must match end + * from the lack of trailing lines if the patch was generated + * with unidiff without any context. + */ + match_end = !state->unidiff_zero && !trailing; + + pos = frag->newpos ? (frag->newpos - 1) : 0; + preimage.buf = oldlines; + preimage.len = old - oldlines; + postimage.buf = newlines.buf; + postimage.len = newlines.len; + preimage.line = preimage.line_allocated; + postimage.line = postimage.line_allocated; + + for (;;) { + + applied_pos = find_pos(state, img, &preimage, &postimage, pos, + ws_rule, match_beginning, match_end); + + if (applied_pos >= 0) + break; + + /* Am I at my context limits? */ + if ((leading <= state->p_context) && (trailing <= state->p_context)) + break; + if (match_beginning || match_end) { + match_beginning = match_end = 0; + continue; + } + + /* + * Reduce the number of context lines; reduce both + * leading and trailing if they are equal otherwise + * just reduce the larger context. + */ + if (leading >= trailing) { + remove_first_line(&preimage); + remove_first_line(&postimage); + pos--; + leading--; + } + if (trailing > leading) { + remove_last_line(&preimage); + remove_last_line(&postimage); + trailing--; + } + } + + if (applied_pos >= 0) { + if (new_blank_lines_at_end && + preimage.nr + applied_pos >= img->nr && + (ws_rule & WS_BLANK_AT_EOF) && + state->ws_error_action != nowarn_ws_error) { + record_ws_error(state, WS_BLANK_AT_EOF, "+", 1, + found_new_blank_lines_at_end); + if (state->ws_error_action == correct_ws_error) { + while (new_blank_lines_at_end--) + remove_last_line(&postimage); + } + /* + * We would want to prevent write_out_results() + * from taking place in apply_patch() that follows + * the callchain led us here, which is: + * apply_patch->check_patch_list->check_patch-> + * apply_data->apply_fragments->apply_one_fragment + */ + if (state->ws_error_action == die_on_ws_error) + state->apply = 0; + } + + if (state->apply_verbosity > verbosity_normal && applied_pos != pos) { + int offset = applied_pos - pos; + if (state->apply_in_reverse) + offset = 0 - offset; + fprintf_ln(stderr, + Q_("Hunk #%d succeeded at %d (offset %d line).", + "Hunk #%d succeeded at %d (offset %d lines).", + offset), + nth_fragment, applied_pos + 1, offset); + } + + /* + * Warn if it was necessary to reduce the number + * of context lines. + */ + if ((leading != frag->leading || + trailing != frag->trailing) && state->apply_verbosity > verbosity_silent) + fprintf_ln(stderr, _("Context reduced to (%ld/%ld)" + " to apply fragment at %d"), + leading, trailing, applied_pos+1); + update_image(state, img, applied_pos, &preimage, &postimage); + } else { + if (state->apply_verbosity > verbosity_normal) + error(_("while searching for:\n%.*s"), + (int)(old - oldlines), oldlines); + } + +out: + free(oldlines); + strbuf_release(&newlines); + free(preimage.line_allocated); + free(postimage.line_allocated); + + return (applied_pos < 0); +} + +static int apply_binary_fragment(struct apply_state *state, + struct image *img, + struct patch *patch) +{ + struct fragment *fragment = patch->fragments; + unsigned long len; + void *dst; + + if (!fragment) + return error(_("missing binary patch data for '%s'"), + patch->new_name ? + patch->new_name : + patch->old_name); + + /* Binary patch is irreversible without the optional second hunk */ + if (state->apply_in_reverse) { + if (!fragment->next) + return error(_("cannot reverse-apply a binary patch " + "without the reverse hunk to '%s'"), + patch->new_name + ? patch->new_name : patch->old_name); + fragment = fragment->next; + } + switch (fragment->binary_patch_method) { + case BINARY_DELTA_DEFLATED: + dst = patch_delta(img->buf, img->len, fragment->patch, + fragment->size, &len); + if (!dst) + return -1; + clear_image(img); + img->buf = dst; + img->len = len; + return 0; + case BINARY_LITERAL_DEFLATED: + clear_image(img); + img->len = fragment->size; + img->buf = xmemdupz(fragment->patch, img->len); + return 0; + } + return -1; +} + +/* + * Replace "img" with the result of applying the binary patch. + * The binary patch data itself in patch->fragment is still kept + * but the preimage prepared by the caller in "img" is freed here + * or in the helper function apply_binary_fragment() this calls. + */ +static int apply_binary(struct apply_state *state, + struct image *img, + struct patch *patch) +{ + const char *name = patch->old_name ? patch->old_name : patch->new_name; + struct object_id oid; + + /* + * For safety, we require patch index line to contain + * full 40-byte textual SHA1 for old and new, at least for now. + */ + if (strlen(patch->old_sha1_prefix) != 40 || + strlen(patch->new_sha1_prefix) != 40 || + get_oid_hex(patch->old_sha1_prefix, &oid) || + get_oid_hex(patch->new_sha1_prefix, &oid)) + return error(_("cannot apply binary patch to '%s' " + "without full index line"), name); + + if (patch->old_name) { + /* + * See if the old one matches what the patch + * applies to. + */ + hash_sha1_file(img->buf, img->len, blob_type, oid.hash); + if (strcmp(oid_to_hex(&oid), patch->old_sha1_prefix)) + return error(_("the patch applies to '%s' (%s), " + "which does not match the " + "current contents."), + name, oid_to_hex(&oid)); + } + else { + /* Otherwise, the old one must be empty. */ + if (img->len) + return error(_("the patch applies to an empty " + "'%s' but it is not empty"), name); + } + + get_oid_hex(patch->new_sha1_prefix, &oid); + if (is_null_oid(&oid)) { + clear_image(img); + return 0; /* deletion patch */ + } + + if (has_sha1_file(oid.hash)) { + /* We already have the postimage */ + enum object_type type; + unsigned long size; + char *result; + + result = read_sha1_file(oid.hash, &type, &size); + if (!result) + return error(_("the necessary postimage %s for " + "'%s' cannot be read"), + patch->new_sha1_prefix, name); + clear_image(img); + img->buf = result; + img->len = size; + } else { + /* + * We have verified buf matches the preimage; + * apply the patch data to it, which is stored + * in the patch->fragments->{patch,size}. + */ + if (apply_binary_fragment(state, img, patch)) + return error(_("binary patch does not apply to '%s'"), + name); + + /* verify that the result matches */ + hash_sha1_file(img->buf, img->len, blob_type, oid.hash); + if (strcmp(oid_to_hex(&oid), patch->new_sha1_prefix)) + return error(_("binary patch to '%s' creates incorrect result (expecting %s, got %s)"), + name, patch->new_sha1_prefix, oid_to_hex(&oid)); + } + + return 0; +} + +static int apply_fragments(struct apply_state *state, struct image *img, struct patch *patch) +{ + struct fragment *frag = patch->fragments; + const char *name = patch->old_name ? patch->old_name : patch->new_name; + unsigned ws_rule = patch->ws_rule; + unsigned inaccurate_eof = patch->inaccurate_eof; + int nth = 0; + + if (patch->is_binary) + return apply_binary(state, img, patch); + + while (frag) { + nth++; + if (apply_one_fragment(state, img, frag, inaccurate_eof, ws_rule, nth)) { + error(_("patch failed: %s:%ld"), name, frag->oldpos); + if (!state->apply_with_reject) + return -1; + frag->rejected = 1; + } + frag = frag->next; + } + return 0; +} + +static int read_blob_object(struct strbuf *buf, const struct object_id *oid, unsigned mode) +{ + if (S_ISGITLINK(mode)) { + strbuf_grow(buf, 100); + strbuf_addf(buf, "Subproject commit %s\n", oid_to_hex(oid)); + } else { + enum object_type type; + unsigned long sz; + char *result; + + result = read_sha1_file(oid->hash, &type, &sz); + if (!result) + return -1; + /* XXX read_sha1_file NUL-terminates */ + strbuf_attach(buf, result, sz, sz + 1); + } + return 0; +} + +static int read_file_or_gitlink(const struct cache_entry *ce, struct strbuf *buf) +{ + if (!ce) + return 0; + return read_blob_object(buf, &ce->oid, ce->ce_mode); +} + +static struct patch *in_fn_table(struct apply_state *state, const char *name) +{ + struct string_list_item *item; + + if (name == NULL) + return NULL; + + item = string_list_lookup(&state->fn_table, name); + if (item != NULL) + return (struct patch *)item->util; + + return NULL; +} + +/* + * item->util in the filename table records the status of the path. + * Usually it points at a patch (whose result records the contents + * of it after applying it), but it could be PATH_WAS_DELETED for a + * path that a previously applied patch has already removed, or + * PATH_TO_BE_DELETED for a path that a later patch would remove. + * + * The latter is needed to deal with a case where two paths A and B + * are swapped by first renaming A to B and then renaming B to A; + * moving A to B should not be prevented due to presence of B as we + * will remove it in a later patch. + */ +#define PATH_TO_BE_DELETED ((struct patch *) -2) +#define PATH_WAS_DELETED ((struct patch *) -1) + +static int to_be_deleted(struct patch *patch) +{ + return patch == PATH_TO_BE_DELETED; +} + +static int was_deleted(struct patch *patch) +{ + return patch == PATH_WAS_DELETED; +} + +static void add_to_fn_table(struct apply_state *state, struct patch *patch) +{ + struct string_list_item *item; + + /* + * Always add new_name unless patch is a deletion + * This should cover the cases for normal diffs, + * file creations and copies + */ + if (patch->new_name != NULL) { + item = string_list_insert(&state->fn_table, patch->new_name); + item->util = patch; + } + + /* + * store a failure on rename/deletion cases because + * later chunks shouldn't patch old names + */ + if ((patch->new_name == NULL) || (patch->is_rename)) { + item = string_list_insert(&state->fn_table, patch->old_name); + item->util = PATH_WAS_DELETED; + } +} + +static void prepare_fn_table(struct apply_state *state, struct patch *patch) +{ + /* + * store information about incoming file deletion + */ + while (patch) { + if ((patch->new_name == NULL) || (patch->is_rename)) { + struct string_list_item *item; + item = string_list_insert(&state->fn_table, patch->old_name); + item->util = PATH_TO_BE_DELETED; + } + patch = patch->next; + } +} + +static int checkout_target(struct index_state *istate, + struct cache_entry *ce, struct stat *st) +{ + struct checkout costate = CHECKOUT_INIT; + + costate.refresh_cache = 1; + costate.istate = istate; + if (checkout_entry(ce, &costate, NULL) || lstat(ce->name, st)) + return error(_("cannot checkout %s"), ce->name); + return 0; +} + +static struct patch *previous_patch(struct apply_state *state, + struct patch *patch, + int *gone) +{ + struct patch *previous; + + *gone = 0; + if (patch->is_copy || patch->is_rename) + return NULL; /* "git" patches do not depend on the order */ + + previous = in_fn_table(state, patch->old_name); + if (!previous) + return NULL; + + if (to_be_deleted(previous)) + return NULL; /* the deletion hasn't happened yet */ + + if (was_deleted(previous)) + *gone = 1; + + return previous; +} + +static int verify_index_match(const struct cache_entry *ce, struct stat *st) +{ + if (S_ISGITLINK(ce->ce_mode)) { + if (!S_ISDIR(st->st_mode)) + return -1; + return 0; + } + return ce_match_stat(ce, st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE); +} + +#define SUBMODULE_PATCH_WITHOUT_INDEX 1 + +static int load_patch_target(struct apply_state *state, + struct strbuf *buf, + const struct cache_entry *ce, + struct stat *st, + const char *name, + unsigned expected_mode) +{ + if (state->cached || state->check_index) { + if (read_file_or_gitlink(ce, buf)) + return error(_("failed to read %s"), name); + } else if (name) { + if (S_ISGITLINK(expected_mode)) { + if (ce) + return read_file_or_gitlink(ce, buf); + else + return SUBMODULE_PATCH_WITHOUT_INDEX; + } else if (has_symlink_leading_path(name, strlen(name))) { + return error(_("reading from '%s' beyond a symbolic link"), name); + } else { + if (read_old_data(st, name, buf)) + return error(_("failed to read %s"), name); + } + } + return 0; +} + +/* + * We are about to apply "patch"; populate the "image" with the + * current version we have, from the working tree or from the index, + * depending on the situation e.g. --cached/--index. If we are + * applying a non-git patch that incrementally updates the tree, + * we read from the result of a previous diff. + */ +static int load_preimage(struct apply_state *state, + struct image *image, + struct patch *patch, struct stat *st, + const struct cache_entry *ce) +{ + struct strbuf buf = STRBUF_INIT; + size_t len; + char *img; + struct patch *previous; + int status; + + previous = previous_patch(state, patch, &status); + if (status) + return error(_("path %s has been renamed/deleted"), + patch->old_name); + if (previous) { + /* We have a patched copy in memory; use that. */ + strbuf_add(&buf, previous->result, previous->resultsize); + } else { + status = load_patch_target(state, &buf, ce, st, + patch->old_name, patch->old_mode); + if (status < 0) + return status; + else if (status == SUBMODULE_PATCH_WITHOUT_INDEX) { + /* + * There is no way to apply subproject + * patch without looking at the index. + * NEEDSWORK: shouldn't this be flagged + * as an error??? + */ + free_fragment_list(patch->fragments); + patch->fragments = NULL; + } else if (status) { + return error(_("failed to read %s"), patch->old_name); + } + } + + img = strbuf_detach(&buf, &len); + prepare_image(image, img, len, !patch->is_binary); + return 0; +} + +static int three_way_merge(struct image *image, + char *path, + const struct object_id *base, + const struct object_id *ours, + const struct object_id *theirs) +{ + mmfile_t base_file, our_file, their_file; + mmbuffer_t result = { NULL }; + int status; + + read_mmblob(&base_file, base); + read_mmblob(&our_file, ours); + read_mmblob(&their_file, theirs); + status = ll_merge(&result, path, + &base_file, "base", + &our_file, "ours", + &their_file, "theirs", NULL); + free(base_file.ptr); + free(our_file.ptr); + free(their_file.ptr); + if (status < 0 || !result.ptr) { + free(result.ptr); + return -1; + } + clear_image(image); + image->buf = result.ptr; + image->len = result.size; + + return status; +} + +/* + * When directly falling back to add/add three-way merge, we read from + * the current contents of the new_name. In no cases other than that + * this function will be called. + */ +static int load_current(struct apply_state *state, + struct image *image, + struct patch *patch) +{ + struct strbuf buf = STRBUF_INIT; + int status, pos; + size_t len; + char *img; + struct stat st; + struct cache_entry *ce; + char *name = patch->new_name; + unsigned mode = patch->new_mode; + + if (!patch->is_new) + die("BUG: patch to %s is not a creation", patch->old_name); + + pos = cache_name_pos(name, strlen(name)); + if (pos < 0) + return error(_("%s: does not exist in index"), name); + ce = active_cache[pos]; + if (lstat(name, &st)) { + if (errno != ENOENT) + return error_errno("%s", name); + if (checkout_target(&the_index, ce, &st)) + return -1; + } + if (verify_index_match(ce, &st)) + return error(_("%s: does not match index"), name); + + status = load_patch_target(state, &buf, ce, &st, name, mode); + if (status < 0) + return status; + else if (status) + return -1; + img = strbuf_detach(&buf, &len); + prepare_image(image, img, len, !patch->is_binary); + return 0; +} + +static int try_threeway(struct apply_state *state, + struct image *image, + struct patch *patch, + struct stat *st, + const struct cache_entry *ce) +{ + struct object_id pre_oid, post_oid, our_oid; + struct strbuf buf = STRBUF_INIT; + size_t len; + int status; + char *img; + struct image tmp_image; + + /* No point falling back to 3-way merge in these cases */ + if (patch->is_delete || + S_ISGITLINK(patch->old_mode) || S_ISGITLINK(patch->new_mode)) + return -1; + + /* Preimage the patch was prepared for */ + if (patch->is_new) + write_sha1_file("", 0, blob_type, pre_oid.hash); + else if (get_sha1(patch->old_sha1_prefix, pre_oid.hash) || + read_blob_object(&buf, &pre_oid, patch->old_mode)) + return error(_("repository lacks the necessary blob to fall back on 3-way merge.")); + + if (state->apply_verbosity > verbosity_silent) + fprintf(stderr, _("Falling back to three-way merge...\n")); + + img = strbuf_detach(&buf, &len); + prepare_image(&tmp_image, img, len, 1); + /* Apply the patch to get the post image */ + if (apply_fragments(state, &tmp_image, patch) < 0) { + clear_image(&tmp_image); + return -1; + } + /* post_oid is theirs */ + write_sha1_file(tmp_image.buf, tmp_image.len, blob_type, post_oid.hash); + clear_image(&tmp_image); + + /* our_oid is ours */ + if (patch->is_new) { + if (load_current(state, &tmp_image, patch)) + return error(_("cannot read the current contents of '%s'"), + patch->new_name); + } else { + if (load_preimage(state, &tmp_image, patch, st, ce)) + return error(_("cannot read the current contents of '%s'"), + patch->old_name); + } + write_sha1_file(tmp_image.buf, tmp_image.len, blob_type, our_oid.hash); + clear_image(&tmp_image); + + /* in-core three-way merge between post and our using pre as base */ + status = three_way_merge(image, patch->new_name, + &pre_oid, &our_oid, &post_oid); + if (status < 0) { + if (state->apply_verbosity > verbosity_silent) + fprintf(stderr, + _("Failed to fall back on three-way merge...\n")); + return status; + } + + if (status) { + patch->conflicted_threeway = 1; + if (patch->is_new) + oidclr(&patch->threeway_stage[0]); + else + oidcpy(&patch->threeway_stage[0], &pre_oid); + oidcpy(&patch->threeway_stage[1], &our_oid); + oidcpy(&patch->threeway_stage[2], &post_oid); + if (state->apply_verbosity > verbosity_silent) + fprintf(stderr, + _("Applied patch to '%s' with conflicts.\n"), + patch->new_name); + } else { + if (state->apply_verbosity > verbosity_silent) + fprintf(stderr, + _("Applied patch to '%s' cleanly.\n"), + patch->new_name); + } + return 0; +} + +static int apply_data(struct apply_state *state, struct patch *patch, + struct stat *st, const struct cache_entry *ce) +{ + struct image image; + + if (load_preimage(state, &image, patch, st, ce) < 0) + return -1; + + if (patch->direct_to_threeway || + apply_fragments(state, &image, patch) < 0) { + /* Note: with --reject, apply_fragments() returns 0 */ + if (!state->threeway || try_threeway(state, &image, patch, st, ce) < 0) + return -1; + } + patch->result = image.buf; + patch->resultsize = image.len; + add_to_fn_table(state, patch); + free(image.line_allocated); + + if (0 < patch->is_delete && patch->resultsize) + return error(_("removal patch leaves file contents")); + + return 0; +} + +/* + * If "patch" that we are looking at modifies or deletes what we have, + * we would want it not to lose any local modification we have, either + * in the working tree or in the index. + * + * This also decides if a non-git patch is a creation patch or a + * modification to an existing empty file. We do not check the state + * of the current tree for a creation patch in this function; the caller + * check_patch() separately makes sure (and errors out otherwise) that + * the path the patch creates does not exist in the current tree. + */ +static int check_preimage(struct apply_state *state, + struct patch *patch, + struct cache_entry **ce, + struct stat *st) +{ + const char *old_name = patch->old_name; + struct patch *previous = NULL; + int stat_ret = 0, status; + unsigned st_mode = 0; + + if (!old_name) + return 0; + + assert(patch->is_new <= 0); + previous = previous_patch(state, patch, &status); + + if (status) + return error(_("path %s has been renamed/deleted"), old_name); + if (previous) { + st_mode = previous->new_mode; + } else if (!state->cached) { + stat_ret = lstat(old_name, st); + if (stat_ret && errno != ENOENT) + return error_errno("%s", old_name); + } + + if (state->check_index && !previous) { + int pos = cache_name_pos(old_name, strlen(old_name)); + if (pos < 0) { + if (patch->is_new < 0) + goto is_new; + return error(_("%s: does not exist in index"), old_name); + } + *ce = active_cache[pos]; + if (stat_ret < 0) { + if (checkout_target(&the_index, *ce, st)) + return -1; + } + if (!state->cached && verify_index_match(*ce, st)) + return error(_("%s: does not match index"), old_name); + if (state->cached) + st_mode = (*ce)->ce_mode; + } else if (stat_ret < 0) { + if (patch->is_new < 0) + goto is_new; + return error_errno("%s", old_name); + } + + if (!state->cached && !previous) + st_mode = ce_mode_from_stat(*ce, st->st_mode); + + if (patch->is_new < 0) + patch->is_new = 0; + if (!patch->old_mode) + patch->old_mode = st_mode; + if ((st_mode ^ patch->old_mode) & S_IFMT) + return error(_("%s: wrong type"), old_name); + if (st_mode != patch->old_mode) + warning(_("%s has type %o, expected %o"), + old_name, st_mode, patch->old_mode); + if (!patch->new_mode && !patch->is_delete) + patch->new_mode = st_mode; + return 0; + + is_new: + patch->is_new = 1; + patch->is_delete = 0; + free(patch->old_name); + patch->old_name = NULL; + return 0; +} + + +#define EXISTS_IN_INDEX 1 +#define EXISTS_IN_WORKTREE 2 + +static int check_to_create(struct apply_state *state, + const char *new_name, + int ok_if_exists) +{ + struct stat nst; + + if (state->check_index && + cache_name_pos(new_name, strlen(new_name)) >= 0 && + !ok_if_exists) + return EXISTS_IN_INDEX; + if (state->cached) + return 0; + + if (!lstat(new_name, &nst)) { + if (S_ISDIR(nst.st_mode) || ok_if_exists) + return 0; + /* + * A leading component of new_name might be a symlink + * that is going to be removed with this patch, but + * still pointing at somewhere that has the path. + * In such a case, path "new_name" does not exist as + * far as git is concerned. + */ + if (has_symlink_leading_path(new_name, strlen(new_name))) + return 0; + + return EXISTS_IN_WORKTREE; + } else if ((errno != ENOENT) && (errno != ENOTDIR)) { + return error_errno("%s", new_name); + } + return 0; +} + +static uintptr_t register_symlink_changes(struct apply_state *state, + const char *path, + uintptr_t what) +{ + struct string_list_item *ent; + + ent = string_list_lookup(&state->symlink_changes, path); + if (!ent) { + ent = string_list_insert(&state->symlink_changes, path); + ent->util = (void *)0; + } + ent->util = (void *)(what | ((uintptr_t)ent->util)); + return (uintptr_t)ent->util; +} + +static uintptr_t check_symlink_changes(struct apply_state *state, const char *path) +{ + struct string_list_item *ent; + + ent = string_list_lookup(&state->symlink_changes, path); + if (!ent) + return 0; + return (uintptr_t)ent->util; +} + +static void prepare_symlink_changes(struct apply_state *state, struct patch *patch) +{ + for ( ; patch; patch = patch->next) { + if ((patch->old_name && S_ISLNK(patch->old_mode)) && + (patch->is_rename || patch->is_delete)) + /* the symlink at patch->old_name is removed */ + register_symlink_changes(state, patch->old_name, APPLY_SYMLINK_GOES_AWAY); + + if (patch->new_name && S_ISLNK(patch->new_mode)) + /* the symlink at patch->new_name is created or remains */ + register_symlink_changes(state, patch->new_name, APPLY_SYMLINK_IN_RESULT); + } +} + +static int path_is_beyond_symlink_1(struct apply_state *state, struct strbuf *name) +{ + do { + unsigned int change; + + while (--name->len && name->buf[name->len] != '/') + ; /* scan backwards */ + if (!name->len) + break; + name->buf[name->len] = '\0'; + change = check_symlink_changes(state, name->buf); + if (change & APPLY_SYMLINK_IN_RESULT) + return 1; + if (change & APPLY_SYMLINK_GOES_AWAY) + /* + * This cannot be "return 0", because we may + * see a new one created at a higher level. + */ + continue; + + /* otherwise, check the preimage */ + if (state->check_index) { + struct cache_entry *ce; + + ce = cache_file_exists(name->buf, name->len, ignore_case); + if (ce && S_ISLNK(ce->ce_mode)) + return 1; + } else { + struct stat st; + if (!lstat(name->buf, &st) && S_ISLNK(st.st_mode)) + return 1; + } + } while (1); + return 0; +} + +static int path_is_beyond_symlink(struct apply_state *state, const char *name_) +{ + int ret; + struct strbuf name = STRBUF_INIT; + + assert(*name_ != '\0'); + strbuf_addstr(&name, name_); + ret = path_is_beyond_symlink_1(state, &name); + strbuf_release(&name); + + return ret; +} + +static int check_unsafe_path(struct patch *patch) +{ + const char *old_name = NULL; + const char *new_name = NULL; + if (patch->is_delete) + old_name = patch->old_name; + else if (!patch->is_new && !patch->is_copy) + old_name = patch->old_name; + if (!patch->is_delete) + new_name = patch->new_name; + + if (old_name && !verify_path(old_name)) + return error(_("invalid path '%s'"), old_name); + if (new_name && !verify_path(new_name)) + return error(_("invalid path '%s'"), new_name); + return 0; +} + +/* + * Check and apply the patch in-core; leave the result in patch->result + * for the caller to write it out to the final destination. + */ +static int check_patch(struct apply_state *state, struct patch *patch) +{ + struct stat st; + const char *old_name = patch->old_name; + const char *new_name = patch->new_name; + const char *name = old_name ? old_name : new_name; + struct cache_entry *ce = NULL; + struct patch *tpatch; + int ok_if_exists; + int status; + + patch->rejected = 1; /* we will drop this after we succeed */ + + status = check_preimage(state, patch, &ce, &st); + if (status) + return status; + old_name = patch->old_name; + + /* + * A type-change diff is always split into a patch to delete + * old, immediately followed by a patch to create new (see + * diff.c::run_diff()); in such a case it is Ok that the entry + * to be deleted by the previous patch is still in the working + * tree and in the index. + * + * A patch to swap-rename between A and B would first rename A + * to B and then rename B to A. While applying the first one, + * the presence of B should not stop A from getting renamed to + * B; ask to_be_deleted() about the later rename. Removal of + * B and rename from A to B is handled the same way by asking + * was_deleted(). + */ + if ((tpatch = in_fn_table(state, new_name)) && + (was_deleted(tpatch) || to_be_deleted(tpatch))) + ok_if_exists = 1; + else + ok_if_exists = 0; + + if (new_name && + ((0 < patch->is_new) || patch->is_rename || patch->is_copy)) { + int err = check_to_create(state, new_name, ok_if_exists); + + if (err && state->threeway) { + patch->direct_to_threeway = 1; + } else switch (err) { + case 0: + break; /* happy */ + case EXISTS_IN_INDEX: + return error(_("%s: already exists in index"), new_name); + break; + case EXISTS_IN_WORKTREE: + return error(_("%s: already exists in working directory"), + new_name); + default: + return err; + } + + if (!patch->new_mode) { + if (0 < patch->is_new) + patch->new_mode = S_IFREG | 0644; + else + patch->new_mode = patch->old_mode; + } + } + + if (new_name && old_name) { + int same = !strcmp(old_name, new_name); + if (!patch->new_mode) + patch->new_mode = patch->old_mode; + if ((patch->old_mode ^ patch->new_mode) & S_IFMT) { + if (same) + return error(_("new mode (%o) of %s does not " + "match old mode (%o)"), + patch->new_mode, new_name, + patch->old_mode); + else + return error(_("new mode (%o) of %s does not " + "match old mode (%o) of %s"), + patch->new_mode, new_name, + patch->old_mode, old_name); + } + } + + if (!state->unsafe_paths && check_unsafe_path(patch)) + return -128; + + /* + * An attempt to read from or delete a path that is beyond a + * symbolic link will be prevented by load_patch_target() that + * is called at the beginning of apply_data() so we do not + * have to worry about a patch marked with "is_delete" bit + * here. We however need to make sure that the patch result + * is not deposited to a path that is beyond a symbolic link + * here. + */ + if (!patch->is_delete && path_is_beyond_symlink(state, patch->new_name)) + return error(_("affected file '%s' is beyond a symbolic link"), + patch->new_name); + + if (apply_data(state, patch, &st, ce) < 0) + return error(_("%s: patch does not apply"), name); + patch->rejected = 0; + return 0; +} + +static int check_patch_list(struct apply_state *state, struct patch *patch) +{ + int err = 0; + + prepare_symlink_changes(state, patch); + prepare_fn_table(state, patch); + while (patch) { + int res; + if (state->apply_verbosity > verbosity_normal) + say_patch_name(stderr, + _("Checking patch %s..."), patch); + res = check_patch(state, patch); + if (res == -128) + return -128; + err |= res; + patch = patch->next; + } + return err; +} + +static int read_apply_cache(struct apply_state *state) +{ + if (state->index_file) + return read_cache_from(state->index_file); + else + return read_cache(); +} + +/* This function tries to read the object name from the current index */ +static int get_current_oid(struct apply_state *state, const char *path, + struct object_id *oid) +{ + int pos; + + if (read_apply_cache(state) < 0) + return -1; + pos = cache_name_pos(path, strlen(path)); + if (pos < 0) + return -1; + oidcpy(oid, &active_cache[pos]->oid); + return 0; +} + +static int preimage_oid_in_gitlink_patch(struct patch *p, struct object_id *oid) +{ + /* + * A usable gitlink patch has only one fragment (hunk) that looks like: + * @@ -1 +1 @@ + * -Subproject commit + * +Subproject commit + * or + * @@ -1 +0,0 @@ + * -Subproject commit + * for a removal patch. + */ + struct fragment *hunk = p->fragments; + static const char heading[] = "-Subproject commit "; + char *preimage; + + if (/* does the patch have only one hunk? */ + hunk && !hunk->next && + /* is its preimage one line? */ + hunk->oldpos == 1 && hunk->oldlines == 1 && + /* does preimage begin with the heading? */ + (preimage = memchr(hunk->patch, '\n', hunk->size)) != NULL && + starts_with(++preimage, heading) && + /* does it record full SHA-1? */ + !get_oid_hex(preimage + sizeof(heading) - 1, oid) && + preimage[sizeof(heading) + GIT_SHA1_HEXSZ - 1] == '\n' && + /* does the abbreviated name on the index line agree with it? */ + starts_with(preimage + sizeof(heading) - 1, p->old_sha1_prefix)) + return 0; /* it all looks fine */ + + /* we may have full object name on the index line */ + return get_oid_hex(p->old_sha1_prefix, oid); +} + +/* Build an index that contains the just the files needed for a 3way merge */ +static int build_fake_ancestor(struct apply_state *state, struct patch *list) +{ + struct patch *patch; + struct index_state result = { NULL }; + static struct lock_file lock; + int res; + + /* Once we start supporting the reverse patch, it may be + * worth showing the new sha1 prefix, but until then... + */ + for (patch = list; patch; patch = patch->next) { + struct object_id oid; + struct cache_entry *ce; + const char *name; + + name = patch->old_name ? patch->old_name : patch->new_name; + if (0 < patch->is_new) + continue; + + if (S_ISGITLINK(patch->old_mode)) { + if (!preimage_oid_in_gitlink_patch(patch, &oid)) + ; /* ok, the textual part looks sane */ + else + return error(_("sha1 information is lacking or " + "useless for submodule %s"), name); + } else if (!get_sha1_blob(patch->old_sha1_prefix, oid.hash)) { + ; /* ok */ + } else if (!patch->lines_added && !patch->lines_deleted) { + /* mode-only change: update the current */ + if (get_current_oid(state, patch->old_name, &oid)) + return error(_("mode change for %s, which is not " + "in current HEAD"), name); + } else + return error(_("sha1 information is lacking or useless " + "(%s)."), name); + + ce = make_cache_entry(patch->old_mode, oid.hash, name, 0, 0); + if (!ce) + return error(_("make_cache_entry failed for path '%s'"), + name); + if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD)) { + free(ce); + return error(_("could not add %s to temporary index"), + name); + } + } + + hold_lock_file_for_update(&lock, state->fake_ancestor, LOCK_DIE_ON_ERROR); + res = write_locked_index(&result, &lock, COMMIT_LOCK); + discard_index(&result); + + if (res) + return error(_("could not write temporary index to %s"), + state->fake_ancestor); + + return 0; + } + + static void stat_patch_list(struct apply_state *state, struct patch *patch) + { + int files, adds, dels; + + for (files = adds = dels = 0 ; patch ; patch = patch->next) { + files++; + adds += patch->lines_added; + dels += patch->lines_deleted; + show_stats(state, patch); + } + + print_stat_summary(stdout, files, adds, dels); + } + + static void numstat_patch_list(struct apply_state *state, + struct patch *patch) + { + for ( ; patch; patch = patch->next) { + const char *name; + name = patch->new_name ? patch->new_name : patch->old_name; + if (patch->is_binary) + printf("-\t-\t"); + else + printf("%d\t%d\t", patch->lines_added, patch->lines_deleted); + write_name_quoted(name, stdout, state->line_termination); + } + } + + static void show_file_mode_name(const char *newdelete, unsigned int mode, const char *name) + { + if (mode) + printf(" %s mode %06o %s\n", newdelete, mode, name); + else + printf(" %s %s\n", newdelete, name); + } + + static void show_mode_change(struct patch *p, int show_name) + { + if (p->old_mode && p->new_mode && p->old_mode != p->new_mode) { + if (show_name) + printf(" mode change %06o => %06o %s\n", + p->old_mode, p->new_mode, p->new_name); + else + printf(" mode change %06o => %06o\n", + p->old_mode, p->new_mode); + } + } + + static void show_rename_copy(struct patch *p) + { + const char *renamecopy = p->is_rename ? "rename" : "copy"; + const char *old, *new; + + /* Find common prefix */ + old = p->old_name; + new = p->new_name; + while (1) { + const char *slash_old, *slash_new; + slash_old = strchr(old, '/'); + slash_new = strchr(new, '/'); + if (!slash_old || + !slash_new || + slash_old - old != slash_new - new || + memcmp(old, new, slash_new - new)) + break; + old = slash_old + 1; + new = slash_new + 1; + } + /* p->old_name thru old is the common prefix, and old and new + * through the end of names are renames + */ + if (old != p->old_name) + printf(" %s %.*s{%s => %s} (%d%%)\n", renamecopy, + (int)(old - p->old_name), p->old_name, + old, new, p->score); + else + printf(" %s %s => %s (%d%%)\n", renamecopy, + p->old_name, p->new_name, p->score); + show_mode_change(p, 0); + } + + static void summary_patch_list(struct patch *patch) + { + struct patch *p; + + for (p = patch; p; p = p->next) { + if (p->is_new) + show_file_mode_name("create", p->new_mode, p->new_name); + else if (p->is_delete) + show_file_mode_name("delete", p->old_mode, p->old_name); + else { + if (p->is_rename || p->is_copy) + show_rename_copy(p); + else { + if (p->score) { + printf(" rewrite %s (%d%%)\n", + p->new_name, p->score); + show_mode_change(p, 0); + } + else + show_mode_change(p, 1); + } + } + } + } + + static void patch_stats(struct apply_state *state, struct patch *patch) + { + int lines = patch->lines_added + patch->lines_deleted; + + if (lines > state->max_change) + state->max_change = lines; + if (patch->old_name) { + int len = quote_c_style(patch->old_name, NULL, NULL, 0); + if (!len) + len = strlen(patch->old_name); + if (len > state->max_len) + state->max_len = len; + } + if (patch->new_name) { + int len = quote_c_style(patch->new_name, NULL, NULL, 0); + if (!len) + len = strlen(patch->new_name); + if (len > state->max_len) + state->max_len = len; + } + } + + static int remove_file(struct apply_state *state, struct patch *patch, int rmdir_empty) + { + if (state->update_index) { + if (remove_file_from_cache(patch->old_name) < 0) + return error(_("unable to remove %s from index"), patch->old_name); + } + if (!state->cached) { + if (!remove_or_warn(patch->old_mode, patch->old_name) && rmdir_empty) { + remove_path(patch->old_name); + } + } + return 0; + } + + static int add_index_file(struct apply_state *state, + const char *path, + unsigned mode, + void *buf, + unsigned long size) + { + struct stat st; + struct cache_entry *ce; + int namelen = strlen(path); + unsigned ce_size = cache_entry_size(namelen); + + if (!state->update_index) + return 0; + + ce = xcalloc(1, ce_size); + memcpy(ce->name, path, namelen); + ce->ce_mode = create_ce_mode(mode); + ce->ce_flags = create_ce_flags(0); + ce->ce_namelen = namelen; + if (S_ISGITLINK(mode)) { + const char *s; + + if (!skip_prefix(buf, "Subproject commit ", &s) || + get_oid_hex(s, &ce->oid)) { + free(ce); + return error(_("corrupt patch for submodule %s"), path); + } + } else { + if (!state->cached) { + if (lstat(path, &st) < 0) { + free(ce); + return error_errno(_("unable to stat newly " + "created file '%s'"), + path); + } + fill_stat_cache_info(ce, &st); + } + if (write_sha1_file(buf, size, blob_type, ce->oid.hash) < 0) { + free(ce); + return error(_("unable to create backing store " + "for newly created file %s"), path); + } + } + if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0) { + free(ce); + return error(_("unable to add cache entry for %s"), path); + } + + return 0; +} + +/* + * Returns: + * -1 if an unrecoverable error happened + * 0 if everything went well + * 1 if a recoverable error happened + */ +static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size) +{ + int fd, res; + struct strbuf nbuf = STRBUF_INIT; + + if (S_ISGITLINK(mode)) { + struct stat st; + if (!lstat(path, &st) && S_ISDIR(st.st_mode)) + return 0; + return !!mkdir(path, 0777); + } + + if (has_symlinks && S_ISLNK(mode)) + /* Although buf:size is counted string, it also is NUL + * terminated. + */ + return !!symlink(buf, path); + + fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666); + if (fd < 0) + return 1; + + if (convert_to_working_tree(path, buf, size, &nbuf)) { + size = nbuf.len; + buf = nbuf.buf; + } + + res = write_in_full(fd, buf, size) < 0; + if (res) + error_errno(_("failed to write to '%s'"), path); + strbuf_release(&nbuf); + + if (close(fd) < 0 && !res) + return error_errno(_("closing file '%s'"), path); + + return res ? -1 : 0; +} + +/* + * We optimistically assume that the directories exist, + * which is true 99% of the time anyway. If they don't, + * we create them and try again. + * + * Returns: + * -1 on error + * 0 otherwise + */ +static int create_one_file(struct apply_state *state, + char *path, + unsigned mode, + const char *buf, + unsigned long size) +{ + int res; + + if (state->cached) + return 0; + + res = try_create_file(path, mode, buf, size); + if (res < 0) + return -1; + if (!res) + return 0; + + if (errno == ENOENT) { + if (safe_create_leading_directories(path)) + return 0; + res = try_create_file(path, mode, buf, size); + if (res < 0) + return -1; + if (!res) + return 0; + } + + if (errno == EEXIST || errno == EACCES) { + /* We may be trying to create a file where a directory + * used to be. + */ + struct stat st; + if (!lstat(path, &st) && (!S_ISDIR(st.st_mode) || !rmdir(path))) + errno = EEXIST; + } + + if (errno == EEXIST) { + unsigned int nr = getpid(); + + for (;;) { + char newpath[PATH_MAX]; + mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr); + res = try_create_file(newpath, mode, buf, size); + if (res < 0) + return -1; + if (!res) { + if (!rename(newpath, path)) + return 0; + unlink_or_warn(newpath); + break; + } + if (errno != EEXIST) + break; + ++nr; + } + } + return error_errno(_("unable to write file '%s' mode %o"), + path, mode); +} + +static int add_conflicted_stages_file(struct apply_state *state, + struct patch *patch) +{ + int stage, namelen; + unsigned ce_size, mode; + struct cache_entry *ce; + + if (!state->update_index) + return 0; + namelen = strlen(patch->new_name); + ce_size = cache_entry_size(namelen); + mode = patch->new_mode ? patch->new_mode : (S_IFREG | 0644); + + remove_file_from_cache(patch->new_name); + for (stage = 1; stage < 4; stage++) { + if (is_null_oid(&patch->threeway_stage[stage - 1])) + continue; + ce = xcalloc(1, ce_size); + memcpy(ce->name, patch->new_name, namelen); + ce->ce_mode = create_ce_mode(mode); + ce->ce_flags = create_ce_flags(stage); + ce->ce_namelen = namelen; + oidcpy(&ce->oid, &patch->threeway_stage[stage - 1]); + if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0) { + free(ce); + return error(_("unable to add cache entry for %s"), + patch->new_name); + } + } + + return 0; +} + +static int create_file(struct apply_state *state, struct patch *patch) +{ + char *path = patch->new_name; + unsigned mode = patch->new_mode; + unsigned long size = patch->resultsize; + char *buf = patch->result; + + if (!mode) + mode = S_IFREG | 0644; + if (create_one_file(state, path, mode, buf, size)) + return -1; + + if (patch->conflicted_threeway) + return add_conflicted_stages_file(state, patch); + else + return add_index_file(state, path, mode, buf, size); +} + +/* phase zero is to remove, phase one is to create */ +static int write_out_one_result(struct apply_state *state, + struct patch *patch, + int phase) +{ + if (patch->is_delete > 0) { + if (phase == 0) + return remove_file(state, patch, 1); + return 0; + } + if (patch->is_new > 0 || patch->is_copy) { + if (phase == 1) + return create_file(state, patch); + return 0; + } + /* + * Rename or modification boils down to the same + * thing: remove the old, write the new + */ + if (phase == 0) + return remove_file(state, patch, patch->is_rename); + if (phase == 1) + return create_file(state, patch); + return 0; +} + +static int write_out_one_reject(struct apply_state *state, struct patch *patch) +{ + FILE *rej; + char namebuf[PATH_MAX]; + struct fragment *frag; + int cnt = 0; + struct strbuf sb = STRBUF_INIT; + + for (cnt = 0, frag = patch->fragments; frag; frag = frag->next) { + if (!frag->rejected) + continue; + cnt++; + } + + if (!cnt) { + if (state->apply_verbosity > verbosity_normal) + say_patch_name(stderr, + _("Applied patch %s cleanly."), patch); + return 0; + } + + /* This should not happen, because a removal patch that leaves + * contents are marked "rejected" at the patch level. + */ + if (!patch->new_name) + die(_("internal error")); + + /* Say this even without --verbose */ + strbuf_addf(&sb, Q_("Applying patch %%s with %d reject...", + "Applying patch %%s with %d rejects...", + cnt), + cnt); + if (state->apply_verbosity > verbosity_silent) + say_patch_name(stderr, sb.buf, patch); + strbuf_release(&sb); + + cnt = strlen(patch->new_name); + if (ARRAY_SIZE(namebuf) <= cnt + 5) { + cnt = ARRAY_SIZE(namebuf) - 5; + warning(_("truncating .rej filename to %.*s.rej"), + cnt - 1, patch->new_name); + } + memcpy(namebuf, patch->new_name, cnt); + memcpy(namebuf + cnt, ".rej", 5); + + rej = fopen(namebuf, "w"); + if (!rej) + return error_errno(_("cannot open %s"), namebuf); + + /* Normal git tools never deal with .rej, so do not pretend + * this is a git patch by saying --git or giving extended + * headers. While at it, maybe please "kompare" that wants + * the trailing TAB and some garbage at the end of line ;-). + */ + fprintf(rej, "diff a/%s b/%s\t(rejected hunks)\n", + patch->new_name, patch->new_name); + for (cnt = 1, frag = patch->fragments; + frag; + cnt++, frag = frag->next) { + if (!frag->rejected) { + if (state->apply_verbosity > verbosity_silent) + fprintf_ln(stderr, _("Hunk #%d applied cleanly."), cnt); + continue; + } + if (state->apply_verbosity > verbosity_silent) + fprintf_ln(stderr, _("Rejected hunk #%d."), cnt); + fprintf(rej, "%.*s", frag->size, frag->patch); + if (frag->patch[frag->size-1] != '\n') + fputc('\n', rej); + } + fclose(rej); + return -1; +} + +/* + * Returns: + * -1 if an error happened + * 0 if the patch applied cleanly + * 1 if the patch did not apply cleanly + */ +static int write_out_results(struct apply_state *state, struct patch *list) +{ + int phase; + int errs = 0; + struct patch *l; + struct string_list cpath = STRING_LIST_INIT_DUP; + + for (phase = 0; phase < 2; phase++) { + l = list; + while (l) { + if (l->rejected) + errs = 1; + else { + if (write_out_one_result(state, l, phase)) { + string_list_clear(&cpath, 0); + return -1; + } + if (phase == 1) { + if (write_out_one_reject(state, l)) + errs = 1; + if (l->conflicted_threeway) { + string_list_append(&cpath, l->new_name); + errs = 1; + } + } + } + l = l->next; + } + } + + if (cpath.nr) { + struct string_list_item *item; + + string_list_sort(&cpath); + if (state->apply_verbosity > verbosity_silent) { + for_each_string_list_item(item, &cpath) + fprintf(stderr, "U %s\n", item->string); + } + string_list_clear(&cpath, 0); + + rerere(0); + } + + return errs; +} + +/* + * Try to apply a patch. + * + * Returns: + * -128 if a bad error happened (like patch unreadable) + * -1 if patch did not apply and user cannot deal with it + * 0 if the patch applied + * 1 if the patch did not apply but user might fix it + */ +static int apply_patch(struct apply_state *state, + int fd, + const char *filename, + int options) +{ + size_t offset; + struct strbuf buf = STRBUF_INIT; /* owns the patch text */ + struct patch *list = NULL, **listp = &list; + int skipped_patch = 0; + int res = 0; + + state->patch_input_file = filename; + if (read_patch_file(&buf, fd) < 0) + return -128; + offset = 0; + while (offset < buf.len) { + struct patch *patch; + int nr; + + patch = xcalloc(1, sizeof(*patch)); + patch->inaccurate_eof = !!(options & APPLY_OPT_INACCURATE_EOF); + patch->recount = !!(options & APPLY_OPT_RECOUNT); + nr = parse_chunk(state, buf.buf + offset, buf.len - offset, patch); + if (nr < 0) { + free_patch(patch); + if (nr == -128) { + res = -128; + goto end; + } + break; + } + if (state->apply_in_reverse) + reverse_patches(patch); + if (use_patch(state, patch)) { + patch_stats(state, patch); + *listp = patch; + listp = &patch->next; + } + else { + if (state->apply_verbosity > verbosity_normal) + say_patch_name(stderr, _("Skipped patch '%s'."), patch); + free_patch(patch); + skipped_patch++; + } + offset += nr; + } + + if (!list && !skipped_patch) { + error(_("unrecognized input")); + res = -128; + goto end; + } + + if (state->whitespace_error && (state->ws_error_action == die_on_ws_error)) + state->apply = 0; + + state->update_index = state->check_index && state->apply; + if (state->update_index && state->newfd < 0) { + if (state->index_file) + state->newfd = hold_lock_file_for_update(state->lock_file, + state->index_file, + LOCK_DIE_ON_ERROR); + else + state->newfd = hold_locked_index(state->lock_file, 1); + } + + if (state->check_index && read_apply_cache(state) < 0) { + error(_("unable to read index file")); + res = -128; + goto end; + } + + if (state->check || state->apply) { + int r = check_patch_list(state, list); + if (r == -128) { + res = -128; + goto end; + } + if (r < 0 && !state->apply_with_reject) { + res = -1; + goto end; + } + } + + if (state->apply) { + int write_res = write_out_results(state, list); + if (write_res < 0) { + res = -128; + goto end; + } + if (write_res > 0) { + /* with --3way, we still need to write the index out */ + res = state->apply_with_reject ? -1 : 1; + goto end; + } + } + + if (state->fake_ancestor && + build_fake_ancestor(state, list)) { + res = -128; + goto end; + } + + if (state->diffstat && state->apply_verbosity > verbosity_silent) + stat_patch_list(state, list); + + if (state->numstat && state->apply_verbosity > verbosity_silent) + numstat_patch_list(state, list); + + if (state->summary && state->apply_verbosity > verbosity_silent) + summary_patch_list(list); + +end: + free_patch_list(list); + strbuf_release(&buf); + string_list_clear(&state->fn_table, 0); + return res; +} + +static int apply_option_parse_exclude(const struct option *opt, + const char *arg, int unset) +{ + struct apply_state *state = opt->value; + add_name_limit(state, arg, 1); + return 0; +} + +static int apply_option_parse_include(const struct option *opt, + const char *arg, int unset) +{ + struct apply_state *state = opt->value; + add_name_limit(state, arg, 0); + state->has_include = 1; + return 0; +} + +static int apply_option_parse_p(const struct option *opt, + const char *arg, + int unset) +{ + struct apply_state *state = opt->value; + state->p_value = atoi(arg); + state->p_value_known = 1; + return 0; +} + +static int apply_option_parse_space_change(const struct option *opt, + const char *arg, int unset) +{ + struct apply_state *state = opt->value; + if (unset) + state->ws_ignore_action = ignore_ws_none; + else + state->ws_ignore_action = ignore_ws_change; + return 0; +} + +static int apply_option_parse_whitespace(const struct option *opt, + const char *arg, int unset) +{ + struct apply_state *state = opt->value; + state->whitespace_option = arg; + if (parse_whitespace_option(state, arg)) + exit(1); + return 0; +} + +static int apply_option_parse_directory(const struct option *opt, + const char *arg, int unset) +{ + struct apply_state *state = opt->value; + strbuf_reset(&state->root); + strbuf_addstr(&state->root, arg); + strbuf_complete(&state->root, '/'); + return 0; +} + +int apply_all_patches(struct apply_state *state, + int argc, + const char **argv, + int options) +{ + int i; + int res; + int errs = 0; + int read_stdin = 1; + + for (i = 0; i < argc; i++) { + const char *arg = argv[i]; + int fd; + + if (!strcmp(arg, "-")) { + res = apply_patch(state, 0, "", options); + if (res < 0) + goto end; + errs |= res; + read_stdin = 0; + continue; + } else if (0 < state->prefix_length) + arg = prefix_filename(state->prefix, + state->prefix_length, + arg); + + fd = open(arg, O_RDONLY); + if (fd < 0) { + error(_("can't open patch '%s': %s"), arg, strerror(errno)); + res = -128; + goto end; + } + read_stdin = 0; + set_default_whitespace_mode(state); + res = apply_patch(state, fd, arg, options); + close(fd); + if (res < 0) + goto end; + errs |= res; + } + set_default_whitespace_mode(state); + if (read_stdin) { + res = apply_patch(state, 0, "", options); + if (res < 0) + goto end; + errs |= res; + } + + if (state->whitespace_error) { + if (state->squelch_whitespace_errors && + state->squelch_whitespace_errors < state->whitespace_error) { + int squelched = + state->whitespace_error - state->squelch_whitespace_errors; + warning(Q_("squelched %d whitespace error", + "squelched %d whitespace errors", + squelched), + squelched); + } + if (state->ws_error_action == die_on_ws_error) { + error(Q_("%d line adds whitespace errors.", + "%d lines add whitespace errors.", + state->whitespace_error), + state->whitespace_error); + res = -128; + goto end; + } + if (state->applied_after_fixing_ws && state->apply) + warning(Q_("%d line applied after" + " fixing whitespace errors.", + "%d lines applied after" + " fixing whitespace errors.", + state->applied_after_fixing_ws), + state->applied_after_fixing_ws); + else if (state->whitespace_error) + warning(Q_("%d line adds whitespace errors.", + "%d lines add whitespace errors.", + state->whitespace_error), + state->whitespace_error); + } + + if (state->update_index) { + res = write_locked_index(&the_index, state->lock_file, COMMIT_LOCK); + if (res) { + error(_("Unable to write new index file")); + res = -128; + goto end; + } + state->newfd = -1; + } + + res = !!errs; + +end: + if (state->newfd >= 0) { + rollback_lock_file(state->lock_file); + state->newfd = -1; + } + + if (state->apply_verbosity <= verbosity_silent) { + set_error_routine(state->saved_error_routine); + set_warn_routine(state->saved_warn_routine); + } + + if (res > -1) + return res; + return (res == -1 ? 1 : 128); +} + +int apply_parse_options(int argc, const char **argv, + struct apply_state *state, + int *force_apply, int *options, + const char * const *apply_usage) +{ + struct option builtin_apply_options[] = { + { OPTION_CALLBACK, 0, "exclude", state, N_("path"), + N_("don't apply changes matching the given path"), + 0, apply_option_parse_exclude }, + { OPTION_CALLBACK, 0, "include", state, N_("path"), + N_("apply changes matching the given path"), + 0, apply_option_parse_include }, + { OPTION_CALLBACK, 'p', NULL, state, N_("num"), + N_("remove leading slashes from traditional diff paths"), + 0, apply_option_parse_p }, + OPT_BOOL(0, "no-add", &state->no_add, + N_("ignore additions made by the patch")), + OPT_BOOL(0, "stat", &state->diffstat, + N_("instead of applying the patch, output diffstat for the input")), + OPT_NOOP_NOARG(0, "allow-binary-replacement"), + OPT_NOOP_NOARG(0, "binary"), + OPT_BOOL(0, "numstat", &state->numstat, + N_("show number of added and deleted lines in decimal notation")), + OPT_BOOL(0, "summary", &state->summary, + N_("instead of applying the patch, output a summary for the input")), + OPT_BOOL(0, "check", &state->check, + N_("instead of applying the patch, see if the patch is applicable")), + OPT_BOOL(0, "index", &state->check_index, + N_("make sure the patch is applicable to the current index")), + OPT_BOOL(0, "cached", &state->cached, + N_("apply a patch without touching the working tree")), + OPT_BOOL(0, "unsafe-paths", &state->unsafe_paths, + N_("accept a patch that touches outside the working area")), + OPT_BOOL(0, "apply", force_apply, + N_("also apply the patch (use with --stat/--summary/--check)")), + OPT_BOOL('3', "3way", &state->threeway, + N_( "attempt three-way merge if a patch does not apply")), + OPT_FILENAME(0, "build-fake-ancestor", &state->fake_ancestor, + N_("build a temporary index based on embedded index information")), + /* Think twice before adding "--nul" synonym to this */ + OPT_SET_INT('z', NULL, &state->line_termination, + N_("paths are separated with NUL character"), '\0'), + OPT_INTEGER('C', NULL, &state->p_context, + N_("ensure at least lines of context match")), + { OPTION_CALLBACK, 0, "whitespace", state, N_("action"), + N_("detect new or modified lines that have whitespace errors"), + 0, apply_option_parse_whitespace }, + { OPTION_CALLBACK, 0, "ignore-space-change", state, NULL, + N_("ignore changes in whitespace when finding context"), + PARSE_OPT_NOARG, apply_option_parse_space_change }, + { OPTION_CALLBACK, 0, "ignore-whitespace", state, NULL, + N_("ignore changes in whitespace when finding context"), + PARSE_OPT_NOARG, apply_option_parse_space_change }, + OPT_BOOL('R', "reverse", &state->apply_in_reverse, + N_("apply the patch in reverse")), + OPT_BOOL(0, "unidiff-zero", &state->unidiff_zero, + N_("don't expect at least one line of context")), + OPT_BOOL(0, "reject", &state->apply_with_reject, + N_("leave the rejected hunks in corresponding *.rej files")), + OPT_BOOL(0, "allow-overlap", &state->allow_overlap, + N_("allow overlapping hunks")), + OPT__VERBOSE(&state->apply_verbosity, N_("be verbose")), + OPT_BIT(0, "inaccurate-eof", options, + N_("tolerate incorrectly detected missing new-line at the end of file"), + APPLY_OPT_INACCURATE_EOF), + OPT_BIT(0, "recount", options, + N_("do not trust the line counts in the hunk headers"), + APPLY_OPT_RECOUNT), + { OPTION_CALLBACK, 0, "directory", state, N_("root"), + N_("prepend to all filenames"), + 0, apply_option_parse_directory }, + OPT_END() + }; + + return parse_options(argc, argv, state->prefix, builtin_apply_options, apply_usage, 0); +} diff --git a/apply.h b/apply.h new file mode 100644 index 0000000..b3d6783 --- /dev/null +++ b/apply.h @@ -0,0 +1,137 @@ +#ifndef APPLY_H +#define APPLY_H + +enum apply_ws_error_action { + nowarn_ws_error, + warn_on_ws_error, + die_on_ws_error, + correct_ws_error +}; + +enum apply_ws_ignore { + ignore_ws_none, + ignore_ws_change +}; + +enum apply_verbosity { + verbosity_silent = -1, + verbosity_normal = 0, + verbosity_verbose = 1 +}; + +/* + * We need to keep track of how symlinks in the preimage are + * manipulated by the patches. A patch to add a/b/c where a/b + * is a symlink should not be allowed to affect the directory + * the symlink points at, but if the same patch removes a/b, + * it is perfectly fine, as the patch removes a/b to make room + * to create a directory a/b so that a/b/c can be created. + * + * See also "struct string_list symlink_changes" in "struct + * apply_state". + */ +#define APPLY_SYMLINK_GOES_AWAY 01 +#define APPLY_SYMLINK_IN_RESULT 02 + +struct apply_state { + const char *prefix; + int prefix_length; + + /* These are lock_file related */ + struct lock_file *lock_file; + int newfd; + + /* These control what gets looked at and modified */ + int apply; /* this is not a dry-run */ + int cached; /* apply to the index only */ + int check; /* preimage must match working tree, don't actually apply */ + int check_index; /* preimage must match the indexed version */ + int update_index; /* check_index && apply */ + + /* These control cosmetic aspect of the output */ + int diffstat; /* just show a diffstat, and don't actually apply */ + int numstat; /* just show a numeric diffstat, and don't actually apply */ + int summary; /* just report creation, deletion, etc, and don't actually apply */ + + /* These boolean parameters control how the apply is done */ + int allow_overlap; + int apply_in_reverse; + int apply_with_reject; + int no_add; + int threeway; + int unidiff_zero; + int unsafe_paths; + + /* Other non boolean parameters */ + const char *index_file; + enum apply_verbosity apply_verbosity; + const char *fake_ancestor; + const char *patch_input_file; + int line_termination; + struct strbuf root; + int p_value; + int p_value_known; + unsigned int p_context; + + /* Exclude and include path parameters */ + struct string_list limit_by_name; + int has_include; + + /* Various "current state" */ + int linenr; /* current line number */ + struct string_list symlink_changes; /* we have to track symlinks */ + + /* + * For "diff-stat" like behaviour, we keep track of the biggest change + * we've seen, and the longest filename. That allows us to do simple + * scaling. + */ + int max_change; + int max_len; + + /* + * Records filenames that have been touched, in order to handle + * the case where more than one patches touch the same file. + */ + struct string_list fn_table; + + /* + * This is to save reporting routines before using + * set_error_routine() or set_warn_routine() to install muting + * routines when in verbosity_silent mode. + */ + void (*saved_error_routine)(const char *err, va_list params); + void (*saved_warn_routine)(const char *warn, va_list params); + + /* These control whitespace errors */ + enum apply_ws_error_action ws_error_action; + enum apply_ws_ignore ws_ignore_action; + const char *whitespace_option; + int whitespace_error; + int squelch_whitespace_errors; + int applied_after_fixing_ws; +}; + +extern int apply_parse_options(int argc, const char **argv, + struct apply_state *state, + int *force_apply, int *options, + const char * const *apply_usage); +extern int init_apply_state(struct apply_state *state, + const char *prefix, + struct lock_file *lock_file); +extern void clear_apply_state(struct apply_state *state); +extern int check_apply_state(struct apply_state *state, int force_apply); + +/* + * Some aspects of the apply behavior are controlled by the following + * bits in the "options" parameter passed to apply_all_patches(). + */ +#define APPLY_OPT_INACCURATE_EOF (1<<0) /* accept inaccurate eof */ +#define APPLY_OPT_RECOUNT (1<<1) /* accept inaccurate line count */ + +extern int apply_all_patches(struct apply_state *state, + int argc, + const char **argv, + int options); + +#endif diff --git a/archive.c b/archive.c index dde1ab4..01751e5 100644 --- a/archive.c +++ b/archive.c @@ -504,15 +504,11 @@ static int parse_archive_args(int argc, const char **argv, } int write_archive(int argc, const char **argv, const char *prefix, - int setup_prefix, const char *name_hint, int remote) + const char *name_hint, int remote) { - int nongit = 0; const struct archiver *ar = NULL; struct archiver_args args; - if (setup_prefix && prefix == NULL) - prefix = setup_git_directory_gently(&nongit); - git_config_get_bool("uploadarchive.allowunreachable", &remote_allow_unreachable); git_config(git_default_config, NULL); @@ -520,7 +516,7 @@ int write_archive(int argc, const char **argv, const char *prefix, init_zip_archiver(); argc = parse_archive_args(argc, argv, &ar, &args, name_hint, remote); - if (nongit) { + if (!startup_info->have_repository) { /* * We know this will die() with an error, so we could just * die ourselves; but its error message will be more specific diff --git a/archive.h b/archive.h index 4a791e1..415e015 100644 --- a/archive.h +++ b/archive.h @@ -36,7 +36,7 @@ typedef int (*write_archive_entry_fn_t)(struct archiver_args *args, unsigned int mode); extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry); -extern int write_archive(int argc, const char **argv, const char *prefix, int setup_prefix, const char *name_hint, int remote); +extern int write_archive(int argc, const char **argv, const char *prefix, const char *name_hint, int remote); const char *archive_format_from_filename(const char *filename); extern void *sha1_file_to_archive(const struct archiver_args *args, diff --git a/attr.c b/attr.c index eec5d7d..1fcf042 100644 --- a/attr.c +++ b/attr.c @@ -531,7 +531,11 @@ static void bootstrap_attr_stack(void) debug_push(elem); } - elem = read_attr_from_file(git_path_info_attributes(), 1); + if (startup_info->have_repository) + elem = read_attr_from_file(git_path_info_attributes(), 1); + else + elem = NULL; + if (!elem) elem = xcalloc(1, sizeof(*elem)); elem->origin = NULL; diff --git a/bisect.c b/bisect.c index 6f512c2..21bc6da 100644 --- a/bisect.c +++ b/bisect.c @@ -215,7 +215,7 @@ static struct commit_list *best_bisection_sorted(struct commit_list *list, int n array[cnt].distance = distance; cnt++; } - qsort(array, cnt, sizeof(*array), compare_commit_dist); + QSORT(array, cnt, compare_commit_dist); for (p = list, i = 0; i < cnt; i++) { char buf[100]; /* enough for dist=%d */ struct object *obj = &(array[i].commit->object); diff --git a/builtin.h b/builtin.h index 6b95006..b9122bc 100644 --- a/builtin.h +++ b/builtin.h @@ -25,7 +25,7 @@ struct fmt_merge_msg_opts { extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out, struct fmt_merge_msg_opts *); -extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, int sha1_valid, char **buf, unsigned long *buf_size); +extern int textconv_object(const char *path, unsigned mode, const struct object_id *oid, int oid_valid, char **buf, unsigned long *buf_size); extern int is_builtin(const char *s); diff --git a/builtin/am.c b/builtin/am.c index 9daeb27..6981f42 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -28,6 +28,7 @@ #include "rerere.h" #include "prompt.h" #include "mailinfo.h" +#include "apply.h" #include "string-list.h" /** @@ -109,7 +110,7 @@ struct am_state { size_t msg_len; /* when --rebasing, records the original commit the patch came from */ - unsigned char orig_commit[GIT_SHA1_RAWSZ]; + struct object_id orig_commit; /* number of digits in patch filename */ int prec; @@ -415,8 +416,8 @@ static void am_load(struct am_state *state) read_commit_msg(state); if (read_state_file(&sb, state, "original-commit", 1) < 0) - hashclr(state->orig_commit); - else if (get_sha1_hex(sb.buf, state->orig_commit) < 0) + oidclr(&state->orig_commit); + else if (get_oid_hex(sb.buf, &state->orig_commit) < 0) die(_("could not parse %s"), am_path(state, "original-commit")); read_state_file(&sb, state, "threeway", 1); @@ -542,14 +543,14 @@ static int copy_notes_for_rebase(const struct am_state *state) fp = xfopen(am_path(state, "rewritten"), "r"); while (!strbuf_getline_lf(&sb, fp)) { - unsigned char from_obj[GIT_SHA1_RAWSZ], to_obj[GIT_SHA1_RAWSZ]; + struct object_id from_obj, to_obj; if (sb.len != GIT_SHA1_HEXSZ * 2 + 1) { ret = error(invalid_line, sb.buf); goto finish; } - if (get_sha1_hex(sb.buf, from_obj)) { + if (get_oid_hex(sb.buf, &from_obj)) { ret = error(invalid_line, sb.buf); goto finish; } @@ -559,14 +560,14 @@ static int copy_notes_for_rebase(const struct am_state *state) goto finish; } - if (get_sha1_hex(sb.buf + GIT_SHA1_HEXSZ + 1, to_obj)) { + if (get_oid_hex(sb.buf + GIT_SHA1_HEXSZ + 1, &to_obj)) { ret = error(invalid_line, sb.buf); goto finish; } - if (copy_note_for_rewrite(c, from_obj, to_obj)) + if (copy_note_for_rewrite(c, from_obj.hash, to_obj.hash)) ret = error(_("Failed to copy notes from '%s' to '%s'"), - sha1_to_hex(from_obj), sha1_to_hex(to_obj)); + oid_to_hex(&from_obj), oid_to_hex(&to_obj)); } finish: @@ -972,7 +973,7 @@ static int split_mail(struct am_state *state, enum patch_format patch_format, static void am_setup(struct am_state *state, enum patch_format patch_format, const char **paths, int keep_cr) { - unsigned char curr_head[GIT_SHA1_RAWSZ]; + struct object_id curr_head; const char *str; struct strbuf sb = STRBUF_INIT; @@ -1040,10 +1041,10 @@ static void am_setup(struct am_state *state, enum patch_format patch_format, else write_state_text(state, "applying", ""); - if (!get_sha1("HEAD", curr_head)) { - write_state_text(state, "abort-safety", sha1_to_hex(curr_head)); + if (!get_oid("HEAD", &curr_head)) { + write_state_text(state, "abort-safety", oid_to_hex(&curr_head)); if (!state->rebasing) - update_ref("am", "ORIG_HEAD", curr_head, NULL, 0, + update_ref_oid("am", "ORIG_HEAD", &curr_head, NULL, 0, UPDATE_REFS_DIE_ON_ERR); } else { write_state_text(state, "abort-safety", ""); @@ -1068,7 +1069,7 @@ static void am_setup(struct am_state *state, enum patch_format patch_format, */ static void am_next(struct am_state *state) { - unsigned char head[GIT_SHA1_RAWSZ]; + struct object_id head; free(state->author_name); state->author_name = NULL; @@ -1086,11 +1087,11 @@ static void am_next(struct am_state *state) unlink(am_path(state, "author-script")); unlink(am_path(state, "final-commit")); - hashclr(state->orig_commit); + oidclr(&state->orig_commit); unlink(am_path(state, "original-commit")); - if (!get_sha1("HEAD", head)) - write_state_text(state, "abort-safety", sha1_to_hex(head)); + if (!get_oid("HEAD", &head)) + write_state_text(state, "abort-safety", oid_to_hex(&head)); else write_state_text(state, "abort-safety", ""); @@ -1132,17 +1133,17 @@ static void refresh_and_write_cache(void) */ static int index_has_changes(struct strbuf *sb) { - unsigned char head[GIT_SHA1_RAWSZ]; + struct object_id head; int i; - if (!get_sha1_tree("HEAD", head)) { + if (!get_sha1_tree("HEAD", head.hash)) { struct diff_options opt; diff_setup(&opt); DIFF_OPT_SET(&opt, EXIT_WITH_STATUS); if (!sb) DIFF_OPT_SET(&opt, QUICK); - do_diff_cache(head, &opt); + do_diff_cache(head.hash, &opt); diffcore_std(&opt); for (i = 0; sb && i < diff_queued_diff.nr; i++) { if (i) @@ -1349,7 +1350,7 @@ finish: * Sets commit_id to the commit hash where the mail was generated from. * Returns 0 on success, -1 on failure. */ -static int get_mail_commit_sha1(unsigned char *commit_id, const char *mail) +static int get_mail_commit_oid(struct object_id *commit_id, const char *mail) { struct strbuf sb = STRBUF_INIT; FILE *fp = xfopen(mail, "r"); @@ -1361,7 +1362,7 @@ static int get_mail_commit_sha1(unsigned char *commit_id, const char *mail) if (!skip_prefix(sb.buf, "From ", &x)) return -1; - if (get_sha1_hex(x, commit_id) < 0) + if (get_oid_hex(x, commit_id) < 0) return -1; strbuf_release(&sb); @@ -1451,12 +1452,12 @@ static void write_commit_patch(const struct am_state *state, struct commit *comm static void write_index_patch(const struct am_state *state) { struct tree *tree; - unsigned char head[GIT_SHA1_RAWSZ]; + struct object_id head; struct rev_info rev_info; FILE *fp; - if (!get_sha1_tree("HEAD", head)) - tree = lookup_tree(head); + if (!get_sha1_tree("HEAD", head.hash)) + tree = lookup_tree(head.hash); else tree = lookup_tree(EMPTY_TREE_SHA1_BIN); @@ -1486,19 +1487,19 @@ static void write_index_patch(const struct am_state *state) static int parse_mail_rebase(struct am_state *state, const char *mail) { struct commit *commit; - unsigned char commit_sha1[GIT_SHA1_RAWSZ]; + struct object_id commit_oid; - if (get_mail_commit_sha1(commit_sha1, mail) < 0) + if (get_mail_commit_oid(&commit_oid, mail) < 0) die(_("could not parse %s"), mail); - commit = lookup_commit_or_die(commit_sha1, mail); + commit = lookup_commit_or_die(commit_oid.hash, mail); get_commit_info(state, commit); write_commit_patch(state, commit); - hashcpy(state->orig_commit, commit_sha1); - write_state_text(state, "original-commit", sha1_to_hex(commit_sha1)); + oidcpy(&state->orig_commit, &commit_oid); + write_state_text(state, "original-commit", oid_to_hex(&commit_oid)); return 0; } @@ -1509,39 +1510,59 @@ static int parse_mail_rebase(struct am_state *state, const char *mail) */ static int run_apply(const struct am_state *state, const char *index_file) { - struct child_process cp = CHILD_PROCESS_INIT; - - cp.git_cmd = 1; - - if (index_file) - argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s", index_file); + struct argv_array apply_paths = ARGV_ARRAY_INIT; + struct argv_array apply_opts = ARGV_ARRAY_INIT; + struct apply_state apply_state; + int res, opts_left; + static struct lock_file lock_file; + int force_apply = 0; + int options = 0; + + if (init_apply_state(&apply_state, NULL, &lock_file)) + die("BUG: init_apply_state() failed"); + + argv_array_push(&apply_opts, "apply"); + argv_array_pushv(&apply_opts, state->git_apply_opts.argv); + + opts_left = apply_parse_options(apply_opts.argc, apply_opts.argv, + &apply_state, &force_apply, &options, + NULL); + + if (opts_left != 0) + die("unknown option passed through to git apply"); + + if (index_file) { + apply_state.index_file = index_file; + apply_state.cached = 1; + } else + apply_state.check_index = 1; /* * If we are allowed to fall back on 3-way merge, don't give false * errors during the initial attempt. */ - if (state->threeway && !index_file) { - cp.no_stdout = 1; - cp.no_stderr = 1; - } + if (state->threeway && !index_file) + apply_state.apply_verbosity = verbosity_silent; - argv_array_push(&cp.args, "apply"); + if (check_apply_state(&apply_state, force_apply)) + die("BUG: check_apply_state() failed"); - argv_array_pushv(&cp.args, state->git_apply_opts.argv); + argv_array_push(&apply_paths, am_path(state, "patch")); - if (index_file) - argv_array_push(&cp.args, "--cached"); - else - argv_array_push(&cp.args, "--index"); + res = apply_all_patches(&apply_state, apply_paths.argc, apply_paths.argv, options); - argv_array_push(&cp.args, am_path(state, "patch")); + argv_array_clear(&apply_paths); + argv_array_clear(&apply_opts); + clear_apply_state(&apply_state); - if (run_command(&cp)) - return -1; + if (res) + return res; - /* Reload index as git-apply will have modified it. */ - discard_cache(); - read_cache_from(index_file ? index_file : get_index_file()); + if (index_file) { + /* Reload index as apply_all_patches() will have modified it. */ + discard_cache(); + read_cache_from(index_file); + } return 0; } @@ -1652,9 +1673,8 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa */ static void do_commit(const struct am_state *state) { - unsigned char tree[GIT_SHA1_RAWSZ], parent[GIT_SHA1_RAWSZ], - commit[GIT_SHA1_RAWSZ]; - unsigned char *ptr; + struct object_id tree, parent, commit; + const struct object_id *old_oid; struct commit_list *parents = NULL; const char *reflog_msg, *author; struct strbuf sb = STRBUF_INIT; @@ -1662,14 +1682,14 @@ static void do_commit(const struct am_state *state) if (run_hook_le(NULL, "pre-applypatch", NULL)) exit(1); - if (write_cache_as_tree(tree, 0, NULL)) + if (write_cache_as_tree(tree.hash, 0, NULL)) die(_("git write-tree failed to write a tree")); - if (!get_sha1_commit("HEAD", parent)) { - ptr = parent; - commit_list_insert(lookup_commit(parent), &parents); + if (!get_sha1_commit("HEAD", parent.hash)) { + old_oid = &parent; + commit_list_insert(lookup_commit(parent.hash), &parents); } else { - ptr = NULL; + old_oid = NULL; say(state, stderr, _("applying to an empty history")); } @@ -1681,7 +1701,7 @@ static void do_commit(const struct am_state *state) setenv("GIT_COMMITTER_DATE", state->ignore_date ? "" : state->author_date, 1); - if (commit_tree(state->msg, state->msg_len, tree, parents, commit, + if (commit_tree(state->msg, state->msg_len, tree.hash, parents, commit.hash, author, state->sign_commit)) die(_("failed to write commit object")); @@ -1692,14 +1712,15 @@ static void do_commit(const struct am_state *state) strbuf_addf(&sb, "%s: %.*s", reflog_msg, linelen(state->msg), state->msg); - update_ref(sb.buf, "HEAD", commit, ptr, 0, UPDATE_REFS_DIE_ON_ERR); + update_ref_oid(sb.buf, "HEAD", &commit, old_oid, 0, + UPDATE_REFS_DIE_ON_ERR); if (state->rebasing) { FILE *fp = xfopen(am_path(state, "rewritten"), "a"); - assert(!is_null_sha1(state->orig_commit)); - fprintf(fp, "%s ", sha1_to_hex(state->orig_commit)); - fprintf(fp, "%s\n", sha1_to_hex(commit)); + assert(!is_null_oid(&state->orig_commit)); + fprintf(fp, "%s ", oid_to_hex(&state->orig_commit)); + fprintf(fp, "%s\n", oid_to_hex(&commit)); fclose(fp); } @@ -2020,30 +2041,30 @@ static int merge_tree(struct tree *tree) * Clean the index without touching entries that are not modified between * `head` and `remote`. */ -static int clean_index(const unsigned char *head, const unsigned char *remote) +static int clean_index(const struct object_id *head, const struct object_id *remote) { struct tree *head_tree, *remote_tree, *index_tree; - unsigned char index[GIT_SHA1_RAWSZ]; + struct object_id index; - head_tree = parse_tree_indirect(head); + head_tree = parse_tree_indirect(head->hash); if (!head_tree) - return error(_("Could not parse object '%s'."), sha1_to_hex(head)); + return error(_("Could not parse object '%s'."), oid_to_hex(head)); - remote_tree = parse_tree_indirect(remote); + remote_tree = parse_tree_indirect(remote->hash); if (!remote_tree) - return error(_("Could not parse object '%s'."), sha1_to_hex(remote)); + return error(_("Could not parse object '%s'."), oid_to_hex(remote)); read_cache_unmerged(); if (fast_forward_to(head_tree, head_tree, 1)) return -1; - if (write_cache_as_tree(index, 0, NULL)) + if (write_cache_as_tree(index.hash, 0, NULL)) return -1; - index_tree = parse_tree_indirect(index); + index_tree = parse_tree_indirect(index.hash); if (!index_tree) - return error(_("Could not parse object '%s'."), sha1_to_hex(index)); + return error(_("Could not parse object '%s'."), oid_to_hex(&index)); if (fast_forward_to(index_tree, remote_tree, 0)) return -1; @@ -2071,14 +2092,14 @@ static void am_rerere_clear(void) */ static void am_skip(struct am_state *state) { - unsigned char head[GIT_SHA1_RAWSZ]; + struct object_id head; am_rerere_clear(); - if (get_sha1("HEAD", head)) - hashcpy(head, EMPTY_TREE_SHA1_BIN); + if (get_oid("HEAD", &head)) + hashcpy(head.hash, EMPTY_TREE_SHA1_BIN); - if (clean_index(head, head)) + if (clean_index(&head, &head)) die(_("failed to clean index")); am_next(state); @@ -2096,21 +2117,21 @@ static void am_skip(struct am_state *state) static int safe_to_abort(const struct am_state *state) { struct strbuf sb = STRBUF_INIT; - unsigned char abort_safety[GIT_SHA1_RAWSZ], head[GIT_SHA1_RAWSZ]; + struct object_id abort_safety, head; if (file_exists(am_path(state, "dirtyindex"))) return 0; if (read_state_file(&sb, state, "abort-safety", 1) > 0) { - if (get_sha1_hex(sb.buf, abort_safety)) + if (get_oid_hex(sb.buf, &abort_safety)) die(_("could not parse %s"), am_path(state, "abort_safety")); } else - hashclr(abort_safety); + oidclr(&abort_safety); - if (get_sha1("HEAD", head)) - hashclr(head); + if (get_oid("HEAD", &head)) + oidclr(&head); - if (!hashcmp(head, abort_safety)) + if (!oidcmp(&head, &abort_safety)) return 1; error(_("You seem to have moved HEAD since the last 'am' failure.\n" @@ -2124,7 +2145,7 @@ static int safe_to_abort(const struct am_state *state) */ static void am_abort(struct am_state *state) { - unsigned char curr_head[GIT_SHA1_RAWSZ], orig_head[GIT_SHA1_RAWSZ]; + struct object_id curr_head, orig_head; int has_curr_head, has_orig_head; char *curr_branch; @@ -2135,20 +2156,20 @@ static void am_abort(struct am_state *state) am_rerere_clear(); - curr_branch = resolve_refdup("HEAD", 0, curr_head, NULL); - has_curr_head = !is_null_sha1(curr_head); + curr_branch = resolve_refdup("HEAD", 0, curr_head.hash, NULL); + has_curr_head = !is_null_oid(&curr_head); if (!has_curr_head) - hashcpy(curr_head, EMPTY_TREE_SHA1_BIN); + hashcpy(curr_head.hash, EMPTY_TREE_SHA1_BIN); - has_orig_head = !get_sha1("ORIG_HEAD", orig_head); + has_orig_head = !get_oid("ORIG_HEAD", &orig_head); if (!has_orig_head) - hashcpy(orig_head, EMPTY_TREE_SHA1_BIN); + hashcpy(orig_head.hash, EMPTY_TREE_SHA1_BIN); - clean_index(curr_head, orig_head); + clean_index(&curr_head, &orig_head); if (has_orig_head) - update_ref("am --abort", "HEAD", orig_head, - has_curr_head ? curr_head : NULL, 0, + update_ref_oid("am --abort", "HEAD", &orig_head, + has_curr_head ? &curr_head : NULL, 0, UPDATE_REFS_DIE_ON_ERR); else if (curr_branch) delete_ref(curr_branch, NULL, REF_NODEREF); diff --git a/builtin/apply.c b/builtin/apply.c index 1a488f9..81b9a61 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -1,4793 +1,16 @@ -/* - * apply.c - * - * Copyright (C) Linus Torvalds, 2005 - * - * This applies patches on top of some (arbitrary) version of the SCM. - * - */ #include "cache.h" -#include "lockfile.h" -#include "cache-tree.h" -#include "quote.h" -#include "blob.h" -#include "delta.h" -#include "builtin.h" -#include "string-list.h" -#include "dir.h" -#include "diff.h" -#include "parse-options.h" -#include "xdiff-interface.h" -#include "ll-merge.h" -#include "rerere.h" - -enum ws_error_action { - nowarn_ws_error, - warn_on_ws_error, - die_on_ws_error, - correct_ws_error -}; - - -enum ws_ignore { - ignore_ws_none, - ignore_ws_change -}; - -/* - * We need to keep track of how symlinks in the preimage are - * manipulated by the patches. A patch to add a/b/c where a/b - * is a symlink should not be allowed to affect the directory - * the symlink points at, but if the same patch removes a/b, - * it is perfectly fine, as the patch removes a/b to make room - * to create a directory a/b so that a/b/c can be created. - * - * See also "struct string_list symlink_changes" in "struct - * apply_state". - */ -#define SYMLINK_GOES_AWAY 01 -#define SYMLINK_IN_RESULT 02 - -struct apply_state { - const char *prefix; - int prefix_length; - - /* These are lock_file related */ - struct lock_file *lock_file; - int newfd; - - /* These control what gets looked at and modified */ - int apply; /* this is not a dry-run */ - int cached; /* apply to the index only */ - int check; /* preimage must match working tree, don't actually apply */ - int check_index; /* preimage must match the indexed version */ - int update_index; /* check_index && apply */ - - /* These control cosmetic aspect of the output */ - int diffstat; /* just show a diffstat, and don't actually apply */ - int numstat; /* just show a numeric diffstat, and don't actually apply */ - int summary; /* just report creation, deletion, etc, and don't actually apply */ - - /* These boolean parameters control how the apply is done */ - int allow_overlap; - int apply_in_reverse; - int apply_with_reject; - int apply_verbosely; - int no_add; - int threeway; - int unidiff_zero; - int unsafe_paths; - - /* Other non boolean parameters */ - const char *fake_ancestor; - const char *patch_input_file; - int line_termination; - struct strbuf root; - int p_value; - int p_value_known; - unsigned int p_context; - - /* Exclude and include path parameters */ - struct string_list limit_by_name; - int has_include; - - /* Various "current state" */ - int linenr; /* current line number */ - struct string_list symlink_changes; /* we have to track symlinks */ - - /* - * For "diff-stat" like behaviour, we keep track of the biggest change - * we've seen, and the longest filename. That allows us to do simple - * scaling. - */ - int max_change; - int max_len; - - /* - * Records filenames that have been touched, in order to handle - * the case where more than one patches touch the same file. - */ - struct string_list fn_table; - - /* These control whitespace errors */ - enum ws_error_action ws_error_action; - enum ws_ignore ws_ignore_action; - const char *whitespace_option; - int whitespace_error; - int squelch_whitespace_errors; - int applied_after_fixing_ws; -}; - -static const char * const apply_usage[] = { - N_("git apply [] [...]"), - NULL -}; - -static void parse_whitespace_option(struct apply_state *state, const char *option) -{ - if (!option) { - state->ws_error_action = warn_on_ws_error; - return; - } - if (!strcmp(option, "warn")) { - state->ws_error_action = warn_on_ws_error; - return; - } - if (!strcmp(option, "nowarn")) { - state->ws_error_action = nowarn_ws_error; - return; - } - if (!strcmp(option, "error")) { - state->ws_error_action = die_on_ws_error; - return; - } - if (!strcmp(option, "error-all")) { - state->ws_error_action = die_on_ws_error; - state->squelch_whitespace_errors = 0; - return; - } - if (!strcmp(option, "strip") || !strcmp(option, "fix")) { - state->ws_error_action = correct_ws_error; - return; - } - die(_("unrecognized whitespace option '%s'"), option); -} - -static void parse_ignorewhitespace_option(struct apply_state *state, - const char *option) -{ - if (!option || !strcmp(option, "no") || - !strcmp(option, "false") || !strcmp(option, "never") || - !strcmp(option, "none")) { - state->ws_ignore_action = ignore_ws_none; - return; - } - if (!strcmp(option, "change")) { - state->ws_ignore_action = ignore_ws_change; - return; - } - die(_("unrecognized whitespace ignore option '%s'"), option); -} - -static void set_default_whitespace_mode(struct apply_state *state) -{ - if (!state->whitespace_option && !apply_default_whitespace) - state->ws_error_action = (state->apply ? warn_on_ws_error : nowarn_ws_error); -} - -/* - * This represents one "hunk" from a patch, starting with - * "@@ -oldpos,oldlines +newpos,newlines @@" marker. The - * patch text is pointed at by patch, and its byte length - * is stored in size. leading and trailing are the number - * of context lines. - */ -struct fragment { - unsigned long leading, trailing; - unsigned long oldpos, oldlines; - unsigned long newpos, newlines; - /* - * 'patch' is usually borrowed from buf in apply_patch(), - * but some codepaths store an allocated buffer. - */ - const char *patch; - unsigned free_patch:1, - rejected:1; - int size; - int linenr; - struct fragment *next; -}; - -/* - * When dealing with a binary patch, we reuse "leading" field - * to store the type of the binary hunk, either deflated "delta" - * or deflated "literal". - */ -#define binary_patch_method leading -#define BINARY_DELTA_DEFLATED 1 -#define BINARY_LITERAL_DEFLATED 2 - -/* - * This represents a "patch" to a file, both metainfo changes - * such as creation/deletion, filemode and content changes represented - * as a series of fragments. - */ -struct patch { - char *new_name, *old_name, *def_name; - unsigned int old_mode, new_mode; - int is_new, is_delete; /* -1 = unknown, 0 = false, 1 = true */ - int rejected; - unsigned ws_rule; - int lines_added, lines_deleted; - int score; - unsigned int is_toplevel_relative:1; - unsigned int inaccurate_eof:1; - unsigned int is_binary:1; - unsigned int is_copy:1; - unsigned int is_rename:1; - unsigned int recount:1; - unsigned int conflicted_threeway:1; - unsigned int direct_to_threeway:1; - struct fragment *fragments; - char *result; - size_t resultsize; - char old_sha1_prefix[41]; - char new_sha1_prefix[41]; - struct patch *next; - - /* three-way fallback result */ - struct object_id threeway_stage[3]; -}; - -static void free_fragment_list(struct fragment *list) -{ - while (list) { - struct fragment *next = list->next; - if (list->free_patch) - free((char *)list->patch); - free(list); - list = next; - } -} - -static void free_patch(struct patch *patch) -{ - free_fragment_list(patch->fragments); - free(patch->def_name); - free(patch->old_name); - free(patch->new_name); - free(patch->result); - free(patch); -} - -static void free_patch_list(struct patch *list) -{ - while (list) { - struct patch *next = list->next; - free_patch(list); - list = next; - } -} - -/* - * A line in a file, len-bytes long (includes the terminating LF, - * except for an incomplete line at the end if the file ends with - * one), and its contents hashes to 'hash'. - */ -struct line { - size_t len; - unsigned hash : 24; - unsigned flag : 8; -#define LINE_COMMON 1 -#define LINE_PATCHED 2 -}; - -/* - * This represents a "file", which is an array of "lines". - */ -struct image { - char *buf; - size_t len; - size_t nr; - size_t alloc; - struct line *line_allocated; - struct line *line; -}; - -static uint32_t hash_line(const char *cp, size_t len) -{ - size_t i; - uint32_t h; - for (i = 0, h = 0; i < len; i++) { - if (!isspace(cp[i])) { - h = h * 3 + (cp[i] & 0xff); - } - } - return h; -} - -/* - * Compare lines s1 of length n1 and s2 of length n2, ignoring - * whitespace difference. Returns 1 if they match, 0 otherwise - */ -static int fuzzy_matchlines(const char *s1, size_t n1, - const char *s2, size_t n2) -{ - const char *last1 = s1 + n1 - 1; - const char *last2 = s2 + n2 - 1; - int result = 0; - - /* ignore line endings */ - while ((*last1 == '\r') || (*last1 == '\n')) - last1--; - while ((*last2 == '\r') || (*last2 == '\n')) - last2--; - - /* skip leading whitespaces, if both begin with whitespace */ - if (s1 <= last1 && s2 <= last2 && isspace(*s1) && isspace(*s2)) { - while (isspace(*s1) && (s1 <= last1)) - s1++; - while (isspace(*s2) && (s2 <= last2)) - s2++; - } - /* early return if both lines are empty */ - if ((s1 > last1) && (s2 > last2)) - return 1; - while (!result) { - result = *s1++ - *s2++; - /* - * Skip whitespace inside. We check for whitespace on - * both buffers because we don't want "a b" to match - * "ab" - */ - if (isspace(*s1) && isspace(*s2)) { - while (isspace(*s1) && s1 <= last1) - s1++; - while (isspace(*s2) && s2 <= last2) - s2++; - } - /* - * If we reached the end on one side only, - * lines don't match - */ - if ( - ((s2 > last2) && (s1 <= last1)) || - ((s1 > last1) && (s2 <= last2))) - return 0; - if ((s1 > last1) && (s2 > last2)) - break; - } - - return !result; -} - -static void add_line_info(struct image *img, const char *bol, size_t len, unsigned flag) -{ - ALLOC_GROW(img->line_allocated, img->nr + 1, img->alloc); - img->line_allocated[img->nr].len = len; - img->line_allocated[img->nr].hash = hash_line(bol, len); - img->line_allocated[img->nr].flag = flag; - img->nr++; -} - -/* - * "buf" has the file contents to be patched (read from various sources). - * attach it to "image" and add line-based index to it. - * "image" now owns the "buf". - */ -static void prepare_image(struct image *image, char *buf, size_t len, - int prepare_linetable) -{ - const char *cp, *ep; - - memset(image, 0, sizeof(*image)); - image->buf = buf; - image->len = len; - - if (!prepare_linetable) - return; - - ep = image->buf + image->len; - cp = image->buf; - while (cp < ep) { - const char *next; - for (next = cp; next < ep && *next != '\n'; next++) - ; - if (next < ep) - next++; - add_line_info(image, cp, next - cp, 0); - cp = next; - } - image->line = image->line_allocated; -} - -static void clear_image(struct image *image) -{ - free(image->buf); - free(image->line_allocated); - memset(image, 0, sizeof(*image)); -} - -/* fmt must contain _one_ %s and no other substitution */ -static void say_patch_name(FILE *output, const char *fmt, struct patch *patch) -{ - struct strbuf sb = STRBUF_INIT; - - if (patch->old_name && patch->new_name && - strcmp(patch->old_name, patch->new_name)) { - quote_c_style(patch->old_name, &sb, NULL, 0); - strbuf_addstr(&sb, " => "); - quote_c_style(patch->new_name, &sb, NULL, 0); - } else { - const char *n = patch->new_name; - if (!n) - n = patch->old_name; - quote_c_style(n, &sb, NULL, 0); - } - fprintf(output, fmt, sb.buf); - fputc('\n', output); - strbuf_release(&sb); -} - -#define SLOP (16) - -static void read_patch_file(struct strbuf *sb, int fd) -{ - if (strbuf_read(sb, fd, 0) < 0) - die_errno("git apply: failed to read"); - - /* - * Make sure that we have some slop in the buffer - * so that we can do speculative "memcmp" etc, and - * see to it that it is NUL-filled. - */ - strbuf_grow(sb, SLOP); - memset(sb->buf + sb->len, 0, SLOP); -} - -static unsigned long linelen(const char *buffer, unsigned long size) -{ - unsigned long len = 0; - while (size--) { - len++; - if (*buffer++ == '\n') - break; - } - return len; -} - -static int is_dev_null(const char *str) -{ - return skip_prefix(str, "/dev/null", &str) && isspace(*str); -} - -#define TERM_SPACE 1 -#define TERM_TAB 2 - -static int name_terminate(int c, int terminate) -{ - if (c == ' ' && !(terminate & TERM_SPACE)) - return 0; - if (c == '\t' && !(terminate & TERM_TAB)) - return 0; - - return 1; -} - -/* remove double slashes to make --index work with such filenames */ -static char *squash_slash(char *name) -{ - int i = 0, j = 0; - - if (!name) - return NULL; - - while (name[i]) { - if ((name[j++] = name[i++]) == '/') - while (name[i] == '/') - i++; - } - name[j] = '\0'; - return name; -} - -static char *find_name_gnu(struct apply_state *state, - const char *line, - const char *def, - int p_value) -{ - struct strbuf name = STRBUF_INIT; - char *cp; - - /* - * Proposed "new-style" GNU patch/diff format; see - * http://marc.info/?l=git&m=112927316408690&w=2 - */ - if (unquote_c_style(&name, line, NULL)) { - strbuf_release(&name); - return NULL; - } - - for (cp = name.buf; p_value; p_value--) { - cp = strchr(cp, '/'); - if (!cp) { - strbuf_release(&name); - return NULL; - } - cp++; - } - - strbuf_remove(&name, 0, cp - name.buf); - if (state->root.len) - strbuf_insert(&name, 0, state->root.buf, state->root.len); - return squash_slash(strbuf_detach(&name, NULL)); -} - -static size_t sane_tz_len(const char *line, size_t len) -{ - const char *tz, *p; - - if (len < strlen(" +0500") || line[len-strlen(" +0500")] != ' ') - return 0; - tz = line + len - strlen(" +0500"); - - if (tz[1] != '+' && tz[1] != '-') - return 0; - - for (p = tz + 2; p != line + len; p++) - if (!isdigit(*p)) - return 0; - - return line + len - tz; -} - -static size_t tz_with_colon_len(const char *line, size_t len) -{ - const char *tz, *p; - - if (len < strlen(" +08:00") || line[len - strlen(":00")] != ':') - return 0; - tz = line + len - strlen(" +08:00"); - - if (tz[0] != ' ' || (tz[1] != '+' && tz[1] != '-')) - return 0; - p = tz + 2; - if (!isdigit(*p++) || !isdigit(*p++) || *p++ != ':' || - !isdigit(*p++) || !isdigit(*p++)) - return 0; - - return line + len - tz; -} - -static size_t date_len(const char *line, size_t len) -{ - const char *date, *p; - - if (len < strlen("72-02-05") || line[len-strlen("-05")] != '-') - return 0; - p = date = line + len - strlen("72-02-05"); - - if (!isdigit(*p++) || !isdigit(*p++) || *p++ != '-' || - !isdigit(*p++) || !isdigit(*p++) || *p++ != '-' || - !isdigit(*p++) || !isdigit(*p++)) /* Not a date. */ - return 0; - - if (date - line >= strlen("19") && - isdigit(date[-1]) && isdigit(date[-2])) /* 4-digit year */ - date -= strlen("19"); - - return line + len - date; -} - -static size_t short_time_len(const char *line, size_t len) -{ - const char *time, *p; - - if (len < strlen(" 07:01:32") || line[len-strlen(":32")] != ':') - return 0; - p = time = line + len - strlen(" 07:01:32"); - - /* Permit 1-digit hours? */ - if (*p++ != ' ' || - !isdigit(*p++) || !isdigit(*p++) || *p++ != ':' || - !isdigit(*p++) || !isdigit(*p++) || *p++ != ':' || - !isdigit(*p++) || !isdigit(*p++)) /* Not a time. */ - return 0; - - return line + len - time; -} - -static size_t fractional_time_len(const char *line, size_t len) -{ - const char *p; - size_t n; - - /* Expected format: 19:41:17.620000023 */ - if (!len || !isdigit(line[len - 1])) - return 0; - p = line + len - 1; - - /* Fractional seconds. */ - while (p > line && isdigit(*p)) - p--; - if (*p != '.') - return 0; - - /* Hours, minutes, and whole seconds. */ - n = short_time_len(line, p - line); - if (!n) - return 0; - - return line + len - p + n; -} - -static size_t trailing_spaces_len(const char *line, size_t len) -{ - const char *p; - - /* Expected format: ' ' x (1 or more) */ - if (!len || line[len - 1] != ' ') - return 0; - - p = line + len; - while (p != line) { - p--; - if (*p != ' ') - return line + len - (p + 1); - } - - /* All spaces! */ - return len; -} - -static size_t diff_timestamp_len(const char *line, size_t len) -{ - const char *end = line + len; - size_t n; - - /* - * Posix: 2010-07-05 19:41:17 - * GNU: 2010-07-05 19:41:17.620000023 -0500 - */ - - if (!isdigit(end[-1])) - return 0; - - n = sane_tz_len(line, end - line); - if (!n) - n = tz_with_colon_len(line, end - line); - end -= n; - - n = short_time_len(line, end - line); - if (!n) - n = fractional_time_len(line, end - line); - end -= n; - - n = date_len(line, end - line); - if (!n) /* No date. Too bad. */ - return 0; - end -= n; - - if (end == line) /* No space before date. */ - return 0; - if (end[-1] == '\t') { /* Success! */ - end--; - return line + len - end; - } - if (end[-1] != ' ') /* No space before date. */ - return 0; - - /* Whitespace damage. */ - end -= trailing_spaces_len(line, end - line); - return line + len - end; -} - -static char *find_name_common(struct apply_state *state, - const char *line, - const char *def, - int p_value, - const char *end, - int terminate) -{ - int len; - const char *start = NULL; - - if (p_value == 0) - start = line; - while (line != end) { - char c = *line; - - if (!end && isspace(c)) { - if (c == '\n') - break; - if (name_terminate(c, terminate)) - break; - } - line++; - if (c == '/' && !--p_value) - start = line; - } - if (!start) - return squash_slash(xstrdup_or_null(def)); - len = line - start; - if (!len) - return squash_slash(xstrdup_or_null(def)); - - /* - * Generally we prefer the shorter name, especially - * if the other one is just a variation of that with - * something else tacked on to the end (ie "file.orig" - * or "file~"). - */ - if (def) { - int deflen = strlen(def); - if (deflen < len && !strncmp(start, def, deflen)) - return squash_slash(xstrdup(def)); - } - - if (state->root.len) { - char *ret = xstrfmt("%s%.*s", state->root.buf, len, start); - return squash_slash(ret); - } - - return squash_slash(xmemdupz(start, len)); -} - -static char *find_name(struct apply_state *state, - const char *line, - char *def, - int p_value, - int terminate) -{ - if (*line == '"') { - char *name = find_name_gnu(state, line, def, p_value); - if (name) - return name; - } - - return find_name_common(state, line, def, p_value, NULL, terminate); -} - -static char *find_name_traditional(struct apply_state *state, - const char *line, - char *def, - int p_value) -{ - size_t len; - size_t date_len; - - if (*line == '"') { - char *name = find_name_gnu(state, line, def, p_value); - if (name) - return name; - } - - len = strchrnul(line, '\n') - line; - date_len = diff_timestamp_len(line, len); - if (!date_len) - return find_name_common(state, line, def, p_value, NULL, TERM_TAB); - len -= date_len; - - return find_name_common(state, line, def, p_value, line + len, 0); -} - -static int count_slashes(const char *cp) -{ - int cnt = 0; - char ch; - - while ((ch = *cp++)) - if (ch == '/') - cnt++; - return cnt; -} - -/* - * Given the string after "--- " or "+++ ", guess the appropriate - * p_value for the given patch. - */ -static int guess_p_value(struct apply_state *state, const char *nameline) -{ - char *name, *cp; - int val = -1; - - if (is_dev_null(nameline)) - return -1; - name = find_name_traditional(state, nameline, NULL, 0); - if (!name) - return -1; - cp = strchr(name, '/'); - if (!cp) - val = 0; - else if (state->prefix) { - /* - * Does it begin with "a/$our-prefix" and such? Then this is - * very likely to apply to our directory. - */ - if (!strncmp(name, state->prefix, state->prefix_length)) - val = count_slashes(state->prefix); - else { - cp++; - if (!strncmp(cp, state->prefix, state->prefix_length)) - val = count_slashes(state->prefix) + 1; - } - } - free(name); - return val; -} - -/* - * Does the ---/+++ line have the POSIX timestamp after the last HT? - * GNU diff puts epoch there to signal a creation/deletion event. Is - * this such a timestamp? - */ -static int has_epoch_timestamp(const char *nameline) -{ - /* - * We are only interested in epoch timestamp; any non-zero - * fraction cannot be one, hence "(\.0+)?" in the regexp below. - * For the same reason, the date must be either 1969-12-31 or - * 1970-01-01, and the seconds part must be "00". - */ - const char stamp_regexp[] = - "^(1969-12-31|1970-01-01)" - " " - "[0-2][0-9]:[0-5][0-9]:00(\\.0+)?" - " " - "([-+][0-2][0-9]:?[0-5][0-9])\n"; - const char *timestamp = NULL, *cp, *colon; - static regex_t *stamp; - regmatch_t m[10]; - int zoneoffset; - int hourminute; - int status; - - for (cp = nameline; *cp != '\n'; cp++) { - if (*cp == '\t') - timestamp = cp + 1; - } - if (!timestamp) - return 0; - if (!stamp) { - stamp = xmalloc(sizeof(*stamp)); - if (regcomp(stamp, stamp_regexp, REG_EXTENDED)) { - warning(_("Cannot prepare timestamp regexp %s"), - stamp_regexp); - return 0; - } - } - - status = regexec(stamp, timestamp, ARRAY_SIZE(m), m, 0); - if (status) { - if (status != REG_NOMATCH) - warning(_("regexec returned %d for input: %s"), - status, timestamp); - return 0; - } - - zoneoffset = strtol(timestamp + m[3].rm_so + 1, (char **) &colon, 10); - if (*colon == ':') - zoneoffset = zoneoffset * 60 + strtol(colon + 1, NULL, 10); - else - zoneoffset = (zoneoffset / 100) * 60 + (zoneoffset % 100); - if (timestamp[m[3].rm_so] == '-') - zoneoffset = -zoneoffset; - - /* - * YYYY-MM-DD hh:mm:ss must be from either 1969-12-31 - * (west of GMT) or 1970-01-01 (east of GMT) - */ - if ((zoneoffset < 0 && memcmp(timestamp, "1969-12-31", 10)) || - (0 <= zoneoffset && memcmp(timestamp, "1970-01-01", 10))) - return 0; - - hourminute = (strtol(timestamp + 11, NULL, 10) * 60 + - strtol(timestamp + 14, NULL, 10) - - zoneoffset); - - return ((zoneoffset < 0 && hourminute == 1440) || - (0 <= zoneoffset && !hourminute)); -} - -/* - * Get the name etc info from the ---/+++ lines of a traditional patch header - * - * FIXME! The end-of-filename heuristics are kind of screwy. For existing - * files, we can happily check the index for a match, but for creating a - * new file we should try to match whatever "patch" does. I have no idea. - */ -static void parse_traditional_patch(struct apply_state *state, - const char *first, - const char *second, - struct patch *patch) -{ - char *name; - - first += 4; /* skip "--- " */ - second += 4; /* skip "+++ " */ - if (!state->p_value_known) { - int p, q; - p = guess_p_value(state, first); - q = guess_p_value(state, second); - if (p < 0) p = q; - if (0 <= p && p == q) { - state->p_value = p; - state->p_value_known = 1; - } - } - if (is_dev_null(first)) { - patch->is_new = 1; - patch->is_delete = 0; - name = find_name_traditional(state, second, NULL, state->p_value); - patch->new_name = name; - } else if (is_dev_null(second)) { - patch->is_new = 0; - patch->is_delete = 1; - name = find_name_traditional(state, first, NULL, state->p_value); - patch->old_name = name; - } else { - char *first_name; - first_name = find_name_traditional(state, first, NULL, state->p_value); - name = find_name_traditional(state, second, first_name, state->p_value); - free(first_name); - if (has_epoch_timestamp(first)) { - patch->is_new = 1; - patch->is_delete = 0; - patch->new_name = name; - } else if (has_epoch_timestamp(second)) { - patch->is_new = 0; - patch->is_delete = 1; - patch->old_name = name; - } else { - patch->old_name = name; - patch->new_name = xstrdup_or_null(name); - } - } - if (!name) - die(_("unable to find filename in patch at line %d"), state->linenr); -} - -static int gitdiff_hdrend(struct apply_state *state, - const char *line, - struct patch *patch) -{ - return -1; -} - -/* - * We're anal about diff header consistency, to make - * sure that we don't end up having strange ambiguous - * patches floating around. - * - * As a result, gitdiff_{old|new}name() will check - * their names against any previous information, just - * to make sure.. - */ -#define DIFF_OLD_NAME 0 -#define DIFF_NEW_NAME 1 - -static void gitdiff_verify_name(struct apply_state *state, - const char *line, - int isnull, - char **name, - int side) -{ - if (!*name && !isnull) { - *name = find_name(state, line, NULL, state->p_value, TERM_TAB); - return; - } - - if (*name) { - int len = strlen(*name); - char *another; - if (isnull) - die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), - *name, state->linenr); - another = find_name(state, line, NULL, state->p_value, TERM_TAB); - if (!another || memcmp(another, *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"), state->linenr); - free(another); - } 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"), state->linenr); - } -} - -static int gitdiff_oldname(struct apply_state *state, - const char *line, - struct patch *patch) -{ - gitdiff_verify_name(state, line, - patch->is_new, &patch->old_name, - DIFF_OLD_NAME); - return 0; -} - -static int gitdiff_newname(struct apply_state *state, - const char *line, - struct patch *patch) -{ - gitdiff_verify_name(state, line, - patch->is_delete, &patch->new_name, - DIFF_NEW_NAME); - return 0; -} - -static int gitdiff_oldmode(struct apply_state *state, - const char *line, - struct patch *patch) -{ - patch->old_mode = strtoul(line, NULL, 8); - return 0; -} - -static int gitdiff_newmode(struct apply_state *state, - const char *line, - struct patch *patch) -{ - patch->new_mode = strtoul(line, NULL, 8); - return 0; -} - -static int gitdiff_delete(struct apply_state *state, - const char *line, - struct patch *patch) -{ - patch->is_delete = 1; - free(patch->old_name); - patch->old_name = xstrdup_or_null(patch->def_name); - return gitdiff_oldmode(state, line, patch); -} - -static int gitdiff_newfile(struct apply_state *state, - const char *line, - struct patch *patch) -{ - patch->is_new = 1; - free(patch->new_name); - patch->new_name = xstrdup_or_null(patch->def_name); - return gitdiff_newmode(state, line, patch); -} - -static int gitdiff_copysrc(struct apply_state *state, - const char *line, - struct patch *patch) -{ - patch->is_copy = 1; - free(patch->old_name); - patch->old_name = find_name(state, line, NULL, state->p_value ? state->p_value - 1 : 0, 0); - return 0; -} - -static int gitdiff_copydst(struct apply_state *state, - const char *line, - struct patch *patch) -{ - patch->is_copy = 1; - free(patch->new_name); - patch->new_name = find_name(state, line, NULL, state->p_value ? state->p_value - 1 : 0, 0); - return 0; -} - -static int gitdiff_renamesrc(struct apply_state *state, - const char *line, - struct patch *patch) -{ - patch->is_rename = 1; - free(patch->old_name); - patch->old_name = find_name(state, line, NULL, state->p_value ? state->p_value - 1 : 0, 0); - return 0; -} - -static int gitdiff_renamedst(struct apply_state *state, - const char *line, - struct patch *patch) -{ - patch->is_rename = 1; - free(patch->new_name); - patch->new_name = find_name(state, line, NULL, state->p_value ? state->p_value - 1 : 0, 0); - return 0; -} - -static int gitdiff_similarity(struct apply_state *state, - const char *line, - struct patch *patch) -{ - unsigned long val = strtoul(line, NULL, 10); - if (val <= 100) - patch->score = val; - return 0; -} - -static int gitdiff_dissimilarity(struct apply_state *state, - const char *line, - struct patch *patch) -{ - unsigned long val = strtoul(line, NULL, 10); - if (val <= 100) - patch->score = val; - return 0; -} - -static int gitdiff_index(struct apply_state *state, - const char *line, - struct patch *patch) -{ - /* - * index line is N hexadecimal, "..", N hexadecimal, - * and optional space with octal mode. - */ - const char *ptr, *eol; - int len; - - ptr = strchr(line, '.'); - if (!ptr || ptr[1] != '.' || 40 < ptr - line) - return 0; - len = ptr - line; - memcpy(patch->old_sha1_prefix, line, len); - patch->old_sha1_prefix[len] = 0; - - line = ptr + 2; - ptr = strchr(line, ' '); - eol = strchrnul(line, '\n'); - - if (!ptr || eol < ptr) - ptr = eol; - len = ptr - line; - - if (40 < len) - return 0; - memcpy(patch->new_sha1_prefix, line, len); - patch->new_sha1_prefix[len] = 0; - if (*ptr == ' ') - patch->old_mode = strtoul(ptr+1, NULL, 8); - return 0; -} - -/* - * This is normal for a diff that doesn't change anything: we'll fall through - * into the next diff. Tell the parser to break out. - */ -static int gitdiff_unrecognized(struct apply_state *state, - const char *line, - struct patch *patch) -{ - return -1; -} - -/* - * Skip p_value leading components from "line"; as we do not accept - * absolute paths, return NULL in that case. - */ -static const char *skip_tree_prefix(struct apply_state *state, - const char *line, - int llen) -{ - int nslash; - int i; - - if (!state->p_value) - return (llen && line[0] == '/') ? NULL : line; - - nslash = state->p_value; - for (i = 0; i < llen; i++) { - int ch = line[i]; - if (ch == '/' && --nslash <= 0) - return (i == 0) ? NULL : &line[i + 1]; - } - return NULL; -} - -/* - * This is to extract the same name that appears on "diff --git" - * line. We do not find and return anything if it is a rename - * patch, and it is OK because we will find the name elsewhere. - * We need to reliably find name only when it is mode-change only, - * creation or deletion of an empty file. In any of these cases, - * both sides are the same name under a/ and b/ respectively. - */ -static char *git_header_name(struct apply_state *state, - const char *line, - int llen) -{ - const char *name; - const char *second = NULL; - size_t len, line_len; - - line += strlen("diff --git "); - llen -= strlen("diff --git "); - - if (*line == '"') { - const char *cp; - struct strbuf first = STRBUF_INIT; - struct strbuf sp = STRBUF_INIT; - - if (unquote_c_style(&first, line, &second)) - goto free_and_fail1; - - /* strip the a/b prefix including trailing slash */ - cp = skip_tree_prefix(state, first.buf, first.len); - if (!cp) - goto free_and_fail1; - strbuf_remove(&first, 0, cp - first.buf); - - /* - * second points at one past closing dq of name. - * find the second name. - */ - while ((second < line + llen) && isspace(*second)) - second++; - - if (line + llen <= second) - goto free_and_fail1; - if (*second == '"') { - if (unquote_c_style(&sp, second, NULL)) - goto free_and_fail1; - cp = skip_tree_prefix(state, sp.buf, sp.len); - if (!cp) - goto free_and_fail1; - /* They must match, otherwise ignore */ - if (strcmp(cp, first.buf)) - goto free_and_fail1; - strbuf_release(&sp); - return strbuf_detach(&first, NULL); - } - - /* unquoted second */ - cp = skip_tree_prefix(state, second, line + llen - second); - if (!cp) - goto free_and_fail1; - if (line + llen - cp != first.len || - memcmp(first.buf, cp, first.len)) - goto free_and_fail1; - return strbuf_detach(&first, NULL); - - free_and_fail1: - strbuf_release(&first); - strbuf_release(&sp); - return NULL; - } - - /* unquoted first name */ - name = skip_tree_prefix(state, line, llen); - if (!name) - return NULL; - - /* - * since the first name is unquoted, a dq if exists must be - * the beginning of the second name. - */ - for (second = name; second < line + llen; second++) { - if (*second == '"') { - struct strbuf sp = STRBUF_INIT; - const char *np; - - if (unquote_c_style(&sp, second, NULL)) - goto free_and_fail2; - - np = skip_tree_prefix(state, sp.buf, sp.len); - if (!np) - goto free_and_fail2; - - len = sp.buf + sp.len - np; - if (len < second - name && - !strncmp(np, name, len) && - isspace(name[len])) { - /* Good */ - strbuf_remove(&sp, 0, np - sp.buf); - return strbuf_detach(&sp, NULL); - } - - free_and_fail2: - strbuf_release(&sp); - return NULL; - } - } - - /* - * Accept a name only if it shows up twice, exactly the same - * form. - */ - second = strchr(name, '\n'); - if (!second) - return NULL; - line_len = second - name; - for (len = 0 ; ; len++) { - switch (name[len]) { - default: - continue; - case '\n': - return NULL; - case '\t': case ' ': - /* - * Is this the separator between the preimage - * and the postimage pathname? Again, we are - * only interested in the case where there is - * no rename, as this is only to set def_name - * and a rename patch has the names elsewhere - * in an unambiguous form. - */ - if (!name[len + 1]) - return NULL; /* no postimage name */ - second = skip_tree_prefix(state, name + len + 1, - line_len - (len + 1)); - if (!second) - return NULL; - /* - * Does len bytes starting at "name" and "second" - * (that are separated by one HT or SP we just - * found) exactly match? - */ - if (second[len] == '\n' && !strncmp(name, second, len)) - return xmemdupz(name, len); - } - } -} - -/* Verify that we recognize the lines following a git header */ -static int parse_git_header(struct apply_state *state, - const char *line, - int len, - unsigned int size, - struct patch *patch) -{ - unsigned long offset; - - /* A git diff has explicit new/delete information, so we don't guess */ - patch->is_new = 0; - patch->is_delete = 0; - - /* - * Some things may not have the old name in the - * rest of the headers anywhere (pure mode changes, - * or removing or adding empty files), so we get - * the default name from the header. - */ - patch->def_name = git_header_name(state, line, len); - if (patch->def_name && state->root.len) { - char *s = xstrfmt("%s%s", state->root.buf, patch->def_name); - free(patch->def_name); - patch->def_name = s; - } - - line += len; - size -= len; - state->linenr++; - for (offset = len ; size > 0 ; offset += len, size -= len, line += len, state->linenr++) { - static const struct opentry { - const char *str; - int (*fn)(struct apply_state *, const char *, struct patch *); - } optable[] = { - { "@@ -", gitdiff_hdrend }, - { "--- ", gitdiff_oldname }, - { "+++ ", gitdiff_newname }, - { "old mode ", gitdiff_oldmode }, - { "new mode ", gitdiff_newmode }, - { "deleted file mode ", gitdiff_delete }, - { "new file mode ", gitdiff_newfile }, - { "copy from ", gitdiff_copysrc }, - { "copy to ", gitdiff_copydst }, - { "rename old ", gitdiff_renamesrc }, - { "rename new ", gitdiff_renamedst }, - { "rename from ", gitdiff_renamesrc }, - { "rename to ", gitdiff_renamedst }, - { "similarity index ", gitdiff_similarity }, - { "dissimilarity index ", gitdiff_dissimilarity }, - { "index ", gitdiff_index }, - { "", gitdiff_unrecognized }, - }; - int i; - - len = linelen(line, size); - if (!len || line[len-1] != '\n') - break; - for (i = 0; i < ARRAY_SIZE(optable); i++) { - const struct opentry *p = optable + i; - int oplen = strlen(p->str); - if (len < oplen || memcmp(p->str, line, oplen)) - continue; - if (p->fn(state, line + oplen, patch) < 0) - return offset; - break; - } - } - - return offset; -} - -static int parse_num(const char *line, unsigned long *p) -{ - char *ptr; - - if (!isdigit(*line)) - return 0; - *p = strtoul(line, &ptr, 10); - return ptr - line; -} - -static int parse_range(const char *line, int len, int offset, const char *expect, - unsigned long *p1, unsigned long *p2) -{ - int digits, ex; - - if (offset < 0 || offset >= len) - return -1; - line += offset; - len -= offset; - - digits = parse_num(line, p1); - if (!digits) - return -1; - - offset += digits; - line += digits; - len -= digits; - - *p2 = 1; - if (*line == ',') { - digits = parse_num(line+1, p2); - if (!digits) - return -1; - - offset += digits+1; - line += digits+1; - len -= digits+1; - } - - ex = strlen(expect); - if (ex > len) - return -1; - if (memcmp(line, expect, ex)) - return -1; - - return offset + ex; -} - -static void recount_diff(const char *line, int size, struct fragment *fragment) -{ - int oldlines = 0, newlines = 0, ret = 0; - - if (size < 1) { - warning("recount: ignore empty hunk"); - return; - } - - for (;;) { - int len = linelen(line, size); - size -= len; - line += len; - - if (size < 1) - break; - - switch (*line) { - case ' ': case '\n': - newlines++; - /* fall through */ - case '-': - oldlines++; - continue; - case '+': - newlines++; - continue; - case '\\': - continue; - case '@': - ret = size < 3 || !starts_with(line, "@@ "); - break; - case 'd': - ret = size < 5 || !starts_with(line, "diff "); - break; - default: - ret = -1; - break; - } - if (ret) { - warning(_("recount: unexpected line: %.*s"), - (int)linelen(line, size), line); - return; - } - break; - } - fragment->oldlines = oldlines; - fragment->newlines = newlines; -} - -/* - * Parse a unified diff fragment header of the - * form "@@ -a,b +c,d @@" - */ -static int parse_fragment_header(const char *line, int len, struct fragment *fragment) -{ - int offset; - - if (!len || line[len-1] != '\n') - return -1; - - /* Figure out the number of lines in a fragment */ - offset = parse_range(line, len, 4, " +", &fragment->oldpos, &fragment->oldlines); - offset = parse_range(line, len, offset, " @@", &fragment->newpos, &fragment->newlines); - - return offset; -} - -static int find_header(struct apply_state *state, - const char *line, - unsigned long size, - int *hdrsize, - struct patch *patch) -{ - unsigned long offset, len; - - patch->is_toplevel_relative = 0; - patch->is_rename = patch->is_copy = 0; - patch->is_new = patch->is_delete = -1; - patch->old_mode = patch->new_mode = 0; - patch->old_name = patch->new_name = NULL; - for (offset = 0; size > 0; offset += len, size -= len, line += len, state->linenr++) { - unsigned long nextlen; - - len = linelen(line, size); - if (!len) - break; - - /* Testing this early allows us to take a few shortcuts.. */ - if (len < 6) - continue; - - /* - * Make sure we don't find any unconnected patch fragments. - * That's a sign that we didn't find a header, and that a - * patch has become corrupted/broken up. - */ - if (!memcmp("@@ -", line, 4)) { - struct fragment dummy; - if (parse_fragment_header(line, len, &dummy) < 0) - continue; - die(_("patch fragment without header at line %d: %.*s"), - state->linenr, (int)len-1, line); - } - - if (size < len + 6) - break; - - /* - * Git patch? It might not have a real patch, just a rename - * or mode change, so we handle that specially - */ - if (!memcmp("diff --git ", line, 11)) { - int git_hdr_len = parse_git_header(state, line, len, size, patch); - if (git_hdr_len <= len) - continue; - if (!patch->old_name && !patch->new_name) { - if (!patch->def_name) - die(Q_("git diff header lacks filename information when removing " - "%d leading pathname component (line %d)", - "git diff header lacks filename information when removing " - "%d leading pathname components (line %d)", - state->p_value), - state->p_value, state->linenr); - patch->old_name = xstrdup(patch->def_name); - patch->new_name = xstrdup(patch->def_name); - } - if (!patch->is_delete && !patch->new_name) - die("git diff header lacks filename information " - "(line %d)", state->linenr); - patch->is_toplevel_relative = 1; - *hdrsize = git_hdr_len; - return offset; - } - - /* --- followed by +++ ? */ - if (memcmp("--- ", line, 4) || memcmp("+++ ", line + len, 4)) - continue; - - /* - * We only accept unified patches, so we want it to - * at least have "@@ -a,b +c,d @@\n", which is 14 chars - * minimum ("@@ -0,0 +1 @@\n" is the shortest). - */ - nextlen = linelen(line + len, size - len); - if (size < nextlen + 14 || memcmp("@@ -", line + len + nextlen, 4)) - continue; - - /* Ok, we'll consider it a patch */ - parse_traditional_patch(state, line, line+len, patch); - *hdrsize = len + nextlen; - state->linenr += 2; - return offset; - } - return -1; -} - -static void record_ws_error(struct apply_state *state, - unsigned result, - const char *line, - int len, - int linenr) -{ - char *err; - - if (!result) - return; - - state->whitespace_error++; - if (state->squelch_whitespace_errors && - state->squelch_whitespace_errors < state->whitespace_error) - return; - - err = whitespace_error_string(result); - fprintf(stderr, "%s:%d: %s.\n%.*s\n", - state->patch_input_file, linenr, err, len, line); - free(err); -} - -static void check_whitespace(struct apply_state *state, - const char *line, - int len, - unsigned ws_rule) -{ - unsigned result = ws_check(line + 1, len - 1, ws_rule); - - record_ws_error(state, result, line + 1, len - 2, state->linenr); -} - -/* - * Parse a unified diff. Note that this really needs to parse each - * fragment separately, since the only way to know the difference - * between a "---" that is part of a patch, and a "---" that starts - * the next patch is to look at the line counts.. - */ -static int parse_fragment(struct apply_state *state, - const char *line, - unsigned long size, - struct patch *patch, - struct fragment *fragment) -{ - int added, deleted; - int len = linelen(line, size), offset; - unsigned long oldlines, newlines; - unsigned long leading, trailing; - - offset = parse_fragment_header(line, len, fragment); - if (offset < 0) - return -1; - if (offset > 0 && patch->recount) - recount_diff(line + offset, size - offset, fragment); - oldlines = fragment->oldlines; - newlines = fragment->newlines; - leading = 0; - trailing = 0; - - /* Parse the thing.. */ - line += len; - size -= len; - state->linenr++; - added = deleted = 0; - for (offset = len; - 0 < size; - offset += len, size -= len, line += len, state->linenr++) { - if (!oldlines && !newlines) - break; - len = linelen(line, size); - if (!len || line[len-1] != '\n') - return -1; - switch (*line) { - default: - return -1; - case '\n': /* newer GNU diff, an empty context line */ - case ' ': - oldlines--; - newlines--; - if (!deleted && !added) - leading++; - trailing++; - if (!state->apply_in_reverse && - state->ws_error_action == correct_ws_error) - check_whitespace(state, line, len, patch->ws_rule); - break; - case '-': - if (state->apply_in_reverse && - state->ws_error_action != nowarn_ws_error) - check_whitespace(state, line, len, patch->ws_rule); - deleted++; - oldlines--; - trailing = 0; - break; - case '+': - if (!state->apply_in_reverse && - state->ws_error_action != nowarn_ws_error) - check_whitespace(state, line, len, patch->ws_rule); - added++; - newlines--; - trailing = 0; - break; - - /* - * We allow "\ No newline at end of file". Depending - * on locale settings when the patch was produced we - * don't know what this line looks like. The only - * thing we do know is that it begins with "\ ". - * Checking for 12 is just for sanity check -- any - * l10n of "\ No newline..." is at least that long. - */ - case '\\': - if (len < 12 || memcmp(line, "\\ ", 2)) - return -1; - break; - } - } - if (oldlines || newlines) - return -1; - if (!deleted && !added) - return -1; - - fragment->leading = leading; - fragment->trailing = trailing; - - /* - * If a fragment ends with an incomplete line, we failed to include - * it in the above loop because we hit oldlines == newlines == 0 - * before seeing it. - */ - if (12 < size && !memcmp(line, "\\ ", 2)) - offset += linelen(line, size); - - patch->lines_added += added; - patch->lines_deleted += deleted; - - if (0 < patch->is_new && oldlines) - return error(_("new file depends on old contents")); - if (0 < patch->is_delete && newlines) - return error(_("deleted file still has contents")); - return offset; -} - -/* - * We have seen "diff --git a/... b/..." header (or a traditional patch - * header). Read hunks that belong to this patch into fragments and hang - * them to the given patch structure. - * - * The (fragment->patch, fragment->size) pair points into the memory given - * by the caller, not a copy, when we return. - */ -static int parse_single_patch(struct apply_state *state, - const char *line, - unsigned long size, - struct patch *patch) -{ - unsigned long offset = 0; - unsigned long oldlines = 0, newlines = 0, context = 0; - struct fragment **fragp = &patch->fragments; - - while (size > 4 && !memcmp(line, "@@ -", 4)) { - struct fragment *fragment; - int len; - - fragment = xcalloc(1, sizeof(*fragment)); - fragment->linenr = state->linenr; - len = parse_fragment(state, line, size, patch, fragment); - if (len <= 0) - die(_("corrupt patch at line %d"), state->linenr); - fragment->patch = line; - fragment->size = len; - oldlines += fragment->oldlines; - newlines += fragment->newlines; - context += fragment->leading + fragment->trailing; - - *fragp = fragment; - fragp = &fragment->next; - - offset += len; - line += len; - size -= len; - } - - /* - * If something was removed (i.e. we have old-lines) it cannot - * be creation, and if something was added it cannot be - * deletion. However, the reverse is not true; --unified=0 - * patches that only add are not necessarily creation even - * though they do not have any old lines, and ones that only - * delete are not necessarily deletion. - * - * Unfortunately, a real creation/deletion patch do _not_ have - * any context line by definition, so we cannot safely tell it - * apart with --unified=0 insanity. At least if the patch has - * more than one hunk it is not creation or deletion. - */ - if (patch->is_new < 0 && - (oldlines || (patch->fragments && patch->fragments->next))) - patch->is_new = 0; - if (patch->is_delete < 0 && - (newlines || (patch->fragments && patch->fragments->next))) - patch->is_delete = 0; - - if (0 < patch->is_new && oldlines) - die(_("new file %s depends on old contents"), patch->new_name); - if (0 < patch->is_delete && newlines) - die(_("deleted file %s still has contents"), patch->old_name); - if (!patch->is_delete && !newlines && context) - fprintf_ln(stderr, - _("** warning: " - "file %s becomes empty but is not deleted"), - patch->new_name); - - return offset; -} - -static inline int metadata_changes(struct patch *patch) -{ - return patch->is_rename > 0 || - patch->is_copy > 0 || - patch->is_new > 0 || - patch->is_delete || - (patch->old_mode && patch->new_mode && - patch->old_mode != patch->new_mode); -} - -static char *inflate_it(const void *data, unsigned long size, - unsigned long inflated_size) -{ - git_zstream stream; - void *out; - int st; - - memset(&stream, 0, sizeof(stream)); - - stream.next_in = (unsigned char *)data; - stream.avail_in = size; - stream.next_out = out = xmalloc(inflated_size); - stream.avail_out = inflated_size; - git_inflate_init(&stream); - st = git_inflate(&stream, Z_FINISH); - git_inflate_end(&stream); - if ((st != Z_STREAM_END) || stream.total_out != inflated_size) { - free(out); - return NULL; - } - return out; -} - -/* - * Read a binary hunk and return a new fragment; fragment->patch - * points at an allocated memory that the caller must free, so - * it is marked as "->free_patch = 1". - */ -static struct fragment *parse_binary_hunk(struct apply_state *state, - char **buf_p, - unsigned long *sz_p, - int *status_p, - int *used_p) -{ - /* - * Expect a line that begins with binary patch method ("literal" - * or "delta"), followed by the length of data before deflating. - * a sequence of 'length-byte' followed by base-85 encoded data - * should follow, terminated by a newline. - * - * Each 5-byte sequence of base-85 encodes up to 4 bytes, - * and we would limit the patch line to 66 characters, - * so one line can fit up to 13 groups that would decode - * to 52 bytes max. The length byte 'A'-'Z' corresponds - * to 1-26 bytes, and 'a'-'z' corresponds to 27-52 bytes. - */ - int llen, used; - unsigned long size = *sz_p; - char *buffer = *buf_p; - int patch_method; - unsigned long origlen; - char *data = NULL; - int hunk_size = 0; - struct fragment *frag; - - llen = linelen(buffer, size); - used = llen; - - *status_p = 0; - - if (starts_with(buffer, "delta ")) { - patch_method = BINARY_DELTA_DEFLATED; - origlen = strtoul(buffer + 6, NULL, 10); - } - else if (starts_with(buffer, "literal ")) { - patch_method = BINARY_LITERAL_DEFLATED; - origlen = strtoul(buffer + 8, NULL, 10); - } - else - return NULL; - - state->linenr++; - buffer += llen; - while (1) { - int byte_length, max_byte_length, newsize; - llen = linelen(buffer, size); - used += llen; - state->linenr++; - if (llen == 1) { - /* consume the blank line */ - buffer++; - size--; - break; - } - /* - * Minimum line is "A00000\n" which is 7-byte long, - * and the line length must be multiple of 5 plus 2. - */ - if ((llen < 7) || (llen-2) % 5) - goto corrupt; - max_byte_length = (llen - 2) / 5 * 4; - byte_length = *buffer; - if ('A' <= byte_length && byte_length <= 'Z') - byte_length = byte_length - 'A' + 1; - else if ('a' <= byte_length && byte_length <= 'z') - byte_length = byte_length - 'a' + 27; - else - goto corrupt; - /* if the input length was not multiple of 4, we would - * have filler at the end but the filler should never - * exceed 3 bytes - */ - if (max_byte_length < byte_length || - byte_length <= max_byte_length - 4) - goto corrupt; - newsize = hunk_size + byte_length; - data = xrealloc(data, newsize); - if (decode_85(data + hunk_size, buffer + 1, byte_length)) - goto corrupt; - hunk_size = newsize; - buffer += llen; - size -= llen; - } - - frag = xcalloc(1, sizeof(*frag)); - frag->patch = inflate_it(data, hunk_size, origlen); - frag->free_patch = 1; - if (!frag->patch) - goto corrupt; - free(data); - frag->size = origlen; - *buf_p = buffer; - *sz_p = size; - *used_p = used; - frag->binary_patch_method = patch_method; - return frag; - - corrupt: - free(data); - *status_p = -1; - error(_("corrupt binary patch at line %d: %.*s"), - state->linenr-1, llen-1, buffer); - return NULL; -} - -/* - * Returns: - * -1 in case of error, - * the length of the parsed binary patch otherwise - */ -static int parse_binary(struct apply_state *state, - char *buffer, - unsigned long size, - struct patch *patch) -{ - /* - * We have read "GIT binary patch\n"; what follows is a line - * that says the patch method (currently, either "literal" or - * "delta") and the length of data before deflating; a - * sequence of 'length-byte' followed by base-85 encoded data - * follows. - * - * When a binary patch is reversible, there is another binary - * hunk in the same format, starting with patch method (either - * "literal" or "delta") with the length of data, and a sequence - * of length-byte + base-85 encoded data, terminated with another - * empty line. This data, when applied to the postimage, produces - * the preimage. - */ - struct fragment *forward; - struct fragment *reverse; - int status; - int used, used_1; - - forward = parse_binary_hunk(state, &buffer, &size, &status, &used); - if (!forward && !status) - /* there has to be one hunk (forward hunk) */ - return error(_("unrecognized binary patch at line %d"), state->linenr-1); - if (status) - /* otherwise we already gave an error message */ - return status; - - reverse = parse_binary_hunk(state, &buffer, &size, &status, &used_1); - if (reverse) - used += used_1; - else if (status) { - /* - * Not having reverse hunk is not an error, but having - * a corrupt reverse hunk is. - */ - free((void*) forward->patch); - free(forward); - return status; - } - forward->next = reverse; - patch->fragments = forward; - patch->is_binary = 1; - return used; -} - -static void prefix_one(struct apply_state *state, char **name) -{ - char *old_name = *name; - if (!old_name) - return; - *name = xstrdup(prefix_filename(state->prefix, state->prefix_length, *name)); - free(old_name); -} - -static void prefix_patch(struct apply_state *state, struct patch *p) -{ - if (!state->prefix || p->is_toplevel_relative) - return; - prefix_one(state, &p->new_name); - prefix_one(state, &p->old_name); -} - -/* - * include/exclude - */ - -static void add_name_limit(struct apply_state *state, - const char *name, - int exclude) -{ - struct string_list_item *it; - - it = string_list_append(&state->limit_by_name, name); - it->util = exclude ? NULL : (void *) 1; -} - -static int use_patch(struct apply_state *state, struct patch *p) -{ - const char *pathname = p->new_name ? p->new_name : p->old_name; - int i; - - /* Paths outside are not touched regardless of "--include" */ - if (0 < state->prefix_length) { - int pathlen = strlen(pathname); - if (pathlen <= state->prefix_length || - memcmp(state->prefix, pathname, state->prefix_length)) - return 0; - } - - /* See if it matches any of exclude/include rule */ - for (i = 0; i < state->limit_by_name.nr; i++) { - struct string_list_item *it = &state->limit_by_name.items[i]; - if (!wildmatch(it->string, pathname, 0, NULL)) - return (it->util != NULL); - } - - /* - * If we had any include, a path that does not match any rule is - * not used. Otherwise, we saw bunch of exclude rules (or none) - * and such a path is used. - */ - return !state->has_include; -} - - -/* - * Read the patch text in "buffer" that extends for "size" bytes; stop - * reading after seeing a single patch (i.e. changes to a single file). - * Create fragments (i.e. patch hunks) and hang them to the given patch. - * Return the number of bytes consumed, so that the caller can call us - * again for the next patch. - */ -static int parse_chunk(struct apply_state *state, char *buffer, unsigned long size, struct patch *patch) -{ - int hdrsize, patchsize; - int offset = find_header(state, buffer, size, &hdrsize, patch); - - if (offset < 0) - return offset; - - prefix_patch(state, patch); - - if (!use_patch(state, patch)) - patch->ws_rule = 0; - else - patch->ws_rule = whitespace_rule(patch->new_name - ? patch->new_name - : patch->old_name); - - patchsize = parse_single_patch(state, - buffer + offset + hdrsize, - size - offset - hdrsize, - patch); - - if (!patchsize) { - static const char git_binary[] = "GIT binary patch\n"; - int hd = hdrsize + offset; - unsigned long llen = linelen(buffer + hd, size - hd); - - if (llen == sizeof(git_binary) - 1 && - !memcmp(git_binary, buffer + hd, llen)) { - int used; - state->linenr++; - used = parse_binary(state, buffer + hd + llen, - size - hd - llen, patch); - if (used < 0) - return -1; - if (used) - patchsize = used + llen; - else - patchsize = 0; - } - else if (!memcmp(" differ\n", buffer + hd + llen - 8, 8)) { - static const char *binhdr[] = { - "Binary files ", - "Files ", - NULL, - }; - int i; - for (i = 0; binhdr[i]; i++) { - int len = strlen(binhdr[i]); - if (len < size - hd && - !memcmp(binhdr[i], buffer + hd, len)) { - state->linenr++; - patch->is_binary = 1; - patchsize = llen; - break; - } - } - } - - /* Empty patch cannot be applied if it is a text patch - * without metadata change. A binary patch appears - * empty to us here. - */ - if ((state->apply || state->check) && - (!patch->is_binary && !metadata_changes(patch))) - die(_("patch with only garbage at line %d"), state->linenr); - } - - return offset + hdrsize + patchsize; -} - -#define swap(a,b) myswap((a),(b),sizeof(a)) - -#define myswap(a, b, size) do { \ - unsigned char mytmp[size]; \ - memcpy(mytmp, &a, size); \ - memcpy(&a, &b, size); \ - memcpy(&b, mytmp, size); \ -} while (0) - -static void reverse_patches(struct patch *p) -{ - for (; p; p = p->next) { - struct fragment *frag = p->fragments; - - swap(p->new_name, p->old_name); - swap(p->new_mode, p->old_mode); - swap(p->is_new, p->is_delete); - swap(p->lines_added, p->lines_deleted); - swap(p->old_sha1_prefix, p->new_sha1_prefix); - - for (; frag; frag = frag->next) { - swap(frag->newpos, frag->oldpos); - swap(frag->newlines, frag->oldlines); - } - } -} - -static const char pluses[] = -"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; -static const char minuses[]= -"----------------------------------------------------------------------"; - -static void show_stats(struct apply_state *state, struct patch *patch) -{ - struct strbuf qname = STRBUF_INIT; - char *cp = patch->new_name ? patch->new_name : patch->old_name; - int max, add, del; - - quote_c_style(cp, &qname, NULL, 0); - - /* - * "scale" the filename - */ - max = state->max_len; - if (max > 50) - max = 50; - - if (qname.len > max) { - cp = strchr(qname.buf + qname.len + 3 - max, '/'); - if (!cp) - cp = qname.buf + qname.len + 3 - max; - strbuf_splice(&qname, 0, cp - qname.buf, "...", 3); - } - - if (patch->is_binary) { - printf(" %-*s | Bin\n", max, qname.buf); - strbuf_release(&qname); - return; - } - - printf(" %-*s |", max, qname.buf); - strbuf_release(&qname); - - /* - * scale the add/delete - */ - max = max + state->max_change > 70 ? 70 - max : state->max_change; - add = patch->lines_added; - del = patch->lines_deleted; - - if (state->max_change > 0) { - int total = ((add + del) * max + state->max_change / 2) / state->max_change; - add = (add * max + state->max_change / 2) / state->max_change; - del = total - add; - } - printf("%5d %.*s%.*s\n", patch->lines_added + patch->lines_deleted, - add, pluses, del, minuses); -} - -static int read_old_data(struct stat *st, const char *path, struct strbuf *buf) -{ - switch (st->st_mode & S_IFMT) { - case S_IFLNK: - if (strbuf_readlink(buf, path, st->st_size) < 0) - return error(_("unable to read symlink %s"), path); - return 0; - case S_IFREG: - if (strbuf_read_file(buf, path, st->st_size) != st->st_size) - return error(_("unable to open or read %s"), path); - convert_to_git(path, buf->buf, buf->len, buf, 0); - return 0; - default: - return -1; - } -} - -/* - * Update the preimage, and the common lines in postimage, - * from buffer buf of length len. If postlen is 0 the postimage - * is updated in place, otherwise it's updated on a new buffer - * of length postlen - */ - -static void update_pre_post_images(struct image *preimage, - struct image *postimage, - char *buf, - size_t len, size_t postlen) -{ - int i, ctx, reduced; - char *new, *old, *fixed; - struct image fixed_preimage; - - /* - * Update the preimage with whitespace fixes. Note that we - * are not losing preimage->buf -- apply_one_fragment() will - * free "oldlines". - */ - prepare_image(&fixed_preimage, buf, len, 1); - assert(postlen - ? fixed_preimage.nr == preimage->nr - : fixed_preimage.nr <= preimage->nr); - for (i = 0; i < fixed_preimage.nr; i++) - fixed_preimage.line[i].flag = preimage->line[i].flag; - free(preimage->line_allocated); - *preimage = fixed_preimage; - - /* - * Adjust the common context lines in postimage. This can be - * done in-place when we are shrinking it with whitespace - * fixing, but needs a new buffer when ignoring whitespace or - * expanding leading tabs to spaces. - * - * We trust the caller to tell us if the update can be done - * in place (postlen==0) or not. - */ - old = postimage->buf; - if (postlen) - new = postimage->buf = xmalloc(postlen); - else - new = old; - fixed = preimage->buf; - - for (i = reduced = ctx = 0; i < postimage->nr; i++) { - size_t l_len = postimage->line[i].len; - if (!(postimage->line[i].flag & LINE_COMMON)) { - /* an added line -- no counterparts in preimage */ - memmove(new, old, l_len); - old += l_len; - new += l_len; - continue; - } - - /* a common context -- skip it in the original postimage */ - old += l_len; - - /* and find the corresponding one in the fixed preimage */ - while (ctx < preimage->nr && - !(preimage->line[ctx].flag & LINE_COMMON)) { - fixed += preimage->line[ctx].len; - ctx++; - } - - /* - * preimage is expected to run out, if the caller - * fixed addition of trailing blank lines. - */ - if (preimage->nr <= ctx) { - reduced++; - continue; - } - - /* and copy it in, while fixing the line length */ - l_len = preimage->line[ctx].len; - memcpy(new, fixed, l_len); - new += l_len; - fixed += l_len; - postimage->line[i].len = l_len; - ctx++; - } - - if (postlen - ? postlen < new - postimage->buf - : postimage->len < new - postimage->buf) - die("BUG: caller miscounted postlen: asked %d, orig = %d, used = %d", - (int)postlen, (int) postimage->len, (int)(new - postimage->buf)); - - /* Fix the length of the whole thing */ - postimage->len = new - postimage->buf; - postimage->nr -= reduced; -} - -static int line_by_line_fuzzy_match(struct image *img, - struct image *preimage, - struct image *postimage, - unsigned long try, - int try_lno, - int preimage_limit) -{ - int i; - size_t imgoff = 0; - size_t preoff = 0; - size_t postlen = postimage->len; - size_t extra_chars; - char *buf; - char *preimage_eof; - char *preimage_end; - struct strbuf fixed; - char *fixed_buf; - size_t fixed_len; - - for (i = 0; i < preimage_limit; i++) { - size_t prelen = preimage->line[i].len; - size_t imglen = img->line[try_lno+i].len; - - if (!fuzzy_matchlines(img->buf + try + imgoff, imglen, - preimage->buf + preoff, prelen)) - return 0; - if (preimage->line[i].flag & LINE_COMMON) - postlen += imglen - prelen; - imgoff += imglen; - preoff += prelen; - } - - /* - * Ok, the preimage matches with whitespace fuzz. - * - * imgoff now holds the true length of the target that - * matches the preimage before the end of the file. - * - * Count the number of characters in the preimage that fall - * beyond the end of the file and make sure that all of them - * are whitespace characters. (This can only happen if - * we are removing blank lines at the end of the file.) - */ - buf = preimage_eof = preimage->buf + preoff; - for ( ; i < preimage->nr; i++) - preoff += preimage->line[i].len; - preimage_end = preimage->buf + preoff; - for ( ; buf < preimage_end; buf++) - if (!isspace(*buf)) - return 0; - - /* - * Update the preimage and the common postimage context - * lines to use the same whitespace as the target. - * If whitespace is missing in the target (i.e. - * if the preimage extends beyond the end of the file), - * use the whitespace from the preimage. - */ - extra_chars = preimage_end - preimage_eof; - strbuf_init(&fixed, imgoff + extra_chars); - strbuf_add(&fixed, img->buf + try, imgoff); - strbuf_add(&fixed, preimage_eof, extra_chars); - fixed_buf = strbuf_detach(&fixed, &fixed_len); - update_pre_post_images(preimage, postimage, - fixed_buf, fixed_len, postlen); - return 1; -} - -static int match_fragment(struct apply_state *state, - struct image *img, - struct image *preimage, - struct image *postimage, - unsigned long try, - int try_lno, - unsigned ws_rule, - int match_beginning, int match_end) -{ - int i; - char *fixed_buf, *buf, *orig, *target; - struct strbuf fixed; - size_t fixed_len, postlen; - int preimage_limit; - - if (preimage->nr + try_lno <= img->nr) { - /* - * The hunk falls within the boundaries of img. - */ - preimage_limit = preimage->nr; - if (match_end && (preimage->nr + try_lno != img->nr)) - return 0; - } else if (state->ws_error_action == correct_ws_error && - (ws_rule & WS_BLANK_AT_EOF)) { - /* - * This hunk extends beyond the end of img, and we are - * removing blank lines at the end of the file. This - * many lines from the beginning of the preimage must - * match with img, and the remainder of the preimage - * must be blank. - */ - preimage_limit = img->nr - try_lno; - } else { - /* - * The hunk extends beyond the end of the img and - * we are not removing blanks at the end, so we - * should reject the hunk at this position. - */ - return 0; - } - - if (match_beginning && try_lno) - return 0; - - /* Quick hash check */ - for (i = 0; i < preimage_limit; i++) - if ((img->line[try_lno + i].flag & LINE_PATCHED) || - (preimage->line[i].hash != img->line[try_lno + i].hash)) - return 0; - - if (preimage_limit == preimage->nr) { - /* - * Do we have an exact match? If we were told to match - * at the end, size must be exactly at try+fragsize, - * otherwise try+fragsize must be still within the preimage, - * and either case, the old piece should match the preimage - * exactly. - */ - if ((match_end - ? (try + preimage->len == img->len) - : (try + preimage->len <= img->len)) && - !memcmp(img->buf + try, preimage->buf, preimage->len)) - return 1; - } else { - /* - * The preimage extends beyond the end of img, so - * there cannot be an exact match. - * - * There must be one non-blank context line that match - * a line before the end of img. - */ - char *buf_end; - - buf = preimage->buf; - buf_end = buf; - for (i = 0; i < preimage_limit; i++) - buf_end += preimage->line[i].len; - - for ( ; buf < buf_end; buf++) - if (!isspace(*buf)) - break; - if (buf == buf_end) - return 0; - } - - /* - * No exact match. If we are ignoring whitespace, run a line-by-line - * fuzzy matching. We collect all the line length information because - * we need it to adjust whitespace if we match. - */ - if (state->ws_ignore_action == ignore_ws_change) - return line_by_line_fuzzy_match(img, preimage, postimage, - try, try_lno, preimage_limit); - - if (state->ws_error_action != correct_ws_error) - return 0; - - /* - * The hunk does not apply byte-by-byte, but the hash says - * it might with whitespace fuzz. We weren't asked to - * ignore whitespace, we were asked to correct whitespace - * errors, so let's try matching after whitespace correction. - * - * While checking the preimage against the target, whitespace - * errors in both fixed, we count how large the corresponding - * postimage needs to be. The postimage prepared by - * apply_one_fragment() has whitespace errors fixed on added - * lines already, but the common lines were propagated as-is, - * which may become longer when their whitespace errors are - * fixed. - */ - - /* First count added lines in postimage */ - postlen = 0; - for (i = 0; i < postimage->nr; i++) { - if (!(postimage->line[i].flag & LINE_COMMON)) - postlen += postimage->line[i].len; - } - - /* - * The preimage may extend beyond the end of the file, - * but in this loop we will only handle the part of the - * preimage that falls within the file. - */ - strbuf_init(&fixed, preimage->len + 1); - orig = preimage->buf; - target = img->buf + try; - for (i = 0; i < preimage_limit; i++) { - size_t oldlen = preimage->line[i].len; - size_t tgtlen = img->line[try_lno + i].len; - size_t fixstart = fixed.len; - struct strbuf tgtfix; - int match; - - /* Try fixing the line in the preimage */ - ws_fix_copy(&fixed, orig, oldlen, ws_rule, NULL); - - /* Try fixing the line in the target */ - strbuf_init(&tgtfix, tgtlen); - ws_fix_copy(&tgtfix, target, tgtlen, ws_rule, NULL); - - /* - * If they match, either the preimage was based on - * a version before our tree fixed whitespace breakage, - * or we are lacking a whitespace-fix patch the tree - * the preimage was based on already had (i.e. target - * has whitespace breakage, the preimage doesn't). - * In either case, we are fixing the whitespace breakages - * so we might as well take the fix together with their - * real change. - */ - match = (tgtfix.len == fixed.len - fixstart && - !memcmp(tgtfix.buf, fixed.buf + fixstart, - fixed.len - fixstart)); - - /* Add the length if this is common with the postimage */ - if (preimage->line[i].flag & LINE_COMMON) - postlen += tgtfix.len; - - strbuf_release(&tgtfix); - if (!match) - goto unmatch_exit; - - orig += oldlen; - target += tgtlen; - } - - - /* - * Now handle the lines in the preimage that falls beyond the - * end of the file (if any). They will only match if they are - * empty or only contain whitespace (if WS_BLANK_AT_EOL is - * false). - */ - for ( ; i < preimage->nr; i++) { - size_t fixstart = fixed.len; /* start of the fixed preimage */ - size_t oldlen = preimage->line[i].len; - int j; - - /* Try fixing the line in the preimage */ - ws_fix_copy(&fixed, orig, oldlen, ws_rule, NULL); - - for (j = fixstart; j < fixed.len; j++) - if (!isspace(fixed.buf[j])) - goto unmatch_exit; - - orig += oldlen; - } - - /* - * Yes, the preimage is based on an older version that still - * has whitespace breakages unfixed, and fixing them makes the - * hunk match. Update the context lines in the postimage. - */ - fixed_buf = strbuf_detach(&fixed, &fixed_len); - if (postlen < postimage->len) - postlen = 0; - update_pre_post_images(preimage, postimage, - fixed_buf, fixed_len, postlen); - return 1; - - unmatch_exit: - strbuf_release(&fixed); - return 0; -} - -static int find_pos(struct apply_state *state, - struct image *img, - struct image *preimage, - struct image *postimage, - int line, - unsigned ws_rule, - int match_beginning, int match_end) -{ - int i; - unsigned long backwards, forwards, try; - int backwards_lno, forwards_lno, try_lno; - - /* - * If match_beginning or match_end is specified, there is no - * point starting from a wrong line that will never match and - * wander around and wait for a match at the specified end. - */ - if (match_beginning) - line = 0; - else if (match_end) - line = img->nr - preimage->nr; - - /* - * Because the comparison is unsigned, the following test - * will also take care of a negative line number that can - * result when match_end and preimage is larger than the target. - */ - if ((size_t) line > img->nr) - line = img->nr; - - try = 0; - for (i = 0; i < line; i++) - try += img->line[i].len; - - /* - * There's probably some smart way to do this, but I'll leave - * that to the smart and beautiful people. I'm simple and stupid. - */ - backwards = try; - backwards_lno = line; - forwards = try; - forwards_lno = line; - try_lno = line; - - for (i = 0; ; i++) { - if (match_fragment(state, img, preimage, postimage, - try, try_lno, ws_rule, - match_beginning, match_end)) - return try_lno; - - again: - if (backwards_lno == 0 && forwards_lno == img->nr) - break; - - if (i & 1) { - if (backwards_lno == 0) { - i++; - goto again; - } - backwards_lno--; - backwards -= img->line[backwards_lno].len; - try = backwards; - try_lno = backwards_lno; - } else { - if (forwards_lno == img->nr) { - i++; - goto again; - } - forwards += img->line[forwards_lno].len; - forwards_lno++; - try = forwards; - try_lno = forwards_lno; - } - - } - return -1; -} - -static void remove_first_line(struct image *img) -{ - img->buf += img->line[0].len; - img->len -= img->line[0].len; - img->line++; - img->nr--; -} - -static void remove_last_line(struct image *img) -{ - img->len -= img->line[--img->nr].len; -} - -/* - * The change from "preimage" and "postimage" has been found to - * apply at applied_pos (counts in line numbers) in "img". - * Update "img" to remove "preimage" and replace it with "postimage". - */ -static void update_image(struct apply_state *state, - struct image *img, - int applied_pos, - struct image *preimage, - struct image *postimage) -{ - /* - * remove the copy of preimage at offset in img - * and replace it with postimage - */ - int i, nr; - size_t remove_count, insert_count, applied_at = 0; - char *result; - int preimage_limit; - - /* - * If we are removing blank lines at the end of img, - * the preimage may extend beyond the end. - * If that is the case, we must be careful only to - * remove the part of the preimage that falls within - * the boundaries of img. Initialize preimage_limit - * to the number of lines in the preimage that falls - * within the boundaries. - */ - preimage_limit = preimage->nr; - if (preimage_limit > img->nr - applied_pos) - preimage_limit = img->nr - applied_pos; - - for (i = 0; i < applied_pos; i++) - applied_at += img->line[i].len; - - remove_count = 0; - for (i = 0; i < preimage_limit; i++) - remove_count += img->line[applied_pos + i].len; - insert_count = postimage->len; - - /* Adjust the contents */ - result = xmalloc(st_add3(st_sub(img->len, remove_count), insert_count, 1)); - memcpy(result, img->buf, applied_at); - memcpy(result + applied_at, postimage->buf, postimage->len); - memcpy(result + applied_at + postimage->len, - img->buf + (applied_at + remove_count), - img->len - (applied_at + remove_count)); - free(img->buf); - img->buf = result; - img->len += insert_count - remove_count; - result[img->len] = '\0'; - - /* Adjust the line table */ - nr = img->nr + postimage->nr - preimage_limit; - if (preimage_limit < postimage->nr) { - /* - * NOTE: this knows that we never call remove_first_line() - * on anything other than pre/post image. - */ - REALLOC_ARRAY(img->line, nr); - img->line_allocated = img->line; - } - if (preimage_limit != postimage->nr) - memmove(img->line + applied_pos + postimage->nr, - img->line + applied_pos + preimage_limit, - (img->nr - (applied_pos + preimage_limit)) * - sizeof(*img->line)); - memcpy(img->line + applied_pos, - postimage->line, - postimage->nr * sizeof(*img->line)); - if (!state->allow_overlap) - for (i = 0; i < postimage->nr; i++) - img->line[applied_pos + i].flag |= LINE_PATCHED; - img->nr = nr; -} - -/* - * Use the patch-hunk text in "frag" to prepare two images (preimage and - * postimage) for the hunk. Find lines that match "preimage" in "img" and - * replace the part of "img" with "postimage" text. - */ -static int apply_one_fragment(struct apply_state *state, - struct image *img, struct fragment *frag, - int inaccurate_eof, unsigned ws_rule, - int nth_fragment) -{ - int match_beginning, match_end; - const char *patch = frag->patch; - int size = frag->size; - char *old, *oldlines; - struct strbuf newlines; - int new_blank_lines_at_end = 0; - int found_new_blank_lines_at_end = 0; - int hunk_linenr = frag->linenr; - unsigned long leading, trailing; - int pos, applied_pos; - struct image preimage; - struct image postimage; - - memset(&preimage, 0, sizeof(preimage)); - memset(&postimage, 0, sizeof(postimage)); - oldlines = xmalloc(size); - strbuf_init(&newlines, size); - - old = oldlines; - while (size > 0) { - char first; - int len = linelen(patch, size); - int plen; - int added_blank_line = 0; - int is_blank_context = 0; - size_t start; - - if (!len) - break; - - /* - * "plen" is how much of the line we should use for - * the actual patch data. Normally we just remove the - * first character on the line, but if the line is - * followed by "\ No newline", then we also remove the - * last one (which is the newline, of course). - */ - plen = len - 1; - if (len < size && patch[len] == '\\') - plen--; - first = *patch; - if (state->apply_in_reverse) { - if (first == '-') - first = '+'; - else if (first == '+') - first = '-'; - } - - switch (first) { - case '\n': - /* Newer GNU diff, empty context line */ - if (plen < 0) - /* ... followed by '\No newline'; nothing */ - break; - *old++ = '\n'; - strbuf_addch(&newlines, '\n'); - add_line_info(&preimage, "\n", 1, LINE_COMMON); - add_line_info(&postimage, "\n", 1, LINE_COMMON); - is_blank_context = 1; - break; - case ' ': - if (plen && (ws_rule & WS_BLANK_AT_EOF) && - ws_blank_line(patch + 1, plen, ws_rule)) - is_blank_context = 1; - case '-': - memcpy(old, patch + 1, plen); - add_line_info(&preimage, old, plen, - (first == ' ' ? LINE_COMMON : 0)); - old += plen; - if (first == '-') - break; - /* Fall-through for ' ' */ - case '+': - /* --no-add does not add new lines */ - if (first == '+' && state->no_add) - break; - - start = newlines.len; - if (first != '+' || - !state->whitespace_error || - state->ws_error_action != correct_ws_error) { - strbuf_add(&newlines, patch + 1, plen); - } - else { - ws_fix_copy(&newlines, patch + 1, plen, ws_rule, &state->applied_after_fixing_ws); - } - add_line_info(&postimage, newlines.buf + start, newlines.len - start, - (first == '+' ? 0 : LINE_COMMON)); - if (first == '+' && - (ws_rule & WS_BLANK_AT_EOF) && - ws_blank_line(patch + 1, plen, ws_rule)) - added_blank_line = 1; - break; - case '@': case '\\': - /* Ignore it, we already handled it */ - break; - default: - if (state->apply_verbosely) - error(_("invalid start of line: '%c'"), first); - applied_pos = -1; - goto out; - } - if (added_blank_line) { - if (!new_blank_lines_at_end) - found_new_blank_lines_at_end = hunk_linenr; - new_blank_lines_at_end++; - } - else if (is_blank_context) - ; - else - new_blank_lines_at_end = 0; - patch += len; - size -= len; - hunk_linenr++; - } - if (inaccurate_eof && - old > oldlines && old[-1] == '\n' && - newlines.len > 0 && newlines.buf[newlines.len - 1] == '\n') { - old--; - strbuf_setlen(&newlines, newlines.len - 1); - } - - leading = frag->leading; - trailing = frag->trailing; - - /* - * A hunk to change lines at the beginning would begin with - * @@ -1,L +N,M @@ - * but we need to be careful. -U0 that inserts before the second - * line also has this pattern. - * - * And a hunk to add to an empty file would begin with - * @@ -0,0 +N,M @@ - * - * In other words, a hunk that is (frag->oldpos <= 1) with or - * without leading context must match at the beginning. - */ - match_beginning = (!frag->oldpos || - (frag->oldpos == 1 && !state->unidiff_zero)); - - /* - * A hunk without trailing lines must match at the end. - * However, we simply cannot tell if a hunk must match end - * from the lack of trailing lines if the patch was generated - * with unidiff without any context. - */ - match_end = !state->unidiff_zero && !trailing; - - pos = frag->newpos ? (frag->newpos - 1) : 0; - preimage.buf = oldlines; - preimage.len = old - oldlines; - postimage.buf = newlines.buf; - postimage.len = newlines.len; - preimage.line = preimage.line_allocated; - postimage.line = postimage.line_allocated; - - for (;;) { - - applied_pos = find_pos(state, img, &preimage, &postimage, pos, - ws_rule, match_beginning, match_end); - - if (applied_pos >= 0) - break; - - /* Am I at my context limits? */ - if ((leading <= state->p_context) && (trailing <= state->p_context)) - break; - if (match_beginning || match_end) { - match_beginning = match_end = 0; - continue; - } - - /* - * Reduce the number of context lines; reduce both - * leading and trailing if they are equal otherwise - * just reduce the larger context. - */ - if (leading >= trailing) { - remove_first_line(&preimage); - remove_first_line(&postimage); - pos--; - leading--; - } - if (trailing > leading) { - remove_last_line(&preimage); - remove_last_line(&postimage); - trailing--; - } - } - - if (applied_pos >= 0) { - if (new_blank_lines_at_end && - preimage.nr + applied_pos >= img->nr && - (ws_rule & WS_BLANK_AT_EOF) && - state->ws_error_action != nowarn_ws_error) { - record_ws_error(state, WS_BLANK_AT_EOF, "+", 1, - found_new_blank_lines_at_end); - if (state->ws_error_action == correct_ws_error) { - while (new_blank_lines_at_end--) - remove_last_line(&postimage); - } - /* - * We would want to prevent write_out_results() - * from taking place in apply_patch() that follows - * the callchain led us here, which is: - * apply_patch->check_patch_list->check_patch-> - * apply_data->apply_fragments->apply_one_fragment - */ - if (state->ws_error_action == die_on_ws_error) - state->apply = 0; - } - - if (state->apply_verbosely && applied_pos != pos) { - int offset = applied_pos - pos; - if (state->apply_in_reverse) - offset = 0 - offset; - fprintf_ln(stderr, - Q_("Hunk #%d succeeded at %d (offset %d line).", - "Hunk #%d succeeded at %d (offset %d lines).", - offset), - nth_fragment, applied_pos + 1, offset); - } - - /* - * Warn if it was necessary to reduce the number - * of context lines. - */ - if ((leading != frag->leading) || - (trailing != frag->trailing)) - fprintf_ln(stderr, _("Context reduced to (%ld/%ld)" - " to apply fragment at %d"), - leading, trailing, applied_pos+1); - update_image(state, img, applied_pos, &preimage, &postimage); - } else { - if (state->apply_verbosely) - error(_("while searching for:\n%.*s"), - (int)(old - oldlines), oldlines); - } - -out: - free(oldlines); - strbuf_release(&newlines); - free(preimage.line_allocated); - free(postimage.line_allocated); - - return (applied_pos < 0); -} - -static int apply_binary_fragment(struct apply_state *state, - struct image *img, - struct patch *patch) -{ - struct fragment *fragment = patch->fragments; - unsigned long len; - void *dst; - - if (!fragment) - return error(_("missing binary patch data for '%s'"), - patch->new_name ? - patch->new_name : - patch->old_name); - - /* Binary patch is irreversible without the optional second hunk */ - if (state->apply_in_reverse) { - if (!fragment->next) - return error("cannot reverse-apply a binary patch " - "without the reverse hunk to '%s'", - patch->new_name - ? patch->new_name : patch->old_name); - fragment = fragment->next; - } - switch (fragment->binary_patch_method) { - case BINARY_DELTA_DEFLATED: - dst = patch_delta(img->buf, img->len, fragment->patch, - fragment->size, &len); - if (!dst) - return -1; - clear_image(img); - img->buf = dst; - img->len = len; - return 0; - case BINARY_LITERAL_DEFLATED: - clear_image(img); - img->len = fragment->size; - img->buf = xmemdupz(fragment->patch, img->len); - return 0; - } - return -1; -} - -/* - * Replace "img" with the result of applying the binary patch. - * The binary patch data itself in patch->fragment is still kept - * but the preimage prepared by the caller in "img" is freed here - * or in the helper function apply_binary_fragment() this calls. - */ -static int apply_binary(struct apply_state *state, - struct image *img, - struct patch *patch) -{ - const char *name = patch->old_name ? patch->old_name : patch->new_name; - unsigned char sha1[20]; - - /* - * For safety, we require patch index line to contain - * full 40-byte textual SHA1 for old and new, at least for now. - */ - if (strlen(patch->old_sha1_prefix) != 40 || - strlen(patch->new_sha1_prefix) != 40 || - get_sha1_hex(patch->old_sha1_prefix, sha1) || - get_sha1_hex(patch->new_sha1_prefix, sha1)) - return error("cannot apply binary patch to '%s' " - "without full index line", name); - - if (patch->old_name) { - /* - * See if the old one matches what the patch - * applies to. - */ - hash_sha1_file(img->buf, img->len, blob_type, sha1); - if (strcmp(sha1_to_hex(sha1), patch->old_sha1_prefix)) - return error("the patch applies to '%s' (%s), " - "which does not match the " - "current contents.", - name, sha1_to_hex(sha1)); - } - else { - /* Otherwise, the old one must be empty. */ - if (img->len) - return error("the patch applies to an empty " - "'%s' but it is not empty", name); - } - - get_sha1_hex(patch->new_sha1_prefix, sha1); - if (is_null_sha1(sha1)) { - clear_image(img); - return 0; /* deletion patch */ - } - - if (has_sha1_file(sha1)) { - /* We already have the postimage */ - enum object_type type; - unsigned long size; - char *result; - - result = read_sha1_file(sha1, &type, &size); - if (!result) - return error("the necessary postimage %s for " - "'%s' cannot be read", - patch->new_sha1_prefix, name); - clear_image(img); - img->buf = result; - img->len = size; - } else { - /* - * We have verified buf matches the preimage; - * apply the patch data to it, which is stored - * in the patch->fragments->{patch,size}. - */ - if (apply_binary_fragment(state, img, patch)) - return error(_("binary patch does not apply to '%s'"), - name); - - /* verify that the result matches */ - hash_sha1_file(img->buf, img->len, blob_type, sha1); - if (strcmp(sha1_to_hex(sha1), patch->new_sha1_prefix)) - return error(_("binary patch to '%s' creates incorrect result (expecting %s, got %s)"), - name, patch->new_sha1_prefix, sha1_to_hex(sha1)); - } - - return 0; -} - -static int apply_fragments(struct apply_state *state, struct image *img, struct patch *patch) -{ - struct fragment *frag = patch->fragments; - const char *name = patch->old_name ? patch->old_name : patch->new_name; - unsigned ws_rule = patch->ws_rule; - unsigned inaccurate_eof = patch->inaccurate_eof; - int nth = 0; - - if (patch->is_binary) - return apply_binary(state, img, patch); - - while (frag) { - nth++; - if (apply_one_fragment(state, img, frag, inaccurate_eof, ws_rule, nth)) { - error(_("patch failed: %s:%ld"), name, frag->oldpos); - if (!state->apply_with_reject) - return -1; - frag->rejected = 1; - } - frag = frag->next; - } - return 0; -} - -static int read_blob_object(struct strbuf *buf, const unsigned char *sha1, unsigned mode) -{ - if (S_ISGITLINK(mode)) { - strbuf_grow(buf, 100); - strbuf_addf(buf, "Subproject commit %s\n", sha1_to_hex(sha1)); - } else { - enum object_type type; - unsigned long sz; - char *result; - - result = read_sha1_file(sha1, &type, &sz); - if (!result) - return -1; - /* XXX read_sha1_file NUL-terminates */ - strbuf_attach(buf, result, sz, sz + 1); - } - return 0; -} - -static int read_file_or_gitlink(const struct cache_entry *ce, struct strbuf *buf) -{ - if (!ce) - return 0; - return read_blob_object(buf, ce->sha1, ce->ce_mode); -} - -static struct patch *in_fn_table(struct apply_state *state, const char *name) -{ - struct string_list_item *item; - - if (name == NULL) - return NULL; - - item = string_list_lookup(&state->fn_table, name); - if (item != NULL) - return (struct patch *)item->util; - - return NULL; -} - -/* - * item->util in the filename table records the status of the path. - * Usually it points at a patch (whose result records the contents - * of it after applying it), but it could be PATH_WAS_DELETED for a - * path that a previously applied patch has already removed, or - * PATH_TO_BE_DELETED for a path that a later patch would remove. - * - * The latter is needed to deal with a case where two paths A and B - * are swapped by first renaming A to B and then renaming B to A; - * moving A to B should not be prevented due to presence of B as we - * will remove it in a later patch. - */ -#define PATH_TO_BE_DELETED ((struct patch *) -2) -#define PATH_WAS_DELETED ((struct patch *) -1) - -static int to_be_deleted(struct patch *patch) -{ - return patch == PATH_TO_BE_DELETED; -} - -static int was_deleted(struct patch *patch) -{ - return patch == PATH_WAS_DELETED; -} - -static void add_to_fn_table(struct apply_state *state, struct patch *patch) -{ - struct string_list_item *item; - - /* - * Always add new_name unless patch is a deletion - * This should cover the cases for normal diffs, - * file creations and copies - */ - if (patch->new_name != NULL) { - item = string_list_insert(&state->fn_table, patch->new_name); - item->util = patch; - } - - /* - * store a failure on rename/deletion cases because - * later chunks shouldn't patch old names - */ - if ((patch->new_name == NULL) || (patch->is_rename)) { - item = string_list_insert(&state->fn_table, patch->old_name); - item->util = PATH_WAS_DELETED; - } -} - -static void prepare_fn_table(struct apply_state *state, struct patch *patch) -{ - /* - * store information about incoming file deletion - */ - while (patch) { - if ((patch->new_name == NULL) || (patch->is_rename)) { - struct string_list_item *item; - item = string_list_insert(&state->fn_table, patch->old_name); - item->util = PATH_TO_BE_DELETED; - } - patch = patch->next; - } -} - -static int checkout_target(struct index_state *istate, - struct cache_entry *ce, struct stat *st) -{ - struct checkout costate; - - memset(&costate, 0, sizeof(costate)); - costate.base_dir = ""; - costate.refresh_cache = 1; - costate.istate = istate; - if (checkout_entry(ce, &costate, NULL) || lstat(ce->name, st)) - return error(_("cannot checkout %s"), ce->name); - return 0; -} - -static struct patch *previous_patch(struct apply_state *state, - struct patch *patch, - int *gone) -{ - struct patch *previous; - - *gone = 0; - if (patch->is_copy || patch->is_rename) - return NULL; /* "git" patches do not depend on the order */ - - previous = in_fn_table(state, patch->old_name); - if (!previous) - return NULL; - - if (to_be_deleted(previous)) - return NULL; /* the deletion hasn't happened yet */ - - if (was_deleted(previous)) - *gone = 1; - - return previous; -} - -static int verify_index_match(const struct cache_entry *ce, struct stat *st) -{ - if (S_ISGITLINK(ce->ce_mode)) { - if (!S_ISDIR(st->st_mode)) - return -1; - return 0; - } - return ce_match_stat(ce, st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE); -} - -#define SUBMODULE_PATCH_WITHOUT_INDEX 1 - -static int load_patch_target(struct apply_state *state, - struct strbuf *buf, - const struct cache_entry *ce, - struct stat *st, - const char *name, - unsigned expected_mode) -{ - if (state->cached || state->check_index) { - if (read_file_or_gitlink(ce, buf)) - return error(_("failed to read %s"), name); - } else if (name) { - if (S_ISGITLINK(expected_mode)) { - if (ce) - return read_file_or_gitlink(ce, buf); - else - return SUBMODULE_PATCH_WITHOUT_INDEX; - } else if (has_symlink_leading_path(name, strlen(name))) { - return error(_("reading from '%s' beyond a symbolic link"), name); - } else { - if (read_old_data(st, name, buf)) - return error(_("failed to read %s"), name); - } - } - return 0; -} - -/* - * We are about to apply "patch"; populate the "image" with the - * current version we have, from the working tree or from the index, - * depending on the situation e.g. --cached/--index. If we are - * applying a non-git patch that incrementally updates the tree, - * we read from the result of a previous diff. - */ -static int load_preimage(struct apply_state *state, - struct image *image, - struct patch *patch, struct stat *st, - const struct cache_entry *ce) -{ - struct strbuf buf = STRBUF_INIT; - size_t len; - char *img; - struct patch *previous; - int status; - - previous = previous_patch(state, patch, &status); - if (status) - return error(_("path %s has been renamed/deleted"), - patch->old_name); - if (previous) { - /* We have a patched copy in memory; use that. */ - strbuf_add(&buf, previous->result, previous->resultsize); - } else { - status = load_patch_target(state, &buf, ce, st, - patch->old_name, patch->old_mode); - if (status < 0) - return status; - else if (status == SUBMODULE_PATCH_WITHOUT_INDEX) { - /* - * There is no way to apply subproject - * patch without looking at the index. - * NEEDSWORK: shouldn't this be flagged - * as an error??? - */ - free_fragment_list(patch->fragments); - patch->fragments = NULL; - } else if (status) { - return error(_("failed to read %s"), patch->old_name); - } - } - - img = strbuf_detach(&buf, &len); - prepare_image(image, img, len, !patch->is_binary); - return 0; -} - -static int three_way_merge(struct image *image, - char *path, - const unsigned char *base, - const unsigned char *ours, - const unsigned char *theirs) -{ - mmfile_t base_file, our_file, their_file; - mmbuffer_t result = { NULL }; - int status; - - read_mmblob(&base_file, base); - read_mmblob(&our_file, ours); - read_mmblob(&their_file, theirs); - status = ll_merge(&result, path, - &base_file, "base", - &our_file, "ours", - &their_file, "theirs", NULL); - free(base_file.ptr); - free(our_file.ptr); - free(their_file.ptr); - if (status < 0 || !result.ptr) { - free(result.ptr); - return -1; - } - clear_image(image); - image->buf = result.ptr; - image->len = result.size; - - return status; -} - -/* - * When directly falling back to add/add three-way merge, we read from - * the current contents of the new_name. In no cases other than that - * this function will be called. - */ -static int load_current(struct apply_state *state, - struct image *image, - struct patch *patch) -{ - struct strbuf buf = STRBUF_INIT; - int status, pos; - size_t len; - char *img; - struct stat st; - struct cache_entry *ce; - char *name = patch->new_name; - unsigned mode = patch->new_mode; - - if (!patch->is_new) - die("BUG: patch to %s is not a creation", patch->old_name); - - pos = cache_name_pos(name, strlen(name)); - if (pos < 0) - return error(_("%s: does not exist in index"), name); - ce = active_cache[pos]; - if (lstat(name, &st)) { - if (errno != ENOENT) - return error(_("%s: %s"), name, strerror(errno)); - if (checkout_target(&the_index, ce, &st)) - return -1; - } - if (verify_index_match(ce, &st)) - return error(_("%s: does not match index"), name); - - status = load_patch_target(state, &buf, ce, &st, name, mode); - if (status < 0) - return status; - else if (status) - return -1; - img = strbuf_detach(&buf, &len); - prepare_image(image, img, len, !patch->is_binary); - return 0; -} - -static int try_threeway(struct apply_state *state, - struct image *image, - struct patch *patch, - struct stat *st, - const struct cache_entry *ce) -{ - unsigned char pre_sha1[20], post_sha1[20], our_sha1[20]; - struct strbuf buf = STRBUF_INIT; - size_t len; - int status; - char *img; - struct image tmp_image; - - /* No point falling back to 3-way merge in these cases */ - if (patch->is_delete || - S_ISGITLINK(patch->old_mode) || S_ISGITLINK(patch->new_mode)) - return -1; - - /* Preimage the patch was prepared for */ - if (patch->is_new) - write_sha1_file("", 0, blob_type, pre_sha1); - else if (get_sha1(patch->old_sha1_prefix, pre_sha1) || - read_blob_object(&buf, pre_sha1, patch->old_mode)) - return error("repository lacks the necessary blob to fall back on 3-way merge."); - - fprintf(stderr, "Falling back to three-way merge...\n"); - - img = strbuf_detach(&buf, &len); - prepare_image(&tmp_image, img, len, 1); - /* Apply the patch to get the post image */ - if (apply_fragments(state, &tmp_image, patch) < 0) { - clear_image(&tmp_image); - return -1; - } - /* post_sha1[] is theirs */ - write_sha1_file(tmp_image.buf, tmp_image.len, blob_type, post_sha1); - clear_image(&tmp_image); - - /* our_sha1[] is ours */ - if (patch->is_new) { - if (load_current(state, &tmp_image, patch)) - return error("cannot read the current contents of '%s'", - patch->new_name); - } else { - if (load_preimage(state, &tmp_image, patch, st, ce)) - return error("cannot read the current contents of '%s'", - patch->old_name); - } - write_sha1_file(tmp_image.buf, tmp_image.len, blob_type, our_sha1); - clear_image(&tmp_image); - - /* in-core three-way merge between post and our using pre as base */ - status = three_way_merge(image, patch->new_name, - pre_sha1, our_sha1, post_sha1); - if (status < 0) { - fprintf(stderr, "Failed to fall back on three-way merge...\n"); - return status; - } - - if (status) { - patch->conflicted_threeway = 1; - if (patch->is_new) - oidclr(&patch->threeway_stage[0]); - else - hashcpy(patch->threeway_stage[0].hash, pre_sha1); - hashcpy(patch->threeway_stage[1].hash, our_sha1); - hashcpy(patch->threeway_stage[2].hash, post_sha1); - fprintf(stderr, "Applied patch to '%s' with conflicts.\n", patch->new_name); - } else { - fprintf(stderr, "Applied patch to '%s' cleanly.\n", patch->new_name); - } - return 0; -} - -static int apply_data(struct apply_state *state, struct patch *patch, - struct stat *st, const struct cache_entry *ce) -{ - struct image image; - - if (load_preimage(state, &image, patch, st, ce) < 0) - return -1; - - if (patch->direct_to_threeway || - apply_fragments(state, &image, patch) < 0) { - /* Note: with --reject, apply_fragments() returns 0 */ - if (!state->threeway || try_threeway(state, &image, patch, st, ce) < 0) - return -1; - } - patch->result = image.buf; - patch->resultsize = image.len; - add_to_fn_table(state, patch); - free(image.line_allocated); - - if (0 < patch->is_delete && patch->resultsize) - return error(_("removal patch leaves file contents")); - - return 0; -} - -/* - * If "patch" that we are looking at modifies or deletes what we have, - * we would want it not to lose any local modification we have, either - * in the working tree or in the index. - * - * This also decides if a non-git patch is a creation patch or a - * modification to an existing empty file. We do not check the state - * of the current tree for a creation patch in this function; the caller - * check_patch() separately makes sure (and errors out otherwise) that - * the path the patch creates does not exist in the current tree. - */ -static int check_preimage(struct apply_state *state, - struct patch *patch, - struct cache_entry **ce, - struct stat *st) -{ - const char *old_name = patch->old_name; - struct patch *previous = NULL; - int stat_ret = 0, status; - unsigned st_mode = 0; - - if (!old_name) - return 0; - - assert(patch->is_new <= 0); - previous = previous_patch(state, patch, &status); - - if (status) - return error(_("path %s has been renamed/deleted"), old_name); - if (previous) { - st_mode = previous->new_mode; - } else if (!state->cached) { - stat_ret = lstat(old_name, st); - if (stat_ret && errno != ENOENT) - return error(_("%s: %s"), old_name, strerror(errno)); - } - - if (state->check_index && !previous) { - int pos = cache_name_pos(old_name, strlen(old_name)); - if (pos < 0) { - if (patch->is_new < 0) - goto is_new; - return error(_("%s: does not exist in index"), old_name); - } - *ce = active_cache[pos]; - if (stat_ret < 0) { - if (checkout_target(&the_index, *ce, st)) - return -1; - } - if (!state->cached && verify_index_match(*ce, st)) - return error(_("%s: does not match index"), old_name); - if (state->cached) - st_mode = (*ce)->ce_mode; - } else if (stat_ret < 0) { - if (patch->is_new < 0) - goto is_new; - return error(_("%s: %s"), old_name, strerror(errno)); - } - - if (!state->cached && !previous) - st_mode = ce_mode_from_stat(*ce, st->st_mode); - - if (patch->is_new < 0) - patch->is_new = 0; - if (!patch->old_mode) - patch->old_mode = st_mode; - if ((st_mode ^ patch->old_mode) & S_IFMT) - return error(_("%s: wrong type"), old_name); - if (st_mode != patch->old_mode) - warning(_("%s has type %o, expected %o"), - old_name, st_mode, patch->old_mode); - if (!patch->new_mode && !patch->is_delete) - patch->new_mode = st_mode; - return 0; - - is_new: - patch->is_new = 1; - patch->is_delete = 0; - free(patch->old_name); - patch->old_name = NULL; - return 0; -} - - -#define EXISTS_IN_INDEX 1 -#define EXISTS_IN_WORKTREE 2 - -static int check_to_create(struct apply_state *state, - const char *new_name, - int ok_if_exists) -{ - struct stat nst; - - if (state->check_index && - cache_name_pos(new_name, strlen(new_name)) >= 0 && - !ok_if_exists) - return EXISTS_IN_INDEX; - if (state->cached) - return 0; - - if (!lstat(new_name, &nst)) { - if (S_ISDIR(nst.st_mode) || ok_if_exists) - return 0; - /* - * A leading component of new_name might be a symlink - * that is going to be removed with this patch, but - * still pointing at somewhere that has the path. - * In such a case, path "new_name" does not exist as - * far as git is concerned. - */ - if (has_symlink_leading_path(new_name, strlen(new_name))) - return 0; - - return EXISTS_IN_WORKTREE; - } else if ((errno != ENOENT) && (errno != ENOTDIR)) { - return error("%s: %s", new_name, strerror(errno)); - } - return 0; -} - -static uintptr_t register_symlink_changes(struct apply_state *state, - const char *path, - uintptr_t what) -{ - struct string_list_item *ent; - - ent = string_list_lookup(&state->symlink_changes, path); - if (!ent) { - ent = string_list_insert(&state->symlink_changes, path); - ent->util = (void *)0; - } - ent->util = (void *)(what | ((uintptr_t)ent->util)); - return (uintptr_t)ent->util; -} - -static uintptr_t check_symlink_changes(struct apply_state *state, const char *path) -{ - struct string_list_item *ent; - - ent = string_list_lookup(&state->symlink_changes, path); - if (!ent) - return 0; - return (uintptr_t)ent->util; -} - -static void prepare_symlink_changes(struct apply_state *state, struct patch *patch) -{ - for ( ; patch; patch = patch->next) { - if ((patch->old_name && S_ISLNK(patch->old_mode)) && - (patch->is_rename || patch->is_delete)) - /* the symlink at patch->old_name is removed */ - register_symlink_changes(state, patch->old_name, SYMLINK_GOES_AWAY); - - if (patch->new_name && S_ISLNK(patch->new_mode)) - /* the symlink at patch->new_name is created or remains */ - register_symlink_changes(state, patch->new_name, SYMLINK_IN_RESULT); - } -} - -static int path_is_beyond_symlink_1(struct apply_state *state, struct strbuf *name) -{ - do { - unsigned int change; - - while (--name->len && name->buf[name->len] != '/') - ; /* scan backwards */ - if (!name->len) - break; - name->buf[name->len] = '\0'; - change = check_symlink_changes(state, name->buf); - if (change & SYMLINK_IN_RESULT) - return 1; - if (change & SYMLINK_GOES_AWAY) - /* - * This cannot be "return 0", because we may - * see a new one created at a higher level. - */ - continue; - - /* otherwise, check the preimage */ - if (state->check_index) { - struct cache_entry *ce; - - ce = cache_file_exists(name->buf, name->len, ignore_case); - if (ce && S_ISLNK(ce->ce_mode)) - return 1; - } else { - struct stat st; - if (!lstat(name->buf, &st) && S_ISLNK(st.st_mode)) - return 1; - } - } while (1); - return 0; -} - -static int path_is_beyond_symlink(struct apply_state *state, const char *name_) -{ - int ret; - struct strbuf name = STRBUF_INIT; - - assert(*name_ != '\0'); - strbuf_addstr(&name, name_); - ret = path_is_beyond_symlink_1(state, &name); - strbuf_release(&name); - - return ret; -} - -static void die_on_unsafe_path(struct patch *patch) -{ - const char *old_name = NULL; - const char *new_name = NULL; - if (patch->is_delete) - old_name = patch->old_name; - else if (!patch->is_new && !patch->is_copy) - old_name = patch->old_name; - if (!patch->is_delete) - new_name = patch->new_name; - - if (old_name && !verify_path(old_name)) - die(_("invalid path '%s'"), old_name); - if (new_name && !verify_path(new_name)) - die(_("invalid path '%s'"), new_name); -} - -/* - * Check and apply the patch in-core; leave the result in patch->result - * for the caller to write it out to the final destination. - */ -static int check_patch(struct apply_state *state, struct patch *patch) -{ - struct stat st; - const char *old_name = patch->old_name; - const char *new_name = patch->new_name; - const char *name = old_name ? old_name : new_name; - struct cache_entry *ce = NULL; - struct patch *tpatch; - int ok_if_exists; - int status; - - patch->rejected = 1; /* we will drop this after we succeed */ - - status = check_preimage(state, patch, &ce, &st); - if (status) - return status; - old_name = patch->old_name; - - /* - * A type-change diff is always split into a patch to delete - * old, immediately followed by a patch to create new (see - * diff.c::run_diff()); in such a case it is Ok that the entry - * to be deleted by the previous patch is still in the working - * tree and in the index. - * - * A patch to swap-rename between A and B would first rename A - * to B and then rename B to A. While applying the first one, - * the presence of B should not stop A from getting renamed to - * B; ask to_be_deleted() about the later rename. Removal of - * B and rename from A to B is handled the same way by asking - * was_deleted(). - */ - if ((tpatch = in_fn_table(state, new_name)) && - (was_deleted(tpatch) || to_be_deleted(tpatch))) - ok_if_exists = 1; - else - ok_if_exists = 0; - - if (new_name && - ((0 < patch->is_new) || patch->is_rename || patch->is_copy)) { - int err = check_to_create(state, new_name, ok_if_exists); - - if (err && state->threeway) { - patch->direct_to_threeway = 1; - } else switch (err) { - case 0: - break; /* happy */ - case EXISTS_IN_INDEX: - return error(_("%s: already exists in index"), new_name); - break; - case EXISTS_IN_WORKTREE: - return error(_("%s: already exists in working directory"), - new_name); - default: - return err; - } - - if (!patch->new_mode) { - if (0 < patch->is_new) - patch->new_mode = S_IFREG | 0644; - else - patch->new_mode = patch->old_mode; - } - } - - if (new_name && old_name) { - int same = !strcmp(old_name, new_name); - if (!patch->new_mode) - patch->new_mode = patch->old_mode; - if ((patch->old_mode ^ patch->new_mode) & S_IFMT) { - if (same) - return error(_("new mode (%o) of %s does not " - "match old mode (%o)"), - patch->new_mode, new_name, - patch->old_mode); - else - return error(_("new mode (%o) of %s does not " - "match old mode (%o) of %s"), - patch->new_mode, new_name, - patch->old_mode, old_name); - } - } - - if (!state->unsafe_paths) - die_on_unsafe_path(patch); - - /* - * An attempt to read from or delete a path that is beyond a - * symbolic link will be prevented by load_patch_target() that - * is called at the beginning of apply_data() so we do not - * have to worry about a patch marked with "is_delete" bit - * here. We however need to make sure that the patch result - * is not deposited to a path that is beyond a symbolic link - * here. - */ - if (!patch->is_delete && path_is_beyond_symlink(state, patch->new_name)) - return error(_("affected file '%s' is beyond a symbolic link"), - patch->new_name); - - if (apply_data(state, patch, &st, ce) < 0) - return error(_("%s: patch does not apply"), name); - patch->rejected = 0; - return 0; -} - -static int check_patch_list(struct apply_state *state, struct patch *patch) -{ - int err = 0; - - prepare_symlink_changes(state, patch); - prepare_fn_table(state, patch); - while (patch) { - if (state->apply_verbosely) - say_patch_name(stderr, - _("Checking patch %s..."), patch); - err |= check_patch(state, patch); - patch = patch->next; - } - return err; -} - -/* This function tries to read the sha1 from the current index */ -static int get_current_sha1(const char *path, unsigned char *sha1) -{ - int pos; - - if (read_cache() < 0) - return -1; - pos = cache_name_pos(path, strlen(path)); - if (pos < 0) - return -1; - hashcpy(sha1, active_cache[pos]->sha1); - return 0; -} - -static int preimage_sha1_in_gitlink_patch(struct patch *p, unsigned char sha1[20]) -{ - /* - * A usable gitlink patch has only one fragment (hunk) that looks like: - * @@ -1 +1 @@ - * -Subproject commit - * +Subproject commit - * or - * @@ -1 +0,0 @@ - * -Subproject commit - * for a removal patch. - */ - struct fragment *hunk = p->fragments; - static const char heading[] = "-Subproject commit "; - char *preimage; - - if (/* does the patch have only one hunk? */ - hunk && !hunk->next && - /* is its preimage one line? */ - hunk->oldpos == 1 && hunk->oldlines == 1 && - /* does preimage begin with the heading? */ - (preimage = memchr(hunk->patch, '\n', hunk->size)) != NULL && - starts_with(++preimage, heading) && - /* does it record full SHA-1? */ - !get_sha1_hex(preimage + sizeof(heading) - 1, sha1) && - preimage[sizeof(heading) + 40 - 1] == '\n' && - /* does the abbreviated name on the index line agree with it? */ - starts_with(preimage + sizeof(heading) - 1, p->old_sha1_prefix)) - return 0; /* it all looks fine */ - - /* we may have full object name on the index line */ - return get_sha1_hex(p->old_sha1_prefix, sha1); -} - -/* Build an index that contains the just the files needed for a 3way merge */ -static void build_fake_ancestor(struct patch *list, const char *filename) -{ - struct patch *patch; - struct index_state result = { NULL }; - static struct lock_file lock; - - /* Once we start supporting the reverse patch, it may be - * worth showing the new sha1 prefix, but until then... - */ - for (patch = list; patch; patch = patch->next) { - unsigned char sha1[20]; - struct cache_entry *ce; - const char *name; - - name = patch->old_name ? patch->old_name : patch->new_name; - if (0 < patch->is_new) - continue; - - if (S_ISGITLINK(patch->old_mode)) { - if (!preimage_sha1_in_gitlink_patch(patch, sha1)) - ; /* ok, the textual part looks sane */ - else - die("sha1 information is lacking or useless for submodule %s", - name); - } else if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) { - ; /* ok */ - } else if (!patch->lines_added && !patch->lines_deleted) { - /* mode-only change: update the current */ - if (get_current_sha1(patch->old_name, sha1)) - die("mode change for %s, which is not " - "in current HEAD", name); - } else - die("sha1 information is lacking or useless " - "(%s).", name); - - ce = make_cache_entry(patch->old_mode, sha1, name, 0, 0); - if (!ce) - die(_("make_cache_entry failed for path '%s'"), name); - if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD)) - die ("Could not add %s to temporary index", name); - } - - hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR); - if (write_locked_index(&result, &lock, COMMIT_LOCK)) - die ("Could not write temporary index to %s", filename); - - discard_index(&result); -} - -static void stat_patch_list(struct apply_state *state, struct patch *patch) -{ - int files, adds, dels; - - for (files = adds = dels = 0 ; patch ; patch = patch->next) { - files++; - adds += patch->lines_added; - dels += patch->lines_deleted; - show_stats(state, patch); - } - - print_stat_summary(stdout, files, adds, dels); -} - -static void numstat_patch_list(struct apply_state *state, - struct patch *patch) -{ - for ( ; patch; patch = patch->next) { - const char *name; - name = patch->new_name ? patch->new_name : patch->old_name; - if (patch->is_binary) - printf("-\t-\t"); - else - printf("%d\t%d\t", patch->lines_added, patch->lines_deleted); - write_name_quoted(name, stdout, state->line_termination); - } -} - -static void show_file_mode_name(const char *newdelete, unsigned int mode, const char *name) -{ - if (mode) - printf(" %s mode %06o %s\n", newdelete, mode, name); - else - printf(" %s %s\n", newdelete, name); -} - -static void show_mode_change(struct patch *p, int show_name) -{ - if (p->old_mode && p->new_mode && p->old_mode != p->new_mode) { - if (show_name) - printf(" mode change %06o => %06o %s\n", - p->old_mode, p->new_mode, p->new_name); - else - printf(" mode change %06o => %06o\n", - p->old_mode, p->new_mode); - } -} - -static void show_rename_copy(struct patch *p) -{ - const char *renamecopy = p->is_rename ? "rename" : "copy"; - const char *old, *new; - - /* Find common prefix */ - old = p->old_name; - new = p->new_name; - while (1) { - const char *slash_old, *slash_new; - slash_old = strchr(old, '/'); - slash_new = strchr(new, '/'); - if (!slash_old || - !slash_new || - slash_old - old != slash_new - new || - memcmp(old, new, slash_new - new)) - break; - old = slash_old + 1; - new = slash_new + 1; - } - /* p->old_name thru old is the common prefix, and old and new - * through the end of names are renames - */ - if (old != p->old_name) - printf(" %s %.*s{%s => %s} (%d%%)\n", renamecopy, - (int)(old - p->old_name), p->old_name, - old, new, p->score); - else - printf(" %s %s => %s (%d%%)\n", renamecopy, - p->old_name, p->new_name, p->score); - show_mode_change(p, 0); -} - -static void summary_patch_list(struct patch *patch) -{ - struct patch *p; - - for (p = patch; p; p = p->next) { - if (p->is_new) - show_file_mode_name("create", p->new_mode, p->new_name); - else if (p->is_delete) - show_file_mode_name("delete", p->old_mode, p->old_name); - else { - if (p->is_rename || p->is_copy) - show_rename_copy(p); - else { - if (p->score) { - printf(" rewrite %s (%d%%)\n", - p->new_name, p->score); - show_mode_change(p, 0); - } - else - show_mode_change(p, 1); - } - } - } -} - -static void patch_stats(struct apply_state *state, struct patch *patch) -{ - int lines = patch->lines_added + patch->lines_deleted; - - if (lines > state->max_change) - state->max_change = lines; - if (patch->old_name) { - int len = quote_c_style(patch->old_name, NULL, NULL, 0); - if (!len) - len = strlen(patch->old_name); - if (len > state->max_len) - state->max_len = len; - } - if (patch->new_name) { - int len = quote_c_style(patch->new_name, NULL, NULL, 0); - if (!len) - len = strlen(patch->new_name); - if (len > state->max_len) - state->max_len = len; - } -} - -static void remove_file(struct apply_state *state, struct patch *patch, int rmdir_empty) -{ - if (state->update_index) { - if (remove_file_from_cache(patch->old_name) < 0) - die(_("unable to remove %s from index"), patch->old_name); - } - if (!state->cached) { - if (!remove_or_warn(patch->old_mode, patch->old_name) && rmdir_empty) { - remove_path(patch->old_name); - } - } -} - -static void add_index_file(struct apply_state *state, - const char *path, - unsigned mode, - void *buf, - unsigned long size) -{ - struct stat st; - struct cache_entry *ce; - int namelen = strlen(path); - unsigned ce_size = cache_entry_size(namelen); - - if (!state->update_index) - return; - - ce = xcalloc(1, ce_size); - memcpy(ce->name, path, namelen); - ce->ce_mode = create_ce_mode(mode); - ce->ce_flags = create_ce_flags(0); - ce->ce_namelen = namelen; - if (S_ISGITLINK(mode)) { - const char *s; - - if (!skip_prefix(buf, "Subproject commit ", &s) || - get_sha1_hex(s, ce->sha1)) - die(_("corrupt patch for submodule %s"), path); - } else { - if (!state->cached) { - if (lstat(path, &st) < 0) - die_errno(_("unable to stat newly created file '%s'"), - path); - fill_stat_cache_info(ce, &st); - } - if (write_sha1_file(buf, size, blob_type, ce->sha1) < 0) - die(_("unable to create backing store for newly created file %s"), path); - } - if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0) - die(_("unable to add cache entry for %s"), path); -} - -static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size) -{ - int fd; - struct strbuf nbuf = STRBUF_INIT; - - if (S_ISGITLINK(mode)) { - struct stat st; - if (!lstat(path, &st) && S_ISDIR(st.st_mode)) - return 0; - return mkdir(path, 0777); - } - - if (has_symlinks && S_ISLNK(mode)) - /* Although buf:size is counted string, it also is NUL - * terminated. - */ - return symlink(buf, path); - - fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666); - if (fd < 0) - return -1; - - if (convert_to_working_tree(path, buf, size, &nbuf)) { - size = nbuf.len; - buf = nbuf.buf; - } - write_or_die(fd, buf, size); - strbuf_release(&nbuf); - - if (close(fd) < 0) - die_errno(_("closing file '%s'"), path); - return 0; -} - -/* - * We optimistically assume that the directories exist, - * which is true 99% of the time anyway. If they don't, - * we create them and try again. - */ -static void create_one_file(struct apply_state *state, - char *path, - unsigned mode, - const char *buf, - unsigned long size) -{ - if (state->cached) - return; - if (!try_create_file(path, mode, buf, size)) - return; - - if (errno == ENOENT) { - if (safe_create_leading_directories(path)) - return; - if (!try_create_file(path, mode, buf, size)) - return; - } - - if (errno == EEXIST || errno == EACCES) { - /* We may be trying to create a file where a directory - * used to be. - */ - struct stat st; - if (!lstat(path, &st) && (!S_ISDIR(st.st_mode) || !rmdir(path))) - errno = EEXIST; - } - - if (errno == EEXIST) { - unsigned int nr = getpid(); - - for (;;) { - char newpath[PATH_MAX]; - mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr); - if (!try_create_file(newpath, mode, buf, size)) { - if (!rename(newpath, path)) - return; - unlink_or_warn(newpath); - break; - } - if (errno != EEXIST) - break; - ++nr; - } - } - die_errno(_("unable to write file '%s' mode %o"), path, mode); -} - -static void add_conflicted_stages_file(struct apply_state *state, - struct patch *patch) -{ - int stage, namelen; - unsigned ce_size, mode; - struct cache_entry *ce; - - if (!state->update_index) - return; - namelen = strlen(patch->new_name); - ce_size = cache_entry_size(namelen); - mode = patch->new_mode ? patch->new_mode : (S_IFREG | 0644); - - remove_file_from_cache(patch->new_name); - for (stage = 1; stage < 4; stage++) { - if (is_null_oid(&patch->threeway_stage[stage - 1])) - continue; - ce = xcalloc(1, ce_size); - memcpy(ce->name, patch->new_name, namelen); - ce->ce_mode = create_ce_mode(mode); - ce->ce_flags = create_ce_flags(stage); - ce->ce_namelen = namelen; - hashcpy(ce->sha1, patch->threeway_stage[stage - 1].hash); - if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0) - die(_("unable to add cache entry for %s"), patch->new_name); - } -} - -static void create_file(struct apply_state *state, struct patch *patch) -{ - char *path = patch->new_name; - unsigned mode = patch->new_mode; - unsigned long size = patch->resultsize; - char *buf = patch->result; - - if (!mode) - mode = S_IFREG | 0644; - create_one_file(state, path, mode, buf, size); - - if (patch->conflicted_threeway) - add_conflicted_stages_file(state, patch); - else - add_index_file(state, path, mode, buf, size); -} - -/* phase zero is to remove, phase one is to create */ -static void write_out_one_result(struct apply_state *state, - struct patch *patch, - int phase) -{ - if (patch->is_delete > 0) { - if (phase == 0) - remove_file(state, patch, 1); - return; - } - if (patch->is_new > 0 || patch->is_copy) { - if (phase == 1) - create_file(state, patch); - return; - } - /* - * Rename or modification boils down to the same - * thing: remove the old, write the new - */ - if (phase == 0) - remove_file(state, patch, patch->is_rename); - if (phase == 1) - create_file(state, patch); -} - -static int write_out_one_reject(struct apply_state *state, struct patch *patch) -{ - FILE *rej; - char namebuf[PATH_MAX]; - struct fragment *frag; - int cnt = 0; - struct strbuf sb = STRBUF_INIT; - - for (cnt = 0, frag = patch->fragments; frag; frag = frag->next) { - if (!frag->rejected) - continue; - cnt++; - } - - if (!cnt) { - if (state->apply_verbosely) - say_patch_name(stderr, - _("Applied patch %s cleanly."), patch); - return 0; - } - - /* This should not happen, because a removal patch that leaves - * contents are marked "rejected" at the patch level. - */ - if (!patch->new_name) - die(_("internal error")); - - /* Say this even without --verbose */ - strbuf_addf(&sb, Q_("Applying patch %%s with %d reject...", - "Applying patch %%s with %d rejects...", - cnt), - cnt); - say_patch_name(stderr, sb.buf, patch); - strbuf_release(&sb); - - cnt = strlen(patch->new_name); - if (ARRAY_SIZE(namebuf) <= cnt + 5) { - cnt = ARRAY_SIZE(namebuf) - 5; - warning(_("truncating .rej filename to %.*s.rej"), - cnt - 1, patch->new_name); - } - memcpy(namebuf, patch->new_name, cnt); - memcpy(namebuf + cnt, ".rej", 5); - - rej = fopen(namebuf, "w"); - if (!rej) - return error(_("cannot open %s: %s"), namebuf, strerror(errno)); - - /* Normal git tools never deal with .rej, so do not pretend - * this is a git patch by saying --git or giving extended - * headers. While at it, maybe please "kompare" that wants - * the trailing TAB and some garbage at the end of line ;-). - */ - fprintf(rej, "diff a/%s b/%s\t(rejected hunks)\n", - patch->new_name, patch->new_name); - for (cnt = 1, frag = patch->fragments; - frag; - cnt++, frag = frag->next) { - if (!frag->rejected) { - fprintf_ln(stderr, _("Hunk #%d applied cleanly."), cnt); - continue; - } - fprintf_ln(stderr, _("Rejected hunk #%d."), cnt); - fprintf(rej, "%.*s", frag->size, frag->patch); - if (frag->patch[frag->size-1] != '\n') - fputc('\n', rej); - } - fclose(rej); - return -1; -} - -static int write_out_results(struct apply_state *state, struct patch *list) -{ - int phase; - int errs = 0; - struct patch *l; - struct string_list cpath = STRING_LIST_INIT_DUP; - - for (phase = 0; phase < 2; phase++) { - l = list; - while (l) { - if (l->rejected) - errs = 1; - else { - write_out_one_result(state, l, phase); - if (phase == 1) { - if (write_out_one_reject(state, l)) - errs = 1; - if (l->conflicted_threeway) { - string_list_append(&cpath, l->new_name); - errs = 1; - } - } - } - l = l->next; - } - } - - if (cpath.nr) { - struct string_list_item *item; - - string_list_sort(&cpath); - for_each_string_list_item(item, &cpath) - fprintf(stderr, "U %s\n", item->string); - string_list_clear(&cpath, 0); - - rerere(0); - } +#include "builtin.h" +#include "parse-options.h" +#include "lockfile.h" +#include "apply.h" - return errs; -} +static const char * const apply_usage[] = { + N_("git apply [] [...]"), + NULL +}; static struct lock_file lock_file; -#define INACCURATE_EOF (1<<0) -#define RECOUNT (1<<1) - -static int apply_patch(struct apply_state *state, - int fd, - const char *filename, - int options) -{ - size_t offset; - struct strbuf buf = STRBUF_INIT; /* owns the patch text */ - struct patch *list = NULL, **listp = &list; - int skipped_patch = 0; - - state->patch_input_file = filename; - read_patch_file(&buf, fd); - offset = 0; - while (offset < buf.len) { - struct patch *patch; - int nr; - - patch = xcalloc(1, sizeof(*patch)); - patch->inaccurate_eof = !!(options & INACCURATE_EOF); - patch->recount = !!(options & RECOUNT); - nr = parse_chunk(state, buf.buf + offset, buf.len - offset, patch); - if (nr < 0) { - free_patch(patch); - break; - } - if (state->apply_in_reverse) - reverse_patches(patch); - if (use_patch(state, patch)) { - patch_stats(state, patch); - *listp = patch; - listp = &patch->next; - } - else { - if (state->apply_verbosely) - say_patch_name(stderr, _("Skipped patch '%s'."), patch); - free_patch(patch); - skipped_patch++; - } - offset += nr; - } - - if (!list && !skipped_patch) - die(_("unrecognized input")); - - if (state->whitespace_error && (state->ws_error_action == die_on_ws_error)) - state->apply = 0; - - state->update_index = state->check_index && state->apply; - if (state->update_index && state->newfd < 0) - state->newfd = hold_locked_index(state->lock_file, 1); - - if (state->check_index) { - if (read_cache() < 0) - die(_("unable to read index file")); - } - - if ((state->check || state->apply) && - check_patch_list(state, list) < 0 && - !state->apply_with_reject) - exit(1); - - if (state->apply && write_out_results(state, list)) { - if (state->apply_with_reject) - exit(1); - /* with --3way, we still need to write the index out */ - return 1; - } - - if (state->fake_ancestor) - build_fake_ancestor(list, state->fake_ancestor); - - if (state->diffstat) - stat_patch_list(state, list); - - if (state->numstat) - numstat_patch_list(state, list); - - if (state->summary) - summary_patch_list(list); - - free_patch_list(list); - strbuf_release(&buf); - string_list_clear(&state->fn_table, 0); - return 0; -} - -static void git_apply_config(void) -{ - git_config_get_string_const("apply.whitespace", &apply_default_whitespace); - git_config_get_string_const("apply.ignorewhitespace", &apply_default_ignorewhitespace); - git_config(git_default_config, NULL); -} - -static int option_parse_exclude(const struct option *opt, - const char *arg, int unset) -{ - struct apply_state *state = opt->value; - add_name_limit(state, arg, 1); - return 0; -} - -static int option_parse_include(const struct option *opt, - const char *arg, int unset) -{ - struct apply_state *state = opt->value; - add_name_limit(state, arg, 0); - state->has_include = 1; - return 0; -} - -static int option_parse_p(const struct option *opt, - const char *arg, - int unset) -{ - struct apply_state *state = opt->value; - state->p_value = atoi(arg); - state->p_value_known = 1; - return 0; -} - -static int option_parse_space_change(const struct option *opt, - const char *arg, int unset) -{ - struct apply_state *state = opt->value; - if (unset) - state->ws_ignore_action = ignore_ws_none; - else - state->ws_ignore_action = ignore_ws_change; - return 0; -} - -static int option_parse_whitespace(const struct option *opt, - const char *arg, int unset) -{ - struct apply_state *state = opt->value; - state->whitespace_option = arg; - parse_whitespace_option(state, arg); - return 0; -} - -static int option_parse_directory(const struct option *opt, - const char *arg, int unset) -{ - struct apply_state *state = opt->value; - strbuf_reset(&state->root); - strbuf_addstr(&state->root, arg); - strbuf_complete(&state->root, '/'); - return 0; -} - -static void init_apply_state(struct apply_state *state, - const char *prefix, - struct lock_file *lock_file) -{ - memset(state, 0, sizeof(*state)); - state->prefix = prefix; - state->prefix_length = state->prefix ? strlen(state->prefix) : 0; - state->lock_file = lock_file; - state->newfd = -1; - state->apply = 1; - state->line_termination = '\n'; - state->p_value = 1; - state->p_context = UINT_MAX; - state->squelch_whitespace_errors = 5; - state->ws_error_action = warn_on_ws_error; - state->ws_ignore_action = ignore_ws_none; - state->linenr = 1; - string_list_init(&state->fn_table, 0); - string_list_init(&state->limit_by_name, 0); - string_list_init(&state->symlink_changes, 0); - strbuf_init(&state->root, 0); - - git_apply_config(); - if (apply_default_whitespace) - parse_whitespace_option(state, apply_default_whitespace); - if (apply_default_ignorewhitespace) - parse_ignorewhitespace_option(state, apply_default_ignorewhitespace); -} - -static void clear_apply_state(struct apply_state *state) -{ - string_list_clear(&state->limit_by_name, 0); - string_list_clear(&state->symlink_changes, 0); - strbuf_release(&state->root); - - /* &state->fn_table is cleared at the end of apply_patch() */ -} - -static void check_apply_state(struct apply_state *state, int force_apply) -{ - int is_not_gitdir = !startup_info->have_repository; - - if (state->apply_with_reject && state->threeway) - die("--reject and --3way cannot be used together."); - if (state->cached && state->threeway) - die("--cached and --3way cannot be used together."); - if (state->threeway) { - if (is_not_gitdir) - die(_("--3way outside a repository")); - state->check_index = 1; - } - if (state->apply_with_reject) - state->apply = state->apply_verbosely = 1; - if (!force_apply && (state->diffstat || state->numstat || state->summary || state->check || state->fake_ancestor)) - state->apply = 0; - if (state->check_index && is_not_gitdir) - die(_("--index outside a repository")); - if (state->cached) { - if (is_not_gitdir) - die(_("--cached outside a repository")); - state->check_index = 1; - } - if (state->check_index) - state->unsafe_paths = 0; - if (!state->lock_file) - die("BUG: state->lock_file should not be NULL"); -} - -static int apply_all_patches(struct apply_state *state, - int argc, - const char **argv, - int options) -{ - int i; - int errs = 0; - int read_stdin = 1; - - for (i = 0; i < argc; i++) { - const char *arg = argv[i]; - int fd; - - if (!strcmp(arg, "-")) { - errs |= apply_patch(state, 0, "", options); - read_stdin = 0; - continue; - } else if (0 < state->prefix_length) - arg = prefix_filename(state->prefix, - state->prefix_length, - arg); - - fd = open(arg, O_RDONLY); - if (fd < 0) - die_errno(_("can't open patch '%s'"), arg); - read_stdin = 0; - set_default_whitespace_mode(state); - errs |= apply_patch(state, fd, arg, options); - close(fd); - } - set_default_whitespace_mode(state); - if (read_stdin) - errs |= apply_patch(state, 0, "", options); - - if (state->whitespace_error) { - if (state->squelch_whitespace_errors && - state->squelch_whitespace_errors < state->whitespace_error) { - int squelched = - state->whitespace_error - state->squelch_whitespace_errors; - warning(Q_("squelched %d whitespace error", - "squelched %d whitespace errors", - squelched), - squelched); - } - if (state->ws_error_action == die_on_ws_error) - die(Q_("%d line adds whitespace errors.", - "%d lines add whitespace errors.", - state->whitespace_error), - state->whitespace_error); - if (state->applied_after_fixing_ws && state->apply) - warning("%d line%s applied after" - " fixing whitespace errors.", - state->applied_after_fixing_ws, - state->applied_after_fixing_ws == 1 ? "" : "s"); - else if (state->whitespace_error) - warning(Q_("%d line adds whitespace errors.", - "%d lines add whitespace errors.", - state->whitespace_error), - state->whitespace_error); - } - - if (state->update_index) { - if (write_locked_index(&the_index, state->lock_file, COMMIT_LOCK)) - die(_("Unable to write new index file")); - state->newfd = -1; - } - - return !!errs; -} - int cmd_apply(int argc, const char **argv, const char *prefix) { int force_apply = 0; @@ -4795,81 +18,15 @@ int cmd_apply(int argc, const char **argv, const char *prefix) int ret; struct apply_state state; - struct option builtin_apply_options[] = { - { OPTION_CALLBACK, 0, "exclude", &state, N_("path"), - N_("don't apply changes matching the given path"), - 0, option_parse_exclude }, - { OPTION_CALLBACK, 0, "include", &state, N_("path"), - N_("apply changes matching the given path"), - 0, option_parse_include }, - { OPTION_CALLBACK, 'p', NULL, &state, N_("num"), - N_("remove leading slashes from traditional diff paths"), - 0, option_parse_p }, - OPT_BOOL(0, "no-add", &state.no_add, - N_("ignore additions made by the patch")), - OPT_BOOL(0, "stat", &state.diffstat, - N_("instead of applying the patch, output diffstat for the input")), - OPT_NOOP_NOARG(0, "allow-binary-replacement"), - OPT_NOOP_NOARG(0, "binary"), - OPT_BOOL(0, "numstat", &state.numstat, - N_("show number of added and deleted lines in decimal notation")), - OPT_BOOL(0, "summary", &state.summary, - N_("instead of applying the patch, output a summary for the input")), - OPT_BOOL(0, "check", &state.check, - N_("instead of applying the patch, see if the patch is applicable")), - OPT_BOOL(0, "index", &state.check_index, - N_("make sure the patch is applicable to the current index")), - OPT_BOOL(0, "cached", &state.cached, - N_("apply a patch without touching the working tree")), - OPT_BOOL(0, "unsafe-paths", &state.unsafe_paths, - N_("accept a patch that touches outside the working area")), - OPT_BOOL(0, "apply", &force_apply, - N_("also apply the patch (use with --stat/--summary/--check)")), - OPT_BOOL('3', "3way", &state.threeway, - N_( "attempt three-way merge if a patch does not apply")), - OPT_FILENAME(0, "build-fake-ancestor", &state.fake_ancestor, - N_("build a temporary index based on embedded index information")), - /* Think twice before adding "--nul" synonym to this */ - OPT_SET_INT('z', NULL, &state.line_termination, - N_("paths are separated with NUL character"), '\0'), - OPT_INTEGER('C', NULL, &state.p_context, - N_("ensure at least lines of context match")), - { OPTION_CALLBACK, 0, "whitespace", &state, N_("action"), - N_("detect new or modified lines that have whitespace errors"), - 0, option_parse_whitespace }, - { OPTION_CALLBACK, 0, "ignore-space-change", &state, NULL, - N_("ignore changes in whitespace when finding context"), - PARSE_OPT_NOARG, option_parse_space_change }, - { OPTION_CALLBACK, 0, "ignore-whitespace", &state, NULL, - N_("ignore changes in whitespace when finding context"), - PARSE_OPT_NOARG, option_parse_space_change }, - OPT_BOOL('R', "reverse", &state.apply_in_reverse, - N_("apply the patch in reverse")), - OPT_BOOL(0, "unidiff-zero", &state.unidiff_zero, - N_("don't expect at least one line of context")), - OPT_BOOL(0, "reject", &state.apply_with_reject, - N_("leave the rejected hunks in corresponding *.rej files")), - OPT_BOOL(0, "allow-overlap", &state.allow_overlap, - N_("allow overlapping hunks")), - OPT__VERBOSE(&state.apply_verbosely, N_("be verbose")), - OPT_BIT(0, "inaccurate-eof", &options, - N_("tolerate incorrectly detected missing new-line at the end of file"), - INACCURATE_EOF), - OPT_BIT(0, "recount", &options, - N_("do not trust the line counts in the hunk headers"), - RECOUNT), - { OPTION_CALLBACK, 0, "directory", &state, N_("root"), - N_("prepend to all filenames"), - 0, option_parse_directory }, - OPT_END() - }; - - init_apply_state(&state, prefix, &lock_file); + if (init_apply_state(&state, prefix, &lock_file)) + exit(128); - argc = parse_options(argc, argv, state.prefix, builtin_apply_options, - apply_usage, 0); + argc = apply_parse_options(argc, argv, + &state, &force_apply, &options, + apply_usage); - check_apply_state(&state, force_apply); + if (check_apply_state(&state, force_apply)) + exit(128); ret = apply_all_patches(&state, argc, argv, options); diff --git a/builtin/archive.c b/builtin/archive.c index a1e3b94..f863465 100644 --- a/builtin/archive.c +++ b/builtin/archive.c @@ -47,10 +47,10 @@ static int run_remote_archiver(int argc, const char **argv, if (name_hint) { const char *format = archive_format_from_filename(name_hint); if (format) - packet_write(fd[1], "argument --format=%s\n", format); + packet_write_fmt(fd[1], "argument --format=%s\n", format); } for (i = 1; i < argc; i++) - packet_write(fd[1], "argument %s\n", argv[i]); + packet_write_fmt(fd[1], "argument %s\n", argv[i]); packet_flush(fd[1]); buf = packet_read_line(fd[0], NULL); @@ -85,8 +85,8 @@ int cmd_archive(int argc, const char **argv, const char *prefix) const char *output = NULL; const char *remote = NULL; struct option local_opts[] = { - OPT_STRING('o', "output", &output, N_("file"), - N_("write the archive to this file")), + OPT_FILENAME('o', "output", &output, + N_("write the archive to this file")), OPT_STRING(0, "remote", &remote, N_("repo"), N_("retrieve the archive from remote repository ")), OPT_STRING(0, "exec", &exec, N_("command"), @@ -105,5 +105,5 @@ int cmd_archive(int argc, const char **argv, const char *prefix) setvbuf(stderr, NULL, _IOLBF, BUFSIZ); - return write_archive(argc, argv, prefix, 1, output, 0); + return write_archive(argc, argv, prefix, output, 0); } diff --git a/builtin/blame.c b/builtin/blame.c index f618392..4ddfadb 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -120,7 +120,7 @@ struct origin { */ struct blame_entry *suspects; mmfile_t file; - unsigned char blob_sha1[20]; + struct object_id blob_oid; unsigned mode; /* guilty gets set when shipping any suspects to the final * blame list instead of other commits @@ -154,8 +154,8 @@ static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, */ int textconv_object(const char *path, unsigned mode, - const unsigned char *sha1, - int sha1_valid, + const struct object_id *oid, + int oid_valid, char **buf, unsigned long *buf_size) { @@ -163,7 +163,7 @@ int textconv_object(const char *path, struct userdiff_driver *textconv; df = alloc_filespec(path); - fill_filespec(df, sha1, sha1_valid, mode); + fill_filespec(df, oid->hash, oid_valid, mode); textconv = get_textconv(df); if (!textconv) { free_filespec(df); @@ -188,15 +188,16 @@ static void fill_origin_blob(struct diff_options *opt, num_read_blob++; if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) && - textconv_object(o->path, o->mode, o->blob_sha1, 1, &file->ptr, &file_size)) + textconv_object(o->path, o->mode, &o->blob_oid, 1, &file->ptr, &file_size)) ; else - file->ptr = read_sha1_file(o->blob_sha1, &type, &file_size); + file->ptr = read_sha1_file(o->blob_oid.hash, &type, + &file_size); file->size = file_size; if (!file->ptr) die("Cannot read blob %s for path %s", - sha1_to_hex(o->blob_sha1), + oid_to_hex(&o->blob_oid), o->path); o->file = *file; } @@ -508,17 +509,17 @@ static struct origin *get_origin(struct scoreboard *sb, */ static int fill_blob_sha1_and_mode(struct origin *origin) { - if (!is_null_sha1(origin->blob_sha1)) + if (!is_null_oid(&origin->blob_oid)) return 0; if (get_tree_entry(origin->commit->object.oid.hash, origin->path, - origin->blob_sha1, &origin->mode)) + origin->blob_oid.hash, &origin->mode)) goto error_out; - if (sha1_object_info(origin->blob_sha1, NULL) != OBJ_BLOB) + if (sha1_object_info(origin->blob_oid.hash, NULL) != OBJ_BLOB) goto error_out; return 0; error_out: - hashclr(origin->blob_sha1); + oidclr(&origin->blob_oid); origin->mode = S_IFINVALID; return -1; } @@ -572,7 +573,7 @@ static struct origin *find_origin(struct scoreboard *sb, if (!diff_queued_diff.nr) { /* The path is the same as parent */ porigin = get_origin(sb, parent, origin->path); - hashcpy(porigin->blob_sha1, origin->blob_sha1); + oidcpy(&porigin->blob_oid, &origin->blob_oid); porigin->mode = origin->mode; } else { /* @@ -598,7 +599,7 @@ static struct origin *find_origin(struct scoreboard *sb, p->status); case 'M': porigin = get_origin(sb, parent, origin->path); - hashcpy(porigin->blob_sha1, p->one->oid.hash); + oidcpy(&porigin->blob_oid, &p->one->oid); porigin->mode = p->one->mode; break; case 'A': @@ -644,7 +645,7 @@ static struct origin *find_rename(struct scoreboard *sb, if ((p->status == 'R' || p->status == 'C') && !strcmp(p->two->path, origin->path)) { porigin = get_origin(sb, parent, p->one->path); - hashcpy(porigin->blob_sha1, p->one->oid.hash); + oidcpy(&porigin->blob_oid, &p->one->oid); porigin->mode = p->one->mode; break; } @@ -1308,7 +1309,7 @@ static void find_copy_in_parent(struct scoreboard *sb, continue; norigin = get_origin(sb, parent, p->one->path); - hashcpy(norigin->blob_sha1, p->one->oid.hash); + oidcpy(&norigin->blob_oid, &p->one->oid); norigin->mode = p->one->mode; fill_origin_blob(&sb->revs->diffopt, norigin, &file_p); if (!file_p.ptr) @@ -1458,15 +1459,14 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt) porigin = find(sb, p, origin); if (!porigin) continue; - if (!hashcmp(porigin->blob_sha1, origin->blob_sha1)) { + if (!oidcmp(&porigin->blob_oid, &origin->blob_oid)) { pass_whole_blame(sb, origin, porigin); origin_decref(porigin); goto finish; } for (j = same = 0; j < i; j++) if (sg_origin[j] && - !hashcmp(sg_origin[j]->blob_sha1, - porigin->blob_sha1)) { + !oidcmp(&sg_origin[j]->blob_oid, &porigin->blob_oid)) { same = 1; break; } @@ -1941,7 +1941,7 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt) cp = nth_line(sb, ent->lno); for (cnt = 0; cnt < ent->num_lines; cnt++) { char ch; - int length = (opt & OUTPUT_LONG_OBJECT_NAME) ? 40 : abbrev; + int length = (opt & OUTPUT_LONG_OBJECT_NAME) ? GIT_SHA1_HEXSZ : abbrev; if (suspect->commit->object.flags & UNINTERESTING) { if (blank_boundary) @@ -2220,6 +2220,8 @@ static int git_blame_config(const char *var, const char *value, void *cb) return 0; } + if (git_diff_heuristic_config(var, value, cb) < 0) + return -1; if (userdiff_config(var, value) < 0) return -1; @@ -2232,12 +2234,12 @@ static void verify_working_tree_path(struct commit *work_tree, const char *path) int pos; for (parents = work_tree->parents; parents; parents = parents->next) { - const unsigned char *commit_sha1 = parents->item->object.oid.hash; - unsigned char blob_sha1[20]; + const struct object_id *commit_oid = &parents->item->object.oid; + struct object_id blob_oid; unsigned mode; - if (!get_tree_entry(commit_sha1, path, blob_sha1, &mode) && - sha1_object_info(blob_sha1, NULL) == OBJ_BLOB) + if (!get_tree_entry(commit_oid->hash, path, blob_oid.hash, &mode) && + sha1_object_info(blob_oid.hash, NULL) == OBJ_BLOB) return; } @@ -2251,13 +2253,13 @@ static void verify_working_tree_path(struct commit *work_tree, const char *path) die("no such path '%s' in HEAD", path); } -static struct commit_list **append_parent(struct commit_list **tail, const unsigned char *sha1) +static struct commit_list **append_parent(struct commit_list **tail, const struct object_id *oid) { struct commit *parent; - parent = lookup_commit_reference(sha1); + parent = lookup_commit_reference(oid->hash); if (!parent) - die("no such commit %s", sha1_to_hex(sha1)); + die("no such commit %s", oid_to_hex(oid)); return &commit_list_insert(parent, tail)->next; } @@ -2274,10 +2276,10 @@ static void append_merge_parents(struct commit_list **tail) } while (!strbuf_getwholeline_fd(&line, merge_head, '\n')) { - unsigned char sha1[20]; - if (line.len < 40 || get_sha1_hex(line.buf, sha1)) + struct object_id oid; + if (line.len < GIT_SHA1_HEXSZ || get_oid_hex(line.buf, &oid)) die("unknown line in '%s': %s", git_path_merge_head(), line.buf); - tail = append_parent(tail, sha1); + tail = append_parent(tail, &oid); } close(merge_head); strbuf_release(&line); @@ -2306,7 +2308,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt, struct commit *commit; struct origin *origin; struct commit_list **parent_tail, *parent; - unsigned char head_sha1[20]; + struct object_id head_oid; struct strbuf buf = STRBUF_INIT; const char *ident; time_t now; @@ -2322,10 +2324,10 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt, commit->date = now; parent_tail = &commit->parents; - if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_sha1, NULL)) + if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_oid.hash, NULL)) die("no such ref: HEAD"); - parent_tail = append_parent(parent_tail, head_sha1); + parent_tail = append_parent(parent_tail, &head_oid); append_merge_parents(parent_tail); verify_working_tree_path(commit, path); @@ -2366,7 +2368,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt, switch (st.st_mode & S_IFMT) { case S_IFREG: if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) && - textconv_object(read_from, mode, null_sha1, 0, &buf_ptr, &buf_len)) + textconv_object(read_from, mode, &null_oid, 0, &buf_ptr, &buf_len)) strbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1); else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size) die_errno("cannot open or read '%s'", read_from); @@ -2388,7 +2390,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt, convert_to_git(path, buf.buf, buf.len, &buf, 0); origin->file.ptr = buf.buf; origin->file.size = buf.len; - pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_sha1); + pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_oid.hash); /* * Read the current index, replace the path entry with @@ -2410,7 +2412,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt, } size = cache_entry_size(len); ce = xcalloc(1, size); - hashcpy(ce->sha1, origin->blob_sha1); + oidcpy(&ce->oid, &origin->blob_oid); memcpy(ce->name, path, len); ce->ce_flags = create_ce_flags(0); ce->ce_namelen = len; @@ -2454,6 +2456,41 @@ static char *prepare_final(struct scoreboard *sb) return xstrdup_or_null(name); } +static const char *dwim_reverse_initial(struct scoreboard *sb) +{ + /* + * DWIM "git blame --reverse ONE -- PATH" as + * "git blame --reverse ONE..HEAD -- PATH" but only do so + * when it makes sense. + */ + struct object *obj; + struct commit *head_commit; + unsigned char head_sha1[20]; + + if (sb->revs->pending.nr != 1) + return NULL; + + /* Is that sole rev a committish? */ + obj = sb->revs->pending.objects[0].item; + obj = deref_tag(obj, NULL, 0); + if (obj->type != OBJ_COMMIT) + return NULL; + + /* Do we have HEAD? */ + if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_sha1, NULL)) + return NULL; + head_commit = lookup_commit_reference_gently(head_sha1, 1); + if (!head_commit) + return NULL; + + /* Turn "ONE" into "ONE..HEAD" then */ + obj->flags |= UNINTERESTING; + add_pending_object(sb->revs, &head_commit->object, "HEAD"); + + sb->final = (struct commit *)obj; + return sb->revs->pending.objects[0].name; +} + static char *prepare_initial(struct scoreboard *sb) { int i; @@ -2472,14 +2509,17 @@ static char *prepare_initial(struct scoreboard *sb) if (obj->type != OBJ_COMMIT) die("Non commit %s?", revs->pending.objects[i].name); if (sb->final) - die("More than one commit to dig down to %s and %s?", + die("More than one commit to dig up from, %s and %s?", revs->pending.objects[i].name, final_commit_name); sb->final = (struct commit *) obj; final_commit_name = revs->pending.objects[i].name; } + + if (!final_commit_name) + final_commit_name = dwim_reverse_initial(sb); if (!final_commit_name) - die("No commit to dig down to?"); + die("No commit to dig up from?"); return xstrdup(final_commit_name); } @@ -2550,6 +2590,15 @@ int cmd_blame(int argc, const char **argv, const char *prefix) OPT_BIT('s', NULL, &output_option, N_("Suppress author name and timestamp (Default: off)"), OUTPUT_NO_AUTHOR), OPT_BIT('e', "show-email", &output_option, N_("Show author email instead of name (Default: off)"), OUTPUT_SHOW_EMAIL), OPT_BIT('w', NULL, &xdl_opts, N_("Ignore whitespace differences"), XDF_IGNORE_WHITESPACE), + + /* + * The following two options are parsed by parse_revision_opt() + * and are only included here to get included in the "-h" + * output: + */ + { OPTION_LOWLEVEL_CALLBACK, 0, "indent-heuristic", NULL, NULL, N_("Use an experimental indent-based heuristic to improve diffs"), PARSE_OPT_NOARG, parse_opt_unknown_cb }, + { OPTION_LOWLEVEL_CALLBACK, 0, "compaction-heuristic", NULL, NULL, N_("Use an experimental blank-line-based heuristic to improve diffs"), PARSE_OPT_NOARG, parse_opt_unknown_cb }, + OPT_BIT(0, "minimal", &xdl_opts, N_("Spend extra cycles to find better match"), XDF_NEED_MINIMAL), OPT_STRING('S', NULL, &revs_file, N_("file"), N_("Use revisions from instead of calling git-rev-list")), OPT_STRING(0, "contents", &contents_from, N_("file"), N_("Use 's contents as the final image")), @@ -2596,12 +2645,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix) } parse_done: no_whole_file_rename = !DIFF_OPT_TST(&revs.diffopt, FOLLOW_RENAMES); + xdl_opts |= revs.diffopt.xdl_opts & (XDF_COMPACTION_HEURISTIC | XDF_INDENT_HEURISTIC); DIFF_OPT_CLR(&revs.diffopt, FOLLOW_RENAMES); argc = parse_options_end(&ctx); if (incremental || (output_option & OUTPUT_PORCELAIN)) { if (show_progress > 0) - die("--progress can't be used with --incremental or porcelain formats"); + die(_("--progress can't be used with --incremental or porcelain formats")); show_progress = 0; } else if (show_progress < 0) show_progress = isatty(2); @@ -2727,7 +2777,7 @@ parse_done: sb.commits.compare = compare_commits_by_commit_date; } else if (contents_from) - die("--contents and --reverse do not blend well."); + die(_("--contents and --reverse do not blend well.")); else { final_commit_name = prepare_initial(&sb); sb.commits.compare = compare_commits_by_reverse_commit_date; @@ -2747,12 +2797,12 @@ parse_done: add_pending_object(&revs, &(sb.final->object), ":"); } else if (contents_from) - die("Cannot use --contents with final commit object name"); + die(_("cannot use --contents with final commit object name")); if (reverse && revs.first_parent_only) { final_commit = find_single_final(sb.revs, NULL); if (!final_commit) - die("--reverse and --first-parent together require specified latest commit"); + die(_("--reverse and --first-parent together require specified latest commit")); } /* @@ -2779,7 +2829,7 @@ parse_done: } if (oidcmp(&c->object.oid, &sb.final->object.oid)) - die("--reverse --first-parent together require range along first-parent chain"); + die(_("--reverse --first-parent together require range along first-parent chain")); } if (is_null_oid(&sb.final->object.oid)) { @@ -2790,19 +2840,19 @@ parse_done: else { o = get_origin(&sb, sb.final, path); if (fill_blob_sha1_and_mode(o)) - die("no such path %s in %s", path, final_commit_name); + die(_("no such path %s in %s"), path, final_commit_name); if (DIFF_OPT_TST(&sb.revs->diffopt, ALLOW_TEXTCONV) && - textconv_object(path, o->mode, o->blob_sha1, 1, (char **) &sb.final_buf, + textconv_object(path, o->mode, &o->blob_oid, 1, (char **) &sb.final_buf, &sb.final_buf_size)) ; else - sb.final_buf = read_sha1_file(o->blob_sha1, &type, + sb.final_buf = read_sha1_file(o->blob_oid.hash, &type, &sb.final_buf_size); if (!sb.final_buf) - die("Cannot read blob %s for path %s", - sha1_to_hex(o->blob_sha1), + die(_("cannot read blob %s for path %s"), + oid_to_hex(&o->blob_oid), path); } num_read_blob++; @@ -2820,7 +2870,9 @@ parse_done: &bottom, &top, sb.path)) usage(blame_usage); if (lno < top || ((lno || bottom) && lno < bottom)) - die("file %s has only %lu lines", path, lno); + die(Q_("file %s has only %lu line", + "file %s has only %lu lines", + lno), path, lno); if (bottom < 1) bottom = 1; if (top < 1) diff --git a/builtin/branch.c b/builtin/branch.c index 6810c3a..60cc5c8 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -657,7 +657,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_SET_INT( 0, "set-upstream", &track, N_("change upstream info"), BRANCH_TRACK_OVERRIDE), 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_BOOL(0, "unset-upstream", &unset_upstream, N_("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"), FILTER_REFS_REMOTES), diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 560f6c2..30383e9 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -17,32 +17,63 @@ struct batch_options { int print_contents; int buffer_output; int all_objects; + int cmdmode; /* may be 'w' or 'c' for --filters or --textconv */ const char *format; }; +static const char *force_path; + +static int filter_object(const char *path, unsigned mode, + const struct object_id *oid, + char **buf, unsigned long *size) +{ + enum object_type type; + + *buf = read_sha1_file(oid->hash, &type, size); + if (!*buf) + return error(_("cannot read object %s '%s'"), + oid_to_hex(oid), path); + if ((type == OBJ_BLOB) && S_ISREG(mode)) { + struct strbuf strbuf = STRBUF_INIT; + if (convert_to_working_tree(path, *buf, *size, &strbuf)) { + free(*buf); + *size = strbuf.len; + *buf = strbuf_detach(&strbuf, NULL); + } + } + + return 0; +} + static int cat_one_file(int opt, const char *exp_type, const char *obj_name, int unknown_type) { - unsigned char sha1[20]; + struct object_id oid; enum object_type type; char *buf; unsigned long size; struct object_context obj_context; - struct object_info oi = {NULL}; + struct object_info oi = OBJECT_INFO_INIT; struct strbuf sb = STRBUF_INIT; unsigned flags = LOOKUP_REPLACE_OBJECT; + const char *path = force_path; if (unknown_type) flags |= LOOKUP_UNKNOWN_OBJECT; - if (get_sha1_with_context(obj_name, 0, sha1, &obj_context)) + if (get_sha1_with_context(obj_name, 0, oid.hash, &obj_context)) die("Not a valid object name %s", obj_name); + if (!path) + path = obj_context.path; + if (obj_context.mode == S_IFINVALID) + obj_context.mode = 0100644; + buf = NULL; switch (opt) { case 't': oi.typename = &sb; - if (sha1_object_info_extended(sha1, &oi, flags) < 0) + if (sha1_object_info_extended(oid.hash, &oi, flags) < 0) die("git cat-file: could not get object info"); if (sb.len) { printf("%s\n", sb.buf); @@ -53,24 +84,34 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, case 's': oi.sizep = &size; - if (sha1_object_info_extended(sha1, &oi, flags) < 0) + if (sha1_object_info_extended(oid.hash, &oi, flags) < 0) die("git cat-file: could not get object info"); printf("%lu\n", size); return 0; case 'e': - return !has_sha1_file(sha1); + return !has_object_file(&oid); + + case 'w': + if (!path[0]) + die("git cat-file --filters %s: must be " + "", obj_name); + + if (filter_object(path, obj_context.mode, + &oid, &buf, &size)) + return -1; + break; case 'c': - if (!obj_context.path[0]) + if (!path[0]) die("git cat-file --textconv %s: must be ", obj_name); - if (textconv_object(obj_context.path, obj_context.mode, sha1, 1, &buf, &size)) + if (textconv_object(path, obj_context.mode, &oid, 1, &buf, &size)) break; case 'p': - type = sha1_object_info(sha1, NULL); + type = sha1_object_info(oid.hash, NULL); if (type < 0) die("Not a valid object name %s", obj_name); @@ -83,8 +124,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, } if (type == OBJ_BLOB) - return stream_blob_to_fd(1, sha1, NULL, 0); - buf = read_sha1_file(sha1, &type, &size); + return stream_blob_to_fd(1, &oid, NULL, 0); + buf = read_sha1_file(oid.hash, &type, &size); if (!buf) die("Cannot read object %s", obj_name); @@ -93,19 +134,19 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, case 0: if (type_from_string(exp_type) == OBJ_BLOB) { - unsigned char blob_sha1[20]; - if (sha1_object_info(sha1, NULL) == OBJ_TAG) { - char *buffer = read_sha1_file(sha1, &type, &size); + struct object_id blob_oid; + if (sha1_object_info(oid.hash, NULL) == OBJ_TAG) { + char *buffer = read_sha1_file(oid.hash, &type, &size); const char *target; if (!skip_prefix(buffer, "object ", &target) || - get_sha1_hex(target, blob_sha1)) - die("%s not a valid tag", sha1_to_hex(sha1)); + get_oid_hex(target, &blob_oid)) + die("%s not a valid tag", oid_to_hex(&oid)); free(buffer); } else - hashcpy(blob_sha1, sha1); + oidcpy(&blob_oid, &oid); - if (sha1_object_info(blob_sha1, NULL) == OBJ_BLOB) - return stream_blob_to_fd(1, blob_sha1, NULL, 0); + if (sha1_object_info(blob_oid.hash, NULL) == OBJ_BLOB) + return stream_blob_to_fd(1, &blob_oid, NULL, 0); /* * we attempted to dereference a tag to a blob * and failed; there may be new dereference @@ -113,7 +154,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, * fall-back to the usual case. */ } - buf = read_object_with_reference(sha1, exp_type, &size, NULL); + buf = read_object_with_reference(oid.hash, exp_type, &size, NULL); break; default: @@ -128,12 +169,12 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, } struct expand_data { - unsigned char sha1[20]; + struct object_id oid; enum object_type type; unsigned long size; off_t disk_size; const char *rest; - unsigned char delta_base_sha1[20]; + struct object_id delta_base_oid; /* * If mark_query is true, we do not expand anything, but rather @@ -176,7 +217,7 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len, if (is_atom("objectname", atom, len)) { if (!data->mark_query) - strbuf_addstr(sb, sha1_to_hex(data->sha1)); + strbuf_addstr(sb, oid_to_hex(&data->oid)); } else if (is_atom("objecttype", atom, len)) { if (data->mark_query) data->info.typep = &data->type; @@ -199,9 +240,10 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len, strbuf_addstr(sb, data->rest); } else if (is_atom("deltabase", atom, len)) { if (data->mark_query) - data->info.delta_base_sha1 = data->delta_base_sha1; + data->info.delta_base_sha1 = data->delta_base_oid.hash; else - strbuf_addstr(sb, sha1_to_hex(data->delta_base_sha1)); + strbuf_addstr(sb, + oid_to_hex(&data->delta_base_oid)); } else die("unknown format element: %.*s", len, atom); } @@ -232,28 +274,53 @@ static void batch_write(struct batch_options *opt, const void *data, int len) static void print_object_or_die(struct batch_options *opt, struct expand_data *data) { - const unsigned char *sha1 = data->sha1; + const struct object_id *oid = &data->oid; assert(data->info.typep); if (data->type == OBJ_BLOB) { if (opt->buffer_output) fflush(stdout); - if (stream_blob_to_fd(1, sha1, NULL, 0) < 0) - die("unable to stream %s to stdout", sha1_to_hex(sha1)); + if (opt->cmdmode) { + char *contents; + unsigned long size; + + if (!data->rest) + die("missing path for '%s'", oid_to_hex(oid)); + + if (opt->cmdmode == 'w') { + if (filter_object(data->rest, 0100644, oid, + &contents, &size)) + die("could not convert '%s' %s", + oid_to_hex(oid), data->rest); + } else if (opt->cmdmode == 'c') { + enum object_type type; + if (!textconv_object(data->rest, 0100644, oid, + 1, &contents, &size)) + contents = read_sha1_file(oid->hash, &type, + &size); + if (!contents) + die("could not convert '%s' %s", + oid_to_hex(oid), data->rest); + } else + die("BUG: invalid cmdmode: %c", opt->cmdmode); + batch_write(opt, contents, size); + free(contents); + } else if (stream_blob_to_fd(1, oid, NULL, 0) < 0) + die("unable to stream %s to stdout", oid_to_hex(oid)); } else { enum object_type type; unsigned long size; void *contents; - contents = read_sha1_file(sha1, &type, &size); + contents = read_sha1_file(oid->hash, &type, &size); if (!contents) - die("object %s disappeared", sha1_to_hex(sha1)); + die("object %s disappeared", oid_to_hex(oid)); if (type != data->type) - die("object %s changed type!?", sha1_to_hex(sha1)); + die("object %s changed type!?", oid_to_hex(oid)); if (data->info.sizep && size != data->size) - die("object %s changed size!?", sha1_to_hex(sha1)); + die("object %s changed size!?", oid_to_hex(oid)); batch_write(opt, contents, size); free(contents); @@ -266,8 +333,9 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt, struct strbuf buf = STRBUF_INIT; 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)); + sha1_object_info_extended(data->oid.hash, &data->info, LOOKUP_REPLACE_OBJECT) < 0) { + printf("%s missing\n", + obj_name ? obj_name : oid_to_hex(&data->oid)); fflush(stdout); return; } @@ -290,7 +358,7 @@ static void batch_one_object(const char *obj_name, struct batch_options *opt, int flags = opt->follow_symlinks ? GET_SHA1_FOLLOW_SYMLINKS : 0; enum follow_symlinks_result result; - result = get_sha1_with_context(obj_name, flags, data->sha1, &ctx); + result = get_sha1_with_context(obj_name, flags, data->oid.hash, &ctx); if (result != FOUND) { switch (result) { case MISSING_OBJECT: @@ -333,11 +401,12 @@ struct object_cb_data { struct expand_data *expand; }; -static void batch_object_cb(const unsigned char sha1[20], void *vdata) +static int batch_object_cb(const unsigned char sha1[20], void *vdata) { struct object_cb_data *data = vdata; - hashcpy(data->expand->sha1, sha1); + hashcpy(data->expand->oid.hash, sha1); batch_object_write(NULL, data->opt, data->expand); + return 0; } static int batch_loose_object(const unsigned char *sha1, @@ -376,10 +445,11 @@ static int batch_objects(struct batch_options *opt) data.mark_query = 1; strbuf_expand(&buf, opt->format, expand_format, &data); data.mark_query = 0; + if (opt->cmdmode) + data.split_on_whitespace = 1; if (opt->all_objects) { - struct object_info empty; - memset(&empty, 0, sizeof(empty)); + struct object_info empty = OBJECT_INFO_INIT; if (!memcmp(&data.info, &empty, sizeof(empty))) data.skip_object_info = 1; } @@ -440,8 +510,8 @@ static int batch_objects(struct batch_options *opt) } static const char * const cat_file_usage[] = { - N_("git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e | -p | | --textconv) "), - N_("git cat-file (--batch | --batch-check) [--follow-symlinks]"), + N_("git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e | -p | | --textconv | --filters) [--path=] "), + N_("git cat-file (--batch | --batch-check) [--follow-symlinks] [--textconv | --filters]"), NULL }; @@ -486,6 +556,10 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) OPT_CMDMODE('p', NULL, &opt, N_("pretty-print object's content"), 'p'), OPT_CMDMODE(0, "textconv", &opt, N_("for blob objects, run textconv on object's content"), 'c'), + OPT_CMDMODE(0, "filters", &opt, + N_("for blob objects, run filters on object's content"), 'w'), + OPT_STRING(0, "path", &force_path, N_("blob"), + N_("use a specific path for --textconv/--filters")), OPT_BOOL(0, "allow-unknown-type", &unknown_type, N_("allow -s and -t to work with broken/corrupt objects")), OPT_BOOL(0, "buffer", &batch.buffer_output, N_("buffer --batch output")), @@ -508,7 +582,9 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, cat_file_usage, 0); if (opt) { - if (argc == 1) + if (batch.enabled && (opt == 'c' || opt == 'w')) + batch.cmdmode = opt; + else if (argc == 1) obj_name = argv[0]; else usage_with_options(cat_file_usage, options); @@ -520,14 +596,28 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) } else usage_with_options(cat_file_usage, options); } - if (batch.enabled && (opt || argc)) { - usage_with_options(cat_file_usage, options); + if (batch.enabled) { + if (batch.cmdmode != opt || argc) + usage_with_options(cat_file_usage, options); + if (batch.cmdmode && batch.all_objects) + die("--batch-all-objects cannot be combined with " + "--textconv nor with --filters"); } if ((batch.follow_symlinks || batch.all_objects) && !batch.enabled) { usage_with_options(cat_file_usage, options); } + if (force_path && opt != 'c' && opt != 'w') { + error("--path= needs --textconv or --filters"); + usage_with_options(cat_file_usage, options); + } + + if (force_path && batch.enabled) { + error("--path= incompatible with --batch"); + usage_with_options(cat_file_usage, options); + } + if (batch.buffer_output < 0) batch.buffer_output = batch.all_objects; diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index 92c6967..30a49d9 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -16,7 +16,7 @@ static int checkout_stage; /* default to checkout stage0 */ static int to_tempfile; static char topath[4][TEMPORARY_FILENAME_LENGTH + 1]; -static struct checkout state; +static struct checkout state = CHECKOUT_INIT; static void write_tempfile_record(const char *name, const char *prefix) { diff --git a/builtin/checkout.c b/builtin/checkout.c index 899bd8d..512492a 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -76,7 +76,7 @@ static int update_some(const unsigned char *sha1, struct strbuf *base, len = base->len + strlen(pathname); ce = xcalloc(1, cache_entry_size(len)); - hashcpy(ce->sha1, sha1); + hashcpy(ce->oid.hash, sha1); memcpy(ce->name, base->buf, base->len); memcpy(ce->name + base->len, pathname, len - base->len); ce->ce_flags = create_ce_flags(0) | CE_UPDATE; @@ -92,7 +92,7 @@ static int update_some(const unsigned char *sha1, struct strbuf *base, if (pos >= 0) { struct cache_entry *old = active_cache[pos]; if (ce->ce_mode == old->ce_mode && - !hashcmp(ce->sha1, old->sha1)) { + !oidcmp(&ce->oid, &old->oid)) { old->ce_flags |= CE_UPDATE; free(ce); return 0; @@ -175,9 +175,9 @@ static int checkout_merged(int pos, const struct checkout *state) const char *path = ce->name; mmfile_t ancestor, ours, theirs; int status; - unsigned char sha1[20]; + struct object_id oid; mmbuffer_t result_buf; - unsigned char threeway[3][20]; + struct object_id threeway[3]; unsigned mode = 0; memset(threeway, 0, sizeof(threeway)); @@ -186,18 +186,18 @@ static int checkout_merged(int pos, const struct checkout *state) stage = ce_stage(ce); if (!stage || strcmp(path, ce->name)) break; - hashcpy(threeway[stage - 1], ce->sha1); + oidcpy(&threeway[stage - 1], &ce->oid); if (stage == 2) mode = create_ce_mode(ce->ce_mode); pos++; ce = active_cache[pos]; } - if (is_null_sha1(threeway[1]) || is_null_sha1(threeway[2])) + if (is_null_oid(&threeway[1]) || is_null_oid(&threeway[2])) return error(_("path '%s' does not have necessary versions"), path); - read_mmblob(&ancestor, threeway[0]); - read_mmblob(&ours, threeway[1]); - read_mmblob(&theirs, threeway[2]); + read_mmblob(&ancestor, &threeway[0]); + read_mmblob(&ours, &threeway[1]); + read_mmblob(&theirs, &threeway[2]); /* * NEEDSWORK: re-create conflicts from merges with @@ -226,9 +226,9 @@ static int checkout_merged(int pos, const struct checkout *state) * object database even when it may contain conflicts). */ if (write_sha1_file(result_buf.ptr, result_buf.size, - blob_type, sha1)) + blob_type, oid.hash)) die(_("Unable to add merge result for '%s'"), path); - ce = make_cache_entry(mode, sha1, path, 2, 0); + ce = make_cache_entry(mode, oid.hash, path, 2, 0); if (!ce) die(_("make_cache_entry failed for path '%s'"), path); status = checkout_entry(ce, state, NULL); @@ -239,9 +239,9 @@ static int checkout_paths(const struct checkout_opts *opts, const char *revision) { int pos; - struct checkout state; + struct checkout state = CHECKOUT_INIT; static char *ps_matched; - unsigned char rev[20]; + struct object_id rev; struct commit *head; int errs = 0; struct lock_file *lock_file; @@ -352,7 +352,6 @@ static int checkout_paths(const struct checkout_opts *opts, return 1; /* Now we are committed to check them out */ - memset(&state, 0, sizeof(state)); state.force = 1; state.refresh_cache = 1; state.istate = &the_index; @@ -374,8 +373,8 @@ 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, NULL); - head = lookup_commit_reference_gently(rev, 1); + read_ref_full("HEAD", 0, rev.hash, NULL); + head = lookup_commit_reference_gently(rev.hash, 1); errs |= post_checkout_hook(head, head, 0); return errs; @@ -808,11 +807,11 @@ static int switch_branches(const struct checkout_opts *opts, int ret = 0; struct branch_info old; void *path_to_free; - unsigned char rev[20]; + struct object_id rev; int flag, writeout_error = 0; memset(&old, 0, sizeof(old)); - old.path = path_to_free = resolve_refdup("HEAD", 0, rev, &flag); - old.commit = lookup_commit_reference_gently(rev, 1); + old.path = path_to_free = resolve_refdup("HEAD", 0, rev.hash, &flag); + old.commit = lookup_commit_reference_gently(rev.hash, 1); if (!(flag & REF_ISSYMREF)) old.path = NULL; @@ -860,7 +859,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb) struct tracking_name_data { /* const */ char *src_ref; char *dst_ref; - unsigned char *dst_sha1; + struct object_id *dst_oid; int unique; }; @@ -871,7 +870,7 @@ static int check_tracking_name(struct remote *remote, void *cb_data) memset(&query, 0, sizeof(struct refspec)); query.src = cb->src_ref; if (remote_find_tracking(remote, &query) || - get_sha1(query.dst, cb->dst_sha1)) { + get_oid(query.dst, cb->dst_oid)) { free(query.dst); return 0; } @@ -884,13 +883,13 @@ static int check_tracking_name(struct remote *remote, void *cb_data) return 0; } -static const char *unique_tracking_name(const char *name, unsigned char *sha1) +static const char *unique_tracking_name(const char *name, struct object_id *oid) { struct tracking_name_data cb_data = { NULL, NULL, NULL, 1 }; char src_ref[PATH_MAX]; snprintf(src_ref, PATH_MAX, "refs/heads/%s", name); cb_data.src_ref = src_ref; - cb_data.dst_sha1 = sha1; + cb_data.dst_oid = oid; for_each_remote(check_tracking_name, &cb_data); if (cb_data.unique) return cb_data.dst_ref; @@ -902,12 +901,12 @@ static int parse_branchname_arg(int argc, const char **argv, int dwim_new_local_branch_ok, struct branch_info *new, struct checkout_opts *opts, - unsigned char rev[20]) + struct object_id *rev) { struct tree **source_tree = &opts->source_tree; const char **new_branch = &opts->new_branch; int argcount = 0; - unsigned char branch_rev[20]; + struct object_id branch_rev; const char *arg; int dash_dash_pos; int has_dash_dash = 0; @@ -973,7 +972,7 @@ static int parse_branchname_arg(int argc, const char **argv, if (!strcmp(arg, "-")) arg = "@{-1}"; - if (get_sha1_mb(arg, rev)) { + if (get_oid_mb(arg, rev)) { /* * Either case (3) or (4), with not being * a commit, or an attempt to use case (1) with an @@ -1022,15 +1021,15 @@ static int parse_branchname_arg(int argc, const char **argv, setup_branch_path(new); if (!check_refname_format(new->path, 0) && - !read_ref(new->path, branch_rev)) - hashcpy(rev, branch_rev); + !read_ref(new->path, branch_rev.hash)) + oidcpy(rev, &branch_rev); else new->path = NULL; /* not an existing branch */ - new->commit = lookup_commit_reference_gently(rev, 1); + new->commit = lookup_commit_reference_gently(rev->hash, 1); if (!new->commit) { /* not a commit */ - *source_tree = parse_tree_indirect(rev); + *source_tree = parse_tree_indirect(rev->hash); } else { parse_commit_or_die(new->commit); *source_tree = new->commit->tree; @@ -1108,9 +1107,9 @@ static int checkout_branch(struct checkout_opts *opts, if (new->path && !opts->force_detach && !opts->new_branch && !opts->ignore_other_worktrees) { - unsigned char sha1[20]; + struct object_id oid; int flag; - char *head_ref = resolve_refdup("HEAD", 0, sha1, &flag); + char *head_ref = resolve_refdup("HEAD", 0, oid.hash, &flag); if (head_ref && (!(flag & REF_ISSYMREF) || strcmp(head_ref, new->path))) die_if_checked_out(new->path, 1); @@ -1118,11 +1117,11 @@ static int checkout_branch(struct checkout_opts *opts, } if (!new->commit && opts->new_branch) { - unsigned char rev[20]; + struct object_id rev; int flag; - if (!read_ref_full("HEAD", 0, rev, &flag) && - (flag & REF_ISSYMREF) && is_null_sha1(rev)) + if (!read_ref_full("HEAD", 0, rev.hash, &flag) && + (flag & REF_ISSYMREF) && is_null_oid(&rev)) return switch_unborn_to_new_branch(opts); } return switch_branches(opts, new); @@ -1232,14 +1231,14 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) * remote branches, erroring out for invalid or ambiguous cases. */ if (argc) { - unsigned char rev[20]; + struct object_id rev; int dwim_ok = !opts.patch_mode && dwim_new_local_branch && opts.track == BRANCH_TRACK_UNSPECIFIED && !opts.new_branch; int n = parse_branchname_arg(argc, argv, dwim_ok, - &new, &opts, rev); + &new, &opts, &rev); argv += n; argc -= n; } diff --git a/builtin/clone.c b/builtin/clone.c index a35d622..6c76a6e 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -41,16 +41,19 @@ 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; -static char *option_template, *option_depth; +static int deepen; +static char *option_template, *option_depth, *option_since; static char *option_origin = NULL; static char *option_branch = NULL; +static struct string_list option_not = STRING_LIST_INIT_NODUP; static const char *real_git_dir; static char *option_upload_pack = "git-upload-pack"; static int option_verbosity; static int option_progress = -1; static enum transport_family family; static struct string_list option_config = STRING_LIST_INIT_NODUP; -static struct string_list option_reference = STRING_LIST_INIT_NODUP; +static struct string_list option_required_reference = STRING_LIST_INIT_NODUP; +static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP; static int option_dissociate; static int max_jobs = -1; @@ -79,8 +82,10 @@ static struct option builtin_clone_options[] = { 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"), + OPT_STRING_LIST(0, "reference", &option_required_reference, N_("repo"), N_("reference repository")), + OPT_STRING_LIST(0, "reference-if-able", &option_optional_reference, + N_("repo"), N_("reference repository")), OPT_BOOL(0, "dissociate", &option_dissociate, N_("use --reference only while cloning")), OPT_STRING('o', "origin", &option_origin, N_("name"), @@ -91,6 +96,10 @@ static struct option builtin_clone_options[] = { N_("path to git-upload-pack on the remote")), OPT_STRING(0, "depth", &option_depth, N_("depth"), N_("create a shallow clone of that depth")), + OPT_STRING(0, "shallow-since", &option_since, N_("time"), + N_("create a shallow clone since a specific time")), + OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("revision"), + N_("deepen history of shallow clone by excluding rev")), OPT_BOOL(0, "single-branch", &option_single_branch, N_("clone only one branch, HEAD or --branch")), OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules, @@ -282,50 +291,37 @@ static void strip_trailing_slashes(char *dir) static int add_one_reference(struct string_list_item *item, void *cb_data) { - char *ref_git; - const char *repo; - struct strbuf alternate = STRBUF_INIT; - - /* Beware: read_gitfile(), real_path() and mkpath() return static buffer */ - ref_git = xstrdup(real_path(item->string)); - - repo = read_gitfile(ref_git); - if (!repo) - repo = read_gitfile(mkpath("%s/.git", ref_git)); - if (repo) { - free(ref_git); - ref_git = xstrdup(repo); - } + struct strbuf err = STRBUF_INIT; + int *required = cb_data; + char *ref_git = compute_alternate_path(item->string, &err); - if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) { - char *ref_git_git = mkpathdup("%s/.git", ref_git); - free(ref_git); - ref_git = ref_git_git; - } else if (!is_directory(mkpath("%s/objects", ref_git))) { + if (!ref_git) { + if (*required) + die("%s", err.buf); + else + fprintf(stderr, + _("info: Could not add alternate for '%s': %s\n"), + item->string, err.buf); + } else { struct strbuf sb = STRBUF_INIT; - if (get_common_dir(&sb, ref_git)) - die(_("reference repository '%s' as a linked checkout is not supported yet."), - item->string); - die(_("reference repository '%s' is not a local repository."), - item->string); + strbuf_addf(&sb, "%s/objects", ref_git); + add_to_alternates_file(sb.buf); + strbuf_release(&sb); } - if (!access(mkpath("%s/shallow", ref_git), F_OK)) - die(_("reference repository '%s' is shallow"), item->string); - - if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) - die(_("reference repository '%s' is grafted"), item->string); - - strbuf_addf(&alternate, "%s/objects", ref_git); - add_to_alternates_file(alternate.buf); - strbuf_release(&alternate); + strbuf_release(&err); free(ref_git); return 0; } static void setup_reference(void) { - for_each_string_list(&option_reference, add_one_reference, NULL); + int required = 1; + for_each_string_list(&option_required_reference, + add_one_reference, &required); + required = 0; + for_each_string_list(&option_optional_reference, + add_one_reference, &required); } static void copy_alternates(struct strbuf *src, struct strbuf *dst, @@ -683,7 +679,7 @@ static void update_head(const struct ref *our, const struct ref *remote, } } -static int checkout(void) +static int checkout(int submodule_progress) { unsigned char sha1[20]; char *head; @@ -747,6 +743,9 @@ static int checkout(void) if (max_jobs != -1) argv_array_pushf(&args, "--jobs=%d", max_jobs); + if (submodule_progress) + argv_array_push(&args, "--progress"); + err = run_command_v_opt(args.argv, RUN_GIT_CMD); argv_array_clear(&args); } @@ -854,6 +853,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) const char *src_ref_prefix = "refs/heads/"; struct remote *remote; int err = 0, complete_refs_before_fetch = 1; + int submodule_progress; struct refspec *refspec; const char *fetch_pattern; @@ -870,8 +870,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix) usage_msg_opt(_("You must specify a repository to clone."), builtin_clone_usage, builtin_clone_options); + if (option_depth || option_since || option_not.nr) + deepen = 1; if (option_single_branch == -1) - option_single_branch = option_depth ? 1 : 0; + option_single_branch = deepen ? 1 : 0; if (option_mirror) option_bare = 1; @@ -944,23 +946,40 @@ int cmd_clone(int argc, const char **argv, const char *prefix) set_git_work_tree(work_tree); } - junk_git_dir = git_dir; + junk_git_dir = real_git_dir ? real_git_dir : git_dir; if (safe_create_leading_directories_const(git_dir) < 0) die(_("could not create leading directories of '%s'"), git_dir); - set_git_dir_init(git_dir, real_git_dir, 0); - if (real_git_dir) { - git_dir = real_git_dir; - junk_git_dir = real_git_dir; - } - if (0 <= option_verbosity) { if (option_bare) fprintf(stderr, _("Cloning into bare repository '%s'...\n"), dir); else fprintf(stderr, _("Cloning into '%s'...\n"), dir); } - init_db(option_template, INIT_DB_QUIET); + + if (option_recursive) { + if (option_required_reference.nr && + option_optional_reference.nr) + die(_("clone --recursive is not compatible with " + "both --reference and --reference-if-able")); + else if (option_required_reference.nr) { + string_list_append(&option_config, + "submodule.alternateLocation=superproject"); + string_list_append(&option_config, + "submodule.alternateErrorStrategy=die"); + } else if (option_optional_reference.nr) { + string_list_append(&option_config, + "submodule.alternateLocation=superproject"); + string_list_append(&option_config, + "submodule.alternateErrorStrategy=info"); + } + } + + init_db(git_dir, real_git_dir, option_template, INIT_DB_QUIET); + + if (real_git_dir) + git_dir = real_git_dir; + write_config(&option_config); git_config(git_default_config, NULL); @@ -980,7 +999,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) git_config_set(key.buf, repo); strbuf_reset(&key); - if (option_reference.nr) + if (option_required_reference.nr || option_optional_reference.nr) setup_reference(); fetch_pattern = value.buf; @@ -998,6 +1017,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (is_local) { if (option_depth) warning(_("--depth is ignored in local clones; use file:// instead.")); + if (option_since) + warning(_("--shallow-since is ignored in local clones; use file:// instead.")); + if (option_not.nr) + warning(_("--shallow-exclude is ignored in local clones; use file:// instead.")); if (!access(mkpath("%s/shallow", path), F_OK)) { if (option_local > 0) warning(_("source repository is shallow, ignoring --local")); @@ -1016,6 +1039,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (option_depth) transport_set_option(transport, TRANS_OPT_DEPTH, option_depth); + if (option_since) + transport_set_option(transport, TRANS_OPT_DEEPEN_SINCE, + option_since); + if (option_not.nr) + transport_set_option(transport, TRANS_OPT_DEEPEN_NOT, + (const char *)&option_not); if (option_single_branch) transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1"); @@ -1023,7 +1052,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) transport_set_option(transport, TRANS_OPT_UPLOADPACK, option_upload_pack); - if (transport->smart_options && !option_depth) + if (transport->smart_options && !deepen) transport->smart_options->check_self_contained_and_connected = 1; refs = transport_get_remote_refs(transport); @@ -1093,6 +1122,14 @@ int cmd_clone(int argc, const char **argv, const char *prefix) update_head(our_head_points_at, remote_head, reflog_msg.buf); + /* + * We want to show progress for recursive submodule clones iff + * we did so for the main clone. But only the transport knows + * the final decision for this flag, so we need to rescue the value + * before we free the transport. + */ + submodule_progress = transport->progress; + transport_unlock_pack(transport); transport_disconnect(transport); @@ -1102,7 +1139,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) } junk_mode = JUNK_LEAVE_REPO; - err = checkout(); + err = checkout(submodule_progress); strbuf_release(&reflog_msg); strbuf_release(&branch_top); diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index 8a674bc..6050172 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -40,8 +40,8 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) { int i, got_tree = 0; struct commit_list *parents = NULL; - unsigned char tree_sha1[20]; - unsigned char commit_sha1[20]; + struct object_id tree_oid; + struct object_id commit_oid; struct strbuf buffer = STRBUF_INIT; git_config(commit_tree_config, NULL); @@ -52,13 +52,13 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "-p")) { - unsigned char sha1[20]; + struct object_id oid; if (argc <= ++i) usage(commit_tree_usage); - if (get_sha1_commit(argv[i], sha1)) + if (get_sha1_commit(argv[i], oid.hash)) die("Not a valid object name %s", argv[i]); - assert_sha1_type(sha1, OBJ_COMMIT); - new_parent(lookup_commit(sha1), &parents); + assert_sha1_type(oid.hash, OBJ_COMMIT); + new_parent(lookup_commit(oid.hash), &parents); continue; } @@ -105,7 +105,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) continue; } - if (get_sha1_tree(arg, tree_sha1)) + if (get_sha1_tree(arg, tree_oid.hash)) die("Not a valid object name %s", arg); if (got_tree) die("Cannot give more than one trees"); @@ -117,13 +117,13 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) die_errno("git commit-tree: failed to read"); } - if (commit_tree(buffer.buf, buffer.len, tree_sha1, parents, - commit_sha1, NULL, sign_commit)) { + if (commit_tree(buffer.buf, buffer.len, tree_oid.hash, parents, + commit_oid.hash, NULL, sign_commit)) { strbuf_release(&buffer); return 1; } - printf("%s\n", sha1_to_hex(commit_sha1)); + printf("%s\n", oid_to_hex(&commit_oid)); strbuf_release(&buffer); return 0; } diff --git a/builtin/commit.c b/builtin/commit.c index 63a8424..8976c3d 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -142,14 +142,24 @@ static int show_ignored_in_status, have_option_m; static const char *only_include_assumed; static struct strbuf message = STRBUF_INIT; -static enum status_format { - STATUS_FORMAT_NONE = 0, - STATUS_FORMAT_LONG, - STATUS_FORMAT_SHORT, - STATUS_FORMAT_PORCELAIN, +static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED; - STATUS_FORMAT_UNSPECIFIED -} status_format = STATUS_FORMAT_UNSPECIFIED; +static int opt_parse_porcelain(const struct option *opt, const char *arg, int unset) +{ + enum wt_status_format *value = (enum wt_status_format *)opt->value; + if (unset) + *value = STATUS_FORMAT_NONE; + else if (!arg) + *value = STATUS_FORMAT_PORCELAIN; + else if (!strcmp(arg, "v1") || !strcmp(arg, "1")) + *value = STATUS_FORMAT_PORCELAIN; + else if (!strcmp(arg, "v2") || !strcmp(arg, "2")) + *value = STATUS_FORMAT_PORCELAIN_V2; + else + die("unsupported porcelain version '%s'", arg); + + return 0; +} static int opt_parse_m(const struct option *opt, const char *arg, int unset) { @@ -173,7 +183,7 @@ static void determine_whence(struct wt_status *s) whence = FROM_MERGE; else if (file_exists(git_path_cherry_pick_head())) { whence = FROM_CHERRY_PICK; - if (file_exists(git_path(SEQ_DIR))) + if (file_exists(git_path_seq_dir())) sequencer_in_use = 1; } else @@ -500,24 +510,13 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int s->fp = fp; s->nowarn = nowarn; s->is_initial = get_sha1(s->reference, sha1) ? 1 : 0; + if (!s->is_initial) + hashcpy(s->sha1_commit, sha1); + s->status_format = status_format; + s->ignore_submodule_arg = ignore_submodule_arg; wt_status_collect(s); - - switch (status_format) { - case STATUS_FORMAT_SHORT: - wt_shortstatus_print(s); - break; - case STATUS_FORMAT_PORCELAIN: - wt_porcelain_print(s); - break; - case STATUS_FORMAT_UNSPECIFIED: - die("BUG: finalize_deferred_config() should have been called"); - break; - case STATUS_FORMAT_NONE: - case STATUS_FORMAT_LONG: - wt_status_print(s); - break; - } + wt_status_print(s); return s->commitable; } @@ -895,9 +894,14 @@ static int prepare_to_commit(const char *index_file, const char *prefix, if (amend) parent = "HEAD^1"; - if (get_sha1(parent, sha1)) - commitable = !!active_nr; - else { + if (get_sha1(parent, sha1)) { + int i, ita_nr = 0; + + for (i = 0; i < active_nr; i++) + if (ce_intent_to_add(active_cache[i])) + ita_nr++; + commitable = active_nr - ita_nr > 0; + } else { /* * Unless the user did explicitly request a submodule * ignore mode by passing a command line option we do @@ -911,7 +915,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, if (ignore_submodule_arg && !strcmp(ignore_submodule_arg, "all")) diff_flags |= DIFF_OPT_IGNORE_SUBMODULES; - commitable = index_differs_from(parent, diff_flags); + commitable = index_differs_from(parent, diff_flags, 1); } } strbuf_release(&committer_ident); @@ -1099,7 +1103,7 @@ static const char *read_commit_message(const char *name) * is not in effect here. */ static struct status_deferred_config { - enum status_format status_format; + enum wt_status_format status_format; int show_branch; } status_deferred_config = { STATUS_FORMAT_UNSPECIFIED, @@ -1109,6 +1113,7 @@ static struct status_deferred_config { static void finalize_deferred_config(struct wt_status *s) { int use_deferred_config = (status_format != STATUS_FORMAT_PORCELAIN && + status_format != STATUS_FORMAT_PORCELAIN_V2 && !s->null_termination); if (s->null_termination) { @@ -1336,9 +1341,9 @@ int cmd_status(int argc, const char **argv, const char *prefix) N_("show status concisely"), STATUS_FORMAT_SHORT), OPT_BOOL('b', "branch", &s.show_branch, N_("show branch information")), - OPT_SET_INT(0, "porcelain", &status_format, - N_("machine-readable output"), - STATUS_FORMAT_PORCELAIN), + { OPTION_CALLBACK, 0, "porcelain", &status_format, + N_("version"), N_("machine-readable output"), + PARSE_OPT_OPTARG, opt_parse_porcelain }, OPT_SET_INT(0, "long", &status_format, N_("show status in long format (default)"), STATUS_FORMAT_LONG), @@ -1380,7 +1385,13 @@ int cmd_status(int argc, const char **argv, const char *prefix) fd = hold_locked_index(&index_lock, 0); s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0; + if (!s.is_initial) + hashcpy(s.sha1_commit, sha1); + s.ignore_submodule_arg = ignore_submodule_arg; + s.status_format = status_format; + s.verbose = verbose; + wt_status_collect(&s); if (0 <= fd) @@ -1389,23 +1400,7 @@ int cmd_status(int argc, const char **argv, const char *prefix) if (s.relative_paths) s.prefix = prefix; - switch (status_format) { - case STATUS_FORMAT_SHORT: - wt_shortstatus_print(&s); - break; - case STATUS_FORMAT_PORCELAIN: - wt_porcelain_print(&s); - break; - case STATUS_FORMAT_UNSPECIFIED: - die("BUG: finalize_deferred_config() should have been called"); - break; - case STATUS_FORMAT_NONE: - case STATUS_FORMAT_LONG: - s.verbose = verbose; - s.ignore_submodule_arg = ignore_submodule_arg; - wt_status_print(&s); - break; - } + wt_status_print(&s); return 0; } diff --git a/builtin/config.c b/builtin/config.c index 6cbf733..05843a0 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -622,8 +622,8 @@ int cmd_config(int argc, const char **argv, const char *prefix) value = normalize_value(argv[0], argv[1]); ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value); if (ret == CONFIG_NOTHING_SET) - error("cannot overwrite multiple values with a single value\n" - " Use a regexp, --add or --replace-all to change %s.", argv[0]); + error(_("cannot overwrite multiple values with a single value\n" + " Use a regexp, --add or --replace-all to change %s."), argv[0]); return ret; } else if (actions == ACTION_SET_ALL) { diff --git a/builtin/count-objects.c b/builtin/count-objects.c index ba92919..a04b4f2 100644 --- a/builtin/count-objects.c +++ b/builtin/count-objects.c @@ -8,6 +8,7 @@ #include "dir.h" #include "builtin.h" #include "parse-options.h" +#include "quote.h" static unsigned long garbage; static off_t size_garbage; @@ -73,6 +74,14 @@ static int count_cruft(const char *basename, const char *path, void *data) return 0; } +static int print_alternate(struct alternate_object_database *alt, void *data) +{ + printf("alternate: "); + quote_c_style(alt->path, NULL, stdout, 0); + putchar('\n'); + return 0; +} + static char const * const count_objects_usage[] = { N_("git count-objects [-v] [-H | --human-readable]"), NULL @@ -88,6 +97,8 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix) OPT_END(), }; + git_config(git_default_config, NULL); + argc = parse_options(argc, argv, prefix, opts, count_objects_usage, 0); /* we do not take arguments other than flags for now */ if (argc) @@ -140,6 +151,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix) printf("prune-packable: %lu\n", packed_loose); printf("garbage: %lu\n", garbage); printf("size-garbage: %s\n", garbage_buf.buf); + foreach_alt_odb(print_alternate, NULL); strbuf_release(&loose_buf); strbuf_release(&pack_buf); strbuf_release(&garbage_buf); diff --git a/builtin/describe.c b/builtin/describe.c index 8a25abe..01490a1 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -352,7 +352,7 @@ static void describe(const char *arg, int last_one) oid_to_hex(oid)); } - qsort(all_matches, match_cnt, sizeof(all_matches[0]), compare_pt); + QSORT(all_matches, match_cnt, compare_pt); if (gave_up_on) { commit_list_insert_by_date(gave_up_on, &list); diff --git a/builtin/diff.c b/builtin/diff.c index b7a9405..7f91f6d 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -301,20 +301,21 @@ int cmd_diff(int argc, const char **argv, const char *prefix) break; } - if (!no_index) - prefix = setup_git_directory_gently(&nongit); + prefix = setup_git_directory_gently(&nongit); - /* - * Treat git diff with at least one path outside of the - * repo the same as if the command would have been executed - * outside of a git repository. In this case it behaves - * the same way as "git diff --no-index ", which acts - * as a colourful "diff" replacement. - */ - if (nongit || ((argc == i + 2) && - (!path_inside_repo(prefix, argv[i]) || - !path_inside_repo(prefix, argv[i + 1])))) - no_index = DIFF_NO_INDEX_IMPLICIT; + if (!no_index) { + /* + * Treat git diff with at least one path outside of the + * repo the same as if the command would have been executed + * outside of a git repository. In this case it behaves + * the same way as "git diff --no-index ", which acts + * as a colourful "diff" replacement. + */ + if (nongit || ((argc == i + 2) && + (!path_inside_repo(prefix, argv[i]) || + !path_inside_repo(prefix, argv[i + 1])))) + no_index = DIFF_NO_INDEX_IMPLICIT; + } if (!no_index) gitmodules_config(); diff --git a/builtin/fast-export.c b/builtin/fast-export.c index c0652a7..1e815b5 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -347,7 +347,7 @@ static void show_filemodify(struct diff_queue_struct *q, * Handle files below a directory first, in case they are all deleted * and the directory changes to a file or symlink. */ - qsort(q->queue, q->nr, sizeof(q->queue[0]), depth_first); + QSORT(q->queue, q->nr, depth_first); for (i = 0; i < q->nr; i++) { struct diff_filespec *ospec = q->queue[i]->one; diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index bfd0be4..cfe9e44 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -51,6 +51,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) struct child_process *conn; struct fetch_pack_args args; struct sha1_array shallow = SHA1_ARRAY_INIT; + struct string_list deepen_not = STRING_LIST_INIT_DUP; packet_trace_identity("fetch-pack"); @@ -60,12 +61,12 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) for (i = 1; i < argc && *argv[i] == '-'; i++) { const char *arg = argv[i]; - if (starts_with(arg, "--upload-pack=")) { - args.uploadpack = arg + 14; + if (skip_prefix(arg, "--upload-pack=", &arg)) { + args.uploadpack = arg; continue; } - if (starts_with(arg, "--exec=")) { - args.uploadpack = arg + 7; + if (skip_prefix(arg, "--exec=", &arg)) { + args.uploadpack = arg; continue; } if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) { @@ -101,8 +102,20 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) args.verbose = 1; continue; } - if (starts_with(arg, "--depth=")) { - args.depth = strtol(arg + 8, NULL, 0); + if (skip_prefix(arg, "--depth=", &arg)) { + args.depth = strtol(arg, NULL, 0); + continue; + } + if (skip_prefix(arg, "--shallow-since=", &arg)) { + args.deepen_since = xstrdup(arg); + continue; + } + if (skip_prefix(arg, "--shallow-exclude=", &arg)) { + string_list_append(&deepen_not, arg); + continue; + } + if (!strcmp(arg, "--deepen-relative")) { + args.deepen_relative = 1; continue; } if (!strcmp("--no-progress", arg)) { @@ -132,6 +145,8 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) } usage(fetch_pack_usage); } + if (deepen_not.nr) + args.deepen_not = &deepen_not; if (i < argc) dest = argv[i++]; diff --git a/builtin/fetch.c b/builtin/fetch.c index cd7e3ce..b6a5597 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -35,13 +35,15 @@ static int fetch_prune_config = -1; /* unspecified */ static int prune = -1; /* unspecified */ #define PRUNE_BY_DEFAULT 0 /* do we prune by default? */ -static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity; +static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity, deepen_relative; static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT; -static int tags = TAGS_DEFAULT, unshallow, update_shallow; +static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen; static int max_children = -1; static enum transport_family family; static const char *depth; +static const char *deepen_since; static const char *upload_pack; +static struct string_list deepen_not = STRING_LIST_INIT_NODUP; static struct strbuf default_rla = STRBUF_INIT; static struct transport *gtransport; static struct transport *gsecondary; @@ -117,6 +119,12 @@ static struct option builtin_fetch_options[] = { OPT_BOOL(0, "progress", &progress, N_("force progress reporting")), OPT_STRING(0, "depth", &depth, N_("depth"), N_("deepen history of shallow clone")), + OPT_STRING(0, "shallow-since", &deepen_since, N_("time"), + N_("deepen history of shallow repository based on time")), + OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("revision"), + N_("deepen history of shallow clone by excluding rev")), + OPT_INTEGER(0, "deepen", &deepen_relative, + N_("deepen history of shallow clone")), { OPTION_SET_INT, 0, "unshallow", &unshallow, NULL, N_("convert to a complete repository"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 }, @@ -569,9 +577,12 @@ static void print_compact(struct strbuf *display, static void format_display(struct strbuf *display, char code, const char *summary, const char *error, - const char *remote, const char *local) + const char *remote, const char *local, + int summary_width) { - strbuf_addf(display, "%c %-*s ", code, TRANSPORT_SUMMARY(summary)); + int width = (summary_width + strlen(summary) - gettext_width(summary)); + + strbuf_addf(display, "%c %-*s ", code, width, summary); if (!compact_format) print_remote_to_local(display, remote, local); else @@ -583,7 +594,8 @@ static void format_display(struct strbuf *display, char code, static int update_local_ref(struct ref *ref, const char *remote, const struct ref *remote_ref, - struct strbuf *display) + struct strbuf *display, + int summary_width) { struct commit *current = NULL, *updated; enum object_type type; @@ -597,7 +609,7 @@ static int update_local_ref(struct ref *ref, if (!oidcmp(&ref->old_oid, &ref->new_oid)) { if (verbosity > 0) format_display(display, '=', _("[up to date]"), NULL, - remote, pretty_ref); + remote, pretty_ref, summary_width); return 0; } @@ -611,7 +623,7 @@ static int update_local_ref(struct ref *ref, */ format_display(display, '!', _("[rejected]"), _("can't fetch in current branch"), - remote, pretty_ref); + remote, pretty_ref, summary_width); return 1; } @@ -621,7 +633,7 @@ static int update_local_ref(struct ref *ref, r = s_update_ref("updating tag", ref, 0); format_display(display, r ? '!' : 't', _("[tag update]"), r ? _("unable to update local ref") : NULL, - remote, pretty_ref); + remote, pretty_ref, summary_width); return r; } @@ -654,7 +666,7 @@ static int update_local_ref(struct ref *ref, r = s_update_ref(msg, ref, 0); format_display(display, r ? '!' : '*', what, r ? _("unable to update local ref") : NULL, - remote, pretty_ref); + remote, pretty_ref, summary_width); return r; } @@ -670,7 +682,7 @@ static int update_local_ref(struct ref *ref, r = s_update_ref("fast-forward", ref, 1); format_display(display, r ? '!' : ' ', quickref.buf, r ? _("unable to update local ref") : NULL, - remote, pretty_ref); + remote, pretty_ref, summary_width); strbuf_release(&quickref); return r; } else if (force || ref->force) { @@ -685,12 +697,12 @@ static int update_local_ref(struct ref *ref, r = s_update_ref("forced-update", ref, 1); format_display(display, r ? '!' : '+', quickref.buf, r ? _("unable to update local ref") : _("forced update"), - remote, pretty_ref); + remote, pretty_ref, summary_width); strbuf_release(&quickref); return r; } else { format_display(display, '!', _("[rejected]"), _("non-fast-forward"), - remote, pretty_ref); + remote, pretty_ref, summary_width); return 1; } } @@ -721,6 +733,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, char *url; const char *filename = dry_run ? "/dev/null" : git_path_fetch_head(); int want_status; + int summary_width = transport_summary_width(ref_map); fp = fopen(filename, "a"); if (!fp) @@ -830,13 +843,14 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, strbuf_reset(¬e); if (ref) { - rc |= update_local_ref(ref, what, rm, ¬e); + rc |= update_local_ref(ref, what, rm, ¬e, + summary_width); free(ref); } else format_display(¬e, '*', *kind ? kind : "branch", NULL, *what ? what : "HEAD", - "FETCH_HEAD"); + "FETCH_HEAD", summary_width); if (note.len) { if (verbosity >= 0 && !shown_url) { fprintf(stderr, _("From %.*s\n"), @@ -878,7 +892,7 @@ static int quickfetch(struct ref *ref_map) * really need to perform. Claiming failure now will ensure * we perform the network exchange to deepen our history. */ - if (depth) + if (deepen) return -1; opt.quiet = 1; return check_connected(iterate_ref_map, &rm, &opt); @@ -903,6 +917,7 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map, int url_len, i, result = 0; struct ref *ref, *stale_refs = get_stale_heads(refs, ref_count, ref_map); char *url; + int summary_width = transport_summary_width(stale_refs); const char *dangling_msg = dry_run ? _(" (%s will become dangling)") : _(" (%s has become dangling)"); @@ -938,7 +953,8 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map, shown_url = 1; } format_display(&sb, '-', _("[deleted]"), NULL, - _("(none)"), prettify_refname(ref->name)); + _("(none)"), prettify_refname(ref->name), + summary_width); fprintf(stderr, " %s\n",sb.buf); strbuf_release(&sb); warn_dangling_symref(stderr, dangling_msg, ref->name); @@ -986,7 +1002,7 @@ static void set_option(struct transport *transport, const char *name, const char name, transport->url); } -static struct transport *prepare_transport(struct remote *remote) +static struct transport *prepare_transport(struct remote *remote, int deepen) { struct transport *transport; transport = transport_get(remote, NULL); @@ -998,6 +1014,13 @@ static struct transport *prepare_transport(struct remote *remote) set_option(transport, TRANS_OPT_KEEP, "yes"); if (depth) set_option(transport, TRANS_OPT_DEPTH, depth); + if (deepen && deepen_since) + set_option(transport, TRANS_OPT_DEEPEN_SINCE, deepen_since); + if (deepen && deepen_not.nr) + set_option(transport, TRANS_OPT_DEEPEN_NOT, + (const char *)&deepen_not); + if (deepen_relative) + set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, "yes"); if (update_shallow) set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes"); return transport; @@ -1005,13 +1028,25 @@ static struct transport *prepare_transport(struct remote *remote) static void backfill_tags(struct transport *transport, struct ref *ref_map) { - if (transport->cannot_reuse) { - gsecondary = prepare_transport(transport->remote); + int cannot_reuse; + + /* + * Once we have set TRANS_OPT_DEEPEN_SINCE, we can't unset it + * when remote helper is used (setting it to an empty string + * is not unsetting). We could extend the remote helper + * protocol for that, but for now, just force a new connection + * without deepen-since. Similar story for deepen-not. + */ + cannot_reuse = transport->cannot_reuse || + deepen_since || deepen_not.nr; + if (cannot_reuse) { + gsecondary = prepare_transport(transport->remote, 0); transport = gsecondary; } transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL); transport_set_option(transport, TRANS_OPT_DEPTH, "0"); + transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL); fetch_refs(transport, ref_map); if (gsecondary) { @@ -1222,7 +1257,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv) die(_("No remote repository specified. Please, specify either a URL or a\n" "remote name from which new revisions should be fetched.")); - gtransport = prepare_transport(remote); + gtransport = prepare_transport(remote, 1); if (prune < 0) { /* no command line request */ @@ -1282,6 +1317,13 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, builtin_fetch_options, builtin_fetch_usage, 0); + if (deepen_relative) { + if (deepen_relative < 0) + die(_("Negative depth in --deepen is not supported")); + if (depth) + die(_("--deepen and --depth are mutually exclusive")); + depth = xstrfmt("%d", deepen_relative); + } if (unshallow) { if (depth) die(_("--depth and --unshallow cannot be used together")); @@ -1294,6 +1336,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) /* no need to be strict, transport_set_option() will validate it again */ if (depth && atoi(depth) < 1) die(_("depth %s is not a positive number"), depth); + if (depth || deepen_since || deepen_not.nr) + deepen = 1; if (recurse_submodules != RECURSE_SUBMODULES_OFF) { if (recurse_submodules_default) { diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c index dc2e9e4..efab62f 100644 --- a/builtin/fmt-merge-msg.c +++ b/builtin/fmt-merge-msg.c @@ -314,14 +314,10 @@ static void add_people_info(struct strbuf *out, struct string_list *authors, struct string_list *committers) { - if (authors->nr) - qsort(authors->items, - authors->nr, sizeof(authors->items[0]), - cmp_string_list_util_as_integral); - if (committers->nr) - qsort(committers->items, - committers->nr, sizeof(committers->items[0]), - cmp_string_list_util_as_integral); + QSORT(authors->items, authors->nr, + cmp_string_list_util_as_integral); + QSORT(committers->items, committers->nr, + cmp_string_list_util_as_integral); credit_people(out, authors, 'a'); credit_people(out, committers, 'c'); diff --git a/builtin/fsck.c b/builtin/fsck.c index 2de272e..f01b81e 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -268,7 +268,7 @@ static void check_unreachable_object(struct object *obj) if (!(f = fopen(filename, "w"))) die_errno("Could not open '%s'", filename); if (obj->type == OBJ_BLOB) { - if (stream_blob_to_fd(fileno(f), obj->oid.hash, NULL, 1)) + if (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1)) die_errno("Could not write '%s'", filename); } else fprintf(f, "%s\n", describe_object(obj)); @@ -644,14 +644,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) fsck_object_dir(get_object_directory()); prepare_alt_odb(); - for (alt = alt_odb_list; alt; alt = alt->next) { - /* directory name, minus trailing slash */ - size_t namelen = alt->name - alt->base - 1; - struct strbuf name = STRBUF_INIT; - strbuf_add(&name, alt->base, namelen); - fsck_object_dir(name.buf); - strbuf_release(&name); - } + for (alt = alt_odb_list; alt; alt = alt->next) + fsck_object_dir(alt->path); } if (check_full) { @@ -722,7 +716,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) mode = active_cache[i]->ce_mode; if (S_ISGITLINK(mode)) continue; - blob = lookup_blob(active_cache[i]->sha1); + blob = lookup_blob(active_cache[i]->oid.hash); if (!blob) continue; obj = &blob->object; diff --git a/builtin/grep.c b/builtin/grep.c index ae73831..8887b6a 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -398,7 +398,8 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int if (cached || (ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) { if (ce_stage(ce) || ce_intent_to_add(ce)) continue; - hit |= grep_sha1(opt, ce->sha1, ce->name, 0, ce->name); + hit |= grep_sha1(opt, ce->oid.hash, ce->name, 0, + ce->name); } else hit |= grep_file(opt, ce->name); diff --git a/builtin/hash-object.c b/builtin/hash-object.c index f7d3567..9028e1f 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -87,6 +87,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) int stdin_paths = 0; int no_filters = 0; int literally = 0; + int nongit = 0; unsigned flags = HASH_FORMAT_CHECK; const char *vpath = NULL; const struct option hash_object_options[] = { @@ -107,12 +108,14 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, NULL, hash_object_options, hash_object_usage, 0); - if (flags & HASH_WRITE_OBJECT) { + if (flags & HASH_WRITE_OBJECT) prefix = setup_git_directory(); - prefix_length = prefix ? strlen(prefix) : 0; - if (vpath && prefix) - vpath = prefix_filename(prefix, prefix_length, vpath); - } + else + prefix = setup_git_directory_gently(&nongit); + + prefix_length = prefix ? strlen(prefix) : 0; + if (vpath && prefix) + vpath = prefix_filename(prefix, prefix_length, vpath); git_config(git_default_config, NULL); diff --git a/builtin/help.c b/builtin/help.c index e8f79d7..49f7a07 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -37,8 +37,10 @@ static int show_all = 0; static int show_guides = 0; static unsigned int colopts; static enum help_format help_format = HELP_FORMAT_NONE; +static int exclude_guides; static struct option builtin_help_options[] = { OPT_BOOL('a', "all", &show_all, N_("print all available commands")), + OPT_HIDDEN_BOOL(0, "exclude-guides", &exclude_guides, N_("exclude guides")), OPT_BOOL('g', "guides", &show_guides, N_("print list of useful guides")), OPT_SET_INT('m', "man", &help_format, N_("show man page"), HELP_FORMAT_MAN), OPT_SET_INT('w', "web", &help_format, N_("show manual in web browser"), @@ -426,10 +428,29 @@ static void list_common_guides_help(void) putchar('\n'); } +static const char *check_git_cmd(const char* cmd) +{ + char *alias; + + if (is_git_command(cmd)) + return cmd; + + alias = alias_lookup(cmd); + if (alias) { + printf_ln(_("`git %s' is aliased to `%s'"), cmd, alias); + free(alias); + exit(0); + } + + if (exclude_guides) + return help_unknown_cmd(cmd); + + return cmd; +} + int cmd_help(int argc, const char **argv, const char *prefix) { int nongit; - char *alias; enum help_format parsed_help_format; argc = parse_options(argc, argv, prefix, builtin_help_options, @@ -469,12 +490,7 @@ int cmd_help(int argc, const char **argv, const char *prefix) if (help_format == HELP_FORMAT_NONE) help_format = parse_help_format(DEFAULT_HELP_FORMAT); - alias = alias_lookup(argv[0]); - if (alias && !is_git_command(argv[0])) { - printf_ln(_("`git %s' is aliased to `%s'"), argv[0], alias); - free(alias); - return 0; - } + argv[0] = check_git_cmd(argv[0]); switch (help_format) { case HELP_FORMAT_NONE: diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 1d2ea58..0a27bab 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -87,6 +87,7 @@ static struct progress *progress; static unsigned char input_buffer[4096]; static unsigned int input_offset, input_len; static off_t consumed_bytes; +static off_t max_input_size; static unsigned deepest_delta; static git_SHA_CTX input_ctx; static uint32_t input_crc32; @@ -297,6 +298,8 @@ static void use(int bytes) if (signed_add_overflows(consumed_bytes, bytes)) die(_("pack too large for current definition of off_t")); consumed_bytes += bytes; + if (max_input_size && consumed_bytes > max_input_size) + die(_("pack exceeds maximum allowed size")); } static const char *open_pack_file(const char *pack_name) @@ -1187,10 +1190,8 @@ static void resolve_deltas(void) return; /* Sort deltas by base SHA1/offset for fast searching */ - qsort(ofs_deltas, nr_ofs_deltas, sizeof(struct ofs_delta_entry), - compare_ofs_delta_entry); - qsort(ref_deltas, nr_ref_deltas, sizeof(struct ref_delta_entry), - compare_ref_delta_entry); + QSORT(ofs_deltas, nr_ofs_deltas, compare_ofs_delta_entry); + QSORT(ref_deltas, nr_ref_deltas, compare_ref_delta_entry); if (verbose || show_resolving_progress) progress = start_progress(_("Resolving deltas"), @@ -1353,7 +1354,7 @@ static void fix_unresolved_deltas(struct sha1file *f) ALLOC_ARRAY(sorted_by_pos, nr_ref_deltas); for (i = 0; i < nr_ref_deltas; i++) sorted_by_pos[i] = &ref_deltas[i]; - qsort(sorted_by_pos, nr_ref_deltas, sizeof(*sorted_by_pos), delta_pos_compare); + QSORT(sorted_by_pos, nr_ref_deltas, delta_pos_compare); for (i = 0; i < nr_ref_deltas; i++) { struct ref_delta_entry *d = sorted_by_pos[i]; @@ -1530,8 +1531,7 @@ static void read_v2_anomalous_offsets(struct packed_git *p, opts->anomaly[opts->anomaly_nr++] = ntohl(idx2[off * 2 + 1]); } - if (1 < opts->anomaly_nr) - qsort(opts->anomaly, opts->anomaly_nr, sizeof(uint32_t), cmp_uint32); + QSORT(opts->anomaly, opts->anomaly_nr, cmp_uint32); } static void read_idx_option(struct pack_idx_option *opts, const char *pack_name) @@ -1714,6 +1714,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) opts.off32_limit = strtoul(c+1, &c, 0); if (*c || opts.off32_limit & 0x80000000) die(_("bad %s"), arg); + } else if (skip_prefix(arg, "--max-input-size=", &arg)) { + max_input_size = strtoumax(arg, NULL, 10); } else usage(index_pack_usage); continue; diff --git a/builtin/init-db.c b/builtin/init-db.c index 3a45f0b..2399b97 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -22,7 +22,6 @@ static int init_is_bare_repository = 0; static int init_shared_repository = -1; static const char *init_db_template_dir; -static const char *git_link; static void copy_templates_1(struct strbuf *path, struct strbuf *template, DIR *dir) @@ -138,7 +137,7 @@ static void copy_templates(const char *template_dir) goto close_free_return; } - strbuf_addstr(&path, get_git_dir()); + strbuf_addstr(&path, get_git_common_dir()); strbuf_complete(&path, '/'); copy_templates_1(&path, &template_path, dir); close_free_return: @@ -171,7 +170,8 @@ static int needs_work_tree_config(const char *git_dir, const char *work_tree) return 1; } -static int create_default_files(const char *template_path) +static int create_default_files(const char *template_path, + const char *original_git_dir) { struct stat st1; struct strbuf buf = STRBUF_INIT; @@ -180,27 +180,30 @@ static int create_default_files(const char *template_path) char junk[2]; int reinit; int filemode; - - /* - * Create .git/refs/{heads,tags} - */ - safe_create_dir(git_path_buf(&buf, "refs"), 1); - safe_create_dir(git_path_buf(&buf, "refs/heads"), 1); - safe_create_dir(git_path_buf(&buf, "refs/tags"), 1); + struct strbuf err = STRBUF_INIT; /* Just look for `init.templatedir` */ git_config(git_init_db_config, NULL); - /* First copy the templates -- we might have the default + /* + * First copy the templates -- we might have the default * config file there, in which case we would want to read * from it after installing. + * + * Before reading that config, we also need to clear out any cached + * values (since we've just potentially changed what's available on + * disk). */ copy_templates(template_path); - + git_config_clear(); + reset_shared_repository(); git_config(git_default_config, NULL); - is_bare_repository_cfg = init_is_bare_repository; - /* reading existing config may have overwrote it */ + /* + * We must make sure command-line options continue to override any + * values we might have just re-read from the config. + */ + is_bare_repository_cfg = init_is_bare_repository; if (init_shared_repository != -1) set_shared_repository(init_shared_repository); @@ -210,12 +213,19 @@ static int create_default_files(const char *template_path) */ 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")); - adjust_shared_perm(git_path_buf(&buf, "refs/tags")); } /* + * We need to create a "refs" dir in any case so that older + * versions of git can tell that this is a repository. + */ + safe_create_dir(git_path("refs"), 1); + adjust_shared_perm(git_path("refs")); + + if (refs_init_db(&err)) + die("failed to set up refs db: %s", err.buf); + + /* * Create the default symlink from ".git/HEAD" to the "master" * branch, if it does not exist yet. */ @@ -254,7 +264,7 @@ static int create_default_files(const char *template_path) /* allow template config file to override the default */ if (log_all_ref_updates == -1) git_config_set("core.logallrefupdates", "true"); - if (needs_work_tree_config(get_git_dir(), work_tree)) + if (needs_work_tree_config(original_git_dir, work_tree)) git_config_set("core.worktree", work_tree); } @@ -302,34 +312,7 @@ static void create_object_directory(void) strbuf_release(&path); } -int set_git_dir_init(const char *git_dir, const char *real_git_dir, - int exist_ok) -{ - if (real_git_dir) { - struct stat st; - - if (!exist_ok && !stat(git_dir, &st)) - die(_("%s already exists"), git_dir); - - if (!exist_ok && !stat(real_git_dir, &st)) - die(_("%s already exists"), real_git_dir); - - /* - * make sure symlinks are resolved because we'll be - * moving the target repo later on in separate_git_dir() - */ - git_link = xstrdup(real_path(git_dir)); - set_git_dir(real_path(real_git_dir)); - } - else { - set_git_dir(real_path(git_dir)); - git_link = NULL; - } - startup_info->have_repository = 1; - return 0; -} - -static void separate_git_dir(const char *git_dir) +static void separate_git_dir(const char *git_dir, const char *git_link) { struct stat st; @@ -350,13 +333,31 @@ static void separate_git_dir(const char *git_dir) write_file(git_link, "gitdir: %s", git_dir); } -int init_db(const char *template_dir, unsigned int flags) +int init_db(const char *git_dir, const char *real_git_dir, + const char *template_dir, unsigned int flags) { int reinit; - const char *git_dir = get_git_dir(); + int exist_ok = flags & INIT_DB_EXIST_OK; + char *original_git_dir = xstrdup(real_path(git_dir)); - if (git_link) - separate_git_dir(git_dir); + if (real_git_dir) { + struct stat st; + + if (!exist_ok && !stat(git_dir, &st)) + die(_("%s already exists"), git_dir); + + if (!exist_ok && !stat(real_git_dir, &st)) + die(_("%s already exists"), real_git_dir); + + set_git_dir(real_path(real_git_dir)); + git_dir = get_git_dir(); + separate_git_dir(git_dir, original_git_dir); + } + else { + set_git_dir(real_path(git_dir)); + git_dir = get_git_dir(); + } + startup_info->have_repository = 1; safe_create_dir(git_dir, 0); @@ -369,7 +370,7 @@ int init_db(const char *template_dir, unsigned int flags) */ check_repository_format(); - reinit = create_default_files(template_dir); + reinit = create_default_files(template_dir, original_git_dir); create_object_directory(); @@ -409,6 +410,7 @@ int init_db(const char *template_dir, unsigned int flags) git_dir, len && git_dir[len-1] != '/' ? "/" : ""); } + free(original_git_dir); return 0; } @@ -576,7 +578,6 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) set_git_work_tree(work_tree); } - set_git_dir_init(git_dir, real_git_dir, 1); - - return init_db(template_dir, flags); + flags |= INIT_DB_EXIST_OK; + return init_db(git_dir, real_git_dir, template_dir, flags); } diff --git a/builtin/log.c b/builtin/log.c index cd9c4a4..55d20cc 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -464,9 +464,9 @@ static void show_tagger(char *buf, int len, struct rev_info *rev) strbuf_release(&out); } -static int show_blob_object(const unsigned char *sha1, struct rev_info *rev, const char *obj_name) +static int show_blob_object(const struct object_id *oid, struct rev_info *rev, const char *obj_name) { - unsigned char sha1c[20]; + struct object_id oidc; struct object_context obj_context; char *buf; unsigned long size; @@ -474,13 +474,13 @@ static int show_blob_object(const unsigned char *sha1, struct rev_info *rev, con fflush(rev->diffopt.file); if (!DIFF_OPT_TOUCHED(&rev->diffopt, ALLOW_TEXTCONV) || !DIFF_OPT_TST(&rev->diffopt, ALLOW_TEXTCONV)) - return stream_blob_to_fd(1, sha1, NULL, 0); + return stream_blob_to_fd(1, oid, NULL, 0); - if (get_sha1_with_context(obj_name, 0, sha1c, &obj_context)) + if (get_sha1_with_context(obj_name, 0, oidc.hash, &obj_context)) die(_("Not a valid object name %s"), obj_name); if (!obj_context.path[0] || - !textconv_object(obj_context.path, obj_context.mode, sha1c, 1, &buf, &size)) - return stream_blob_to_fd(1, sha1, NULL, 0); + !textconv_object(obj_context.path, obj_context.mode, &oidc, 1, &buf, &size)) + return stream_blob_to_fd(1, oid, NULL, 0); if (!buf) die(_("git show %s: bad file"), obj_name); @@ -489,15 +489,15 @@ static int show_blob_object(const unsigned char *sha1, struct rev_info *rev, con return 0; } -static int show_tag_object(const unsigned char *sha1, struct rev_info *rev) +static int show_tag_object(const struct object_id *oid, struct rev_info *rev) { unsigned long size; enum object_type type; - char *buf = read_sha1_file(sha1, &type, &size); + char *buf = read_sha1_file(oid->hash, &type, &size); int offset = 0; if (!buf) - return error(_("Could not read object %s"), sha1_to_hex(sha1)); + return error(_("Could not read object %s"), oid_to_hex(oid)); assert(type == OBJ_TAG); while (offset < size && buf[offset] != '\n') { @@ -574,7 +574,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) const char *name = objects[i].name; switch (o->type) { case OBJ_BLOB: - ret = show_blob_object(o->oid.hash, &rev, name); + ret = show_blob_object(&o->oid, &rev, name); break; case OBJ_TAG: { struct tag *t = (struct tag *)o; @@ -585,7 +585,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) diff_get_color_opt(&rev.diffopt, DIFF_COMMIT), t->tag, diff_get_color_opt(&rev.diffopt, DIFF_RESET)); - ret = show_tag_object(o->oid.hash, &rev); + ret = show_tag_object(&o->oid, &rev); rev.shown_one = 1; if (ret) break; @@ -1111,6 +1111,11 @@ static int subject_prefix_callback(const struct option *opt, const char *arg, return 0; } +static int rfc_callback(const struct option *opt, const char *arg, int unset) +{ + return subject_prefix_callback(opt, "RFC PATCH", unset); +} + static int numbered_cmdline_opt = 0; static int numbered_callback(const struct option *opt, const char *arg, @@ -1247,11 +1252,11 @@ static struct commit *get_base_commit(const char *base_commit, if (upstream) { struct commit_list *base_list; struct commit *commit; - unsigned char sha1[20]; + struct object_id oid; - if (get_sha1(upstream, sha1)) + if (get_oid(upstream, &oid)) die(_("Failed to resolve '%s' as a valid ref."), upstream); - commit = lookup_commit_or_die(sha1, "upstream base"); + commit = lookup_commit_or_die(oid.hash, "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) @@ -1338,15 +1343,15 @@ static void prepare_bases(struct base_tree_info *bases, * and stuff them in bases structure. */ while ((commit = get_revision(&revs)) != NULL) { - unsigned char sha1[20]; + struct object_id oid; struct object_id *patch_id; if (commit->util) continue; - if (commit_patch_id(commit, &diffopt, sha1, 0)) + if (commit_patch_id(commit, &diffopt, oid.hash, 0)) 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); + oidcpy(patch_id, &oid); bases->nr_patch_id++; } } @@ -1418,6 +1423,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) N_("start numbering patches at instead of 1")), OPT_INTEGER('v', "reroll-count", &reroll_count, N_("mark the series as Nth re-roll")), + { OPTION_CALLBACK, 0, "rfc", &rev, NULL, + N_("Use [RFC PATCH] instead of [PATCH]"), + PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback }, { OPTION_CALLBACK, 0, "subject-prefix", &rev, N_("prefix"), N_("Use [] instead of [PATCH]"), PARSE_OPT_NONEG, subject_prefix_callback }, @@ -1556,7 +1564,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (numbered && keep_subject) die (_("-n and -k are mutually exclusive.")); if (keep_subject && subject_prefix) - die (_("--subject-prefix and -k are mutually exclusive.")); + die (_("--subject-prefix/--rfc and -k are mutually exclusive.")); rev.preserve_subject = keep_subject; argc = setup_revisions(argc, argv, &rev, &s_r_opt); @@ -1627,10 +1635,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) check_head = 1; if (check_head) { - unsigned char sha1[20]; + struct object_id oid; const char *ref, *v; ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, - sha1, NULL); + oid.hash, NULL); if (ref && skip_prefix(ref, "refs/heads/", &v)) branch_name = xstrdup(v); else @@ -1675,16 +1683,16 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* nothing to do */ return 0; total = nr; - if (!keep_subject && auto_number && total > 1) - numbered = 1; - if (numbered) - rev.total = total + start_number - 1; if (cover_letter == -1) { if (config_cover_letter == COVER_AUTO) cover_letter = (total > 1); else cover_letter = (config_cover_letter == COVER_ON); } + if (!keep_subject && auto_number && (total > 1 || cover_letter)) + numbered = 1; + if (numbered) + rev.total = total + start_number - 1; if (!signature) { ; /* --no-signature inhibits all signatures */ @@ -1802,9 +1810,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) static int add_pending_commit(const char *arg, struct rev_info *revs, int flags) { - unsigned char sha1[20]; - if (get_sha1(arg, sha1) == 0) { - struct commit *commit = lookup_commit_reference(sha1); + struct object_id oid; + if (get_oid(arg, &oid) == 0) { + struct commit *commit = lookup_commit_reference(oid.hash); if (commit) { commit->object.flags |= flags; add_pending_object(revs, &commit->object, arg); diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 00ea91a..1592290 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -14,6 +14,7 @@ #include "resolve-undo.h" #include "string-list.h" #include "pathspec.h" +#include "run-command.h" static int abbrev; static int show_deleted; @@ -28,8 +29,11 @@ static int show_valid_bit; static int line_terminator = '\n'; static int debug_mode; static int show_eol; +static int recurse_submodules; +static struct argv_array submodules_options = ARGV_ARRAY_INIT; static const char *prefix; +static const char *super_prefix; static int max_prefix_len; static int prefix_len; static struct pathspec pathspec; @@ -68,11 +72,24 @@ static void write_eolinfo(const struct cache_entry *ce, const char *path) static void write_name(const char *name) { /* + * Prepend the super_prefix to name to construct the full_name to be + * written. + */ + struct strbuf full_name = STRBUF_INIT; + if (super_prefix) { + strbuf_addstr(&full_name, super_prefix); + strbuf_addstr(&full_name, name); + name = full_name.buf; + } + + /* * With "--full-name", prefix_len=0; this caller needs to pass * an empty string in that case (a NULL is good for ""). */ write_name_quoted_relative(name, prefix_len ? prefix : NULL, stdout, line_terminator); + + strbuf_release(&full_name); } static void show_dir_entry(const char *tag, struct dir_entry *ent) @@ -152,55 +169,117 @@ static void show_killed_files(struct dir_struct *dir) } } +/* + * Compile an argv_array with all of the options supported by --recurse_submodules + */ +static void compile_submodule_options(const struct dir_struct *dir, int show_tag) +{ + if (line_terminator == '\0') + argv_array_push(&submodules_options, "-z"); + if (show_tag) + argv_array_push(&submodules_options, "-t"); + if (show_valid_bit) + argv_array_push(&submodules_options, "-v"); + if (show_cached) + argv_array_push(&submodules_options, "--cached"); + if (show_eol) + argv_array_push(&submodules_options, "--eol"); + if (debug_mode) + argv_array_push(&submodules_options, "--debug"); +} + +/** + * Recursively call ls-files on a submodule + */ +static void show_gitlink(const struct cache_entry *ce) +{ + struct child_process cp = CHILD_PROCESS_INIT; + int status; + int i; + + argv_array_pushf(&cp.args, "--super-prefix=%s%s/", + super_prefix ? super_prefix : "", + ce->name); + argv_array_push(&cp.args, "ls-files"); + argv_array_push(&cp.args, "--recurse-submodules"); + + /* add supported options */ + argv_array_pushv(&cp.args, submodules_options.argv); + + /* + * Pass in the original pathspec args. The submodule will be + * responsible for prepending the 'submodule_prefix' prior to comparing + * against the pathspec for matches. + */ + argv_array_push(&cp.args, "--"); + for (i = 0; i < pathspec.nr; i++) + argv_array_push(&cp.args, pathspec.items[i].original); + + cp.git_cmd = 1; + cp.dir = ce->name; + status = run_command(&cp); + if (status) + exit(status); +} + static void show_ce_entry(const char *tag, const struct cache_entry *ce) { + struct strbuf name = STRBUF_INIT; int len = max_prefix_len; + if (super_prefix) + strbuf_addstr(&name, super_prefix); + strbuf_addstr(&name, ce->name); if (len >= ce_namelen(ce)) die("git ls-files: internal error - cache entry not superset of prefix"); - if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce), - len, ps_matched, - S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode))) - return; + if (recurse_submodules && S_ISGITLINK(ce->ce_mode) && + submodule_path_match(&pathspec, name.buf, ps_matched)) { + show_gitlink(ce); + } else if (match_pathspec(&pathspec, name.buf, name.len, + len, ps_matched, + S_ISDIR(ce->ce_mode) || + S_ISGITLINK(ce->ce_mode))) { + if (tag && *tag && show_valid_bit && + (ce->ce_flags & CE_VALID)) { + static char alttag[4]; + memcpy(alttag, tag, 3); + if (isalpha(tag[0])) + alttag[0] = tolower(tag[0]); + else if (tag[0] == '?') + alttag[0] = '!'; + else { + alttag[0] = 'v'; + alttag[1] = tag[0]; + alttag[2] = ' '; + alttag[3] = 0; + } + tag = alttag; + } - if (tag && *tag && show_valid_bit && - (ce->ce_flags & CE_VALID)) { - static char alttag[4]; - memcpy(alttag, tag, 3); - if (isalpha(tag[0])) - alttag[0] = tolower(tag[0]); - else if (tag[0] == '?') - alttag[0] = '!'; - else { - alttag[0] = 'v'; - alttag[1] = tag[0]; - alttag[2] = ' '; - alttag[3] = 0; + if (!show_stage) { + fputs(tag, stdout); + } else { + printf("%s%06o %s %d\t", + tag, + ce->ce_mode, + find_unique_abbrev(ce->oid.hash, abbrev), + ce_stage(ce)); + } + write_eolinfo(ce, ce->name); + write_name(ce->name); + if (debug_mode) { + const struct stat_data *sd = &ce->ce_stat_data; + + printf(" ctime: %d:%d\n", sd->sd_ctime.sec, sd->sd_ctime.nsec); + printf(" mtime: %d:%d\n", sd->sd_mtime.sec, sd->sd_mtime.nsec); + printf(" dev: %d\tino: %d\n", sd->sd_dev, sd->sd_ino); + printf(" uid: %d\tgid: %d\n", sd->sd_uid, sd->sd_gid); + printf(" size: %d\tflags: %x\n", sd->sd_size, ce->ce_flags); } - tag = alttag; } - if (!show_stage) { - fputs(tag, stdout); - } else { - printf("%s%06o %s %d\t", - tag, - ce->ce_mode, - find_unique_abbrev(ce->sha1,abbrev), - ce_stage(ce)); - } - write_eolinfo(ce, ce->name); - write_name(ce->name); - if (debug_mode) { - const struct stat_data *sd = &ce->ce_stat_data; - - printf(" ctime: %d:%d\n", sd->sd_ctime.sec, sd->sd_ctime.nsec); - printf(" mtime: %d:%d\n", sd->sd_mtime.sec, sd->sd_mtime.nsec); - printf(" dev: %d\tino: %d\n", sd->sd_dev, sd->sd_ino); - printf(" uid: %d\tgid: %d\n", sd->sd_uid, sd->sd_gid); - printf(" size: %d\tflags: %x\n", sd->sd_size, ce->ce_flags); - } + strbuf_release(&name); } static void show_ru_info(void) @@ -468,6 +547,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) { OPTION_SET_INT, 0, "full-name", &prefix_len, NULL, N_("make the output relative to the project top directory"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL }, + OPT_BOOL(0, "recurse-submodules", &recurse_submodules, + N_("recurse through submodules")), OPT_BOOL(0, "error-unmatch", &error_unmatch, N_("if any is not in the index, treat this as an error")), OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"), @@ -484,6 +565,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) prefix = cmd_prefix; if (prefix) prefix_len = strlen(prefix); + super_prefix = get_super_prefix(); git_config(git_default_config, NULL); if (read_cache() < 0) @@ -519,13 +601,32 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) if (require_work_tree && !is_inside_work_tree()) setup_work_tree(); + if (recurse_submodules) + compile_submodule_options(&dir, show_tag); + + if (recurse_submodules && + (show_stage || show_deleted || show_others || show_unmerged || + show_killed || show_modified || show_resolve_undo || with_tree)) + die("ls-files --recurse-submodules unsupported mode"); + + if (recurse_submodules && error_unmatch) + die("ls-files --recurse-submodules does not support " + "--error-unmatch"); + parse_pathspec(&pathspec, 0, PATHSPEC_PREFER_CWD | PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP, prefix, argv); - /* Find common prefix for all pathspec's */ - max_prefix = common_prefix(&pathspec); + /* + * Find common prefix for all pathspec's + * This is used as a performance optimization which unfortunately cannot + * be done when recursing into submodules + */ + if (recurse_submodules) + max_prefix = NULL; + else + max_prefix = common_prefix(&pathspec); max_prefix_len = max_prefix ? strlen(max_prefix) : 0; /* Treat unmatching pathspec elements as errors */ diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c index f6df274..e3b62f2 100644 --- a/builtin/mailinfo.c +++ b/builtin/mailinfo.c @@ -11,15 +11,20 @@ static const char mailinfo_usage[] = "git mailinfo [-k | -b] [-m | --message-id] [-u | --encoding= | -n] [--scissors | --no-scissors] < mail >info"; +static char *prefix_copy(const char *prefix, const char *filename) +{ + if (!prefix || is_absolute_path(filename)) + return xstrdup(filename); + return xstrdup(prefix_filename(prefix, strlen(prefix), filename)); +} + int cmd_mailinfo(int argc, const char **argv, const char *prefix) { const char *def_charset; struct mailinfo mi; int status; + char *msgfile, *patchfile; - /* NEEDSWORK: might want to do the optional .git/ directory - * discovery - */ setup_mailinfo(&mi); def_charset = get_commit_output_encoding(); @@ -54,8 +59,14 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix) mi.input = stdin; mi.output = stdout; - status = !!mailinfo(&mi, argv[1], argv[2]); + + msgfile = prefix_copy(prefix, argv[1]); + patchfile = prefix_copy(prefix, argv[2]); + + status = !!mailinfo(&mi, msgfile, patchfile); clear_mailinfo(&mi); + free(msgfile); + free(patchfile); return status; } diff --git a/builtin/merge-index.c b/builtin/merge-index.c index 1c3427c..ce356b1 100644 --- a/builtin/merge-index.c +++ b/builtin/merge-index.c @@ -22,7 +22,7 @@ static int merge_entry(int pos, const char *path) if (strcmp(ce->name, path)) break; found++; - sha1_to_hex_r(hexbuf[stage], ce->sha1); + sha1_to_hex_r(hexbuf[stage], ce->oid.hash); xsnprintf(ownbuf[stage], sizeof(ownbuf[stage]), "%o", ce->ce_mode); arguments[stage] = hexbuf[stage]; arguments[stage + 4] = ownbuf[stage]; diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index fd2c455..0dd9021 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -42,36 +42,39 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) if (!arg[2]) break; if (parse_merge_opt(&o, arg + 2)) - die("Unknown option %s", arg); + die(_("unknown option %s"), arg); continue; } if (bases_count < ARRAY_SIZE(bases)-1) { struct object_id *oid = xmalloc(sizeof(struct object_id)); if (get_oid(argv[i], oid)) - die("Could not parse object '%s'", argv[i]); + die(_("could not parse object '%s'"), argv[i]); bases[bases_count++] = oid; } else - warning("Cannot handle more than %d bases. " - "Ignoring %s.", + warning(Q_("cannot handle more than %d base. " + "Ignoring %s.", + "cannot handle more than %d bases. " + "Ignoring %s.", + (int)ARRAY_SIZE(bases)-1), (int)ARRAY_SIZE(bases)-1, argv[i]); } if (argc - i != 3) /* "--" "" "" */ - die("Not handling anything other than two heads merge."); + die(_("not handling anything other than two heads merge.")); o.branch1 = argv[++i]; o.branch2 = argv[++i]; if (get_oid(o.branch1, &h1)) - die("Could not resolve ref '%s'", o.branch1); + die(_("could not resolve ref '%s'"), o.branch1); if (get_oid(o.branch2, &h2)) - die("Could not resolve ref '%s'", o.branch2); + die(_("could not resolve ref '%s'"), o.branch2); o.branch1 = better_branch_name(o.branch1); o.branch2 = better_branch_name(o.branch2); if (o.verbosity >= 3) - printf("Merging %s with %s\n", o.branch1, o.branch2); + printf(_("Merging %s with %s\n"), o.branch1, o.branch2); failed = merge_recursive_generic(&o, &h1, &h2, bases_count, bases, &result); if (failed < 0) diff --git a/builtin/merge.c b/builtin/merge.c index a8b57c7..b65eeaa 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -1374,12 +1374,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix) struct commit *commit; if (verbosity >= 0) { - char from[GIT_SHA1_HEXSZ + 1], to[GIT_SHA1_HEXSZ + 1]; - find_unique_abbrev_r(from, head_commit->object.oid.hash, - DEFAULT_ABBREV); - find_unique_abbrev_r(to, remoteheads->item->object.oid.hash, - DEFAULT_ABBREV); - printf(_("Updating %s..%s\n"), from, to); + printf(_("Updating %s..%s\n"), + find_unique_abbrev(head_commit->object.oid.hash, + DEFAULT_ABBREV), + find_unique_abbrev(remoteheads->item->object.oid.hash, + DEFAULT_ABBREV)); } strbuf_addstr(&msg, "Fast-forward"); if (have_message) diff --git a/builtin/mktree.c b/builtin/mktree.c index 4282b62..de9b40f 100644 --- a/builtin/mktree.c +++ b/builtin/mktree.c @@ -46,7 +46,7 @@ static void write_tree(unsigned char *sha1) size_t size; int i; - qsort(entries, used, sizeof(*entries), ent_compare); + QSORT(entries, used, ent_compare); for (size = i = 0; i < used; i++) size += 32 + entries[i]->len; diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 57be35f..cd89d48 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -195,8 +195,7 @@ static const char *get_exact_ref_match(const struct object *o) return NULL; if (!tip_table.sorted) { - qsort(tip_table.table, tip_table.nr, sizeof(*tip_table.table), - tipcmp); + QSORT(tip_table.table, tip_table.nr, tipcmp); tip_table.sorted = 1; } diff --git a/builtin/notes.c b/builtin/notes.c index f848b89..5248a9b 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -191,7 +191,7 @@ static void prepare_note_data(const unsigned char *object, struct note_data *d, strbuf_reset(&d->buf); if (launch_editor(d->edit_path, &d->buf, NULL)) { - die(_("Please supply the note contents using either -m or -F option")); + die(_("please supply the note contents using either -m or -F option")); } strbuf_stripspace(&d->buf, 1); } @@ -202,7 +202,7 @@ static void write_note_data(struct note_data *d, unsigned char *sha1) if (write_sha1_file(d->buf.buf, d->buf.len, blob_type, sha1)) { error(_("unable to write note object")); if (d->edit_path) - error(_("The note contents have been left in %s"), + error(_("the note contents have been left in %s"), d->edit_path); exit(128); } @@ -251,14 +251,14 @@ static int parse_reuse_arg(const struct option *opt, const char *arg, int unset) strbuf_addch(&d->buf, '\n'); if (get_sha1(arg, object)) - die(_("Failed to resolve '%s' as a valid ref."), arg); + die(_("failed to resolve '%s' as a valid ref."), arg); if (!(buf = read_sha1_file(object, &type, &len))) { free(buf); - die(_("Failed to read object '%s'."), arg); + die(_("failed to read object '%s'."), arg); } if (type != OBJ_BLOB) { free(buf); - die(_("Cannot read note data from non-blob object '%s'."), arg); + die(_("cannot read note data from non-blob object '%s'."), arg); } strbuf_add(&d->buf, buf, len); free(buf); @@ -298,13 +298,13 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd) split = strbuf_split(&buf, ' '); if (!split[0] || !split[1]) - die(_("Malformed input line: '%s'."), buf.buf); + die(_("malformed input line: '%s'."), buf.buf); strbuf_rtrim(split[0]); strbuf_rtrim(split[1]); if (get_sha1(split[0]->buf, from_obj)) - die(_("Failed to resolve '%s' as a valid ref."), split[0]->buf); + die(_("failed to resolve '%s' as a valid ref."), split[0]->buf); if (get_sha1(split[1]->buf, to_obj)) - die(_("Failed to resolve '%s' as a valid ref."), split[1]->buf); + die(_("failed to resolve '%s' as a valid ref."), split[1]->buf); if (rewrite_cmd) err = copy_note_for_rewrite(c, from_obj, to_obj); @@ -313,7 +313,7 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd) combine_notes_overwrite); if (err) { - error(_("Failed to copy notes from '%s' to '%s'"), + error(_("failed to copy notes from '%s' to '%s'"), split[0]->buf, split[1]->buf); ret = 1; } @@ -340,7 +340,9 @@ static struct notes_tree *init_notes_check(const char *subcommand, ref = (flags & NOTES_INIT_WRITABLE) ? t->update_ref : t->ref; if (!starts_with(ref, "refs/notes/")) - die("Refusing to %s notes in %s (outside of refs/notes/)", + /* TRANSLATORS: the first %s will be replaced by a + git notes command: 'add', 'merge', 'remove', etc.*/ + die(_("refusing to %s notes in %s (outside of refs/notes/)"), subcommand, ref); return t; } @@ -367,13 +369,13 @@ static int list(int argc, const char **argv, const char *prefix) t = init_notes_check("list", 0); if (argc) { if (get_sha1(argv[0], object)) - die(_("Failed to resolve '%s' as a valid ref."), argv[0]); + die(_("failed to resolve '%s' as a valid ref."), argv[0]); note = get_note(t, object); if (note) { puts(sha1_to_hex(note)); retval = 0; } else - retval = error(_("No note found for object %s."), + retval = error(_("no note found for object %s."), sha1_to_hex(object)); } else retval = for_each_note(t, 0, list_each_note, NULL); @@ -422,7 +424,7 @@ static int add(int argc, const char **argv, const char *prefix) object_ref = argc > 1 ? argv[1] : "HEAD"; if (get_sha1(object_ref, object)) - die(_("Failed to resolve '%s' as a valid ref."), object_ref); + die(_("failed to resolve '%s' as a valid ref."), object_ref); t = init_notes_check("add", NOTES_INIT_WRITABLE); note = get_note(t, object); @@ -508,12 +510,12 @@ static int copy(int argc, const char **argv, const char *prefix) } if (get_sha1(argv[0], from_obj)) - die(_("Failed to resolve '%s' as a valid ref."), argv[0]); + die(_("failed to resolve '%s' as a valid ref."), argv[0]); object_ref = 1 < argc ? argv[1] : "HEAD"; if (get_sha1(object_ref, object)) - die(_("Failed to resolve '%s' as a valid ref."), object_ref); + die(_("failed to resolve '%s' as a valid ref."), object_ref); t = init_notes_check("copy", NOTES_INIT_WRITABLE); note = get_note(t, object); @@ -532,7 +534,7 @@ static int copy(int argc, const char **argv, const char *prefix) from_note = get_note(t, from_obj); if (!from_note) { - retval = error(_("Missing notes on source object %s. Cannot " + retval = error(_("missing notes on source object %s. Cannot " "copy."), sha1_to_hex(from_obj)); goto out; } @@ -591,7 +593,7 @@ static int append_edit(int argc, const char **argv, const char *prefix) object_ref = 1 < argc ? argv[1] : "HEAD"; if (get_sha1(object_ref, object)) - die(_("Failed to resolve '%s' as a valid ref."), object_ref); + die(_("failed to resolve '%s' as a valid ref."), object_ref); t = init_notes_check(argv[0], NOTES_INIT_WRITABLE); note = get_note(t, object); @@ -654,13 +656,13 @@ static int show(int argc, const char **argv, const char *prefix) object_ref = argc ? argv[0] : "HEAD"; if (get_sha1(object_ref, object)) - die(_("Failed to resolve '%s' as a valid ref."), object_ref); + die(_("failed to resolve '%s' as a valid ref."), object_ref); t = init_notes_check("show", 0); note = get_note(t, object); if (!note) - retval = error(_("No note found for object %s."), + retval = error(_("no note found for object %s."), sha1_to_hex(object)); else { const char *show_args[3] = {"show", sha1_to_hex(note), NULL}; @@ -680,11 +682,11 @@ static int merge_abort(struct notes_merge_options *o) */ if (delete_ref("NOTES_MERGE_PARTIAL", NULL, 0)) - ret += error("Failed to delete ref NOTES_MERGE_PARTIAL"); + ret += error(_("failed to delete ref NOTES_MERGE_PARTIAL")); if (delete_ref("NOTES_MERGE_REF", NULL, REF_NODEREF)) - ret += error("Failed to delete ref NOTES_MERGE_REF"); + ret += error(_("failed to delete ref NOTES_MERGE_REF")); if (notes_merge_abort(o)) - ret += error("Failed to remove 'git notes merge' worktree"); + ret += error(_("failed to remove 'git notes merge' worktree")); return ret; } @@ -704,11 +706,11 @@ static int merge_commit(struct notes_merge_options *o) */ if (get_sha1("NOTES_MERGE_PARTIAL", sha1)) - die("Failed to read ref NOTES_MERGE_PARTIAL"); + die(_("failed to read ref NOTES_MERGE_PARTIAL")); else if (!(partial = lookup_commit_reference(sha1))) - die("Could not find commit from NOTES_MERGE_PARTIAL."); + die(_("could not find commit from NOTES_MERGE_PARTIAL.")); else if (parse_commit(partial)) - die("Could not parse commit from NOTES_MERGE_PARTIAL."); + die(_("could not parse commit from NOTES_MERGE_PARTIAL.")); if (partial->parents) hashcpy(parent_sha1, partial->parents->item->object.oid.hash); @@ -721,10 +723,10 @@ static int merge_commit(struct notes_merge_options *o) o->local_ref = local_ref_to_free = resolve_refdup("NOTES_MERGE_REF", 0, sha1, NULL); if (!o->local_ref) - die("Failed to resolve NOTES_MERGE_REF"); + die(_("failed to resolve NOTES_MERGE_REF")); if (notes_merge_commit(o, t, partial, sha1)) - die("Failed to finalize notes merge"); + die(_("failed to finalize notes merge")); /* Reuse existing commit message in reflog message */ memset(&pretty_ctx, 0, sizeof(pretty_ctx)); @@ -794,7 +796,7 @@ static int merge(int argc, const char **argv, const char *prefix) } if (do_merge && argc != 1) { - error(_("Must specify a notes ref to merge")); + error(_("must specify a notes ref to merge")); usage_with_options(git_notes_merge_usage, options); } else if (!do_merge && argc) { error(_("too many parameters")); @@ -818,7 +820,7 @@ static int merge(int argc, const char **argv, const char *prefix) if (strategy) { if (parse_notes_merge_strategy(strategy, &o.strategy)) { - error(_("Unknown -s/--strategy: %s"), strategy); + error(_("unknown -s/--strategy: %s"), strategy); usage_with_options(git_notes_merge_usage, options); } } else { @@ -855,10 +857,10 @@ static int merge(int argc, const char **argv, const char *prefix) /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */ wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref()); if (wt) - die(_("A notes merge into %s is already in-progress at %s"), + die(_("a notes merge into %s is already in-progress at %s"), 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)"), + die(_("failed to store link to current notes ref (%s)"), default_notes_ref()); printf(_("Automatic notes merge failed. Fix conflicts in %s and " "commit the result with 'git notes merge --commit', or " @@ -1014,7 +1016,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix) else if (!strcmp(argv[0], "get-ref")) result = get_ref(argc, argv, prefix); else { - result = error(_("Unknown subcommand: %s"), argv[0]); + result = error(_("unknown subcommand: %s"), argv[0]); usage_with_options(git_notes_usage, options); } diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 0954375..0fd52bd 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -23,6 +23,7 @@ #include "reachable.h" #include "sha1-array.h" #include "argv-array.h" +#include "mru.h" static const char *pack_usage[] = { N_("git pack-objects --stdout [...] [< | < ]"), @@ -67,7 +68,8 @@ static struct packed_git *reuse_packfile; static uint32_t reuse_packfile_objects; static off_t reuse_packfile_offset; -static int use_bitmap_index = 1; +static int use_bitmap_index_default = 1; +static int use_bitmap_index = -1; static int write_bitmap_index; static uint16_t write_bitmap_options; @@ -718,7 +720,7 @@ static off_t write_reused_pack(struct sha1file *f) if (!is_pack_valid(reuse_packfile)) die("packfile is invalid: %s", reuse_packfile->pack_name); - fd = git_open_noatime(reuse_packfile->pack_name); + fd = git_open(reuse_packfile->pack_name); if (fd < 0) die_errno("unable to open packfile for reuse: %s", reuse_packfile->pack_name); @@ -945,29 +947,80 @@ static int have_duplicate_entry(const unsigned char *sha1, return 1; } +static int want_found_object(int exclude, struct packed_git *p) +{ + if (exclude) + return 1; + if (incremental) + return 0; + + /* + * When asked to do --local (do not include an object that appears in a + * pack we borrow from elsewhere) or --honor-pack-keep (do not include + * an object that appears in a pack marked with .keep), finding a pack + * that matches the criteria is sufficient for us to decide to omit it. + * However, even if this pack does not satisfy the criteria, we need to + * make sure no copy of this object appears in _any_ pack that makes us + * to omit the object, so we need to check all the packs. + * + * We can however first check whether these options can possible matter; + * if they do not matter we know we want the object in generated pack. + * Otherwise, we signal "-1" at the end to tell the caller that we do + * not know either way, and it needs to check more packs. + */ + if (!ignore_packed_keep && + (!local || !have_non_local_packs)) + return 1; + + if (local && !p->pack_local) + return 0; + if (ignore_packed_keep && p->pack_local && p->pack_keep) + return 0; + + /* we don't know yet; keep looking for more packs */ + return -1; +} + /* * Check whether we want the object in the pack (e.g., we do not want * objects found in non-local stores if the "--local" option was used). * - * As a side effect of this check, we will find the packed version of this - * object, if any. We therefore pass out the pack information to avoid having - * to look it up again later. + * If the caller already knows an existing pack it wants to take the object + * from, that is passed in *found_pack and *found_offset; otherwise this + * function finds if there is any pack that has the object and returns the pack + * and its offset in these variables. */ static int want_object_in_pack(const unsigned char *sha1, int exclude, struct packed_git **found_pack, off_t *found_offset) { - struct packed_git *p; + struct mru_entry *entry; + int want; if (!exclude && local && has_loose_object_nonlocal(sha1)) return 0; - *found_pack = NULL; - *found_offset = 0; + /* + * If we already know the pack object lives in, start checks from that + * pack - in the usual case when neither --local was given nor .keep files + * are present we will determine the answer right now. + */ + if (*found_pack) { + want = want_found_object(exclude, *found_pack); + if (want != -1) + return want; + } + + for (entry = packed_git_mru->head; entry; entry = entry->next) { + struct packed_git *p = entry->item; + off_t offset; + + if (p == *found_pack) + offset = *found_offset; + else + offset = find_pack_entry_one(sha1, p); - for (p = packed_git; p; p = p->next) { - off_t offset = find_pack_entry_one(sha1, p); if (offset) { if (!*found_pack) { if (!is_pack_valid(p)) @@ -975,31 +1028,11 @@ static int want_object_in_pack(const unsigned char *sha1, *found_offset = offset; *found_pack = p; } - if (exclude) - return 1; - if (incremental) - return 0; - - /* - * When asked to do --local (do not include an - * object that appears in a pack we borrow - * from elsewhere) or --honor-pack-keep (do not - * include an object that appears in a pack marked - * with .keep), we need to make sure no copy of this - * object come from in _any_ pack that causes us to - * omit it, and need to complete this loop. When - * neither option is in effect, we know the object - * we just found is going to be packed, so break - * out of the loop to return 1 now. - */ - if (!ignore_packed_keep && - (!local || !have_non_local_packs)) - break; - - if (local && !p->pack_local) - return 0; - if (ignore_packed_keep && p->pack_local && p->pack_keep) - return 0; + want = want_found_object(exclude, p); + if (!exclude && want > 0) + mru_mark(packed_git_mru, entry); + if (want != -1) + return want; } } @@ -1040,8 +1073,8 @@ static const char no_closure_warning[] = N_( static int add_object_entry(const unsigned char *sha1, enum object_type type, const char *name, int exclude) { - struct packed_git *found_pack; - off_t found_offset; + struct packed_git *found_pack = NULL; + off_t found_offset = 0; uint32_t index_pos; if (have_duplicate_entry(sha1, exclude, &index_pos)) @@ -1074,6 +1107,9 @@ static int add_object_entry_from_bitmap(const unsigned char *sha1, if (have_duplicate_entry(sha1, 0, &index_pos)) return 0; + if (!want_object_in_pack(sha1, 0, &pack, &offset)) + return 0; + create_object_entry(sha1, type, name_hash, 0, 0, index_pos, pack, offset); display_progress(progress_state, nr_result); @@ -1495,6 +1531,83 @@ static int pack_offset_sort(const void *_a, const void *_b) (a->in_pack_offset > b->in_pack_offset); } +/* + * Drop an on-disk delta we were planning to reuse. Naively, this would + * just involve blanking out the "delta" field, but we have to deal + * with some extra book-keeping: + * + * 1. Removing ourselves from the delta_sibling linked list. + * + * 2. Updating our size/type to the non-delta representation. These were + * either not recorded initially (size) or overwritten with the delta type + * (type) when check_object() decided to reuse the delta. + */ +static void drop_reused_delta(struct object_entry *entry) +{ + struct object_entry **p = &entry->delta->delta_child; + struct object_info oi = OBJECT_INFO_INIT; + + while (*p) { + if (*p == entry) + *p = (*p)->delta_sibling; + else + p = &(*p)->delta_sibling; + } + entry->delta = NULL; + + oi.sizep = &entry->size; + oi.typep = &entry->type; + if (packed_object_info(entry->in_pack, entry->in_pack_offset, &oi) < 0) { + /* + * We failed to get the info from this pack for some reason; + * fall back to sha1_object_info, which may find another copy. + * And if that fails, the error will be recorded in entry->type + * and dealt with in prepare_pack(). + */ + entry->type = sha1_object_info(entry->idx.sha1, &entry->size); + } +} + +/* + * Follow the chain of deltas from this entry onward, throwing away any links + * that cause us to hit a cycle (as determined by the DFS state flags in + * the entries). + */ +static void break_delta_chains(struct object_entry *entry) +{ + /* If it's not a delta, it can't be part of a cycle. */ + if (!entry->delta) { + entry->dfs_state = DFS_DONE; + return; + } + + switch (entry->dfs_state) { + case DFS_NONE: + /* + * This is the first time we've seen the object. We mark it as + * part of the active potential cycle and recurse. + */ + entry->dfs_state = DFS_ACTIVE; + break_delta_chains(entry->delta); + entry->dfs_state = DFS_DONE; + break; + + case DFS_DONE: + /* object already examined, and not part of a cycle */ + break; + + case DFS_ACTIVE: + /* + * We found a cycle that needs broken. It would be correct to + * break any link in the chain, but it's convenient to + * break this one. + */ + drop_reused_delta(entry); + entry->dfs_state = DFS_DONE; + break; + } +} + static void get_object_details(void) { uint32_t i; @@ -1503,7 +1616,7 @@ static void get_object_details(void) sorted_by_offset = xcalloc(to_pack.nr_objects, sizeof(struct object_entry *)); for (i = 0; i < to_pack.nr_objects; i++) sorted_by_offset[i] = to_pack.objects + i; - qsort(sorted_by_offset, to_pack.nr_objects, sizeof(*sorted_by_offset), pack_offset_sort); + QSORT(sorted_by_offset, to_pack.nr_objects, pack_offset_sort); for (i = 0; i < to_pack.nr_objects; i++) { struct object_entry *entry = sorted_by_offset[i]; @@ -1512,6 +1625,13 @@ static void get_object_details(void) entry->no_try_delta = 1; } + /* + * This must happen in a second pass, since we rely on the delta + * information for the whole list being completed. + */ + for (i = 0; i < to_pack.nr_objects; i++) + break_delta_chains(&to_pack.objects[i]); + free(sorted_by_offset); } @@ -2225,7 +2345,7 @@ static void prepare_pack(int window, int depth) if (progress) progress_state = start_progress(_("Compressing objects"), nr_deltas); - qsort(delta_list, n, sizeof(*delta_list), type_size_sort); + QSORT(delta_list, n, type_size_sort); ll_find_deltas(delta_list, n, window+1, depth, &nr_done); stop_progress(&progress_state); if (nr_done != nr_deltas) @@ -2273,7 +2393,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) write_bitmap_options &= ~BITMAP_OPT_HASH_CACHE; } if (!strcmp(k, "pack.usebitmaps")) { - use_bitmap_index = git_config_bool(k, v); + use_bitmap_index_default = git_config_bool(k, v); return 0; } if (!strcmp(k, "pack.threads")) { @@ -2417,8 +2537,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs) } if (in_pack.nr) { - qsort(in_pack.array, in_pack.nr, sizeof(in_pack.array[0]), - ofscmp); + QSORT(in_pack.array, in_pack.nr, ofscmp); for (i = 0; i < in_pack.nr; i++) { struct object *o = in_pack.array[i].object; add_object_entry(o->oid.hash, o->type, "", 0); @@ -2522,13 +2641,13 @@ static void loosen_unused_packed_objects(struct rev_info *revs) } /* - * This tracks any options which a reader of the pack might - * not understand, and which would therefore prevent blind reuse - * of what we have on disk. + * This tracks any options which pack-reuse code expects to be on, or which a + * reader of the pack might not understand, and which would therefore prevent + * blind reuse of what we have on disk. */ static int pack_options_allow_reuse(void) { - return allow_ofs_delta; + return pack_to_stdout && allow_ofs_delta; } static int get_object_list_from_bitmap(struct rev_info *revs) @@ -2821,7 +2940,23 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) if (!rev_list_all || !rev_list_reflog || !rev_list_index) unpack_unreachable_expiration = 0; - if (!use_internal_rev_list || !pack_to_stdout || is_repository_shallow()) + /* + * "soft" reasons not to use bitmaps - for on-disk repack by default we want + * + * - to produce good pack (with bitmap index not-yet-packed objects are + * packed in suboptimal order). + * + * - to use more robust pack-generation codepath (avoiding possible + * bugs in bitmap code and possible bitmap index corruption). + */ + if (!pack_to_stdout) + use_bitmap_index_default = 0; + + if (use_bitmap_index < 0) + use_bitmap_index = use_bitmap_index_default; + + /* "hard" reasons not to use bitmaps; these just won't work at all */ + if (!use_internal_rev_list || (!pack_to_stdout && write_bitmap_index) || is_repository_shallow()) use_bitmap_index = 0; if (pack_to_stdout || !rev_list_all) diff --git a/builtin/pull.c b/builtin/pull.c index 398aae1..d6e46ee 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -17,6 +17,7 @@ #include "revision.h" #include "tempfile.h" #include "lockfile.h" +#include "wt-status.h" enum rebase_type { REBASE_INVALID = -1, @@ -326,73 +327,6 @@ static int git_pull_config(const char *var, const char *value, void *cb) } /** - * Returns 1 if there are unstaged changes, 0 otherwise. - */ -static int has_unstaged_changes(const char *prefix) -{ - struct rev_info rev_info; - int result; - - init_revisions(&rev_info, prefix); - DIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES); - DIFF_OPT_SET(&rev_info.diffopt, QUICK); - diff_setup_done(&rev_info.diffopt); - result = run_diff_files(&rev_info, 0); - return diff_result_code(&rev_info.diffopt, result); -} - -/** - * Returns 1 if there are uncommitted changes, 0 otherwise. - */ -static int has_uncommitted_changes(const char *prefix) -{ - struct rev_info rev_info; - int result; - - if (is_cache_unborn()) - return 0; - - init_revisions(&rev_info, prefix); - DIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES); - DIFF_OPT_SET(&rev_info.diffopt, QUICK); - add_head_to_pending(&rev_info); - diff_setup_done(&rev_info.diffopt); - result = run_diff_index(&rev_info, 1); - return diff_result_code(&rev_info.diffopt, result); -} - -/** - * If the work tree has unstaged or uncommitted changes, dies with the - * appropriate message. - */ -static void die_on_unclean_work_tree(const char *prefix) -{ - struct lock_file *lock_file = xcalloc(1, sizeof(*lock_file)); - int do_die = 0; - - hold_locked_index(lock_file, 0); - refresh_cache(REFRESH_QUIET); - update_index_if_able(&the_index, lock_file); - rollback_lock_file(lock_file); - - if (has_unstaged_changes(prefix)) { - error(_("Cannot pull with rebase: You have unstaged changes.")); - do_die = 1; - } - - if (has_uncommitted_changes(prefix)) { - if (do_die) - error(_("Additionally, your index contains uncommitted changes.")); - else - error(_("Cannot pull with rebase: Your index contains uncommitted changes.")); - do_die = 1; - } - - if (do_die) - exit(1); -} - -/** * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge * into merge_heads. */ @@ -875,7 +809,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix) die(_("Updating an unborn branch with changes added to the index.")); if (!autostash) - die_on_unclean_work_tree(prefix); + require_clean_work_tree(N_("pull with rebase"), + _("please commit or stash them."), 1, 0); if (get_rebase_fork_point(rebase_fork_point, repo, *refspecs)) hashclr(rebase_fork_point); diff --git a/builtin/read-tree.c b/builtin/read-tree.c index 8c693e7..9bd1fd7 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -78,7 +78,7 @@ static void debug_stage(const char *label, const struct cache_entry *ce, else printf("%06o #%d %s %.8s\n", ce->ce_mode, ce_stage(ce), ce->name, - sha1_to_hex(ce->sha1)); + oid_to_hex(&ce->oid)); } static int debug_merge(const struct cache_entry * const *stages, diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 011db00..e6b3879 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -20,6 +20,7 @@ #include "gpg-interface.h" #include "sigchain.h" #include "fsck.h" +#include "tmp-objdir.h" static const char * const receive_pack_usage[] = { N_("git receive-pack "), @@ -46,6 +47,7 @@ static int transfer_unpack_limit = -1; static int advertise_atomic_push = 1; static int advertise_push_options; static int unpack_limit = 100; +static off_t max_input_size; static int report_status; static int use_sideband; static int use_atomic; @@ -85,6 +87,8 @@ static enum { } use_keepalive; static int keepalive_in_sec = 5; +static struct tmp_objdir *tmp_objdir; + static enum deny_action parse_deny_action(const char *var, const char *value) { if (value) { @@ -212,13 +216,18 @@ static int receive_pack_config(const char *var, const char *value, void *cb) return 0; } + if (strcmp(var, "receive.maxinputsize") == 0) { + max_input_size = git_config_int64(var, value); + return 0; + } + return git_default_config(var, value, cb); } static void show_ref(const char *path, const unsigned char *sha1) { if (sent_capabilities) { - packet_write(1, "%s %s\n", sha1_to_hex(sha1), path); + packet_write_fmt(1, "%s %s\n", sha1_to_hex(sha1), path); } else { struct strbuf cap = STRBUF_INIT; @@ -233,7 +242,7 @@ static void show_ref(const char *path, const unsigned char *sha1) if (advertise_push_options) strbuf_addstr(&cap, " push-options"); strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized()); - packet_write(1, "%s %s%c%s\n", + packet_write_fmt(1, "%s %s%c%s\n", sha1_to_hex(sha1), path, 0, cap.buf); strbuf_release(&cap); sent_capabilities = 1; @@ -262,9 +271,10 @@ static int show_ref_cb(const char *path_full, const struct object_id *oid, return 0; } -static void show_one_alternate_sha1(const unsigned char sha1[20], void *unused) +static int show_one_alternate_sha1(const unsigned char sha1[20], void *unused) { show_ref(".have", sha1); + return 0; } static void collect_one_alternate_ref(const struct ref *ref, void *data) @@ -657,6 +667,9 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, } else argv_array_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT"); + if (tmp_objdir) + argv_array_pushv(&proc.env_array, tmp_objdir_env(tmp_objdir)); + if (use_sideband) { memset(&muxer, 0, sizeof(muxer)); muxer.proc = copy_to_sideband; @@ -756,6 +769,7 @@ static int run_update_hook(struct command *cmd) proc.stdout_to_stderr = 1; proc.err = use_sideband ? -1 : 0; proc.argv = argv; + proc.env = tmp_objdir_env(tmp_objdir); code = start_command(&proc); if (code) @@ -775,47 +789,39 @@ static int is_ref_checked_out(const char *ref) return !strcmp(head_name, ref); } -static char *refuse_unconfigured_deny_msg[] = { - "By default, updating the current branch in a non-bare repository", - "is denied, because it will make the index and work tree inconsistent", - "with what you pushed, and will require 'git reset --hard' to match", - "the work tree to HEAD.", - "", - "You can set 'receive.denyCurrentBranch' configuration variable to", - "'ignore' or 'warn' in the remote repository to allow pushing into", - "its current branch; however, this is not recommended unless you", - "arranged to update its work tree to match what you pushed in some", - "other way.", - "", - "To squelch this message and still keep the default behaviour, set", - "'receive.denyCurrentBranch' configuration variable to 'refuse'." -}; +static char *refuse_unconfigured_deny_msg = + N_("By default, updating the current branch in a non-bare repository\n" + "is denied, because it will make the index and work tree inconsistent\n" + "with what you pushed, and will require 'git reset --hard' to match\n" + "the work tree to HEAD.\n" + "\n" + "You can set 'receive.denyCurrentBranch' configuration variable to\n" + "'ignore' or 'warn' in the remote repository to allow pushing into\n" + "its current branch; however, this is not recommended unless you\n" + "arranged to update its work tree to match what you pushed in some\n" + "other way.\n" + "\n" + "To squelch this message and still keep the default behaviour, set\n" + "'receive.denyCurrentBranch' configuration variable to 'refuse'."); static void refuse_unconfigured_deny(void) { - int i; - for (i = 0; i < ARRAY_SIZE(refuse_unconfigured_deny_msg); i++) - rp_error("%s", refuse_unconfigured_deny_msg[i]); + rp_error("%s", _(refuse_unconfigured_deny_msg)); } -static char *refuse_unconfigured_deny_delete_current_msg[] = { - "By default, deleting the current branch is denied, because the next", - "'git clone' won't result in any file checked out, causing confusion.", - "", - "You can set 'receive.denyDeleteCurrent' configuration variable to", - "'warn' or 'ignore' in the remote repository to allow deleting the", - "current branch, with or without a warning message.", - "", - "To squelch this message, you can set it to 'refuse'." -}; +static char *refuse_unconfigured_deny_delete_current_msg = + N_("By default, deleting the current branch is denied, because the next\n" + "'git clone' won't result in any file checked out, causing confusion.\n" + "\n" + "You can set 'receive.denyDeleteCurrent' configuration variable to\n" + "'warn' or 'ignore' in the remote repository to allow deleting the\n" + "current branch, with or without a warning message.\n" + "\n" + "To squelch this message, you can set it to 'refuse'."); static void refuse_unconfigured_deny_delete_current(void) { - int i; - for (i = 0; - i < ARRAY_SIZE(refuse_unconfigured_deny_delete_current_msg); - i++) - rp_error("%s", refuse_unconfigured_deny_delete_current_msg[i]); + rp_error("%s", _(refuse_unconfigured_deny_delete_current_msg)); } static int command_singleton_iterator(void *cb_data, unsigned char sha1[20]); @@ -835,6 +841,7 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si) !delayed_reachability_test(si, i)) sha1_array_append(&extra, si->shallow->sha1[i]); + opt.env = tmp_objdir_env(tmp_objdir); setup_alternate_shallow(&shallow_lock, &opt.shallow_file, &extra); if (check_connected(command_singleton_iterator, cmd, &opt)) { rollback_lock_file(&shallow_lock); @@ -1156,10 +1163,6 @@ static void check_aliased_update(struct command *cmd, struct string_list *list) struct string_list_item *item; struct command *dst_cmd; unsigned char sha1[GIT_SHA1_RAWSZ]; - char cmd_oldh[GIT_SHA1_HEXSZ + 1], - cmd_newh[GIT_SHA1_HEXSZ + 1], - dst_oldh[GIT_SHA1_HEXSZ + 1], - dst_newh[GIT_SHA1_HEXSZ + 1]; int flag; strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name); @@ -1190,14 +1193,14 @@ static void check_aliased_update(struct command *cmd, struct string_list *list) dst_cmd->skip_update = 1; - find_unique_abbrev_r(cmd_oldh, cmd->old_sha1, DEFAULT_ABBREV); - find_unique_abbrev_r(cmd_newh, cmd->new_sha1, DEFAULT_ABBREV); - find_unique_abbrev_r(dst_oldh, dst_cmd->old_sha1, DEFAULT_ABBREV); - find_unique_abbrev_r(dst_newh, dst_cmd->new_sha1, DEFAULT_ABBREV); rp_error("refusing inconsistent update between symref '%s' (%s..%s) and" " its target '%s' (%s..%s)", - cmd->ref_name, cmd_oldh, cmd_newh, - dst_cmd->ref_name, dst_oldh, dst_newh); + cmd->ref_name, + find_unique_abbrev(cmd->old_sha1, DEFAULT_ABBREV), + find_unique_abbrev(cmd->new_sha1, DEFAULT_ABBREV), + dst_cmd->ref_name, + find_unique_abbrev(dst_cmd->old_sha1, DEFAULT_ABBREV), + find_unique_abbrev(dst_cmd->new_sha1, DEFAULT_ABBREV)); cmd->error_string = dst_cmd->error_string = "inconsistent aliased update"; @@ -1242,12 +1245,17 @@ static void set_connectivity_errors(struct command *commands, for (cmd = commands; cmd; cmd = cmd->next) { struct command *singleton = cmd; + struct check_connected_options opt = CHECK_CONNECTED_INIT; + if (shallow_update && si->shallow_ref[cmd->index]) /* to be checked in update_shallow_ref() */ continue; + + opt.env = tmp_objdir_env(tmp_objdir); if (!check_connected(command_singleton_iterator, &singleton, - NULL)) + &opt)) continue; + cmd->error_string = "missing necessary objects"; } } @@ -1430,6 +1438,7 @@ static void execute_commands(struct command *commands, data.si = si; opt.err_fd = err_fd; opt.progress = err_fd && !quiet; + opt.env = tmp_objdir_env(tmp_objdir); if (check_connected(iterate_receive_command_list, &data, &opt)) set_connectivity_errors(commands, si); @@ -1446,6 +1455,19 @@ static void execute_commands(struct command *commands, return; } + /* + * Now we'll start writing out refs, which means the objects need + * to be in their final positions so that other processes can see them. + */ + if (tmp_objdir_migrate(tmp_objdir) < 0) { + for (cmd = commands; cmd; cmd = cmd->next) { + if (!cmd->error_string) + cmd->error_string = "unable to migrate objects to permanent storage"; + } + return; + } + tmp_objdir = NULL; + check_aliased_updates(commands); free(head_name_to_free); @@ -1641,6 +1663,18 @@ static const char *unpack(int err_fd, struct shallow_info *si) argv_array_push(&child.args, alt_shallow_file); } + tmp_objdir = tmp_objdir_create(); + if (!tmp_objdir) + return "unable to create temporary object directory"; + child.env = tmp_objdir_env(tmp_objdir); + + /* + * Normally we just pass the tmp_objdir environment to the child + * processes that do the heavy lifting, but we may need to see these + * objects ourselves to set up shallow information. + */ + tmp_objdir_add_as_alternate(tmp_objdir); + if (ntohl(hdr.hdr_entries) < unpack_limit) { argv_array_pushl(&child.args, "unpack-objects", hdr_arg, NULL); if (quiet) @@ -1648,6 +1682,9 @@ 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 (max_input_size) + argv_array_pushf(&child.args, "--max-input-size=%"PRIuMAX, + (uintmax_t)max_input_size); child.no_stdout = 1; child.err = err_fd; child.git_cmd = 1; @@ -1676,6 +1713,9 @@ static const char *unpack(int err_fd, struct shallow_info *si) fsck_msg_types.buf); if (!reject_thin) argv_array_push(&child.args, "--fix-thin"); + if (max_input_size) + argv_array_pushf(&child.args, "--max-input-size=%"PRIuMAX, + (uintmax_t)max_input_size); child.out = -1; child.err = err_fd; child.git_cmd = 1; diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c index 88eb8f9..11b48bf 100644 --- a/builtin/remote-ext.c +++ b/builtin/remote-ext.c @@ -128,9 +128,9 @@ static void send_git_request(int stdin_fd, const char *serv, const char *repo, const char *vhost) { if (!vhost) - packet_write(stdin_fd, "%s %s%c", serv, repo, 0); + packet_write_fmt(stdin_fd, "%s %s%c", serv, repo, 0); else - packet_write(stdin_fd, "%s %s%chost=%s%c", serv, repo, 0, + packet_write_fmt(stdin_fd, "%s %s%chost=%s%c", serv, repo, 0, vhost, 0); } diff --git a/builtin/remote.c b/builtin/remote.c index 9f6a6b3..e52cf39 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -1197,8 +1197,7 @@ static int show(int argc, const char **argv) info.width = info.width2 = 0; for_each_string_list(&states.push, add_push_to_show_info, &info); - qsort(info.list->items, info.list->nr, - sizeof(*info.list->items), cmp_string_with_push); + QSORT(info.list->items, info.list->nr, cmp_string_with_push); if (info.list->nr) printf_ln(Q_(" Local ref configured for 'git push'%s:", " Local refs configured for 'git push'%s:", diff --git a/builtin/reset.c b/builtin/reset.c index 9400acc..c04ac07 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -39,7 +39,7 @@ static inline int is_merge(void) return !access(git_path_merge_head(), F_OK); } -static int reset_index(const unsigned char *sha1, int reset_type, int quiet) +static int reset_index(const struct object_id *oid, int reset_type, int quiet) { int nr = 1; struct tree_desc desc[2]; @@ -69,22 +69,22 @@ static int reset_index(const unsigned char *sha1, int reset_type, int quiet) read_cache_unmerged(); if (reset_type == KEEP) { - unsigned char head_sha1[20]; - if (get_sha1("HEAD", head_sha1)) + struct object_id head_oid; + if (get_oid("HEAD", &head_oid)) return error(_("You do not have a valid HEAD.")); - if (!fill_tree_descriptor(desc, head_sha1)) + if (!fill_tree_descriptor(desc, head_oid.hash)) return error(_("Failed to find tree of HEAD.")); nr++; opts.fn = twoway_merge; } - if (!fill_tree_descriptor(desc + nr - 1, sha1)) - return error(_("Failed to find tree of %s."), sha1_to_hex(sha1)); + if (!fill_tree_descriptor(desc + nr - 1, oid->hash)) + return error(_("Failed to find tree of %s."), oid_to_hex(oid)); if (unpack_trees(nr, desc, &opts)) return -1; if (reset_type == MIXED || reset_type == HARD) { - tree = parse_tree_indirect(sha1); + tree = parse_tree_indirect(oid->hash); prime_cache_tree(&the_index, tree); } @@ -143,7 +143,7 @@ static void update_index_from_diff(struct diff_queue_struct *q, } static int read_from_tree(const struct pathspec *pathspec, - unsigned char *tree_sha1, + struct object_id *tree_oid, int intent_to_add) { struct diff_options opt; @@ -154,7 +154,7 @@ static int read_from_tree(const struct pathspec *pathspec, opt.format_callback = update_index_from_diff; opt.format_callback_data = &intent_to_add; - if (do_diff_cache(tree_sha1, &opt)) + if (do_diff_cache(tree_oid->hash, &opt)) return 1; diffcore_std(&opt); diff_flush(&opt); @@ -191,7 +191,7 @@ static void parse_args(struct pathspec *pathspec, const char **rev_ret) { const char *rev = "HEAD"; - unsigned char unused[20]; + struct object_id unused; /* * Possible arguments are: * @@ -216,8 +216,8 @@ static void parse_args(struct pathspec *pathspec, * has to be unambiguous. If there is a single argument, it * can not be a tree */ - else if ((!argv[1] && !get_sha1_committish(argv[0], unused)) || - (argv[1] && !get_sha1_treeish(argv[0], unused))) { + else if ((!argv[1] && !get_sha1_committish(argv[0], unused.hash)) || + (argv[1] && !get_sha1_treeish(argv[0], unused.hash))) { /* * Ok, argv[0] looks like a commit/tree; it should not * be a filename. @@ -241,24 +241,24 @@ static void parse_args(struct pathspec *pathspec, prefix, argv); } -static int reset_refs(const char *rev, const unsigned char *sha1) +static int reset_refs(const char *rev, const struct object_id *oid) { int update_ref_status; struct strbuf msg = STRBUF_INIT; - unsigned char *orig = NULL, sha1_orig[20], - *old_orig = NULL, sha1_old_orig[20]; + struct object_id *orig = NULL, oid_orig, + *old_orig = NULL, oid_old_orig; - if (!get_sha1("ORIG_HEAD", sha1_old_orig)) - old_orig = sha1_old_orig; - if (!get_sha1("HEAD", sha1_orig)) { - orig = sha1_orig; + if (!get_oid("ORIG_HEAD", &oid_old_orig)) + old_orig = &oid_old_orig; + if (!get_oid("HEAD", &oid_orig)) { + orig = &oid_orig; set_reflog_message(&msg, "updating ORIG_HEAD", NULL); - update_ref(msg.buf, "ORIG_HEAD", orig, old_orig, 0, + update_ref_oid(msg.buf, "ORIG_HEAD", orig, old_orig, 0, UPDATE_REFS_MSG_ON_ERR); } else if (old_orig) - delete_ref("ORIG_HEAD", old_orig, 0); + delete_ref("ORIG_HEAD", old_orig->hash, 0); set_reflog_message(&msg, "updating HEAD", rev); - update_ref_status = update_ref(msg.buf, "HEAD", sha1, orig, 0, + update_ref_status = update_ref_oid(msg.buf, "HEAD", oid, orig, 0, UPDATE_REFS_MSG_ON_ERR); strbuf_release(&msg); return update_ref_status; @@ -357,15 +357,15 @@ int cmd_reset(int argc, const char **argv, const char *prefix) hold_locked_index(lock, 1); if (reset_type == MIXED) { int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN; - if (read_from_tree(&pathspec, oid.hash, intent_to_add)) + if (read_from_tree(&pathspec, &oid, intent_to_add)) return 1; if (get_git_work_tree()) refresh_index(&the_index, flags, NULL, NULL, _("Unstaged changes after reset:")); } else { - int err = reset_index(oid.hash, reset_type, quiet); + int err = reset_index(&oid, reset_type, quiet); if (reset_type == KEEP && !err) - err = reset_index(oid.hash, MIXED, quiet); + err = reset_index(&oid, MIXED, quiet); if (err) die(_("Could not reset index file to revision '%s'."), rev); } @@ -377,7 +377,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) if (!pathspec.nr && !unborn) { /* Any resets without paths update HEAD to the head being * switched to, saving the previous head in ORIG_HEAD before. */ - update_ref_status = reset_refs(rev, oid.hash); + update_ref_status = reset_refs(rev, &oid); if (reset_type == HARD && !update_ref_status && !quiet) print_new_head_line(lookup_commit_reference(oid.hash)); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 0ba82b1..c43decd 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -122,48 +122,40 @@ static void show_commit(struct commit *commit, void *data) ctx.fmt = revs->commit_format; ctx.output_encoding = get_log_output_encoding(); pretty_print_commit(&ctx, commit, &buf); - if (revs->graph) { - if (buf.len) { - if (revs->commit_format != CMIT_FMT_ONELINE) - graph_show_oneline(revs->graph); - - graph_show_commit_msg(revs->graph, &buf); - - /* - * Add a newline after the commit message. - * - * Usually, this newline produces a blank - * padding line between entries, in which case - * we need to add graph padding on this line. - * - * However, the commit message may not end in a - * newline. In this case the newline simply - * ends the last line of the commit message, - * and we don't need any graph output. (This - * always happens with CMIT_FMT_ONELINE, and it - * happens with CMIT_FMT_USERFORMAT when the - * format doesn't explicitly end in a newline.) - */ - if (buf.len && buf.buf[buf.len - 1] == '\n') - graph_show_padding(revs->graph); - putchar('\n'); - } else { - /* - * If the message buffer is empty, just show - * the rest of the graph output for this - * commit. - */ - if (graph_show_remainder(revs->graph)) - putchar('\n'); - if (revs->commit_format == CMIT_FMT_ONELINE) - putchar('\n'); - } + if (buf.len) { + if (revs->commit_format != CMIT_FMT_ONELINE) + graph_show_oneline(revs->graph); + + graph_show_commit_msg(revs->graph, stdout, &buf); + + /* + * Add a newline after the commit message. + * + * Usually, this newline produces a blank + * padding line between entries, in which case + * we need to add graph padding on this line. + * + * However, the commit message may not end in a + * newline. In this case the newline simply + * ends the last line of the commit message, + * and we don't need any graph output. (This + * always happens with CMIT_FMT_ONELINE, and it + * happens with CMIT_FMT_USERFORMAT when the + * format doesn't explicitly end in a newline.) + */ + if (buf.len && buf.buf[buf.len - 1] == '\n') + graph_show_padding(revs->graph); + putchar(info->hdr_termination); } else { - if (revs->commit_format != CMIT_FMT_USERFORMAT || - buf.len) { - fwrite(buf.buf, 1, buf.len, stdout); - putchar(info->hdr_termination); - } + /* + * If the message buffer is empty, just show + * the rest of the graph output for this + * commit. + */ + if (graph_show_remainder(revs->graph)) + putchar('\n'); + if (revs->commit_format == CMIT_FMT_ONELINE) + putchar('\n'); } strbuf_release(&buf); } else { diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 76cf05e..cfb0f15 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -298,14 +298,30 @@ static int try_parent_shorthands(const char *arg) unsigned char sha1[20]; struct commit *commit; struct commit_list *parents; - int parents_only; - - if ((dotdot = strstr(arg, "^!"))) - parents_only = 0; - else if ((dotdot = strstr(arg, "^@"))) - parents_only = 1; - - if (!dotdot || dotdot[2]) + int parent_number; + int include_rev = 0; + int include_parents = 0; + int exclude_parent = 0; + + if ((dotdot = strstr(arg, "^!"))) { + include_rev = 1; + if (dotdot[2]) + return 0; + } else if ((dotdot = strstr(arg, "^@"))) { + include_parents = 1; + if (dotdot[2]) + return 0; + } else if ((dotdot = strstr(arg, "^-"))) { + include_rev = 1; + exclude_parent = 1; + + if (dotdot[2]) { + char *end; + exclude_parent = strtoul(dotdot + 2, &end, 10); + if (*end != '\0' || !exclude_parent) + return 0; + } + } else return 0; *dotdot = 0; @@ -314,12 +330,24 @@ static int try_parent_shorthands(const char *arg) return 0; } - if (!parents_only) - show_rev(NORMAL, sha1, arg); commit = lookup_commit_reference(sha1); - for (parents = commit->parents; parents; parents = parents->next) - show_rev(parents_only ? NORMAL : REVERSED, - parents->item->object.oid.hash, arg); + if (exclude_parent && + exclude_parent > commit_list_count(commit->parents)) { + *dotdot = '^'; + return 0; + } + + if (include_rev) + show_rev(NORMAL, sha1, arg); + for (parents = commit->parents, parent_number = 1; + parents; + parents = parents->next, parent_number++) { + if (exclude_parent && parent_number != exclude_parent) + continue; + + show_rev(include_parents ? NORMAL : REVERSED, + parents->item->object.oid.hash, arg); + } *dotdot = '^'; return 1; @@ -643,8 +671,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) filter &= ~(DO_FLAGS|DO_NOREV); verify = 1; abbrev = DEFAULT_ABBREV; - if (arg[7] == '=') - abbrev = strtoul(arg + 8, NULL, 10); + if (!arg[7]) + continue; + abbrev = strtoul(arg + 8, NULL, 10); if (abbrev < MINIMUM_ABBREV) abbrev = MINIMUM_ABBREV; else if (40 <= abbrev) diff --git a/builtin/revert.c b/builtin/revert.c index 4e69380..4ca5b51 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -71,7 +71,7 @@ static void verify_opt_compatible(const char *me, const char *base_opt, ...) die(_("%s: %s cannot be used with %s"), me, this_opt, base_opt); } -static void parse_args(int argc, const char **argv, struct replay_opts *opts) +static int run_sequencer(int argc, const char **argv, struct replay_opts *opts) { const char * const * usage_str = revert_or_cherry_pick_usage(opts); const char *me = action_name(opts); @@ -115,25 +115,15 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts) if (opts->keep_redundant_commits) opts->allow_empty = 1; - /* Set the subcommand */ - if (cmd == 'q') - opts->subcommand = REPLAY_REMOVE_STATE; - else if (cmd == 'c') - opts->subcommand = REPLAY_CONTINUE; - else if (cmd == 'a') - opts->subcommand = REPLAY_ROLLBACK; - else - opts->subcommand = REPLAY_NONE; - /* Check for incompatible command line arguments */ - if (opts->subcommand != REPLAY_NONE) { + if (cmd) { char *this_operation; - if (opts->subcommand == REPLAY_REMOVE_STATE) + if (cmd == 'q') this_operation = "--quit"; - else if (opts->subcommand == REPLAY_CONTINUE) + else if (cmd == 'c') this_operation = "--continue"; else { - assert(opts->subcommand == REPLAY_ROLLBACK); + assert(cmd == 'a'); this_operation = "--abort"; } @@ -156,7 +146,7 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts) "--edit", opts->edit, NULL); - if (opts->subcommand != REPLAY_NONE) { + if (cmd) { opts->revs = NULL; } else { struct setup_revision_opt s_r_opt; @@ -174,20 +164,30 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts) if (argc > 1) usage_with_options(usage_str, options); + + /* These option values will be free()d */ + opts->gpg_sign = xstrdup_or_null(opts->gpg_sign); + opts->strategy = xstrdup_or_null(opts->strategy); + + if (cmd == 'q') + return sequencer_remove_state(opts); + if (cmd == 'c') + return sequencer_continue(opts); + if (cmd == 'a') + return sequencer_rollback(opts); + return sequencer_pick_revisions(opts); } int cmd_revert(int argc, const char **argv, const char *prefix) { - struct replay_opts opts; + struct replay_opts opts = REPLAY_OPTS_INIT; int res; - memset(&opts, 0, sizeof(opts)); if (isatty(0)) opts.edit = 1; opts.action = REPLAY_REVERT; git_config(git_default_config, NULL); - parse_args(argc, argv, &opts); - res = sequencer_pick_revisions(&opts); + res = run_sequencer(argc, argv, &opts); if (res < 0) die(_("revert failed")); return res; @@ -195,14 +195,12 @@ int cmd_revert(int argc, const char **argv, const char *prefix) int cmd_cherry_pick(int argc, const char **argv, const char *prefix) { - struct replay_opts opts; + struct replay_opts opts = REPLAY_OPTS_INIT; int res; - memset(&opts, 0, sizeof(opts)); opts.action = REPLAY_PICK; git_config(git_default_config, NULL); - parse_args(argc, argv, &opts); - res = sequencer_pick_revisions(&opts); + res = run_sequencer(argc, argv, &opts); if (res < 0) die(_("cherry-pick failed")); return res; diff --git a/builtin/rm.c b/builtin/rm.c index b2fee3e..3f3e24e 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -107,7 +107,7 @@ static int check_submodules_use_gitfiles(void) return errs; } -static int check_local_mod(unsigned char *head, int index_only) +static int check_local_mod(struct object_id *head, int index_only) { /* * Items in list are already sorted in the cache order, @@ -123,13 +123,13 @@ static int check_local_mod(unsigned char *head, int index_only) struct string_list files_submodule = STRING_LIST_INIT_NODUP; struct string_list files_local = STRING_LIST_INIT_NODUP; - no_head = is_null_sha1(head); + no_head = is_null_oid(head); for (i = 0; i < list.nr; i++) { struct stat st; int pos; const struct cache_entry *ce; const char *name = list.entry[i].name; - unsigned char sha1[20]; + struct object_id oid; unsigned mode; int local_changes = 0; int staged_changes = 0; @@ -197,9 +197,9 @@ static int check_local_mod(unsigned char *head, int index_only) * way as changed from the HEAD. */ if (no_head - || get_tree_entry(head, name, sha1, &mode) + || get_tree_entry(head->hash, name, oid.hash, &mode) || ce->ce_mode != create_ce_mode(mode) - || hashcmp(ce->sha1, sha1)) + || oidcmp(&ce->oid, &oid)) staged_changes = 1; /* @@ -351,10 +351,10 @@ int cmd_rm(int argc, const char **argv, const char *prefix) * report no changes unless forced. */ if (!force) { - unsigned char sha1[20]; - if (get_sha1("HEAD", sha1)) - hashclr(sha1); - if (check_local_mod(sha1, index_only)) + struct object_id oid; + if (get_oid("HEAD", &oid)) + oidclr(&oid); + if (check_local_mod(&oid, index_only)) exit(1); } else if (!index_only) { if (check_submodules_use_gitfiles()) diff --git a/builtin/shortlog.c b/builtin/shortlog.c index 25fa8a6..ba0e115 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -308,7 +308,7 @@ void shortlog_output(struct shortlog *log) struct strbuf sb = STRBUF_INIT; if (log->sort_by_number) - qsort(log->list.items, log->list.nr, sizeof(struct string_list_item), + QSORT(log->list.items, log->list.nr, log->summary ? compare_by_counter : compare_by_list); for (i = 0; i < log->list.nr; i++) { const struct string_list_item *item = &log->list.items[i]; diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 2566935..974f340 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -353,8 +353,7 @@ static int compare_ref_name(const void *a_, const void *b_) static void sort_ref_range(int bottom, int top) { - qsort(ref_name + bottom, top - bottom, sizeof(ref_name[0]), - compare_ref_name); + QSORT(ref_name + bottom, top - bottom, compare_ref_name); } static int append_ref(const char *refname, const struct object_id *oid, @@ -373,8 +372,9 @@ static int append_ref(const char *refname, const struct object_id *oid, return 0; } if (MAX_REVS <= ref_name_cnt) { - warning("ignoring %s; cannot handle more than %d refs", - refname, MAX_REVS); + warning(Q_("ignoring %s; cannot handle more than %d ref", + "ignoring %s; cannot handle more than %d refs", + MAX_REVS), refname, MAX_REVS); return 0; } ref_name[ref_name_cnt++] = xstrdup(refname); @@ -538,9 +538,8 @@ static void append_one_rev(const char *av) for_each_ref(append_matching_ref, NULL); if (saved_matches == ref_name_cnt && ref_name_cnt < MAX_REVS) - error("no matching refs with %s", av); - if (saved_matches + 1 < ref_name_cnt) - sort_ref_range(saved_matches, ref_name_cnt); + error(_("no matching refs with %s"), av); + sort_ref_range(saved_matches, ref_name_cnt); return; } die("bad sha1 reference %s", av); @@ -701,8 +700,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) * * Also --all and --remotes do not make sense either. */ - die("--reflog is incompatible with --all, --remotes, " - "--independent or --merge-base"); + die(_("--reflog is incompatible with --all, --remotes, " + "--independent or --merge-base")); } /* If nothing is specified, show all branches by default */ @@ -725,16 +724,17 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) av = fake_av; ac = 1; if (!*av) - die("no branches given, and HEAD is not valid"); + die(_("no branches given, and HEAD is not valid")); } if (ac != 1) - die("--reflog option needs one branch name"); + die(_("--reflog option needs one branch name")); if (MAX_REVS < reflog) - die("Only %d entries can be shown at one time.", - MAX_REVS); + die(Q_("only %d entry can be shown at one time.", + "only %d entries can be shown at one time.", + MAX_REVS), MAX_REVS); if (!dwim_ref(*av, strlen(*av), oid.hash, &ref)) - die("No such ref %s", *av); + die(_("no such ref %s"), *av); /* Has the base been specified? */ if (reflog_base) { @@ -826,12 +826,14 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) unsigned int flag = 1u << (num_rev + REV_SHIFT); if (MAX_REVS <= num_rev) - die("cannot handle more than %d revs.", MAX_REVS); + die(Q_("cannot handle more than %d rev.", + "cannot handle more than %d revs.", + MAX_REVS), MAX_REVS); if (get_sha1(ref_name[num_rev], revkey.hash)) - die("'%s' is not a valid ref.", ref_name[num_rev]); + die(_("'%s' is not a valid ref."), ref_name[num_rev]); commit = lookup_commit_reference(revkey.hash); if (!commit) - die("cannot find commit %s (%s)", + die(_("cannot find commit %s (%s)"), ref_name[num_rev], oid_to_hex(&revkey)); parse_commit(commit); mark_seen(commit, &seen); diff --git a/builtin/stripspace.c b/builtin/stripspace.c index 15e716e..1e62a00 100644 --- a/builtin/stripspace.c +++ b/builtin/stripspace.c @@ -44,8 +44,10 @@ int cmd_stripspace(int argc, const char **argv, const char *prefix) if (argc) usage_with_options(stripspace_usage, options); - if (mode == STRIP_COMMENTS || mode == COMMENT_LINES) + if (mode == STRIP_COMMENTS || mode == COMMENT_LINES) { + setup_git_directory_gently(NULL); git_config(git_default_config, NULL); + } if (strbuf_read(&buf, 0, 1024) < 0) die_errno("could not read the input"); diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index dbe5699..4beeda5 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -95,6 +95,8 @@ static int chop_last_dir(char **remoteurl, int is_relative) * 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://a.com/c same as previous line, but + * ignore trailing slash in url * 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 @@ -113,8 +115,8 @@ static char *relative_url(const char *remote_url, struct strbuf sb = STRBUF_INIT; size_t len = strlen(remoteurl); - if (is_dir_sep(remoteurl[len])) - remoteurl[len] = '\0'; + if (is_dir_sep(remoteurl[len-1])) + remoteurl[len-1] = '\0'; if (!url_is_local_not_ssh(remoteurl) || is_absolute_path(remoteurl)) is_relative = 0; @@ -147,6 +149,8 @@ static char *relative_url(const char *remote_url, } strbuf_reset(&sb); strbuf_addf(&sb, "%s%s%s", remoteurl, colonsep ? ":" : "/", url); + if (ends_with(url, "/")) + strbuf_setlen(&sb, sb.len - 1); free(remoteurl); if (starts_with_dot_slash(sb.buf)) @@ -296,7 +300,8 @@ static int module_list(int argc, const char **argv, const char *prefix) if (ce_stage(ce)) printf("%06o %s U\t", ce->ce_mode, sha1_to_hex(null_sha1)); else - printf("%06o %s %d\t", ce->ce_mode, sha1_to_hex(ce->sha1), ce_stage(ce)); + printf("%06o %s %d\t", ce->ce_mode, + oid_to_hex(&ce->oid), ce_stage(ce)); utf8_fprintf(stdout, "%s\n", ce->name); } @@ -442,7 +447,8 @@ static int module_name(int argc, const char **argv, const char *prefix) } static int clone_submodule(const char *path, const char *gitdir, const char *url, - const char *depth, const char *reference, int quiet) + const char *depth, struct string_list *reference, + int quiet, int progress) { struct child_process cp = CHILD_PROCESS_INIT; @@ -450,10 +456,16 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url argv_array_push(&cp.args, "--no-checkout"); if (quiet) argv_array_push(&cp.args, "--quiet"); + if (progress) + argv_array_push(&cp.args, "--progress"); if (depth && *depth) argv_array_pushl(&cp.args, "--depth", depth, NULL); - if (reference && *reference) - argv_array_pushl(&cp.args, "--reference", reference, NULL); + if (reference->nr) { + struct string_list_item *item; + for_each_string_list_item(item, reference) + argv_array_pushl(&cp.args, "--reference", + item->string, NULL); + } if (gitdir && *gitdir) argv_array_pushl(&cp.args, "--separate-git-dir", gitdir, NULL); @@ -467,15 +479,110 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url return run_command(&cp); } +struct submodule_alternate_setup { + const char *submodule_name; + enum SUBMODULE_ALTERNATE_ERROR_MODE { + SUBMODULE_ALTERNATE_ERROR_DIE, + SUBMODULE_ALTERNATE_ERROR_INFO, + SUBMODULE_ALTERNATE_ERROR_IGNORE + } error_mode; + struct string_list *reference; +}; +#define SUBMODULE_ALTERNATE_SETUP_INIT { NULL, \ + SUBMODULE_ALTERNATE_ERROR_IGNORE, NULL } + +static int add_possible_reference_from_superproject( + struct alternate_object_database *alt, void *sas_cb) +{ + struct submodule_alternate_setup *sas = sas_cb; + + /* + * If the alternate object store is another repository, try the + * standard layout with .git/modules//objects + */ + if (ends_with(alt->path, ".git/objects")) { + char *sm_alternate; + struct strbuf sb = STRBUF_INIT; + struct strbuf err = STRBUF_INIT; + strbuf_add(&sb, alt->path, strlen(alt->path) - strlen("objects")); + + /* + * We need to end the new path with '/' to mark it as a dir, + * otherwise a submodule name containing '/' will be broken + * as the last part of a missing submodule reference would + * be taken as a file name. + */ + strbuf_addf(&sb, "modules/%s/", sas->submodule_name); + + sm_alternate = compute_alternate_path(sb.buf, &err); + if (sm_alternate) { + string_list_append(sas->reference, xstrdup(sb.buf)); + free(sm_alternate); + } else { + switch (sas->error_mode) { + case SUBMODULE_ALTERNATE_ERROR_DIE: + die(_("submodule '%s' cannot add alternate: %s"), + sas->submodule_name, err.buf); + case SUBMODULE_ALTERNATE_ERROR_INFO: + fprintf(stderr, _("submodule '%s' cannot add alternate: %s"), + sas->submodule_name, err.buf); + case SUBMODULE_ALTERNATE_ERROR_IGNORE: + ; /* nothing */ + } + } + strbuf_release(&sb); + } + + return 0; +} + +static void prepare_possible_alternates(const char *sm_name, + struct string_list *reference) +{ + char *sm_alternate = NULL, *error_strategy = NULL; + struct submodule_alternate_setup sas = SUBMODULE_ALTERNATE_SETUP_INIT; + + git_config_get_string("submodule.alternateLocation", &sm_alternate); + if (!sm_alternate) + return; + + git_config_get_string("submodule.alternateErrorStrategy", &error_strategy); + + if (!error_strategy) + error_strategy = xstrdup("die"); + + sas.submodule_name = sm_name; + sas.reference = reference; + if (!strcmp(error_strategy, "die")) + sas.error_mode = SUBMODULE_ALTERNATE_ERROR_DIE; + else if (!strcmp(error_strategy, "info")) + sas.error_mode = SUBMODULE_ALTERNATE_ERROR_INFO; + else if (!strcmp(error_strategy, "ignore")) + sas.error_mode = SUBMODULE_ALTERNATE_ERROR_IGNORE; + else + die(_("Value '%s' for submodule.alternateErrorStrategy is not recognized"), error_strategy); + + if (!strcmp(sm_alternate, "superproject")) + foreach_alt_odb(add_possible_reference_from_superproject, &sas); + else if (!strcmp(sm_alternate, "no")) + ; /* do nothing */ + else + die(_("Value '%s' for submodule.alternateLocation is not recognized"), sm_alternate); + + free(sm_alternate); + free(error_strategy); +} + static int module_clone(int argc, const char **argv, const char *prefix) { - const char *name = NULL, *url = NULL; - const char *reference = NULL, *depth = NULL; + const char *name = NULL, *url = NULL, *depth = NULL; int quiet = 0; + int progress = 0; FILE *submodule_dot_git; char *p, *path = NULL, *sm_gitdir; struct strbuf rel_path = STRBUF_INIT; struct strbuf sb = STRBUF_INIT; + struct string_list reference = STRING_LIST_INIT_NODUP; struct option module_clone_options[] = { OPT_STRING(0, "prefix", &prefix, @@ -490,13 +597,15 @@ static int module_clone(int argc, const char **argv, const char *prefix) OPT_STRING(0, "url", &url, N_("string"), N_("url where to clone the submodule from")), - OPT_STRING(0, "reference", &reference, - N_("string"), + OPT_STRING_LIST(0, "reference", &reference, + N_("repo"), N_("reference repository")), OPT_STRING(0, "depth", &depth, N_("string"), N_("depth for shallow clones")), OPT__QUIET(&quiet, "Suppress output for cloning a submodule"), + OPT_BOOL(0, "progress", &progress, + N_("force cloning progress")), OPT_END() }; @@ -527,7 +636,11 @@ static int module_clone(int argc, const char **argv, const char *prefix) if (!file_exists(sm_gitdir)) { if (safe_create_leading_directories_const(sm_gitdir) < 0) die(_("could not create directory '%s'"), sm_gitdir); - if (clone_submodule(path, sm_gitdir, url, depth, reference, quiet)) + + prepare_possible_alternates(name, &reference); + + if (clone_submodule(path, sm_gitdir, url, depth, &reference, + quiet, progress)) die(_("clone of '%s' into submodule path '%s' failed"), url, path); } else { @@ -577,9 +690,10 @@ struct submodule_update_clone { struct submodule_update_strategy update; /* configuration parameters which are passed on to the children */ + int progress; int quiet; int recommend_shallow; - const char *reference; + struct string_list references; const char *depth; const char *recursive_prefix; const char *prefix; @@ -595,7 +709,8 @@ struct submodule_update_clone { int failed_clones_nr, failed_clones_alloc; }; #define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \ - SUBMODULE_UPDATE_STRATEGY_INIT, 0, -1, NULL, NULL, NULL, NULL, \ + SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, \ + NULL, NULL, NULL, \ STRING_LIST_INIT_DUP, 0, NULL, 0, 0} @@ -683,7 +798,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, strbuf_reset(&sb); strbuf_addf(&sb, "%06o %s %d %d\t%s\n", ce->ce_mode, - sha1_to_hex(ce->sha1), ce_stage(ce), + oid_to_hex(&ce->oid), ce_stage(ce), needs_cloning, ce->name); string_list_append(&suc->projectlines, sb.buf); @@ -696,6 +811,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, child->err = -1; argv_array_push(&child->args, "submodule--helper"); argv_array_push(&child->args, "clone"); + if (suc->progress) + argv_array_push(&child->args, "--progress"); if (suc->quiet) argv_array_push(&child->args, "--quiet"); if (suc->prefix) @@ -705,8 +822,11 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, 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->references.nr) { + struct string_list_item *item; + for_each_string_list_item(item, &suc->references) + argv_array_pushl(&child->args, "--reference", item->string, NULL); + } if (suc->depth) argv_array_push(&child->args, suc->depth); @@ -830,7 +950,7 @@ static int update_clone(int argc, const char **argv, const char *prefix) OPT_STRING(0, "update", &update, N_("string"), N_("rebase, merge, checkout or none")), - OPT_STRING(0, "reference", &suc.reference, N_("repo"), + OPT_STRING_LIST(0, "reference", &suc.references, N_("repo"), N_("reference repository")), OPT_STRING(0, "depth", &suc.depth, "", N_("Create a shallow clone truncated to the " @@ -840,6 +960,8 @@ static int update_clone(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "recommend-shallow", &suc.recommend_shallow, N_("whether the initial clone should follow the shallow recommendation")), OPT__QUIET(&suc.quiet, N_("don't print cloning progress")), + OPT_BOOL(0, "progress", &suc.progress, + N_("force cloning progress")), OPT_END() }; diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 172470b..4532aa0 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -19,6 +19,7 @@ static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict] static unsigned char buffer[4096]; static unsigned int offset, len; static off_t consumed_bytes; +static off_t max_input_size; static git_SHA_CTX ctx; static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; @@ -87,6 +88,8 @@ static void use(int bytes) if (signed_add_overflows(consumed_bytes, bytes)) die("pack too large for current definition of off_t"); consumed_bytes += bytes; + if (max_input_size && consumed_bytes > max_input_size) + die(_("pack exceeds maximum allowed size")); } static void *get_data(unsigned long size) @@ -550,6 +553,10 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix) len = sizeof(*hdr); continue; } + if (skip_prefix(arg, "--max-input-size=", &arg)) { + max_input_size = strtoumax(arg, NULL, 10); + continue; + } usage(unpack_usage); } diff --git a/builtin/update-index.c b/builtin/update-index.c index 9e9e040..f3f07e7 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -275,7 +275,7 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len fill_stat_cache_info(ce, st); ce->ce_mode = ce_mode_from_stat(old, st->st_mode); - if (index_path(ce->sha1, path, st, + if (index_path(ce->oid.hash, path, st, info_only ? 0 : HASH_WRITE_OBJECT)) { free(ce); return -1; @@ -312,7 +312,7 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len */ static int process_directory(const char *path, int len, struct stat *st) { - unsigned char sha1[20]; + struct object_id oid; int pos = cache_name_pos(path, len); /* Exact match: file or existing gitlink */ @@ -321,7 +321,7 @@ static int process_directory(const char *path, int len, struct stat *st) if (S_ISGITLINK(ce->ce_mode)) { /* Do nothing to the index if there is no HEAD! */ - if (resolve_gitlink_ref(path, "HEAD", sha1) < 0) + if (resolve_gitlink_ref(path, "HEAD", oid.hash) < 0) return 0; return add_one_path(ce, path, len, st); @@ -347,7 +347,7 @@ static int process_directory(const char *path, int len, struct stat *st) } /* No match - should we add it as a gitlink? */ - if (!resolve_gitlink_ref(path, "HEAD", sha1)) + if (!resolve_gitlink_ref(path, "HEAD", oid.hash)) return add_one_path(NULL, path, len, st); /* Error out. */ @@ -390,7 +390,7 @@ static int process_path(const char *path) return add_one_path(ce, path, len, &st); } -static int add_cacheinfo(unsigned int mode, const unsigned char *sha1, +static int add_cacheinfo(unsigned int mode, const struct object_id *oid, const char *path, int stage) { int size, len, option; @@ -403,7 +403,7 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1, size = cache_entry_size(len); ce = xcalloc(1, size); - hashcpy(ce->sha1, sha1); + oidcpy(&ce->oid, oid); memcpy(ce->name, path, len); ce->ce_flags = create_ce_flags(stage); ce->ce_namelen = len; @@ -475,7 +475,7 @@ static void read_index_info(int nul_term_line) while (getline_fn(&buf, stdin) != EOF) { char *ptr, *tab; char *path_name; - unsigned char sha1[20]; + struct object_id oid; unsigned int mode; unsigned long ul; int stage; @@ -504,7 +504,7 @@ static void read_index_info(int nul_term_line) mode = ul; tab = strchr(ptr, '\t'); - if (!tab || tab - ptr < 41) + if (!tab || tab - ptr < GIT_SHA1_HEXSZ + 1) goto bad_line; if (tab[-2] == ' ' && '0' <= tab[-1] && tab[-1] <= '3') { @@ -517,7 +517,8 @@ static void read_index_info(int nul_term_line) ptr = tab + 1; /* point at the head of path */ } - if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ') + if (get_oid_hex(tab - GIT_SHA1_HEXSZ, &oid) || + tab[-(GIT_SHA1_HEXSZ + 1)] != ' ') goto bad_line; path_name = ptr; @@ -545,8 +546,8 @@ static void read_index_info(int nul_term_line) * ptr[-1] points at tab, * ptr[-41] is at the beginning of sha1 */ - ptr[-42] = ptr[-1] = 0; - if (add_cacheinfo(mode, sha1, path_name, stage)) + ptr[-(GIT_SHA1_HEXSZ + 2)] = ptr[-1] = 0; + if (add_cacheinfo(mode, &oid, path_name, stage)) die("git update-index: unable to update %s", path_name); } @@ -564,19 +565,19 @@ static const char * const update_index_usage[] = { NULL }; -static unsigned char head_sha1[20]; -static unsigned char merge_head_sha1[20]; +static struct object_id head_oid; +static struct object_id merge_head_oid; static struct cache_entry *read_one_ent(const char *which, - unsigned char *ent, const char *path, + struct object_id *ent, const char *path, int namelen, int stage) { unsigned mode; - unsigned char sha1[20]; + struct object_id oid; int size; struct cache_entry *ce; - if (get_tree_entry(ent, path, sha1, &mode)) { + if (get_tree_entry(ent->hash, path, oid.hash, &mode)) { if (which) error("%s: not in %s branch.", path, which); return NULL; @@ -589,7 +590,7 @@ static struct cache_entry *read_one_ent(const char *which, size = cache_entry_size(namelen); ce = xcalloc(1, size); - hashcpy(ce->sha1, sha1); + oidcpy(&ce->oid, &oid); memcpy(ce->name, path, namelen); ce->ce_flags = create_ce_flags(stage); ce->ce_namelen = namelen; @@ -639,14 +640,14 @@ static int unresolve_one(const char *path) * stuff HEAD version in stage #2, * stuff MERGE_HEAD version in stage #3. */ - ce_2 = read_one_ent("our", head_sha1, path, namelen, 2); - ce_3 = read_one_ent("their", merge_head_sha1, path, namelen, 3); + ce_2 = read_one_ent("our", &head_oid, path, namelen, 2); + ce_3 = read_one_ent("their", &merge_head_oid, path, namelen, 3); if (!ce_2 || !ce_3) { ret = -1; goto free_return; } - if (!hashcmp(ce_2->sha1, ce_3->sha1) && + if (!oidcmp(&ce_2->oid, &ce_3->oid) && ce_2->ce_mode == ce_3->ce_mode) { fprintf(stderr, "%s: identical in both, skipping.\n", path); @@ -671,9 +672,9 @@ static int unresolve_one(const char *path) static void read_head_pointers(void) { - if (read_ref("HEAD", head_sha1)) + if (read_ref("HEAD", head_oid.hash)) die("No HEAD -- no initial commit yet?"); - if (read_ref("MERGE_HEAD", merge_head_sha1)) { + if (read_ref("MERGE_HEAD", merge_head_oid.hash)) { fprintf(stderr, "Not in the middle of a merge.\n"); exit(0); } @@ -713,7 +714,7 @@ static int do_reupdate(int ac, const char **av, PATHSPEC_PREFER_CWD, prefix, av + 1); - if (read_ref("HEAD", head_sha1)) + if (read_ref("HEAD", head_oid.hash)) /* If there is no HEAD, that means it is an initial * commit. Update everything in the index. */ @@ -728,10 +729,10 @@ static int do_reupdate(int ac, const char **av, if (ce_stage(ce) || !ce_path_match(ce, &pathspec, NULL)) continue; if (has_head) - old = read_one_ent(NULL, head_sha1, + old = read_one_ent(NULL, &head_oid, ce->name, ce_namelen(ce), 0); if (old && ce->ce_mode == old->ce_mode && - !hashcmp(ce->sha1, old->sha1)) { + !oidcmp(&ce->oid, &old->oid)) { free(old); continue; /* unchanged */ } @@ -795,7 +796,7 @@ static int resolve_undo_clear_callback(const struct option *opt, static int parse_new_style_cacheinfo(const char *arg, unsigned int *mode, - unsigned char sha1[], + struct object_id *oid, const char **path) { unsigned long ul; @@ -810,21 +811,21 @@ static int parse_new_style_cacheinfo(const char *arg, return -1; /* not a new-style cacheinfo */ *mode = ul; endp++; - if (get_sha1_hex(endp, sha1) || endp[40] != ',') + if (get_oid_hex(endp, oid) || endp[GIT_SHA1_HEXSZ] != ',') return -1; - *path = endp + 41; + *path = endp + GIT_SHA1_HEXSZ + 1; return 0; } static int cacheinfo_callback(struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) { - unsigned char sha1[20]; + struct object_id oid; unsigned int mode; const char *path; - if (!parse_new_style_cacheinfo(ctx->argv[1], &mode, sha1, &path)) { - if (add_cacheinfo(mode, sha1, path, 0)) + if (!parse_new_style_cacheinfo(ctx->argv[1], &mode, &oid, &path)) { + if (add_cacheinfo(mode, &oid, path, 0)) die("git update-index: --cacheinfo cannot add %s", path); ctx->argv++; ctx->argc--; @@ -833,8 +834,8 @@ static int cacheinfo_callback(struct parse_opt_ctx_t *ctx, if (ctx->argc <= 3) return error("option 'cacheinfo' expects ,,"); if (strtoul_ui(*++ctx->argv, 8, &mode) || - get_sha1_hex(*++ctx->argv, sha1) || - add_cacheinfo(mode, sha1, *++ctx->argv, 0)) + get_oid_hex(*++ctx->argv, &oid) || + add_cacheinfo(mode, &oid, *++ctx->argv, 0)) die("git update-index: --cacheinfo cannot add %s", *ctx->argv); ctx->argc -= 3; return 0; @@ -1115,9 +1116,9 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) break; case UC_DISABLE: if (git_config_get_untracked_cache() == 1) - warning("core.untrackedCache is set to true; " - "remove or change it, if you really want to " - "disable the untracked cache"); + warning(_("core.untrackedCache is set to true; " + "remove or change it, if you really want to " + "disable the untracked cache")); remove_untracked_cache(&the_index); report(_("Untracked cache disabled")); break; @@ -1127,9 +1128,9 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) case UC_ENABLE: case UC_FORCE: if (git_config_get_untracked_cache() == 0) - warning("core.untrackedCache is set to false; " - "remove or change it, if you really want to " - "enable the untracked cache"); + warning(_("core.untrackedCache is set to false; " + "remove or change it, if you really want to " + "enable the untracked cache")); add_untracked_cache(&the_index); report(_("Untracked cache enabled for '%s'"), get_git_work_tree()); break; diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c index 2caedf1..cde0697 100644 --- a/builtin/upload-archive.c +++ b/builtin/upload-archive.c @@ -43,7 +43,7 @@ int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix) } /* parse all options sent by the client */ - return write_archive(sent_argv.argc, sent_argv.argv, prefix, 0, NULL, 1); + return write_archive(sent_argv.argc, sent_argv.argv, prefix, NULL, 1); } __attribute__((format (printf, 1, 2))) @@ -88,11 +88,11 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix) writer.git_cmd = 1; if (start_command(&writer)) { int err = errno; - packet_write(1, "NACK unable to spawn subprocess\n"); + packet_write_fmt(1, "NACK unable to spawn subprocess\n"); die("upload-archive: %s", strerror(err)); } - packet_write(1, "ACK\n"); + packet_write_fmt(1, "ACK\n"); packet_flush(1); while (1) { diff --git a/cache-tree.c b/cache-tree.c index f28b1f4..345ea35 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -168,7 +168,7 @@ static int verify_cache(struct cache_entry **cache, break; } fprintf(stderr, "%s: unmerged (%s)\n", - ce->name, sha1_to_hex(ce->sha1)); + ce->name, oid_to_hex(&ce->oid)); } } if (funny) @@ -349,7 +349,7 @@ static int update_one(struct cache_tree *it, } } else { - sha1 = ce->sha1; + sha1 = ce->oid.hash; mode = ce->ce_mode; entlen = pathlen - baselen; i++; diff --git a/cache.h b/cache.h index 2125eb5..a50a61a 100644 --- a/cache.h +++ b/cache.h @@ -173,7 +173,7 @@ struct cache_entry { unsigned int ce_flags; unsigned int ce_namelen; unsigned int index; /* for link extension */ - unsigned char sha1[20]; + struct object_id oid; char name[FLEX_ARRAY]; /* more */ }; @@ -409,6 +409,7 @@ static inline enum object_type object_type(unsigned int mode) #define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE" #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE" #define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX" +#define GIT_SUPER_PREFIX_ENVIRONMENT "GIT_INTERNAL_SUPER_PREFIX" #define DEFAULT_GIT_DIR_ENVIRONMENT ".git" #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY" #define INDEX_ENVIRONMENT "GIT_INDEX_FILE" @@ -433,6 +434,7 @@ static inline enum object_type object_type(unsigned int mode) #define GIT_GLOB_PATHSPECS_ENVIRONMENT "GIT_GLOB_PATHSPECS" #define GIT_NOGLOB_PATHSPECS_ENVIRONMENT "GIT_NOGLOB_PATHSPECS" #define GIT_ICASE_PATHSPECS_ENVIRONMENT "GIT_ICASE_PATHSPECS" +#define GIT_QUARANTINE_ENVIRONMENT "GIT_QUARANTINE_PATH" /* * This environment variable is expected to contain a boolean indicating @@ -454,6 +456,12 @@ static inline enum object_type object_type(unsigned int mode) */ extern const char * const local_repo_env[]; +/* + * Returns true iff we have a configured git repository (either via + * setup_git_directory, or in the environment via $GIT_DIR). + */ +int have_git_dir(void); + extern int is_bare_repository_cfg; extern int is_bare_repository(void); extern int is_inside_git_dir(void); @@ -469,6 +477,7 @@ extern int get_common_dir_noenv(struct strbuf *sb, const char *gitdir); extern int get_common_dir(struct strbuf *sb, const char *gitdir); extern const char *get_git_namespace(void); extern const char *strip_namespace(const char *namespaced_ref); +extern const char *get_super_prefix(void); extern const char *get_git_work_tree(void); /* @@ -520,9 +529,10 @@ extern void verify_non_filename(const char *prefix, const char *name); extern int path_inside_repo(const char *prefix, const char *path); #define INIT_DB_QUIET 0x0001 +#define INIT_DB_EXIST_OK 0x0002 -extern int set_git_dir_init(const char *git_dir, const char *real_git_dir, int); -extern int init_db(const char *template_dir, unsigned int flags); +extern int init_db(const char *git_dir, const char *real_git_dir, + const char *template_dir, unsigned int flags); extern void sanitize_stdfds(void); extern int daemonize(void); @@ -667,8 +677,15 @@ extern size_t delta_base_cache_limit; extern unsigned long big_file_threshold; extern unsigned long pack_size_limit_cfg; +/* + * Accessors for the core.sharedrepository config which lazy-load the value + * from the config (if not already set). The "reset" function can be + * used to unset "set" or cached value, meaning that the value will be loaded + * fresh from the config file on the next call to get_shared_repository(). + */ void set_shared_repository(int value); int get_shared_repository(void); +void reset_shared_repository(void); /* * Do replace refs need to be checked this run? This variable is @@ -821,8 +838,8 @@ 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, - const char *fmt, ...) +extern int strbuf_git_path_submodule(struct strbuf *sb, const char *path, + const char *fmt, ...) __attribute__((format (printf, 3, 4))); extern char *git_pathdup(const char *fmt, ...) __attribute__((format (printf, 1, 2))); @@ -886,8 +903,8 @@ extern char *sha1_pack_index_name(const unsigned char *sha1); * The result will be at least `len` characters long, and will be NUL * terminated. * - * The non-`_r` version returns a static buffer which will be overwritten by - * subsequent calls. + * The non-`_r` version returns a static buffer which remains valid until 4 + * more calls to find_unique_abbrev are made. * * The `_r` variant writes to a buffer supplied by the caller, which must be at * least `GIT_SHA1_HEXSZ + 1` bytes. The return value is the number of bytes @@ -955,22 +972,39 @@ static inline void oidclr(struct object_id *oid) #define EMPTY_TREE_SHA1_BIN_LITERAL \ "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60" \ "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04" -#define EMPTY_TREE_SHA1_BIN \ - ((const unsigned char *) EMPTY_TREE_SHA1_BIN_LITERAL) +extern const struct object_id empty_tree_oid; +#define EMPTY_TREE_SHA1_BIN (empty_tree_oid.hash) #define EMPTY_BLOB_SHA1_HEX \ "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" #define EMPTY_BLOB_SHA1_BIN_LITERAL \ "\xe6\x9d\xe2\x9b\xb2\xd1\xd6\x43\x4b\x8b" \ "\x29\xae\x77\x5a\xd8\xc2\xe4\x8c\x53\x91" -#define EMPTY_BLOB_SHA1_BIN \ - ((const unsigned char *) EMPTY_BLOB_SHA1_BIN_LITERAL) +extern const struct object_id empty_blob_oid; +#define EMPTY_BLOB_SHA1_BIN (empty_blob_oid.hash) + static inline int is_empty_blob_sha1(const unsigned char *sha1) { return !hashcmp(sha1, EMPTY_BLOB_SHA1_BIN); } +static inline int is_empty_blob_oid(const struct object_id *oid) +{ + return !hashcmp(oid->hash, EMPTY_BLOB_SHA1_BIN); +} + +static inline int is_empty_tree_sha1(const unsigned char *sha1) +{ + return !hashcmp(sha1, EMPTY_TREE_SHA1_BIN); +} + +static inline int is_empty_tree_oid(const struct object_id *oid) +{ + return !hashcmp(oid->hash, EMPTY_TREE_SHA1_BIN); +} + + int git_mkstemp(char *path, size_t n, const char *template); /* set default permissions by passing mode arguments to open(2) */ @@ -1042,14 +1076,6 @@ char *strip_path_suffix(const char *path, const char *suffix); int daemon_avoid_alias(const char *path); extern int is_ntfs_dotgit(const char *name); -/* - * Returns true iff "str" could be confused as a command-line option when - * passed to a sub-program like "ssh". Note that this has nothing to do with - * shell-quoting, which should be handled separately; we're assuming here that - * the string makes it verbatim to the sub-program. - */ -int looks_like_command_line_option(const char *str); - /** * Return a newly allocated string with the evaluation of * "$XDG_CONFIG_HOME/git/$filename" if $XDG_CONFIG_HOME is non-empty, otherwise @@ -1099,7 +1125,7 @@ extern int write_sha1_file(const void *buf, unsigned long len, const char *type, extern int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type, unsigned char *sha1, unsigned flags); extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *); extern int force_object_loose(const unsigned char *sha1, time_t mtime); -extern int git_open_noatime(const char *name); +extern int git_open(const char *name); extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size); extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz); extern int parse_sha1_header(const char *hdr, unsigned long *sizep); @@ -1164,6 +1190,9 @@ static inline int hex2chr(const char *s) #define MINIMUM_ABBREV minimum_abbrev #define DEFAULT_ABBREV default_abbrev +/* used when the code does not know or care what the default abbrev is */ +#define FALLBACK_DEFAULT_ABBREV 7 + struct object_context { unsigned char tree[20]; char path[PATH_MAX]; @@ -1184,6 +1213,11 @@ struct object_context { #define GET_SHA1_FOLLOW_SYMLINKS 0100 #define GET_SHA1_ONLY_TO_DIE 04000 +#define GET_SHA1_DISAMBIGUATORS \ + (GET_SHA1_COMMIT | GET_SHA1_COMMITTISH | \ + GET_SHA1_TREE | GET_SHA1_TREEISH | \ + GET_SHA1_BLOB) + extern int get_sha1(const char *str, unsigned char *sha1); extern int get_sha1_commit(const char *str, unsigned char *sha1); extern int get_sha1_committish(const char *str, unsigned char *sha1); @@ -1198,6 +1232,8 @@ 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 *); +extern int set_disambiguate_hint_config(const char *var, const char *value); + /* * Try to read a SHA1 in hexadecimal format from the 40 characters * starting at hex. Write the 20-byte result to sha1 in binary form. @@ -1225,7 +1261,7 @@ extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */ extern char *oid_to_hex(const struct object_id *oid); /* same static buffer as sha1_to_hex */ extern int interpret_branch_name(const char *str, int len, struct strbuf *); -extern int get_sha1_mb(const char *str, unsigned char *sha1); +extern int get_oid_mb(const char *str, struct object_id *oid); extern int validate_headref(const char *ref); @@ -1335,6 +1371,7 @@ struct checkout { not_new:1, refresh_cache:1; }; +#define CHECKOUT_INIT { NULL, "" } #define TEMPORARY_FILENAME_LENGTH 25 extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath); @@ -1360,15 +1397,46 @@ extern void remove_scheduled_dirs(void); extern struct alternate_object_database { struct alternate_object_database *next; - char *name; - char base[FLEX_ARRAY]; /* more */ + + /* see alt_scratch_buf() */ + struct strbuf scratch; + size_t base_len; + + char path[FLEX_ARRAY]; } *alt_odb_list; extern void prepare_alt_odb(void); extern void read_info_alternates(const char * relative_base, int depth); -extern void add_to_alternates_file(const char *reference); +extern char *compute_alternate_path(const char *path, struct strbuf *err); typedef int alt_odb_fn(struct alternate_object_database *, void *); extern int foreach_alt_odb(alt_odb_fn, void*); +/* + * Allocate a "struct alternate_object_database" but do _not_ actually + * add it to the list of alternates. + */ +struct alternate_object_database *alloc_alt_odb(const char *dir); + +/* + * Add the directory to the on-disk alternates file; the new entry will also + * take effect in the current process. + */ +extern void add_to_alternates_file(const char *dir); + +/* + * Add the directory to the in-memory list of alternates (along with any + * recursive alternates it points to), but do not modify the on-disk alternates + * file. + */ +extern void add_to_alternates_memory(const char *dir); + +/* + * Returns a scratch strbuf pre-filled with the alternate object directory, + * including a trailing slash, which can be used to access paths in the + * alternate. Always use this over direct access to alt->scratch, as it + * cleans up any previous use of the scratch buffer. + */ +extern struct strbuf *alt_scratch_buf(struct alternate_object_database *alt); + struct pack_window { struct pack_window *next; unsigned char *base; @@ -1425,6 +1493,12 @@ extern void prepare_packed_git(void); extern void reprepare_packed_git(void); extern void install_packed_git(struct packed_git *pack); +/* + * Give a rough count of objects in the repository. This sacrifices accuracy + * for speed. + */ +unsigned long approximate_object_count(void); + extern struct packed_git *find_sha1_pack(const unsigned char *sha1, struct packed_git *packs); @@ -1571,7 +1645,15 @@ struct object_info { } packed; } u; }; + +/* + * Initializer for a "struct object_info" that wants no items. You may + * also memset() the memory to all-zeroes. + */ +#define OBJECT_INFO_INIT {NULL} + extern int sha1_object_info_extended(const unsigned char *, struct object_info *, unsigned flags); +extern int packed_object_info(struct packed_git *pack, off_t offset, struct object_info *); /* Dumb servers support */ extern int update_server_info(int); @@ -1806,7 +1888,6 @@ extern void write_file(const char *path, const char *fmt, ...); /* pager.c */ extern void setup_pager(void); -extern const char *pager_program; extern int pager_in_use(void); extern int pager_use_color; extern int term_columns(void); diff --git a/combine-diff.c b/combine-diff.c index 8e2a577..59501db 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -1203,9 +1203,9 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re /* Show sha1's */ for (i = 0; i < num_parent; i++) - printf(" %s", diff_unique_abbrev(p->parent[i].oid.hash, - opt->abbrev)); - printf(" %s ", diff_unique_abbrev(p->oid.hash, opt->abbrev)); + printf(" %s", diff_aligned_abbrev(&p->parent[i].oid, + opt->abbrev)); + printf(" %s ", diff_aligned_abbrev(&p->oid, opt->abbrev)); } if (opt->output_format & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS)) { diff --git a/commit.c b/commit.c index aada266..856fd4a 100644 --- a/commit.c +++ b/commit.c @@ -1511,9 +1511,9 @@ static int verify_utf8(struct strbuf *buf) } static const char commit_utf8_warn[] = -"Warning: commit message did not conform to UTF-8.\n" -"You may want to amend it after fixing the message, or set the config\n" -"variable i18n.commitencoding to the encoding your project uses.\n"; +N_("Warning: commit message did not conform to UTF-8.\n" + "You may want to amend it after fixing the message, or set the config\n" + "variable i18n.commitencoding to the encoding your project uses.\n"); int commit_tree_extended(const char *msg, size_t msg_len, const unsigned char *tree, @@ -1566,7 +1566,7 @@ int commit_tree_extended(const char *msg, size_t msg_len, /* And check the encoding */ if (encoding_is_utf8 && !verify_utf8(&buffer)) - fprintf(stderr, commit_utf8_warn); + fprintf(stderr, _(commit_utf8_warn)); if (sign_commit && do_sign_commit(&buffer, sign_commit)) return -1; diff --git a/commit.h b/commit.h index 32e1a11..afd14f3 100644 --- a/commit.h +++ b/commit.h @@ -267,6 +267,8 @@ extern int for_each_commit_graft(each_commit_graft_fn, void *); extern int is_repository_shallow(void); extern struct commit_list *get_shallow_commits(struct object_array *heads, int depth, int shallow_flag, int not_shallow_flag); +extern struct commit_list *get_shallow_commits_by_rev_list( + int ac, const char **av, int shallow_flag, int not_shallow_flag); extern void set_alternate_shallow_file(const char *path, int override); extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol, const struct sha1_array *extra); diff --git a/config.c b/config.c index 0dfed68..83fdecb 100644 --- a/config.c +++ b/config.c @@ -841,6 +841,9 @@ static int git_default_core_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.disambiguate")) + return set_disambiguate_hint_config(var, value); + if (!strcmp(var, "core.loosecompression")) { int level = git_config_int(var, value); if (level == -1) @@ -927,9 +930,6 @@ static int git_default_core_config(const char *var, const char *value) return 0; } - if (!strcmp(var, "core.pager")) - return git_config_string(&pager_program, var, value); - if (!strcmp(var, "core.editor")) return git_config_string(&editor_program, var, value); @@ -1289,7 +1289,7 @@ static int do_git_config_sequence(config_fn_t fn, void *data) int ret = 0; char *xdg_config = xdg_config_home("config"); char *user_config = expand_user_path("~/.gitconfig"); - char *repo_config = git_pathdup("config"); + char *repo_config = have_git_dir() ? git_pathdup("config") : NULL; current_parsing_scope = CONFIG_SCOPE_SYSTEM; if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) diff --git a/connect.c b/connect.c index 048fa04..8cb93b0 100644 --- a/connect.c +++ b/connect.c @@ -43,14 +43,14 @@ int check_ref_type(const struct ref *ref, int flags) return check_ref(ref->name, flags); } -static void die_initial_contact(int got_at_least_one_head) +static void die_initial_contact(int unexpected) { - if (got_at_least_one_head) - die("The remote end hung up upon initial contact"); + if (unexpected) + die(_("The remote end hung up upon initial contact")); else - die("Could not read from remote repository.\n\n" - "Please make sure you have the correct access rights\n" - "and the repository exists."); + die(_("Could not read from remote repository.\n\n" + "Please make sure you have the correct access rights\n" + "and the repository exists.")); } static void parse_one_symref_info(struct string_list *symref, const char *val, int len) @@ -115,10 +115,18 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t src_len, struct sha1_array *shallow_points) { struct ref **orig_list = list; - int got_at_least_one_head = 0; + + /* + * A hang-up after seeing some response from the other end + * means that it is unexpected, as we know the other end is + * willing to talk to us. A hang-up before seeing any + * response does not necessarily mean an ACL problem, though. + */ + int saw_response; + int got_dummy_ref_with_capabilities_declaration = 0; *list = NULL; - for (;;) { + for (saw_response = 0; ; saw_response = 1) { struct ref *ref; struct object_id old_oid; char *name; @@ -131,7 +139,7 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t src_len, PACKET_READ_GENTLE_ON_EOF | PACKET_READ_CHOMP_NEWLINE); if (len < 0) - die_initial_contact(got_at_least_one_head); + die_initial_contact(saw_response); if (!len) break; @@ -165,13 +173,25 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t src_len, continue; } + if (!strcmp(name, "capabilities^{}")) { + if (saw_response) + die("protocol error: unexpected capabilities^{}"); + if (got_dummy_ref_with_capabilities_declaration) + die("protocol error: multiple capabilities^{}"); + got_dummy_ref_with_capabilities_declaration = 1; + continue; + } + if (!check_ref(name, flags)) continue; + + if (got_dummy_ref_with_capabilities_declaration) + die("protocol error: unexpected ref after capabilities^{}"); + ref = alloc_ref(buffer + GIT_SHA1_HEXSZ + 1); oidcpy(&ref->old_oid, &old_oid); *list = ref; list = &ref->next; - got_at_least_one_head = 1; } annotate_refs_with_symref_info(*orig_list); @@ -557,11 +577,6 @@ static struct child_process *git_proxy_connect(int fd[2], char *host) get_host_and_port(&host, &port); - if (looks_like_command_line_option(host)) - die("strange hostname '%s' blocked", host); - if (looks_like_command_line_option(port)) - die("strange port '%s' blocked", port); - proxy = xmalloc(sizeof(*proxy)); child_process_init(proxy); argv_array_push(&proxy->args, git_proxy_command); @@ -735,7 +750,7 @@ struct child_process *git_connect(int fd[2], const char *url, * Note: Do not add any other headers here! Doing so * will cause older git-daemon servers to crash. */ - packet_write(fd[1], + packet_write_fmt(fd[1], "%s %s%chost=%s%c", prog, path, 0, target_host, 0); @@ -744,9 +759,6 @@ struct child_process *git_connect(int fd[2], const char *url, conn = xmalloc(sizeof(*conn)); child_process_init(conn); - if (looks_like_command_line_option(path)) - die("strange pathname '%s' blocked", path); - strbuf_addstr(&cmd, prog); strbuf_addch(&cmd, ' '); sq_quote_buf(&cmd, path); @@ -779,9 +791,6 @@ struct child_process *git_connect(int fd[2], const char *url, return NULL; } - if (looks_like_command_line_option(ssh_host)) - die("strange hostname '%s' blocked", ssh_host); - ssh = get_ssh_command(); if (!ssh) { const char *base; diff --git a/connected.c b/connected.c index 8e3e4b1..136c2ac 100644 --- a/connected.c +++ b/connected.c @@ -63,6 +63,7 @@ int check_connected(sha1_iterate_fn fn, void *cb_data, _("Checking connectivity")); rev_list.git_cmd = 1; + rev_list.env = opt->env; rev_list.in = -1; rev_list.no_stdout = 1; if (opt->err_fd) diff --git a/connected.h b/connected.h index afa48cc..4ca325f 100644 --- a/connected.h +++ b/connected.h @@ -33,6 +33,11 @@ struct check_connected_options { /* If non-zero, show progress as we traverse the objects. */ int progress; + + /* + * Insert these variables into the environment of the child process. + */ + const char **env; }; #define CHECK_CONNECTED_INIT { 0 } diff --git a/contrib/coccinelle/qsort.cocci b/contrib/coccinelle/qsort.cocci new file mode 100644 index 0000000..22b93a9 --- /dev/null +++ b/contrib/coccinelle/qsort.cocci @@ -0,0 +1,37 @@ +@@ +expression base, nmemb, compar; +@@ +- qsort(base, nmemb, sizeof(*base), compar); ++ QSORT(base, nmemb, compar); + +@@ +expression base, nmemb, compar; +@@ +- qsort(base, nmemb, sizeof(base[0]), compar); ++ QSORT(base, nmemb, compar); + +@@ +type T; +T *base; +expression nmemb, compar; +@@ +- qsort(base, nmemb, sizeof(T), compar); ++ QSORT(base, nmemb, compar); + +@@ +expression base, nmemb, compar; +@@ +- if (nmemb) + QSORT(base, nmemb, compar); + +@@ +expression base, nmemb, compar; +@@ +- if (nmemb > 0) + QSORT(base, nmemb, compar); + +@@ +expression base, nmemb, compar; +@@ +- if (nmemb > 1) + QSORT(base, nmemb, compar); diff --git a/contrib/credential/libsecret/Makefile b/contrib/credential/libsecret/Makefile new file mode 100644 index 0000000..3e67552 --- /dev/null +++ b/contrib/credential/libsecret/Makefile @@ -0,0 +1,25 @@ +MAIN:=git-credential-libsecret +all:: $(MAIN) + +CC = gcc +RM = rm -f +CFLAGS = -g -O2 -Wall +PKG_CONFIG = pkg-config + +-include ../../../config.mak.autogen +-include ../../../config.mak + +INCS:=$(shell $(PKG_CONFIG) --cflags libsecret-1 glib-2.0) +LIBS:=$(shell $(PKG_CONFIG) --libs libsecret-1 glib-2.0) + +SRCS:=$(MAIN).c +OBJS:=$(SRCS:.c=.o) + +%.o: %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(INCS) -o $@ -c $< + +$(MAIN): $(OBJS) + $(CC) -o $@ $(LDFLAGS) $^ $(LIBS) + +clean: + @$(RM) $(MAIN) $(OBJS) diff --git a/contrib/credential/libsecret/git-credential-libsecret.c b/contrib/credential/libsecret/git-credential-libsecret.c new file mode 100644 index 0000000..4c56979 --- /dev/null +++ b/contrib/credential/libsecret/git-credential-libsecret.c @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2011 John Szakmeister + * 2012 Philipp A. Hartmann + * 2016 Mantas Mikulėnas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Credits: + * - GNOME Keyring API handling originally written by John Szakmeister + * - ported to credential helper API by Philipp A. Hartmann + */ + +#include +#include +#include +#include +#include + +/* + * This credential struct and API is simplified from git's credential.{h,c} + */ +struct credential { + char *protocol; + char *host; + unsigned short port; + char *path; + char *username; + char *password; +}; + +#define CREDENTIAL_INIT { NULL, NULL, 0, NULL, NULL, NULL } + +typedef int (*credential_op_cb)(struct credential *); + +struct credential_operation { + char *name; + credential_op_cb op; +}; + +#define CREDENTIAL_OP_END { NULL, NULL } + +/* ----------------- Secret Service functions ----------------- */ + +static char *make_label(struct credential *c) +{ + if (c->port) + return g_strdup_printf("Git: %s://%s:%hu/%s", + c->protocol, c->host, c->port, c->path ? c->path : ""); + else + return g_strdup_printf("Git: %s://%s/%s", + c->protocol, c->host, c->path ? c->path : ""); +} + +static GHashTable *make_attr_list(struct credential *c) +{ + GHashTable *al = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); + + if (c->username) + g_hash_table_insert(al, "user", g_strdup(c->username)); + if (c->protocol) + g_hash_table_insert(al, "protocol", g_strdup(c->protocol)); + if (c->host) + g_hash_table_insert(al, "server", g_strdup(c->host)); + if (c->port) + g_hash_table_insert(al, "port", g_strdup_printf("%hu", c->port)); + if (c->path) + g_hash_table_insert(al, "object", g_strdup(c->path)); + + return al; +} + +static int keyring_get(struct credential *c) +{ + SecretService *service = NULL; + GHashTable *attributes = NULL; + GError *error = NULL; + GList *items = NULL; + + if (!c->protocol || !(c->host || c->path)) + return EXIT_FAILURE; + + service = secret_service_get_sync(0, NULL, &error); + if (error != NULL) { + g_critical("could not connect to Secret Service: %s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + + attributes = make_attr_list(c); + items = secret_service_search_sync(service, + SECRET_SCHEMA_COMPAT_NETWORK, + attributes, + SECRET_SEARCH_LOAD_SECRETS, + NULL, + &error); + g_hash_table_unref(attributes); + if (error != NULL) { + g_critical("lookup failed: %s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + + if (items != NULL) { + SecretItem *item; + SecretValue *secret; + const char *s; + + item = items->data; + secret = secret_item_get_secret(item); + attributes = secret_item_get_attributes(item); + + s = g_hash_table_lookup(attributes, "user"); + if (s) { + g_free(c->username); + c->username = g_strdup(s); + } + + s = secret_value_get_text(secret); + if (s) { + g_free(c->password); + c->password = g_strdup(s); + } + + g_hash_table_unref(attributes); + secret_value_unref(secret); + g_list_free_full(items, g_object_unref); + } + + return EXIT_SUCCESS; +} + + +static int keyring_store(struct credential *c) +{ + char *label = NULL; + GHashTable *attributes = NULL; + GError *error = NULL; + + /* + * Sanity check that what we are storing is actually sensible. + * In particular, we can't make a URL without a protocol field. + * Without either a host or pathname (depending on the scheme), + * we have no primary key. And without a username and password, + * we are not actually storing a credential. + */ + if (!c->protocol || !(c->host || c->path) || + !c->username || !c->password) + return EXIT_FAILURE; + + label = make_label(c); + attributes = make_attr_list(c); + secret_password_storev_sync(SECRET_SCHEMA_COMPAT_NETWORK, + attributes, + NULL, + label, + c->password, + NULL, + &error); + g_free(label); + g_hash_table_unref(attributes); + + if (error != NULL) { + g_critical("store failed: %s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static int keyring_erase(struct credential *c) +{ + GHashTable *attributes = NULL; + GError *error = NULL; + + /* + * Sanity check that we actually have something to match + * against. The input we get is a restrictive pattern, + * so technically a blank credential means "erase everything". + * But it is too easy to accidentally send this, since it is equivalent + * to empty input. So explicitly disallow it, and require that the + * pattern have some actual content to match. + */ + if (!c->protocol && !c->host && !c->path && !c->username) + return EXIT_FAILURE; + + attributes = make_attr_list(c); + secret_password_clearv_sync(SECRET_SCHEMA_COMPAT_NETWORK, + attributes, + NULL, + &error); + g_hash_table_unref(attributes); + + if (error != NULL) { + g_critical("erase failed: %s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +/* + * Table with helper operation callbacks, used by generic + * credential helper main function. + */ +static struct credential_operation const credential_helper_ops[] = { + { "get", keyring_get }, + { "store", keyring_store }, + { "erase", keyring_erase }, + CREDENTIAL_OP_END +}; + +/* ------------------ credential functions ------------------ */ + +static void credential_init(struct credential *c) +{ + memset(c, 0, sizeof(*c)); +} + +static void credential_clear(struct credential *c) +{ + g_free(c->protocol); + g_free(c->host); + g_free(c->path); + g_free(c->username); + g_free(c->password); + + credential_init(c); +} + +static int credential_read(struct credential *c) +{ + char *buf; + size_t line_len; + char *key; + char *value; + + key = buf = g_malloc(1024); + + while (fgets(buf, 1024, stdin)) { + line_len = strlen(buf); + + if (line_len && buf[line_len-1] == '\n') + buf[--line_len] = '\0'; + + if (!line_len) + break; + + value = strchr(buf, '='); + if (!value) { + g_warning("invalid credential line: %s", key); + g_free(buf); + return -1; + } + *value++ = '\0'; + + if (!strcmp(key, "protocol")) { + g_free(c->protocol); + c->protocol = g_strdup(value); + } else if (!strcmp(key, "host")) { + g_free(c->host); + c->host = g_strdup(value); + value = strrchr(c->host, ':'); + if (value) { + *value++ = '\0'; + c->port = atoi(value); + } + } else if (!strcmp(key, "path")) { + g_free(c->path); + c->path = g_strdup(value); + } else if (!strcmp(key, "username")) { + g_free(c->username); + c->username = g_strdup(value); + } else if (!strcmp(key, "password")) { + g_free(c->password); + c->password = g_strdup(value); + while (*value) + *value++ = '\0'; + } + /* + * Ignore other lines; we don't know what they mean, but + * this future-proofs us when later versions of git do + * learn new lines, and the helpers are updated to match. + */ + } + + g_free(buf); + + return 0; +} + +static void credential_write_item(FILE *fp, const char *key, const char *value) +{ + if (!value) + return; + fprintf(fp, "%s=%s\n", key, value); +} + +static void credential_write(const struct credential *c) +{ + /* only write username/password, if set */ + credential_write_item(stdout, "username", c->username); + credential_write_item(stdout, "password", c->password); +} + +static void usage(const char *name) +{ + struct credential_operation const *try_op = credential_helper_ops; + const char *basename = strrchr(name, '/'); + + basename = (basename) ? basename + 1 : name; + fprintf(stderr, "usage: %s <", basename); + while (try_op->name) { + fprintf(stderr, "%s", (try_op++)->name); + if (try_op->name) + fprintf(stderr, "%s", "|"); + } + fprintf(stderr, "%s", ">\n"); +} + +int main(int argc, char *argv[]) +{ + int ret = EXIT_SUCCESS; + + struct credential_operation const *try_op = credential_helper_ops; + struct credential cred = CREDENTIAL_INIT; + + if (!argv[1]) { + usage(argv[0]); + exit(EXIT_FAILURE); + } + + g_set_application_name("Git Credential Helper"); + + /* lookup operation callback */ + while (try_op->name && strcmp(argv[1], try_op->name)) + try_op++; + + /* unsupported operation given -- ignore silently */ + if (!try_op->name || !try_op->op) + goto out; + + ret = credential_read(&cred); + if (ret) + goto out; + + /* perform credential operation */ + ret = (*try_op->op)(&cred); + + credential_write(&cred); + +out: + credential_clear(&cred); + return ret; +} diff --git a/contrib/long-running-filter/example.pl b/contrib/long-running-filter/example.pl new file mode 100755 index 0000000..3945705 --- /dev/null +++ b/contrib/long-running-filter/example.pl @@ -0,0 +1,128 @@ +#!/usr/bin/perl +# +# Example implementation for the Git filter protocol version 2 +# See Documentation/gitattributes.txt, section "Filter Protocol" +# +# Please note, this pass-thru filter is a minimal skeleton. No proper +# error handling was implemented. +# + +use strict; +use warnings; + +my $MAX_PACKET_CONTENT_SIZE = 65516; + +sub packet_bin_read { + my $buffer; + my $bytes_read = read STDIN, $buffer, 4; + if ( $bytes_read == 0 ) { + + # EOF - Git stopped talking to us! + exit(); + } + elsif ( $bytes_read != 4 ) { + die "invalid packet: '$buffer'"; + } + my $pkt_size = hex($buffer); + if ( $pkt_size == 0 ) { + return ( 1, "" ); + } + elsif ( $pkt_size > 4 ) { + my $content_size = $pkt_size - 4; + $bytes_read = read STDIN, $buffer, $content_size; + if ( $bytes_read != $content_size ) { + die "invalid packet ($content_size bytes expected; $bytes_read bytes read)"; + } + return ( 0, $buffer ); + } + else { + die "invalid packet size: $pkt_size"; + } +} + +sub packet_txt_read { + my ( $res, $buf ) = packet_bin_read(); + unless ( $buf =~ s/\n$// ) { + die "A non-binary line MUST be terminated by an LF."; + } + return ( $res, $buf ); +} + +sub packet_bin_write { + my $buf = shift; + print STDOUT sprintf( "%04x", length($buf) + 4 ); + print STDOUT $buf; + STDOUT->flush(); +} + +sub packet_txt_write { + packet_bin_write( $_[0] . "\n" ); +} + +sub packet_flush { + print STDOUT sprintf( "%04x", 0 ); + STDOUT->flush(); +} + +( packet_txt_read() eq ( 0, "git-filter-client" ) ) || die "bad initialize"; +( packet_txt_read() eq ( 0, "version=2" ) ) || die "bad version"; +( packet_bin_read() eq ( 1, "" ) ) || die "bad version end"; + +packet_txt_write("git-filter-server"); +packet_txt_write("version=2"); +packet_flush(); + +( packet_txt_read() eq ( 0, "capability=clean" ) ) || die "bad capability"; +( packet_txt_read() eq ( 0, "capability=smudge" ) ) || die "bad capability"; +( packet_bin_read() eq ( 1, "" ) ) || die "bad capability end"; + +packet_txt_write("capability=clean"); +packet_txt_write("capability=smudge"); +packet_flush(); + +while (1) { + my ($command) = packet_txt_read() =~ /^command=([^=]+)$/; + my ($pathname) = packet_txt_read() =~ /^pathname=([^=]+)$/; + + packet_bin_read(); + + my $input = ""; + { + binmode(STDIN); + my $buffer; + my $done = 0; + while ( !$done ) { + ( $done, $buffer ) = packet_bin_read(); + $input .= $buffer; + } + } + + my $output; + if ( $command eq "clean" ) { + ### Perform clean here ### + $output = $input; + } + elsif ( $command eq "smudge" ) { + ### Perform smudge here ### + $output = $input; + } + else { + die "bad command '$command'"; + } + + packet_txt_write("status=success"); + packet_flush(); + while ( length($output) > 0 ) { + my $packet = substr( $output, 0, $MAX_PACKET_CONTENT_SIZE ); + packet_bin_write($packet); + if ( length($output) > $MAX_PACKET_CONTENT_SIZE ) { + $output = substr( $output, $MAX_PACKET_CONTENT_SIZE ); + } + else { + $output = ""; + } + } + packet_flush(); # flush content! + packet_flush(); # empty list, keep "status=success" unchanged! + +} diff --git a/convert.c b/convert.c index 077f5e6..be91358 100644 --- a/convert.c +++ b/convert.c @@ -3,6 +3,7 @@ #include "run-command.h" #include "quote.h" #include "sigchain.h" +#include "pkt-line.h" /* * convert.c - convert a file when checking it out and checking it in. @@ -197,17 +198,21 @@ static void check_safe_crlf(const char *path, enum crlf_action crlf_action, * CRLFs would not be restored by checkout */ if (checksafe == SAFE_CRLF_WARN) - warning("CRLF will be replaced by LF in %s.\nThe file will have its original line endings in your working directory.", path); + warning(_("CRLF will be replaced by LF in %s.\n" + "The file will have its original line" + " endings in your working directory."), path); else /* i.e. SAFE_CRLF_FAIL */ - die("CRLF would be replaced by LF in %s.", path); + die(_("CRLF would be replaced by LF in %s."), path); } else if (old_stats->lonelf && !new_stats->lonelf ) { /* * CRLFs would be added by checkout */ if (checksafe == SAFE_CRLF_WARN) - warning("LF will be replaced by CRLF in %s.\nThe file will have its original line endings in your working directory.", path); + warning(_("LF will be replaced by CRLF in %s.\n" + "The file will have its original line" + " endings in your working directory."), path); else /* i.e. SAFE_CRLF_FAIL */ - die("LF would be replaced by CRLF in %s", path); + die(_("LF would be replaced by CRLF in %s"), path); } } @@ -412,7 +417,7 @@ static int filter_buffer_or_fd(int in, int out, void *data) child_process.out = out; if (start_command(&child_process)) - return error("cannot fork to run external filter %s", params->cmd); + return error("cannot fork to run external filter '%s'", params->cmd); sigchain_push(SIGPIPE, SIG_IGN); @@ -430,19 +435,19 @@ static int filter_buffer_or_fd(int in, int out, void *data) if (close(child_process.in)) write_err = 1; if (write_err) - error("cannot feed the input to external filter %s", params->cmd); + error("cannot feed the input to external filter '%s'", params->cmd); sigchain_pop(SIGPIPE); status = finish_command(&child_process); if (status) - error("external filter %s failed %d", params->cmd, status); + error("external filter '%s' failed %d", params->cmd, status); strbuf_release(&cmd); return (write_err || status); } -static int apply_filter(const char *path, const char *src, size_t len, int fd, +static int apply_single_file_filter(const char *path, const char *src, size_t len, int fd, struct strbuf *dst, const char *cmd) { /* @@ -451,17 +456,11 @@ static int apply_filter(const char *path, const char *src, size_t len, int fd, * * (child --> cmd) --> us */ - int ret = 1; + int err = 0; struct strbuf nbuf = STRBUF_INIT; struct async async; struct filter_params params; - if (!cmd || !*cmd) - return 0; - - if (!dst) - return 1; - memset(&async, 0, sizeof(async)); async.proc = filter_buffer_or_fd; async.data = ¶ms; @@ -477,23 +476,304 @@ static int apply_filter(const char *path, const char *src, size_t len, int fd, return 0; /* error was already reported */ if (strbuf_read(&nbuf, async.out, len) < 0) { - error("read from external filter %s failed", cmd); - ret = 0; + err = error("read from external filter '%s' failed", cmd); } if (close(async.out)) { - error("read from external filter %s failed", cmd); - ret = 0; + err = error("read from external filter '%s' failed", cmd); } if (finish_async(&async)) { - error("external filter %s failed", cmd); - ret = 0; + err = error("external filter '%s' failed", cmd); } - if (ret) { + if (!err) { strbuf_swap(dst, &nbuf); } strbuf_release(&nbuf); - return ret; + return !err; +} + +#define CAP_CLEAN (1u<<0) +#define CAP_SMUDGE (1u<<1) + +struct cmd2process { + struct hashmap_entry ent; /* must be the first member! */ + unsigned int supported_capabilities; + const char *cmd; + struct child_process process; +}; + +static int cmd_process_map_initialized; +static struct hashmap cmd_process_map; + +static int cmd2process_cmp(const struct cmd2process *e1, + const struct cmd2process *e2, + const void *unused) +{ + return strcmp(e1->cmd, e2->cmd); +} + +static struct cmd2process *find_multi_file_filter_entry(struct hashmap *hashmap, const char *cmd) +{ + struct cmd2process key; + hashmap_entry_init(&key, strhash(cmd)); + key.cmd = cmd; + return hashmap_get(hashmap, &key, NULL); +} + +static int packet_write_list(int fd, const char *line, ...) +{ + va_list args; + int err; + va_start(args, line); + for (;;) { + if (!line) + break; + if (strlen(line) > LARGE_PACKET_DATA_MAX) + return -1; + err = packet_write_fmt_gently(fd, "%s\n", line); + if (err) + return err; + line = va_arg(args, const char*); + } + va_end(args); + return packet_flush_gently(fd); +} + +static void read_multi_file_filter_status(int fd, struct strbuf *status) +{ + struct strbuf **pair; + char *line; + for (;;) { + line = packet_read_line(fd, NULL); + if (!line) + break; + pair = strbuf_split_str(line, '=', 2); + if (pair[0] && pair[0]->len && pair[1]) { + /* the last "status=" line wins */ + if (!strcmp(pair[0]->buf, "status=")) { + strbuf_reset(status); + strbuf_addbuf(status, pair[1]); + } + } + strbuf_list_free(pair); + } +} + +static void kill_multi_file_filter(struct hashmap *hashmap, struct cmd2process *entry) +{ + if (!entry) + return; + + entry->process.clean_on_exit = 0; + kill(entry->process.pid, SIGTERM); + finish_command(&entry->process); + + hashmap_remove(hashmap, entry, NULL); + free(entry); +} + +static void stop_multi_file_filter(struct child_process *process) +{ + sigchain_push(SIGPIPE, SIG_IGN); + /* Closing the pipe signals the filter to initiate a shutdown. */ + close(process->in); + close(process->out); + sigchain_pop(SIGPIPE); + /* Finish command will wait until the shutdown is complete. */ + finish_command(process); +} + +static struct cmd2process *start_multi_file_filter(struct hashmap *hashmap, const char *cmd) +{ + int err; + struct cmd2process *entry; + struct child_process *process; + const char *argv[] = { cmd, NULL }; + struct string_list cap_list = STRING_LIST_INIT_NODUP; + char *cap_buf; + const char *cap_name; + + entry = xmalloc(sizeof(*entry)); + entry->cmd = cmd; + entry->supported_capabilities = 0; + process = &entry->process; + + child_process_init(process); + process->argv = argv; + process->use_shell = 1; + process->in = -1; + process->out = -1; + process->clean_on_exit = 1; + process->clean_on_exit_handler = stop_multi_file_filter; + + if (start_command(process)) { + error("cannot fork to run external filter '%s'", cmd); + return NULL; + } + + hashmap_entry_init(entry, strhash(cmd)); + + sigchain_push(SIGPIPE, SIG_IGN); + + err = packet_write_list(process->in, "git-filter-client", "version=2", NULL); + if (err) + goto done; + + err = strcmp(packet_read_line(process->out, NULL), "git-filter-server"); + if (err) { + error("external filter '%s' does not support filter protocol version 2", cmd); + goto done; + } + err = strcmp(packet_read_line(process->out, NULL), "version=2"); + if (err) + goto done; + err = packet_read_line(process->out, NULL) != NULL; + if (err) + goto done; + + err = packet_write_list(process->in, "capability=clean", "capability=smudge", NULL); + + for (;;) { + cap_buf = packet_read_line(process->out, NULL); + if (!cap_buf) + break; + string_list_split_in_place(&cap_list, cap_buf, '=', 1); + + if (cap_list.nr != 2 || strcmp(cap_list.items[0].string, "capability")) + continue; + + cap_name = cap_list.items[1].string; + if (!strcmp(cap_name, "clean")) { + entry->supported_capabilities |= CAP_CLEAN; + } else if (!strcmp(cap_name, "smudge")) { + entry->supported_capabilities |= CAP_SMUDGE; + } else { + warning( + "external filter '%s' requested unsupported filter capability '%s'", + cmd, cap_name + ); + } + + string_list_clear(&cap_list, 0); + } + +done: + sigchain_pop(SIGPIPE); + + if (err || errno == EPIPE) { + error("initialization for external filter '%s' failed", cmd); + kill_multi_file_filter(hashmap, entry); + return NULL; + } + + hashmap_add(hashmap, entry); + return entry; +} + +static int apply_multi_file_filter(const char *path, const char *src, size_t len, + int fd, struct strbuf *dst, const char *cmd, + const unsigned int wanted_capability) +{ + int err; + struct cmd2process *entry; + struct child_process *process; + struct strbuf nbuf = STRBUF_INIT; + struct strbuf filter_status = STRBUF_INIT; + const char *filter_type; + + if (!cmd_process_map_initialized) { + cmd_process_map_initialized = 1; + hashmap_init(&cmd_process_map, (hashmap_cmp_fn) cmd2process_cmp, 0); + entry = NULL; + } else { + entry = find_multi_file_filter_entry(&cmd_process_map, cmd); + } + + fflush(NULL); + + if (!entry) { + entry = start_multi_file_filter(&cmd_process_map, cmd); + if (!entry) + return 0; + } + process = &entry->process; + + if (!(wanted_capability & entry->supported_capabilities)) + return 0; + + if (CAP_CLEAN & wanted_capability) + filter_type = "clean"; + else if (CAP_SMUDGE & wanted_capability) + filter_type = "smudge"; + else + die("unexpected filter type"); + + sigchain_push(SIGPIPE, SIG_IGN); + + assert(strlen(filter_type) < LARGE_PACKET_DATA_MAX - strlen("command=\n")); + err = packet_write_fmt_gently(process->in, "command=%s\n", filter_type); + if (err) + goto done; + + err = strlen(path) > LARGE_PACKET_DATA_MAX - strlen("pathname=\n"); + if (err) { + error("path name too long for external filter"); + goto done; + } + + err = packet_write_fmt_gently(process->in, "pathname=%s\n", path); + if (err) + goto done; + + err = packet_flush_gently(process->in); + if (err) + goto done; + + if (fd >= 0) + err = write_packetized_from_fd(fd, process->in); + else + err = write_packetized_from_buf(src, len, process->in); + if (err) + goto done; + + read_multi_file_filter_status(process->out, &filter_status); + err = strcmp(filter_status.buf, "success"); + if (err) + goto done; + + err = read_packetized_to_strbuf(process->out, &nbuf) < 0; + if (err) + goto done; + + read_multi_file_filter_status(process->out, &filter_status); + err = strcmp(filter_status.buf, "success"); + +done: + sigchain_pop(SIGPIPE); + + if (err || errno == EPIPE) { + if (!strcmp(filter_status.buf, "error")) { + /* The filter signaled a problem with the file. */ + } else if (!strcmp(filter_status.buf, "abort")) { + /* + * The filter signaled a permanent problem. Don't try to filter + * files with the same command for the lifetime of the current + * Git process. + */ + entry->supported_capabilities &= ~wanted_capability; + } else { + /* + * Something went wrong with the protocol filter. + * Force shutdown and restart if another blob requires filtering. + */ + error("external filter '%s' failed", cmd); + kill_multi_file_filter(&cmd_process_map, entry); + } + } else { + strbuf_swap(dst, &nbuf); + } + strbuf_release(&nbuf); + return !err; } static struct convert_driver { @@ -501,9 +781,35 @@ static struct convert_driver { struct convert_driver *next; const char *smudge; const char *clean; + const char *process; int required; } *user_convert, **user_convert_tail; +static int apply_filter(const char *path, const char *src, size_t len, + int fd, struct strbuf *dst, struct convert_driver *drv, + const unsigned int wanted_capability) +{ + const char *cmd = NULL; + + if (!drv) + return 0; + + if (!dst) + return 1; + + if ((CAP_CLEAN & wanted_capability) && !drv->process && drv->clean) + cmd = drv->clean; + else if ((CAP_SMUDGE & wanted_capability) && !drv->process && drv->smudge) + cmd = drv->smudge; + + if (cmd && *cmd) + return apply_single_file_filter(path, src, len, fd, dst, cmd); + else if (drv->process && *drv->process) + return apply_multi_file_filter(path, src, len, fd, dst, drv->process, wanted_capability); + + return 0; +} + static int read_convert_config(const char *var, const char *value, void *cb) { const char *key, *name; @@ -541,6 +847,9 @@ static int read_convert_config(const char *var, const char *value, void *cb) if (!strcmp("clean", key)) return git_config_string(&drv->clean, var, value); + if (!strcmp("process", key)) + return git_config_string(&drv->process, var, value); + if (!strcmp("required", key)) { drv->required = git_config_bool(var, value); return 0; @@ -842,7 +1151,7 @@ int would_convert_to_git_filter_fd(const char *path) if (!ca.drv->required) return 0; - return apply_filter(path, NULL, 0, -1, NULL, ca.drv->clean); + return apply_filter(path, NULL, 0, -1, NULL, ca.drv, CAP_CLEAN); } const char *get_convert_attr_ascii(const char *path) @@ -875,18 +1184,12 @@ int convert_to_git(const char *path, const char *src, size_t len, struct strbuf *dst, enum safe_crlf checksafe) { int ret = 0; - const char *filter = NULL; - int required = 0; struct conv_attrs ca; convert_attrs(&ca, path); - if (ca.drv) { - filter = ca.drv->clean; - required = ca.drv->required; - } - ret |= apply_filter(path, src, len, -1, dst, filter); - if (!ret && required) + ret |= apply_filter(path, src, len, -1, dst, ca.drv, CAP_CLEAN); + if (!ret && ca.drv && ca.drv->required) die("%s: clean filter '%s' failed", path, ca.drv->name); if (ret && dst) { @@ -908,9 +1211,9 @@ void convert_to_git_filter_fd(const char *path, int fd, struct strbuf *dst, convert_attrs(&ca, path); assert(ca.drv); - assert(ca.drv->clean); + assert(ca.drv->clean || ca.drv->process); - if (!apply_filter(path, NULL, 0, fd, dst, ca.drv->clean)) + if (!apply_filter(path, NULL, 0, fd, dst, ca.drv, CAP_CLEAN)) die("%s: clean filter '%s' failed", path, ca.drv->name); crlf_to_git(path, dst->buf, dst->len, dst, ca.crlf_action, checksafe); @@ -922,15 +1225,9 @@ static int convert_to_working_tree_internal(const char *path, const char *src, int normalizing) { int ret = 0, ret_filter = 0; - const char *filter = NULL; - int required = 0; struct conv_attrs ca; convert_attrs(&ca, path); - if (ca.drv) { - filter = ca.drv->smudge; - required = ca.drv->required; - } ret |= ident_to_worktree(path, src, len, dst, ca.ident); if (ret) { @@ -939,9 +1236,10 @@ static int convert_to_working_tree_internal(const char *path, const char *src, } /* * CRLF conversion can be skipped if normalizing, unless there - * is a smudge filter. The filter might expect CRLFs. + * is a smudge or process filter (even if the process filter doesn't + * support smudge). The filters might expect CRLFs. */ - if (filter || !normalizing) { + if ((ca.drv && (ca.drv->smudge || ca.drv->process)) || !normalizing) { ret |= crlf_to_worktree(path, src, len, dst, ca.crlf_action); if (ret) { src = dst->buf; @@ -949,8 +1247,8 @@ static int convert_to_working_tree_internal(const char *path, const char *src, } } - ret_filter = apply_filter(path, src, len, -1, dst, filter); - if (!ret_filter && required) + ret_filter = apply_filter(path, src, len, -1, dst, ca.drv, CAP_SMUDGE); + if (!ret_filter && ca.drv && ca.drv->required) die("%s: smudge filter %s failed", path, ca.drv->name); return ret | ret_filter; @@ -1402,7 +1700,7 @@ struct stream_filter *get_stream_filter(const char *path, const unsigned char *s struct stream_filter *filter = NULL; convert_attrs(&ca, path); - if (ca.drv && (ca.drv->smudge || ca.drv->clean)) + if (ca.drv && (ca.drv->process || ca.drv->smudge || ca.drv->clean)) return NULL; if (ca.crlf_action == CRLF_AUTO || ca.crlf_action == CRLF_AUTO_CRLF) diff --git a/credential-cache--daemon.c b/credential-cache--daemon.c index 1e5f16a..46c5937 100644 --- a/credential-cache--daemon.c +++ b/credential-cache--daemon.c @@ -219,11 +219,11 @@ static void serve_cache(const char *socket_path, int debug) close(fd); } -static const char permissions_advice[] = +static const char permissions_advice[] = N_( "The permissions on your socket directory are too loose; other\n" "users may be able to read your cached credentials. Consider running:\n" "\n" -" chmod 0700 %s"; +" chmod 0700 %s"); static void init_socket_directory(const char *path) { struct stat st; @@ -232,7 +232,7 @@ static void init_socket_directory(const char *path) if (!stat(dir, &st)) { if (st.st_mode & 077) - die(permissions_advice, dir); + die(_(permissions_advice), dir); } else { /* * We must be sure to create the directory with the correct mode, diff --git a/daemon.c b/daemon.c index ff0fa58..473e6b6 100644 --- a/daemon.c +++ b/daemon.c @@ -298,7 +298,7 @@ static int daemon_error(const char *dir, const char *msg) { if (!informative_errors) msg = "access denied or repository not exported"; - packet_write(1, "ERR %s: %s", msg, dir); + packet_write_fmt(1, "ERR %s: %s", msg, dir); return -1; } diff --git a/diff-lib.c b/diff-lib.c index bc49c70..5244746 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -155,7 +155,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option) if (2 <= stage) { int mode = nce->ce_mode; num_compare_stages++; - hashcpy(dpath->parent[stage-2].oid.hash, nce->sha1); + oidcpy(&dpath->parent[stage - 2].oid, + &nce->oid); dpath->parent[stage-2].mode = ce_mode_from_stat(nce, mode); dpath->parent[stage-2].status = DIFF_STATUS_MODIFIED; @@ -209,7 +210,14 @@ int run_diff_files(struct rev_info *revs, unsigned int option) continue; } diff_addremove(&revs->diffopt, '-', ce->ce_mode, - ce->sha1, !is_null_sha1(ce->sha1), + ce->oid.hash, + !is_null_oid(&ce->oid), + ce->name, 0); + continue; + } else if (revs->diffopt.ita_invisible_in_index && + ce_intent_to_add(ce)) { + diff_addremove(&revs->diffopt, '+', ce->ce_mode, + EMPTY_BLOB_SHA1_BIN, 0, ce->name, 0); continue; } @@ -225,8 +233,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option) continue; } oldmode = ce->ce_mode; - old_sha1 = ce->sha1; - new_sha1 = changed ? null_sha1 : ce->sha1; + old_sha1 = ce->oid.hash; + new_sha1 = changed ? null_sha1 : ce->oid.hash; diff_change(&revs->diffopt, oldmode, newmode, old_sha1, new_sha1, !is_null_sha1(old_sha1), @@ -261,7 +269,7 @@ static int get_stat_data(const struct cache_entry *ce, int cached, int match_missing, unsigned *dirty_submodule, struct diff_options *diffopt) { - const unsigned char *sha1 = ce->sha1; + const unsigned char *sha1 = ce->oid.hash; unsigned int mode = ce->ce_mode; if (!cached && !ce_uptodate(ce)) { @@ -324,12 +332,13 @@ static int show_modified(struct rev_info *revs, &dirty_submodule, &revs->diffopt) < 0) { if (report_missing) diff_index_show_file(revs, "-", old, - old->sha1, 1, old->ce_mode, 0); + old->oid.hash, 1, old->ce_mode, + 0); return -1; } if (revs->combine_merges && !cached && - (hashcmp(sha1, old->sha1) || hashcmp(old->sha1, new->sha1))) { + (hashcmp(sha1, old->oid.hash) || oidcmp(&old->oid, &new->oid))) { struct combine_diff_path *p; int pathlen = ce_namelen(new); @@ -343,22 +352,22 @@ static int show_modified(struct rev_info *revs, memset(p->parent, 0, 2 * sizeof(struct combine_diff_parent)); p->parent[0].status = DIFF_STATUS_MODIFIED; p->parent[0].mode = new->ce_mode; - hashcpy(p->parent[0].oid.hash, new->sha1); + oidcpy(&p->parent[0].oid, &new->oid); p->parent[1].status = DIFF_STATUS_MODIFIED; p->parent[1].mode = old->ce_mode; - hashcpy(p->parent[1].oid.hash, old->sha1); + oidcpy(&p->parent[1].oid, &old->oid); show_combined_diff(p, 2, revs->dense_combined_merges, revs); free(p); return 0; } oldmode = old->ce_mode; - if (mode == oldmode && !hashcmp(sha1, old->sha1) && !dirty_submodule && + if (mode == oldmode && !hashcmp(sha1, old->oid.hash) && !dirty_submodule && !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER)) return 0; diff_change(&revs->diffopt, oldmode, mode, - old->sha1, sha1, 1, !is_null_sha1(sha1), + old->oid.hash, sha1, 1, !is_null_sha1(sha1), old->name, 0, dirty_submodule); return 0; } @@ -376,6 +385,14 @@ static void do_oneway_diff(struct unpack_trees_options *o, struct rev_info *revs = o->unpack_data; int match_missing, cached; + /* i-t-a entries do not actually exist in the index */ + if (revs->diffopt.ita_invisible_in_index && + idx && ce_intent_to_add(idx)) { + idx = NULL; + if (!tree) + return; /* nothing to diff.. */ + } + /* if the entry is not checked out, don't examine work tree */ cached = o->index_only || (idx && ((idx->ce_flags & CE_VALID) || ce_skip_worktree(idx))); @@ -392,7 +409,8 @@ static void do_oneway_diff(struct unpack_trees_options *o, struct diff_filepair *pair; pair = diff_unmerge(&revs->diffopt, idx->name); if (tree) - fill_filespec(pair->one, tree->sha1, 1, tree->ce_mode); + fill_filespec(pair->one, tree->oid.hash, 1, + tree->ce_mode); return; } @@ -408,7 +426,8 @@ static void do_oneway_diff(struct unpack_trees_options *o, * Something removed from the tree? */ if (!idx) { - diff_index_show_file(revs, "-", tree, tree->sha1, 1, tree->ce_mode, 0); + diff_index_show_file(revs, "-", tree, tree->oid.hash, 1, + tree->ce_mode, 0); return; } @@ -516,7 +535,8 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt) return 0; } -int index_differs_from(const char *def, int diff_flags) +int index_differs_from(const char *def, int diff_flags, + int ita_invisible_in_index) { struct rev_info rev; struct setup_revision_opt opt; @@ -528,6 +548,7 @@ int index_differs_from(const char *def, int diff_flags) DIFF_OPT_SET(&rev.diffopt, QUICK); DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS); rev.diffopt.flags |= diff_flags; + rev.diffopt.ita_invisible_in_index = ita_invisible_in_index; run_diff_index(&rev, 1); if (rev.pending.alloc) free(rev.pending.objects); diff --git a/diff-no-index.c b/diff-no-index.c index 1f8999b..f420786 100644 --- a/diff-no-index.c +++ b/diff-no-index.c @@ -281,6 +281,9 @@ void diff_no_index(struct rev_info *revs, DIFF_OPT_SET(&revs->diffopt, NO_INDEX); + DIFF_OPT_SET(&revs->diffopt, RELATIVE_NAME); + revs->diffopt.prefix = prefix; + revs->max_count = -2; diff_setup_done(&revs->diffopt); diff --git a/diff.c b/diff.c index 8c78fce..ec87283 100644 --- a/diff.c +++ b/diff.c @@ -18,6 +18,7 @@ #include "ll-merge.h" #include "string-list.h" #include "argv-array.h" +#include "graph.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@ -26,6 +27,7 @@ #endif static int diff_detect_rename_default; +static int diff_indent_heuristic; /* experimental */ static int diff_compaction_heuristic; /* experimental */ static int diff_rename_limit_default = 400; static int diff_suppress_blank_empty; @@ -41,6 +43,7 @@ static int diff_stat_graph_width; static int diff_dirstat_permille_default = 30; static struct diff_options default_diff_options; static long diff_algorithm; +static unsigned ws_error_highlight_default = WSEH_NEW; static char diff_colors[][COLOR_MAXLEN] = { GIT_COLOR_RESET, @@ -54,6 +57,11 @@ static char diff_colors[][COLOR_MAXLEN] = { GIT_COLOR_NORMAL, /* FUNCINFO */ }; +static NORETURN void die_want_option(const char *option_name) +{ + die(_("option '%s' requires a value"), option_name); +} + static int parse_diff_color_slot(const char *var) { if (!strcasecmp(var, "context") || !strcasecmp(var, "plain")) @@ -131,9 +139,11 @@ static int parse_dirstat_params(struct diff_options *options, const char *params static int parse_submodule_params(struct diff_options *options, const char *value) { if (!strcmp(value, "log")) - DIFF_OPT_SET(options, SUBMODULE_LOG); + options->submodule_format = DIFF_SUBMODULE_LOG; else if (!strcmp(value, "short")) - DIFF_OPT_CLR(options, SUBMODULE_LOG); + options->submodule_format = DIFF_SUBMODULE_SHORT; + else if (!strcmp(value, "diff")) + options->submodule_format = DIFF_SUBMODULE_INLINE_DIFF; else return -1; return 0; @@ -163,6 +173,43 @@ long parse_algorithm_value(const char *value) return -1; } +static int parse_one_token(const char **arg, const char *token) +{ + const char *rest; + if (skip_prefix(*arg, token, &rest) && (!*rest || *rest == ',')) { + *arg = rest; + return 1; + } + return 0; +} + +static int parse_ws_error_highlight(const char *arg) +{ + const char *orig_arg = arg; + unsigned val = 0; + + while (*arg) { + if (parse_one_token(&arg, "none")) + val = 0; + else if (parse_one_token(&arg, "default")) + val = WSEH_NEW; + else if (parse_one_token(&arg, "all")) + val = WSEH_NEW | WSEH_OLD | WSEH_CONTEXT; + else if (parse_one_token(&arg, "new")) + val |= WSEH_NEW; + else if (parse_one_token(&arg, "old")) + val |= WSEH_OLD; + else if (parse_one_token(&arg, "context")) + val |= WSEH_CONTEXT; + else { + return -1 - (int)(arg - orig_arg); + } + if (*arg) + arg++; + } + return val; +} + /* * These are to give UI layer defaults. * The core-level commands such as git-diff-files should @@ -174,6 +221,21 @@ void init_diff_ui_defaults(void) diff_detect_rename_default = 1; } +int git_diff_heuristic_config(const char *var, const char *value, void *cb) +{ + if (!strcmp(var, "diff.indentheuristic")) { + diff_indent_heuristic = git_config_bool(var, value); + if (diff_indent_heuristic) + diff_compaction_heuristic = 0; + } + if (!strcmp(var, "diff.compactionheuristic")) { + diff_compaction_heuristic = git_config_bool(var, value); + if (diff_compaction_heuristic) + diff_indent_heuristic = 0; + } + return 0; +} + int git_diff_ui_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { @@ -190,10 +252,6 @@ 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; @@ -234,6 +292,17 @@ int git_diff_ui_config(const char *var, const char *value, void *cb) return 0; } + if (git_diff_heuristic_config(var, value, cb) < 0) + return -1; + + if (!strcmp(var, "diff.wserrorhighlight")) { + int val = parse_ws_error_highlight(value); + if (val < 0) + return -1; + ws_error_highlight_default = val; + return 0; + } + if (git_color_config(var, value, cb) < 0) return -1; @@ -1616,7 +1685,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options) */ if (options->stat_width == -1) - width = term_columns() - options->output_prefix_length; + width = term_columns() - strlen(line_prefix); else width = options->stat_width ? options->stat_width : 80; number_width = decimal_width(max_change) > number_width ? @@ -1997,7 +2066,7 @@ found_damage: return; /* Show all directories with more than x% of the changes */ - qsort(dir.files, dir.nr, sizeof(dir.files[0]), dirstat_compare); + QSORT(dir.files, dir.nr, dirstat_compare); gather_dirstat(options, &dir, changed, "", 0); } @@ -2041,7 +2110,7 @@ static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *o return; /* Show all directories with more than x% of the changes */ - qsort(dir.files, dir.nr, sizeof(dir.files[0]), dirstat_compare); + QSORT(dir.files, dir.nr, dirstat_compare); gather_dirstat(options, &dir, changed, "", 0); } @@ -2290,17 +2359,37 @@ static void builtin_diff(const char *name_a, struct strbuf header = STRBUF_INIT; const char *line_prefix = diff_line_prefix(o); - if (DIFF_OPT_TST(o, SUBMODULE_LOG) && - (!one->mode || S_ISGITLINK(one->mode)) && - (!two->mode || S_ISGITLINK(two->mode))) { + diff_set_mnemonic_prefix(o, "a/", "b/"); + if (DIFF_OPT_TST(o, REVERSE_DIFF)) { + a_prefix = o->b_prefix; + b_prefix = o->a_prefix; + } else { + a_prefix = o->a_prefix; + b_prefix = o->b_prefix; + } + + if (o->submodule_format == DIFF_SUBMODULE_LOG && + (!one->mode || S_ISGITLINK(one->mode)) && + (!two->mode || S_ISGITLINK(two->mode))) { const char *del = diff_get_color_opt(o, DIFF_FILE_OLD); const char *add = diff_get_color_opt(o, DIFF_FILE_NEW); show_submodule_summary(o->file, one->path ? one->path : two->path, line_prefix, - one->oid.hash, two->oid.hash, + &one->oid, &two->oid, two->dirty_submodule, meta, del, add, reset); return; + } else if (o->submodule_format == DIFF_SUBMODULE_INLINE_DIFF && + (!one->mode || S_ISGITLINK(one->mode)) && + (!two->mode || S_ISGITLINK(two->mode))) { + const char *del = diff_get_color_opt(o, DIFF_FILE_OLD); + const char *add = diff_get_color_opt(o, DIFF_FILE_NEW); + show_submodule_inline_diff(o->file, one->path ? one->path : two->path, + line_prefix, + &one->oid, &two->oid, + two->dirty_submodule, + meta, del, add, reset, o); + return; } if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) { @@ -2308,15 +2397,6 @@ static void builtin_diff(const char *name_a, textconv_two = get_textconv(two); } - diff_set_mnemonic_prefix(o, "a/", "b/"); - if (DIFF_OPT_TST(o, REVERSE_DIFF)) { - a_prefix = o->b_prefix; - b_prefix = o->a_prefix; - } else { - a_prefix = o->a_prefix; - b_prefix = o->b_prefix; - } - /* Never use a non-valid filename anywhere if at all possible */ name_a = DIFF_FILE_VALID(one) ? name_a : name_b; name_b = DIFF_FILE_VALID(two) ? name_b : name_a; @@ -2690,7 +2770,7 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int * This is not the sha1 we are looking for, or * unreusable because it is not a regular file. */ - if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode)) + if (hashcmp(sha1, ce->oid.hash) || !S_ISREG(ce->ce_mode)) return 0; /* @@ -3016,6 +3096,21 @@ static int similarity_index(struct diff_filepair *p) return p->score * 100 / MAX_SCORE; } +static const char *diff_abbrev_oid(const struct object_id *oid, int abbrev) +{ + if (startup_info->have_repository) + return find_unique_abbrev(oid->hash, abbrev); + else { + char *hex = oid_to_hex(oid); + if (abbrev < 0) + abbrev = FALLBACK_DEFAULT_ABBREV; + if (abbrev > GIT_SHA1_HEXSZ) + die("BUG: oid abbreviation out of range: %d", abbrev); + hex[abbrev] = '\0'; + return hex; + } +} + static void fill_metainfo(struct strbuf *msg, const char *name, const char *other, @@ -3074,9 +3169,9 @@ static void fill_metainfo(struct strbuf *msg, (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two))) abbrev = 40; } - strbuf_addf(msg, "%s%sindex %s..", line_prefix, set, - find_unique_abbrev(one->oid.hash, abbrev)); - strbuf_add_unique_abbrev(msg, two->oid.hash, abbrev); + strbuf_addf(msg, "%s%sindex %s..%s", line_prefix, set, + diff_abbrev_oid(&one->oid, abbrev), + diff_abbrev_oid(&two->oid, abbrev)); if (one->mode == two->mode) strbuf_addf(msg, " %06o", one->mode); strbuf_addf(msg, "%s\n", reset); @@ -3274,7 +3369,7 @@ void diff_setup(struct diff_options *options) options->rename_limit = -1; options->dirstat_permille = diff_dirstat_permille_default; options->context = diff_context_default; - options->ws_error_highlight = WSEH_NEW; + options->ws_error_highlight = ws_error_highlight_default; DIFF_OPT_SET(options, RENAME_EMPTY); /* pathchange left =NULL by default */ @@ -3283,7 +3378,9 @@ 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) + if (diff_indent_heuristic) + DIFF_XDL_SET(options, INDENT_HEURISTIC); + else if (diff_compaction_heuristic) DIFF_XDL_SET(options, COMPACTION_HEURISTIC); options->orderfile = diff_order_file_cfg; @@ -3312,7 +3409,7 @@ void diff_setup_done(struct diff_options *options) if (options->output_format & DIFF_FORMAT_NO_OUTPUT) count++; if (count > 1) - die("--name-only, --name-status, --check and -s are mutually exclusive"); + die(_("--name-only, --name-status, --check and -s are mutually exclusive")); /* * Most of the time we can say "there are changes" @@ -3386,7 +3483,7 @@ void diff_setup_done(struct diff_options *options) */ read_cache(); } - if (options->abbrev <= 0 || 40 < options->abbrev) + if (40 < options->abbrev) options->abbrev = 40; /* full */ /* @@ -3508,7 +3605,7 @@ static int stat_opt(struct diff_options *options, const char **av) if (*arg == '=') width = strtoul(arg + 1, &end, 10); else if (!*arg && !av[1]) - die("Option '--stat-width' requires a value"); + die_want_option("--stat-width"); else if (!*arg) { width = strtoul(av[1], &end, 10); argcount = 2; @@ -3517,7 +3614,7 @@ static int stat_opt(struct diff_options *options, const char **av) if (*arg == '=') name_width = strtoul(arg + 1, &end, 10); else if (!*arg && !av[1]) - die("Option '--stat-name-width' requires a value"); + die_want_option("--stat-name-width"); else if (!*arg) { name_width = strtoul(av[1], &end, 10); argcount = 2; @@ -3526,7 +3623,7 @@ static int stat_opt(struct diff_options *options, const char **av) if (*arg == '=') graph_width = strtoul(arg + 1, &end, 10); else if (!*arg && !av[1]) - die("Option '--stat-graph-width' requires a value"); + die_want_option("--stat-graph-width"); else if (!*arg) { graph_width = strtoul(av[1], &end, 10); argcount = 2; @@ -3535,7 +3632,7 @@ static int stat_opt(struct diff_options *options, const char **av) if (*arg == '=') count = strtoul(arg + 1, &end, 10); else if (!*arg && !av[1]) - die("Option '--stat-count' requires a value"); + die_want_option("--stat-count"); else if (!*arg) { count = strtoul(av[1], &end, 10); argcount = 2; @@ -3663,40 +3760,14 @@ static void enable_patch_output(int *fmt) { *fmt |= DIFF_FORMAT_PATCH; } -static int parse_one_token(const char **arg, const char *token) +static int parse_ws_error_highlight_opt(struct diff_options *opt, const char *arg) { - const char *rest; - if (skip_prefix(*arg, token, &rest) && (!*rest || *rest == ',')) { - *arg = rest; - return 1; - } - return 0; -} + int val = parse_ws_error_highlight(arg); -static int parse_ws_error_highlight(struct diff_options *opt, const char *arg) -{ - const char *orig_arg = arg; - unsigned val = 0; - while (*arg) { - if (parse_one_token(&arg, "none")) - val = 0; - else if (parse_one_token(&arg, "default")) - val = WSEH_NEW; - else if (parse_one_token(&arg, "all")) - val = WSEH_NEW | WSEH_OLD | WSEH_CONTEXT; - else if (parse_one_token(&arg, "new")) - val |= WSEH_NEW; - else if (parse_one_token(&arg, "old")) - val |= WSEH_OLD; - else if (parse_one_token(&arg, "context")) - val |= WSEH_CONTEXT; - else { - error("unknown value after ws-error-highlight=%.*s", - (int)(arg - orig_arg), orig_arg); - return 0; - } - if (*arg) - arg++; + if (val < 0) { + error("unknown value after ws-error-highlight=%.*s", + -1 - val, arg); + return 0; } opt->ws_error_highlight = val; return 1; @@ -3805,9 +3876,15 @@ 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")) + else if (!strcmp(arg, "--indent-heuristic")) { + DIFF_XDL_SET(options, INDENT_HEURISTIC); + DIFF_XDL_CLR(options, COMPACTION_HEURISTIC); + } else if (!strcmp(arg, "--no-indent-heuristic")) + DIFF_XDL_CLR(options, INDENT_HEURISTIC); + else if (!strcmp(arg, "--compaction-heuristic")) { DIFF_XDL_SET(options, COMPACTION_HEURISTIC); - else if (!strcmp(arg, "--no-compaction-heuristic")) + DIFF_XDL_CLR(options, INDENT_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); @@ -3905,11 +3982,15 @@ int diff_opt_parse(struct diff_options *options, DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG); handle_ignore_submodules_arg(options, arg); } else if (!strcmp(arg, "--submodule")) - DIFF_OPT_SET(options, SUBMODULE_LOG); + options->submodule_format = DIFF_SUBMODULE_LOG; else if (skip_prefix(arg, "--submodule=", &arg)) return parse_submodule_opt(options, arg); else if (skip_prefix(arg, "--ws-error-highlight=", &arg)) - return parse_ws_error_highlight(options, arg); + return parse_ws_error_highlight_opt(options, arg); + else if (!strcmp(arg, "--ita-invisible-in-index")) + options->ita_invisible_in_index = 1; + else if (!strcmp(arg, "--ita-visible-in-index")) + options->ita_invisible_in_index = 0; /* misc options */ else if (!strcmp(arg, "-z")) @@ -3956,6 +4037,12 @@ int diff_opt_parse(struct diff_options *options, options->a_prefix = optarg; return argcount; } + else if ((argcount = parse_long_opt("line-prefix", av, &optarg))) { + options->line_prefix = optarg; + options->line_prefix_length = strlen(options->line_prefix); + graph_setup_line_prefix(options); + return argcount; + } else if ((argcount = parse_long_opt("dst-prefix", av, &optarg))) { options->b_prefix = optarg; return argcount; @@ -4089,18 +4176,15 @@ void diff_free_filepair(struct diff_filepair *p) free(p); } -/* - * This is different from find_unique_abbrev() in that - * it stuffs the result with dots for alignment. - */ -const char *diff_unique_abbrev(const unsigned char *sha1, int len) +const char *diff_aligned_abbrev(const struct object_id *oid, int len) { int abblen; const char *abbrev; - if (len == 40) - return sha1_to_hex(sha1); - abbrev = find_unique_abbrev(sha1, len); + if (len == GIT_SHA1_HEXSZ) + return oid_to_hex(oid); + + abbrev = diff_abbrev_oid(oid, len); abblen = strlen(abbrev); /* @@ -4122,15 +4206,16 @@ const char *diff_unique_abbrev(const unsigned char *sha1, int len) * the automatic sizing is supposed to give abblen that ensures * uniqueness across all objects (statistically speaking). */ - if (abblen < 37) { - static char hex[41]; + if (abblen < GIT_SHA1_HEXSZ - 3) { + static char hex[GIT_SHA1_HEXSZ + 1]; if (len < abblen && abblen <= len + 2) xsnprintf(hex, sizeof(hex), "%s%.*s", abbrev, len+3-abblen, ".."); else xsnprintf(hex, sizeof(hex), "%s...", abbrev); return hex; } - return sha1_to_hex(sha1); + + return oid_to_hex(oid); } static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt) @@ -4141,9 +4226,9 @@ static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt) fprintf(opt->file, "%s", diff_line_prefix(opt)); if (!(opt->output_format & DIFF_FORMAT_NAME_STATUS)) { fprintf(opt->file, ":%06o %06o %s ", p->one->mode, p->two->mode, - diff_unique_abbrev(p->one->oid.hash, opt->abbrev)); + diff_aligned_abbrev(&p->one->oid, opt->abbrev)); fprintf(opt->file, "%s ", - diff_unique_abbrev(p->two->oid.hash, opt->abbrev)); + diff_aligned_abbrev(&p->two->oid, opt->abbrev)); } if (p->score) { fprintf(opt->file, "%c%03d%c", p->status, similarity_index(p), @@ -4612,25 +4697,25 @@ static int is_summary_empty(const struct diff_queue_struct *q) } static const char rename_limit_warning[] = -"inexact rename detection was skipped due to too many files."; +N_("inexact rename detection was skipped due to too many files."); static const char degrade_cc_to_c_warning[] = -"only found copies from modified paths due to too many files."; +N_("only found copies from modified paths due to too many files."); static const char rename_limit_advice[] = -"you may want to set your %s variable to at least " -"%d and retry the command."; +N_("you may want to set your %s variable to at least " + "%d and retry the command."); void diff_warn_rename_limit(const char *varname, int needed, int degraded_cc) { if (degraded_cc) - warning(degrade_cc_to_c_warning); + warning(_(degrade_cc_to_c_warning)); else if (needed) - warning(rename_limit_warning); + warning(_(rename_limit_warning)); else return; if (0 < needed && needed < 32767) - warning(rename_limit_advice, varname, needed); + warning(_(rename_limit_advice), varname, needed); } void diff_flush(struct diff_options *options) @@ -4897,7 +4982,7 @@ static int diffnamecmp(const void *a_, const void *b_) void diffcore_fix_diff_index(struct diff_options *options) { struct diff_queue_struct *q = &diff_queued_diff; - qsort(q->queue, q->nr, sizeof(q->queue[0]), diffnamecmp); + QSORT(q->queue, q->nr, diffnamecmp); } void diffcore_std(struct diff_options *options) diff --git a/diff.h b/diff.h index 7883729..e9ccb38 100644 --- a/diff.h +++ b/diff.h @@ -83,7 +83,6 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data) #define DIFF_OPT_DIRSTAT_BY_FILE (1 << 20) #define DIFF_OPT_ALLOW_TEXTCONV (1 << 21) #define DIFF_OPT_DIFF_FROM_CONTENTS (1 << 22) -#define DIFF_OPT_SUBMODULE_LOG (1 << 23) #define DIFF_OPT_DIRTY_SUBMODULES (1 << 24) #define DIFF_OPT_IGNORE_UNTRACKED_IN_SUBMODULES (1 << 25) #define DIFF_OPT_IGNORE_DIRTY_SUBMODULES (1 << 26) @@ -110,11 +109,19 @@ enum diff_words_type { DIFF_WORDS_COLOR }; +enum diff_submodule_format { + DIFF_SUBMODULE_SHORT = 0, + DIFF_SUBMODULE_LOG, + DIFF_SUBMODULE_INLINE_DIFF +}; + struct diff_options { const char *orderfile; const char *pickaxe; const char *single_follow; const char *a_prefix, *b_prefix; + const char *line_prefix; + size_t line_prefix_length; unsigned flags; unsigned touched_flags; @@ -139,6 +146,7 @@ struct diff_options { int dirstat_permille; int setup; int abbrev; + int ita_invisible_in_index; /* white-space error highlighting */ #define WSEH_NEW 1 #define WSEH_CONTEXT 2 @@ -155,6 +163,7 @@ struct diff_options { int stat_count; const char *word_regex; enum diff_words_type word_diff; + enum diff_submodule_format submodule_format; /* this is set by diffcore for DIFF_FORMAT_PATCH */ int found_changes; @@ -174,7 +183,6 @@ struct diff_options { diff_format_fn_t format_callback; void *format_callback_data; diff_prefix_fn_t output_prefix; - int output_prefix_length; void *output_prefix_data; int diff_path_counter; @@ -266,6 +274,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 int git_diff_heuristic_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 *); @@ -332,7 +341,11 @@ extern void diff_warn_rename_limit(const char *varname, int needed, int degraded #define DIFF_STATUS_FILTER_AON '*' #define DIFF_STATUS_FILTER_BROKEN 'B' -extern const char *diff_unique_abbrev(const unsigned char *, int); +/* + * This is different from find_unique_abbrev() in that + * it stuffs the result with dots for alignment. + */ +extern const char *diff_aligned_abbrev(const struct object_id *sha1, int); /* do not report anything on removed paths */ #define DIFF_SILENT_ON_REMOVED 01 @@ -348,7 +361,7 @@ extern int diff_result_code(struct diff_options *, int); extern void diff_no_index(struct rev_info *, int, const char **); -extern int index_differs_from(const char *def, int diff_flags); +extern int index_differs_from(const char *def, int diff_flags, int ita_invisible_in_index); /* * Fill the contents of the filespec "df", respecting any textconv defined by diff --git a/diffcore-delta.c b/diffcore-delta.c index e2db85a..ebe70fb 100644 --- a/diffcore-delta.c +++ b/diffcore-delta.c @@ -158,10 +158,7 @@ static struct spanhash_top *hash_chars(struct diff_filespec *one) n = 0; accum1 = accum2 = 0; } - qsort(hash->data, - 1ul << hash->alloc_log2, - sizeof(hash->data[0]), - spanhash_cmp); + QSORT(hash->data, 1ul << hash->alloc_log2, spanhash_cmp); return hash; } diff --git a/diffcore-order.c b/diffcore-order.c index 69d41f7..1957f82 100644 --- a/diffcore-order.c +++ b/diffcore-order.c @@ -101,7 +101,7 @@ void order_objects(const char *orderfile, obj_path_fn_t obj_path, objs[i].orig_order = i; objs[i].order = match_order(obj_path(objs[i].obj)); } - qsort(objs, nr, sizeof(*objs), compare_objs_order); + QSORT(objs, nr, compare_objs_order); } static const char *pair_pathtwo(void *obj) diff --git a/diffcore-rename.c b/diffcore-rename.c index 15c014d..f7444c8 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -576,7 +576,7 @@ void diffcore_rename(struct diff_options *options) stop_progress(&progress); /* cost matrix sorted by most to least similar pair */ - qsort(mx, dst_cnt * NUM_CANDIDATE_PER_DST, sizeof(*mx), score_compare); + QSORT(mx, dst_cnt * NUM_CANDIDATE_PER_DST, score_compare); rename_count += find_renames(mx, dst_cnt, minimum_score, 0); if (detect_rename == DIFF_DETECT_COPY) diff --git a/dir.c b/dir.c index 0ea235f..bfa8c8a 100644 --- a/dir.c +++ b/dir.c @@ -207,8 +207,9 @@ int within_depth(const char *name, int namelen, return 1; } -#define DO_MATCH_EXCLUDE 1 -#define DO_MATCH_DIRECTORY 2 +#define DO_MATCH_EXCLUDE (1<<0) +#define DO_MATCH_DIRECTORY (1<<1) +#define DO_MATCH_SUBMODULE (1<<2) /* * Does 'match' match the given name? @@ -283,6 +284,32 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix, item->nowildcard_len - prefix)) return MATCHED_FNMATCH; + /* Perform checks to see if "name" is a super set of the pathspec */ + if (flags & DO_MATCH_SUBMODULE) { + /* name is a literal prefix of the pathspec */ + if ((namelen < matchlen) && + (match[namelen] == '/') && + !ps_strncmp(item, match, name, namelen)) + return MATCHED_RECURSIVELY; + + /* name" doesn't match up to the first wild character */ + if (item->nowildcard_len < item->len && + ps_strncmp(item, match, name, + item->nowildcard_len - prefix)) + return 0; + + /* + * Here is where we would perform a wildmatch to check if + * "name" can be matched as a directory (or a prefix) against + * the pathspec. Since wildmatch doesn't have this capability + * at the present we have to punt and say that it is a match, + * potentially returning a false positive + * The submodules themselves will be able to perform more + * accurate matching to determine if the pathspec matches. + */ + return MATCHED_RECURSIVELY; + } + return 0; } @@ -386,6 +413,21 @@ int match_pathspec(const struct pathspec *ps, return negative ? 0 : positive; } +/** + * Check if a submodule is a superset of the pathspec + */ +int submodule_path_match(const struct pathspec *ps, + const char *submodule_name, + char *seen) +{ + int matched = do_match_pathspec(ps, submodule_name, + strlen(submodule_name), + 0, seen, + DO_MATCH_DIRECTORY | + DO_MATCH_SUBMODULE); + return matched; +} + int report_path_error(const char *ps_matched, const struct pathspec *pathspec, const char *prefix) @@ -525,7 +567,7 @@ static void *read_skip_worktree_file_from_index(const char *path, size_t *size, return NULL; if (!ce_skip_worktree(active_cache[pos])) return NULL; - data = read_sha1_file(active_cache[pos]->sha1, &type, &sz); + data = read_sha1_file(active_cache[pos]->oid.hash, &type, &sz); if (!data || type != OBJ_BLOB) { free(data); return NULL; @@ -533,7 +575,7 @@ static void *read_skip_worktree_file_from_index(const char *path, size_t *size, *size = xsize_t(sz); if (sha1_stat) { memset(&sha1_stat->stat, 0, sizeof(sha1_stat->stat)); - hashcpy(sha1_stat->sha1, active_cache[pos]->sha1); + hashcpy(sha1_stat->sha1, active_cache[pos]->oid.hash); } return data; } @@ -713,7 +755,8 @@ static int add_excludes(const char *fname, const char *base, int baselen, !ce_stage(active_cache[pos]) && ce_uptodate(active_cache[pos]) && !would_convert_to_git(fname)) - hashcpy(sha1_stat->sha1, active_cache[pos]->sha1); + hashcpy(sha1_stat->sha1, + active_cache[pos]->oid.hash); else hash_sha1_file(buf, size, "blob", sha1_stat->sha1); fill_stat_data(&sha1_stat->stat, &st); @@ -2004,8 +2047,8 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru if (!len || treat_leading_path(dir, path, len, simplify)) read_directory_recursive(dir, path, len, untracked, 0, simplify); free_simplify(simplify); - qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name); - qsort(dir->ignored, dir->ignored_nr, sizeof(struct dir_entry *), cmp_name); + QSORT(dir->entries, dir->nr, cmp_name); + QSORT(dir->ignored, dir->ignored_nr, cmp_name); if (dir->untracked) { static struct trace_key trace_untracked_stats = TRACE_KEY_INIT(UNTRACKED_STATS); trace_printf_key(&trace_untracked_stats, @@ -2194,8 +2237,6 @@ static GIT_PATH_FUNC(git_path_info_exclude, "info/exclude") void setup_standard_excludes(struct dir_struct *dir) { - const char *path; - dir->exclude_per_dir = ".gitignore"; /* core.excludefile defaulting to $XDG_HOME/git/ignore */ @@ -2206,10 +2247,12 @@ void setup_standard_excludes(struct dir_struct *dir) dir->untracked ? &dir->ss_excludes_file : NULL); /* per repository user preference */ - path = git_path_info_exclude(); - if (!access_or_warn(path, R_OK, 0)) - add_excludes_from_file_1(dir, path, - dir->untracked ? &dir->ss_info_exclude : NULL); + if (startup_info->have_repository) { + const char *path = git_path_info_exclude(); + if (!access_or_warn(path, R_OK, 0)) + add_excludes_from_file_1(dir, path, + dir->untracked ? &dir->ss_info_exclude : NULL); + } } int remove_path(const char *name) diff --git a/dir.h b/dir.h index da1a858..97c83bb 100644 --- a/dir.h +++ b/dir.h @@ -304,6 +304,10 @@ extern int git_fnmatch(const struct pathspec_item *item, const char *pattern, const char *string, int prefix); +extern int submodule_path_match(const struct pathspec *ps, + const char *submodule_name, + char *seen); + static inline int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec, char *seen) diff --git a/entry.c b/entry.c index 519e042..c6eea24 100644 --- a/entry.c +++ b/entry.c @@ -82,7 +82,7 @@ static int create_file(const char *path, unsigned int mode) static void *read_blob_entry(const struct cache_entry *ce, unsigned long *size) { enum object_type type; - void *new = read_sha1_file(ce->sha1, &type, size); + void *new = read_sha1_file(ce->oid.hash, &type, size); if (new) { if (type == OBJ_BLOB) @@ -127,7 +127,7 @@ static int streaming_write_entry(const struct cache_entry *ce, char *path, if (fd < 0) return -1; - result |= stream_blob_to_fd(fd, ce->sha1, filter, 1); + result |= stream_blob_to_fd(fd, &ce->oid, filter, 1); *fstat_done = fstat_output(fd, state, statbuf); result |= close(fd); @@ -148,7 +148,8 @@ static int write_entry(struct cache_entry *ce, struct stat st; if (ce_mode_s_ifmt == S_IFREG) { - struct stream_filter *filter = get_stream_filter(ce->name, ce->sha1); + struct stream_filter *filter = get_stream_filter(ce->name, + ce->oid.hash); if (filter && !streaming_write_entry(ce, path, filter, state, to_tempfile, @@ -162,7 +163,7 @@ static int write_entry(struct cache_entry *ce, new = read_blob_entry(ce, &size); if (!new) return error("unable to read sha1 file of %s (%s)", - path, sha1_to_hex(ce->sha1)); + path, oid_to_hex(&ce->oid)); if (ce_mode_s_ifmt == S_IFLNK && has_symlinks && !to_tempfile) { ret = symlink(new, path); diff --git a/environment.c b/environment.c index ca72464..0935ec6 100644 --- a/environment.c +++ b/environment.c @@ -16,7 +16,7 @@ int trust_executable_bit = 1; int trust_ctime = 1; int check_stat = 1; int has_symlinks = 1; -int minimum_abbrev = 4, default_abbrev = 7; +int minimum_abbrev = 4, default_abbrev = -1; int ignore_case; int assume_unchanged; int prefer_symlink_refs; @@ -40,7 +40,6 @@ size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE; size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT; size_t delta_base_cache_limit = 96 * 1024 * 1024; unsigned long big_file_threshold = 512 * 1024 * 1024; -const char *pager_program; int pager_use_color = 1; const char *editor_program; const char *askpass_program; @@ -100,6 +99,8 @@ static char *work_tree; static const char *namespace; static size_t namespace_len; +static const char *super_prefix; + static const char *git_dir, *git_common_dir; static char *git_object_dir, *git_index_file, *git_graft_file; int git_db_env, git_index_env, git_graft_env, git_common_dir_env; @@ -120,6 +121,7 @@ const char * const local_repo_env[] = { NO_REPLACE_OBJECTS_ENVIRONMENT, GIT_REPLACE_REF_BASE_ENVIRONMENT, GIT_PREFIX_ENVIRONMENT, + GIT_SUPER_PREFIX_ENVIRONMENT, GIT_SHALLOW_FILE_ENVIRONMENT, GIT_COMMON_DIR_ENVIRONMENT, NULL @@ -196,6 +198,13 @@ int is_bare_repository(void) return is_bare_repository_cfg && !get_git_work_tree(); } +int have_git_dir(void) +{ + return startup_info->have_repository + || git_dir + || getenv(GIT_DIR_ENVIRONMENT); +} + const char *get_git_dir(void) { if (!git_dir) @@ -222,6 +231,16 @@ const char *strip_namespace(const char *namespaced_ref) return namespaced_ref + namespace_len; } +const char *get_super_prefix(void) +{ + static int initialized; + if (!initialized) { + super_prefix = getenv(GIT_SUPER_PREFIX_ENVIRONMENT); + initialized = 1; + } + return super_prefix; +} + static int git_work_tree_initialized; /* @@ -345,3 +364,8 @@ int get_shared_repository(void) } return the_shared_repository; } + +void reset_shared_repository(void) +{ + need_shared_repository_from_config = 1; +} diff --git a/fast-import.c b/fast-import.c index bf53ac9..cb545d7 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1460,9 +1460,9 @@ static void mktree(struct tree_content *t, int v, struct strbuf *b) unsigned int i; if (!v) - qsort(t->entries,t->entry_count,sizeof(t->entries[0]),tecmp0); + QSORT(t->entries, t->entry_count, tecmp0); else - qsort(t->entries,t->entry_count,sizeof(t->entries[0]),tecmp1); + QSORT(t->entries, t->entry_count, tecmp1); for (i = 0; i < t->entry_count; i++) { if (t->entries[i]->versions[v].mode) diff --git a/fetch-pack.c b/fetch-pack.c index 413937e..601f077 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -21,6 +21,8 @@ static int fetch_unpack_limit = -1; static int unpack_limit = 100; static int prefer_ofs_delta = 1; static int no_done; +static int deepen_since_ok; +static int deepen_not_ok; static int fetch_fsck_objects = -1; static int transfer_fsck_objects = -1; static int agent_supported; @@ -50,6 +52,21 @@ static int non_common_revs, multi_ack, use_sideband; #define ALLOW_REACHABLE_SHA1 02 static unsigned int allow_unadvertised_object_request; +__attribute__((format (printf, 2, 3))) +static inline void print_verbose(const struct fetch_pack_args *args, + const char *fmt, ...) +{ + va_list params; + + if (!args->verbose) + return; + + va_start(params, fmt); + vfprintf(stderr, fmt, params); + va_end(params); + fputc('\n', stderr); +} + static void rev_list_push(struct commit *commit, int mark) { if (!(commit->object.flags & mark)) { @@ -182,7 +199,7 @@ enum ack_type { static void consume_shallow_list(struct fetch_pack_args *args, int fd) { - if (args->stateless_rpc && args->depth > 0) { + if (args->stateless_rpc && args->deepen) { /* If we sent a depth we will get back "duplicate" * shallow and unshallow commands every time there * is a block of have lines exchanged. @@ -193,7 +210,7 @@ static void consume_shallow_list(struct fetch_pack_args *args, int fd) continue; if (starts_with(line, "unshallow ")) continue; - die("git fetch-pack: expected shallow list"); + die(_("git fetch-pack: expected shallow list")); } } } @@ -205,7 +222,7 @@ static enum ack_type get_ack(int fd, unsigned char *result_sha1) const char *arg; if (!len) - die("git fetch-pack: expected ACK/NAK, got EOF"); + die(_("git fetch-pack: expected ACK/NAK, got EOF")); if (!strcmp(line, "NAK")) return NAK; if (skip_prefix(line, "ACK ", &arg)) { @@ -223,7 +240,7 @@ static enum ack_type get_ack(int fd, unsigned char *result_sha1) return ACK; } } - die("git fetch_pack: expected ACK/NAK, got '%s'", line); + die(_("git fetch-pack: expected ACK/NAK, got '%s'"), line); } static void send_request(struct fetch_pack_args *args, @@ -275,7 +292,7 @@ static int find_common(struct fetch_pack_args *args, size_t state_len = 0; if (args->stateless_rpc && multi_ack == 1) - die("--stateless-rpc requires multi_ack_detailed"); + die(_("--stateless-rpc requires multi_ack_detailed")); if (marked) for_each_ref(clear_marks, NULL); marked = 1; @@ -312,10 +329,13 @@ static int find_common(struct fetch_pack_args *args, if (no_done) strbuf_addstr(&c, " no-done"); if (use_sideband == 2) strbuf_addstr(&c, " side-band-64k"); if (use_sideband == 1) strbuf_addstr(&c, " side-band"); + if (args->deepen_relative) strbuf_addstr(&c, " deepen-relative"); if (args->use_thin_pack) strbuf_addstr(&c, " thin-pack"); if (args->no_progress) strbuf_addstr(&c, " no-progress"); if (args->include_tag) strbuf_addstr(&c, " include-tag"); if (prefer_ofs_delta) strbuf_addstr(&c, " ofs-delta"); + if (deepen_since_ok) strbuf_addstr(&c, " deepen-since"); + if (deepen_not_ok) strbuf_addstr(&c, " deepen-not"); if (agent_supported) strbuf_addf(&c, " agent=%s", git_user_agent_sanitized()); packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf); @@ -335,10 +355,21 @@ static int find_common(struct fetch_pack_args *args, write_shallow_commits(&req_buf, 1, NULL); if (args->depth > 0) packet_buf_write(&req_buf, "deepen %d", args->depth); + if (args->deepen_since) { + unsigned long max_age = approxidate(args->deepen_since); + packet_buf_write(&req_buf, "deepen-since %lu", max_age); + } + if (args->deepen_not) { + int i; + for (i = 0; i < args->deepen_not->nr; i++) { + struct string_list_item *s = args->deepen_not->items + i; + packet_buf_write(&req_buf, "deepen-not %s", s->string); + } + } packet_buf_flush(&req_buf); state_len = req_buf.len; - if (args->depth > 0) { + if (args->deepen) { char *line; const char *arg; unsigned char sha1[20]; @@ -347,23 +378,23 @@ static int find_common(struct fetch_pack_args *args, while ((line = packet_read_line(fd[0], NULL))) { if (skip_prefix(line, "shallow ", &arg)) { if (get_sha1_hex(arg, sha1)) - die("invalid shallow line: %s", line); + die(_("invalid shallow line: %s"), line); register_shallow(sha1); continue; } if (skip_prefix(line, "unshallow ", &arg)) { if (get_sha1_hex(arg, sha1)) - die("invalid unshallow line: %s", line); + die(_("invalid unshallow line: %s"), line); if (!lookup_object(sha1)) - die("object not found: %s", line); + die(_("object not found: %s"), line); /* make sure that it is parsed as shallow */ if (!parse_object(sha1)) - die("error in object: %s", line); + die(_("error in object: %s"), line); if (unregister_shallow(sha1)) - die("no shallow found: %s", line); + die(_("no shallow found: %s"), line); continue; } - die("expected shallow/unshallow, got %s", line); + die(_("expected shallow/unshallow, got %s"), line); } } else if (!args->stateless_rpc) send_request(args, fd[1], &req_buf); @@ -380,8 +411,7 @@ static int find_common(struct fetch_pack_args *args, retval = -1; while ((sha1 = get_rev())) { packet_buf_write(&req_buf, "have %s\n", sha1_to_hex(sha1)); - if (args->verbose) - fprintf(stderr, "have %s\n", sha1_to_hex(sha1)); + print_verbose(args, "have %s", sha1_to_hex(sha1)); in_vain++; if (flush_at <= ++count) { int ack; @@ -402,9 +432,9 @@ static int find_common(struct fetch_pack_args *args, consume_shallow_list(args, fd[0]); do { ack = get_ack(fd[0], result_sha1); - if (args->verbose && ack) - fprintf(stderr, "got ack %d %s\n", ack, - sha1_to_hex(result_sha1)); + if (ack) + print_verbose(args, _("got %s %d %s"), "ack", + ack, sha1_to_hex(result_sha1)); switch (ack) { case ACK: flushes = 0; @@ -417,7 +447,7 @@ static int find_common(struct fetch_pack_args *args, struct commit *commit = lookup_commit(result_sha1); if (!commit) - die("invalid commit %s", sha1_to_hex(result_sha1)); + die(_("invalid commit %s"), sha1_to_hex(result_sha1)); if (args->stateless_rpc && ack == ACK_common && !(commit->object.flags & COMMON)) { @@ -450,8 +480,7 @@ static int find_common(struct fetch_pack_args *args, } while (ack); flushes--; if (got_continue && MAX_IN_VAIN < in_vain) { - if (args->verbose) - fprintf(stderr, "giving up\n"); + print_verbose(args, _("giving up")); break; /* give up */ } } @@ -461,8 +490,7 @@ done: packet_buf_write(&req_buf, "done\n"); send_request(args, fd[1], &req_buf); } - if (args->verbose) - fprintf(stderr, "done\n"); + print_verbose(args, _("done")); if (retval != 0) { multi_ack = 0; flushes++; @@ -474,9 +502,8 @@ done: while (flushes || multi_ack) { int ack = get_ack(fd[0], result_sha1); if (ack) { - if (args->verbose) - fprintf(stderr, "got ack (%d) %s\n", ack, - sha1_to_hex(result_sha1)); + print_verbose(args, _("got %s (%d) %s"), "ack", + ack, sha1_to_hex(result_sha1)); if (ack == ACK) return 0; multi_ack = 1; @@ -521,9 +548,8 @@ static void mark_recent_complete_commits(struct fetch_pack_args *args, unsigned long cutoff) { while (complete && cutoff <= complete->item->date) { - if (args->verbose) - fprintf(stderr, "Marking %s as complete\n", - oid_to_hex(&complete->item->object.oid)); + print_verbose(args, _("Marking %s as complete"), + oid_to_hex(&complete->item->object.oid)); pop_most_recent_commit(&complete, COMPLETE); } } @@ -559,7 +585,7 @@ static void filter_refs(struct fetch_pack_args *args, } if (!keep && args->fetch_all && - (!args->depth || !starts_with(ref->name, "refs/tags/"))) + (!args->deepen || !starts_with(ref->name, "refs/tags/"))) keep = 1; if (keep) { @@ -629,7 +655,7 @@ static int everything_local(struct fetch_pack_args *args, } } - if (!args->depth) { + if (!args->deepen) { for_each_ref(mark_complete_oid, NULL); for_each_alternate_ref(mark_alternate_complete, NULL); commit_list_sort_by_date(&complete); @@ -664,18 +690,12 @@ static int everything_local(struct fetch_pack_args *args, o = lookup_object(remote); if (!o || !(o->flags & COMPLETE)) { retval = 0; - if (!args->verbose) - continue; - fprintf(stderr, - "want %s (%s)\n", sha1_to_hex(remote), - ref->name); + print_verbose(args, "want %s (%s)", sha1_to_hex(remote), + ref->name); continue; } - if (!args->verbose) - continue; - fprintf(stderr, - "already have %s (%s)\n", sha1_to_hex(remote), - ref->name); + print_verbose(args, _("already have %s (%s)"), sha1_to_hex(remote), + ref->name); } return retval; } @@ -712,8 +732,7 @@ static int get_pack(struct fetch_pack_args *args, demux.out = -1; demux.isolate_sigpipe = 1; if (start_async(&demux)) - die("fetch-pack: unable to fork off sideband" - " demultiplexer"); + die(_("fetch-pack: unable to fork off sideband demultiplexer")); } else demux.out = xd[0]; @@ -721,7 +740,7 @@ static int get_pack(struct fetch_pack_args *args, if (!args->keep_pack && unpack_limit) { if (read_pack_header(demux.out, &header)) - die("protocol error: bad pack header"); + die(_("protocol error: bad pack header")); pass_header = 1; if (ntohl(header.hdr_entries) < unpack_limit) do_keep = 0; @@ -777,7 +796,7 @@ static int get_pack(struct fetch_pack_args *args, cmd.in = demux.out; cmd.git_cmd = 1; if (start_command(&cmd)) - die("fetch-pack: unable to fork off %s", cmd_name); + die(_("fetch-pack: unable to fork off %s"), cmd_name); if (do_keep && pack_lockfile) { *pack_lockfile = index_pack_lockfile(cmd.out); close(cmd.out); @@ -793,9 +812,9 @@ static int get_pack(struct fetch_pack_args *args, args->check_self_contained_and_connected && ret == 0; else - die("%s failed", cmd_name); + die(_("%s failed"), cmd_name); if (use_sideband && finish_async(&demux)) - die("error in sideband demultiplexer"); + die(_("error in sideband demultiplexer")); return 0; } @@ -819,44 +838,39 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, int agent_len; sort_ref_list(&ref, ref_compare_name); - qsort(sought, nr_sought, sizeof(*sought), cmp_ref_by_name); + QSORT(sought, nr_sought, cmp_ref_by_name); if ((args->depth > 0 || is_repository_shallow()) && !server_supports("shallow")) - die("Server does not support shallow clients"); + die(_("Server does not support shallow clients")); + if (args->depth > 0 || args->deepen_since || args->deepen_not) + args->deepen = 1; if (server_supports("multi_ack_detailed")) { - if (args->verbose) - fprintf(stderr, "Server supports multi_ack_detailed\n"); + print_verbose(args, _("Server supports multi_ack_detailed")); multi_ack = 2; if (server_supports("no-done")) { - if (args->verbose) - fprintf(stderr, "Server supports no-done\n"); + print_verbose(args, _("Server supports no-done")); if (args->stateless_rpc) no_done = 1; } } else if (server_supports("multi_ack")) { - if (args->verbose) - fprintf(stderr, "Server supports multi_ack\n"); + print_verbose(args, _("Server supports multi_ack")); multi_ack = 1; } if (server_supports("side-band-64k")) { - if (args->verbose) - fprintf(stderr, "Server supports side-band-64k\n"); + print_verbose(args, _("Server supports side-band-64k")); use_sideband = 2; } else if (server_supports("side-band")) { - if (args->verbose) - fprintf(stderr, "Server supports side-band\n"); + print_verbose(args, _("Server supports side-band")); use_sideband = 1; } if (server_supports("allow-tip-sha1-in-want")) { - if (args->verbose) - fprintf(stderr, "Server supports allow-tip-sha1-in-want\n"); + print_verbose(args, _("Server supports allow-tip-sha1-in-want")); allow_unadvertised_object_request |= ALLOW_TIP_SHA1; } if (server_supports("allow-reachable-sha1-in-want")) { - if (args->verbose) - fprintf(stderr, "Server supports allow-reachable-sha1-in-want\n"); + print_verbose(args, _("Server supports allow-reachable-sha1-in-want")); allow_unadvertised_object_request |= ALLOW_REACHABLE_SHA1; } if (!server_supports("thin-pack")) @@ -865,18 +879,27 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, args->no_progress = 0; if (!server_supports("include-tag")) args->include_tag = 0; - if (server_supports("ofs-delta")) { - if (args->verbose) - fprintf(stderr, "Server supports ofs-delta\n"); - } else + if (server_supports("ofs-delta")) + print_verbose(args, _("Server supports ofs-delta")); + else prefer_ofs_delta = 0; if ((agent_feature = server_feature_value("agent", &agent_len))) { agent_supported = 1; - if (args->verbose && agent_len) - fprintf(stderr, "Server version is %.*s\n", - agent_len, agent_feature); + if (agent_len) + print_verbose(args, _("Server version is %.*s"), + agent_len, agent_feature); } + if (server_supports("deepen-since")) + deepen_since_ok = 1; + else if (args->deepen_since) + die(_("Server does not support --shallow-since")); + if (server_supports("deepen-not")) + deepen_not_ok = 1; + else if (args->deepen_not) + die(_("Server does not support --shallow-exclude")); + if (!server_supports("deepen-relative") && args->deepen_relative) + die(_("Server does not support --deepen")); if (everything_local(args, &ref, sought, nr_sought)) { packet_flush(fd[1]); @@ -887,11 +910,11 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, /* When cloning, it is not unusual to have * no common commit. */ - warning("no common commits"); + warning(_("no common commits")); if (args->stateless_rpc) packet_flush(fd[1]); - if (args->depth > 0) + if (args->deepen) setup_alternate_shallow(&shallow_lock, &alternate_shallow_file, NULL); else if (si->nr_ours || si->nr_theirs) @@ -899,7 +922,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args, else alternate_shallow_file = NULL; if (get_pack(args, fd, pack_lockfile)) - die("git fetch-pack: fetch failed."); + die(_("git fetch-pack: fetch failed.")); all_done: return ref; @@ -958,7 +981,7 @@ static void update_shallow(struct fetch_pack_args *args, int *status; int i; - if (args->depth > 0 && alternate_shallow_file) { + if (args->deepen && alternate_shallow_file) { if (*alternate_shallow_file == '\0') { /* --unshallow */ unlink_or_warn(git_path_shallow()); rollback_lock_file(&shallow_lock); @@ -1061,7 +1084,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args, if (!ref) { packet_flush(fd[1]); - die("no matching remote head"); + die(_("no matching remote head")); } prepare_shallow_info(&si, shallow); ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, diff --git a/fetch-pack.h b/fetch-pack.h index bb7fd76..c912e3d 100644 --- a/fetch-pack.h +++ b/fetch-pack.h @@ -10,6 +10,9 @@ struct fetch_pack_args { const char *uploadpack; int unpacklimit; int depth; + const char *deepen_since; + const struct string_list *deepen_not; + unsigned deepen_relative:1; unsigned quiet:1; unsigned keep_pack:1; unsigned lock_pack:1; @@ -25,6 +28,7 @@ struct fetch_pack_args { unsigned self_contained_and_connected:1; unsigned cloning:1; unsigned update_shallow:1; + unsigned deepen:1; }; /* diff --git a/fsck.c b/fsck.c index c9cf3de..4a3069e 100644 --- a/fsck.c +++ b/fsck.c @@ -347,8 +347,9 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op return -1; name = get_object_name(options, &tree->object); - init_tree_desc(&desc, tree->buffer, tree->size); - while (tree_entry(&desc, &entry)) { + if (init_tree_desc_gently(&desc, tree->buffer, tree->size)) + return -1; + while (tree_entry_gently(&desc, &entry)) { struct object *obj; int result; @@ -520,7 +521,7 @@ static int verify_ordered(unsigned mode1, const char *name1, unsigned mode2, con static int fsck_tree(struct tree *item, struct fsck_options *options) { - int retval; + int retval = 0; int has_null_sha1 = 0; int has_full_path = 0; int has_empty_name = 0; @@ -535,7 +536,10 @@ static int fsck_tree(struct tree *item, struct fsck_options *options) unsigned o_mode; const char *o_name; - init_tree_desc(&desc, item->buffer, item->size); + if (init_tree_desc_gently(&desc, item->buffer, item->size)) { + retval += report(options, &item->object, FSCK_MSG_BAD_TREE, "cannot be parsed as a tree"); + return retval; + } o_mode = 0; o_name = NULL; @@ -556,7 +560,10 @@ static int fsck_tree(struct tree *item, struct fsck_options *options) is_hfs_dotgit(name) || is_ntfs_dotgit(name)); has_zero_pad |= *(char *)desc.buffer == '0'; - update_tree_entry(&desc); + if (update_tree_entry_gently(&desc)) { + retval += report(options, &item->object, FSCK_MSG_BAD_TREE, "cannot be parsed as a tree"); + break; + } switch (mode) { /* @@ -597,7 +604,6 @@ static int fsck_tree(struct tree *item, struct fsck_options *options) o_name = name; } - retval = 0; if (has_null_sha1) retval += report(options, &item->object, FSCK_MSG_NULL_SHA1, "contains entries pointing to null sha1"); if (has_full_path) diff --git a/git-add--interactive.perl b/git-add--interactive.perl index 642cce1..ee3d812 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -45,6 +45,7 @@ my ($diff_new_color) = my $normal_color = $repo->get_color("", "reset"); my $diff_algorithm = $repo->config('diff.algorithm'); +my $diff_indent_heuristic = $repo->config_bool('diff.indentheuristic'); my $diff_compaction_heuristic = $repo->config_bool('diff.compactionheuristic'); my $diff_filter = $repo->config('interactive.difffilter'); @@ -750,7 +751,9 @@ sub parse_diff { if (defined $diff_algorithm) { splice @diff_cmd, 1, 0, "--diff-algorithm=${diff_algorithm}"; } - if ($diff_compaction_heuristic) { + if ($diff_indent_heuristic) { + splice @diff_cmd, 1, 0, "--indent-heuristic"; + } elsif ($diff_compaction_heuristic) { splice @diff_cmd, 1, 0, "--compaction-heuristic"; } if (defined $patch_mode_revision) { diff --git a/git-archimport.perl b/git-archimport.perl index b7c173c..9cb123a 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -983,7 +983,7 @@ sub find_parents { # check that we actually know about the branch next unless -e "$git_dir/refs/heads/$branch"; - my $mergebase = safe_pipe_capture(qw(git-merge-base), $branch, $ps->{branch}); + my $mergebase = `git-merge-base $branch $ps->{branch}`; if ($?) { # Don't die here, Arch supports one-way cherry-picking # between branches with no common base (or any relationship @@ -1074,7 +1074,7 @@ sub find_parents { sub git_rev_parse { my $name = shift; - my $val = safe_pipe_capture(qw(git-rev-parse), $name); + my $val = `git-rev-parse $name`; die "Error: git-rev-parse $name" if $?; chomp $val; return $val; diff --git a/git-compat-util.h b/git-compat-util.h index d89a786..87237b0 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -441,6 +441,9 @@ static inline int const_error(void) extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params)); extern void set_error_routine(void (*routine)(const char *err, va_list params)); +extern void (*get_error_routine(void))(const char *err, va_list params); +extern void set_warn_routine(void (*routine)(const char *warn, va_list params)); +extern void (*get_warn_routine(void))(const char *warn, va_list params); extern void set_die_is_recursing_routine(int (*routine)(void)); extern void set_error_handle(FILE *); @@ -977,6 +980,14 @@ void git_qsort(void *base, size_t nmemb, size_t size, #define qsort git_qsort #endif +#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar) +static inline void sane_qsort(void *base, size_t nmemb, size_t size, + int(*compar)(const void *, const void *)) +{ + if (nmemb > 1) + qsort(base, nmemb, size, compar); +} + #ifndef REG_STARTEND #error "Git requires REG_STARTEND support. Compile with NO_REGEX=NeedsStartEnd" #endif diff --git a/git-cvsimport.perl b/git-cvsimport.perl index 3692992..1e4e65a 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -642,7 +642,6 @@ sub is_sha1 { sub get_headref ($) { my $name = shift; - $name =~ s/'/'\\''/; my $r = `git rev-parse --verify '$name' 2>/dev/null`; return undef unless $? == 0; chomp $r; diff --git a/git-cvsserver.perl b/git-cvsserver.perl index ae10442..d50c85e 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -356,7 +356,7 @@ sub req_Root return 0; } - my @gitvars = safe_pipe_capture(qw(git config -l)); + my @gitvars = `git config -l`; if ($?) { print "E problems executing git-config on the server -- this is not a git repository or the PATH is not set correctly.\n"; print "E \n"; @@ -841,7 +841,7 @@ sub req_Modified # Save the file data in $state $state->{entries}{$state->{directory}.$data}{modified_filename} = $filename; $state->{entries}{$state->{directory}.$data}{modified_mode} = $mode; - $state->{entries}{$state->{directory}.$data}{modified_hash} = safe_pipe_capture('git','hash-object',$filename); + $state->{entries}{$state->{directory}.$data}{modified_hash} = `git hash-object $filename`; $state->{entries}{$state->{directory}.$data}{modified_hash} =~ s/\s.*$//s; #$log->debug("req_Modified : file=$data mode=$mode size=$size"); @@ -943,7 +943,7 @@ sub req_co # Provide list of modules, if -c was used. if (exists $state->{opt}{c}) { - my $showref = safe_pipe_capture(qw(git show-ref --heads)); + my $showref = `git show-ref --heads`; for my $line (split '\n', $showref) { if ( $line =~ m% refs/heads/(.*)$% ) { print "M $1\t$1\n"; @@ -1181,7 +1181,7 @@ sub req_update # projects (heads in this case) to checkout. # if ($state->{module} eq '') { - my $showref = safe_pipe_capture(qw(git show-ref --heads)); + my $showref = `git show-ref --heads`; print "E cvs update: Updating .\n"; for my $line (split '\n', $showref) { if ( $line =~ m% refs/heads/(.*)$% ) { @@ -1463,7 +1463,7 @@ sub req_update # transmit file, format is single integer on a line by itself (file # size) followed by the file contents # TODO : we should copy files in blocks - my $data = safe_pipe_capture('cat', $mergedFile); + my $data = `cat $mergedFile`; $log->debug("File size : " . length($data)); print length($data) . "\n"; print $data; @@ -1579,7 +1579,7 @@ sub req_ci $branchRef = "refs/heads/$stickyInfo->{tag}"; } - $parenthash = safe_pipe_capture('git', 'show-ref', '-s', $branchRef); + $parenthash = `git show-ref -s $branchRef`; chomp $parenthash; if ($parenthash !~ /^[0-9a-f]{40}$/) { @@ -1687,7 +1687,7 @@ sub req_ci return; } - my $treehash = safe_pipe_capture(qw(git write-tree)); + my $treehash = `git write-tree`; chomp $treehash; $log->debug("Treehash : $treehash, Parenthash : $parenthash"); @@ -1704,7 +1704,7 @@ sub req_ci } close $msg_fh; - my $commithash = safe_pipe_capture('git', 'commit-tree', $treehash, '-p', $parenthash, '-F', $msg_filename); + my $commithash = `git commit-tree $treehash -p $parenthash < $msg_filename`; chomp($commithash); $log->info("Commit hash : $commithash"); @@ -2854,12 +2854,12 @@ sub transmitfile die "Need filehash" unless ( defined ( $filehash ) and $filehash =~ /^[a-zA-Z0-9]{40}$/ ); - my $type = safe_pipe_capture('git', 'cat-file', '-t', $filehash); + my $type = `git cat-file -t $filehash`; chomp $type; die ( "Invalid type '$type' (expected 'blob')" ) unless ( defined ( $type ) and $type eq "blob" ); - my $size = safe_pipe_capture('git', 'cat-file', '-s', $filehash); + my $size = `git cat-file -s $filehash`; chomp $size; $log->debug("transmitfile($filehash) size=$size, type=$type"); @@ -3040,7 +3040,7 @@ sub ensureWorkTree chdir $work->{emptyDir} or die "Unable to chdir to $work->{emptyDir}\n"; - my $ver = safe_pipe_capture('git', 'show-ref', '-s', "refs/heads/$state->{module}"); + my $ver = `git show-ref -s refs/heads/$state->{module}`; chomp $ver; if ($ver !~ /^[0-9a-f]{40}$/) { @@ -3287,7 +3287,7 @@ sub open_blob_or_die die "Need filehash\n"; } - my $type = safe_pipe_capture('git', 'cat-file', '-t', $name); + my $type = `git cat-file -t $name`; chomp $type; unless ( defined ( $type ) and $type eq "blob" ) @@ -3296,7 +3296,7 @@ sub open_blob_or_die die ( "Invalid type '$type' (expected 'blob')" ) } - my $size = safe_pipe_capture('git', 'cat-file', '-s', $name); + my $size = `git cat-file -s $name`; chomp $size; $log->debug("open_blob_or_die($name) size=$size, type=$type"); @@ -3406,22 +3406,6 @@ sub refHashEqual return $out; } -# an alternative to `command` that allows input to be passed as an array -# to work around shell problems with weird characters in arguments - -sub safe_pipe_capture { - - my @output; - - if (my $pid = open my $child, '-|') { - @output = (<$child>); - close $child or die join(' ',@_).": $! $?"; - } else { - exec(@_) or die "$! $?"; # exec() can fail the executable can't be found - } - return wantarray ? @output : join('',@output); -} - package GITCVS::log; @@ -3813,10 +3797,10 @@ sub update # first lets get the commit list $ENV{GIT_DIR} = $self->{git_path}; - my $commitsha1 = ::safe_pipe_capture('git', 'rev-parse', $self->{module}); + my $commitsha1 = `git rev-parse $self->{module}`; chomp $commitsha1; - my $commitinfo = ::safe_pipe_capture('git', 'cat-file', 'commit', $self->{module}); + my $commitinfo = `git cat-file commit $self->{module} 2>&1`; unless ( $commitinfo =~ /tree\s+[a-zA-Z0-9]{40}/ ) { die("Invalid module '$self->{module}'"); @@ -3898,7 +3882,7 @@ sub update # several candidate merge bases. let's assume # that the first one is the best one. my $base = eval { - ::safe_pipe_capture('git', 'merge-base', + safe_pipe_capture('git', 'merge-base', $lastpicked, $parent); }; # The two branches may not be related at all, @@ -4765,7 +4749,7 @@ sub getMetaFromCommithash return $retVal; } - my($fileHash) = ::safe_pipe_capture("git","rev-parse","$revCommit:$filename"); + my($fileHash)=safe_pipe_capture("git","rev-parse","$revCommit:$filename"); chomp $fileHash; if(!($fileHash=~/^[0-9a-f]{40}$/)) { @@ -4860,8 +4844,8 @@ sub lookupCommitRef return $commitHash; } - $commitHash = ::safe_pipe_capture("git","rev-parse","--verify","--quiet", - $self->unescapeRefName($ref)); + $commitHash=safe_pipe_capture("git","rev-parse","--verify","--quiet", + $self->unescapeRefName($ref)); $commitHash=~s/\s*$//; if(!($commitHash=~/^[0-9a-f]{40}$/)) { @@ -4870,7 +4854,7 @@ sub lookupCommitRef if( defined($commitHash) ) { - my $type = ::safe_pipe_capture("git","cat-file","-t",$commitHash); + my $type=safe_pipe_capture("git","cat-file","-t",$commitHash); if( ! ($type=~/^commit\s*$/ ) ) { $commitHash=undef; @@ -4923,7 +4907,7 @@ sub commitmessage return $message; } - my @lines = ::safe_pipe_capture("git", "cat-file", "commit", $commithash); + my @lines = safe_pipe_capture("git", "cat-file", "commit", $commithash); shift @lines while ( $lines[0] =~ /\S/ ); $message = join("",@lines); $message .= " " if ( $message =~ /\n$/ ); @@ -5072,6 +5056,25 @@ sub in_array return $retval; } +=head2 safe_pipe_capture + +an alternative to `command` that allows input to be passed as an array +to work around shell problems with weird characters in arguments + +=cut +sub safe_pipe_capture { + + my @output; + + if (my $pid = open my $child, '-|') { + @output = (<$child>); + close $child or die join(' ',@_).": $! $?"; + } else { + exec(@_) or die "$! $?"; # exec() can fail the executable can't be found + } + return wantarray ? @output : join('',@output); +} + =head2 mangle_dirname create a string from a directory name that is suitable to use as diff --git a/git-gui/GIT-VERSION-GEN b/git-gui/GIT-VERSION-GEN index a88b682..92373d2 100755 --- a/git-gui/GIT-VERSION-GEN +++ b/git-gui/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=0.20.GITGUI +DEF_VER=0.21.GITGUI LF=' ' diff --git a/git-gui/Makefile b/git-gui/Makefile index 4f00bdd..fe30be3 100644 --- a/git-gui/Makefile +++ b/git-gui/Makefile @@ -259,7 +259,7 @@ lib/tclIndex: $(ALL_LIBFILES) GIT-GUI-VARS rm -f $@ ; \ echo '# Autogenerated by git-gui Makefile' >$@ && \ echo >>$@ && \ - $(foreach p,$(PRELOAD_FILES) $(ALL_LIBFILES),echo '$(subst lib/,,$p)' >>$@ &&) \ + $(foreach p,$(PRELOAD_FILES) $(sort $(ALL_LIBFILES)),echo '$(subst lib/,,$p)' >>$@ &&) \ echo >>$@ ; \ fi diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh index 11048c7..5bc21b8 100755 --- a/git-gui/git-gui.sh +++ b/git-gui/git-gui.sh @@ -275,6 +275,10 @@ proc is_Cygwin {} { set _iscygwin 0 } else { set _iscygwin 1 + # Handle MSys2 which is only cygwin when MSYSTEM is MSYS. + if {[info exists ::env(MSYSTEM)] && $::env(MSYSTEM) ne "MSYS"} { + set _iscygwin 0 + } } } else { set _iscygwin 0 @@ -530,28 +534,10 @@ proc _lappend_nice {cmd_var} { } proc git {args} { - set opt [list] - - while {1} { - switch -- [lindex $args 0] { - --nice { - _lappend_nice opt - } - - default { - break - } - - } - - set args [lrange $args 1 end] - } - - set cmdp [_git_cmd [lindex $args 0]] - set args [lrange $args 1 end] - - _trace_exec [concat $opt $cmdp $args] - set result [eval exec $opt $cmdp $args] + set fd [eval [list git_read] $args] + fconfigure $fd -translation binary -encoding utf-8 + set result [string trimright [read $fd] "\n"] + close $fd if {$::_trace} { puts stderr "< $result" } @@ -1107,7 +1093,7 @@ git-version proc _parse_config {arr_name args} { [list git_read config] \ $args \ [list --null --list]] - fconfigure $fd_rc -translation binary + fconfigure $fd_rc -translation binary -encoding utf-8 set buf [read $fd_rc] close $fd_rc } @@ -1616,11 +1602,13 @@ proc run_prepare_commit_msg_hook {} { if {[file isfile [gitdir MERGE_MSG]]} { set pcm_source "merge" set fd_mm [open [gitdir MERGE_MSG] r] + fconfigure $fd_mm -encoding utf-8 puts -nonewline $fd_pcm [read $fd_mm] close $fd_mm } elseif {[file isfile [gitdir SQUASH_MSG]]} { set pcm_source "squash" set fd_sm [open [gitdir SQUASH_MSG] r] + fconfigure $fd_sm -encoding utf-8 puts -nonewline $fd_pcm [read $fd_sm] close $fd_sm } else { @@ -1685,7 +1673,7 @@ proc read_diff_index {fd after} { set i [split [string range $buf_rdi $c [expr {$z1 - 2}]] { }] set p [string range $buf_rdi $z1 [expr {$z2 - 1}]] merge_state \ - [encoding convertfrom $p] \ + [encoding convertfrom utf-8 $p] \ [lindex $i 4]? \ [list [lindex $i 0] [lindex $i 2]] \ [list] @@ -1718,7 +1706,7 @@ proc read_diff_files {fd after} { set i [split [string range $buf_rdf $c [expr {$z1 - 2}]] { }] set p [string range $buf_rdf $z1 [expr {$z2 - 1}]] merge_state \ - [encoding convertfrom $p] \ + [encoding convertfrom utf-8 $p] \ ?[lindex $i 4] \ [list] \ [list [lindex $i 0] [lindex $i 2]] @@ -1741,7 +1729,7 @@ proc read_ls_others {fd after} { set pck [split $buf_rlo "\0"] set buf_rlo [lindex $pck end] foreach p [lrange $pck 0 end-1] { - set p [encoding convertfrom $p] + set p [encoding convertfrom utf-8 $p] if {[string index $p end] eq {/}} { set p [string range $p 0 end-1] } @@ -2505,13 +2493,28 @@ proc force_first_diff {after} { } } -proc toggle_or_diff {w x y} { +proc toggle_or_diff {mode w args} { global file_states file_lists current_diff_path ui_index ui_workdir global last_clicked selected_paths - set pos [split [$w index @$x,$y] .] - set lno [lindex $pos 0] - set col [lindex $pos 1] + if {$mode eq "click"} { + foreach {x y} $args break + set pos [split [$w index @$x,$y] .] + foreach {lno col} $pos break + } else { + if {$last_clicked ne {}} { + set lno [lindex $last_clicked 1] + } else { + set lno [expr {int([lindex [$w tag ranges in_diff] 0])}] + } + if {$mode eq "toggle"} { + set col 0; set y 2 + } else { + incr lno [expr {$mode eq "up" ? -1 : 1}] + set col 1 + } + } + set path [lindex $file_lists($w) [expr {$lno - 1}]] if {$path eq {}} { set last_clicked {} @@ -2519,6 +2522,7 @@ proc toggle_or_diff {w x y} { } set last_clicked [list $w $lno] + focus $w array unset selected_paths $ui_index tag remove in_sel 0.0 end $ui_workdir tag remove in_sel 0.0 end @@ -2598,7 +2602,7 @@ proc add_range_to_selection {w x y} { global file_lists last_clicked selected_paths if {[lindex $last_clicked 0] ne $w} { - toggle_or_diff $w $x $y + toggle_or_diff click $w $x $y return } @@ -3007,7 +3011,7 @@ bind all <$M1B-Key-W> {destroy [winfo toplevel %W]} set subcommand_args {} proc usage {} { - set s "usage: $::argv0 $::subcommand $::subcommand_args" + set s "[mc usage:] $::argv0 $::subcommand $::subcommand_args" if {[tk windowingsystem] eq "win32"} { wm withdraw . tk_messageBox -icon info -message $s \ @@ -3139,7 +3143,7 @@ gui { # fall through to setup UI for commits } default { - set err "usage: $argv0 \[{blame|browser|citool}\]" + set err "[mc usage:] $argv0 \[{blame|browser|citool}\]" if {[tk windowingsystem] eq "win32"} { wm withdraw . tk_messageBox -icon error -message $err \ @@ -3178,16 +3182,38 @@ if {$use_ttk} { } pack .vpane -anchor n -side top -fill both -expand 1 +# -- Working Directory File List + +textframe .vpane.files.workdir -height 100 -width 200 +tlabel .vpane.files.workdir.title -text [mc "Unstaged Changes"] \ + -background lightsalmon -foreground black +ttext $ui_workdir -background white -foreground black \ + -borderwidth 0 \ + -width 20 -height 10 \ + -wrap none \ + -takefocus 1 -highlightthickness 1\ + -cursor $cursor_ptr \ + -xscrollcommand {.vpane.files.workdir.sx set} \ + -yscrollcommand {.vpane.files.workdir.sy set} \ + -state disabled +${NS}::scrollbar .vpane.files.workdir.sx -orient h -command [list $ui_workdir xview] +${NS}::scrollbar .vpane.files.workdir.sy -orient v -command [list $ui_workdir yview] +pack .vpane.files.workdir.title -side top -fill x +pack .vpane.files.workdir.sx -side bottom -fill x +pack .vpane.files.workdir.sy -side right -fill y +pack $ui_workdir -side left -fill both -expand 1 + # -- Index File List # -${NS}::frame .vpane.files.index -height 100 -width 200 +textframe .vpane.files.index -height 100 -width 200 tlabel .vpane.files.index.title \ -text [mc "Staged Changes (Will Commit)"] \ -background lightgreen -foreground black -text $ui_index -background white -foreground black \ +ttext $ui_index -background white -foreground black \ -borderwidth 0 \ -width 20 -height 10 \ -wrap none \ + -takefocus 1 -highlightthickness 1\ -cursor $cursor_ptr \ -xscrollcommand {.vpane.files.index.sx set} \ -yscrollcommand {.vpane.files.index.sy set} \ @@ -3199,26 +3225,8 @@ pack .vpane.files.index.sx -side bottom -fill x pack .vpane.files.index.sy -side right -fill y pack $ui_index -side left -fill both -expand 1 -# -- Working Directory File List +# -- Insert the workdir and index into the panes # -${NS}::frame .vpane.files.workdir -height 100 -width 200 -tlabel .vpane.files.workdir.title -text [mc "Unstaged Changes"] \ - -background lightsalmon -foreground black -text $ui_workdir -background white -foreground black \ - -borderwidth 0 \ - -width 20 -height 10 \ - -wrap none \ - -cursor $cursor_ptr \ - -xscrollcommand {.vpane.files.workdir.sx set} \ - -yscrollcommand {.vpane.files.workdir.sy set} \ - -state disabled -${NS}::scrollbar .vpane.files.workdir.sx -orient h -command [list $ui_workdir xview] -${NS}::scrollbar .vpane.files.workdir.sy -orient v -command [list $ui_workdir yview] -pack .vpane.files.workdir.title -side top -fill x -pack .vpane.files.workdir.sx -side bottom -fill x -pack .vpane.files.workdir.sy -side right -fill y -pack $ui_workdir -side left -fill both -expand 1 - .vpane.files add .vpane.files.workdir .vpane.files add .vpane.files.index if {!$use_ttk} { @@ -3301,7 +3309,7 @@ if {![is_enabled nocommit]} { # ${NS}::frame .vpane.lower.commarea.buffer ${NS}::frame .vpane.lower.commarea.buffer.header -set ui_comm .vpane.lower.commarea.buffer.t +set ui_comm .vpane.lower.commarea.buffer.frame.t set ui_coml .vpane.lower.commarea.buffer.header.l if {![is_enabled nocommit]} { @@ -3344,20 +3352,25 @@ if {![is_enabled nocommit]} { pack .vpane.lower.commarea.buffer.header.new -side right } -text $ui_comm -background white -foreground black \ +textframe .vpane.lower.commarea.buffer.frame +ttext $ui_comm -background white -foreground black \ -borderwidth 1 \ -undo true \ -maxundo 20 \ -autoseparators true \ + -takefocus 1 \ + -highlightthickness 1 \ -relief sunken \ -width $repo_config(gui.commitmsgwidth) -height 9 -wrap none \ -font font_diff \ - -yscrollcommand {.vpane.lower.commarea.buffer.sby set} -${NS}::scrollbar .vpane.lower.commarea.buffer.sby \ + -yscrollcommand {.vpane.lower.commarea.buffer.frame.sby set} +${NS}::scrollbar .vpane.lower.commarea.buffer.frame.sby \ -command [list $ui_comm yview] -pack .vpane.lower.commarea.buffer.header -side top -fill x -pack .vpane.lower.commarea.buffer.sby -side right -fill y + +pack .vpane.lower.commarea.buffer.frame.sby -side right -fill y pack $ui_comm -side left -fill y +pack .vpane.lower.commarea.buffer.header -side top -fill x +pack .vpane.lower.commarea.buffer.frame -side left -fill y pack .vpane.lower.commarea.buffer -side left -fill y # -- Commit Message Buffer Context Menu @@ -3455,12 +3468,13 @@ bind_button3 .vpane.lower.diff.header.path "tk_popup $ctxm %X %Y" # -- Diff Body # -${NS}::frame .vpane.lower.diff.body +textframe .vpane.lower.diff.body set ui_diff .vpane.lower.diff.body.t -text $ui_diff -background white -foreground black \ +ttext $ui_diff -background white -foreground black \ -borderwidth 0 \ -width 80 -height 5 -wrap none \ -font font_diff \ + -takefocus 1 -highlightthickness 1 \ -xscrollcommand {.vpane.lower.diff.body.sbx set} \ -yscrollcommand {.vpane.lower.diff.body.sby set} \ -state disabled @@ -3815,10 +3829,10 @@ bind . <$M1B-Key-r> ui_do_rescan bind . <$M1B-Key-R> ui_do_rescan bind . <$M1B-Key-s> do_signoff bind . <$M1B-Key-S> do_signoff -bind . <$M1B-Key-t> do_add_selection -bind . <$M1B-Key-T> do_add_selection -bind . <$M1B-Key-u> do_unstage_selection -bind . <$M1B-Key-U> do_unstage_selection +bind . <$M1B-Key-t> { toggle_or_diff toggle %W } +bind . <$M1B-Key-T> { toggle_or_diff toggle %W } +bind . <$M1B-Key-u> { toggle_or_diff toggle %W } +bind . <$M1B-Key-U> { toggle_or_diff toggle %W } bind . <$M1B-Key-j> do_revert_selection bind . <$M1B-Key-J> do_revert_selection bind . <$M1B-Key-i> do_add_all @@ -3830,9 +3844,11 @@ bind . <$M1B-Key-plus> {show_more_context;break} bind . <$M1B-Key-KP_Add> {show_more_context;break} bind . <$M1B-Key-Return> do_commit foreach i [list $ui_index $ui_workdir] { - bind $i "toggle_or_diff $i %x %y; break" - bind $i <$M1B-Button-1> "add_one_to_selection $i %x %y; break" - bind $i "add_range_to_selection $i %x %y; break" + bind $i { toggle_or_diff click %W %x %y; break } + bind $i <$M1B-Button-1> { add_one_to_selection %W %x %y; break } + bind $i { add_range_to_selection %W %x %y; break } + bind $i { toggle_or_diff up %W; break } + bind $i { toggle_or_diff down %W; break } } unset i diff --git a/git-gui/lib/blame.tcl b/git-gui/lib/blame.tcl index b1d15f4..a1aeb8b 100644 --- a/git-gui/lib/blame.tcl +++ b/git-gui/lib/blame.tcl @@ -70,7 +70,7 @@ constructor new {i_commit i_path i_jump} { set path $i_path make_toplevel top w - wm title $top [append "[appname] ([reponame]): " [mc "File Viewer"]] + wm title $top [mc "%s (%s): File Viewer" [appname] [reponame]] set font_w [font measure font_diff "0"] diff --git a/git-gui/lib/branch_checkout.tcl b/git-gui/lib/branch_checkout.tcl index 2e459a8..d06037d 100644 --- a/git-gui/lib/branch_checkout.tcl +++ b/git-gui/lib/branch_checkout.tcl @@ -13,7 +13,7 @@ constructor dialog {} { global use_ttk NS make_dialog top w wm withdraw $w - wm title $top [append "[appname] ([reponame]): " [mc "Checkout Branch"]] + wm title $top [mc "%s (%s): Checkout Branch" [appname] [reponame]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } diff --git a/git-gui/lib/branch_create.tcl b/git-gui/lib/branch_create.tcl index 4bb9077..ba367d5 100644 --- a/git-gui/lib/branch_create.tcl +++ b/git-gui/lib/branch_create.tcl @@ -20,7 +20,7 @@ constructor dialog {} { make_dialog top w wm withdraw $w - wm title $top [append "[appname] ([reponame]): " [mc "Create Branch"]] + wm title $top [mc "%s (%s): Create Branch" [appname] [reponame]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } diff --git a/git-gui/lib/branch_delete.tcl b/git-gui/lib/branch_delete.tcl index 867938e..a505163 100644 --- a/git-gui/lib/branch_delete.tcl +++ b/git-gui/lib/branch_delete.tcl @@ -13,7 +13,7 @@ constructor dialog {} { make_dialog top w wm withdraw $w - wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch"]] + wm title $top [mc "%s (%s): Delete Branch" [appname] [reponame]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } @@ -128,7 +128,7 @@ method _delete {} { set b [lindex $i 0] set o [lindex $i 1] if {[catch {git branch -D $b} err]} { - append failed " - $b: $err\n" + append failed [mc " - %s:" $b] " $err\n" } } diff --git a/git-gui/lib/branch_rename.tcl b/git-gui/lib/branch_rename.tcl index 6e510ec..3a2d79a 100644 --- a/git-gui/lib/branch_rename.tcl +++ b/git-gui/lib/branch_rename.tcl @@ -12,7 +12,7 @@ constructor dialog {} { make_dialog top w wm withdraw $w - wm title $top [append "[appname] ([reponame]): " [mc "Rename Branch"]] + wm title $top [mc "%s (%s): Rename Branch" [appname] [reponame]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } diff --git a/git-gui/lib/browser.tcl b/git-gui/lib/browser.tcl index 0328338..a982983 100644 --- a/git-gui/lib/browser.tcl +++ b/git-gui/lib/browser.tcl @@ -24,7 +24,7 @@ constructor new {commit {path {}}} { global cursor_ptr M1B use_ttk NS make_dialog top w wm withdraw $top - wm title $top [append "[appname] ([reponame]): " [mc "File Browser"]] + wm title $top [mc "%s (%s): File Browser" [appname] [reponame]] if {$path ne {}} { if {[string index $path end] ne {/}} { @@ -197,7 +197,7 @@ method _ls {tree_id {name {}}} { $w conf -state disabled set fd [git_read ls-tree -z $tree_id] - fconfigure $fd -blocking 0 -translation binary -encoding binary + fconfigure $fd -blocking 0 -translation binary -encoding utf-8 fileevent $fd readable [cb _read $fd] } @@ -272,7 +272,7 @@ constructor dialog {} { global use_ttk NS make_dialog top w wm withdraw $top - wm title $top [append "[appname] ([reponame]): " [mc "Browse Branch Files"]] + wm title $top [mc "%s (%s): Browse Branch Files" [appname] [reponame]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm transient $top . diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl index 01d2cc2..83620b7 100644 --- a/git-gui/lib/commit.tcl +++ b/git-gui/lib/commit.tcl @@ -2,7 +2,7 @@ # Copyright (C) 2006, 2007 Shawn Pearce proc load_last_commit {} { - global HEAD PARENT MERGE_HEAD commit_type ui_comm + global HEAD PARENT MERGE_HEAD commit_type ui_comm commit_author global repo_config if {[llength $PARENT] == 0} { @@ -34,6 +34,8 @@ You are currently in the middle of a merge that has not been fully completed. Y lappend parents [string range $line 7 end] } elseif {[string match {encoding *} $line]} { set enc [string tolower [string range $line 9 end]] + } elseif {[regexp "author (.*)\\s<(.*)>\\s(\\d.*$)" $line all name email time]} { + set commit_author [list name $name email $email date $time] } } set msg [read $fd] @@ -106,9 +108,10 @@ proc do_signoff {} { } proc create_new_commit {} { - global commit_type ui_comm + global commit_type ui_comm commit_author set commit_type normal + unset -nocomplain commit_author $ui_comm delete 0.0 end $ui_comm edit reset $ui_comm edit modified false @@ -322,11 +325,12 @@ proc commit_writetree {curHEAD msg_p} { } proc commit_committree {fd_wt curHEAD msg_p} { - global HEAD PARENT MERGE_HEAD commit_type + global HEAD PARENT MERGE_HEAD commit_type commit_author global current_branch global ui_comm selected_commit_type global file_states selected_paths rescan_active global repo_config + global env gets $fd_wt tree_id if {[catch {close $fd_wt} err]} { @@ -366,6 +370,9 @@ A rescan will be automatically started now. } } + if {[info exists commit_author]} { + set old_author [commit_author_ident $commit_author] + } # -- Create the commit. # set cmd [list commit-tree $tree_id] @@ -381,8 +388,14 @@ A rescan will be automatically started now. error_popup [strcat [mc "commit-tree failed:"] "\n\n$err"] ui_status [mc "Commit failed."] unlock_index + unset -nocomplain commit_author + commit_author_reset $old_author return } + if {[info exists commit_author]} { + unset -nocomplain commit_author + commit_author_reset $old_author + } # -- Update the HEAD ref. # @@ -509,3 +522,20 @@ proc commit_postcommit_wait {fd_ph cmt_id} { } fconfigure $fd_ph -blocking 0 } + +proc commit_author_ident {details} { + global env + array set author $details + set old [array get env GIT_AUTHOR_*] + set env(GIT_AUTHOR_NAME) $author(name) + set env(GIT_AUTHOR_EMAIL) $author(email) + set env(GIT_AUTHOR_DATE) $author(date) + return $old +} +proc commit_author_reset {details} { + global env + unset env(GIT_AUTHOR_NAME) env(GIT_AUTHOR_EMAIL) env(GIT_AUTHOR_DATE) + if {$details ne {}} { + array set env $details + } +} diff --git a/git-gui/lib/database.tcl b/git-gui/lib/database.tcl index 1f187ed..8578308 100644 --- a/git-gui/lib/database.tcl +++ b/git-gui/lib/database.tcl @@ -54,7 +54,7 @@ proc do_stats {} { set value "$value[lindex $s 2]" } - ${NS}::label $w.stat.l_$name -text "$label:" -anchor w + ${NS}::label $w.stat.l_$name -text [mc "%s:" $label] -anchor w ${NS}::label $w.stat.v_$name -text $value -anchor w grid $w.stat.l_$name $w.stat.v_$name -sticky we -padx {0 5} } @@ -63,7 +63,7 @@ proc do_stats {} { bind $w "grab $w; focus $w.buttons.close" bind $w [list destroy $w] bind $w [list destroy $w] - wm title $w [append "[appname] ([reponame]): " [mc "Database Statistics"]] + wm title $w [mc "%s (%s): Database Statistics" [appname] [reponame]] wm deiconify $w tkwait window $w } diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl index 0d56986..4cae10a 100644 --- a/git-gui/lib/diff.tcl +++ b/git-gui/lib/diff.tcl @@ -127,6 +127,9 @@ proc show_diff {path w {lno {}} {scroll_pos {}} {callback {}}} { } else { start_show_diff $cont_info } + + global current_diff_path selected_paths + set selected_paths($current_diff_path) 1 } proc show_unmerged_diff {cont_info} { @@ -220,10 +223,9 @@ proc show_other_diff {path w m cont_info} { } $ui_diff conf -state normal if {$type eq {submodule}} { - $ui_diff insert end [append \ - "* " \ - [mc "Git Repository (subproject)"] \ - "\n"] d_info + $ui_diff insert end \ + "* [mc "Git Repository (subproject)"]\n" \ + d_info } elseif {![catch {set type [exec file $path]}]} { set n [string length $path] if {[string equal -length $n $path $type]} { @@ -608,7 +610,7 @@ proc apply_hunk {x y} { puts -nonewline $p $current_diff_header puts -nonewline $p [$ui_diff get $s_lno $e_lno] close $p} err]} { - error_popup [append $failed_msg "\n\n$err"] + error_popup "$failed_msg\n\n$err" unlock_index return } @@ -826,7 +828,7 @@ proc apply_range_or_line {x y} { puts -nonewline $p $current_diff_header puts -nonewline $p $wholepatch close $p} err]} { - error_popup [append $failed_msg "\n\n$err"] + error_popup "$failed_msg\n\n$err" } unlock_index diff --git a/git-gui/lib/error.tcl b/git-gui/lib/error.tcl index c0fa69a..8968a57 100644 --- a/git-gui/lib/error.tcl +++ b/git-gui/lib/error.tcl @@ -17,7 +17,7 @@ proc error_popup {msg} { set cmd [list tk_messageBox \ -icon error \ -type ok \ - -title [append "$title: " [mc "error"]] \ + -title [mc "%s: error" $title] \ -message $msg] if {[winfo ismapped [_error_parent]]} { lappend cmd -parent [_error_parent] @@ -33,7 +33,7 @@ proc warn_popup {msg} { set cmd [list tk_messageBox \ -icon warning \ -type ok \ - -title [append "$title: " [mc "warning"]] \ + -title [mc "%s: warning" $title] \ -message $msg] if {[winfo ismapped [_error_parent]]} { lappend cmd -parent [_error_parent] @@ -77,7 +77,7 @@ proc hook_failed_popup {hook msg {is_fatal 1}} { wm withdraw $w ${NS}::frame $w.m - ${NS}::label $w.m.l1 -text "$hook hook failed:" \ + ${NS}::label $w.m.l1 -text [mc "%s hook failed:" $hook] \ -anchor w \ -justify left \ -font font_uibold @@ -113,7 +113,7 @@ proc hook_failed_popup {hook msg {is_fatal 1}} { bind $w "grab $w; focus $w" bind $w "destroy $w" - wm title $w [strcat "[appname] ([reponame]): " [mc "error"]] + wm title $w [mc "%s (%s): error" [appname] [reponame]] wm deiconify $w tkwait window $w } diff --git a/git-gui/lib/index.tcl b/git-gui/lib/index.tcl index 74a81a7..b588db1 100644 --- a/git-gui/lib/index.tcl +++ b/git-gui/lib/index.tcl @@ -115,7 +115,7 @@ proc write_update_indexinfo {fd pathList totalCnt batch after} { set info [lindex $s 2] if {$info eq {}} continue - puts -nonewline $fd "$info\t[encoding convertto $path]\0" + puts -nonewline $fd "$info\t[encoding convertto utf-8 $path]\0" display_file $path $new } @@ -186,7 +186,7 @@ proc write_update_index {fd pathList totalCnt batch after} { ?M {set new M_} ?? {continue} } - puts -nonewline $fd "[encoding convertto $path]\0" + puts -nonewline $fd "[encoding convertto utf-8 $path]\0" display_file $path $new } @@ -247,7 +247,7 @@ proc write_checkout_index {fd pathList totalCnt batch after} { ?M - ?T - ?D { - puts -nonewline $fd "[encoding convertto $path]\0" + puts -nonewline $fd "[encoding convertto utf-8 $path]\0" display_file $path ?_ } } @@ -291,7 +291,7 @@ proc do_unstage_selection {} { if {[array size selected_paths] > 0} { unstage_helper \ - {Unstaging selected files from commit} \ + [mc "Unstaging selected files from commit"] \ [array names selected_paths] } elseif {$current_diff_path ne {}} { unstage_helper \ @@ -343,7 +343,7 @@ proc do_add_selection {} { if {[array size selected_paths] > 0} { add_helper \ - {Adding selected files} \ + [mc "Adding selected files"] \ [array names selected_paths] } elseif {$current_diff_path ne {}} { add_helper \ @@ -385,7 +385,7 @@ proc do_add_all {} { set paths [concat $paths $untracked_paths] } } - add_helper {Adding all changed files} $paths + add_helper [mc "Adding all changed files"] $paths } proc revert_helper {txt paths} { diff --git a/git-gui/lib/merge.tcl b/git-gui/lib/merge.tcl index 5ab6f8f..9f253db 100644 --- a/git-gui/lib/merge.tcl +++ b/git-gui/lib/merge.tcl @@ -112,7 +112,16 @@ method _start {} { close $fh set _last_merged_branch $branch - set cmd [list git merge --strategy=recursive FETCH_HEAD] + if {[git-version >= "2.5.0"]} { + set cmd [list git merge --strategy=recursive FETCH_HEAD] + } else { + set cmd [list git] + lappend cmd merge + lappend cmd --strategy=recursive + lappend cmd [git fmt-merge-msg <[gitdir FETCH_HEAD]] + lappend cmd HEAD + lappend cmd $name + } ui_status [mc "Merging %s and %s..." $current_branch $stitle] set cons [console::new [mc "Merge"] "merge $stitle"] @@ -144,7 +153,7 @@ constructor dialog {} { } make_dialog top w - wm title $top [append "[appname] ([reponame]): " [mc "Merge"]] + wm title $top [mc "%s (%s): Merge" [appname] [reponame]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } diff --git a/git-gui/lib/option.tcl b/git-gui/lib/option.tcl index b5b6b2f..e43971b 100644 --- a/git-gui/lib/option.tcl +++ b/git-gui/lib/option.tcl @@ -179,7 +179,7 @@ proc do_options {} { i-* { regexp -- {-(\d+)\.\.(\d+)$} $type _junk min max ${NS}::frame $w.$f.$optid - ${NS}::label $w.$f.$optid.l -text "$text:" + ${NS}::label $w.$f.$optid.l -text [mc "%s:" $text] pack $w.$f.$optid.l -side left -anchor w -fill x tspinbox $w.$f.$optid.v \ -textvariable ${f}_config_new($name) \ @@ -194,7 +194,7 @@ proc do_options {} { c - t { ${NS}::frame $w.$f.$optid - ${NS}::label $w.$f.$optid.l -text "$text:" + ${NS}::label $w.$f.$optid.l -text [mc "%s:" $text] ${NS}::entry $w.$f.$optid.v \ -width 20 \ -textvariable ${f}_config_new($name) @@ -217,7 +217,7 @@ proc do_options {} { s { set opts [eval [lindex $option 3]] ${NS}::frame $w.$f.$optid - ${NS}::label $w.$f.$optid.l -text "$text:" + ${NS}::label $w.$f.$optid.l -text [mc "%s:" $text] if {$use_ttk} { ttk::combobox $w.$f.$optid.v \ -textvariable ${f}_config_new($name) \ @@ -279,7 +279,7 @@ proc do_options {} { [font configure $font -size] ${NS}::frame $w.global.$name - ${NS}::label $w.global.$name.l -text "$text:" + ${NS}::label $w.global.$name.l -text [mc "%s:" $text] ${NS}::button $w.global.$name.b \ -text [mc "Change Font"] \ -command [list \ diff --git a/git-gui/lib/remote.tcl b/git-gui/lib/remote.tcl index 4e5c784..ef77ed7 100644 --- a/git-gui/lib/remote.tcl +++ b/git-gui/lib/remote.tcl @@ -246,22 +246,22 @@ proc update_all_remotes_menu_entry {} { if {$have_remote > 1} { make_sure_remote_submenues_exist $remote_m if {[$fetch_m type end] eq "command" \ - && [$fetch_m entrycget end -label] ne "All"} { + && [$fetch_m entrycget end -label] ne [mc "All"]} { $fetch_m insert end separator $fetch_m insert end command \ - -label "All" \ + -label [mc "All"] \ -command fetch_from_all $prune_m insert end separator $prune_m insert end command \ - -label "All" \ + -label [mc "All"] \ -command prune_from_all } } else { if {[winfo exists $fetch_m]} { if {[$fetch_m type end] eq "command" \ - && [$fetch_m entrycget end -label] eq "All"} { + && [$fetch_m entrycget end -label] eq [mc "All"]} { delete_from_menu $fetch_m end delete_from_menu $fetch_m end diff --git a/git-gui/lib/remote_add.tcl b/git-gui/lib/remote_add.tcl index 50029d0..480a6b3 100644 --- a/git-gui/lib/remote_add.tcl +++ b/git-gui/lib/remote_add.tcl @@ -17,7 +17,7 @@ constructor dialog {} { make_dialog top w wm withdraw $top - wm title $top [append "[appname] ([reponame]): " [mc "Add Remote"]] + wm title $top [mc "%s (%s): Add Remote" [appname] [reponame]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } diff --git a/git-gui/lib/remote_branch_delete.tcl b/git-gui/lib/remote_branch_delete.tcl index fcc06d0..5ba9fca 100644 --- a/git-gui/lib/remote_branch_delete.tcl +++ b/git-gui/lib/remote_branch_delete.tcl @@ -26,7 +26,7 @@ constructor dialog {} { global all_remotes M1B use_ttk NS make_dialog top w - wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch Remotely"]] + wm title $top [mc "%s (%s): Delete Branch Remotely" [appname] [reponame]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } diff --git a/git-gui/lib/shortcut.tcl b/git-gui/lib/shortcut.tcl index 78878ef..97d1d7a 100644 --- a/git-gui/lib/shortcut.tcl +++ b/git-gui/lib/shortcut.tcl @@ -5,17 +5,20 @@ proc do_windows_shortcut {} { global _gitworktree set fn [tk_getSaveFile \ -parent . \ - -title [append "[appname] ([reponame]): " [mc "Create Desktop Icon"]] \ + -title [mc "%s (%s): Create Desktop Icon" [appname] [reponame]] \ -initialfile "Git [reponame].lnk"] if {$fn != {}} { if {[file extension $fn] ne {.lnk}} { set fn ${fn}.lnk } + # Use git-gui.exe if available (ie: git-for-windows) + set cmdLine [auto_execok git-gui.exe] + if {$cmdLine eq {}} { + set cmdLine [list [info nameofexecutable] \ + [file normalize $::argv0]] + } if {[catch { - win32_create_lnk $fn [list \ - [info nameofexecutable] \ - [file normalize $::argv0] \ - ] \ + win32_create_lnk $fn $cmdLine \ [file normalize $_gitworktree] } err]} { error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"] @@ -37,7 +40,7 @@ proc do_cygwin_shortcut {} { } set fn [tk_getSaveFile \ -parent . \ - -title [append "[appname] ([reponame]): " [mc "Create Desktop Icon"]] \ + -title [mc "%s (%s): Create Desktop Icon" [appname] [reponame]] \ -initialdir $desktop \ -initialfile "Git [reponame].lnk"] if {$fn != {}} { @@ -69,7 +72,7 @@ proc do_macosx_app {} { set fn [tk_getSaveFile \ -parent . \ - -title [append "[appname] ([reponame]): " [mc "Create Desktop Icon"]] \ + -title [mc "%s (%s): Create Desktop Icon" [appname] [reponame]] \ -initialdir [file join $env(HOME) Desktop] \ -initialfile "Git [reponame].app"] if {$fn != {}} { diff --git a/git-gui/lib/themed.tcl b/git-gui/lib/themed.tcl index 8b88d36..351a712 100644 --- a/git-gui/lib/themed.tcl +++ b/git-gui/lib/themed.tcl @@ -78,6 +78,57 @@ proc InitTheme {} { } } +# Define a style used for the surround of text widgets. +proc InitEntryFrame {} { + ttk::style theme settings default { + ttk::style layout EntryFrame { + EntryFrame.field -sticky nswe -border 0 -children { + EntryFrame.fill -sticky nswe -children { + EntryFrame.padding -sticky nswe + } + } + } + ttk::style configure EntryFrame -padding 1 -relief sunken + ttk::style map EntryFrame -background {} + } + ttk::style theme settings classic { + ttk::style configure EntryFrame -padding 2 -relief sunken + ttk::style map EntryFrame -background {} + } + ttk::style theme settings alt { + ttk::style configure EntryFrame -padding 2 + ttk::style map EntryFrame -background {} + } + ttk::style theme settings clam { + ttk::style configure EntryFrame -padding 2 + ttk::style map EntryFrame -background {} + } + + # Ignore errors for missing native themes + catch { + ttk::style theme settings winnative { + ttk::style configure EntryFrame -padding 2 + } + ttk::style theme settings xpnative { + ttk::style configure EntryFrame -padding 1 + ttk::style element create EntryFrame.field vsapi \ + EDIT 1 {disabled 4 focus 3 active 2 {} 1} -padding 1 + } + ttk::style theme settings vista { + ttk::style configure EntryFrame -padding 2 + ttk::style element create EntryFrame.field vsapi \ + EDIT 6 {disabled 4 focus 3 active 2 {} 1} -padding 2 + } + } + + bind EntryFrame {%W instate !disabled {%W state active}} + bind EntryFrame {%W state !active} + bind EntryFrame <> { + set pad [ttk::style lookup EntryFrame -padding] + %W configure -padding [expr {$pad eq {} ? 1 : $pad}] + } +} + proc gold_frame {w args} { global use_ttk if {$use_ttk} { @@ -123,7 +174,7 @@ proc paddedlabel {w args} { # place a themed frame over the surface. proc Dialog {w args} { eval [linsert $args 0 toplevel $w -class Dialog] - catch {wm attributes $w -type dialog} + catch {wm attributes $w -type dialog} pave_toplevel $w return $w } @@ -193,6 +244,40 @@ proc tspinbox {w args} { } } +# Create a text widget with any theme specific properties. +proc ttext {w args} { + global use_ttk + if {$use_ttk} { + switch -- [ttk::style theme use] { + "vista" - "xpnative" { + lappend args -highlightthickness 0 -borderwidth 0 + } + } + } + set w [eval [linsert $args 0 text $w]] + if {$use_ttk} { + if {[winfo class [winfo parent $w]] eq "EntryFrame"} { + bind $w {[winfo parent %W] state focus} + bind $w {[winfo parent %W] state !focus} + } + } + return $w +} + +# themed frame suitable for surrounding a text field. +proc textframe {w args} { + global use_ttk + if {$use_ttk} { + if {[catch {ttk::style layout EntryFrame}]} { + InitEntryFrame + } + eval [linsert $args 0 ttk::frame $w -class EntryFrame -style EntryFrame] + } else { + eval [linsert $args 0 frame $w] + } + return $w +} + proc tentry {w args} { global use_ttk if {$use_ttk} { diff --git a/git-gui/lib/tools.tcl b/git-gui/lib/tools.tcl index 6ec9411..413f1a1 100644 --- a/git-gui/lib/tools.tcl +++ b/git-gui/lib/tools.tcl @@ -69,6 +69,7 @@ proc tools_populate_one {fullname} { proc tools_exec {fullname} { global repo_config env current_diff_path global current_branch is_detached + global selected_paths if {[is_config_true "guitool.$fullname.needsfile"]} { if {$current_diff_path eq {}} { @@ -100,6 +101,7 @@ proc tools_exec {fullname} { set env(GIT_GUITOOL) $fullname set env(FILENAME) $current_diff_path + set env(FILENAMES) [join [array names selected_paths] \n] if {$is_detached} { set env(CUR_BRANCH) "" } else { @@ -121,6 +123,7 @@ proc tools_exec {fullname} { unset env(GIT_GUITOOL) unset env(FILENAME) + unset env(FILENAMES) unset env(CUR_BRANCH) catch { unset env(ARGS) } catch { unset env(REVISION) } diff --git a/git-gui/lib/tools_dlg.tcl b/git-gui/lib/tools_dlg.tcl index 7eeda9d..c05413c 100644 --- a/git-gui/lib/tools_dlg.tcl +++ b/git-gui/lib/tools_dlg.tcl @@ -19,7 +19,7 @@ constructor dialog {} { global repo_config use_ttk NS make_dialog top w - wm title $top [append "[appname] ([reponame]): " [mc "Add Tool"]] + wm title $top [mc "%s (%s): Add Tool" [appname] [reponame]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm transient $top . @@ -184,7 +184,7 @@ constructor dialog {} { load_config 1 make_dialog top w - wm title $top [append "[appname] ([reponame]): " [mc "Remove Tool"]] + wm title $top [mc "%s (%s): Remove Tool" [appname] [reponame]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm transient $top . @@ -280,7 +280,7 @@ constructor dialog {fullname} { } make_dialog top w -autodelete 0 - wm title $top [append "[appname] ([reponame]): " $title] + wm title $top "[mc "%s (%s):" [appname] [reponame]] $title" if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm transient $top . diff --git a/git-gui/lib/transport.tcl b/git-gui/lib/transport.tcl index e5d211e..a1a424a 100644 --- a/git-gui/lib/transport.tcl +++ b/git-gui/lib/transport.tcl @@ -226,7 +226,7 @@ proc do_push_anywhere {} { bind $w "grab $w; focus $w.buttons.create" bind $w "destroy $w" bind $w [list start_push_anywhere_action $w] - wm title $w [append "[appname] ([reponame]): " [mc "Push"]] + wm title $w [mc "%s (%s): Push" [appname] [reponame]] wm deiconify $w tkwait window $w } diff --git a/git-gui/po/bg.po b/git-gui/po/bg.po index 4d9b039..5af78f1 100644 --- a/git-gui/po/bg.po +++ b/git-gui/po/bg.po @@ -1,15 +1,15 @@ # Bulgarian translation of git-gui po-file. -# Copyright (C) 2012, 2013, 2014, 2015 Alexander Shopov . +# Copyright (C) 2012, 2013, 2014, 2015, 2016 Alexander Shopov . # This file is distributed under the same license as the git package. -# Alexander Shopov , 2012, 2013, 2014, 2015. +# Alexander Shopov , 2012, 2013, 2014, 2015, 2016. # # msgid "" msgstr "" "Project-Id-Version: git-gui master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-07 07:37+0300\n" -"PO-Revision-Date: 2015-04-07 07:46+0300\n" +"POT-Creation-Date: 2016-10-13 15:16+0300\n" +"PO-Revision-Date: 2016-10-13 15:16+0300\n" "Last-Translator: Alexander Shopov \n" "Language-Team: Bulgarian \n" "Language: bg\n" @@ -18,33 +18,33 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: git-gui.sh:861 +#: git-gui.sh:865 #, tcl-format msgid "Invalid font specified in %s:" msgstr "Указан е неправилен шрифт в „%s“:" -#: git-gui.sh:915 +#: git-gui.sh:919 msgid "Main Font" msgstr "Основен шрифт" -#: git-gui.sh:916 +#: git-gui.sh:920 msgid "Diff/Console Font" msgstr "Шрифт за разликите/конзолата" -#: git-gui.sh:931 git-gui.sh:945 git-gui.sh:958 git-gui.sh:1048 -#: git-gui.sh:1067 git-gui.sh:3125 +#: git-gui.sh:935 git-gui.sh:949 git-gui.sh:962 git-gui.sh:1052 git-gui.sh:1071 +#: git-gui.sh:3147 msgid "git-gui: fatal error" msgstr "git-gui: фатална грешка" -#: git-gui.sh:932 +#: git-gui.sh:936 msgid "Cannot find git in PATH." msgstr "Командата git липсва в пътя (PATH)." -#: git-gui.sh:959 +#: git-gui.sh:963 msgid "Cannot parse Git version string:" msgstr "Низът с версията на Git не може да бъде интерпретиран:" -#: git-gui.sh:984 +#: git-gui.sh:988 #, tcl-format msgid "" "Git version cannot be determined.\n" @@ -63,503 +63,506 @@ msgstr "" "\n" "Да се приеме ли, че „%s“ е версия „1.5.0“?\n" -#: git-gui.sh:1281 +#: git-gui.sh:1285 msgid "Git directory not found:" msgstr "Директорията на Git не е открита:" -#: git-gui.sh:1315 +#: git-gui.sh:1319 msgid "Cannot move to top of working directory:" msgstr "Не може да се премине към родителската директория." -#: git-gui.sh:1323 +#: git-gui.sh:1327 msgid "Cannot use bare repository:" msgstr "Голо хранилище не може да се използва:" -#: git-gui.sh:1331 +#: git-gui.sh:1335 msgid "No working directory" msgstr "Работната директория липсва" -#: git-gui.sh:1503 lib/checkout_op.tcl:306 +#: git-gui.sh:1507 lib/checkout_op.tcl:306 msgid "Refreshing file status..." msgstr "Обновяване на състоянието на файла…" -#: git-gui.sh:1563 +#: git-gui.sh:1567 msgid "Scanning for modified files ..." msgstr "Проверка за променени файлове…" -#: git-gui.sh:1639 +#: git-gui.sh:1645 msgid "Calling prepare-commit-msg hook..." msgstr "Куката „prepare-commit-msg“ се изпълнява в момента…" -#: git-gui.sh:1656 +#: git-gui.sh:1662 msgid "Commit declined by prepare-commit-msg hook." msgstr "Подаването е отхвърлено от куката „prepare-commit-msg“." -#: git-gui.sh:1814 lib/browser.tcl:252 +#: git-gui.sh:1820 lib/browser.tcl:252 msgid "Ready." msgstr "Готово." -#: git-gui.sh:1978 +#: git-gui.sh:1984 #, tcl-format msgid "" "Display limit (gui.maxfilesdisplayed = %s) reached, not showing all %s files." msgstr "" -"Достигнат е максималният брой файлове за показване (gui.maxfilesdisplayed = " -"%s). Файловете са общо %s." +"Достигнат е максималният размер на списъка за извеждане(gui." +"maxfilesdisplayed = %s), съответно не са показани всички %s файла." -#: git-gui.sh:2101 +#: git-gui.sh:2107 msgid "Unmodified" msgstr "Непроменен" -#: git-gui.sh:2103 +#: git-gui.sh:2109 msgid "Modified, not staged" msgstr "Променен, но не е в индекса" -#: git-gui.sh:2104 git-gui.sh:2116 +#: git-gui.sh:2110 git-gui.sh:2122 msgid "Staged for commit" msgstr "В индекса за подаване" -#: git-gui.sh:2105 git-gui.sh:2117 +#: git-gui.sh:2111 git-gui.sh:2123 msgid "Portions staged for commit" msgstr "Части са в индекса за подаване" -#: git-gui.sh:2106 git-gui.sh:2118 +#: git-gui.sh:2112 git-gui.sh:2124 msgid "Staged for commit, missing" msgstr "В индекса за подаване, но липсва" -#: git-gui.sh:2108 +#: git-gui.sh:2114 msgid "File type changed, not staged" msgstr "Видът на файла е сменен, но не е в индекса" -#: git-gui.sh:2109 git-gui.sh:2110 +#: git-gui.sh:2115 git-gui.sh:2116 msgid "File type changed, old type staged for commit" -msgstr "Видът на файла е сменен, но в индекса е все още старият" +msgstr "Видът на файла е сменен, но новият вид не е в индекса" -#: git-gui.sh:2111 +#: git-gui.sh:2117 msgid "File type changed, staged" msgstr "Видът на файла е сменен и е в индекса" -#: git-gui.sh:2112 +#: git-gui.sh:2118 msgid "File type change staged, modification not staged" -msgstr "Видът на файла е сменен, но промяната не е в индекса" +msgstr "Видът на файла е сменен в индекса, но не и съдържанието" -#: git-gui.sh:2113 +#: git-gui.sh:2119 msgid "File type change staged, file missing" -msgstr "Видът на файла е сменен, файлът липсва" +msgstr "Видът на файла е сменен в индекса, но файлът липсва" -#: git-gui.sh:2115 +#: git-gui.sh:2121 msgid "Untracked, not staged" msgstr "Неследен" -#: git-gui.sh:2120 +#: git-gui.sh:2126 msgid "Missing" msgstr "Липсващ" -#: git-gui.sh:2121 +#: git-gui.sh:2127 msgid "Staged for removal" msgstr "В индекса за изтриване" -#: git-gui.sh:2122 +#: git-gui.sh:2128 msgid "Staged for removal, still present" msgstr "В индекса за изтриване, но още го има" -#: git-gui.sh:2124 git-gui.sh:2125 git-gui.sh:2126 git-gui.sh:2127 -#: git-gui.sh:2128 git-gui.sh:2129 +#: git-gui.sh:2130 git-gui.sh:2131 git-gui.sh:2132 git-gui.sh:2133 +#: git-gui.sh:2134 git-gui.sh:2135 msgid "Requires merge resolution" msgstr "Изисква коригиране при сливане" -#: git-gui.sh:2164 +#: git-gui.sh:2170 msgid "Starting gitk... please wait..." msgstr "Стартиране на „gitk“…, изчакайте…" -#: git-gui.sh:2176 +#: git-gui.sh:2182 msgid "Couldn't find gitk in PATH" msgstr "Командата „gitk“ липсва в пътищата, определени от променливата PATH." -#: git-gui.sh:2235 +#: git-gui.sh:2241 msgid "Couldn't find git gui in PATH" msgstr "" "Командата „git gui“ липсва в пътищата, определени от променливата PATH." -#: git-gui.sh:2654 lib/choose_repository.tcl:41 +#: git-gui.sh:2676 lib/choose_repository.tcl:41 msgid "Repository" msgstr "Хранилище" -#: git-gui.sh:2655 +#: git-gui.sh:2677 msgid "Edit" msgstr "Редактиране" -#: git-gui.sh:2657 lib/choose_rev.tcl:567 +#: git-gui.sh:2679 lib/choose_rev.tcl:567 msgid "Branch" msgstr "Клон" -#: git-gui.sh:2660 lib/choose_rev.tcl:554 +#: git-gui.sh:2682 lib/choose_rev.tcl:554 msgid "Commit@@noun" msgstr "Подаване" -#: git-gui.sh:2663 lib/merge.tcl:123 lib/merge.tcl:152 lib/merge.tcl:170 +#: git-gui.sh:2685 lib/merge.tcl:127 lib/merge.tcl:174 msgid "Merge" msgstr "Сливане" -#: git-gui.sh:2664 lib/choose_rev.tcl:563 +#: git-gui.sh:2686 lib/choose_rev.tcl:563 msgid "Remote" msgstr "Отдалечено хранилище" -#: git-gui.sh:2667 +#: git-gui.sh:2689 msgid "Tools" msgstr "Команди" -#: git-gui.sh:2676 +#: git-gui.sh:2698 msgid "Explore Working Copy" msgstr "Разглеждане на работното копие" -#: git-gui.sh:2682 +#: git-gui.sh:2704 msgid "Git Bash" msgstr "Bash за Git" -#: git-gui.sh:2692 +#: git-gui.sh:2714 msgid "Browse Current Branch's Files" msgstr "Разглеждане на файловете в текущия клон" -#: git-gui.sh:2696 +#: git-gui.sh:2718 msgid "Browse Branch Files..." msgstr "Разглеждане на текущия клон…" -#: git-gui.sh:2701 +#: git-gui.sh:2723 msgid "Visualize Current Branch's History" msgstr "Визуализация на историята на текущия клон" -#: git-gui.sh:2705 +#: git-gui.sh:2727 msgid "Visualize All Branch History" msgstr "Визуализация на историята на всички клонове" -#: git-gui.sh:2712 +#: git-gui.sh:2734 #, tcl-format msgid "Browse %s's Files" -msgstr "Разглеждане на файловете в %s" +msgstr "Разглеждане на файловете в „%s“" -#: git-gui.sh:2714 +#: git-gui.sh:2736 #, tcl-format msgid "Visualize %s's History" -msgstr "Визуализация на историята на %s" +msgstr "Визуализация на историята на „%s“" -#: git-gui.sh:2719 lib/database.tcl:40 lib/database.tcl:66 +#: git-gui.sh:2741 lib/database.tcl:40 msgid "Database Statistics" msgstr "Статистика на базата от данни" -#: git-gui.sh:2722 lib/database.tcl:33 +#: git-gui.sh:2744 lib/database.tcl:33 msgid "Compress Database" msgstr "Компресиране на базата от данни" -#: git-gui.sh:2725 +#: git-gui.sh:2747 msgid "Verify Database" msgstr "Проверка на базата от данни" -#: git-gui.sh:2732 git-gui.sh:2736 git-gui.sh:2740 lib/shortcut.tcl:8 -#: lib/shortcut.tcl:40 lib/shortcut.tcl:72 +#: git-gui.sh:2754 git-gui.sh:2758 git-gui.sh:2762 msgid "Create Desktop Icon" msgstr "Добавяне на икона на работния плот" -#: git-gui.sh:2748 lib/choose_repository.tcl:193 lib/choose_repository.tcl:201 +#: git-gui.sh:2770 lib/choose_repository.tcl:193 lib/choose_repository.tcl:201 msgid "Quit" msgstr "Спиране на програмата" -#: git-gui.sh:2756 +#: git-gui.sh:2778 msgid "Undo" msgstr "Отмяна" -#: git-gui.sh:2759 +#: git-gui.sh:2781 msgid "Redo" msgstr "Повторение" -#: git-gui.sh:2763 git-gui.sh:3368 +#: git-gui.sh:2785 git-gui.sh:3399 msgid "Cut" msgstr "Отрязване" -#: git-gui.sh:2766 git-gui.sh:3371 git-gui.sh:3445 git-gui.sh:3530 +#: git-gui.sh:2788 git-gui.sh:3402 git-gui.sh:3476 git-gui.sh:3562 #: lib/console.tcl:69 msgid "Copy" msgstr "Копиране" -#: git-gui.sh:2769 git-gui.sh:3374 +#: git-gui.sh:2791 git-gui.sh:3405 msgid "Paste" msgstr "Поставяне" -#: git-gui.sh:2772 git-gui.sh:3377 lib/remote_branch_delete.tcl:39 -#: lib/branch_delete.tcl:28 +#: git-gui.sh:2794 git-gui.sh:3408 lib/branch_delete.tcl:28 +#: lib/remote_branch_delete.tcl:39 msgid "Delete" msgstr "Изтриване" -#: git-gui.sh:2776 git-gui.sh:3381 git-gui.sh:3534 lib/console.tcl:71 +#: git-gui.sh:2798 git-gui.sh:3412 git-gui.sh:3566 lib/console.tcl:71 msgid "Select All" msgstr "Избиране на всичко" -#: git-gui.sh:2785 +#: git-gui.sh:2807 msgid "Create..." msgstr "Създаване…" -#: git-gui.sh:2791 +#: git-gui.sh:2813 msgid "Checkout..." msgstr "Изтегляне…" -#: git-gui.sh:2797 +#: git-gui.sh:2819 msgid "Rename..." msgstr "Преименуване…" -#: git-gui.sh:2802 +#: git-gui.sh:2824 msgid "Delete..." msgstr "Изтриване…" -#: git-gui.sh:2807 +#: git-gui.sh:2829 msgid "Reset..." msgstr "Отмяна на промените…" -#: git-gui.sh:2817 +#: git-gui.sh:2839 msgid "Done" msgstr "Готово" -#: git-gui.sh:2819 +#: git-gui.sh:2841 msgid "Commit@@verb" msgstr "Подаване" -#: git-gui.sh:2828 git-gui.sh:3309 +#: git-gui.sh:2850 git-gui.sh:3335 msgid "New Commit" msgstr "Ново подаване" -#: git-gui.sh:2836 git-gui.sh:3316 +#: git-gui.sh:2858 git-gui.sh:3342 msgid "Amend Last Commit" msgstr "Поправяне на последното подаване" -#: git-gui.sh:2846 git-gui.sh:3270 lib/remote_branch_delete.tcl:101 +#: git-gui.sh:2868 git-gui.sh:3296 lib/remote_branch_delete.tcl:101 msgid "Rescan" msgstr "Обновяване" -#: git-gui.sh:2852 +#: git-gui.sh:2874 msgid "Stage To Commit" msgstr "Към индекса за подаване" -#: git-gui.sh:2858 +#: git-gui.sh:2880 msgid "Stage Changed Files To Commit" msgstr "Всички променени файлове към индекса за подаване" -#: git-gui.sh:2864 +#: git-gui.sh:2886 msgid "Unstage From Commit" msgstr "Изваждане от индекса за подаване" -#: git-gui.sh:2870 lib/index.tcl:442 +#: git-gui.sh:2892 lib/index.tcl:442 msgid "Revert Changes" msgstr "Връщане на оригинала" -#: git-gui.sh:2878 git-gui.sh:3581 git-gui.sh:3612 +#: git-gui.sh:2900 git-gui.sh:3613 git-gui.sh:3644 msgid "Show Less Context" msgstr "По-малко контекст" -#: git-gui.sh:2882 git-gui.sh:3585 git-gui.sh:3616 +#: git-gui.sh:2904 git-gui.sh:3617 git-gui.sh:3648 msgid "Show More Context" msgstr "Повече контекст" -#: git-gui.sh:2889 git-gui.sh:3283 git-gui.sh:3392 +#: git-gui.sh:2911 git-gui.sh:3309 git-gui.sh:3423 msgid "Sign Off" msgstr "Подписване" -#: git-gui.sh:2905 +#: git-gui.sh:2927 msgid "Local Merge..." msgstr "Локално сливане…" -#: git-gui.sh:2910 +#: git-gui.sh:2932 msgid "Abort Merge..." msgstr "Преустановяване на сливане…" -#: git-gui.sh:2922 git-gui.sh:2950 +#: git-gui.sh:2944 git-gui.sh:2972 msgid "Add..." msgstr "Добавяне…" -#: git-gui.sh:2926 +#: git-gui.sh:2948 msgid "Push..." -msgstr "Избутване…" +msgstr "Изтласкване…" -#: git-gui.sh:2930 +#: git-gui.sh:2952 msgid "Delete Branch..." msgstr "Изтриване на клон…" -#: git-gui.sh:2940 git-gui.sh:3563 +#: git-gui.sh:2962 git-gui.sh:3595 msgid "Options..." msgstr "Опции…" -#: git-gui.sh:2951 +#: git-gui.sh:2973 msgid "Remove..." msgstr "Премахване…" -#: git-gui.sh:2960 lib/choose_repository.tcl:55 +#: git-gui.sh:2982 lib/choose_repository.tcl:55 msgid "Help" msgstr "Помощ" -#: git-gui.sh:2964 git-gui.sh:2968 lib/choose_repository.tcl:49 -#: lib/choose_repository.tcl:58 lib/about.tcl:14 +#: git-gui.sh:2986 git-gui.sh:2990 lib/about.tcl:14 +#: lib/choose_repository.tcl:49 lib/choose_repository.tcl:58 #, tcl-format msgid "About %s" msgstr "Относно %s" -#: git-gui.sh:2992 +#: git-gui.sh:3014 msgid "Online Documentation" msgstr "Документация в Интернет" -#: git-gui.sh:2995 lib/choose_repository.tcl:52 lib/choose_repository.tcl:61 +#: git-gui.sh:3017 lib/choose_repository.tcl:52 lib/choose_repository.tcl:61 msgid "Show SSH Key" msgstr "Показване на ключа за SSH" -#: git-gui.sh:3014 git-gui.sh:3146 +#: git-gui.sh:3032 git-gui.sh:3164 +msgid "usage:" +msgstr "употреба:" + +#: git-gui.sh:3036 git-gui.sh:3168 msgid "Usage" msgstr "Употреба" -#: git-gui.sh:3095 lib/blame.tcl:573 +#: git-gui.sh:3117 lib/blame.tcl:573 msgid "Error" msgstr "Грешка" -#: git-gui.sh:3126 +#: git-gui.sh:3148 #, tcl-format msgid "fatal: cannot stat path %s: No such file or directory" msgstr "" "ФАТАЛНА ГРЕШКА: пътят %s не може да бъде открит: такъв файл или директория " "няма" -#: git-gui.sh:3159 +#: git-gui.sh:3181 msgid "Current Branch:" msgstr "Текущ клон:" -#: git-gui.sh:3185 -msgid "Staged Changes (Will Commit)" -msgstr "Промени в индекса (за подаване)" - -#: git-gui.sh:3205 +#: git-gui.sh:3206 msgid "Unstaged Changes" msgstr "Промени извън индекса" -#: git-gui.sh:3276 +#: git-gui.sh:3228 +msgid "Staged Changes (Will Commit)" +msgstr "Промени в индекса (за подаване)" + +#: git-gui.sh:3302 msgid "Stage Changed" msgstr "Индексът е променен" -#: git-gui.sh:3295 lib/transport.tcl:137 lib/transport.tcl:229 +#: git-gui.sh:3321 lib/transport.tcl:137 msgid "Push" msgstr "Изтласкване" -#: git-gui.sh:3330 +#: git-gui.sh:3356 msgid "Initial Commit Message:" msgstr "Първоначално съобщение при подаване:" -#: git-gui.sh:3331 +#: git-gui.sh:3357 msgid "Amended Commit Message:" msgstr "Поправено съобщение при подаване:" -#: git-gui.sh:3332 +#: git-gui.sh:3358 msgid "Amended Initial Commit Message:" msgstr "Поправено първоначално съобщение при подаване:" -#: git-gui.sh:3333 +#: git-gui.sh:3359 msgid "Amended Merge Commit Message:" msgstr "Поправено съобщение при подаване със сливане:" -#: git-gui.sh:3334 +#: git-gui.sh:3360 msgid "Merge Commit Message:" msgstr "Съобщение при подаване със сливане:" -#: git-gui.sh:3335 +#: git-gui.sh:3361 msgid "Commit Message:" msgstr "Съобщение при подаване:" -#: git-gui.sh:3384 git-gui.sh:3538 lib/console.tcl:73 +#: git-gui.sh:3415 git-gui.sh:3570 lib/console.tcl:73 msgid "Copy All" msgstr "Копиране на всичко" -#: git-gui.sh:3408 lib/blame.tcl:105 +#: git-gui.sh:3439 lib/blame.tcl:105 msgid "File:" msgstr "Файл:" -#: git-gui.sh:3526 +#: git-gui.sh:3558 msgid "Refresh" msgstr "Обновяване" -#: git-gui.sh:3547 +#: git-gui.sh:3579 msgid "Decrease Font Size" msgstr "По-едър шрифт" -#: git-gui.sh:3551 +#: git-gui.sh:3583 msgid "Increase Font Size" msgstr "По-дребен шрифт" -#: git-gui.sh:3559 lib/blame.tcl:294 +#: git-gui.sh:3591 lib/blame.tcl:294 msgid "Encoding" msgstr "Кодиране" -#: git-gui.sh:3570 +#: git-gui.sh:3602 msgid "Apply/Reverse Hunk" msgstr "Прилагане/връщане на парче" -#: git-gui.sh:3575 +#: git-gui.sh:3607 msgid "Apply/Reverse Line" msgstr "Прилагане/връщане на ред" -#: git-gui.sh:3594 +#: git-gui.sh:3626 msgid "Run Merge Tool" msgstr "Изпълнение на програмата за сливане" -#: git-gui.sh:3599 +#: git-gui.sh:3631 msgid "Use Remote Version" msgstr "Версия от отдалеченото хранилище" -#: git-gui.sh:3603 +#: git-gui.sh:3635 msgid "Use Local Version" msgstr "Локална версия" -#: git-gui.sh:3607 +#: git-gui.sh:3639 msgid "Revert To Base" msgstr "Връщане към родителската версия" -#: git-gui.sh:3625 +#: git-gui.sh:3657 msgid "Visualize These Changes In The Submodule" msgstr "Визуализиране на промените в подмодула" -#: git-gui.sh:3629 +#: git-gui.sh:3661 msgid "Visualize Current Branch History In The Submodule" msgstr "Визуализация на историята на текущия клон в историята за подмодула" -#: git-gui.sh:3633 +#: git-gui.sh:3665 msgid "Visualize All Branch History In The Submodule" msgstr "Визуализация на историята на всички клони в историята за подмодула" -#: git-gui.sh:3638 +#: git-gui.sh:3670 msgid "Start git gui In The Submodule" msgstr "Стартиране на „git gui“ за подмодула" -#: git-gui.sh:3673 +#: git-gui.sh:3705 msgid "Unstage Hunk From Commit" msgstr "Изваждане на парчето от подаването" -#: git-gui.sh:3675 +#: git-gui.sh:3707 msgid "Unstage Lines From Commit" msgstr "Изваждане на редовете от подаването" -#: git-gui.sh:3677 +#: git-gui.sh:3709 msgid "Unstage Line From Commit" msgstr "Изваждане на реда от подаването" -#: git-gui.sh:3680 +#: git-gui.sh:3712 msgid "Stage Hunk For Commit" msgstr "Добавяне на парчето за подаване" -#: git-gui.sh:3682 +#: git-gui.sh:3714 msgid "Stage Lines For Commit" msgstr "Добавяне на редовете за подаване" -#: git-gui.sh:3684 +#: git-gui.sh:3716 msgid "Stage Line For Commit" msgstr "Добавяне на реда за подаване" -#: git-gui.sh:3709 +#: git-gui.sh:3741 msgid "Initializing..." msgstr "Инициализиране…" -#: git-gui.sh:3852 +#: git-gui.sh:3886 #, tcl-format msgid "" "Possible environment issues exist.\n" @@ -576,7 +579,7 @@ msgstr "" "от %s:\n" "\n" -#: git-gui.sh:3881 +#: git-gui.sh:3915 msgid "" "\n" "This is due to a known issue with the\n" @@ -586,7 +589,7 @@ msgstr "" "Това е познат проблем и се дължи на\n" "версията на Tcl включена в Cygwin." -#: git-gui.sh:3886 +#: git-gui.sh:3920 #, tcl-format msgid "" "\n" @@ -602,199 +605,126 @@ msgstr "" "е да поставите настройките „user.name“ и\n" "„user.email“ в личния си файл „~/.gitconfig“.\n" -#: lib/spellcheck.tcl:57 -msgid "Unsupported spell checker" -msgstr "Тази програма за проверка на правописа не се поддържа" - -#: lib/spellcheck.tcl:65 -msgid "Spell checking is unavailable" -msgstr "Липсва програма за проверка на правописа" - -#: lib/spellcheck.tcl:68 -msgid "Invalid spell checking configuration" -msgstr "Неправилни настройки на проверката на правописа" +#: lib/about.tcl:26 +msgid "git-gui - a graphical user interface for Git." +msgstr "git-gui — графичен интерфейс за Git." -#: lib/spellcheck.tcl:70 +#: lib/blame.tcl:73 #, tcl-format -msgid "Reverting dictionary to %s." -msgstr "Ползване на речник за език „%s“." - -#: lib/spellcheck.tcl:73 -msgid "Spell checker silently failed on startup" -msgstr "Програмата за правопис даже не стартира успешно." - -#: lib/spellcheck.tcl:80 -msgid "Unrecognized spell checker" -msgstr "Непозната програма за проверка на правописа" - -#: lib/spellcheck.tcl:186 -msgid "No Suggestions" -msgstr "Няма предложения" - -#: lib/spellcheck.tcl:388 -msgid "Unexpected EOF from spell checker" -msgstr "Неочакван край на файл от програмата за проверка на правописа" - -#: lib/spellcheck.tcl:392 -msgid "Spell Checker Failed" -msgstr "Грешка в програмата за проверка на правописа" - -#: lib/remote_add.tcl:20 -msgid "Add Remote" -msgstr "Добавяне на отдалечено хранилище" - -#: lib/remote_add.tcl:25 -msgid "Add New Remote" -msgstr "Добавяне на отдалечено хранилище" - -#: lib/remote_add.tcl:30 lib/tools_dlg.tcl:37 -msgid "Add" -msgstr "Добавяне" - -#: lib/remote_add.tcl:34 lib/browser.tcl:292 lib/branch_checkout.tcl:30 -#: lib/transport.tcl:141 lib/branch_rename.tcl:32 lib/choose_font.tcl:45 -#: lib/option.tcl:127 lib/tools_dlg.tcl:41 lib/tools_dlg.tcl:202 -#: lib/tools_dlg.tcl:345 lib/remote_branch_delete.tcl:43 -#: lib/checkout_op.tcl:579 lib/branch_create.tcl:37 lib/branch_delete.tcl:34 -#: lib/merge.tcl:174 -msgid "Cancel" -msgstr "Отказване" - -#: lib/remote_add.tcl:39 -msgid "Remote Details" -msgstr "Данни за отдалеченото хранилище" - -#: lib/remote_add.tcl:41 lib/tools_dlg.tcl:51 lib/branch_create.tcl:44 -msgid "Name:" -msgstr "Име:" +msgid "%s (%s): File Viewer" +msgstr "%s (%s): Преглед на файлове" -#: lib/remote_add.tcl:50 -msgid "Location:" -msgstr "Местоположение:" +#: lib/blame.tcl:79 +msgid "Commit:" +msgstr "Подаване:" -#: lib/remote_add.tcl:60 -msgid "Further Action" -msgstr "Следващо действие" +#: lib/blame.tcl:280 +msgid "Copy Commit" +msgstr "Копиране на подаване" -#: lib/remote_add.tcl:63 -msgid "Fetch Immediately" -msgstr "Незабавно доставяне" +#: lib/blame.tcl:284 +msgid "Find Text..." +msgstr "Търсене на текст…" -#: lib/remote_add.tcl:69 -msgid "Initialize Remote Repository and Push" -msgstr "Инициализиране на отдалеченото хранилище и изтласкване на промените" +#: lib/blame.tcl:288 +msgid "Goto Line..." +msgstr "Към ред…" -#: lib/remote_add.tcl:75 -msgid "Do Nothing Else Now" -msgstr "Да не се прави нищо" +#: lib/blame.tcl:297 +msgid "Do Full Copy Detection" +msgstr "Пълно търсене на копиране" -#: lib/remote_add.tcl:100 -msgid "Please supply a remote name." -msgstr "Задайте име за отдалеченото хранилище." +#: lib/blame.tcl:301 +msgid "Show History Context" +msgstr "Показване на контекста от историята" -#: lib/remote_add.tcl:113 -#, tcl-format -msgid "'%s' is not an acceptable remote name." -msgstr "Отдалечено хранилище не може да се казва „%s“." +#: lib/blame.tcl:304 +msgid "Blame Parent Commit" +msgstr "Анотиране на родителското подаване" -#: lib/remote_add.tcl:124 +#: lib/blame.tcl:466 #, tcl-format -msgid "Failed to add remote '%s' of location '%s'." -msgstr "Неуспешно добавяне на отдалеченото хранилище „%s“ от адрес „%s“." +msgid "Reading %s..." +msgstr "Чете се „%s“…" -#: lib/remote_add.tcl:132 lib/transport.tcl:6 -#, tcl-format -msgid "fetch %s" -msgstr "доставяне на „%s“" +#: lib/blame.tcl:594 +msgid "Loading copy/move tracking annotations..." +msgstr "Зареждане на анотациите за проследяване на копирането/преместването…" -#: lib/remote_add.tcl:133 -#, tcl-format -msgid "Fetching the %s" -msgstr "Доставяне на „%s“" +#: lib/blame.tcl:614 +msgid "lines annotated" +msgstr "реда анотирани" -#: lib/remote_add.tcl:156 -#, tcl-format -msgid "Do not know how to initialize repository at location '%s'." -msgstr "Хранилището с местоположение „%s“ не може да бъде инициализирано." +#: lib/blame.tcl:806 +msgid "Loading original location annotations..." +msgstr "Зареждане на анотациите за първоначалното местоположение…" -#: lib/remote_add.tcl:162 lib/transport.tcl:54 lib/transport.tcl:92 -#: lib/transport.tcl:110 -#, tcl-format -msgid "push %s" -msgstr "изтласкване на „%s“" +#: lib/blame.tcl:809 +msgid "Annotation complete." +msgstr "Анотирането завърши." -#: lib/remote_add.tcl:163 -#, tcl-format -msgid "Setting up the %s (at %s)" -msgstr "Добавяне на хранилище „%s“ (с адрес „%s“)" +#: lib/blame.tcl:839 +msgid "Busy" +msgstr "Операцията не е завършила" -#: lib/browser.tcl:17 -msgid "Starting..." -msgstr "Стартиране…" +#: lib/blame.tcl:840 +msgid "Annotation process is already running." +msgstr "В момента тече процес на анотиране." -#: lib/browser.tcl:27 -msgid "File Browser" -msgstr "Файлов браузър" +#: lib/blame.tcl:879 +msgid "Running thorough copy detection..." +msgstr "Изпълнява се цялостен процес на откриване на копиране…" -#: lib/browser.tcl:132 lib/browser.tcl:149 -#, tcl-format -msgid "Loading %s..." -msgstr "Зареждане на „%s“…" +#: lib/blame.tcl:947 +msgid "Loading annotation..." +msgstr "Зареждане на анотации…" -#: lib/browser.tcl:193 -msgid "[Up To Parent]" -msgstr "[Към родителя]" +#: lib/blame.tcl:1000 +msgid "Author:" +msgstr "Автор:" -#: lib/browser.tcl:275 lib/browser.tcl:282 -msgid "Browse Branch Files" -msgstr "Разглеждане на файловете в клона" +#: lib/blame.tcl:1004 +msgid "Committer:" +msgstr "Подал:" -#: lib/browser.tcl:288 lib/choose_repository.tcl:422 -#: lib/choose_repository.tcl:509 lib/choose_repository.tcl:518 -#: lib/choose_repository.tcl:1074 -msgid "Browse" -msgstr "Разглеждане" +#: lib/blame.tcl:1009 +msgid "Original File:" +msgstr "Първоначален файл:" -#: lib/browser.tcl:297 lib/branch_checkout.tcl:35 lib/tools_dlg.tcl:321 -msgid "Revision" -msgstr "Версия" +#: lib/blame.tcl:1057 +msgid "Cannot find HEAD commit:" +msgstr "Подаването за връх „HEAD“ не може да се открие:" -#: lib/tools.tcl:75 -#, tcl-format -msgid "Running %s requires a selected file." -msgstr "За изпълнението на „%s“ трябва да изберете файл." +#: lib/blame.tcl:1112 +msgid "Cannot find parent commit:" +msgstr "Родителското подаване не може да бъде открито" -#: lib/tools.tcl:91 -#, tcl-format -msgid "Are you sure you want to run %1$s on file \"%2$s\"?" -msgstr "Сигурни ли сте, че искате да изпълните „%1$s“ върху файла „%2$s“?" +#: lib/blame.tcl:1127 +msgid "Unable to display parent" +msgstr "Родителят не може да бъде показан" -#: lib/tools.tcl:95 -#, tcl-format -msgid "Are you sure you want to run %s?" -msgstr "Сигурни ли сте, че искате да изпълните „%s“?" +#: lib/blame.tcl:1128 lib/diff.tcl:358 +msgid "Error loading diff:" +msgstr "Грешка при зареждане на разлика:" -#: lib/tools.tcl:116 -#, tcl-format -msgid "Tool: %s" -msgstr "Команда: %s" +#: lib/blame.tcl:1269 +msgid "Originally By:" +msgstr "Първоначално от:" -#: lib/tools.tcl:117 -#, tcl-format -msgid "Running: %s" -msgstr "Изпълнение: %s" +#: lib/blame.tcl:1275 +msgid "In File:" +msgstr "Във файл:" -#: lib/tools.tcl:155 -#, tcl-format -msgid "Tool completed successfully: %s" -msgstr "Командата завърши успешно: %s" +#: lib/blame.tcl:1280 +msgid "Copied Or Moved Here By:" +msgstr "Копирано или преместено тук от:" -#: lib/tools.tcl:157 +#: lib/branch_checkout.tcl:16 #, tcl-format -msgid "Tool failed: %s" -msgstr "Командата върна грешка: %s" +msgid "%s (%s): Checkout Branch" +msgstr "%s (%s): Клон за изтегляне" -#: lib/branch_checkout.tcl:16 lib/branch_checkout.tcl:21 +#: lib/branch_checkout.tcl:21 msgid "Checkout Branch" msgstr "Клон за изтегляне" @@ -802,7 +732,19 @@ msgstr "Клон за изтегляне" msgid "Checkout" msgstr "Изтегляне" -#: lib/branch_checkout.tcl:39 lib/option.tcl:310 lib/branch_create.tcl:69 +#: lib/branch_checkout.tcl:30 lib/branch_create.tcl:37 lib/branch_delete.tcl:34 +#: lib/branch_rename.tcl:32 lib/browser.tcl:292 lib/checkout_op.tcl:579 +#: lib/choose_font.tcl:45 lib/merge.tcl:178 lib/option.tcl:127 +#: lib/remote_add.tcl:34 lib/remote_branch_delete.tcl:43 lib/tools_dlg.tcl:41 +#: lib/tools_dlg.tcl:202 lib/tools_dlg.tcl:345 lib/transport.tcl:141 +msgid "Cancel" +msgstr "Отказване" + +#: lib/branch_checkout.tcl:35 lib/browser.tcl:297 lib/tools_dlg.tcl:321 +msgid "Revision" +msgstr "Версия" + +#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:69 lib/option.tcl:310 msgid "Options" msgstr "Опции" @@ -814,167 +756,129 @@ msgstr "Изтегляне на промените от следения кло msgid "Detach From Local Branch" msgstr "Изтриване от локалния клон" -#: lib/transport.tcl:7 +#: lib/branch_create.tcl:23 #, tcl-format -msgid "Fetching new changes from %s" -msgstr "Доставяне на промените от „%s“" +msgid "%s (%s): Create Branch" +msgstr "%s (%s): Създаване на клон" -#: lib/transport.tcl:18 -#, tcl-format -msgid "remote prune %s" -msgstr "окастряне на следящите клони към „%s“" - -#: lib/transport.tcl:19 -#, tcl-format -msgid "Pruning tracking branches deleted from %s" -msgstr "Окастряне на следящите клони на изтритите клони от „%s“" - -#: lib/transport.tcl:25 -msgid "fetch all remotes" -msgstr "доставяне на всички отдалечени хранилища" - -#: lib/transport.tcl:26 -msgid "Fetching new changes from all remotes" -msgstr "Доставяне на новите промени от всички отдалечени хранилища" - -#: lib/transport.tcl:40 -msgid "remote prune all remotes" -msgstr "окастряне на всички следящи клони" +#: lib/branch_create.tcl:28 +msgid "Create New Branch" +msgstr "Създаване на нов клон" -#: lib/transport.tcl:41 -msgid "Pruning tracking branches deleted from all remotes" -msgstr "" -"Окастряне на всички клони, които следят изтрити клони от отдалечени хранилища" +#: lib/branch_create.tcl:33 lib/choose_repository.tcl:407 +msgid "Create" +msgstr "Създаване" -#: lib/transport.tcl:55 -#, tcl-format -msgid "Pushing changes to %s" -msgstr "Изтласкване на промените към „%s“" +#: lib/branch_create.tcl:42 +msgid "Branch Name" +msgstr "Име на клона" -#: lib/transport.tcl:93 -#, tcl-format -msgid "Mirroring to %s" -msgstr "Изтласкване на всичко към „%s“" +#: lib/branch_create.tcl:44 lib/remote_add.tcl:41 lib/tools_dlg.tcl:51 +msgid "Name:" +msgstr "Име:" -#: lib/transport.tcl:111 -#, tcl-format -msgid "Pushing %s %s to %s" -msgstr "Изтласкване на %s „%s“ към „%s“" +#: lib/branch_create.tcl:57 +msgid "Match Tracking Branch Name" +msgstr "Съвпадане по името на следения клон" -#: lib/transport.tcl:132 -msgid "Push Branches" -msgstr "Клони за изтласкване" +#: lib/branch_create.tcl:66 +msgid "Starting Revision" +msgstr "Начална версия" -#: lib/transport.tcl:147 -msgid "Source Branches" -msgstr "Клони-източници" +#: lib/branch_create.tcl:72 +msgid "Update Existing Branch:" +msgstr "Обновяване на съществуващ клон:" -#: lib/transport.tcl:162 -msgid "Destination Repository" -msgstr "Целево хранилище" +#: lib/branch_create.tcl:75 +msgid "No" +msgstr "Не" -#: lib/transport.tcl:165 lib/remote_branch_delete.tcl:51 -msgid "Remote:" -msgstr "Отдалечено хранилище:" +#: lib/branch_create.tcl:80 +msgid "Fast Forward Only" +msgstr "Само тривиално превъртащо сливане" -#: lib/transport.tcl:187 lib/remote_branch_delete.tcl:72 -msgid "Arbitrary Location:" -msgstr "Произволно местоположение:" +#: lib/branch_create.tcl:85 lib/checkout_op.tcl:571 +msgid "Reset" +msgstr "Отначало" -#: lib/transport.tcl:205 -msgid "Transfer Options" -msgstr "Настройки при пренасянето" +#: lib/branch_create.tcl:97 +msgid "Checkout After Creation" +msgstr "Преминаване към клона след създаването му" -#: lib/transport.tcl:207 -msgid "Force overwrite existing branch (may discard changes)" -msgstr "" -"Изрично презаписване на съществуващ клон (някои промени може да бъдат " -"загубени)" +#: lib/branch_create.tcl:132 +msgid "Please select a tracking branch." +msgstr "Изберете клон за следени." -#: lib/transport.tcl:211 -msgid "Use thin pack (for slow network connections)" -msgstr "Максимална компресия (за бавни мрежови връзки)" +#: lib/branch_create.tcl:141 +#, tcl-format +msgid "Tracking branch %s is not a branch in the remote repository." +msgstr "Следящият клон — „%s“, не съществува в отдалеченото хранилище." -#: lib/transport.tcl:215 -msgid "Include tags" -msgstr "Включване на етикетите" +#: lib/branch_create.tcl:154 lib/branch_rename.tcl:92 +msgid "Please supply a branch name." +msgstr "Дайте име на клона." -#: lib/status_bar.tcl:87 +#: lib/branch_create.tcl:165 lib/branch_rename.tcl:112 #, tcl-format -msgid "%s ... %*i of %*i %s (%3i%%)" -msgstr "%s… %*i от общо %*i %s (%3i%%)" +msgid "'%s' is not an acceptable branch name." +msgstr "„%s“ не може да се използва за име на клон." -#: lib/remote.tcl:200 -msgid "Push to" -msgstr "Изтласкване към" +#: lib/branch_delete.tcl:16 +#, tcl-format +msgid "%s (%s): Delete Branch" +msgstr "%s (%s): Изтриване на клон" -#: lib/remote.tcl:218 -msgid "Remove Remote" -msgstr "Премахване на отдалечено хранилище" +#: lib/branch_delete.tcl:21 +msgid "Delete Local Branch" +msgstr "Изтриване на локален клон" -#: lib/remote.tcl:223 -msgid "Prune from" -msgstr "Окастряне от" +#: lib/branch_delete.tcl:39 +msgid "Local Branches" +msgstr "Локални клони" -#: lib/remote.tcl:228 -msgid "Fetch from" -msgstr "Доставяне от" +#: lib/branch_delete.tcl:51 +msgid "Delete Only If Merged Into" +msgstr "Изтриване, само ако промените са слети и другаде" -#: lib/sshkey.tcl:31 -msgid "No keys found." -msgstr "Не са открити ключове." +#: lib/branch_delete.tcl:53 lib/remote_branch_delete.tcl:120 +msgid "Always (Do not perform merge checks)" +msgstr "Винаги (без проверка за сливане)" -#: lib/sshkey.tcl:34 +#: lib/branch_delete.tcl:103 #, tcl-format -msgid "Found a public key in: %s" -msgstr "Открит е публичен ключ в „%s“" - -#: lib/sshkey.tcl:40 -msgid "Generate Key" -msgstr "Генериране на ключ" - -#: lib/sshkey.tcl:55 lib/checkout_op.tcl:146 lib/console.tcl:81 -#: lib/database.tcl:30 -msgid "Close" -msgstr "Затваряне" - -#: lib/sshkey.tcl:58 -msgid "Copy To Clipboard" -msgstr "Копиране към системния буфер" +msgid "The following branches are not completely merged into %s:" +msgstr "Не всички промени в клоните са слети в „%s“:" -#: lib/sshkey.tcl:72 -msgid "Your OpenSSH Public Key" -msgstr "Публичният ви ключ за OpenSSH" +#: lib/branch_delete.tcl:115 lib/remote_branch_delete.tcl:218 +msgid "" +"Recovering deleted branches is difficult.\n" +"\n" +"Delete the selected branches?" +msgstr "" +"Възстановяването на изтрити клони може да е трудно.\n" +"\n" +"Сигурни ли сте, че искате да триете?" -#: lib/sshkey.tcl:80 -msgid "Generating..." -msgstr "Генериране…" +#: lib/branch_delete.tcl:131 +#, tcl-format +msgid " - %s:" +msgstr " — „%s:“" -#: lib/sshkey.tcl:86 +#: lib/branch_delete.tcl:141 #, tcl-format msgid "" -"Could not start ssh-keygen:\n" -"\n" +"Failed to delete branches:\n" "%s" msgstr "" -"Програмата „ssh-keygen“ не може да бъде стартирана:\n" -"\n" +"Неуспешно триене на клони:\n" "%s" -#: lib/sshkey.tcl:113 -msgid "Generation failed." -msgstr "Неуспешно генериране." - -#: lib/sshkey.tcl:120 -msgid "Generation succeeded, but no keys found." -msgstr "Генерирането завърши успешно, а не са намерени ключове." - -#: lib/sshkey.tcl:123 +#: lib/branch_rename.tcl:15 #, tcl-format -msgid "Your key is in: %s" -msgstr "Ключът ви е в „%s“" +msgid "%s (%s): Rename Branch" +msgstr "%s (%s): Преименуване на клон" -#: lib/branch_rename.tcl:15 lib/branch_rename.tcl:23 +#: lib/branch_rename.tcl:23 msgid "Rename Branch" msgstr "Преименуване на клон" @@ -994,426 +898,777 @@ msgstr "Ново име:" msgid "Please select a branch to rename." msgstr "Изберете клон за преименуване." -#: lib/branch_rename.tcl:92 lib/branch_create.tcl:154 -msgid "Please supply a branch name." -msgstr "Дайте име на клона." - #: lib/branch_rename.tcl:102 lib/checkout_op.tcl:202 #, tcl-format msgid "Branch '%s' already exists." msgstr "Клонът „%s“ вече съществува." -#: lib/branch_rename.tcl:112 lib/branch_create.tcl:165 -#, tcl-format -msgid "'%s' is not an acceptable branch name." -msgstr "„%s“ не може да се използва за име на клон." - #: lib/branch_rename.tcl:123 #, tcl-format msgid "Failed to rename '%s'." msgstr "Неуспешно преименуване на „%s“." -#: lib/choose_font.tcl:41 -msgid "Select" -msgstr "Избор" - -#: lib/choose_font.tcl:55 -msgid "Font Family" -msgstr "Шрифт" +#: lib/browser.tcl:17 +msgid "Starting..." +msgstr "Стартиране…" -#: lib/choose_font.tcl:76 -msgid "Font Size" -msgstr "Размер" +#: lib/browser.tcl:27 +#, tcl-format +msgid "%s (%s): File Browser" +msgstr "%s (%s): Файлов браузър" -#: lib/choose_font.tcl:93 -msgid "Font Example" -msgstr "Мостра" +#: lib/browser.tcl:132 lib/browser.tcl:149 +#, tcl-format +msgid "Loading %s..." +msgstr "Зареждане на „%s“…" -#: lib/choose_font.tcl:105 -msgid "" -"This is example text.\n" -"If you like this text, it can be your font." -msgstr "" -"Това е примерен текст.\n" -"Ако ви харесва как изглежда, изберете шрифта." +#: lib/browser.tcl:193 +msgid "[Up To Parent]" +msgstr "[Към родителя]" -#: lib/option.tcl:11 +#: lib/browser.tcl:275 #, tcl-format -msgid "Invalid global encoding '%s'" -msgstr "Неправилно глобално кодиране „%s“" +msgid "%s (%s): Browse Branch Files" +msgstr "%s (%s): Разглеждане на файловете в клона" -#: lib/option.tcl:19 -#, tcl-format -msgid "Invalid repo encoding '%s'" -msgstr "Неправилно кодиране „%s“ на хранилището" +#: lib/browser.tcl:282 +msgid "Browse Branch Files" +msgstr "Разглеждане на файловете в клона" -#: lib/option.tcl:119 -msgid "Restore Defaults" -msgstr "Стандартни настройки" +#: lib/browser.tcl:288 lib/choose_repository.tcl:422 +#: lib/choose_repository.tcl:509 lib/choose_repository.tcl:518 +#: lib/choose_repository.tcl:1074 +msgid "Browse" +msgstr "Разглеждане" -#: lib/option.tcl:123 -msgid "Save" -msgstr "Запазване" +#: lib/checkout_op.tcl:85 +#, tcl-format +msgid "Fetching %s from %s" +msgstr "Доставяне на „%s“ от „%s“" -#: lib/option.tcl:133 +#: lib/checkout_op.tcl:133 #, tcl-format -msgid "%s Repository" -msgstr "Хранилище „%s“" +msgid "fatal: Cannot resolve %s" +msgstr "фатална грешка: „%s“ не може да се открие" -#: lib/option.tcl:134 -msgid "Global (All Repositories)" -msgstr "Глобално (за всички хранилища)" +#: lib/checkout_op.tcl:146 lib/console.tcl:81 lib/database.tcl:30 +#: lib/sshkey.tcl:55 +msgid "Close" +msgstr "Затваряне" -#: lib/option.tcl:140 -msgid "User Name" -msgstr "Потребителско име" +#: lib/checkout_op.tcl:175 +#, tcl-format +msgid "Branch '%s' does not exist." +msgstr "Клонът „%s“ не съществува." -#: lib/option.tcl:141 -msgid "Email Address" -msgstr "Адрес на е-поща" +#: lib/checkout_op.tcl:194 +#, tcl-format +msgid "Failed to configure simplified git-pull for '%s'." +msgstr "Неуспешно настройване на опростен git-pull за „%s“." -#: lib/option.tcl:143 -msgid "Summarize Merge Commits" -msgstr "Обобщаване на подаванията при сливане" +#: lib/checkout_op.tcl:229 +#, tcl-format +msgid "" +"Branch '%s' already exists.\n" +"\n" +"It cannot fast-forward to %s.\n" +"A merge is required." +msgstr "" +"Клонът „%s“ съществува.\n" +"\n" +"Той не може да бъде тривиално слят до „%s“.\n" +"Необходимо е сливане." -#: lib/option.tcl:144 -msgid "Merge Verbosity" -msgstr "Подробности при сливанията" +#: lib/checkout_op.tcl:243 +#, tcl-format +msgid "Merge strategy '%s' not supported." +msgstr "Стратегия за сливане „%s“ не се поддържа." -#: lib/option.tcl:145 -msgid "Show Diffstat After Merge" -msgstr "Извеждане на статистика след сливанията" +#: lib/checkout_op.tcl:262 +#, tcl-format +msgid "Failed to update '%s'." +msgstr "Неуспешно обновяване на „%s“." -#: lib/option.tcl:146 -msgid "Use Merge Tool" -msgstr "Използване на програма за сливане" +#: lib/checkout_op.tcl:274 +msgid "Staging area (index) is already locked." +msgstr "Индексът вече е заключен." -#: lib/option.tcl:148 -msgid "Trust File Modification Timestamps" -msgstr "Доверие във времето на промяна на файловете" +#: lib/checkout_op.tcl:289 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before the current branch can be changed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Състоянието при последната проверка не отговаря на състоянието на " +"хранилището.\n" +"\n" +"Някой друг процес за Git е променил хранилището междувременно. Състоянието " +"трябва да бъде проверено, преди да се премине към нов клон.\n" +"\n" +"Автоматично ще започне нова проверка.\n" -#: lib/option.tcl:149 -msgid "Prune Tracking Branches During Fetch" -msgstr "Окастряне на следящите клонове при доставяне" +#: lib/checkout_op.tcl:345 +#, tcl-format +msgid "Updating working directory to '%s'..." +msgstr "Работната директория се привежда към „%s“…" -#: lib/option.tcl:150 -msgid "Match Tracking Branches" -msgstr "Напасване на следящите клонове" +#: lib/checkout_op.tcl:346 +msgid "files checked out" +msgstr "файла са изтеглени" -#: lib/option.tcl:151 -msgid "Use Textconv For Diffs and Blames" +#: lib/checkout_op.tcl:376 +#, tcl-format +msgid "Aborted checkout of '%s' (file level merging is required)." msgstr "" -"Преобразуване на текста с „textconv“ при анотиране и извеждане на разлики" +"Преустановяване на изтеглянето на „%s“ (необходимо е пофайлово сливане)." -#: lib/option.tcl:152 -msgid "Blame Copy Only On Changed Files" -msgstr "Анотиране на копието само по променените файлове" +#: lib/checkout_op.tcl:377 +msgid "File level merge required." +msgstr "Необходимо е пофайлово сливане." -#: lib/option.tcl:153 -msgid "Maximum Length of Recent Repositories List" -msgstr "Максимална дължина на списъка със скоро ползвани хранилища" +#: lib/checkout_op.tcl:381 +#, tcl-format +msgid "Staying on branch '%s'." +msgstr "Оставане върху клона „%s“." -#: lib/option.tcl:154 -msgid "Minimum Letters To Blame Copy On" -msgstr "Минимален брой знаци за анотиране на копието" +#: lib/checkout_op.tcl:452 +msgid "" +"You are no longer on a local branch.\n" +"\n" +"If you wanted to be on a branch, create one now starting from 'This Detached " +"Checkout'." +msgstr "" +"Вече не сте на локален клон.\n" +"\n" +"Ако искате да сте на клон, създайте базиран на „Това несвързано изтегляне“." -#: lib/option.tcl:155 -msgid "Blame History Context Radius (days)" -msgstr "Исторически обхват за анотиране в дни" +#: lib/checkout_op.tcl:503 lib/checkout_op.tcl:507 +#, tcl-format +msgid "Checked out '%s'." +msgstr "„%s“ е изтеглен." -#: lib/option.tcl:156 -msgid "Number of Diff Context Lines" -msgstr "Брой редове за контекста при извеждане на разликите" +#: lib/checkout_op.tcl:535 +#, tcl-format +msgid "Resetting '%s' to '%s' will lose the following commits:" +msgstr "" +"Зануляването на „%s“ към „%s“ ще доведе до загубването на следните подавания:" -#: lib/option.tcl:157 -msgid "Additional Diff Parameters" -msgstr "Допълнителни аргументи към „git diff“" +#: lib/checkout_op.tcl:557 +msgid "Recovering lost commits may not be easy." +msgstr "Възстановяването на загубените подавания може да е трудно." -#: lib/option.tcl:158 -msgid "Commit Message Text Width" -msgstr "Широчина на текста на съобщението при подаване" +#: lib/checkout_op.tcl:562 +#, tcl-format +msgid "Reset '%s'?" +msgstr "Зануляване на „%s“?" -#: lib/option.tcl:159 -msgid "New Branch Name Template" -msgstr "Шаблон за името на новите клони" +#: lib/checkout_op.tcl:567 lib/merge.tcl:170 lib/tools_dlg.tcl:336 +msgid "Visualize" +msgstr "Визуализация" -#: lib/option.tcl:160 -msgid "Default File Contents Encoding" -msgstr "Стандартно кодиране на файловете" +#: lib/checkout_op.tcl:635 +#, tcl-format +msgid "" +"Failed to set current branch.\n" +"\n" +"This working directory is only partially switched. We successfully updated " +"your files, but failed to update an internal Git file.\n" +"\n" +"This should not have occurred. %s will now close and give up." +msgstr "" +"Неуспешно задаване на текущия клон.\n" +"\n" +"Работната директория е само частично обновена: файловете са обновени " +"успешно, но някой от вътрешните, служебни файлове на Git не е бил.\n" +"\n" +"Това състояние е аварийно и не трябва да се случва. Програмата „%s“ ще " +"преустанови работа." -#: lib/option.tcl:161 -msgid "Warn before committing to a detached head" -msgstr "Предупреждаване при подаването при несвързан връх" +#: lib/choose_font.tcl:41 +msgid "Select" +msgstr "Избор" -#: lib/option.tcl:162 -msgid "Staging of untracked files" -msgstr "Вкарване на неследени файлове в индекса" +#: lib/choose_font.tcl:55 +msgid "Font Family" +msgstr "Шрифт" -#: lib/option.tcl:163 -msgid "Show untracked files" -msgstr "Показване на неследените файлове" +#: lib/choose_font.tcl:76 +msgid "Font Size" +msgstr "Размер" -#: lib/option.tcl:164 -msgid "Tab spacing" -msgstr "Размер на табулацията в интервали" +#: lib/choose_font.tcl:93 +msgid "Font Example" +msgstr "Мостра" -#: lib/option.tcl:210 -msgid "Change" -msgstr "Смяна" +#: lib/choose_font.tcl:105 +msgid "" +"This is example text.\n" +"If you like this text, it can be your font." +msgstr "" +"Това е примерен текст.\n" +"Ако ви харесва как изглежда, изберете шрифта." + +#: lib/choose_repository.tcl:33 +msgid "Git Gui" +msgstr "ГПИ на Git" + +#: lib/choose_repository.tcl:92 lib/choose_repository.tcl:412 +msgid "Create New Repository" +msgstr "Създаване на ново хранилище" + +#: lib/choose_repository.tcl:98 +msgid "New..." +msgstr "Ново…" + +#: lib/choose_repository.tcl:105 lib/choose_repository.tcl:496 +msgid "Clone Existing Repository" +msgstr "Клониране на съществуващо хранилище" + +#: lib/choose_repository.tcl:116 +msgid "Clone..." +msgstr "Клониране…" + +#: lib/choose_repository.tcl:123 lib/choose_repository.tcl:1064 +msgid "Open Existing Repository" +msgstr "Отваряне на съществуващо хранилище" + +#: lib/choose_repository.tcl:129 +msgid "Open..." +msgstr "Отваряне…" + +#: lib/choose_repository.tcl:142 +msgid "Recent Repositories" +msgstr "Скоро ползвани" + +#: lib/choose_repository.tcl:148 +msgid "Open Recent Repository:" +msgstr "Отваряне на хранилище ползвано наскоро:" + +#: lib/choose_repository.tcl:316 lib/choose_repository.tcl:323 +#: lib/choose_repository.tcl:330 +#, tcl-format +msgid "Failed to create repository %s:" +msgstr "Неуспешно създаване на хранилището „%s“:" + +#: lib/choose_repository.tcl:417 +msgid "Directory:" +msgstr "Директория:" + +#: lib/choose_repository.tcl:447 lib/choose_repository.tcl:573 +#: lib/choose_repository.tcl:1098 +msgid "Git Repository" +msgstr "Хранилище на Git" + +#: lib/choose_repository.tcl:472 +#, tcl-format +msgid "Directory %s already exists." +msgstr "Вече съществува директория „%s“." + +#: lib/choose_repository.tcl:476 +#, tcl-format +msgid "File %s already exists." +msgstr "Вече съществува файл „%s“." + +#: lib/choose_repository.tcl:491 +msgid "Clone" +msgstr "Клониране" + +#: lib/choose_repository.tcl:504 +msgid "Source Location:" +msgstr "Адрес на източника:" + +#: lib/choose_repository.tcl:513 +msgid "Target Directory:" +msgstr "Целева директория:" + +#: lib/choose_repository.tcl:523 +msgid "Clone Type:" +msgstr "Вид клониране:" + +#: lib/choose_repository.tcl:528 +msgid "Standard (Fast, Semi-Redundant, Hardlinks)" +msgstr "Стандартно (бързо, частично споделяне на файлове, твърди връзки)" + +#: lib/choose_repository.tcl:533 +msgid "Full Copy (Slower, Redundant Backup)" +msgstr "Пълно (бавно, пълноценно резервно копие)" + +#: lib/choose_repository.tcl:538 +msgid "Shared (Fastest, Not Recommended, No Backup)" +msgstr "Споделено (най-бързо, не се препоръчва, не прави резервно копие)" + +#: lib/choose_repository.tcl:545 +msgid "Recursively clone submodules too" +msgstr "Рекурсивно клониране и на подмодулите" + +#: lib/choose_repository.tcl:579 lib/choose_repository.tcl:626 +#: lib/choose_repository.tcl:772 lib/choose_repository.tcl:842 +#: lib/choose_repository.tcl:1104 lib/choose_repository.tcl:1112 +#, tcl-format +msgid "Not a Git repository: %s" +msgstr "Това не е хранилище на Git: %s" + +#: lib/choose_repository.tcl:615 +msgid "Standard only available for local repository." +msgstr "Само локални хранилища могат да се клонират стандартно" + +#: lib/choose_repository.tcl:619 +msgid "Shared only available for local repository." +msgstr "Само локални хранилища могат да се клонират споделено" + +#: lib/choose_repository.tcl:640 +#, tcl-format +msgid "Location %s already exists." +msgstr "Местоположението „%s“ вече съществува." + +#: lib/choose_repository.tcl:651 +msgid "Failed to configure origin" +msgstr "Неуспешно настройване на хранилището-източник" + +#: lib/choose_repository.tcl:663 +msgid "Counting objects" +msgstr "Преброяване на обекти" + +#: lib/choose_repository.tcl:664 +msgid "buckets" +msgstr "клетки" + +#: lib/choose_repository.tcl:688 +#, tcl-format +msgid "Unable to copy objects/info/alternates: %s" +msgstr "Обектите/информацията/синонимите не могат да бъдат копирани: %s" + +#: lib/choose_repository.tcl:724 +#, tcl-format +msgid "Nothing to clone from %s." +msgstr "Няма какво да се клонира от „%s“." + +#: lib/choose_repository.tcl:726 lib/choose_repository.tcl:940 +#: lib/choose_repository.tcl:952 +msgid "The 'master' branch has not been initialized." +msgstr "Основният клон — „master“ не е инициализиран." + +#: lib/choose_repository.tcl:739 +msgid "Hardlinks are unavailable. Falling back to copying." +msgstr "Не се поддържат твърди връзки. Преминава се към копиране." + +#: lib/choose_repository.tcl:751 +#, tcl-format +msgid "Cloning from %s" +msgstr "Клониране на „%s“" + +#: lib/choose_repository.tcl:782 +msgid "Copying objects" +msgstr "Копиране на обекти" + +#: lib/choose_repository.tcl:783 +msgid "KiB" +msgstr "KiB" + +#: lib/choose_repository.tcl:807 +#, tcl-format +msgid "Unable to copy object: %s" +msgstr "Неуспешно копиране на обект: %s" + +#: lib/choose_repository.tcl:817 +msgid "Linking objects" +msgstr "Създаване на връзки към обектите" + +#: lib/choose_repository.tcl:818 +msgid "objects" +msgstr "обекти" + +#: lib/choose_repository.tcl:826 +#, tcl-format +msgid "Unable to hardlink object: %s" +msgstr "Неуспешно създаване на твърда връзка към обект: %s" + +#: lib/choose_repository.tcl:881 +msgid "Cannot fetch branches and objects. See console output for details." +msgstr "" +"Клоните и обектите не могат да бъдат изтеглени. За повече информация " +"погледнете изхода на конзолата." + +#: lib/choose_repository.tcl:892 +msgid "Cannot fetch tags. See console output for details." +msgstr "" +"Етикетите не могат да бъдат изтеглени. За повече информация погледнете " +"изхода на конзолата." + +#: lib/choose_repository.tcl:916 +msgid "Cannot determine HEAD. See console output for details." +msgstr "" +"Върхът „HEAD“ не може да бъде определен. За повече информация погледнете " +"изхода на конзолата." + +#: lib/choose_repository.tcl:925 +#, tcl-format +msgid "Unable to cleanup %s" +msgstr "„%s“ не може да се зачисти" + +#: lib/choose_repository.tcl:931 +msgid "Clone failed." +msgstr "Неуспешно клониране." + +#: lib/choose_repository.tcl:938 +msgid "No default branch obtained." +msgstr "Не е получен клон по подразбиране." + +#: lib/choose_repository.tcl:949 +#, tcl-format +msgid "Cannot resolve %s as a commit." +msgstr "Няма подаване отговарящо на „%s“." + +#: lib/choose_repository.tcl:961 +msgid "Creating working directory" +msgstr "Създаване на работната директория" + +#: lib/choose_repository.tcl:962 lib/index.tcl:70 lib/index.tcl:136 +#: lib/index.tcl:207 +msgid "files" +msgstr "файлове" + +#: lib/choose_repository.tcl:981 +msgid "Cannot clone submodules." +msgstr "Подмодулите не могат да се клонират." + +#: lib/choose_repository.tcl:990 +msgid "Cloning submodules" +msgstr "Клониране на подмодули" + +#: lib/choose_repository.tcl:1015 +msgid "Initial file checkout failed." +msgstr "Неуспешно първоначално изтегляне." + +#: lib/choose_repository.tcl:1059 +msgid "Open" +msgstr "Отваряне" + +#: lib/choose_repository.tcl:1069 +msgid "Repository:" +msgstr "Хранилище:" + +#: lib/choose_repository.tcl:1118 +#, tcl-format +msgid "Failed to open repository %s:" +msgstr "Неуспешно отваряне на хранилището „%s“:" + +#: lib/choose_rev.tcl:52 +msgid "This Detached Checkout" +msgstr "Това несвързано изтегляне" + +#: lib/choose_rev.tcl:60 +msgid "Revision Expression:" +msgstr "Израз за версия:" + +#: lib/choose_rev.tcl:72 +msgid "Local Branch" +msgstr "Локален клон" -#: lib/option.tcl:254 -msgid "Spelling Dictionary:" -msgstr "Правописен речник:" +#: lib/choose_rev.tcl:77 +msgid "Tracking Branch" +msgstr "Следящ клон" -#: lib/option.tcl:284 -msgid "Change Font" -msgstr "Смяна на шрифта" +#: lib/choose_rev.tcl:82 lib/choose_rev.tcl:544 +msgid "Tag" +msgstr "Етикет" -#: lib/option.tcl:288 +#: lib/choose_rev.tcl:321 #, tcl-format -msgid "Choose %s" -msgstr "Избор на „%s“" +msgid "Invalid revision: %s" +msgstr "Неправилна версия: %s" -#: lib/option.tcl:294 -msgid "pt." -msgstr "тчк." +#: lib/choose_rev.tcl:342 +msgid "No revision selected." +msgstr "Не е избрана версия." -#: lib/option.tcl:308 -msgid "Preferences" -msgstr "Настройки" +#: lib/choose_rev.tcl:350 +msgid "Revision expression is empty." +msgstr "Изразът за версия е празен." -#: lib/option.tcl:345 -msgid "Failed to completely save options:" -msgstr "Неуспешно запазване на настройките:" +#: lib/choose_rev.tcl:537 +msgid "Updated" +msgstr "Обновен" -#: lib/encoding.tcl:443 -msgid "Default" -msgstr "Стандартното" +#: lib/choose_rev.tcl:565 +msgid "URL" +msgstr "Адрес" -#: lib/encoding.tcl:448 -#, tcl-format -msgid "System (%s)" -msgstr "Системното (%s)" +#: lib/commit.tcl:9 +msgid "" +"There is nothing to amend.\n" +"\n" +"You are about to create the initial commit. There is no commit before this " +"to amend.\n" +msgstr "" +"Няма какво да се поправи.\n" +"\n" +"Ще създадете първоначалното подаване. Преди него няма други подавания, които " +"да поправите.\n" -#: lib/encoding.tcl:459 lib/encoding.tcl:465 -msgid "Other" -msgstr "Друго" +#: lib/commit.tcl:18 +msgid "" +"Cannot amend while merging.\n" +"\n" +"You are currently in the middle of a merge that has not been fully " +"completed. You cannot amend the prior commit unless you first abort the " +"current merge activity.\n" +msgstr "" +"По време на сливане не може да поправяте.\n" +"\n" +"В момента все още не сте завършили операция по сливане. Не може да поправите " +"предишното подаване, освен ако първо не преустановите текущото сливане.\n" -#: lib/mergetool.tcl:8 -msgid "Force resolution to the base version?" -msgstr "Да се използва базовата версия" +#: lib/commit.tcl:48 +msgid "Error loading commit data for amend:" +msgstr "Грешка при зареждане на данните от подаване, които да се поправят:" -#: lib/mergetool.tcl:9 -msgid "Force resolution to this branch?" -msgstr "Да се използва версията от този клон" +#: lib/commit.tcl:75 +msgid "Unable to obtain your identity:" +msgstr "Идентификацията ви не може да бъде определена:" -#: lib/mergetool.tcl:10 -msgid "Force resolution to the other branch?" -msgstr "Да се използва версията от другия клон" +#: lib/commit.tcl:80 +msgid "Invalid GIT_COMMITTER_IDENT:" +msgstr "Неправилно поле „GIT_COMMITTER_IDENT“:" -#: lib/mergetool.tcl:14 +#: lib/commit.tcl:129 #, tcl-format +msgid "warning: Tcl does not support encoding '%s'." +msgstr "предупреждение: Tcl не поддържа кодирането „%s“." + +#: lib/commit.tcl:149 msgid "" -"Note that the diff shows only conflicting changes.\n" +"Last scanned state does not match repository state.\n" "\n" -"%s will be overwritten.\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before another commit can be created.\n" "\n" -"This operation can be undone only by restarting the merge." +"The rescan will be automatically started now.\n" msgstr "" -"Разликата показва само разликите с конфликт.\n" +"Състоянието при последната проверка не отговаря на състоянието на " +"хранилището.\n" "\n" -"Файлът „%s“ ще бъде презаписан.\n" +"Някой друг процес за Git е променил хранилището междувременно. Състоянието " +"трябва да бъде проверено преди ново подаване.\n" "\n" -"Тази операция може да бъде отменена само чрез започване на сливането наново." +"Автоматично ще започне нова проверка.\n" -#: lib/mergetool.tcl:45 +#: lib/commit.tcl:173 #, tcl-format -msgid "File %s seems to have unresolved conflicts, still stage?" +msgid "" +"Unmerged files cannot be committed.\n" +"\n" +"File %s has merge conflicts. You must resolve them and stage the file " +"before committing.\n" msgstr "" -"Изглежда, че все още има некоригирани конфликти във файла „%s“. Да се добави " -"ли файлът към индекса?" +"Неслетите файлове не могат да бъдат подавани.\n" +"\n" +"Във файла „%s“ има конфликти при сливане. За да го подадете, трябва първо да " +"коригирате конфликтите и да добавите файла към индекса за подаване.\n" -#: lib/mergetool.tcl:60 +#: lib/commit.tcl:181 #, tcl-format -msgid "Adding resolution for %s" -msgstr "Добавяне на корекция на конфликтите в „%s“" - -#: lib/mergetool.tcl:141 -msgid "Cannot resolve deletion or link conflicts using a tool" +msgid "" +"Unknown file state %s detected.\n" +"\n" +"File %s cannot be committed by this program.\n" msgstr "" -"Конфликтите при символни връзки или изтриване не могат да бъдат коригирани с " -"външна програма." - -#: lib/mergetool.tcl:146 -msgid "Conflict file does not exist" -msgstr "Файлът, в който е конфликтът, не съществува" - -#: lib/mergetool.tcl:246 -#, tcl-format -msgid "Not a GUI merge tool: '%s'" -msgstr "Това не е графична програма за сливане: „%s“" - -#: lib/mergetool.tcl:275 -#, tcl-format -msgid "Unsupported merge tool '%s'" -msgstr "Неподдържана програма за сливане: „%s“" - -#: lib/mergetool.tcl:310 -msgid "Merge tool is already running, terminate it?" -msgstr "Програмата за сливане вече е стартирана. Да бъде ли изключена?" +"Непознато състояние на файл „%s“.\n" +"\n" +"Файлът „%s“ не може да бъде подаден чрез текущата програма.\n" -#: lib/mergetool.tcl:330 -#, tcl-format +#: lib/commit.tcl:189 msgid "" -"Error retrieving versions:\n" -"%s" +"No changes to commit.\n" +"\n" +"You must stage at least 1 file before you can commit.\n" msgstr "" -"Грешка при изтеглянето на версии:\n" -"%s" +"Няма промени за подаване.\n" +"\n" +"Трябва да добавите поне един файл към индекса, за да подадете.\n" -#: lib/mergetool.tcl:350 -#, tcl-format +#: lib/commit.tcl:204 msgid "" -"Could not start the merge tool:\n" +"Please supply a commit message.\n" "\n" -"%s" +"A good commit message has the following format:\n" +"\n" +"- First line: Describe in one sentence what you did.\n" +"- Second line: Blank\n" +"- Remaining lines: Describe why this change is good.\n" msgstr "" -"Програмата за сливане не може да бъде стартирана:\n" +"Задайте добро съобщение при подаване.\n" "\n" -"%s" - -#: lib/mergetool.tcl:354 -msgid "Running merge tool..." -msgstr "Стартиране на програмата за сливане…" +"Използвайте следния формат:\n" +"\n" +"● Първи ред: описание в едно изречение на промяната.\n" +"● Втори ред: празен.\n" +"● Останалите редове: опишете защо се налага тази промяна.\n" -#: lib/mergetool.tcl:382 lib/mergetool.tcl:390 -msgid "Merge tool failed." -msgstr "Грешка в програмата за сливане." +#: lib/commit.tcl:235 +msgid "Calling pre-commit hook..." +msgstr "Изпълняване на куката преди подаване…" -#: lib/tools_dlg.tcl:22 -msgid "Add Tool" -msgstr "Добавяне на команда" +#: lib/commit.tcl:250 +msgid "Commit declined by pre-commit hook." +msgstr "Подаването е отхвърлено от куката преди подаване." -#: lib/tools_dlg.tcl:28 -msgid "Add New Tool Command" -msgstr "Добавяне на команда" +#: lib/commit.tcl:269 +msgid "" +"You are about to commit on a detached head. This is a potentially dangerous " +"thing to do because if you switch to another branch you will lose your " +"changes and it can be difficult to retrieve them later from the reflog. You " +"should probably cancel this commit and create a new branch to continue.\n" +" \n" +" Do you really want to proceed with your Commit?" +msgstr "" +"Ще подадете към несвързан, отделѐн указател „HEAD“. Това е опасно, защото " +"при преминаването към клон ще загубите промените си, като единственият начин " +"да ги върнете ще е чрез журнала на указателите (reflog). Най-вероятно трябва " +"да не правите това подаване, а да създадете нов клон, преди да продължите.\n" +" \n" +"Сигурни ли сте, че искате да извършите текущото подаване?" -#: lib/tools_dlg.tcl:34 -msgid "Add globally" -msgstr "Глобално добавяне" +#: lib/commit.tcl:290 +msgid "Calling commit-msg hook..." +msgstr "Изпълняване на куката за съобщението при подаване…" -#: lib/tools_dlg.tcl:46 -msgid "Tool Details" -msgstr "Подробности за командата" +#: lib/commit.tcl:305 +msgid "Commit declined by commit-msg hook." +msgstr "Подаването е отхвърлено от куката за съобщението при подаване." -#: lib/tools_dlg.tcl:49 -msgid "Use '/' separators to create a submenu tree:" -msgstr "За създаване на подменюта използвайте знака „/“ за разделител:" +#: lib/commit.tcl:318 +msgid "Committing changes..." +msgstr "Подаване на промените…" -#: lib/tools_dlg.tcl:60 -msgid "Command:" -msgstr "Команда:" +#: lib/commit.tcl:334 +msgid "write-tree failed:" +msgstr "неуспешно запазване на дървото (write-tree):" -#: lib/tools_dlg.tcl:71 -msgid "Show a dialog before running" -msgstr "Преди изпълнение да се извежда диалогов прозорец" +#: lib/commit.tcl:335 lib/commit.tcl:382 lib/commit.tcl:403 +msgid "Commit failed." +msgstr "Неуспешно подаване." -#: lib/tools_dlg.tcl:77 -msgid "Ask the user to select a revision (sets $REVISION)" -msgstr "Потребителят да укаже версия (задаване на променливата $REVISION)" +#: lib/commit.tcl:352 +#, tcl-format +msgid "Commit %s appears to be corrupt" +msgstr "Подаването „%s“ изглежда повредено" -#: lib/tools_dlg.tcl:82 -msgid "Ask the user for additional arguments (sets $ARGS)" +#: lib/commit.tcl:357 +msgid "" +"No changes to commit.\n" +"\n" +"No files were modified by this commit and it was not a merge commit.\n" +"\n" +"A rescan will be automatically started now.\n" msgstr "" -"Потребителят да укаже допълнителни аргументи (задаване на променливата $ARGS)" +"Няма промени за подаване.\n" +"\n" +"В това подаване не са променяни никакви файлове, а и не е подаване със " +"сливане.\n" +"\n" +"Автоматично ще започне нова проверка.\n" -#: lib/tools_dlg.tcl:89 -msgid "Don't show the command output window" -msgstr "Без показване на прозорец с изхода от командата" +#: lib/commit.tcl:364 +msgid "No changes to commit." +msgstr "Няма промени за подаване." -#: lib/tools_dlg.tcl:94 -msgid "Run only if a diff is selected ($FILENAME not empty)" -msgstr "" -"Стартиране само след избор на разлика (променливата $FILENAME не е празна)" +#: lib/commit.tcl:381 +msgid "commit-tree failed:" +msgstr "неуспешно подаване на дървото (commit-tree):" -#: lib/tools_dlg.tcl:118 -msgid "Please supply a name for the tool." -msgstr "Задайте име за командата." +#: lib/commit.tcl:402 +msgid "update-ref failed:" +msgstr "неуспешно обновяване на указателите (update-ref):" -#: lib/tools_dlg.tcl:126 +#: lib/commit.tcl:495 #, tcl-format -msgid "Tool '%s' already exists." -msgstr "Командата „%s“ вече съществува." +msgid "Created commit %s: %s" +msgstr "Успешно подаване %s: %s" -#: lib/tools_dlg.tcl:148 -#, tcl-format -msgid "" -"Could not add tool:\n" -"%s" -msgstr "" -"Командата не може да бъде добавена:\n" -"%s" +#: lib/console.tcl:59 +msgid "Working... please wait..." +msgstr "В момента се извършва действие, изчакайте…" -#: lib/tools_dlg.tcl:187 -msgid "Remove Tool" -msgstr "Премахване на команда" +#: lib/console.tcl:186 +msgid "Success" +msgstr "Успех" -#: lib/tools_dlg.tcl:193 -msgid "Remove Tool Commands" -msgstr "Премахване на команди" +#: lib/console.tcl:200 +msgid "Error: Command Failed" +msgstr "Грешка: неуспешно изпълнение на команда" -#: lib/tools_dlg.tcl:198 -msgid "Remove" -msgstr "Премахване" +#: lib/database.tcl:42 +msgid "Number of loose objects" +msgstr "Брой непакетирани обекти" -#: lib/tools_dlg.tcl:231 -msgid "(Blue denotes repository-local tools)" -msgstr "(командите към локалното хранилище са обозначени в синьо)" +#: lib/database.tcl:43 +msgid "Disk space used by loose objects" +msgstr "Дисково пространство заето от непакетирани обекти" -#: lib/tools_dlg.tcl:292 -#, tcl-format -msgid "Run Command: %s" -msgstr "Изпълнение на командата „%s“" +#: lib/database.tcl:44 +msgid "Number of packed objects" +msgstr "Брой пакетирани обекти" -#: lib/tools_dlg.tcl:306 -msgid "Arguments" -msgstr "Аргументи" +#: lib/database.tcl:45 +msgid "Number of packs" +msgstr "Брой пакети" -#: lib/tools_dlg.tcl:336 lib/checkout_op.tcl:567 lib/merge.tcl:166 -msgid "Visualize" -msgstr "Визуализация" +#: lib/database.tcl:46 +msgid "Disk space used by packed objects" +msgstr "Дисково пространство заето от пакетирани обекти" -#: lib/tools_dlg.tcl:341 -msgid "OK" -msgstr "Добре" +#: lib/database.tcl:47 +msgid "Packed objects waiting for pruning" +msgstr "Пакетирани обекти за окастряне" -#: lib/search.tcl:48 -msgid "Find:" -msgstr "Търсене:" +#: lib/database.tcl:48 +msgid "Garbage files" +msgstr "Файлове за боклука" -#: lib/search.tcl:50 -msgid "Next" -msgstr "Следваща поява" +#: lib/database.tcl:57 lib/option.tcl:182 lib/option.tcl:197 lib/option.tcl:220 +#: lib/option.tcl:282 +#, tcl-format +msgid "%s:" +msgstr "%s:" -#: lib/search.tcl:51 -msgid "Prev" -msgstr "Предишна поява" +#: lib/database.tcl:66 +#, tcl-format +msgid "%s (%s): Database Statistics" +msgstr "%s (%s): Статистика на базата от данни" -#: lib/search.tcl:52 -msgid "RegExp" -msgstr "Рег. израз" +#: lib/database.tcl:72 +msgid "Compressing the object database" +msgstr "Компресиране на базата с данни за обектите" -#: lib/search.tcl:54 -msgid "Case" -msgstr "Регистър" +#: lib/database.tcl:83 +msgid "Verifying the object database with fsck-objects" +msgstr "Проверка на базата с данни за обектите с програмата „fsck-objects“" -#: lib/shortcut.tcl:21 lib/shortcut.tcl:62 -msgid "Cannot write shortcut:" -msgstr "Клавишната комбинация не може да бъде запазена:" +#: lib/database.tcl:107 +#, tcl-format +msgid "" +"This repository currently has approximately %i loose objects.\n" +"\n" +"To maintain optimal performance it is strongly recommended that you compress " +"the database.\n" +"\n" +"Compress the database now?" +msgstr "" +"В това хранилище в момента има към %i непакетирани обекти.\n" +"\n" +"За добра производителност се препоръчва да компресирате базата с данни за " +"обектите.\n" +"\n" +"Да се започне ли компресирането?" -#: lib/shortcut.tcl:137 -msgid "Cannot write icon:" -msgstr "Иконата не може да бъде запазена:" +#: lib/date.tcl:25 +#, tcl-format +msgid "Invalid date from Git: %s" +msgstr "Неправилни данни от Git: %s" #: lib/diff.tcl:77 #, tcl-format @@ -1443,7 +1698,7 @@ msgstr "" msgid "Loading diff of %s..." msgstr "Зареждане на разликите в „%s“…" -#: lib/diff.tcl:140 +#: lib/diff.tcl:143 msgid "" "LOCAL: deleted\n" "REMOTE:\n" @@ -1451,7 +1706,7 @@ msgstr "" "ЛОКАЛНО: изтрит\n" "ОТДАЛЕЧЕНО:\n" -#: lib/diff.tcl:145 +#: lib/diff.tcl:148 msgid "" "REMOTE: deleted\n" "LOCAL:\n" @@ -1459,32 +1714,32 @@ msgstr "" "ОТДАЛЕЧЕНО: изтрит\n" "ЛОКАЛНО:\n" -#: lib/diff.tcl:152 +#: lib/diff.tcl:155 msgid "LOCAL:\n" msgstr "ЛОКАЛНО:\n" -#: lib/diff.tcl:155 +#: lib/diff.tcl:158 msgid "REMOTE:\n" msgstr "ОТДАЛЕЧЕНО:\n" -#: lib/diff.tcl:217 lib/diff.tcl:355 +#: lib/diff.tcl:220 lib/diff.tcl:357 #, tcl-format msgid "Unable to display %s" msgstr "Файлът „%s“ не може да бъде показан" -#: lib/diff.tcl:218 +#: lib/diff.tcl:221 msgid "Error loading file:" msgstr "Грешка при зареждане на файл:" -#: lib/diff.tcl:225 +#: lib/diff.tcl:227 msgid "Git Repository (subproject)" msgstr "Хранилище на Git (подмодул)" -#: lib/diff.tcl:237 +#: lib/diff.tcl:239 msgid "* Binary file (not showing content)." msgstr "● Двоичен файл (съдържанието не се показва)." -#: lib/diff.tcl:242 +#: lib/diff.tcl:244 #, tcl-format msgid "" "* Untracked file is %d bytes.\n" @@ -1493,1222 +1748,1060 @@ msgstr "" "● Неследеният файл е %d байта.\n" "● Показват се само първите %d байта.\n" -#: lib/diff.tcl:248 -#, tcl-format -msgid "" -"\n" -"* Untracked file clipped here by %s.\n" -"* To see the entire file, use an external editor.\n" -msgstr "" -"\n" -"● Неследеният файл е отрязан дотук от програмата „%s“.\n" -"● Използвайте външен редактор, за да видите целия файл.\n" - -#: lib/diff.tcl:356 lib/blame.tcl:1128 -msgid "Error loading diff:" -msgstr "Грешка при зареждане на разлика:" - -#: lib/diff.tcl:578 -msgid "Failed to unstage selected hunk." -msgstr "Избраното парче не може да бъде извадено от индекса." - -#: lib/diff.tcl:585 -msgid "Failed to stage selected hunk." -msgstr "Избраното парче не може да бъде добавено към индекса." - -#: lib/diff.tcl:664 -msgid "Failed to unstage selected line." -msgstr "Избраният ред не може да бъде изваден от индекса." - -#: lib/diff.tcl:672 -msgid "Failed to stage selected line." -msgstr "Избраният ред не може да бъде добавен към индекса." - -#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 -msgid "Delete Branch Remotely" -msgstr "Изтриване на отдалечения клон" - -#: lib/remote_branch_delete.tcl:48 -msgid "From Repository" -msgstr "От хранилище" - -#: lib/remote_branch_delete.tcl:88 -msgid "Branches" -msgstr "Клони" - -#: lib/remote_branch_delete.tcl:110 -msgid "Delete Only If" -msgstr "Изтриване, само ако" - -#: lib/remote_branch_delete.tcl:112 -msgid "Merged Into:" -msgstr "Слят в:" - -#: lib/remote_branch_delete.tcl:120 lib/branch_delete.tcl:53 -msgid "Always (Do not perform merge checks)" -msgstr "Винаги (без проверка за сливане)" - -#: lib/remote_branch_delete.tcl:153 -msgid "A branch is required for 'Merged Into'." -msgstr "За данните „Слят в“ е необходимо да зададете клон." - -#: lib/remote_branch_delete.tcl:185 -#, tcl-format -msgid "" -"The following branches are not completely merged into %s:\n" -"\n" -" - %s" -msgstr "" -"Следните клони не са слети напълно в „%s“:\n" -"\n" -" ● %s" - -#: lib/remote_branch_delete.tcl:190 +#: lib/diff.tcl:250 #, tcl-format msgid "" -"One or more of the merge tests failed because you have not fetched the " -"necessary commits. Try fetching from %s first." -msgstr "" -"Поне една от пробите за сливане е неуспешна, защото не сте доставили всички " -"необходими подавания. Пробвайте първо да доставите подаванията от „%s“." - -#: lib/remote_branch_delete.tcl:208 -msgid "Please select one or more branches to delete." -msgstr "Изберете поне един клон за изтриване." - -#: lib/remote_branch_delete.tcl:218 lib/branch_delete.tcl:115 -msgid "" -"Recovering deleted branches is difficult.\n" -"\n" -"Delete the selected branches?" -msgstr "" -"Възстановяването на изтрити клони може да е трудно.\n" "\n" -"Сигурни ли сте, че искате да триете?" - -#: lib/remote_branch_delete.tcl:227 -#, tcl-format -msgid "Deleting branches from %s" -msgstr "Изтриване на клони от „%s“" - -#: lib/remote_branch_delete.tcl:300 -msgid "No repository selected." -msgstr "Не е избрано хранилище." - -#: lib/remote_branch_delete.tcl:305 -#, tcl-format -msgid "Scanning %s..." -msgstr "Претърсване на „%s“…" - -#: lib/choose_repository.tcl:33 -msgid "Git Gui" -msgstr "ГПИ на Git" - -#: lib/choose_repository.tcl:92 lib/choose_repository.tcl:412 -msgid "Create New Repository" -msgstr "Създаване на ново хранилище" - -#: lib/choose_repository.tcl:98 -msgid "New..." -msgstr "Ново…" - -#: lib/choose_repository.tcl:105 lib/choose_repository.tcl:496 -msgid "Clone Existing Repository" -msgstr "Клониране на съществуващо хранилище" +"* Untracked file clipped here by %s.\n" +"* To see the entire file, use an external editor.\n" +msgstr "" +"\n" +"● Неследеният файл е отрязан дотук от програмата „%s“.\n" +"● Използвайте външен редактор, за да видите целия файл.\n" -#: lib/choose_repository.tcl:116 -msgid "Clone..." -msgstr "Клониране…" +#: lib/diff.tcl:580 +msgid "Failed to unstage selected hunk." +msgstr "Избраното парче не може да бъде извадено от индекса." -#: lib/choose_repository.tcl:123 lib/choose_repository.tcl:1064 -msgid "Open Existing Repository" -msgstr "Отваряне на съществуващо хранилище" +#: lib/diff.tcl:587 +msgid "Failed to stage selected hunk." +msgstr "Избраното парче не може да бъде добавено към индекса." -#: lib/choose_repository.tcl:129 -msgid "Open..." -msgstr "Отваряне…" +#: lib/diff.tcl:666 +msgid "Failed to unstage selected line." +msgstr "Избраният ред не може да бъде изваден от индекса." -#: lib/choose_repository.tcl:142 -msgid "Recent Repositories" -msgstr "Скоро ползвани" +#: lib/diff.tcl:674 +msgid "Failed to stage selected line." +msgstr "Избраният ред не може да бъде добавен към индекса." -#: lib/choose_repository.tcl:148 -msgid "Open Recent Repository:" -msgstr "Отваряне на хранилище ползвано наскоро:" +#: lib/encoding.tcl:443 +msgid "Default" +msgstr "Стандартното" -#: lib/choose_repository.tcl:316 lib/choose_repository.tcl:323 -#: lib/choose_repository.tcl:330 +#: lib/encoding.tcl:448 #, tcl-format -msgid "Failed to create repository %s:" -msgstr "Неуспешно създаване на хранилището „%s“:" - -#: lib/choose_repository.tcl:407 lib/branch_create.tcl:33 -msgid "Create" -msgstr "Създаване" +msgid "System (%s)" +msgstr "Системното (%s)" -#: lib/choose_repository.tcl:417 -msgid "Directory:" -msgstr "Директория:" +#: lib/encoding.tcl:459 lib/encoding.tcl:465 +msgid "Other" +msgstr "Друго" -#: lib/choose_repository.tcl:447 lib/choose_repository.tcl:573 -#: lib/choose_repository.tcl:1098 -msgid "Git Repository" -msgstr "Хранилище на Git" +#: lib/error.tcl:20 +#, tcl-format +msgid "%s: error" +msgstr "%s: грешка" -#: lib/choose_repository.tcl:472 +#: lib/error.tcl:36 #, tcl-format -msgid "Directory %s already exists." -msgstr "Вече съществува директория „%s“." +msgid "%s: warning" +msgstr "%s: предупреждение" -#: lib/choose_repository.tcl:476 +#: lib/error.tcl:80 #, tcl-format -msgid "File %s already exists." -msgstr "Вече съществува файл „%s“." +msgid "%s hook failed:" +msgstr "%s: грешка от куката" -#: lib/choose_repository.tcl:491 -msgid "Clone" -msgstr "Клониране" +#: lib/error.tcl:96 +msgid "You must correct the above errors before committing." +msgstr "Преди да можете да подадете, коригирайте горните грешки." -#: lib/choose_repository.tcl:504 -msgid "Source Location:" -msgstr "Адрес на източника:" +#: lib/error.tcl:116 +#, tcl-format +msgid "%s (%s): error" +msgstr "%s (%s): грешка" -#: lib/choose_repository.tcl:513 -msgid "Target Directory:" -msgstr "Целева директория:" +#: lib/index.tcl:6 +msgid "Unable to unlock the index." +msgstr "Индексът не може да бъде отключен." -#: lib/choose_repository.tcl:523 -msgid "Clone Type:" -msgstr "Вид клониране:" +#: lib/index.tcl:17 +msgid "Index Error" +msgstr "Грешка в индекса" -#: lib/choose_repository.tcl:528 -msgid "Standard (Fast, Semi-Redundant, Hardlinks)" -msgstr "Стандартно (бързо, частично споделяне на файлове, твърди връзки)" +#: lib/index.tcl:19 +msgid "" +"Updating the Git index failed. A rescan will be automatically started to " +"resynchronize git-gui." +msgstr "" +"Неуспешно обновяване на индекса на Git. Автоматично ще започне нова проверка " +"за синхронизирането на git-gui." -#: lib/choose_repository.tcl:533 -msgid "Full Copy (Slower, Redundant Backup)" -msgstr "Пълно (бавно, пълноценно резервно копие)" +#: lib/index.tcl:30 +msgid "Continue" +msgstr "Продължаване" -#: lib/choose_repository.tcl:538 -msgid "Shared (Fastest, Not Recommended, No Backup)" -msgstr "Споделено (най-бързо, не се препоръчва, не прави резервно копие)" +#: lib/index.tcl:33 +msgid "Unlock Index" +msgstr "Отключване на индекса" -#: lib/choose_repository.tcl:545 -msgid "Recursively clone submodules too" -msgstr "Рекурсивно клониране и на подмодулите" +#: lib/index.tcl:294 +msgid "Unstaging selected files from commit" +msgstr "Изваждане на избраните файлове от подаването" -#: lib/choose_repository.tcl:579 lib/choose_repository.tcl:626 -#: lib/choose_repository.tcl:772 lib/choose_repository.tcl:842 -#: lib/choose_repository.tcl:1104 lib/choose_repository.tcl:1112 +#: lib/index.tcl:298 #, tcl-format -msgid "Not a Git repository: %s" -msgstr "Това не е хранилище на Git: %s" +msgid "Unstaging %s from commit" +msgstr "Изваждане на „%s“ от подаването" -#: lib/choose_repository.tcl:615 -msgid "Standard only available for local repository." -msgstr "Само локални хранилища могат да се клонират стандартно" +#: lib/index.tcl:337 +msgid "Ready to commit." +msgstr "Готовност за подаване." -#: lib/choose_repository.tcl:619 -msgid "Shared only available for local repository." -msgstr "Само локални хранилища могат да се клонират споделено" +#: lib/index.tcl:346 +msgid "Adding selected files" +msgstr "Добавяне на избраните файлове" -#: lib/choose_repository.tcl:640 +#: lib/index.tcl:350 #, tcl-format -msgid "Location %s already exists." -msgstr "Местоположението „%s“ вече съществува." - -#: lib/choose_repository.tcl:651 -msgid "Failed to configure origin" -msgstr "Неуспешно настройване на хранилището-източник" +msgid "Adding %s" +msgstr "Добавяне на „%s“" -#: lib/choose_repository.tcl:663 -msgid "Counting objects" -msgstr "Преброяване на обекти" +#: lib/index.tcl:380 +#, tcl-format +msgid "Stage %d untracked files?" +msgstr "Да се добавят ли %d неследени файла към индекса?" -#: lib/choose_repository.tcl:664 -msgid "buckets" -msgstr "клетки" +#: lib/index.tcl:388 +msgid "Adding all changed files" +msgstr "Добавяне на всички променени файлове" -#: lib/choose_repository.tcl:688 +#: lib/index.tcl:428 #, tcl-format -msgid "Unable to copy objects/info/alternates: %s" -msgstr "Обектите/информацията/синонимите не могат да бъдат копирани: %s" +msgid "Revert changes in file %s?" +msgstr "Да се махнат ли промените във файла „%s“?" -#: lib/choose_repository.tcl:724 +#: lib/index.tcl:430 #, tcl-format -msgid "Nothing to clone from %s." -msgstr "Няма какво да се клонира от „%s“." - -#: lib/choose_repository.tcl:726 lib/choose_repository.tcl:940 -#: lib/choose_repository.tcl:952 -msgid "The 'master' branch has not been initialized." -msgstr "Основният клон — „master“ не е инициализиран." - -#: lib/choose_repository.tcl:739 -msgid "Hardlinks are unavailable. Falling back to copying." -msgstr "Не се поддържат твърди връзки. Преминава се към копиране." +msgid "Revert changes in these %i files?" +msgstr "Да се махнат ли промените в тези %i файла?" -#: lib/choose_repository.tcl:751 -#, tcl-format -msgid "Cloning from %s" -msgstr "Клониране на „%s“" +#: lib/index.tcl:438 +msgid "Any unstaged changes will be permanently lost by the revert." +msgstr "" +"Всички промени, които не са били вкарани в индекса, ще бъдат безвъзвратно " +"загубени." -#: lib/choose_repository.tcl:782 -msgid "Copying objects" -msgstr "Копиране на обекти" +#: lib/index.tcl:441 +msgid "Do Nothing" +msgstr "Нищо да не се прави" -#: lib/choose_repository.tcl:783 -msgid "KiB" -msgstr "KiB" +#: lib/index.tcl:459 +msgid "Reverting selected files" +msgstr "Махане на промените в избраните файлове" -#: lib/choose_repository.tcl:807 +#: lib/index.tcl:463 #, tcl-format -msgid "Unable to copy object: %s" -msgstr "Неуспешно копиране на обект: %s" +msgid "Reverting %s" +msgstr "Махане на промените в „%s“" -#: lib/choose_repository.tcl:817 -msgid "Linking objects" -msgstr "Създаване на връзки към обектите" +#: lib/line.tcl:17 +msgid "Goto Line:" +msgstr "Към ред:" -#: lib/choose_repository.tcl:818 -msgid "objects" -msgstr "обекти" +#: lib/line.tcl:23 +msgid "Go" +msgstr "Придвижване" -#: lib/choose_repository.tcl:826 -#, tcl-format -msgid "Unable to hardlink object: %s" -msgstr "Неуспешно създаване на твърда връзка към обект: %s" +#: lib/merge.tcl:13 +msgid "" +"Cannot merge while amending.\n" +"\n" +"You must finish amending this commit before starting any type of merge.\n" +msgstr "" +"По време на поправяне не може да сливане.\n" +"\n" +"Трябва да завършите поправянето на текущото подаване, преди да започнете " +"сливане.\n" -#: lib/choose_repository.tcl:881 -msgid "Cannot fetch branches and objects. See console output for details." +#: lib/merge.tcl:27 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before a merge can be performed.\n" +"\n" +"The rescan will be automatically started now.\n" msgstr "" -"Клоните и обектите не могат да бъдат изтеглени. За повече информация " -"погледнете изхода на конзолата." +"Последно установеното състояние не отговаря на това в хранилището.\n" +"\n" +"Някой друг процес за Git е променил хранилището междувременно. Състоянието " +"трябва да бъде проверено, преди да се извърши сливане.\n" +"\n" +"Автоматично ще започне нова проверка.\n" +"\n" -#: lib/choose_repository.tcl:892 -msgid "Cannot fetch tags. See console output for details." +#: lib/merge.tcl:45 +#, tcl-format +msgid "" +"You are in the middle of a conflicted merge.\n" +"\n" +"File %s has merge conflicts.\n" +"\n" +"You must resolve them, stage the file, and commit to complete the current " +"merge. Only then can you begin another merge.\n" msgstr "" -"Етикетите не могат да бъдат изтеглени. За повече информация погледнете " -"изхода на конзолата." +"В момента тече сливане, но има конфликти.\n" +"\n" +"Погледнете файла „%s“.\n" +"\n" +"Трябва да коригирате конфликтите в него, да го добавите към индекса и да " +"завършите текущото сливане чрез подаване. Чак тогава може да започнете ново " +"сливане.\n" -#: lib/choose_repository.tcl:916 -msgid "Cannot determine HEAD. See console output for details." +#: lib/merge.tcl:55 +#, tcl-format +msgid "" +"You are in the middle of a change.\n" +"\n" +"File %s is modified.\n" +"\n" +"You should complete the current commit before starting a merge. Doing so " +"will help you abort a failed merge, should the need arise.\n" msgstr "" -"Върхът „HEAD“ не може да бъде определен. За повече информация погледнете " -"изхода на конзолата." +"В момента тече подаване.\n" +"\n" +"Файлът „%s“ е променен.\n" +"\n" +"Трябва да завършите текущото подаване, преди да започнете сливане. Така ще " +"можете лесно да преустановите сливането, ако възникне нужда.\n" -#: lib/choose_repository.tcl:925 +#: lib/merge.tcl:108 #, tcl-format -msgid "Unable to cleanup %s" -msgstr "„%s“ не може да се зачисти" +msgid "%s of %s" +msgstr "%s от общо %s" -#: lib/choose_repository.tcl:931 -msgid "Clone failed." -msgstr "Неуспешно клониране." +#: lib/merge.tcl:126 +#, tcl-format +msgid "Merging %s and %s..." +msgstr "Сливане на „%s“ и „%s“…" -#: lib/choose_repository.tcl:938 -msgid "No default branch obtained." -msgstr "Не е получен клон по подразбиране." +#: lib/merge.tcl:137 +msgid "Merge completed successfully." +msgstr "Сливането завърши успешно." -#: lib/choose_repository.tcl:949 -#, tcl-format -msgid "Cannot resolve %s as a commit." -msgstr "Няма подаване отговарящо на „%s“." +#: lib/merge.tcl:139 +msgid "Merge failed. Conflict resolution is required." +msgstr "Неуспешно сливане — има конфликти за коригиране." -#: lib/choose_repository.tcl:961 -msgid "Creating working directory" -msgstr "Създаване на работната директория" +#: lib/merge.tcl:156 +#, tcl-format +msgid "%s (%s): Merge" +msgstr "%s (%s): Сливане" -#: lib/choose_repository.tcl:962 lib/index.tcl:70 lib/index.tcl:136 -#: lib/index.tcl:207 -msgid "files" -msgstr "файлове" +#: lib/merge.tcl:164 +#, tcl-format +msgid "Merge Into %s" +msgstr "Сливане в „%s“" -#: lib/choose_repository.tcl:981 -msgid "Cannot clone submodules." -msgstr "Подмодулите не могат да се клонират." +#: lib/merge.tcl:183 +msgid "Revision To Merge" +msgstr "Версия за сливане" -#: lib/choose_repository.tcl:990 -msgid "Cloning submodules" -msgstr "Клониране на подмодулите" +#: lib/merge.tcl:218 +msgid "" +"Cannot abort while amending.\n" +"\n" +"You must finish amending this commit.\n" +msgstr "" +"Поправянето не може да бъде преустановено.\n" +"\n" +"Трябва да завършите поправката на това подаване.\n" -#: lib/choose_repository.tcl:1015 -msgid "Initial file checkout failed." -msgstr "Неуспешно първоначално изтегляне." +#: lib/merge.tcl:228 +msgid "" +"Abort merge?\n" +"\n" +"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with aborting the current merge?" +msgstr "" +"Да се преустанови ли сливането?\n" +"\n" +"В такъв случай ●ВСИЧКИ● неподадени промени ще бъдат безвъзвратно загубени.\n" +"\n" +"Наистина ли да се преустанови сливането?" -#: lib/choose_repository.tcl:1059 -msgid "Open" -msgstr "Отваряне" +#: lib/merge.tcl:234 +msgid "" +"Reset changes?\n" +"\n" +"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with resetting the current changes?" +msgstr "" +"Да се занулят ли промените?\n" +"\n" +"В такъв случай ●ВСИЧКИ● неподадени промени ще бъдат безвъзвратно загубени.\n" +"\n" +"Наистина ли да се занулят промените?" -#: lib/choose_repository.tcl:1069 -msgid "Repository:" -msgstr "Хранилище:" +#: lib/merge.tcl:245 +msgid "Aborting" +msgstr "Преустановяване" -#: lib/choose_repository.tcl:1118 -#, tcl-format -msgid "Failed to open repository %s:" -msgstr "Неуспешно отваряне на хранилището „%s“:" +#: lib/merge.tcl:245 +msgid "files reset" +msgstr "файла със занулени промени" -#: lib/about.tcl:26 -msgid "git-gui - a graphical user interface for Git." -msgstr "git-gui — графичен интерфейс за Git." +#: lib/merge.tcl:273 +msgid "Abort failed." +msgstr "Неуспешно преустановяване." -#: lib/checkout_op.tcl:85 -#, tcl-format -msgid "Fetching %s from %s" -msgstr "Доставяне на „%s“ от „%s“" +#: lib/merge.tcl:275 +msgid "Abort completed. Ready." +msgstr "Успешно преустановяване. Готовност за следващо действие." -#: lib/checkout_op.tcl:133 -#, tcl-format -msgid "fatal: Cannot resolve %s" -msgstr "фатална грешка: „%s“ не може да се открие" +#: lib/mergetool.tcl:8 +msgid "Force resolution to the base version?" +msgstr "Да се използва базовата версия" -#: lib/checkout_op.tcl:175 -#, tcl-format -msgid "Branch '%s' does not exist." -msgstr "Клонът „%s“ не съществува." +#: lib/mergetool.tcl:9 +msgid "Force resolution to this branch?" +msgstr "Да се използва версията от този клон" -#: lib/checkout_op.tcl:194 -#, tcl-format -msgid "Failed to configure simplified git-pull for '%s'." -msgstr "Неуспешно настройване на опростен git-pull за „%s“." +#: lib/mergetool.tcl:10 +msgid "Force resolution to the other branch?" +msgstr "Да се използва версията от другия клон" -#: lib/checkout_op.tcl:229 +#: lib/mergetool.tcl:14 #, tcl-format msgid "" -"Branch '%s' already exists.\n" +"Note that the diff shows only conflicting changes.\n" "\n" -"It cannot fast-forward to %s.\n" -"A merge is required." +"%s will be overwritten.\n" +"\n" +"This operation can be undone only by restarting the merge." msgstr "" -"Клонът „%s“ съществува.\n" +"Разликата показва само разликите с конфликт.\n" "\n" -"Той не може да бъде тривиално слят до „%s“.\n" -"Необходимо е сливане." +"Файлът „%s“ ще бъде презаписан.\n" +"\n" +"Тази операция може да бъде отменена само чрез започване на сливането наново." -#: lib/checkout_op.tcl:243 +#: lib/mergetool.tcl:45 #, tcl-format -msgid "Merge strategy '%s' not supported." -msgstr "Стратегия за сливане „%s“ не се поддържа." +msgid "File %s seems to have unresolved conflicts, still stage?" +msgstr "" +"Изглежда, че все още има некоригирани конфликти във файла „%s“. Да се добави " +"ли файлът към индекса?" -#: lib/checkout_op.tcl:262 +#: lib/mergetool.tcl:60 #, tcl-format -msgid "Failed to update '%s'." -msgstr "Неуспешно обновяване на „%s“." - -#: lib/checkout_op.tcl:274 -msgid "Staging area (index) is already locked." -msgstr "Индексът вече е заключен." +msgid "Adding resolution for %s" +msgstr "Добавяне на корекция на конфликтите в „%s“" -#: lib/checkout_op.tcl:289 -msgid "" -"Last scanned state does not match repository state.\n" -"\n" -"Another Git program has modified this repository since the last scan. A " -"rescan must be performed before the current branch can be changed.\n" -"\n" -"The rescan will be automatically started now.\n" +#: lib/mergetool.tcl:141 +msgid "Cannot resolve deletion or link conflicts using a tool" msgstr "" -"Състоянието при последната проверка не отговаря на състоянието на " -"хранилището.\n" -"\n" -"Някой друг процес за Git е променил хранилището междувременно. Състоянието " -"трябва да бъде проверено, преди да се премине към нов клон.\n" -"\n" -"Автоматично ще започне нова проверка.\n" +"Конфликтите при символни връзки или изтриване не могат да бъдат коригирани с " +"външна програма." -#: lib/checkout_op.tcl:345 -#, tcl-format -msgid "Updating working directory to '%s'..." -msgstr "Работната директория се привежда към „%s“…" +#: lib/mergetool.tcl:146 +msgid "Conflict file does not exist" +msgstr "Файлът, в който е конфликтът, не съществува" -#: lib/checkout_op.tcl:346 -msgid "files checked out" -msgstr "файла са изтеглени" +#: lib/mergetool.tcl:246 +#, tcl-format +msgid "Not a GUI merge tool: '%s'" +msgstr "Това не е графична програма за сливане: „%s“" -#: lib/checkout_op.tcl:376 +#: lib/mergetool.tcl:275 #, tcl-format -msgid "Aborted checkout of '%s' (file level merging is required)." -msgstr "" -"Преустановяване на изтеглянето на „%s“ (необходимо е пофайлово сливане)." +msgid "Unsupported merge tool '%s'" +msgstr "Неподдържана програма за сливане: „%s“" -#: lib/checkout_op.tcl:377 -msgid "File level merge required." -msgstr "Необходимо е пофайлово сливане." +#: lib/mergetool.tcl:310 +msgid "Merge tool is already running, terminate it?" +msgstr "Програмата за сливане вече е стартирана. Да бъде ли изключена?" -#: lib/checkout_op.tcl:381 +#: lib/mergetool.tcl:330 #, tcl-format -msgid "Staying on branch '%s'." -msgstr "Оставане върху клона „%s“." +msgid "" +"Error retrieving versions:\n" +"%s" +msgstr "" +"Грешка при изтеглянето на версии:\n" +"%s" -#: lib/checkout_op.tcl:452 +#: lib/mergetool.tcl:350 +#, tcl-format msgid "" -"You are no longer on a local branch.\n" +"Could not start the merge tool:\n" "\n" -"If you wanted to be on a branch, create one now starting from 'This Detached " -"Checkout'." +"%s" msgstr "" -"Вече не сте на локален клон.\n" +"Програмата за сливане не може да бъде стартирана:\n" "\n" -"Ако искате да сте на клон, създайте базиран на „Това несвързано изтегляне“." +"%s" -#: lib/checkout_op.tcl:503 lib/checkout_op.tcl:507 +#: lib/mergetool.tcl:354 +msgid "Running merge tool..." +msgstr "Стартиране на програмата за сливане…" + +#: lib/mergetool.tcl:382 lib/mergetool.tcl:390 +msgid "Merge tool failed." +msgstr "Грешка в програмата за сливане." + +#: lib/option.tcl:11 #, tcl-format -msgid "Checked out '%s'." -msgstr "„%s“ е изтеглен." +msgid "Invalid global encoding '%s'" +msgstr "Неправилно глобално кодиране „%s“" -#: lib/checkout_op.tcl:535 +#: lib/option.tcl:19 #, tcl-format -msgid "Resetting '%s' to '%s' will lose the following commits:" -msgstr "" -"Зануляването на „%s“ към „%s“ ще доведе до загубването на следните подавания:" +msgid "Invalid repo encoding '%s'" +msgstr "Неправилно кодиране „%s“ на хранилището" -#: lib/checkout_op.tcl:557 -msgid "Recovering lost commits may not be easy." -msgstr "Възстановяването на загубените подавания може да е трудно." +#: lib/option.tcl:119 +msgid "Restore Defaults" +msgstr "Стандартни настройки" -#: lib/checkout_op.tcl:562 +#: lib/option.tcl:123 +msgid "Save" +msgstr "Запазване" + +#: lib/option.tcl:133 #, tcl-format -msgid "Reset '%s'?" -msgstr "Зануляване на „%s“?" +msgid "%s Repository" +msgstr "Хранилище „%s“" -#: lib/checkout_op.tcl:571 lib/branch_create.tcl:85 -msgid "Reset" -msgstr "Отначало" +#: lib/option.tcl:134 +msgid "Global (All Repositories)" +msgstr "Глобално (за всички хранилища)" -#: lib/checkout_op.tcl:635 -#, tcl-format -msgid "" -"Failed to set current branch.\n" -"\n" -"This working directory is only partially switched. We successfully updated " -"your files, but failed to update an internal Git file.\n" -"\n" -"This should not have occurred. %s will now close and give up." -msgstr "" -"Неуспешно задаване на текущия клон.\n" -"\n" -"Работната директория е само частично обновена: файловете са обновени " -"успешно, но някой от вътрешните, служебни файлове на Git не е бил.\n" -"\n" -"Това състояние е аварийно и не трябва да се случва. Програмата „%s“ ще " -"преустанови работа." +#: lib/option.tcl:140 +msgid "User Name" +msgstr "Потребителско име" -#: lib/branch_create.tcl:23 -msgid "Create Branch" -msgstr "Създаване на клон" +#: lib/option.tcl:141 +msgid "Email Address" +msgstr "Адрес на е-поща" -#: lib/branch_create.tcl:28 -msgid "Create New Branch" -msgstr "Създаване на нов клон" +#: lib/option.tcl:143 +msgid "Summarize Merge Commits" +msgstr "Обобщаване на подаванията при сливане" -#: lib/branch_create.tcl:42 -msgid "Branch Name" -msgstr "Име на клона" +#: lib/option.tcl:144 +msgid "Merge Verbosity" +msgstr "Подробности при сливанията" -#: lib/branch_create.tcl:57 -msgid "Match Tracking Branch Name" -msgstr "Съвпадане по името на следения клон" +#: lib/option.tcl:145 +msgid "Show Diffstat After Merge" +msgstr "Извеждане на статистика след сливанията" -#: lib/branch_create.tcl:66 -msgid "Starting Revision" -msgstr "Начална версия" +#: lib/option.tcl:146 +msgid "Use Merge Tool" +msgstr "Използване на програма за сливане" -#: lib/branch_create.tcl:72 -msgid "Update Existing Branch:" -msgstr "Обновяване на съществуващ клон:" +#: lib/option.tcl:148 +msgid "Trust File Modification Timestamps" +msgstr "Доверие във времето на промяна на файловете" -#: lib/branch_create.tcl:75 -msgid "No" -msgstr "Не" +#: lib/option.tcl:149 +msgid "Prune Tracking Branches During Fetch" +msgstr "Окастряне на следящите клонове при доставяне" -#: lib/branch_create.tcl:80 -msgid "Fast Forward Only" -msgstr "Само тривиално превъртащо сливане" +#: lib/option.tcl:150 +msgid "Match Tracking Branches" +msgstr "Напасване на следящите клонове" -#: lib/branch_create.tcl:97 -msgid "Checkout After Creation" -msgstr "Преминаване към клона след създаването му" +#: lib/option.tcl:151 +msgid "Use Textconv For Diffs and Blames" +msgstr "Използване на „textconv“ за разликите и анотирането" -#: lib/branch_create.tcl:132 -msgid "Please select a tracking branch." -msgstr "Изберете клон за следени." +#: lib/option.tcl:152 +msgid "Blame Copy Only On Changed Files" +msgstr "Анотиране на копието само по променените файлове" -#: lib/branch_create.tcl:141 -#, tcl-format -msgid "Tracking branch %s is not a branch in the remote repository." -msgstr "Следящият клон — „%s“, не съществува в отдалеченото хранилище." +#: lib/option.tcl:153 +msgid "Maximum Length of Recent Repositories List" +msgstr "Максимален брой на списъка „Скоро ползвани“ хранилища" -#: lib/console.tcl:59 -msgid "Working... please wait..." -msgstr "В момента се извършва действие, изчакайте…" +#: lib/option.tcl:154 +msgid "Minimum Letters To Blame Copy On" +msgstr "Минимален брой знаци за анотиране на копието" -#: lib/console.tcl:186 -msgid "Success" -msgstr "Успех" +#: lib/option.tcl:155 +msgid "Blame History Context Radius (days)" +msgstr "Исторически обхват за анотиране в дни" -#: lib/console.tcl:200 -msgid "Error: Command Failed" -msgstr "Грешка: неуспешно изпълнение на команда" +#: lib/option.tcl:156 +msgid "Number of Diff Context Lines" +msgstr "Брой редове за контекста на разликите" -#: lib/choose_rev.tcl:52 -msgid "This Detached Checkout" -msgstr "Това несвързано изтегляне" +#: lib/option.tcl:157 +msgid "Additional Diff Parameters" +msgstr "Аргументи към командата за разликите" -#: lib/choose_rev.tcl:60 -msgid "Revision Expression:" -msgstr "Израз за версия:" +#: lib/option.tcl:158 +msgid "Commit Message Text Width" +msgstr "Широчина на текста на съобщението при подаване" -#: lib/choose_rev.tcl:72 -msgid "Local Branch" -msgstr "Локален клон" +#: lib/option.tcl:159 +msgid "New Branch Name Template" +msgstr "Шаблон за името на новите клони" -#: lib/choose_rev.tcl:77 -msgid "Tracking Branch" -msgstr "Следящ клон" +#: lib/option.tcl:160 +msgid "Default File Contents Encoding" +msgstr "Кодиране на файловете" -#: lib/choose_rev.tcl:82 lib/choose_rev.tcl:544 -msgid "Tag" -msgstr "Етикет" +#: lib/option.tcl:161 +msgid "Warn before committing to a detached head" +msgstr "Предупреждаване при подаване към несвързан указател" -#: lib/choose_rev.tcl:321 -#, tcl-format -msgid "Invalid revision: %s" -msgstr "Неправилна версия: %s" +#: lib/option.tcl:162 +msgid "Staging of untracked files" +msgstr "Добавяне на неследените файлове към индекса" -#: lib/choose_rev.tcl:342 -msgid "No revision selected." -msgstr "Не е избрана версия." +#: lib/option.tcl:163 +msgid "Show untracked files" +msgstr "Показване на неследените файлове" -#: lib/choose_rev.tcl:350 -msgid "Revision expression is empty." -msgstr "Изразът за версия е празен." +#: lib/option.tcl:164 +msgid "Tab spacing" +msgstr "Ширина на табулацията" -#: lib/choose_rev.tcl:537 -msgid "Updated" -msgstr "Обновен" +#: lib/option.tcl:210 +msgid "Change" +msgstr "Смяна" -#: lib/choose_rev.tcl:565 -msgid "URL" -msgstr "Адрес" +#: lib/option.tcl:254 +msgid "Spelling Dictionary:" +msgstr "Правописен речник:" -#: lib/line.tcl:17 -msgid "Goto Line:" -msgstr "Към ред:" +#: lib/option.tcl:284 +msgid "Change Font" +msgstr "Смяна на шрифта" -#: lib/line.tcl:23 -msgid "Go" -msgstr "Придвижване" +#: lib/option.tcl:288 +#, tcl-format +msgid "Choose %s" +msgstr "Избор на „%s“" -#: lib/commit.tcl:9 -msgid "" -"There is nothing to amend.\n" -"\n" -"You are about to create the initial commit. There is no commit before this " -"to amend.\n" -msgstr "" -"Няма какво да се поправи.\n" -"\n" -"Ще създадете първоначалното подаване. Преди него няма други подавания, които " -"да поправите.\n" +#: lib/option.tcl:294 +msgid "pt." +msgstr "тчк." -#: lib/commit.tcl:18 -msgid "" -"Cannot amend while merging.\n" -"\n" -"You are currently in the middle of a merge that has not been fully " -"completed. You cannot amend the prior commit unless you first abort the " -"current merge activity.\n" -msgstr "" -"По време на сливане не може да поправяте.\n" -"\n" -"В момента все още не сте завършили операция по сливане. Не може да поправите " -"предишното подаване, освен ако първо не преустановите текущото сливане.\n" +#: lib/option.tcl:308 +msgid "Preferences" +msgstr "Настройки" -#: lib/commit.tcl:48 -msgid "Error loading commit data for amend:" -msgstr "Грешка при зареждане на данните от подаване, които да се поправят:" +#: lib/option.tcl:345 +msgid "Failed to completely save options:" +msgstr "Неуспешно запазване на настройките:" -#: lib/commit.tcl:75 -msgid "Unable to obtain your identity:" -msgstr "Идентификацията ви не може да бъде определена:" +#: lib/remote.tcl:200 +msgid "Push to" +msgstr "Изтласкване към" -#: lib/commit.tcl:80 -msgid "Invalid GIT_COMMITTER_IDENT:" -msgstr "Неправилно поле „GIT_COMMITTER_IDENT“:" +#: lib/remote.tcl:218 +msgid "Remove Remote" +msgstr "Премахване на отдалечено хранилище" -#: lib/commit.tcl:129 -#, tcl-format -msgid "warning: Tcl does not support encoding '%s'." -msgstr "предупреждение: Tcl не поддържа кодирането „%s“." +#: lib/remote.tcl:223 +msgid "Prune from" +msgstr "Окастряне от" + +#: lib/remote.tcl:228 +msgid "Fetch from" +msgstr "Доставяне от" -#: lib/commit.tcl:149 -msgid "" -"Last scanned state does not match repository state.\n" -"\n" -"Another Git program has modified this repository since the last scan. A " -"rescan must be performed before another commit can be created.\n" -"\n" -"The rescan will be automatically started now.\n" -msgstr "" -"Състоянието при последната проверка не отговаря на състоянието на " -"хранилището.\n" -"\n" -"Някой друг процес за Git е променил хранилището междувременно. Състоянието " -"трябва да бъде проверено преди ново подаване.\n" -"\n" -"Автоматично ще започне нова проверка.\n" +#: lib/remote.tcl:253 lib/remote.tcl:258 +msgid "All" +msgstr "Всички" -#: lib/commit.tcl:173 +#: lib/remote_add.tcl:20 #, tcl-format -msgid "" -"Unmerged files cannot be committed.\n" -"\n" -"File %s has merge conflicts. You must resolve them and stage the file " -"before committing.\n" -msgstr "" -"Неслетите файлове не могат да бъдат подавани.\n" -"\n" -"Във файла „%s“ има конфликти при сливане. За да го подадете, трябва първо да " -"коригирате конфликтите и да добавите файла към индекса за подаване.\n" +msgid "%s (%s): Add Remote" +msgstr "%s (%s): Добавяне на отдалечено хранилище" -#: lib/commit.tcl:181 -#, tcl-format -msgid "" -"Unknown file state %s detected.\n" -"\n" -"File %s cannot be committed by this program.\n" -msgstr "" -"Непознато състояние на файл „%s“.\n" -"\n" -"Файлът „%s“ не може да бъде подаден чрез текущата програма.\n" +#: lib/remote_add.tcl:25 +msgid "Add New Remote" +msgstr "Добавяне на отдалечено хранилище" -#: lib/commit.tcl:189 -msgid "" -"No changes to commit.\n" -"\n" -"You must stage at least 1 file before you can commit.\n" -msgstr "" -"Няма промени за подаване.\n" -"\n" -"Трябва да добавите поне един файл към индекса, за да подадете.\n" +#: lib/remote_add.tcl:30 lib/tools_dlg.tcl:37 +msgid "Add" +msgstr "Добавяне" -#: lib/commit.tcl:204 -msgid "" -"Please supply a commit message.\n" -"\n" -"A good commit message has the following format:\n" -"\n" -"- First line: Describe in one sentence what you did.\n" -"- Second line: Blank\n" -"- Remaining lines: Describe why this change is good.\n" -msgstr "" -"Задайте добро съобщение при подаване.\n" -"\n" -"Използвайте следния формат:\n" -"\n" -"● Първи ред: описание в едно изречение на промяната.\n" -"● Втори ред: празен.\n" -"● Останалите редове: опишете защо се налага тази промяна.\n" +#: lib/remote_add.tcl:39 +msgid "Remote Details" +msgstr "Данни за отдалеченото хранилище" -#: lib/commit.tcl:235 -msgid "Calling pre-commit hook..." -msgstr "Изпълняване на куката преди подаване…" +#: lib/remote_add.tcl:50 +msgid "Location:" +msgstr "Местоположение:" -#: lib/commit.tcl:250 -msgid "Commit declined by pre-commit hook." -msgstr "Подаването е отхвърлено от куката преди подаване." +#: lib/remote_add.tcl:60 +msgid "Further Action" +msgstr "Следващо действие" -#: lib/commit.tcl:269 -msgid "" -"You are about to commit on a detached head. This is a potentially dangerous " -"thing to do because if you switch to another branch you will lose your " -"changes and it can be difficult to retrieve them later from the reflog. You " -"should probably cancel this commit and create a new branch to continue.\n" -" \n" -" Do you really want to proceed with your Commit?" -msgstr "" -"Ще подавате към несвързан връх. Това е опасно — при изтеглянето на друг клон " -"ще изгубите промените си. След това може да е невъзможно да ги възстановите " -"от журнала на указателите „reflog“. Най-вероятно трябва да отмените това " -"подаване и да създадете клон, в който да подадете.\n" -" \n" -"Сигурни ли сте, че искате да подадете към несвързан връх?" +#: lib/remote_add.tcl:63 +msgid "Fetch Immediately" +msgstr "Незабавно доставяне" -#: lib/commit.tcl:290 -msgid "Calling commit-msg hook..." -msgstr "Изпълняване на куката за съобщението при подаване…" +#: lib/remote_add.tcl:69 +msgid "Initialize Remote Repository and Push" +msgstr "Инициализиране на отдалеченото хранилище и изтласкване на промените" -#: lib/commit.tcl:305 -msgid "Commit declined by commit-msg hook." -msgstr "Подаването е отхвърлено от куката за съобщението при подаване." +#: lib/remote_add.tcl:75 +msgid "Do Nothing Else Now" +msgstr "Да не се прави нищо" -#: lib/commit.tcl:318 -msgid "Committing changes..." -msgstr "Подаване на промените…" +#: lib/remote_add.tcl:100 +msgid "Please supply a remote name." +msgstr "Задайте име за отдалеченото хранилище." -#: lib/commit.tcl:334 -msgid "write-tree failed:" -msgstr "неуспешно запазване на дървото (write-tree):" +#: lib/remote_add.tcl:113 +#, tcl-format +msgid "'%s' is not an acceptable remote name." +msgstr "Отдалечено хранилище не може да се казва „%s“." -#: lib/commit.tcl:335 lib/commit.tcl:379 lib/commit.tcl:400 -msgid "Commit failed." -msgstr "Неуспешно подаване." +#: lib/remote_add.tcl:124 +#, tcl-format +msgid "Failed to add remote '%s' of location '%s'." +msgstr "Неуспешно добавяне на отдалеченото хранилище „%s“ от адрес „%s“." -#: lib/commit.tcl:352 +#: lib/remote_add.tcl:132 lib/transport.tcl:6 #, tcl-format -msgid "Commit %s appears to be corrupt" -msgstr "Подаването „%s“ изглежда повредено" +msgid "fetch %s" +msgstr "доставяне на „%s“" -#: lib/commit.tcl:357 -msgid "" -"No changes to commit.\n" -"\n" -"No files were modified by this commit and it was not a merge commit.\n" -"\n" -"A rescan will be automatically started now.\n" -msgstr "" -"Няма промени за подаване.\n" -"\n" -"В това подаване не са променяни никакви файлове, а и не е подаване със " -"сливане.\n" -"\n" -"Автоматично ще започне нова проверка.\n" +#: lib/remote_add.tcl:133 +#, tcl-format +msgid "Fetching the %s" +msgstr "Доставяне на „%s“" -#: lib/commit.tcl:364 -msgid "No changes to commit." -msgstr "Няма промени за подаване." +#: lib/remote_add.tcl:156 +#, tcl-format +msgid "Do not know how to initialize repository at location '%s'." +msgstr "Хранилището с местоположение „%s“ не може да бъде инициализирано." -#: lib/commit.tcl:378 -msgid "commit-tree failed:" -msgstr "неуспешно подаване на дървото (commit-tree):" +#: lib/remote_add.tcl:162 lib/transport.tcl:54 lib/transport.tcl:92 +#: lib/transport.tcl:110 +#, tcl-format +msgid "push %s" +msgstr "изтласкване на „%s“" -#: lib/commit.tcl:399 -msgid "update-ref failed:" -msgstr "неуспешно обновяване на указателите (update-ref):" +#: lib/remote_add.tcl:163 +#, tcl-format +msgid "Setting up the %s (at %s)" +msgstr "Добавяне на хранилище „%s“ (с адрес „%s“)" -#: lib/commit.tcl:492 +#: lib/remote_branch_delete.tcl:29 #, tcl-format -msgid "Created commit %s: %s" -msgstr "Успешно подаване %s: %s" +msgid "%s (%s): Delete Branch Remotely" +msgstr "%s (%s): Изтриване на отдалечения клон" -#: lib/branch_delete.tcl:16 -msgid "Delete Branch" -msgstr "Изтриване на клон" +#: lib/remote_branch_delete.tcl:34 +msgid "Delete Branch Remotely" +msgstr "Изтриване на отдалечения клон" -#: lib/branch_delete.tcl:21 -msgid "Delete Local Branch" -msgstr "Изтриване на локален клон" +#: lib/remote_branch_delete.tcl:48 +msgid "From Repository" +msgstr "От хранилище" -#: lib/branch_delete.tcl:39 -msgid "Local Branches" -msgstr "Локални клони" +#: lib/remote_branch_delete.tcl:51 lib/transport.tcl:165 +msgid "Remote:" +msgstr "Отдалечено хранилище:" -#: lib/branch_delete.tcl:51 -msgid "Delete Only If Merged Into" -msgstr "Изтриване, само ако промените са слети и другаде" +#: lib/remote_branch_delete.tcl:72 lib/transport.tcl:187 +msgid "Arbitrary Location:" +msgstr "Произволно местоположение:" -#: lib/branch_delete.tcl:103 -#, tcl-format -msgid "The following branches are not completely merged into %s:" -msgstr "Не всички промени в клоните са слети в „%s“:" +#: lib/remote_branch_delete.tcl:88 +msgid "Branches" +msgstr "Клони" -#: lib/branch_delete.tcl:141 +#: lib/remote_branch_delete.tcl:110 +msgid "Delete Only If" +msgstr "Изтриване, само ако" + +#: lib/remote_branch_delete.tcl:112 +msgid "Merged Into:" +msgstr "Слят в:" + +#: lib/remote_branch_delete.tcl:153 +msgid "A branch is required for 'Merged Into'." +msgstr "За данните „Слят в“ е необходимо да зададете клон." + +#: lib/remote_branch_delete.tcl:185 #, tcl-format msgid "" -"Failed to delete branches:\n" -"%s" +"The following branches are not completely merged into %s:\n" +"\n" +" - %s" msgstr "" -"Неуспешно триене на клони:\n" -"%s" +"Следните клони не са слети напълно в „%s“:\n" +"\n" +" ● %s" -#: lib/blame.tcl:73 -msgid "File Viewer" -msgstr "Преглед на файлове" +#: lib/remote_branch_delete.tcl:190 +#, tcl-format +msgid "" +"One or more of the merge tests failed because you have not fetched the " +"necessary commits. Try fetching from %s first." +msgstr "" +"Поне една от пробите за сливане е неуспешна, защото не сте доставили всички " +"необходими подавания. Пробвайте първо да доставите подаванията от „%s“." -#: lib/blame.tcl:79 -msgid "Commit:" -msgstr "Подаване:" +#: lib/remote_branch_delete.tcl:208 +msgid "Please select one or more branches to delete." +msgstr "Изберете поне един клон за изтриване." -#: lib/blame.tcl:280 -msgid "Copy Commit" -msgstr "Копиране на подаване" +#: lib/remote_branch_delete.tcl:227 +#, tcl-format +msgid "Deleting branches from %s" +msgstr "Изтриване на клони от „%s“" -#: lib/blame.tcl:284 -msgid "Find Text..." -msgstr "Търсене на текст…" +#: lib/remote_branch_delete.tcl:300 +msgid "No repository selected." +msgstr "Не е избрано хранилище." -#: lib/blame.tcl:288 -msgid "Goto Line..." -msgstr "Към ред…" +#: lib/remote_branch_delete.tcl:305 +#, tcl-format +msgid "Scanning %s..." +msgstr "Претърсване на „%s“…" -#: lib/blame.tcl:297 -msgid "Do Full Copy Detection" -msgstr "Пълно търсене на копиране" +#: lib/search.tcl:48 +msgid "Find:" +msgstr "Търсене:" -#: lib/blame.tcl:301 -msgid "Show History Context" -msgstr "Показване на контекста от историята" +#: lib/search.tcl:50 +msgid "Next" +msgstr "Следваща поява" -#: lib/blame.tcl:304 -msgid "Blame Parent Commit" -msgstr "Анотиране на родителското подаване" +#: lib/search.tcl:51 +msgid "Prev" +msgstr "Предишна поява" -#: lib/blame.tcl:466 -#, tcl-format -msgid "Reading %s..." -msgstr "Чете се „%s“…" +#: lib/search.tcl:52 +msgid "RegExp" +msgstr "РегИзр" -#: lib/blame.tcl:594 -msgid "Loading copy/move tracking annotations..." -msgstr "Зареждане на анотациите за проследяване на копирането/преместването…" +#: lib/search.tcl:54 +msgid "Case" +msgstr "Главни/малки" -#: lib/blame.tcl:614 -msgid "lines annotated" -msgstr "реда анотирани" +#: lib/shortcut.tcl:8 lib/shortcut.tcl:43 lib/shortcut.tcl:75 +#, tcl-format +msgid "%s (%s): Create Desktop Icon" +msgstr "%s (%s): Добавяне на икона на работния плот" -#: lib/blame.tcl:806 -msgid "Loading original location annotations..." -msgstr "Зареждане на анотациите за първоначалното местоположение…" +#: lib/shortcut.tcl:24 lib/shortcut.tcl:65 +msgid "Cannot write shortcut:" +msgstr "Клавишната комбинация не може да бъде запазена:" -#: lib/blame.tcl:809 -msgid "Annotation complete." -msgstr "Анотирането завърши." +#: lib/shortcut.tcl:140 +msgid "Cannot write icon:" +msgstr "Иконата не може да бъде запазена:" -#: lib/blame.tcl:839 -msgid "Busy" -msgstr "Операцията не е завършила" +#: lib/spellcheck.tcl:57 +msgid "Unsupported spell checker" +msgstr "Тази програма за проверка на правописа не се поддържа" -#: lib/blame.tcl:840 -msgid "Annotation process is already running." -msgstr "В момента тече процес на анотиране." +#: lib/spellcheck.tcl:65 +msgid "Spell checking is unavailable" +msgstr "Липсва програма за проверка на правописа" -#: lib/blame.tcl:879 -msgid "Running thorough copy detection..." -msgstr "Изпълнява се цялостен процес на откриване на копиране…" +#: lib/spellcheck.tcl:68 +msgid "Invalid spell checking configuration" +msgstr "Неправилни настройки на проверката на правописа" -#: lib/blame.tcl:947 -msgid "Loading annotation..." -msgstr "Зареждане на анотации…" +#: lib/spellcheck.tcl:70 +#, tcl-format +msgid "Reverting dictionary to %s." +msgstr "Ползване на речник за език „%s“." -#: lib/blame.tcl:1000 -msgid "Author:" -msgstr "Автор:" +#: lib/spellcheck.tcl:73 +msgid "Spell checker silently failed on startup" +msgstr "Програмата за правопис даже не стартира успешно." -#: lib/blame.tcl:1004 -msgid "Committer:" -msgstr "Подал:" +#: lib/spellcheck.tcl:80 +msgid "Unrecognized spell checker" +msgstr "Непозната програма за проверка на правописа" -#: lib/blame.tcl:1009 -msgid "Original File:" -msgstr "Първоначален файл:" +#: lib/spellcheck.tcl:186 +msgid "No Suggestions" +msgstr "Няма предложения" -#: lib/blame.tcl:1057 -msgid "Cannot find HEAD commit:" -msgstr "Подаването за връх „HEAD“ не може да се открие:" +#: lib/spellcheck.tcl:388 +msgid "Unexpected EOF from spell checker" +msgstr "Неочакван край на файл от програмата за проверка на правописа" -#: lib/blame.tcl:1112 -msgid "Cannot find parent commit:" -msgstr "Родителското подаване не може да бъде открито" +#: lib/spellcheck.tcl:392 +msgid "Spell Checker Failed" +msgstr "Грешка в програмата за проверка на правописа" -#: lib/blame.tcl:1127 -msgid "Unable to display parent" -msgstr "Родителят не може да бъде показан" +#: lib/sshkey.tcl:31 +msgid "No keys found." +msgstr "Не са открити ключове." -#: lib/blame.tcl:1269 -msgid "Originally By:" -msgstr "Първоначално от:" +#: lib/sshkey.tcl:34 +#, tcl-format +msgid "Found a public key in: %s" +msgstr "Открит е публичен ключ в „%s“" -#: lib/blame.tcl:1275 -msgid "In File:" -msgstr "Във файл:" +#: lib/sshkey.tcl:40 +msgid "Generate Key" +msgstr "Генериране на ключ" -#: lib/blame.tcl:1280 -msgid "Copied Or Moved Here By:" -msgstr "Копирано или преместено тук от:" +#: lib/sshkey.tcl:58 +msgid "Copy To Clipboard" +msgstr "Копиране към системния буфер" -#: lib/index.tcl:6 -msgid "Unable to unlock the index." -msgstr "Индексът не може да бъде отключен." +#: lib/sshkey.tcl:72 +msgid "Your OpenSSH Public Key" +msgstr "Публичният ви ключ за OpenSSH" -#: lib/index.tcl:17 -msgid "Index Error" -msgstr "Грешка в индекса" +#: lib/sshkey.tcl:80 +msgid "Generating..." +msgstr "Генериране…" -#: lib/index.tcl:19 +#: lib/sshkey.tcl:86 +#, tcl-format msgid "" -"Updating the Git index failed. A rescan will be automatically started to " -"resynchronize git-gui." +"Could not start ssh-keygen:\n" +"\n" +"%s" msgstr "" -"Неуспешно обновяване на индекса на Git. Автоматично ще започне нова проверка " -"за синхронизирането на git-gui." +"Програмата „ssh-keygen“ не може да бъде стартирана:\n" +"\n" +"%s" -#: lib/index.tcl:30 -msgid "Continue" -msgstr "Продължаване" +#: lib/sshkey.tcl:113 +msgid "Generation failed." +msgstr "Неуспешно генериране." -#: lib/index.tcl:33 -msgid "Unlock Index" -msgstr "Отключване на индекса" +#: lib/sshkey.tcl:120 +msgid "Generation succeeded, but no keys found." +msgstr "Генерирането завърши успешно, а не са намерени ключове." -#: lib/index.tcl:298 +#: lib/sshkey.tcl:123 #, tcl-format -msgid "Unstaging %s from commit" -msgstr "Изваждане на „%s“ от подаването" +msgid "Your key is in: %s" +msgstr "Ключът ви е в „%s“" -#: lib/index.tcl:337 -msgid "Ready to commit." -msgstr "Готовност за подаване." +#: lib/status_bar.tcl:87 +#, tcl-format +msgid "%s ... %*i of %*i %s (%3i%%)" +msgstr "%s… %*i от общо %*i %s (%3i%%)" -#: lib/index.tcl:350 +#: lib/tools.tcl:76 #, tcl-format -msgid "Adding %s" -msgstr "Добавяне на „%s“" +msgid "Running %s requires a selected file." +msgstr "За изпълнението на „%s“ трябва да изберете файл." -#: lib/index.tcl:380 +#: lib/tools.tcl:92 #, tcl-format -msgid "Stage %d untracked files?" -msgstr "Да се вкарат ли %d неследени файла в индекса?" +msgid "Are you sure you want to run %1$s on file \"%2$s\"?" +msgstr "Сигурни ли сте, че искате да изпълните „%1$s“ върху файла „%2$s“?" -#: lib/index.tcl:428 +#: lib/tools.tcl:96 #, tcl-format -msgid "Revert changes in file %s?" -msgstr "Да се махнат ли промените във файла „%s“?" +msgid "Are you sure you want to run %s?" +msgstr "Сигурни ли сте, че искате да изпълните „%s“?" -#: lib/index.tcl:430 +#: lib/tools.tcl:118 #, tcl-format -msgid "Revert changes in these %i files?" -msgstr "Да се махнат ли промените в тези %i файла?" +msgid "Tool: %s" +msgstr "Команда: %s" -#: lib/index.tcl:438 -msgid "Any unstaged changes will be permanently lost by the revert." +#: lib/tools.tcl:119 +#, tcl-format +msgid "Running: %s" +msgstr "Изпълнение: %s" + +#: lib/tools.tcl:158 +#, tcl-format +msgid "Tool completed successfully: %s" +msgstr "Командата завърши успешно: %s" + +#: lib/tools.tcl:160 +#, tcl-format +msgid "Tool failed: %s" +msgstr "Командата върна грешка: %s" + +#: lib/tools_dlg.tcl:22 +#, tcl-format +msgid "%s (%s): Add Tool" +msgstr "%s (%s): Добавяне на команда" + +#: lib/tools_dlg.tcl:28 +msgid "Add New Tool Command" +msgstr "Добавяне на команда" + +#: lib/tools_dlg.tcl:34 +msgid "Add globally" +msgstr "Глобално добавяне" + +#: lib/tools_dlg.tcl:46 +msgid "Tool Details" +msgstr "Подробности за командата" + +#: lib/tools_dlg.tcl:49 +msgid "Use '/' separators to create a submenu tree:" +msgstr "За създаване на подменюта използвайте знака „/“ за разделител:" + +#: lib/tools_dlg.tcl:60 +msgid "Command:" +msgstr "Команда:" + +#: lib/tools_dlg.tcl:71 +msgid "Show a dialog before running" +msgstr "Преди изпълнение да се извежда диалогов прозорец" + +#: lib/tools_dlg.tcl:77 +msgid "Ask the user to select a revision (sets $REVISION)" +msgstr "Потребителят да укаже версия (задаване на променливата $REVISION)" + +#: lib/tools_dlg.tcl:82 +msgid "Ask the user for additional arguments (sets $ARGS)" msgstr "" -"Всички промени, които не са били вкарани в индекса, ще бъдат безвъзвратно " -"загубени." +"Потребителят да укаже допълнителни аргументи (задаване на променливата $ARGS)" -#: lib/index.tcl:441 -msgid "Do Nothing" -msgstr "Нищо да не се прави" +#: lib/tools_dlg.tcl:89 +msgid "Don't show the command output window" +msgstr "Без показване на прозорец с изхода от командата" + +#: lib/tools_dlg.tcl:94 +msgid "Run only if a diff is selected ($FILENAME not empty)" +msgstr "" +"Стартиране само след избор на разлика (променливата $FILENAME не е празна)" -#: lib/index.tcl:459 -msgid "Reverting selected files" -msgstr "Махане на промените в избраните файлове" +#: lib/tools_dlg.tcl:118 +msgid "Please supply a name for the tool." +msgstr "Задайте име за командата." -#: lib/index.tcl:463 +#: lib/tools_dlg.tcl:126 #, tcl-format -msgid "Reverting %s" -msgstr "Махане на промените в „%s“" +msgid "Tool '%s' already exists." +msgstr "Командата „%s“ вече съществува." -#: lib/date.tcl:25 +#: lib/tools_dlg.tcl:148 #, tcl-format -msgid "Invalid date from Git: %s" -msgstr "Неправилни данни от Git: %s" - -#: lib/database.tcl:42 -msgid "Number of loose objects" -msgstr "Брой непакетирани обекти" +msgid "" +"Could not add tool:\n" +"%s" +msgstr "" +"Командата не може да бъде добавена:\n" +"%s" -#: lib/database.tcl:43 -msgid "Disk space used by loose objects" -msgstr "Дисково пространство заето от непакетирани обекти" +#: lib/tools_dlg.tcl:187 +#, tcl-format +msgid "%s (%s): Remove Tool" +msgstr "%s (%s): Премахване на команда" -#: lib/database.tcl:44 -msgid "Number of packed objects" -msgstr "Брой пакетирани обекти" +#: lib/tools_dlg.tcl:193 +msgid "Remove Tool Commands" +msgstr "Премахване на команди" -#: lib/database.tcl:45 -msgid "Number of packs" -msgstr "Брой пакети" +#: lib/tools_dlg.tcl:198 +msgid "Remove" +msgstr "Премахване" -#: lib/database.tcl:46 -msgid "Disk space used by packed objects" -msgstr "Дисково пространство заето от пакетирани обекти" +#: lib/tools_dlg.tcl:231 +msgid "(Blue denotes repository-local tools)" +msgstr "(командите към локалното хранилище са обозначени в синьо)" -#: lib/database.tcl:47 -msgid "Packed objects waiting for pruning" -msgstr "Пакетирани обекти за окастряне" +#: lib/tools_dlg.tcl:283 +#, tcl-format +msgid "%s (%s):" +msgstr "%s (%s):" -#: lib/database.tcl:48 -msgid "Garbage files" -msgstr "Файлове за боклука" +#: lib/tools_dlg.tcl:292 +#, tcl-format +msgid "Run Command: %s" +msgstr "Изпълнение на командата „%s“" -#: lib/database.tcl:72 -msgid "Compressing the object database" -msgstr "Компресиране на базата с данни за обектите" +#: lib/tools_dlg.tcl:306 +msgid "Arguments" +msgstr "Аргументи" -#: lib/database.tcl:83 -msgid "Verifying the object database with fsck-objects" -msgstr "Проверка на базата с данни за обектите с програмата „fsck-objects“" +#: lib/tools_dlg.tcl:341 +msgid "OK" +msgstr "Добре" -#: lib/database.tcl:107 +#: lib/transport.tcl:7 #, tcl-format -msgid "" -"This repository currently has approximately %i loose objects.\n" -"\n" -"To maintain optimal performance it is strongly recommended that you compress " -"the database.\n" -"\n" -"Compress the database now?" -msgstr "" -"В това хранилище в момента има към %i непакетирани обекти.\n" -"\n" -"За добра производителност се препоръчва да компресирате базата с данни за " -"обектите.\n" -"\n" -"Да се започне ли компресирането?" +msgid "Fetching new changes from %s" +msgstr "Доставяне на промените от „%s“" -#: lib/error.tcl:20 lib/error.tcl:116 -msgid "error" -msgstr "грешка" +#: lib/transport.tcl:18 +#, tcl-format +msgid "remote prune %s" +msgstr "окастряне на следящите клони към „%s“" -#: lib/error.tcl:36 -msgid "warning" -msgstr "предупреждение" +#: lib/transport.tcl:19 +#, tcl-format +msgid "Pruning tracking branches deleted from %s" +msgstr "Окастряне на следящите клони на изтритите клони от „%s“" -#: lib/error.tcl:96 -msgid "You must correct the above errors before committing." -msgstr "Преди да можете да подадете, коригирайте горните грешки." +#: lib/transport.tcl:25 +msgid "fetch all remotes" +msgstr "доставяне от всички отдалечени" -#: lib/merge.tcl:13 -msgid "" -"Cannot merge while amending.\n" -"\n" -"You must finish amending this commit before starting any type of merge.\n" -msgstr "" -"По време на поправяне не може да сливане.\n" -"\n" -"Трябва да завършите поправянето на текущото подаване, преди да започнете " -"сливане.\n" +#: lib/transport.tcl:26 +msgid "Fetching new changes from all remotes" +msgstr "Доставяне на промените от всички отдалечени хранилища" -#: lib/merge.tcl:27 -msgid "" -"Last scanned state does not match repository state.\n" -"\n" -"Another Git program has modified this repository since the last scan. A " -"rescan must be performed before a merge can be performed.\n" -"\n" -"The rescan will be automatically started now.\n" -msgstr "" -"Последно установеното състояние не отговаря на това в хранилището.\n" -"\n" -"Някой друг процес за Git е променил хранилището междувременно. Състоянието " -"трябва да бъде проверено, преди да се извърши сливане.\n" -"\n" -"Автоматично ще започне нова проверка.\n" -"\n" +#: lib/transport.tcl:40 +msgid "remote prune all remotes" +msgstr "окастряне на следящите изтрити" -#: lib/merge.tcl:45 -#, tcl-format -msgid "" -"You are in the middle of a conflicted merge.\n" -"\n" -"File %s has merge conflicts.\n" -"\n" -"You must resolve them, stage the file, and commit to complete the current " -"merge. Only then can you begin another merge.\n" +#: lib/transport.tcl:41 +msgid "Pruning tracking branches deleted from all remotes" msgstr "" -"В момента тече сливане, но има конфликти.\n" -"\n" -"Погледнете файла „%s“.\n" -"\n" -"Трябва да коригирате конфликтите в него, да го добавите към индекса и да " -"завършите текущото сливане чрез подаване. Чак тогава може да започнете ново " -"сливане.\n" +"Окастряне на следящите клони на изтритите клони от всички отдалечени " +"хранилища" -#: lib/merge.tcl:55 +#: lib/transport.tcl:55 #, tcl-format -msgid "" -"You are in the middle of a change.\n" -"\n" -"File %s is modified.\n" -"\n" -"You should complete the current commit before starting a merge. Doing so " -"will help you abort a failed merge, should the need arise.\n" -msgstr "" -"В момента тече подаване.\n" -"\n" -"Файлът „%s“ е променен.\n" -"\n" -"Трябва да завършите текущото подаване, преди да започнете сливане. Така ще " -"можете лесно да преустановите сливането, ако възникне нужда.\n" +msgid "Pushing changes to %s" +msgstr "Изтласкване на промените към „%s“" -#: lib/merge.tcl:108 +#: lib/transport.tcl:93 #, tcl-format -msgid "%s of %s" -msgstr "%s от общо %s" +msgid "Mirroring to %s" +msgstr "Изтласкване на всичко към „%s“" -#: lib/merge.tcl:122 +#: lib/transport.tcl:111 #, tcl-format -msgid "Merging %s and %s..." -msgstr "Сливане на „%s“ и „%s“…" - -#: lib/merge.tcl:133 -msgid "Merge completed successfully." -msgstr "Сливането завърши успешно." - -#: lib/merge.tcl:135 -msgid "Merge failed. Conflict resolution is required." -msgstr "Неуспешно сливане — има конфликти за коригиране." +msgid "Pushing %s %s to %s" +msgstr "Изтласкване на %s „%s“ към „%s“" -#: lib/merge.tcl:160 -#, tcl-format -msgid "Merge Into %s" -msgstr "Сливане в „%s“" +#: lib/transport.tcl:132 +msgid "Push Branches" +msgstr "Клони за изтласкване" -#: lib/merge.tcl:179 -msgid "Revision To Merge" -msgstr "Версия за сливане" +#: lib/transport.tcl:147 +msgid "Source Branches" +msgstr "Клони-източници" -#: lib/merge.tcl:214 -msgid "" -"Cannot abort while amending.\n" -"\n" -"You must finish amending this commit.\n" -msgstr "" -"Поправянето не може да бъде преустановено.\n" -"\n" -"Трябва да завършите поправката на това подаване.\n" +#: lib/transport.tcl:162 +msgid "Destination Repository" +msgstr "Целево хранилище" -#: lib/merge.tcl:224 -msgid "" -"Abort merge?\n" -"\n" -"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" -"\n" -"Continue with aborting the current merge?" -msgstr "" -"Да се преустанови ли сливането?\n" -"\n" -"В такъв случай ●ВСИЧКИ● неподадени промени ще бъдат безвъзвратно загубени.\n" -"\n" -"Наистина ли да се преустанови сливането?" +#: lib/transport.tcl:205 +msgid "Transfer Options" +msgstr "Настройки при пренасянето" -#: lib/merge.tcl:230 -msgid "" -"Reset changes?\n" -"\n" -"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" -"\n" -"Continue with resetting the current changes?" +#: lib/transport.tcl:207 +msgid "Force overwrite existing branch (may discard changes)" msgstr "" -"Да се занулят ли промените?\n" -"\n" -"В такъв случай ●ВСИЧКИ● неподадени промени ще бъдат безвъзвратно загубени.\n" -"\n" -"Наистина ли да се занулят промените?" - -#: lib/merge.tcl:241 -msgid "Aborting" -msgstr "Преустановяване" +"Изрично презаписване на съществуващ клон (някои промени може да бъдат " +"загубени)" -#: lib/merge.tcl:241 -msgid "files reset" -msgstr "файла със занулени промени" +#: lib/transport.tcl:211 +msgid "Use thin pack (for slow network connections)" +msgstr "Максимална компресия (за бавни мрежови връзки)" -#: lib/merge.tcl:269 -msgid "Abort failed." -msgstr "Неуспешно преустановяване." +#: lib/transport.tcl:215 +msgid "Include tags" +msgstr "Включване на етикетите" -#: lib/merge.tcl:271 -msgid "Abort completed. Ready." -msgstr "Успешно преустановяване. Готовност за следващо действие." +#: lib/transport.tcl:229 +#, tcl-format +msgid "%s (%s): Push" +msgstr "%s (%s): Изтласкване" diff --git a/git-gui/po/glossary/pt_pt.po b/git-gui/po/glossary/pt_pt.po new file mode 100644 index 0000000..adc3b54 --- /dev/null +++ b/git-gui/po/glossary/pt_pt.po @@ -0,0 +1,293 @@ +# Portuguese translations for git-gui glossary. +# Copyright (C) 2016 Shawn Pearce, et al. +# This file is distributed under the same license as the git package. +# Vasco Almeida , 2016. +msgid "" +msgstr "" +"Project-Id-Version: git-gui glossary\n" +"POT-Creation-Date: 2016-05-06 10:22+0000\n" +"PO-Revision-Date: 2016-05-06 12:32+0000\n" +"Last-Translator: Vasco Almeida \n" +"Language-Team: Portuguese\n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.1\n" + +#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)" +msgid "" +"English Term (Dear translator: This file will never be visible to the user!)" +msgstr "" +"Outro SCM em português:\n" +"http://svn.code.sf.net/p/tortoisesvn/code/trunk/Languages/pt/TortoiseUI.po e " +"\n" +"http://svn.code.sf.net/p/tortoisesvn/code/trunk/Languages/pt/TortoiseDoc.po\n" +" em html: https://tortoisesvn.net/docs/release/TortoiseSVN_pt/index.html\n" +"\n" +"https://translations.launchpad.net/tortoisehg (medíocre)" + +#. "" +msgid "amend" +msgstr "emendar" + +#. "" +msgid "annotate" +msgstr "anotar" + +#. "A 'branch' is an active line of development." +msgid "branch [noun]" +msgstr "ramo" + +#. "" +msgid "branch [verb]" +msgstr "criar ramo" + +#. "" +msgid "checkout [noun]" +msgstr "extração" + +#. "The action of updating the working tree to a revision which was stored in the object database." +msgid "checkout [verb]" +msgstr "extrair" + +#. "" +msgid "clone [verb]" +msgstr "clonar" + +#. "A single point in the git history." +msgid "commit [noun]" +msgstr "commit" + +#. "The action of storing a new snapshot of the project's state in the git history." +msgid "commit [verb]" +msgstr "submeter" + +#. "" +msgid "diff [noun]" +msgstr "diferenças" + +#. "" +msgid "diff [verb]" +msgstr "mostrar diferenças" + +#. "A fast-forward is a special type of merge where you have a revision and you are merging another branch's changes that happen to be a descendant of what you have." +msgid "fast forward merge" +msgstr "integração por avanço rápido" + +#. "Fetching a branch means to get the branch's head from a remote repository, to find out which objects are missing from the local object database, and to get them, too." +msgid "fetch" +msgstr "obter" + +#. "One context of consecutive lines in a whole patch, which consists of many such hunks" +msgid "hunk" +msgstr "excerto" + +#. "A collection of files. The index is a stored version of your working tree." +msgid "index (in git-gui: staging area)" +msgstr "índice" + +#. "A successful merge results in the creation of a new commit representing the result of the merge." +msgid "merge [noun]" +msgstr "integração" + +#. "To bring the contents of another branch into the current branch." +msgid "merge [verb]" +msgstr "integrar" + +#. "" +msgid "message" +msgstr "mensagem" + +#. "Deletes all stale tracking branches under . These stale branches have already been removed from the remote repository referenced by , but are still locally available in 'remotes/'." +msgid "prune" +msgstr "podar" + +#. "Pulling a branch means to fetch it and merge it." +msgid "pull" +msgstr "puxar" + +#. "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)" +msgid "push" +msgstr "publicar" + +#. "" +msgid "redo" +msgstr "refazer" + +#. "An other repository ('remote'). One might have a set of remotes whose branches one tracks." +msgid "remote" +msgstr "remoto" + +#. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)" +msgid "repository" +msgstr "repositório" + +#. "" +msgid "reset" +msgstr "repor" + +#. "" +msgid "revert" +msgstr "reverter" + +#. "A particular state of files and directories which was stored in the object database." +msgid "revision" +msgstr "revisão" + +#. "" +msgid "sign off" +msgstr "assinar por baixo" + +#. "" +msgid "staging area" +msgstr "área de estágio" + +#. "" +msgid "status" +msgstr "estado" + +#. "A ref pointing to a tag or commit object" +msgid "tag [noun]" +msgstr "tag" + +#. "" +msgid "tag [verb]" +msgstr "criar tag" + +#. "A regular git branch that is used to follow changes from another repository." +msgid "tracking branch" +msgstr "ramo de monitorização" + +#. "" +msgid "undo" +msgstr "desfazer" + +#. "" +msgid "update" +msgstr "atualizar" + +#. "" +msgid "verify" +msgstr "verificar" + +#. "The tree of actual checked out files." +msgid "working copy, working tree" +msgstr "cópia de trabalho, árvore de trabalho" + +#. "a commit that succeeds the current one in git's graph of commits (not necessarily directly)" +msgid "ancestor" +msgstr "antecessor" + +#. "prematurely stop and abandon an operation" +msgid "abort" +msgstr "abortar" + +#. "a repository with only .git directory, without working directory" +msgid "bare repository" +msgstr "repositório nu" + +#. "a parent version of the current file" +msgid "base" +msgstr "base" + +#. "get the authors responsible for each line in a file" +msgid "blame" +msgstr "culpar" + +#. "to select and apply a single commit without merging" +msgid "cherry-pick" +msgstr "efetuar cherry-pick (escolher-a-dedo?, selecionar?)" + +#. "a commit that directly succeeds the current one in git's graph of commits" +msgid "child" +msgstr "filho" + +#. "clean the state of the git repository, often after manually stopped operation" +msgid "cleanup" +msgstr "limpar" + +#. "a message that gets attached with any commit" +msgid "commit message" +msgstr "mensagem de commit" + +#. "a commit that precedes the current one in git's graph of commits (not necessarily directly)" +msgid "descendant" +msgstr "descendente" + +#. "checkout of a revision rather than a some head" +msgid "detached checkout" +msgstr "extração destacada" + +#. "any merge strategy that works on a file by file basis" +msgid "file level merging" +msgstr "integração ao nível de ficheiros" + +#. "the last revision in a branch" +msgid "head" +msgstr "cabeça" + +#. "script that gets executed automatically on some event" +msgid "hook" +msgstr "gancho" + +#. "the first checkout during a clone operation" +msgid "initial checkout" +msgstr "extração inicial" + +#. "a branch that resides in the local git repository" +msgid "local branch" +msgstr "ramo local" + +#. "a Git object that is not part of any pack" +msgid "loose object" +msgstr "objeto solto" + +#. "a branch called by convention 'master' that exists in a newly created git repository" +msgid "master branch" +msgstr "ramo mestre" + +#. "a remote called by convention 'origin' that the current git repository has been cloned from" +msgid "origin" +msgstr "origem" + +#. "a file containing many git objects packed together" +msgid "pack [noun]" +msgstr "pacote" + +#. "a Git object part of some pack" +msgid "packed object" +msgstr "objeto compactado" + +#. "a commit that directly precedes the current one in git's graph of commits" +msgid "parent" +msgstr "pai" + +#. "the log file containing all states of the HEAD reference (in other words past pristine states of the working copy)" +msgid "reflog" +msgstr "reflog" + +#. "decide which changes from alternative versions of a file should persist in Git" +msgid "resolve (a conflict)" +msgstr "resolver (um conflito)" + +#. "abandon changes and go to pristine version" +msgid "revert changes" +msgstr "reverter alterações" + +#. "expression that signifies a revision in git" +msgid "revision expression" +msgstr "expressão de revisão" + +#. "add some content of files and directories to the staging area in preparation for a commit" +msgid "stage/unstage" +msgstr "preparar/retirar" + +#. "temporarily save changes in a stack without committing" +msgid "stash" +msgstr "empilhar" + +#. "file whose content is tracked/not tracked by git" +msgid "tracked/untracked" +msgstr "controlado/não controlado" diff --git a/git-gui/po/pt_pt.po b/git-gui/po/pt_pt.po new file mode 100644 index 0000000..0ef3c79 --- /dev/null +++ b/git-gui/po/pt_pt.po @@ -0,0 +1,2716 @@ +# Portuguese translations for git-gui package. +# Copyright (C) 2016 Shawn Pearce, et al. +# This file is distributed under the same license as the git package. +# Vasco Almeida , 2016. +msgid "" +msgstr "" +"Project-Id-Version: git-gui\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-05-06 09:36+0000\n" +"PO-Revision-Date: 2016-05-06 13:09+0000\n" +"Last-Translator: Vasco Almeida \n" +"Language-Team: Portuguese\n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.1\n" + +#: git-gui.sh:861 +#, tcl-format +msgid "Invalid font specified in %s:" +msgstr "Tipo de letra inválido especificado em %s:" + +#: git-gui.sh:915 +msgid "Main Font" +msgstr "Tipo de letra principal" + +#: git-gui.sh:916 +msgid "Diff/Console Font" +msgstr "Tipo de letra Diferenças/Consola" + +#: git-gui.sh:931 git-gui.sh:945 git-gui.sh:958 git-gui.sh:1048 +#: git-gui.sh:1067 git-gui.sh:3125 +msgid "git-gui: fatal error" +msgstr "git-gui: erro fatal" + +#: git-gui.sh:932 +msgid "Cannot find git in PATH." +msgstr "Não é possível encontrar o git em PATH." + +#: git-gui.sh:959 +msgid "Cannot parse Git version string:" +msgstr "Não é possível analisar a versão do Git:" + +#: git-gui.sh:984 +#, tcl-format +msgid "" +"Git version cannot be determined.\n" +"\n" +"%s claims it is version '%s'.\n" +"\n" +"%s requires at least Git 1.5.0 or later.\n" +"\n" +"Assume '%s' is version 1.5.0?\n" +msgstr "" +"A versão do Git não pôde ser determinada.\n" +"\n" +"%s alega que está na versão '%s'.\n" +"\n" +"%s requer pelo menos Git 1.5.0 ou mais recente.\n" +"\n" +"Assumir que '%s' está na versão 1.5.0?\n" + +#: git-gui.sh:1281 +msgid "Git directory not found:" +msgstr "Diretório Git não encontrado:" + +#: git-gui.sh:1315 +msgid "Cannot move to top of working directory:" +msgstr "Não é possível mover para o topo do diretório de trabalho:" + +#: git-gui.sh:1323 +msgid "Cannot use bare repository:" +msgstr "Não é possível usar repositório nu:" + +#: git-gui.sh:1331 +msgid "No working directory" +msgstr "Nenhum diretório de trabalho" + +#: git-gui.sh:1503 lib/checkout_op.tcl:306 +msgid "Refreshing file status..." +msgstr "A atualizar estado do ficheiro..." + +#: git-gui.sh:1563 +msgid "Scanning for modified files ..." +msgstr "A procurar por ficheiros modificados..." + +#: git-gui.sh:1639 +msgid "Calling prepare-commit-msg hook..." +msgstr "" +"A invocar gancho preparar-mensagem-de-commit (prepare-commit-msg hook)..." + +#: git-gui.sh:1656 +msgid "Commit declined by prepare-commit-msg hook." +msgstr "" +"Commit recusado pelo gancho preparar-mensagem-de-commit (prepare-commit-msg " +"hook)." + +#: git-gui.sh:1814 lib/browser.tcl:252 +msgid "Ready." +msgstr "Pronto." + +#: git-gui.sh:1978 +#, tcl-format +msgid "" +"Display limit (gui.maxfilesdisplayed = %s) reached, not showing all %s files." +msgstr "" +"Limite de visualização (gui.maxfilesdisplayed = %s) atingido, não são " +"mostrados todos os %s ficheiros." + +#: git-gui.sh:2101 +msgid "Unmodified" +msgstr "Não modificado" + +#: git-gui.sh:2103 +msgid "Modified, not staged" +msgstr "Modificado, não preparado" + +#: git-gui.sh:2104 git-gui.sh:2116 +msgid "Staged for commit" +msgstr "Preparado para commit" + +#: git-gui.sh:2105 git-gui.sh:2117 +msgid "Portions staged for commit" +msgstr "Porções preparadas para commit" + +#: git-gui.sh:2106 git-gui.sh:2118 +msgid "Staged for commit, missing" +msgstr "Preparado para commit, em falta" + +#: git-gui.sh:2108 +msgid "File type changed, not staged" +msgstr "Tipo de ficheiro modificado, não preparado" + +#: git-gui.sh:2109 git-gui.sh:2110 +msgid "File type changed, old type staged for commit" +msgstr "Tipo de ficheiro modificado, tipo antigo preparado para commit" + +#: git-gui.sh:2111 +msgid "File type changed, staged" +msgstr "Tipo de ficheiro modificado, preparado" + +#: git-gui.sh:2112 +msgid "File type change staged, modification not staged" +msgstr "Tipo de ficheiro modificado, modificação não preparada" + +#: git-gui.sh:2113 +msgid "File type change staged, file missing" +msgstr "Tipo de ficheiro modificado, ficheiro em falta" + +#: git-gui.sh:2115 +msgid "Untracked, not staged" +msgstr "Não controlado, não preparado" + +#: git-gui.sh:2120 +msgid "Missing" +msgstr "Em falta" + +#: git-gui.sh:2121 +msgid "Staged for removal" +msgstr "Preparado para remoção" + +#: git-gui.sh:2122 +msgid "Staged for removal, still present" +msgstr "Preparado para remoção, ainda presente" + +#: git-gui.sh:2124 git-gui.sh:2125 git-gui.sh:2126 git-gui.sh:2127 +#: git-gui.sh:2128 git-gui.sh:2129 +msgid "Requires merge resolution" +msgstr "Requer resolução de integração" + +#: git-gui.sh:2164 +msgid "Starting gitk... please wait..." +msgstr "A iniciar gitk... aguarde..." + +#: git-gui.sh:2176 +msgid "Couldn't find gitk in PATH" +msgstr "Não foi possível encontrar gitk em PATH" + +#: git-gui.sh:2235 +msgid "Couldn't find git gui in PATH" +msgstr "Não foi possível encontrar git gui em PATH" + +#: git-gui.sh:2654 lib/choose_repository.tcl:41 +msgid "Repository" +msgstr "Repositório" + +#: git-gui.sh:2655 +msgid "Edit" +msgstr "Editar" + +#: git-gui.sh:2657 lib/choose_rev.tcl:567 +msgid "Branch" +msgstr "Ramo" + +#: git-gui.sh:2660 lib/choose_rev.tcl:554 +msgid "Commit@@noun" +msgstr "Commit" + +#: git-gui.sh:2663 lib/merge.tcl:123 lib/merge.tcl:152 lib/merge.tcl:170 +msgid "Merge" +msgstr "Integrar" + +#: git-gui.sh:2664 lib/choose_rev.tcl:563 +msgid "Remote" +msgstr "Remoto" + +#: git-gui.sh:2667 +msgid "Tools" +msgstr "Ferramentas" + +#: git-gui.sh:2676 +msgid "Explore Working Copy" +msgstr "Explorar cópia de trabalho" + +#: git-gui.sh:2682 +msgid "Git Bash" +msgstr "Git Bash" + +#: git-gui.sh:2692 +msgid "Browse Current Branch's Files" +msgstr "Navegar pelos ficheiro do ramo atual" + +#: git-gui.sh:2696 +msgid "Browse Branch Files..." +msgstr "Navegar pelos ficheiros do ramo..." + +#: git-gui.sh:2701 +msgid "Visualize Current Branch's History" +msgstr "Visualizar histórico do ramo atual" + +#: git-gui.sh:2705 +msgid "Visualize All Branch History" +msgstr "Visualizar histórico de todos os ramos" + +#: git-gui.sh:2712 +#, tcl-format +msgid "Browse %s's Files" +msgstr "Navegar pelos ficheiro de %s" + +#: git-gui.sh:2714 +#, tcl-format +msgid "Visualize %s's History" +msgstr "Visualizar histórico de %s" + +#: git-gui.sh:2719 lib/database.tcl:40 lib/database.tcl:66 +msgid "Database Statistics" +msgstr "Estatísticas da base de dados" + +#: git-gui.sh:2722 lib/database.tcl:33 +msgid "Compress Database" +msgstr "Comprimir base de dados" + +#: git-gui.sh:2725 +msgid "Verify Database" +msgstr "Verificar base de dados" + +#: git-gui.sh:2732 git-gui.sh:2736 git-gui.sh:2740 lib/shortcut.tcl:8 +#: lib/shortcut.tcl:40 lib/shortcut.tcl:72 +msgid "Create Desktop Icon" +msgstr "Criar ícone no ambiente de trabalho" + +#: git-gui.sh:2748 lib/choose_repository.tcl:193 lib/choose_repository.tcl:201 +msgid "Quit" +msgstr "Sair" + +#: git-gui.sh:2756 +msgid "Undo" +msgstr "Desfazer" + +#: git-gui.sh:2759 +msgid "Redo" +msgstr "Refazer" + +#: git-gui.sh:2763 git-gui.sh:3368 +msgid "Cut" +msgstr "Cortar" + +#: git-gui.sh:2766 git-gui.sh:3371 git-gui.sh:3445 git-gui.sh:3530 +#: lib/console.tcl:69 +msgid "Copy" +msgstr "Copiar" + +#: git-gui.sh:2769 git-gui.sh:3374 +msgid "Paste" +msgstr "Colar" + +#: git-gui.sh:2772 git-gui.sh:3377 lib/remote_branch_delete.tcl:39 +#: lib/branch_delete.tcl:28 +msgid "Delete" +msgstr "Eliminar" + +#: git-gui.sh:2776 git-gui.sh:3381 git-gui.sh:3534 lib/console.tcl:71 +msgid "Select All" +msgstr "Selecionar tudo" + +#: git-gui.sh:2785 +msgid "Create..." +msgstr "Criar..." + +#: git-gui.sh:2791 +msgid "Checkout..." +msgstr "Extrair..." + +#: git-gui.sh:2797 +msgid "Rename..." +msgstr "Mudar nome..." + +#: git-gui.sh:2802 +msgid "Delete..." +msgstr "Eliminar..." + +#: git-gui.sh:2807 +msgid "Reset..." +msgstr "Repor..." + +#: git-gui.sh:2817 +msgid "Done" +msgstr "Concluído" + +#: git-gui.sh:2819 +msgid "Commit@@verb" +msgstr "Submeter" + +#: git-gui.sh:2828 git-gui.sh:3309 +msgid "New Commit" +msgstr "Novo commit" + +#: git-gui.sh:2836 git-gui.sh:3316 +msgid "Amend Last Commit" +msgstr "Emendar último commit" + +#: git-gui.sh:2846 git-gui.sh:3270 lib/remote_branch_delete.tcl:101 +msgid "Rescan" +msgstr "Reanalisar" + +#: git-gui.sh:2852 +msgid "Stage To Commit" +msgstr "Preparar para commit" + +#: git-gui.sh:2858 +msgid "Stage Changed Files To Commit" +msgstr "Preparar ficheiros modificados para commit" + +#: git-gui.sh:2864 +msgid "Unstage From Commit" +msgstr "Retirar do commit" + +#: git-gui.sh:2870 lib/index.tcl:442 +msgid "Revert Changes" +msgstr "Reverter alterações" + +#: git-gui.sh:2878 git-gui.sh:3581 git-gui.sh:3612 +msgid "Show Less Context" +msgstr "Mostrar menos contexto" + +#: git-gui.sh:2882 git-gui.sh:3585 git-gui.sh:3616 +msgid "Show More Context" +msgstr "Mostrar mais contexto" + +#: git-gui.sh:2889 git-gui.sh:3283 git-gui.sh:3392 +msgid "Sign Off" +msgstr "Assinar por baixo" + +#: git-gui.sh:2905 +msgid "Local Merge..." +msgstr "Integração local..." + +#: git-gui.sh:2910 +msgid "Abort Merge..." +msgstr "Abortar integração..." + +#: git-gui.sh:2922 git-gui.sh:2950 +msgid "Add..." +msgstr "Adicionar..." + +#: git-gui.sh:2926 +msgid "Push..." +msgstr "Publicar..." + +#: git-gui.sh:2930 +msgid "Delete Branch..." +msgstr "Eliminar ramo..." + +#: git-gui.sh:2940 git-gui.sh:3563 +msgid "Options..." +msgstr "Opções..." + +#: git-gui.sh:2951 +msgid "Remove..." +msgstr "Remover..." + +#: git-gui.sh:2960 lib/choose_repository.tcl:55 +msgid "Help" +msgstr "Ajuda" + +#: git-gui.sh:2964 git-gui.sh:2968 lib/choose_repository.tcl:49 +#: lib/choose_repository.tcl:58 lib/about.tcl:14 +#, tcl-format +msgid "About %s" +msgstr "Sobre %s" + +#: git-gui.sh:2992 +msgid "Online Documentation" +msgstr "Documentação online" + +#: git-gui.sh:2995 lib/choose_repository.tcl:52 lib/choose_repository.tcl:61 +msgid "Show SSH Key" +msgstr "Mostrar chave SSH" + +#: git-gui.sh:3014 git-gui.sh:3146 +msgid "Usage" +msgstr "Utilização" + +#: git-gui.sh:3095 lib/blame.tcl:573 +msgid "Error" +msgstr "Erro" + +#: git-gui.sh:3126 +#, tcl-format +msgid "fatal: cannot stat path %s: No such file or directory" +msgstr "" +"fatal: não é possível obter estado do caminho %s: Ficheiro ou diretório " +"inexistente" + +#: git-gui.sh:3159 +msgid "Current Branch:" +msgstr "Ramo atual:" + +#: git-gui.sh:3185 +msgid "Staged Changes (Will Commit)" +msgstr "Alterações preparadas (para commit)" + +#: git-gui.sh:3205 +msgid "Unstaged Changes" +msgstr "Alterações não preparadas" + +#: git-gui.sh:3276 +msgid "Stage Changed" +msgstr "Preparar modificados" + +#: git-gui.sh:3295 lib/transport.tcl:137 lib/transport.tcl:229 +msgid "Push" +msgstr "Publicar" + +#: git-gui.sh:3330 +msgid "Initial Commit Message:" +msgstr "Mensagem de commit inicial:" + +#: git-gui.sh:3331 +msgid "Amended Commit Message:" +msgstr "Mensagem de commit emendada:" + +#: git-gui.sh:3332 +msgid "Amended Initial Commit Message:" +msgstr "Mensagem de commit inicial emendada:" + +#: git-gui.sh:3333 +msgid "Amended Merge Commit Message:" +msgstr "Mensagem de commit de integração emendada:" + +#: git-gui.sh:3334 +msgid "Merge Commit Message:" +msgstr "Mensagem de commit de integração:" + +#: git-gui.sh:3335 +msgid "Commit Message:" +msgstr "Mensagem de commit:" + +#: git-gui.sh:3384 git-gui.sh:3538 lib/console.tcl:73 +msgid "Copy All" +msgstr "Copiar tudo" + +#: git-gui.sh:3408 lib/blame.tcl:105 +msgid "File:" +msgstr "Ficheiro:" + +#: git-gui.sh:3526 +msgid "Refresh" +msgstr "Atualizar" + +#: git-gui.sh:3547 +msgid "Decrease Font Size" +msgstr "Diminuir tamanho de letra" + +#: git-gui.sh:3551 +msgid "Increase Font Size" +msgstr "Aumentar tamanho de letra" + +#: git-gui.sh:3559 lib/blame.tcl:294 +msgid "Encoding" +msgstr "Codificação" + +#: git-gui.sh:3570 +msgid "Apply/Reverse Hunk" +msgstr "Aplicar/Reverter excerto" + +#: git-gui.sh:3575 +msgid "Apply/Reverse Line" +msgstr "Aplicar/Reverter linha" + +#: git-gui.sh:3594 +msgid "Run Merge Tool" +msgstr "Executar ferramenta de integração" + +#: git-gui.sh:3599 +msgid "Use Remote Version" +msgstr "Usar a versão remota" + +#: git-gui.sh:3603 +msgid "Use Local Version" +msgstr "Usar a versão local" + +#: git-gui.sh:3607 +msgid "Revert To Base" +msgstr "Reverter para a base" + +#: git-gui.sh:3625 +msgid "Visualize These Changes In The Submodule" +msgstr "Visualizar estas alterações no submódulo" + +#: git-gui.sh:3629 +msgid "Visualize Current Branch History In The Submodule" +msgstr "Visualizar histórico do ramo atual no submódulo" + +#: git-gui.sh:3633 +msgid "Visualize All Branch History In The Submodule" +msgstr "Visualizar histórico de todos os ramos no submódulo" + +#: git-gui.sh:3638 +msgid "Start git gui In The Submodule" +msgstr "Iniciar git gui no submódulo" + +#: git-gui.sh:3673 +msgid "Unstage Hunk From Commit" +msgstr "Retirar excerto do commit" + +#: git-gui.sh:3675 +msgid "Unstage Lines From Commit" +msgstr "Retirar linhas do commit" + +#: git-gui.sh:3677 +msgid "Unstage Line From Commit" +msgstr "Retirar linha do commit" + +#: git-gui.sh:3680 +msgid "Stage Hunk For Commit" +msgstr "Preparar excerto para commit" + +#: git-gui.sh:3682 +msgid "Stage Lines For Commit" +msgstr "Preparar linhas para commit" + +#: git-gui.sh:3684 +msgid "Stage Line For Commit" +msgstr "Preparar linha para commit" + +#: git-gui.sh:3709 +msgid "Initializing..." +msgstr "A inicializar..." + +#: git-gui.sh:3852 +#, tcl-format +msgid "" +"Possible environment issues exist.\n" +"\n" +"The following environment variables are probably\n" +"going to be ignored by any Git subprocess run\n" +"by %s:\n" +"\n" +msgstr "" +"Existem possíveis erros de ambiente.\n" +"\n" +"As seguintes variáveis de ambiente serão provavelmente\n" +"ignoradas pelos subprocessos do Git executados\n" +"por %s:\n" +"\n" + +#: git-gui.sh:3881 +msgid "" +"\n" +"This is due to a known issue with the\n" +"Tcl binary distributed by Cygwin." +msgstr "" +"\n" +"Devido a um problema conhecido com o\n" +"binário Tcl distribuído pelo Cygwin." + +#: git-gui.sh:3886 +#, tcl-format +msgid "" +"\n" +"\n" +"A good replacement for %s\n" +"is placing values for the user.name and\n" +"user.email settings into your personal\n" +"~/.gitconfig file.\n" +msgstr "" +"\n" +"\n" +"Um bom substituto para %s\n" +"é colocar valores das definições user.name e\n" +"user.email no ficheiro pessoal ~/.gitconfig.\n" + +#: lib/line.tcl:17 +msgid "Goto Line:" +msgstr "Ir para a linha:" + +#: lib/line.tcl:23 +msgid "Go" +msgstr "Ir" + +#: lib/console.tcl:59 +msgid "Working... please wait..." +msgstr "A processar... aguarde..." + +#: lib/console.tcl:81 lib/checkout_op.tcl:146 lib/sshkey.tcl:55 +#: lib/database.tcl:30 +msgid "Close" +msgstr "Fechar" + +#: lib/console.tcl:186 +msgid "Success" +msgstr "Sucesso" + +#: lib/console.tcl:200 +msgid "Error: Command Failed" +msgstr "Erro: falha ao executar comando" + +#: lib/checkout_op.tcl:85 +#, tcl-format +msgid "Fetching %s from %s" +msgstr "A obter %s de %s" + +#: lib/checkout_op.tcl:133 +#, tcl-format +msgid "fatal: Cannot resolve %s" +msgstr "fatal: Não é possível resolver %s" + +#: lib/checkout_op.tcl:175 +#, tcl-format +msgid "Branch '%s' does not exist." +msgstr "O ramo '%s' não existe." + +#: lib/checkout_op.tcl:194 +#, tcl-format +msgid "Failed to configure simplified git-pull for '%s'." +msgstr "Falha ao configurar git-pull simplificado de '%s'." + +#: lib/checkout_op.tcl:202 lib/branch_rename.tcl:102 +#, tcl-format +msgid "Branch '%s' already exists." +msgstr "O ramo '%s' já existe." + +#: lib/checkout_op.tcl:229 +#, tcl-format +msgid "" +"Branch '%s' already exists.\n" +"\n" +"It cannot fast-forward to %s.\n" +"A merge is required." +msgstr "" +"O ramo '%s' já existe.\n" +"\n" +"Não pode ser avançado rapidamente para %s.\n" +"Integração necessária." + +#: lib/checkout_op.tcl:243 +#, tcl-format +msgid "Merge strategy '%s' not supported." +msgstr "A estratégia de integração '%s' não é suportada." + +#: lib/checkout_op.tcl:262 +#, tcl-format +msgid "Failed to update '%s'." +msgstr "Falha ao atualizar '%s'." + +#: lib/checkout_op.tcl:274 +msgid "Staging area (index) is already locked." +msgstr "A área de estágio (índice) já está bloqueada." + +#: lib/checkout_op.tcl:289 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before the current branch can be changed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"O último estado analisado não corresponde ao estado do repositório.\n" +"\n" +"Outro programa Git modificou este repositório deste a última análise. Deve-" +"se reanalisar antes do ramo atual poder ser alterado.\n" +"\n" +"Irá-se reanalisar automaticamente agora.\n" + +#: lib/checkout_op.tcl:345 +#, tcl-format +msgid "Updating working directory to '%s'..." +msgstr "A atualizar o diretório de trabalho para '%s'..." + +#: lib/checkout_op.tcl:346 +msgid "files checked out" +msgstr "ficheiros extraídos" + +#: lib/checkout_op.tcl:376 +#, tcl-format +msgid "Aborted checkout of '%s' (file level merging is required)." +msgstr "" +"Extração de '%s' abortada (é necessário integrar ao nível de ficheiros)." + +#: lib/checkout_op.tcl:377 +msgid "File level merge required." +msgstr "Integração ao nível de ficheiros necessária." + +#: lib/checkout_op.tcl:381 +#, tcl-format +msgid "Staying on branch '%s'." +msgstr "Permanecer no ramo '%s'." + +#: lib/checkout_op.tcl:452 +msgid "" +"You are no longer on a local branch.\n" +"\n" +"If you wanted to be on a branch, create one now starting from 'This Detached " +"Checkout'." +msgstr "" +"Já não se encontra num ramo local.\n" +"\n" +"Se queria estar sobre um ramo, crie um a partir de 'Esta extração destacada'." + +#: lib/checkout_op.tcl:503 lib/checkout_op.tcl:507 +#, tcl-format +msgid "Checked out '%s'." +msgstr "'%s' extraído." + +#: lib/checkout_op.tcl:535 +#, tcl-format +msgid "Resetting '%s' to '%s' will lose the following commits:" +msgstr "Ao repor '%s' para '%s' perderá os seguintes commits:" + +#: lib/checkout_op.tcl:557 +msgid "Recovering lost commits may not be easy." +msgstr "Recuperar commits perdidos pode não ser fácil." + +#: lib/checkout_op.tcl:562 +#, tcl-format +msgid "Reset '%s'?" +msgstr "Repor '%s'?" + +#: lib/checkout_op.tcl:567 lib/tools_dlg.tcl:336 lib/merge.tcl:166 +msgid "Visualize" +msgstr "Visualizar" + +#: lib/checkout_op.tcl:571 lib/branch_create.tcl:85 +msgid "Reset" +msgstr "Repor" + +#: lib/checkout_op.tcl:579 lib/transport.tcl:141 lib/remote_add.tcl:34 +#: lib/browser.tcl:292 lib/branch_checkout.tcl:30 lib/choose_font.tcl:45 +#: lib/option.tcl:127 lib/tools_dlg.tcl:41 lib/tools_dlg.tcl:202 +#: lib/tools_dlg.tcl:345 lib/branch_rename.tcl:32 +#: lib/remote_branch_delete.tcl:43 lib/branch_create.tcl:37 +#: lib/branch_delete.tcl:34 lib/merge.tcl:174 +msgid "Cancel" +msgstr "Cancelar" + +#: lib/checkout_op.tcl:635 +#, tcl-format +msgid "" +"Failed to set current branch.\n" +"\n" +"This working directory is only partially switched. We successfully updated " +"your files, but failed to update an internal Git file.\n" +"\n" +"This should not have occurred. %s will now close and give up." +msgstr "" +"Falha ao definir ramo atual.\n" +"\n" +"Apenas se mudou o diretório de trabalho parcialmente. Os ficheiros foram " +"atualizados com sucesso, mas não foi possível atualizar o ficheiro Git " +"interno.\n" +"\n" +"Não devia ter ocorrido. %s irá terminar e desistir." + +#: lib/transport.tcl:6 lib/remote_add.tcl:132 +#, tcl-format +msgid "fetch %s" +msgstr "obter %s" + +#: lib/transport.tcl:7 +#, tcl-format +msgid "Fetching new changes from %s" +msgstr "Obter novas alterações de %s" + +#: lib/transport.tcl:18 +#, tcl-format +msgid "remote prune %s" +msgstr "poda remota de %s" + +#: lib/transport.tcl:19 +#, tcl-format +msgid "Pruning tracking branches deleted from %s" +msgstr "A podar ramos de monitorização eliminados de %s" + +#: lib/transport.tcl:25 +msgid "fetch all remotes" +msgstr "obter de todos os remotos" + +#: lib/transport.tcl:26 +msgid "Fetching new changes from all remotes" +msgstr "A obter novas alterações de todos os remotos" + +#: lib/transport.tcl:40 +msgid "remote prune all remotes" +msgstr "poda remota de todos os remotos" + +#: lib/transport.tcl:41 +msgid "Pruning tracking branches deleted from all remotes" +msgstr "A podar ramos de monitorização eliminados de todos os remotos" + +#: lib/transport.tcl:54 lib/transport.tcl:92 lib/transport.tcl:110 +#: lib/remote_add.tcl:162 +#, tcl-format +msgid "push %s" +msgstr "publicar %s" + +#: lib/transport.tcl:55 +#, tcl-format +msgid "Pushing changes to %s" +msgstr "A publicar alterações em %s" + +#: lib/transport.tcl:93 +#, tcl-format +msgid "Mirroring to %s" +msgstr "A espelhar em %s" + +#: lib/transport.tcl:111 +#, tcl-format +msgid "Pushing %s %s to %s" +msgstr "A publicar %s %s em %s" + +#: lib/transport.tcl:132 +msgid "Push Branches" +msgstr "Publicar ramos" + +#: lib/transport.tcl:147 +msgid "Source Branches" +msgstr "Ramos de origem" + +#: lib/transport.tcl:162 +msgid "Destination Repository" +msgstr "Repositório de destino" + +#: lib/transport.tcl:165 lib/remote_branch_delete.tcl:51 +msgid "Remote:" +msgstr "Remoto:" + +#: lib/transport.tcl:187 lib/remote_branch_delete.tcl:72 +msgid "Arbitrary Location:" +msgstr "Localização arbitrária:" + +#: lib/transport.tcl:205 +msgid "Transfer Options" +msgstr "Opções de transferência" + +#: lib/transport.tcl:207 +msgid "Force overwrite existing branch (may discard changes)" +msgstr "Forçar substituição de ramos existente (pode descartar alterações)" + +#: lib/transport.tcl:211 +msgid "Use thin pack (for slow network connections)" +msgstr "Usar pacote fino (para conexões de rede lentas)" + +#: lib/transport.tcl:215 +msgid "Include tags" +msgstr "Incluir tags" + +#: lib/remote_add.tcl:20 +msgid "Add Remote" +msgstr "Adicionar remoto" + +#: lib/remote_add.tcl:25 +msgid "Add New Remote" +msgstr "Adicionar novo remoto" + +#: lib/remote_add.tcl:30 lib/tools_dlg.tcl:37 +msgid "Add" +msgstr "Adicionar" + +#: lib/remote_add.tcl:39 +msgid "Remote Details" +msgstr "Detalhes do remoto" + +#: lib/remote_add.tcl:41 lib/tools_dlg.tcl:51 lib/branch_create.tcl:44 +msgid "Name:" +msgstr "Nome:" + +#: lib/remote_add.tcl:50 +msgid "Location:" +msgstr "Localização:" + +#: lib/remote_add.tcl:60 +msgid "Further Action" +msgstr "Ação adicional" + +#: lib/remote_add.tcl:63 +msgid "Fetch Immediately" +msgstr "Obter imediatamente" + +#: lib/remote_add.tcl:69 +msgid "Initialize Remote Repository and Push" +msgstr "Inicializar repositório remoto e publicar" + +#: lib/remote_add.tcl:75 +msgid "Do Nothing Else Now" +msgstr "Não fazer mais nada agora" + +#: lib/remote_add.tcl:100 +msgid "Please supply a remote name." +msgstr "Forneça um nome para o remoto." + +#: lib/remote_add.tcl:113 +#, tcl-format +msgid "'%s' is not an acceptable remote name." +msgstr "'%s' não pode ser aceite como nome de remoto." + +#: lib/remote_add.tcl:124 +#, tcl-format +msgid "Failed to add remote '%s' of location '%s'." +msgstr "Falha ao adicionar remoto '%s' localizado em '%s'." + +#: lib/remote_add.tcl:133 +#, tcl-format +msgid "Fetching the %s" +msgstr "A obter de %s" + +#: lib/remote_add.tcl:156 +#, tcl-format +msgid "Do not know how to initialize repository at location '%s'." +msgstr "Não se sabe como inicializar o repositório localizado em '%s'." + +#: lib/remote_add.tcl:163 +#, tcl-format +msgid "Setting up the %s (at %s)" +msgstr "A configurar %s (em %s)" + +#: lib/browser.tcl:17 +msgid "Starting..." +msgstr "A iniciar..." + +#: lib/browser.tcl:27 +msgid "File Browser" +msgstr "Navegador de ficheiros" + +#: lib/browser.tcl:132 lib/browser.tcl:149 +#, tcl-format +msgid "Loading %s..." +msgstr "A carregar %s..." + +#: lib/browser.tcl:193 +msgid "[Up To Parent]" +msgstr "[Subir]" + +#: lib/browser.tcl:275 lib/browser.tcl:282 +msgid "Browse Branch Files" +msgstr "Navegar pelos ficheiros do ramo" + +#: lib/browser.tcl:288 lib/choose_repository.tcl:422 +#: lib/choose_repository.tcl:509 lib/choose_repository.tcl:518 +#: lib/choose_repository.tcl:1074 +msgid "Browse" +msgstr "Navegar" + +#: lib/browser.tcl:297 lib/branch_checkout.tcl:35 lib/tools_dlg.tcl:321 +msgid "Revision" +msgstr "Revisão" + +#: lib/tools.tcl:75 +#, tcl-format +msgid "Running %s requires a selected file." +msgstr "Deve selecionar um ficheiro para executar %s." + +#: lib/tools.tcl:91 +#, tcl-format +msgid "Are you sure you want to run %1$s on file \"%2$s\"?" +msgstr "Tem a certeza que pretende executar %1$s sobre o ficheiro \"%2$s\"?" + +#: lib/tools.tcl:95 +#, tcl-format +msgid "Are you sure you want to run %s?" +msgstr "Tem a certeza que pretende executar %s?" + +#: lib/tools.tcl:116 +#, tcl-format +msgid "Tool: %s" +msgstr "Ferramenta: %s" + +#: lib/tools.tcl:117 +#, tcl-format +msgid "Running: %s" +msgstr "A executar: %s" + +#: lib/tools.tcl:155 +#, tcl-format +msgid "Tool completed successfully: %s" +msgstr "A ferramenta concluí com sucesso: %s" + +#: lib/tools.tcl:157 +#, tcl-format +msgid "Tool failed: %s" +msgstr "A ferramenta falhou: %s" + +#: lib/branch_checkout.tcl:16 lib/branch_checkout.tcl:21 +msgid "Checkout Branch" +msgstr "Extrair ramo" + +#: lib/branch_checkout.tcl:26 +msgid "Checkout" +msgstr "Extrair" + +#: lib/branch_checkout.tcl:39 lib/option.tcl:310 lib/branch_create.tcl:69 +msgid "Options" +msgstr "Opções" + +#: lib/branch_checkout.tcl:42 lib/branch_create.tcl:92 +msgid "Fetch Tracking Branch" +msgstr "Obter ramo de monitorização" + +#: lib/branch_checkout.tcl:47 +msgid "Detach From Local Branch" +msgstr "Destacar do ramo local" + +#: lib/spellcheck.tcl:57 +msgid "Unsupported spell checker" +msgstr "Corretor ortográfico não suportado" + +#: lib/spellcheck.tcl:65 +msgid "Spell checking is unavailable" +msgstr "Correção ortográfica indisponível" + +#: lib/spellcheck.tcl:68 +msgid "Invalid spell checking configuration" +msgstr "Configuração inválida do corretor ortográfico" + +#: lib/spellcheck.tcl:70 +#, tcl-format +msgid "Reverting dictionary to %s." +msgstr "A reverter dicionário para %s." + +#: lib/spellcheck.tcl:73 +msgid "Spell checker silently failed on startup" +msgstr "O corretor ortográfico falhou silenciosamente ao iniciar" + +#: lib/spellcheck.tcl:80 +msgid "Unrecognized spell checker" +msgstr "Corretor ortográfico não reconhecido" + +#: lib/spellcheck.tcl:186 +msgid "No Suggestions" +msgstr "Sem sugestões" + +#: lib/spellcheck.tcl:388 +msgid "Unexpected EOF from spell checker" +msgstr "EOF (fim de ficheiro) inesperado do corretor ortográfico" + +#: lib/spellcheck.tcl:392 +msgid "Spell Checker Failed" +msgstr "Corretor ortográfico falhou" + +#: lib/status_bar.tcl:87 +#, tcl-format +msgid "%s ... %*i of %*i %s (%3i%%)" +msgstr "%s ... %*i de %*i %s (%3i%%)" + +#: lib/diff.tcl:77 +#, tcl-format +msgid "" +"No differences detected.\n" +"\n" +"%s has no changes.\n" +"\n" +"The modification date of this file was updated by another application, but " +"the content within the file was not changed.\n" +"\n" +"A rescan will be automatically started to find other files which may have " +"the same state." +msgstr "" +"Nenhum diferença detetada.\n" +"\n" +"%s não tem alterações.\n" +"\n" +"A data de modificação deste ficheiro foi atualizada por outra aplicação, mas " +"o conteúdo no interior do ficheiro não foi alterado.\n" +"\n" +"Irá-se reanalisar automaticamente para encontrar outros ficheiros que " +"estejam no mesmo estado." + +#: lib/diff.tcl:117 +#, tcl-format +msgid "Loading diff of %s..." +msgstr "A carregar diferenças de %s..." + +#: lib/diff.tcl:140 +msgid "" +"LOCAL: deleted\n" +"REMOTE:\n" +msgstr "" +"LOCAL: eliminado\n" +"REMOTO:\n" + +#: lib/diff.tcl:145 +msgid "" +"REMOTE: deleted\n" +"LOCAL:\n" +msgstr "" +"REMOTO: eliminado\n" +"LOCAL:\n" + +#: lib/diff.tcl:152 +msgid "LOCAL:\n" +msgstr "LOCAL:\n" + +#: lib/diff.tcl:155 +msgid "REMOTE:\n" +msgstr "REMOTO:\n" + +#: lib/diff.tcl:217 lib/diff.tcl:355 +#, tcl-format +msgid "Unable to display %s" +msgstr "Não é possível mostrar %s" + +#: lib/diff.tcl:218 +msgid "Error loading file:" +msgstr "Erro ao carregar ficheiro:" + +#: lib/diff.tcl:225 +msgid "Git Repository (subproject)" +msgstr "Repositório Git (subprojeto)" + +#: lib/diff.tcl:237 +msgid "* Binary file (not showing content)." +msgstr "* Ficheiro binário (conteúdo não exibido)." + +#: lib/diff.tcl:242 +#, tcl-format +msgid "" +"* Untracked file is %d bytes.\n" +"* Showing only first %d bytes.\n" +msgstr "" +"* O ficheiro não controlado tem %d bytes.\n" +"* Exibido apenas os primeiros %d bytes.\n" + +#: lib/diff.tcl:248 +#, tcl-format +msgid "" +"\n" +"* Untracked file clipped here by %s.\n" +"* To see the entire file, use an external editor.\n" +msgstr "" +"\n" +"* Ficheiro não controlado recortado aqui por %s.\n" +"* Para ver o ficheiro inteiro, use um editor externo.\n" + +#: lib/diff.tcl:356 lib/blame.tcl:1128 +msgid "Error loading diff:" +msgstr "Erro ao carregar diferenças:" + +#: lib/diff.tcl:578 +msgid "Failed to unstage selected hunk." +msgstr "Falha ao retirar excerto selecionado do índice." + +#: lib/diff.tcl:585 +msgid "Failed to stage selected hunk." +msgstr "Falha ao preparar excerto selecionado." + +#: lib/diff.tcl:664 +msgid "Failed to unstage selected line." +msgstr "Falha ao retirar linha selecionada do índice." + +#: lib/diff.tcl:672 +msgid "Failed to stage selected line." +msgstr "Falha ao preparar linha selecionada." + +#: lib/remote.tcl:200 +msgid "Push to" +msgstr "Publicar em" + +#: lib/remote.tcl:218 +msgid "Remove Remote" +msgstr "Remover remoto" + +#: lib/remote.tcl:223 +msgid "Prune from" +msgstr "Podar de" + +#: lib/remote.tcl:228 +msgid "Fetch from" +msgstr "Obter de" + +#: lib/choose_font.tcl:41 +msgid "Select" +msgstr "Selecionar" + +#: lib/choose_font.tcl:55 +msgid "Font Family" +msgstr "Família de tipo de letra" + +#: lib/choose_font.tcl:76 +msgid "Font Size" +msgstr "Tamanho de letra" + +#: lib/choose_font.tcl:93 +msgid "Font Example" +msgstr "Exemplo do tipo de letra" + +#: lib/choose_font.tcl:105 +msgid "" +"This is example text.\n" +"If you like this text, it can be your font." +msgstr "" +"Este texto é um exemplo.\n" +"Se gostar deste texto, pode defini-lo como tipo de letra." + +#: lib/option.tcl:11 +#, tcl-format +msgid "Invalid global encoding '%s'" +msgstr "Codificação global '%s' inválida" + +#: lib/option.tcl:19 +#, tcl-format +msgid "Invalid repo encoding '%s'" +msgstr "Codificação do repositório '%s' inválida" + +#: lib/option.tcl:119 +msgid "Restore Defaults" +msgstr "Restaurar predefinições" + +#: lib/option.tcl:123 +msgid "Save" +msgstr "Guardar" + +#: lib/option.tcl:133 +#, tcl-format +msgid "%s Repository" +msgstr "Repositório %s" + +#: lib/option.tcl:134 +msgid "Global (All Repositories)" +msgstr "Global (todos os repositórios)" + +#: lib/option.tcl:140 +msgid "User Name" +msgstr "Nome de utilizador" + +#: lib/option.tcl:141 +msgid "Email Address" +msgstr "Endereço de e-mail" + +#: lib/option.tcl:143 +msgid "Summarize Merge Commits" +msgstr "Resumir commits de integração" + +#: lib/option.tcl:144 +msgid "Merge Verbosity" +msgstr "Verbosidade de integração" + +#: lib/option.tcl:145 +msgid "Show Diffstat After Merge" +msgstr "Mostrar estatísticas de diferenças depois de integrar" + +#: lib/option.tcl:146 +msgid "Use Merge Tool" +msgstr "Usar ferramenta de integração" + +#: lib/option.tcl:148 +msgid "Trust File Modification Timestamps" +msgstr "Confiar na data de modificação dos ficheiros" + +#: lib/option.tcl:149 +msgid "Prune Tracking Branches During Fetch" +msgstr "Podar ramos de monitorização ao obter" + +#: lib/option.tcl:150 +msgid "Match Tracking Branches" +msgstr "Corresponder ramos de monitorização" + +#: lib/option.tcl:151 +msgid "Use Textconv For Diffs and Blames" +msgstr "Usar textconv para mostrar diferenças e culpar" + +#: lib/option.tcl:152 +msgid "Blame Copy Only On Changed Files" +msgstr "Detetar cópia apenas em ficheiros modificados" + +#: lib/option.tcl:153 +msgid "Maximum Length of Recent Repositories List" +msgstr "Comprimento máximo da lista de repositórios recentes" + +#: lib/option.tcl:154 +msgid "Minimum Letters To Blame Copy On" +msgstr "Número mínimo de letras para detetar cópia" + +#: lib/option.tcl:155 +msgid "Blame History Context Radius (days)" +msgstr "Raio de contexto histórico para culpar (dias)" + +#: lib/option.tcl:156 +msgid "Number of Diff Context Lines" +msgstr "Número de linhas de contexto ao mostrar diferenças" + +#: lib/option.tcl:157 +msgid "Additional Diff Parameters" +msgstr "Parâmetros de diff adicionais" + +#: lib/option.tcl:158 +msgid "Commit Message Text Width" +msgstr "Largura do texto da mensagem de commit" + +#: lib/option.tcl:159 +msgid "New Branch Name Template" +msgstr "Modelo para nome de novo ramo" + +#: lib/option.tcl:160 +msgid "Default File Contents Encoding" +msgstr "Codificação predefinida dos conteúdos de ficheiros" + +#: lib/option.tcl:161 +msgid "Warn before committing to a detached head" +msgstr "Avisar antes de submeter numa cabeça destacada" + +#: lib/option.tcl:162 +msgid "Staging of untracked files" +msgstr "Preparar ficheiros não controlados" + +#: lib/option.tcl:163 +msgid "Show untracked files" +msgstr "Mostrar ficheiros não controlados" + +#: lib/option.tcl:164 +msgid "Tab spacing" +msgstr "Espaçamento da tabulação" + +#: lib/option.tcl:210 +msgid "Change" +msgstr "Alterar" + +#: lib/option.tcl:254 +msgid "Spelling Dictionary:" +msgstr "Dicionário ortográfico:" + +#: lib/option.tcl:284 +msgid "Change Font" +msgstr "Alterar tipo de letra" + +#: lib/option.tcl:288 +#, tcl-format +msgid "Choose %s" +msgstr "Escolher %s" + +#: lib/option.tcl:294 +msgid "pt." +msgstr "pt." + +#: lib/option.tcl:308 +msgid "Preferences" +msgstr "Preferências" + +#: lib/option.tcl:345 +msgid "Failed to completely save options:" +msgstr "Falha ao guardar todas as opções:" + +#: lib/mergetool.tcl:8 +msgid "Force resolution to the base version?" +msgstr "Forçar resolução para a versão base?" + +#: lib/mergetool.tcl:9 +msgid "Force resolution to this branch?" +msgstr "Forçar resolução para este ramo?" + +#: lib/mergetool.tcl:10 +msgid "Force resolution to the other branch?" +msgstr "Forçar resolução para o outro ramo?" + +#: lib/mergetool.tcl:14 +#, tcl-format +msgid "" +"Note that the diff shows only conflicting changes.\n" +"\n" +"%s will be overwritten.\n" +"\n" +"This operation can be undone only by restarting the merge." +msgstr "" +"Note que as diferenças mostram apenas alterações em conflito.\n" +"\n" +"%s será substituído.\n" +"\n" +"Esta operação só pode ser anulada reiniciando a integração." + +#: lib/mergetool.tcl:45 +#, tcl-format +msgid "File %s seems to have unresolved conflicts, still stage?" +msgstr "" +"O ficheiro %s parece ter conflitos não resolvidos, prepará-lo mesmo assim?" + +#: lib/mergetool.tcl:60 +#, tcl-format +msgid "Adding resolution for %s" +msgstr "A adicionar resolução de %s" + +#: lib/mergetool.tcl:141 +msgid "Cannot resolve deletion or link conflicts using a tool" +msgstr "" +"Não é possível resolver conflitos de exclusão ou ligação usando uma " +"ferramenta" + +#: lib/mergetool.tcl:146 +msgid "Conflict file does not exist" +msgstr "O ficheiro em conflito não existe" + +#: lib/mergetool.tcl:246 +#, tcl-format +msgid "Not a GUI merge tool: '%s'" +msgstr "Não é uma ferramenta GUI de integração: '%s'" + +#: lib/mergetool.tcl:275 +#, tcl-format +msgid "Unsupported merge tool '%s'" +msgstr "Ferramenta de integração '%s' não suportada" + +#: lib/mergetool.tcl:310 +msgid "Merge tool is already running, terminate it?" +msgstr "A ferramenta de integração já está a executar, terminá-la?" + +#: lib/mergetool.tcl:330 +#, tcl-format +msgid "" +"Error retrieving versions:\n" +"%s" +msgstr "" +"Erro ao obter versões:\n" +"%s" + +#: lib/mergetool.tcl:350 +#, tcl-format +msgid "" +"Could not start the merge tool:\n" +"\n" +"%s" +msgstr "" +"Não foi possível iniciar a ferramenta de integração:\n" +"\n" +"%s" + +#: lib/mergetool.tcl:354 +msgid "Running merge tool..." +msgstr "A executar a ferramenta de integração..." + +#: lib/mergetool.tcl:382 lib/mergetool.tcl:390 +msgid "Merge tool failed." +msgstr "A ferramenta de integração falhou." + +#: lib/tools_dlg.tcl:22 +msgid "Add Tool" +msgstr "Adicionar ferramenta" + +#: lib/tools_dlg.tcl:28 +msgid "Add New Tool Command" +msgstr "Adicionar novo comando de ferramenta" + +#: lib/tools_dlg.tcl:34 +msgid "Add globally" +msgstr "Adicionar globalmente" + +#: lib/tools_dlg.tcl:46 +msgid "Tool Details" +msgstr "Detalhes da ferramenta" + +#: lib/tools_dlg.tcl:49 +msgid "Use '/' separators to create a submenu tree:" +msgstr "Use separadores '/' para criar uma árvore de submenus:" + +#: lib/tools_dlg.tcl:60 +msgid "Command:" +msgstr "Comando:" + +#: lib/tools_dlg.tcl:71 +msgid "Show a dialog before running" +msgstr "Mostrar um diálogo antes de executar" + +#: lib/tools_dlg.tcl:77 +msgid "Ask the user to select a revision (sets $REVISION)" +msgstr "Pedir ao utilizador para selecionar uma revisão (define $REVISION)" + +#: lib/tools_dlg.tcl:82 +msgid "Ask the user for additional arguments (sets $ARGS)" +msgstr "Pedir ao utilizador argumentos adicionais (define $ARGS)" + +#: lib/tools_dlg.tcl:89 +msgid "Don't show the command output window" +msgstr "Não mostrar a janela com a saída do comando" + +#: lib/tools_dlg.tcl:94 +msgid "Run only if a diff is selected ($FILENAME not empty)" +msgstr "Executar só se for selecionada um diferença ($FILENAME não vazio)" + +#: lib/tools_dlg.tcl:118 +msgid "Please supply a name for the tool." +msgstr "Forneça um nome para a ferramenta." + +#: lib/tools_dlg.tcl:126 +#, tcl-format +msgid "Tool '%s' already exists." +msgstr "A ferramenta '%s' já existe." + +#: lib/tools_dlg.tcl:148 +#, tcl-format +msgid "" +"Could not add tool:\n" +"%s" +msgstr "" +"Não foi possível adicionar ferramenta:\n" +"%s" + +#: lib/tools_dlg.tcl:187 +msgid "Remove Tool" +msgstr "Remover ferramenta" + +#: lib/tools_dlg.tcl:193 +msgid "Remove Tool Commands" +msgstr "Remover comandos de ferramenta" + +#: lib/tools_dlg.tcl:198 +msgid "Remove" +msgstr "Remover" + +#: lib/tools_dlg.tcl:231 +msgid "(Blue denotes repository-local tools)" +msgstr "(Azul denota ferramentas locais do repositório)" + +#: lib/tools_dlg.tcl:292 +#, tcl-format +msgid "Run Command: %s" +msgstr "Executar comando: %s" + +#: lib/tools_dlg.tcl:306 +msgid "Arguments" +msgstr "Argumentos" + +#: lib/tools_dlg.tcl:341 +msgid "OK" +msgstr "OK" + +#: lib/search.tcl:48 +msgid "Find:" +msgstr "Procurar:" + +#: lib/search.tcl:50 +msgid "Next" +msgstr "Seguinte" + +#: lib/search.tcl:51 +msgid "Prev" +msgstr "Anterior" + +#: lib/search.tcl:52 +msgid "RegExp" +msgstr "ExpReg" + +#: lib/search.tcl:54 +msgid "Case" +msgstr "Maiúsculas" + +#: lib/shortcut.tcl:21 lib/shortcut.tcl:62 +msgid "Cannot write shortcut:" +msgstr "Não é possível escrever atalho:" + +#: lib/shortcut.tcl:137 +msgid "Cannot write icon:" +msgstr "Não é possível escrever ícone:" + +#: lib/branch_rename.tcl:15 lib/branch_rename.tcl:23 +msgid "Rename Branch" +msgstr "Mudar nome de ramo" + +#: lib/branch_rename.tcl:28 +msgid "Rename" +msgstr "Mudar nome" + +#: lib/branch_rename.tcl:38 +msgid "Branch:" +msgstr "Ramo:" + +#: lib/branch_rename.tcl:46 +msgid "New Name:" +msgstr "Novo nome:" + +#: lib/branch_rename.tcl:81 +msgid "Please select a branch to rename." +msgstr "Selecione um ramo para mudar de nome." + +#: lib/branch_rename.tcl:92 lib/branch_create.tcl:154 +msgid "Please supply a branch name." +msgstr "Indique um nome para o ramo." + +#: lib/branch_rename.tcl:112 lib/branch_create.tcl:165 +#, tcl-format +msgid "'%s' is not an acceptable branch name." +msgstr "'%s' não pode ser aceite como nome de ramo." + +#: lib/branch_rename.tcl:123 +#, tcl-format +msgid "Failed to rename '%s'." +msgstr "Falha ao mudar o nome de '%s'." + +#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 +msgid "Delete Branch Remotely" +msgstr "Remover ramo remotamente" + +#: lib/remote_branch_delete.tcl:48 +msgid "From Repository" +msgstr "Do repositório" + +#: lib/remote_branch_delete.tcl:88 +msgid "Branches" +msgstr "Ramos" + +#: lib/remote_branch_delete.tcl:110 +msgid "Delete Only If" +msgstr "Eliminar só se" + +#: lib/remote_branch_delete.tcl:112 +msgid "Merged Into:" +msgstr "Integrar em:" + +#: lib/remote_branch_delete.tcl:120 lib/branch_delete.tcl:53 +msgid "Always (Do not perform merge checks)" +msgstr "Sempre (não realizar verificação de integração)" + +#: lib/remote_branch_delete.tcl:153 +msgid "A branch is required for 'Merged Into'." +msgstr "É necessário um ramo em 'Integrar em'." + +#: lib/remote_branch_delete.tcl:185 +#, tcl-format +msgid "" +"The following branches are not completely merged into %s:\n" +"\n" +" - %s" +msgstr "" +"Os seguintes ramos não foram completamente integrados em %s:\n" +"\n" +" - %s" + +#: lib/remote_branch_delete.tcl:190 +#, tcl-format +msgid "" +"One or more of the merge tests failed because you have not fetched the " +"necessary commits. Try fetching from %s first." +msgstr "" +"Um ou mais testes de integração falharam porque não obteve os commits " +"necessários. Tente primeiro obter de %s." + +#: lib/remote_branch_delete.tcl:208 +msgid "Please select one or more branches to delete." +msgstr "Selecione um ou mais ramos para eliminar." + +#: lib/remote_branch_delete.tcl:218 lib/branch_delete.tcl:115 +msgid "" +"Recovering deleted branches is difficult.\n" +"\n" +"Delete the selected branches?" +msgstr "" +"Recuperar ramos eliminados é difícil.\n" +"\n" +"Eliminar os ramos selecionado?" + +#: lib/remote_branch_delete.tcl:227 +#, tcl-format +msgid "Deleting branches from %s" +msgstr "A eliminar ramos de %s" + +#: lib/remote_branch_delete.tcl:300 +msgid "No repository selected." +msgstr "Nenhum repositório selecionado." + +#: lib/remote_branch_delete.tcl:305 +#, tcl-format +msgid "Scanning %s..." +msgstr "A analisar %s..." + +#: lib/choose_repository.tcl:33 +msgid "Git Gui" +msgstr "Git Gui" + +#: lib/choose_repository.tcl:92 lib/choose_repository.tcl:412 +msgid "Create New Repository" +msgstr "Criar novo repositório" + +#: lib/choose_repository.tcl:98 +msgid "New..." +msgstr "Novo..." + +#: lib/choose_repository.tcl:105 lib/choose_repository.tcl:496 +msgid "Clone Existing Repository" +msgstr "Clonar repositório existente" + +#: lib/choose_repository.tcl:116 +msgid "Clone..." +msgstr "Clonar..." + +#: lib/choose_repository.tcl:123 lib/choose_repository.tcl:1064 +msgid "Open Existing Repository" +msgstr "Abrir repositório existente" + +#: lib/choose_repository.tcl:129 +msgid "Open..." +msgstr "Abrir..." + +#: lib/choose_repository.tcl:142 +msgid "Recent Repositories" +msgstr "Repositórios recentes" + +#: lib/choose_repository.tcl:148 +msgid "Open Recent Repository:" +msgstr "Abrir repositório recente:" + +#: lib/choose_repository.tcl:316 lib/choose_repository.tcl:323 +#: lib/choose_repository.tcl:330 +#, tcl-format +msgid "Failed to create repository %s:" +msgstr "Falha ao criar o repositório %s:" + +#: lib/choose_repository.tcl:407 lib/branch_create.tcl:33 +msgid "Create" +msgstr "Criar" + +#: lib/choose_repository.tcl:417 +msgid "Directory:" +msgstr "Diretório:" + +#: lib/choose_repository.tcl:447 lib/choose_repository.tcl:573 +#: lib/choose_repository.tcl:1098 +msgid "Git Repository" +msgstr "Repositório Git" + +#: lib/choose_repository.tcl:472 +#, tcl-format +msgid "Directory %s already exists." +msgstr "O diretório %s já existe." + +#: lib/choose_repository.tcl:476 +#, tcl-format +msgid "File %s already exists." +msgstr "O ficheiro %s já existe." + +#: lib/choose_repository.tcl:491 +msgid "Clone" +msgstr "Clonar" + +#: lib/choose_repository.tcl:504 +msgid "Source Location:" +msgstr "Localização de origem:" + +#: lib/choose_repository.tcl:513 +msgid "Target Directory:" +msgstr "Diretório de destino:" + +#: lib/choose_repository.tcl:523 +msgid "Clone Type:" +msgstr "Tipo de clone:" + +#: lib/choose_repository.tcl:528 +msgid "Standard (Fast, Semi-Redundant, Hardlinks)" +msgstr "Padrão (rápido, semi-redundante, ligações fixas)" + +#: lib/choose_repository.tcl:533 +msgid "Full Copy (Slower, Redundant Backup)" +msgstr "Cópia Total (lento, cópia de segurança redundante)" + +#: lib/choose_repository.tcl:538 +msgid "Shared (Fastest, Not Recommended, No Backup)" +msgstr "Partilhado (mais rápido, não recomendado, sem cópia)" + +#: lib/choose_repository.tcl:545 +msgid "Recursively clone submodules too" +msgstr "Clonar recursivamente submódulos também" + +#: lib/choose_repository.tcl:579 lib/choose_repository.tcl:626 +#: lib/choose_repository.tcl:772 lib/choose_repository.tcl:842 +#: lib/choose_repository.tcl:1104 lib/choose_repository.tcl:1112 +#, tcl-format +msgid "Not a Git repository: %s" +msgstr "Não é um repositório Git: %s" + +#: lib/choose_repository.tcl:615 +msgid "Standard only available for local repository." +msgstr "Padrão só disponível em repositórios locais." + +#: lib/choose_repository.tcl:619 +msgid "Shared only available for local repository." +msgstr "Partilhado só disponível em repositórios locais." + +#: lib/choose_repository.tcl:640 +#, tcl-format +msgid "Location %s already exists." +msgstr "A localização %s já existe." + +#: lib/choose_repository.tcl:651 +msgid "Failed to configure origin" +msgstr "Falha ao configurar origem" + +#: lib/choose_repository.tcl:663 +msgid "Counting objects" +msgstr "A contar objetos" + +#: lib/choose_repository.tcl:664 +msgid "buckets" +msgstr "baldes" + +#: lib/choose_repository.tcl:688 +#, tcl-format +msgid "Unable to copy objects/info/alternates: %s" +msgstr "Não é possível copiar objects/info/alternates: %s" + +#: lib/choose_repository.tcl:724 +#, tcl-format +msgid "Nothing to clone from %s." +msgstr "Nada para clonar de %s." + +#: lib/choose_repository.tcl:726 lib/choose_repository.tcl:940 +#: lib/choose_repository.tcl:952 +msgid "The 'master' branch has not been initialized." +msgstr "O ramo 'master' não foi inicializado." + +#: lib/choose_repository.tcl:739 +msgid "Hardlinks are unavailable. Falling back to copying." +msgstr "Ligações fixas indisponíveis. A recorrer a cópia." + +#: lib/choose_repository.tcl:751 +#, tcl-format +msgid "Cloning from %s" +msgstr "A clonar de %s" + +#: lib/choose_repository.tcl:782 +msgid "Copying objects" +msgstr "A copiar objetos" + +#: lib/choose_repository.tcl:783 +msgid "KiB" +msgstr "KiB" + +#: lib/choose_repository.tcl:807 +#, tcl-format +msgid "Unable to copy object: %s" +msgstr "Não é possível copiar objeto: %s" + +#: lib/choose_repository.tcl:817 +msgid "Linking objects" +msgstr "A ligar objetos" + +#: lib/choose_repository.tcl:818 +msgid "objects" +msgstr "objetos" + +#: lib/choose_repository.tcl:826 +#, tcl-format +msgid "Unable to hardlink object: %s" +msgstr "Não é possível criar ligação fixa de objeto: %s" + +#: lib/choose_repository.tcl:881 +msgid "Cannot fetch branches and objects. See console output for details." +msgstr "" +"Não é possível obter ramos e objetos. Ver saída na consola para detalhes." + +#: lib/choose_repository.tcl:892 +msgid "Cannot fetch tags. See console output for details." +msgstr "Não é possível obter tags. Ver saída na consola para detalhes." + +#: lib/choose_repository.tcl:916 +msgid "Cannot determine HEAD. See console output for details." +msgstr "Não é possível determinar HEAD. Ver saída na consola para detalhes." + +#: lib/choose_repository.tcl:925 +#, tcl-format +msgid "Unable to cleanup %s" +msgstr "Não foi possível limpar %s" + +#: lib/choose_repository.tcl:931 +msgid "Clone failed." +msgstr "Falha ao clonar." + +#: lib/choose_repository.tcl:938 +msgid "No default branch obtained." +msgstr "Não foi obtido nenhum ramo predefinido." + +#: lib/choose_repository.tcl:949 +#, tcl-format +msgid "Cannot resolve %s as a commit." +msgstr "Não é possível resolver %s como um commit." + +#: lib/choose_repository.tcl:961 +msgid "Creating working directory" +msgstr "A criar diretório de trabalho" + +#: lib/choose_repository.tcl:962 lib/index.tcl:70 lib/index.tcl:136 +#: lib/index.tcl:207 +msgid "files" +msgstr "ficheiros" + +#: lib/choose_repository.tcl:981 +msgid "Cannot clone submodules." +msgstr "Não é possível clonar submódulos." + +#: lib/choose_repository.tcl:990 +msgid "Cloning submodules" +msgstr "A clonar submódulos" + +#: lib/choose_repository.tcl:1015 +msgid "Initial file checkout failed." +msgstr "Falha de extração inicial de ficheiro." + +#: lib/choose_repository.tcl:1059 +msgid "Open" +msgstr "Abrir" + +#: lib/choose_repository.tcl:1069 +msgid "Repository:" +msgstr "Repositório:" + +#: lib/choose_repository.tcl:1118 +#, tcl-format +msgid "Failed to open repository %s:" +msgstr "Falha ao abrir o repositório %s:" + +#: lib/about.tcl:26 +msgid "git-gui - a graphical user interface for Git." +msgstr "git-gui - uma interface gráfica do Git." + +#: lib/blame.tcl:73 +msgid "File Viewer" +msgstr "Visualizador de ficheiros" + +#: lib/blame.tcl:79 +msgid "Commit:" +msgstr "Commit:" + +#: lib/blame.tcl:280 +msgid "Copy Commit" +msgstr "Copiar commit" + +#: lib/blame.tcl:284 +msgid "Find Text..." +msgstr "Procurar texto..." + +#: lib/blame.tcl:288 +msgid "Goto Line..." +msgstr "Ir para a linha..." + +#: lib/blame.tcl:297 +msgid "Do Full Copy Detection" +msgstr "Efetuar deteção de cópia integral" + +#: lib/blame.tcl:301 +msgid "Show History Context" +msgstr "Mostrar contexto histórico" + +#: lib/blame.tcl:304 +msgid "Blame Parent Commit" +msgstr "Culpar commit pai" + +#: lib/blame.tcl:466 +#, tcl-format +msgid "Reading %s..." +msgstr "A ler %s..." + +#: lib/blame.tcl:594 +msgid "Loading copy/move tracking annotations..." +msgstr "A carregar anotações de cópia/movimento..." + +#: lib/blame.tcl:614 +msgid "lines annotated" +msgstr "linhas anotadas" + +#: lib/blame.tcl:806 +msgid "Loading original location annotations..." +msgstr "A carregar anotações da localização original..." + +#: lib/blame.tcl:809 +msgid "Annotation complete." +msgstr "Anotação concluída." + +#: lib/blame.tcl:839 +msgid "Busy" +msgstr "A processar" + +#: lib/blame.tcl:840 +msgid "Annotation process is already running." +msgstr "O processo de anotação já está em execução." + +#: lib/blame.tcl:879 +msgid "Running thorough copy detection..." +msgstr "A executar deteção de cópia integral..." + +#: lib/blame.tcl:947 +msgid "Loading annotation..." +msgstr "A carregar anotação..." + +#: lib/blame.tcl:1000 +msgid "Author:" +msgstr "Autor:" + +#: lib/blame.tcl:1004 +msgid "Committer:" +msgstr "Committer:" + +#: lib/blame.tcl:1009 +msgid "Original File:" +msgstr "Ficheiro original:" + +#: lib/blame.tcl:1057 +msgid "Cannot find HEAD commit:" +msgstr "Não é possível encontrar commit HEAD:" + +#: lib/blame.tcl:1112 +msgid "Cannot find parent commit:" +msgstr "Não é possível encontrar commit pai:" + +#: lib/blame.tcl:1127 +msgid "Unable to display parent" +msgstr "Não é possível mostrar pai" + +#: lib/blame.tcl:1269 +msgid "Originally By:" +msgstr "Originalmente por:" + +#: lib/blame.tcl:1275 +msgid "In File:" +msgstr "No ficheiro:" + +#: lib/blame.tcl:1280 +msgid "Copied Or Moved Here By:" +msgstr "Copiado ou Movido para aqui por:" + +#: lib/sshkey.tcl:31 +msgid "No keys found." +msgstr "Nenhum chave encontrada." + +#: lib/sshkey.tcl:34 +#, tcl-format +msgid "Found a public key in: %s" +msgstr "Chave pública encontrada em: %s" + +#: lib/sshkey.tcl:40 +msgid "Generate Key" +msgstr "Gerar chave" + +#: lib/sshkey.tcl:58 +msgid "Copy To Clipboard" +msgstr "Copiar para a área de transferência" + +#: lib/sshkey.tcl:72 +msgid "Your OpenSSH Public Key" +msgstr "A sua chave OpenSSH pública" + +#: lib/sshkey.tcl:80 +msgid "Generating..." +msgstr "A gerar..." + +#: lib/sshkey.tcl:86 +#, tcl-format +msgid "" +"Could not start ssh-keygen:\n" +"\n" +"%s" +msgstr "" +"Não foi possível iniciar ssh-keygen:\n" +"\n" +"%s" + +#: lib/sshkey.tcl:113 +msgid "Generation failed." +msgstr "Falha ao gerar." + +#: lib/sshkey.tcl:120 +msgid "Generation succeeded, but no keys found." +msgstr "Gerada com sucesso, mas não foi encontrada nenhum chave." + +#: lib/sshkey.tcl:123 +#, tcl-format +msgid "Your key is in: %s" +msgstr "A sua chave encontra-se em: %s" + +#: lib/branch_create.tcl:23 +msgid "Create Branch" +msgstr "Criar ramo" + +#: lib/branch_create.tcl:28 +msgid "Create New Branch" +msgstr "Cria novo ramo" + +#: lib/branch_create.tcl:42 +msgid "Branch Name" +msgstr "Nome do ramo" + +#: lib/branch_create.tcl:57 +msgid "Match Tracking Branch Name" +msgstr "Corresponder ao nome do ramo de monitorização" + +#: lib/branch_create.tcl:66 +msgid "Starting Revision" +msgstr "Revisão inicial" + +#: lib/branch_create.tcl:72 +msgid "Update Existing Branch:" +msgstr "Atualizar ramo existente:" + +#: lib/branch_create.tcl:75 +msgid "No" +msgstr "Não" + +#: lib/branch_create.tcl:80 +msgid "Fast Forward Only" +msgstr "Apenas avanço rápido (fast-forward)" + +#: lib/branch_create.tcl:97 +msgid "Checkout After Creation" +msgstr "Extrair depois de criar" + +#: lib/branch_create.tcl:132 +msgid "Please select a tracking branch." +msgstr "Selecione um ramo de monitorização." + +#: lib/branch_create.tcl:141 +#, tcl-format +msgid "Tracking branch %s is not a branch in the remote repository." +msgstr "O ramo de monitorização %s não é um ramo no repositório remoto." + +#: lib/commit.tcl:9 +msgid "" +"There is nothing to amend.\n" +"\n" +"You are about to create the initial commit. There is no commit before this " +"to amend.\n" +msgstr "" +"Não há nada para emendar.\n" +"\n" +"Está prestes a criar o commit inicial. Não há nenhum commit antes deste para " +"emendar.\n" + +#: lib/commit.tcl:18 +msgid "" +"Cannot amend while merging.\n" +"\n" +"You are currently in the middle of a merge that has not been fully " +"completed. You cannot amend the prior commit unless you first abort the " +"current merge activity.\n" +msgstr "" +"Não é possível emendar ao mesmo tempo que se integra.\n" +"\n" +"Há uma integração em curso que não foi concluída. Não pode emendar o commit " +"anterior a não ser que primeiro aborte a atividade da integração atual.\n" + +#: lib/commit.tcl:48 +msgid "Error loading commit data for amend:" +msgstr "Erro ao carregar dados do commit para emendar:" + +#: lib/commit.tcl:75 +msgid "Unable to obtain your identity:" +msgstr "Não é possível obter a sua identidade:" + +#: lib/commit.tcl:80 +msgid "Invalid GIT_COMMITTER_IDENT:" +msgstr "GIT_COMMITTER_IDENT inválido:" + +#: lib/commit.tcl:129 +#, tcl-format +msgid "warning: Tcl does not support encoding '%s'." +msgstr "aviso: Tcl não suporta a codificação '%s'." + +#: lib/commit.tcl:149 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before another commit can be created.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"O último estado analisado não corresponde ao estado do repositório.\n" +"\n" +"Outro programa Git modificou este repositório deste a última análise. Deve-" +"se reanalisar antes que se possa criar outro commit.\n" +"\n" +"Irá-se reanalisar automaticamente agora.\n" + +#: lib/commit.tcl:173 +#, tcl-format +msgid "" +"Unmerged files cannot be committed.\n" +"\n" +"File %s has merge conflicts. You must resolve them and stage the file " +"before committing.\n" +msgstr "" +"Não pode fazer commit de ficheiros não integrados.\n" +"\n" +"O ficheiro %s tem conflitos de integração. Deve resolvê-los e preparar o " +"ficheiro antes de submeter.\n" + +#: lib/commit.tcl:181 +#, tcl-format +msgid "" +"Unknown file state %s detected.\n" +"\n" +"File %s cannot be committed by this program.\n" +msgstr "" +"Detetado estado de ficheiro %s desconhecido.\n" +"\n" +"Este programa não pode submeter o ficheiro %s.\n" + +#: lib/commit.tcl:189 +msgid "" +"No changes to commit.\n" +"\n" +"You must stage at least 1 file before you can commit.\n" +msgstr "" +"Nenhum alteração para submeter.\n" +"\n" +"Deve preparar pelo menos 1 ficheiro antes de submeter.\n" + +#: lib/commit.tcl:204 +msgid "" +"Please supply a commit message.\n" +"\n" +"A good commit message has the following format:\n" +"\n" +"- First line: Describe in one sentence what you did.\n" +"- Second line: Blank\n" +"- Remaining lines: Describe why this change is good.\n" +msgstr "" +"Forneça uma mensagem de commit.\n" +"\n" +"Um boa mensagem de commit tem o seguinte formato:\n" +"\n" +"- Primeira linha: descreve numa frase o que fez.\n" +"- Segunda linha: em branco.\n" +"- Linhas restantes: descreve porque esta alteração é vantajosa.\n" + +#: lib/commit.tcl:235 +msgid "Calling pre-commit hook..." +msgstr "A invocar gancho de pré-commit (pre-commit hook)..." + +#: lib/commit.tcl:250 +msgid "Commit declined by pre-commit hook." +msgstr "Commit recusado pela retina de pré-commit (pre-commit hook)." + +#: lib/commit.tcl:269 +msgid "" +"You are about to commit on a detached head. This is a potentially dangerous " +"thing to do because if you switch to another branch you will lose your " +"changes and it can be difficult to retrieve them later from the reflog. You " +"should probably cancel this commit and create a new branch to continue.\n" +" \n" +" Do you really want to proceed with your Commit?" +msgstr "" +"Está prestes a submeter numa cabeça destacada. Fazê-lo é potencialmente " +"perigoso, porque, se mudar para outro ramo, perderá as suas alterações e " +"pode ser difícil recuperá-las do reflog posteriormente. Provavelmente deve " +"cancelar este commit e criar um novo ramo para continuar.\n" +"\n" +"Pretende mesmo continuar com o commit?" + +#: lib/commit.tcl:290 +msgid "Calling commit-msg hook..." +msgstr "A invocar gancho de mensagem-de-commit (commit-msg hook)..." + +#: lib/commit.tcl:305 +msgid "Commit declined by commit-msg hook." +msgstr "Commit recusado pelo gancho de mensagem-de-commit (commit-msg hook)." + +#: lib/commit.tcl:318 +msgid "Committing changes..." +msgstr "A submeter alterações..." + +#: lib/commit.tcl:334 +msgid "write-tree failed:" +msgstr "write-tree falhou:" + +#: lib/commit.tcl:335 lib/commit.tcl:379 lib/commit.tcl:400 +msgid "Commit failed." +msgstr "Falha ao submeter." + +#: lib/commit.tcl:352 +#, tcl-format +msgid "Commit %s appears to be corrupt" +msgstr "O commit %s parece estar corrompido" + +#: lib/commit.tcl:357 +msgid "" +"No changes to commit.\n" +"\n" +"No files were modified by this commit and it was not a merge commit.\n" +"\n" +"A rescan will be automatically started now.\n" +msgstr "" +"Não há alterações para submeter.\n" +"\n" +"Nenhum ficheiro foi modificado por este commit e não era um commit de " +"integração.\n" +"\n" +"Irá-se reanalisar agora automaticamente.\n" + +#: lib/commit.tcl:364 +msgid "No changes to commit." +msgstr "Não há alterações para submeter." + +#: lib/commit.tcl:378 +msgid "commit-tree failed:" +msgstr "commit-tree falhou:" + +#: lib/commit.tcl:399 +msgid "update-ref failed:" +msgstr "update-ref falhou:" + +#: lib/commit.tcl:492 +#, tcl-format +msgid "Created commit %s: %s" +msgstr "Commit %s criado: %s" + +#: lib/branch_delete.tcl:16 +msgid "Delete Branch" +msgstr "Eliminar ramo" + +#: lib/branch_delete.tcl:21 +msgid "Delete Local Branch" +msgstr "Eliminar ramo local" + +#: lib/branch_delete.tcl:39 +msgid "Local Branches" +msgstr "Ramos locais" + +#: lib/branch_delete.tcl:51 +msgid "Delete Only If Merged Into" +msgstr "Eliminar só se foi integrado" + +#: lib/branch_delete.tcl:103 +#, tcl-format +msgid "The following branches are not completely merged into %s:" +msgstr "Os seguintes ramos não foram completamente integrados em %s:" + +#: lib/branch_delete.tcl:141 +#, tcl-format +msgid "" +"Failed to delete branches:\n" +"%s" +msgstr "" +"Falha ao eliminar ramos:\n" +"%s" + +#: lib/index.tcl:6 +msgid "Unable to unlock the index." +msgstr "Não é possível desbloquear o índice." + +#: lib/index.tcl:17 +msgid "Index Error" +msgstr "Erro de Índice" + +#: lib/index.tcl:19 +msgid "" +"Updating the Git index failed. A rescan will be automatically started to " +"resynchronize git-gui." +msgstr "" +"Falha ao atualizar o índice do Git. Irá-se reanalisar automaticamente para " +"ressincronizar o git-gui." + +#: lib/index.tcl:30 +msgid "Continue" +msgstr "Continuar" + +#: lib/index.tcl:33 +msgid "Unlock Index" +msgstr "Desbloquear índice" + +#: lib/index.tcl:294 +msgid "Unstaging selected files from commit" +msgstr "A retirar ficheiros selecionados do commit" + +#: lib/index.tcl:298 +#, tcl-format +msgid "Unstaging %s from commit" +msgstr "A retirar %s do commit" + +#: lib/index.tcl:337 +msgid "Ready to commit." +msgstr "Pronto para submeter." + +#: lib/index.tcl:346 +msgid "Adding selected files" +msgstr "A adicionar ficheiros selecionados" + +#: lib/index.tcl:350 +#, tcl-format +msgid "Adding %s" +msgstr "A adicionar %s" + +#: lib/index.tcl:380 +#, tcl-format +msgid "Stage %d untracked files?" +msgstr "Preparar %d ficheiros não controlados?" + +#: lib/index.tcl:388 +msgid "Adding all changed files" +msgstr "A adicionar todos os ficheiros controlados" + +#: lib/index.tcl:428 +#, tcl-format +msgid "Revert changes in file %s?" +msgstr "Reverter alterações no ficheiro %s?" + +#: lib/index.tcl:430 +#, tcl-format +msgid "Revert changes in these %i files?" +msgstr "Reverter alterações nestes %i ficheiros?" + +#: lib/index.tcl:438 +msgid "Any unstaged changes will be permanently lost by the revert." +msgstr "" +"Qualquer alteração não preparada será permanentemente perdida ao reverter." + +#: lib/index.tcl:441 +msgid "Do Nothing" +msgstr "Não fazer nada" + +#: lib/index.tcl:459 +msgid "Reverting selected files" +msgstr "A reverter ficheiros selecionados" + +#: lib/index.tcl:463 +#, tcl-format +msgid "Reverting %s" +msgstr "A reverter %s" + +#: lib/encoding.tcl:443 +msgid "Default" +msgstr "Predefinição" + +#: lib/encoding.tcl:448 +#, tcl-format +msgid "System (%s)" +msgstr "Sistema (%s)" + +#: lib/encoding.tcl:459 lib/encoding.tcl:465 +msgid "Other" +msgstr "Outro" + +#: lib/date.tcl:25 +#, tcl-format +msgid "Invalid date from Git: %s" +msgstr "Data do Git inválida: %s" + +#: lib/choose_rev.tcl:52 +msgid "This Detached Checkout" +msgstr "Esta extração destacada" + +#: lib/choose_rev.tcl:60 +msgid "Revision Expression:" +msgstr "Expressão de revisão:" + +#: lib/choose_rev.tcl:72 +msgid "Local Branch" +msgstr "Ramo local" + +#: lib/choose_rev.tcl:77 +msgid "Tracking Branch" +msgstr "Ramo de monitorização" + +#: lib/choose_rev.tcl:82 lib/choose_rev.tcl:544 +msgid "Tag" +msgstr "Tag" + +#: lib/choose_rev.tcl:321 +#, tcl-format +msgid "Invalid revision: %s" +msgstr "Revisão inválida: %s" + +#: lib/choose_rev.tcl:342 +msgid "No revision selected." +msgstr "Nenhum revisão selecionada." + +#: lib/choose_rev.tcl:350 +msgid "Revision expression is empty." +msgstr "A expressão de revisão está vazia." + +#: lib/choose_rev.tcl:537 +msgid "Updated" +msgstr "Atualizado" + +#: lib/choose_rev.tcl:565 +msgid "URL" +msgstr "URL" + +#: lib/database.tcl:42 +msgid "Number of loose objects" +msgstr "Número de objetos soltos" + +#: lib/database.tcl:43 +msgid "Disk space used by loose objects" +msgstr "Espaço em disco usados por objetos soltos" + +#: lib/database.tcl:44 +msgid "Number of packed objects" +msgstr "Número de objetos compactados" + +#: lib/database.tcl:45 +msgid "Number of packs" +msgstr "Números de pacotes" + +#: lib/database.tcl:46 +msgid "Disk space used by packed objects" +msgstr "Espaço em disco usado por objetos compactados" + +#: lib/database.tcl:47 +msgid "Packed objects waiting for pruning" +msgstr "Objetos compactados à espera de poda" + +#: lib/database.tcl:48 +msgid "Garbage files" +msgstr "Ficheiros de lixo" + +#: lib/database.tcl:72 +msgid "Compressing the object database" +msgstr "A comprimir a base de dados de objetos" + +#: lib/database.tcl:83 +msgid "Verifying the object database with fsck-objects" +msgstr "A verificar a base de dados de objetos com fsck-objects" + +#: lib/database.tcl:107 +#, tcl-format +msgid "" +"This repository currently has approximately %i loose objects.\n" +"\n" +"To maintain optimal performance it is strongly recommended that you compress " +"the database.\n" +"\n" +"Compress the database now?" +msgstr "" +"Este repositório tem aproximadamente %i objetos soltos.\n" +"\n" +"Para manter o desempenho ótimo é veemente recomendado que comprima a base de " +"dados.\n" +"\n" +"Comprimir a base de dados agora?" + +#: lib/error.tcl:20 lib/error.tcl:116 +msgid "error" +msgstr "erro" + +#: lib/error.tcl:36 +msgid "warning" +msgstr "aviso" + +#: lib/error.tcl:96 +msgid "You must correct the above errors before committing." +msgstr "Deve corrigir os erros acima antes de submeter." + +#: lib/merge.tcl:13 +msgid "" +"Cannot merge while amending.\n" +"\n" +"You must finish amending this commit before starting any type of merge.\n" +msgstr "" +"Não possível integrar ao mesmo tempo que se emenda.\n" +"\n" +"Deve acabar de emendar este commit antes de iniciar qualquer tipo de " +"integração.\n" + +#: lib/merge.tcl:27 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before a merge can be performed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"O último estado analisado não corresponde ao estado do repositório.\n" +"\n" +"Outro programa Git modificou este repositório deste a última análise. Deve-" +"se reanalisar antes de se poder integrar.\n" +"\n" +"Irá-se reanalisar agora automaticamente.\n" + +#: lib/merge.tcl:45 +#, tcl-format +msgid "" +"You are in the middle of a conflicted merge.\n" +"\n" +"File %s has merge conflicts.\n" +"\n" +"You must resolve them, stage the file, and commit to complete the current " +"merge. Only then can you begin another merge.\n" +msgstr "" +"Integração com conflitos em curso.\n" +"\n" +"O ficheiro %s tem conflitos de integração.\n" +"\n" +"Deve resolvê-los, preparar o ficheiro e submeter para concluir a integração " +"atual. Só então pode iniciar outra integração.\n" + +#: lib/merge.tcl:55 +#, tcl-format +msgid "" +"You are in the middle of a change.\n" +"\n" +"File %s is modified.\n" +"\n" +"You should complete the current commit before starting a merge. Doing so " +"will help you abort a failed merge, should the need arise.\n" +msgstr "" +"Tem alterações presentes.\n" +"\n" +"O ficheiro %s foi modificado.\n" +"\n" +"Deve concluir o commit atual antes de iniciar uma integração. Assim, ajuda-o " +"a abortar uma integração falhada, caso necessário.\n" + +#: lib/merge.tcl:108 +#, tcl-format +msgid "%s of %s" +msgstr "%s de %s" + +#: lib/merge.tcl:122 +#, tcl-format +msgid "Merging %s and %s..." +msgstr "A integrar %s e %s..." + +#: lib/merge.tcl:133 +msgid "Merge completed successfully." +msgstr "Integração concluída com sucesso." + +#: lib/merge.tcl:135 +msgid "Merge failed. Conflict resolution is required." +msgstr "Integração falhada. É necessário resolver conflitos." + +#: lib/merge.tcl:160 +#, tcl-format +msgid "Merge Into %s" +msgstr "Integrar em %s" + +#: lib/merge.tcl:179 +msgid "Revision To Merge" +msgstr "Revisão a integrar" + +#: lib/merge.tcl:214 +msgid "" +"Cannot abort while amending.\n" +"\n" +"You must finish amending this commit.\n" +msgstr "" +"Não é possível abortar enquanto se emenda.\n" +"\n" +"Deve acabar de emendar este commit.\n" + +#: lib/merge.tcl:224 +msgid "" +"Abort merge?\n" +"\n" +"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with aborting the current merge?" +msgstr "" +"Abortar integração?\n" +"\n" +"Ao abortar a integração atual perderá *TODAS* as alteração que não foram " +"submetidas.\n" +"\n" +"Continuar a abortar a integração atual?" + +#: lib/merge.tcl:230 +msgid "" +"Reset changes?\n" +"\n" +"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with resetting the current changes?" +msgstr "" +"Repor alterações?\n" +"\n" +"Ao repor as alterações perderá *TODAS* as alterações não submetidas.\n" +"\n" +"Continuar a repor as alterações atuais?" + +#: lib/merge.tcl:241 +msgid "Aborting" +msgstr "A abortar" + +#: lib/merge.tcl:241 +msgid "files reset" +msgstr "ficheiros repostos" + +#: lib/merge.tcl:269 +msgid "Abort failed." +msgstr "Falha ao abortar." + +#: lib/merge.tcl:271 +msgid "Abort completed. Ready." +msgstr "Aborto concluído. Pronto." + +#~ msgid "Displaying only %s of %s files." +#~ msgstr "A mostrar apenas %s de %s ficheiros." + +#~ msgid "Case-Sensitive" +#~ msgstr "Distinguir Maiúsculas" diff --git a/git-gui/po/ru.po b/git-gui/po/ru.po index ca4343b..9f5305c 100644 --- a/git-gui/po/ru.po +++ b/git-gui/po/ru.po @@ -1,19 +1,22 @@ # Translation of git-gui to russian # Copyright (C) 2007 Shawn Pearce # This file is distributed under the same license as the git-gui package. -# Irina Riesen , 2007. -# +# Translators: +# Dimitriy Ryazantcev , 2015-2016 +# Irina Riesen , 2007 msgid "" msgstr "" -"Project-Id-Version: git-gui\n" +"Project-Id-Version: Git Russian Localization Project\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-01-26 15:47-0800\n" -"PO-Revision-Date: 2007-10-22 22:30-0200\n" -"Last-Translator: Alex Riesen \n" -"Language-Team: Russian Translation \n" +"PO-Revision-Date: 2016-06-30 12:39+0000\n" +"Last-Translator: Dimitriy Ryazantcev \n" +"Language-Team: Russian (http://www.transifex.com/djm00n/git-po-ru/language/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" #: git-gui.sh:41 git-gui.sh:793 git-gui.sh:807 git-gui.sh:820 git-gui.sh:903 #: git-gui.sh:922 @@ -51,14 +54,7 @@ msgid "" "%s requires at least Git 1.5.0 or later.\n" "\n" "Assume '%s' is version 1.5.0?\n" -msgstr "" -"Невозможно определить версию Git\n" -"\n" -"%s указывает на версию '%s'.\n" -"\n" -"для %s требуется версия Git, начиная с 1.5.0\n" -"\n" -"Принять '%s' как версию 1.5.0?\n" +msgstr "Невозможно определить версию Git\n\n%s указывает на версию «%s».\n\nдля %s требуется версия Git, начиная с 1.5.0\n\nПредположить, что «%s» и есть версия 1.5.0?\n" #: git-gui.sh:1128 msgid "Git directory not found:" @@ -78,20 +74,19 @@ msgstr "Отсутствует рабочий каталог" #: git-gui.sh:1334 lib/checkout_op.tcl:306 msgid "Refreshing file status..." -msgstr "Обновление информации о состоянии файлов..." +msgstr "Обновление информации о состоянии файлов…" #: git-gui.sh:1390 msgid "Scanning for modified files ..." -msgstr "Поиск измененных файлов..." +msgstr "Поиск измененных файлов…" #: git-gui.sh:1454 msgid "Calling prepare-commit-msg hook..." -msgstr "Вызов программы поддержки репозитория prepare-commit-msg..." +msgstr "Вызов перехватчика prepare-commit-msg…" #: git-gui.sh:1471 msgid "Commit declined by prepare-commit-msg hook." -msgstr "" -"Сохранение прервано программой поддержки репозитория prepare-commit-msg" +msgstr "Коммит прерван перехватчиком prepare-commit-msg." #: git-gui.sh:1629 lib/browser.tcl:246 msgid "Ready." @@ -108,31 +103,31 @@ msgstr "Не изменено" #: git-gui.sh:1915 msgid "Modified, not staged" -msgstr "Изменено, не подготовлено" +msgstr "Изменено, не в индексе" #: git-gui.sh:1916 git-gui.sh:1924 msgid "Staged for commit" -msgstr "Подготовлено для сохранения" +msgstr "В индексе для коммита" #: git-gui.sh:1917 git-gui.sh:1925 msgid "Portions staged for commit" -msgstr "Части, подготовленные для сохранения" +msgstr "Части, в индексе для коммита" #: git-gui.sh:1918 git-gui.sh:1926 msgid "Staged for commit, missing" -msgstr "Подготовлено для сохранения, отсутствует" +msgstr "В индексе для коммита, отсутствует" #: git-gui.sh:1920 msgid "File type changed, not staged" -msgstr "Тип файла изменён, не подготовлено" +msgstr "Тип файла изменён, не в индексе" #: git-gui.sh:1921 msgid "File type changed, staged" -msgstr "Тип файла изменён, подготовлено" +msgstr "Тип файла изменён, в индексе" #: git-gui.sh:1923 msgid "Untracked, not staged" -msgstr "Не отслеживается, не подготовлено" +msgstr "Не отслеживается, не в индексе" #: git-gui.sh:1928 msgid "Missing" @@ -140,11 +135,11 @@ msgstr "Отсутствует" #: git-gui.sh:1929 msgid "Staged for removal" -msgstr "Подготовлено для удаления" +msgstr "В индексе для удаления" #: git-gui.sh:1930 msgid "Staged for removal, still present" -msgstr "Подготовлено для удаления, еще не удалено" +msgstr "В индексе для удаления, еще не удалено" #: git-gui.sh:1932 git-gui.sh:1933 git-gui.sh:1934 git-gui.sh:1935 #: git-gui.sh:1936 git-gui.sh:1937 @@ -153,7 +148,7 @@ msgstr "Требуется разрешение конфликта при сли #: git-gui.sh:1972 msgid "Starting gitk... please wait..." -msgstr "Запускается gitk... Подождите, пожалуйста..." +msgstr "Запускается gitk… Подождите, пожалуйста…" #: git-gui.sh:1984 msgid "Couldn't find gitk in PATH" @@ -173,11 +168,11 @@ msgstr "Редактировать" #: git-gui.sh:2458 lib/choose_rev.tcl:561 msgid "Branch" -msgstr "Ветвь" +msgstr "Ветка" #: git-gui.sh:2461 lib/choose_rev.tcl:548 msgid "Commit@@noun" -msgstr "Состояние" +msgstr "Коммит" #: git-gui.sh:2464 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" @@ -197,29 +192,29 @@ msgstr "Просмотр рабочего каталога" #: git-gui.sh:2483 msgid "Browse Current Branch's Files" -msgstr "Просмотреть файлы текущей ветви" +msgstr "Просмотреть файлы текущей ветки" #: git-gui.sh:2487 msgid "Browse Branch Files..." -msgstr "Показать файлы ветви..." +msgstr "Показать файлы ветки…" #: git-gui.sh:2492 msgid "Visualize Current Branch's History" -msgstr "Показать историю текущей ветви" +msgstr "Показать историю текущей ветки" #: git-gui.sh:2496 msgid "Visualize All Branch History" -msgstr "Показать историю всех ветвей" +msgstr "Показать историю всех веток" #: git-gui.sh:2503 #, tcl-format msgid "Browse %s's Files" -msgstr "Показать файлы ветви %s" +msgstr "Показать файлы ветки %s" #: git-gui.sh:2505 #, tcl-format msgid "Visualize %s's History" -msgstr "Показать историю ветви %s" +msgstr "Показать историю ветки %s" #: git-gui.sh:2510 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" @@ -274,23 +269,23 @@ msgstr "Выделить все" #: git-gui.sh:2576 msgid "Create..." -msgstr "Создать..." +msgstr "Создать…" #: git-gui.sh:2582 msgid "Checkout..." -msgstr "Перейти..." +msgstr "Перейти…" #: git-gui.sh:2588 msgid "Rename..." -msgstr "Переименовать..." +msgstr "Переименовать…" #: git-gui.sh:2593 msgid "Delete..." -msgstr "Удалить..." +msgstr "Удалить…" #: git-gui.sh:2598 msgid "Reset..." -msgstr "Сбросить..." +msgstr "Сбросить…" #: git-gui.sh:2608 msgid "Done" @@ -298,15 +293,15 @@ msgstr "Завершено" #: git-gui.sh:2610 msgid "Commit@@verb" -msgstr "Сохранить" +msgstr "Закоммитить" #: git-gui.sh:2619 git-gui.sh:3050 msgid "New Commit" -msgstr "Новое состояние" +msgstr "Новый коммит" #: git-gui.sh:2627 git-gui.sh:3057 msgid "Amend Last Commit" -msgstr "Исправить последнее состояние" +msgstr "Исправить последний коммит" #: git-gui.sh:2637 git-gui.sh:3011 lib/remote_branch_delete.tcl:99 msgid "Rescan" @@ -314,19 +309,19 @@ msgstr "Перечитать" #: git-gui.sh:2643 msgid "Stage To Commit" -msgstr "Подготовить для сохранения" +msgstr "Добавить в индекс" #: git-gui.sh:2649 msgid "Stage Changed Files To Commit" -msgstr "Подготовить измененные файлы для сохранения" +msgstr "Добавить изменённые файлы в индекс" #: git-gui.sh:2655 msgid "Unstage From Commit" -msgstr "Убрать из подготовленного" +msgstr "Убрать из издекса" #: git-gui.sh:2661 lib/index.tcl:412 msgid "Revert Changes" -msgstr "Отменить изменения" +msgstr "Обратить изменения" #: git-gui.sh:2669 git-gui.sh:3310 git-gui.sh:3341 msgid "Show Less Context" @@ -342,31 +337,31 @@ msgstr "Вставить Signed-off-by" #: git-gui.sh:2696 msgid "Local Merge..." -msgstr "Локальное слияние..." +msgstr "Локальное слияние…" #: git-gui.sh:2701 msgid "Abort Merge..." -msgstr "Прервать слияние..." +msgstr "Прервать слияние…" #: git-gui.sh:2713 git-gui.sh:2741 msgid "Add..." -msgstr "Добавить..." +msgstr "Добавить…" #: git-gui.sh:2717 msgid "Push..." -msgstr "Отправить..." +msgstr "Отправить…" #: git-gui.sh:2721 msgid "Delete Branch..." -msgstr "Удалить ветвь..." +msgstr "Удалить ветку…" #: git-gui.sh:2731 git-gui.sh:3292 msgid "Options..." -msgstr "Настройки..." +msgstr "Настройки…" #: git-gui.sh:2742 msgid "Remove..." -msgstr "Удалить..." +msgstr "Удалить…" #: git-gui.sh:2751 lib/choose_repository.tcl:50 msgid "Help" @@ -393,11 +388,11 @@ msgstr "критическая ошибка: %s: нет такого файла #: git-gui.sh:2926 msgid "Current Branch:" -msgstr "Текущая ветвь:" +msgstr "Текущая ветка:" #: git-gui.sh:2947 msgid "Staged Changes (Will Commit)" -msgstr "Подготовлено (будет сохранено)" +msgstr "Изменения в индексе (будут закоммичены)" #: git-gui.sh:2967 msgid "Unstaged Changes" @@ -405,7 +400,7 @@ msgstr "Изменено (не будет сохранено)" #: git-gui.sh:3017 msgid "Stage Changed" -msgstr "Подготовить все" +msgstr "Индексировать всё" #: git-gui.sh:3036 lib/transport.tcl:104 lib/transport.tcl:193 msgid "Push" @@ -413,27 +408,27 @@ msgstr "Отправить" #: git-gui.sh:3071 msgid "Initial Commit Message:" -msgstr "Комментарий к первому состоянию:" +msgstr "Сообщение первого коммита:" #: git-gui.sh:3072 msgid "Amended Commit Message:" -msgstr "Комментарий к исправленному состоянию:" +msgstr "Сообщение исправленного коммита:" #: git-gui.sh:3073 msgid "Amended Initial Commit Message:" -msgstr "Комментарий к исправленному первоначальному состоянию:" +msgstr "Сообщение исправленного первого коммита:" #: git-gui.sh:3074 msgid "Amended Merge Commit Message:" -msgstr "Комментарий к исправленному слиянию:" +msgstr "Сообщение исправленного слияния:" #: git-gui.sh:3075 msgid "Merge Commit Message:" -msgstr "Комментарий к слиянию:" +msgstr "Сообщение слияния:" #: git-gui.sh:3076 msgid "Commit Message:" -msgstr "Комментарий к состоянию:" +msgstr "Сообщение коммита:" #: git-gui.sh:3125 git-gui.sh:3267 lib/console.tcl:73 msgid "Copy All" @@ -481,51 +476,51 @@ msgstr "Взять локальную версию" #: git-gui.sh:3336 msgid "Revert To Base" -msgstr "Отменить изменения" +msgstr "Обратить изменения" #: git-gui.sh:3354 msgid "Visualize These Changes In The Submodule" -msgstr "" +msgstr "Показать эти изменения подмодуля" #: git-gui.sh:3358 msgid "Visualize Current Branch History In The Submodule" -msgstr "Показать историю текущей ветви подмодуля" +msgstr "Показать историю текущей ветки подмодуля" #: git-gui.sh:3362 msgid "Visualize All Branch History In The Submodule" -msgstr "Показать историю всех ветвей подмодуля" +msgstr "Показать историю всех веток подмодуля" #: git-gui.sh:3367 msgid "Start git gui In The Submodule" -msgstr "" +msgstr "Запустить git gui в подмодуле" #: git-gui.sh:3389 msgid "Unstage Hunk From Commit" -msgstr "Не сохранять часть" +msgstr "Убрать блок из индекса" #: git-gui.sh:3391 msgid "Unstage Lines From Commit" -msgstr "Убрать строки из подготовленного" +msgstr "Убрать строки из индекса" #: git-gui.sh:3393 msgid "Unstage Line From Commit" -msgstr "Убрать строку из подготовленного" +msgstr "Убрать строку из индекса" #: git-gui.sh:3396 msgid "Stage Hunk For Commit" -msgstr "Подготовить часть для сохранения" +msgstr "Добавить блок в индекс" #: git-gui.sh:3398 msgid "Stage Lines For Commit" -msgstr "Подготовить строки для сохранения" +msgstr "Добавить строки в индекс" #: git-gui.sh:3400 msgid "Stage Line For Commit" -msgstr "Подготовить строку для сохранения" +msgstr "Добавить строку в индекс" #: git-gui.sh:3424 msgid "Initializing..." -msgstr "Инициализация..." +msgstr "Инициализация…" #: git-gui.sh:3541 #, tcl-format @@ -536,23 +531,14 @@ msgid "" "going to be ignored by any Git subprocess run\n" "by %s:\n" "\n" -msgstr "" -"Возможны ошибки в переменных окружения.\n" -"\n" -"Переменные окружения, которые возможно\n" -"будут проигнорированы командами Git,\n" -"запущенными из %s\n" -"\n" +msgstr "Возможны ошибки в переменных окружения.\n\nПеременные окружения, которые возможно\nбудут проигнорированы командами Git,\nзапущенными из %s\n\n" #: git-gui.sh:3570 msgid "" "\n" "This is due to a known issue with the\n" "Tcl binary distributed by Cygwin." -msgstr "" -"\n" -"Это известная проблема с Tcl,\n" -"распространяемым Cygwin." +msgstr "\nЭто известная проблема с Tcl,\nраспространяемым Cygwin." #: git-gui.sh:3575 #, tcl-format @@ -563,13 +549,7 @@ msgid "" "is placing values for the user.name and\n" "user.email settings into your personal\n" "~/.gitconfig file.\n" -msgstr "" -"\n" -"\n" -"Вместо использования %s можно\n" -"сохранить значения user.name и\n" -"user.email в Вашем персональном\n" -"файле ~/.gitconfig.\n" +msgstr "\n\nВместо использования %s можно\nсохранить значения user.name и\nuser.email в Вашем персональном\nфайле ~/.gitconfig.\n" #: lib/about.tcl:26 msgid "git-gui - a graphical user interface for Git." @@ -581,15 +561,15 @@ msgstr "Просмотр файла" #: lib/blame.tcl:78 msgid "Commit:" -msgstr "Сохраненное состояние:" +msgstr "Коммит:" #: lib/blame.tcl:271 msgid "Copy Commit" -msgstr "Скопировать SHA-1" +msgstr "Копировать SHA-1" #: lib/blame.tcl:275 msgid "Find Text..." -msgstr "Найти текст..." +msgstr "Найти текст…" #: lib/blame.tcl:284 msgid "Do Full Copy Detection" @@ -601,16 +581,16 @@ msgstr "Показать исторический контекст" #: lib/blame.tcl:291 msgid "Blame Parent Commit" -msgstr "Рассмотреть состояние предка" +msgstr "Авторы родительского коммита" #: lib/blame.tcl:450 #, tcl-format msgid "Reading %s..." -msgstr "Чтение %s..." +msgstr "Чтение %s…" #: lib/blame.tcl:557 msgid "Loading copy/move tracking annotations..." -msgstr "Загрузка аннотации копирований/переименований..." +msgstr "Загрузка аннотации копирований/переименований…" #: lib/blame.tcl:577 msgid "lines annotated" @@ -618,7 +598,7 @@ msgstr "строк прокомментировано" #: lib/blame.tcl:769 msgid "Loading original location annotations..." -msgstr "Загрузка аннотаций первоначального положения объекта..." +msgstr "Загрузка аннотаций первоначального положения объекта…" #: lib/blame.tcl:772 msgid "Annotation complete." @@ -634,11 +614,11 @@ msgstr "Аннотация уже запущена" #: lib/blame.tcl:842 msgid "Running thorough copy detection..." -msgstr "Выполнение полного поиска копий..." +msgstr "Выполнение полного поиска копий…" #: lib/blame.tcl:910 msgid "Loading annotation..." -msgstr "Загрузка аннотации..." +msgstr "Загрузка аннотации…" #: lib/blame.tcl:963 msgid "Author:" @@ -646,7 +626,7 @@ msgstr "Автор:" #: lib/blame.tcl:967 msgid "Committer:" -msgstr "Сохранил:" +msgstr "Коммитер:" #: lib/blame.tcl:972 msgid "Original File:" @@ -654,11 +634,11 @@ msgstr "Исходный файл:" #: lib/blame.tcl:1020 msgid "Cannot find HEAD commit:" -msgstr "Невозможно найти текущее состояние:" +msgstr "Не удалось найти текущее состояние:" #: lib/blame.tcl:1075 msgid "Cannot find parent commit:" -msgstr "Невозможно найти состояние предка:" +msgstr "Не удалось найти родительское состояние:" #: lib/blame.tcl:1090 msgid "Unable to display parent" @@ -682,7 +662,7 @@ msgstr "Скопировано/перемещено в:" #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" -msgstr "Перейти на ветвь" +msgstr "Перейти на ветку" #: lib/branch_checkout.tcl:23 msgid "Checkout" @@ -707,19 +687,19 @@ msgstr "Настройки" #: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92 msgid "Fetch Tracking Branch" -msgstr "Получить изменения из внешней ветви" +msgstr "Извлечь изменения из внешней ветки" #: lib/branch_checkout.tcl:44 msgid "Detach From Local Branch" -msgstr "Отсоединить от локальной ветви" +msgstr "Отсоединить от локальной ветки" #: lib/branch_create.tcl:22 msgid "Create Branch" -msgstr "Создание ветви" +msgstr "Создать ветку" #: lib/branch_create.tcl:27 msgid "Create New Branch" -msgstr "Создать новую ветвь" +msgstr "Создать новую ветку" #: lib/branch_create.tcl:31 lib/choose_repository.tcl:381 msgid "Create" @@ -727,7 +707,7 @@ msgstr "Создать" #: lib/branch_create.tcl:40 msgid "Branch Name" -msgstr "Название ветви" +msgstr "Имя ветки" #: lib/branch_create.tcl:43 lib/remote_add.tcl:39 lib/tools_dlg.tcl:50 msgid "Name:" @@ -735,7 +715,7 @@ msgstr "Название:" #: lib/branch_create.tcl:58 msgid "Match Tracking Branch Name" -msgstr "Взять из имен ветвей слежения" +msgstr "Соответствовать имени отслеживаемой ветки" #: lib/branch_create.tcl:66 msgid "Starting Revision" @@ -743,7 +723,7 @@ msgstr "Начальная версия" #: lib/branch_create.tcl:72 msgid "Update Existing Branch:" -msgstr "Обновить имеющуюся ветвь:" +msgstr "Обновить имеющуюся ветку:" #: lib/branch_create.tcl:75 msgid "No" @@ -763,33 +743,33 @@ msgstr "После создания сделать текущей" #: lib/branch_create.tcl:131 msgid "Please select a tracking branch." -msgstr "Укажите ветвь слежения." +msgstr "Укажите отлеживаемую ветку." #: lib/branch_create.tcl:140 #, tcl-format msgid "Tracking branch %s is not a branch in the remote repository." -msgstr "Ветвь слежения %s не является ветвью во внешнем репозитории." +msgstr "Отслеживаемая ветка %s не является веткой на внешнем репозитории." #: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 msgid "Please supply a branch name." -msgstr "Укажите название ветви." +msgstr "Укажите имя ветки." #: lib/branch_create.tcl:164 lib/branch_rename.tcl:106 #, tcl-format msgid "'%s' is not an acceptable branch name." -msgstr "Недопустимое название ветви '%s'." +msgstr "Недопустимое имя ветки «%s»." #: lib/branch_delete.tcl:15 msgid "Delete Branch" -msgstr "Удаление ветви" +msgstr "Удаление ветки" #: lib/branch_delete.tcl:20 msgid "Delete Local Branch" -msgstr "Удалить локальную ветвь" +msgstr "Удалить локальную ветку" #: lib/branch_delete.tcl:37 msgid "Local Branches" -msgstr "Локальные ветви" +msgstr "Локальные ветки" #: lib/branch_delete.tcl:52 msgid "Delete Only If Merged Into" @@ -802,30 +782,25 @@ msgstr "Всегда (не выполнять проверку на слияни #: lib/branch_delete.tcl:103 #, tcl-format msgid "The following branches are not completely merged into %s:" -msgstr "Ветви, которые не полностью сливаются с %s:" +msgstr "Ветки, которые не полностью сливаются с %s:" #: lib/branch_delete.tcl:115 lib/remote_branch_delete.tcl:217 msgid "" "Recovering deleted branches is difficult.\n" "\n" "Delete the selected branches?" -msgstr "" -"Восстановить удаленные ветви сложно.\n" -"\n" -"Продолжить?" +msgstr "Восстановить удаленные ветки сложно.\n\nПродолжить?" #: lib/branch_delete.tcl:141 #, tcl-format msgid "" "Failed to delete branches:\n" "%s" -msgstr "" -"Не удалось удалить ветви:\n" -"%s" +msgstr "Не удалось удалить ветки:\n%s" #: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22 msgid "Rename Branch" -msgstr "Переименование ветви" +msgstr "Переименование ветки" #: lib/branch_rename.tcl:26 msgid "Rename" @@ -833,7 +808,7 @@ msgstr "Переименовать" #: lib/branch_rename.tcl:36 msgid "Branch:" -msgstr "Ветвь:" +msgstr "Ветка:" #: lib/branch_rename.tcl:39 msgid "New Name:" @@ -841,21 +816,21 @@ msgstr "Новое название:" #: lib/branch_rename.tcl:75 msgid "Please select a branch to rename." -msgstr "Укажите ветвь для переименования." +msgstr "Укажите ветку для переименования." #: lib/branch_rename.tcl:96 lib/checkout_op.tcl:202 #, tcl-format msgid "Branch '%s' already exists." -msgstr "Ветвь '%s' уже существует." +msgstr "Ветка «%s» уже существует." #: lib/branch_rename.tcl:117 #, tcl-format msgid "Failed to rename '%s'." -msgstr "Не удалось переименовать '%s'. " +msgstr "Не удалось переименовать «%s». " #: lib/browser.tcl:17 msgid "Starting..." -msgstr "Запуск..." +msgstr "Запуск…" #: lib/browser.tcl:26 msgid "File Browser" @@ -864,7 +839,7 @@ msgstr "Просмотр списка файлов" #: lib/browser.tcl:126 lib/browser.tcl:143 #, tcl-format msgid "Loading %s..." -msgstr "Загрузка %s..." +msgstr "Загрузка %s…" #: lib/browser.tcl:187 msgid "[Up To Parent]" @@ -872,7 +847,7 @@ msgstr "[На уровень выше]" #: lib/browser.tcl:267 lib/browser.tcl:273 msgid "Browse Branch Files" -msgstr "Показать файлы ветви" +msgstr "Показать файлы ветки" #: lib/browser.tcl:278 lib/choose_repository.tcl:398 #: lib/choose_repository.tcl:486 lib/choose_repository.tcl:497 @@ -883,7 +858,7 @@ msgstr "Показать" #: lib/checkout_op.tcl:85 #, tcl-format msgid "Fetching %s from %s" -msgstr "Получение %s из %s " +msgstr "Извлечение %s из %s " #: lib/checkout_op.tcl:133 #, tcl-format @@ -898,12 +873,12 @@ msgstr "Закрыть" #: lib/checkout_op.tcl:175 #, tcl-format msgid "Branch '%s' does not exist." -msgstr "Ветвь '%s' не существует " +msgstr "Ветка «%s» не существует." #: lib/checkout_op.tcl:194 #, tcl-format msgid "Failed to configure simplified git-pull for '%s'." -msgstr "Ошибка создания упрощённой конфигурации git pull для '%s'." +msgstr "Ошибка создания упрощённой конфигурации git pull для «%s»." #: lib/checkout_op.tcl:229 #, tcl-format @@ -912,21 +887,17 @@ msgid "" "\n" "It cannot fast-forward to %s.\n" "A merge is required." -msgstr "" -"Ветвь '%s' уже существует.\n" -"\n" -"Она не может быть прокручена(fast-forward) к %s.\n" -"Требуется слияние." +msgstr "Ветка «%s» уже существует.\n\nОна не может быть перемотана вперед к %s.\nТребуется слияние." #: lib/checkout_op.tcl:243 #, tcl-format msgid "Merge strategy '%s' not supported." -msgstr "Неизвестная стратегия слияния: '%s'." +msgstr "Неизвестная стратегия слияния «%s»." #: lib/checkout_op.tcl:262 #, tcl-format msgid "Failed to update '%s'." -msgstr "Не удалось обновить '%s'." +msgstr "Не удалось обновить «%s»." #: lib/checkout_op.tcl:274 msgid "Staging area (index) is already locked." @@ -936,22 +907,15 @@ msgstr "Рабочая область заблокирована другим п msgid "" "Last scanned state does not match repository state.\n" "\n" -"Another Git program has modified this repository since the last scan. A " -"rescan must be performed before the current branch can be changed.\n" +"Another Git program has modified this repository since the last scan. A rescan must be performed before the current branch can be changed.\n" "\n" "The rescan will be automatically started now.\n" -msgstr "" -"Последнее прочитанное состояние репозитория не соответствует текущему.\n" -"\n" -"С момента последней проверки репозиторий был изменен другой программой Git. " -"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь.\n" -"\n" -"Это будет сделано сейчас автоматически.\n" +msgstr "Последнее прочитанное состояние репозитория не соответствует текущему.\n\nС момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем текущая ветка может быть изменена.\n\nЭто будет сделано сейчас автоматически.\n" #: lib/checkout_op.tcl:345 #, tcl-format msgid "Updating working directory to '%s'..." -msgstr "Обновление рабочего каталога из '%s'..." +msgstr "Обновление рабочего каталога из «%s»…" #: lib/checkout_op.tcl:346 msgid "files checked out" @@ -960,7 +924,7 @@ msgstr "файлы извлечены" #: lib/checkout_op.tcl:376 #, tcl-format msgid "Aborted checkout of '%s' (file level merging is required)." -msgstr "Прерван переход на '%s' (требуется слияние содержания файлов)" +msgstr "Прерван переход на «%s» (требуется слияние содержимого файлов)" #: lib/checkout_op.tcl:377 msgid "File level merge required." @@ -969,38 +933,33 @@ msgstr "Требуется слияние содержания файлов." #: lib/checkout_op.tcl:381 #, tcl-format msgid "Staying on branch '%s'." -msgstr "Ветвь '%s' остается текущей." +msgstr "Ветка «%s» остаётся текущей." #: lib/checkout_op.tcl:452 msgid "" "You are no longer on a local branch.\n" "\n" -"If you wanted to be on a branch, create one now starting from 'This Detached " -"Checkout'." -msgstr "" -"Вы находитесь не в локальной ветви.\n" -"\n" -"Если вы хотите снова вернуться к какой-нибудь ветви, создайте ее сейчас, " -"начиная с 'Текущего отсоединенного состояния'." +"If you wanted to be on a branch, create one now starting from 'This Detached Checkout'." +msgstr "Вы более не находитесь на локальной ветке.\n\nЕсли вы хотите снова вернуться к какой-нибудь ветке, создайте её сейчас, начиная с «Текущего отсоединенного состояния»." #: lib/checkout_op.tcl:503 lib/checkout_op.tcl:507 #, tcl-format msgid "Checked out '%s'." -msgstr "Ветвь '%s' сделана текущей." +msgstr "Выполнен переход на «%s»." #: lib/checkout_op.tcl:535 #, tcl-format msgid "Resetting '%s' to '%s' will lose the following commits:" -msgstr "Сброс '%s' в '%s' приведет к потере следующих сохраненных состояний: " +msgstr "Сброс «%s» на «%s» приведет к потере следующих коммитов:" #: lib/checkout_op.tcl:557 msgid "Recovering lost commits may not be easy." -msgstr "Восстановить потерянные сохраненные состояния будет сложно." +msgstr "Восстановить потерянные коммиты будет сложно." #: lib/checkout_op.tcl:562 #, tcl-format msgid "Reset '%s'?" -msgstr "Сбросить '%s'?" +msgstr "Сбросить «%s»?" #: lib/checkout_op.tcl:567 lib/merge.tcl:164 lib/tools_dlg.tcl:343 msgid "Visualize" @@ -1011,17 +970,10 @@ msgstr "Наглядно" msgid "" "Failed to set current branch.\n" "\n" -"This working directory is only partially switched. We successfully updated " -"your files, but failed to update an internal Git file.\n" +"This working directory is only partially switched. We successfully updated your files, but failed to update an internal Git file.\n" "\n" "This should not have occurred. %s will now close and give up." -msgstr "" -"Не удалось установить текущую ветвь.\n" -"\n" -"Ваш рабочий каталог обновлен только частично. Были обновлены все файлы кроме " -"служебных файлов Git. \n" -"\n" -"Этого не должно было произойти. %s завершается." +msgstr "Не удалось установить текущую ветку.\n\nВаш рабочий каталог обновлён только частично. Были обновлены все файлы кроме служебных файлов Git. \n\nЭтого не должно было произойти. %s завершается." #: lib/choose_font.tcl:39 msgid "Select" @@ -1043,9 +995,7 @@ msgstr "Пример текста" msgid "" "This is example text.\n" "If you like this text, it can be your font." -msgstr "" -"Это пример текста.\n" -"Если Вам нравится этот текст, это может быть Ваш шрифт." +msgstr "Это пример текста.\nЕсли Вам нравится этот текст, это может быть Ваш шрифт." #: lib/choose_repository.tcl:28 msgid "Git Gui" @@ -1057,7 +1007,7 @@ msgstr "Создать новый репозиторий" #: lib/choose_repository.tcl:93 msgid "New..." -msgstr "Новый..." +msgstr "Новый…" #: lib/choose_repository.tcl:100 lib/choose_repository.tcl:471 msgid "Clone Existing Repository" @@ -1065,7 +1015,7 @@ msgstr "Склонировать существующий репозиторий #: lib/choose_repository.tcl:106 msgid "Clone..." -msgstr "Склонировать..." +msgstr "Клонировать…" #: lib/choose_repository.tcl:113 lib/choose_repository.tcl:1016 msgid "Open Existing Repository" @@ -1073,7 +1023,7 @@ msgstr "Выбрать существующий репозиторий" #: lib/choose_repository.tcl:119 msgid "Open..." -msgstr "Открыть..." +msgstr "Открыть…" #: lib/choose_repository.tcl:132 msgid "Recent Repositories" @@ -1126,7 +1076,7 @@ msgstr "Тип клона:" #: lib/choose_repository.tcl:508 msgid "Standard (Fast, Semi-Redundant, Hardlinks)" -msgstr "Стандартный (Быстрый, полуизбыточный, \"жесткие\" ссылки)" +msgstr "Стандартный (Быстрый, полуизбыточный, «жесткие» ссылки)" #: lib/choose_repository.tcl:514 msgid "Full Copy (Slower, Redundant Backup)" @@ -1166,7 +1116,7 @@ msgstr "Считаю объекты" #: lib/choose_repository.tcl:641 msgid "buckets" -msgstr "" +msgstr "блоки" #: lib/choose_repository.tcl:665 #, tcl-format @@ -1181,11 +1131,11 @@ msgstr "Нечего клонировать с %s." #: lib/choose_repository.tcl:703 lib/choose_repository.tcl:917 #: lib/choose_repository.tcl:929 msgid "The 'master' branch has not been initialized." -msgstr "Не инициализирована ветвь 'master'." +msgstr "Не инициализирована ветвь «master»." #: lib/choose_repository.tcl:716 msgid "Hardlinks are unavailable. Falling back to copying." -msgstr "\"Жесткие ссылки\" недоступны. Будет использовано копирование." +msgstr "«Жесткие ссылки» недоступны. Будет использовано копирование." #: lib/choose_repository.tcl:728 #, tcl-format @@ -1216,16 +1166,15 @@ msgstr "объекты" #: lib/choose_repository.tcl:803 #, tcl-format msgid "Unable to hardlink object: %s" -msgstr "Не могу \"жестко связать\" объект: %s" +msgstr "Не могу создать «жесткую ссылку» на объект: %s" #: lib/choose_repository.tcl:858 msgid "Cannot fetch branches and objects. See console output for details." -msgstr "" -"Не могу получить ветви и объекты. Дополнительная информация на консоли." +msgstr "Не удалось извлечь ветки и объекты. Дополнительная информация на консоли." #: lib/choose_repository.tcl:869 msgid "Cannot fetch tags. See console output for details." -msgstr "Не могу получить метки. Дополнительная информация на консоли." +msgstr "Не удалось извлечь метки. Дополнительная информация на консоли." #: lib/choose_repository.tcl:893 msgid "Cannot determine HEAD. See console output for details." @@ -1242,12 +1191,12 @@ msgstr "Клонирование не удалось." #: lib/choose_repository.tcl:915 msgid "No default branch obtained." -msgstr "Не было получено ветви по умолчанию." +msgstr "Ветка по умолчанию не была получена." #: lib/choose_repository.tcl:926 #, tcl-format msgid "Cannot resolve %s as a commit." -msgstr "Не могу распознать %s как состояние." +msgstr "Не могу распознать %s как коммит." #: lib/choose_repository.tcl:938 msgid "Creating working directory" @@ -1285,11 +1234,11 @@ msgstr "Выражение для определения версии:" #: lib/choose_rev.tcl:74 msgid "Local Branch" -msgstr "Локальная ветвь:" +msgstr "Локальная ветка:" #: lib/choose_rev.tcl:79 msgid "Tracking Branch" -msgstr "Ветвь слежения" +msgstr "Отслеживаемая ветка" #: lib/choose_rev.tcl:84 lib/choose_rev.tcl:538 msgid "Tag" @@ -1320,29 +1269,19 @@ msgstr "Ссылка" msgid "" "There is nothing to amend.\n" "\n" -"You are about to create the initial commit. There is no commit before this " -"to amend.\n" -msgstr "" -"Отсутствует состояние для исправления.\n" -"\n" -"Вы создаете первое состояние в репозитории, здесь еще нечего исправлять.\n" +"You are about to create the initial commit. There is no commit before this to amend.\n" +msgstr "Отсутствует коммиты для исправления.\n\nВы создаете начальный коммит, здесь еще нечего исправлять.\n" #: lib/commit.tcl:18 msgid "" "Cannot amend while merging.\n" "\n" -"You are currently in the middle of a merge that has not been fully " -"completed. You cannot amend the prior commit unless you first abort the " -"current merge activity.\n" -msgstr "" -"Невозможно исправить состояние во время операции слияния.\n" -"\n" -"Текущее слияние не завершено. Невозможно исправить предыдущее сохраненное " -"состояние, не прерывая эту операцию.\n" +"You are currently in the middle of a merge that has not been fully completed. You cannot amend the prior commit unless you first abort the current merge activity.\n" +msgstr "Невозможно исправить коммит во время слияния.\n\nТекущее слияние не завершено. Невозможно исправить предыдуий коммит, не прерывая эту операцию.\n" #: lib/commit.tcl:48 msgid "Error loading commit data for amend:" -msgstr "Ошибка при загрузке данных для исправления сохраненного состояния:" +msgstr "Ошибка при загрузке данных для исправления коммита:" #: lib/commit.tcl:75 msgid "Unable to obtain your identity:" @@ -1350,41 +1289,29 @@ msgstr "Невозможно получить информацию об авто #: lib/commit.tcl:80 msgid "Invalid GIT_COMMITTER_IDENT:" -msgstr "Неверный GIT_COMMITTER_IDENT:" +msgstr "Недопустимый GIT_COMMITTER_IDENT:" #: lib/commit.tcl:129 #, tcl-format msgid "warning: Tcl does not support encoding '%s'." -msgstr "предупреждение: Tcl не поддерживает кодировку '%s'." +msgstr "предупреждение: Tcl не поддерживает кодировку «%s»." #: lib/commit.tcl:149 msgid "" "Last scanned state does not match repository state.\n" "\n" -"Another Git program has modified this repository since the last scan. A " -"rescan must be performed before another commit can be created.\n" +"Another Git program has modified this repository since the last scan. A rescan must be performed before another commit can be created.\n" "\n" "The rescan will be automatically started now.\n" -msgstr "" -"Последнее прочитанное состояние репозитория не соответствует текущему.\n" -"\n" -"С момента последней проверки репозиторий был изменен другой программой Git. " -"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" -"\n" -"Это будет сделано сейчас автоматически.\n" +msgstr "Последнее прочитанное состояние репозитория не соответствует текущему.\n\nС момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n\nЭто будет сделано сейчас автоматически.\n" #: lib/commit.tcl:172 #, tcl-format msgid "" "Unmerged files cannot be committed.\n" "\n" -"File %s has merge conflicts. You must resolve them and stage the file " -"before committing.\n" -msgstr "" -"Нельзя сохранить файлы с незавершённой операцией слияния.\n" -"\n" -"Для файла %s возник конфликт слияния. Разрешите конфликт и добавьте к " -"подготовленным файлам перед сохранением.\n" +"File %s has merge conflicts. You must resolve them and stage the file before committing.\n" +msgstr "Нельзя выполнить коммит с незавершённой операцией слияния.\n\nДля файла %s возник конфликт слияния. Разрешите конфликт и добавьте их в индекс перед выполнением коммита.\n" #: lib/commit.tcl:180 #, tcl-format @@ -1392,20 +1319,14 @@ msgid "" "Unknown file state %s detected.\n" "\n" "File %s cannot be committed by this program.\n" -msgstr "" -"Обнаружено неизвестное состояние файла %s.\n" -"\n" -"Файл %s не может быть сохранен данной программой.\n" +msgstr "Обнаружено неизвестное состояние файла %s.\n\nФайл %s не может быть закоммичен этой программой.\n" #: lib/commit.tcl:188 msgid "" "No changes to commit.\n" "\n" "You must stage at least 1 file before you can commit.\n" -msgstr "" -"Отсутствуют изменения для сохранения.\n" -"\n" -"Подготовьте хотя бы один файл до создания сохраненного состояния.\n" +msgstr "Отсутствуют изменения для сохранения.\n\nДобавьте в индекс хотя бы один файл перед выполнением коммита.\n" #: lib/commit.tcl:203 msgid "" @@ -1416,34 +1337,27 @@ msgid "" "- First line: Describe in one sentence what you did.\n" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" -msgstr "" -"Напишите комментарий к сохраненному состоянию.\n" -"\n" -"Рекомендуется следующий формат комментария:\n" -"\n" -"- первая строка: краткое описание сделанных изменений.\n" -"- вторая строка пустая\n" -"- оставшиеся строки: опишите, что дают ваши изменения.\n" +msgstr "Укажите сообщение коммита.\n\nРекомендуется следующий формат сообщения:\n\n- в первой строке краткое описание сделанных изменений\n- вторая строка пустая\n- в оставшихся строках опишите, что дают ваши изменения\n" #: lib/commit.tcl:234 msgid "Calling pre-commit hook..." -msgstr "Вызов программы поддержки репозитория pre-commit..." +msgstr "Вызов перехватчика pre-commit…" #: lib/commit.tcl:249 msgid "Commit declined by pre-commit hook." -msgstr "Сохранение прервано программой поддержки репозитория pre-commit" +msgstr "Коммит прерван переватчиком pre-commit." #: lib/commit.tcl:272 msgid "Calling commit-msg hook..." -msgstr "Вызов программы поддержки репозитория commit-msg..." +msgstr "Вызов перехватчика commit-msg…" #: lib/commit.tcl:287 msgid "Commit declined by commit-msg hook." -msgstr "Сохранение прервано программой поддержки репозитория commit-msg" +msgstr "Коммит прерван переватчиком commit-msg" #: lib/commit.tcl:300 msgid "Committing changes..." -msgstr "Сохранение изменений..." +msgstr "Коммит изменений…" #: lib/commit.tcl:316 msgid "write-tree failed:" @@ -1451,12 +1365,12 @@ msgstr "Программа write-tree завершилась с ошибкой:" #: lib/commit.tcl:317 lib/commit.tcl:361 lib/commit.tcl:382 msgid "Commit failed." -msgstr "Сохранить состояние не удалось." +msgstr "Не удалось закоммитить изменения." #: lib/commit.tcl:334 #, tcl-format msgid "Commit %s appears to be corrupt" -msgstr "Состояние %s выглядит поврежденным" +msgstr "Коммит %s похоже поврежден" #: lib/commit.tcl:339 msgid "" @@ -1465,16 +1379,11 @@ msgid "" "No files were modified by this commit and it was not a merge commit.\n" "\n" "A rescan will be automatically started now.\n" -msgstr "" -"Отсутствуют изменения для сохранения.\n" -"\n" -"Ни один файл не был изменен и не было слияния.\n" -"\n" -"Сейчас автоматически запустится перечитывание репозитория.\n" +msgstr "Нет изменения для коммита.\n\nНи один файл не был изменен и не было слияния.\n\nСейчас автоматически запустится перечитывание репозитория.\n" #: lib/commit.tcl:346 msgid "No changes to commit." -msgstr "Отсутствуют изменения для сохранения." +msgstr "Нет изменения для коммита." #: lib/commit.tcl:360 msgid "commit-tree failed:" @@ -1487,11 +1396,11 @@ msgstr "Программа update-ref завершилась с ошибкой:" #: lib/commit.tcl:469 #, tcl-format msgid "Created commit %s: %s" -msgstr "Создано состояние %s: %s " +msgstr "Создан коммит %s: %s " #: lib/console.tcl:59 msgid "Working... please wait..." -msgstr "В процессе... пожалуйста, ждите..." +msgstr "В процессе… пожалуйста, ждите…" #: lib/console.tcl:186 msgid "Success" @@ -1542,16 +1451,10 @@ msgstr "Проверка базы объектов при помощи fsck" msgid "" "This repository currently has approximately %i loose objects.\n" "\n" -"To maintain optimal performance it is strongly recommended that you compress " -"the database.\n" +"To maintain optimal performance it is strongly recommended that you compress the database.\n" "\n" "Compress the database now?" -msgstr "" -"Этот репозиторий сейчас содержит примерно %i свободных объектов\n" -"\n" -"Для лучшей производительности рекомендуется сжать базу данных.\n" -"\n" -"Сжать базу данных сейчас?" +msgstr "Этот репозиторий сейчас содержит примерно %i свободных объектов\n\nДля лучшей производительности рекомендуется сжать базу данных.\n\nСжать базу данных сейчас?" #: lib/date.tcl:25 #, tcl-format @@ -1565,41 +1468,27 @@ msgid "" "\n" "%s has no changes.\n" "\n" -"The modification date of this file was updated by another application, but " -"the content within the file was not changed.\n" -"\n" -"A rescan will be automatically started to find other files which may have " -"the same state." -msgstr "" -"Изменений не обнаружено.\n" +"The modification date of this file was updated by another application, but the content within the file was not changed.\n" "\n" -"в %s отсутствуют изменения.\n" -"\n" -"Дата изменения файла была обновлена другой программой, но содержимое файла " -"осталось прежним.\n" -"\n" -"Сейчас будет запущено перечитывание репозитория, чтобы найти подобные файлы." +"A rescan will be automatically started to find other files which may have the same state." +msgstr "Изменений не обнаружено.\n\nв %s отсутствуют изменения.\n\nДата изменения файла была обновлена другой программой, но содержимое файла осталось прежним.\n\nСейчас будет запущено перечитывание репозитория, чтобы найти подобные файлы." #: lib/diff.tcl:104 #, tcl-format msgid "Loading diff of %s..." -msgstr "Загрузка изменений в %s..." +msgstr "Загрузка изменений %s…" #: lib/diff.tcl:125 msgid "" "LOCAL: deleted\n" "REMOTE:\n" -msgstr "" -"ЛОКАЛЬНО: удалён\n" -"ВНЕШНИЙ:\n" +msgstr "ЛОКАЛЬНО: удалён\nВНЕШНИЙ:\n" #: lib/diff.tcl:130 msgid "" "REMOTE: deleted\n" "LOCAL:\n" -msgstr "" -"ВНЕШНИЙ: удалён\n" -"ЛОКАЛЬНО:\n" +msgstr "ВНЕШНИЙ: удалён\nЛОКАЛЬНО:\n" #: lib/diff.tcl:137 msgid "LOCAL:\n" @@ -1631,9 +1520,7 @@ msgstr "* Двоичный файл (содержимое не показано) msgid "" "* Untracked file is %d bytes.\n" "* Showing only first %d bytes.\n" -msgstr "" -"* Размер неподготовленного файла %d байт.\n" -"* Показано первых %d байт.\n" +msgstr "* Размер неотслеживаемого файла %d байт.\n* Показано первых %d байт.\n" #: lib/diff.tcl:233 #, tcl-format @@ -1641,10 +1528,7 @@ msgid "" "\n" "* Untracked file clipped here by %s.\n" "* To see the entire file, use an external editor.\n" -msgstr "" -"\n" -"* Неподготовленный файл обрезан: %s.\n" -"* Чтобы увидеть весь файл, используйте программу-редактор.\n" +msgstr "\n* Неотслеживаемый файл обрезан: %s.\n* Чтобы увидеть весь файл, используйте внешний редактор.\n" #: lib/diff.tcl:482 msgid "Failed to unstage selected hunk." @@ -1652,7 +1536,7 @@ msgstr "Не удалось исключить выбранную часть." #: lib/diff.tcl:489 msgid "Failed to stage selected hunk." -msgstr "Не удалось подготовить к сохранению выбранную часть." +msgstr "Не удалось проиндексировать выбранный блок изменений." #: lib/diff.tcl:568 msgid "Failed to unstage selected line." @@ -1660,7 +1544,7 @@ msgstr "Не удалось исключить выбранную строку." #: lib/diff.tcl:576 msgid "Failed to stage selected line." -msgstr "Не удалось подготовить к сохранению выбранную строку." +msgstr "Не удалось проиндексировать выбранную строку." #: lib/encoding.tcl:443 msgid "Default" @@ -1685,7 +1569,7 @@ msgstr "предупреждение" #: lib/error.tcl:94 msgid "You must correct the above errors before committing." -msgstr "Прежде чем сохранить, исправьте вышеуказанные ошибки." +msgstr "Перед коммитом, исправьте вышеуказанные ошибки." #: lib/index.tcl:6 msgid "Unable to unlock the index." @@ -1699,9 +1583,7 @@ msgstr "Ошибка в индексе" msgid "" "Updating the Git index failed. A rescan will be automatically started to " "resynchronize git-gui." -msgstr "" -"Не удалось обновить индекс Git. Состояние репозитория будет перечитано " -"автоматически." +msgstr "Не удалось обновить индекс Git. Состояние репозитория будет перечитано автоматически." #: lib/index.tcl:28 msgid "Continue" @@ -1714,32 +1596,30 @@ msgstr "Разблокировать индекс" #: lib/index.tcl:289 #, tcl-format msgid "Unstaging %s from commit" -msgstr "Удаление %s из подготовленного" +msgstr "Удаление %s из индекса" #: lib/index.tcl:328 msgid "Ready to commit." -msgstr "Подготовлено для сохранения" +msgstr "Готов для коммита." #: lib/index.tcl:341 #, tcl-format msgid "Adding %s" -msgstr "Добавление %s..." +msgstr "Добавление %s…" #: lib/index.tcl:398 #, tcl-format msgid "Revert changes in file %s?" -msgstr "Отменить изменения в файле %s?" +msgstr "Обратить изменения в файле %s?" #: lib/index.tcl:400 #, tcl-format msgid "Revert changes in these %i files?" -msgstr "Отменить изменения в %i файле(-ах)?" +msgstr "Обратить изменения в %i файле(-ах)?" #: lib/index.tcl:408 msgid "Any unstaged changes will be permanently lost by the revert." -msgstr "" -"Любые изменения, не подготовленные к сохранению, будут потеряны при данной " -"операции." +msgstr "Любые непроиндексированные изменения, будут потеряны при обращении изменений." #: lib/index.tcl:411 msgid "Do Nothing" @@ -1747,38 +1627,28 @@ msgstr "Ничего не делать" #: lib/index.tcl:429 msgid "Reverting selected files" -msgstr "Удаление изменений в выбранных файлах" +msgstr "Обращение изменений в выбранных файлах" #: lib/index.tcl:433 #, tcl-format msgid "Reverting %s" -msgstr "Отмена изменений в %s" +msgstr "Обращение изменений в %s" #: lib/merge.tcl:13 msgid "" "Cannot merge while amending.\n" "\n" "You must finish amending this commit before starting any type of merge.\n" -msgstr "" -"Невозможно выполнить слияние во время исправления.\n" -"\n" -"Завершите исправление данного состояния перед выполнением операции слияния.\n" +msgstr "Невозможно выполнить слияние во время исправления.\n\nЗавершите исправление данного коммита перед выполнением операции слияния.\n" #: lib/merge.tcl:27 msgid "" "Last scanned state does not match repository state.\n" "\n" -"Another Git program has modified this repository since the last scan. A " -"rescan must be performed before a merge can be performed.\n" +"Another Git program has modified this repository since the last scan. A rescan must be performed before a merge can be performed.\n" "\n" "The rescan will be automatically started now.\n" -msgstr "" -"Последнее прочитанное состояние репозитория не соответствует текущему.\n" -"\n" -"С момента последней проверки репозиторий был изменен другой программой Git. " -"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь.\n" -"\n" -"Это будет сделано сейчас автоматически.\n" +msgstr "Последнее прочитанное состояние репозитория не соответствует текущему.\n\nС момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем слияние может быть сделано.\n\nЭто будет сделано сейчас автоматически.\n" #: lib/merge.tcl:45 #, tcl-format @@ -1787,15 +1657,8 @@ msgid "" "\n" "File %s has merge conflicts.\n" "\n" -"You must resolve them, stage the file, and commit to complete the current " -"merge. Only then can you begin another merge.\n" -msgstr "" -"Предыдущее слияние не завершено из-за конфликта.\n" -"\n" -"Для файла %s возник конфликт слияния.\n" -"\n" -"Разрешите конфликт, подготовьте файл и сохраните. Только после этого можно " -"начать следующее слияние.\n" +"You must resolve them, stage the file, and commit to complete the current merge. Only then can you begin another merge.\n" +msgstr "Предыдущее слияние не завершено из-за конфликта.\n\nДля файла %s возник конфликт слияния.\n\nРазрешите конфликт, добавьте файл в индекс и закоммитьте. Только после этого можно начать следующее слияние.\n" #: lib/merge.tcl:55 #, tcl-format @@ -1804,15 +1667,8 @@ msgid "" "\n" "File %s is modified.\n" "\n" -"You should complete the current commit before starting a merge. Doing so " -"will help you abort a failed merge, should the need arise.\n" -msgstr "" -"Изменения не сохранены.\n" -"\n" -"Файл %s изменен.\n" -"\n" -"Подготовьте и сохраните изменения перед началом слияния. В случае " -"необходимости это позволит прервать операцию слияния.\n" +"You should complete the current commit before starting a merge. Doing so will help you abort a failed merge, should the need arise.\n" +msgstr "Вы находитесь в процессе изменений.\n\nФайл %s изменён.\n\nВы должны завершить текущий коммит перед началом слияния. В случае необходимости, это позволит прервать операцию слияния.\n" #: lib/merge.tcl:107 #, tcl-format @@ -1822,7 +1678,7 @@ msgstr "%s из %s" #: lib/merge.tcl:120 #, tcl-format msgid "Merging %s and %s..." -msgstr "Слияние %s и %s..." +msgstr "Слияние %s и %s…" #: lib/merge.tcl:131 msgid "Merge completed successfully." @@ -1846,10 +1702,7 @@ msgid "" "Cannot abort while amending.\n" "\n" "You must finish amending this commit.\n" -msgstr "" -"Невозможно прервать исправление.\n" -"\n" -"Завершите текущее исправление сохраненного состояния.\n" +msgstr "Невозможно прервать исправление.\n\nЗавершите текущее исправление коммита.\n" #: lib/merge.tcl:222 msgid "" @@ -1858,12 +1711,7 @@ msgid "" "Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" "\n" "Continue with aborting the current merge?" -msgstr "" -"Прервать операцию слияния?\n" -"\n" -"Прерывание этой операции приведет к потере *ВСЕХ* несохраненных изменений.\n" -"\n" -"Продолжить?" +msgstr "Прервать операцию слияния?\n\nПрерывание текущего слияния приведет к потере *ВСЕХ* несохраненных изменений.\n\nПродолжить?" #: lib/merge.tcl:228 msgid "" @@ -1872,12 +1720,7 @@ msgid "" "Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" "\n" "Continue with resetting the current changes?" -msgstr "" -"Прервать операцию слияния?\n" -"\n" -"Прерывание этой операции приведет к потере *ВСЕХ* несохраненных изменений.\n" -"\n" -"Продолжить?" +msgstr "Сбросить изменения?\n\nСброс изменений приведет к потере *ВСЕХ* несохраненных изменений.\n\nПродолжить?" #: lib/merge.tcl:239 msgid "Aborting" @@ -1901,11 +1744,11 @@ msgstr "Использовать базовую версию для разреш #: lib/mergetool.tcl:9 msgid "Force resolution to this branch?" -msgstr "Использовать версию этой ветви для разрешения конфликта?" +msgstr "Использовать версию из этой ветки для разрешения конфликта?" #: lib/mergetool.tcl:10 msgid "Force resolution to the other branch?" -msgstr "Использовать версию другой ветви для разрешения конфликта?" +msgstr "Использовать версию из другой ветки для разрешения конфликта?" #: lib/mergetool.tcl:14 #, tcl-format @@ -1915,19 +1758,12 @@ msgid "" "%s will be overwritten.\n" "\n" "This operation can be undone only by restarting the merge." -msgstr "" -"Внимание! Список изменений показывает только конфликтующие отличия.\n" -"\n" -"%s будет переписан.\n" -"\n" -"Это действие можно отменить только перезапуском операции слияния." +msgstr "Внимание! Список изменений показывает только конфликтующие отличия.\n\n%s будет переписан.\n\nЭто действие можно отменить только перезапуском операции слияния." #: lib/mergetool.tcl:45 #, tcl-format msgid "File %s seems to have unresolved conflicts, still stage?" -msgstr "" -"Файл %s, похоже, содержит необработанные конфликты. Продолжить подготовку к " -"сохранению?" +msgstr "Похоже, что файл %s содержит неразрешенные конфликты. Продолжить индексацию?" #: lib/mergetool.tcl:60 #, tcl-format @@ -1936,8 +1772,7 @@ msgstr "Добавляю результат разрешения для %s" #: lib/mergetool.tcl:141 msgid "Cannot resolve deletion or link conflicts using a tool" -msgstr "" -"Программа слияния не обрабатывает конфликты с удалением или участием ссылок" +msgstr "Программа слияния не обрабатывает конфликты с удалением или участием ссылок" #: lib/mergetool.tcl:146 msgid "Conflict file does not exist" @@ -1946,12 +1781,12 @@ msgstr "Конфликтующий файл не существует" #: lib/mergetool.tcl:264 #, tcl-format msgid "Not a GUI merge tool: '%s'" -msgstr "'%s' не является программой слияния" +msgstr "«%s» не является программой слияния" #: lib/mergetool.tcl:268 #, tcl-format msgid "Unsupported merge tool '%s'" -msgstr "Неизвестная программа слияния '%s'" +msgstr "Неподдерживаемая программа слияния «%s»" #: lib/mergetool.tcl:303 msgid "Merge tool is already running, terminate it?" @@ -1962,9 +1797,7 @@ msgstr "Программа слияния уже работает. Прерва msgid "" "Error retrieving versions:\n" "%s" -msgstr "" -"Ошибка получения версий:\n" -"%s" +msgstr "Ошибка получения версий:\n%s" #: lib/mergetool.tcl:343 #, tcl-format @@ -1972,14 +1805,11 @@ msgid "" "Could not start the merge tool:\n" "\n" "%s" -msgstr "" -"Ошибка запуска программы слияния:\n" -"\n" -"%s" +msgstr "Ошибка запуска программы слияния:\n\n%s" #: lib/mergetool.tcl:347 msgid "Running merge tool..." -msgstr "Запуск программы слияния..." +msgstr "Запуск программы слияния…" #: lib/mergetool.tcl:375 lib/mergetool.tcl:383 msgid "Merge tool failed." @@ -1988,12 +1818,12 @@ msgstr "Ошибка выполнения программы слияния." #: lib/option.tcl:11 #, tcl-format msgid "Invalid global encoding '%s'" -msgstr "Ошибка в глобальной установке кодировки '%s'" +msgstr "Неверная глобальная кодировка «%s»" #: lib/option.tcl:19 #, tcl-format msgid "Invalid repo encoding '%s'" -msgstr "Неверная кодировка репозитория: '%s'" +msgstr "Неверная кодировка репозитория «%s»" #: lib/option.tcl:117 msgid "Restore Defaults" @@ -2022,7 +1852,7 @@ msgstr "Адрес электронной почты" #: lib/option.tcl:141 msgid "Summarize Merge Commits" -msgstr "Суммарный комментарий при слиянии" +msgstr "Суммарное сообщение при слиянии" #: lib/option.tcl:142 msgid "Merge Verbosity" @@ -2042,11 +1872,11 @@ msgstr "Доверять времени модификации файла" #: lib/option.tcl:147 msgid "Prune Tracking Branches During Fetch" -msgstr "Чистка ветвей слежения при получении изменений" +msgstr "Чистка отслеживаемых веток при извлечении изменений" #: lib/option.tcl:148 msgid "Match Tracking Branches" -msgstr "Имя новой ветви взять из имен ветвей слежения" +msgstr "Такое же имя, как и у отслеживаемой ветки" #: lib/option.tcl:149 msgid "Blame Copy Only On Changed Files" @@ -2066,11 +1896,11 @@ msgstr "Число строк в контексте diff" #: lib/option.tcl:153 msgid "Commit Message Text Width" -msgstr "Ширина текста комментария" +msgstr "Ширина текста сообщения коммита" #: lib/option.tcl:154 msgid "New Branch Name Template" -msgstr "Шаблон для имени новой ветви" +msgstr "Шаблон для имени новой ветки" #: lib/option.tcl:155 msgid "Default File Contents Encoding" @@ -2093,7 +1923,6 @@ msgstr "Изменить" msgid "Choose %s" msgstr "Выберите %s" -# carbon copy #: lib/option.tcl:264 msgid "pt." msgstr "pt." @@ -2116,7 +1945,7 @@ msgstr "Чистка" #: lib/remote.tcl:173 msgid "Fetch from" -msgstr "Получение из" +msgstr "Извлечение из" #: lib/remote.tcl:215 msgid "Push to" @@ -2132,7 +1961,7 @@ msgstr "Добавить внешний репозиторий" #: lib/remote_add.tcl:28 lib/tools_dlg.tcl:36 msgid "Add" -msgstr "" +msgstr "Добавить" #: lib/remote_add.tcl:37 msgid "Remote Details" @@ -2148,7 +1977,7 @@ msgstr "Следующая операция" #: lib/remote_add.tcl:65 msgid "Fetch Immediately" -msgstr "Скачать сразу" +msgstr "Сразу извлечь изменения" #: lib/remote_add.tcl:71 msgid "Initialize Remote Repository and Push" @@ -2165,27 +1994,27 @@ msgstr "Укажите название внешнего репозитория. #: lib/remote_add.tcl:114 #, tcl-format msgid "'%s' is not an acceptable remote name." -msgstr "Недопустимое название внешнего репозитория '%s'." +msgstr "«%s» не является допустимым именем внешнего репозитория." #: lib/remote_add.tcl:125 #, tcl-format msgid "Failed to add remote '%s' of location '%s'." -msgstr "Не удалось добавить '%s' из '%s'. " +msgstr "Не удалось добавить «%s» из «%s». " #: lib/remote_add.tcl:133 lib/transport.tcl:6 #, tcl-format msgid "fetch %s" -msgstr "получение %s" +msgstr "извлечение %s" #: lib/remote_add.tcl:134 #, tcl-format msgid "Fetching the %s" -msgstr "Получение %s" +msgstr "Извлечение %s" #: lib/remote_add.tcl:157 #, tcl-format msgid "Do not know how to initialize repository at location '%s'." -msgstr "Невозможно инициализировать репозиторий в '%s'." +msgstr "Невозможно инициализировать репозиторий в «%s»." #: lib/remote_add.tcl:163 lib/transport.tcl:25 lib/transport.tcl:63 #: lib/transport.tcl:81 @@ -2200,7 +2029,7 @@ msgstr "Настройка %s (в %s)" #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 msgid "Delete Branch Remotely" -msgstr "Удаление ветви во внешнем репозитории" +msgstr "Удаление ветки во внешнем репозитории" #: lib/remote_branch_delete.tcl:47 msgid "From Repository" @@ -2216,7 +2045,7 @@ msgstr "Указанное положение:" #: lib/remote_branch_delete.tcl:84 msgid "Branches" -msgstr "Ветви" +msgstr "Ветки" #: lib/remote_branch_delete.tcl:109 msgid "Delete Only If" @@ -2228,7 +2057,7 @@ msgstr "Слияние с:" #: lib/remote_branch_delete.tcl:152 msgid "A branch is required for 'Merged Into'." -msgstr "Для опции 'Слияние с' требуется указать ветвь." +msgstr "Для операции «Слияние с» требуется указать ветку." #: lib/remote_branch_delete.tcl:184 #, tcl-format @@ -2236,28 +2065,23 @@ msgid "" "The following branches are not completely merged into %s:\n" "\n" " - %s" -msgstr "" -"Следующие ветви могут быть объединены с %s при помощи операции слияния:\n" -"\n" -" - %s" +msgstr "Следующие ветки могут быть объединены с %s при помощи операции слияния:\n\n - %s" #: lib/remote_branch_delete.tcl:189 #, tcl-format msgid "" "One or more of the merge tests failed because you have not fetched the " "necessary commits. Try fetching from %s first." -msgstr "" -"Некоторые тесты на слияние не прошли, потому что Вы не получили необходимые " -"состояния. Попытайтесь получить их из %s." +msgstr "Некоторые тесты на слияние не прошли, потому что вы не извлекли необходимые коммиты. Попытайтесь извлечь их из %s." #: lib/remote_branch_delete.tcl:207 msgid "Please select one or more branches to delete." -msgstr "Укажите одну или несколько ветвей для удаления." +msgstr "Укажите одну или несколько веток для удаления." #: lib/remote_branch_delete.tcl:226 #, tcl-format msgid "Deleting branches from %s" -msgstr "Удаление ветвей из %s" +msgstr "Удаление веток из %s" #: lib/remote_branch_delete.tcl:292 msgid "No repository selected." @@ -2266,7 +2090,7 @@ msgstr "Не указан репозиторий." #: lib/remote_branch_delete.tcl:297 #, tcl-format msgid "Scanning %s..." -msgstr "Перечитывание %s... " +msgstr "Перечитывание %s…" #: lib/search.tcl:21 msgid "Find:" @@ -2352,7 +2176,7 @@ msgstr "Ваш публичный ключ OpenSSH" #: lib/sshkey.tcl:78 msgid "Generating..." -msgstr "Создание..." +msgstr "Создание…" #: lib/sshkey.tcl:84 #, tcl-format @@ -2360,10 +2184,7 @@ msgid "" "Could not start ssh-keygen:\n" "\n" "%s" -msgstr "" -"Ошибка запуска ssh-keygen:\n" -"\n" -"%s" +msgstr "Ошибка запуска ssh-keygen:\n\n%s" #: lib/sshkey.tcl:111 msgid "Generation failed." @@ -2381,7 +2202,7 @@ msgstr "Ваш ключ находится в: %s" #: lib/status_bar.tcl:83 #, tcl-format msgid "%s ... %*i of %*i %s (%3i%%)" -msgstr "%s ... %*i из %*i %s (%3i%%)" +msgstr "%s … %*i из %*i %s (%3i%%)" #: lib/tools.tcl:75 #, tcl-format @@ -2431,7 +2252,7 @@ msgstr "Описание вспомогательной операции" #: lib/tools_dlg.tcl:48 msgid "Use '/' separators to create a submenu tree:" -msgstr "Используйте '/' для создания подменю" +msgstr "Используйте «/» для создания подменю" #: lib/tools_dlg.tcl:61 msgid "Command:" @@ -2464,16 +2285,14 @@ msgstr "Укажите название вспомогательной опер #: lib/tools_dlg.tcl:129 #, tcl-format msgid "Tool '%s' already exists." -msgstr "Вспомогательная операция '%s' уже существует." +msgstr "Вспомогательная операция «%s» уже существует." #: lib/tools_dlg.tcl:151 #, tcl-format msgid "" "Could not add tool:\n" "%s" -msgstr "" -"Ошибка добавления программы:\n" -"%s" +msgstr "Ошибка добавления программы:\n%s" #: lib/tools_dlg.tcl:190 msgid "Remove Tool" @@ -2507,9 +2326,8 @@ msgstr "OK" #: lib/transport.tcl:7 #, tcl-format msgid "Fetching new changes from %s" -msgstr "Получение изменений из %s " +msgstr "Извлечение изменений из %s " -# carbon copy #: lib/transport.tcl:18 #, tcl-format msgid "remote prune %s" @@ -2518,7 +2336,7 @@ msgstr "чистка внешнего %s" #: lib/transport.tcl:19 #, tcl-format msgid "Pruning tracking branches deleted from %s" -msgstr "Чистка ветвей слежения, удаленных из %s" +msgstr "Чистка отслеживаемых веток, удалённых из %s" #: lib/transport.tcl:26 #, tcl-format @@ -2537,11 +2355,11 @@ msgstr "Отправка %s %s в %s" #: lib/transport.tcl:100 msgid "Push Branches" -msgstr "Отправить изменения в ветвях" +msgstr "Отправить ветки" #: lib/transport.tcl:114 msgid "Source Branches" -msgstr "Исходные ветви" +msgstr "Исходные ветки" #: lib/transport.tcl:131 msgid "Destination Repository" @@ -2553,7 +2371,7 @@ msgstr "Настройки отправки" #: lib/transport.tcl:171 msgid "Force overwrite existing branch (may discard changes)" -msgstr "Намеренно переписать существующую ветвь (возможна потеря изменений)" +msgstr "Принудительно перезаписать существующую ветку (возможна потеря изменений)" #: lib/transport.tcl:175 msgid "Use thin pack (for slow network connections)" diff --git a/git-mergetool.sh b/git-mergetool.sh index bf86270..e52b4e4 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -3,12 +3,13 @@ # This program resolves merge conflicts in git # # Copyright (c) 2006 Theodore Y. Ts'o +# Copyright (c) 2009-2016 David Aguilar # # This file is licensed under the GPL v2, or a later version # at the discretion of Junio C Hamano. # -USAGE='[--tool=tool] [--tool-help] [-y|--no-prompt|--prompt] [file to merge] ...' +USAGE='[--tool=tool] [--tool-help] [-y|--no-prompt|--prompt] [-O] [file to merge] ...' SUBDIRECTORY_OK=Yes NONGIT_OK=Yes OPTIONS_SPEC= @@ -365,51 +366,6 @@ merge_file () { return 0 } -prompt=$(git config --bool mergetool.prompt) -guessed_merge_tool=false - -while test $# != 0 -do - case "$1" in - --tool-help=*) - TOOL_MODE=${1#--tool-help=} - show_tool_help - ;; - --tool-help) - show_tool_help - ;; - -t|--tool*) - case "$#,$1" in - *,*=*) - merge_tool=$(expr "z$1" : 'z-[^=]*=\(.*\)') - ;; - 1,*) - usage ;; - *) - merge_tool="$2" - shift ;; - esac - ;; - -y|--no-prompt) - prompt=false - ;; - --prompt) - prompt=true - ;; - --) - shift - break - ;; - -*) - usage - ;; - *) - break - ;; - esac - shift -done - prompt_after_failed_merge () { while true do @@ -426,57 +382,113 @@ prompt_after_failed_merge () { done } -git_dir_init -require_work_tree +print_noop_and_exit () { + echo "No files need merging" + exit 0 +} + +main () { + prompt=$(git config --bool mergetool.prompt) + guessed_merge_tool=false + orderfile= + + while test $# != 0 + do + case "$1" in + --tool-help=*) + TOOL_MODE=${1#--tool-help=} + show_tool_help + ;; + --tool-help) + show_tool_help + ;; + -t|--tool*) + case "$#,$1" in + *,*=*) + merge_tool=$(expr "z$1" : 'z-[^=]*=\(.*\)') + ;; + 1,*) + usage ;; + *) + merge_tool="$2" + shift ;; + esac + ;; + -y|--no-prompt) + prompt=false + ;; + --prompt) + prompt=true + ;; + -O*) + orderfile="$1" + ;; + --) + shift + break + ;; + -*) + usage + ;; + *) + break + ;; + esac + shift + done + + git_dir_init + require_work_tree -if test -z "$merge_tool" -then - # Check if a merge tool has been configured - merge_tool=$(get_configured_merge_tool) - # Try to guess an appropriate merge tool if no tool has been set. if test -z "$merge_tool" then - merge_tool=$(guess_merge_tool) || exit - guessed_merge_tool=true + # Check if a merge tool has been configured + merge_tool=$(get_configured_merge_tool) + # Try to guess an appropriate merge tool if no tool has been set. + if test -z "$merge_tool" + then + merge_tool=$(guess_merge_tool) || exit + guessed_merge_tool=true + fi + fi + merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)" + merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)" + + if test $# -eq 0 && test -e "$GIT_DIR/MERGE_RR" + then + set -- $(git rerere remaining) + if test $# -eq 0 + then + print_noop_and_exit + fi fi -fi -merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)" -merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)" -files= + files=$(git -c core.quotePath=false \ + diff --name-only --diff-filter=U \ + ${orderfile:+"$orderfile"} -- "$@") -if test $# -eq 0 -then cd_to_toplevel - if test -e "$GIT_DIR/MERGE_RR" + if test -z "$files" then - files=$(git rerere remaining) - else - files=$(git ls-files -u | sed -e 's/^[^ ]* //' | sort -u) + print_noop_and_exit fi -else - files=$(git ls-files -u -- "$@" | sed -e 's/^[^ ]* //' | sort -u) -fi -if test -z "$files" -then - echo "No files need merging" - exit 0 -fi + printf "Merging:\n" + printf "%s\n" "$files" -printf "Merging:\n" -printf "%s\n" "$files" + rc=0 + for i in $files + do + printf "\n" + if ! merge_file "$i" + then + rc=1 + prompt_after_failed_merge || exit 1 + fi + done -rc=0 -for i in $files -do - printf "\n" - if ! merge_file "$i" - then - rc=1 - prompt_after_failed_merge || exit 1 - fi -done + exit $rc +} -exit $rc +main "$@" diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index ca994c5..41fd374 100644 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -93,8 +93,17 @@ eval ' GIT_CHERRY_PICK_HELP="$resolvemsg" export GIT_CHERRY_PICK_HELP -comment_char=$(git config --get core.commentchar 2>/dev/null | cut -c1) -: ${comment_char:=#} +comment_char=$(git config --get core.commentchar 2>/dev/null) +case "$comment_char" in +'' | auto) + comment_char="#" + ;; +?) + ;; +*) + comment_char=$(echo "$comment_char" | cut -c1) + ;; +esac warn () { printf '%s\n' "$*" >&2 diff --git a/git-stash.sh b/git-stash.sh index 826af18..4546aba 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -100,7 +100,7 @@ create_stash () { u_tree=$(git write-tree) && printf 'untracked files on %s\n' "$msg" | git commit-tree $u_tree && rm -f "$TMPindex" - ) ) || die "Cannot save the untracked files" + ) ) || die "$(gettext "Cannot save the untracked files")" untracked_commit_option="-p $u_commit"; else @@ -248,7 +248,7 @@ save_stash () { if test -n "$patch_mode" && test -n "$untracked" then - die "Can't use --patch and --include-untracked or --all at the same time" + die "$(gettext "Can't use --patch and --include-untracked or --all at the same time")" fi stash_msg="$*" @@ -384,9 +384,8 @@ parse_flags_and_rev() i_tree= u_tree= - REV=$(git rev-parse --no-flags --symbolic --sq "$@") || exit 1 - FLAGS= + REV= for opt do case "$opt" in @@ -404,6 +403,9 @@ parse_flags_and_rev() die "$(eval_gettext "unknown option: \$opt")" FLAGS="${FLAGS}${FLAGS:+ }$opt" ;; + *) + REV="${REV}${REV:+ }'$opt'" + ;; esac done @@ -422,6 +424,15 @@ parse_flags_and_rev() ;; esac + case "$1" in + *[!0-9]*) + : + ;; + *) + set -- "${ref_stash}@{$1}" + ;; + esac + REV=$(git rev-parse --symbolic --verify --quiet "$1") || { reference="$1" die "$(eval_gettext "\$reference is not a valid reference")" @@ -494,7 +505,7 @@ apply_stash () { GIT_INDEX_FILE="$TMPindex" git-read-tree "$u_tree" && GIT_INDEX_FILE="$TMPindex" git checkout-index --all && rm -f "$TMPindex" || - die 'Could not restore untracked files from stash' + die "$(gettext "Could not restore untracked files from stash")" fi eval " diff --git a/git-submodule.sh b/git-submodule.sh index b57f87d..a024a13 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -44,6 +44,7 @@ update= prefix= custom_name= depth= +progress= die_if_unmatched () { @@ -498,6 +499,9 @@ cmd_update() -q|--quiet) GIT_QUIET=1 ;; + --progress) + progress="--progress" + ;; -i|--init) init=1 ;; @@ -573,10 +577,11 @@ cmd_update() { git submodule--helper update-clone ${GIT_QUIET:+--quiet} \ + ${progress:+"$progress"} \ ${wt_prefix:+--prefix "$wt_prefix"} \ ${prefix:+--recursive-prefix "$prefix"} \ ${update:+--update "$update"} \ - ${reference:+--reference "$reference"} \ + ${reference:+"$reference"} \ ${depth:+--depth "$depth"} \ ${recommend_shallow:+"$recommend_shallow"} \ ${jobs:+$jobs} \ diff --git a/git-svn.perl b/git-svn.perl index 4d41d22..fa42364 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -44,6 +44,7 @@ use Git qw( command_close_pipe command_bidi_pipe command_close_bidi_pipe + get_record ); BEGIN { @@ -1699,7 +1700,7 @@ sub cmd_gc { "files will not be compressed.\n"; } File::Find::find({ wanted => \&gc_directory, no_chdir => 1}, - "$ENV{GIT_DIR}/svn"); + Git::SVN::svn_dir()); } ########################### utility functions ######################### @@ -1733,7 +1734,7 @@ sub post_fetch_checkout { return unless verify_ref('HEAD^0'); return if $ENV{GIT_DIR} !~ m#^(?:.*/)?\.git$#; - my $index = $ENV{GIT_INDEX_FILE} || "$ENV{GIT_DIR}/index"; + my $index = command_oneline(qw(rev-parse --git-path index)); return if -f $index; return if command_oneline(qw/rev-parse --is-inside-work-tree/) eq 'false'; @@ -1835,8 +1836,9 @@ sub get_tree_from_treeish { sub get_commit_entry { my ($treeish) = shift; my %log_entry = ( log => '', tree => get_tree_from_treeish($treeish) ); - my $commit_editmsg = "$ENV{GIT_DIR}/COMMIT_EDITMSG"; - my $commit_msg = "$ENV{GIT_DIR}/COMMIT_MSG"; + my @git_path = qw(rev-parse --git-path); + my $commit_editmsg = command_oneline(@git_path, 'COMMIT_EDITMSG'); + my $commit_msg = command_oneline(@git_path, 'COMMIT_MSG'); open my $log_fh, '>', $commit_editmsg or croak $!; my $type = command_oneline(qw/cat-file -t/, $treeish); @@ -1880,10 +1882,9 @@ sub get_commit_entry { { require Encode; # SVN requires messages to be UTF-8 when entering the repo - local $/; open $log_fh, '<', $commit_msg or croak $!; binmode $log_fh; - chomp($log_entry{log} = <$log_fh>); + chomp($log_entry{log} = get_record($log_fh, undef)); my $enc = Git::config('i18n.commitencoding') || 'UTF-8'; my $msg = $log_entry{log}; diff --git a/git.c b/git.c index 7acf290..dce529f 100644 --- a/git.c +++ b/git.c @@ -163,6 +163,20 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) setenv(GIT_WORK_TREE_ENVIRONMENT, cmd, 1); if (envchanged) *envchanged = 1; + } else if (!strcmp(cmd, "--super-prefix")) { + if (*argc < 2) { + fprintf(stderr, "No prefix given for --super-prefix.\n" ); + usage(git_usage_string); + } + setenv(GIT_SUPER_PREFIX_ENVIRONMENT, (*argv)[1], 1); + if (envchanged) + *envchanged = 1; + (*argv)++; + (*argc)--; + } else if (skip_prefix(cmd, "--super-prefix=", &cmd)) { + setenv(GIT_SUPER_PREFIX_ENVIRONMENT, cmd, 1); + if (envchanged) + *envchanged = 1; } else if (!strcmp(cmd, "--bare")) { char *cwd = xgetcwd(); is_bare_repository_cfg = 1; @@ -309,6 +323,7 @@ static int handle_alias(int *argcp, const char ***argv) * RUN_SETUP for reading from the configuration file. */ #define NEED_WORK_TREE (1<<3) +#define SUPPORT_SUPER_PREFIX (1<<4) struct cmd_struct { const char *cmd; @@ -343,6 +358,13 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) } commit_pager_choice(); + if (!help && get_super_prefix()) { + if (!(p->option & SUPPORT_SUPER_PREFIX)) + die("%s doesn't support --super-prefix", p->cmd); + if (prefix) + die("can't use --super-prefix from a subdirectory"); + } + if (!help && p->option & NEED_WORK_TREE) setup_work_tree(); @@ -374,7 +396,7 @@ static struct cmd_struct commands[] = { { "am", cmd_am, RUN_SETUP | NEED_WORK_TREE }, { "annotate", cmd_annotate, RUN_SETUP }, { "apply", cmd_apply, RUN_SETUP_GENTLY }, - { "archive", cmd_archive }, + { "archive", cmd_archive, RUN_SETUP_GENTLY }, { "bisect--helper", cmd_bisect__helper, RUN_SETUP }, { "blame", cmd_blame, RUN_SETUP }, { "branch", cmd_branch, RUN_SETUP }, @@ -420,10 +442,10 @@ static struct cmd_struct commands[] = { { "init-db", cmd_init_db }, { "interpret-trailers", cmd_interpret_trailers, RUN_SETUP_GENTLY }, { "log", cmd_log, RUN_SETUP }, - { "ls-files", cmd_ls_files, RUN_SETUP }, + { "ls-files", cmd_ls_files, RUN_SETUP | SUPPORT_SUPER_PREFIX }, { "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY }, { "ls-tree", cmd_ls_tree, RUN_SETUP }, - { "mailinfo", cmd_mailinfo }, + { "mailinfo", cmd_mailinfo, RUN_SETUP_GENTLY }, { "mailsplit", cmd_mailsplit }, { "merge", cmd_merge, RUN_SETUP | NEED_WORK_TREE }, { "merge-base", cmd_merge_base, RUN_SETUP }, @@ -443,7 +465,7 @@ static struct cmd_struct commands[] = { { "pack-objects", cmd_pack_objects, RUN_SETUP }, { "pack-redundant", cmd_pack_redundant, RUN_SETUP }, { "pack-refs", cmd_pack_refs, RUN_SETUP }, - { "patch-id", cmd_patch_id }, + { "patch-id", cmd_patch_id, RUN_SETUP_GENTLY }, { "pickaxe", cmd_blame, RUN_SETUP }, { "prune", cmd_prune, RUN_SETUP }, { "prune-packed", cmd_prune_packed, RUN_SETUP }, @@ -521,21 +543,34 @@ static void strip_extension(const char **argv) static void handle_builtin(int argc, const char **argv) { + struct argv_array args = ARGV_ARRAY_INIT; const char *cmd; struct cmd_struct *builtin; strip_extension(argv); cmd = argv[0]; - /* Turn "git cmd --help" into "git help cmd" */ + /* Turn "git cmd --help" into "git help --exclude-guides cmd" */ if (argc > 1 && !strcmp(argv[1], "--help")) { + int i; + argv[1] = argv[0]; argv[0] = cmd = "help"; + + for (i = 0; i < argc; i++) { + argv_array_push(&args, argv[i]); + if (!i) + argv_array_push(&args, "--exclude-guides"); + } + + argc++; + argv = args.argv; } builtin = get_builtin(cmd); if (builtin) exit(run_builtin(builtin, argc, argv)); + argv_array_clear(&args); } static void execv_dashed_external(const char **argv) @@ -544,6 +579,9 @@ static void execv_dashed_external(const char **argv) const char *tmp; int status; + if (get_super_prefix()) + die("%s doesn't support --super-prefix", argv[0]); + if (use_pager == -1) use_pager = check_pager_config(argv[0]); commit_pager_choice(); diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 33d701d..7cf68f0 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1616,7 +1616,7 @@ sub esc_path { return $str; } -# Sanitize for use in XHTML + application/xml+xhtm (valid XML 1.0) +# Sanitize for use in XHTML + application/xml+xhtml (valid XML 1.0) sub sanitize { my $str = shift; @@ -2036,10 +2036,24 @@ sub format_log_line_html { my $line = shift; $line = esc_html($line, -nbsp=>1); - $line =~ s{\b([0-9a-fA-F]{8,40})\b}{ + $line =~ s{ + \b + ( + # The output of "git describe", e.g. v2.10.0-297-gf6727b0 + # or hadoop-20160921-113441-20-g094fb7d + (?a({-href => href(action=>"object", hash=>$1), -class => "text"}, $1); - }eg; + }egx; return $line; } @@ -3913,7 +3927,7 @@ sub blob_contenttype { # guess file syntax for syntax highlighting; return undef if no highlighting # the name of syntax can (in the future) depend on syntax highlighter used sub guess_file_syntax { - my ($highlight, $mimetype, $file_name) = @_; + my ($highlight, $file_name) = @_; return undef unless ($highlight && defined $file_name); my $basename = basename($file_name, '.in'); return $highlight_basename{$basename} @@ -3931,15 +3945,16 @@ sub guess_file_syntax { # or return original FD if no highlighting sub run_highlighter { my ($fd, $highlight, $syntax) = @_; - return $fd unless ($highlight && defined $syntax); + return $fd unless ($highlight); close $fd; + my $syntax_arg = (defined $syntax) ? "--syntax $syntax" : "--force"; 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 |" + " --replace-tabs=8 --fragment $syntax_arg |" or die_error(500, "Couldn't open file or run syntax highlighter"); return $fd; } @@ -7062,9 +7077,8 @@ sub git_blob { $have_blame &&= ($mimetype =~ m!^text/!); my $highlight = gitweb_check_feature('highlight'); - my $syntax = guess_file_syntax($highlight, $mimetype, $file_name); - $fd = run_highlighter($fd, $highlight, $syntax) - if $syntax; + my $syntax = guess_file_syntax($highlight, $file_name); + $fd = run_highlighter($fd, $highlight, $syntax); git_header_html(undef, $expires); my $formats_nav = ''; @@ -7117,7 +7131,7 @@ sub git_blob { $line = untabify($line); printf qq!\n!, $nr, esc_attr(href(-replay => 1)), $nr, $nr, - $syntax ? sanitize($line) : esc_html($line, -nbsp=>1); + $highlight ? sanitize($line) : esc_html($line, -nbsp=>1); } } close $fd diff --git a/gpg-interface.c b/gpg-interface.c index 8672eda..e44cc27 100644 --- a/gpg-interface.c +++ b/gpg-interface.c @@ -33,6 +33,10 @@ static struct { { 'B', "\n[GNUPG:] BADSIG " }, { 'U', "\n[GNUPG:] TRUST_NEVER" }, { 'U', "\n[GNUPG:] TRUST_UNDEFINED" }, + { 'E', "\n[GNUPG:] ERRSIG "}, + { 'X', "\n[GNUPG:] EXPSIG "}, + { 'Y', "\n[GNUPG:] EXPKEYSIG "}, + { 'R', "\n[GNUPG:] REVKEYSIG "}, }; void parse_gpg_output(struct signature_check *sigc) @@ -54,9 +58,12 @@ void parse_gpg_output(struct signature_check *sigc) /* The trust messages are not followed by key/signer information */ if (sigc->result != 'U') { sigc->key = xmemdupz(found, 16); - found += 17; - next = strchrnul(found, '\n'); - sigc->signer = xmemdupz(found, next - found); + /* The ERRSIG message is not followed by signer information */ + if (sigc-> result != 'E') { + found += 17; + next = strchrnul(found, '\n'); + sigc->signer = xmemdupz(found, next - found); + } } } } diff --git a/graph.c b/graph.c index 4200f74..d4e8519 100644 --- a/graph.c +++ b/graph.c @@ -2,7 +2,6 @@ #include "commit.h" #include "color.h" #include "graph.h" -#include "diff.h" #include "revision.h" /* Internal API */ @@ -28,8 +27,15 @@ static void graph_padding_line(struct git_graph *graph, struct strbuf *sb); * responsible for printing this line's graph (perhaps via * graph_show_commit() or graph_show_oneline()) before calling * graph_show_strbuf(). + * + * Note that unlike some other graph display functions, you must pass the file + * handle directly. It is assumed that this is the same file handle as the + * file specified by the graph diff options. This is necessary so that + * graph_show_strbuf can be called even with a NULL graph. */ -static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb); +static void graph_show_strbuf(struct git_graph *graph, + FILE *file, + struct strbuf const *sb); /* * TODO: @@ -59,6 +65,17 @@ enum graph_state { GRAPH_COLLAPSING }; +static void graph_show_line_prefix(const struct diff_options *diffopt) +{ + if (!diffopt || !diffopt->line_prefix) + return; + + fwrite(diffopt->line_prefix, + sizeof(char), + diffopt->line_prefix_length, + diffopt->file); +} + static const char **column_colors; static unsigned short column_colors_max; @@ -195,14 +212,28 @@ static struct strbuf *diff_output_prefix_callback(struct diff_options *opt, void static struct strbuf msgbuf = STRBUF_INIT; assert(opt); - assert(graph); - opt->output_prefix_length = graph->width; strbuf_reset(&msgbuf); - graph_padding_line(graph, &msgbuf); + if (opt->line_prefix) + strbuf_add(&msgbuf, opt->line_prefix, + opt->line_prefix_length); + if (graph) + graph_padding_line(graph, &msgbuf); return &msgbuf; } +static const struct diff_options *default_diffopt; + +void graph_setup_line_prefix(struct diff_options *diffopt) +{ + default_diffopt = diffopt; + + /* setup an output prefix callback if necessary */ + if (diffopt && !diffopt->output_prefix) + diffopt->output_prefix = diff_output_prefix_callback; +} + + struct git_graph *graph_init(struct rev_info *opt) { struct git_graph *graph = xmalloc(sizeof(struct git_graph)); @@ -245,7 +276,6 @@ struct git_graph *graph_init(struct rev_info *opt) */ opt->diffopt.output_prefix = diff_output_prefix_callback; opt->diffopt.output_prefix_data = graph; - opt->diffopt.output_prefix_length = 0; return graph; } @@ -1193,6 +1223,8 @@ void graph_show_commit(struct git_graph *graph) struct strbuf msgbuf = STRBUF_INIT; int shown_commit_line = 0; + graph_show_line_prefix(default_diffopt); + if (!graph) return; @@ -1210,8 +1242,10 @@ void graph_show_commit(struct git_graph *graph) shown_commit_line = graph_next_line(graph, &msgbuf); fwrite(msgbuf.buf, sizeof(char), msgbuf.len, graph->revs->diffopt.file); - if (!shown_commit_line) + if (!shown_commit_line) { putc('\n', graph->revs->diffopt.file); + graph_show_line_prefix(&graph->revs->diffopt); + } strbuf_setlen(&msgbuf, 0); } @@ -1222,6 +1256,8 @@ void graph_show_oneline(struct git_graph *graph) { struct strbuf msgbuf = STRBUF_INIT; + graph_show_line_prefix(default_diffopt); + if (!graph) return; @@ -1234,6 +1270,8 @@ void graph_show_padding(struct git_graph *graph) { struct strbuf msgbuf = STRBUF_INIT; + graph_show_line_prefix(default_diffopt); + if (!graph) return; @@ -1247,6 +1285,8 @@ int graph_show_remainder(struct git_graph *graph) struct strbuf msgbuf = STRBUF_INIT; int shown = 0; + graph_show_line_prefix(default_diffopt); + if (!graph) return 0; @@ -1260,27 +1300,24 @@ int graph_show_remainder(struct git_graph *graph) strbuf_setlen(&msgbuf, 0); shown = 1; - if (!graph_is_commit_finished(graph)) + if (!graph_is_commit_finished(graph)) { putc('\n', graph->revs->diffopt.file); - else + graph_show_line_prefix(&graph->revs->diffopt); + } else { break; + } } strbuf_release(&msgbuf); return shown; } - -static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb) +static void graph_show_strbuf(struct git_graph *graph, + FILE *file, + struct strbuf const *sb) { char *p; - if (!graph) { - fwrite(sb->buf, sizeof(char), sb->len, - graph->revs->diffopt.file); - return; - } - /* * Print the strbuf line by line, * and display the graph info before each line but the first. @@ -1295,7 +1332,7 @@ static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb) } else { len = (sb->buf + sb->len) - p; } - fwrite(p, sizeof(char), len, graph->revs->diffopt.file); + fwrite(p, sizeof(char), len, file); if (next_p && *next_p != '\0') graph_show_oneline(graph); p = next_p; @@ -1303,29 +1340,20 @@ static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb) } void graph_show_commit_msg(struct git_graph *graph, + FILE *file, struct strbuf const *sb) { int newline_terminated; - if (!graph) { - /* - * If there's no graph, just print the message buffer. - * - * The message buffer for CMIT_FMT_ONELINE and - * CMIT_FMT_USERFORMAT are already missing a terminating - * newline. All of the other formats should have it. - */ - fwrite(sb->buf, sizeof(char), sb->len, - graph->revs->diffopt.file); - return; - } - - newline_terminated = (sb->len && sb->buf[sb->len - 1] == '\n'); - /* * Show the commit message */ - graph_show_strbuf(graph, sb); + graph_show_strbuf(graph, file, sb); + + if (!graph) + return; + + newline_terminated = (sb->len && sb->buf[sb->len - 1] == '\n'); /* * If there is more output needed for this commit, show it now @@ -1337,7 +1365,7 @@ void graph_show_commit_msg(struct git_graph *graph, * new line. */ if (!newline_terminated) - putc('\n', graph->revs->diffopt.file); + putc('\n', file); graph_show_remainder(graph); @@ -1345,6 +1373,6 @@ void graph_show_commit_msg(struct git_graph *graph, * If sb ends with a newline, our output should too. */ if (newline_terminated) - putc('\n', graph->revs->diffopt.file); + putc('\n', file); } } diff --git a/graph.h b/graph.h index 3f48c19..af62339 100644 --- a/graph.h +++ b/graph.h @@ -1,10 +1,23 @@ #ifndef GRAPH_H #define GRAPH_H +#include "diff.h" /* A graph is a pointer to this opaque structure */ struct git_graph; /* + * Called to setup global display of line_prefix diff option. + * + * Passed a diff_options structure which indicates the line_prefix and the + * file to output the prefix to. This is sort of a hack used so that the + * line_prefix will be honored by all flows which also honor "--graph" + * regardless of whether a graph has actually been setup. The normal graph + * flow will honor the exact diff_options passed, but a NULL graph will cause + * display of a line_prefix to stdout. + */ +void graph_setup_line_prefix(struct diff_options *diffopt); + +/* * Set up a custom scheme for column colors. * * The default column color scheme inserts ANSI color escapes to colorize @@ -113,7 +126,14 @@ int graph_show_remainder(struct git_graph *graph); * missing a terminating newline (including if it is empty), the output * printed by graph_show_commit_msg() will also be missing a terminating * newline. + * + * Note that unlike some other graph display functions, you must pass the file + * handle directly. It is assumed that this is the same file handle as the + * file specified by the graph diff options. This is necessary so that + * graph_show_commit_msg can be called even with a NULL graph. */ -void graph_show_commit_msg(struct git_graph *graph, struct strbuf const *sb); +void graph_show_commit_msg(struct git_graph *graph, + FILE *file, + struct strbuf const *sb); #endif /* GRAPH_H */ diff --git a/help.c b/help.c index 2ff3b5a..53e2a67 100644 --- a/help.c +++ b/help.c @@ -170,8 +170,7 @@ void load_command_list(const char *prefix, if (exec_path) { list_commands_in_dir(main_cmds, exec_path, prefix); - qsort(main_cmds->names, main_cmds->cnt, - sizeof(*main_cmds->names), cmdname_compare); + QSORT(main_cmds->names, main_cmds->cnt, cmdname_compare); uniq(main_cmds); } @@ -190,8 +189,7 @@ void load_command_list(const char *prefix, } free(paths); - qsort(other_cmds->names, other_cmds->cnt, - sizeof(*other_cmds->names), cmdname_compare); + QSORT(other_cmds->names, other_cmds->cnt, cmdname_compare); uniq(other_cmds); } exclude_cmds(other_cmds, main_cmds); @@ -238,8 +236,7 @@ void list_common_cmds_help(void) longest = strlen(common_cmds[i].name); } - qsort(common_cmds, ARRAY_SIZE(common_cmds), - sizeof(common_cmds[0]), cmd_group_cmp); + QSORT(common_cmds, ARRAY_SIZE(common_cmds), cmd_group_cmp); puts(_("These are common Git commands used in various situations:")); @@ -324,8 +321,7 @@ const char *help_unknown_cmd(const char *cmd) add_cmd_list(&main_cmds, &aliases); add_cmd_list(&main_cmds, &other_cmds); - qsort(main_cmds.names, main_cmds.cnt, - sizeof(*main_cmds.names), cmdname_compare); + QSORT(main_cmds.names, main_cmds.cnt, cmdname_compare); uniq(&main_cmds); /* This abuses cmdname->len for levenshtein distance */ @@ -359,8 +355,7 @@ const char *help_unknown_cmd(const char *cmd) levenshtein(cmd, candidate, 0, 2, 1, 3) + 1; } - qsort(main_cmds.names, main_cmds.cnt, - sizeof(*main_cmds.names), levenshtein_compare); + QSORT(main_cmds.names, main_cmds.cnt, levenshtein_compare); if (!main_cmds.cnt) die(_("Uh oh. Your system reports no Git commands at all.")); diff --git a/http-backend.c b/http-backend.c index adc8c8c..eef0a36 100644 --- a/http-backend.c +++ b/http-backend.c @@ -464,7 +464,7 @@ static void get_info_refs(struct strbuf *hdr, char *arg) hdr_str(hdr, content_type, buf.buf); end_headers(hdr); - packet_write(1, "# service=git-%s\n", svc->name); + packet_write_fmt(1, "# service=git-%s\n", svc->name); packet_flush(1); argv[0] = svc->name; diff --git a/http.c b/http.c index bd0dba2..4c4a812 100644 --- a/http.c +++ b/http.c @@ -90,6 +90,18 @@ static struct { * here, too */ }; +#if LIBCURL_VERSION_NUM >= 0x071600 +static const char *curl_deleg; +static struct { + const char *name; + long curl_deleg_param; +} curl_deleg_levels[] = { + { "none", CURLGSSAPI_DELEGATION_NONE }, + { "policy", CURLGSSAPI_DELEGATION_POLICY_FLAG }, + { "always", CURLGSSAPI_DELEGATION_FLAG }, +}; +#endif + static struct credential proxy_auth = CREDENTIAL_INIT; static const char *curl_proxyuserpwd; static const char *curl_cookie_file; @@ -323,6 +335,15 @@ static int http_options(const char *var, const char *value, void *cb) return 0; } + if (!strcmp("http.delegation", var)) { +#if LIBCURL_VERSION_NUM >= 0x071600 + return git_config_string(&curl_deleg, var, value); +#else + warning(_("Delegation control is not supported with cURL < 7.22.0")); + return 0; +#endif + } + if (!strcmp("http.pinnedpubkey", var)) { #if LIBCURL_VERSION_NUM >= 0x072c00 return git_config_pathname(&ssl_pinnedkey, var, value); @@ -629,6 +650,22 @@ static CURL *get_curl_handle(void) curl_easy_setopt(result, CURLOPT_HTTPAUTH, CURLAUTH_ANY); #endif +#if LIBCURL_VERSION_NUM >= 0x071600 + if (curl_deleg) { + int i; + for (i = 0; i < ARRAY_SIZE(curl_deleg_levels); i++) { + if (!strcmp(curl_deleg, curl_deleg_levels[i].name)) { + curl_easy_setopt(result, CURLOPT_GSSAPI_DELEGATION, + curl_deleg_levels[i].curl_deleg_param); + break; + } + } + if (i == ARRAY_SIZE(curl_deleg_levels)) + warning("Unknown delegation method '%s': using default", + curl_deleg); + } +#endif + if (http_proactive_auth) init_curl_http_auth(result); diff --git a/ident.c b/ident.c index d17b5bd..ac4ae02 100644 --- a/ident.c +++ b/ident.c @@ -331,17 +331,17 @@ person_only: } static const char *env_hint = -"\n" -"*** Please tell me who you are.\n" -"\n" -"Run\n" -"\n" -" git config --global user.email \"you@example.com\"\n" -" git config --global user.name \"Your Name\"\n" -"\n" -"to set your account\'s default identity.\n" -"Omit --global to set the identity only in this repository.\n" -"\n"; +N_("\n" + "*** Please tell me who you are.\n" + "\n" + "Run\n" + "\n" + " git config --global user.email \"you@example.com\"\n" + " git config --global user.name \"Your Name\"\n" + "\n" + "to set your account\'s default identity.\n" + "Omit --global to set the identity only in this repository.\n" + "\n"); const char *fmt_ident(const char *name, const char *email, const char *date_str, int flag) @@ -356,13 +356,13 @@ const char *fmt_ident(const char *name, const char *email, if (!name) { if (strict && ident_use_config_only && !(ident_config_given & IDENT_NAME_GIVEN)) { - fputs(env_hint, stderr); + 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); + fputs(_(env_hint), stderr); die("unable to auto-detect name (got '%s')", name); } } @@ -370,7 +370,7 @@ const char *fmt_ident(const char *name, const char *email, struct passwd *pw; if (strict) { if (using_default) - fputs(env_hint, stderr); + fputs(_(env_hint), stderr); die("empty ident name (for <%s>) not allowed", email); } pw = xgetpwuid_self(NULL); @@ -381,12 +381,12 @@ 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); + 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); + fputs(_(env_hint), stderr); die("unable to auto-detect email address (got '%s')", email); } } diff --git a/line-log.c b/line-log.c index 916e724..65f3558 100644 --- a/line-log.c +++ b/line-log.c @@ -113,7 +113,7 @@ void sort_and_merge_range_set(struct range_set *rs) int i; int o = 0; /* output cursor */ - qsort(rs->ranges, rs->nr, sizeof(struct range), range_cmp); + QSORT(rs->ranges, rs->nr, range_cmp); for (i = 0; i < rs->nr; i++) { if (rs->ranges[i].start == rs->ranges[i].end) diff --git a/log-tree.c b/log-tree.c index bfb735c..8c24157 100644 --- a/log-tree.c +++ b/log-tree.c @@ -715,10 +715,7 @@ void show_log(struct rev_info *opt) else opt->missing_newline = 0; - if (opt->graph) - graph_show_commit_msg(opt->graph, &msgbuf); - else - fwrite(msgbuf.buf, sizeof(char), msgbuf.len, opt->diffopt.file); + graph_show_commit_msg(opt->graph, opt->diffopt.file, &msgbuf); if (opt->use_terminator && !commit_format_is_empty(opt->commit_format)) { if (!opt->missing_newline) graph_show_padding(opt->graph); diff --git a/mailinfo.c b/mailinfo.c index b4118a0..2fb3877 100644 --- a/mailinfo.c +++ b/mailinfo.c @@ -577,26 +577,26 @@ static int check_header(struct mailinfo *mi, goto check_header_out; } - /* for inbody stuff */ - if (starts_with(line->buf, ">From") && isspace(line->buf[5])) { - ret = is_format_patch_separator(line->buf + 1, line->len - 1); - goto check_header_out; - } - if (starts_with(line->buf, "[PATCH]") && isspace(line->buf[7])) { - for (i = 0; header[i]; i++) { - if (!strcmp("Subject", header[i])) { - handle_header(&hdr_data[i], line); - ret = 1; - goto check_header_out; - } - } - } - check_header_out: strbuf_release(&sb); return ret; } +/* + * Returns 1 if the given line or any line beginning with the given line is an + * in-body header (that is, check_header will succeed when passed + * mi->s_hdr_data). + */ +static int is_inbody_header(const struct mailinfo *mi, + const struct strbuf *line) +{ + int i; + for (i = 0; header[i]; i++) + if (!mi->s_hdr_data[i] && cmp_header(line, header[i])) + return 1; + return 0; +} + static void decode_transfer_encoding(struct mailinfo *mi, struct strbuf *line) { struct strbuf *ret; @@ -654,37 +654,35 @@ static inline int patchbreak(const struct strbuf *line) return 0; } -static int is_scissors_line(const struct strbuf *line) +static int is_scissors_line(const char *line) { - size_t i, len = line->len; + const char *c; int scissors = 0, gap = 0; - int first_nonblank = -1; - int last_nonblank = 0, visible, perforation = 0, in_perforation = 0; - const char *buf = line->buf; + const char *first_nonblank = NULL, *last_nonblank = NULL; + int visible, perforation = 0, in_perforation = 0; - for (i = 0; i < len; i++) { - if (isspace(buf[i])) { + for (c = line; *c; c++) { + if (isspace(*c)) { if (in_perforation) { perforation++; gap++; } continue; } - last_nonblank = i; - if (first_nonblank < 0) - first_nonblank = i; - if (buf[i] == '-') { + last_nonblank = c; + if (first_nonblank == NULL) + first_nonblank = c; + if (*c == '-') { in_perforation = 1; perforation++; continue; } - if (i + 1 < len && - (!memcmp(buf + i, ">8", 2) || !memcmp(buf + i, "8<", 2) || - !memcmp(buf + i, ">%", 2) || !memcmp(buf + i, "%<", 2))) { + if ((!memcmp(c, ">8", 2) || !memcmp(c, "8<", 2) || + !memcmp(c, ">%", 2) || !memcmp(c, "%<", 2))) { in_perforation = 1; perforation += 2; scissors += 2; - i++; + c++; continue; } in_perforation = 0; @@ -699,12 +697,60 @@ static int is_scissors_line(const struct strbuf *line) * than half of the perforation. */ - visible = last_nonblank - first_nonblank + 1; + if (first_nonblank && last_nonblank) + visible = last_nonblank - first_nonblank + 1; + else + visible = 0; return (scissors && 8 <= visible && visible < perforation * 3 && gap * 2 < perforation); } +static void flush_inbody_header_accum(struct mailinfo *mi) +{ + if (!mi->inbody_header_accum.len) + return; + assert(check_header(mi, &mi->inbody_header_accum, mi->s_hdr_data, 0)); + strbuf_reset(&mi->inbody_header_accum); +} + +static int check_inbody_header(struct mailinfo *mi, const struct strbuf *line) +{ + if (mi->inbody_header_accum.len && + (line->buf[0] == ' ' || line->buf[0] == '\t')) { + if (mi->use_scissors && is_scissors_line(line->buf)) { + /* + * This is a scissors line; do not consider this line + * as a header continuation line. + */ + flush_inbody_header_accum(mi); + return 0; + } + strbuf_strip_suffix(&mi->inbody_header_accum, "\n"); + strbuf_addbuf(&mi->inbody_header_accum, line); + return 1; + } + + flush_inbody_header_accum(mi); + + if (starts_with(line->buf, ">From") && isspace(line->buf[5])) + return is_format_patch_separator(line->buf + 1, line->len - 1); + if (starts_with(line->buf, "[PATCH]") && isspace(line->buf[7])) { + int i; + for (i = 0; header[i]; i++) + if (!strcmp("Subject", header[i])) { + handle_header(&mi->s_hdr_data[i], line); + return 1; + } + return 0; + } + if (is_inbody_header(mi, line)) { + strbuf_addbuf(&mi->inbody_header_accum, line); + return 1; + } + return 0; +} + static int handle_commit_msg(struct mailinfo *mi, struct strbuf *line) { assert(!mi->filter_stage); @@ -715,7 +761,7 @@ static int handle_commit_msg(struct mailinfo *mi, struct strbuf *line) } if (mi->use_inbody_headers && mi->header_stage) { - mi->header_stage = check_header(mi, line, mi->s_hdr_data, 0); + mi->header_stage = check_inbody_header(mi, line); if (mi->header_stage) return 0; } else @@ -728,7 +774,7 @@ static int handle_commit_msg(struct mailinfo *mi, struct strbuf *line) if (convert_to_utf8(mi, line, mi->charset.buf)) return 0; /* mi->input_error already set */ - if (mi->use_scissors && is_scissors_line(line)) { + if (mi->use_scissors && is_scissors_line(line->buf)) { int i; strbuf_setlen(&mi->log_message, 0); @@ -968,6 +1014,8 @@ static void handle_body(struct mailinfo *mi, struct strbuf *line) break; } while (!strbuf_getwholeline(line, mi->input, '\n')); + flush_inbody_header_accum(mi); + handle_body_out: strbuf_release(&prev); } @@ -1083,6 +1131,7 @@ void setup_mailinfo(struct mailinfo *mi) strbuf_init(&mi->email, 0); strbuf_init(&mi->charset, 0); strbuf_init(&mi->log_message, 0); + strbuf_init(&mi->inbody_header_accum, 0); mi->header_stage = 1; mi->use_inbody_headers = 1; mi->content_top = mi->content; @@ -1096,6 +1145,7 @@ void clear_mailinfo(struct mailinfo *mi) strbuf_release(&mi->name); strbuf_release(&mi->email); strbuf_release(&mi->charset); + strbuf_release(&mi->inbody_header_accum); free(mi->message_id); for (i = 0; mi->p_hdr_data[i]; i++) diff --git a/mailinfo.h b/mailinfo.h index 93776a7..04a2535 100644 --- a/mailinfo.h +++ b/mailinfo.h @@ -27,6 +27,7 @@ struct mailinfo { int patch_lines; int filter_stage; /* still reading log or are we copying patch? */ int header_stage; /* still checking in-body headers? */ + struct strbuf inbody_header_accum; struct strbuf **p_hdr_data; struct strbuf **s_hdr_data; diff --git a/merge-recursive.c b/merge-recursive.c index aa92e30..9041c2f 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -382,7 +382,7 @@ static struct string_list *get_unmerged(void) } e = item->util; e->stages[ce_stage(ce)].mode = ce->ce_mode; - hashcpy(e->stages[ce_stage(ce)].oid.hash, ce->sha1); + oidcpy(&e->stages[ce_stage(ce)].oid, &ce->oid); } return unmerged; @@ -910,9 +910,9 @@ static int merge_3way(struct merge_options *o, name2 = mkpathdup("%s", branch2); } - read_mmblob(&orig, one->oid.hash); - read_mmblob(&src1, a->oid.hash); - read_mmblob(&src2, b->oid.hash); + read_mmblob(&orig, &one->oid); + read_mmblob(&src1, &a->oid); + read_mmblob(&src2, &b->oid); merge_status = ll_merge(result_buf, a->path, &orig, base_name, &src1, name1, &src2, name2, &ll_opts); diff --git a/merge.c b/merge.c index 5db7d56..23866c9 100644 --- a/merge.c +++ b/merge.c @@ -57,7 +57,8 @@ int checkout_fast_forward(const unsigned char *head, refresh_cache(REFRESH_QUIET); - hold_locked_index(lock_file, 1); + if (hold_locked_index(lock_file, 0) < 0) + return -1; memset(&trees, 0, sizeof(trees)); memset(&opts, 0, sizeof(opts)); @@ -90,7 +91,9 @@ int checkout_fast_forward(const unsigned char *head, } if (unpack_trees(nr_trees, t, &opts)) return -1; - if (write_locked_index(&the_index, lock_file, COMMIT_LOCK)) - die(_("unable to write new index file")); + if (write_locked_index(&the_index, lock_file, COMMIT_LOCK)) { + rollback_lock_file(lock_file); + return error(_("unable to write new index file")); + } return 0; } diff --git a/notes-merge.c b/notes-merge.c index 97fc42f..5998605 100644 --- a/notes-merge.c +++ b/notes-merge.c @@ -12,7 +12,7 @@ #include "notes-utils.h" struct notes_merge_pair { - unsigned char obj[20], base[20], local[20], remote[20]; + struct object_id obj, base, local, remote; }; void init_notes_merge_options(struct notes_merge_options *o) @@ -75,7 +75,7 @@ static struct notes_merge_pair *find_notes_merge_pair_pos( int i = last_index < len ? last_index : len - 1; int prev_cmp = 0, cmp = -1; while (i >= 0 && i < len) { - cmp = hashcmp(obj, list[i].obj); + cmp = hashcmp(obj, list[i].obj.hash); if (!cmp) /* obj belongs @ i */ break; else if (cmp < 0 && prev_cmp <= 0) /* obj belongs < i */ @@ -108,9 +108,10 @@ static struct notes_merge_pair *find_notes_merge_pair_pos( return list + i; } -static unsigned char uninitialized[20] = +static struct object_id uninitialized = { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \ - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; + "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +}; static struct notes_merge_pair *diff_tree_remote(struct notes_merge_options *o, const unsigned char *base, @@ -149,25 +150,25 @@ static struct notes_merge_pair *diff_tree_remote(struct notes_merge_options *o, mp = find_notes_merge_pair_pos(changes, len, obj, 1, &occupied); if (occupied) { /* We've found an addition/deletion pair */ - assert(!hashcmp(mp->obj, obj)); + assert(!hashcmp(mp->obj.hash, obj)); if (is_null_oid(&p->one->oid)) { /* addition */ - assert(is_null_sha1(mp->remote)); - hashcpy(mp->remote, p->two->oid.hash); + assert(is_null_oid(&mp->remote)); + oidcpy(&mp->remote, &p->two->oid); } else if (is_null_oid(&p->two->oid)) { /* deletion */ - assert(is_null_sha1(mp->base)); - hashcpy(mp->base, p->one->oid.hash); + assert(is_null_oid(&mp->base)); + oidcpy(&mp->base, &p->one->oid); } else assert(!"Invalid existing change recorded"); } else { - hashcpy(mp->obj, obj); - hashcpy(mp->base, p->one->oid.hash); - hashcpy(mp->local, uninitialized); - hashcpy(mp->remote, p->two->oid.hash); + hashcpy(mp->obj.hash, obj); + oidcpy(&mp->base, &p->one->oid); + oidcpy(&mp->local, &uninitialized); + oidcpy(&mp->remote, &p->two->oid); len++; } trace_printf("\t\tStored remote change for %s: %.7s -> %.7s\n", - sha1_to_hex(mp->obj), sha1_to_hex(mp->base), - sha1_to_hex(mp->remote)); + oid_to_hex(&mp->obj), oid_to_hex(&mp->base), + oid_to_hex(&mp->remote)); } diff_flush(&opt); clear_pathspec(&opt.pathspec); @@ -216,7 +217,7 @@ static void diff_tree_local(struct notes_merge_options *o, continue; } - assert(!hashcmp(mp->obj, obj)); + assert(!hashcmp(mp->obj.hash, obj)); if (is_null_oid(&p->two->oid)) { /* deletion */ /* * Either this is a true deletion (1), or it is part @@ -227,8 +228,8 @@ static void diff_tree_local(struct notes_merge_options *o, * (3) mp->local is uninitialized; set it to null_sha1 * (will be overwritten by following addition) */ - if (!hashcmp(mp->local, uninitialized)) - hashclr(mp->local); + if (!oidcmp(&mp->local, &uninitialized)) + oidclr(&mp->local); } else if (is_null_oid(&p->one->oid)) { /* addition */ /* * Either this is a true addition (1), or it is part @@ -238,22 +239,22 @@ static void diff_tree_local(struct notes_merge_options *o, * (2) mp->local is uninitialized; set to p->two->sha1 * (3) mp->local is null_sha1; set to p->two->sha1 */ - assert(is_null_sha1(mp->local) || - !hashcmp(mp->local, uninitialized)); - hashcpy(mp->local, p->two->oid.hash); + assert(is_null_oid(&mp->local) || + !oidcmp(&mp->local, &uninitialized)); + oidcpy(&mp->local, &p->two->oid); } else { /* modification */ /* * This is a true modification. p->one->sha1 shall * match mp->base, and mp->local shall be uninitialized. * Set mp->local to p->two->sha1. */ - assert(!hashcmp(p->one->oid.hash, mp->base)); - assert(!hashcmp(mp->local, uninitialized)); - hashcpy(mp->local, p->two->oid.hash); + assert(!oidcmp(&p->one->oid, &mp->base)); + assert(!oidcmp(&mp->local, &uninitialized)); + oidcpy(&mp->local, &p->two->oid); } trace_printf("\t\tStored local change for %s: %.7s -> %.7s\n", - sha1_to_hex(mp->obj), sha1_to_hex(mp->base), - sha1_to_hex(mp->local)); + oid_to_hex(&mp->obj), oid_to_hex(&mp->base), + oid_to_hex(&mp->local)); } diff_flush(&opt); clear_pathspec(&opt.pathspec); @@ -269,15 +270,15 @@ static void check_notes_merge_worktree(struct notes_merge_options *o) if (file_exists(git_path(NOTES_MERGE_WORKTREE)) && !is_empty_dir(git_path(NOTES_MERGE_WORKTREE))) { if (advice_resolve_conflict) - die("You have not concluded your previous " + die(_("You have not concluded your previous " "notes merge (%s exists).\nPlease, use " "'git notes merge --commit' or 'git notes " "merge --abort' to commit/abort the " "previous merge before you start a new " - "notes merge.", git_path("NOTES_MERGE_*")); + "notes merge."), git_path("NOTES_MERGE_*")); else - die("You have not concluded your notes merge " - "(%s exists).", git_path("NOTES_MERGE_*")); + die(_("You have not concluded your notes merge " + "(%s exists)."), git_path("NOTES_MERGE_*")); } if (safe_create_leading_directories_const(git_path( @@ -343,11 +344,11 @@ static int ll_merge_in_worktree(struct notes_merge_options *o, mmfile_t base, local, remote; int status; - read_mmblob(&base, p->base); - read_mmblob(&local, p->local); - read_mmblob(&remote, p->remote); + read_mmblob(&base, &p->base); + read_mmblob(&local, &p->local); + read_mmblob(&remote, &p->remote); - status = ll_merge(&result_buf, sha1_to_hex(p->obj), &base, NULL, + status = ll_merge(&result_buf, oid_to_hex(&p->obj), &base, NULL, &local, o->local_ref, &remote, o->remote_ref, NULL); free(base.ptr); @@ -357,7 +358,7 @@ static int ll_merge_in_worktree(struct notes_merge_options *o, if ((status < 0) || !result_buf.ptr) die("Failed to execute internal merge"); - write_buf_to_worktree(p->obj, result_buf.ptr, result_buf.size); + write_buf_to_worktree(p->obj.hash, result_buf.ptr, result_buf.size); free(result_buf.ptr); return status; @@ -372,51 +373,52 @@ static int merge_one_change_manual(struct notes_merge_options *o, trace_printf("\t\t\tmerge_one_change_manual(obj = %.7s, base = %.7s, " "local = %.7s, remote = %.7s)\n", - sha1_to_hex(p->obj), sha1_to_hex(p->base), - sha1_to_hex(p->local), sha1_to_hex(p->remote)); + oid_to_hex(&p->obj), oid_to_hex(&p->base), + oid_to_hex(&p->local), oid_to_hex(&p->remote)); /* add "Conflicts:" section to commit message first time through */ if (!o->has_worktree) strbuf_addstr(&(o->commit_msg), "\n\nConflicts:\n"); - strbuf_addf(&(o->commit_msg), "\t%s\n", sha1_to_hex(p->obj)); + strbuf_addf(&(o->commit_msg), "\t%s\n", oid_to_hex(&p->obj)); if (o->verbosity >= 2) - printf("Auto-merging notes for %s\n", sha1_to_hex(p->obj)); + printf("Auto-merging notes for %s\n", oid_to_hex(&p->obj)); check_notes_merge_worktree(o); - if (is_null_sha1(p->local)) { + if (is_null_oid(&p->local)) { /* D/F conflict, checkout p->remote */ - assert(!is_null_sha1(p->remote)); + assert(!is_null_oid(&p->remote)); if (o->verbosity >= 1) printf("CONFLICT (delete/modify): Notes for object %s " "deleted in %s and modified in %s. Version from %s " "left in tree.\n", - sha1_to_hex(p->obj), lref, rref, rref); - write_note_to_worktree(p->obj, p->remote); - } else if (is_null_sha1(p->remote)) { + oid_to_hex(&p->obj), lref, rref, rref); + write_note_to_worktree(p->obj.hash, p->remote.hash); + } else if (is_null_oid(&p->remote)) { /* D/F conflict, checkout p->local */ - assert(!is_null_sha1(p->local)); + assert(!is_null_oid(&p->local)); if (o->verbosity >= 1) printf("CONFLICT (delete/modify): Notes for object %s " "deleted in %s and modified in %s. Version from %s " "left in tree.\n", - sha1_to_hex(p->obj), rref, lref, lref); - write_note_to_worktree(p->obj, p->local); + oid_to_hex(&p->obj), rref, lref, lref); + write_note_to_worktree(p->obj.hash, p->local.hash); } else { /* "regular" conflict, checkout result of ll_merge() */ const char *reason = "content"; - if (is_null_sha1(p->base)) + if (is_null_oid(&p->base)) reason = "add/add"; - assert(!is_null_sha1(p->local)); - assert(!is_null_sha1(p->remote)); + assert(!is_null_oid(&p->local)); + assert(!is_null_oid(&p->remote)); if (o->verbosity >= 1) printf("CONFLICT (%s): Merge conflict in notes for " - "object %s\n", reason, sha1_to_hex(p->obj)); + "object %s\n", reason, + oid_to_hex(&p->obj)); ll_merge_in_worktree(o, p); } trace_printf("\t\t\tremoving from partial merge result\n"); - remove_note(t, p->obj); + remove_note(t, p->obj.hash); return 1; } @@ -435,29 +437,29 @@ static int merge_one_change(struct notes_merge_options *o, case NOTES_MERGE_RESOLVE_OURS: if (o->verbosity >= 2) printf("Using local notes for %s\n", - sha1_to_hex(p->obj)); + oid_to_hex(&p->obj)); /* nothing to do */ return 0; case NOTES_MERGE_RESOLVE_THEIRS: if (o->verbosity >= 2) printf("Using remote notes for %s\n", - sha1_to_hex(p->obj)); - if (add_note(t, p->obj, p->remote, combine_notes_overwrite)) + oid_to_hex(&p->obj)); + if (add_note(t, p->obj.hash, p->remote.hash, combine_notes_overwrite)) die("BUG: combine_notes_overwrite failed"); return 0; case NOTES_MERGE_RESOLVE_UNION: if (o->verbosity >= 2) printf("Concatenating local and remote notes for %s\n", - sha1_to_hex(p->obj)); - if (add_note(t, p->obj, p->remote, combine_notes_concatenate)) + oid_to_hex(&p->obj)); + if (add_note(t, p->obj.hash, p->remote.hash, combine_notes_concatenate)) die("failed to concatenate notes " "(combine_notes_concatenate)"); return 0; case NOTES_MERGE_RESOLVE_CAT_SORT_UNIQ: if (o->verbosity >= 2) printf("Concatenating unique lines in local and remote " - "notes for %s\n", sha1_to_hex(p->obj)); - if (add_note(t, p->obj, p->remote, combine_notes_cat_sort_uniq)) + "notes for %s\n", oid_to_hex(&p->obj)); + if (add_note(t, p->obj.hash, p->remote.hash, combine_notes_cat_sort_uniq)) die("failed to concatenate notes " "(combine_notes_cat_sort_uniq)"); return 0; @@ -475,20 +477,21 @@ static int merge_changes(struct notes_merge_options *o, for (i = 0; i < *num_changes; i++) { struct notes_merge_pair *p = changes + i; trace_printf("\t\t%.7s: %.7s -> %.7s/%.7s\n", - sha1_to_hex(p->obj), sha1_to_hex(p->base), - sha1_to_hex(p->local), sha1_to_hex(p->remote)); + oid_to_hex(&p->obj), oid_to_hex(&p->base), + oid_to_hex(&p->local), + oid_to_hex(&p->remote)); - if (!hashcmp(p->base, p->remote)) { + if (!oidcmp(&p->base, &p->remote)) { /* no remote change; nothing to do */ trace_printf("\t\t\tskipping (no remote change)\n"); - } else if (!hashcmp(p->local, p->remote)) { + } else if (!oidcmp(&p->local, &p->remote)) { /* same change in local and remote; nothing to do */ trace_printf("\t\t\tskipping (local == remote)\n"); - } else if (!hashcmp(p->local, uninitialized) || - !hashcmp(p->local, p->base)) { + } else if (!oidcmp(&p->local, &uninitialized) || + !oidcmp(&p->local, &p->base)) { /* no local change; adopt remote change */ trace_printf("\t\t\tno local change, adopted remote\n"); - if (add_note(t, p->obj, p->remote, + if (add_note(t, p->obj.hash, p->remote.hash, combine_notes_overwrite)) die("BUG: combine_notes_overwrite failed"); } else { diff --git a/notes.c b/notes.c index df4660f..2bab961 100644 --- a/notes.c +++ b/notes.c @@ -993,7 +993,7 @@ const char *default_notes_ref(void) void init_notes(struct notes_tree *t, const char *notes_ref, combine_notes_fn combine_notes, int flags) { - unsigned char sha1[20], object_sha1[20]; + struct object_id oid, object_oid; unsigned mode; struct leaf_node root_tree; @@ -1017,16 +1017,16 @@ void init_notes(struct notes_tree *t, const char *notes_ref, t->dirty = 0; if (flags & NOTES_INIT_EMPTY || !notes_ref || - get_sha1_treeish(notes_ref, object_sha1)) + get_sha1_treeish(notes_ref, object_oid.hash)) return; - if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, object_sha1)) + if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, object_oid.hash)) die("Cannot use notes ref %s", notes_ref); - if (get_tree_entry(object_sha1, "", sha1, &mode)) + if (get_tree_entry(object_oid.hash, "", oid.hash, &mode)) die("Failed to read notes tree referenced by %s (%s)", - notes_ref, sha1_to_hex(object_sha1)); + notes_ref, oid_to_hex(&object_oid)); hashclr(root_tree.key_sha1); - hashcpy(root_tree.val_sha1, sha1); + hashcpy(root_tree.val_sha1, oid.hash); load_subtree(t, &root_tree, t->root, 0); } diff --git a/object.h b/object.h index f8b6442..614a006 100644 --- a/object.h +++ b/object.h @@ -31,7 +31,7 @@ struct object_array { * revision.h: 0---------10 26 * fetch-pack.c: 0---4 * walker.c: 0-2 - * upload-pack.c: 11----------------19 + * upload-pack.c: 4 11----------------19 * builtin/blame.c: 12-13 * bisect.c: 16 * bundle.c: 16 diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index c30bcd0..9705596 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -385,8 +385,7 @@ void bitmap_writer_select_commits(struct commit **indexed_commits, { unsigned int i = 0, j, next; - qsort(indexed_commits, indexed_commits_nr, sizeof(indexed_commits[0]), - date_compare); + QSORT(indexed_commits, indexed_commits_nr, date_compare); if (writer.show_progress) writer.progress = start_progress("Selecting bitmap commits", 0); diff --git a/pack-bitmap.c b/pack-bitmap.c index b949e51..39bcc16 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -266,7 +266,7 @@ static int open_pack_bitmap_1(struct packed_git *packfile) return -1; idx_name = pack_bitmap_filename(packfile); - fd = git_open_noatime(idx_name); + fd = git_open(idx_name); free(idx_name); if (fd < 0) diff --git a/pack-check.c b/pack-check.c index c5c7763..27f70d3 100644 --- a/pack-check.c +++ b/pack-check.c @@ -96,7 +96,7 @@ static int verify_packfile(struct packed_git *p, entries[i].offset = nth_packed_object_offset(p, i); entries[i].nr = i; } - qsort(entries, nr_objects, sizeof(*entries), compare_entries); + QSORT(entries, nr_objects, compare_entries); for (i = 0; i < nr_objects; i++) { void *data; diff --git a/pack-objects.h b/pack-objects.h index d1b98b3..cc9b9a9 100644 --- a/pack-objects.h +++ b/pack-objects.h @@ -27,6 +27,15 @@ struct object_entry { unsigned no_try_delta:1; unsigned tagged:1; /* near the very tip of refs */ unsigned filled:1; /* assigned write-order */ + + /* + * State flags for depth-first search used for analyzing delta cycles. + */ + enum { + DFS_NONE = 0, + DFS_ACTIVE, + DFS_DONE + } dfs_state; }; struct packing_data { diff --git a/pack-write.c b/pack-write.c index ea0b788..88bc7f9 100644 --- a/pack-write.c +++ b/pack-write.c @@ -61,8 +61,7 @@ const char *write_idx_file(const char *index_name, struct pack_idx_entry **objec if (objects[i]->offset > last_obj_offset) last_obj_offset = objects[i]->offset; } - qsort(sorted_by_sha, nr_objects, sizeof(sorted_by_sha[0]), - sha1_compare); + QSORT(sorted_by_sha, nr_objects, sha1_compare); } else sorted_by_sha = list = last = NULL; diff --git a/pager.c b/pager.c index 6470b81..ae79643 100644 --- a/pager.c +++ b/pager.c @@ -6,12 +6,8 @@ #define DEFAULT_PAGER "less" #endif -/* - * This is split up from the rest of git so that we can do - * something different on Windows. - */ - static struct child_process pager_process = CHILD_PROCESS_INIT; +static const char *pager_program; static void wait_for_pager(int in_signal) { @@ -40,6 +36,44 @@ static void wait_for_pager_signal(int signo) raise(signo); } +static int core_pager_config(const char *var, const char *value, void *data) +{ + if (!strcmp(var, "core.pager")) + return git_config_string(&pager_program, var, value); + return 0; +} + +static void read_early_config(config_fn_t cb, void *data) +{ + git_config_with_options(cb, data, NULL, 1); + + /* + * Note that this is a really dirty hack that does the wrong thing in + * many cases. The crux of the problem is that we cannot run + * setup_git_directory() early on in git's setup, so we have no idea if + * we are in a repository or not, and therefore are not sure whether + * and how to read repository-local config. + * + * So if we _aren't_ in a repository (or we are but we would reject its + * core.repositoryformatversion), we'll read whatever is in .git/config + * blindly. Similarly, if we _are_ in a repository, but not at the + * root, we'll fail to find .git/config (because it's really + * ../.git/config, etc). See t7006 for a complete set of failures. + * + * However, we have historically provided this hack because it does + * work some of the time (namely when you are at the top-level of a + * valid repository), and would rarely make things worse (i.e., you do + * not generally have a .git/config file sitting around). + */ + if (!startup_info->have_repository) { + struct git_config_source repo_config; + + memset(&repo_config, 0, sizeof(repo_config)); + repo_config.file = ".git/config"; + git_config_with_options(cb, data, &repo_config, 1); + } +} + const char *git_pager(int stdout_is_tty) { const char *pager; @@ -50,7 +84,7 @@ const char *git_pager(int stdout_is_tty) pager = getenv("GIT_PAGER"); if (!pager) { if (!pager_program) - git_config(git_default_config, NULL); + read_early_config(core_pager_config, NULL); pager = pager_program; } if (!pager) @@ -180,23 +214,42 @@ int decimal_width(uintmax_t number) return width; } -/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */ -int check_pager_config(const char *cmd) +struct pager_command_config_data { + const char *cmd; + int want; + char *value; +}; + +static int pager_command_config(const char *var, const char *value, void *vdata) { - int want = -1; - struct strbuf key = STRBUF_INIT; - const char *value = NULL; - strbuf_addf(&key, "pager.%s", cmd); - if (git_config_key_is_valid(key.buf) && - !git_config_get_value(key.buf, &value)) { - int b = git_config_maybe_bool(key.buf, value); + struct pager_command_config_data *data = vdata; + const char *cmd; + + if (skip_prefix(var, "pager.", &cmd) && !strcmp(cmd, data->cmd)) { + int b = git_config_maybe_bool(var, value); if (b >= 0) - want = b; + data->want = b; else { - want = 1; - pager_program = xstrdup(value); + data->want = 1; + data->value = xstrdup(value); } } - strbuf_release(&key); - return want; + + return 0; +} + +/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */ +int check_pager_config(const char *cmd) +{ + struct pager_command_config_data data; + + data.cmd = cmd; + data.want = -1; + data.value = NULL; + + read_early_config(pager_command_config, &data); + + if (data.value) + pager_program = data.value; + return data.want; } diff --git a/parse-options-cb.c b/parse-options-cb.c index 1681883..b7d8f7d 100644 --- a/parse-options-cb.c +++ b/parse-options-cb.c @@ -159,6 +159,18 @@ int parse_opt_noop_cb(const struct option *opt, const char *arg, int unset) } /** + * Report that the option is unknown, so that other code can handle + * it. This can be used as a callback together with + * OPTION_LOWLEVEL_CALLBACK to allow an option to be documented in the + * "-h" output even if it's not being handled directly by + * parse_options(). + */ +int parse_opt_unknown_cb(const struct option *opt, const char *arg, int unset) +{ + return -2; +} + +/** * Recreates the command-line option in the strbuf. */ static int recreate_opt(struct strbuf *sb, const struct option *opt, diff --git a/parse-options.h b/parse-options.h index 78f8384..dcd8a09 100644 --- a/parse-options.h +++ b/parse-options.h @@ -228,6 +228,7 @@ extern int parse_opt_commits(const struct option *, const char *, int); extern int parse_opt_tertiary(const struct option *, const char *, int); extern int parse_opt_string_list(const struct option *, const char *, int); extern int parse_opt_noop_cb(const struct option *, const char *, int); +extern int parse_opt_unknown_cb(const struct option *, const char *, int); extern int parse_opt_passthru(const struct option *, const char *, int); extern int parse_opt_passthru_argv(const struct option *, const char *, int); diff --git a/path.c b/path.c index 6d4b007..52d889c 100644 --- a/path.c +++ b/path.c @@ -6,6 +6,7 @@ #include "string-list.h" #include "dir.h" #include "worktree.h" +#include "submodule-config.h" static int get_st_mode_bits(const char *path, int *mode) { @@ -469,12 +470,16 @@ const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...) return pathname->buf; } -static void do_submodule_path(struct strbuf *buf, const char *path, - const char *fmt, va_list args) +/* Returns 0 on success, negative on failure. */ +#define SUBMODULE_PATH_ERR_NOT_CONFIGURED -1 +static int do_submodule_path(struct strbuf *buf, const char *path, + const char *fmt, va_list args) { const char *git_dir; struct strbuf git_submodule_common_dir = STRBUF_INIT; struct strbuf git_submodule_dir = STRBUF_INIT; + const struct submodule *sub; + int err = 0; strbuf_addstr(buf, path); strbuf_complete(buf, '/'); @@ -485,6 +490,17 @@ static void do_submodule_path(struct strbuf *buf, const char *path, strbuf_reset(buf); strbuf_addstr(buf, git_dir); } + if (!is_git_directory(buf->buf)) { + gitmodules_config(); + sub = submodule_from_path(null_sha1, path); + if (!sub) { + err = SUBMODULE_PATH_ERR_NOT_CONFIGURED; + goto cleanup; + } + strbuf_reset(buf); + strbuf_git_path(buf, "%s/%s", "modules", sub->name); + } + strbuf_addch(buf, '/'); strbuf_addbuf(&git_submodule_dir, buf); @@ -495,27 +511,38 @@ static void do_submodule_path(struct strbuf *buf, const char *path, strbuf_cleanup_path(buf); +cleanup: strbuf_release(&git_submodule_dir); strbuf_release(&git_submodule_common_dir); + + return err; } char *git_pathdup_submodule(const char *path, const char *fmt, ...) { + int err; va_list args; struct strbuf buf = STRBUF_INIT; va_start(args, fmt); - do_submodule_path(&buf, path, fmt, args); + err = do_submodule_path(&buf, path, fmt, args); va_end(args); + if (err) { + strbuf_release(&buf); + return NULL; + } return strbuf_detach(&buf, NULL); } -void strbuf_git_path_submodule(struct strbuf *buf, const char *path, - const char *fmt, ...) +int strbuf_git_path_submodule(struct strbuf *buf, const char *path, + const char *fmt, ...) { + int err; va_list args; va_start(args, fmt); - do_submodule_path(buf, path, fmt, args); + err = do_submodule_path(buf, path, fmt, args); va_end(args); + + return err; } static void do_git_common_path(struct strbuf *buf, @@ -1225,11 +1252,6 @@ int is_ntfs_dotgit(const char *name) } } -int looks_like_command_line_option(const char *str) -{ - return str && str[0] == '-'; -} - char *xdg_config_home(const char *filename) { const char *home, *config_home; diff --git a/pathspec.c b/pathspec.c index 49a5360..22ca74a 100644 --- a/pathspec.c +++ b/pathspec.c @@ -364,7 +364,7 @@ void parse_pathspec(struct pathspec *pathspec, { struct pathspec_item *item; const char *entry = argv ? *argv : NULL; - int i, n, prefixlen, nr_exclude = 0; + int i, n, prefixlen, warn_empty_string, nr_exclude = 0; memset(pathspec, 0, sizeof(*pathspec)); @@ -402,8 +402,15 @@ void parse_pathspec(struct pathspec *pathspec, } n = 0; - while (argv[n]) + warn_empty_string = 1; + while (argv[n]) { + if (*argv[n] == '\0' && warn_empty_string) { + warning(_("empty strings as pathspecs will be made invalid in upcoming releases. " + "please use . instead if you meant to match all paths")); + warn_empty_string = 0; + } n++; + } pathspec->nr = n; ALLOC_ARRAY(pathspec->items, n); @@ -446,8 +453,7 @@ void parse_pathspec(struct pathspec *pathspec, if (pathspec->magic & PATHSPEC_MAXDEPTH) { if (flags & PATHSPEC_KEEP_ORDER) die("BUG: PATHSPEC_MAXDEPTH_VALID and PATHSPEC_KEEP_ORDER are incompatible"); - qsort(pathspec->items, pathspec->nr, - sizeof(struct pathspec_item), pathspec_item_cmp); + QSORT(pathspec->items, pathspec->nr, pathspec_item_cmp); } } diff --git a/perl/Git.pm b/perl/Git.pm index 864123f..b273282 100644 --- a/perl/Git.pm +++ b/perl/Git.pm @@ -59,7 +59,7 @@ require Exporter; command_bidi_pipe command_close_bidi_pipe version exec_path html_path hash_object git_cmd_try remote_refs prompt - get_tz_offset + get_tz_offset get_record credential credential_read credential_write temp_acquire temp_is_locked temp_release temp_reset temp_path); @@ -538,6 +538,20 @@ sub get_tz_offset { return sprintf("%s%02d%02d", $sign, (gmtime(abs($t - $gm)))[2,1]); } +=item get_record ( FILEHANDLE, INPUT_RECORD_SEPARATOR ) + +Read one record from FILEHANDLE delimited by INPUT_RECORD_SEPARATOR, +removing any trailing INPUT_RECORD_SEPARATOR. + +=cut + +sub get_record { + my ($fh, $rs) = @_; + local $/ = $rs; + my $rec = <$fh>; + chomp $rec if defined $rs; + $rec; +} =item prompt ( PROMPT , ISPASSWORD ) diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm index 018beb8..711d268 100644 --- a/perl/Git/SVN.pm +++ b/perl/Git/SVN.pm @@ -807,10 +807,15 @@ sub get_fetch_range { (++$min, $max); } +sub svn_dir { + command_oneline(qw(rev-parse --git-path svn)); +} + sub tmp_config { my (@args) = @_; - my $old_def_config = "$ENV{GIT_DIR}/svn/config"; - my $config = "$ENV{GIT_DIR}/svn/.metadata"; + my $svn_dir = svn_dir(); + my $old_def_config = "$svn_dir/config"; + my $config = "$svn_dir/.metadata"; if (! -f $config && -f $old_def_config) { rename $old_def_config, $config or die "Failed rename $old_def_config => $config: $!\n"; @@ -1658,7 +1663,17 @@ sub tie_for_persistent_memoization { if ($memo_backend > 0) { tie %$hash => 'Git::SVN::Memoize::YAML', "$path.yaml"; } else { - tie %$hash => 'Memoize::Storable', "$path.db", 'nstore'; + # first verify that any existing file can actually be loaded + # (it may have been saved by an incompatible version) + my $db = "$path.db"; + if (-e $db) { + use Storable qw(retrieve); + + if (!eval { retrieve($db); 1 }) { + unlink $db or die "unlink $db failed: $!"; + } + } + tie %$hash => 'Memoize::Storable', $db, 'nstore'; } } @@ -1671,7 +1686,7 @@ sub tie_for_persistent_memoization { return if $memoized; $memoized = 1; - my $cache_path = "$ENV{GIT_DIR}/svn/.caches/"; + my $cache_path = svn_dir() . '/.caches/'; mkpath([$cache_path]) unless -d $cache_path; my %lookup_svn_merge_cache; @@ -1712,7 +1727,7 @@ sub tie_for_persistent_memoization { sub clear_memoized_mergeinfo_caches { die "Only call this method in non-memoized context" if ($memoized); - my $cache_path = "$ENV{GIT_DIR}/svn/.caches/"; + my $cache_path = svn_dir() . '/.caches/'; return unless -d $cache_path; for my $cache_file (("$cache_path/lookup_svn_merge", @@ -2446,12 +2461,13 @@ sub _new { "refs/remotes/$prefix$default_ref_id"; } $_[1] = $repo_id; - my $dir = "$ENV{GIT_DIR}/svn/$ref_id"; + my $svn_dir = svn_dir(); + my $dir = "$svn_dir/$ref_id"; - # Older repos imported by us used $GIT_DIR/svn/foo instead of - # $GIT_DIR/svn/refs/remotes/foo when tracking refs/remotes/foo + # Older repos imported by us used $svn_dir/foo instead of + # $svn_dir/refs/remotes/foo when tracking refs/remotes/foo if ($ref_id =~ m{^refs/remotes/(.+)}) { - my $old_dir = "$ENV{GIT_DIR}/svn/$1"; + my $old_dir = "$svn_dir/$1"; if (-d $old_dir && ! -d $dir) { $dir = $old_dir; } @@ -2461,7 +2477,7 @@ sub _new { mkpath([$dir]); my $obj = bless { ref_id => $ref_id, dir => $dir, index => "$dir/index", - config => "$ENV{GIT_DIR}/svn/config", + config => "$svn_dir/config", map_root => "$dir/.rev_map", repo_id => $repo_id }, $class; # Ensure it gets canonicalized diff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm index 4c4199a..0df16ed 100644 --- a/perl/Git/SVN/Editor.pm +++ b/perl/Git/SVN/Editor.pm @@ -7,7 +7,9 @@ use SVN::Delta; use Carp qw/croak/; use Git qw/command command_oneline command_noisy command_output_pipe command_input_pipe command_close_pipe - command_bidi_pipe command_close_bidi_pipe/; + command_bidi_pipe command_close_bidi_pipe + get_record/; + BEGIN { @ISA = qw(SVN::Delta::Editor); } @@ -57,11 +59,9 @@ sub generate_diff { push @diff_tree, "-l$_rename_limit" if defined $_rename_limit; push @diff_tree, $tree_a, $tree_b; my ($diff_fh, $ctx) = command_output_pipe(@diff_tree); - local $/ = "\0"; my $state = 'meta'; my @mods; - while (<$diff_fh>) { - chomp $_; # this gets rid of the trailing "\0" + while (defined($_ = get_record($diff_fh, "\0"))) { if ($state eq 'meta' && /^:(\d{6})\s(\d{6})\s ($::sha1)\s($::sha1)\s ([MTCRAD])\d*$/xo) { @@ -173,9 +173,7 @@ sub rmdirs { my ($fh, $ctx) = command_output_pipe(qw/ls-tree --name-only -r -z/, $self->{tree_b}); - local $/ = "\0"; - while (<$fh>) { - chomp; + while (defined($_ = get_record($fh, "\0"))) { my @dn = split m#/#, $_; while (pop @dn) { delete $rm->{join '/', @dn}; diff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm index d8c21ad..64e900a 100644 --- a/perl/Git/SVN/Fetcher.pm +++ b/perl/Git/SVN/Fetcher.pm @@ -9,7 +9,8 @@ use Carp qw/croak/; use File::Basename qw/dirname/; use Git qw/command command_oneline command_noisy command_output_pipe command_input_pipe command_close_pipe - command_bidi_pipe command_close_bidi_pipe/; + command_bidi_pipe command_close_bidi_pipe + get_record/; BEGIN { @ISA = qw(SVN::Delta::Editor); } @@ -86,11 +87,9 @@ sub _mark_empty_symlinks { my $printed_warning; chomp(my $empty_blob = `git hash-object -t blob --stdin < /dev/null`); my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r -z/, $cmt); - local $/ = "\0"; my $pfx = defined($switch_path) ? $switch_path : $git_svn->path; $pfx .= '/' if length($pfx); - while (<$ls>) { - chomp; + while (defined($_ = get_record($ls, "\0"))) { s/\A100644 blob $empty_blob\t//o or next; unless ($printed_warning) { print STDERR "Scanning for empty symlinks, ", @@ -179,9 +178,7 @@ sub delete_entry { my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r --name-only -z/, $tree); - local $/ = "\0"; - while (<$ls>) { - chomp; + while (defined($_ = get_record($ls, "\0"))) { my $rmpath = "$gpath/$_"; $self->{gii}->remove($rmpath); print "\tD\t$rmpath\n" unless $::_q; @@ -247,9 +244,7 @@ sub add_directory { my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r --name-only -z/, $self->{c}); - local $/ = "\0"; - while (<$ls>) { - chomp; + while (defined($_ = get_record($ls, "\0"))) { $self->{gii}->remove($_); print "\tD\t$_\n" unless $::_q; push @deleted_gpath, $gpath; diff --git a/perl/Git/SVN/Migration.pm b/perl/Git/SVN/Migration.pm index cf6ffa7..dc90f6a 100644 --- a/perl/Git/SVN/Migration.pm +++ b/perl/Git/SVN/Migration.pm @@ -44,7 +44,9 @@ use Git qw( command_noisy command_output_pipe command_close_pipe + command_oneline ); +use Git::SVN; sub migrate_from_v0 { my $git_dir = $ENV{GIT_DIR}; @@ -55,7 +57,9 @@ sub migrate_from_v0 { chomp; my ($id, $orig_ref) = ($_, $_); next unless $id =~ s#^refs/heads/(.+)-HEAD$#$1#; - next unless -f "$git_dir/$id/info/url"; + my $info_url = command_oneline(qw(rev-parse --git-path), + "$id/info/url"); + next unless -f $info_url; my $new_ref = "refs/remotes/$id"; if (::verify_ref("$new_ref^0")) { print STDERR "W: $orig_ref is probably an old ", @@ -82,7 +86,7 @@ sub migrate_from_v1 { my $git_dir = $ENV{GIT_DIR}; my $migrated = 0; return $migrated unless -d $git_dir; - my $svn_dir = "$git_dir/svn"; + my $svn_dir = Git::SVN::svn_dir(); # just in case somebody used 'svn' as their $id at some point... return $migrated if -d $svn_dir && ! -f "$svn_dir/info/url"; @@ -97,27 +101,28 @@ sub migrate_from_v1 { my $x = $_; next unless $x =~ s#^refs/remotes/##; chomp $x; - next unless -f "$git_dir/$x/info/url"; - my $u = eval { ::file_to_s("$git_dir/$x/info/url") }; + my $info_url = command_oneline(qw(rev-parse --git-path), + "$x/info/url"); + next unless -f $info_url; + my $u = eval { ::file_to_s($info_url) }; next unless $u; - my $dn = dirname("$git_dir/svn/$x"); + my $dn = dirname("$svn_dir/$x"); mkpath([$dn]) unless -d $dn; if ($x eq 'svn') { # they used 'svn' as GIT_SVN_ID: - mkpath(["$git_dir/svn/svn"]); + mkpath(["$svn_dir/svn"]); print STDERR " - $git_dir/$x/info => ", - "$git_dir/svn/$x/info\n"; - rename "$git_dir/$x/info", "$git_dir/svn/$x/info" or + "$svn_dir/$x/info\n"; + rename "$git_dir/$x/info", "$svn_dir/$x/info" or croak "$!: $x"; # don't worry too much about these, they probably # don't exist with repos this old (save for index, # and we can easily regenerate that) foreach my $f (qw/unhandled.log index .rev_db/) { - rename "$git_dir/$x/$f", "$git_dir/svn/$x/$f"; + rename "$git_dir/$x/$f", "$svn_dir/$x/$f"; } } else { - print STDERR " - $git_dir/$x => $git_dir/svn/$x\n"; - rename "$git_dir/$x", "$git_dir/svn/$x" or - croak "$!: $x"; + print STDERR " - $git_dir/$x => $svn_dir/$x\n"; + rename "$git_dir/$x", "$svn_dir/$x" or croak "$!: $x"; } $migrated++; } @@ -139,9 +144,10 @@ sub read_old_urls { push @dir, $_; } } + my $svn_dir = Git::SVN::svn_dir(); foreach (@dir) { my $x = $_; - $x =~ s!^\Q$ENV{GIT_DIR}\E/svn/!!o; + $x =~ s!^\Q$svn_dir\E/!!o; read_old_urls($l_map, $x, $_); } } @@ -150,7 +156,7 @@ sub migrate_from_v2 { my @cfg = command(qw/config -l/); return if grep /^svn-remote\..+\.url=/, @cfg; my %l_map; - read_old_urls(\%l_map, '', "$ENV{GIT_DIR}/svn"); + read_old_urls(\%l_map, '', Git::SVN::svn_dir()); my $migrated = 0; require Git::SVN; @@ -239,7 +245,8 @@ sub minimize_connections { } } if (@emptied) { - my $file = $ENV{GIT_CONFIG} || "$ENV{GIT_DIR}/config"; + my $file = $ENV{GIT_CONFIG} || + command_oneline(qw(rev-parse --git-path config)); print STDERR <> 12); + buf[1] = hex(size >> 8); + buf[2] = hex(size >> 4); + buf[3] = hex(size); + #undef hex +} + +static void format_packet(struct strbuf *out, const char *fmt, va_list args) +{ size_t orig_len, n; orig_len = out->len; @@ -111,23 +129,63 @@ static void format_packet(struct strbuf *out, const char *fmt, va_list args) if (n > LARGE_PACKET_MAX) die("protocol error: impossibly long line"); - out->buf[orig_len + 0] = hex(n >> 12); - out->buf[orig_len + 1] = hex(n >> 8); - out->buf[orig_len + 2] = hex(n >> 4); - out->buf[orig_len + 3] = hex(n); + set_packet_header(&out->buf[orig_len], n); packet_trace(out->buf + orig_len + 4, n - 4, 1); } -void packet_write(int fd, const char *fmt, ...) +static int packet_write_fmt_1(int fd, int gently, + const char *fmt, va_list args) +{ + struct strbuf buf = STRBUF_INIT; + ssize_t count; + + format_packet(&buf, fmt, args); + count = write_in_full(fd, buf.buf, buf.len); + if (count == buf.len) + return 0; + + if (!gently) { + check_pipe(errno); + die_errno("packet write with format failed"); + } + return error("packet write with format failed"); +} + +void packet_write_fmt(int fd, const char *fmt, ...) { - static struct strbuf buf = STRBUF_INIT; va_list args; - strbuf_reset(&buf); va_start(args, fmt); - format_packet(&buf, fmt, args); + packet_write_fmt_1(fd, 0, fmt, args); + va_end(args); +} + +int packet_write_fmt_gently(int fd, const char *fmt, ...) +{ + int status; + va_list args; + + va_start(args, fmt); + status = packet_write_fmt_1(fd, 1, fmt, args); va_end(args); - write_or_die(fd, buf.buf, buf.len); + return status; +} + +static int packet_write_gently(const int fd_out, const char *buf, size_t size) +{ + static char packet_write_buffer[LARGE_PACKET_MAX]; + size_t packet_size; + + if (size > sizeof(packet_write_buffer) - 4) + return error("packet write failed - data exceeds max packet size"); + + packet_trace(buf, size, 1); + packet_size = size + 4; + set_packet_header(packet_write_buffer, packet_size); + memcpy(packet_write_buffer + 4, buf, size); + if (write_in_full(fd_out, packet_write_buffer, packet_size) == packet_size) + return 0; + return error("packet write failed"); } void packet_buf_write(struct strbuf *buf, const char *fmt, ...) @@ -139,6 +197,46 @@ void packet_buf_write(struct strbuf *buf, const char *fmt, ...) va_end(args); } +int write_packetized_from_fd(int fd_in, int fd_out) +{ + static char buf[LARGE_PACKET_DATA_MAX]; + int err = 0; + ssize_t bytes_to_write; + + while (!err) { + bytes_to_write = xread(fd_in, buf, sizeof(buf)); + if (bytes_to_write < 0) + return COPY_READ_ERROR; + if (bytes_to_write == 0) + break; + err = packet_write_gently(fd_out, buf, bytes_to_write); + } + if (!err) + err = packet_flush_gently(fd_out); + return err; +} + +int write_packetized_from_buf(const char *src_in, size_t len, int fd_out) +{ + int err = 0; + size_t bytes_written = 0; + size_t bytes_to_write; + + while (!err) { + if ((len - bytes_written) > LARGE_PACKET_DATA_MAX) + bytes_to_write = LARGE_PACKET_DATA_MAX; + else + bytes_to_write = len - bytes_written; + if (bytes_to_write == 0) + break; + err = packet_write_gently(fd_out, src_in + bytes_written, bytes_to_write); + bytes_written += bytes_to_write; + } + if (!err) + err = packet_flush_gently(fd_out); + return err; +} + static int get_packet_data(int fd, char **src_buf, size_t *src_size, void *dst, unsigned size, int options) { @@ -229,3 +327,35 @@ char *packet_read_line_buf(char **src, size_t *src_len, int *dst_len) { return packet_read_line_generic(-1, src, src_len, dst_len); } + +ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out) +{ + int packet_len; + + size_t orig_len = sb_out->len; + size_t orig_alloc = sb_out->alloc; + + for (;;) { + strbuf_grow(sb_out, LARGE_PACKET_DATA_MAX); + packet_len = packet_read(fd_in, NULL, NULL, + /* strbuf_grow() above always allocates one extra byte to + * store a '\0' at the end of the string. packet_read() + * writes a '\0' extra byte at the end, too. Let it know + * that there is already room for the extra byte. + */ + sb_out->buf + sb_out->len, LARGE_PACKET_DATA_MAX+1, + PACKET_READ_GENTLE_ON_EOF); + if (packet_len <= 0) + break; + sb_out->len += packet_len; + } + + if (packet_len < 0) { + if (orig_alloc == 0) + strbuf_release(sb_out); + else + strbuf_setlen(sb_out, orig_len); + return packet_len; + } + return sb_out->len - orig_len; +} diff --git a/pkt-line.h b/pkt-line.h index 3cb9d91..18eac64 100644 --- a/pkt-line.h +++ b/pkt-line.h @@ -20,9 +20,13 @@ * side can't, we stay with pure read/write interfaces. */ void packet_flush(int fd); -void packet_write(int fd, const char *fmt, ...) __attribute__((format (printf, 2, 3))); +void packet_write_fmt(int fd, const char *fmt, ...) __attribute__((format (printf, 2, 3))); void packet_buf_flush(struct strbuf *buf); void packet_buf_write(struct strbuf *buf, const char *fmt, ...) __attribute__((format (printf, 2, 3))); +int packet_flush_gently(int fd); +int packet_write_fmt_gently(int fd, const char *fmt, ...) __attribute__((format (printf, 2, 3))); +int write_packetized_from_fd(int fd_in, int fd_out); +int write_packetized_from_buf(const char *src_in, size_t len, int fd_out); /* * Read a packetized line into the buffer, which must be at least size bytes @@ -75,8 +79,14 @@ char *packet_read_line(int fd, int *size); */ char *packet_read_line_buf(char **src_buf, size_t *src_len, int *size); +/* + * Reads a stream of variable sized packets until a flush packet is detected. + */ +ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out); + #define DEFAULT_PACKET_MAX 1000 #define LARGE_PACKET_MAX 65520 +#define LARGE_PACKET_DATA_MAX (LARGE_PACKET_MAX - 4) extern char packet_buffer[LARGE_PACKET_MAX]; #endif diff --git a/po/ca.po b/po/ca.po index 30e00e2..57d0e2f 100644 --- a/po/ca.po +++ b/po/ca.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List \n" -"POT-Creation-Date: 2016-08-27 23:21+0800\n" -"PO-Revision-Date: 2016-08-28 10:32-0600\n" +"POT-Creation-Date: 2016-11-25 22:50+0800\n" +"PO-Revision-Date: 2016-11-28 20:03-0700\n" "Last-Translator: Alex Henrie \n" "Language-Team: Catalan\n" "Language: ca\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 1.8.8\n" +"X-Generator: Poedit 1.8.11\n" #: advice.c:55 #, c-format @@ -100,3957 +100,4458 @@ msgstr "" "\n" " git checkout -b \n" -#: archive.c:12 -msgid "git archive [] [...]" -msgstr "git archive [] [...]" +#: apply.c:57 +#, c-format +msgid "unrecognized whitespace option '%s'" +msgstr "opció d'espai en blanc '%s' no reconeguda" -#: archive.c:13 -msgid "git archive --list" -msgstr "git archive --list" +#: apply.c:73 +#, c-format +msgid "unrecognized whitespace ignore option '%s'" +msgstr "opció d'ignoral d'espai en blanc '%s' no reconeguda" -#: archive.c:14 -msgid "" -"git archive --remote [--exec ] [] [...]" -msgstr "" -"git archive --remote [--exec ] [] " -"[...]" +#: apply.c:125 +msgid "--reject and --3way cannot be used together." +msgstr "--reject i --3way no es poden usar junts." -#: archive.c:15 -msgid "git archive --remote [--exec ] --list" -msgstr "git archive --remote [--exec ] --list" +#: apply.c:127 +msgid "--cached and --3way cannot be used together." +msgstr "--cached i --3way no es poden usar junts." -#: archive.c:344 builtin/add.c:139 builtin/add.c:435 builtin/rm.c:327 -#, c-format -msgid "pathspec '%s' did not match any files" -msgstr "L'especificació de camí '%s' no ha coincidit amb cap fitxer" +#: apply.c:130 +msgid "--3way outside a repository" +msgstr "--3way fora d'un dipòsit" -#: archive.c:429 -msgid "fmt" -msgstr "format" +#: apply.c:141 +msgid "--index outside a repository" +msgstr "--index fora d'un dipòsit" -#: archive.c:429 -msgid "archive format" -msgstr "format d'arxiu" +#: apply.c:144 +msgid "--cached outside a repository" +msgstr "--cached fora d'un dipòsit" -#: archive.c:430 builtin/log.c:1422 -msgid "prefix" -msgstr "prefix" +#: apply.c:845 +#, c-format +msgid "Cannot prepare timestamp regexp %s" +msgstr "No es pot preparar l'expressió regular de marca de temps %s" -#: archive.c:431 -msgid "prepend prefix to each pathname in the archive" -msgstr "anteposa el prefix a cada nom de camí en l'arxiu" +#: apply.c:854 +#, c-format +msgid "regexec returned %d for input: %s" +msgstr "regexec ha retornat %d per l'entrada: %s" -#: archive.c:432 builtin/archive.c:88 builtin/blame.c:2553 builtin/blame.c:2554 -#: builtin/config.c:59 builtin/fast-export.c:987 builtin/fast-export.c:989 -#: builtin/grep.c:722 builtin/hash-object.c:100 builtin/ls-files.c:460 -#: builtin/ls-files.c:463 builtin/notes.c:399 builtin/notes.c:562 -#: builtin/read-tree.c:109 parse-options.h:153 -msgid "file" -msgstr "fitxer" +#: apply.c:938 +#, c-format +msgid "unable to find filename in patch at line %d" +msgstr "no s'ha pogut trobar el nom de fitxer en el pedaç a la línia %d" -#: archive.c:433 builtin/archive.c:89 -msgid "write the archive to this file" -msgstr "escriu l'arxiu a aquest fitxer" +#: apply.c:977 +#, c-format +msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d" +msgstr "" +"git apply: git-diff dolent - /dev/null esperat, %s rebut en la línia %d" -#: archive.c:435 -msgid "read .gitattributes in working directory" -msgstr "llegeix .gitattributes en el directori de treball" +#: apply.c:983 +#, c-format +msgid "git apply: bad git-diff - inconsistent new filename on line %d" +msgstr "" +"git apply: git-diff dolent - nom de fitxer nou inconsistent en la línia %d" -#: archive.c:436 -msgid "report archived files on stderr" -msgstr "informa de fitxers arxivats en stderr" +#: apply.c:984 +#, c-format +msgid "git apply: bad git-diff - inconsistent old filename on line %d" +msgstr "" +"git apply: git-diff dolent - nom de fitxer antic inconsistent en la línia %d" -#: archive.c:437 -msgid "store only" -msgstr "només emmagatzema" +#: apply.c:990 +#, c-format +msgid "git apply: bad git-diff - expected /dev/null on line %d" +msgstr "git apply: git-diff dolent - /dev/null esperat en la línia %d" -#: archive.c:438 -msgid "compress faster" -msgstr "comprimeix més ràpidament" +#: apply.c:1488 +#, c-format +msgid "recount: unexpected line: %.*s" +msgstr "recompte: línia inesperada: %.*s" -#: archive.c:446 -msgid "compress better" -msgstr "comprimeix millor" +#: apply.c:1557 +#, c-format +msgid "patch fragment without header at line %d: %.*s" +msgstr "fragment de pedaç sense capçalera a la línia %d: %.*s" -#: archive.c:449 -msgid "list supported archive formats" -msgstr "allista els formats d'arxiu admesos" +#: apply.c:1577 +#, c-format +msgid "" +"git diff header lacks filename information when removing %d leading pathname " +"component (line %d)" +msgid_plural "" +"git diff header lacks filename information when removing %d leading pathname " +"components (line %d)" +msgstr[0] "" +"a la capçalera de git diff li manca informació de nom de fitxer en eliminar " +"%d component de nom de camí inicial (línia %d)" +msgstr[1] "" +"a la capçalera de git diff li manca informació de nom de fitxer en eliminar " +"%d components de nom de camí inicial (línia %d)" -#: archive.c:451 builtin/archive.c:90 builtin/clone.c:82 -#: builtin/submodule--helper.c:832 -msgid "repo" -msgstr "dipòsit" +#: apply.c:1589 +#, c-format +msgid "git diff header lacks filename information (line %d)" +msgstr "" +"a la capçalera de git diff li manca informació de nom de fitxer (línia %d)" -#: archive.c:452 builtin/archive.c:91 -msgid "retrieve the archive from remote repository " -msgstr "recupera l'arxiu del dipòsit remot " +#: apply.c:1759 +msgid "new file depends on old contents" +msgstr "el fitxer nou depèn dels continguts antics" -#: archive.c:453 builtin/archive.c:92 builtin/notes.c:483 -msgid "command" -msgstr "ordre" +#: apply.c:1761 +msgid "deleted file still has contents" +msgstr "el fitxer suprimit encara té continguts" -#: archive.c:454 builtin/archive.c:93 -msgid "path to the remote git-upload-archive command" -msgstr "camí a l'ordre git-upload-archive remota" +#: apply.c:1795 +#, c-format +msgid "corrupt patch at line %d" +msgstr "pedaç malmès a la línia %d" -#: archive.c:461 -msgid "Unexpected option --remote" -msgstr "Opció inesperada --remote" +#: apply.c:1832 +#, c-format +msgid "new file %s depends on old contents" +msgstr "el fitxer nou %s depèn dels continguts antics" -#: archive.c:463 -msgid "Option --exec can only be used together with --remote" -msgstr "L'opció --exec només es pot usar junt amb --remote" +#: apply.c:1834 +#, c-format +msgid "deleted file %s still has contents" +msgstr "el fitxer suprimit %s encara té continguts" -#: archive.c:465 -msgid "Unexpected option --output" -msgstr "Opció inesperada --output" +#: apply.c:1837 +#, c-format +msgid "** warning: file %s becomes empty but is not deleted" +msgstr "** advertència: el fitxer %s queda buit però no se suprimeix" -#: archive.c:487 +#: apply.c:1984 #, c-format -msgid "Unknown archive format '%s'" -msgstr "Format d'arxiu desconegut '%s'" +msgid "corrupt binary patch at line %d: %.*s" +msgstr "pedaç binari malmès a la línia %d: %.*s" -#: archive.c:494 +#: apply.c:2021 #, c-format -msgid "Argument not supported for format '%s': -%d" -msgstr "Paràmetre no admet per al format '%s': -%d" +msgid "unrecognized binary patch at line %d" +msgstr "pedaç binari no reconegut a la línia %d" -#: attr.c:263 -msgid "" -"Negative patterns are ignored in git attributes\n" -"Use '\\!' for literal leading exclamation." -msgstr "" -"Els patrons negatius s'ignoren en els atributs de git\n" -"Useu '\\!' per exclamació capdavantera literal." +#: apply.c:2182 +#, c-format +msgid "patch with only garbage at line %d" +msgstr "pedaç amb només escombraries a la línia %d" -#: bisect.c:441 +#: apply.c:2274 #, c-format -msgid "Could not open file '%s'" -msgstr "No s'ha pogut obrir el fitxer '%s'" +msgid "unable to read symlink %s" +msgstr "no s'ha pogut llegir l'enllaç simbòlic %s" -#: bisect.c:446 +#: apply.c:2278 #, c-format -msgid "Badly quoted content in file '%s': %s" -msgstr "Comentari amb cometes dolentes en el fitxer '%s': %s" +msgid "unable to open or read %s" +msgstr "no s'ha pogut obrir o llegir %s" -#: bisect.c:655 +#: apply.c:2931 #, c-format -msgid "We cannot bisect more!\n" -msgstr "No podem bisecar més!\n" +msgid "invalid start of line: '%c'" +msgstr "inici de línia no vàlid: '%c'" -#: bisect.c:708 +#: apply.c:3050 #, c-format -msgid "Not a valid commit name %s" -msgstr "No és un nom de comissió vàlid %s" +msgid "Hunk #%d succeeded at %d (offset %d line)." +msgid_plural "Hunk #%d succeeded at %d (offset %d lines)." +msgstr[0] "El tros #%d ha tingut èxit a %d (desplaçament d'%d línia)." +msgstr[1] "El tros #%d ha tingut èxit a %d (desplaçament de %d línies)." -#: bisect.c:732 +#: apply.c:3062 #, c-format -msgid "" -"The merge base %s is bad.\n" -"This means the bug has been fixed between %s and [%s].\n" -msgstr "" -"La base de fusió %s és dolenta.\n" -"Això vol dir que el defecte s'ha arreglat entre %s i [%s].\n" +msgid "Context reduced to (%ld/%ld) to apply fragment at %d" +msgstr "El context s'ha reduït a (%ld/%ld) per a aplicar el fragment a %d" -#: bisect.c:737 +#: apply.c:3068 #, c-format msgid "" -"The merge base %s is new.\n" -"The property has changed between %s and [%s].\n" +"while searching for:\n" +"%.*s" msgstr "" -"La base de fusió %s és nova.\n" -"La propietat s'ha canviat entre %s i [%s].\n" +"tot cercant:\n" +"%.*s" -#: bisect.c:742 +#: apply.c:3090 #, c-format -msgid "" -"The merge base %s is %s.\n" -"This means the first '%s' commit is between %s and [%s].\n" -msgstr "" -"La base de fusió %s és %s.\n" -"Això vol dir que la primera comissió '%s' és entre %s i [%s].\n" +msgid "missing binary patch data for '%s'" +msgstr "manquen les dades de pedaç binari de '%s'" -#: bisect.c:750 +#: apply.c:3098 #, c-format -msgid "" -"Some %s revs are not ancestor of the %s rev.\n" -"git bisect cannot work properly in this case.\n" -"Maybe you mistook %s and %s revs?\n" +msgid "cannot reverse-apply a binary patch without the reverse hunk to '%s'" +msgstr "no es pot aplicar al revés un pedaç binari sense el tros revés a '%s'" + +#: apply.c:3144 +#, c-format +msgid "cannot apply binary patch to '%s' without full index line" msgstr "" -"Unes %s revisions no són els avantpassats de la revisió %s.\n" -"git bisect no pot funcionar correctament en aquest cas.\n" -"Potser heu confós les revisions %s i %s?\n" +"no es pot aplicar un pedaç binari a '%s' sense la línia d'índex completa" -#: bisect.c:763 +#: apply.c:3154 #, c-format msgid "" -"the merge base between %s and [%s] must be skipped.\n" -"So we cannot be sure the first %s commit is between %s and %s.\n" -"We continue anyway." +"the patch applies to '%s' (%s), which does not match the current contents." msgstr "" -"s'ha de saltar la base de fusió entre %s i [%s].\n" -"Llavors, no podem estar segurs que la primera comissió %s sigui entre %s i " -"%s.\n" -"Continuem de totes maneres." +"el pedaç s'aplica a '%s' (%s), el qual no coincideix amb els continguts " +"actuals." -#: bisect.c:798 +#: apply.c:3162 #, c-format -msgid "Bisecting: a merge base must be tested\n" -msgstr "Bisecant: s'ha de provar una base de fusió\n" +msgid "the patch applies to an empty '%s' but it is not empty" +msgstr "el pedaç s'aplica a un '%s' buit però no és buit" -#: bisect.c:849 +#: apply.c:3180 #, c-format -msgid "a %s revision is needed" -msgstr "es necessita una revisió %s" +msgid "the necessary postimage %s for '%s' cannot be read" +msgstr "no es pot llegir la postimatge necessari %s per a '%s'" -#: bisect.c:866 builtin/notes.c:174 builtin/tag.c:248 +#: apply.c:3193 #, c-format -msgid "could not create file '%s'" -msgstr "no s'ha pogut crear el fitxer '%s'" +msgid "binary patch does not apply to '%s'" +msgstr "el pedaç binari no s'aplica a '%s'" -#: bisect.c:917 +#: apply.c:3199 #, c-format -msgid "could not read file '%s'" -msgstr "no s'ha pogut llegir el fitxer '%s'" +msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)" +msgstr "" +"el pedaç binari a '%s' crea un resultat incorrecte (esperant %s, %s rebut)" -#: bisect.c:947 -msgid "reading bisect refs failed" -msgstr "la lectura de les referències de bisecció ha fallat" +#: apply.c:3220 +#, c-format +msgid "patch failed: %s:%ld" +msgstr "el pedaç ha fallat: %s:%ld" -#: bisect.c:967 +#: apply.c:3342 #, c-format -msgid "%s was both %s and %s\n" -msgstr "%s era ambdós %s i %s\n" +msgid "cannot checkout %s" +msgstr "no es pot agafar %s" -#: bisect.c:975 +#: apply.c:3390 apply.c:3401 apply.c:3447 setup.c:248 #, c-format -msgid "" -"No testable commit found.\n" -"Maybe you started with bad path parameters?\n" -msgstr "" -"No s'ha trobat cap comissió provable.\n" -"Potser heu començat amb paràmetres de camí dolents?\n" +msgid "failed to read %s" +msgstr "s'ha fallat en llegir %s" -#: bisect.c:994 +#: apply.c:3398 #, c-format -msgid "(roughly %d step)" -msgid_plural "(roughly %d steps)" -msgstr[0] "(aproximadament %d pas)" -msgstr[1] "(aproximadament %d passos)" +msgid "reading from '%s' beyond a symbolic link" +msgstr "s'està llegint de '%s' més enllà d'un enllaç simbòlic" -#. TRANSLATORS: the last %s will be replaced with -#. "(roughly %d steps)" translation -#: bisect.c:998 +#: apply.c:3427 apply.c:3667 #, c-format -msgid "Bisecting: %d revision left to test after this %s\n" -msgid_plural "Bisecting: %d revisions left to test after this %s\n" -msgstr[0] "Bisecant: manca %d revisió a provar després d'aquesta %s\n" -msgstr[1] "Bisecant: manquen %d revisions a provar després d'aquesta %s\n" +msgid "path %s has been renamed/deleted" +msgstr "el camí %s s'ha canviat de nom / s'ha suprimit" -#: branch.c:53 +#: apply.c:3510 apply.c:3681 #, 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" -"Després de corregir la causa de l'error, podeu\n" -"intentar corregir la informació de seguiment remot\n" -"invocant \"git branch --set-upstream-to=%s%s%s\"." +msgid "%s: does not exist in index" +msgstr "%s: no existeix en l'índex" -#: branch.c:67 +#: apply.c:3519 apply.c:3689 #, c-format -msgid "Not setting branch %s as its own upstream." -msgstr "No s'està establint la branca %s com a la seva pròpia font." +msgid "%s: does not match index" +msgstr "%s: no coincideix amb l'índex" -#: branch.c:93 -#, c-format -msgid "Branch %s set up to track remote branch %s from %s by rebasing." +#: apply.c:3554 +msgid "repository lacks the necessary blob to fall back on 3-way merge." msgstr "" -"La branca %s està configurada per a seguir la branca remota %s de %s per " -"rebasar." +"al dipòsit li manca el blob necessari per a retrocedir a una fusió de 3 vies." -#: branch.c:94 +#: apply.c:3557 #, c-format -msgid "Branch %s set up to track remote branch %s from %s." -msgstr "La branca %s està configurada per a seguir la branca remota %s de %s." +msgid "Falling back to three-way merge...\n" +msgstr "S'està retrocedint a una fusió de 3 vies...\n" -#: branch.c:98 +#: apply.c:3573 apply.c:3577 #, c-format -msgid "Branch %s set up to track local branch %s by rebasing." -msgstr "" -"La branca %s està configurada per a seguir la branca local %s per rebasar." +msgid "cannot read the current contents of '%s'" +msgstr "no es poden llegir els continguts actuals de '%s'" -#: branch.c:99 +#: apply.c:3589 #, c-format -msgid "Branch %s set up to track local branch %s." -msgstr "La branca %s està configurada per a seguir la branca local %s." +msgid "Failed to fall back on three-way merge...\n" +msgstr "S'ha fallat en retrocedir a una fusió de 3 vies...\n" -#: branch.c:104 +#: apply.c:3603 #, c-format -msgid "Branch %s set up to track remote ref %s by rebasing." -msgstr "" -"La branca %s està configurada per a seguir la referència remota %s per " -"rebasar." +msgid "Applied patch to '%s' with conflicts.\n" +msgstr "S'ha aplicat el pedaç a '%s' amb conflictes.\n" -#: branch.c:105 +#: apply.c:3608 #, c-format -msgid "Branch %s set up to track remote ref %s." -msgstr "La branca %s està configurada per a seguir la referència remota %s." +msgid "Applied patch to '%s' cleanly.\n" +msgstr "S'ha aplicat el pedaç a '%s' netament.\n" -#: branch.c:109 -#, c-format -msgid "Branch %s set up to track local ref %s by rebasing." -msgstr "" -"La branca %s està configurada per a seguir la referència local %s per " -"rebasar." +#: apply.c:3634 +msgid "removal patch leaves file contents" +msgstr "el pedaç d'eliminació deixa els continguts dels fitxers" -#: branch.c:110 +#: apply.c:3706 #, c-format -msgid "Branch %s set up to track local ref %s." -msgstr "La branca %s està configurada per a seguir la referència local %s." - -#: branch.c:119 -msgid "Unable to write upstream branch configuration" -msgstr "No es pot escriure la configuració de la branca font" +msgid "%s: wrong type" +msgstr "%s: tipus erroni" -#: branch.c:156 +#: apply.c:3708 #, c-format -msgid "Not tracking: ambiguous information for ref %s" -msgstr "No seguint: informació ambigua per a la referència %s" +msgid "%s has type %o, expected %o" +msgstr "%s és del tipus %o, s'esperava %o" -#: branch.c:185 +#: apply.c:3859 apply.c:3861 #, c-format -msgid "'%s' is not a valid branch name." -msgstr "'%s' no és un nom de branca vàlid." +msgid "invalid path '%s'" +msgstr "camí no vàlid: %s" -#: branch.c:190 +#: apply.c:3917 #, c-format -msgid "A branch named '%s' already exists." -msgstr "Una branca amb nom '%s' ja existeix." - -#: branch.c:198 -msgid "Cannot force update the current branch." -msgstr "No es pot actualitzar la branca actual a la força." +msgid "%s: already exists in index" +msgstr "%s: ja existeix en l'índex" -#: branch.c:218 +#: apply.c:3920 #, c-format -msgid "Cannot setup tracking information; starting point '%s' is not a branch." -msgstr "" -"No es pot configurar la informació de seguiment; el punt inicial '%s' no és " -"una branca." +msgid "%s: already exists in working directory" +msgstr "%s: ja existeix en el directori de treball" -#: branch.c:220 +#: apply.c:3940 #, c-format -msgid "the requested upstream branch '%s' does not exist" -msgstr "la branca font demanada '%s' no existeix" - -#: branch.c:222 -msgid "" -"\n" -"If you are planning on basing your work on an upstream\n" -"branch that already exists at the remote, you may need to\n" -"run \"git fetch\" to retrieve it.\n" -"\n" -"If you are planning to push out a new local branch that\n" -"will track its remote counterpart, you may want to use\n" -"\"git push -u\" to set the upstream config as you push." -msgstr "" -"\n" -"Si teniu pensat basar el vostre treball en una branca\n" -"font que ja existeix al remot, pot ser que necessiteu\n" -"executar \"git fetch\" per a obtenir-la.\n" -"\n" -"Si teniu pensat pujar una branca local nova que seguirà\n" -"la seva contrapart remota, pot ser que vulgueu usar\n" -"\"git push -u\" per a establir la configuració font\n" -"mentre pugeu." +msgid "new mode (%o) of %s does not match old mode (%o)" +msgstr "el mode nou (%o) de %s no coincideix amb el mode antic (%o)" -#: branch.c:266 +#: apply.c:3945 #, c-format -msgid "Not a valid object name: '%s'." -msgstr "No és un nom d'objecte vàlid: '%s'." +msgid "new mode (%o) of %s does not match old mode (%o) of %s" +msgstr "el mode nou (%o) de %s no coincideix amb el mode antic (%o) de %s" -#: branch.c:286 +#: apply.c:3965 #, c-format -msgid "Ambiguous object name: '%s'." -msgstr "Nom d'objecte ambigu: '%s'." +msgid "affected file '%s' is beyond a symbolic link" +msgstr "el fitxer afectat '%s' és més enllà d'un enllaç simbòlic" -#: branch.c:291 +#: apply.c:3969 #, c-format -msgid "Not a valid branch point: '%s'." -msgstr "No és un punt de ramificació vàlid: '%s'." +msgid "%s: patch does not apply" +msgstr "%s: el pedaç no s'aplica" -#: branch.c:345 +#: apply.c:3984 #, c-format -msgid "'%s' is already checked out at '%s'" -msgstr "'%s' ja s'ha agafat a '%s'" +msgid "Checking patch %s..." +msgstr "S'està comprovant el pedaç %s..." -#: branch.c:364 +#: apply.c:4075 #, c-format -msgid "HEAD of working tree %s is not updated" -msgstr "La HEAD de l'arbre de treball %s no està actualitzat" +msgid "sha1 information is lacking or useless for submodule %s" +msgstr "falta la informació sha1 o és inútil per al submòdul %s" -#: bundle.c:34 +#: apply.c:4082 #, c-format -msgid "'%s' does not look like a v2 bundle file" -msgstr "'%s' no sembla un fitxer de farcell v2" +msgid "mode change for %s, which is not in current HEAD" +msgstr "canvi de mode per a %s, el qual no està en el HEAD actual" -#: bundle.c:61 +#: apply.c:4085 #, c-format -msgid "unrecognized header: %s%s (%d)" -msgstr "capçalera no reconeguda: %s%s (%d)" +msgid "sha1 information is lacking or useless (%s)." +msgstr "falta informació sha1 o és inútil (%s)." -#: bundle.c:87 builtin/commit.c:778 +#: apply.c:4090 builtin/checkout.c:233 builtin/reset.c:135 #, c-format -msgid "could not open '%s'" -msgstr "no s'ha pogut obrir '%s'" - -#: bundle.c:139 -msgid "Repository lacks these prerequisite commits:" -msgstr "Al dipòsit li manquen aquestes comissions prerequisits:" +msgid "make_cache_entry failed for path '%s'" +msgstr "make_cache_entry ha fallat per al camí '%s'" -#: bundle.c:163 ref-filter.c:1462 sequencer.c:630 sequencer.c:1085 -#: builtin/blame.c:2763 builtin/commit.c:1057 builtin/log.c:348 -#: builtin/log.c:890 builtin/log.c:1336 builtin/log.c:1659 builtin/log.c:1901 -#: builtin/merge.c:356 builtin/shortlog.c:170 -msgid "revision walk setup failed" -msgstr "la configuració del passeig per revisions ha fallat" +#: apply.c:4094 +#, c-format +msgid "could not add %s to temporary index" +msgstr "no s'ha pogut afegir %s a l'index temporal" -#: bundle.c:185 +#: apply.c:4104 #, c-format -msgid "The bundle contains this ref:" -msgid_plural "The bundle contains these %d refs:" -msgstr[0] "El farcell conté aquesta referència:" -msgstr[1] "El farcell conté aquestes %d referències:" +msgid "could not write temporary index to %s" +msgstr "no s'ha pogut escriure l'índex temporal a %s" -#: bundle.c:192 -msgid "The bundle records a complete history." -msgstr "El farcell registra una història completa." +#: apply.c:4242 +#, c-format +msgid "unable to remove %s from index" +msgstr "no s'ha pogut eliminar %s de l'índex" -#: bundle.c:194 +#: apply.c:4277 #, c-format -msgid "The bundle requires this ref:" -msgid_plural "The bundle requires these %d refs:" -msgstr[0] "El farcell requereix aquesta referència:" -msgstr[1] "El farcell requereix aquestes %d referències:" +msgid "corrupt patch for submodule %s" +msgstr "pedaç malmès per al submòdul %s" -#: bundle.c:253 -msgid "Could not spawn pack-objects" -msgstr "No s'ha pogut executar el pack-objects" +#: apply.c:4283 +#, c-format +msgid "unable to stat newly created file '%s'" +msgstr "no s'ha pogut fer stat al fitxer novament creat '%s'" -#: bundle.c:264 -msgid "pack-objects died" -msgstr "El pack-objects s'ha mort" +#: apply.c:4291 +#, c-format +msgid "unable to create backing store for newly created file %s" +msgstr "" +"no s'ha pogut crear un magatzem de recolzament per al fitxer novament creat " +"%s" -#: bundle.c:304 -msgid "rev-list died" -msgstr "El rev-list s'ha mort" +#: apply.c:4297 apply.c:4441 +#, c-format +msgid "unable to add cache entry for %s" +msgstr "no s'ha pogut afegir una entrada de cau per a %s" -#: bundle.c:353 +#: apply.c:4338 #, c-format -msgid "ref '%s' is excluded by the rev-list options" -msgstr "les opcions de la llista de revisions exclouen la referència '%s'" +msgid "failed to write to '%s'" +msgstr "s'ha fallat en escriure a '%s'" -#: bundle.c:443 builtin/log.c:165 builtin/log.c:1565 builtin/shortlog.c:273 +#: apply.c:4342 #, c-format -msgid "unrecognized argument: %s" -msgstr "paràmetre no reconegut: %s" +msgid "closing file '%s'" +msgstr "s'està tancant el fitxer '%s'" -#: bundle.c:451 -msgid "Refusing to create empty bundle." -msgstr "S'està refusant crear un farcell buit." +#: apply.c:4412 +#, c-format +msgid "unable to write file '%s' mode %o" +msgstr "no s'ha pogut escriure el fitxer '%s' mode %o" -#: bundle.c:463 +#: apply.c:4510 #, c-format -msgid "cannot create '%s'" -msgstr "no es pot crear '%s'" +msgid "Applied patch %s cleanly." +msgstr "El pedaç %s s'ha aplicat netament." -#: bundle.c:491 -msgid "index-pack died" -msgstr "L'index-pack s'ha mort" +#: apply.c:4518 +msgid "internal error" +msgstr "error intern" -#: color.c:290 +#: apply.c:4521 #, c-format -msgid "invalid color value: %.*s" -msgstr "valor de color no vàlid: %.*s" +msgid "Applying patch %%s with %d reject..." +msgid_plural "Applying patch %%s with %d rejects..." +msgstr[0] "S'està aplicant el pedaç %%s amb %d rebuig..." +msgstr[1] "S'està aplicant el pedaç %%s amb %d rebuitjos..." -#: commit.c:40 builtin/am.c:433 builtin/am.c:469 builtin/am.c:1505 -#: builtin/am.c:2119 +#: apply.c:4532 #, c-format -msgid "could not parse %s" -msgstr "no s'ha pogut analitzar %s" +msgid "truncating .rej filename to %.*s.rej" +msgstr "s'està truncant el nom del fitxer .rej a %.*s.rej" -#: commit.c:42 +#: apply.c:4540 builtin/fetch.c:740 builtin/fetch.c:989 #, c-format -msgid "%s %s is not a commit!" -msgstr "%s %s no és una comissió!" +msgid "cannot open %s" +msgstr "no es pot obrir %s" -#: compat/obstack.c:406 compat/obstack.c:408 -msgid "memory exhausted" -msgstr "memòria esgotada" +#: apply.c:4554 +#, c-format +msgid "Hunk #%d applied cleanly." +msgstr "El tros #%d s'ha aplicat netament." -#: config.c:516 +#: apply.c:4558 #, c-format -msgid "bad config line %d in blob %s" -msgstr "línia de configuració dolenta %d en el blob %s" +msgid "Rejected hunk #%d." +msgstr "S'ha rebutjat el tros #%d." -#: config.c:520 +#: apply.c:4668 #, c-format -msgid "bad config line %d in file %s" -msgstr "línia de configuració dolenta %d en el fitxer %s" +msgid "Skipped patch '%s'." +msgstr "S'ha saltat el pedaç '%s'." -#: config.c:524 +#: apply.c:4676 +msgid "unrecognized input" +msgstr "entrada no reconeguda" + +#: apply.c:4695 +msgid "unable to read index file" +msgstr "no es pot llegir el fitxer d'índex" + +#: apply.c:4833 #, c-format -msgid "bad config line %d in standard input" -msgstr "línia de configuració dolenta %d en l'entrada estàndard" +msgid "can't open patch '%s': %s" +msgstr "no es pot obrir el pedaç '%s': %s" -#: config.c:528 +#: apply.c:4858 #, c-format -msgid "bad config line %d in submodule-blob %s" -msgstr "línia de configuració dolenta %d en el blob de submòdul %s" +msgid "squelched %d whitespace error" +msgid_plural "squelched %d whitespace errors" +msgstr[0] "s'ha omès %d error d'espai en blanc" +msgstr[1] "s'han omès %d errors d'espai en blanc" -#: config.c:532 +#: apply.c:4864 apply.c:4879 #, c-format -msgid "bad config line %d in command line %s" -msgstr "línia de configuració dolenta %d en la línia d'ordres %s" +msgid "%d line adds whitespace errors." +msgid_plural "%d lines add whitespace errors." +msgstr[0] "%d línia afegeix errors d'espai en blanc." +msgstr[1] "%d línies afegeixen errors d'espai en blanc." -#: config.c:536 +#: apply.c:4872 #, c-format -msgid "bad config line %d in %s" -msgstr "línia de configuració dolenta %d en %s" +msgid "%d line applied after fixing whitespace errors." +msgid_plural "%d lines applied after fixing whitespace errors." +msgstr[0] "" +"S'ha aplicat %d línia desprès d'arreglar els errors d'espai en blanc." +msgstr[1] "" +"S'han aplicat %d línies desprès d'arreglar els errors d'espai en blanc." -#: config.c:655 -msgid "out of range" -msgstr "fora de rang" +#: apply.c:4888 builtin/add.c:463 builtin/mv.c:286 builtin/rm.c:431 +msgid "Unable to write new index file" +msgstr "no s'ha pogut escriure un fitxer d'índex nou" -#: config.c:655 -msgid "invalid unit" -msgstr "unitat no vàlida" +#: apply.c:4919 apply.c:4922 builtin/am.c:2277 builtin/am.c:2280 +#: builtin/clone.c:95 builtin/fetch.c:98 builtin/pull.c:180 +#: builtin/submodule--helper.c:281 builtin/submodule--helper.c:407 +#: builtin/submodule--helper.c:589 builtin/submodule--helper.c:592 +#: builtin/submodule--helper.c:944 builtin/submodule--helper.c:947 +msgid "path" +msgstr "camí" -#: config.c:661 -#, c-format -msgid "bad numeric config value '%s' for '%s': %s" -msgstr "valor de configuració numèric dolent '%s' per '%s': %s" +#: apply.c:4920 +msgid "don't apply changes matching the given path" +msgstr "no apliquis els canvis que coincideixin amb el camí donat" -#: config.c:666 -#, c-format -msgid "bad numeric config value '%s' for '%s' in blob %s: %s" -msgstr "valor de configuració numèric dolent '%s' per '%s' en el blob %s: %s" +#: apply.c:4923 +msgid "apply changes matching the given path" +msgstr "aplica els canvis que coincideixin amb el camí donat" -#: config.c:669 -#, c-format -msgid "bad numeric config value '%s' for '%s' in file %s: %s" -msgstr "valor de configuració numèric dolent '%s' per '%s' en el fitxer %s: %s" +#: apply.c:4925 builtin/am.c:2286 +msgid "num" +msgstr "número" -#: config.c:672 -#, c-format -msgid "bad numeric config value '%s' for '%s' in standard input: %s" +#: apply.c:4926 +msgid "remove leading slashes from traditional diff paths" msgstr "" -"valor de configuració numèric dolent '%s' per '%s' en l'entrada estàndard: %s" +"elimina barres obliqües inicials dels camins de diferència " +"tradicionals" -#: config.c:675 -#, c-format -msgid "bad numeric config value '%s' for '%s' in submodule-blob %s: %s" -msgstr "" -"valor de configuració numèric dolent '%s' per '%s' en el blob de submòdul " -"%s: %s" +#: apply.c:4929 +msgid "ignore additions made by the patch" +msgstr "ignora afegiments fets pel pedaç" -#: config.c:678 -#, c-format -msgid "bad numeric config value '%s' for '%s' in command line %s: %s" +#: apply.c:4931 +msgid "instead of applying the patch, output diffstat for the input" msgstr "" -"valor de configuració numèric dolent '%s' per '%s' en la línia d'ordres %s: " -"%s" +"en lloc d'aplicar el pedaç, emet les estadístiques de diferència de l'entrada" -#: config.c:681 -#, c-format -msgid "bad numeric config value '%s' for '%s' in %s: %s" -msgstr "valor de configuració numèric dolent '%s' per '%s' en %s: %s" +#: apply.c:4935 +msgid "show number of added and deleted lines in decimal notation" +msgstr "mostra el nombre de línies afegides i suprimides en notació decimal" -#: config.c:768 -#, c-format -msgid "failed to expand user dir in: '%s'" -msgstr "s'ha fallat en expandir el directori d'usuari en '%s'" +#: apply.c:4937 +msgid "instead of applying the patch, output a summary for the input" +msgstr "en lloc d'aplicar el pedaç, emet un resum de l'entrada" -#: config.c:849 config.c:860 -#, c-format -msgid "bad zlib compression level %d" -msgstr "nivell de compressió de zlib dolent %d" +#: apply.c:4939 +msgid "instead of applying the patch, see if the patch is applicable" +msgstr "en lloc d'aplicar el pedaç, veges si el pedaç és aplicable" -#: config.c:978 -#, c-format -msgid "invalid mode for object creation: %s" -msgstr "mode de creació d'objecte no vàlid: %s" +#: apply.c:4941 +msgid "make sure the patch is applicable to the current index" +msgstr "assegura que el pedaç sigui aplicable a l'índex actual" -#: config.c:1312 -msgid "unable to parse command-line config" -msgstr "no s'ha pogut analitzar la configuració de la línia d'ordres" +#: apply.c:4943 +msgid "apply a patch without touching the working tree" +msgstr "aplica un pedaç sense tocar l'arbre de treball" -#: config.c:1362 -msgid "unknown error occurred while reading the configuration files" -msgstr "un error desconegut ha ocorregut en llegir els fitxers de configuració" +#: apply.c:4945 +msgid "accept a patch that touches outside the working area" +msgstr "accepta un pedaç que toqui fora de l'àrea de treball" -#: config.c:1716 -#, c-format -msgid "unable to parse '%s' from command-line config" -msgstr "no s'ha pogut analitzar '%s' de la configuració de la línia d'ordres" +#: apply.c:4947 +msgid "also apply the patch (use with --stat/--summary/--check)" +msgstr "aplica el pedaç també (useu amb --stat/--summary/--check)" -#: config.c:1718 -#, c-format -msgid "bad config variable '%s' in file '%s' at line %d" -msgstr "variable de configuració dolenta '%s' en el fitxer '%s' a la línia %d" +#: apply.c:4949 +msgid "attempt three-way merge if a patch does not apply" +msgstr "intenta una fusió de tres vies si el pedaç no s'aplica" -#: config.c:1777 -#, c-format -msgid "%s has multiple values" -msgstr "%s té múltiples valors" +#: apply.c:4951 +msgid "build a temporary index based on embedded index information" +msgstr "construeix un índex temporal basat en la informació d'índex incrustada" -#: config.c:2311 -#, c-format -msgid "could not set '%s' to '%s'" -msgstr "no s'ha pogut establir '%s' a '%s'" +#: apply.c:4954 builtin/checkout-index.c:169 builtin/ls-files.c:505 +msgid "paths are separated with NUL character" +msgstr "els camins se separen amb el caràcter NUL" -#: config.c:2313 -#, c-format -msgid "could not unset '%s'" -msgstr "no s'ha pogut desestablir '%s'" +#: apply.c:4956 +msgid "ensure at least lines of context match" +msgstr "assegura't que almenys línies de context coincideixin" -#: connected.c:63 builtin/fsck.c:173 builtin/prune.c:140 -msgid "Checking connectivity" -msgstr "S'està comprovant la connectivitat" +#: apply.c:4957 builtin/am.c:2265 +msgid "action" +msgstr "acció" -#: connected.c:74 -msgid "Could not run 'git rev-list'" -msgstr "No s'ha pogut executar 'git rev-list'" +#: apply.c:4958 +msgid "detect new or modified lines that have whitespace errors" +msgstr "" +"detecta les línies noves o modificades que tinguin errors d'espai en blanc" -#: connected.c:94 -msgid "failed write to rev-list" -msgstr "escriptura fallada a rev-list" +#: apply.c:4961 apply.c:4964 +msgid "ignore changes in whitespace when finding context" +msgstr "ignora els canvis d'espai en blanc en cercar context" -#: connected.c:101 -msgid "failed to close rev-list's stdin" -msgstr "s'ha fallat en tancar l'stdin del rev-list" +#: apply.c:4967 +msgid "apply the patch in reverse" +msgstr "aplica el pedaç al revés" -#: date.c:97 -msgid "in the future" -msgstr "en el futur" +#: apply.c:4969 +msgid "don't expect at least one line of context" +msgstr "no esperis almenys una línia de context" -#: date.c:103 -#, c-format -msgid "%lu second ago" -msgid_plural "%lu seconds ago" -msgstr[0] "fa %lu segon" -msgstr[1] "fa %lu segons" +#: apply.c:4971 +msgid "leave the rejected hunks in corresponding *.rej files" +msgstr "deixa els trossos rebutjats en fitxers *.reg corresponents" -#: date.c:110 -#, c-format -msgid "%lu minute ago" -msgid_plural "%lu minutes ago" -msgstr[0] "fa %lu minut" -msgstr[1] "fa %lu minuts" +#: apply.c:4973 +msgid "allow overlapping hunks" +msgstr "permet trossos encavalcants" -#: date.c:117 -#, c-format -msgid "%lu hour ago" -msgid_plural "%lu hours ago" -msgstr[0] "fa %lu hora" -msgstr[1] "fa %lu hores" +#: apply.c:4974 builtin/add.c:267 builtin/check-ignore.c:19 +#: builtin/commit.c:1339 builtin/count-objects.c:94 builtin/fsck.c:593 +#: builtin/log.c:1860 builtin/mv.c:110 builtin/read-tree.c:114 +msgid "be verbose" +msgstr "sigues detallat" -#: date.c:124 -#, c-format -msgid "%lu day ago" -msgid_plural "%lu days ago" -msgstr[0] "fa %lu dia" -msgstr[1] "fa %lu dies" +#: apply.c:4976 +msgid "tolerate incorrectly detected missing new-line at the end of file" +msgstr "tolera una línia nova incorrectament detectada al final del fitxer" -#: date.c:130 -#, c-format -msgid "%lu week ago" -msgid_plural "%lu weeks ago" -msgstr[0] "fa %lu setmana" -msgstr[1] "fa %lu setmanes" +#: apply.c:4979 +msgid "do not trust the line counts in the hunk headers" +msgstr "no confiïs en els recomptes de línia en les capçaleres dels trossos" -#: date.c:137 -#, c-format -msgid "%lu month ago" -msgid_plural "%lu months ago" -msgstr[0] "fa %lu mes" -msgstr[1] "fa %lu mesos" +#: apply.c:4981 builtin/am.c:2274 +msgid "root" +msgstr "arrel" -#: date.c:148 -#, c-format -msgid "%lu year" -msgid_plural "%lu years" -msgstr[0] "%lu any" -msgstr[1] "%lu anys" +#: apply.c:4982 +msgid "prepend to all filenames" +msgstr "anteposa a tots els noms de fitxer" -#. TRANSLATORS: "%s" is " years" -#: date.c:151 -#, c-format -msgid "%s, %lu month ago" -msgid_plural "%s, %lu months ago" -msgstr[0] "fa %s i %lu mes" -msgstr[1] "fa %s i %lu mesos" +#: archive.c:12 +msgid "git archive [] [...]" +msgstr "git archive [] [...]" -#: date.c:156 date.c:161 -#, c-format -msgid "%lu year ago" -msgid_plural "%lu years ago" -msgstr[0] "fa %lu any" -msgstr[1] "fa %lu anys" +#: archive.c:13 +msgid "git archive --list" +msgstr "git archive --list" -#: diffcore-order.c:24 -#, c-format -msgid "failed to read orderfile '%s'" -msgstr "s'ha fallat en llegir el fitxer d'ordres '%s'" +#: archive.c:14 +msgid "" +"git archive --remote [--exec ] [] [...]" +msgstr "" +"git archive --remote [--exec ] [] " +"[...]" -#: diffcore-rename.c:540 -msgid "Performing inexact rename detection" -msgstr "S'està realitzant una detecció inexacta de canvis de nom" +#: archive.c:15 +msgid "git archive --remote [--exec ] --list" +msgstr "git archive --remote [--exec ] --list" -#: diff.c:116 +#: archive.c:344 builtin/add.c:152 builtin/add.c:442 builtin/rm.c:327 #, c-format -msgid " Failed to parse dirstat cut-off percentage '%s'\n" -msgstr " S'ha fallat en analitzar el percentatge limitant de dirstat '%s'\n" +msgid "pathspec '%s' did not match any files" +msgstr "l'especificació de camí '%s' no ha coincidit amb cap fitxer" -#: diff.c:121 -#, c-format -msgid " Unknown dirstat parameter '%s'\n" -msgstr " Paràmetre de dirstat desconegut '%s'\n" +#: archive.c:429 +msgid "fmt" +msgstr "format" -#: diff.c:225 -#, c-format -msgid "Unknown value for 'diff.submodule' config variable: '%s'" -msgstr "" -"Valor desconegut de la variable de configuració de 'diff.submodule': '%s'" +#: archive.c:429 +msgid "archive format" +msgstr "format d'arxiu" -#: diff.c:277 -#, c-format -msgid "" -"Found errors in 'diff.dirstat' config variable:\n" -"%s" -msgstr "" -"S'han trobat errors en la variable de configuració 'diff.dirstat':\n" -"%s" +#: archive.c:430 builtin/log.c:1429 +msgid "prefix" +msgstr "prefix" -#: diff.c:3017 -#, c-format -msgid "external diff died, stopping at %s" -msgstr "El diff external s'ha mort, s'està aturant a %s" +#: archive.c:431 +msgid "prepend prefix to each pathname in the archive" +msgstr "anteposa el prefix a cada nom de camí en l'arxiu" -#: diff.c:3415 -msgid "--follow requires exactly one pathspec" -msgstr "--follow requereix exactament una especificació de camí" +#: archive.c:432 builtin/blame.c:2603 builtin/blame.c:2604 builtin/config.c:59 +#: builtin/fast-export.c:987 builtin/fast-export.c:989 builtin/grep.c:723 +#: builtin/hash-object.c:101 builtin/ls-files.c:539 builtin/ls-files.c:542 +#: builtin/notes.c:401 builtin/notes.c:564 builtin/read-tree.c:109 +#: parse-options.h:153 +msgid "file" +msgstr "fitxer" -#: diff.c:3578 -#, c-format -msgid "" -"Failed to parse --dirstat/-X option parameter:\n" -"%s" -msgstr "" -"S'ha fallat en analitzar el paràmetre d'opció de --dirstat/-X:\n" -"%s" +#: archive.c:433 builtin/archive.c:89 +msgid "write the archive to this file" +msgstr "escriu l'arxiu a aquest fitxer" -#: diff.c:3592 -#, c-format -msgid "Failed to parse --submodule option parameter: '%s'" -msgstr "S'ha fallat en analitzar el paràmetre d'opció de --submodule: %s" +#: archive.c:435 +msgid "read .gitattributes in working directory" +msgstr "llegeix .gitattributes en el directori de treball" -#: dir.c:1823 -msgid "failed to get kernel name and information" -msgstr "s'ha fallat en obtenir el nombre i la informació del nucli" +#: archive.c:436 +msgid "report archived files on stderr" +msgstr "informa de fitxers arxivats en stderr" -#: dir.c:1942 -msgid "Untracked cache is disabled on this system or location." -msgstr "" -"La memòria cau no seguida està inhabilitada en aquest sistema o ubicació." +#: archive.c:437 +msgid "store only" +msgstr "només emmagatzema" -#: gpg-interface.c:178 -msgid "gpg failed to sign the data" -msgstr "gpg ha fallat en signar les dades" +#: archive.c:438 +msgid "compress faster" +msgstr "comprimeix més ràpidament" -#: gpg-interface.c:208 -msgid "could not create temporary file" -msgstr "no s'ha pogut crear el fitxer temporal" +#: archive.c:446 +msgid "compress better" +msgstr "comprimeix millor" -#: gpg-interface.c:210 -#, c-format -msgid "failed writing detached signature to '%s'" -msgstr "s'ha fallat en escriure la signatura separada a '%s'" +#: archive.c:449 +msgid "list supported archive formats" +msgstr "allista els formats d'arxiu admesos" -#: grep.c:1792 -#, c-format -msgid "'%s': unable to read %s" -msgstr "'%s': no s'ha pogut llegir %s" +#: archive.c:451 builtin/archive.c:90 builtin/clone.c:85 builtin/clone.c:88 +#: builtin/submodule--helper.c:601 builtin/submodule--helper.c:953 +msgid "repo" +msgstr "dipòsit" -#: grep.c:1809 builtin/clone.c:382 builtin/diff.c:84 builtin/rm.c:155 -#, c-format -msgid "failed to stat '%s'" -msgstr "s'ha fallat en fer stat a '%s'" +#: archive.c:452 builtin/archive.c:91 +msgid "retrieve the archive from remote repository " +msgstr "recupera l'arxiu del dipòsit remot " -#: grep.c:1820 -#, c-format -msgid "'%s': short read" -msgstr "'%s': lectura curta" +#: archive.c:453 builtin/archive.c:92 builtin/notes.c:485 +msgid "command" +msgstr "ordre" -#: help.c:205 -#, c-format -msgid "available git commands in '%s'" -msgstr "ordres de git disponibles en '%s'" +#: archive.c:454 builtin/archive.c:93 +msgid "path to the remote git-upload-archive command" +msgstr "camí a l'ordre git-upload-archive remota" -#: help.c:212 -msgid "git commands available from elsewhere on your $PATH" -msgstr "ordres de git disponibles d'altres llocs en el vostre $PATH" +#: archive.c:461 +msgid "Unexpected option --remote" +msgstr "Opció inesperada --remote" -#: help.c:244 -msgid "These are common Git commands used in various situations:" -msgstr "Aquestes són ordres del Git comunament usades en diverses situacions:" +#: archive.c:463 +msgid "Option --exec can only be used together with --remote" +msgstr "L'opció --exec només es pot usar junt amb --remote" -#: help.c:309 -#, c-format -msgid "" -"'%s' appears to be a git command, but we were not\n" -"able to execute it. Maybe git-%s is broken?" -msgstr "" -"'%s' sembla una ordre de git, però no hem pogut\n" -"executar-la. Pot ser que git-%s estigui estropejat?" +#: archive.c:465 +msgid "Unexpected option --output" +msgstr "Opció inesperada --output" -#: help.c:366 -msgid "Uh oh. Your system reports no Git commands at all." -msgstr "Ai. El vostre sistema no informa de cap ordre de Git." +#: archive.c:487 +#, c-format +msgid "Unknown archive format '%s'" +msgstr "Format d'arxiu desconegut '%s'" -#: help.c:388 +#: archive.c:494 #, c-format +msgid "Argument not supported for format '%s': -%d" +msgstr "Paràmetre no admès per al format '%s': -%d" + +#: attr.c:263 msgid "" -"WARNING: You called a Git command named '%s', which does not exist.\n" -"Continuing under the assumption that you meant '%s'" +"Negative patterns are ignored in git attributes\n" +"Use '\\!' for literal leading exclamation." msgstr "" -"ADVERTÈNCIA: Heu invocat una ordre de Git amb nom '%s', la qual no " -"existeix.\n" -"S'està continuant sota l'assumpció que volíeu dir '%s'" +"Els patrons negatius s'ignoren en els atributs de git\n" +"Useu '\\!' per exclamació capdavantera literal." -#: help.c:393 +#: bisect.c:441 #, c-format -msgid "in %0.1f seconds automatically..." -msgstr "en %0.1f segons automàticament..." +msgid "Could not open file '%s'" +msgstr "No s'ha pogut obrir el fitxer '%s'" -#: help.c:400 +#: bisect.c:446 #, c-format -msgid "git: '%s' is not a git command. See 'git --help'." -msgstr "git: '%s' no és una ordre de git. Vegeu 'git --help'." +msgid "Badly quoted content in file '%s': %s" +msgstr "Comentari amb cometes dolentes en el fitxer '%s': %s" -#: help.c:404 help.c:470 -msgid "" -"\n" -"Did you mean this?" -msgid_plural "" -"\n" -"Did you mean one of these?" -msgstr[0] "" -"\n" -"Volíeu dir això?" -msgstr[1] "" -"\n" -"Volíeu dir un d'aquests?" +#: bisect.c:655 +#, c-format +msgid "We cannot bisect more!\n" +msgstr "No podem bisecar més!\n" -#: help.c:466 +#: bisect.c:708 #, c-format -msgid "%s: %s - %s" -msgstr "%s: %s - %s" +msgid "Not a valid commit name %s" +msgstr "No és un nom de comissió vàlid %s" -#: lockfile.c:152 +#: bisect.c:732 #, 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." +"The merge base %s is bad.\n" +"This means the bug has been fixed between %s and [%s].\n" msgstr "" -"No s'ha pogut crear '%s.lock': %s.\n" -"\n" -"Sembla que un altre procés de git s'està executant en aquest\n" -"dipòsit, per exemple, un editor obert per 'git commit'. Si us\n" -"plau, assegureu-vos que tots els processos s'hagin terminat i\n" -"llavors trobeu de nou. Si encara falla, potser que un procés de\n" -"git ha tingut una pana:\n" -"elimineu el fitxer manualment per a continuar." +"La base de fusió %s és dolenta.\n" +"Això vol dir que el defecte s'ha arreglat entre %s i [%s].\n" -#: lockfile.c:160 +#: bisect.c:737 #, c-format -msgid "Unable to create '%s.lock': %s" -msgstr "No es pot crear '%s.lock': %s" +msgid "" +"The merge base %s is new.\n" +"The property has changed between %s and [%s].\n" +msgstr "" +"La base de fusió %s és nova.\n" +"La propietat s'ha canviat entre %s i [%s].\n" -#: merge.c:41 -msgid "failed to read the cache" -msgstr "s'ha fallat en llegir la memòria cau" +#: bisect.c:742 +#, c-format +msgid "" +"The merge base %s is %s.\n" +"This means the first '%s' commit is between %s and [%s].\n" +msgstr "" +"La base de fusió %s és %s.\n" +"Això vol dir que la primera comissió '%s' és entre %s i [%s].\n" -#: merge.c:94 builtin/am.c:1992 builtin/am.c:2027 builtin/checkout.c:375 -#: builtin/checkout.c:589 builtin/clone.c:732 -msgid "unable to write new index file" -msgstr "no s'ha pogut escriure un fitxer d'índex nou" +#: bisect.c:750 +#, c-format +msgid "" +"Some %s revs are not ancestor of the %s rev.\n" +"git bisect cannot work properly in this case.\n" +"Maybe you mistook %s and %s revs?\n" +msgstr "" +"Unes revisions %s no són els avantpassats de la revisió %s.\n" +"git bisect no pot funcionar correctament en aquest cas.\n" +"Potser heu confós les revisions %s i %s?\n" -#: merge-recursive.c:209 -msgid "(bad commit)\n" -msgstr "(comissió dolenta)\n" +#: bisect.c:763 +#, c-format +msgid "" +"the merge base between %s and [%s] must be skipped.\n" +"So we cannot be sure the first %s commit is between %s and %s.\n" +"We continue anyway." +msgstr "" +"s'ha de saltar la base de fusió entre %s i [%s].\n" +"Llavors, no podem estar segurs de que la primera comissió %s sigui entre %s " +"i %s.\n" +"Continuem de totes maneres." -#: merge-recursive.c:231 +#: bisect.c:798 #, c-format -msgid "addinfo_cache failed for path '%s'" -msgstr "addinfo_cache ha fallat per al camí '%s'" +msgid "Bisecting: a merge base must be tested\n" +msgstr "Bisecant: s'ha de provar una base de fusió\n" -#: merge-recursive.c:301 -msgid "error building trees" -msgstr "error en construir arbres" +#: bisect.c:849 +#, c-format +msgid "a %s revision is needed" +msgstr "es necessita una revisió %s" -#: merge-recursive.c:720 +#: bisect.c:866 builtin/notes.c:174 builtin/tag.c:248 #, c-format -msgid "failed to create path '%s'%s" -msgstr "s'ha fallat en crear el camí '%s' %s" +msgid "could not create file '%s'" +msgstr "no s'ha pogut crear el fitxer '%s'" -#: merge-recursive.c:731 +#: bisect.c:917 #, c-format -msgid "Removing %s to make room for subdirectory\n" -msgstr "S'està eliminant %s per a fer espai per al subdirectori\n" +msgid "could not read file '%s'" +msgstr "no s'ha pogut llegir el fitxer '%s'" -#: merge-recursive.c:745 merge-recursive.c:764 -msgid ": perhaps a D/F conflict?" -msgstr ": potser un conflicte D/F?" +#: bisect.c:947 +msgid "reading bisect refs failed" +msgstr "la lectura de les referències de bisecció ha fallat" -#: merge-recursive.c:754 +#: bisect.c:967 #, c-format -msgid "refusing to lose untracked file at '%s'" -msgstr "s'està refusant perdre el fitxer no seguit a '%s'" +msgid "%s was both %s and %s\n" +msgstr "%s era ambdós %s i %s\n" -#: merge-recursive.c:796 +#: bisect.c:975 #, c-format -msgid "cannot read object %s '%s'" -msgstr "no es pot llegir l'objecte %s '%s'" +msgid "" +"No testable commit found.\n" +"Maybe you started with bad path parameters?\n" +msgstr "" +"No s'ha trobat cap comissió provable.\n" +"Potser heu començat amb paràmetres de camí dolents?\n" -#: merge-recursive.c:798 +#: bisect.c:994 #, c-format -msgid "blob expected for %s '%s'" -msgstr "blob esperat per a %s '%s'" +msgid "(roughly %d step)" +msgid_plural "(roughly %d steps)" +msgstr[0] "(aproximadament %d pas)" +msgstr[1] "(aproximadament %d passos)" -#: merge-recursive.c:822 +#. TRANSLATORS: the last %s will be replaced with +#. "(roughly %d steps)" translation +#: bisect.c:998 #, c-format -msgid "failed to open '%s': %s" -msgstr "s'ha fallat en obrir '%s': %s" +msgid "Bisecting: %d revision left to test after this %s\n" +msgid_plural "Bisecting: %d revisions left to test after this %s\n" +msgstr[0] "Bisecant: manca %d revisió a provar després d'aquesta %s\n" +msgstr[1] "Bisecant: manquen %d revisions a provar després d'aquesta %s\n" -#: merge-recursive.c:833 +#: branch.c:53 #, c-format -msgid "failed to symlink '%s': %s" -msgstr "s'ha fallat en fer l'enllaç simbòlic '%s': %s" +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" +"Després de corregir la causa de l'error, podeu\n" +"intentar corregir la informació de seguiment remot\n" +"invocant \"git branch --set-upstream-to=%s%s%s\"." -#: merge-recursive.c:838 +#: branch.c:67 #, c-format -msgid "do not know what to do with %06o %s '%s'" -msgstr "no se sap què fer amb %06o %s '%s'" - -#: merge-recursive.c:978 -msgid "Failed to execute internal merge" -msgstr "S'ha fallat en executar la fusió interna" +msgid "Not setting branch %s as its own upstream." +msgstr "No s'està establint la branca %s com a la seva pròpia font." -#: merge-recursive.c:982 +#: branch.c:93 #, c-format -msgid "Unable to add %s to database" -msgstr "no s'ha pogut afegir %s a la base de dades" +msgid "Branch %s set up to track remote branch %s from %s by rebasing." +msgstr "" +"La branca %s està configurada per a seguir la branca remota %s de %s per " +"rebasar." -#: merge-recursive.c:1081 merge-recursive.c:1095 +#: branch.c:94 #, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree." -msgstr "" -"CONFLICTE: (%s/supressió): %s suprimit en %s i %s en %s. La versió %s de %s " -"s'ha deixat en l'arbre." +msgid "Branch %s set up to track remote branch %s from %s." +msgstr "La branca %s està configurada per a seguir la branca remota %s de %s." -#: merge-recursive.c:1087 merge-recursive.c:1100 +#: branch.c:98 #, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree at %s." +msgid "Branch %s set up to track local branch %s by rebasing." msgstr "" -"CONFLICTE: (%s/supressió): %s suprimit en %s i %s en %s. La versió %s de %s " -"s'ha deixat en l'arbre a %s." - -#: merge-recursive.c:1143 -msgid "rename" -msgstr "canvia de nom" - -#: merge-recursive.c:1143 -msgid "renamed" -msgstr "canviat de nom" +"La branca %s està configurada per a seguir la branca local %s per rebasar." -#: merge-recursive.c:1200 +#: branch.c:99 #, c-format -msgid "%s is a directory in %s adding as %s instead" -msgstr "%s és un directori en %s; s'està afegint com a %s en lloc d'això" +msgid "Branch %s set up to track local branch %s." +msgstr "La branca %s està configurada per a seguir la branca local %s." -#: merge-recursive.c:1225 +#: branch.c:104 #, c-format -msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s" -"\"->\"%s\" in \"%s\"%s" +msgid "Branch %s set up to track remote ref %s by rebasing." msgstr "" -"CONFLICTE (canvi de nom/canvi de nom): Canvi de nom \"%s\"->\"%s\" en la " -"branca \"%s\" canvi de nom \"%s\"->\"%s\" en \"%s\"%s" +"La branca %s està configurada per a seguir la referència remota %s per " +"rebasar." -#: merge-recursive.c:1230 -msgid " (left unresolved)" -msgstr " (deixat sense resolució)" +#: branch.c:105 +#, c-format +msgid "Branch %s set up to track remote ref %s." +msgstr "La branca %s està configurada per a seguir la referència remota %s." -#: merge-recursive.c:1292 +#: branch.c:109 #, c-format -msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" +msgid "Branch %s set up to track local ref %s by rebasing." msgstr "" -"CONFLICTE (canvi de nom/canvi de nom): Canvi de nom %s->%s en %s. Canvi de " -"nom %s->%s en %s" +"La branca %s està configurada per a seguir la referència local %s per " +"rebasar." -#: merge-recursive.c:1325 +#: branch.c:110 #, c-format -msgid "Renaming %s to %s and %s to %s instead" -msgstr "S'està canviant el nom de %s a %s i %s a %s en lloc d'això" +msgid "Branch %s set up to track local ref %s." +msgstr "La branca %s està configurada per a seguir la referència local %s." -#: merge-recursive.c:1531 +#: branch.c:119 +msgid "Unable to write upstream branch configuration" +msgstr "No es pot escriure la configuració de la branca font" + +#: branch.c:156 #, c-format -msgid "CONFLICT (rename/add): Rename %s->%s in %s. %s added in %s" -msgstr "" -"CONFLICTE (canvi de nom/afegiment): Canvi de nom %s->%s en %s. %s afegit en " -"%s" +msgid "Not tracking: ambiguous information for ref %s" +msgstr "No seguint: informació ambigua per a la referència %s" -#: merge-recursive.c:1546 +#: branch.c:185 #, c-format -msgid "Adding merged %s" -msgstr "S'està afegint %s fusionat" +msgid "'%s' is not a valid branch name." +msgstr "'%s' no és un nom de branca vàlid." -#: merge-recursive.c:1553 merge-recursive.c:1766 +#: branch.c:190 #, c-format -msgid "Adding as %s instead" -msgstr "S'està afegint com a %s en lloc d'això" +msgid "A branch named '%s' already exists." +msgstr "Una branca amb nom '%s' ja existeix." -#: merge-recursive.c:1610 +#: branch.c:198 +msgid "Cannot force update the current branch." +msgstr "No es pot actualitzar la branca actual a la força." + +#: branch.c:218 #, c-format -msgid "cannot read object %s" -msgstr "no es pot llegir l'objecte %s" +msgid "Cannot setup tracking information; starting point '%s' is not a branch." +msgstr "" +"No es pot configurar la informació de seguiment; el punt inicial '%s' no és " +"una branca." -#: merge-recursive.c:1613 +#: branch.c:220 #, c-format -msgid "object %s is not a blob" -msgstr "L'objecte %s no és un blob" +msgid "the requested upstream branch '%s' does not exist" +msgstr "la branca font demanada '%s' no existeix" -#: merge-recursive.c:1666 -msgid "modify" -msgstr "modifica" +#: branch.c:222 +msgid "" +"\n" +"If you are planning on basing your work on an upstream\n" +"branch that already exists at the remote, you may need to\n" +"run \"git fetch\" to retrieve it.\n" +"\n" +"If you are planning to push out a new local branch that\n" +"will track its remote counterpart, you may want to use\n" +"\"git push -u\" to set the upstream config as you push." +msgstr "" +"\n" +"Si teniu pensat basar el vostre treball en una branca\n" +"font que ja existeix al remot, pot ser que necessiteu\n" +"executar \"git fetch\" per a obtenir-la.\n" +"\n" +"Si teniu pensat pujar una branca local nova que seguirà\n" +"la seva contrapart remota, pot ser que vulgueu usar\n" +"\"git push -u\" per a establir la configuració font\n" +"mentre pugeu." -#: merge-recursive.c:1666 -msgid "modified" -msgstr "modificat" +#: branch.c:265 +#, c-format +msgid "Not a valid object name: '%s'." +msgstr "No és un nom d'objecte vàlid: '%s'." -#: merge-recursive.c:1676 -msgid "content" -msgstr "contingut" +#: branch.c:285 +#, c-format +msgid "Ambiguous object name: '%s'." +msgstr "Nom d'objecte ambigu: '%s'." -#: merge-recursive.c:1683 -msgid "add/add" -msgstr "afegiment/afegiment" +#: branch.c:290 +#, c-format +msgid "Not a valid branch point: '%s'." +msgstr "No és un punt de ramificació vàlid: '%s'." -#: merge-recursive.c:1718 +#: branch.c:344 #, c-format -msgid "Skipped %s (merged same as existing)" -msgstr "S'ha saltat %s (el fusionat és igual a l'existent)" +msgid "'%s' is already checked out at '%s'" +msgstr "'%s' ja s'ha agafat a '%s'" -#: merge-recursive.c:1732 +#: branch.c:363 #, c-format -msgid "Auto-merging %s" -msgstr "S'està autofusionant %s" +msgid "HEAD of working tree %s is not updated" +msgstr "La HEAD de l'arbre de treball %s no està actualitzat" -#: merge-recursive.c:1736 git-submodule.sh:919 -msgid "submodule" -msgstr "submòdul" +#: bundle.c:34 +#, c-format +msgid "'%s' does not look like a v2 bundle file" +msgstr "'%s' no sembla un fitxer de farcell v2" -#: merge-recursive.c:1737 +#: bundle.c:61 #, c-format -msgid "CONFLICT (%s): Merge conflict in %s" -msgstr "CONFLICTE (%s): Conflicte de fusió en %s" +msgid "unrecognized header: %s%s (%d)" +msgstr "capçalera no reconeguda: %s%s (%d)" -#: merge-recursive.c:1831 +#: bundle.c:87 sequencer.c:963 builtin/commit.c:777 #, c-format -msgid "Removing %s" -msgstr "S'està eliminant %s" +msgid "could not open '%s'" +msgstr "no s'ha pogut obrir '%s'" -#: merge-recursive.c:1857 -msgid "file/directory" -msgstr "fitxer/directori" +#: bundle.c:139 +msgid "Repository lacks these prerequisite commits:" +msgstr "Al dipòsit li manquen aquestes comissions prerequisits:" -#: merge-recursive.c:1863 -msgid "directory/file" -msgstr "directori/fitxer" +#: bundle.c:163 ref-filter.c:1462 sequencer.c:830 sequencer.c:1374 +#: builtin/blame.c:2814 builtin/commit.c:1061 builtin/log.c:348 +#: builtin/log.c:890 builtin/log.c:1340 builtin/log.c:1666 builtin/log.c:1909 +#: builtin/merge.c:356 builtin/shortlog.c:170 +msgid "revision walk setup failed" +msgstr "la configuració del passeig per revisions ha fallat" -#: merge-recursive.c:1868 +#: bundle.c:185 #, c-format -msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" -msgstr "" -"CONFLICTE (%s): Hi ha un directori amb nom %s en %s. S'està afegint %s com a " -"%s" - -#: merge-recursive.c:1877 -#, c-format -msgid "Adding %s" -msgstr "S'està afegint %s" +msgid "The bundle contains this ref:" +msgid_plural "The bundle contains these %d refs:" +msgstr[0] "El farcell conté aquesta referència:" +msgstr[1] "El farcell conté aquestes %d referències:" -#: merge-recursive.c:1914 -msgid "Already up-to-date!" -msgstr "Ja està al dia!" +#: bundle.c:192 +msgid "The bundle records a complete history." +msgstr "El farcell registra una història completa." -#: merge-recursive.c:1923 +#: bundle.c:194 #, c-format -msgid "merging of trees %s and %s failed" -msgstr "la fusió dels arbres %s i %s ha fallat" +msgid "The bundle requires this ref:" +msgid_plural "The bundle requires these %d refs:" +msgstr[0] "El farcell requereix aquesta referència:" +msgstr[1] "El farcell requereix aquestes %d referències:" -#: merge-recursive.c:2006 -msgid "Merging:" -msgstr "Fusionant:" +#: bundle.c:253 +msgid "Could not spawn pack-objects" +msgstr "No s'ha pogut executar el pack-objects" -#: merge-recursive.c:2019 -#, c-format -msgid "found %u common ancestor:" -msgid_plural "found %u common ancestors:" -msgstr[0] "s'ha trobat %u avantpassat:" -msgstr[1] "s'han trobat %u avantpassats:" +#: bundle.c:264 +msgid "pack-objects died" +msgstr "El pack-objects s'ha mort" -#: merge-recursive.c:2058 -msgid "merge returned no commit" -msgstr "la fusió no ha retornat cap comissió" +#: bundle.c:304 +msgid "rev-list died" +msgstr "El rev-list s'ha mort" -#: merge-recursive.c:2121 +#: bundle.c:353 #, c-format -msgid "Could not parse object '%s'" -msgstr "No s'ha pogut analitzar l'objecte '%s'" +msgid "ref '%s' is excluded by the rev-list options" +msgstr "les opcions de la llista de revisions exclouen la referència '%s'" -#: merge-recursive.c:2135 builtin/merge.c:641 builtin/merge.c:788 -msgid "Unable to write index." -msgstr "No s'ha pogut escriure l'índex." +#: bundle.c:443 builtin/log.c:165 builtin/log.c:1572 builtin/shortlog.c:273 +#, c-format +msgid "unrecognized argument: %s" +msgstr "paràmetre no reconegut: %s" -#: notes-utils.c:41 -msgid "Cannot commit uninitialized/unreferenced notes tree" -msgstr "No es pot cometre un arbre de notes no inicialitzat / no referenciat" +#: bundle.c:451 +msgid "Refusing to create empty bundle." +msgstr "S'està refusant crear un farcell buit." -#: notes-utils.c:100 +#: bundle.c:463 #, c-format -msgid "Bad notes.rewriteMode value: '%s'" -msgstr "Valor de notes.rewriteMode dolent: '%s'" +msgid "cannot create '%s'" +msgstr "no es pot crear '%s'" -#: notes-utils.c:110 +#: bundle.c:491 +msgid "index-pack died" +msgstr "L'index-pack s'ha mort" + +#: color.c:290 #, c-format -msgid "Refusing to rewrite notes in %s (outside of refs/notes/)" -msgstr "S'està refusant reescriure les notes en %s (fora de refs/notes/)" +msgid "invalid color value: %.*s" +msgstr "valor de color no vàlid: %.*s" -#. TRANSLATORS: The first %s is the name of the -#. environment variable, the second %s is its value -#: notes-utils.c:137 +#: commit.c:40 builtin/am.c:421 builtin/am.c:457 builtin/am.c:1493 +#: builtin/am.c:2127 #, c-format -msgid "Bad %s value: '%s'" -msgstr "Valor dolent de %s: '%s'" +msgid "could not parse %s" +msgstr "no s'ha pogut analitzar %s" -#: object.c:242 +#: commit.c:42 #, c-format -msgid "unable to parse object: %s" -msgstr "no s'ha pogut analitzar l'objecte: %s" +msgid "%s %s is not a commit!" +msgstr "%s %s no és una comissió!" -#: parse-options.c:572 -msgid "..." -msgstr "..." +#: commit.c:1514 +msgid "" +"Warning: commit message did not conform to UTF-8.\n" +"You may want to amend it after fixing the message, or set the config\n" +"variable i18n.commitencoding to the encoding your project uses.\n" +msgstr "" +"Advertència: el missatge de comissió no conformava a UTF-8.\n" +"Potser voleu esemenar-lo després de corregir el missatge, o establir\n" +"la variable de configuració i18n.commitencoding a la codificació que\n" +"usi el vostre projecte.\n" -#: parse-options.c:590 +#: compat/obstack.c:406 compat/obstack.c:408 +msgid "memory exhausted" +msgstr "memòria esgotada" + +#: config.c:516 #, c-format -msgid "usage: %s" -msgstr "ús: %s" +msgid "bad config line %d in blob %s" +msgstr "línia de configuració dolenta %d en el blob %s" -#. TRANSLATORS: the colon here should align with the -#. one in "usage: %s" translation -#: parse-options.c:594 +#: config.c:520 #, c-format -msgid " or: %s" -msgstr " o: %s" +msgid "bad config line %d in file %s" +msgstr "línia de configuració dolenta %d en el fitxer %s" -#: parse-options.c:597 +#: config.c:524 #, c-format -msgid " %s" -msgstr " %s" +msgid "bad config line %d in standard input" +msgstr "línia de configuració dolenta %d en l'entrada estàndard" -#: parse-options.c:631 -msgid "-NUM" -msgstr "-NUM" +#: config.c:528 +#, c-format +msgid "bad config line %d in submodule-blob %s" +msgstr "línia de configuració dolenta %d en el blob de submòdul %s" -#: parse-options-cb.c:108 +#: config.c:532 #, c-format -msgid "malformed object name '%s'" -msgstr "nom de camp mal format '%s'" +msgid "bad config line %d in command line %s" +msgstr "línia de configuració dolenta %d en la línia d'ordres %s" -#: path.c:798 +#: config.c:536 #, c-format -msgid "Could not make %s writable by group" -msgstr "No s'ha pogut fer %s escrivible pel grup" +msgid "bad config line %d in %s" +msgstr "línia de configuració dolenta %d en %s" -#: pathspec.c:133 -msgid "global 'glob' and 'noglob' pathspec settings are incompatible" -msgstr "" -"els ajusts d'especificació de camí 'glob' i 'noglob' globals són " -"incompatibles" +#: config.c:655 +msgid "out of range" +msgstr "fora de rang" -#: pathspec.c:143 -msgid "" -"global 'literal' pathspec setting is incompatible with all other global " -"pathspec settings" -msgstr "" -"l'ajust d'especificació de camí 'literal' global és incompatible amb tots " -"els altres ajusts d'especificació de camí globals" +#: config.c:655 +msgid "invalid unit" +msgstr "unitat no vàlida" -#: pathspec.c:177 -msgid "invalid parameter for pathspec magic 'prefix'" -msgstr "paràmetre no vàlid per a la màgia d'especificació de camí 'prefix'" +#: config.c:661 +#, c-format +msgid "bad numeric config value '%s' for '%s': %s" +msgstr "valor de configuració numèric dolent '%s' per '%s': %s" -#: pathspec.c:183 +#: config.c:666 #, c-format -msgid "Invalid pathspec magic '%.*s' in '%s'" -msgstr "Màgia d'especificació de camí no vàlida '%.*s' en '%s'" +msgid "bad numeric config value '%s' for '%s' in blob %s: %s" +msgstr "valor de configuració numèric dolent '%s' per '%s' en el blob %s: %s" -#: pathspec.c:187 +#: config.c:669 #, c-format -msgid "Missing ')' at the end of pathspec magic in '%s'" -msgstr "')' mancant al final de la màgia d'especificació de camí en '%s'" +msgid "bad numeric config value '%s' for '%s' in file %s: %s" +msgstr "valor de configuració numèric dolent '%s' per '%s' en el fitxer %s: %s" -#: pathspec.c:205 +#: config.c:672 #, c-format -msgid "Unimplemented pathspec magic '%c' in '%s'" -msgstr "Màgia d'especificació de camí no implementada '%c' en '%s'" +msgid "bad numeric config value '%s' for '%s' in standard input: %s" +msgstr "" +"valor de configuració numèric dolent '%s' per '%s' en l'entrada estàndard: %s" -#: pathspec.c:230 +#: config.c:675 #, c-format -msgid "%s: 'literal' and 'glob' are incompatible" -msgstr "%s: 'literal' i 'glob' són incompatibles" +msgid "bad numeric config value '%s' for '%s' in submodule-blob %s: %s" +msgstr "" +"valor de configuració numèric dolent '%s' per '%s' en el blob de submòdul " +"%s: %s" -#: pathspec.c:241 +#: config.c:678 #, c-format -msgid "%s: '%s' is outside repository" -msgstr "%s: '%s' és fora del dipòsit" +msgid "bad numeric config value '%s' for '%s' in command line %s: %s" +msgstr "" +"valor de configuració numèric dolent '%s' per '%s' en la línia d'ordres %s: " +"%s" -#: pathspec.c:291 +#: config.c:681 #, c-format -msgid "Pathspec '%s' is in submodule '%.*s'" -msgstr "L'especificació '%s' és en el submòdul '%.*s'" +msgid "bad numeric config value '%s' for '%s' in %s: %s" +msgstr "valor de configuració numèric dolent '%s' per '%s' en %s: %s" -#: pathspec.c:353 +#: config.c:768 #, c-format -msgid "%s: pathspec magic not supported by this command: %s" -msgstr "" -"%s: aquesta ordre no és compatible amb la màgia d'especificació de camí: %s" +msgid "failed to expand user dir in: '%s'" +msgstr "s'ha fallat en expandir el directori d'usuari en: '%s'" -#: pathspec.c:433 +#: config.c:852 config.c:863 #, c-format -msgid "pathspec '%s' is beyond a symbolic link" -msgstr "l'especificació de camí '%s' és més enllà d'un enllaç simbòlic" +msgid "bad zlib compression level %d" +msgstr "nivell de compressió de zlib dolent %d" -#: pathspec.c:442 -msgid "" -"There is nothing to exclude from by :(exclude) patterns.\n" -"Perhaps you forgot to add either ':/' or '.' ?" -msgstr "" -"No hi ha res a excloure per patrons :(exclusió).\n" -"Potser heu oblidat afegir o ':/' o '.' ?" +#: config.c:978 +#, c-format +msgid "invalid mode for object creation: %s" +msgstr "mode de creació d'objecte no vàlid: %s" -#: pretty.c:973 -msgid "unable to parse --pretty format" -msgstr "no s'ha pogut analitzar el format --pretty" +#: config.c:1312 +msgid "unable to parse command-line config" +msgstr "no s'ha pogut analitzar la configuració de la línia d'ordres" -#: progress.c:235 -msgid "done" -msgstr "fet" +#: config.c:1362 +msgid "unknown error occurred while reading the configuration files" +msgstr "un error desconegut ha ocorregut en llegir els fitxers de configuració" -#: read-cache.c:1281 +#: config.c:1716 #, c-format -msgid "" -"index.version set, but the value is invalid.\n" -"Using version %i" -msgstr "" -"index.version establert, però el valor no és vàlid.\n" -"S'està usant la versió %i" +msgid "unable to parse '%s' from command-line config" +msgstr "no s'ha pogut analitzar '%s' de la configuració de la línia d'ordres" -#: read-cache.c:1291 +#: config.c:1718 #, c-format -msgid "" -"GIT_INDEX_VERSION set, but the value is invalid.\n" -"Using version %i" -msgstr "" -"GIT_INDEX_VERSION establert, però el valor no és vàlid.\n" -"S'està usant la versió %i" +msgid "bad config variable '%s' in file '%s' at line %d" +msgstr "variable de configuració dolenta '%s' en el fitxer '%s' a la línia %d" -#: refs.c:551 builtin/merge.c:840 +#: config.c:1777 #, c-format -msgid "Could not open '%s' for writing" -msgstr "No s'ha pogut obrir '%s' per a escriptura" +msgid "%s has multiple values" +msgstr "%s té múltiples valors" -#: refs/files-backend.c:2534 +#: config.c:2311 #, c-format -msgid "could not delete reference %s: %s" -msgstr "no s'ha pogut suprimir la referència %s: %s" +msgid "could not set '%s' to '%s'" +msgstr "no s'ha pogut establir '%s' a '%s'" -#: refs/files-backend.c:2537 +#: config.c:2313 #, c-format -msgid "could not delete references: %s" -msgstr "no s'ha pogut suprimir les referències: %s" +msgid "could not unset '%s'" +msgstr "no s'ha pogut desestablir '%s'" + +#: connect.c:49 +msgid "The remote end hung up upon initial contact" +msgstr "El costat remot ha penjat en el moment de contacte inicial" + +#: connect.c:51 +msgid "" +"Could not read from remote repository.\n" +"\n" +"Please make sure you have the correct access rights\n" +"and the repository exists." +msgstr "" +"No s'ha pogut llegir del dipòsit remot.\n" +"\n" +"Si us plau, assegureu-vos que tingueu els drets\n" +"d'accés correctes i que el dipòsit existeixi." + +#: connected.c:63 builtin/fsck.c:173 builtin/prune.c:140 +msgid "Checking connectivity" +msgstr "S'està comprovant la connectivitat" + +#: connected.c:75 +msgid "Could not run 'git rev-list'" +msgstr "No s'ha pogut executar 'git rev-list'" + +#: connected.c:95 +msgid "failed write to rev-list" +msgstr "escriptura fallada al rev-list" -#: refs/files-backend.c:2546 +#: connected.c:102 +msgid "failed to close rev-list's stdin" +msgstr "s'ha fallat en tancar l'stdin del rev-list" + +#: convert.c:201 #, c-format -msgid "could not remove reference %s" -msgstr "no s'ha pogut eliminar la referència %s" +msgid "" +"CRLF will be replaced by LF in %s.\n" +"The file will have its original line endings in your working directory." +msgstr "" +"LF reemplaçarà CRLF en %s.\n" +"El fitxer tindrà els seus terminadors de línia originals en el vostre " +"directori de treball." -#: ref-filter.c:55 +#: convert.c:205 #, c-format -msgid "expected format: %%(color:)" -msgstr "format esperat: %%(color:)" +msgid "CRLF would be replaced by LF in %s." +msgstr "LF reemplaçaria CRLF en %s." -#: ref-filter.c:57 +#: convert.c:211 #, c-format -msgid "unrecognized color: %%(color:%s)" -msgstr "color no reconegut: %%(color:%s)" +msgid "" +"LF will be replaced by CRLF in %s.\n" +"The file will have its original line endings in your working directory." +msgstr "" +"CRLF reemplaçarà LF en %s.\n" +"El fitxer tindrà els seus terminadors de línia originals en el vostre " +"directori de treball." -#: ref-filter.c:71 +#: convert.c:215 #, c-format -msgid "unrecognized format: %%(%s)" -msgstr "format no reconegut: %%(%s)" +msgid "LF would be replaced by CRLF in %s" +msgstr "CRLF reemplaçaria LF en %s" -#: ref-filter.c:77 +#: date.c:97 +msgid "in the future" +msgstr "en el futur" + +#: date.c:103 #, c-format -msgid "%%(body) does not take arguments" -msgstr "%%(body) no accepta paràmetres" +msgid "%lu second ago" +msgid_plural "%lu seconds ago" +msgstr[0] "fa %lu segon" +msgstr[1] "fa %lu segons" -#: ref-filter.c:84 +#: date.c:110 #, c-format -msgid "%%(subject) does not take arguments" -msgstr "%%(subject) no accepta paràmetres" +msgid "%lu minute ago" +msgid_plural "%lu minutes ago" +msgstr[0] "fa %lu minut" +msgstr[1] "fa %lu minuts" -#: ref-filter.c:101 +#: date.c:117 #, c-format -msgid "positive value expected contents:lines=%s" -msgstr "valor positiu esperat contents:lines=%s" +msgid "%lu hour ago" +msgid_plural "%lu hours ago" +msgstr[0] "fa %lu hora" +msgstr[1] "fa %lu hores" -#: ref-filter.c:103 +#: date.c:124 #, c-format -msgid "unrecognized %%(contents) argument: %s" -msgstr "paràmetre %%(contents) no reconegut: %s" +msgid "%lu day ago" +msgid_plural "%lu days ago" +msgstr[0] "fa %lu dia" +msgstr[1] "fa %lu dies" -#: ref-filter.c:113 +#: date.c:130 #, c-format -msgid "unrecognized %%(objectname) argument: %s" -msgstr "paràmetre %%(objectname) no reconegut: %s" +msgid "%lu week ago" +msgid_plural "%lu weeks ago" +msgstr[0] "fa %lu setmana" +msgstr[1] "fa %lu setmanes" -#: ref-filter.c:135 +#: date.c:137 #, c-format -msgid "expected format: %%(align:,)" -msgstr "format esperat: %%(align:,)" +msgid "%lu month ago" +msgid_plural "%lu months ago" +msgstr[0] "fa %lu mes" +msgstr[1] "fa %lu mesos" -#: ref-filter.c:147 +#: date.c:148 #, c-format -msgid "unrecognized position:%s" -msgstr "posició no reconeguda:%s" +msgid "%lu year" +msgid_plural "%lu years" +msgstr[0] "%lu any" +msgstr[1] "%lu anys" -#: ref-filter.c:151 +#. TRANSLATORS: "%s" is " years" +#: date.c:151 #, c-format -msgid "unrecognized width:%s" -msgstr "amplada no reconeguda:%s" +msgid "%s, %lu month ago" +msgid_plural "%s, %lu months ago" +msgstr[0] "fa %s i %lu mes" +msgstr[1] "fa %s i %lu mesos" -#: ref-filter.c:157 +#: date.c:156 date.c:161 #, c-format -msgid "unrecognized %%(align) argument: %s" -msgstr "paràmetre %%(align) no reconegut: %s" +msgid "%lu year ago" +msgid_plural "%lu years ago" +msgstr[0] "fa %lu any" +msgstr[1] "fa %lu anys" -#: ref-filter.c:161 +#: diffcore-order.c:24 #, c-format -msgid "positive width expected with the %%(align) atom" -msgstr "amplada positiva esperada amb l'àtom %%(align)" +msgid "failed to read orderfile '%s'" +msgstr "s'ha fallat en llegir el fitxer d'ordres '%s'" -#: ref-filter.c:244 +#: diffcore-rename.c:536 +msgid "Performing inexact rename detection" +msgstr "S'està realitzant una detecció inexacta de canvis de nom" + +#: diff.c:62 #, c-format -msgid "malformed field name: %.*s" -msgstr "nom d'objecte mal format: %.*s" +msgid "option '%s' requires a value" +msgstr "l'opció '%s' requereix un valor" -#: ref-filter.c:270 +#: diff.c:124 #, c-format -msgid "unknown field name: %.*s" -msgstr "nom de camp desconegut: %.*s" +msgid " Failed to parse dirstat cut-off percentage '%s'\n" +msgstr " S'ha fallat en analitzar el percentatge limitant de dirstat '%s'\n" -#: ref-filter.c:372 +#: diff.c:129 #, c-format -msgid "format: %%(end) atom used without corresponding atom" -msgstr "format: s'ha usat l'àtom %%(end) sense l'àtom corresponent" +msgid " Unknown dirstat parameter '%s'\n" +msgstr " Paràmetre de dirstat desconegut '%s'\n" -#: ref-filter.c:424 +#: diff.c:283 #, c-format -msgid "malformed format string %s" -msgstr "cadena de format mal format %s" +msgid "Unknown value for 'diff.submodule' config variable: '%s'" +msgstr "" +"Valor desconegut de la variable de configuració de 'diff.submodule': '%s'" -#: ref-filter.c:878 -msgid ":strip= requires a positive integer argument" -msgstr ":strip= requereix un paràmetre enter positiu" +#: diff.c:346 +#, c-format +msgid "" +"Found errors in 'diff.dirstat' config variable:\n" +"%s" +msgstr "" +"S'han trobat errors en la variable de configuració 'diff.dirstat':\n" +"%s" -#: ref-filter.c:883 +#: diff.c:3087 #, c-format -msgid "ref '%s' does not have %ld components to :strip" -msgstr "la referència '%s' no té %ld components per a :strip" +msgid "external diff died, stopping at %s" +msgstr "el diff external s'ha mort, s'està aturant a %s" -#: ref-filter.c:1046 +#: diff.c:3412 +msgid "--name-only, --name-status, --check and -s are mutually exclusive" +msgstr "--name-only, --name-status, --check i -s són mutualment exclusius" + +#: diff.c:3502 +msgid "--follow requires exactly one pathspec" +msgstr "--follow requereix exactament una especificació de camí" + +#: diff.c:3665 #, c-format -msgid "unknown %.*s format %s" -msgstr "format de %.*s desconegut %s" +msgid "" +"Failed to parse --dirstat/-X option parameter:\n" +"%s" +msgstr "" +"S'ha fallat en analitzar el paràmetre d'opció de --dirstat/-X:\n" +"%s" -#: ref-filter.c:1066 ref-filter.c:1097 +#: diff.c:3679 #, c-format -msgid "missing object %s for %s" -msgstr "manca l'objecte %s per a %s" +msgid "Failed to parse --submodule option parameter: '%s'" +msgstr "S'ha fallat en analitzar el paràmetre d'opció de --submodule: '%s'" -#: ref-filter.c:1069 ref-filter.c:1100 +#: diff.c:4700 +msgid "inexact rename detection was skipped due to too many files." +msgstr "s'ha saltat la detecció de canvi de nom a causa de massa fitxers." + +#: diff.c:4703 +msgid "only found copies from modified paths due to too many files." +msgstr "" +"només s'han trobat còpies des de camins modificats a causa de massa fitxers." + +#: diff.c:4706 #, c-format -msgid "parse_object_buffer failed on %s for %s" -msgstr "parse_object_buffer ha fallat en %s per a %s" +msgid "" +"you may want to set your %s variable to at least %d and retry the command." +msgstr "" +"potser voleu establir la vostra variable %s a almenys %d i tornar a intentar " +"l'ordre." -#: ref-filter.c:1311 +#: dir.c:1866 +msgid "failed to get kernel name and information" +msgstr "s'ha fallat en obtenir el nombre i la informació del nucli" + +#: dir.c:1985 +msgid "Untracked cache is disabled on this system or location." +msgstr "" +"La memòria cau no seguida està inhabilitada en aquest sistema o ubicació." + +#: fetch-pack.c:213 +msgid "git fetch-pack: expected shallow list" +msgstr "git fetch-pack: llista superficial esperada" + +#: fetch-pack.c:225 +msgid "git fetch-pack: expected ACK/NAK, got EOF" +msgstr "git fetch-pack: ACK/NAK esperat, EOF rebut" + +#: fetch-pack.c:243 #, c-format -msgid "malformed object at '%s'" -msgstr "objecte mal format a '%s'" +msgid "git fetch-pack: expected ACK/NAK, got '%s'" +msgstr "git fetch-pack: ACK/NAK esperat, '%s' rebut" -#: ref-filter.c:1373 +#: fetch-pack.c:295 +msgid "--stateless-rpc requires multi_ack_detailed" +msgstr "--stateless-rpc requereix multi_ack_detailed" + +#: fetch-pack.c:381 #, c-format -msgid "ignoring ref with broken name %s" -msgstr "s'està ignorant la referència amb nom trencat %s" +msgid "invalid shallow line: %s" +msgstr "línia de shallow no vàlida: %s" -#: ref-filter.c:1378 +#: fetch-pack.c:387 #, c-format -msgid "ignoring broken ref %s" -msgstr "s'està ignorant la referència trencada %s" +msgid "invalid unshallow line: %s" +msgstr "línia d'unshallow no vàlida: %s" -#: ref-filter.c:1651 +#: fetch-pack.c:389 #, c-format -msgid "format: %%(end) atom missing" -msgstr "format: manca l'àtom %%(end)" +msgid "object not found: %s" +msgstr "objecte no trobat: %s" -#: ref-filter.c:1705 +#: fetch-pack.c:392 #, c-format -msgid "malformed object name %s" -msgstr "nom d'objecte %s mal format" +msgid "error in object: %s" +msgstr "error en objecte: %s" -#: remote.c:746 +#: fetch-pack.c:394 #, c-format -msgid "Cannot fetch both %s and %s to %s" -msgstr "No es pot obtenir ambdós %s i %s a %s" +msgid "no shallow found: %s" +msgstr "no s'ha trobat cap superficial: %s" -#: remote.c:750 +#: fetch-pack.c:397 #, c-format -msgid "%s usually tracks %s, not %s" -msgstr "%s generalment segueix %s, no %s" +msgid "expected shallow/unshallow, got %s" +msgstr "s'esperava shallow/unshallow, s'ha rebut %s" -#: remote.c:754 +#: fetch-pack.c:436 #, c-format -msgid "%s tracks both %s and %s" -msgstr "%s segueix ambdós %s i %s" +msgid "got %s %d %s" +msgstr "%s %d %s rebut" -#: remote.c:762 -msgid "Internal error" -msgstr "Error intern" +#: fetch-pack.c:450 +#, c-format +msgid "invalid commit %s" +msgstr "comissió no vàlida %s" -#: remote.c:1677 remote.c:1720 -msgid "HEAD does not point to a branch" -msgstr "HEAD no assenyala cap branca" +#: fetch-pack.c:483 +msgid "giving up" +msgstr "s'està rendint" -#: remote.c:1686 -#, c-format -msgid "no such branch: '%s'" -msgstr "no hi ha tal branca: '%s'" +#: fetch-pack.c:493 progress.c:235 +msgid "done" +msgstr "fet" -#: remote.c:1689 +#: fetch-pack.c:505 #, c-format -msgid "no upstream configured for branch '%s'" -msgstr "cap font configurada per a la branca '%s'" +msgid "got %s (%d) %s" +msgstr "s'ha rebut %s (%d) %s" -#: remote.c:1695 +#: fetch-pack.c:551 #, c-format -msgid "upstream branch '%s' not stored as a remote-tracking branch" -msgstr "La branca font '%s' no s'emmagatzema com a branca amb seguiment remot" +msgid "Marking %s as complete" +msgstr "S'està marcant %s com a complet" -#: remote.c:1710 +#: fetch-pack.c:697 #, c-format -msgid "push destination '%s' on remote '%s' has no local tracking branch" -msgstr "" -"el destí de pujada '%s' en el remot '%s' no té cap branca seguidora local" +msgid "already have %s (%s)" +msgstr "ja es té %s (%s)" -#: remote.c:1725 +#: fetch-pack.c:735 +msgid "fetch-pack: unable to fork off sideband demultiplexer" +msgstr "fetch-pack: no s'ha pogut bifurcar del demultiplexor de banda lateral" + +#: fetch-pack.c:743 +msgid "protocol error: bad pack header" +msgstr "error de protocol: capçalera de paquet dolent" + +#: fetch-pack.c:799 #, c-format -msgid "branch '%s' has no remote for pushing" -msgstr "la branca '%s' no té cap remot al qual pujar" +msgid "fetch-pack: unable to fork off %s" +msgstr "fetch-pack: no es pot bifurcar de %s" -#: remote.c:1736 +#: fetch-pack.c:815 #, c-format -msgid "push refspecs for '%s' do not include '%s'" -msgstr "les especificacions de referència de '%s' no inclouen '%s'" +msgid "%s failed" +msgstr "%s ha fallat" -#: remote.c:1749 -msgid "push has no destination (push.default is 'nothing')" -msgstr "push no té destí (push.default és 'nothing')" +#: fetch-pack.c:817 +msgid "error in sideband demultiplexer" +msgstr "error en demultiplexor de banda lateral" -#: remote.c:1771 -msgid "cannot resolve 'simple' push to a single destination" -msgstr "no es pot resoldre una pujada 'simple' a un sol destí" +#: fetch-pack.c:844 +msgid "Server does not support shallow clients" +msgstr "El servidor no permet clients superficials" -#: remote.c:2073 -#, c-format -msgid "Your branch is based on '%s', but the upstream is gone.\n" -msgstr "La vostra branca està basada en '%s', però la font no hi és.\n" - -#: remote.c:2077 -msgid " (use \"git branch --unset-upstream\" to fixup)\n" -msgstr " (useu \"git branch --unset-upstream\" per a arreglar)\n" - -#: remote.c:2080 -#, c-format -msgid "Your branch is up-to-date with '%s'.\n" -msgstr "La vostra branca està al dia amb '%s'.\n" +#: fetch-pack.c:848 +msgid "Server supports multi_ack_detailed" +msgstr "El servidor accepta multi_ack_detailed" -#: remote.c:2084 -#, 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] "La vostra branca està davant de '%s' per %d comissió.\n" -msgstr[1] "La vostra branca està davant de '%s' per %d comissions.\n" +#: fetch-pack.c:851 +msgid "Server supports no-done" +msgstr "El servidor accepta no-done" -#: remote.c:2090 -msgid " (use \"git push\" to publish your local commits)\n" -msgstr " (useu \"git push\" per a publicar les vostres comissions locals)\n" +#: fetch-pack.c:857 +msgid "Server supports multi_ack" +msgstr "El servidor accepta multi_ack" -#: remote.c:2093 -#, c-format -msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n" -msgid_plural "" -"Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n" -msgstr[0] "" -"La vostra branca està darrere de '%s' per %d comissió, i pot avançar-se " -"ràpidament.\n" -msgstr[1] "" -"La vostra branca està darrere de '%s' per %d comissions, i pot avançar-se " -"ràpidament.\n" +#: fetch-pack.c:861 +msgid "Server supports side-band-64k" +msgstr "El servidor accepta side-band-64k" -#: remote.c:2101 -msgid " (use \"git pull\" to update your local branch)\n" -msgstr " (useu \"git pull\" per a actualitzar la vostra branca local)\n" +#: fetch-pack.c:865 +msgid "Server supports side-band" +msgstr "El servidor accepta banda lateral" -#: remote.c:2104 -#, c-format -msgid "" -"Your branch and '%s' have diverged,\n" -"and have %d and %d different commit each, respectively.\n" -msgid_plural "" -"Your branch and '%s' have diverged,\n" -"and have %d and %d different commits each, respectively.\n" -msgstr[0] "" -"La vostra branca i '%s' s'han divergit,\n" -"i tenen %d i %d comissió distinta cada una, respectivament.\n" -msgstr[1] "" -"La vostra branca i '%s' s'han divergit,\n" -"i tenen %d i %d comissions distintes cada una, respectivament.\n" +#: fetch-pack.c:869 +msgid "Server supports allow-tip-sha1-in-want" +msgstr "El servidor accepta allow-tip-sha1-in-want" -#: remote.c:2114 -msgid " (use \"git pull\" to merge the remote branch into yours)\n" -msgstr " (useu \"git pull\" per a fusionar la branca remota a la vostra)\n" +#: fetch-pack.c:873 +msgid "Server supports allow-reachable-sha1-in-want" +msgstr "El servidor accepta allow-reachable-sha1-in-want" -#: revision.c:2132 -msgid "your current branch appears to be broken" -msgstr "la vostra branca actual sembla trencada" +#: fetch-pack.c:883 +msgid "Server supports ofs-delta" +msgstr "El servidor accepta ofs-delta" -#: revision.c:2135 +#: fetch-pack.c:890 #, c-format -msgid "your current branch '%s' does not have any commits yet" -msgstr "la vostra branca actual '%s' encara no té cap comissió" - -#: revision.c:2329 -msgid "--first-parent is incompatible with --bisect" -msgstr "--first-parent és incompatible amb --bisect" - -#: run-command.c:92 -msgid "open /dev/null failed" -msgstr "s'ha fallat en obrir /dev/null" +msgid "Server version is %.*s" +msgstr "La versió del servidor és %.*s" -#: run-command.c:94 -#, c-format -msgid "dup2(%d,%d) failed" -msgstr "dup2(%d,%d) ha fallat" +#: fetch-pack.c:896 +msgid "Server does not support --shallow-since" +msgstr "El servidor no admet --shallow-since" -#: send-pack.c:298 -msgid "failed to sign the push certificate" -msgstr "s'ha fallat en signar el certificat de pujada" +#: fetch-pack.c:900 +msgid "Server does not support --shallow-exclude" +msgstr "El servidor no admet --shallow-exclude" -#: send-pack.c:411 -msgid "the receiving end does not support --signed push" -msgstr "el destí receptor no admet pujar --signed" +#: fetch-pack.c:902 +msgid "Server does not support --deepen" +msgstr "El servidor no admet --deepen" -#: send-pack.c:413 -msgid "" -"not sending a push certificate since the receiving end does not support --" -"signed push" -msgstr "" -"no s'està enviant una certificació de pujada perquè el destí receptor no " -"admet pujar --signed" +#: fetch-pack.c:913 +msgid "no common commits" +msgstr "cap comissió en comú" -#: send-pack.c:425 -msgid "the receiving end does not support --atomic push" -msgstr "el destí receptor no admet pujar --atomic" +#: fetch-pack.c:925 +msgid "git fetch-pack: fetch failed." +msgstr "git fetch-pack: l'obtenció ha fallat." -#: send-pack.c:430 -msgid "the receiving end does not support push options" -msgstr "el destí receptor no admet opcions de pujada" +#: fetch-pack.c:1087 +msgid "no matching remote head" +msgstr "no hi ha cap cap remot coincident" -#: sequencer.c:174 -msgid "" -"after resolving the conflicts, mark the corrected paths\n" -"with 'git add ' or 'git rm '" -msgstr "" -"després de resoldre els conflictes, marqueu els camins\n" -"corregits amb 'git add ' o 'git rm '" +#: gpg-interface.c:185 +msgid "gpg failed to sign the data" +msgstr "gpg ha fallat en signar les dades" -#: sequencer.c:177 -msgid "" -"after resolving the conflicts, mark the corrected paths\n" -"with 'git add ' or 'git rm '\n" -"and commit the result with 'git commit'" -msgstr "" -"després de resoldre els conflictes, marqueu els camins\n" -"corregits amb 'git add ' o 'git rm '\n" -"i cometeu el resultat amb 'git commit'" +#: gpg-interface.c:215 +msgid "could not create temporary file" +msgstr "no s'ha pogut crear el fitxer temporal" -#: sequencer.c:190 sequencer.c:841 sequencer.c:924 +#: gpg-interface.c:217 #, c-format -msgid "Could not write to %s" -msgstr "No s'ha pogut escriure a %s" +msgid "failed writing detached signature to '%s'" +msgstr "s'ha fallat en escriure la signatura separada a '%s'" -#: sequencer.c:193 sequencer.c:843 sequencer.c:928 +#: grep.c:1782 #, c-format -msgid "Error wrapping up %s." -msgstr "Ha hagut un error en finalitzar %s." - -#: sequencer.c:208 -msgid "Your local changes would be overwritten by cherry-pick." -msgstr "Els vostres canvis locals se sobreescriurien pel recull de cireres." - -#: sequencer.c:210 -msgid "Your local changes would be overwritten by revert." -msgstr "Els vostres canvis locals se sobreescriurien per la reversió." - -#: sequencer.c:213 -msgid "Commit your changes or stash them to proceed." -msgstr "Cometeu els vostres canvis o emmagatzemeu-los per a procedir." +msgid "'%s': unable to read %s" +msgstr "'%s': no s'ha pogut llegir %s" -#: sequencer.c:228 +#: grep.c:1799 builtin/clone.c:381 builtin/diff.c:84 builtin/rm.c:155 #, c-format -msgid "%s: fast-forward" -msgstr "%s: avanç ràpid" +msgid "failed to stat '%s'" +msgstr "s'ha fallat en fer stat a '%s'" -#. TRANSLATORS: %s will be "revert" or "cherry-pick" -#: sequencer.c:303 +#: grep.c:1810 #, c-format -msgid "%s: Unable to write new index file" -msgstr "%s: No s'ha pogut escriure un fitxer d'índex nou" - -#: sequencer.c:321 -msgid "Could not resolve HEAD commit\n" -msgstr "No s'ha pogut resoldre la comissió HEAD\n" - -#: sequencer.c:341 -msgid "Unable to update cache tree\n" -msgstr "No s'ha pogut actualitzar l'arbre cau\n" +msgid "'%s': short read" +msgstr "'%s': lectura curta" -#: sequencer.c:393 +#: help.c:203 #, c-format -msgid "Could not parse commit %s\n" -msgstr "No s'ha pogut analitzar la comissió %s\n" +msgid "available git commands in '%s'" +msgstr "ordres de git disponibles en '%s'" -#: sequencer.c:398 -#, c-format -msgid "Could not parse parent commit %s\n" -msgstr "No s'ha pogut analitzar la comissió mare %s\n" +#: help.c:210 +msgid "git commands available from elsewhere on your $PATH" +msgstr "ordres de git disponibles d'altres llocs en el vostre $PATH" -#: sequencer.c:463 -msgid "Your index file is unmerged." -msgstr "El vostre fitxer d'índex està sense fusionar." +#: help.c:241 +msgid "These are common Git commands used in various situations:" +msgstr "Aquestes són ordres del Git comunament usades en diverses situacions:" -#: sequencer.c:482 +#: help.c:306 #, c-format -msgid "Commit %s is a merge but no -m option was given." -msgstr "La comissió %s és una fusió però no s'ha donat cap opció -m." +msgid "" +"'%s' appears to be a git command, but we were not\n" +"able to execute it. Maybe git-%s is broken?" +msgstr "" +"'%s' sembla una ordre de git, però no hem pogut\n" +"executar-la. Pot ser que git-%s estigui estropejat?" -#: sequencer.c:490 -#, c-format -msgid "Commit %s does not have parent %d" -msgstr "La comissió %s no té mare %d" +#: help.c:361 +msgid "Uh oh. Your system reports no Git commands at all." +msgstr "Ai. El vostre sistema no informa de cap ordre de Git." -#: sequencer.c:494 +#: help.c:383 #, c-format -msgid "Mainline was specified but commit %s is not a merge." +msgid "" +"WARNING: You called a Git command named '%s', which does not exist.\n" +"Continuing under the assumption that you meant '%s'" msgstr "" -"S'ha especificat la línia principal però la comissió %s no és una fusió." +"ADVERTÈNCIA: Heu invocat una ordre de Git amb nom '%s', la qual no " +"existeix.\n" +"S'està continuant sota l'assumpció que volíeu dir '%s'" -#. TRANSLATORS: The first %s will be "revert" or -#. "cherry-pick", the second %s a SHA1 -#: sequencer.c:507 +#: help.c:388 #, c-format -msgid "%s: cannot parse parent commit %s" -msgstr "%s: no es pot analitzar la comissió mare %s" +msgid "in %0.1f seconds automatically..." +msgstr "en %0.1f segons automàticament..." -#: sequencer.c:511 +#: help.c:395 #, c-format -msgid "Cannot get commit message for %s" -msgstr "No es pot obtenir el missatge de comissió de %s" +msgid "git: '%s' is not a git command. See 'git --help'." +msgstr "git: '%s' no és una ordre de git. Vegeu 'git --help'." -#: sequencer.c:597 -#, c-format -msgid "could not revert %s... %s" -msgstr "no s'ha pogut revertir %s...%s" +#: help.c:399 help.c:465 +msgid "" +"\n" +"Did you mean this?" +msgid_plural "" +"\n" +"Did you mean one of these?" +msgstr[0] "" +"\n" +"Volíeu dir això?" +msgstr[1] "" +"\n" +"Volíeu dir un d'aquests?" -#: sequencer.c:598 +#: help.c:461 #, c-format -msgid "could not apply %s... %s" -msgstr "no s'ha pogut aplicar %s...%s" +msgid "%s: %s - %s" +msgstr "%s: %s - %s" -#: sequencer.c:633 -msgid "empty commit set passed" -msgstr "conjunt de comissions buit passat" +#: ident.c:334 +msgid "" +"\n" +"*** Please tell me who you are.\n" +"\n" +"Run\n" +"\n" +" git config --global user.email \"you@example.com\"\n" +" git config --global user.name \"Your Name\"\n" +"\n" +"to set your account's default identity.\n" +"Omit --global to set the identity only in this repository.\n" +"\n" +msgstr "" +"\n" +"*** Si us plau, digueu-me qui sou.\n" +"\n" +"Executeu\n" +"\n" +" git config --global user.email \"vós@example.com\"\n" +" git config --global user.name \"El Vostre Nom\"\n" +"\n" +"per a establir la identitat predeterminat del vostre compte.\n" +"Ometeu --global per a establir la identitat només en aquest dipòsit.\n" -#: sequencer.c:641 +#: lockfile.c:152 #, c-format -msgid "git %s: failed to read the index" -msgstr "git %s: s'ha fallat en llegir l'índex" +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 "" +"No s'ha pogut crear '%s.lock': %s.\n" +"\n" +"Sembla que un altre procés de git s'està executant en aquest\n" +"dipòsit, per exemple, un editor obert per 'git commit'. Si us\n" +"plau, assegureu-vos que tots els processos s'hagin terminat i\n" +"llavors trobeu de nou. Si encara falla, potser que un procés de\n" +"git ha tingut una pana:\n" +"elimineu el fitxer manualment per a continuar." -#: sequencer.c:645 +#: lockfile.c:160 #, c-format -msgid "git %s: failed to refresh the index" -msgstr "git %s: s'ha fallat en actualitzar l'índex" - -#: sequencer.c:705 -msgid "Cannot revert during another revert." -msgstr "No es pot revertir durant una altra reversió." +msgid "Unable to create '%s.lock': %s" +msgstr "No s'ha pogut crear '%s.lock': %s" -#: sequencer.c:706 -msgid "Cannot revert during a cherry-pick." -msgstr "No es pot revertir durant un recull de cireres." +#: merge.c:41 +msgid "failed to read the cache" +msgstr "s'ha fallat en llegir la memòria cau" -#: sequencer.c:709 -msgid "Cannot cherry-pick during a revert." -msgstr "No es pot recollir cireres durant una reversió." +#: merge.c:96 builtin/am.c:2000 builtin/am.c:2035 builtin/checkout.c:374 +#: builtin/checkout.c:588 builtin/clone.c:731 +msgid "unable to write new index file" +msgstr "no s'ha pogut escriure un fitxer d'índex nou" -#: sequencer.c:710 -msgid "Cannot cherry-pick during another cherry-pick." -msgstr "No es pot recollir cireres durant altre recull de cireres." +#: merge-recursive.c:209 +msgid "(bad commit)\n" +msgstr "(comissió dolenta)\n" -#: sequencer.c:732 +#: merge-recursive.c:231 #, c-format -msgid "Could not parse line %d." -msgstr "No s'ha pogut analitzar la línia %d." +msgid "addinfo_cache failed for path '%s'" +msgstr "addinfo_cache ha fallat per al camí '%s'" -#: sequencer.c:737 -msgid "No commits parsed." -msgstr "No s'ha analitzat cap comissió." +#: merge-recursive.c:301 +msgid "error building trees" +msgstr "error en construir arbres" -#: sequencer.c:749 +#: merge-recursive.c:720 #, c-format -msgid "Could not open %s" -msgstr "No s'ha pogut obrir %s" +msgid "failed to create path '%s'%s" +msgstr "s'ha fallat en crear el camí '%s'%s" -#: sequencer.c:753 +#: merge-recursive.c:731 #, c-format -msgid "Could not read %s." -msgstr "No s'ha pogut llegir %s." +msgid "Removing %s to make room for subdirectory\n" +msgstr "S'està eliminant %s per a fer espai per al subdirectori\n" -#: sequencer.c:760 -#, c-format -msgid "Unusable instruction sheet: %s" -msgstr "Full d'instruccions inusable: %s" +#: merge-recursive.c:745 merge-recursive.c:764 +msgid ": perhaps a D/F conflict?" +msgstr ": potser un conflicte D/F?" -#: sequencer.c:790 +#: merge-recursive.c:754 #, c-format -msgid "Invalid key: %s" -msgstr "Clau no vàlida: %s" +msgid "refusing to lose untracked file at '%s'" +msgstr "s'està refusant perdre el fitxer no seguit a '%s'" -#: sequencer.c:793 builtin/pull.c:50 builtin/pull.c:52 +#: merge-recursive.c:796 builtin/cat-file.c:34 #, c-format -msgid "Invalid value for %s: %s" -msgstr "Valor no vàlid per a %s: %s" +msgid "cannot read object %s '%s'" +msgstr "no es pot llegir l'objecte %s '%s'" -#: sequencer.c:803 +#: merge-recursive.c:798 #, c-format -msgid "Malformed options sheet: %s" -msgstr "Full d'opcions mal format: %s" - -#: sequencer.c:822 -msgid "a cherry-pick or revert is already in progress" -msgstr "un recull de cireres o una reversió ja està en curs" - -#: sequencer.c:823 -msgid "try \"git cherry-pick (--continue | --quit | --abort)\"" -msgstr "intenteu \"git cherry-pick (--continue | --quit | --abort)\"" +msgid "blob expected for %s '%s'" +msgstr "blob esperat per a %s '%s'" -#: sequencer.c:827 +#: merge-recursive.c:822 #, c-format -msgid "Could not create sequencer directory %s" -msgstr "No s'ha pogut crear el directori de seqüenciador %s" - -#: sequencer.c:862 sequencer.c:998 -msgid "no cherry-pick or revert in progress" -msgstr "ni hi ha cap recull de cireres ni cap reversió en curs" - -#: sequencer.c:864 -msgid "cannot resolve HEAD" -msgstr "no es pot resoldre HEAD" - -#: sequencer.c:866 sequencer.c:900 -msgid "cannot abort from a branch yet to be born" -msgstr "no es pot avortar des d'una branca que encara ha de nàixer" +msgid "failed to open '%s': %s" +msgstr "s'ha fallat en obrir '%s': %s" -#: sequencer.c:886 builtin/fetch.c:724 builtin/fetch.c:970 +#: merge-recursive.c:833 #, c-format -msgid "cannot open %s" -msgstr "no es pot obrir %s" +msgid "failed to symlink '%s': %s" +msgstr "s'ha fallat en fer l'enllaç simbòlic '%s': %s" -#: sequencer.c:888 +#: merge-recursive.c:838 #, c-format -msgid "cannot read %s: %s" -msgstr "no es pot llegir %s: %s" - -#: sequencer.c:889 -msgid "unexpected end of file" -msgstr "final de fitxer inesperat" - -#: sequencer.c:895 -#, c-format -msgid "stored pre-cherry-pick HEAD file '%s' is corrupt" -msgstr "el fitxer HEAD emmagatzemat abans del recull de cireres '%s' és malmès" - -#: sequencer.c:921 -#, c-format -msgid "Could not format %s." -msgstr "No s'ha pogut formatar %s." - -#: sequencer.c:1066 -#, c-format -msgid "%s: can't cherry-pick a %s" -msgstr "%s: no es pot recollir com a cirera un %s" - -#: sequencer.c:1069 -#, c-format -msgid "%s: bad revision" -msgstr "%s: revisió dolenta" +msgid "do not know what to do with %06o %s '%s'" +msgstr "no se sap què fer amb %06o %s '%s'" -#: sequencer.c:1102 -msgid "Can't revert as initial commit" -msgstr "No es pot revertir com a comissió inicial" +#: merge-recursive.c:978 +msgid "Failed to execute internal merge" +msgstr "S'ha fallat en executar la fusió interna" -#: setup.c:160 +#: merge-recursive.c:982 #, c-format -msgid "" -"%s: no such path in the working tree.\n" -"Use 'git -- ...' to specify paths that do not exist locally." -msgstr "" -"%s: no hi ha tal camí en l'arbre de treball.\n" -"Useu 'git -- ...' per a especificar camins que no existeixin " -"localment." +msgid "Unable to add %s to database" +msgstr "no s'ha pogut afegir %s a la base de dades" -#: setup.c:173 +#: merge-recursive.c:1081 merge-recursive.c:1095 #, c-format msgid "" -"ambiguous argument '%s': unknown revision or path not in the working tree.\n" -"Use '--' to separate paths from revisions, like this:\n" -"'git [...] -- [...]'" +"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " +"in tree." msgstr "" -"paràmetre ambigu '%s': revisió no coneguda o camí no en l'arbre de treball.\n" -"Useu '--' per a separar els camins de les revisions, com això:\n" -"'git [...] -- [...]'" +"CONFLICTE: (%s/supressió): %s suprimit en %s i %s en %s. La versió %s de %s " +"s'ha deixat en l'arbre." -#: setup.c:223 +#: merge-recursive.c:1087 merge-recursive.c:1100 #, c-format msgid "" -"ambiguous argument '%s': both revision and filename\n" -"Use '--' to separate paths from revisions, like this:\n" -"'git [...] -- [...]'" +"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " +"in tree at %s." msgstr "" -"paràmetre ambigu '%s': ambdós una revisió i un nom de fitxer\n" -"Useu '--' per a separar els camins de les revisions, com això:\n" -"'git [...] -- [...]'" - -#: setup.c:248 builtin/apply.c:3362 builtin/apply.c:3373 builtin/apply.c:3419 -#, c-format -msgid "failed to read %s" -msgstr "s'ha fallat en llegir %s" +"CONFLICTE: (%s/supressió): %s suprimit en %s i %s en %s. La versió %s de %s " +"s'ha deixat en l'arbre a %s." -#: setup.c:468 -#, c-format -msgid "Expected git repo version <= %d, found %d" -msgstr "S'esperava una versió de dipòsit de git <= %d, s'ha trobat %d" +#: merge-recursive.c:1143 +msgid "rename" +msgstr "canvi de nom" -#: setup.c:476 -msgid "unknown repository extensions found:" -msgstr "s'han trobat extensions de dipòsit desconegudes:" +#: merge-recursive.c:1143 +msgid "renamed" +msgstr "canviat de nom" -#: setup.c:762 +#: merge-recursive.c:1200 #, c-format -msgid "Not a git repository (or any of the parent directories): %s" -msgstr "No un dipòsit de git (ni cap dels directoris pares): %s" - -#: setup.c:764 setup.c:915 builtin/index-pack.c:1641 -msgid "Cannot come back to cwd" -msgstr "No es pot tornar al directori de treball actual" - -#: setup.c:845 -msgid "Unable to read current working directory" -msgstr "No s'ha pogut llegir el directori de treball actual" +msgid "%s is a directory in %s adding as %s instead" +msgstr "%s és un directori en %s; s'està afegint com a %s en lloc d'això" -#: setup.c:920 +#: merge-recursive.c:1225 #, c-format msgid "" -"Not a git repository (or any parent up to mount point %s)\n" -"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)." +"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s" +"\"->\"%s\" in \"%s\"%s" msgstr "" -"No un dipòsit de git (ni cap pare fins el punt de muntatge %s)\n" -"S'atura a la frontera de sistema de fitxers (GIT_DISCOVERY_ACROSS_FILESYSTEM " -"no està establert)." +"CONFLICTE (canvi de nom/canvi de nom): Canvi de nom \"%s\"->\"%s\" en la " +"branca \"%s\" canvi de nom \"%s\"->\"%s\" en \"%s\"%s" -#: setup.c:927 -#, c-format -msgid "Cannot change to '%s/..'" -msgstr "No es pot canviar a '%s/..'" +#: merge-recursive.c:1230 +msgid " (left unresolved)" +msgstr " (deixat sense resolució)" -#: setup.c:989 +#: merge-recursive.c:1292 #, c-format -msgid "" -"Problem with core.sharedRepository filemode value (0%.3o).\n" -"The owner of files must always have read and write permissions." +msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" msgstr "" -"Problema amb el valor de mode de fitxer core.sharedRepository (0%.3o).\n" -"El propietari dels fitxers sempre ha de tenir permissions de lectura i " -"escriptura." - -#: sha1_file.c:1046 -msgid "offset before end of packfile (broken .idx?)" -msgstr "desplaçament abans de la fi del fitxer de paquet (.idx trencat?)" +"CONFLICTE (canvi de nom/canvi de nom): Canvi de nom %s->%s en %s. Canvi de " +"nom %s->%s en %s" -#: sha1_file.c:2434 +#: merge-recursive.c:1325 #, c-format -msgid "offset before start of pack index for %s (corrupt index?)" -msgstr "" -"desplaçament abans d'inici d'índex de paquet per a %s (índex corromput?)" +msgid "Renaming %s to %s and %s to %s instead" +msgstr "S'està canviant el nom de %s a %s i %s a %s en lloc d'això" -#: sha1_file.c:2438 +#: merge-recursive.c:1531 #, c-format -msgid "offset beyond end of pack index for %s (truncated index?)" -msgstr "" -"desplaçament més enllà de la fi d'índex de paquet per a %s (índex truncat?)" - -#: 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" -"may be created by mistake. For example,\n" -"\n" -" git checkout -b $br $(git rev-parse ...)\n" -"\n" -"where \"$br\" is somehow empty and a 40-hex ref is created. Please\n" -"examine these refs and maybe delete them. Turn this message off by\n" -"running \"git config advice.objectNameWarning false\"" +msgid "CONFLICT (rename/add): Rename %s->%s in %s. %s added in %s" msgstr "" -"Git normalment mai crea una referència que acabi amb 40 caràcters\n" -"hexadecimals perquè s'ignorarà quan només especifiqueu 40 caràcters\n" -"hexadecimals. Aquestes referències es poden crear per error. Per\n" -"exemple,\n" -"\n" -" git checkout -b $br $(git rev-parse ...)\n" -"\n" -"on \"$br\" és d'alguna manera buit i una referència de 40 caràcters\n" -"hexadecimals. Si us plau, examineu aquestes referències i potser\n" -"suprimiu-les. Desactiveu aquest missatge executant\n" -"\"git config advice.objectNameWarning false\"" +"CONFLICTE (canvi de nom/afegiment): Canvi de nom %s->%s en %s. %s afegit en " +"%s" -#: submodule.c:64 submodule.c:98 -msgid "Cannot change unmerged .gitmodules, resolve merge conflicts first" -msgstr "" -"No es pot canviar un .gitmodules no fusionat, primer resoldreu els " -"conflictes de fusió" +#: merge-recursive.c:1546 +#, c-format +msgid "Adding merged %s" +msgstr "S'està afegint %s fusionat" -#: submodule.c:68 submodule.c:102 +#: merge-recursive.c:1553 merge-recursive.c:1766 #, c-format -msgid "Could not find section in .gitmodules where path=%s" -msgstr "No s'ha pogut trobar la secció en .gitmodules on path=%s" +msgid "Adding as %s instead" +msgstr "S'està afegint com a %s en lloc d'això" -#: submodule.c:76 +#: merge-recursive.c:1610 #, c-format -msgid "Could not update .gitmodules entry %s" -msgstr "No s'ha pogut actualitzar l'entrada de .gitmodules %s" +msgid "cannot read object %s" +msgstr "no es pot llegir l'objecte %s" -#: submodule.c:109 +#: merge-recursive.c:1613 #, c-format -msgid "Could not remove .gitmodules entry for %s" -msgstr "No s'ha pogut eliminar l'entrada de .gitmodules per a %s" +msgid "object %s is not a blob" +msgstr "l'objecte %s no és un blob" -#: submodule.c:120 -msgid "staging updated .gitmodules failed" -msgstr "L'allistament del .gitmodules actualitzat ha fallat" +#: merge-recursive.c:1666 +msgid "modify" +msgstr "modificació" -#: submodule.c:177 -msgid "negative values not allowed for submodule.fetchJobs" -msgstr "no es permeten els valors negatius a submodule.fetchJobs" +#: merge-recursive.c:1666 +msgid "modified" +msgstr "modificat" -#: submodule-config.c:358 -#, c-format -msgid "invalid value for %s" -msgstr "valor no vàlid per a %s" +#: merge-recursive.c:1676 +msgid "content" +msgstr "contingut" -#: trailer.c:237 -#, c-format -msgid "running trailer command '%s' failed" -msgstr "l'execució de l'ordre de remolc '%s' ha fallat" +#: merge-recursive.c:1683 +msgid "add/add" +msgstr "afegiment/afegiment" -#: trailer.c:492 trailer.c:496 trailer.c:500 trailer.c:554 trailer.c:558 -#: trailer.c:562 +#: merge-recursive.c:1718 #, c-format -msgid "unknown value '%s' for key '%s'" -msgstr "valor desconegut '%s' per a la clau '%s'" +msgid "Skipped %s (merged same as existing)" +msgstr "S'ha saltat %s (el fusionat és igual a l'existent)" -#: trailer.c:544 trailer.c:549 builtin/remote.c:289 +#: merge-recursive.c:1732 #, c-format -msgid "more than one %s" -msgstr "més d'un %s" +msgid "Auto-merging %s" +msgstr "S'està autofusionant %s" + +#: merge-recursive.c:1736 git-submodule.sh:924 +msgid "submodule" +msgstr "submòdul" -#: trailer.c:582 +#: merge-recursive.c:1737 #, c-format -msgid "empty trailer token in trailer '%.*s'" -msgstr "fitxa de remolc buida en el remolc '%.*s'" +msgid "CONFLICT (%s): Merge conflict in %s" +msgstr "CONFLICTE (%s): Conflicte de fusió en %s" -#: trailer.c:702 +#: merge-recursive.c:1831 #, c-format -msgid "could not read input file '%s'" -msgstr "no s'ha pogut llegir el fitxer d'entrada '%s'" +msgid "Removing %s" +msgstr "S'està eliminant %s" -#: trailer.c:705 -msgid "could not read from stdin" -msgstr "No s'ha pogut llegir des d'stdin" +#: merge-recursive.c:1857 +msgid "file/directory" +msgstr "fitxer/directori" -#: trailer.c:857 builtin/am.c:42 -#, c-format -msgid "could not stat %s" -msgstr "no s'ha pogut fer stat a %s" +#: merge-recursive.c:1863 +msgid "directory/file" +msgstr "directori/fitxer" -#: trailer.c:859 +#: merge-recursive.c:1868 #, c-format -msgid "file %s is not a regular file" -msgstr "el fitxer %s no és un fitxer regular" +msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" +msgstr "" +"CONFLICTE (%s): Hi ha un directori amb nom %s en %s. S'està afegint %s com a " +"%s" -#: trailer.c:861 +#: merge-recursive.c:1877 #, c-format -msgid "file %s is not writable by user" -msgstr "el fitxer %s no és gravable per l'usuari" +msgid "Adding %s" +msgstr "S'està afegint %s" -#: trailer.c:873 -msgid "could not open temporary file" -msgstr "no s'ha pogut obrir el fitxer temporal" +#: merge-recursive.c:1914 +msgid "Already up-to-date!" +msgstr "Ja està al dia!" -#: trailer.c:912 +#: merge-recursive.c:1923 #, c-format -msgid "could not rename temporary file to %s" -msgstr "no s'ha pogut canviar el nom del fitxer temporal a %s" +msgid "merging of trees %s and %s failed" +msgstr "la fusió dels arbres %s i %s ha fallat" -#: transport.c:62 +#: merge-recursive.c:2006 +msgid "Merging:" +msgstr "Fusionant:" + +#: merge-recursive.c:2019 #, c-format -msgid "Would set upstream of '%s' to '%s' of '%s'\n" -msgstr "Canviaria la font de '%s' a '%s' de '%s'\n" +msgid "found %u common ancestor:" +msgid_plural "found %u common ancestors:" +msgstr[0] "s'ha trobat %u avantpassat en comú:" +msgstr[1] "s'han trobat %u avantpassats en comú:" -#: transport.c:151 +#: merge-recursive.c:2058 +msgid "merge returned no commit" +msgstr "la fusió no ha retornat cap comissió" + +#: merge-recursive.c:2121 #, c-format -msgid "transport: invalid depth option '%s'" -msgstr "transport: opció de profunditat no vàlida '%s'" +msgid "Could not parse object '%s'" +msgstr "No s'ha pogut analitzar l'objecte '%s'" + +#: merge-recursive.c:2135 builtin/merge.c:641 builtin/merge.c:788 +msgid "Unable to write index." +msgstr "No s'ha pogut escriure l'índex." -#: transport.c:771 +#: notes-merge.c:273 #, c-format msgid "" -"The following submodule paths contain changes that can\n" -"not be found on any remote:\n" +"You have not concluded your previous notes merge (%s exists).\n" +"Please, use 'git notes merge --commit' or 'git notes merge --abort' to " +"commit/abort the previous merge before you start a new notes merge." msgstr "" -"Els camins de submòdul següents contenen canvis que no\n" -"es poden trobar en cap remot:\n" +"No heu conclòs la vostra fusió de notes prèvia (%s existeix).\n" +"Si us plau, useu 'git notes merge --commit' o 'git notes merge --abort' per " +"a cometre/avortar la fusió prèvia abans de començar una fusió de notes nova." -#: transport.c:775 +#: notes-merge.c:280 #, c-format -msgid "" -"\n" -"Please try\n" -"\n" -"\tgit push --recurse-submodules=on-demand\n" -"\n" -"or cd to the path and use\n" -"\n" -"\tgit push\n" -"\n" -"to push them to a remote.\n" -"\n" -msgstr "" -"\n" -"Si us plau, intenteu\n" -"\n" -"\tgit push --recurse-submodules=on-demand\n" -"\n" -"o canviar de directori al camí i useu\n" -"\n" -"\tgit push\n" -"\n" -"per a pujar-los a un remot.\n" +msgid "You have not concluded your notes merge (%s exists)." +msgstr "No heu conclòs la vostra fusió de notes (%s existeix)." -#: transport.c:783 -msgid "Aborting." -msgstr "S'està avortant." +#: notes-utils.c:41 +msgid "Cannot commit uninitialized/unreferenced notes tree" +msgstr "No es pot cometre un arbre de notes no inicialitzat / no referenciat" -#: transport-helper.c:1041 +#: notes-utils.c:100 #, c-format -msgid "Could not read ref %s" -msgstr "No s'ha pogut llegir la referència %s" +msgid "Bad notes.rewriteMode value: '%s'" +msgstr "Valor de notes.rewriteMode dolent: '%s'" -#: unpack-trees.c:64 +#: notes-utils.c:110 #, c-format -msgid "" -"Your local changes to the following files would be overwritten by checkout:\n" -"%%sPlease commit your changes or stash them before you switch branches." -msgstr "" -"Els vostres canvis locals als fitxers següents se sobreescriurien per " -"agafar:\n" -"%%sSi us plau, cometeu els vostres canvis o emmagatzemeu-los abans de " -"canviar de branca." +msgid "Refusing to rewrite notes in %s (outside of refs/notes/)" +msgstr "S'està refusant reescriure les notes en %s (fora de refs/notes/)" -#: unpack-trees.c:66 +#. TRANSLATORS: The first %s is the name of the +#. environment variable, the second %s is its value +#: notes-utils.c:137 #, c-format -msgid "" -"Your local changes to the following files would be overwritten by checkout:\n" -"%%s" -msgstr "" -"Els vostres canvis locals als fitxers següents se sobreescriurien per " -"agafar:\n" -"%%s" +msgid "Bad %s value: '%s'" +msgstr "Valor dolent de %s: '%s'" -#: unpack-trees.c:69 +#: object.c:242 #, c-format -msgid "" -"Your local changes to the following files would be overwritten by merge:\n" -"%%sPlease commit your changes or stash them before you merge." -msgstr "" -"Els vostres canvis locals als fitxers següents se sobreescriurien per " -"fusionar:\n" -"%%sSi us plau, cometeu els vostres canvis o emmagatzemeu-los abans de " -"fusionar." +msgid "unable to parse object: %s" +msgstr "no s'ha pogut analitzar l'objecte: %s" -#: unpack-trees.c:71 +#: parse-options.c:572 +msgid "..." +msgstr "..." + +#: parse-options.c:590 #, c-format -msgid "" -"Your local changes to the following files would be overwritten by merge:\n" -"%%s" -msgstr "" -"Els vostres canvis locals als fitxers següents se sobreescriurien per " -"fusionar:\n" -"%%s" +msgid "usage: %s" +msgstr "ús: %s" -#: unpack-trees.c:74 +#. TRANSLATORS: the colon here should align with the +#. one in "usage: %s" translation +#: parse-options.c:594 #, c-format -msgid "" -"Your local changes to the following files would be overwritten by %s:\n" -"%%sPlease commit your changes or stash them before you %s." -msgstr "" -"Els vostres canvis locals als fitxers següents se sobreescriurien per %s:\n" -"%%sSi us plau, cometeu els vostres canvis o emmagatzemeu-los abans de %s." +msgid " or: %s" +msgstr " o: %s" -#: unpack-trees.c:76 +#: parse-options.c:597 #, c-format -msgid "" -"Your local changes to the following files would be overwritten by %s:\n" -"%%s" -msgstr "" -"Els vostres canvis locals als fitxers següents se sobreescriurien per %s:\n" -"%%s" +msgid " %s" +msgstr " %s" -#: unpack-trees.c:81 +#: parse-options.c:631 +msgid "-NUM" +msgstr "-NUM" + +#: parse-options-cb.c:108 #, c-format -msgid "" -"Updating the following directories would lose untracked files in it:\n" -"%s" -msgstr "" -"Actualitzar els directoris següents perdria fitxers no seguits en el:\n" -"%s" +msgid "malformed object name '%s'" +msgstr "nom d'objecte mal format '%s'" -#: unpack-trees.c:85 +#: path.c:826 #, c-format -msgid "" -"The following untracked working tree files would be removed by checkout:\n" -"%%sPlease move or remove them before you switch branches." +msgid "Could not make %s writable by group" +msgstr "No s'ha pogut fer %s escrivible pel grup" + +#: pathspec.c:133 +msgid "global 'glob' and 'noglob' pathspec settings are incompatible" msgstr "" -"Els següents fitxers no seguits en l'arbre de treball s'eliminarien per " -"agafar:\n" -"%%sSi us plau, moveu-los o elimineu-los abans de canviar de branca." +"els ajusts d'especificació de camí 'glob' i 'noglob' globals són " +"incompatibles" -#: unpack-trees.c:87 -#, c-format +#: pathspec.c:143 msgid "" -"The following untracked working tree files would be removed by checkout:\n" -"%%s" +"global 'literal' pathspec setting is incompatible with all other global " +"pathspec settings" msgstr "" -"Els següents fitxers no seguits en l'arbre de treball s'eliminarien per " -"agafar:\n" -"%%s" +"l'ajust d'especificació de camí 'literal' global és incompatible amb tots " +"els altres ajusts d'especificació de camí globals" -#: unpack-trees.c:90 +#: pathspec.c:177 +msgid "invalid parameter for pathspec magic 'prefix'" +msgstr "paràmetre no vàlid per a la màgia d'especificació de camí 'prefix'" + +#: pathspec.c:183 #, c-format -msgid "" -"The following untracked working tree files would be removed by merge:\n" -"%%sPlease move or remove them before you merge." -msgstr "" -"Els següents fitxers no seguits en l'arbre de treball s'eliminarien per " -"fusionar:\n" -"%%sSi us plau, moveu-los o elimineu-los abans de fusionar." +msgid "Invalid pathspec magic '%.*s' in '%s'" +msgstr "Màgia d'especificació de camí no vàlida '%.*s' en '%s'" -#: unpack-trees.c:92 +#: pathspec.c:187 #, c-format -msgid "" -"The following untracked working tree files would be removed by merge:\n" -"%%s" -msgstr "" -"Els següents fitxers no seguits en l'arbre de treball s'eliminarien per " -"fusionar:\n" -"%%s" +msgid "Missing ')' at the end of pathspec magic in '%s'" +msgstr "')' mancant al final de la màgia d'especificació de camí en '%s'" -#: unpack-trees.c:95 +#: pathspec.c:205 +#, c-format +msgid "Unimplemented pathspec magic '%c' in '%s'" +msgstr "Màgia d'especificació de camí no implementada '%c' en '%s'" + +#: pathspec.c:230 +#, c-format +msgid "%s: 'literal' and 'glob' are incompatible" +msgstr "%s: 'literal' i 'glob' són incompatibles" + +#: pathspec.c:241 +#, c-format +msgid "%s: '%s' is outside repository" +msgstr "%s: '%s' és fora del dipòsit" + +#: pathspec.c:291 #, c-format +msgid "Pathspec '%s' is in submodule '%.*s'" +msgstr "L'especificació '%s' és en el submòdul '%.*s'" + +#: pathspec.c:353 +#, c-format +msgid "%s: pathspec magic not supported by this command: %s" +msgstr "" +"%s: aquesta ordre no és compatible amb la màgia d'especificació de camí: %s" + +#: pathspec.c:408 msgid "" -"The following untracked working tree files would be removed by %s:\n" -"%%sPlease move or remove them before you %s." +"empty strings as pathspecs will be made invalid in upcoming releases. please " +"use . instead if you meant to match all paths" msgstr "" -"Els següents fitxers no seguits en l'arbre de treball s'eliminarien per %s:\n" -"%%sSi us plau, moveu-los o elimineu-los abans de %s." +"es faran no vàlides les cadenes buides com especificacions de camí en " +"versions futures. si us plau, useu . en lloc d'això si volíeu coincidir amb " +"tots els camins" -#: unpack-trees.c:97 +#: pathspec.c:440 #, c-format +msgid "pathspec '%s' is beyond a symbolic link" +msgstr "l'especificació de camí '%s' és més enllà d'un enllaç simbòlic" + +#: pathspec.c:449 msgid "" -"The following untracked working tree files would be removed by %s:\n" -"%%s" +"There is nothing to exclude from by :(exclude) patterns.\n" +"Perhaps you forgot to add either ':/' or '.' ?" msgstr "" -"Els següents fitxers no seguits en l'arbre de treball s'eliminarien per %s:\n" -"%%s" +"No hi ha res a excloure per patrons :(exclusió).\n" +"Potser heu oblidat afegir o ':/' o '.' ?" -#: unpack-trees.c:102 +#: pretty.c:971 +msgid "unable to parse --pretty format" +msgstr "no s'ha pogut analitzar el format --pretty" + +#: read-cache.c:1315 #, c-format msgid "" -"The following untracked working tree files would be overwritten by " -"checkout:\n" -"%%sPlease move or remove them before you switch branches." +"index.version set, but the value is invalid.\n" +"Using version %i" msgstr "" -"Els següents fitxers no seguits en l'arbre de treball se sobreescriurien per " -"agafar:\n" -"%%sSi us plau, moveu-los o elimineu-los abans de canviar de branca." +"index.version està establerta, però el valor no és vàlid.\n" +"S'està usant la versió %i" -#: unpack-trees.c:104 +#: read-cache.c:1325 #, c-format msgid "" -"The following untracked working tree files would be overwritten by " -"checkout:\n" -"%%s" +"GIT_INDEX_VERSION set, but the value is invalid.\n" +"Using version %i" msgstr "" -"Els següents fitxers no seguits en l'arbre de treball se sobreescriurien per " -"agafar:\n" -"%%s" +"GIT_INDEX_VERSION està establerta, però el valor no és vàlid.\n" +"S'està usant la versió %i" -#: unpack-trees.c:107 +#: refs.c:576 builtin/merge.c:840 #, c-format -msgid "" -"The following untracked working tree files would be overwritten by merge:\n" -"%%sPlease move or remove them before you merge." -msgstr "" -"Els següents fitxers no seguits en l'arbre de treball se sobreescriurien per " -"fusionar:\n" -"%%sSi us plau, moveu-los o elimineu-los abans de fusionar." +msgid "Could not open '%s' for writing" +msgstr "No s'ha pogut obrir '%s' per a escriptura" -#: unpack-trees.c:109 +#: refs/files-backend.c:2481 #, c-format -msgid "" -"The following untracked working tree files would be overwritten by merge:\n" -"%%s" -msgstr "" -"Els següents fitxers no seguits en l'arbre de treball se sobreescriurien per " -"fusionar:\n" -"%%s" +msgid "could not delete reference %s: %s" +msgstr "no s'ha pogut suprimir la referència %s: %s" -#: unpack-trees.c:112 +#: refs/files-backend.c:2484 #, c-format -msgid "" -"The following untracked working tree files would be overwritten by %s:\n" -"%%sPlease move or remove them before you %s." +msgid "could not delete references: %s" +msgstr "no s'ha pogut suprimir les referències: %s" + +#: refs/files-backend.c:2493 +#, c-format +msgid "could not remove reference %s" +msgstr "no s'ha pogut eliminar la referència %s" + +#: ref-filter.c:55 +#, c-format +msgid "expected format: %%(color:)" +msgstr "format esperat: %%(color:)" + +#: ref-filter.c:57 +#, c-format +msgid "unrecognized color: %%(color:%s)" +msgstr "color no reconegut: %%(color:%s)" + +#: ref-filter.c:71 +#, c-format +msgid "unrecognized format: %%(%s)" +msgstr "format no reconegut: %%(%s)" + +#: ref-filter.c:77 +#, c-format +msgid "%%(body) does not take arguments" +msgstr "%%(body) no accepta paràmetres" + +#: ref-filter.c:84 +#, c-format +msgid "%%(subject) does not take arguments" +msgstr "%%(subject) no accepta paràmetres" + +#: ref-filter.c:101 +#, c-format +msgid "positive value expected contents:lines=%s" +msgstr "valor positiu esperat contents:lines=%s" + +#: ref-filter.c:103 +#, c-format +msgid "unrecognized %%(contents) argument: %s" +msgstr "paràmetre %%(contents) no reconegut: %s" + +#: ref-filter.c:113 +#, c-format +msgid "unrecognized %%(objectname) argument: %s" +msgstr "paràmetre %%(objectname) no reconegut: %s" + +#: ref-filter.c:135 +#, c-format +msgid "expected format: %%(align:,)" +msgstr "format esperat: %%(align:,)" + +#: ref-filter.c:147 +#, c-format +msgid "unrecognized position:%s" +msgstr "posició no reconeguda:%s" + +#: ref-filter.c:151 +#, c-format +msgid "unrecognized width:%s" +msgstr "amplada no reconeguda:%s" + +#: ref-filter.c:157 +#, c-format +msgid "unrecognized %%(align) argument: %s" +msgstr "paràmetre %%(align) no reconegut: %s" + +#: ref-filter.c:161 +#, c-format +msgid "positive width expected with the %%(align) atom" +msgstr "amplada positiva esperada amb l'àtom %%(align)" + +#: ref-filter.c:244 +#, c-format +msgid "malformed field name: %.*s" +msgstr "nom de camp mal format: %.*s" + +#: ref-filter.c:270 +#, c-format +msgid "unknown field name: %.*s" +msgstr "nom de camp desconegut: %.*s" + +#: ref-filter.c:372 +#, c-format +msgid "format: %%(end) atom used without corresponding atom" +msgstr "format: s'ha usat l'àtom %%(end) sense l'àtom corresponent" + +#: ref-filter.c:424 +#, c-format +msgid "malformed format string %s" +msgstr "cadena de format mal format %s" + +#: ref-filter.c:878 +msgid ":strip= requires a positive integer argument" +msgstr ":strip= requereix un paràmetre enter positiu" + +#: ref-filter.c:883 +#, c-format +msgid "ref '%s' does not have %ld components to :strip" +msgstr "la referència '%s' no té %ld components per a :strip" + +#: ref-filter.c:1046 +#, c-format +msgid "unknown %.*s format %s" +msgstr "format de %.*s desconegut %s" + +#: ref-filter.c:1066 ref-filter.c:1097 +#, c-format +msgid "missing object %s for %s" +msgstr "manca l'objecte %s per a %s" + +#: ref-filter.c:1069 ref-filter.c:1100 +#, c-format +msgid "parse_object_buffer failed on %s for %s" +msgstr "parse_object_buffer ha fallat en %s per a %s" + +#: ref-filter.c:1311 +#, c-format +msgid "malformed object at '%s'" +msgstr "objecte mal format a '%s'" + +#: ref-filter.c:1373 +#, c-format +msgid "ignoring ref with broken name %s" +msgstr "s'està ignorant la referència amb nom trencat %s" + +#: ref-filter.c:1378 +#, c-format +msgid "ignoring broken ref %s" +msgstr "s'està ignorant la referència trencada %s" + +#: ref-filter.c:1633 +#, c-format +msgid "format: %%(end) atom missing" +msgstr "format: manca l'àtom %%(end)" + +#: ref-filter.c:1687 +#, c-format +msgid "malformed object name %s" +msgstr "nom d'objecte %s mal format" + +#: remote.c:746 +#, c-format +msgid "Cannot fetch both %s and %s to %s" +msgstr "No es pot obtenir ambdós %s i %s a %s" + +#: remote.c:750 +#, c-format +msgid "%s usually tracks %s, not %s" +msgstr "%s generalment segueix %s, no %s" + +#: remote.c:754 +#, c-format +msgid "%s tracks both %s and %s" +msgstr "%s segueix ambdós %s i %s" + +#: remote.c:762 +msgid "Internal error" +msgstr "Error intern" + +#: remote.c:1677 remote.c:1720 +msgid "HEAD does not point to a branch" +msgstr "HEAD no assenyala cap branca" + +#: remote.c:1686 +#, c-format +msgid "no such branch: '%s'" +msgstr "no hi ha tal branca: '%s'" + +#: remote.c:1689 +#, c-format +msgid "no upstream configured for branch '%s'" +msgstr "cap font configurada per a la branca '%s'" + +#: remote.c:1695 +#, c-format +msgid "upstream branch '%s' not stored as a remote-tracking branch" +msgstr "la branca font '%s' no s'emmagatzema com a branca amb seguiment remot" + +#: remote.c:1710 +#, c-format +msgid "push destination '%s' on remote '%s' has no local tracking branch" msgstr "" -"Els següents fitxers no seguits en l'arbre de treball se sobreescriurien per " -"%s:\n" -"%%sSi us plau, moveu-los o elimineu-los abans de %s." +"el destí de pujada '%s' en el remot '%s' no té cap branca seguidora local" -#: unpack-trees.c:114 +#: remote.c:1725 +#, c-format +msgid "branch '%s' has no remote for pushing" +msgstr "la branca '%s' no té cap remot al qual pujar" + +#: remote.c:1736 +#, c-format +msgid "push refspecs for '%s' do not include '%s'" +msgstr "les especificacions de referència de '%s' no inclouen '%s'" + +#: remote.c:1749 +msgid "push has no destination (push.default is 'nothing')" +msgstr "push no té destí (push.default és 'nothing')" + +#: remote.c:1771 +msgid "cannot resolve 'simple' push to a single destination" +msgstr "no es pot resoldre una pujada 'simple' a un sol destí" + +#: remote.c:2073 +#, c-format +msgid "Your branch is based on '%s', but the upstream is gone.\n" +msgstr "La vostra branca està basada en '%s', però la font no hi és.\n" + +#: remote.c:2077 +msgid " (use \"git branch --unset-upstream\" to fixup)\n" +msgstr " (useu \"git branch --unset-upstream\" per a arreglar)\n" + +#: remote.c:2080 +#, c-format +msgid "Your branch is up-to-date with '%s'.\n" +msgstr "La vostra branca està al dia amb '%s'.\n" + +#: remote.c:2084 +#, 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] "La vostra branca està davant de '%s' per %d comissió.\n" +msgstr[1] "La vostra branca està davant de '%s' per %d comissions.\n" + +#: remote.c:2090 +msgid " (use \"git push\" to publish your local commits)\n" +msgstr " (useu \"git push\" per a publicar les vostres comissions locals)\n" + +#: remote.c:2093 +#, c-format +msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n" +msgid_plural "" +"Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n" +msgstr[0] "" +"La vostra branca està darrere de '%s' per %d comissió, i pot avançar-se " +"ràpidament.\n" +msgstr[1] "" +"La vostra branca està darrere de '%s' per %d comissions, i pot avançar-se " +"ràpidament.\n" + +#: remote.c:2101 +msgid " (use \"git pull\" to update your local branch)\n" +msgstr " (useu \"git pull\" per a actualitzar la vostra branca local)\n" + +#: remote.c:2104 #, c-format msgid "" -"The following untracked working tree files would be overwritten by %s:\n" -"%%s" -msgstr "" -"Els següents fitxers no seguits en l'arbre de treball se sobreescriurien per " -"%s:\n" -"%%s" +"Your branch and '%s' have diverged,\n" +"and have %d and %d different commit each, respectively.\n" +msgid_plural "" +"Your branch and '%s' have diverged,\n" +"and have %d and %d different commits each, respectively.\n" +msgstr[0] "" +"La vostra branca i '%s' s'han divergit,\n" +"i tenen %d i %d comissió distinta cada una, respectivament.\n" +msgstr[1] "" +"La vostra branca i '%s' s'han divergit,\n" +"i tenen %d i %d comissions distintes cada una, respectivament.\n" -#: unpack-trees.c:121 +#: remote.c:2114 +msgid " (use \"git pull\" to merge the remote branch into yours)\n" +msgstr " (useu \"git pull\" per a fusionar la branca remota a la vostra)\n" + +#: revision.c:2158 +msgid "your current branch appears to be broken" +msgstr "la vostra branca actual sembla trencada" + +#: revision.c:2161 #, c-format -msgid "Entry '%s' overlaps with '%s'. Cannot bind." -msgstr "L'entrada '%s' encavalca amb '%s'. No es pot vincular." +msgid "your current branch '%s' does not have any commits yet" +msgstr "la vostra branca actual '%s' encara no té cap comissió" -#: unpack-trees.c:124 +#: revision.c:2355 +msgid "--first-parent is incompatible with --bisect" +msgstr "--first-parent és incompatible amb --bisect" + +#: run-command.c:106 +msgid "open /dev/null failed" +msgstr "s'ha fallat en obrir /dev/null" + +#: run-command.c:108 #, c-format +msgid "dup2(%d,%d) failed" +msgstr "dup2(%d,%d) ha fallat" + +#: send-pack.c:297 +msgid "failed to sign the push certificate" +msgstr "s'ha fallat en signar el certificat de pujada" + +#: send-pack.c:410 +msgid "the receiving end does not support --signed push" +msgstr "el destí receptor no admet pujar --signed" + +#: send-pack.c:412 msgid "" -"Cannot update sparse checkout: the following entries are not up-to-date:\n" -"%s" +"not sending a push certificate since the receiving end does not support --" +"signed push" msgstr "" -"No es pot actualitzar l'agafament parcial: les entrades següents no estan al " -"dia:\n" -"%s" +"no s'està enviant una certificació de pujada perquè el destí receptor no " +"admet pujar --signed" -#: unpack-trees.c:126 -#, c-format +#: send-pack.c:424 +msgid "the receiving end does not support --atomic push" +msgstr "el destí receptor no admet pujar --atomic" + +#: send-pack.c:429 +msgid "the receiving end does not support push options" +msgstr "el destí receptor no admet opcions de pujada" + +#: sequencer.c:171 +msgid "revert" +msgstr "revertir" + +#: sequencer.c:171 +msgid "cherry-pick" +msgstr "recollir cireres" + +#: sequencer.c:228 msgid "" -"The following Working tree files would be overwritten by sparse checkout " -"update:\n" -"%s" +"after resolving the conflicts, mark the corrected paths\n" +"with 'git add ' or 'git rm '" msgstr "" -"Els fitxers següents en l'arbre de treball se sobreescriurien per " -"actualitzar l'agafament parcial:\n" -"%s" +"després de resoldre els conflictes, marqueu els camins\n" +"corregits amb 'git add ' o 'git rm '" -#: unpack-trees.c:128 -#, c-format +#: sequencer.c:231 msgid "" -"The following Working tree files would be removed by sparse checkout " -"update:\n" -"%s" +"after resolving the conflicts, mark the corrected paths\n" +"with 'git add ' or 'git rm '\n" +"and commit the result with 'git commit'" msgstr "" -"Els fitxers següents en l'arbre de treball s'eliminarien per actualitzar " -"l'agafament parcial:\n" -"%s" +"després de resoldre els conflictes, marqueu els camins\n" +"corregits amb 'git add ' o 'git rm '\n" +"i cometeu el resultat amb 'git commit'" -#: unpack-trees.c:205 +#: sequencer.c:244 sequencer.c:1209 #, c-format -msgid "Aborting\n" -msgstr "S'està avortant\n" +msgid "could not lock '%s'" +msgstr "no s'ha pogut bloquejar '%s'" -#: unpack-trees.c:237 -msgid "Checking out files" -msgstr "S'està agafant fitxers" +#: sequencer.c:247 sequencer.c:1125 sequencer.c:1214 +#, c-format +msgid "could not write to '%s'" +msgstr "no s'ha pogut escriure a '%s'" -#: urlmatch.c:120 -msgid "invalid URL scheme name or missing '://' suffix" -msgstr "l'esquema d'URL no és vàlid o li manca el sufix '://'" +#: sequencer.c:251 +#, c-format +msgid "could not write eol to '%s'" +msgstr "no s'ha pogut escriure el terminador de línia a '%s'" -#: urlmatch.c:144 urlmatch.c:297 urlmatch.c:356 +#: sequencer.c:255 sequencer.c:1130 sequencer.c:1216 #, c-format -msgid "invalid %XX escape sequence" -msgstr "seqüència d'escapament %XX no vàlida" +msgid "failed to finalize '%s'." +msgstr "s'ha fallat en finalitzar '%s'." -#: urlmatch.c:172 -msgid "missing host and scheme is not 'file:'" -msgstr "manca la màquina i l'esquema no és 'file:'" +#: sequencer.c:279 builtin/am.c:259 builtin/commit.c:749 builtin/merge.c:1032 +#, c-format +msgid "could not read '%s'" +msgstr "no s'ha pogut llegir '%s'" -#: urlmatch.c:189 -msgid "a 'file:' URL may not have a port number" -msgstr "un URL 'file:' no pot tenir número de port" +#: sequencer.c:305 +#, c-format +msgid "your local changes would be overwritten by %s." +msgstr "els vostres canvis locals se sobreescriurien per %s." -#: urlmatch.c:199 -msgid "invalid characters in host name" -msgstr "hi ha caràcters no vàlids en el nom de màquina" +#: sequencer.c:309 +msgid "commit your changes or stash them to proceed." +msgstr "cometeu els vostres canvis o emmagatzemeu-los per a procedir." -#: urlmatch.c:244 urlmatch.c:255 -msgid "invalid port number" -msgstr "número de port no vàlid" +#: sequencer.c:324 +#, c-format +msgid "%s: fast-forward" +msgstr "%s: avanç ràpid" + +#. TRANSLATORS: %s will be "revert" or "cherry-pick" +#: sequencer.c:399 +#, c-format +msgid "%s: Unable to write new index file" +msgstr "%s: No s'ha pogut escriure un fitxer d'índex nou" -#: urlmatch.c:322 -msgid "invalid '..' path segment" -msgstr "segment de camí '..' no vàlid" +#: sequencer.c:418 +msgid "could not resolve HEAD commit\n" +msgstr "no s'ha pogut resoldre la comissió HEAD\n" -#: worktree.c:282 -#, c-format -msgid "failed to read '%s'" -msgstr "s'ha fallat en llegir '%s'" +#: sequencer.c:438 +msgid "unable to update cache tree\n" +msgstr "no s'ha pogut actualitzar l'arbre cau\n" -#: wrapper.c:222 wrapper.c:392 +#: sequencer.c:483 #, c-format -msgid "could not open '%s' for reading and writing" -msgstr "no s'ha pogut obrir '%s' per a lectura i escriptura" +msgid "" +"you have staged changes in your working tree\n" +"If these changes are meant to be squashed into the previous commit, run:\n" +"\n" +" git commit --amend %s\n" +"\n" +"If they are meant to go into a new commit, run:\n" +"\n" +" git commit %s\n" +"\n" +"In both cases, once you're done, continue with:\n" +"\n" +" git rebase --continue\n" +msgstr "" +"teniu canvis allistats en el vostre arbre de treball\n" +"Si aquests canvis són per a aixafar-se a la comissió prèvia, executeu:\n" +"\n" +" git commit --amend %s\n" +"\n" +"Si són per a formar una comissió nova, executeu:\n" +"\n" +" git commit %s\n" +"\n" +"En ambdós cassos, quan hàgiu terminat, continueu amb:\n" +"\n" +" git rebase --continue\n" -#: wrapper.c:224 wrapper.c:394 builtin/am.c:778 +#: sequencer.c:567 #, c-format -msgid "could not open '%s' for writing" -msgstr "no s'ha pogut obrir '%s' per a escriptura" +msgid "could not parse commit %s\n" +msgstr "no s'ha pogut analitzar la comissió %s\n" -#: wrapper.c:226 wrapper.c:396 builtin/am.c:324 builtin/am.c:771 -#: builtin/am.c:859 builtin/commit.c:1712 builtin/merge.c:1029 -#: builtin/pull.c:407 +#: sequencer.c:572 #, c-format -msgid "could not open '%s' for reading" -msgstr "no s'ha pogut obrir '%s' per a lectura" +msgid "could not parse parent commit %s\n" +msgstr "no s'ha pogut analitzar la comissió mare %s\n" -#: wrapper.c:605 wrapper.c:626 +#: sequencer.c:656 +msgid "your index file is unmerged." +msgstr "el vostre fitxer d'índex està sense fusionar." + +#: sequencer.c:675 #, c-format -msgid "unable to access '%s'" -msgstr "no s'ha pogut accedir a '%s'" +msgid "commit %s is a merge but no -m option was given." +msgstr "la comissió %s és una fusió però no s'ha donat cap opció -m." -#: wrapper.c:634 -msgid "unable to get current working directory" -msgstr "no s'ha pogut obtenir el directori de treball actual" +#: sequencer.c:683 +#, c-format +msgid "commit %s does not have parent %d" +msgstr "la comissió %s no té mare %d" -#: wrapper.c:658 +#: sequencer.c:687 #, c-format -msgid "could not write to %s" -msgstr "no s'ha pogut escriure a %s" +msgid "mainline was specified but commit %s is not a merge." +msgstr "" +"s'ha especificat la línia principal però la comissió %s no és una fusió." -#: wrapper.c:660 +#. TRANSLATORS: The first %s will be a "todo" command like +#. "revert" or "pick", the second %s a SHA1. +#: sequencer.c:700 #, c-format -msgid "could not close %s" -msgstr "no s'ha pogut tancar %s" +msgid "%s: cannot parse parent commit %s" +msgstr "%s: no es pot analitzar la comissió mare %s" -#: wt-status.c:150 -msgid "Unmerged paths:" -msgstr "Camins sense fusionar:" +#: sequencer.c:705 +#, c-format +msgid "cannot get commit message for %s" +msgstr "no es pot obtenir el missatge de comissió de %s" -#: wt-status.c:177 wt-status.c:204 +#: sequencer.c:797 #, c-format -msgid " (use \"git reset %s ...\" to unstage)" -msgstr " (useu \"git reset %s ...\" per a desallistar)" +msgid "could not revert %s... %s" +msgstr "no s'ha pogut revertir %s... %s" -#: wt-status.c:179 wt-status.c:206 -msgid " (use \"git rm --cached ...\" to unstage)" -msgstr " (useu \"git rm --cached ...\" per a desallistar)" +#: sequencer.c:798 +#, c-format +msgid "could not apply %s... %s" +msgstr "no s'ha pogut aplicar %s... %s" -#: wt-status.c:183 -msgid " (use \"git add ...\" to mark resolution)" -msgstr " (useu \"git add ...\" per a senyalar resolució)" +#: sequencer.c:833 +msgid "empty commit set passed" +msgstr "conjunt de comissions buit passat" -#: wt-status.c:185 wt-status.c:189 -msgid " (use \"git add/rm ...\" as appropriate to mark resolution)" -msgstr "" -" (useu \"git add/rm ...\" segons sigui apropiat per a senyalar " -"resolució)" +#: sequencer.c:843 +#, c-format +msgid "git %s: failed to read the index" +msgstr "git %s: s'ha fallat en llegir l'índex" -#: wt-status.c:187 -msgid " (use \"git rm ...\" to mark resolution)" -msgstr " (useu \"git rm ...\" per a senyalar resolució)" +#: sequencer.c:850 +#, c-format +msgid "git %s: failed to refresh the index" +msgstr "git %s: s'ha fallat en actualitzar l'índex" -#: wt-status.c:198 wt-status.c:882 -msgid "Changes to be committed:" -msgstr "Canvis a cometre:" +#: sequencer.c:944 +#, c-format +msgid "invalid line %d: %.*s" +msgstr "línia no vàlida %d: %.*s" -#: wt-status.c:216 wt-status.c:891 -msgid "Changes not staged for commit:" -msgstr "Canvis no allistats per a cometre:" +#: sequencer.c:950 +msgid "no commits parsed." +msgstr "no s'ha analitzat cap comissió." -#: wt-status.c:220 -msgid " (use \"git add ...\" to update what will be committed)" -msgstr " (useu \"git add ...\" per a actualitzar què es cometrà)" +#: sequencer.c:966 +#, c-format +msgid "could not read '%s'." +msgstr "no s'ha pogut llegir '%s'." -#: wt-status.c:222 -msgid " (use \"git add/rm ...\" to update what will be committed)" -msgstr " (useu \"git add/rm ...\" per a actualitzar què es cometrà)" +#: sequencer.c:972 +#, c-format +msgid "unusable instruction sheet: '%s'" +msgstr "full d'instruccions inusable: '%s'" -#: wt-status.c:223 -msgid "" -" (use \"git checkout -- ...\" to discard changes in working directory)" -msgstr "" -" (useu \"git checkout -- ...\" per a descartar els canvis en el " -"directori de treball)" +#: sequencer.c:983 +msgid "cannot cherry-pick during a revert." +msgstr "no es pot recollir cireres durant una reversió." -#: wt-status.c:225 -msgid " (commit or discard the untracked or modified content in submodules)" -msgstr "" -" (cometeu o descarteu el contingut modificat o no seguit en els submòduls)" +#: sequencer.c:985 +msgid "cannot revert during a cherry-pick." +msgstr "no es pot revertir durant un recull de cireres." -#: wt-status.c:237 +#: sequencer.c:1028 #, c-format -msgid " (use \"git %s ...\" to include in what will be committed)" -msgstr " (useu \"git %s ...\" per a incloure-ho en què es cometrà)" - -#: wt-status.c:252 -msgid "both deleted:" -msgstr "suprimit per ambdós:" +msgid "invalid key: %s" +msgstr "clau no vàlida: %s" -#: wt-status.c:254 -msgid "added by us:" -msgstr "afegit per nosaltres:" - -#: wt-status.c:256 -msgid "deleted by them:" -msgstr "suprimit per ells:" +#: sequencer.c:1031 +#, c-format +msgid "invalid value for %s: %s" +msgstr "valor no vàlid per a %s: %s" -#: wt-status.c:258 -msgid "added by them:" -msgstr "afegit per ells:" +#: sequencer.c:1063 +#, c-format +msgid "malformed options sheet: '%s'" +msgstr "full d'opcions mal format: '%s'" -#: wt-status.c:260 -msgid "deleted by us:" -msgstr "suprimit per nosaltres:" +#: sequencer.c:1101 +msgid "a cherry-pick or revert is already in progress" +msgstr "un recull de cireres o una reversió ja està en curs" -#: wt-status.c:262 -msgid "both added:" -msgstr "afegit per ambdós:" +#: sequencer.c:1102 +msgid "try \"git cherry-pick (--continue | --quit | --abort)\"" +msgstr "intenteu \"git cherry-pick (--continue | --quit | --abort)\"" -#: wt-status.c:264 -msgid "both modified:" -msgstr "modificat per ambdós:" +#: sequencer.c:1106 +#, c-format +msgid "could not create sequencer directory '%s'" +msgstr "no s'ha pogut crear el directori de seqüenciador '%s'" -#: wt-status.c:274 -msgid "new file:" -msgstr "fitxer nou:" +#: sequencer.c:1120 +msgid "could not lock HEAD" +msgstr "no s'ha pogut bloquejar HEAD" -#: wt-status.c:276 -msgid "copied:" -msgstr "copiat:" +#: sequencer.c:1151 sequencer.c:1289 +msgid "no cherry-pick or revert in progress" +msgstr "ni hi ha cap recull de cireres ni cap reversió en curs" -#: wt-status.c:278 -msgid "deleted:" -msgstr "suprimit:" +#: sequencer.c:1153 +msgid "cannot resolve HEAD" +msgstr "no es pot resoldre HEAD" -#: wt-status.c:280 -msgid "modified:" -msgstr "modificat:" +#: sequencer.c:1155 sequencer.c:1189 +msgid "cannot abort from a branch yet to be born" +msgstr "no es pot avortar des d'una branca que encara ha de nàixer" -#: wt-status.c:282 -msgid "renamed:" -msgstr "canviat de nom:" +#: sequencer.c:1175 builtin/grep.c:578 +#, c-format +msgid "cannot open '%s'" +msgstr "no es pot obrir '%s'" -#: wt-status.c:284 -msgid "typechange:" -msgstr "canviat de tipus:" +#: sequencer.c:1177 +#, c-format +msgid "cannot read '%s': %s" +msgstr "no es pot llegir '%s': %s" -#: wt-status.c:286 -msgid "unknown:" -msgstr "desconegut:" +#: sequencer.c:1178 +msgid "unexpected end of file" +msgstr "final de fitxer inesperat" -#: wt-status.c:288 -msgid "unmerged:" -msgstr "sense fusionar:" +#: sequencer.c:1184 +#, c-format +msgid "stored pre-cherry-pick HEAD file '%s' is corrupt" +msgstr "el fitxer HEAD emmagatzemat abans del recull de cireres '%s' és malmès" -#: wt-status.c:370 -msgid "new commits, " -msgstr "comissions noves, " +#: sequencer.c:1354 +#, c-format +msgid "%s: can't cherry-pick a %s" +msgstr "%s: no es pot recollir com a cirera un %s" -#: wt-status.c:372 -msgid "modified content, " -msgstr "contingut modificat, " +#: sequencer.c:1358 +#, c-format +msgid "%s: bad revision" +msgstr "%s: revisió dolenta" -#: wt-status.c:374 -msgid "untracked content, " -msgstr "contingut no seguit, " +#: sequencer.c:1391 +msgid "can't revert as initial commit" +msgstr "no es pot revertir com a comissió inicial" -#: wt-status.c:756 -msgid "Submodules changed but not updated:" -msgstr "Submòduls canviats però no actualitzats:" +#: setup.c:160 +#, c-format +msgid "" +"%s: no such path in the working tree.\n" +"Use 'git -- ...' to specify paths that do not exist locally." +msgstr "" +"%s: no hi ha tal camí en l'arbre de treball.\n" +"Useu 'git -- ...' per a especificar camins que no existeixin " +"localment." -#: wt-status.c:758 -msgid "Submodule changes to be committed:" -msgstr "Canvis de submòdul a cometre:" +#: setup.c:173 +#, c-format +msgid "" +"ambiguous argument '%s': unknown revision or path not in the working tree.\n" +"Use '--' to separate paths from revisions, like this:\n" +"'git [...] -- [...]'" +msgstr "" +"paràmetre ambigu '%s': revisió no coneguda o camí no en l'arbre de treball.\n" +"Useu '--' per a separar els camins de les revisions, com això:\n" +"'git [...] -- [...]'" -#: wt-status.c:839 +#: setup.c:223 +#, c-format msgid "" -"Do not touch the line above.\n" -"Everything below will be removed." +"ambiguous argument '%s': both revision and filename\n" +"Use '--' to separate paths from revisions, like this:\n" +"'git [...] -- [...]'" msgstr "" -"No toqueu la línia de sobre.\n" -"Tot el que hi ha a sota s'eliminarà." +"paràmetre ambigu '%s': ambdós una revisió i un nom de fitxer\n" +"Useu '--' per a separar els camins de les revisions, com això:\n" +"'git [...] -- [...]'" -#: wt-status.c:950 -msgid "You have unmerged paths." -msgstr "Teniu camins sense fusionar." +#: setup.c:468 +#, c-format +msgid "Expected git repo version <= %d, found %d" +msgstr "S'esperava una versió de dipòsit de git <= %d, s'ha trobat %d" -#: wt-status.c:953 -msgid " (fix conflicts and run \"git commit\")" -msgstr " (arregleu els conflictes i executeu \"git commit\")" +#: setup.c:476 +msgid "unknown repository extensions found:" +msgstr "s'han trobat extensions de dipòsit desconegudes:" -#: wt-status.c:955 -msgid " (use \"git merge --abort\" to abort the merge)" -msgstr " (useu \"git merge --abort\" per a avortar la fusió)" +#: setup.c:762 +#, c-format +msgid "Not a git repository (or any of the parent directories): %s" +msgstr "No és un dipòsit de git (ni cap dels directoris pares): %s" -#: wt-status.c:960 -msgid "All conflicts fixed but you are still merging." -msgstr "Tots els conflictes estan arreglats però encara esteu fusionant." +#: setup.c:764 setup.c:915 builtin/index-pack.c:1641 +msgid "Cannot come back to cwd" +msgstr "No es pot tornar al directori de treball actual" -#: wt-status.c:963 -msgid " (use \"git commit\" to conclude merge)" -msgstr " (useu \"git commit\" per a concloure la fusió)" +#: setup.c:845 +msgid "Unable to read current working directory" +msgstr "No s'ha pogut llegir el directori de treball actual" -#: wt-status.c:973 -msgid "You are in the middle of an am session." -msgstr "Esteu enmig d'una sessió am." +#: setup.c:920 +#, c-format +msgid "" +"Not a git repository (or any parent up to mount point %s)\n" +"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)." +msgstr "" +"No un dipòsit de git (ni cap pare fins el punt de muntatge %s)\n" +"S'atura a la frontera de sistema de fitxers (GIT_DISCOVERY_ACROSS_FILESYSTEM " +"no està establert)." -#: wt-status.c:976 -msgid "The current patch is empty." -msgstr "El pedaç actual està buit." +#: setup.c:927 +#, c-format +msgid "Cannot change to '%s/..'" +msgstr "No es pot canviar a '%s/..'" -#: wt-status.c:980 -msgid " (fix conflicts and then run \"git am --continue\")" -msgstr " (arregleu els conflictes i després executeu \"git am --continue\")" +#: setup.c:989 +#, c-format +msgid "" +"Problem with core.sharedRepository filemode value (0%.3o).\n" +"The owner of files must always have read and write permissions." +msgstr "" +"Hi ha un problema amb el valor de mode de fitxer core.sharedRepository " +"(0%.3o).\n" +"El propietari dels fitxers sempre ha de tenir permissions de lectura i " +"escriptura." -#: wt-status.c:982 -msgid " (use \"git am --skip\" to skip this patch)" -msgstr " (useu \"git am --skip\" per a ometre aquest pedaç)" +#: sha1_file.c:473 +#, c-format +msgid "path '%s' does not exist" +msgstr "el camí '%s' no existeix" -#: wt-status.c:984 -msgid " (use \"git am --abort\" to restore the original branch)" -msgstr " (useu \"git am --abort\" per a restaurar la branca original)" +#: sha1_file.c:499 +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "" +"Encara no se suporta el dipòsit de referència '%s' com a agafament enllaçat." -#: wt-status.c:1109 -msgid "No commands done." -msgstr "No s'ha fet cap ordre." +#: sha1_file.c:505 +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "el dipòsit de referència '%s' no és un dipòsit local." -#: wt-status.c:1112 +#: sha1_file.c:511 #, c-format -msgid "Last command done (%d command done):" -msgid_plural "Last commands done (%d commands done):" -msgstr[0] "Última ordre feta (%d ordre feta):" -msgstr[1] "Últimes ordres fetes (%d ordres fetes):" +msgid "reference repository '%s' is shallow" +msgstr "el dipòsit de referència '%s' és superficial" -#: wt-status.c:1123 +#: sha1_file.c:519 #, c-format -msgid " (see more in file %s)" -msgstr " (vegeu més en el fitxer %s)" +msgid "reference repository '%s' is grafted" +msgstr "el dipòsit de referència '%s' és empeltat" -#: wt-status.c:1128 -msgid "No commands remaining." -msgstr "No manca cap ordre." +#: sha1_file.c:1159 +msgid "offset before end of packfile (broken .idx?)" +msgstr "desplaçament abans de la fi del fitxer de paquet (.idx trencat?)" -#: wt-status.c:1131 +#: sha1_file.c:2592 #, c-format -msgid "Next command to do (%d remaining command):" -msgid_plural "Next commands to do (%d remaining commands):" -msgstr[0] "Ordre següent a fer (manca %d ordre):" -msgstr[1] "Ordres següents a fer (manquen %d ordres):" +msgid "offset before start of pack index for %s (corrupt index?)" +msgstr "" +"desplaçament abans d'inici d'índex de paquet per a %s (índex corromput?)" -#: wt-status.c:1139 -msgid " (use \"git rebase --edit-todo\" to view and edit)" -msgstr " (useu \"git rebase --edit-todo\" per a veure i editar)" +#: sha1_file.c:2596 +#, c-format +msgid "offset beyond end of pack index for %s (truncated index?)" +msgstr "" +"desplaçament més enllà de la fi d'índex de paquet per a %s (índex truncat?)" -#: wt-status.c:1152 +#: sha1_name.c:407 #, c-format -msgid "You are currently rebasing branch '%s' on '%s'." -msgstr "Actualment esteu rebasant la branca '%s' en '%s'." +msgid "short SHA1 %s is ambiguous" +msgstr "l'SHA1 %s curt és ambigu" -#: wt-status.c:1157 -msgid "You are currently rebasing." -msgstr "Actualment esteu rebasant." +#: sha1_name.c:418 +msgid "The candidates are:" +msgstr "Els candidats són:" -#: wt-status.c:1171 -msgid " (fix conflicts and then run \"git rebase --continue\")" +#: sha1_name.c:578 +msgid "" +"Git normally never creates a ref that ends with 40 hex characters\n" +"because it will be ignored when you just specify 40-hex. These refs\n" +"may be created by mistake. For example,\n" +"\n" +" git checkout -b $br $(git rev-parse ...)\n" +"\n" +"where \"$br\" is somehow empty and a 40-hex ref is created. Please\n" +"examine these refs and maybe delete them. Turn this message off by\n" +"running \"git config advice.objectNameWarning false\"" msgstr "" -" (arregleu els conflictes i després executeu \"git rebase --continue\")" +"Git normalment mai crea una referència que acabi amb 40 caràcters\n" +"hexadecimals perquè s'ignorarà quan només especifiqueu 40 caràcters\n" +"hexadecimals. Aquestes referències es poden crear per error. Per\n" +"exemple,\n" +"\n" +" git checkout -b $br $(git rev-parse ...)\n" +"\n" +"on \"$br\" és d'alguna manera buida i una referència de 40 caràcters\n" +"hexadecimals. Si us plau, examineu aquestes referències i potser\n" +"suprimiu-les. Desactiveu aquest missatge executant\n" +"\"git config advice.objectNameWarning false\"" -#: wt-status.c:1173 -msgid " (use \"git rebase --skip\" to skip this patch)" -msgstr " (useu \"git rebase --skip\" per a saltar aquest pedaç)" +#: submodule.c:64 submodule.c:98 +msgid "Cannot change unmerged .gitmodules, resolve merge conflicts first" +msgstr "" +"No es pot canviar un .gitmodules no fusionat, primer resoldreu els " +"conflictes de fusió" -#: wt-status.c:1175 -msgid " (use \"git rebase --abort\" to check out the original branch)" -msgstr " (useu \"git rebase --abort\" per a agafar la branca original)" +#: submodule.c:68 submodule.c:102 +#, c-format +msgid "Could not find section in .gitmodules where path=%s" +msgstr "No s'ha pogut trobar la secció en .gitmodules on path=%s" -#: wt-status.c:1181 -msgid " (all conflicts fixed: run \"git rebase --continue\")" -msgstr " (tots els conflictes arreglats: executeu \"git rebase --continue\")" +#: submodule.c:76 +#, c-format +msgid "Could not update .gitmodules entry %s" +msgstr "No s'ha pogut actualitzar l'entrada de .gitmodules %s" -#: wt-status.c:1185 +#: submodule.c:109 #, c-format -msgid "" -"You are currently splitting a commit while rebasing branch '%s' on '%s'." -msgstr "" -"Actualment esteu dividint una comissió mentre rebaseu la branca '%s' en '%s'." +msgid "Could not remove .gitmodules entry for %s" +msgstr "No s'ha pogut eliminar l'entrada de .gitmodules per a %s" -#: wt-status.c:1190 -msgid "You are currently splitting a commit during a rebase." -msgstr "Actualment esteu dividint una comissió durant un rebasament." +#: submodule.c:120 +msgid "staging updated .gitmodules failed" +msgstr "l'allistament del .gitmodules actualitzat ha fallat" -#: wt-status.c:1193 -msgid " (Once your working directory is clean, run \"git rebase --continue\")" -msgstr "" -" (Una vegada que el vostre directori de treball sigui net, executeu \"git " -"rebase --continue\")" +#: submodule.c:158 +msgid "negative values not allowed for submodule.fetchJobs" +msgstr "no es permeten els valors negatius a submodule.fetchJobs" -#: wt-status.c:1197 +#: submodule-config.c:358 #, c-format -msgid "You are currently editing a commit while rebasing branch '%s' on '%s'." -msgstr "" -"Actualment esteu editant una comissió mentre rebaseu la branca '%s' en '%s'." +msgid "invalid value for %s" +msgstr "valor no vàlid per a %s" -#: wt-status.c:1202 -msgid "You are currently editing a commit during a rebase." -msgstr "Actualment esteu editant una comissió durant un rebasament." +#: trailer.c:238 +#, c-format +msgid "running trailer command '%s' failed" +msgstr "l'execució de l'ordre de remolc '%s' ha fallat" -#: wt-status.c:1205 -msgid " (use \"git commit --amend\" to amend the current commit)" -msgstr " (useu \"git commit --amend\" per a esmenar la comissió actual)" +#: trailer.c:471 trailer.c:475 trailer.c:479 trailer.c:533 trailer.c:537 +#: trailer.c:541 +#, c-format +msgid "unknown value '%s' for key '%s'" +msgstr "valor desconegut '%s' per a la clau '%s'" -#: wt-status.c:1207 -msgid "" -" (use \"git rebase --continue\" once you are satisfied with your changes)" -msgstr "" -" (useu \"git rebase --continue\" una vegada que esteu satisfet amb els " -"vostres canvis)" +#: trailer.c:523 trailer.c:528 builtin/remote.c:289 +#, c-format +msgid "more than one %s" +msgstr "més d'un %s" -#: wt-status.c:1217 +#: trailer.c:672 #, c-format -msgid "You are currently cherry-picking commit %s." -msgstr "Actualment esteu recollint com a cirera la comissió %s." +msgid "empty trailer token in trailer '%.*s'" +msgstr "fitxa de remolc buida en el remolc '%.*s'" -#: wt-status.c:1222 -msgid " (fix conflicts and run \"git cherry-pick --continue\")" -msgstr " (arregleu els conflictes i executeu \"git cherry-pick --continue\")" +#: trailer.c:695 +#, c-format +msgid "could not read input file '%s'" +msgstr "no s'ha pogut llegir el fitxer d'entrada '%s'" -#: wt-status.c:1225 -msgid " (all conflicts fixed: run \"git cherry-pick --continue\")" -msgstr "" -" (tots els conflictes arreglats: executeu \"git cherry-pick --continue\")" +#: trailer.c:698 +msgid "could not read from stdin" +msgstr "no s'ha pogut llegir des d'stdin" -#: wt-status.c:1227 -msgid " (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)" -msgstr "" -" (useu \"git cherry-pick --abort\" per a cancel·lar l'operació de recull de " -"cireres)" +#: trailer.c:929 builtin/am.c:44 +#, c-format +msgid "could not stat %s" +msgstr "no s'ha pogut fer stat a %s" -#: wt-status.c:1236 +#: trailer.c:931 #, c-format -msgid "You are currently reverting commit %s." -msgstr "Actualment esteu revertint la comissió %s." +msgid "file %s is not a regular file" +msgstr "el fitxer %s no és un fitxer regular" -#: wt-status.c:1241 -msgid " (fix conflicts and run \"git revert --continue\")" -msgstr " (arregleu els conflictes i executeu \"git revert --continue\")" +#: trailer.c:933 +#, c-format +msgid "file %s is not writable by user" +msgstr "el fitxer %s no és gravable per l'usuari" -#: wt-status.c:1244 -msgid " (all conflicts fixed: run \"git revert --continue\")" -msgstr "" -" (tots els conflictes estan arreglats: executeu \"git revert --continue\")" +#: trailer.c:945 +msgid "could not open temporary file" +msgstr "no s'ha pogut obrir el fitxer temporal" -#: wt-status.c:1246 -msgid " (use \"git revert --abort\" to cancel the revert operation)" -msgstr "" -" (useu \"git revert --abort\" per a cancel·lar l'operació de reversió)" +#: trailer.c:983 +#, c-format +msgid "could not rename temporary file to %s" +msgstr "no s'ha pogut canviar el nom del fitxer temporal a %s" -#: wt-status.c:1257 +#: transport.c:62 #, c-format -msgid "You are currently bisecting, started from branch '%s'." -msgstr "Actualment esteu bisecant, heu començat des de la branca '%s'." +msgid "Would set upstream of '%s' to '%s' of '%s'\n" +msgstr "Canviaria la font de '%s' a '%s' de '%s'\n" -#: wt-status.c:1261 -msgid "You are currently bisecting." -msgstr "Actualment esteu bisecant." +#: transport.c:151 +#, c-format +msgid "transport: invalid depth option '%s'" +msgstr "transport: opció de profunditat no vàlida '%s'" -#: wt-status.c:1264 -msgid " (use \"git bisect reset\" to get back to the original branch)" -msgstr " (useu \"git bisect reset\" per a tornar a la branca original)" +#: transport.c:817 +#, c-format +msgid "" +"The following submodule paths contain changes that can\n" +"not be found on any remote:\n" +msgstr "" +"Els camins de submòdul següents contenen canvis que no\n" +"es poden trobar en cap remot:\n" -#: wt-status.c:1464 -msgid "On branch " -msgstr "En la branca " +#: transport.c:821 +#, c-format +msgid "" +"\n" +"Please try\n" +"\n" +"\tgit push --recurse-submodules=on-demand\n" +"\n" +"or cd to the path and use\n" +"\n" +"\tgit push\n" +"\n" +"to push them to a remote.\n" +"\n" +msgstr "" +"\n" +"Si us plau, intenteu\n" +"\n" +"\tgit push --recurse-submodules=on-demand\n" +"\n" +"o canviar de directori al camí i useu\n" +"\n" +"\tgit push\n" +"\n" +"per a pujar-los a un remot.\n" -#: wt-status.c:1470 -msgid "interactive rebase in progress; onto " -msgstr "rebasament interactiu en progrés; sobre " +#: transport.c:829 +msgid "Aborting." +msgstr "S'està avortant." -#: wt-status.c:1472 -msgid "rebase in progress; onto " -msgstr "rebasament en progrés; sobre " +#: transport-helper.c:1075 +#, c-format +msgid "Could not read ref %s" +msgstr "No s'ha pogut llegir la referència %s" -#: wt-status.c:1477 -msgid "HEAD detached at " -msgstr "HEAD separat a " +#: tree-walk.c:31 +msgid "too-short tree object" +msgstr "objecte d'arbre massa curt" -#: wt-status.c:1479 -msgid "HEAD detached from " -msgstr "HEAD separat de " +#: tree-walk.c:37 +msgid "malformed mode in tree entry" +msgstr "mode mal format en entrada d'arbre" -#: wt-status.c:1482 -msgid "Not currently on any branch." -msgstr "Actualment no s'és en cap branca." +#: tree-walk.c:41 +msgid "empty filename in tree entry" +msgstr "nom de fitxer buit en entrada de arbre" -#: wt-status.c:1500 -msgid "Initial commit" -msgstr "Comissió inicial" +#: tree-walk.c:113 +msgid "too-short tree file" +msgstr "fitxer d'arbre massa curt" -#: wt-status.c:1514 -msgid "Untracked files" -msgstr "Fitxers no seguits" +#: 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 switch branches." +msgstr "" +"Els vostres canvis locals als fitxers següents se sobreescriurien per " +"agafar:\n" +"%%sSi us plau, cometeu els vostres canvis o emmagatzemeu-los abans de " +"canviar de branca." -#: wt-status.c:1516 -msgid "Ignored files" -msgstr "Fitxers ignorats" +#: unpack-trees.c:66 +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by checkout:\n" +"%%s" +msgstr "" +"Els vostres canvis locals als fitxers següents se sobreescriurien per " +"agafar:\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 merge." +msgstr "" +"Els vostres canvis locals als fitxers següents se sobreescriurien per " +"fusionar:\n" +"%%sSi us plau, cometeu els vostres canvis o emmagatzemeu-los abans de " +"fusionar." -#: wt-status.c:1520 +#: unpack-trees.c:71 #, c-format msgid "" -"It took %.2f seconds to enumerate untracked files. 'status -uno'\n" -"may speed it up, but you have to be careful not to forget to add\n" -"new files yourself (see 'git help status')." +"Your local changes to the following files would be overwritten by merge:\n" +"%%s" msgstr "" -"S'ha trigat %.2f segons a enumerar fitxers no seguits.\n" -"'status -uno' pot accelerar-ho, però heu d'anar amb compte de no\n" -"oblidar-vos d'afegir fitxers nous per vós mateix (vegeu\n" -"'git help status')." +"Els vostres canvis locals als fitxers següents se sobreescriurien per " +"fusionar:\n" +"%%s" -#: wt-status.c:1526 +#: unpack-trees.c:74 #, c-format -msgid "Untracked files not listed%s" -msgstr "Els fitxers no seguits no estan llistats%s" - -#: wt-status.c:1528 -msgid " (use -u option to show untracked files)" -msgstr " (useu l'opció -u per a mostrar els fitxers no seguits)" - -#: wt-status.c:1534 -msgid "No changes" -msgstr "Sense canvis" +msgid "" +"Your local changes to the following files would be overwritten by %s:\n" +"%%sPlease commit your changes or stash them before you %s." +msgstr "" +"Els vostres canvis locals als fitxers següents se sobreescriurien per %s:\n" +"%%sSi us plau, cometeu els vostres canvis o emmagatzemeu-los abans de %s." -#: wt-status.c:1539 +#: unpack-trees.c:76 #, c-format -msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n" +msgid "" +"Your local changes to the following files would be overwritten by %s:\n" +"%%s" msgstr "" -"no hi ha canvis afegits a cometre (useu \"git add\" o \"git commit -a\")\n" +"Els vostres canvis locals als fitxers següents se sobreescriurien per %s:\n" +"%%s" -#: wt-status.c:1542 +#: unpack-trees.c:81 #, c-format -msgid "no changes added to commit\n" -msgstr "no hi ha canvis afegits a cometre\n" +msgid "" +"Updating the following directories would lose untracked files in it:\n" +"%s" +msgstr "" +"Actualitzar els directoris següents perdria fitxers no seguits en el:\n" +"%s" -#: wt-status.c:1545 +#: unpack-trees.c:85 #, c-format msgid "" -"nothing added to commit but untracked files present (use \"git add\" to " -"track)\n" +"The following untracked working tree files would be removed by checkout:\n" +"%%sPlease move or remove them before you switch branches." msgstr "" -"no hi ha res afegit a cometre però fitxers no seguits estan presents (useu " -"\"git add\" per a seguir-los)\n" +"Els següents fitxers no seguits en l'arbre de treball s'eliminarien per " +"agafar:\n" +"%%sSi us plau, moveu-los o elimineu-los abans de canviar de branca." -#: wt-status.c:1548 +#: unpack-trees.c:87 #, c-format -msgid "nothing added to commit but untracked files present\n" -msgstr "no hi ha res afegit a cometre però fitxers no seguits estan presents\n" +msgid "" +"The following untracked working tree files would be removed by checkout:\n" +"%%s" +msgstr "" +"Els següents fitxers no seguits en l'arbre de treball s'eliminarien per " +"agafar:\n" +"%%s" -#: wt-status.c:1551 +#: unpack-trees.c:90 #, c-format -msgid "nothing to commit (create/copy files and use \"git add\" to track)\n" +msgid "" +"The following untracked working tree files would be removed by merge:\n" +"%%sPlease move or remove them before you merge." msgstr "" -"no hi ha res a cometre (creeu/copieu fitxers i useu \"git add\" per a seguir-" -"los)\n" +"Els següents fitxers no seguits en l'arbre de treball s'eliminarien per " +"fusionar:\n" +"%%sSi us plau, moveu-los o elimineu-los abans de fusionar." -#: wt-status.c:1554 wt-status.c:1559 +#: unpack-trees.c:92 #, c-format -msgid "nothing to commit\n" -msgstr "no hi ha res a cometre\n" +msgid "" +"The following untracked working tree files would be removed by merge:\n" +"%%s" +msgstr "" +"Els següents fitxers no seguits en l'arbre de treball s'eliminarien per " +"fusionar:\n" +"%%s" -#: wt-status.c:1557 +#: unpack-trees.c:95 #, c-format -msgid "nothing to commit (use -u to show untracked files)\n" +msgid "" +"The following untracked working tree files would be removed by %s:\n" +"%%sPlease move or remove them before you %s." msgstr "" -"no hi ha res a cometre (useu -u per a mostrar els fitxers no seguits)\n" +"Els següents fitxers no seguits en l'arbre de treball s'eliminarien per %s:\n" +"%%sSi us plau, moveu-los o elimineu-los abans de %s." -#: wt-status.c:1561 +#: unpack-trees.c:97 #, c-format -msgid "nothing to commit, working tree clean\n" -msgstr "no hi ha res a cometre, l'arbre de treball està net\n" - -#: wt-status.c:1668 -msgid "Initial commit on " -msgstr "Comissió inicial en " - -#: wt-status.c:1672 -msgid "HEAD (no branch)" -msgstr "HEAD (sense branca)" - -#: wt-status.c:1701 -msgid "gone" -msgstr "no hi és" - -#: wt-status.c:1703 wt-status.c:1711 -msgid "behind " -msgstr "darrere " - -#: wt-status.c:1706 wt-status.c:1709 -msgid "ahead " -msgstr "davant per " +msgid "" +"The following untracked working tree files would be removed by %s:\n" +"%%s" +msgstr "" +"Els següents fitxers no seguits en l'arbre de treball s'eliminarien per %s:\n" +"%%s" -#: compat/precompose_utf8.c:57 builtin/clone.c:415 +#: unpack-trees.c:102 #, c-format -msgid "failed to unlink '%s'" -msgstr "s'ha fallat en desenllaçar '%s'" - -#: builtin/add.c:22 -msgid "git add [] [--] ..." -msgstr "git add [] [--] ..." +msgid "" +"The following untracked working tree files would be overwritten by " +"checkout:\n" +"%%sPlease move or remove them before you switch branches." +msgstr "" +"Els següents fitxers no seguits en l'arbre de treball se sobreescriurien per " +"agafar:\n" +"%%sSi us plau, moveu-los o elimineu-los abans de canviar de branca." -#: builtin/add.c:65 +#: unpack-trees.c:104 #, c-format -msgid "unexpected diff status %c" -msgstr "estat de diff inesperat %c" - -#: builtin/add.c:71 builtin/commit.c:281 -msgid "updating files failed" -msgstr "s'ha fallat en actualitzar els fitxers" +msgid "" +"The following untracked working tree files would be overwritten by " +"checkout:\n" +"%%s" +msgstr "" +"Els següents fitxers no seguits en l'arbre de treball se sobreescriurien per " +"agafar:\n" +"%%s" -#: builtin/add.c:81 +#: unpack-trees.c:107 #, c-format -msgid "remove '%s'\n" -msgstr "elimina '%s'\n" +msgid "" +"The following untracked working tree files would be overwritten by merge:\n" +"%%sPlease move or remove them before you merge." +msgstr "" +"Els següents fitxers no seguits en l'arbre de treball se sobreescriurien per " +"fusionar:\n" +"%%sSi us plau, moveu-los o elimineu-los abans de fusionar." -#: builtin/add.c:136 -msgid "Unstaged changes after refreshing the index:" -msgstr "Canvis no allistats després d'actualitzar l'índex:" +#: unpack-trees.c:109 +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by merge:\n" +"%%s" +msgstr "" +"Els següents fitxers no seguits en l'arbre de treball se sobreescriurien per " +"fusionar:\n" +"%%s" -#: builtin/add.c:196 builtin/rev-parse.c:811 -msgid "Could not read the index" -msgstr "No s'ha pogut llegir l'índex" +#: 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 %s." +msgstr "" +"Els següents fitxers no seguits en l'arbre de treball se sobreescriurien per " +"%s:\n" +"%%sSi us plau, moveu-los o elimineu-los abans de %s." -#: builtin/add.c:207 +#: unpack-trees.c:114 #, c-format -msgid "Could not open '%s' for writing." -msgstr "No s'ha pogut obrir '%s' per a escriptura." +msgid "" +"The following untracked working tree files would be overwritten by %s:\n" +"%%s" +msgstr "" +"Els següents fitxers no seguits en l'arbre de treball se sobreescriurien per " +"%s:\n" +"%%s" -#: builtin/add.c:211 -msgid "Could not write patch" -msgstr "No s'ha pogut escriure el pedaç" +#: unpack-trees.c:121 +#, c-format +msgid "Entry '%s' overlaps with '%s'. Cannot bind." +msgstr "L'entrada '%s' encavalca amb '%s'. No es pot vincular." -#: builtin/add.c:214 -msgid "editing patch failed" -msgstr "l'edició del pedaç ha fallat" +#: unpack-trees.c:124 +#, c-format +msgid "" +"Cannot update sparse checkout: the following entries are not up-to-date:\n" +"%s" +msgstr "" +"No es pot actualitzar l'agafament parcial: les entrades següents no estan al " +"dia:\n" +"%s" -#: builtin/add.c:217 +#: unpack-trees.c:126 #, c-format -msgid "Could not stat '%s'" -msgstr "No s'ha pogut fer stat a '%s'" +msgid "" +"The following working tree files would be overwritten by sparse checkout " +"update:\n" +"%s" +msgstr "" +"Els fitxers següents en l'arbre de treball se sobreescriurien per " +"actualitzar l'agafament parcial:\n" +"%s" -#: builtin/add.c:219 -msgid "Empty patch. Aborted." -msgstr "El pedaç és buit. S'ha avortat." +#: unpack-trees.c:128 +#, c-format +msgid "" +"The following working tree files would be removed by sparse checkout " +"update:\n" +"%s" +msgstr "" +"Els fitxers següents en l'arbre de treball s'eliminarien per actualitzar " +"l'agafament parcial:\n" +"%s" -#: builtin/add.c:224 +#: unpack-trees.c:205 #, c-format -msgid "Could not apply '%s'" -msgstr "No s'ha pogut aplicar '%s'" +msgid "Aborting\n" +msgstr "S'està avortant\n" -#: builtin/add.c:234 -msgid "The following paths are ignored by one of your .gitignore files:\n" -msgstr "" -"Els camins següents s'ignoren per un dels vostres fitxers .gitignore:\n" +#: unpack-trees.c:237 +msgid "Checking out files" +msgstr "S'està agafant fitxers" -#: builtin/add.c:253 builtin/clean.c:870 builtin/fetch.c:113 builtin/mv.c:111 -#: builtin/prune-packed.c:55 builtin/pull.c:197 builtin/push.c:521 -#: builtin/remote.c:1327 builtin/rm.c:268 builtin/send-pack.c:162 -msgid "dry run" -msgstr "marxa en sec" +#: urlmatch.c:120 +msgid "invalid URL scheme name or missing '://' suffix" +msgstr "l'esquema d'URL no és vàlid o li manca el sufix '://'" -#: builtin/add.c:254 builtin/apply.c:4854 builtin/check-ignore.c:19 -#: builtin/commit.c:1334 builtin/count-objects.c:85 builtin/fsck.c:593 -#: builtin/log.c:1852 builtin/mv.c:110 builtin/read-tree.c:114 -msgid "be verbose" -msgstr "sigues detallat" +#: urlmatch.c:144 urlmatch.c:297 urlmatch.c:356 +#, c-format +msgid "invalid %XX escape sequence" +msgstr "seqüència d'escapament %XX no vàlida" + +#: urlmatch.c:172 +msgid "missing host and scheme is not 'file:'" +msgstr "manca la màquina i l'esquema no és 'file:'" -#: builtin/add.c:256 -msgid "interactive picking" -msgstr "recull interactiu" +#: urlmatch.c:189 +msgid "a 'file:' URL may not have a port number" +msgstr "un URL 'file:' no pot tenir número de port" -#: builtin/add.c:257 builtin/checkout.c:1157 builtin/reset.c:286 -msgid "select hunks interactively" -msgstr "selecciona els trossos interactivament" +#: urlmatch.c:199 +msgid "invalid characters in host name" +msgstr "hi ha caràcters no vàlids en el nom de màquina" -#: builtin/add.c:258 -msgid "edit current diff and apply" -msgstr "edita la diferència actual i aplica-la" +#: urlmatch.c:244 urlmatch.c:255 +msgid "invalid port number" +msgstr "número de port no vàlid" -#: builtin/add.c:259 -msgid "allow adding otherwise ignored files" -msgstr "permet afegir fitxers que d'altra manera s'ignoren" +#: urlmatch.c:322 +msgid "invalid '..' path segment" +msgstr "segment de camí '..' no vàlid" -#: builtin/add.c:260 -msgid "update tracked files" -msgstr "actualitza els fitxers seguits" +#: worktree.c:282 +#, c-format +msgid "failed to read '%s'" +msgstr "s'ha fallat en llegir '%s'" -#: builtin/add.c:261 -msgid "record only the fact that the path will be added later" -msgstr "registra només el fet que el camí s'afegirà més tard" +#: wrapper.c:222 wrapper.c:392 +#, c-format +msgid "could not open '%s' for reading and writing" +msgstr "no s'ha pogut obrir '%s' per a lectura i escriptura" -#: builtin/add.c:262 -msgid "add changes from all tracked and untracked files" -msgstr "afegeix els canvis de tots els fitxers seguits i no seguits" +#: wrapper.c:224 wrapper.c:394 builtin/am.c:766 +#, c-format +msgid "could not open '%s' for writing" +msgstr "no s'ha pogut obrir '%s' per a escriptura" -#: builtin/add.c:265 -msgid "ignore paths removed in the working tree (same as --no-all)" -msgstr "" -"ignora els camins eliminats en l'arbre de treball (el mateix que --no-all)" +#: wrapper.c:226 wrapper.c:396 builtin/am.c:320 builtin/am.c:759 +#: builtin/am.c:847 builtin/commit.c:1705 builtin/merge.c:1029 +#: builtin/pull.c:341 +#, c-format +msgid "could not open '%s' for reading" +msgstr "no s'ha pogut obrir '%s' per a lectura" -#: builtin/add.c:267 -msgid "don't add, only refresh the index" -msgstr "no afegeixis, només actualitza l'índex" +#: wrapper.c:605 wrapper.c:626 +#, c-format +msgid "unable to access '%s'" +msgstr "no s'ha pogut accedir a '%s'" -#: builtin/add.c:268 -msgid "just skip files which cannot be added because of errors" -msgstr "només omet els fitxers que no es poden afegir a causa d'errors" +#: wrapper.c:634 +msgid "unable to get current working directory" +msgstr "no s'ha pogut obtenir el directori de treball actual" -#: builtin/add.c:269 -msgid "check if - even missing - files are ignored in dry run" -msgstr "" -"comproveu si els fitxers - fins i tot els absents - s'ignoren en marxa en sec" +#: wrapper.c:658 +#, c-format +msgid "could not write to %s" +msgstr "no s'ha pogut escriure a %s" -#: builtin/add.c:270 builtin/update-index.c:958 -msgid "(+/-)x" -msgstr "(+/-)x" +#: wrapper.c:660 +#, c-format +msgid "could not close %s" +msgstr "no s'ha pogut tancar %s" -#: builtin/add.c:270 builtin/update-index.c:959 -msgid "override the executable bit of the listed files" -msgstr "passa per alt el bit executable dels fitxers llistats" +#: wt-status.c:151 +msgid "Unmerged paths:" +msgstr "Camins sense fusionar:" -#: builtin/add.c:292 +#: wt-status.c:178 wt-status.c:205 #, c-format -msgid "Use -f if you really want to add them.\n" -msgstr "Useu -f si realment els voleu afegir.\n" +msgid " (use \"git reset %s ...\" to unstage)" +msgstr " (useu \"git reset %s ...\" per a desallistar)" -#: builtin/add.c:300 -msgid "adding files failed" -msgstr "l'afegiment de fitxers ha fallat" +#: wt-status.c:180 wt-status.c:207 +msgid " (use \"git rm --cached ...\" to unstage)" +msgstr " (useu \"git rm --cached ...\" per a desallistar)" -#: builtin/add.c:336 -msgid "-A and -u are mutually incompatible" -msgstr "-A i -u són mutualment incompatibles" +#: wt-status.c:184 +msgid " (use \"git add ...\" to mark resolution)" +msgstr " (useu \"git add ...\" per a senyalar resolució)" -#: builtin/add.c:343 -msgid "Option --ignore-missing can only be used together with --dry-run" -msgstr "L'opció --ignore-missing només es pot usar junt amb --dry-run" +#: wt-status.c:186 wt-status.c:190 +msgid " (use \"git add/rm ...\" as appropriate to mark resolution)" +msgstr "" +" (useu \"git add/rm ...\" segons sigui apropiat per a senyalar " +"resolució)" -#: builtin/add.c:352 -#, c-format -msgid "--chmod param '%s' must be either -x or +x" -msgstr "el paràmetre --chmod '%s' ha de ser o -x o +x" +#: wt-status.c:188 +msgid " (use \"git rm ...\" to mark resolution)" +msgstr " (useu \"git rm ...\" per a senyalar resolució)" -#: builtin/add.c:367 -#, c-format -msgid "Nothing specified, nothing added.\n" -msgstr "No s'ha especificat res, no s'ha afegit res.\n" +#: wt-status.c:199 wt-status.c:945 +msgid "Changes to be committed:" +msgstr "Canvis a cometre:" -#: builtin/add.c:368 -#, c-format -msgid "Maybe you wanted to say 'git add .'?\n" -msgstr "Potser volíeu dir 'git add .'?\n" +#: wt-status.c:217 wt-status.c:954 +msgid "Changes not staged for commit:" +msgstr "Canvis no allistats per a cometre:" -#: builtin/add.c:373 builtin/check-ignore.c:172 builtin/checkout.c:279 -#: builtin/checkout.c:473 builtin/clean.c:914 builtin/commit.c:340 -#: builtin/mv.c:131 builtin/reset.c:235 builtin/rm.c:298 -#: builtin/submodule--helper.c:240 -msgid "index file corrupt" -msgstr "fitxer d'índex malmès" +#: wt-status.c:221 +msgid " (use \"git add ...\" to update what will be committed)" +msgstr " (useu \"git add ...\" per a actualitzar què es cometrà)" -#: builtin/add.c:454 builtin/apply.c:4784 builtin/mv.c:286 builtin/rm.c:431 -msgid "Unable to write new index file" -msgstr "no s'ha pogut escriure un fitxer d'índex nou" +#: wt-status.c:223 +msgid " (use \"git add/rm ...\" to update what will be committed)" +msgstr " (useu \"git add/rm ...\" per a actualitzar què es cometrà)" -#: builtin/am.c:257 builtin/commit.c:750 builtin/merge.c:1032 -#, c-format -msgid "could not read '%s'" -msgstr "no s'ha pogut llegir '%s'" +#: wt-status.c:224 +msgid "" +" (use \"git checkout -- ...\" to discard changes in working directory)" +msgstr "" +" (useu \"git checkout -- ...\" per a descartar els canvis en el " +"directori de treball)" -#: builtin/am.c:426 -msgid "could not parse author script" -msgstr "no s'ha pogut analitzar l'script d'autor" +#: wt-status.c:226 +msgid " (commit or discard the untracked or modified content in submodules)" +msgstr "" +" (cometeu o descarteu el contingut modificat o no seguit en els submòduls)" -#: builtin/am.c:503 +#: wt-status.c:238 #, c-format -msgid "'%s' was deleted by the applypatch-msg hook" -msgstr "s'ha suprimit '%s' pel ganxo applypatch-msg" +msgid " (use \"git %s ...\" to include in what will be committed)" +msgstr " (useu \"git %s ...\" per a incloure-ho en què es cometrà)" -#: builtin/am.c:544 builtin/notes.c:301 -#, c-format -msgid "Malformed input line: '%s'." -msgstr "Línia d'entrada mal formada: '%s'." +#: wt-status.c:253 +msgid "both deleted:" +msgstr "suprimit per ambdós:" -#: builtin/am.c:581 builtin/notes.c:316 -#, c-format -msgid "Failed to copy notes from '%s' to '%s'" -msgstr "S'ha fallat en copiar les notes de '%s' a '%s'" +#: wt-status.c:255 +msgid "added by us:" +msgstr "afegit per nosaltres:" -#: builtin/am.c:607 -msgid "fseek failed" -msgstr "fseek ha fallat" +#: wt-status.c:257 +msgid "deleted by them:" +msgstr "suprimit per ells:" -#: builtin/am.c:787 -#, c-format -msgid "could not parse patch '%s'" -msgstr "no s'ha pogut analitzar el pedaç '%s'" +#: wt-status.c:259 +msgid "added by them:" +msgstr "afegit per ells:" -#: builtin/am.c:852 -msgid "Only one StGIT patch series can be applied at once" -msgstr "només una sèrie de pedaços StGIT es pot aplicar a la vegada" +#: wt-status.c:261 +msgid "deleted by us:" +msgstr "suprimit per nosaltres:" -#: builtin/am.c:899 -msgid "invalid timestamp" -msgstr "marca de temps no vàlida" +#: wt-status.c:263 +msgid "both added:" +msgstr "afegit per ambdós:" -#: builtin/am.c:902 builtin/am.c:910 -msgid "invalid Date line" -msgstr "línia Date no vàlida" +#: wt-status.c:265 +msgid "both modified:" +msgstr "modificat per ambdós:" -#: builtin/am.c:907 -msgid "invalid timezone offset" -msgstr "desplaçament de zona de temps no vàlid" +#: wt-status.c:275 +msgid "new file:" +msgstr "fitxer nou:" -#: builtin/am.c:996 -msgid "Patch format detection failed." -msgstr "La detecció de format de pedaç ha fallat." +#: wt-status.c:277 +msgid "copied:" +msgstr "copiat:" -#: builtin/am.c:1001 builtin/clone.c:380 -#, c-format -msgid "failed to create directory '%s'" -msgstr "s'ha fallat en crear el directori '%s'" +#: wt-status.c:279 +msgid "deleted:" +msgstr "suprimit:" -#: builtin/am.c:1005 -msgid "Failed to split patches." -msgstr "S'ha fallat en dividir els pedaços." +#: wt-status.c:281 +msgid "modified:" +msgstr "modificat:" -#: builtin/am.c:1137 builtin/commit.c:366 -msgid "unable to write index file" -msgstr "no s'ha pogut escriure el fitxer d'índex" +#: wt-status.c:283 +msgid "renamed:" +msgstr "canviat de nom:" -#: builtin/am.c:1188 -#, c-format -msgid "When you have resolved this problem, run \"%s --continue\"." -msgstr "Quan hàgiu resolt aquest problema, executeu \"%s --continue\"." +#: wt-status.c:285 +msgid "typechange:" +msgstr "canviat de tipus:" -#: builtin/am.c:1189 -#, c-format -msgid "If you prefer to skip this patch, run \"%s --skip\" instead." -msgstr "" -"Si preferiu saltar aquest pedaç, executeu \"%s --skip\" en lloc d'això." +#: wt-status.c:287 +msgid "unknown:" +msgstr "desconegut:" -#: builtin/am.c:1190 -#, c-format -msgid "To restore the original branch and stop patching, run \"%s --abort\"." -msgstr "" -"Per a restaurar la branca original i deixar d'apedaçar, executeu \"%s --abort" -"\"." +#: wt-status.c:289 +msgid "unmerged:" +msgstr "sense fusionar:" -#: builtin/am.c:1328 -msgid "Patch is empty. Was it split wrong?" -msgstr "El pedaç és buit. S'ha dividit malament?" +#: wt-status.c:371 +msgid "new commits, " +msgstr "comissions noves, " -#: builtin/am.c:1402 builtin/log.c:1543 -#, c-format -msgid "invalid ident line: %s" -msgstr "línia d'identitat no vàlida: %s" +#: wt-status.c:373 +msgid "modified content, " +msgstr "contingut modificat, " -#: builtin/am.c:1429 -#, c-format -msgid "unable to parse commit %s" -msgstr "no s'ha pogut analitzar la comissió %s" +#: wt-status.c:375 +msgid "untracked content, " +msgstr "contingut no seguit, " -#: builtin/am.c:1602 -msgid "Repository lacks necessary blobs to fall back on 3-way merge." -msgstr "" -"Al dipòsit li manquen els blobs necessaris per a retrocedir a una fusió de 3 " -"vies." +#: wt-status.c:818 +msgid "Submodules changed but not updated:" +msgstr "Submòduls canviats però no actualitzats:" -#: builtin/am.c:1604 -msgid "Using index info to reconstruct a base tree..." -msgstr "S'està usant la informació d'índex per a reconstruir un arbre base..." +#: wt-status.c:820 +msgid "Submodule changes to be committed:" +msgstr "Canvis de submòdul a cometre:" -#: builtin/am.c:1623 +#: wt-status.c:901 msgid "" -"Did you hand edit your patch?\n" -"It does not apply to blobs recorded in its index." +"Do not touch the line above.\n" +"Everything below will be removed." msgstr "" -"Heu editat el vostre pedaç a mà?\n" -"No s'aplica als blobs recordats en el seu índex." +"No toqueu la línia a dalt.\n" +"Tot el que hi ha a sota s'eliminarà." -#: builtin/am.c:1629 -msgid "Falling back to patching base and 3-way merge..." -msgstr "S'està retrocedint a apedaçar la base i fusionar de 3 vies..." +#: wt-status.c:1013 +msgid "You have unmerged paths." +msgstr "Teniu camins sense fusionar." -#: builtin/am.c:1654 -msgid "Failed to merge in the changes." -msgstr "S'ha fallat en fusionar els canvis." +#: wt-status.c:1016 +msgid " (fix conflicts and run \"git commit\")" +msgstr " (arregleu els conflictes i executeu \"git commit\")" -#: builtin/am.c:1679 builtin/merge.c:628 -msgid "git write-tree failed to write a tree" -msgstr "git write-tree ha fallat en escriure un arbre" +#: wt-status.c:1018 +msgid " (use \"git merge --abort\" to abort the merge)" +msgstr " (useu \"git merge --abort\" per a avortar la fusió)" -#: builtin/am.c:1686 -msgid "applying to an empty history" -msgstr "s'està aplicant a una història buida" +#: wt-status.c:1023 +msgid "All conflicts fixed but you are still merging." +msgstr "Tots els conflictes estan arreglats però encara esteu fusionant." + +#: wt-status.c:1026 +msgid " (use \"git commit\" to conclude merge)" +msgstr " (useu \"git commit\" per a concloure la fusió)" + +#: wt-status.c:1036 +msgid "You are in the middle of an am session." +msgstr "Esteu enmig d'una sessió am." -#: builtin/am.c:1699 builtin/commit.c:1776 builtin/merge.c:798 -#: builtin/merge.c:823 -msgid "failed to write commit object" -msgstr "s'ha fallat en escriure l'objecte de comissió" +#: wt-status.c:1039 +msgid "The current patch is empty." +msgstr "El pedaç actual està buit." -#: builtin/am.c:1731 builtin/am.c:1735 -#, c-format -msgid "cannot resume: %s does not exist." -msgstr "no es pot reprendre: %s no existeix." +#: wt-status.c:1043 +msgid " (fix conflicts and then run \"git am --continue\")" +msgstr " (arregleu els conflictes i després executeu \"git am --continue\")" -#: builtin/am.c:1751 -msgid "cannot be interactive without stdin connected to a terminal." -msgstr "" -"no es pot ser interactiu sense que stdin sigui connectat a un terminal." +#: wt-status.c:1045 +msgid " (use \"git am --skip\" to skip this patch)" +msgstr " (useu \"git am --skip\" per a ometre aquest pedaç)" -#: builtin/am.c:1756 -msgid "Commit Body is:" -msgstr "El cos de la comissió és:" +#: wt-status.c:1047 +msgid " (use \"git am --abort\" to restore the original branch)" +msgstr " (useu \"git am --abort\" per a restaurar la branca original)" -#. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a] -#. in your translation. The program will only accept English -#. input at this point. -#. -#: builtin/am.c:1766 -msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: " -msgstr "" -"Voleu aplicar-lo? [y]es/[n]o/[e]dita/[v]isualitza el pedaç/[a]ccepta'ls " -"tots: " +#: wt-status.c:1172 +msgid "No commands done." +msgstr "No s'ha fet cap ordre." -#: builtin/am.c:1816 +#: wt-status.c:1175 #, c-format -msgid "Dirty index: cannot apply patches (dirty: %s)" -msgstr "Índex brut: no es pot aplicar pedaços (bruts: %s)" +msgid "Last command done (%d command done):" +msgid_plural "Last commands done (%d commands done):" +msgstr[0] "Última ordre feta (%d ordre feta):" +msgstr[1] "Últimes ordres fetes (%d ordres fetes):" -#: builtin/am.c:1853 builtin/am.c:1925 +#: wt-status.c:1186 #, c-format -msgid "Applying: %.*s" -msgstr "S'està aplicant: %.*s" +msgid " (see more in file %s)" +msgstr " (vegeu més en el fitxer %s)" -#: builtin/am.c:1869 -msgid "No changes -- Patch already applied." -msgstr "Sense canvis -- El pedaç ja s'ha aplicat." +#: wt-status.c:1191 +msgid "No commands remaining." +msgstr "No manca cap ordre." -#: builtin/am.c:1877 +#: wt-status.c:1194 #, c-format -msgid "Patch failed at %s %.*s" -msgstr "El pedaç ha fallat a %s %.*s" +msgid "Next command to do (%d remaining command):" +msgid_plural "Next commands to do (%d remaining commands):" +msgstr[0] "Ordre següent a fer (manca %d ordre):" +msgstr[1] "Ordres següents a fer (manquen %d ordres):" + +#: wt-status.c:1202 +msgid " (use \"git rebase --edit-todo\" to view and edit)" +msgstr " (useu \"git rebase --edit-todo\" per a veure i editar)" -#: builtin/am.c:1883 +#: wt-status.c:1215 #, c-format -msgid "The copy of the patch that failed is found in: %s" -msgstr "La còpia del pedaç que ha fallat es troba en: %s" +msgid "You are currently rebasing branch '%s' on '%s'." +msgstr "Actualment esteu rebasant la branca '%s' en '%s'." -#: builtin/am.c:1928 -msgid "" -"No changes - did you forget to use 'git add'?\n" -"If there is nothing left to stage, chances are that something else\n" -"already introduced the same changes; you might want to skip this patch." -msgstr "" -"Cap canvi - heu oblidat d'usar 'git add'?\n" -"Si no hi ha res a allistar, probablement alguna altra cosa\n" -"ja ha introduït els mateixos canvis; potser voleu ometre aquest pedaç." +#: wt-status.c:1220 +msgid "You are currently rebasing." +msgstr "Actualment esteu rebasant." -#: builtin/am.c:1935 -msgid "" -"You still have unmerged paths in your index.\n" -"Did you forget to use 'git add'?" +#: wt-status.c:1234 +msgid " (fix conflicts and then run \"git rebase --continue\")" msgstr "" -"Encara teniu camins sense fusionar en el vostre índex.\n" -"Heu oblidat d'usar 'git add'?" +" (arregleu els conflictes i després executeu \"git rebase --continue\")" -#: builtin/am.c:2043 builtin/am.c:2047 builtin/am.c:2059 builtin/reset.c:308 -#: builtin/reset.c:316 -#, c-format -msgid "Could not parse object '%s'." -msgstr "No s'ha pogut analitzar l'objecte '%s'." +#: wt-status.c:1236 +msgid " (use \"git rebase --skip\" to skip this patch)" +msgstr " (useu \"git rebase --skip\" per a saltar aquest pedaç)" -#: builtin/am.c:2095 -msgid "failed to clean index" -msgstr "s'ha fallat en netejar l'índex" +#: wt-status.c:1238 +msgid " (use \"git rebase --abort\" to check out the original branch)" +msgstr " (useu \"git rebase --abort\" per a agafar la branca original)" -#: builtin/am.c:2129 -msgid "" -"You seem to have moved HEAD since the last 'am' failure.\n" -"Not rewinding to ORIG_HEAD" +#: wt-status.c:1244 +msgid " (all conflicts fixed: run \"git rebase --continue\")" msgstr "" -"Sembla que heu mogut HEAD després de l'última fallada de 'am'.\n" -"No rebobinant a ORIG_HEAD" +" (tots els conflictes estan arreglats: executeu \"git rebase --continue\")" -#: builtin/am.c:2192 +#: wt-status.c:1248 #, c-format -msgid "Invalid value for --patch-format: %s" -msgstr "Valor no vàlid per a --patch-format: %s" - -#: builtin/am.c:2225 -msgid "git am [] [(|)...]" -msgstr "git am [] [(|)...]" - -#: builtin/am.c:2226 -msgid "git am [] (--continue | --skip | --abort)" -msgstr "git am [] (--continue | --skip | --abort)" - -#: builtin/am.c:2232 -msgid "run interactively" -msgstr "executa interactivament" - -#: builtin/am.c:2234 -msgid "historical option -- no-op" -msgstr "opció històrica -- no-op" - -#: builtin/am.c:2236 -msgid "allow fall back on 3way merging if needed" -msgstr "permet retrocedir a una fusió de 3 vies si és necessari" - -#: builtin/am.c:2237 builtin/init-db.c:481 builtin/prune-packed.c:57 -#: builtin/repack.c:172 -msgid "be quiet" -msgstr "calla" - -#: builtin/am.c:2239 -msgid "add a Signed-off-by line to the commit message" -msgstr "afegeix una línia Signed-off-by al missatge de comissió" +msgid "" +"You are currently splitting a commit while rebasing branch '%s' on '%s'." +msgstr "" +"Actualment esteu dividint una comissió mentre rebaseu la branca '%s' en '%s'." -#: builtin/am.c:2242 -msgid "recode into utf8 (default)" -msgstr "recodifica en utf8 (per defecte)" +#: wt-status.c:1253 +msgid "You are currently splitting a commit during a rebase." +msgstr "Actualment esteu dividint una comissió durant un rebasament." -#: builtin/am.c:2244 -msgid "pass -k flag to git-mailinfo" -msgstr "passa la bandera -k al git-mailinfo" +#: wt-status.c:1256 +msgid " (Once your working directory is clean, run \"git rebase --continue\")" +msgstr "" +" (Una vegada que el vostre directori de treball sigui net, executeu \"git " +"rebase --continue\")" -#: builtin/am.c:2246 -msgid "pass -b flag to git-mailinfo" -msgstr "passa la bandera -b al git-mailinfo" +#: wt-status.c:1260 +#, c-format +msgid "You are currently editing a commit while rebasing branch '%s' on '%s'." +msgstr "" +"Actualment esteu editant una comissió mentre rebaseu la branca '%s' en '%s'." -#: builtin/am.c:2248 -msgid "pass -m flag to git-mailinfo" -msgstr "passa la bandera -m al git-mailinfo" +#: wt-status.c:1265 +msgid "You are currently editing a commit during a rebase." +msgstr "Actualment esteu editant una comissió durant un rebasament." -#: builtin/am.c:2250 -msgid "pass --keep-cr flag to git-mailsplit for mbox format" -msgstr "passa la bandera --keep-cr al git-mailsplit pel format mbox" +#: wt-status.c:1268 +msgid " (use \"git commit --amend\" to amend the current commit)" +msgstr " (useu \"git commit --amend\" per a esmenar la comissió actual)" -#: builtin/am.c:2253 -msgid "do not pass --keep-cr flag to git-mailsplit independent of am.keepcr" +#: wt-status.c:1270 +msgid "" +" (use \"git rebase --continue\" once you are satisfied with your changes)" msgstr "" -"no passis la bandera --keep-cr al git-mailsplit independent de am.keepcr" - -#: builtin/am.c:2256 -msgid "strip everything before a scissors line" -msgstr "despulla tot abans d'una línia de tissores" - -#: builtin/am.c:2257 builtin/apply.c:4837 -msgid "action" -msgstr "acció" +" (useu \"git rebase --continue\" una vegada que estigueu satisfet amb els " +"vostres canvis)" -#: builtin/am.c:2258 builtin/am.c:2261 builtin/am.c:2264 builtin/am.c:2267 -#: builtin/am.c:2270 builtin/am.c:2273 builtin/am.c:2276 builtin/am.c:2279 -#: builtin/am.c:2285 -msgid "pass it through git-apply" -msgstr "passa-ho a través del git-apply" +#: wt-status.c:1280 +#, c-format +msgid "You are currently cherry-picking commit %s." +msgstr "Actualment esteu recollint com a cirera la comissió %s." -#: builtin/am.c:2266 builtin/apply.c:4861 -msgid "root" -msgstr "arrel" +#: wt-status.c:1285 +msgid " (fix conflicts and run \"git cherry-pick --continue\")" +msgstr " (arregleu els conflictes i executeu \"git cherry-pick --continue\")" -#: builtin/am.c:2269 builtin/am.c:2272 builtin/apply.c:4799 -#: builtin/apply.c:4802 builtin/clone.c:90 builtin/fetch.c:96 -#: builtin/pull.c:179 builtin/submodule--helper.c:277 -#: builtin/submodule--helper.c:402 builtin/submodule--helper.c:482 -#: builtin/submodule--helper.c:485 builtin/submodule--helper.c:823 -#: builtin/submodule--helper.c:826 -msgid "path" -msgstr "camí" +#: wt-status.c:1288 +msgid " (all conflicts fixed: run \"git cherry-pick --continue\")" +msgstr "" +" (tots els conflictes estan arreglats: executeu \"git cherry-pick --continue" +"\")" -#: builtin/am.c:2275 builtin/fmt-merge-msg.c:666 builtin/fmt-merge-msg.c:669 -#: builtin/grep.c:706 builtin/merge.c:200 builtin/pull.c:134 builtin/pull.c:193 -#: builtin/repack.c:181 builtin/repack.c:185 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 "n" +#: wt-status.c:1290 +msgid " (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)" +msgstr "" +" (useu \"git cherry-pick --abort\" per a cancel·lar l'operació de recull de " +"cireres)" -#: builtin/am.c:2278 builtin/apply.c:4805 -msgid "num" -msgstr "número" +#: wt-status.c:1299 +#, c-format +msgid "You are currently reverting commit %s." +msgstr "Actualment esteu revertint la comissió %s." -#: builtin/am.c:2281 builtin/for-each-ref.c:37 builtin/replace.c:438 -#: builtin/tag.c:372 -msgid "format" -msgstr "format" +#: wt-status.c:1304 +msgid " (fix conflicts and run \"git revert --continue\")" +msgstr " (arregleu els conflictes i executeu \"git revert --continue\")" -#: builtin/am.c:2282 -msgid "format the patch(es) are in" -msgstr "el format en el qual estan els pedaços" +#: wt-status.c:1307 +msgid " (all conflicts fixed: run \"git revert --continue\")" +msgstr "" +" (tots els conflictes estan arreglats: executeu \"git revert --continue\")" -#: builtin/am.c:2288 -msgid "override error message when patch failure occurs" +#: wt-status.c:1309 +msgid " (use \"git revert --abort\" to cancel the revert operation)" msgstr "" -"passa per alt el missatge d'error quan s'ocorre una fallada en apedaçar" +" (useu \"git revert --abort\" per a cancel·lar l'operació de reversió)" -#: builtin/am.c:2290 -msgid "continue applying patches after resolving a conflict" -msgstr "segueix aplicant pedaços després de resoldre un conflicte" +#: wt-status.c:1320 +#, c-format +msgid "You are currently bisecting, started from branch '%s'." +msgstr "Actualment esteu bisecant, heu començat des de la branca '%s'." -#: builtin/am.c:2293 -msgid "synonyms for --continue" -msgstr "sinònims de --continue" +#: wt-status.c:1324 +msgid "You are currently bisecting." +msgstr "Actualment esteu bisecant." -#: builtin/am.c:2296 -msgid "skip the current patch" -msgstr "salta el pedaç actual" +#: wt-status.c:1327 +msgid " (use \"git bisect reset\" to get back to the original branch)" +msgstr " (useu \"git bisect reset\" per a tornar a la branca original)" -#: builtin/am.c:2299 -msgid "restore the original branch and abort the patching operation." -msgstr "restaura la branca original i avorta l'operació d'apedaçament." +#: wt-status.c:1524 +msgid "On branch " +msgstr "En la branca " -#: builtin/am.c:2303 -msgid "lie about committer date" -msgstr "menteix sobre la data del comitent" +#: wt-status.c:1530 +msgid "interactive rebase in progress; onto " +msgstr "rebasament interactiu en progrés; sobre " -#: builtin/am.c:2305 -msgid "use current timestamp for author date" -msgstr "usa el marc de temps actual per la data d'autor" +#: wt-status.c:1532 +msgid "rebase in progress; onto " +msgstr "rebasament en progrés; sobre " -#: builtin/am.c:2307 builtin/commit.c:1610 builtin/merge.c:229 -#: builtin/pull.c:164 builtin/revert.c:92 builtin/tag.c:355 -msgid "key-id" -msgstr "ID de clau" +#: wt-status.c:1537 +msgid "HEAD detached at " +msgstr "HEAD separat a " -#: builtin/am.c:2308 -msgid "GPG-sign commits" -msgstr "signa les comissions amb GPG" +#: wt-status.c:1539 +msgid "HEAD detached from " +msgstr "HEAD separat de " -#: builtin/am.c:2311 -msgid "(internal use for git-rebase)" -msgstr "(ús intern per al git-rebase)" +#: wt-status.c:1542 +msgid "Not currently on any branch." +msgstr "Actualment no s'és en cap branca." -#: builtin/am.c:2326 -msgid "" -"The -b/--binary option has been a no-op for long time, and\n" -"it will be removed. Please do not use it anymore." -msgstr "" -"Fa molt que l'opció -b/--binary no ha fet res, i\n" -"s'eliminarà. Si us plau, no l'useu més." +#: wt-status.c:1560 +msgid "Initial commit" +msgstr "Comissió inicial" -#: builtin/am.c:2333 -msgid "failed to read the index" -msgstr "s'ha fallat en llegir l'índex" +#: wt-status.c:1574 +msgid "Untracked files" +msgstr "Fitxers no seguits" -#: builtin/am.c:2348 -#, c-format -msgid "previous rebase directory %s still exists but mbox given." -msgstr "" -"un directori de rebasament anterior %s encara existeix però s'ha donat una " -"bústia." +#: wt-status.c:1576 +msgid "Ignored files" +msgstr "Fitxers ignorats" -#: builtin/am.c:2372 +#: wt-status.c:1580 #, c-format msgid "" -"Stray %s directory found.\n" -"Use \"git am --abort\" to remove it." +"It took %.2f seconds to enumerate untracked files. 'status -uno'\n" +"may speed it up, but you have to be careful not to forget to add\n" +"new files yourself (see 'git help status')." msgstr "" -"Directori %s extraviat trobat.\n" -"Useu \"git am --abort\" per a eliminar-lo." +"Ha trigat %.2f segons enumerar els fitxers no seguits.\n" +"'status -uno' pot accelerar-ho, però heu d'anar amb compte de no\n" +"oblidar-vos d'afegir fitxers nous per vós mateix (vegeu\n" +"'git help status')." -#: builtin/am.c:2378 -msgid "Resolve operation not in progress, we are not resuming." -msgstr "Operació de resolució no en curs; no reprenem." +#: wt-status.c:1586 +#, c-format +msgid "Untracked files not listed%s" +msgstr "Els fitxers no seguits no estan llistats%s" -#: builtin/apply.c:122 -msgid "git apply [] [...]" -msgstr "git apply [] [...]" +#: wt-status.c:1588 +msgid " (use -u option to show untracked files)" +msgstr " (useu l'opció -u per a mostrar els fitxers no seguits)" -#: builtin/apply.c:153 -#, c-format -msgid "unrecognized whitespace option '%s'" -msgstr "opció d'espai en blanc '%s' no reconeguda" +#: wt-status.c:1594 +msgid "No changes" +msgstr "Sense canvis" -#: builtin/apply.c:169 +#: wt-status.c:1599 #, c-format -msgid "unrecognized whitespace ignore option '%s'" -msgstr "opció d'ignoral d'espai en blanc '%s' no reconeguda" +msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n" +msgstr "" +"no hi ha canvis afegits a cometre (useu \"git add\" o \"git commit -a\")\n" -#: builtin/apply.c:854 +#: wt-status.c:1602 #, c-format -msgid "Cannot prepare timestamp regexp %s" -msgstr "No es pot preparar l'expressió regular de marca de temps %s" +msgid "no changes added to commit\n" +msgstr "no hi ha canvis afegits a cometre\n" -#: builtin/apply.c:863 +#: wt-status.c:1605 #, c-format -msgid "regexec returned %d for input: %s" -msgstr "regexec ha retornat %d per l'entrada: %s" +msgid "" +"nothing added to commit but untracked files present (use \"git add\" to " +"track)\n" +msgstr "" +"no hi ha res afegit a cometre però fitxers no seguits estan presents (useu " +"\"git add\" per a seguir-los)\n" -#: builtin/apply.c:947 +#: wt-status.c:1608 #, c-format -msgid "unable to find filename in patch at line %d" -msgstr "no s'ha pogut trobar el nom de fitxer en el pedaç a la línia %d" +msgid "nothing added to commit but untracked files present\n" +msgstr "no hi ha res afegit a cometre però fitxers no seguits estan presents\n" -#: builtin/apply.c:984 +#: wt-status.c:1611 #, c-format -msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d" +msgid "nothing to commit (create/copy files and use \"git add\" to track)\n" msgstr "" -"git apply: git-diff dolent - /dev/null esperat, %s rebut en la línia %d" +"no hi ha res a cometre (creeu/copieu fitxers i useu \"git add\" per a seguir-" +"los)\n" -#: builtin/apply.c:989 +#: wt-status.c:1614 wt-status.c:1619 #, c-format -msgid "git apply: bad git-diff - inconsistent new filename on line %d" -msgstr "" -"git apply: git-diff dolent - nom de fitxer nou inconsistent en la línia %d" +msgid "nothing to commit\n" +msgstr "no hi ha res a cometre\n" -#: builtin/apply.c:990 +#: wt-status.c:1617 #, c-format -msgid "git apply: bad git-diff - inconsistent old filename on line %d" +msgid "nothing to commit (use -u to show untracked files)\n" msgstr "" -"git apply: git-diff dolent - nom de fitxer antic inconsistent en la línia %d" +"no hi ha res a cometre (useu -u per a mostrar els fitxers no seguits)\n" -#: builtin/apply.c:995 +#: wt-status.c:1621 #, c-format -msgid "git apply: bad git-diff - expected /dev/null on line %d" -msgstr "git apply: git-diff dolent - /dev/null esperat en la línia %d" +msgid "nothing to commit, working tree clean\n" +msgstr "no hi ha res a cometre, l'arbre de treball està net\n" -#: builtin/apply.c:1489 -#, c-format -msgid "recount: unexpected line: %.*s" -msgstr "recompte: línia inesperada: %.*s" +#: wt-status.c:1728 +msgid "Initial commit on " +msgstr "Comissió inicial en " -#: builtin/apply.c:1550 -#, c-format -msgid "patch fragment without header at line %d: %.*s" -msgstr "fragment de pedaç sense capçalera a la línia %d: %.*s" +#: wt-status.c:1732 +msgid "HEAD (no branch)" +msgstr "HEAD (sense branca)" -#: builtin/apply.c:1567 -#, c-format -msgid "" -"git diff header lacks filename information when removing %d leading pathname " -"component (line %d)" -msgid_plural "" -"git diff header lacks filename information when removing %d leading pathname " -"components (line %d)" -msgstr[0] "" -"a la capçalera de git diff li manca informació de nom de fitxer en eliminar " -"%d component de nom de camí inicial (línia %d)" -msgstr[1] "" -"a la capçalera de git diff li manca informació de nom de fitxer en eliminar " -"%d components de nom de camí inicial (línia %d)" +#: wt-status.c:1761 +msgid "gone" +msgstr "no hi és" -#: builtin/apply.c:1743 -msgid "new file depends on old contents" -msgstr "el fitxer nou depèn dels continguts antics" +#: wt-status.c:1763 wt-status.c:1771 +msgid "behind " +msgstr "darrere " -#: builtin/apply.c:1745 -msgid "deleted file still has contents" -msgstr "el fitxer suprimit encara té continguts" +#: wt-status.c:1766 wt-status.c:1769 +msgid "ahead " +msgstr "davant per " -#: builtin/apply.c:1774 +#. TRANSLATORS: the action is e.g. "pull with rebase" +#: wt-status.c:2270 #, c-format -msgid "corrupt patch at line %d" -msgstr "el pedaç és malmès a la línia %d" +msgid "cannot %s: You have unstaged changes." +msgstr "no es pot %s: Teniu canvis no allistats." -#: builtin/apply.c:1810 -#, c-format -msgid "new file %s depends on old contents" -msgstr "el fitxer nou %s depèn dels continguts antics" +#: wt-status.c:2276 +msgid "additionally, your index contains uncommitted changes." +msgstr "addicionalment, el vostre índex conté canvis sense cometre." -#: builtin/apply.c:1812 +#: wt-status.c:2278 #, c-format -msgid "deleted file %s still has contents" -msgstr "el fitxer suprimit %s encara té continguts" +msgid "cannot %s: Your index contains uncommitted changes." +msgstr "no es pot %s: El vostre índex conté canvis sense cometre." -#: builtin/apply.c:1815 +#: compat/precompose_utf8.c:57 builtin/clone.c:414 #, c-format -msgid "** warning: file %s becomes empty but is not deleted" -msgstr "** advertència: el fitxer %s queda buit però no se suprimeix" +msgid "failed to unlink '%s'" +msgstr "s'ha fallat en desenllaçar '%s'" -#: builtin/apply.c:1962 -#, c-format -msgid "corrupt binary patch at line %d: %.*s" -msgstr "pedaç binari malmès a la línia %d: %.*s" +#: builtin/add.c:22 +msgid "git add [] [--] ..." +msgstr "git add [] [--] ..." -#: builtin/apply.c:1999 +#: builtin/add.c:80 #, c-format -msgid "unrecognized binary patch at line %d" -msgstr "pedaç binari no reconegut a la línia %d" +msgid "unexpected diff status %c" +msgstr "estat de diff inesperat %c" + +#: builtin/add.c:85 builtin/commit.c:291 +msgid "updating files failed" +msgstr "s'ha fallat en actualitzar els fitxers" -#: builtin/apply.c:2154 +#: builtin/add.c:95 #, c-format -msgid "patch with only garbage at line %d" -msgstr "pedaç amb només escombraries a la línia %d" +msgid "remove '%s'\n" +msgstr "elimina '%s'\n" + +#: builtin/add.c:149 +msgid "Unstaged changes after refreshing the index:" +msgstr "Canvis no allistats després d'actualitzar l'índex:" -#: builtin/apply.c:2244 +#: builtin/add.c:209 builtin/rev-parse.c:840 +msgid "Could not read the index" +msgstr "No s'ha pogut llegir l'índex" + +#: builtin/add.c:220 #, c-format -msgid "unable to read symlink %s" -msgstr "no s'ha pogut llegir l'enllaç simbòlic %s" +msgid "Could not open '%s' for writing." +msgstr "No s'ha pogut obrir '%s' per a escriptura." + +#: builtin/add.c:224 +msgid "Could not write patch" +msgstr "No s'ha pogut escriure el pedaç" + +#: builtin/add.c:227 +msgid "editing patch failed" +msgstr "l'edició del pedaç ha fallat" -#: builtin/apply.c:2248 +#: builtin/add.c:230 #, c-format -msgid "unable to open or read %s" -msgstr "no s'ha pogut obrir o llegir %s" +msgid "Could not stat '%s'" +msgstr "No s'ha pogut fer stat a '%s'" + +#: builtin/add.c:232 +msgid "Empty patch. Aborted." +msgstr "El pedaç és buit. S'ha avortat." -#: builtin/apply.c:2901 +#: builtin/add.c:237 #, c-format -msgid "invalid start of line: '%c'" -msgstr "inici de línia no vàlid: '%c'" +msgid "Could not apply '%s'" +msgstr "No s'ha pogut aplicar '%s'" + +#: builtin/add.c:247 +msgid "The following paths are ignored by one of your .gitignore files:\n" +msgstr "" +"Els camins següents s'ignoren per un dels vostres fitxers .gitignore:\n" + +#: builtin/add.c:266 builtin/clean.c:870 builtin/fetch.c:115 builtin/mv.c:111 +#: builtin/prune-packed.c:55 builtin/pull.c:198 builtin/push.c:521 +#: builtin/remote.c:1326 builtin/rm.c:268 builtin/send-pack.c:162 +msgid "dry run" +msgstr "marxa en sec" + +#: builtin/add.c:269 +msgid "interactive picking" +msgstr "recull interactiu" + +#: builtin/add.c:270 builtin/checkout.c:1156 builtin/reset.c:286 +msgid "select hunks interactively" +msgstr "selecciona els trossos interactivament" + +#: builtin/add.c:271 +msgid "edit current diff and apply" +msgstr "edita la diferència actual i aplica-la" + +#: builtin/add.c:272 +msgid "allow adding otherwise ignored files" +msgstr "permet afegir fitxers que d'altra manera s'ignoren" + +#: builtin/add.c:273 +msgid "update tracked files" +msgstr "actualitza els fitxers seguits" + +#: builtin/add.c:274 +msgid "record only the fact that the path will be added later" +msgstr "registra només el fet de que el camí s'afegirà més tard" + +#: builtin/add.c:275 +msgid "add changes from all tracked and untracked files" +msgstr "afegeix els canvis de tots els fitxers seguits i no seguits" + +#: builtin/add.c:278 +msgid "ignore paths removed in the working tree (same as --no-all)" +msgstr "" +"ignora els camins eliminats en l'arbre de treball (el mateix que --no-all)" + +#: builtin/add.c:280 +msgid "don't add, only refresh the index" +msgstr "no afegeixis, només actualitza l'índex" + +#: builtin/add.c:281 +msgid "just skip files which cannot be added because of errors" +msgstr "només omet els fitxers que no es poden afegir a causa d'errors" + +#: builtin/add.c:282 +msgid "check if - even missing - files are ignored in dry run" +msgstr "" +"comproveu si els fitxers - fins i tot els absents - s'ignoren en marxa en sec" + +#: builtin/add.c:283 builtin/update-index.c:947 +msgid "(+/-)x" +msgstr "(+/-)x" + +#: builtin/add.c:283 builtin/update-index.c:948 +msgid "override the executable bit of the listed files" +msgstr "passa per alt el bit executable dels fitxers llistats" -#: builtin/apply.c:3020 +#: builtin/add.c:305 #, c-format -msgid "Hunk #%d succeeded at %d (offset %d line)." -msgid_plural "Hunk #%d succeeded at %d (offset %d lines)." -msgstr[0] "El tros #%d ha tingut èxit a %d (desplaçament %d línia)." -msgstr[1] "El tros #%d ha tingut èxit a %d (desplaçament %d línies)." +msgid "Use -f if you really want to add them.\n" +msgstr "Useu -f si realment els voleu afegir.\n" + +#: builtin/add.c:312 +msgid "adding files failed" +msgstr "l'afegiment de fitxers ha fallat" + +#: builtin/add.c:348 +msgid "-A and -u are mutually incompatible" +msgstr "-A i -u són mutualment incompatibles" + +#: builtin/add.c:355 +msgid "Option --ignore-missing can only be used together with --dry-run" +msgstr "L'opció --ignore-missing només es pot usar junt amb --dry-run" -#: builtin/apply.c:3032 +#: builtin/add.c:359 #, c-format -msgid "Context reduced to (%ld/%ld) to apply fragment at %d" -msgstr "El context s'ha reduït a (%ld/%ld) per a aplicar el fragment a %d" +msgid "--chmod param '%s' must be either -x or +x" +msgstr "el paràmetre --chmod '%s' ha de ser o -x o +x" -#: builtin/apply.c:3038 +#: builtin/add.c:374 #, c-format -msgid "" -"while searching for:\n" -"%.*s" -msgstr "" -"tot cercant:\n" -"%.*s" +msgid "Nothing specified, nothing added.\n" +msgstr "No s'ha especificat res, no s'ha afegit res.\n" -#: builtin/apply.c:3060 +#: builtin/add.c:375 #, c-format -msgid "missing binary patch data for '%s'" -msgstr "manquen les dades de pedaç binari de '%s'" +msgid "Maybe you wanted to say 'git add .'?\n" +msgstr "Potser volíeu dir 'git add .'?\n" + +#: builtin/add.c:380 builtin/check-ignore.c:172 builtin/checkout.c:279 +#: builtin/checkout.c:472 builtin/clean.c:914 builtin/commit.c:350 +#: builtin/mv.c:131 builtin/reset.c:235 builtin/rm.c:298 +#: builtin/submodule--helper.c:244 +msgid "index file corrupt" +msgstr "fitxer d'índex malmès" + +#: builtin/am.c:414 +msgid "could not parse author script" +msgstr "no s'ha pogut analitzar l'script d'autor" -#: builtin/apply.c:3163 +#: builtin/am.c:491 #, c-format -msgid "binary patch does not apply to '%s'" -msgstr "el pedaç binari no s'aplica a '%s'" +msgid "'%s' was deleted by the applypatch-msg hook" +msgstr "s'ha suprimit '%s' pel ganxo applypatch-msg" -#: builtin/apply.c:3169 +#: builtin/am.c:532 #, c-format -msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)" -msgstr "" -"el pedaç binari a '%s' crea un resultat incorrecte (esperant %s, %s rebut)" +msgid "Malformed input line: '%s'." +msgstr "Línia d'entrada mal formada: '%s'." -#: builtin/apply.c:3190 +#: builtin/am.c:569 #, c-format -msgid "patch failed: %s:%ld" -msgstr "el pedaç ha fallat: %s:%ld" +msgid "Failed to copy notes from '%s' to '%s'" +msgstr "S'ha fallat en copiar les notes de '%s' a '%s'" + +#: builtin/am.c:595 +msgid "fseek failed" +msgstr "fseek ha fallat" -#: builtin/apply.c:3314 +#: builtin/am.c:775 #, c-format -msgid "cannot checkout %s" -msgstr "no es pot agafar %s" +msgid "could not parse patch '%s'" +msgstr "no s'ha pogut analitzar el pedaç '%s'" + +#: builtin/am.c:840 +msgid "Only one StGIT patch series can be applied at once" +msgstr "només una sèrie de pedaços StGIT es pot aplicar a la vegada" -#: builtin/apply.c:3370 -#, c-format -msgid "reading from '%s' beyond a symbolic link" -msgstr "s'està llegint de '%s' més enllà d'un enllaç simbòlic" +#: builtin/am.c:887 +msgid "invalid timestamp" +msgstr "marca de temps no vàlida" -#: builtin/apply.c:3399 builtin/apply.c:3630 -#, c-format -msgid "path %s has been renamed/deleted" -msgstr "el camí %s s'ha canviat de nom / s'ha suprimit" +#: builtin/am.c:890 builtin/am.c:898 +msgid "invalid Date line" +msgstr "línia Date no vàlida" -#: builtin/apply.c:3482 builtin/apply.c:3644 -#, c-format -msgid "%s: does not exist in index" -msgstr "%s: no existeix en l'índex" +#: builtin/am.c:895 +msgid "invalid timezone offset" +msgstr "desplaçament de zona de temps no vàlid" -#: builtin/apply.c:3486 builtin/apply.c:3636 builtin/apply.c:3658 -#, c-format -msgid "%s: %s" -msgstr "%s: %s" +#: builtin/am.c:984 +msgid "Patch format detection failed." +msgstr "La detecció de format de pedaç ha fallat." -#: builtin/apply.c:3491 builtin/apply.c:3652 +#: builtin/am.c:989 builtin/clone.c:379 #, c-format -msgid "%s: does not match index" -msgstr "%s: no coincideix amb l'índex" +msgid "failed to create directory '%s'" +msgstr "s'ha fallat en crear el directori '%s'" -#: builtin/apply.c:3597 -msgid "removal patch leaves file contents" -msgstr "el pedaç d'eliminació deixa els continguts dels fitxers" +#: builtin/am.c:993 +msgid "Failed to split patches." +msgstr "S'ha fallat en dividir els pedaços." -#: builtin/apply.c:3669 -#, c-format -msgid "%s: wrong type" -msgstr "%s: tipus erroni" +#: builtin/am.c:1125 builtin/commit.c:376 +msgid "unable to write index file" +msgstr "no s'ha pogut escriure el fitxer d'índex" -#: builtin/apply.c:3671 +#: builtin/am.c:1176 #, c-format -msgid "%s has type %o, expected %o" -msgstr "%s és del tipus %o, s'esperava %o" +msgid "When you have resolved this problem, run \"%s --continue\"." +msgstr "Quan hàgiu resolt aquest problema, executeu \"%s --continue\"." -#: builtin/apply.c:3822 builtin/apply.c:3824 +#: builtin/am.c:1177 #, c-format -msgid "invalid path '%s'" -msgstr "camí no vàlid: %s" +msgid "If you prefer to skip this patch, run \"%s --skip\" instead." +msgstr "" +"Si preferiu saltar aquest pedaç, executeu \"%s --skip\" en lloc d'això." -#: builtin/apply.c:3879 +#: builtin/am.c:1178 #, c-format -msgid "%s: already exists in index" -msgstr "%s: ja existeix en l'índex" +msgid "To restore the original branch and stop patching, run \"%s --abort\"." +msgstr "" +"Per a restaurar la branca original i deixar d'apedaçar, executeu \"%s --abort" +"\"." -#: builtin/apply.c:3882 -#, c-format -msgid "%s: already exists in working directory" -msgstr "%s: ja existeix en el directori de treball" +#: builtin/am.c:1316 +msgid "Patch is empty. Was it split wrong?" +msgstr "El pedaç és buit. S'ha dividit malament?" -#: builtin/apply.c:3902 +#: builtin/am.c:1390 builtin/log.c:1550 #, c-format -msgid "new mode (%o) of %s does not match old mode (%o)" -msgstr "el mode nou (%o) de %s no coincideix amb el mode antic (%o)" +msgid "invalid ident line: %s" +msgstr "línia d'identitat no vàlida: %s" -#: builtin/apply.c:3907 +#: builtin/am.c:1417 #, c-format -msgid "new mode (%o) of %s does not match old mode (%o) of %s" -msgstr "el mode nou (%o) de %s no coincideix amb el mode antic (%o) de %s" +msgid "unable to parse commit %s" +msgstr "no s'ha pogut analitzar la comissió %s" -#: builtin/apply.c:3927 -#, c-format -msgid "affected file '%s' is beyond a symbolic link" -msgstr "el fitxer afectat '%s' és més enllà d'un enllaç simbòlic" +#: builtin/am.c:1610 +msgid "Repository lacks necessary blobs to fall back on 3-way merge." +msgstr "" +"Al dipòsit li manquen els blobs necessaris per a retrocedir a una fusió de 3 " +"vies." -#: builtin/apply.c:3931 -#, c-format -msgid "%s: patch does not apply" -msgstr "%s: el pedaç no s'aplica" +#: builtin/am.c:1612 +msgid "Using index info to reconstruct a base tree..." +msgstr "S'està usant la informació d'índex per a reconstruir un arbre base..." -#: builtin/apply.c:3945 -#, c-format -msgid "Checking patch %s..." -msgstr "S'està comprovant el pedaç %s..." +#: builtin/am.c:1631 +msgid "" +"Did you hand edit your patch?\n" +"It does not apply to blobs recorded in its index." +msgstr "" +"Heu editat el vostre pedaç a mà?\n" +"No s'aplica als blobs recordats en el seu índex." -#: builtin/apply.c:4038 builtin/checkout.c:233 builtin/reset.c:135 -#, c-format -msgid "make_cache_entry failed for path '%s'" -msgstr "make_cache_entry ha fallat per al camí '%s'" +#: builtin/am.c:1637 +msgid "Falling back to patching base and 3-way merge..." +msgstr "S'està retrocedint a apedaçar la base i fusionar de 3 vies..." -#: builtin/apply.c:4182 -#, c-format -msgid "unable to remove %s from index" -msgstr "no s'ha pogut eliminar %s de l'índex" +#: builtin/am.c:1662 +msgid "Failed to merge in the changes." +msgstr "S'ha fallat en fusionar els canvis." -#: builtin/apply.c:4215 -#, c-format -msgid "corrupt patch for submodule %s" -msgstr "pedaç malmès per al submòdul %s" +#: builtin/am.c:1686 builtin/merge.c:628 +msgid "git write-tree failed to write a tree" +msgstr "git write-tree ha fallat en escriure un arbre" -#: builtin/apply.c:4219 -#, c-format -msgid "unable to stat newly created file '%s'" -msgstr "no s'ha pogut fer stat al fitxer novament creat '%s'" +#: builtin/am.c:1693 +msgid "applying to an empty history" +msgstr "s'està aplicant a una història buida" + +#: builtin/am.c:1706 builtin/commit.c:1769 builtin/merge.c:798 +#: builtin/merge.c:823 +msgid "failed to write commit object" +msgstr "s'ha fallat en escriure l'objecte de comissió" -#: builtin/apply.c:4224 +#: builtin/am.c:1739 builtin/am.c:1743 #, c-format -msgid "unable to create backing store for newly created file %s" +msgid "cannot resume: %s does not exist." +msgstr "no es pot reprendre: %s no existeix." + +#: builtin/am.c:1759 +msgid "cannot be interactive without stdin connected to a terminal." msgstr "" -"no s'ha pogut crear un magatzem de recolzament per al fitxer novament creat " -"%s" +"no es pot ser interactiu sense que stdin estigui connectada a un terminal." -#: builtin/apply.c:4227 builtin/apply.c:4340 -#, c-format -msgid "unable to add cache entry for %s" -msgstr "no s'ha pogut afegir una entrada de cau per a %s" +#: builtin/am.c:1764 +msgid "Commit Body is:" +msgstr "El cos de la comissió és:" -#: builtin/apply.c:4260 -#, c-format -msgid "closing file '%s'" -msgstr "s'està tancant el fitxer '%s'" +#. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a] +#. in your translation. The program will only accept English +#. input at this point. +#. +#: builtin/am.c:1774 +msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: " +msgstr "" +"Voleu aplicar-lo? [y]es/[n]o/[e]dita/[v]isualitza el pedaç/[a]ccepta'ls " +"tots: " -#: builtin/apply.c:4313 +#: builtin/am.c:1824 #, c-format -msgid "unable to write file '%s' mode %o" -msgstr "no s'ha pogut escriure el fitxer '%s' mode %o" +msgid "Dirty index: cannot apply patches (dirty: %s)" +msgstr "Índex brut: no es pot aplicar pedaços (bruts: %s)" -#: builtin/apply.c:4403 +#: builtin/am.c:1861 builtin/am.c:1933 #, c-format -msgid "Applied patch %s cleanly." -msgstr "El pedaç %s s'ha aplicat netament." +msgid "Applying: %.*s" +msgstr "S'està aplicant: %.*s" -#: builtin/apply.c:4411 -msgid "internal error" -msgstr "error intern" +#: builtin/am.c:1877 +msgid "No changes -- Patch already applied." +msgstr "Sense canvis -- El pedaç ja s'ha aplicat." -#: builtin/apply.c:4414 +#: builtin/am.c:1885 #, c-format -msgid "Applying patch %%s with %d reject..." -msgid_plural "Applying patch %%s with %d rejects..." -msgstr[0] "S'està aplicant el pedaç %%s amb %d rebuig..." -msgstr[1] "S'està aplicant el pedaç %%s amb %d rebuitjos..." +msgid "Patch failed at %s %.*s" +msgstr "El pedaç ha fallat a %s %.*s" -#: builtin/apply.c:4424 +#: builtin/am.c:1891 #, c-format -msgid "truncating .rej filename to %.*s.rej" -msgstr "s'està truncant el nom del fitxer .rej a %.*s.rej" +msgid "The copy of the patch that failed is found in: %s" +msgstr "La còpia del pedaç que ha fallat es troba en: %s" -#: builtin/apply.c:4432 -#, c-format -msgid "cannot open %s: %s" -msgstr "no es pot obrir %s: %s" +#: builtin/am.c:1936 +msgid "" +"No changes - did you forget to use 'git add'?\n" +"If there is nothing left to stage, chances are that something else\n" +"already introduced the same changes; you might want to skip this patch." +msgstr "" +"Cap canvi - heu oblidat d'usar 'git add'?\n" +"Si no hi ha res a allistar, probablement alguna altra cosa ja ha\n" +"introduït els mateixos canvis; potser voleu ometre aquest pedaç." -#: builtin/apply.c:4445 -#, c-format -msgid "Hunk #%d applied cleanly." -msgstr "El tros #%d s'ha aplicat netament." +#: builtin/am.c:1943 +msgid "" +"You still have unmerged paths in your index.\n" +"Did you forget to use 'git add'?" +msgstr "" +"Encara teniu camins sense fusionar en el vostre índex.\n" +"Heu oblidat d'usar 'git add'?" -#: builtin/apply.c:4448 +#: builtin/am.c:2051 builtin/am.c:2055 builtin/am.c:2067 builtin/reset.c:308 +#: builtin/reset.c:316 #, c-format -msgid "Rejected hunk #%d." -msgstr "S'ha rebutjat el tros #%d." +msgid "Could not parse object '%s'." +msgstr "No s'ha pogut analitzar l'objecte '%s'." + +#: builtin/am.c:2103 +msgid "failed to clean index" +msgstr "s'ha fallat en netejar l'índex" + +#: builtin/am.c:2137 +msgid "" +"You seem to have moved HEAD since the last 'am' failure.\n" +"Not rewinding to ORIG_HEAD" +msgstr "" +"Sembla que heu mogut HEAD després de l'última fallada de 'am'.\n" +"No s'està rebobinant a ORIG_HEAD" -#: builtin/apply.c:4537 +#: builtin/am.c:2200 #, c-format -msgid "Skipped patch '%s'." -msgstr "S'ha saltat el pedaç '%s'." +msgid "Invalid value for --patch-format: %s" +msgstr "Valor no vàlid per a --patch-format: %s" -#: builtin/apply.c:4545 -msgid "unrecognized input" -msgstr "entrada no reconeguda" +#: builtin/am.c:2233 +msgid "git am [] [( | )...]" +msgstr "git am [] [( | )...]" -#: builtin/apply.c:4556 -msgid "unable to read index file" -msgstr "no es pot llegir el fitxer d'índex" +#: builtin/am.c:2234 +msgid "git am [] (--continue | --skip | --abort)" +msgstr "git am [] (--continue | --skip | --abort)" -#: builtin/apply.c:4701 -msgid "--3way outside a repository" -msgstr "--3way fora d'un dipòsit" +#: builtin/am.c:2240 +msgid "run interactively" +msgstr "executa interactivament" -#: builtin/apply.c:4709 -msgid "--index outside a repository" -msgstr "--index fora d'un dipòsit" +#: builtin/am.c:2242 +msgid "historical option -- no-op" +msgstr "opció històrica -- no-op" -#: builtin/apply.c:4712 -msgid "--cached outside a repository" -msgstr "--cached fora d'un dipòsit" +#: builtin/am.c:2244 +msgid "allow fall back on 3way merging if needed" +msgstr "permet retrocedir a una fusió de 3 vies si és necessari" -#: builtin/apply.c:4745 -#, c-format -msgid "can't open patch '%s'" -msgstr "no es pot obrir el pedaç '%s'" +#: builtin/am.c:2245 builtin/init-db.c:483 builtin/prune-packed.c:57 +#: builtin/repack.c:172 +msgid "be quiet" +msgstr "calla" -#: builtin/apply.c:4760 -#, c-format -msgid "squelched %d whitespace error" -msgid_plural "squelched %d whitespace errors" -msgstr[0] "s'ha omès %d error d'espai en blanc" -msgstr[1] "s'han omès %d errors d'espai en blanc" +#: builtin/am.c:2247 +msgid "add a Signed-off-by line to the commit message" +msgstr "afegeix una línia Signed-off-by al missatge de comissió" -#: builtin/apply.c:4766 builtin/apply.c:4776 -#, c-format -msgid "%d line adds whitespace errors." -msgid_plural "%d lines add whitespace errors." -msgstr[0] "%d línia afegeix errors d'espai en blanc." -msgstr[1] "%d línies afegeixen errors d'espai en blanc." +#: builtin/am.c:2250 +msgid "recode into utf8 (default)" +msgstr "recodifica en utf8 (per defecte)" -#: builtin/apply.c:4800 -msgid "don't apply changes matching the given path" -msgstr "no apliquis els canvis que coincideixin amb el camí donat" +#: builtin/am.c:2252 +msgid "pass -k flag to git-mailinfo" +msgstr "passa la bandera -k al git-mailinfo" -#: builtin/apply.c:4803 -msgid "apply changes matching the given path" -msgstr "aplica els canvis que coincideixin amb el camí donat" +#: builtin/am.c:2254 +msgid "pass -b flag to git-mailinfo" +msgstr "passa la bandera -b al git-mailinfo" -#: builtin/apply.c:4806 -msgid "remove leading slashes from traditional diff paths" -msgstr "" -"elimina barres obliqües inicials dels camins de diferència " -"tradicionals" +#: builtin/am.c:2256 +msgid "pass -m flag to git-mailinfo" +msgstr "passa la bandera -m al git-mailinfo" -#: builtin/apply.c:4809 -msgid "ignore additions made by the patch" -msgstr "ignora afegiments fets pel pedaç" +#: builtin/am.c:2258 +msgid "pass --keep-cr flag to git-mailsplit for mbox format" +msgstr "passa la bandera --keep-cr al git-mailsplit per al format mbox" -#: builtin/apply.c:4811 -msgid "instead of applying the patch, output diffstat for the input" +#: builtin/am.c:2261 +msgid "do not pass --keep-cr flag to git-mailsplit independent of am.keepcr" msgstr "" -"en lloc d'aplicar el pedaç, emet les estadístiques de diferència de l'entrada" +"no passis la bandera --keep-cr al git-mailsplit independent de am.keepcr" -#: builtin/apply.c:4815 -msgid "show number of added and deleted lines in decimal notation" -msgstr "mostra el nombre de línies afegides i suprimides en notació decimal" +#: builtin/am.c:2264 +msgid "strip everything before a scissors line" +msgstr "despulla tot abans d'una línia de tissores" -#: builtin/apply.c:4817 -msgid "instead of applying the patch, output a summary for the input" -msgstr "en lloc d'aplicar el pedaç, emet un resum de l'entrada" +#: builtin/am.c:2266 builtin/am.c:2269 builtin/am.c:2272 builtin/am.c:2275 +#: builtin/am.c:2278 builtin/am.c:2281 builtin/am.c:2284 builtin/am.c:2287 +#: builtin/am.c:2293 +msgid "pass it through git-apply" +msgstr "passa-ho a través del git-apply" + +#: builtin/am.c:2283 builtin/fmt-merge-msg.c:662 builtin/fmt-merge-msg.c:665 +#: builtin/grep.c:707 builtin/merge.c:200 builtin/pull.c:135 builtin/pull.c:194 +#: builtin/repack.c:181 builtin/repack.c:185 builtin/show-branch.c:644 +#: builtin/show-ref.c:175 builtin/tag.c:340 parse-options.h:132 +#: parse-options.h:134 parse-options.h:245 +msgid "n" +msgstr "n" -#: builtin/apply.c:4819 -msgid "instead of applying the patch, see if the patch is applicable" -msgstr "en lloc d'aplicar el pedaç, veges si el pedaç és aplicable" +#: builtin/am.c:2289 builtin/for-each-ref.c:37 builtin/replace.c:438 +#: builtin/tag.c:372 +msgid "format" +msgstr "format" -#: builtin/apply.c:4821 -msgid "make sure the patch is applicable to the current index" -msgstr "assegura que el pedaç sigui aplicable a l'índex actual" +#: builtin/am.c:2290 +msgid "format the patch(es) are in" +msgstr "el format en el qual estan els pedaços" -#: builtin/apply.c:4823 -msgid "apply a patch without touching the working tree" -msgstr "aplica un pedaç sense tocar l'arbre de treball" +#: builtin/am.c:2296 +msgid "override error message when patch failure occurs" +msgstr "" +"passa per alt el missatge d'error quan s'ocorre una fallada en apedaçar" -#: builtin/apply.c:4825 -msgid "accept a patch that touches outside the working area" -msgstr "accepta un pedaç que toqui fora de l'àrea de treball" +#: builtin/am.c:2298 +msgid "continue applying patches after resolving a conflict" +msgstr "segueix aplicant pedaços després de resoldre un conflicte" -#: builtin/apply.c:4827 -msgid "also apply the patch (use with --stat/--summary/--check)" -msgstr "aplica el pedaç també (useu amb --stat/--summary/--check)" +#: builtin/am.c:2301 +msgid "synonyms for --continue" +msgstr "sinònims de --continue" -#: builtin/apply.c:4829 -msgid "attempt three-way merge if a patch does not apply" -msgstr "intenta una fusió de tres vies si el pedaç no s'aplica" +#: builtin/am.c:2304 +msgid "skip the current patch" +msgstr "salta el pedaç actual" -#: builtin/apply.c:4831 -msgid "build a temporary index based on embedded index information" -msgstr "construeix un índex temporal basat en la informació d'índex incrustada" +#: builtin/am.c:2307 +msgid "restore the original branch and abort the patching operation." +msgstr "restaura la branca original i avorta l'operació d'apedaçament." -#: builtin/apply.c:4834 builtin/checkout-index.c:169 builtin/ls-files.c:426 -msgid "paths are separated with NUL character" -msgstr "els camins se separen amb el caràcter NUL" +#: builtin/am.c:2311 +msgid "lie about committer date" +msgstr "menteix sobre la data del comitent" -#: builtin/apply.c:4836 -msgid "ensure at least lines of context match" -msgstr "assegura't que almenys línies de context coincideixin" +#: builtin/am.c:2313 +msgid "use current timestamp for author date" +msgstr "usa el marc de temps actual per la data d'autor" -#: builtin/apply.c:4838 -msgid "detect new or modified lines that have whitespace errors" -msgstr "" -"detecta les línies noves o modificades que tinguin errors d'espai en blanc" +#: builtin/am.c:2315 builtin/commit.c:1605 builtin/merge.c:229 +#: builtin/pull.c:165 builtin/revert.c:92 builtin/tag.c:355 +msgid "key-id" +msgstr "ID de clau" -#: builtin/apply.c:4841 builtin/apply.c:4844 -msgid "ignore changes in whitespace when finding context" -msgstr "ignora els canvis d'espai en blanc en cercar context" +#: builtin/am.c:2316 +msgid "GPG-sign commits" +msgstr "signa les comissions amb GPG" -#: builtin/apply.c:4847 -msgid "apply the patch in reverse" -msgstr "aplica el pedaç al revés" +#: builtin/am.c:2319 +msgid "(internal use for git-rebase)" +msgstr "(ús intern per al git-rebase)" -#: builtin/apply.c:4849 -msgid "don't expect at least one line of context" -msgstr "no esperis almenys una línia de context" +#: builtin/am.c:2334 +msgid "" +"The -b/--binary option has been a no-op for long time, and\n" +"it will be removed. Please do not use it anymore." +msgstr "" +"Fa molt que l'opció -b/--binary no ha fet res, i\n" +"s'eliminarà. Si us plau, no l'useu més." -#: builtin/apply.c:4851 -msgid "leave the rejected hunks in corresponding *.rej files" -msgstr "deixa els trossos rebutjats en fitxers *.reg coresspondents" +#: builtin/am.c:2341 +msgid "failed to read the index" +msgstr "s'ha fallat en llegir l'índex" -#: builtin/apply.c:4853 -msgid "allow overlapping hunks" -msgstr "permet trossos encavalcants" +#: builtin/am.c:2356 +#, c-format +msgid "previous rebase directory %s still exists but mbox given." +msgstr "" +"un directori de rebasament anterior %s encara existeix però s'ha donat una " +"bústia." -#: builtin/apply.c:4856 -msgid "tolerate incorrectly detected missing new-line at the end of file" -msgstr "tolera una línia nova incorrectament detectada al final del fitxer" +#: builtin/am.c:2380 +#, c-format +msgid "" +"Stray %s directory found.\n" +"Use \"git am --abort\" to remove it." +msgstr "" +"S'ha trobat un directori %s extraviat.\n" +"Useu \"git am --abort\" per a eliminar-lo." -#: builtin/apply.c:4859 -msgid "do not trust the line counts in the hunk headers" -msgstr "no confiïs en els recomptes de línia en les capçaleres dels trossos" +#: builtin/am.c:2386 +msgid "Resolve operation not in progress, we are not resuming." +msgstr "Una operació de resolució no està en curs; no reprenem." -#: builtin/apply.c:4862 -msgid "prepend to all filenames" -msgstr "anteposa a tots els noms de fitxer" +#: builtin/apply.c:8 +msgid "git apply [] [...]" +msgstr "git apply [] [...]" #: builtin/archive.c:17 #, c-format @@ -4111,118 +4612,172 @@ msgstr "es documenten les en git-rev-list(1)" msgid "Blaming lines" msgstr "S'estan culpant les línies" -#: builtin/blame.c:2536 +#: builtin/blame.c:2577 msgid "Show blame entries as we find them, incrementally" msgstr "Mostra les entrades de culpa mentre les trobem, incrementalment" -#: builtin/blame.c:2537 +#: builtin/blame.c:2578 msgid "Show blank SHA-1 for boundary commits (Default: off)" msgstr "" "Mostra un SHA-1 en blanc per les comissions de frontera (Per defecte: " "desactivat)" -#: builtin/blame.c:2538 +#: builtin/blame.c:2579 msgid "Do not treat root commits as boundaries (Default: off)" msgstr "" "No tractis les comissions d'arrel com a límits (Per defecte: desactivat)" -#: builtin/blame.c:2539 +#: builtin/blame.c:2580 msgid "Show work cost statistics" msgstr "Mostra les estadístiques de preu de treball" -#: builtin/blame.c:2540 +#: builtin/blame.c:2581 msgid "Force progress reporting" msgstr "Força l'informe de progrés" -#: builtin/blame.c:2541 +#: builtin/blame.c:2582 msgid "Show output score for blame entries" msgstr "Mostra la puntuació de sortida de les entrades de culpa" -#: builtin/blame.c:2542 +#: builtin/blame.c:2583 msgid "Show original filename (Default: auto)" msgstr "Mostra el nom de fitxer original (Per defecte: automàtic)" -#: builtin/blame.c:2543 +#: builtin/blame.c:2584 msgid "Show original linenumber (Default: off)" msgstr "Mostra el número de línia original (Per defecte: desactivat)" -#: builtin/blame.c:2544 +#: builtin/blame.c:2585 msgid "Show in a format designed for machine consumption" msgstr "Presenta en un format dissenyat per consumpció per màquina" -#: builtin/blame.c:2545 +#: builtin/blame.c:2586 msgid "Show porcelain format with per-line commit information" msgstr "Mostra el format de porcellana amb informació de comissió per línia" -#: builtin/blame.c:2546 +#: builtin/blame.c:2587 msgid "Use the same output mode as git-annotate (Default: off)" msgstr "" "Usa el mateix mode de sortida que git-annotate (Per defecte: desactivat)" -#: builtin/blame.c:2547 +#: builtin/blame.c:2588 msgid "Show raw timestamp (Default: off)" msgstr "Mostra la marca de temps crua (Per defecte: desactivat)" -#: builtin/blame.c:2548 +#: builtin/blame.c:2589 msgid "Show long commit SHA1 (Default: off)" msgstr "Mostra l'SHA1 de comissió llarg (Per defecte: desactivat)" -#: builtin/blame.c:2549 +#: builtin/blame.c:2590 msgid "Suppress author name and timestamp (Default: off)" msgstr "Omet el nom d'autor i la marca de temps (Per defecte: desactivat)" -#: builtin/blame.c:2550 +#: builtin/blame.c:2591 msgid "Show author email instead of name (Default: off)" msgstr "" "Mostra l'adreça de correu electrònic de l'autor en lloc del nom (Per " "defecte: desactivat)" -#: builtin/blame.c:2551 +#: builtin/blame.c:2592 msgid "Ignore whitespace differences" msgstr "Ignora les diferències d'espai en blanc" -#: builtin/blame.c:2552 +#: builtin/blame.c:2599 +msgid "Use an experimental indent-based heuristic to improve diffs" +msgstr "" +"Usa un heurístic experimental basat en sagnat per a millorar les diferències" + +#: builtin/blame.c:2600 +msgid "Use an experimental blank-line-based heuristic to improve diffs" +msgstr "" +"Usa un heurístic experimental basat en línies en blanc per a millorar les " +"diferències" + +#: builtin/blame.c:2602 msgid "Spend extra cycles to find better match" msgstr "Gasta cicles extres per a trobar una coincidència millor" -#: builtin/blame.c:2553 +#: builtin/blame.c:2603 msgid "Use revisions from instead of calling git-rev-list" msgstr "Usa les revisions de en lloc d'invocar git-rev-list" -#: builtin/blame.c:2554 +#: builtin/blame.c:2604 msgid "Use 's contents as the final image" msgstr "Usa els continguts de com a la imatge final" -#: builtin/blame.c:2555 builtin/blame.c:2556 +#: builtin/blame.c:2605 builtin/blame.c:2606 msgid "score" msgstr "puntuació" -#: builtin/blame.c:2555 +#: builtin/blame.c:2605 msgid "Find line copies within and across files" msgstr "Troba còpies de línia dins i a través dels fitxers" -#: builtin/blame.c:2556 +#: builtin/blame.c:2606 msgid "Find line movements within and across files" msgstr "Troba moviments de línia dins i a través dels fitxers" -#: builtin/blame.c:2557 +#: builtin/blame.c:2607 msgid "n,m" msgstr "n,m" -#: builtin/blame.c:2557 +#: builtin/blame.c:2607 msgid "Process only line range n,m, counting from 1" msgstr "Processa només el rang de línies n,m, comptant des d'1" +#: builtin/blame.c:2654 +msgid "--progress can't be used with --incremental or porcelain formats" +msgstr "" +"no es pot usar --progress amb els formats --incremental o de porcellana" + #. TRANSLATORS: This string is used to tell us the maximum #. display width for a relative timestamp in "git blame" #. output. For C locale, "4 years, 11 months ago", which #. takes 22 places, is the longest among various forms of #. relative timestamps, but your language may need more or #. fewer display columns. -#: builtin/blame.c:2649 +#: builtin/blame.c:2700 msgid "4 years, 11 months ago" msgstr "fa 4 anys i 11 mesos" +#: builtin/blame.c:2780 +msgid "--contents and --reverse do not blend well." +msgstr "--contents i --reverse no es jutgen bé." + +#: builtin/blame.c:2800 +msgid "cannot use --contents with final commit object name" +msgstr "no es pot usar --contents amb el nom d'objecte de la comissió final" + +#: builtin/blame.c:2805 +msgid "--reverse and --first-parent together require specified latest commit" +msgstr "" +"--reverse i --first-parent-together requereixen una última comissió " +"especificada" + +#: builtin/blame.c:2832 +msgid "" +"--reverse --first-parent together require range along first-parent chain" +msgstr "" +"--reverse --first-parent junts requereixen un rang de la cadena de mares " +"primeres" + +#: builtin/blame.c:2843 +#, c-format +msgid "no such path %s in %s" +msgstr "no hi ha tal camí %s en %s" + +#: builtin/blame.c:2854 +#, c-format +msgid "cannot read blob %s for path %s" +msgstr "no es pot llegir el blob %s per al camí %s" + +#: builtin/blame.c:2873 +#, c-format +msgid "file %s has only %lu line" +msgid_plural "file %s has only %lu lines" +msgstr[0] "el fitxer %s té només %lu línia" +msgstr[1] "el fitxer %s té només %lu línies" + #: builtin/branch.c:26 msgid "git branch [] [-r | -a] [--merged | --no-merged]" msgstr "git branch [] [-r | -a] [--merged | --no-merged]" @@ -4474,6 +5029,10 @@ msgstr "font" msgid "change the upstream info" msgstr "canvia la informació de font" +#: builtin/branch.c:660 +msgid "Unset the upstream info" +msgstr "Desestableix la informació de font" + #: builtin/branch.c:661 msgid "use colored output" msgstr "usa sortida colorada" @@ -4546,8 +5105,8 @@ msgstr "clau" msgid "field name to sort on" msgstr "nom del camp en el qual ordenar" -#: builtin/branch.c:686 builtin/for-each-ref.c:41 builtin/notes.c:402 -#: builtin/notes.c:405 builtin/notes.c:565 builtin/notes.c:568 +#: builtin/branch.c:686 builtin/for-each-ref.c:41 builtin/notes.c:404 +#: builtin/notes.c:407 builtin/notes.c:567 builtin/notes.c:570 #: builtin/tag.c:369 msgid "object" msgstr "objecte" @@ -4560,7 +5119,7 @@ msgstr "imprimeix només les branques de l'objecte" msgid "Failed to resolve HEAD as a valid ref." msgstr "S'ha fallat en resoldre HEAD com a referència vàlida." -#: builtin/branch.c:709 builtin/clone.c:707 +#: builtin/branch.c:709 builtin/clone.c:706 msgid "HEAD not found below refs/heads!" msgstr "HEAD no trobat sota refs/heads!" @@ -4671,65 +5230,82 @@ msgstr "Cal un dipòsit per a fer un farcell." msgid "Need a repository to unbundle." msgstr "Cal un dipòsit per a desfer un farcell." -#: builtin/cat-file.c:443 +#: builtin/cat-file.c:513 msgid "" -"git cat-file (-t [--allow-unknown-type]|-s [--allow-unknown-type]|-e|-p|" -"|--textconv) " +"git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e | -" +"p | | --textconv | --filters) [--path=] " msgstr "" -"git cat-file (-t [--allow-unknown-type]|-s [--allow-unknown-type]|-e|-p|" -"|--textconv) " +"git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e | -" +"p | | --textconv | --filters [--path=]) " -#: builtin/cat-file.c:444 -msgid "git cat-file (--batch | --batch-check) [--follow-symlinks]" -msgstr "git cat-file (--batch | --batch-check) [--follow-symlinks]" +#: builtin/cat-file.c:514 +msgid "" +"git cat-file (--batch | --batch-check) [--follow-symlinks] [--textconv | --" +"filters]" +msgstr "" +"git cat-file (--batch | --batch-check) [--follow-symlinks] [--textconv | --" +"filters]" -#: builtin/cat-file.c:481 +#: builtin/cat-file.c:551 msgid " can be one of: blob, tree, commit, tag" msgstr " pot ser un de: blob, tree, commit, tag" -#: builtin/cat-file.c:482 +#: builtin/cat-file.c:552 msgid "show object type" msgstr "mostra el tipus de l'objecte" -#: builtin/cat-file.c:483 +#: builtin/cat-file.c:553 msgid "show object size" msgstr "mostra la mida de l'objecte" -#: builtin/cat-file.c:485 +#: builtin/cat-file.c:555 msgid "exit with zero when there's no error" msgstr "surt amb zero quan no hi ha error" -#: builtin/cat-file.c:486 +#: builtin/cat-file.c:556 msgid "pretty-print object's content" msgstr "imprimeix bellament el contingut de l'objecte" -#: builtin/cat-file.c:488 +#: builtin/cat-file.c:558 msgid "for blob objects, run textconv on object's content" msgstr "en els objectes de blob, executa textconv en el contingut de l'objecte" -#: builtin/cat-file.c:490 +#: builtin/cat-file.c:560 +msgid "for blob objects, run filters on object's content" +msgstr "" +"en els objectes de blob, executa els filtres en el contingut de l'objecte" + +#: builtin/cat-file.c:561 git-submodule.sh:923 +msgid "blob" +msgstr "blob" + +#: builtin/cat-file.c:562 +msgid "use a specific path for --textconv/--filters" +msgstr "usa un camí especìfic per a --textconv/--filters" + +#: builtin/cat-file.c:564 msgid "allow -s and -t to work with broken/corrupt objects" msgstr "permet que -s i -t funcionin amb objectes trencats/malmesos" -#: builtin/cat-file.c:491 +#: builtin/cat-file.c:565 msgid "buffer --batch output" msgstr "posa la sortida de --batch en memòria intermèdia" -#: builtin/cat-file.c:493 +#: builtin/cat-file.c:567 msgid "show info and content of objects fed from the standard input" msgstr "" "mostra la informació i contingut dels objectes rebuts de l'entrada estàndard" -#: builtin/cat-file.c:496 +#: builtin/cat-file.c:570 msgid "show info about objects fed from the standard input" msgstr "mostra informació sobre els objectes rebuts de l'entrada estàndard" -#: builtin/cat-file.c:499 +#: builtin/cat-file.c:573 msgid "follow in-tree symlinks (used with --batch or --batch-check)" msgstr "" "segueix els enllaços simbòlics en l'arbre (s'usa amb --batch o --batch-check)" -#: builtin/cat-file.c:501 +#: builtin/cat-file.c:575 msgid "show all objects with --batch or --batch-check" msgstr "mostra tots els objectes amb --batch o --batch-check" @@ -4749,7 +5325,7 @@ msgstr "informa de tots els atributs establerts en el fitxer" msgid "use .gitattributes only from the index" msgstr "usa .gitattributes només des de l'índex" -#: builtin/check-attr.c:21 builtin/check-ignore.c:22 builtin/hash-object.c:97 +#: builtin/check-attr.c:21 builtin/check-ignore.c:22 builtin/hash-object.c:98 msgid "read file names from stdin" msgstr "llegeix els noms de fitxer d'stdin" @@ -4757,7 +5333,7 @@ msgstr "llegeix els noms de fitxer d'stdin" msgid "terminate input and output records by a NUL character" msgstr "acaba els registres d'entrada i de sortida amb un caràcter NUL" -#: builtin/check-ignore.c:18 builtin/checkout.c:1138 builtin/gc.c:325 +#: builtin/check-ignore.c:18 builtin/checkout.c:1137 builtin/gc.c:325 msgid "suppress progress reporting" msgstr "omet el reportatge de progrés" @@ -4847,9 +5423,9 @@ msgid "write the content to temporary files" msgstr "escriu el contingut a fitxers temporals" #: builtin/checkout-index.c:174 builtin/column.c:30 -#: builtin/submodule--helper.c:488 builtin/submodule--helper.c:491 -#: builtin/submodule--helper.c:494 builtin/submodule--helper.c:497 -#: builtin/submodule--helper.c:830 builtin/worktree.c:469 +#: builtin/submodule--helper.c:595 builtin/submodule--helper.c:598 +#: builtin/submodule--helper.c:604 builtin/submodule--helper.c:951 +#: builtin/worktree.c:469 msgid "string" msgstr "cadena" @@ -4897,7 +5473,7 @@ msgstr "camí '%s': no es pot fusionar" #: builtin/checkout.c:230 #, c-format msgid "Unable to add merge result for '%s'" -msgstr "no s'ha pogut afegir el resultat de fusió per a '%s'" +msgstr "No s'ha pogut afegir el resultat de fusió per a '%s'" #: builtin/checkout.c:250 builtin/checkout.c:253 builtin/checkout.c:256 #: builtin/checkout.c:259 @@ -4921,54 +5497,54 @@ msgstr "" msgid "path '%s' is unmerged" msgstr "el camí '%s' està sense fusionar" -#: builtin/checkout.c:495 +#: builtin/checkout.c:494 msgid "you need to resolve your current index first" msgstr "heu de primer resoldre el vostre índex actual" -#: builtin/checkout.c:625 +#: builtin/checkout.c:624 #, c-format msgid "Can not do reflog for '%s': %s\n" msgstr "No es pot fer reflog per a '%s': %s\n" -#: builtin/checkout.c:664 +#: builtin/checkout.c:663 msgid "HEAD is now at" msgstr "HEAD ara és a" -#: builtin/checkout.c:668 builtin/clone.c:661 +#: builtin/checkout.c:667 builtin/clone.c:660 msgid "unable to update HEAD" msgstr "no s'ha pogut actualitzar HEAD" -#: builtin/checkout.c:672 +#: builtin/checkout.c:671 #, c-format msgid "Reset branch '%s'\n" msgstr "Restableix la branca '%s'\n" -#: builtin/checkout.c:675 +#: builtin/checkout.c:674 #, c-format msgid "Already on '%s'\n" msgstr "Ja en '%s'\n" -#: builtin/checkout.c:679 +#: builtin/checkout.c:678 #, c-format msgid "Switched to and reset branch '%s'\n" msgstr "S'ha agafat i restablert la branca '%s'\n" -#: builtin/checkout.c:681 builtin/checkout.c:1070 +#: builtin/checkout.c:680 builtin/checkout.c:1069 #, c-format msgid "Switched to a new branch '%s'\n" msgstr "S'ha agafat la branca nova '%s'\n" -#: builtin/checkout.c:683 +#: builtin/checkout.c:682 #, c-format msgid "Switched to branch '%s'\n" msgstr "S'ha agafat la branca '%s'\n" -#: builtin/checkout.c:734 +#: builtin/checkout.c:733 #, c-format msgid " ... and %d more.\n" msgstr " ... i %d més.\n" -#: builtin/checkout.c:740 +#: builtin/checkout.c:739 #, c-format msgid "" "Warning: you are leaving %d commit behind, not connected to\n" @@ -4991,7 +5567,7 @@ msgstr[1] "" "\n" "%s\n" -#: builtin/checkout.c:759 +#: builtin/checkout.c:758 #, c-format msgid "" "If you want to keep it by creating a new branch, this may be a good time\n" @@ -5018,150 +5594,150 @@ msgstr[1] "" " git branch %s\n" "\n" -#: builtin/checkout.c:795 +#: builtin/checkout.c:794 msgid "internal error in revision walk" msgstr "error intern en el passeig per revisions" -#: builtin/checkout.c:799 +#: builtin/checkout.c:798 msgid "Previous HEAD position was" msgstr "La posició de HEAD anterior era" -#: builtin/checkout.c:826 builtin/checkout.c:1065 +#: builtin/checkout.c:825 builtin/checkout.c:1064 msgid "You are on a branch yet to be born" msgstr "Sou en una branca que encara ha de nàixer" -#: builtin/checkout.c:971 +#: builtin/checkout.c:970 #, c-format msgid "only one reference expected, %d given." msgstr "s'esperava només una referència, s'han donat %d." -#: builtin/checkout.c:1011 builtin/worktree.c:214 +#: builtin/checkout.c:1010 builtin/worktree.c:214 #, c-format msgid "invalid reference: %s" msgstr "referència no vàlida: %s" -#: builtin/checkout.c:1040 +#: builtin/checkout.c:1039 #, c-format msgid "reference is not a tree: %s" msgstr "la referència no és un arbre: %s" -#: builtin/checkout.c:1079 +#: builtin/checkout.c:1078 msgid "paths cannot be used with switching branches" msgstr "els camins no es poden usar amb canvi de branca" -#: builtin/checkout.c:1082 builtin/checkout.c:1086 +#: builtin/checkout.c:1081 builtin/checkout.c:1085 #, c-format msgid "'%s' cannot be used with switching branches" msgstr "'%s' no es pot usar amb canvi de branca" -#: builtin/checkout.c:1090 builtin/checkout.c:1093 builtin/checkout.c:1098 -#: builtin/checkout.c:1101 +#: builtin/checkout.c:1089 builtin/checkout.c:1092 builtin/checkout.c:1097 +#: builtin/checkout.c:1100 #, c-format msgid "'%s' cannot be used with '%s'" msgstr "'%s' no es pot usar amb '%s'" -#: builtin/checkout.c:1106 +#: builtin/checkout.c:1105 #, c-format msgid "Cannot switch branch to a non-commit '%s'" msgstr "No es pot canviar la branca a la no comissió '%s'" -#: builtin/checkout.c:1139 builtin/checkout.c:1141 builtin/clone.c:88 +#: builtin/checkout.c:1138 builtin/checkout.c:1140 builtin/clone.c:93 #: builtin/remote.c:165 builtin/remote.c:167 builtin/worktree.c:324 #: builtin/worktree.c:326 msgid "branch" msgstr "branca" -#: builtin/checkout.c:1140 +#: builtin/checkout.c:1139 msgid "create and checkout a new branch" msgstr "crea i agafa una branca nova" -#: builtin/checkout.c:1142 +#: builtin/checkout.c:1141 msgid "create/reset and checkout a branch" msgstr "crea/restableix i agafa una branca" -#: builtin/checkout.c:1143 +#: builtin/checkout.c:1142 msgid "create reflog for new branch" msgstr "crea un registre de referència per a la branca nova" -#: builtin/checkout.c:1144 builtin/worktree.c:328 +#: builtin/checkout.c:1143 builtin/worktree.c:328 msgid "detach HEAD at named commit" msgstr "separa HEAD a la comissió anomenada" -#: builtin/checkout.c:1145 +#: builtin/checkout.c:1144 msgid "set upstream info for new branch" msgstr "estableix la informació de font de la branca nova" -#: builtin/checkout.c:1147 +#: builtin/checkout.c:1146 msgid "new-branch" msgstr "branca-nova" -#: builtin/checkout.c:1147 +#: builtin/checkout.c:1146 msgid "new unparented branch" msgstr "branca òrfena nova" -#: builtin/checkout.c:1148 +#: builtin/checkout.c:1147 msgid "checkout our version for unmerged files" msgstr "agafa la versió nostra dels fitxers sense fusionar" -#: builtin/checkout.c:1150 +#: builtin/checkout.c:1149 msgid "checkout their version for unmerged files" msgstr "agafa la versió seva dels fitxers sense fusionar" -#: builtin/checkout.c:1152 +#: builtin/checkout.c:1151 msgid "force checkout (throw away local modifications)" msgstr "agafa a la força (descarta qualsevulla modificació local)" -#: builtin/checkout.c:1153 +#: builtin/checkout.c:1152 msgid "perform a 3-way merge with the new branch" msgstr "realitza una fusió de 3 vies amb la branca nova" -#: builtin/checkout.c:1154 builtin/merge.c:231 +#: builtin/checkout.c:1153 builtin/merge.c:231 msgid "update ignored files (default)" msgstr "actualitza els fitxers ignorats (per defecte)" -#: builtin/checkout.c:1155 builtin/log.c:1459 parse-options.h:250 +#: builtin/checkout.c:1154 builtin/log.c:1466 parse-options.h:251 msgid "style" msgstr "estil" -#: builtin/checkout.c:1156 +#: builtin/checkout.c:1155 msgid "conflict style (merge or diff3)" msgstr "estil de conflicte (fusió o diff3)" -#: builtin/checkout.c:1159 +#: builtin/checkout.c:1158 msgid "do not limit pathspecs to sparse entries only" msgstr "no limitis les especificacions de camí només a entrades disperses" -#: builtin/checkout.c:1161 +#: builtin/checkout.c:1160 msgid "second guess 'git checkout '" msgstr "dubta 'git checkout '" -#: builtin/checkout.c:1163 +#: builtin/checkout.c:1162 msgid "do not check if another worktree is holding the given ref" msgstr "no comprovis si altre arbre de treball té la referència donada" -#: builtin/checkout.c:1164 builtin/clone.c:60 builtin/fetch.c:117 -#: builtin/merge.c:228 builtin/pull.c:116 builtin/push.c:536 +#: builtin/checkout.c:1163 builtin/clone.c:63 builtin/fetch.c:119 +#: builtin/merge.c:228 builtin/pull.c:117 builtin/push.c:536 #: builtin/send-pack.c:168 msgid "force progress reporting" msgstr "força l'informe de progrés" -#: builtin/checkout.c:1195 +#: builtin/checkout.c:1194 msgid "-b, -B and --orphan are mutually exclusive" msgstr "-b, -B i --orphan són mutualment exclusius" -#: builtin/checkout.c:1212 +#: builtin/checkout.c:1211 msgid "--track needs a branch name" msgstr "--track necessita un nom de branca" -#: builtin/checkout.c:1217 +#: builtin/checkout.c:1216 msgid "Missing branch name; try -b" msgstr "Manca el nom de branca; proveu -b" -#: builtin/checkout.c:1253 +#: builtin/checkout.c:1252 msgid "invalid path specification" msgstr "especificació de camí no vàlida" -#: builtin/checkout.c:1260 +#: builtin/checkout.c:1259 #, c-format msgid "" "Cannot update paths and switch to branch '%s' at the same time.\n" @@ -5170,12 +5746,12 @@ msgstr "" "No es poden actualitzar els camins i canviar a la branca '%s' a la vegada.\n" "Volíeu agafar '%s', la qual no es pot resoldre com a comissió?" -#: builtin/checkout.c:1265 +#: builtin/checkout.c:1264 #, c-format msgid "git checkout: --detach does not take a path argument '%s'" msgstr "git checkout: --detach no accepta un paràmetre de camí '%s'" -#: builtin/checkout.c:1269 +#: builtin/checkout.c:1268 msgid "" "git checkout: --ours/--theirs, --force and --merge are incompatible when\n" "checking out of the index." @@ -5327,8 +5903,8 @@ msgstr "neteja interactiva" msgid "remove whole directories" msgstr "elimina directoris sencers" -#: builtin/clean.c:875 builtin/describe.c:407 builtin/grep.c:724 -#: builtin/ls-files.c:457 builtin/name-rev.c:314 builtin/show-ref.c:182 +#: builtin/clean.c:875 builtin/describe.c:407 builtin/grep.c:725 +#: builtin/ls-files.c:536 builtin/name-rev.c:313 builtin/show-ref.c:182 msgid "pattern" msgstr "patró" @@ -5368,112 +5944,129 @@ msgstr "" msgid "git clone [] [--] []" msgstr "git clone [] [--] []" -#: builtin/clone.c:62 +#: builtin/clone.c:65 msgid "don't create a checkout" msgstr "no facis cap agafament" -#: builtin/clone.c:63 builtin/clone.c:65 builtin/init-db.c:476 +#: builtin/clone.c:66 builtin/clone.c:68 builtin/init-db.c:478 msgid "create a bare repository" msgstr "crea un dipòsit nu" -#: builtin/clone.c:67 +#: builtin/clone.c:70 msgid "create a mirror repository (implies bare)" msgstr "crea un dipòsit reflectit (implica bare)" -#: builtin/clone.c:69 +#: builtin/clone.c:72 msgid "to clone from a local repository" msgstr "per a clonar des d'un dipòsit local" -#: builtin/clone.c:71 +#: builtin/clone.c:74 msgid "don't use local hardlinks, always copy" msgstr "no usis enllaços durs locals, sempre copia" -#: builtin/clone.c:73 +#: builtin/clone.c:76 msgid "setup as shared repository" msgstr "configura com a dipòsit compartit" -#: builtin/clone.c:75 builtin/clone.c:77 +#: builtin/clone.c:78 builtin/clone.c:80 msgid "initialize submodules in the clone" msgstr "inicialitza els submòduls en el clon" -#: builtin/clone.c:79 +#: builtin/clone.c:82 msgid "number of submodules cloned in parallel" msgstr "nombre de submòduls clonats en paral·lel" -#: builtin/clone.c:80 builtin/init-db.c:473 +#: builtin/clone.c:83 builtin/init-db.c:475 msgid "template-directory" msgstr "directori-de-plantilla" -#: builtin/clone.c:81 builtin/init-db.c:474 +#: builtin/clone.c:84 builtin/init-db.c:476 msgid "directory from which templates will be used" msgstr "directori del qual les plantilles s'usaran" -#: builtin/clone.c:83 builtin/submodule--helper.c:495 -#: builtin/submodule--helper.c:833 +#: builtin/clone.c:86 builtin/clone.c:88 builtin/submodule--helper.c:602 +#: builtin/submodule--helper.c:954 msgid "reference repository" msgstr "dipòsit de referència" -#: builtin/clone.c:85 +#: builtin/clone.c:90 msgid "use --reference only while cloning" msgstr "usa --reference només en clonar" -#: builtin/clone.c:86 builtin/column.c:26 builtin/merge-file.c:44 +#: builtin/clone.c:91 builtin/column.c:26 builtin/merge-file.c:44 msgid "name" msgstr "nom" -#: builtin/clone.c:87 +#: builtin/clone.c:92 msgid "use instead of 'origin' to track upstream" msgstr "usa en lloc de 'origin' per a seguir la font" -#: builtin/clone.c:89 +#: builtin/clone.c:94 msgid "checkout instead of the remote's HEAD" msgstr "agafa en lloc del HEAD del remot" -#: builtin/clone.c:91 +#: builtin/clone.c:96 msgid "path to git-upload-pack on the remote" msgstr "camí a git-upload-pack en el remot" -#: builtin/clone.c:92 builtin/fetch.c:118 builtin/grep.c:667 builtin/pull.c:201 +#: builtin/clone.c:97 builtin/fetch.c:120 builtin/grep.c:668 builtin/pull.c:202 msgid "depth" msgstr "profunditat" -#: builtin/clone.c:93 +#: builtin/clone.c:98 msgid "create a shallow clone of that depth" msgstr "crea un clon superficial de tal profunditat" -#: builtin/clone.c:95 +#: builtin/clone.c:99 builtin/fetch.c:122 builtin/pack-objects.c:2848 +#: parse-options.h:142 +msgid "time" +msgstr "hora" + +#: builtin/clone.c:100 +msgid "create a shallow clone since a specific time" +msgstr "crea un clon superficial des d'una hora específica" + +#: builtin/clone.c:101 builtin/fetch.c:124 +msgid "revision" +msgstr "revisió" + +#: builtin/clone.c:102 builtin/fetch.c:125 +msgid "deepen history of shallow clone by excluding rev" +msgstr "aprofundeix la història d'un clon superficial excloent una revisió" + +#: builtin/clone.c:104 msgid "clone only one branch, HEAD or --branch" msgstr "clona només una branca, HEAD o --branch" -#: builtin/clone.c:97 +#: builtin/clone.c:106 msgid "any cloned submodules will be shallow" msgstr "qualsevol submòdul clonat serà superficial" -#: builtin/clone.c:98 builtin/init-db.c:482 +#: builtin/clone.c:107 builtin/init-db.c:484 msgid "gitdir" msgstr "directori de git" -#: builtin/clone.c:99 builtin/init-db.c:483 +#: builtin/clone.c:108 builtin/init-db.c:485 msgid "separate git dir from working tree" msgstr "separa el directori de git de l'arbre de treball" -#: builtin/clone.c:100 +#: builtin/clone.c:109 msgid "key=value" msgstr "clau=valor" -#: builtin/clone.c:101 +#: builtin/clone.c:110 msgid "set config inside the new repository" msgstr "estableix la configuració dins del dipòsit nou" -#: builtin/clone.c:102 builtin/fetch.c:132 builtin/push.c:547 +#: builtin/clone.c:111 builtin/fetch.c:140 builtin/push.c:547 msgid "use IPv4 addresses only" msgstr "usa només les adreces IPv4" -#: builtin/clone.c:104 builtin/fetch.c:134 builtin/push.c:549 +#: builtin/clone.c:113 builtin/fetch.c:142 builtin/push.c:549 msgid "use IPv6 addresses only" msgstr "usa només les adreces IPv6" -#: builtin/clone.c:241 +#: builtin/clone.c:250 msgid "" "No directory name could be guessed.\n" "Please specify a directory on the command line" @@ -5481,58 +6074,42 @@ msgstr "" "No s'ha pogut endevinar cap nom de directori.\n" "Si us plau, especifiqueu un directori en la línia d'ordres" -#: builtin/clone.c:307 -#, c-format -msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "" -"Encara no se suporta el dipòsit de referència '%s' com a agafament enllaçat." - -#: builtin/clone.c:309 -#, c-format -msgid "reference repository '%s' is not a local repository." -msgstr "el dipòsit de referència '%s' no és un dipòsit local." - -#: builtin/clone.c:314 -#, c-format -msgid "reference repository '%s' is shallow" -msgstr "el dipòsit de referència '%s' és superficial" - -#: builtin/clone.c:317 +#: builtin/clone.c:303 #, c-format -msgid "reference repository '%s' is grafted" -msgstr "el dipòsit de referència '%s' és empeltat" +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "info: No s'ha pogut afegir un alternatiu per a '%s': %s\n" -#: builtin/clone.c:376 +#: builtin/clone.c:375 #, c-format msgid "failed to open '%s'" msgstr "s'ha fallat en obrir '%s'" -#: builtin/clone.c:384 +#: builtin/clone.c:383 #, c-format msgid "%s exists and is not a directory" msgstr "%s existeix i no és directori" -#: builtin/clone.c:398 +#: builtin/clone.c:397 #, c-format msgid "failed to stat %s\n" msgstr "s'ha fallat en fer stat a '%s'\n" -#: builtin/clone.c:420 +#: builtin/clone.c:419 #, c-format msgid "failed to create link '%s'" msgstr "s'ha fallat en crear l'enllaç '%s'" -#: builtin/clone.c:424 +#: builtin/clone.c:423 #, c-format msgid "failed to copy file to '%s'" msgstr "s'ha fallat en copiar el fitxer a '%s'" -#: builtin/clone.c:449 +#: builtin/clone.c:448 #, c-format msgid "done.\n" msgstr "fet.\n" -#: builtin/clone.c:461 +#: builtin/clone.c:460 msgid "" "Clone succeeded, but checkout failed.\n" "You can inspect what was checked out with 'git status'\n" @@ -5543,123 +6120,141 @@ msgstr "" "'git status' i tornar a intentar l'agafament amb\n" "'git checkout -f HEAD'\n" -#: builtin/clone.c:538 +#: builtin/clone.c:537 #, c-format msgid "Could not find remote branch %s to clone." msgstr "No s'ha pogut trobar la branca remota %s per a clonar." -#: builtin/clone.c:633 +#: builtin/clone.c:632 msgid "remote did not send all necessary objects" msgstr "el remot no ha enviat tots els objectes necessaris" -#: builtin/clone.c:649 +#: builtin/clone.c:648 #, c-format msgid "unable to update %s" msgstr "no s'ha pogut actualitzar %s" -#: builtin/clone.c:698 +#: builtin/clone.c:697 msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n" msgstr "" "el HEAD remot es refereix a una referència que no existeix; no s'ha pogut " "agafar.\n" -#: builtin/clone.c:729 +#: builtin/clone.c:728 msgid "unable to checkout working tree" msgstr "no s'ha pogut agafar l'arbre de treball" -#: builtin/clone.c:766 +#: builtin/clone.c:768 msgid "unable to write parameters to config file" msgstr "no s'ha pogut escriure els paràmetres al fitxer de configuració" -#: builtin/clone.c:829 +#: builtin/clone.c:831 msgid "cannot repack to clean up" msgstr "no es pot reempaquetar per a netejar" -#: builtin/clone.c:831 +#: builtin/clone.c:833 msgid "cannot unlink temporary alternates file" msgstr "no es pot desenllaçar el fitxer d'alternatives temporal" -#: builtin/clone.c:863 builtin/receive-pack.c:1855 +#: builtin/clone.c:866 builtin/receive-pack.c:1895 msgid "Too many arguments." msgstr "Hi ha massa paràmetres." -#: builtin/clone.c:867 +#: builtin/clone.c:870 msgid "You must specify a repository to clone." msgstr "Heu d'especificar un dipòsit per a clonar." -#: builtin/clone.c:878 +#: builtin/clone.c:883 #, c-format msgid "--bare and --origin %s options are incompatible." msgstr "les opcions --bare i --origin %s són incompatibles." -#: builtin/clone.c:881 +#: builtin/clone.c:886 msgid "--bare and --separate-git-dir are incompatible." msgstr "--bare i --separate-git-dir són incompatibles." -#: builtin/clone.c:894 +#: builtin/clone.c:899 #, c-format msgid "repository '%s' does not exist" msgstr "el dipòsit '%s' no existeix" -#: builtin/clone.c:900 builtin/fetch.c:1293 +#: builtin/clone.c:905 builtin/fetch.c:1338 #, c-format msgid "depth %s is not a positive number" msgstr "la profunditat %s no és nombre positiu" -#: builtin/clone.c:910 +#: builtin/clone.c:915 #, c-format msgid "destination path '%s' already exists and is not an empty directory." msgstr "el camí destí '%s' ja existeix i no és un directori buit." -#: builtin/clone.c:920 +#: builtin/clone.c:925 #, c-format msgid "working tree '%s' already exists." msgstr "l'arbre de treball '%s' ja existeix." -#: builtin/clone.c:935 builtin/clone.c:946 builtin/submodule--helper.c:544 +#: builtin/clone.c:940 builtin/clone.c:951 builtin/submodule--helper.c:657 #: builtin/worktree.c:222 builtin/worktree.c:249 #, c-format msgid "could not create leading directories of '%s'" msgstr "no s'ha pogut crear els directoris inicials de '%s'" -#: builtin/clone.c:938 +#: builtin/clone.c:943 #, c-format msgid "could not create work tree dir '%s'" msgstr "no s'ha pogut crear el directori d'arbre de treball '%s'" -#: builtin/clone.c:956 +#: builtin/clone.c:955 #, c-format msgid "Cloning into bare repository '%s'...\n" msgstr "S'està clonant al dipòsit nu '%s'...\n" -#: builtin/clone.c:958 +#: builtin/clone.c:957 #, c-format msgid "Cloning into '%s'...\n" msgstr "S'està clonant a '%s'...\n" -#: builtin/clone.c:997 +#: builtin/clone.c:963 +msgid "" +"clone --recursive is not compatible with both --reference and --reference-if-" +"able" +msgstr "" +"clone --recursive no és compatible amb ambdòs --reference i --reference-if-" +"able" + +#: builtin/clone.c:1019 msgid "--depth is ignored in local clones; use file:// instead." msgstr "--depth s'ignora en els clons locals; useu file:// en lloc d'això." -#: builtin/clone.c:1000 +#: builtin/clone.c:1021 +msgid "--shallow-since is ignored in local clones; use file:// instead." +msgstr "" +"--shallow-since s'ignora en els clons locals; useu file:// en lloc d'això." + +#: builtin/clone.c:1023 +msgid "--shallow-exclude is ignored in local clones; use file:// instead." +msgstr "" +"--shallow-exclude s'ignora en els clons locals; useu file:// en lloc d'això." + +#: builtin/clone.c:1026 msgid "source repository is shallow, ignoring --local" msgstr "el dipòsit font és superficial, s'està ignorant --local" -#: builtin/clone.c:1005 +#: builtin/clone.c:1031 msgid "--local is ignored" msgstr "--local s'ignora" -#: builtin/clone.c:1009 +#: builtin/clone.c:1035 #, c-format msgid "Don't know how to clone %s" msgstr "No se sap com clonar %s" -#: builtin/clone.c:1058 builtin/clone.c:1066 +#: builtin/clone.c:1090 builtin/clone.c:1098 #, c-format msgid "Remote branch %s not found in upstream %s" msgstr "La branca remota %s no es troba en la font %s" -#: builtin/clone.c:1069 +#: builtin/clone.c:1101 msgid "You appear to have cloned an empty repository." msgstr "Sembla que heu clonat un dipòsit buit." @@ -5801,66 +6396,66 @@ msgstr "" "Llavors \"git cherry-pick --continue\" reprendrà recollint\n" "com a cireres les comissions restants.\n" -#: builtin/commit.c:308 +#: builtin/commit.c:318 msgid "failed to unpack HEAD tree object" msgstr "s'ha fallat en desempaquetar l'objecte d'arbre HEAD" -#: builtin/commit.c:349 +#: builtin/commit.c:359 msgid "unable to create temporary index" msgstr "no s'ha pogut crear un índex temporal" -#: builtin/commit.c:355 +#: builtin/commit.c:365 msgid "interactive add failed" msgstr "l'afegiment interactiu ha fallat" -#: builtin/commit.c:368 +#: builtin/commit.c:378 msgid "unable to update temporary index" msgstr "no s'ha pogut actualitzar l'índex temporal" -#: builtin/commit.c:370 +#: builtin/commit.c:380 msgid "Failed to update main cache tree" msgstr "S'ha fallat en actualitzar l'arbre principal de memòria cau" -#: builtin/commit.c:394 builtin/commit.c:417 builtin/commit.c:466 +#: builtin/commit.c:404 builtin/commit.c:427 builtin/commit.c:476 msgid "unable to write new_index file" msgstr "no s'ha pogut escriure el fitxer new_index" -#: builtin/commit.c:448 +#: builtin/commit.c:458 msgid "cannot do a partial commit during a merge." msgstr "no es pot fer una comissió parcial durant una fusió." -#: builtin/commit.c:450 +#: builtin/commit.c:460 msgid "cannot do a partial commit during a cherry-pick." msgstr "no es pot fer una comissió parcial durant un recull de cireres." -#: builtin/commit.c:459 +#: builtin/commit.c:469 msgid "cannot read the index" msgstr "no es pot llegir l'índex" -#: builtin/commit.c:478 +#: builtin/commit.c:488 msgid "unable to write temporary index file" msgstr "no s'ha pogut escriure un fitxer d'índex temporal" -#: builtin/commit.c:583 +#: builtin/commit.c:582 #, c-format msgid "commit '%s' lacks author header" msgstr "a la comissió '%s' li manca la capçalera d'autor" -#: builtin/commit.c:585 +#: builtin/commit.c:584 #, c-format msgid "commit '%s' has malformed author line" msgstr "la comissió '%s' té una línia d'autor mal formada" -#: builtin/commit.c:604 +#: builtin/commit.c:603 msgid "malformed --author parameter" msgstr "paràmetre --author mal format" -#: builtin/commit.c:612 +#: builtin/commit.c:611 #, c-format msgid "invalid date format: %s" msgstr "format de data no vàlid: %s" -#: builtin/commit.c:656 +#: builtin/commit.c:655 msgid "" "unable to select a comment character that is not used\n" "in the current commit message" @@ -5868,38 +6463,38 @@ msgstr "" "no es pot seleccionar un caràcter de comentari que\n" "no sigui usat en el missatge de comissió actual" -#: builtin/commit.c:693 builtin/commit.c:726 builtin/commit.c:1092 +#: builtin/commit.c:692 builtin/commit.c:725 builtin/commit.c:1096 #, c-format msgid "could not lookup commit %s" msgstr "no s'ha pogut trobar la comissió %s" -#: builtin/commit.c:705 builtin/shortlog.c:286 +#: builtin/commit.c:704 builtin/shortlog.c:286 #, c-format msgid "(reading log message from standard input)\n" msgstr "(s'està llegint el missatge de registre des de l'entrada estàndard)\n" -#: builtin/commit.c:707 +#: builtin/commit.c:706 msgid "could not read log from standard input" msgstr "no s'ha pogut llegir el registre des de l'entrada estàndard" -#: builtin/commit.c:711 +#: builtin/commit.c:710 #, c-format msgid "could not read log file '%s'" msgstr "no s'ha pogut llegir el fitxer de registre '%s'" -#: builtin/commit.c:738 builtin/commit.c:746 +#: builtin/commit.c:737 builtin/commit.c:745 msgid "could not read SQUASH_MSG" msgstr "no s'ha pogut llegir SQUASH_MSG" -#: builtin/commit.c:743 +#: builtin/commit.c:742 msgid "could not read MERGE_MSG" msgstr "no s'ha pogut llegir MERGE_MSG" -#: builtin/commit.c:797 +#: builtin/commit.c:796 msgid "could not write commit template" msgstr "no s'ha pogut escriure la plantilla de comissió" -#: builtin/commit.c:815 +#: builtin/commit.c:814 #, c-format msgid "" "\n" @@ -5914,7 +6509,7 @@ msgstr "" "\t%s\n" "i intenteu-ho de nou.\n" -#: builtin/commit.c:820 +#: builtin/commit.c:819 #, c-format msgid "" "\n" @@ -5929,7 +6524,7 @@ msgstr "" "\t%s\n" "i intenteu-ho de nou.\n" -#: builtin/commit.c:833 +#: builtin/commit.c:832 #, c-format msgid "" "Please enter the commit message for your changes. Lines starting\n" @@ -5939,7 +6534,7 @@ msgstr "" "S'ignoraran les línies començant amb '%c', i un missatge de\n" "comissió buit avorta la comissió.\n" -#: builtin/commit.c:840 +#: builtin/commit.c:839 #, c-format msgid "" "Please enter the commit message for your changes. Lines starting\n" @@ -5950,150 +6545,154 @@ msgstr "" "Es retindran les línies començants amb '%c'; podeu eliminar-les per vós\n" "mateix si voleu. Un missatge buit avorta la comissió.\n" -#: builtin/commit.c:860 +#: builtin/commit.c:859 #, c-format msgid "%sAuthor: %.*s <%.*s>" msgstr "%sAutor: %.*s <%.*s>" -#: builtin/commit.c:868 +#: builtin/commit.c:867 #, c-format msgid "%sDate: %s" msgstr "%sData: %s" -#: builtin/commit.c:875 +#: builtin/commit.c:874 #, c-format msgid "%sCommitter: %.*s <%.*s>" msgstr "%sComitent: %.*s <%.*s>" -#: builtin/commit.c:893 +#: builtin/commit.c:892 msgid "Cannot read index" msgstr "No es pot llegir l'índex" -#: builtin/commit.c:950 +#: builtin/commit.c:954 msgid "Error building trees" msgstr "Error en construir arbres" -#: builtin/commit.c:965 builtin/tag.c:266 +#: builtin/commit.c:969 builtin/tag.c:266 #, c-format msgid "Please supply the message using either -m or -F option.\n" msgstr "Si us plau, proveïu el missatge per usar o l'opció -m o l'opció -F.\n" -#: builtin/commit.c:1067 +#: builtin/commit.c:1071 #, c-format msgid "--author '%s' is not 'Name ' and matches no existing author" msgstr "" "--author '%s' no és 'Nom ' i no coincideix amb\n" "cap autor existent" -#: builtin/commit.c:1082 builtin/commit.c:1322 +#: builtin/commit.c:1086 builtin/commit.c:1327 #, c-format msgid "Invalid untracked files mode '%s'" msgstr "Mode de fitxers no seguits no vàlid '%s'" -#: builtin/commit.c:1119 +#: builtin/commit.c:1124 msgid "--long and -z are incompatible" msgstr "--long i -z són incompatibles" -#: builtin/commit.c:1149 +#: builtin/commit.c:1154 msgid "Using both --reset-author and --author does not make sense" msgstr "Usar ambdós --reset-author i --author no té sentit" -#: builtin/commit.c:1158 +#: builtin/commit.c:1163 msgid "You have nothing to amend." msgstr "No teniu res a esmenar." -#: builtin/commit.c:1161 +#: builtin/commit.c:1166 msgid "You are in the middle of a merge -- cannot amend." msgstr "Esteu enmig d'una fusió -- no es pot esmenar." -#: builtin/commit.c:1163 +#: builtin/commit.c:1168 msgid "You are in the middle of a cherry-pick -- cannot amend." msgstr "Esteu enmig d'un recull de cireres -- no es pot esmenar." -#: builtin/commit.c:1166 +#: builtin/commit.c:1171 msgid "Options --squash and --fixup cannot be used together" msgstr "Les opcions --squash i --fixup no es poden usar juntes" -#: builtin/commit.c:1176 +#: builtin/commit.c:1181 msgid "Only one of -c/-C/-F/--fixup can be used." msgstr "Només un de -c/-C/-F/--fixup es pot usar." -#: builtin/commit.c:1178 +#: builtin/commit.c:1183 msgid "Option -m cannot be combined with -c/-C/-F/--fixup." msgstr "L'opció -m no es pot combinar amb -c/-C/-F/--fixup." -#: builtin/commit.c:1186 +#: builtin/commit.c:1191 msgid "--reset-author can be used only with -C, -c or --amend." msgstr "--reset-author només es pot usar amb -C, -c o --amend." -#: builtin/commit.c:1203 +#: builtin/commit.c:1208 msgid "Only one of --include/--only/--all/--interactive/--patch can be used." msgstr "Només un de --include/--only/--all/--interactive/--patch es pot usar." -#: builtin/commit.c:1205 +#: builtin/commit.c:1210 msgid "No paths with --include/--only does not make sense." msgstr "--include/--only no té sentit sense camí." -#: builtin/commit.c:1207 +#: builtin/commit.c:1212 msgid "Clever... amending the last one with dirty index." msgstr "Intel·ligent... s'està esmenant l'últim amb índex brut." -#: builtin/commit.c:1209 +#: builtin/commit.c:1214 msgid "Explicit paths specified without -i or -o; assuming --only paths..." msgstr "" "S'han especificat camins explícits sense -i o -o; s'està presumint camins --" "only..." -#: builtin/commit.c:1221 builtin/tag.c:474 +#: builtin/commit.c:1226 builtin/tag.c:474 #, c-format msgid "Invalid cleanup mode %s" msgstr "Mode de neteja no vàlid %s" -#: builtin/commit.c:1226 +#: builtin/commit.c:1231 msgid "Paths with -a does not make sense." msgstr "-a no té sentit amb camins." -#: builtin/commit.c:1336 builtin/commit.c:1622 +#: builtin/commit.c:1341 builtin/commit.c:1617 msgid "show status concisely" msgstr "mostra l'estat concisament" -#: builtin/commit.c:1338 builtin/commit.c:1624 +#: builtin/commit.c:1343 builtin/commit.c:1619 msgid "show branch information" msgstr "mostra la informació de branca" -#: builtin/commit.c:1340 builtin/commit.c:1626 builtin/push.c:522 +#: builtin/commit.c:1345 +msgid "version" +msgstr "versió" + +#: builtin/commit.c:1345 builtin/commit.c:1621 builtin/push.c:522 #: builtin/worktree.c:440 msgid "machine-readable output" msgstr "sortida llegible per màquina" -#: builtin/commit.c:1343 builtin/commit.c:1628 +#: builtin/commit.c:1348 builtin/commit.c:1623 msgid "show status in long format (default)" msgstr "mostra l'estat en format llarg (per defecte)" -#: builtin/commit.c:1346 builtin/commit.c:1631 +#: builtin/commit.c:1351 builtin/commit.c:1626 msgid "terminate entries with NUL" msgstr "acaba les entrades amb NUL" -#: builtin/commit.c:1348 builtin/commit.c:1634 builtin/fast-export.c:981 +#: builtin/commit.c:1353 builtin/commit.c:1629 builtin/fast-export.c:981 #: builtin/fast-export.c:984 builtin/tag.c:353 msgid "mode" msgstr "mode" -#: builtin/commit.c:1349 builtin/commit.c:1634 +#: builtin/commit.c:1354 builtin/commit.c:1629 msgid "show untracked files, optional modes: all, normal, no. (Default: all)" msgstr "" "mostra els fitxers no seguits, modes opcionals: all, normal, no. (Per " "defecte: all)" -#: builtin/commit.c:1352 +#: builtin/commit.c:1357 msgid "show ignored files" msgstr "mostra els fitxers ignorats" -#: builtin/commit.c:1353 parse-options.h:155 +#: builtin/commit.c:1358 parse-options.h:155 msgid "when" msgstr "quan" -#: builtin/commit.c:1354 +#: builtin/commit.c:1359 msgid "" "ignore changes to submodules, optional when: all, dirty, untracked. " "(Default: all)" @@ -6101,202 +6700,202 @@ msgstr "" "ignora els canvis als submòduls, opcional quan: all, dirty, untracked. (Per " "defecte: all)" -#: builtin/commit.c:1356 +#: builtin/commit.c:1361 msgid "list untracked files in columns" msgstr "mostra els fitxers no seguits en columnes" -#: builtin/commit.c:1442 +#: builtin/commit.c:1437 msgid "couldn't look up newly created commit" msgstr "no s'ha pogut trobar la comissió novament creada" -#: builtin/commit.c:1444 +#: builtin/commit.c:1439 msgid "could not parse newly created commit" msgstr "no s'ha pogut analitzar la comissió novament creada" -#: builtin/commit.c:1489 +#: builtin/commit.c:1484 msgid "detached HEAD" msgstr "HEAD separat" -#: builtin/commit.c:1492 +#: builtin/commit.c:1487 msgid " (root-commit)" msgstr " (comissió d'arrel)" -#: builtin/commit.c:1592 +#: builtin/commit.c:1587 msgid "suppress summary after successful commit" msgstr "omet el resum després d'una comissió reeixida" -#: builtin/commit.c:1593 +#: builtin/commit.c:1588 msgid "show diff in commit message template" msgstr "mostra la diferència en la plantilla de missatge de comissió" -#: builtin/commit.c:1595 +#: builtin/commit.c:1590 msgid "Commit message options" msgstr "Opcions de missatge de comissió" -#: builtin/commit.c:1596 builtin/tag.c:351 +#: builtin/commit.c:1591 builtin/tag.c:351 msgid "read message from file" msgstr "llegiu el missatge des d'un fitxer" -#: builtin/commit.c:1597 +#: builtin/commit.c:1592 msgid "author" msgstr "autor" -#: builtin/commit.c:1597 +#: builtin/commit.c:1592 msgid "override author for commit" msgstr "autor corregit de la comissió" -#: builtin/commit.c:1598 builtin/gc.c:326 +#: builtin/commit.c:1593 builtin/gc.c:326 msgid "date" msgstr "data" -#: builtin/commit.c:1598 +#: builtin/commit.c:1593 msgid "override date for commit" msgstr "data corregida de la comissió" -#: builtin/commit.c:1599 builtin/merge.c:220 builtin/notes.c:396 -#: builtin/notes.c:559 builtin/tag.c:349 +#: builtin/commit.c:1594 builtin/merge.c:220 builtin/notes.c:398 +#: builtin/notes.c:561 builtin/tag.c:349 msgid "message" msgstr "missatge" -#: builtin/commit.c:1599 +#: builtin/commit.c:1594 msgid "commit message" msgstr "missatge de comissió" -#: builtin/commit.c:1600 builtin/commit.c:1601 builtin/commit.c:1602 -#: builtin/commit.c:1603 parse-options.h:256 ref-filter.h:79 +#: builtin/commit.c:1595 builtin/commit.c:1596 builtin/commit.c:1597 +#: builtin/commit.c:1598 parse-options.h:257 ref-filter.h:79 msgid "commit" msgstr "comissió" -#: builtin/commit.c:1600 +#: builtin/commit.c:1595 msgid "reuse and edit message from specified commit" msgstr "reusa i edita el missatge de la comissió especificada" -#: builtin/commit.c:1601 +#: builtin/commit.c:1596 msgid "reuse message from specified commit" msgstr "reusa el missatge de la comissió especificada" -#: builtin/commit.c:1602 +#: builtin/commit.c:1597 msgid "use autosquash formatted message to fixup specified commit" msgstr "" "usa el missatge formatat d'aixafada automàtica per a arreglar la comissió " "especificada" -#: builtin/commit.c:1603 +#: builtin/commit.c:1598 msgid "use autosquash formatted message to squash specified commit" msgstr "" "usa el missatge formatat d'aixafada automàtica per a aixafar la comissió " "especificada" -#: builtin/commit.c:1604 +#: builtin/commit.c:1599 msgid "the commit is authored by me now (used with -C/-c/--amend)" msgstr "l'autor de la comissió ja sóc jo (s'usa amb -C/-c/--amend)" -#: builtin/commit.c:1605 builtin/log.c:1409 builtin/revert.c:86 +#: builtin/commit.c:1600 builtin/log.c:1413 builtin/revert.c:86 msgid "add Signed-off-by:" msgstr "afegeix Signed-off-by:" -#: builtin/commit.c:1606 +#: builtin/commit.c:1601 msgid "use specified template file" msgstr "usa el fitxer de plantilla especificat" -#: builtin/commit.c:1607 +#: builtin/commit.c:1602 msgid "force edit of commit" msgstr "força l'edició de la comissió" -#: builtin/commit.c:1608 +#: builtin/commit.c:1603 msgid "default" msgstr "per defecte" -#: builtin/commit.c:1608 builtin/tag.c:354 +#: builtin/commit.c:1603 builtin/tag.c:354 msgid "how to strip spaces and #comments from message" msgstr "com despullar els espais i #comentaris del missatge" -#: builtin/commit.c:1609 +#: builtin/commit.c:1604 msgid "include status in commit message template" msgstr "inclou l'estat en la plantilla de missatge de comissió" -#: builtin/commit.c:1611 builtin/merge.c:230 builtin/pull.c:165 +#: builtin/commit.c:1606 builtin/merge.c:230 builtin/pull.c:166 #: builtin/revert.c:93 msgid "GPG sign commit" msgstr "signa la comissió amb GPG" -#: builtin/commit.c:1614 +#: builtin/commit.c:1609 msgid "Commit contents options" msgstr "Opcions dels continguts de les comissions" -#: builtin/commit.c:1615 +#: builtin/commit.c:1610 msgid "commit all changed files" msgstr "comet tots els fitxers canviats" -#: builtin/commit.c:1616 +#: builtin/commit.c:1611 msgid "add specified files to index for commit" msgstr "afegeix els fitxers especificats a l'índex per a cometre" -#: builtin/commit.c:1617 +#: builtin/commit.c:1612 msgid "interactively add files" msgstr "afegeix els fitxers interactivament" -#: builtin/commit.c:1618 +#: builtin/commit.c:1613 msgid "interactively add changes" msgstr "afegeix els canvis interactivament" -#: builtin/commit.c:1619 +#: builtin/commit.c:1614 msgid "commit only specified files" msgstr "comet només els fitxers especificats" -#: builtin/commit.c:1620 +#: builtin/commit.c:1615 msgid "bypass pre-commit and commit-msg hooks" msgstr "evita els ganxos de precomissió i missatge de comissió" -#: builtin/commit.c:1621 +#: builtin/commit.c:1616 msgid "show what would be committed" msgstr "mostra què es cometria" -#: builtin/commit.c:1632 +#: builtin/commit.c:1627 msgid "amend previous commit" msgstr "esmena la comissió anterior" -#: builtin/commit.c:1633 +#: builtin/commit.c:1628 msgid "bypass post-rewrite hook" msgstr "evita el ganxo de postreescriure" -#: builtin/commit.c:1638 +#: builtin/commit.c:1633 msgid "ok to record an empty change" msgstr "està bé registrar un canvi buit" -#: builtin/commit.c:1640 +#: builtin/commit.c:1635 msgid "ok to record a change with an empty message" msgstr "està bé registrar un canvi amb missatge buit" -#: builtin/commit.c:1669 +#: builtin/commit.c:1664 msgid "could not parse HEAD commit" msgstr "no s'ha pogut analitzar la comissió HEAD" -#: builtin/commit.c:1719 +#: builtin/commit.c:1712 #, c-format msgid "Corrupt MERGE_HEAD file (%s)" msgstr "Fitxer MERGE_HEAD malmès (%s)" -#: builtin/commit.c:1726 +#: builtin/commit.c:1719 msgid "could not read MERGE_MODE" msgstr "no s'ha pogut llegir MERGE_MODE" -#: builtin/commit.c:1745 +#: builtin/commit.c:1738 #, c-format msgid "could not read commit message: %s" msgstr "no s'ha pogut llegir el missatge de comissió: %s" -#: builtin/commit.c:1756 +#: builtin/commit.c:1749 #, c-format msgid "Aborting commit; you did not edit the message.\n" msgstr "S'està avortant la comissió; no heu editat el missatge.\n" -#: builtin/commit.c:1761 +#: builtin/commit.c:1754 #, c-format msgid "Aborting commit due to empty commit message.\n" msgstr "S'està avortant la comissió a causa d'un missatge de comissió buit.\n" -#: builtin/commit.c:1809 +#: builtin/commit.c:1802 msgid "" "Repository has been updated, but unable to write\n" "new_index file. Check that disk is not full and quota is\n" @@ -6466,17 +7065,26 @@ msgstr "" msgid "cannot create configuration file %s" msgstr "no es pot crear el fitxer de configuració '%s'" -#: builtin/count-objects.c:77 +#: builtin/config.c:625 +#, c-format +msgid "" +"cannot overwrite multiple values with a single value\n" +" Use a regexp, --add or --replace-all to change %s." +msgstr "" +"no es pot sobreescriure múltiples valors amb un sol valor\n" +" Useu una expresió regular, --add o --replace-all per a canviar %s." + +#: builtin/count-objects.c:86 msgid "git count-objects [-v] [-H | --human-readable]" msgstr "git count-objects [-v] [-H | --human-readable]" -#: builtin/count-objects.c:87 +#: builtin/count-objects.c:96 msgid "print sizes in human readable format" msgstr "imprimeix les mides en un format llegible pels humans" #: builtin/describe.c:17 msgid "git describe [] [...]" -msgstr "git describe [opcions] [...]" +msgstr "git describe [] [...]" #: builtin/describe.c:18 msgid "git describe [] --dirty" @@ -6590,7 +7198,7 @@ msgstr "considera les etiquetes més recents (per defecte: 10)" msgid "only consider tags matching " msgstr "només considera les etiquetes que coincideixen amb " -#: builtin/describe.c:410 builtin/name-rev.c:321 +#: builtin/describe.c:410 builtin/name-rev.c:320 msgid "show abbreviated commit object as fallback" msgstr "mostra l'objecte de comissió abreviat com a retrocediment" @@ -6624,21 +7232,21 @@ msgstr "'%s': no és ni fitxer regular ni enllaç simbòlic" msgid "invalid option: %s" msgstr "opció no vàlida: %s" -#: builtin/diff.c:360 +#: builtin/diff.c:361 msgid "Not a git repository" msgstr "No és un dipòsit de git" -#: builtin/diff.c:403 +#: builtin/diff.c:404 #, c-format msgid "invalid object '%s' given." msgstr "s'ha donat un objecte no vàlid '%s'." -#: builtin/diff.c:412 +#: builtin/diff.c:413 #, c-format msgid "more than two blobs given: '%s'" msgstr "s'ha donat més de dos blobs: '%s" -#: builtin/diff.c:419 +#: builtin/diff.c:420 #, c-format msgid "unhandled object '%s' given." msgstr "s'ha donat l'objecte no gestionat '%s'." @@ -6711,162 +7319,166 @@ msgstr "git fetch --multiple [] [( | )...]" msgid "git fetch --all []" msgstr "git fetch --all []" -#: builtin/fetch.c:93 builtin/pull.c:174 +#: builtin/fetch.c:95 builtin/pull.c:175 msgid "fetch from all remotes" msgstr "obtén de tots els remots" -#: builtin/fetch.c:95 builtin/pull.c:177 +#: builtin/fetch.c:97 builtin/pull.c:178 msgid "append to .git/FETCH_HEAD instead of overwriting" msgstr "annexa a .git/FETCH_HEAD en lloc de sobreescriure" -#: builtin/fetch.c:97 builtin/pull.c:180 +#: builtin/fetch.c:99 builtin/pull.c:181 msgid "path to upload pack on remote end" msgstr "camí al qual pujar el paquet al costat remot" -#: builtin/fetch.c:98 builtin/pull.c:182 +#: builtin/fetch.c:100 builtin/pull.c:183 msgid "force overwrite of local branch" msgstr "força la sobreescriptura de la branca local" -#: builtin/fetch.c:100 +#: builtin/fetch.c:102 msgid "fetch from multiple remotes" msgstr "obtén de múltiples remots" -#: builtin/fetch.c:102 builtin/pull.c:184 +#: builtin/fetch.c:104 builtin/pull.c:185 msgid "fetch all tags and associated objects" msgstr "obtén totes les etiquetes i tots els objectes associats" -#: builtin/fetch.c:104 +#: builtin/fetch.c:106 msgid "do not fetch all tags (--no-tags)" msgstr "no obtinguis les etiquetes (--no-tags)" -#: builtin/fetch.c:106 +#: builtin/fetch.c:108 msgid "number of submodules fetched in parallel" msgstr "nombre de submòduls obtinguts en paral·lel" -#: builtin/fetch.c:108 builtin/pull.c:187 +#: builtin/fetch.c:110 builtin/pull.c:188 msgid "prune remote-tracking branches no longer on remote" msgstr "poda les branques amb seguiment remot que ja no estiguin en el remot" -#: builtin/fetch.c:109 builtin/pull.c:190 +#: builtin/fetch.c:111 builtin/pull.c:191 msgid "on-demand" msgstr "sota demanda" -#: builtin/fetch.c:110 builtin/pull.c:191 +#: builtin/fetch.c:112 builtin/pull.c:192 msgid "control recursive fetching of submodules" msgstr "controla l'obtenció recursiva de submòduls" -#: builtin/fetch.c:114 builtin/pull.c:199 +#: builtin/fetch.c:116 builtin/pull.c:200 msgid "keep downloaded pack" msgstr "retén el paquet baixat" -#: builtin/fetch.c:116 +#: builtin/fetch.c:118 msgid "allow updating of HEAD ref" msgstr "permet l'actualització de la referència HEAD" -#: builtin/fetch.c:119 builtin/pull.c:202 +#: builtin/fetch.c:121 builtin/fetch.c:127 builtin/pull.c:203 msgid "deepen history of shallow clone" msgstr "aprofundeix la història d'un clon superficial" -#: builtin/fetch.c:121 builtin/pull.c:205 +#: builtin/fetch.c:123 +msgid "deepen history of shallow repository based on time" +msgstr "aprofundeix la història d'un clon superficial basat en temps" + +#: builtin/fetch.c:129 builtin/pull.c:206 msgid "convert to a complete repository" msgstr "converteix en un dipòsit complet" -#: builtin/fetch.c:123 builtin/log.c:1426 +#: builtin/fetch.c:131 builtin/log.c:1433 msgid "dir" msgstr "directori" -#: builtin/fetch.c:124 +#: builtin/fetch.c:132 msgid "prepend this to submodule path output" msgstr "anteposa això a la sortida de camí del submòdul" -#: builtin/fetch.c:127 +#: builtin/fetch.c:135 msgid "default mode for recursion" msgstr "mode de recursivitat per defecte" -#: builtin/fetch.c:129 builtin/pull.c:208 +#: builtin/fetch.c:137 builtin/pull.c:209 msgid "accept refs that update .git/shallow" msgstr "accepta les referències que actualitzin .git/shallow" -#: builtin/fetch.c:130 builtin/pull.c:210 +#: builtin/fetch.c:138 builtin/pull.c:211 msgid "refmap" msgstr "mapa de referències" -#: builtin/fetch.c:131 builtin/pull.c:211 +#: builtin/fetch.c:139 builtin/pull.c:212 msgid "specify fetch refmap" msgstr "mostra el mapa de referències d'obtenció" -#: builtin/fetch.c:387 +#: builtin/fetch.c:398 msgid "Couldn't find remote ref HEAD" msgstr "No s'ha pogut trobar la referència HEAD remota" -#: builtin/fetch.c:503 +#: builtin/fetch.c:514 #, c-format msgid "configuration fetch.output contains invalid value %s" msgstr "la configuració fetch.output conté un valor no vàlid %s" -#: builtin/fetch.c:592 +#: builtin/fetch.c:607 #, c-format msgid "object %s not found" msgstr "objecte %s no trobat" -#: builtin/fetch.c:596 +#: builtin/fetch.c:611 msgid "[up to date]" msgstr "[al dia]" -#: builtin/fetch.c:609 builtin/fetch.c:689 +#: builtin/fetch.c:624 builtin/fetch.c:704 msgid "[rejected]" msgstr "[rebutjat]" -#: builtin/fetch.c:610 +#: builtin/fetch.c:625 msgid "can't fetch in current branch" msgstr "no es pot obtenir en la branca actual" -#: builtin/fetch.c:619 +#: builtin/fetch.c:634 msgid "[tag update]" msgstr "[actualització d'etiqueta]" -#: builtin/fetch.c:620 builtin/fetch.c:653 builtin/fetch.c:669 -#: builtin/fetch.c:684 +#: builtin/fetch.c:635 builtin/fetch.c:668 builtin/fetch.c:684 +#: builtin/fetch.c:699 msgid "unable to update local ref" msgstr "no s'ha pogut actualitzar la referència local" -#: builtin/fetch.c:639 +#: builtin/fetch.c:654 msgid "[new tag]" msgstr "[etiqueta nova]" -#: builtin/fetch.c:642 +#: builtin/fetch.c:657 msgid "[new branch]" msgstr "[branca nova]" -#: builtin/fetch.c:645 +#: builtin/fetch.c:660 msgid "[new ref]" msgstr "[referència nova]" -#: builtin/fetch.c:684 +#: builtin/fetch.c:699 msgid "forced update" msgstr "actualització forçada" -#: builtin/fetch.c:689 +#: builtin/fetch.c:704 msgid "non-fast-forward" msgstr "sense avanç ràpid" -#: builtin/fetch.c:733 +#: builtin/fetch.c:749 #, c-format msgid "%s did not send all necessary objects\n" msgstr "%s no ha enviat tots els objectes necessaris\n" -#: builtin/fetch.c:753 +#: builtin/fetch.c:769 #, c-format msgid "reject %s because shallow roots are not allowed to be updated" msgstr "" "rebutja %s perquè no es permet que les arrels superficials s'actualitzin" -#: builtin/fetch.c:839 builtin/fetch.c:934 +#: builtin/fetch.c:856 builtin/fetch.c:952 #, c-format msgid "From %.*s\n" msgstr "De %.*s\n" -#: builtin/fetch.c:850 +#: builtin/fetch.c:867 #, c-format msgid "" "some local refs could not be updated; try running\n" @@ -6876,55 +7488,55 @@ msgstr "" " intenteu executar 'git remote prune %s' per a eliminar\n" " qualsevulla branca antiga o conflictiva" -#: builtin/fetch.c:904 +#: builtin/fetch.c:922 #, c-format msgid " (%s will become dangling)" msgstr " (%s es tornarà penjant)" -#: builtin/fetch.c:905 +#: builtin/fetch.c:923 #, c-format msgid " (%s has become dangling)" msgstr " (%s s'ha tornat penjant)" -#: builtin/fetch.c:937 +#: builtin/fetch.c:955 msgid "[deleted]" msgstr "[suprimit]" -#: builtin/fetch.c:938 builtin/remote.c:1020 +#: builtin/fetch.c:956 builtin/remote.c:1020 msgid "(none)" msgstr "(cap)" -#: builtin/fetch.c:960 +#: builtin/fetch.c:979 #, c-format msgid "Refusing to fetch into current branch %s of non-bare repository" msgstr "S'està refusant obtenir en la branca actual %s d'un dipòsit no nu" -#: builtin/fetch.c:979 +#: builtin/fetch.c:998 #, c-format msgid "Option \"%s\" value \"%s\" is not valid for %s" msgstr "L'opció \"%s\" amb valor \"%s\" no és vàlida per a %s" -#: builtin/fetch.c:982 +#: builtin/fetch.c:1001 #, c-format msgid "Option \"%s\" is ignored for %s\n" msgstr "S'ignora l'opció \"%s\" per a %s\n" -#: builtin/fetch.c:1039 +#: builtin/fetch.c:1077 #, c-format msgid "Don't know how to fetch from %s" msgstr "No se sap com obtenir de %s" -#: builtin/fetch.c:1199 +#: builtin/fetch.c:1237 #, c-format msgid "Fetching %s\n" msgstr "S'està obtenint %s\n" -#: builtin/fetch.c:1201 builtin/remote.c:96 +#: builtin/fetch.c:1239 builtin/remote.c:96 #, c-format msgid "Could not fetch %s" msgstr "No s'ha pogut obtenir %s" -#: builtin/fetch.c:1219 +#: builtin/fetch.c:1257 msgid "" "No remote repository specified. Please, specify either a URL or a\n" "remote name from which new revisions should be fetched." @@ -6932,32 +7544,40 @@ msgstr "" "Cap dipòsit remot especificat. Si us plau, especifiqueu o un URL o\n" "un nom remot del qual es deuen obtenir les revisions noves." -#: builtin/fetch.c:1242 +#: builtin/fetch.c:1280 msgid "You need to specify a tag name." msgstr "Necessiteu especificar un nom d'etiqueta." -#: builtin/fetch.c:1284 +#: builtin/fetch.c:1322 +msgid "Negative depth in --deepen is not supported" +msgstr "No s'admet una profunditat negativa en --deepen" + +#: builtin/fetch.c:1324 +msgid "--deepen and --depth are mutually exclusive" +msgstr "--deepen i --depth són mutualment exclusius" + +#: builtin/fetch.c:1329 msgid "--depth and --unshallow cannot be used together" msgstr "--depth i --unshallow no es poden usar junts" -#: builtin/fetch.c:1286 +#: builtin/fetch.c:1331 msgid "--unshallow on a complete repository does not make sense" msgstr "--unshallow en un dipòsit complet no té sentit" -#: builtin/fetch.c:1306 +#: builtin/fetch.c:1353 msgid "fetch --all does not take a repository argument" msgstr "fetch --all no accepta un paràmetre de dipòsit" -#: builtin/fetch.c:1308 +#: builtin/fetch.c:1355 msgid "fetch --all does not make sense with refspecs" msgstr "fetch --all no té sentit amb especificacions de referència" -#: builtin/fetch.c:1319 +#: builtin/fetch.c:1366 #, c-format msgid "No such remote or remote group: %s" msgstr "No hi ha tal remot ni tal grup remot: %s" -#: builtin/fetch.c:1327 +#: builtin/fetch.c:1374 msgid "Fetching a group and specifying refspecs does not make sense" msgstr "Obtenir un grup i especificar referències no té sentit" @@ -6967,23 +7587,23 @@ msgid "" msgstr "" "git fmt-merge-msg [-m ] [--log[=] | --no-log] [--file ]" -#: builtin/fmt-merge-msg.c:667 +#: builtin/fmt-merge-msg.c:663 msgid "populate log with at most entries from shortlog" msgstr "emplena el registre amb entrades del registre curt com a màxim" -#: builtin/fmt-merge-msg.c:670 +#: builtin/fmt-merge-msg.c:666 msgid "alias for --log (deprecated)" msgstr "àlies per --log (desaprovat)" -#: builtin/fmt-merge-msg.c:673 +#: builtin/fmt-merge-msg.c:669 msgid "text" msgstr "text" -#: builtin/fmt-merge-msg.c:674 +#: builtin/fmt-merge-msg.c:670 msgid "use as start of message" msgstr "usa com a inici de missatge" -#: builtin/fmt-merge-msg.c:675 +#: builtin/fmt-merge-msg.c:671 msgid "file to read from" msgstr "fitxer del qual llegir" @@ -7101,7 +7721,7 @@ msgstr "mostra el progrés" msgid "show verbose names for reachable objects" msgstr "mostra els noms detallats dels objectes abastables" -#: builtin/fsck.c:671 +#: builtin/fsck.c:665 msgid "Checking objects" msgstr "S'estan comprovant els objectes" @@ -7195,228 +7815,223 @@ msgstr "grep: s'ha fallat en crear fil: %s" msgid "invalid number of threads specified (%d) for %s" msgstr "s'ha especificat un nombre de fils no vàlid (%d) per a %s" -#: builtin/grep.c:452 builtin/grep.c:487 +#: builtin/grep.c:453 builtin/grep.c:488 #, c-format msgid "unable to read tree (%s)" msgstr "no s'ha pogut llegir l'arbre (%s)" -#: builtin/grep.c:502 +#: builtin/grep.c:503 #, c-format msgid "unable to grep from object of type %s" msgstr "no es pot fer grep des d'un objecte de tipus %s" -#: builtin/grep.c:560 +#: builtin/grep.c:561 #, c-format msgid "switch `%c' expects a numerical value" msgstr "l'opció `%c' espera un valor numèric" -#: builtin/grep.c:577 -#, c-format -msgid "cannot open '%s'" -msgstr "no es pot obrir '%s'" - -#: builtin/grep.c:646 +#: builtin/grep.c:647 msgid "search in index instead of in the work tree" msgstr "cerca en l'índex en lloc de l'arbre de treball" -#: builtin/grep.c:648 +#: builtin/grep.c:649 msgid "find in contents not managed by git" msgstr "cerca en continguts no gestionats per git" -#: builtin/grep.c:650 +#: builtin/grep.c:651 msgid "search in both tracked and untracked files" msgstr "cerca tant en fitxers seguits com en no seguits" -#: builtin/grep.c:652 +#: builtin/grep.c:653 msgid "ignore files specified via '.gitignore'" msgstr "ignora els fitxers especificats mitjançant '.gitignore'" -#: builtin/grep.c:655 +#: builtin/grep.c:656 msgid "show non-matching lines" msgstr "mostra les línies no coincidents" -#: builtin/grep.c:657 +#: builtin/grep.c:658 msgid "case insensitive matching" msgstr "coincidència insensible a majúscula i minúscula" -#: builtin/grep.c:659 +#: builtin/grep.c:660 msgid "match patterns only at word boundaries" msgstr "coincideix amb els patrons només als límits de paraula" -#: builtin/grep.c:661 +#: builtin/grep.c:662 msgid "process binary files as text" msgstr "processa els fitxers binaris com a text" -#: builtin/grep.c:663 +#: builtin/grep.c:664 msgid "don't match patterns in binary files" msgstr "no coincideixis amb els patrons en els fitxers binaris" -#: builtin/grep.c:666 +#: builtin/grep.c:667 msgid "process binary files with textconv filters" msgstr "processa els fitxers binaris amb filtres de textconv" -#: builtin/grep.c:668 +#: builtin/grep.c:669 msgid "descend at most levels" msgstr "descendeix com a màxim nivells" -#: builtin/grep.c:672 +#: builtin/grep.c:673 msgid "use extended POSIX regular expressions" msgstr "usa les expressions regulars POSIX esteses" -#: builtin/grep.c:675 +#: builtin/grep.c:676 msgid "use basic POSIX regular expressions (default)" msgstr "usa les expressions regulars POSIX bàsiques (per defecte)" -#: builtin/grep.c:678 +#: builtin/grep.c:679 msgid "interpret patterns as fixed strings" msgstr "interpreta els patrons com a cadenes fixes" -#: builtin/grep.c:681 +#: builtin/grep.c:682 msgid "use Perl-compatible regular expressions" msgstr "usa les expressions regulars compatibles amb Perl" -#: builtin/grep.c:684 +#: builtin/grep.c:685 msgid "show line numbers" msgstr "mostra els números de línia" -#: builtin/grep.c:685 +#: builtin/grep.c:686 msgid "don't show filenames" msgstr "no mostris els noms de fitxer" -#: builtin/grep.c:686 +#: builtin/grep.c:687 msgid "show filenames" msgstr "mostra els noms de fitxer" -#: builtin/grep.c:688 +#: builtin/grep.c:689 msgid "show filenames relative to top directory" msgstr "mostra els noms de fitxer relatius al directori superior" -#: builtin/grep.c:690 +#: builtin/grep.c:691 msgid "show only filenames instead of matching lines" msgstr "mostra només els noms de fitxer en lloc de les línies coincidents" -#: builtin/grep.c:692 +#: builtin/grep.c:693 msgid "synonym for --files-with-matches" msgstr "sinònim de --files-with-matches" -#: builtin/grep.c:695 +#: builtin/grep.c:696 msgid "show only the names of files without match" msgstr "mostra només els noms dels fitxers sense coincidència" -#: builtin/grep.c:697 +#: builtin/grep.c:698 msgid "print NUL after filenames" msgstr "imprimeix NUL després dels noms de fitxer" -#: builtin/grep.c:699 +#: builtin/grep.c:700 msgid "show the number of matches instead of matching lines" msgstr "mostra el nombre de coincidències en lloc de les línies coincidents" -#: builtin/grep.c:700 +#: builtin/grep.c:701 msgid "highlight matches" msgstr "ressalta les coincidències" -#: builtin/grep.c:702 +#: builtin/grep.c:703 msgid "print empty line between matches from different files" msgstr "imprimeix una línia buida entre coincidències de fitxers distints" -#: builtin/grep.c:704 +#: builtin/grep.c:705 msgid "show filename only once above matches from same file" msgstr "" "mostra el nom de fitxer només una vegada a dalt de les coincidències del " "mateix fitxer" -#: builtin/grep.c:707 +#: builtin/grep.c:708 msgid "show context lines before and after matches" msgstr "mostra línies de context abans i després d'una coincidència" -#: builtin/grep.c:710 +#: builtin/grep.c:711 msgid "show context lines before matches" msgstr "mostra línies de context abans d'una coincidència" -#: builtin/grep.c:712 +#: builtin/grep.c:713 msgid "show context lines after matches" msgstr "mostra línies de context després d'una coincidència" -#: builtin/grep.c:714 +#: builtin/grep.c:715 msgid "use worker threads" msgstr "usa fils obrers" -#: builtin/grep.c:715 +#: builtin/grep.c:716 msgid "shortcut for -C NUM" msgstr "drecera per -C NUM" -#: builtin/grep.c:718 +#: builtin/grep.c:719 msgid "show a line with the function name before matches" msgstr "mostra una línia amb el nom de funció abans de les coincidències" -#: builtin/grep.c:720 +#: builtin/grep.c:721 msgid "show the surrounding function" msgstr "mostra la funció circumdant" -#: builtin/grep.c:723 +#: builtin/grep.c:724 msgid "read patterns from file" msgstr "llegeix els patrons des d'un fitxer" -#: builtin/grep.c:725 +#: builtin/grep.c:726 msgid "match " msgstr "coincideix amb " -#: builtin/grep.c:727 +#: builtin/grep.c:728 msgid "combine patterns specified with -e" msgstr "combina els patrons especificats amb -e" -#: builtin/grep.c:739 +#: builtin/grep.c:740 msgid "indicate hit with exit status without output" msgstr "indica coincidència amb estat de sortida sense sortida textual" -#: builtin/grep.c:741 +#: builtin/grep.c:742 msgid "show only matches from files that match all patterns" msgstr "" "mostra només les coincidències dels fitxers que coincideixin amb tots els " "patrons" -#: builtin/grep.c:743 +#: builtin/grep.c:744 msgid "show parse tree for grep expression" msgstr "mostra l'arbre d'anàlisis de l'expressió de grep" -#: builtin/grep.c:747 +#: builtin/grep.c:748 msgid "pager" msgstr "paginador" -#: builtin/grep.c:747 +#: builtin/grep.c:748 msgid "show matching files in the pager" msgstr "mostra els fitxers coincidents en el paginador" -#: builtin/grep.c:750 +#: builtin/grep.c:751 msgid "allow calling of grep(1) (ignored by this build)" msgstr "permet la invocació de grep(1) (ignorat per aquesta compilació)" -#: builtin/grep.c:813 +#: builtin/grep.c:814 msgid "no pattern given." msgstr "cap patró donat." -#: builtin/grep.c:845 builtin/index-pack.c:1479 +#: builtin/grep.c:846 builtin/index-pack.c:1480 #, c-format msgid "invalid number of threads specified (%d)" msgstr "s'ha especificat un nombre de fils no vàlid (%d)" -#: builtin/grep.c:875 +#: builtin/grep.c:876 msgid "--open-files-in-pager only works on the worktree" msgstr "--open-files-in-pager només funciona en l'arbre de treball" -#: builtin/grep.c:901 +#: builtin/grep.c:902 msgid "--cached or --untracked cannot be used with --no-index." msgstr "--cached o --untracked no es pot usar amb --no-index." -#: builtin/grep.c:906 +#: builtin/grep.c:907 msgid "--no-index or --untracked cannot be used with revs." msgstr "--no-index o --untracked no es pot usar amb revisions." -#: builtin/grep.c:909 +#: builtin/grep.c:910 msgid "--[no-]exclude-standard cannot be used for tracked contents." msgstr "--[no-]exclude-standard no es pot usar per als continguts seguits." -#: builtin/grep.c:917 +#: builtin/grep.c:918 msgid "both --cached and trees are given." msgstr "s'han donat ambdós --caches i arbres." @@ -7432,85 +8047,89 @@ msgstr "" msgid "git hash-object --stdin-paths" msgstr "git hash-object --stdin-paths" -#: builtin/hash-object.c:93 +#: builtin/hash-object.c:94 msgid "type" msgstr "tipus" -#: builtin/hash-object.c:93 +#: builtin/hash-object.c:94 msgid "object type" msgstr "tipus d'objecte" -#: builtin/hash-object.c:94 +#: builtin/hash-object.c:95 msgid "write the object into the object database" msgstr "escriu l'objecte a la base de dades d'objectes" -#: builtin/hash-object.c:96 +#: builtin/hash-object.c:97 msgid "read the object from stdin" msgstr "llegeix l'objecte des d'stdin" -#: builtin/hash-object.c:98 +#: builtin/hash-object.c:99 msgid "store file as is without filters" msgstr "emmagatzema el fitxer tal com és sense filtres" -#: builtin/hash-object.c:99 +#: builtin/hash-object.c:100 msgid "" "just hash any random garbage to create corrupt objects for debugging Git" msgstr "" "només suma qualsevulla brossa aleatòria per a crear objectes malmesos per a " "depurar al Git" -#: builtin/hash-object.c:100 +#: builtin/hash-object.c:101 msgid "process file as it were from this path" msgstr "processa el fitxer com si fos d'aquest camí" -#: builtin/help.c:41 +#: builtin/help.c:42 msgid "print all available commands" msgstr "imprimeix totes les ordres disponibles" -#: builtin/help.c:42 +#: builtin/help.c:43 +msgid "exclude guides" +msgstr "exclou guíes" + +#: builtin/help.c:44 msgid "print list of useful guides" msgstr "imprimeix la llista de guies útils" -#: builtin/help.c:43 +#: builtin/help.c:45 msgid "show man page" msgstr "mostra la pàgina de manual" -#: builtin/help.c:44 +#: builtin/help.c:46 msgid "show manual in web browser" msgstr "mostra la pàgina de manual en el navegador web" -#: builtin/help.c:46 +#: builtin/help.c:48 msgid "show info page" msgstr "mostra la pàgina d'informació" -#: builtin/help.c:52 +#: builtin/help.c:54 msgid "git help [--all] [--guides] [--man | --web | --info] []" msgstr "git help [--all] [--guides] [--man | --web | --info] []" -#: builtin/help.c:64 +#: builtin/help.c:66 #, c-format msgid "unrecognized help format '%s'" msgstr "format d'ajuda no reconegut '%s'" -#: builtin/help.c:91 +#: builtin/help.c:93 msgid "Failed to start emacsclient." msgstr "S'ha fallat en iniciar emacsclient." -#: builtin/help.c:104 +#: builtin/help.c:106 msgid "Failed to parse emacsclient version." msgstr "S'ha fallat en analitzar la versió d'emacsclient." -#: builtin/help.c:112 +#: builtin/help.c:114 #, c-format msgid "emacsclient version '%d' too old (< 22)." msgstr "la versió d'emacsclient '%d' és massa vella (< 22)." -#: builtin/help.c:130 builtin/help.c:151 builtin/help.c:160 builtin/help.c:168 +#: builtin/help.c:132 builtin/help.c:153 builtin/help.c:162 builtin/help.c:170 #, c-format msgid "failed to exec '%s'" msgstr "s'ha fallat en executar '%s'" -#: builtin/help.c:205 +#: builtin/help.c:207 #, c-format msgid "" "'%s': path for unsupported man viewer.\n" @@ -7519,7 +8138,7 @@ msgstr "" "'%s': camí a un visualitzador de manuals no compatible.\n" "Si us plau, considereu usar 'man..cmd' en lloc d'això." -#: builtin/help.c:217 +#: builtin/help.c:219 #, c-format msgid "" "'%s': cmd for supported man viewer.\n" @@ -7528,155 +8147,159 @@ msgstr "" "'%s': ordre per a un visualitzador de manuals compatible.\n" "Si us plau, considereu usar 'man..path' en lloc d'això." -#: builtin/help.c:334 +#: builtin/help.c:336 #, c-format msgid "'%s': unknown man viewer." msgstr "'%s': visualitzador de manuals desconegut." -#: builtin/help.c:351 +#: builtin/help.c:353 msgid "no man viewer handled the request" msgstr "cap visualitzador de manuals ha gestionat la sol·licitud" -#: builtin/help.c:359 +#: builtin/help.c:361 msgid "no info viewer handled the request" msgstr "cap visualitzador d'informació ha gestionat la sol·licitud" -#: builtin/help.c:401 +#: builtin/help.c:403 msgid "Defining attributes per path" msgstr "La definició d'atributs per camí" -#: builtin/help.c:402 +#: builtin/help.c:404 msgid "Everyday Git With 20 Commands Or So" msgstr "Git quotidià amb més o menys 20 ordres" -#: builtin/help.c:403 +#: builtin/help.c:405 msgid "A Git glossary" msgstr "Un glossari de Git" -#: builtin/help.c:404 +#: builtin/help.c:406 msgid "Specifies intentionally untracked files to ignore" msgstr "Especifica els fitxers intencionalment no seguits a ignorar" -#: builtin/help.c:405 +#: builtin/help.c:407 msgid "Defining submodule properties" msgstr "La definició de les propietats de submòduls" -#: builtin/help.c:406 +#: builtin/help.c:408 msgid "Specifying revisions and ranges for Git" msgstr "L'especificació de revisions i rangs per al Git" -#: builtin/help.c:407 +#: builtin/help.c:409 msgid "A tutorial introduction to Git (for version 1.5.1 or newer)" msgstr "Una introducció tutorial al Git (per a la versió 1.5.1 o més nou)" -#: builtin/help.c:408 +#: builtin/help.c:410 msgid "An overview of recommended workflows with Git" msgstr "Una visió de conjunt de fluxos de treball recomanats amb Git" -#: builtin/help.c:420 +#: builtin/help.c:422 msgid "The common Git guides are:\n" msgstr "Les guies de Git comunes són:\n" -#: builtin/help.c:441 builtin/help.c:458 -#, c-format -msgid "usage: %s%s" -msgstr "ús: %s%s" - -#: builtin/help.c:474 +#: builtin/help.c:440 #, c-format msgid "`git %s' is aliased to `%s'" msgstr "`git %s' és un àlies de `%s'" -#: builtin/index-pack.c:153 +#: builtin/help.c:462 builtin/help.c:479 +#, c-format +msgid "usage: %s%s" +msgstr "ús: %s%s" + +#: builtin/index-pack.c:154 #, c-format msgid "unable to open %s" msgstr "no s'ha pogut obrir %s" -#: builtin/index-pack.c:203 +#: builtin/index-pack.c:204 #, c-format msgid "object type mismatch at %s" msgstr "hi ha una discordança de tipus d'objecte a %s" -#: builtin/index-pack.c:223 +#: builtin/index-pack.c:224 #, c-format msgid "did not receive expected object %s" msgstr "no s'ha rebut l'objecte esperat %s" -#: builtin/index-pack.c:226 +#: builtin/index-pack.c:227 #, c-format msgid "object %s: expected type %s, found %s" msgstr "objecte %s: tipus %s esperat, %s trobat" -#: builtin/index-pack.c:268 +#: builtin/index-pack.c:269 #, c-format msgid "cannot fill %d byte" msgid_plural "cannot fill %d bytes" msgstr[0] "no es pot omplir %d octet" msgstr[1] "no es pot omplir %d octets" -#: builtin/index-pack.c:278 +#: builtin/index-pack.c:279 msgid "early EOF" msgstr "EOF prematur" -#: builtin/index-pack.c:279 +#: builtin/index-pack.c:280 msgid "read error on input" msgstr "error de lectura d'entrada" -#: builtin/index-pack.c:291 +#: builtin/index-pack.c:292 msgid "used more bytes than were available" msgstr "s'han usat més octets que hi havia disponibles" -#: builtin/index-pack.c:298 +#: builtin/index-pack.c:299 msgid "pack too large for current definition of off_t" msgstr "paquet massa gran per a la definició actual d'off_t" -#: builtin/index-pack.c:314 +#: builtin/index-pack.c:302 builtin/unpack-objects.c:92 +msgid "pack exceeds maximum allowed size" +msgstr "el paquet supera la mida màxima permesa" + +#: builtin/index-pack.c:317 #, c-format msgid "unable to create '%s'" -msgstr "no es pot crear '%s'" +msgstr "no s'ha pogut crear '%s'" -#: builtin/index-pack.c:319 +#: builtin/index-pack.c:322 #, c-format msgid "cannot open packfile '%s'" msgstr "no es pot obrir el fitxer de paquet '%s'" -#: builtin/index-pack.c:333 +#: builtin/index-pack.c:336 msgid "pack signature mismatch" msgstr "hi ha una discordança de signatura de paquet" -#: builtin/index-pack.c:335 +#: builtin/index-pack.c:338 #, c-format msgid "pack version % unsupported" msgstr "la versió de paquet % no és compatible" -#: builtin/index-pack.c:353 +#: builtin/index-pack.c:356 #, c-format msgid "pack has bad object at offset %: %s" msgstr "el paquet té un objecte dolent a la posició %: %s" -#: builtin/index-pack.c:475 +#: builtin/index-pack.c:478 #, c-format msgid "inflate returned %d" msgstr "la inflació ha retornat %d" -#: builtin/index-pack.c:524 +#: builtin/index-pack.c:527 msgid "offset value overflow for delta base object" msgstr "desbordament de valor de desplaçament per a l'objecte base de delta" -#: builtin/index-pack.c:532 +#: builtin/index-pack.c:535 msgid "delta base offset is out of bound" msgstr "el desplaçament de base de delta està fora de límits" -#: builtin/index-pack.c:540 +#: builtin/index-pack.c:543 #, c-format msgid "unknown object type %d" msgstr "tipus d'objecte desconegut %d" -#: builtin/index-pack.c:571 +#: builtin/index-pack.c:574 msgid "cannot pread pack file" msgstr "no es pot fer pread en el fitxer de paquet" -#: builtin/index-pack.c:573 +#: builtin/index-pack.c:576 #, c-format msgid "premature end of pack file, % byte missing" msgid_plural "premature end of pack file, % bytes missing" @@ -7684,144 +8307,144 @@ msgstr[0] "el final del fitxer de paquet és prematur, manca % octet" msgstr[1] "" "el final del fitxer de paquet és prematur, manquen % octets" -#: builtin/index-pack.c:599 +#: builtin/index-pack.c:602 msgid "serious inflate inconsistency" msgstr "hi ha una inconsistència seriosa d'inflació" -#: builtin/index-pack.c:745 builtin/index-pack.c:751 builtin/index-pack.c:774 -#: builtin/index-pack.c:808 builtin/index-pack.c:817 +#: builtin/index-pack.c:748 builtin/index-pack.c:754 builtin/index-pack.c:777 +#: builtin/index-pack.c:811 builtin/index-pack.c:820 #, c-format msgid "SHA1 COLLISION FOUND WITH %s !" msgstr "S'HA TROBAT UNA COL·LISIÓ SHA1 AMB %s !" -#: builtin/index-pack.c:748 builtin/pack-objects.c:164 -#: builtin/pack-objects.c:256 +#: builtin/index-pack.c:751 builtin/pack-objects.c:166 +#: builtin/pack-objects.c:258 #, c-format msgid "unable to read %s" msgstr "no s'ha pogut llegir %s" -#: builtin/index-pack.c:814 +#: builtin/index-pack.c:817 #, c-format msgid "cannot read existing object %s" msgstr "no es pot llegir l'objecte existent %s" -#: builtin/index-pack.c:828 +#: builtin/index-pack.c:831 #, c-format msgid "invalid blob object %s" msgstr "objecte de blob no vàlid %s" -#: builtin/index-pack.c:842 +#: builtin/index-pack.c:845 #, c-format msgid "invalid %s" msgstr "%s no vàlid" -#: builtin/index-pack.c:845 +#: builtin/index-pack.c:848 msgid "Error in object" msgstr "Error en objecte" -#: builtin/index-pack.c:847 +#: builtin/index-pack.c:850 #, c-format msgid "Not all child objects of %s are reachable" msgstr "No tots els objectes fills de %s són abastables" -#: builtin/index-pack.c:919 builtin/index-pack.c:950 +#: builtin/index-pack.c:922 builtin/index-pack.c:953 msgid "failed to apply delta" msgstr "s'ha fallat en aplicar la delta" -#: builtin/index-pack.c:1120 +#: builtin/index-pack.c:1123 msgid "Receiving objects" msgstr "S'estan rebent objectes" -#: builtin/index-pack.c:1120 +#: builtin/index-pack.c:1123 msgid "Indexing objects" msgstr "S'estan indexant objectes" -#: builtin/index-pack.c:1152 +#: builtin/index-pack.c:1155 msgid "pack is corrupted (SHA1 mismatch)" msgstr "el paquet és malmès (discordança SHA1)" -#: builtin/index-pack.c:1157 +#: builtin/index-pack.c:1160 msgid "cannot fstat packfile" msgstr "no es pot fer fstat en el fitxer de paquet" -#: builtin/index-pack.c:1160 +#: builtin/index-pack.c:1163 msgid "pack has junk at the end" msgstr "el paquet té brossa al seu final" -#: builtin/index-pack.c:1171 +#: builtin/index-pack.c:1174 msgid "confusion beyond insanity in parse_pack_objects()" msgstr "confusió més enllà de la bogeria en parse_pack_objects()" -#: builtin/index-pack.c:1196 +#: builtin/index-pack.c:1197 msgid "Resolving deltas" msgstr "S'estan resolent les deltes" -#: builtin/index-pack.c:1207 +#: builtin/index-pack.c:1208 #, c-format msgid "unable to create thread: %s" msgstr "no s'ha pogut crear fil: %s" -#: builtin/index-pack.c:1249 +#: builtin/index-pack.c:1250 msgid "confusion beyond insanity" msgstr "confusió més enllà de la bogeria" -#: builtin/index-pack.c:1255 +#: builtin/index-pack.c:1256 #, c-format msgid "completed with %d local object" msgid_plural "completed with %d local objects" msgstr[0] "s'ha completat amb %d objecte local" msgstr[1] "s'ha completat amb %d objectes locals" -#: builtin/index-pack.c:1267 +#: builtin/index-pack.c:1268 #, c-format msgid "Unexpected tail checksum for %s (disk corruption?)" msgstr "Suma de verificació final no esperada per a %s (corrupció de disc?)" -#: builtin/index-pack.c:1271 +#: builtin/index-pack.c:1272 #, c-format msgid "pack has %d unresolved delta" msgid_plural "pack has %d unresolved deltas" msgstr[0] "El paquet té %d delta no resolta" msgstr[1] "El paquet té %d deltes no resoltes" -#: builtin/index-pack.c:1295 +#: builtin/index-pack.c:1296 #, c-format msgid "unable to deflate appended object (%d)" msgstr "no s'ha pogut desinflar l'objecte annexat (%d)" -#: builtin/index-pack.c:1371 +#: builtin/index-pack.c:1372 #, c-format msgid "local object %s is corrupt" msgstr "l'objecte local %s és malmès" -#: builtin/index-pack.c:1395 +#: builtin/index-pack.c:1396 msgid "error while closing pack file" msgstr "error en tancar el fitxer de paquet" -#: builtin/index-pack.c:1408 +#: builtin/index-pack.c:1409 #, c-format msgid "cannot write keep file '%s'" msgstr "no es pot escriure el fitxer a retenir '%s'" -#: builtin/index-pack.c:1416 +#: builtin/index-pack.c:1417 #, c-format msgid "cannot close written keep file '%s'" msgstr "no es pot tancar el fitxer escrit a retenir '%s'" -#: builtin/index-pack.c:1429 +#: builtin/index-pack.c:1430 msgid "cannot store pack file" msgstr "no es pot emmagatzemar el fitxer de paquet" -#: builtin/index-pack.c:1440 +#: builtin/index-pack.c:1441 msgid "cannot store index file" msgstr "no es pot emmagatzemar el fitxer d'índex" -#: builtin/index-pack.c:1473 +#: builtin/index-pack.c:1474 #, c-format msgid "bad pack.indexversion=%" msgstr "pack.indexversion=% dolent" -#: builtin/index-pack.c:1483 builtin/index-pack.c:1681 +#: builtin/index-pack.c:1484 builtin/index-pack.c:1681 #, c-format msgid "no threads support, ignoring %s" msgstr "no hi ha suport de fils, s'està ignorant %s" @@ -7861,95 +8484,95 @@ msgstr "el nom del fitxer de paquet '%s' no acaba amb '.pack'" msgid "bad %s" msgstr "%s dolent" -#: builtin/index-pack.c:1730 +#: builtin/index-pack.c:1732 msgid "--fix-thin cannot be used without --stdin" msgstr "--fix-thin no es pot usar sense --stdin" -#: builtin/index-pack.c:1738 +#: builtin/index-pack.c:1740 msgid "--verify with no packfile name given" msgstr "s'ha donat --verify sense nom de fitxer de paquet" -#: builtin/init-db.c:55 +#: builtin/init-db.c:54 #, c-format msgid "cannot stat '%s'" msgstr "no es pot fer stat en '%s'" -#: builtin/init-db.c:61 +#: builtin/init-db.c:60 #, c-format msgid "cannot stat template '%s'" msgstr "no es pot fer stat en la plantilla '%s'" -#: builtin/init-db.c:66 +#: builtin/init-db.c:65 #, c-format msgid "cannot opendir '%s'" msgstr "no es pot fer opendir en el directori '%s'" -#: builtin/init-db.c:77 +#: builtin/init-db.c:76 #, c-format msgid "cannot readlink '%s'" msgstr "no es pot fer readlink en '%s'" -#: builtin/init-db.c:79 +#: builtin/init-db.c:78 #, c-format msgid "cannot symlink '%s' '%s'" msgstr "no es pot fer symlink en '%s' '%s'" -#: builtin/init-db.c:85 +#: builtin/init-db.c:84 #, c-format msgid "cannot copy '%s' to '%s'" msgstr "no es pot copiar '%s' a '%s'" -#: builtin/init-db.c:89 +#: builtin/init-db.c:88 #, c-format msgid "ignoring template %s" msgstr "s'està ignorant la plantilla %s" -#: builtin/init-db.c:120 +#: builtin/init-db.c:119 #, c-format msgid "templates not found %s" msgstr "no s'han trobat les plantilles %s" -#: builtin/init-db.c:135 +#: builtin/init-db.c:134 #, c-format msgid "not copying templates from '%s': %s" msgstr "no s'està copiant plantilles de '%s': %s" -#: builtin/init-db.c:312 builtin/init-db.c:315 -#, c-format -msgid "%s already exists" -msgstr "%s ja existeix" - -#: builtin/init-db.c:344 +#: builtin/init-db.c:327 #, c-format msgid "unable to handle file type %d" msgstr "no s'ha pogut gestionar el tipus de fitxer %d" -#: builtin/init-db.c:347 +#: builtin/init-db.c:330 #, c-format msgid "unable to move %s to %s" msgstr "no s'ha pogut moure %s a %s" -#: builtin/init-db.c:402 +#: builtin/init-db.c:347 builtin/init-db.c:350 +#, c-format +msgid "%s already exists" +msgstr "%s ja existeix" + +#: builtin/init-db.c:403 #, c-format msgid "Reinitialized existing shared Git repository in %s%s\n" msgstr "S'ha reinicialitzat el dipòsit compartit existent del Git en %s%s\n" -#: builtin/init-db.c:403 +#: builtin/init-db.c:404 #, c-format msgid "Reinitialized existing Git repository in %s%s\n" msgstr "S'ha reinicialitzat el dipòsit existent del Git en %s%s\n" -#: builtin/init-db.c:407 +#: builtin/init-db.c:408 #, c-format msgid "Initialized empty shared Git repository in %s%s\n" msgstr "S'ha inicialitzat un dipòsit compartit buit del Git en %s%s\n" -#: builtin/init-db.c:408 +#: builtin/init-db.c:409 #, c-format msgid "Initialized empty Git repository in %s%s\n" msgstr "S'ha inicialitzat un dipòsit buit del Git en %s%s\n" -#: builtin/init-db.c:455 +#: builtin/init-db.c:457 msgid "" "git init [-q | --quiet] [--bare] [--template=] [--" "shared[=]] []" @@ -7957,25 +8580,25 @@ msgstr "" "git init [-q | --quiet] [--bare] [--template=] [--" "shared[=]] []" -#: builtin/init-db.c:478 +#: builtin/init-db.c:480 msgid "permissions" msgstr "permisos" -#: builtin/init-db.c:479 +#: builtin/init-db.c:481 msgid "specify that the git repository is to be shared amongst several users" msgstr "especifica que el dipòsit de git es compartirà entre diversos usuaris" -#: builtin/init-db.c:513 builtin/init-db.c:518 +#: builtin/init-db.c:515 builtin/init-db.c:520 #, c-format msgid "cannot mkdir %s" msgstr "no es pot mkdir %s" -#: builtin/init-db.c:522 +#: builtin/init-db.c:524 #, c-format msgid "cannot chdir to %s" msgstr "no es pot canviar de directori a %s" -#: builtin/init-db.c:543 +#: builtin/init-db.c:545 #, c-format msgid "" "%s (or --work-tree=) not allowed without specifying %s (or --git-" @@ -7984,7 +8607,7 @@ msgstr "" "no es permet %s (o --work-tree=) sense especificar %s (o --git-" "dir=)" -#: builtin/init-db.c:571 +#: builtin/init-db.c:573 #, c-format msgid "Cannot access work tree '%s'" msgstr "No es pot accedir a l'arbre de treball '%s'" @@ -8095,37 +8718,34 @@ msgstr "No és un rang." msgid "Cover letter needs email format" msgstr "La carta de presentació necessita el format de correu electrònic" -#: builtin/log.c:1064 +#: builtin/log.c:1063 #, c-format msgid "insane in-reply-to: %s" msgstr "in-reply-to boig: %s" -#: builtin/log.c:1092 +#: builtin/log.c:1091 msgid "git format-patch [] [ | ]" msgstr "git format-patch [] [ | ]" -#: builtin/log.c:1137 +#: builtin/log.c:1141 msgid "Two output directories?" msgstr "Hi ha dos directoris de sortida?" -#: builtin/log.c:1244 builtin/log.c:1883 builtin/log.c:1885 builtin/log.c:1897 +#: builtin/log.c:1248 builtin/log.c:1891 builtin/log.c:1893 builtin/log.c:1905 #, c-format msgid "Unknown commit %s" msgstr "Comissió desconeguda %s" -#: builtin/log.c:1254 builtin/notes.c:254 builtin/notes.c:305 -#: builtin/notes.c:307 builtin/notes.c:370 builtin/notes.c:425 -#: builtin/notes.c:511 builtin/notes.c:516 builtin/notes.c:594 -#: builtin/notes.c:657 builtin/notes.c:882 builtin/tag.c:455 +#: builtin/log.c:1258 builtin/notes.c:884 builtin/tag.c:455 #, c-format msgid "Failed to resolve '%s' as a valid ref." msgstr "S'ha fallat en resoldre '%s' com a referència vàlida." -#: builtin/log.c:1259 +#: builtin/log.c:1263 msgid "Could not find exact merge base." msgstr "No s'ha pogut trobar la base exacta de fusió." -#: builtin/log.c:1263 +#: builtin/log.c:1267 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" @@ -8136,211 +8756,215 @@ msgstr "" "seguir una branca remot. O podeu especificar la comissió base manualment\n" "amb --base=." -#: builtin/log.c:1283 +#: builtin/log.c:1287 msgid "Failed to find exact merge base" msgstr "S'ha fallat en trobar la base exacta de fusió." -#: builtin/log.c:1294 +#: builtin/log.c:1298 msgid "base commit should be the ancestor of revision list" msgstr "la comissió base ha de ser l'avantpassat de la llista de revisions" -#: builtin/log.c:1298 +#: builtin/log.c:1302 msgid "base commit shouldn't be in revision list" msgstr "la comissió base no ha de ser en la llista de revisions" -#: builtin/log.c:1347 +#: builtin/log.c:1351 msgid "cannot get patch id" msgstr "no es pot obtenir l'id del pedaç" -#: builtin/log.c:1404 +#: builtin/log.c:1408 msgid "use [PATCH n/m] even with a single patch" msgstr "usa [PATCH n/m] fins i tot amb un sol pedaç" -#: builtin/log.c:1407 +#: builtin/log.c:1411 msgid "use [PATCH] even with multiple patches" msgstr "usa [PATCH] fins i tot amb múltiples pedaços" -#: builtin/log.c:1411 +#: builtin/log.c:1415 msgid "print patches to standard out" msgstr "imprimeix els pedaços a la sortida estàndard" -#: builtin/log.c:1413 +#: builtin/log.c:1417 msgid "generate a cover letter" msgstr "genera una carta de presentació" -#: builtin/log.c:1415 +#: builtin/log.c:1419 msgid "use simple number sequence for output file names" msgstr "usa una seqüència de números per als noms dels fitxers de sortida" -#: builtin/log.c:1416 +#: builtin/log.c:1420 msgid "sfx" msgstr "sufix" -#: builtin/log.c:1417 +#: builtin/log.c:1421 msgid "use instead of '.patch'" msgstr "usa en lloc de '.patch'" -#: builtin/log.c:1419 +#: builtin/log.c:1423 msgid "start numbering patches at instead of 1" msgstr "comença numerant els pedaços a en lloc d'1" -#: builtin/log.c:1421 +#: builtin/log.c:1425 msgid "mark the series as Nth re-roll" msgstr "marca la sèrie com a l'enèsima llançada" -#: builtin/log.c:1423 +#: builtin/log.c:1427 +msgid "Use [RFC PATCH] instead of [PATCH]" +msgstr "Usa [RFC PATCH] en lloc de [PATCH]" + +#: builtin/log.c:1430 msgid "Use [] instead of [PATCH]" msgstr "Usa [] en lloc de [PATCH]" -#: builtin/log.c:1426 +#: builtin/log.c:1433 msgid "store resulting files in " msgstr "emmagatzema els fitxers resultants a " -#: builtin/log.c:1429 +#: builtin/log.c:1436 msgid "don't strip/add [PATCH]" msgstr "no despullis/afegeixis [PATCH]" -#: builtin/log.c:1432 +#: builtin/log.c:1439 msgid "don't output binary diffs" msgstr "no emetis diferències binàries" -#: builtin/log.c:1434 +#: builtin/log.c:1441 msgid "output all-zero hash in From header" msgstr "emet un hash de tots zeros en la capçalera From" -#: builtin/log.c:1436 +#: builtin/log.c:1443 msgid "don't include a patch matching a commit upstream" msgstr "no incloguis pedaços que coincideixin amb comissions a la font" -#: builtin/log.c:1438 +#: builtin/log.c:1445 msgid "show patch format instead of default (patch + stat)" msgstr "" "mostra el format de pedaç en lloc del per defecte (pedaç + estadístiques)" -#: builtin/log.c:1440 +#: builtin/log.c:1447 msgid "Messaging" msgstr "Missatgeria" -#: builtin/log.c:1441 +#: builtin/log.c:1448 msgid "header" msgstr "capçalera" -#: builtin/log.c:1442 +#: builtin/log.c:1449 msgid "add email header" msgstr "afegeix una capçalera de correu electrònic" -#: builtin/log.c:1443 builtin/log.c:1445 +#: builtin/log.c:1450 builtin/log.c:1452 msgid "email" msgstr "correu electrònic" -#: builtin/log.c:1443 +#: builtin/log.c:1450 msgid "add To: header" msgstr "afegeix la capçalera To:" -#: builtin/log.c:1445 +#: builtin/log.c:1452 msgid "add Cc: header" msgstr "afegeix la capçalera Cc:" -#: builtin/log.c:1447 +#: builtin/log.c:1454 msgid "ident" msgstr "identitat" -#: builtin/log.c:1448 +#: builtin/log.c:1455 msgid "set From address to (or committer ident if absent)" msgstr "" "estableix l'adreça From a (o la identitat del comitent si manca)" -#: builtin/log.c:1450 +#: builtin/log.c:1457 msgid "message-id" msgstr "ID de missatge" -#: builtin/log.c:1451 +#: builtin/log.c:1458 msgid "make first mail a reply to " msgstr "fes que el primer missatge sigui una resposta a " -#: builtin/log.c:1452 builtin/log.c:1455 +#: builtin/log.c:1459 builtin/log.c:1462 msgid "boundary" msgstr "límit" -#: builtin/log.c:1453 +#: builtin/log.c:1460 msgid "attach the patch" msgstr "ajunta el pedaç" -#: builtin/log.c:1456 +#: builtin/log.c:1463 msgid "inline the patch" msgstr "posa el pedaç en el cos" -#: builtin/log.c:1460 +#: builtin/log.c:1467 msgid "enable message threading, styles: shallow, deep" msgstr "habilita l'enfilada de missatges, estils: shallow, deep" -#: builtin/log.c:1462 +#: builtin/log.c:1469 msgid "signature" msgstr "signatura" -#: builtin/log.c:1463 +#: builtin/log.c:1470 msgid "add a signature" msgstr "afegeix una signatura" -#: builtin/log.c:1464 +#: builtin/log.c:1471 msgid "base-commit" msgstr "comissió base" -#: builtin/log.c:1465 +#: builtin/log.c:1472 msgid "add prerequisite tree info to the patch series" msgstr "afegeix la informació d'arbre prerequerida a la sèrie de pedaços" -#: builtin/log.c:1467 +#: builtin/log.c:1474 msgid "add a signature from a file" msgstr "afegeix una signatura des d'un fitxer" -#: builtin/log.c:1468 +#: builtin/log.c:1475 msgid "don't print the patch filenames" msgstr "no imprimeixis els noms de fitxer del pedaç" -#: builtin/log.c:1558 +#: builtin/log.c:1565 msgid "-n and -k are mutually exclusive." msgstr "-n i -k són mutualment exclusius." -#: builtin/log.c:1560 -msgid "--subject-prefix and -k are mutually exclusive." -msgstr "--subject-prefix i -k són mutualment exclusius." +#: builtin/log.c:1567 +msgid "--subject-prefix/--rfc and -k are mutually exclusive." +msgstr "--subject-prefix/--rfc i -k són mutualment exclusius." -#: builtin/log.c:1568 +#: builtin/log.c:1575 msgid "--name-only does not make sense" msgstr "--name-only no té sentit" -#: builtin/log.c:1570 +#: builtin/log.c:1577 msgid "--name-status does not make sense" msgstr "--name-status no té sentit" -#: builtin/log.c:1572 +#: builtin/log.c:1579 msgid "--check does not make sense" msgstr "--check no té sentit" -#: builtin/log.c:1602 +#: builtin/log.c:1609 msgid "standard output, or directory, which one?" msgstr "sortida estàndard o directori, quin dels dos?" -#: builtin/log.c:1604 +#: builtin/log.c:1611 #, c-format msgid "Could not create directory '%s'" msgstr "No s'ha pogut crear el directori '%s'" -#: builtin/log.c:1698 +#: builtin/log.c:1705 #, c-format msgid "unable to read signature file '%s'" msgstr "no s'ha pogut llegir el fitxer de signatura '%s'" -#: builtin/log.c:1769 +#: builtin/log.c:1777 msgid "Failed to create output files" msgstr "S'ha fallat en crear els fitxers de sortida" -#: builtin/log.c:1818 +#: builtin/log.c:1826 msgid "git cherry [-v] [ [ []]]" msgstr "git cherry [-v] [ [ []]]" -#: builtin/log.c:1872 +#: builtin/log.c:1880 #, c-format msgid "" "Could not find a tracked remote branch, please specify manually.\n" @@ -8348,101 +8972,105 @@ msgstr "" "No s'ha pogut trobar una branca remota seguida. Si us plau, especifiqueu " " manualment.\n" -#: builtin/ls-files.c:379 +#: builtin/ls-files.c:458 msgid "git ls-files [] [...]" msgstr "git ls-files [] [...]" -#: builtin/ls-files.c:428 +#: builtin/ls-files.c:507 msgid "identify the file status with tags" msgstr "identifica l'estat de fitxer amb etiquetes" -#: builtin/ls-files.c:430 +#: builtin/ls-files.c:509 msgid "use lowercase letters for 'assume unchanged' files" msgstr "usa lletres minúscules per als fitxers 'assume unchanged'" -#: builtin/ls-files.c:432 +#: builtin/ls-files.c:511 msgid "show cached files in the output (default)" msgstr "" "mostra en la sortida els fitxers desats en la memòria cau (per defecte)" -#: builtin/ls-files.c:434 +#: builtin/ls-files.c:513 msgid "show deleted files in the output" msgstr "mostra en la sortida els fitxers suprimits" -#: builtin/ls-files.c:436 +#: builtin/ls-files.c:515 msgid "show modified files in the output" msgstr "mostra en la sortida els fitxers modificats" -#: builtin/ls-files.c:438 +#: builtin/ls-files.c:517 msgid "show other files in the output" msgstr "mostra en la sortida els altres fitxers" -#: builtin/ls-files.c:440 +#: builtin/ls-files.c:519 msgid "show ignored files in the output" msgstr "mostra en la sortida els fitxers ignorats" -#: builtin/ls-files.c:443 +#: builtin/ls-files.c:522 msgid "show staged contents' object name in the output" msgstr "mostra en la sortida el nom d'objecte dels continguts allistats" -#: builtin/ls-files.c:445 +#: builtin/ls-files.c:524 msgid "show files on the filesystem that need to be removed" msgstr "mostra els fitxers en el sistema de fitxers que s'han d'eliminar" -#: builtin/ls-files.c:447 +#: builtin/ls-files.c:526 msgid "show 'other' directories' names only" msgstr "mostra només els noms dels directoris 'other'" -#: builtin/ls-files.c:449 +#: builtin/ls-files.c:528 msgid "show line endings of files" -msgstr "mostra els terminis de línia dels fitxers" +msgstr "mostra els terminadors de línia dels fitxers" -#: builtin/ls-files.c:451 +#: builtin/ls-files.c:530 msgid "don't show empty directories" msgstr "no mostris els directoris buits" -#: builtin/ls-files.c:454 +#: builtin/ls-files.c:533 msgid "show unmerged files in the output" msgstr "mostra en la sortida els fitxers sense fusionar" -#: builtin/ls-files.c:456 +#: builtin/ls-files.c:535 msgid "show resolve-undo information" msgstr "mostra la informació de resolució de desfet" -#: builtin/ls-files.c:458 +#: builtin/ls-files.c:537 msgid "skip files matching pattern" msgstr "salta els fitxers coincidents amb el patró" -#: builtin/ls-files.c:461 +#: builtin/ls-files.c:540 msgid "exclude patterns are read from " msgstr "els patrons d'exclusió es llegeixen de " -#: builtin/ls-files.c:464 +#: builtin/ls-files.c:543 msgid "read additional per-directory exclude patterns in " msgstr "llegeix els patrons addicionals d'exclusió per directori en " -#: builtin/ls-files.c:466 +#: builtin/ls-files.c:545 msgid "add the standard git exclusions" msgstr "afegeix les exclusions estàndards de git" -#: builtin/ls-files.c:469 +#: builtin/ls-files.c:548 msgid "make the output relative to the project top directory" msgstr "fes que la sortida sigui relativa al directori superior del projecte" -#: builtin/ls-files.c:472 +#: builtin/ls-files.c:551 +msgid "recurse through submodules" +msgstr "recursa als submòduls" + +#: builtin/ls-files.c:553 msgid "if any is not in the index, treat this as an error" msgstr "si qualsevol no és en l'índex, tracta això com a error" -#: builtin/ls-files.c:473 +#: builtin/ls-files.c:554 msgid "tree-ish" msgstr "arbre" -#: builtin/ls-files.c:474 +#: builtin/ls-files.c:555 msgid "pretend that paths removed since are still present" msgstr "" "pretén que els camins eliminats després de encara siguin presents" -#: builtin/ls-files.c:476 +#: builtin/ls-files.c:557 msgid "show debugging data" msgstr "mostra les dades de depuració" @@ -8561,33 +9189,33 @@ msgstr "Les estratègies disponibles són:" msgid "Available custom strategies are:" msgstr "Les estratègies personalitzades disponibles són:" -#: builtin/merge.c:195 builtin/pull.c:126 +#: builtin/merge.c:195 builtin/pull.c:127 msgid "do not show a diffstat at the end of the merge" msgstr "no mostris les estadístiques de diferència al final de la fusió" -#: builtin/merge.c:198 builtin/pull.c:129 +#: builtin/merge.c:198 builtin/pull.c:130 msgid "show a diffstat at the end of the merge" msgstr "mostra les estadístiques de diferència al final de la fusió" -#: builtin/merge.c:199 builtin/pull.c:132 +#: builtin/merge.c:199 builtin/pull.c:133 msgid "(synonym to --stat)" msgstr "(sinònim de --stat)" -#: builtin/merge.c:201 builtin/pull.c:135 +#: builtin/merge.c:201 builtin/pull.c:136 msgid "add (at most ) entries from shortlog to merge commit message" msgstr "" "afegeix (com a màxim ) entrades del registre curt al missatge de comissió " "de fusió" -#: builtin/merge.c:204 builtin/pull.c:138 +#: builtin/merge.c:204 builtin/pull.c:139 msgid "create a single commit instead of doing a merge" msgstr "crea una única comissió en lloc de fusionar" -#: builtin/merge.c:206 builtin/pull.c:141 +#: builtin/merge.c:206 builtin/pull.c:142 msgid "perform a commit if the merge succeeds (default)" msgstr "realitza una comissió si la fusió té èxit (per defecte)" -#: builtin/merge.c:208 builtin/pull.c:144 +#: builtin/merge.c:208 builtin/pull.c:145 msgid "edit message before committing" msgstr "edita el missatge abans de cometre" @@ -8595,28 +9223,28 @@ msgstr "edita el missatge abans de cometre" msgid "allow fast-forward (default)" msgstr "permet l'avanç ràpid (per defecte)" -#: builtin/merge.c:211 builtin/pull.c:150 +#: builtin/merge.c:211 builtin/pull.c:151 msgid "abort if fast-forward is not possible" msgstr "avorta si l'avanç ràpid no és possible" -#: builtin/merge.c:215 builtin/pull.c:153 +#: builtin/merge.c:215 builtin/pull.c:154 msgid "verify that the named commit has a valid GPG signature" msgstr "verifica que la comissió anomenada tingui una signatura GPG vàlida" -#: builtin/merge.c:216 builtin/notes.c:772 builtin/pull.c:157 +#: builtin/merge.c:216 builtin/notes.c:774 builtin/pull.c:158 #: builtin/revert.c:89 msgid "strategy" msgstr "estratègia" -#: builtin/merge.c:217 builtin/pull.c:158 +#: builtin/merge.c:217 builtin/pull.c:159 msgid "merge strategy to use" msgstr "estratègia de fusió a usar" -#: builtin/merge.c:218 builtin/pull.c:161 +#: builtin/merge.c:218 builtin/pull.c:162 msgid "option=value" msgstr "opció=valor" -#: builtin/merge.c:219 builtin/pull.c:162 +#: builtin/merge.c:219 builtin/pull.c:163 msgid "option for selected merge strategy" msgstr "opció per a l'estratègia de fusió seleccionada" @@ -8628,7 +9256,7 @@ msgstr "missatge de comissió de fusió (per a una fusió no d'avanç ràpid)" msgid "abort the current in-progress merge" msgstr "avorta la fusió en curs actual" -#: builtin/merge.c:227 builtin/pull.c:169 +#: builtin/merge.c:227 builtin/pull.c:170 msgid "allow merging unrelated histories" msgstr "permet fusionar històries no relacionades" @@ -8851,55 +9479,55 @@ msgstr "s'està refusant fusionar històries no relacionades" msgid "Already up-to-date." msgstr "Ja està al dia." -#: builtin/merge.c:1382 +#: builtin/merge.c:1377 #, c-format msgid "Updating %s..%s\n" msgstr "S'estan actualitzant %s..%s\n" -#: builtin/merge.c:1419 +#: builtin/merge.c:1418 #, c-format msgid "Trying really trivial in-index merge...\n" msgstr "S'està intentant una fusió molt trivial en l'índex...\n" -#: builtin/merge.c:1426 +#: builtin/merge.c:1425 #, c-format msgid "Nope.\n" msgstr "No.\n" -#: builtin/merge.c:1451 +#: builtin/merge.c:1450 msgid "Already up-to-date. Yeeah!" msgstr "Ja està al dia. Estupend!" -#: builtin/merge.c:1457 +#: builtin/merge.c:1456 msgid "Not possible to fast-forward, aborting." msgstr "No és possible avançar ràpidament, s'està avortant." -#: builtin/merge.c:1480 builtin/merge.c:1559 +#: builtin/merge.c:1479 builtin/merge.c:1558 #, c-format msgid "Rewinding the tree to pristine...\n" msgstr "S'està rebobinant l'arbre a la pristina...\n" -#: builtin/merge.c:1484 +#: builtin/merge.c:1483 #, c-format msgid "Trying merge strategy %s...\n" msgstr "S'està intentant l'estratègia de fusió %s...\n" -#: builtin/merge.c:1550 +#: builtin/merge.c:1549 #, c-format msgid "No merge strategy handled the merge.\n" msgstr "Cap estratègia de fusió ha gestionat la fusió.\n" -#: builtin/merge.c:1552 +#: builtin/merge.c:1551 #, c-format msgid "Merge with strategy %s failed.\n" msgstr "L'estratègia de fusió %s ha fallat.\n" -#: builtin/merge.c:1561 +#: builtin/merge.c:1560 #, c-format msgid "Using the %s to prepare resolving by hand.\n" msgstr "S'està usant el %s per a preparar la resolució a mà.\n" -#: builtin/merge.c:1573 +#: builtin/merge.c:1572 #, c-format msgid "Automatic merge went well; stopped before committing as requested\n" msgstr "" @@ -8926,23 +9554,23 @@ msgstr "git merge-base --is-ancestor " msgid "git merge-base --fork-point []" msgstr "git merge-base --fork-point []" -#: builtin/merge-base.c:214 +#: builtin/merge-base.c:217 msgid "output all common ancestors" msgstr "emet tots els avantpassats comuns" -#: builtin/merge-base.c:216 +#: builtin/merge-base.c:219 msgid "find ancestors for a single n-way merge" msgstr "troba els avantpassats per a una sola fusió d'n vies" -#: builtin/merge-base.c:218 +#: builtin/merge-base.c:221 msgid "list revs not reachable from others" msgstr "llista les revisions no abastables d'altres" -#: builtin/merge-base.c:220 +#: builtin/merge-base.c:223 msgid "is the first one ancestor of the other?" msgstr "és la primera un avantpassat de l'altre?" -#: builtin/merge-base.c:222 +#: builtin/merge-base.c:225 msgid "find where forked from reflog of " msgstr "" "troba on s'ha bifurcat del registre de referències de " @@ -8987,6 +9615,37 @@ msgstr "no avisis de conflictes" msgid "set labels for file1/orig-file/file2" msgstr "estableix les etiquetes per a fitxer1/fitxer-original/fitxer2" +#: builtin/merge-recursive.c:45 +#, c-format +msgid "unknown option %s" +msgstr "opció desconeguda %s" + +#: builtin/merge-recursive.c:51 +#, c-format +msgid "could not parse object '%s'" +msgstr "no s'ha pogut analitzar l'objecte '%s'" + +#: builtin/merge-recursive.c:55 +#, c-format +msgid "cannot handle more than %d base. Ignoring %s." +msgid_plural "cannot handle more than %d bases. Ignoring %s." +msgstr[0] "no es pot gestionar més d'%d base. S'està ignorant %s." +msgstr[1] "no es poden gestionar més de %d bases. S'està ignorant %s." + +#: builtin/merge-recursive.c:63 +msgid "not handling anything other than two heads merge." +msgstr "no s'està gestionant res a part de la fusió de dos caps." + +#: builtin/merge-recursive.c:69 builtin/merge-recursive.c:71 +#, c-format +msgid "could not resolve ref '%s'" +msgstr "no s'ha pogut resoldre la referència '%s'" + +#: builtin/merge-recursive.c:77 +#, c-format +msgid "Merging %s with %s\n" +msgstr "S'està fusionant %s amb %s\n" + #: builtin/mktree.c:65 msgid "git mktree [-z] [--missing] [--batch]" msgstr "git mktree [-z] [--missing] [--batch]" @@ -9097,43 +9756,43 @@ msgstr "S'està canviant el nom de %s a %s\n" msgid "renaming '%s' failed" msgstr "el canvi del nom de '%s' ha fallat" -#: builtin/name-rev.c:258 +#: builtin/name-rev.c:257 msgid "git name-rev [] ..." msgstr "git name-rev [] ..." -#: builtin/name-rev.c:259 +#: builtin/name-rev.c:258 msgid "git name-rev [] --all" msgstr "git name-rev [] --all" -#: builtin/name-rev.c:260 +#: builtin/name-rev.c:259 msgid "git name-rev [] --stdin" msgstr "git name-rev [] --stdin" -#: builtin/name-rev.c:312 +#: builtin/name-rev.c:311 msgid "print only names (no SHA-1)" msgstr "imprimeix només els noms (sense SHA-1)" -#: builtin/name-rev.c:313 +#: builtin/name-rev.c:312 msgid "only use tags to name the commits" msgstr "només usa les etiquetes per a anomenar les comissions" -#: builtin/name-rev.c:315 +#: builtin/name-rev.c:314 msgid "only use refs matching " msgstr "només usa les referències que coincideixin amb " -#: builtin/name-rev.c:317 +#: builtin/name-rev.c:316 msgid "list all commits reachable from all refs" msgstr "llista totes les comissions abastables de totes les referències" -#: builtin/name-rev.c:318 +#: builtin/name-rev.c:317 msgid "read from stdin" msgstr "llegeix d'stdin" -#: builtin/name-rev.c:319 +#: builtin/name-rev.c:318 msgid "allow to print `undefined` names (default)" msgstr "permet imprimir els noms `undefined` (per defecte)" -#: builtin/name-rev.c:325 +#: builtin/name-rev.c:324 msgid "dereference tags in the input (internal use)" msgstr "dereferencia les etiquetes en l'entrada (ús intern)" @@ -9269,9 +9928,9 @@ msgid "failed to finish 'show' for object '%s'" msgstr "s'ha fallat en finalitzar 'show' per a l'objecte '%s'" #: builtin/notes.c:194 -msgid "Please supply the note contents using either -m or -F option" +msgid "please supply the note contents using either -m or -F option" msgstr "" -"Si us plau, proveïu els continguts de la nota fent servir l'opció -m o " +"si us plau, proveïu els continguts de la nota fent servir l'opció -m o " "l'opció -F" #: builtin/notes.c:203 @@ -9280,8 +9939,8 @@ msgstr "no s'ha pogut escriure l'objecte de nota" #: builtin/notes.c:205 #, c-format -msgid "The note contents have been left in %s" -msgstr "Els continguts de la nota s'han deixat en %s" +msgid "the note contents have been left in %s" +msgstr "s'han deixat els continguts de la nota en %s" #: builtin/notes.c:233 builtin/tag.c:439 #, c-format @@ -9293,52 +9952,76 @@ msgstr "no es pot llegir '%s'" msgid "could not open or read '%s'" msgstr "no s'ha pogut obrir o llegir '%s'" +#: builtin/notes.c:254 builtin/notes.c:305 builtin/notes.c:307 +#: builtin/notes.c:372 builtin/notes.c:427 builtin/notes.c:513 +#: builtin/notes.c:518 builtin/notes.c:596 builtin/notes.c:659 +#, c-format +msgid "failed to resolve '%s' as a valid ref." +msgstr "s'ha fallat en resoldre '%s' com a referència vàlida." + #: builtin/notes.c:257 #, c-format -msgid "Failed to read object '%s'." -msgstr "S'ha fallat en llegir l'objecte '%s'." +msgid "failed to read object '%s'." +msgstr "s'ha fallat en llegir l'objecte '%s'." #: builtin/notes.c:261 #, c-format -msgid "Cannot read note data from non-blob object '%s'." -msgstr "No es pot llegir les dades de node de l'objecte no de blob '%s'." +msgid "cannot read note data from non-blob object '%s'." +msgstr "no es pot llegir les dades de node de l'objecte no de blob '%s'." + +#: builtin/notes.c:301 +#, c-format +msgid "malformed input line: '%s'." +msgstr "línia d'entrada mal formada: '%s'." + +#: builtin/notes.c:316 +#, c-format +msgid "failed to copy notes from '%s' to '%s'" +msgstr "s'ha fallat en copiar les notes de '%s' a '%s'" + +#. TRANSLATORS: the first %s will be replaced by a +#. git notes command: 'add', 'merge', 'remove', etc. +#: builtin/notes.c:345 +#, c-format +msgid "refusing to %s notes in %s (outside of refs/notes/)" +msgstr "s'està refusant %s les notes en %s (fora de refs/notes/)" -#: builtin/notes.c:363 builtin/notes.c:418 builtin/notes.c:494 -#: builtin/notes.c:506 builtin/notes.c:582 builtin/notes.c:650 -#: builtin/notes.c:800 builtin/notes.c:947 builtin/notes.c:968 +#: builtin/notes.c:365 builtin/notes.c:420 builtin/notes.c:496 +#: builtin/notes.c:508 builtin/notes.c:584 builtin/notes.c:652 +#: builtin/notes.c:802 builtin/notes.c:949 builtin/notes.c:970 msgid "too many parameters" msgstr "massa paràmetres" -#: builtin/notes.c:376 builtin/notes.c:663 +#: builtin/notes.c:378 builtin/notes.c:665 #, c-format -msgid "No note found for object %s." -msgstr "No s'ha trobat cap nota per a l'objecte %s." +msgid "no note found for object %s." +msgstr "no s'ha trobat cap nota per a l'objecte %s." -#: builtin/notes.c:397 builtin/notes.c:560 +#: builtin/notes.c:399 builtin/notes.c:562 msgid "note contents as a string" msgstr "anota els continguts com a cadena" -#: builtin/notes.c:400 builtin/notes.c:563 +#: builtin/notes.c:402 builtin/notes.c:565 msgid "note contents in a file" msgstr "anota els continguts en un fitxer" -#: builtin/notes.c:403 builtin/notes.c:566 +#: builtin/notes.c:405 builtin/notes.c:568 msgid "reuse and edit specified note object" msgstr "reusa i edita l'objecte de nota especificat" -#: builtin/notes.c:406 builtin/notes.c:569 +#: builtin/notes.c:408 builtin/notes.c:571 msgid "reuse specified note object" msgstr "reusa l'objecte de nota especificat" -#: builtin/notes.c:409 builtin/notes.c:572 +#: builtin/notes.c:411 builtin/notes.c:574 msgid "allow storing empty note" msgstr "permet l'emmagatzematge d'una nota buida" -#: builtin/notes.c:410 builtin/notes.c:481 +#: builtin/notes.c:412 builtin/notes.c:483 msgid "replace existing notes" msgstr "reemplaça les notes existents" -#: builtin/notes.c:435 +#: builtin/notes.c:437 #, c-format msgid "" "Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite " @@ -9347,30 +10030,30 @@ msgstr "" "No es pot afegir les notes. S'han trobat notes existents de l'objecte %s. " "Useu '-f' per a sobreescriure les notes existents." -#: builtin/notes.c:450 builtin/notes.c:529 +#: builtin/notes.c:452 builtin/notes.c:531 #, c-format msgid "Overwriting existing notes for object %s\n" msgstr "S'estan sobreescrivint les notes existents de l'objecte %s\n" -#: builtin/notes.c:461 builtin/notes.c:622 builtin/notes.c:887 +#: builtin/notes.c:463 builtin/notes.c:624 builtin/notes.c:889 #, c-format msgid "Removing note for object %s\n" msgstr "S'està eliminant la nota de l'objecte %s\n" -#: builtin/notes.c:482 +#: builtin/notes.c:484 msgid "read objects from stdin" msgstr "llegeix els objectes des d'stdin" -#: builtin/notes.c:484 +#: builtin/notes.c:486 msgid "load rewriting config for (implies --stdin)" msgstr "" "carrega la configuració de reescriptura per a (implica --stdin)" -#: builtin/notes.c:502 +#: builtin/notes.c:504 msgid "too few parameters" msgstr "hi ha massa pocs paràmetres" -#: builtin/notes.c:523 +#: builtin/notes.c:525 #, c-format msgid "" "Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite " @@ -9379,12 +10062,12 @@ msgstr "" "No es pot copiar les notes. S'han trobat notes existents de l'objecte %s. " "Useu '-f' per a sobreescriure les notes existents." -#: builtin/notes.c:535 +#: builtin/notes.c:537 #, c-format -msgid "Missing notes on source object %s. Cannot copy." -msgstr "Manquen notes a l'objecte font %s. No es pot copiar." +msgid "missing notes on source object %s. Cannot copy." +msgstr "manquen notes a l'objecte font %s. No es pot copiar." -#: builtin/notes.c:587 +#: builtin/notes.c:589 #, c-format msgid "" "The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n" @@ -9393,20 +10076,52 @@ msgstr "" "S'han desaprovat les opcions -m/-F/-c/-C en favor de la subordre 'edit'.\n" "Si us plau, useu 'git notes add -f -m/-F/-c/-C' en lloc d'això.\n" -#: builtin/notes.c:753 +#: builtin/notes.c:685 +msgid "failed to delete ref NOTES_MERGE_PARTIAL" +msgstr "s'ha fallat en suprimir la referència NOTES_MERGE_PARTIAL" + +#: builtin/notes.c:687 +msgid "failed to delete ref NOTES_MERGE_REF" +msgstr "s'ha fallat en suprimir la referència NOTES_MERGE_REF" + +#: builtin/notes.c:689 +msgid "failed to remove 'git notes merge' worktree" +msgstr "s'ha fallat en eliminar l'arbre de treball de 'git notes merge'" + +#: builtin/notes.c:709 +msgid "failed to read ref NOTES_MERGE_PARTIAL" +msgstr "s'ha fallat en llegir la referència NOTES_MERGE_PARTIAL" + +#: builtin/notes.c:711 +msgid "could not find commit from NOTES_MERGE_PARTIAL." +msgstr "no s'ha pogut trobar cap comissió de NOTES_MERGE_PARTIAL." + +#: builtin/notes.c:713 +msgid "could not parse commit from NOTES_MERGE_PARTIAL." +msgstr "no s'ha pogut analitzar la comissió de NOTES_MERGE_PARTIAL." + +#: builtin/notes.c:726 +msgid "failed to resolve NOTES_MERGE_REF" +msgstr "s'ha fallat en resoldre NOTES_MERGE_REF" + +#: builtin/notes.c:729 +msgid "failed to finalize notes merge" +msgstr "s'ha fallat en finalitzar la fusió de notes" + +#: builtin/notes.c:755 #, c-format msgid "unknown notes merge strategy %s" msgstr "estratègia de fusió de notes desconeguda %s" -#: builtin/notes.c:769 +#: builtin/notes.c:771 msgid "General options" msgstr "Opcions generals" -#: builtin/notes.c:771 +#: builtin/notes.c:773 msgid "Merge options" msgstr "Opcions de fusió" -#: builtin/notes.c:773 +#: builtin/notes.c:775 msgid "" "resolve notes conflicts using the given strategy (manual/ours/theirs/union/" "cat_sort_uniq)" @@ -9414,47 +10129,47 @@ msgstr "" "resol els conflictes de nota usant l'estratègia donada (manual/ours/theirs/" "union/cat_sort_uniq)" -#: builtin/notes.c:775 +#: builtin/notes.c:777 msgid "Committing unmerged notes" msgstr "S'estan cometent les notes sense fusionar" -#: builtin/notes.c:777 +#: builtin/notes.c:779 msgid "finalize notes merge by committing unmerged notes" msgstr "finalitza la fusió de notes cometent les notes sense fusionar" -#: builtin/notes.c:779 +#: builtin/notes.c:781 msgid "Aborting notes merge resolution" msgstr "S'està avortant la resolució de fusió de notes" -#: builtin/notes.c:781 +#: builtin/notes.c:783 msgid "abort notes merge" msgstr "avorta la fusió de notes" -#: builtin/notes.c:792 +#: builtin/notes.c:794 msgid "cannot mix --commit, --abort or -s/--strategy" msgstr "no es pot combinar --commit, --abort i -s/--strategy" -#: builtin/notes.c:797 -msgid "Must specify a notes ref to merge" -msgstr "Cal especificar una referència de notes a fusionar" +#: builtin/notes.c:799 +msgid "must specify a notes ref to merge" +msgstr "cal especificar una referència de notes a fusionar" -#: builtin/notes.c:821 +#: builtin/notes.c:823 #, c-format -msgid "Unknown -s/--strategy: %s" +msgid "unknown -s/--strategy: %s" msgstr "-s/--strategy desconeguda: %s" -#: builtin/notes.c:858 +#: builtin/notes.c:860 #, c-format -msgid "A notes merge into %s is already in-progress at %s" -msgstr "Una fusió de notes a %s ja està en curs a %s" +msgid "a notes merge into %s is already in-progress at %s" +msgstr "una fusió de notes a %s ja està en curs a %s" -#: builtin/notes.c:861 +#: builtin/notes.c:863 #, c-format -msgid "Failed to store link to current notes ref (%s)" +msgid "failed to store link to current notes ref (%s)" msgstr "" -"S'ha fallat en emmagatzemar l'enllaç a la referència de notes actual (%s)" +"s'ha fallat en emmagatzemar l'enllaç a la referència de notes actual (%s)" -#: builtin/notes.c:863 +#: builtin/notes.c:865 #, c-format msgid "" "Automatic notes merge failed. Fix conflicts in %s and commit the result with " @@ -9465,239 +10180,235 @@ msgstr "" "cometeu el resultat amb 'git notes merge --commit', o avorteu la fusió amb " "'git notes merge --abort'.\n" -#: builtin/notes.c:885 +#: builtin/notes.c:887 #, c-format msgid "Object %s has no note\n" msgstr "L'objecte %s no té cap nota\n" -#: builtin/notes.c:897 +#: builtin/notes.c:899 msgid "attempt to remove non-existent note is not an error" msgstr "l'intent d'eliminar una nota no existent no és un error" -#: builtin/notes.c:900 +#: builtin/notes.c:902 msgid "read object names from the standard input" msgstr "llegeix els noms d'objecte des de l'entrada estàndard" -#: builtin/notes.c:938 builtin/prune.c:105 builtin/worktree.c:127 +#: builtin/notes.c:940 builtin/prune.c:105 builtin/worktree.c:127 msgid "do not remove, show only" msgstr "no eliminis, només mostra" -#: builtin/notes.c:939 +#: builtin/notes.c:941 msgid "report pruned notes" msgstr "informa de notes podades" -#: builtin/notes.c:981 +#: builtin/notes.c:983 msgid "notes-ref" msgstr "referència de notes" -#: builtin/notes.c:982 +#: builtin/notes.c:984 msgid "use notes from " msgstr "usa les notes de " -#: builtin/notes.c:1017 builtin/remote.c:1623 +#: builtin/notes.c:1019 #, c-format -msgid "Unknown subcommand: %s" -msgstr "Subordre desconeguda: %s" +msgid "unknown subcommand: %s" +msgstr "subordre desconeguda: %s" -#: builtin/pack-objects.c:28 +#: builtin/pack-objects.c:29 msgid "" "git pack-objects --stdout [...] [< | < ]" msgstr "" "git pack-objects --stdout [...] [< | < " "]" -#: builtin/pack-objects.c:29 +#: builtin/pack-objects.c:30 msgid "" "git pack-objects [...] [< | < ]" msgstr "" "git pack-objects [...] [< | < " "]" -#: builtin/pack-objects.c:177 builtin/pack-objects.c:180 +#: builtin/pack-objects.c:179 builtin/pack-objects.c:182 #, c-format msgid "deflate error (%d)" msgstr "error de deflació (%d)" -#: builtin/pack-objects.c:766 +#: builtin/pack-objects.c:768 msgid "disabling bitmap writing, packs are split due to pack.packSizeLimit" msgstr "" "s'està inhabilitant l'escriptura de mapes de bits, es divideixen els paquets " "a causa de pack.packSizeLimit" -#: builtin/pack-objects.c:779 +#: builtin/pack-objects.c:781 msgid "Writing objects" msgstr "S'estan escrivint els objectes" -#: builtin/pack-objects.c:1037 +#: builtin/pack-objects.c:1070 msgid "disabling bitmap writing, as some objects are not being packed" msgstr "" "s'està inhabilitant l'escriptura de mapes de bits, perquè alguns objectes no " "s'empaqueten" -#: builtin/pack-objects.c:2197 +#: builtin/pack-objects.c:2346 msgid "Compressing objects" msgstr "S'estan comprimint objectes" -#: builtin/pack-objects.c:2611 +#: builtin/pack-objects.c:2759 #, c-format msgid "unsupported index version %s" msgstr "versió d'índex no compatible %s" -#: builtin/pack-objects.c:2615 +#: builtin/pack-objects.c:2763 #, c-format msgid "bad index version '%s'" msgstr "versió d'índex dolenta '%s'" -#: builtin/pack-objects.c:2645 +#: builtin/pack-objects.c:2793 msgid "do not show progress meter" msgstr "no mostris l'indicador de progrés" -#: builtin/pack-objects.c:2647 +#: builtin/pack-objects.c:2795 msgid "show progress meter" msgstr "mostra l'indicador de progrés" -#: builtin/pack-objects.c:2649 +#: builtin/pack-objects.c:2797 msgid "show progress meter during object writing phase" msgstr "mostra l'indicador de progrés durant la fase d'escriptura d'objectes" -#: builtin/pack-objects.c:2652 +#: builtin/pack-objects.c:2800 msgid "similar to --all-progress when progress meter is shown" msgstr "similar a --all-progress quan l'indicador de progrés es mostra" -#: builtin/pack-objects.c:2653 +#: builtin/pack-objects.c:2801 msgid "version[,offset]" msgstr "versió[,desplaçament]" -#: builtin/pack-objects.c:2654 +#: builtin/pack-objects.c:2802 msgid "write the pack index file in the specified idx format version" msgstr "" "escriu el fitxer d'índex de paquet en la versió de format d'índex " "especificada" -#: builtin/pack-objects.c:2657 +#: builtin/pack-objects.c:2805 msgid "maximum size of each output pack file" msgstr "mida màxima de cada fitxer de paquet de sortida" -#: builtin/pack-objects.c:2659 +#: builtin/pack-objects.c:2807 msgid "ignore borrowed objects from alternate object store" msgstr "" "ignora els objectes prestats d'un emmagatzemament d'objectes alternatiu" -#: builtin/pack-objects.c:2661 +#: builtin/pack-objects.c:2809 msgid "ignore packed objects" msgstr "ignora els objectes empaquetats" -#: builtin/pack-objects.c:2663 +#: builtin/pack-objects.c:2811 msgid "limit pack window by objects" msgstr "limita la finestra d'empaquetament per objectes" -#: builtin/pack-objects.c:2665 +#: builtin/pack-objects.c:2813 msgid "limit pack window by memory in addition to object limit" msgstr "" "limita la finestra d'empaquetament per memòria a més del límit d'objectes" -#: builtin/pack-objects.c:2667 +#: builtin/pack-objects.c:2815 msgid "maximum length of delta chain allowed in the resulting pack" msgstr "longitud màxima de la cadena de deltes permesa en el paquet resultant" -#: builtin/pack-objects.c:2669 +#: builtin/pack-objects.c:2817 msgid "reuse existing deltas" msgstr "reusa les deltes existents" -#: builtin/pack-objects.c:2671 +#: builtin/pack-objects.c:2819 msgid "reuse existing objects" msgstr "reusa els objectes existents" -#: builtin/pack-objects.c:2673 +#: builtin/pack-objects.c:2821 msgid "use OFS_DELTA objects" msgstr "usa objectes OFS_DELTA" -#: builtin/pack-objects.c:2675 +#: builtin/pack-objects.c:2823 msgid "use threads when searching for best delta matches" msgstr "usa fils en cercar les millores coincidències de delta" -#: builtin/pack-objects.c:2677 +#: builtin/pack-objects.c:2825 msgid "do not create an empty pack output" msgstr "no creïs una emissió de paquet buida" -#: builtin/pack-objects.c:2679 +#: builtin/pack-objects.c:2827 msgid "read revision arguments from standard input" msgstr "llegeix els paràmetres de revisió des de l'entrada estàndard" -#: builtin/pack-objects.c:2681 +#: builtin/pack-objects.c:2829 msgid "limit the objects to those that are not yet packed" msgstr "limita els objectes als quals encara no s'hagin empaquetat" -#: builtin/pack-objects.c:2684 +#: builtin/pack-objects.c:2832 msgid "include objects reachable from any reference" msgstr "inclou els objectes abastables de qualsevulla referència" -#: builtin/pack-objects.c:2687 +#: builtin/pack-objects.c:2835 msgid "include objects referred by reflog entries" msgstr "" "inclou els objectes als quals facin referència les entrades del registre de " "referències" -#: builtin/pack-objects.c:2690 +#: builtin/pack-objects.c:2838 msgid "include objects referred to by the index" msgstr "inclou els objectes als quals faci referència l'índex" -#: builtin/pack-objects.c:2693 +#: builtin/pack-objects.c:2841 msgid "output pack to stdout" msgstr "emet el paquet a stdout" -#: builtin/pack-objects.c:2695 +#: builtin/pack-objects.c:2843 msgid "include tag objects that refer to objects to be packed" msgstr "" "inclou els objectes d'etiqueta que facin referència als objectes a empaquetar" -#: builtin/pack-objects.c:2697 +#: builtin/pack-objects.c:2845 msgid "keep unreachable objects" msgstr "retén els objectes inabastables" -#: builtin/pack-objects.c:2699 +#: builtin/pack-objects.c:2847 msgid "pack loose unreachable objects" msgstr "empaqueta els objectes inabastables solts" -#: builtin/pack-objects.c:2700 parse-options.h:142 -msgid "time" -msgstr "hora" - -#: builtin/pack-objects.c:2701 +#: builtin/pack-objects.c:2849 msgid "unpack unreachable objects newer than
%4i %s