]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'sb/sparse-more'
authorJunio C Hamano <gitster@pobox.com>
Sat, 2 Apr 2011 00:50:20 +0000 (17:50 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 2 Apr 2011 00:50:20 +0000 (17:50 -0700)
* sb/sparse-more:
  Makefile: Cover more files with make check

133 files changed:
Documentation/RelNotes/1.7.4.2.txt
Documentation/RelNotes/1.7.5.txt
Documentation/config.txt
Documentation/git-am.txt
Documentation/git-bisect.txt
Documentation/git-filter-branch.txt
Documentation/git-grep.txt
Documentation/git-pack-objects.txt
Documentation/git-rev-list.txt
Documentation/git-tag.txt
Documentation/rev-list-options.txt
Documentation/technical/index-format.txt [new file with mode: 0644]
GIT-VERSION-GEN
Makefile
alloc.c
attr.c
builtin/checkout.c
builtin/clone.c
builtin/commit.c
builtin/config.c
builtin/describe.c
builtin/diff.c
builtin/fetch-pack.c
builtin/fmt-merge-msg.c
builtin/fsck.c
builtin/grep.c
builtin/hash-object.c
builtin/index-pack.c
builtin/log.c
builtin/merge-index.c
builtin/merge-recursive.c
builtin/merge-tree.c
builtin/mktag.c
builtin/notes.c
builtin/pack-redundant.c
builtin/pack-refs.c
builtin/patch-id.c
builtin/receive-pack.c
builtin/remote-ext.c
builtin/remote-fd.c
builtin/remote.c
builtin/reset.c
builtin/rev-list.c
builtin/rev-parse.c
builtin/send-pack.c
builtin/unpack-file.c
builtin/var.c
cache.h
config.c
config.mak.in
configure.ac
contrib/completion/git-completion.bash
contrib/fast-import/git-p4
contrib/thunderbird-patch-inline/appp.sh
daemon.c
diff-lib.c
diff.c
environment.c
fast-import.c
git-bisect.sh
git-gui/git-gui.sh
git-gui/lib/browser.tcl
git-gui/lib/choose_repository.tcl
git-gui/lib/commit.tcl
git-gui/lib/diff.tcl
git-gui/lib/index.tcl
git-gui/lib/merge.tcl
git-gui/lib/mergetool.tcl
git-gui/lib/remote.tcl
git-gui/lib/remote_branch_delete.tcl
git-gui/lib/transport.tcl
git-gui/po/glossary/pt_br.po [new file with mode: 0644]
git-gui/po/pt_br.po [new file with mode: 0644]
git-gui/po/ru.po
git-parse-remote.sh
git-stash.sh
git-svn.perl
gitweb/gitweb.perl
graph.c
imap-send.c
list-objects.c
log-tree.c
notes-merge.c
parse-options.c
pretty.c
reachable.c
read-cache.c
replace_object.c
rerere.c
revision.c
revision.h
run-command.c
sha1_file.c
strbuf.h
submodule.c
t/README
t/t0001-init.sh
t/t0081-line-buffer.sh
t/t1021-rerere-in-workdir.sh [new file with mode: 0755]
t/t2020-checkout-detach.sh
t/t3903-stash.sh
t/t4040-whitespace-status.sh
t/t5501-fetch-push-alternates.sh [new file with mode: 0755]
t/t5601-clone.sh
t/t6007-rev-list-cherry-pick-file.sh
t/t6009-rev-list-parent.sh
t/t6110-rev-list-sparse.sh [new file with mode: 0755]
t/t7607-merge-overwrite.sh
t/t8001-annotate.sh
t/t9010-svn-fe.sh
t/t9130-git-svn-authors-file.sh
t/t9800-git-p4.sh
t/test-lib.sh
test-line-buffer.c
test-subprocess.c
thread-utils.c
trace.c
transport-helper.c
transport.c
transport.h
tree-diff.c
unpack-trees.c
upload-pack.c
url.c
usage.c
vcs-svn/fast_export.c
vcs-svn/fast_export.h
vcs-svn/line_buffer.c
vcs-svn/line_buffer.h
vcs-svn/line_buffer.txt
vcs-svn/repo_tree.c
vcs-svn/repo_tree.h
vcs-svn/svndump.c

index 991dae4811d35b7be3c6e8f11dbb0b62c0420dd2..ef4ce1fcd37acedee7977ff0b0c73d31e6e30321 100644 (file)
@@ -12,6 +12,10 @@ Fixes since v1.7.4.1
    tiny packfiles.  We now close the file descriptor early when the entire
    packfile fits inside one mmap window.
 
+ * "git bisect visualize" tried to run "gitk" in windowing
+   environments even when "gitk" is not installed, resulting in a
+   strange error message.
+
  * "git clone /no/such/path" did not fail correctly.
 
  * "git commit" did not correctly error out when the user asked to use a
@@ -45,6 +49,9 @@ Fixes since v1.7.4.1
 
  * gitweb's "highlight" interface mishandled tabs.
 
+ * gitweb didn't understand timezones with GMT offset that is not
+   multiple of a whole hour.
+
  * gitweb had a few forward-incompatible syntactic constructs and
    also used incorrect variable when showing the file mode in a diff.
 
index b917d0bcf06080175eb929e4c88d6c75e03fd832..648dbfd908d02d0c3a3c9a66330be02c0f4f7b32 100644 (file)
@@ -10,11 +10,20 @@ Updates since v1.7.4
 
  * Various vcs-svn enhancements.
 
+ * Various git-gui updates (0.14.0).
+
  * Update to more modern HP-UX port.
 
  * The codebase is getting prepared for i18n/l10n; no translated/translatable
    strings in the code yet.
 
+ * The bash completion script can now complete symmetric difference
+   for "git diff" command, e.g. "git diff ...bra<TAB>".
+
+ * The default minimum length of abbreviated and unique object names
+   can now be configured by setting the core.abbrev configuration
+   variable.
+
  * "git apply -v" reports offset lines when the patch does not apply at
    the exact location recorded in the diff output.
 
@@ -43,6 +52,11 @@ Updates since v1.7.4
    reached, without spewing unnecessary error messages that complain about
    the server response it never got.
 
+ * "git fetch" vs "git upload-pack" transfer learned 'no-done'
+   protocol extension to save one round-trip after the content
+   negotiation is done. This saves one HTTP RPC, reducing the overall
+   latency for a trivial fetch.
+
  * "git grep -f <filename>" learned to treat "-" as "read from the
    standard input stream".
 
@@ -52,6 +66,11 @@ Updates since v1.7.4
  * "git log" type commands now understand globbing pathspecs.  You
    can say "git log -- '*.txt'" for example.
 
+ * "git log" family of commands learned --cherry and --cherry-mark
+   options that can be used to view two diverged branches while omitting
+   or highlighting equivalent changes that appear on both sides of a
+   symmetric difference (e.g. "log --cherry A...B").
+
  * "git mergetool" learned how to drive "beyond compare 3" as well.
 
  * "git rerere forget" without pathspec used to forget all the saved
@@ -93,8 +112,29 @@ release, unless otherwise noted.
    in the working tree that are in the way in order to check out paths
    under it from the named branch (js/checkout-untracked-symlink).
 
+ * "git diff --quiet" did not work very well with the "--diff-filter"
+   option (jc/maint-diff-q-filter).
+
+ * "git fetch" from a client that is mostly following the remote
+   needlessly told all of its refs to the server for both sides to
+   compute the set of objects that need to be transferred efficiently,
+   instead of stopping when the server heard enough. In a project with
+   many tags, this turns out to be extremely wasteful, especially over
+   the smart HTTP transport (sp/maint-{upload,fetch}-pack-stop-early~1).
+
+ * "git fetch" run from a repository that uses the same repository as
+   its alternate object store as the repository it is fetching from
+   did not tell the server that it already has access to objects
+   reachable from the refs in their common alternate object store,
+   causing it to fetch unnecessary objects (jc/maint-fetch-alt).
+
+ * "git stash apply" reported the result of its operation by running
+   "git status" from the top-level of the working tree; it should (and
+   now does) run it from the user's working directory
+   (pk/stash-apply-status-relative).
+
 ---
 exec >/var/tmp/1
-O=v1.7.4.1-352-gcdc3466
+O=v1.7.5-rc0
 echo O=$(git describe 'master')
 git shortlog --no-merges ^maint ^$O master
index 701fba92dc1cfda8982aee8b66eb39b8b1c5816b..52ffbf4efb8d17c22893112208c5864d4c19741d 100644 (file)
@@ -62,7 +62,7 @@ Internal whitespace within a variable value is retained verbatim.
 
 The values following the equals sign in variable assign are all either
 a string, an integer, or a boolean.  Boolean values may be given as yes/no,
-0/1, true/false or on/off.  Case is not significant in boolean values, when
+1/0, true/false or on/off.  Case is not significant in boolean values, when
 converting value to the canonical form using '--bool' type specifier;
 'git config' will ensure that the output is "true" or "false".
 
@@ -558,6 +558,12 @@ core.sparseCheckout::
        Enable "sparse checkout" feature. See section "Sparse checkout" in
        linkgit:git-read-tree[1] for more information.
 
+core.abbrev::
+       Set the length object names are abbreviated to.  If unspecified,
+       many commands abbreviate to 7 hexdigits, which may not be enough
+       for abbreviated object names to stay unique for sufficiently long
+       time.
+
 add.ignore-errors::
 add.ignoreErrors::
        Tells 'git add' to continue adding files when some files cannot be
index 621b720091f92008c11a03ea2a1e69b72e50a03b..6b1b5af64e2daec1ecc8ee832f58f5186d740a79 100644 (file)
@@ -173,9 +173,9 @@ aborts in the middle.  You can recover from this in one of two ways:
   the index file to bring it into a state that the patch should
   have produced.  Then run the command with the '--resolved' option.
 
-The command refuses to process new mailboxes while the `.git/rebase-apply`
-directory exists, so if you decide to start over from scratch,
-run `rm -f -r .git/rebase-apply` before running the command with mailbox
+The command refuses to process new mailboxes until the current
+operation is finished, so if you decide to start over from scratch,
+run `git am --abort` before running the command with mailbox
 names.
 
 Before any patches are applied, ORIG_HEAD is set to the tip of the
index 4b4b096ce5390d4343c73fe187d686e7072d3549..7b7bafba0c514755f9eec423b5aed19db640c091 100644 (file)
@@ -279,53 +279,68 @@ $ git bisect start HEAD origin --    # HEAD is bad, origin is good
 $ git bisect run make test           # "make test" builds and tests
 ------------
 
-* Automatically bisect a broken test suite:
+* Automatically bisect a broken test case:
 +
 ------------
 $ cat ~/test.sh
 #!/bin/sh
-make || exit 125                   # this skips broken builds
-make test                          # "make test" runs the test suite
-$ git bisect start v1.3 v1.1 --    # v1.3 is bad, v1.1 is good
+make || exit 125                     # this skips broken builds
+~/check_test_case.sh                 # does the test case pass?
+$ git bisect start HEAD HEAD~10 --   # culprit is among the last 10
 $ git bisect run ~/test.sh
 ------------
 +
 Here we use a "test.sh" custom script. In this script, if "make"
 fails, we skip the current commit.
+"check_test_case.sh" should "exit 0" if the test case passes,
+and "exit 1" otherwise.
 +
-It is safer to use a custom script outside the repository to prevent
-interactions between the bisect, make and test processes and the
-script.
-+
-"make test" should "exit 0", if the test suite passes, and
-"exit 1" otherwise.
+It is safer if both "test.sh" and "check_test_case.sh" are
+outside the repository to prevent interactions between the bisect,
+make and test processes and the scripts.
 
-* Automatically bisect a broken test case:
+* Automatically bisect with temporary modifications (hot-fix):
 +
 ------------
 $ cat ~/test.sh
 #!/bin/sh
-make || exit 125                     # this skips broken builds
-~/check_test_case.sh                 # does the test case passes ?
-$ git bisect start HEAD HEAD~10 --   # culprit is among the last 10
-$ git bisect run ~/test.sh
+
+# tweak the working tree by merging the hot-fix branch
+# and then attempt a build
+if     git merge --no-commit hot-fix &&
+       make
+then
+       # run project specific test and report its status
+       ~/check_test_case.sh
+       status=$?
+else
+       # tell the caller this is untestable
+       status=125
+fi
+
+# undo the tweak to allow clean flipping to the next commit
+git reset --hard
+
+# return control
+exit $status
 ------------
 +
-Here "check_test_case.sh" should "exit 0" if the test case passes,
-and "exit 1" otherwise.
-+
-It is safer if both "test.sh" and "check_test_case.sh" scripts are
-outside the repository to prevent interactions between the bisect,
-make and test processes and the scripts.
+This applies modifications from a hot-fix branch before each test run,
+e.g. in case your build or test environment changed so that older
+revisions may need a fix which newer ones have already. (Make sure the
+hot-fix branch is based off a commit which is contained in all revisions
+which you are bisecting, so that the merge does not pull in too much, or
+use `git cherry-pick` instead of `git merge`.)
 
-* Automatically bisect a broken test suite:
+* Automatically bisect a broken test case:
 +
 ------------
 $ git bisect start HEAD HEAD~10 --   # culprit is among the last 10
 $ git bisect run sh -c "make || exit 125; ~/check_test_case.sh"
 ------------
 +
-Does the same as the previous example, but on a single line.
+This shows that you can do without a run script if you write the test
+on a single line.
 
 SEE ALSO
 --------
index 03c76c717ac6c41edfaaed47fa9798344e5e8f94..9dc1f2a94708d40daf428a427dd2ea4256cc172a 100644 (file)
@@ -361,7 +361,7 @@ git filter-branch --index-filter \
        'git ls-files -s | sed "s-\t\"*-&newsubdir/-" |
                GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
                        git update-index --index-info &&
-        mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' HEAD
+        mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
 ---------------------------------------------------------------
 
 
index d4d425ea30292d69edd6e89a78e25dbe6346ef40..132505eb4f83fdc64778df8cf58b595ca6eadf1f 100644 (file)
@@ -93,6 +93,7 @@ OPTIONS
        as a regex).
 
 -n::
+--line-number::
        Prefix the line number to matching lines.
 
 -l::
index a51071e5247f3a6c525b93384ec0ffc1a12eb8d2..442018bcb8f14dbb7572ad87a3c1adb588444278 100644 (file)
@@ -190,9 +190,9 @@ self-contained. Use `git index-pack --fix-thin`
 (see linkgit:git-index-pack[1]) to restore the self-contained property.
 
 --delta-base-offset::
-       A packed archive can express base object of a delta as
-       either 20-byte object name or as an offset in the
-       stream, but older version of git does not understand the
+       A packed archive can express the base object of a delta as
+       either 20-byte object name or as an offset in the
+       stream, but older versions of git don't understand the
        latter.  By default, 'git pack-objects' only uses the
        former format for better compatibility.  This option
        allows the command to use the latter format for
index 5ce4d7fd0b2fbab894e67fa266afae2d13c78284..415f4f0b303da22e9eec19c1b9e24732a74ecf67 100644 (file)
@@ -16,6 +16,10 @@ SYNOPSIS
             [ \--sparse ]
             [ \--merges ]
             [ \--no-merges ]
+            [ \--min-parents=<number> ]
+            [ \--no-min-parents ]
+            [ \--max-parents=<number> ]
+            [ \--no-max-parents ]
             [ \--first-parent ]
             [ \--remove-empty ]
             [ \--full-history ]
@@ -31,6 +35,9 @@ SYNOPSIS
             [ \--parents ]
             [ \--timestamp ]
             [ \--left-right ]
+            [ \--left-only ]
+            [ \--right-only ]
+            [ \--cherry-mark ]
             [ \--cherry-pick ]
             [ \--encoding[=<encoding>] ]
             [ \--(author|committer|grep)=<pattern> ]
index 61263fa3290598680207c93d23d44ac3cd1f34e1..d82f62120a21059a31d9c708c39d93b2a630d590 100644 (file)
@@ -165,13 +165,12 @@ You can test which tag you have by doing
 
 which should return 0123456789abcdef.. if you have the new version.
 
-Sorry for inconvenience.
+Sorry for the inconvenience.
 ------------
 
 Does this seem a bit complicated?  It *should* be. There is no
-way that it would be correct to just "fix" it behind peoples
-backs. People need to know that their tags might have been
-changed.
+way that it would be correct to just "fix" it automatically.
+People need to know that their tags might have been changed.
 
 
 On Automatic following
@@ -189,9 +188,10 @@ the toplevel but not limited to them.  Mere mortals when pulling
 from each other do not necessarily want to automatically get
 private anchor point tags from the other person.
 
-You would notice "please pull" messages on the mailing list says
-repo URL and branch name alone.  This is designed to be easily
-cut&pasted to a 'git fetch' command line:
+Often, "please pull" messages on the mailing list just provide
+two pieces of information: a repo URL and a branch name; this
+is designed to be easily cut&pasted at the end of a 'git fetch'
+command line:
 
 ------------
 Linus, please pull from
@@ -207,14 +207,14 @@ becomes:
 $ git pull git://git..../proj.git master
 ------------
 
-In such a case, you do not want to automatically follow other's
-tags.
+In such a case, you do not want to automatically follow the other
+person's tags.
 
-One important aspect of git is it is distributed, and being
-distributed largely means there is no inherent "upstream" or
+One important aspect of git is its distributed nature, which
+largely means there is no inherent "upstream" or
 "downstream" in the system.  On the face of it, the above
 example might seem to indicate that the tag namespace is owned
-by upper echelon of people and tags only flow downwards, but
+by the upper echelon of people and that tags only flow downwards, but
 that is not the case.  It only shows that the usage pattern
 determines who are interested in whose tags.
 
@@ -232,7 +232,7 @@ this case.
 
 It may well be that among networking people, they may want to
 exchange the tags internal to their group, but in that workflow
-they are most likely tracking with each other's progress by
+they are most likely tracking each other's progress by
 having remote-tracking branches.  Again, the heuristic to automatically
 follow such tags is a good thing.
 
@@ -242,21 +242,21 @@ On Backdating Tags
 
 If you have imported some changes from another VCS and would like
 to add tags for major releases of your work, it is useful to be able
-to specify the date to embed inside of the tag object.  The data in
+to specify the date to embed inside of the tag object; such data in
 the tag object affects, for example, the ordering of tags in the
 gitweb interface.
 
 To set the date used in future tag objects, set the environment
-variable GIT_COMMITTER_DATE to one or more of the date and time.  The
-date and time can be specified in a number of ways; the most common
-is "YYYY-MM-DD HH:MM".
+variable GIT_COMMITTER_DATE (see the later discussion of possible
+values; the most common form is "YYYY-MM-DD HH:MM").
 
-An example follows.
+For example:
 
 ------------
 $ GIT_COMMITTER_DATE="2006-10-02 10:31" git tag -s v1.0.1
 ------------
 
+include::date-formats.txt[]
 
 SEE ALSO
 --------
index 09860de9c2ff18115806c3cdf50ebd6163b3560e..ea5c6c49bd1b673aba48c057add1b5d15ae840a0 100644 (file)
@@ -72,11 +72,26 @@ endif::git-rev-list[]
 
 --merges::
 
-       Print only merge commits.
+       Print only merge commits. This is exactly the same as `--min-parents=2`.
 
 --no-merges::
 
-       Do not print commits with more than one parent.
+       Do not print commits with more than one parent. This is
+       exactly the same as `--max-parents=1`.
+
+--min-parents=<number>::
+--max-parents=<number>::
+--no-min-parents::
+--no-max-parents::
+
+       Show only commits which have at least (or at most) that many
+       commits. In particular, `--max-parents=1` is the same as `--no-merges`,
+       `--min-parents=2` is the same as `--merges`.  `--max-parents=0`
+       gives all root commits and `--min-parents=3` all octopus merges.
++
+`--no-min-parents` and `--no-max-parents` reset these limits (to no limit)
+again.  Equivalent forms are `--min-parents=0` (any commit has 0 or more
+parents) and `--max-parents=-1` (negative numbers denote no upper limit).
 
 --first-parent::
        Follow only the first parent commit upon seeing a merge
@@ -151,6 +166,11 @@ ifdef::git-rev-list[]
        to /dev/null as the output does not have to be formatted.
 endif::git-rev-list[]
 
+--cherry-mark::
+
+       Like `--cherry-pick` (see below) but mark equivalent commits
+       with `=` rather than omitting them, and inequivalent ones with `+`.
+
 --cherry-pick::
 
        Omit any commit that introduces the same change as
@@ -165,6 +185,27 @@ from the other branch (for example, "3rd on b" may be cherry-picked
 from branch A).  With this option, such pairs of commits are
 excluded from the output.
 
+--left-only::
+--right-only::
+
+       List only commits on the respective side of a symmetric range,
+       i.e. only those which would be marked `<` resp. `>` by
+       `--left-right`.
++
+For example, `--cherry-pick --right-only A...B` omits those
+commits from `B` which are in `A` or are patch-equivalent to a commit in
+`A`. In other words, this lists the `{plus}` commits from `git cherry A B`.
+More precisely, `--cherry-pick --right-only --no-merges` gives the exact
+list.
+
+--cherry::
+
+       A synonym for `--right-only --cherry-mark --no-merges`; useful to
+       limit the output to the commits on our side and mark those that
+       have been applied to the other side of a forked history with
+       `git log --cherry upstream...mybranch`, similar to
+       `git cherry upstream mybranch`.
+
 -g::
 --walk-reflogs::
 
diff --git a/Documentation/technical/index-format.txt b/Documentation/technical/index-format.txt
new file mode 100644 (file)
index 0000000..7b233ca
--- /dev/null
@@ -0,0 +1,185 @@
+GIT index format
+================
+
+= The git index file has the following format
+
+  All binary numbers are in network byte order. Version 2 is described
+  here unless stated otherwise.
+
+   - A 12-byte header consisting of
+
+     4-byte signature:
+       The signature is { 'D', 'I', 'R', 'C' } (stands for "dircache")
+
+     4-byte version number:
+       The current supported versions are 2 and 3.
+
+     32-bit number of index entries.
+
+   - A number of sorted index entries (see below).
+
+   - Extensions
+
+     Extensions are identified by signature. Optional extensions can
+     be ignored if GIT does not understand them.
+
+     GIT currently supports cached tree and resolve undo extensions.
+
+     4-byte extension signature. If the first byte is 'A'..'Z' the
+     extension is optional and can be ignored.
+
+     32-bit size of the extension
+
+     Extension data
+
+   - 160-bit SHA-1 over the content of the index file before this
+     checksum.
+
+== Index entry
+
+  Index entries are sorted in ascending order on the name field,
+  interpreted as a string of unsigned bytes (i.e. memcmp() order, no
+  localization, no special casing of directory separator '/'). Entries
+  with the same name are sorted by their stage field.
+
+  32-bit ctime seconds, the last time a file's metadata changed
+    this is stat(2) data
+
+  32-bit ctime nanosecond fractions
+    this is stat(2) data
+
+  32-bit mtime seconds, the last time a file's data changed
+    this is stat(2) data
+
+  32-bit mtime nanosecond fractions
+    this is stat(2) data
+
+  32-bit dev
+    this is stat(2) data
+
+  32-bit ino
+    this is stat(2) data
+
+  32-bit mode, split into (high to low bits)
+
+    4-bit object type
+      valid values in binary are 1000 (regular file), 1010 (symbolic link)
+      and 1110 (gitlink)
+
+    3-bit unused
+
+    9-bit unix permission. Only 0755 and 0644 are valid for regular files.
+    Symbolic links and gitlinks have value 0 in this field.
+
+  32-bit uid
+    this is stat(2) data
+
+  32-bit gid
+    this is stat(2) data
+
+  32-bit file size
+    This is the on-disk size from stat(2), truncated to 32-bit.
+
+  160-bit SHA-1 for the represented object
+
+  A 16-bit 'flags' field split into (high to low bits)
+
+    1-bit assume-valid flag
+
+    1-bit extended flag (must be zero in version 2)
+
+    2-bit stage (during merge)
+
+    12-bit name length if the length is less than 0xFFF; otherwise 0xFFF
+    is stored in this field.
+
+  (Version 3) A 16-bit field, only applicable if the "extended flag"
+  above is 1, split into (high to low bits).
+
+    1-bit reserved for future
+
+    1-bit skip-worktree flag (used by sparse checkout)
+
+    1-bit intent-to-add flag (used by "git add -N")
+
+    13-bit unused, must be zero
+
+  Entry path name (variable length) relative to top level directory
+    (without leading slash). '/' is used as path separator. The special
+    path components ".", ".." and ".git" (without quotes) are disallowed.
+    Trailing slash is also disallowed.
+
+    The exact encoding is undefined, but the '.' and '/' characters
+    are encoded in 7-bit ASCII and the encoding cannot contain a NUL
+    byte (iow, this is a UNIX pathname).
+
+  1-8 nul bytes as necessary to pad the entry to a multiple of eight bytes
+  while keeping the name NUL-terminated.
+
+== Extensions
+
+=== Cached tree
+
+  Cached tree extension contains pre-computed hashes for trees that can
+  be derived from the index. It helps speed up tree object generation
+  from index for a new commit.
+
+  When a path is updated in index, the path must be invalidated and
+  removed from tree cache.
+
+  The signature for this extension is { 'T', 'R', 'E', 'E' }.
+
+  A series of entries fill the entire extension; each of which
+  consists of:
+
+  - NUL-terminated path component (relative to its parent directory);
+
+  - ASCII decimal number of entries in the index that is covered by the
+    tree this entry represents (entry_count);
+
+  - A space (ASCII 32);
+
+  - ASCII decimal number that represents the number of subtrees this
+    tree has;
+
+  - A newline (ASCII 10); and
+
+  - 160-bit object name for the object that would result from writing
+    this span of index as a tree.
+
+  An entry can be in an invalidated state and is represented by having -1
+  in the entry_count field.
+
+  The entries are written out in the top-down, depth-first order.  The
+  first entry represents the root level of the repository, followed by the
+  first subtree---let's call this A---of the root level (with its name
+  relative to the root level), followed by the first subtree of A (with
+  its name relative to A), ...
+
+=== Resolve undo
+
+  A conflict is represented in the index as a set of higher stage entries.
+  When a conflict is resolved (e.g. with "git add path"), these higher
+  stage entries will be removed and a stage-0 entry with proper resoluton
+  is added.
+
+  When these higher stage entries are removed, they are saved in the
+  resolve undo extension, so that conflicts can be recreated (e.g. with
+  "git checkout -m"), in case users want to redo a conflict resolution
+  from scratch.
+
+  The signature for this extension is { 'R', 'E', 'U', 'C' }.
+
+  A series of entries fill the entire extension; each of which
+  consists of:
+
+  - NUL-terminated pathname the entry describes (relative to the root of
+    the repository, i.e. full pathname);
+
+  - Three NUL-terminated ASCII octal numbers, entry mode of entries in
+    stage 1 to 3 (a missing stage is represented by "0" in this field);
+    and
+
+  - At most three 160-bit object names of the entry in stages from 1 to 3
+    (nothing is written for a missing stage).
+
index 92fe7a59dbf81b0a055280f9351811641ce7044a..35848df0346aef1c2f91fb81cecd8751590db196 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.7.4
+DEF_VER=v1.7.5-rc0
 
 LF='
 '
index 97cd1507fa2924b958a1ea88568844b11e653dbd..92c1c5e23b96f8bed1b1ac2dbff6c05580ecf678 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -45,11 +45,6 @@ all::
 # Define NO_D_TYPE_IN_DIRENT if your platform defines DT_UNKNOWN but lacks
 # d_type in struct dirent (Cygwin 1.5, fixed in Cygwin 1.7).
 #
-# Define NO_C99_FORMAT if your formatted IO functions (printf/scanf et.al.)
-# do not support the 'size specifiers' introduced by C99, namely ll, hh,
-# j, z, t. (representing long long int, char, intmax_t, size_t, ptrdiff_t).
-# some C compilers supported these specifiers prior to C99 as an extension.
-#
 # Define NO_STRCASESTR if you don't have strcasestr.
 #
 # Define NO_MEMMEM if you don't have memmem.
@@ -878,7 +873,6 @@ ifeq ($(uname_S),SunOS)
                NO_UNSETENV = YesPlease
                NO_SETENV = YesPlease
                NO_STRLCPY = YesPlease
-               NO_C99_FORMAT = YesPlease
                NO_STRTOUMAX = YesPlease
                GIT_TEST_CMP = cmp
        endif
@@ -889,21 +883,18 @@ ifeq ($(uname_S),SunOS)
                NO_UNSETENV = YesPlease
                NO_SETENV = YesPlease
                NO_STRLCPY = YesPlease
-               NO_C99_FORMAT = YesPlease
                NO_STRTOUMAX = YesPlease
                GIT_TEST_CMP = cmp
        endif
        ifeq ($(uname_R),5.8)
                NO_UNSETENV = YesPlease
                NO_SETENV = YesPlease
-               NO_C99_FORMAT = YesPlease
                NO_STRTOUMAX = YesPlease
                GIT_TEST_CMP = cmp
        endif
        ifeq ($(uname_R),5.9)
                NO_UNSETENV = YesPlease
                NO_SETENV = YesPlease
-               NO_C99_FORMAT = YesPlease
                NO_STRTOUMAX = YesPlease
                GIT_TEST_CMP = cmp
        endif
@@ -1083,7 +1074,6 @@ ifeq ($(uname_S),Windows)
        NO_MEMMEM = YesPlease
        # NEEDS_LIBICONV = YesPlease
        NO_ICONV = YesPlease
-       NO_C99_FORMAT = YesPlease
        NO_STRTOUMAX = YesPlease
        NO_STRTOULL = YesPlease
        NO_MKDTEMP = YesPlease
@@ -1160,7 +1150,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))
        NO_MEMMEM = YesPlease
        NEEDS_LIBICONV = YesPlease
        OLD_ICONV = YesPlease
-       NO_C99_FORMAT = YesPlease
        NO_STRTOUMAX = YesPlease
        NO_MKDTEMP = YesPlease
        NO_MKSTEMPS = YesPlease
@@ -1363,9 +1352,6 @@ endif
 ifdef NO_NSEC
        BASIC_CFLAGS += -DNO_NSEC
 endif
-ifdef NO_C99_FORMAT
-       BASIC_CFLAGS += -DNO_C99_FORMAT
-endif
 ifdef SNPRINTF_RETURNS_BOGUS
        COMPAT_CFLAGS += -DSNPRINTF_RETURNS_BOGUS
        COMPAT_OBJS += compat/snprintf.o
diff --git a/alloc.c b/alloc.c
index 6ef6753d180afad29bc335854150c824b9de8a18..aeae55c976802264d714282218e58a858a9c68b5 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -51,19 +51,12 @@ DEFINE_ALLOCATOR(commit, struct commit)
 DEFINE_ALLOCATOR(tag, struct tag)
 DEFINE_ALLOCATOR(object, union any_object)
 
-#ifdef NO_C99_FORMAT
-#define SZ_FMT "%u"
-#else
-#define SZ_FMT "%zu"
-#endif
-
 static void report(const char *name, unsigned int count, size_t size)
 {
-    fprintf(stderr, "%10s: %8u (" SZ_FMT " kB)\n", name, count, size);
+       fprintf(stderr, "%10s: %8u (%"PRIuMAX" kB)\n",
+                       name, count, (uintmax_t) size);
 }
 
-#undef SZ_FMT
-
 #define REPORT(name)   \
     report(#name, name##_allocs, name##_allocs*sizeof(struct name) >> 10)
 
diff --git a/attr.c b/attr.c
index 6aff6951d38d7f672aeb9851eca88c6e5a26b950..0e28ba871f9ba0da129610019cd0d0246f3a15f0 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -478,11 +478,6 @@ int git_attr_system(void)
        return !git_env_bool("GIT_ATTR_NOSYSTEM", 0);
 }
 
-int git_attr_global(void)
-{
-       return !git_env_bool("GIT_ATTR_NOGLOBAL", 0);
-}
-
 static int git_attr_config(const char *var, const char *value, void *dummy)
 {
        if (!strcmp(var, "core.attributesfile"))
@@ -511,7 +506,7 @@ static void bootstrap_attr_stack(void)
                }
 
                git_config(git_attr_config, NULL);
-               if (git_attr_global() && attributes_file) {
+               if (attributes_file) {
                        elem = read_attr_from_file(attributes_file, 1);
                        if (elem) {
                                elem->origin = NULL;
index 2bf02f2841a84a2a86de08e53328dbbb87ff3587..686d0ffd300e3e23cfd31b12d4267b5930787317 100644 (file)
@@ -603,13 +603,26 @@ static int add_one_ref_to_rev_list_arg(const char *refname,
        return 0;
 }
 
+static int clear_commit_marks_from_one_ref(const char *refname,
+                                     const unsigned char *sha1,
+                                     int flags,
+                                     void *cb_data)
+{
+       struct commit *commit = lookup_commit_reference_gently(sha1, 1);
+       if (commit)
+               clear_commit_marks(commit, -1);
+       return 0;
+}
 
 static void describe_one_orphan(struct strbuf *sb, struct commit *commit)
 {
        struct pretty_print_context ctx = { 0 };
 
        parse_commit(commit);
-       strbuf_addstr(sb, " - ");
+       strbuf_addstr(sb, "  ");
+       strbuf_addstr(sb,
+               find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
+       strbuf_addch(sb, ' ');
        pretty_print_commit(CMIT_FMT_ONELINE, commit, sb, &ctx);
        strbuf_addch(sb, '\n');
 }
@@ -674,6 +687,9 @@ static void orphaned_commit_warning(struct commit *commit)
                suggest_reattach(commit, &revs);
        else
                describe_detached_head("Previous HEAD position was", commit);
+
+       clear_commit_marks(commit, -1);
+       for_each_ref(clear_commit_marks_from_one_ref, NULL);
 }
 
 static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
index 02547adba5d841c066ed7e9c93247b509b2b9c44..c6e10bb9e916a21ad5c71018d6380ad85540dc65 100644 (file)
@@ -8,7 +8,7 @@
  * Clone a repository into a different directory that does not yet exist.
  */
 
-#include "cache.h"
+#include "builtin.h"
 #include "parse-options.h"
 #include "fetch-pack.h"
 #include "refs.h"
index 3979b823ef4227aac641be48c47581c56423b9d7..54b20497b120bc2bf5ee6e4904eca0ca5d83ff4f 100644 (file)
@@ -1203,13 +1203,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
        refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, s.pathspec, NULL, NULL);
 
        fd = hold_locked_index(&index_lock, 0);
-       if (0 <= fd) {
-               if (active_cache_changed &&
-                   !write_cache(fd, active_cache, active_nr))
-                       commit_locked_index(&index_lock);
-               else
-                       rollback_lock_file(&index_lock);
-       }
+       if (0 <= fd)
+               update_index_if_able(&the_index, &index_lock);
 
        s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
        s.ignore_submodule_arg = ignore_submodule_arg;
index 76be0b786fd52f181f91b5ad3bdef891068946f1..3e3c52849773348a568241f678b3e3ee2e8d123a 100644 (file)
@@ -160,7 +160,7 @@ static int get_value(const char *key_, const char *regex_)
        if (!local) {
                const char *home = getenv("HOME");
                local = repo_config = git_pathdup("config");
-               if (git_config_global() && home)
+               if (home)
                        global = xstrdup(mkpath("%s/.gitconfig", home));
                if (git_config_system())
                        system_wide = git_etc_gitconfig();
index 3ba26dc8192d0a75d7e330d2f73d0d9841a6216c..4afd1504a666d670ec71bdbd61b09bc0530ed04b 100644 (file)
@@ -21,7 +21,7 @@ static int debug;     /* Display lots of verbose info */
 static int all;        /* Any valid ref can be used */
 static int tags;       /* Allow lightweight tags */
 static int longformat;
-static int abbrev = DEFAULT_ABBREV;
+static int abbrev = -1; /* unspecified */
 static int max_candidates = 10;
 static struct hash_table names;
 static int have_util;
@@ -420,7 +420,11 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
                OPT_END(),
        };
 
+       git_config(git_default_config, NULL);
        argc = parse_options(argc, argv, prefix, options, describe_usage, 0);
+       if (abbrev < 0)
+               abbrev = DEFAULT_ABBREV;
+
        if (max_candidates < 0)
                max_candidates = 0;
        else if (max_candidates > MAX_TAGS)
index 4c9deb28ec15d0c2adae795cc2c177b24256e585..655a013ed05edd369225aa9ee9f39f347d687172 100644 (file)
@@ -197,12 +197,7 @@ static void refresh_index_quietly(void)
        discard_cache();
        read_cache();
        refresh_cache(REFRESH_QUIET|REFRESH_UNMERGED);
-
-       if (active_cache_changed &&
-           !write_cache(fd, active_cache, active_nr))
-               commit_locked_index(lock_file);
-
-       rollback_lock_file(lock_file);
+       update_index_if_able(&the_index, lock_file);
 }
 
 static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv)
index 272bc383d6de5c19970f7c65b924551d9b76598a..85aff029b225c023f09fda635f16cc00a22ed7ca 100644 (file)
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "builtin.h"
 #include "refs.h"
 #include "pkt-line.h"
 #include "commit.h"
@@ -9,11 +9,13 @@
 #include "fetch-pack.h"
 #include "remote.h"
 #include "run-command.h"
+#include "transport.h"
 
 static int transfer_unpack_limit = -1;
 static int fetch_unpack_limit = -1;
 static int unpack_limit = 100;
 static int prefer_ofs_delta = 1;
+static int no_done = 0;
 static struct fetch_pack_args args = {
        /* .uploadpack = */ "git-upload-pack",
 };
@@ -217,14 +219,40 @@ static void send_request(int fd, struct strbuf *buf)
                safe_write(fd, buf->buf, buf->len);
 }
 
+static void insert_one_alternate_ref(const struct ref *ref, void *unused)
+{
+       rev_list_insert_ref(NULL, ref->old_sha1, 0, NULL);
+}
+
+static void insert_alternate_refs(void)
+{
+       foreach_alt_odb(refs_from_alternate_cb, insert_one_alternate_ref);
+}
+
+#define INITIAL_FLUSH 16
+#define PIPESAFE_FLUSH 32
+#define LARGE_FLUSH 1024
+
+static int next_flush(int count)
+{
+       int flush_limit = args.stateless_rpc ? LARGE_FLUSH : PIPESAFE_FLUSH;
+
+       if (count < flush_limit)
+               count <<= 1;
+       else
+               count += flush_limit;
+       return count;
+}
+
 static int find_common(int fd[2], unsigned char *result_sha1,
                       struct ref *refs)
 {
        int fetching;
-       int count = 0, flushes = 0, retval;
+       int count = 0, flushes = 0, flush_at = INITIAL_FLUSH, retval;
        const unsigned char *sha1;
        unsigned in_vain = 0;
        int got_continue = 0;
+       int got_ready = 0;
        struct strbuf req_buf = STRBUF_INIT;
        size_t state_len = 0;
 
@@ -235,6 +263,7 @@ static int find_common(int fd[2], unsigned char *result_sha1,
        marked = 1;
 
        for_each_ref(rev_list_insert_ref, NULL);
+       insert_alternate_refs();
 
        fetching = 0;
        for ( ; refs ; refs = refs->next) {
@@ -262,6 +291,7 @@ static int find_common(int fd[2], unsigned char *result_sha1,
                        struct strbuf c = STRBUF_INIT;
                        if (multi_ack == 2)     strbuf_addstr(&c, " multi_ack_detailed");
                        if (multi_ack == 1)     strbuf_addstr(&c, " multi_ack");
+                       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.use_thin_pack) strbuf_addstr(&c, " thin-pack");
@@ -332,19 +362,20 @@ static int find_common(int fd[2], unsigned char *result_sha1,
                if (args.verbose)
                        fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
                in_vain++;
-               if (!(31 & ++count)) {
+               if (flush_at <= ++count) {
                        int ack;
 
                        packet_buf_flush(&req_buf);
                        send_request(fd[1], &req_buf);
                        strbuf_setlen(&req_buf, state_len);
                        flushes++;
+                       flush_at = next_flush(count);
 
                        /*
                         * We keep one window "ahead" of the other side, and
                         * will wait for an ACK only on the next one
                         */
-                       if (!args.stateless_rpc && count == 32)
+                       if (!args.stateless_rpc && count == INITIAL_FLUSH)
                                continue;
 
                        consume_shallow_list(fd[0]);
@@ -379,6 +410,10 @@ static int find_common(int fd[2], unsigned char *result_sha1,
                                        retval = 0;
                                        in_vain = 0;
                                        got_continue = 1;
+                                       if (ack == ACK_ready) {
+                                               rev_list = NULL;
+                                               got_ready = 1;
+                                       }
                                        break;
                                        }
                                }
@@ -392,8 +427,10 @@ static int find_common(int fd[2], unsigned char *result_sha1,
                }
        }
 done:
-       packet_buf_write(&req_buf, "done\n");
-       send_request(fd[1], &req_buf);
+       if (!got_ready || !no_done) {
+               packet_buf_write(&req_buf, "done\n");
+               send_request(fd[1], &req_buf);
+       }
        if (args.verbose)
                fprintf(stderr, "done\n");
        if (retval != 0) {
@@ -696,6 +733,12 @@ static struct ref *do_fetch_pack(int fd[2],
                if (args.verbose)
                        fprintf(stderr, "Server supports multi_ack_detailed\n");
                multi_ack = 2;
+               if (server_supports("no-done")) {
+                       if (args.verbose)
+                               fprintf(stderr, "Server supports no-done\n");
+                       if (args.stateless_rpc)
+                               no_done = 1;
+               }
        }
        else if (server_supports("multi_ack")) {
                if (args.verbose)
index 5189b16c9e59c20b449435c413c34da9f7bf9baa..75816329d6153c35e0763b35f70cfaf165f2a4b8 100644 (file)
@@ -31,7 +31,7 @@ struct src_data {
        int head_status;
 };
 
-void init_src_data(struct src_data *data)
+static void init_src_data(struct src_data *data)
 {
        data->branch.strdup_strings = 1;
        data->tag.strdup_strings = 1;
index 795aba087fe9c6ce0e644526d662a561b7f13f31..5ae0366bc8cfe52f226c2af151a66d39b9df02aa 100644 (file)
@@ -140,11 +140,10 @@ static int traverse_reachable(void)
        int result = 0;
        while (pending.nr) {
                struct object_array_entry *entry;
-               struct object *obj, *parent;
+               struct object *obj;
 
                entry = pending.objects + --pending.nr;
                obj = entry->item;
-               parent = (struct object *) entry->name;
                result |= traverse_one_object(obj);
        }
        return !!result;
index 0bf8c0116a6a4c178a2c368f17d4103e91486624..85e9583a1335330f8e852d7937abb10c97798bc0 100644 (file)
@@ -769,7 +769,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                OPT_BOOLEAN('F', "fixed-strings", &opt.fixed,
                        "interpret patterns as fixed strings"),
                OPT_GROUP(""),
-               OPT_BOOLEAN('n', NULL, &opt.linenum, "show line numbers"),
+               OPT_BOOLEAN('n', "line-number", &opt.linenum, "show line numbers"),
                OPT_NEGBIT('h', NULL, &opt.pathname, "don't show filenames", 1),
                OPT_BIT('H', NULL, &opt.pathname, "show filenames", 1),
                OPT_NEGBIT(0, "full-name", &opt.relative,
index c90acddcb2c32ce5170a220c9b1af96b44552a41..b96f46acf52d23f68c1ec164be8264396dea22db 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) Linus Torvalds, 2005
  * Copyright (C) Junio C Hamano, 2005
  */
-#include "cache.h"
+#include "builtin.h"
 #include "blob.h"
 #include "quote.h"
 #include "parse-options.h"
index c7e600db4745c80fddcb14986bc192d80630aa51..5a67c8181e5273ab0e79b8cb704dadc87cde1a37 100644 (file)
@@ -207,7 +207,7 @@ static void parse_pack_header(void)
 static NORETURN void bad_object(unsigned long offset, const char *format,
                       ...) __attribute__((format (printf, 2, 3)));
 
-static void bad_object(unsigned long offset, const char *format, ...)
+static NORETURN void bad_object(unsigned long offset, const char *format, ...)
 {
        va_list params;
        char buf[1024];
index 796e9e57460468748d1e2af975ac52a6470a379d..4a0f78dc7139ac529e60e7e1099834ff7efe1163 100644 (file)
@@ -1061,7 +1061,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        rev.commit_format = CMIT_FMT_EMAIL;
        rev.verbose_header = 1;
        rev.diff = 1;
-       rev.no_merges = 1;
+       rev.max_parents = 1;
        DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
        rev.subject_prefix = fmt_patch_subject_prefix;
        memset(&s_r_opt, 0, sizeof(s_r_opt));
index 2c4cf5e559b4166973f12bda567e1a6c5657a7e7..23388325879c5a52a4a8c25f254aafe23573e820 100644 (file)
@@ -1,6 +1,5 @@
-#include "cache.h"
+#include "builtin.h"
 #include "run-command.h"
-#include "exec_cmd.h"
 
 static const char *pgm;
 static int one_shot, quiet;
index c33091b3ed52bc8539ff82f039ec8c7718f3dcc2..3a64f5d0bdbcc8d7d21edb01f285cc8b41755228 100644 (file)
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "builtin.h"
 #include "commit.h"
 #include "tag.h"
 #include "merge-recursive.h"
index 9b25ddc9794efe489ee9ec9fd3203ffa997f03f7..19917426fba19cf60b838ff9b07d20b5e44259a5 100644 (file)
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "builtin.h"
 #include "tree-walk.h"
 #include "xdiff-interface.h"
 #include "blob.h"
index 1cb0f3f2a7cf580efc76957de24684630d596af9..324a267163d758b5dea51405265ae89042a657ad 100644 (file)
@@ -1,6 +1,5 @@
-#include "cache.h"
+#include "builtin.h"
 #include "tag.h"
-#include "exec_cmd.h"
 
 /*
  * A signature file has a very simple fixed format: four lines
@@ -35,12 +34,6 @@ static int verify_object(const unsigned char *sha1, const char *expected_type)
        return ret;
 }
 
-#ifdef NO_C99_FORMAT
-#define PD_FMT "%d"
-#else
-#define PD_FMT "%td"
-#endif
-
 static int verify_tag(char *buffer, unsigned long size)
 {
        int typelen;
@@ -70,15 +63,18 @@ static int verify_tag(char *buffer, unsigned long size)
        /* Verify tag-line */
        tag_line = strchr(type_line, '\n');
        if (!tag_line)
-               return error("char" PD_FMT ": could not find next \"\\n\"", type_line - buffer);
+               return error("char%"PRIuMAX": could not find next \"\\n\"",
+                               (uintmax_t) (type_line - buffer));
        tag_line++;
        if (memcmp(tag_line, "tag ", 4) || tag_line[4] == '\n')
-               return error("char" PD_FMT ": no \"tag \" found", tag_line - buffer);
+               return error("char%"PRIuMAX": no \"tag \" found",
+                               (uintmax_t) (tag_line - buffer));
 
        /* Get the actual type */
        typelen = tag_line - type_line - strlen("type \n");
        if (typelen >= sizeof(type))
-               return error("char" PD_FMT ": type too long", type_line+5 - buffer);
+               return error("char%"PRIuMAX": type too long",
+                               (uintmax_t) (type_line+5 - buffer));
 
        memcpy(type, type_line+5, typelen);
        type[typelen] = 0;
@@ -95,15 +91,16 @@ static int verify_tag(char *buffer, unsigned long size)
                        break;
                if (c > ' ')
                        continue;
-               return error("char" PD_FMT ": could not verify tag name", tag_line - buffer);
+               return error("char%"PRIuMAX": could not verify tag name",
+                               (uintmax_t) (tag_line - buffer));
        }
 
        /* Verify the tagger line */
        tagger_line = tag_line;
 
        if (memcmp(tagger_line, "tagger ", 7))
-               return error("char" PD_FMT ": could not find \"tagger \"",
-                       tagger_line - buffer);
+               return error("char%"PRIuMAX": could not find \"tagger \"",
+                       (uintmax_t) (tagger_line - buffer));
 
        /*
         * Check for correct form for name and email
@@ -115,44 +112,42 @@ static int verify_tag(char *buffer, unsigned long size)
        if (!(lb = strstr(tagger_line, " <")) || !(rb = strstr(lb+2, "> ")) ||
                strpbrk(tagger_line, "<>\n") != lb+1 ||
                strpbrk(lb+2, "><\n ") != rb)
-               return error("char" PD_FMT ": malformed tagger field",
-                       tagger_line - buffer);
+               return error("char%"PRIuMAX": malformed tagger field",
+                       (uintmax_t) (tagger_line - buffer));
 
        /* Check for author name, at least one character, space is acceptable */
        if (lb == tagger_line)
-               return error("char" PD_FMT ": missing tagger name",
-                       tagger_line - buffer);
+               return error("char%"PRIuMAX": missing tagger name",
+                       (uintmax_t) (tagger_line - buffer));
 
        /* timestamp, 1 or more digits followed by space */
        tagger_line = rb + 2;
        if (!(len = strspn(tagger_line, "0123456789")))
-               return error("char" PD_FMT ": missing tag timestamp",
-                       tagger_line - buffer);
+               return error("char%"PRIuMAX": missing tag timestamp",
+                       (uintmax_t) (tagger_line - buffer));
        tagger_line += len;
        if (*tagger_line != ' ')
-               return error("char" PD_FMT ": malformed tag timestamp",
-                       tagger_line - buffer);
+               return error("char%"PRIuMAX": malformed tag timestamp",
+                       (uintmax_t) (tagger_line - buffer));
        tagger_line++;
 
        /* timezone, 5 digits [+-]hhmm, max. 1400 */
        if (!((tagger_line[0] == '+' || tagger_line[0] == '-') &&
              strspn(tagger_line+1, "0123456789") == 4 &&
              tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400))
-               return error("char" PD_FMT ": malformed tag timezone",
-                       tagger_line - buffer);
+               return error("char%"PRIuMAX": malformed tag timezone",
+                       (uintmax_t) (tagger_line - buffer));
        tagger_line += 6;
 
        /* Verify the blank line separating the header from the body */
        if (*tagger_line != '\n')
-               return error("char" PD_FMT ": trailing garbage in tag header",
-                       tagger_line - buffer);
+               return error("char%"PRIuMAX": trailing garbage in tag header",
+                       (uintmax_t) (tagger_line - buffer));
 
        /* The actual stuff afterwards we don't care about.. */
        return 0;
 }
 
-#undef PD_FMT
-
 int cmd_mktag(int argc, const char **argv, const char *prefix)
 {
        struct strbuf buf = STRBUF_INIT;
index 0aab150c52c839512b82b5efc6e978b7a80653e3..a0f310b72956dcb00d2a0899d39ddfb9f7811fa4 100644 (file)
@@ -423,7 +423,7 @@ void finish_copy_notes_for_rewrite(struct notes_rewrite_cfg *c)
        free(c);
 }
 
-int notes_copy_from_stdin(int force, const char *rewrite_cmd)
+static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
 {
        struct strbuf buf = STRBUF_INIT;
        struct notes_rewrite_cfg *c = NULL;
@@ -819,7 +819,7 @@ static int merge_commit(struct notes_merge_options *o)
        t = xcalloc(1, sizeof(struct notes_tree));
        init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0);
 
-       o->local_ref = resolve_ref("NOTES_MERGE_REF", sha1, 0, 0);
+       o->local_ref = resolve_ref("NOTES_MERGE_REF", sha1, 0, NULL);
        if (!o->local_ref)
                die("Failed to resolve NOTES_MERGE_REF");
 
index 41e1615a28d772d1677c172ff2f570f31de4026f..f5c6afc5dd46c8f856d0f125287724bbfdc65db7 100644 (file)
@@ -6,8 +6,7 @@
 *
 */
 
-#include "cache.h"
-#include "exec_cmd.h"
+#include "builtin.h"
 
 #define BLKSIZE 512
 
index 091860b2e370561f0811399b0d307e732e9eaac3..39a9d89fbdf322a8ef42a62e41ac36af934ff638 100644 (file)
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "builtin.h"
 #include "parse-options.h"
 #include "pack-refs.h"
 
index 49a0472a9bd28274c4be1352996e700a1db4b94a..f821eb3f0b864c26d5e822cc7c5b0747340abee5 100644 (file)
@@ -1,5 +1,4 @@
-#include "cache.h"
-#include "exec_cmd.h"
+#include "builtin.h"
 
 static void flush_current_id(int patchlen, unsigned char *id, git_SHA_CTX *c)
 {
@@ -57,7 +56,7 @@ static int scan_hunk_header(const char *p, int *p_before, int *p_after)
        return 1;
 }
 
-int get_one_patchid(unsigned char *next_sha1, git_SHA_CTX *ctx)
+static int get_one_patchid(unsigned char *next_sha1, git_SHA_CTX *ctx)
 {
        static char line[1000];
        int patchlen = 0, found_next = 0;
index d8e2c5fca7902d6d9a9e8300e129d58ad7a98192..27050e7c1627ed2899963fb3fdb81a7ba95d06df 100644 (file)
@@ -731,43 +731,14 @@ static int delete_only(struct command *commands)
        return 1;
 }
 
-static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
+static void add_one_alternate_ref(const struct ref *ref, void *unused)
 {
-       char *other;
-       size_t len;
-       struct remote *remote;
-       struct transport *transport;
-       const struct ref *extra;
-
-       e->name[-1] = '\0';
-       other = xstrdup(real_path(e->base));
-       e->name[-1] = '/';
-       len = strlen(other);
-
-       while (other[len-1] == '/')
-               other[--len] = '\0';
-       if (len < 8 || memcmp(other + len - 8, "/objects", 8))
-               return 0;
-       /* Is this a git repository with refs? */
-       memcpy(other + len - 8, "/refs", 6);
-       if (!is_directory(other))
-               return 0;
-       other[len - 8] = '\0';
-       remote = remote_get(other);
-       transport = transport_get(remote, other);
-       for (extra = transport_get_remote_refs(transport);
-            extra;
-            extra = extra->next) {
-               add_extra_ref(".have", extra->old_sha1, 0);
-       }
-       transport_disconnect(transport);
-       free(other);
-       return 0;
+       add_extra_ref(".have", ref->old_sha1, 0);
 }
 
 static void add_alternate_refs(void)
 {
-       foreach_alt_odb(add_refs_from_alternate, NULL);
+       foreach_alt_odb(refs_from_alternate_cb, add_one_alternate_ref);
 }
 
 int cmd_receive_pack(int argc, const char **argv, const char *prefix)
index ea71977c8360e1a7899bbd035cf26f93d889800b..692c834d9dd48615e42b67e3924c64e3397ad903 100644 (file)
@@ -1,4 +1,4 @@
-#include "git-compat-util.h"
+#include "builtin.h"
 #include "transport.h"
 #include "run-command.h"
 
@@ -30,16 +30,12 @@ static char *strip_escapes(const char *str, const char *service,
        size_t rpos = 0;
        int escape = 0;
        char special = 0;
-       size_t pslen = 0;
-       size_t pSlen = 0;
        size_t psoff = 0;
        struct strbuf ret = STRBUF_INIT;
 
        /* Calculate prefix length for \s and lengths for \s and \S */
        if (!strncmp(service, "git-", 4))
                psoff = 4;
-       pSlen = strlen(service);
-       pslen = pSlen - psoff;
 
        /* Pass the service to command. */
        setenv("GIT_EXT_SERVICE", service, 1);
index 1f2467bdb756435764f9156ffefeeb510dc872d8..08d7121b6d118042a45086d2902769d282c062f8 100644 (file)
@@ -1,4 +1,4 @@
-#include "git-compat-util.h"
+#include "builtin.h"
 #include "transport.h"
 
 /*
index cb26080956077f8c9ae02c91ffdc341293a4f9f1..b71ecd228f5c27bc436602469d3090eb860a1222 100644 (file)
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "builtin.h"
 #include "parse-options.h"
 #include "transport.h"
 #include "remote.h"
index 5de2bceeec8c1d243ed6da70464d0c4dd60d7352..eb5f98c16320cd4eded3c842ec1d019e75c5b9c3 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 2005, 2006 Linus Torvalds and Junio C Hamano
  */
-#include "cache.h"
+#include "builtin.h"
 #include "tag.h"
 #include "object.h"
 #include "commit.h"
index ba27d39f977f2807cddb6e18364837b9fd50e970..9bfb94201f298f5902c6da13b12f4ca539bb86ed 100644 (file)
@@ -16,6 +16,10 @@ static const char rev_list_usage[] =
 "    --min-age=<epoch>\n"
 "    --sparse\n"
 "    --no-merges\n"
+"    --min-parents=<n>\n"
+"    --no-min-parents\n"
+"    --max-parents=<n>\n"
+"    --no-max-parents\n"
 "    --remove-empty\n"
 "    --all\n"
 "    --branches\n"
@@ -64,18 +68,8 @@ static void show_commit(struct commit *commit, void *data)
        if (info->header_prefix)
                fputs(info->header_prefix, stdout);
 
-       if (!revs->graph) {
-               if (commit->object.flags & BOUNDARY)
-                       putchar('-');
-               else if (commit->object.flags & UNINTERESTING)
-                       putchar('^');
-               else if (revs->left_right) {
-                       if (commit->object.flags & SYMMETRIC_LEFT)
-                               putchar('<');
-                       else
-                               putchar('>');
-               }
-       }
+       if (!revs->graph)
+               fputs(get_revision_mark(revs, commit), stdout);
        if (revs->abbrev_commit && revs->abbrev)
                fputs(find_unique_abbrev(commit->object.sha1, revs->abbrev),
                      stdout);
index a5a1c86e92720e8beefd8275acfc5df2dbdce175..adb1cae4f27ad3993aa2418f7b0fd355d19cdab9 100644 (file)
@@ -48,6 +48,10 @@ static int is_rev_argument(const char *arg)
                "--max-count=",
                "--min-age=",
                "--no-merges",
+               "--min-parents=",
+               "--no-min-parents",
+               "--max-parents=",
+               "--no-max-parents",
                "--objects",
                "--objects-edge",
                "--parents",
index 2cd1c40b70890732905ad9433e452aa9a9548533..8b0911c0d2ac5a60f8a3c7a43e7960617ded9d7a 100644 (file)
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include "builtin.h"
 #include "commit.h"
 #include "refs.h"
 #include "pkt-line.h"
index 608590ada8105a2e6a8cb9d6176696b511b410f6..19200291a2632554223b1a675d5324b4682248ab 100644 (file)
@@ -1,6 +1,4 @@
-#include "cache.h"
-#include "blob.h"
-#include "exec_cmd.h"
+#include "builtin.h"
 
 static char *create_temp_file(unsigned char *sha1)
 {
index 0744bb83185289e26bd32b3b2ecaec717d8c75d7..99d068a5327255f36c8e415ecb8d0cf98cbbe180 100644 (file)
@@ -3,8 +3,7 @@
  *
  * Copyright (C) Eric Biederman, 2005
  */
-#include "cache.h"
-#include "exec_cmd.h"
+#include "builtin.h"
 
 static const char var_usage[] = "git var (-l | <variable>)";
 
diff --git a/cache.h b/cache.h
index be6ce7237d4c2d8a6d708629985c3c058c236563..9f06d215790ef98c2138ab26c1a9b4ddafd33c55 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -543,6 +543,7 @@ extern NORETURN void unable_to_lock_index_die(const char *path, int err);
 extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
 extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
 extern int commit_lock_file(struct lock_file *);
+extern void update_index_if_able(struct index_state *, struct lock_file *);
 
 extern int hold_locked_index(struct lock_file *, int);
 extern int commit_locked_index(struct lock_file *);
@@ -556,6 +557,7 @@ extern int trust_executable_bit;
 extern int trust_ctime;
 extern int quote_path_fully;
 extern int has_symlinks;
+extern int minimum_abbrev, default_abbrev;
 extern int ignore_case;
 extern int assume_unchanged;
 extern int prefer_symlink_refs;
@@ -725,6 +727,7 @@ int set_shared_perm(const char *path, int mode);
 #define adjust_shared_perm(path) set_shared_perm((path), 0)
 int safe_create_leading_directories(char *path);
 int safe_create_leading_directories_const(const char *path);
+int mkdir_in_gitdir(const char *path);
 extern char *expand_user_path(const char *path);
 char *enter_repo(char *path, int strict);
 static inline int is_absolute_path(const char *path)
@@ -775,8 +778,8 @@ static inline unsigned int hexval(unsigned char c)
 }
 
 /* Convert to/from hex/sha1 representation */
-#define MINIMUM_ABBREV 4
-#define DEFAULT_ABBREV 7
+#define MINIMUM_ABBREV minimum_abbrev
+#define DEFAULT_ABBREV default_abbrev
 
 struct object_context {
        unsigned char tree[20];
@@ -1022,7 +1025,6 @@ extern const char *git_etc_gitconfig(void);
 extern int check_repository_format_version(const char *var, const char *value, void *cb);
 extern int git_env_bool(const char *, int);
 extern int git_config_system(void);
-extern int git_config_global(void);
 extern int config_error_nonbool(const char *);
 extern const char *get_log_output_encoding(void);
 extern const char *get_commit_output_encoding(void);
index fa740a6a60a49512b613f70add97d445f622afd2..0abcada9381a3e6638f94bcf41bf9ee7b96f4de8 100644 (file)
--- a/config.c
+++ b/config.c
@@ -523,6 +523,14 @@ static int git_default_core_config(const char *var, const char *value)
                return 0;
        }
 
+       if (!strcmp(var, "core.abbrev")) {
+               int abbrev = git_config_int(var, value);
+               if (abbrev < minimum_abbrev || abbrev > 40)
+                       return -1;
+               default_abbrev = abbrev;
+               return 0;
+       }
+
        if (!strcmp(var, "core.loosecompression")) {
                int level = git_config_int(var, value);
                if (level == -1)
@@ -825,11 +833,6 @@ int git_config_system(void)
        return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0);
 }
 
-int git_config_global(void)
-{
-       return !git_env_bool("GIT_CONFIG_NOGLOBAL", 0);
-}
-
 int git_config_from_parameters(config_fn_t fn, void *data)
 {
        static int loaded_environment;
@@ -861,7 +864,7 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
        }
 
        home = getenv("HOME");
-       if (git_config_global() && home) {
+       if (home) {
                char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
                if (!access(user_config, R_OK)) {
                        ret += git_config_from_file(fn, user_config, data);
index 961497305777fcbd67001fdae1335fcfe2910e88..e378534cbd57add4a6c75b8eb45353e8a9322914 100644 (file)
@@ -43,7 +43,6 @@ NO_D_INO_IN_DIRENT=@NO_D_INO_IN_DIRENT@
 NO_D_TYPE_IN_DIRENT=@NO_D_TYPE_IN_DIRENT@
 NO_SOCKADDR_STORAGE=@NO_SOCKADDR_STORAGE@
 NO_IPV6=@NO_IPV6@
-NO_C99_FORMAT=@NO_C99_FORMAT@
 NO_HSTRERROR=@NO_HSTRERROR@
 NO_STRCASESTR=@NO_STRCASESTR@
 NO_STRTOK_R=@NO_STRTOK_R@
index 20039c546f1cc91575771acbe6f52de6778bea89..fafd81557c2d3dd17cb1c15c545f3602a3a0c6bf 100644 (file)
@@ -686,30 +686,6 @@ AC_CHECK_TYPE([struct addrinfo],[
 ])
 AC_SUBST(NO_IPV6)
 #
-# Define NO_C99_FORMAT if your formatted IO functions (printf/scanf et.al.)
-# do not support the 'size specifiers' introduced by C99, namely ll, hh,
-# j, z, t. (representing long long int, char, intmax_t, size_t, ptrdiff_t).
-# some C compilers supported these specifiers prior to C99 as an extension.
-AC_CACHE_CHECK([whether formatted IO functions support C99 size specifiers],
- [ac_cv_c_c99_format],
-[# Actually git uses only %z (%zu) in alloc.c, and %t (%td) in mktag.c
-AC_RUN_IFELSE(
-       [AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
-               [[char buf[64];
-               if (sprintf(buf, "%lld%hhd%jd%zd%td", (long long int)1, (char)2, (intmax_t)3, (size_t)4, (ptrdiff_t)5) != 5)
-                 return 1;
-               else if (strcmp(buf, "12345"))
-                 return 2;]])],
-       [ac_cv_c_c99_format=yes],
-       [ac_cv_c_c99_format=no])
-])
-if test $ac_cv_c_c99_format = no; then
-       NO_C99_FORMAT=YesPlease
-else
-       NO_C99_FORMAT=
-fi
-AC_SUBST(NO_C99_FORMAT)
-#
 # Define NO_REGEX if you have no or inferior regex support in your C library.
 AC_CACHE_CHECK([whether the platform regex can handle null bytes],
  [ac_cv_c_excellent_regex], [
@@ -919,7 +895,9 @@ AC_LANG_PROGRAM([[
 #include <pthread.h>
 ]], [[
        pthread_mutex_t test_mutex;
+       pthread_key_t test_key;
        int retcode = 0;
+       retcode |= pthread_key_create(&test_key, (void *)0);
        retcode |= pthread_mutex_init(&test_mutex,(void *)0);
        retcode |= pthread_mutex_lock(&test_mutex);
        retcode |= pthread_mutex_unlock(&test_mutex);
index ccdc172a06bcc55ff5c5c3c1854bb34f84910f90..840ae38760a5de84b369b208a52cc579ce478378 100755 (executable)
@@ -664,11 +664,14 @@ __git_compute_merge_strategies ()
        : ${__git_merge_strategies:=$(__git_list_merge_strategies)}
 }
 
-__git_complete_file ()
+__git_complete_revlist_file ()
 {
        local pfx ls ref cur
        _get_comp_words_by_ref -n =: cur
        case "$cur" in
+       *..?*:*)
+               return
+               ;;
        ?*:*)
                ref="${cur%%:*}"
                cur="${cur#*:}"
@@ -682,7 +685,7 @@ __git_complete_file ()
                *)
                        ls="$ref"
                        ;;
-           esac
+               esac
 
                case "$COMP_WORDBREAKS" in
                *:*) : great ;;
@@ -707,17 +710,6 @@ __git_complete_file ()
                                       s/^.*    //')" \
                        -- "$cur"))
                ;;
-       *)
-               __gitcomp "$(__git_refs)"
-               ;;
-       esac
-}
-
-__git_complete_revlist ()
-{
-       local pfx cur
-       _get_comp_words_by_ref -n =: cur
-       case "$cur" in
        *...*)
                pfx="${cur%...*}..."
                cur="${cur#*...}"
@@ -734,6 +726,17 @@ __git_complete_revlist ()
        esac
 }
 
+
+__git_complete_file ()
+{
+       __git_complete_revlist_file
+}
+
+__git_complete_revlist ()
+{
+       __git_complete_revlist_file
+}
+
 __git_complete_remote_or_refspec ()
 {
        local cur words cword
@@ -1356,7 +1359,7 @@ _git_diff ()
                return
                ;;
        esac
-       __git_complete_file
+       __git_complete_revlist_file
 }
 
 __git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff
@@ -1508,7 +1511,7 @@ _git_help ()
                ;;
        esac
        __git_compute_all_commands
-       __gitcomp "$__git_all_commands
+       __gitcomp "$__git_all_commands $(__git_aliases)
                attributes cli core-tutorial cvs-migration
                diffcore gitk glossary hooks ignore modules
                repository-layout tutorial tutorial-2
@@ -1574,6 +1577,8 @@ __git_log_common_options="
        --max-count=
        --max-age= --since= --after=
        --min-age= --until= --before=
+       --min-parents= --max-parents=
+       --no-min-parents --no-max-parents
 "
 # Options that go well for log and gitk (not shortlog)
 __git_log_gitk_options="
index 7cb479c5e1b21e4b0de936ced57981e0bf804b0c..388151503423aeff0a99ee943f7eebf0c8fec476 100755 (executable)
@@ -333,9 +333,13 @@ def gitBranchExists(branch):
     return proc.wait() == 0;
 
 _gitConfig = {}
-def gitConfig(key):
+def gitConfig(key, args = None): # set args to "--bool", for instance
     if not _gitConfig.has_key(key):
-        _gitConfig[key] = read_pipe("git config %s" % key, ignore_error=True).strip()
+        argsFilter = ""
+        if args != None:
+            argsFilter = "%s " % args
+        cmd = "git config %s%s" % (argsFilter, key)
+        _gitConfig[key] = read_pipe(cmd, ignore_error=True).strip()
     return _gitConfig[key]
 
 def p4BranchesInGit(branchesAreInRemotes = True):
@@ -452,6 +456,19 @@ def p4ChangesForPaths(depotPaths, changeRange):
     changelist.sort()
     return changelist
 
+def p4PathStartsWith(path, prefix):
+    # This method tries to remedy a potential mixed-case issue:
+    #
+    # If UserA adds  //depot/DirA/file1
+    # and UserB adds //depot/dira/file2
+    #
+    # we may or may not have a problem. If you have core.ignorecase=true,
+    # we treat DirA and dira as the same directory
+    ignorecase = gitConfig("core.ignorecase", "--bool") == "true"
+    if ignorecase:
+        return path.lower().startswith(prefix.lower())
+    return path.startswith(prefix)
+
 class Command:
     def __init__(self):
         self.usage = "usage: %prog [options]"
@@ -599,7 +616,7 @@ class P4Submit(Command):
                     lastTab = path.rfind("\t")
                     if lastTab != -1:
                         path = path[:lastTab]
-                        if not path.startswith(self.depotPath):
+                        if not p4PathStartsWith(path, self.depotPath):
                             continue
                 else:
                     inFilesSection = False
@@ -937,11 +954,11 @@ class P4Sync(Command):
             path =  commit["depotFile%s" % fnum]
 
             if [p for p in self.cloneExclude
-                if path.startswith (p)]:
+                if p4PathStartsWith(path, p)]:
                 found = False
             else:
                 found = [p for p in self.depotPaths
-                         if path.startswith (p)]
+                         if p4PathStartsWith(path, p)]
             if not found:
                 fnum = fnum + 1
                 continue
@@ -976,7 +993,7 @@ class P4Sync(Command):
             prefixes = [re.sub("^(//[^/]+/).*", r'\1', prefixes[0])]
 
         for p in prefixes:
-            if path.startswith(p):
+            if p4PathStartsWith(path, p):
                 path = path[len(p):]
 
         return path
@@ -987,7 +1004,7 @@ class P4Sync(Command):
         while commit.has_key("depotFile%s" % fnum):
             path =  commit["depotFile%s" % fnum]
             found = [p for p in self.depotPaths
-                     if path.startswith (p)]
+                     if p4PathStartsWith(path, p)]
             if not found:
                 fnum = fnum + 1
                 continue
@@ -1140,10 +1157,10 @@ class P4Sync(Command):
         # create a commit.
         new_files = []
         for f in files:
-            if [p for p in branchPrefixes if f['path'].startswith(p)]:
+            if [p for p in branchPrefixes if p4PathStartsWith(f['path'], p)]:
                 new_files.append (f)
             else:
-                sys.stderr.write("Ignoring file outside of prefix: %s\n" % path)
+                sys.stderr.write("Ignoring file outside of prefix: %s\n" % f['path'])
 
         self.gitStream.write("commit %s\n" % branch)
 #        gitStream.write("mark :%s\n" % details["change"])
@@ -1304,7 +1321,7 @@ class P4Sync(Command):
                 source = paths[0]
                 destination = paths[1]
                 ## HACK
-                if source.startswith(self.depotPaths[0]) and destination.startswith(self.depotPaths[0]):
+                if p4PathStartsWith(source, self.depotPaths[0]) and p4PathStartsWith(destination, self.depotPaths[0]):
                     source = source[len(self.depotPaths[0]):-4]
                     destination = destination[len(self.depotPaths[0]):-4]
 
@@ -1763,7 +1780,9 @@ class P4Sync(Command):
 
                 changes.sort()
             else:
-                if not isinstance(self, P4Clone) and not self.p4BranchesInGit:
+                # catch "git-p4 sync" with no new branches, in a repo that
+                # does not have any existing git-p4 branches
+                if len(args) == 0 and not self.p4BranchesInGit:
                     die("No remote p4 branches.  Perhaps you never did \"git p4 clone\" in here.");
                 if self.verbose:
                     print "Getting p4 changes for %s...%s" % (', '.join(self.depotPaths),
index cc518f3c890158d29e751e008436e0c3790746ee..5eb4a5164397e3a34be10690025a9cd472261db9 100755 (executable)
@@ -1,8 +1,8 @@
-#!/bin/bash
+#!/bin/sh
 # Copyright 2008 Lukas Sandström <luksan@gmail.com>
 #
 # AppendPatch - A script to be used together with ExternalEditor
-# for Mozilla Thunderbird to properly include pathes inline i e-mails.
+# for Mozilla Thunderbird to properly include patches inline in e-mails.
 
 # ExternalEditor can be downloaded at http://globs.org/articles.php?lng=en&pg=2
 
index 347fd0c52b4cd797f5dafffb6885324f7c7f0274..4c8346d5a1fe1325de2dd335a4e61a2dad994211 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -660,7 +660,7 @@ static void check_dead_children(void)
 static char **cld_argv;
 static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
 {
-       struct child_process cld = { 0 };
+       struct child_process cld = { NULL };
        char addrbuf[300] = "REMOTE_ADDR=", portbuf[300];
        char *env[] = { addrbuf, portbuf, NULL };
 
index 1e22992cb10420b9dd6def16f80efc5f196ffbbb..2870de400ed533d83c77269ee1654af212c6510c 100644 (file)
@@ -103,7 +103,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                unsigned dirty_submodule = 0;
 
                if (DIFF_OPT_TST(&revs->diffopt, QUICK) &&
-                       DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
+                   !revs->diffopt.filter &&
+                   DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
                        break;
 
                if (!ce_path_match(ce, &revs->prune_data))
diff --git a/diff.c b/diff.c
index 42a107c58ae6f81ffe514e573afdaec881c4532e..9fa841010cc21bebc464926b15232b2aace0f5ba 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -628,7 +628,7 @@ struct diff_words_style {
        const char *newline;
 };
 
-struct diff_words_style diff_words_styles[] = {
+static struct diff_words_style diff_words_styles[] = {
        { DIFF_WORDS_PORCELAIN, {"+", "\n"}, {"-", "\n"}, {" ", "\n"}, "~\n" },
        { DIFF_WORDS_PLAIN, {"{+", "+}"}, {"[-", "-]"}, {"", ""}, "\n" },
        { DIFF_WORDS_COLOR, {"", ""}, {"", ""}, {"", ""}, "\n" }
@@ -1242,7 +1242,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
        uintmax_t max_change = 0, max_len = 0;
        int total_files = data->nr;
        int width, name_width;
-       const char *reset, *set, *add_c, *del_c;
+       const char *reset, *add_c, *del_c;
        const char *line_prefix = "";
        struct strbuf *msg = NULL;
 
@@ -1269,7 +1269,6 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 
        /* Find the longest filename and max number of changes */
        reset = diff_get_color_opt(options, DIFF_RESET);
-       set   = diff_get_color_opt(options, DIFF_PLAIN);
        add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
        del_c = diff_get_color_opt(options, DIFF_FILE_OLD);
 
index cc670b1562504f9cfe79247d98e50c62c50eaea5..f4549d3f7b0367b31b0fa0042fb12ff183beb081 100644 (file)
@@ -15,6 +15,7 @@ int user_ident_explicitly_given;
 int trust_executable_bit = 1;
 int trust_ctime = 1;
 int has_symlinks = 1;
+int minimum_abbrev = 4, default_abbrev = 7;
 int ignore_case;
 int assume_unchanged;
 int prefer_symlink_refs;
index d9f9a3f524671877d01d0897141a753f8b9c766a..65d65bf8f91b7a584c7dc77f84a5dec263c3d11c 100644 (file)
@@ -2939,7 +2939,7 @@ static void parse_ls(struct branch *b)
 {
        const char *p;
        struct tree_entry *root = NULL;
-       struct tree_entry leaf = {0};
+       struct tree_entry leaf = {NULL};
 
        /* ls SP (<treeish> SP)? <path> */
        p = command_buf.buf + strlen("ls ");
index c21e33c8d133af0e9e0ae3edaffd0a5593ff4ac3..415a8d04ccc4f313eb111a3bbfbf2af2382beebd 100755 (executable)
@@ -288,10 +288,12 @@ bisect_visualize() {
 
        if test $# = 0
        then
-               case "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" in
-               '')     set git log ;;
-               set*)   set gitk ;;
-               esac
+               if test -n "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" &&
+                  type gitk >/dev/null 2>&1; then
+                       set gitk
+               else
+                       set git log
+               fi
        else
                case "$1" in
                git*|tig) ;;
index d3acf0d2134b40b8ffb3d0e8c3229f71fa6db663..fd6a43d0a29986d38094df2818b66beba0f49234 100755 (executable)
@@ -93,6 +93,25 @@ if {![catch {set _verbose $env(GITGUI_VERBOSE)}]} {
 
 package require msgcat
 
+# Check for Windows 7 MUI language pack (missed by msgcat < 1.4.4)
+if {[tk windowingsystem] eq "win32"
+       && [package vcompare [package provide msgcat] 1.4.4] < 0
+} then {
+       proc _mc_update_locale {} {
+               set key {HKEY_CURRENT_USER\Control Panel\Desktop}
+               if {![catch {
+                       package require registry
+                       set uilocale [registry get $key "PreferredUILanguages"]
+                       msgcat::ConvertLocale [string map {- _} [lindex $uilocale 0]]
+               } uilocale]} {
+                       if {[string length $uilocale] > 0} {
+                               msgcat::mclocale $uilocale
+                       }
+               }
+       }
+       _mc_update_locale
+}
+
 proc _mc_trim {fmt} {
        set cmk [string first @@ $fmt]
        if {$cmk > 0} {
@@ -139,6 +158,10 @@ if {$_trace >= 0} {
        set _trace 0
 }
 
+# variable for the last merged branch (useful for a default when deleting
+# branches).
+set _last_merged_branch {}
+
 proc shellpath {} {
        global _shellpath env
        if {[string match @@* $_shellpath]} {
@@ -1448,13 +1471,17 @@ proc rescan_stage2 {fd after} {
                close $fd
        }
 
-       set ls_others [list --exclude-per-directory=.gitignore]
-       if {[have_info_exclude]} {
-               lappend ls_others "--exclude-from=[gitdir info exclude]"
-       }
-       set user_exclude [get_config core.excludesfile]
-       if {$user_exclude ne {} && [file readable $user_exclude]} {
-               lappend ls_others "--exclude-from=$user_exclude"
+       if {[package vsatisfies $::_git_version 1.6.3]} {
+               set ls_others [list --exclude-standard]
+       } else {
+               set ls_others [list --exclude-per-directory=.gitignore]
+               if {[have_info_exclude]} {
+                       lappend ls_others "--exclude-from=[gitdir info exclude]"
+               }
+               set user_exclude [get_config core.excludesfile]
+               if {$user_exclude ne {} && [file readable $user_exclude]} {
+                       lappend ls_others "--exclude-from=[file normalize $user_exclude]"
+               }
        }
 
        set buf_rdi {}
@@ -1958,8 +1985,8 @@ static unsigned char file_merge_bits[] = {
 } -maskdata $filemask
 
 image create bitmap file_statechange -background white -foreground green -data {
-#define file_merge_width 14
-#define file_merge_height 15
+#define file_statechange_width 14
+#define file_statechange_height 15
 static unsigned char file_statechange_bits[] = {
    0xfe, 0x01, 0x02, 0x03, 0x02, 0x05, 0x02, 0x09, 0x02, 0x1f, 0x62, 0x10,
    0x62, 0x10, 0xba, 0x11, 0xba, 0x11, 0x62, 0x10, 0x62, 0x10, 0x02, 0x10,
@@ -1993,7 +2020,11 @@ foreach i {
                {MD {mc "Staged for commit, missing"}}
 
                {_T {mc "File type changed, not staged"}}
+               {MT {mc "File type changed, old type staged for commit"}}
+               {AT {mc "File type changed, old type staged for commit"}}
                {T_ {mc "File type changed, staged"}}
+               {TM {mc "File type change staged, modification not staged"}}
+               {TD {mc "File type change staged, file missing"}}
 
                {_O {mc "Untracked, not staged"}}
                {A_ {mc "Staged for commit"}}
@@ -3331,6 +3362,8 @@ foreach {n c} {0 black 1 red4 2 green4 3 yellow4 4 blue4 5 magenta4 6 cyan4 7 gr
 }
 $ui_diff tag configure clr1 -font font_diffbold
 
+$ui_diff tag conf d_info -foreground blue -font font_diffbold
+
 $ui_diff tag conf d_cr -elide true
 $ui_diff tag conf d_@ -font font_diffbold
 $ui_diff tag conf d_+ -foreground {#00a000}
@@ -3351,13 +3384,13 @@ $ui_diff tag conf d_s- \
        -foreground red \
        -background ivory1
 
-$ui_diff tag conf d<<<<<<< \
+$ui_diff tag conf d< \
        -foreground orange \
        -font font_diffbold
-$ui_diff tag conf d======= \
+$ui_diff tag conf d= \
        -foreground orange \
        -font font_diffbold
-$ui_diff tag conf d>>>>>>> \
+$ui_diff tag conf d> \
        -foreground orange \
        -font font_diffbold
 
@@ -3533,8 +3566,8 @@ proc popup_diff_menu {ctxm ctxmmg ctxmsm x y X Y} {
                        || $current_diff_path eq {}
                        || {__} eq $state
                        || {_O} eq $state
-                       || {_T} eq $state
-                       || {T_} eq $state
+                       || [string match {?T} $state]
+                       || [string match {T?} $state]
                        || [has_textconv $current_diff_path]} {
                        set s disabled
                } else {
index c2415729e036d87bc892b53901bd45d7e71b5ec2..a8c622351167be937b9f02df149a1a6ec2a16e98 100644 (file)
@@ -121,7 +121,7 @@ method _parent {} {
                if {$browser_stack eq {}} {
                        regsub {:.*$} $browser_path {:} browser_path
                } else {
-                       regsub {/[^/]+$} $browser_path {} browser_path
+                       regsub {/[^/]+/$} $browser_path {/} browser_path
                }
                set browser_status [mc "Loading %s..." $browser_path]
                _ls $this [lindex $parent 0] [lindex $parent 1]
index fae119286d3d4511d1b362fb05a8fab775e80a40..657f7d5dc19b13f36a31b833f04407b8ca0b2901 100644 (file)
@@ -214,14 +214,6 @@ constructor pick {} {
        }
 }
 
-proc _home {} {
-       if {[catch {set h $::env(HOME)}]
-               || ![file isdirectory $h]} {
-               set h .
-       }
-       return $h
-}
-
 method _center {} {
        set nx [winfo reqwidth $top]
        set ny [winfo reqheight $top]
@@ -420,7 +412,7 @@ method _new_local_path {} {
        if {$local_path ne {}} {
                set p [file dirname $local_path]
        } else {
-               set p [_home]
+               set p [pwd]
        }
 
        set p [tk_chooseDirectory \
@@ -541,7 +533,7 @@ method _open_origin {} {
        if {$origin_url ne {} && [file isdirectory $origin_url]} {
                set p $origin_url
        } else {
-               set p [_home]
+               set p [pwd]
        }
 
        set p [tk_chooseDirectory \
@@ -1042,7 +1034,7 @@ method _open_local_path {} {
        if {$local_path ne {}} {
                set p $local_path
        } else {
-               set p [_home]
+               set p [pwd]
        }
 
        set p [tk_chooseDirectory \
index 7f459cd5647f690a5e48ed7c29fc0d75eef89d0c..5ce46877bfb24701187f5ff5e94ce4aaf8b666b2 100644 (file)
@@ -161,11 +161,12 @@ The rescan will be automatically started now.
        #
        set files_ready 0
        foreach path [array names file_states] {
-               switch -glob -- [lindex $file_states($path) 0] {
+               set s $file_states($path)
+               switch -glob -- [lindex $s 0] {
                _? {continue}
                A? -
                D? -
-               T_ -
+               T? -
                M? {set files_ready 1}
                _U -
                U? {
@@ -452,7 +453,11 @@ A rescan will be automatically started now.
                }
                AM -
                AD -
+               AT -
+               TM -
+               TD -
                MM -
+               MT -
                MD {
                        set file_states($path) [list \
                                _[string index $m 1] \
index dcf0711be0119a8f5ec42b48d97980330f7113b3..cf8a95ec346a9a8afa60a3812d59a8caa4bb4c3f 100644 (file)
@@ -122,22 +122,22 @@ proc show_unmerged_diff {cont_info} {
        if {$merge_stages(2) eq {}} {
                set is_conflict_diff 1
                lappend current_diff_queue \
-                       [list [mc "LOCAL: deleted\nREMOTE:\n"] d======= \
+                       [list [mc "LOCAL: deleted\nREMOTE:\n"] d= \
                            [list ":1:$current_diff_path" ":3:$current_diff_path"]]
        } elseif {$merge_stages(3) eq {}} {
                set is_conflict_diff 1
                lappend current_diff_queue \
-                       [list [mc "REMOTE: deleted\nLOCAL:\n"] d======= \
+                       [list [mc "REMOTE: deleted\nLOCAL:\n"] d= \
                            [list ":1:$current_diff_path" ":2:$current_diff_path"]]
        } elseif {[lindex $merge_stages(1) 0] eq {120000}
                || [lindex $merge_stages(2) 0] eq {120000}
                || [lindex $merge_stages(3) 0] eq {120000}} {
                set is_conflict_diff 1
                lappend current_diff_queue \
-                       [list [mc "LOCAL:\n"] d======= \
+                       [list [mc "LOCAL:\n"] d= \
                            [list ":1:$current_diff_path" ":2:$current_diff_path"]]
                lappend current_diff_queue \
-                       [list [mc "REMOTE:\n"] d======= \
+                       [list [mc "REMOTE:\n"] d= \
                            [list ":1:$current_diff_path" ":3:$current_diff_path"]]
        } else {
                start_show_diff $cont_info
@@ -208,32 +208,32 @@ proc show_other_diff {path w m cont_info} {
                        $ui_diff insert end [append \
                                "* " \
                                [mc "Git Repository (subproject)"] \
-                               "\n"] d_@
+                               "\n"] d_info
                } elseif {![catch {set type [exec file $path]}]} {
                        set n [string length $path]
                        if {[string equal -length $n $path $type]} {
                                set type [string range $type $n end]
                                regsub {^:?\s*} $type {} type
                        }
-                       $ui_diff insert end "* $type\n" d_@
+                       $ui_diff insert end "* $type\n" d_info
                }
                if {[string first "\0" $content] != -1} {
                        $ui_diff insert end \
                                [mc "* Binary file (not showing content)."] \
-                               d_@
+                               d_info
                } else {
                        if {$sz > $max_sz} {
                                $ui_diff insert end [mc \
 "* Untracked file is %d bytes.
 * Showing only first %d bytes.
-" $sz $max_sz] d_@
+" $sz $max_sz] d_info
                        }
                        $ui_diff insert end $content
                        if {$sz > $max_sz} {
                                $ui_diff insert end [mc "
 * Untracked file clipped here by %s.
 * To see the entire file, use an external editor.
-" [appname]] d_@
+" [appname]] d_info
                        }
                }
                $ui_diff conf -state disabled
@@ -253,6 +253,19 @@ proc show_other_diff {path w m cont_info} {
        }
 }
 
+proc get_conflict_marker_size {path} {
+       set size 7
+       catch {
+               set fd_rc [eval [list git_read check-attr "conflict-marker-size" -- $path]]
+               set ret [gets $fd_rc line]
+               close $fd_rc
+               if {$ret > 0} {
+                       regexp {.*: conflict-marker-size: (\d+)$} $line line size
+               }
+       }
+       return $size
+}
+
 proc start_show_diff {cont_info {add_opts {}}} {
        global file_states file_lists
        global is_3way_diff is_submodule_diff diff_active repo_config
@@ -268,6 +281,7 @@ proc start_show_diff {cont_info {add_opts {}}} {
        set is_submodule_diff 0
        set diff_active 1
        set current_diff_header {}
+       set conflict_size [get_conflict_marker_size $path]
 
        set cmd [list]
        if {$w eq $ui_index} {
@@ -329,7 +343,7 @@ proc start_show_diff {cont_info {add_opts {}}} {
                -blocking 0 \
                -encoding [get_path_encoding $path] \
                -translation lf
-       fileevent $fd readable [list read_diff $fd $cont_info]
+       fileevent $fd readable [list read_diff $fd $conflict_size $cont_info]
 }
 
 proc parse_color_line {line} {
@@ -337,19 +351,27 @@ proc parse_color_line {line} {
        set result ""
        set markup [list]
        set regexp {\033\[((?:\d+;)*\d+)?m}
+       set need_reset 0
        while {[regexp -indices -start $start $regexp $line match code]} {
                foreach {begin end} $match break
                append result [string range $line $start [expr {$begin - 1}]]
-               lappend markup [string length $result] \
-                       [eval [linsert $code 0 string range $line]]
+               set pos [string length $result]
+               set col [eval [linsert $code 0 string range $line]]
                set start [incr end]
+               if {$col eq "0" || $col eq ""} {
+                       if {!$need_reset} continue
+                       set need_reset 0
+               } else {
+                       set need_reset 1
+               }
+               lappend markup $pos $col
        }
        append result [string range $line $start end]
        if {[llength $markup] < 4} {set markup {}}
        return [list $result $markup]
 }
 
-proc read_diff {fd cont_info} {
+proc read_diff {fd conflict_size cont_info} {
        global ui_diff diff_active is_submodule_diff
        global is_3way_diff is_conflict_diff current_diff_header
        global current_diff_queue
@@ -360,37 +382,50 @@ proc read_diff {fd cont_info} {
                foreach {line markup} [parse_color_line $line] break
                set line [string map {\033 ^} $line]
 
-               # -- Cleanup uninteresting diff header lines.
+               set tags {}
+
+               # -- Check for start of diff header.
+               if {   [string match {diff --git *}      $line]
+                   || [string match {diff --cc *}       $line]
+                   || [string match {diff --combined *} $line]} {
+                       set ::current_diff_inheader 1
+               }
+
+               # -- Check for end of diff header (any hunk line will do this).
+               #
+               if {[regexp {^@@+ } $line]} {set ::current_diff_inheader 0}
+
+               # -- Automatically detect if this is a 3 way diff.
                #
+               if {[string match {@@@ *} $line]} {set is_3way_diff 1}
+
                if {$::current_diff_inheader} {
+
+                       # -- These two lines stop a diff header and shouldn't be in there
+                       if {   [string match {Binary files * and * differ} $line]
+                           || [regexp {^\* Unmerged path }                $line]} {
+                               set ::current_diff_inheader 0
+                       } else {
+                               append current_diff_header $line "\n"
+                       }
+
+                       # -- Cleanup uninteresting diff header lines.
+                       #
                        if {   [string match {diff --git *}      $line]
                            || [string match {diff --cc *}       $line]
                            || [string match {diff --combined *} $line]
                            || [string match {--- *}             $line]
-                           || [string match {+++ *}             $line]} {
-                               append current_diff_header $line "\n"
+                           || [string match {+++ *}             $line]
+                           || [string match {index *}           $line]} {
                                continue
                        }
-               }
-               if {[string match {index *} $line]} continue
-               if {$line eq {deleted file mode 120000}} {
-                       set line "deleted symlink"
-               }
-               set ::current_diff_inheader 0
 
-               # -- Automatically detect if this is a 3 way diff.
-               #
-               if {[string match {@@@ *} $line]} {set is_3way_diff 1}
+                       # -- Name it symlink, not 120000
+                       #    Note, that the original line is in $current_diff_header
+                       regsub {^(deleted|new) file mode 120000} $line {\1 symlink} line
 
-               if {[string match {mode *} $line]
-                       || [string match {new file *} $line]
-                       || [regexp {^(old|new) mode *} $line]
-                       || [string match {deleted file *} $line]
-                       || [string match {deleted symlink} $line]
-                       || [string match {Binary files * and * differ} $line]
-                       || $line eq {\ No newline at end of file}
-                       || [regexp {^\* Unmerged path } $line]} {
-                       set tags {}
+               } elseif {   $line eq {\ No newline at end of file}} {
+                       # -- Handle some special lines
                } elseif {$is_3way_diff} {
                        set op [string range $line 0 1]
                        switch -- $op {
@@ -402,7 +437,9 @@ proc read_diff {fd cont_info} {
                        {- } {set tags d_-s}
                        {--} {set tags d_--}
                        {++} {
-                               if {[regexp {^\+\+([<>]{7} |={7})} $line _g op]} {
+                               set regexp [string map [list %conflict_size $conflict_size]\
+                                                               {^\+\+([<>=]){%conflict_size}(?: |$)}]
+                               if {[regexp $regexp $line _g op]} {
                                        set is_conflict_diff 1
                                        set line [string replace $line 0 1 {  }]
                                        set tags d$op
@@ -418,10 +455,10 @@ proc read_diff {fd cont_info} {
                } elseif {$is_submodule_diff} {
                        if {$line == ""} continue
                        if {[regexp {^Submodule } $line]} {
-                               set tags d_@
+                               set tags d_info
                        } elseif {[regexp {^\* } $line]} {
                                set line [string replace $line 0 1 {Submodule }]
-                               set tags d_@
+                               set tags d_info
                        } else {
                                set op [string range $line 0 2]
                                switch -- $op {
@@ -441,7 +478,9 @@ proc read_diff {fd cont_info} {
                        {@} {set tags d_@}
                        {-} {set tags d_-}
                        {+} {
-                               if {[regexp {^\+([<>]{7} |={7})} $line _g op]} {
+                               set regexp [string map [list %conflict_size $conflict_size]\
+                                                               {^\+([<>=]){%conflict_size}(?: |$)}]
+                               if {[regexp $regexp $line _g op]} {
                                        set is_conflict_diff 1
                                        set tags d$op
                                } else {
index e9db0c49895fbebdf8dbe7c0472546a05fea26a0..5d7bbf23eddeb2ff146487b28a79feee1d296289 100644 (file)
@@ -103,8 +103,11 @@ proc write_update_indexinfo {fd pathList totalCnt batch after} {
                set s $file_states($path)
                switch -glob -- [lindex $s 0] {
                A? {set new _O}
-               M? {set new _M}
+               MT -
+               TM -
                T_ {set new _T}
+               M? {set new _M}
+               TD -
                D_ {set new _D}
                D? {set new _?}
                ?? {continue}
@@ -167,7 +170,10 @@ proc write_update_index {fd pathList totalCnt batch after} {
                AD {set new __}
                ?D {set new D_}
                _O -
+               AT -
                AM {set new A_}
+               TM -
+               MT -
                _T {set new T_}
                _U -
                U? {
@@ -261,7 +267,7 @@ proc unstage_helper {txt paths} {
                switch -glob -- [lindex $file_states($path) 0] {
                A? -
                M? -
-               T_ -
+               T? -
                D? {
                        lappend pathList $path
                        if {$path eq $current_diff_path} {
index 5cded2341c541b5688adbac35d3d2e1216bc2d0b..460d32fa22fc77f6621e5ec9a9c6ba6dc98050c2 100644 (file)
@@ -83,6 +83,7 @@ method _visualize {} {
 
 method _start {} {
        global HEAD current_branch remote_url
+       global _last_merged_branch
 
        set name [_rev $this]
        if {$name eq {}} {
@@ -109,6 +110,7 @@ method _start {} {
        regsub ^refs/heads/ $branch {} branch
        puts $fh "$cmit\t\tbranch '$branch' of $remote"
        close $fh
+       set _last_merged_branch $branch
 
        set cmd [list git]
        lappend cmd merge
index 3fe90e697002baaa1c5fa8df4c3d3eae199b062d..3c8e73bcebea652c11e328169f63a6d9950d6dc2 100644 (file)
@@ -175,43 +175,56 @@ proc merge_resolve_tool2 {} {
 
        # Build the command line
        switch -- $tool {
-       kdiff3 {
+       araxis {
                if {$base_stage ne {}} {
-                       set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Base)" \
-                               --L2 "$MERGED (Local)" --L3 "$MERGED (Remote)" -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE"]
+                       set cmdline [list "$merge_tool_path" -wait -merge -3 -a1 \
+                               -title1:"'$MERGED (Base)'" -title2:"'$MERGED (Local)'" \
+                               -title3:"'$MERGED (Remote)'" \
+                               "$BASE" "$LOCAL" "$REMOTE" "$MERGED"]
                } else {
-                       set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Local)" \
-                               --L2 "$MERGED (Remote)" -o "$MERGED" "$LOCAL" "$REMOTE"]
+                       set cmdline [list "$merge_tool_path" -wait -2 \
+                                -title1:"'$MERGED (Local)'" -title2:"'$MERGED (Remote)'" \
+                                "$LOCAL" "$REMOTE" "$MERGED"]
                }
        }
-       tkdiff {
+       bc3 {
                if {$base_stage ne {}} {
-                       set cmdline [list "$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE"]
+                       set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" -mergeoutput="$MERGED"]
                } else {
-                       set cmdline [list "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"]
+                       set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -mergeoutput="$MERGED"]
                }
        }
-       meld {
-               set cmdline [list "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"]
+       ecmerge {
+               if {$base_stage ne {}} {
+                       set cmdline [list "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" --default --mode=merge3 --to="$MERGED"]
+               } else {
+                       set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" --default --mode=merge2 --to="$MERGED"]
+               }
+       }
+       emerge {
+               if {$base_stage ne {}} {
+                       set cmdline [list "$merge_tool_path" -f emerge-files-with-ancestor-command \
+                                       "$LOCAL" "$REMOTE" "$BASE" "$basename"]
+               } else {
+                       set cmdline [list "$merge_tool_path" -f emerge-files-command \
+                                       "$LOCAL" "$REMOTE" "$basename"]
+               }
        }
        gvimdiff {
                set cmdline [list "$merge_tool_path" -f "$LOCAL" "$MERGED" "$REMOTE"]
        }
-       xxdiff {
+       kdiff3 {
                if {$base_stage ne {}} {
-                       set cmdline [list "$merge_tool_path" -X --show-merged-pane \
-                                           -R {Accel.SaveAsMerged: "Ctrl-S"} \
-                                           -R {Accel.Search: "Ctrl+F"} \
-                                           -R {Accel.SearchForward: "Ctrl-G"} \
-                                           --merged-file "$MERGED" "$LOCAL" "$BASE" "$REMOTE"]
+                       set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Base)" \
+                               --L2 "$MERGED (Local)" --L3 "$MERGED (Remote)" -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE"]
                } else {
-                       set cmdline [list "$merge_tool_path" -X --show-merged-pane \
-                                           -R {Accel.SaveAsMerged: "Ctrl-S"} \
-                                           -R {Accel.Search: "Ctrl+F"} \
-                                           -R {Accel.SearchForward: "Ctrl-G"} \
-                                           --merged-file "$MERGED" "$LOCAL" "$REMOTE"]
+                       set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Local)" \
+                               --L2 "$MERGED (Remote)" -o "$MERGED" "$LOCAL" "$REMOTE"]
                }
        }
+       meld {
+               set cmdline [list "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"]
+       }
        opendiff {
                if {$base_stage ne {}} {
                        set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED"]
@@ -219,22 +232,20 @@ proc merge_resolve_tool2 {} {
                        set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -merge "$MERGED"]
                }
        }
-       ecmerge {
-               if {$base_stage ne {}} {
-                       set cmdline [list "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" --default --mode=merge3 --to="$MERGED"]
-               } else {
-                       set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" --default --mode=merge2 --to="$MERGED"]
-               }
+       p4merge {
+               set cmdline [list "$merge_tool_path" "$BASE" "$REMOTE" "$LOCAL" "$MERGED"]
        }
-       emerge {
+       tkdiff {
                if {$base_stage ne {}} {
-                       set cmdline [list "$merge_tool_path" -f emerge-files-with-ancestor-command \
-                                       "$LOCAL" "$REMOTE" "$BASE" "$basename"]
+                       set cmdline [list "$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE"]
                } else {
-                       set cmdline [list "$merge_tool_path" -f emerge-files-command \
-                                       "$LOCAL" "$REMOTE" "$basename"]
+                       set cmdline [list "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"]
                }
        }
+       vimdiff {
+               error_popup [mc "Not a GUI merge tool: '%s'" $tool]
+               return
+       }
        winmerge {
                if {$base_stage ne {}} {
                        # This tool does not support 3-way merges.
@@ -245,25 +256,21 @@ proc merge_resolve_tool2 {} {
                                -dl "Theirs File" -dr "Mine File" "$REMOTE" "$LOCAL" "$MERGED"]
                }
        }
-       araxis {
+       xxdiff {
                if {$base_stage ne {}} {
-                       set cmdline [list "$merge_tool_path" -wait -merge -3 -a1 \
-                               -title1:"'$MERGED (Base)'" -title2:"'$MERGED (Local)'" \
-                               -title3:"'$MERGED (Remote)'" \
-                               "$BASE" "$LOCAL" "$REMOTE" "$MERGED"]
+                       set cmdline [list "$merge_tool_path" -X --show-merged-pane \
+                                           -R {Accel.SaveAsMerged: "Ctrl-S"} \
+                                           -R {Accel.Search: "Ctrl+F"} \
+                                           -R {Accel.SearchForward: "Ctrl-G"} \
+                                           --merged-file "$MERGED" "$LOCAL" "$BASE" "$REMOTE"]
                } else {
-                       set cmdline [list "$merge_tool_path" -wait -2 \
-                                -title1:"'$MERGED (Local)'" -title2:"'$MERGED (Remote)'" \
-                                "$LOCAL" "$REMOTE" "$MERGED"]
+                       set cmdline [list "$merge_tool_path" -X --show-merged-pane \
+                                           -R {Accel.SaveAsMerged: "Ctrl-S"} \
+                                           -R {Accel.Search: "Ctrl+F"} \
+                                           -R {Accel.SearchForward: "Ctrl-G"} \
+                                           --merged-file "$MERGED" "$LOCAL" "$REMOTE"]
                }
        }
-       p4merge {
-               set cmdline [list "$merge_tool_path" "$BASE" "$REMOTE" "$LOCAL" "$MERGED"]
-       }
-       vimdiff {
-               error_popup [mc "Not a GUI merge tool: '%s'" $tool]
-               return
-       }
        default {
                error_popup [mc "Unsupported merge tool '%s'" $tool]
                return
index b92b429cf766d525402047175ed0a69af015c682..5e4e7f4c83952ac2ec4c60eb79426248071ae54e 100644 (file)
@@ -157,22 +157,7 @@ proc add_fetch_entry {r} {
        }
 
        if {$enable} {
-               if {![winfo exists $fetch_m]} {
-                       menu $remove_m
-                       $remote_m insert 0 cascade \
-                               -label [mc "Remove Remote"] \
-                               -menu $remove_m
-
-                       menu $prune_m
-                       $remote_m insert 0 cascade \
-                               -label [mc "Prune from"] \
-                               -menu $prune_m
-
-                       menu $fetch_m
-                       $remote_m insert 0 cascade \
-                               -label [mc "Fetch from"] \
-                               -menu $fetch_m
-               }
+               make_sure_remote_submenues_exist $remote_m
 
                $fetch_m add command \
                        -label $r \
@@ -222,6 +207,70 @@ proc add_push_entry {r} {
        }
 }
 
+proc make_sure_remote_submenues_exist {remote_m} {
+       set fetch_m $remote_m.fetch
+       set prune_m $remote_m.prune
+       set remove_m $remote_m.remove
+
+       if {![winfo exists $fetch_m]} {
+               menu $remove_m
+               $remote_m insert 0 cascade \
+                       -label [mc "Remove Remote"] \
+                       -menu $remove_m
+
+               menu $prune_m
+               $remote_m insert 0 cascade \
+                       -label [mc "Prune from"] \
+                       -menu $prune_m
+
+               menu $fetch_m
+               $remote_m insert 0 cascade \
+                       -label [mc "Fetch from"] \
+                       -menu $fetch_m
+       }
+}
+
+proc update_all_remotes_menu_entry {} {
+       global all_remotes
+
+       if {[git-version < 1.6.6]} { return }
+
+       set have_remote 0
+       foreach r $all_remotes {
+               incr have_remote
+       }
+
+       set remote_m .mbar.remote
+       set fetch_m $remote_m.fetch
+       set prune_m $remote_m.prune
+       if {$have_remote > 1} {
+               make_sure_remote_submenues_exist $remote_m
+               if {[$fetch_m entrycget end -label] ne "All"} {
+
+                       $fetch_m insert end separator
+                       $fetch_m insert end command \
+                               -label "All" \
+                               -command fetch_from_all
+
+                       $prune_m insert end separator
+                       $prune_m insert end command \
+                               -label "All" \
+                               -command prune_from_all
+               }
+       } else {
+               if {[winfo exists $fetch_m]} {
+                       if {[$fetch_m entrycget end -label] eq "All"} {
+
+                               delete_from_menu $fetch_m end
+                               delete_from_menu $fetch_m end
+
+                               delete_from_menu $prune_m end
+                               delete_from_menu $prune_m end
+                       }
+               }
+       }
+}
+
 proc populate_remotes_menu {} {
        global all_remotes
 
@@ -229,6 +278,8 @@ proc populate_remotes_menu {} {
                add_fetch_entry $r
                add_push_entry $r
        }
+
+       update_all_remotes_menu_entry
 }
 
 proc add_single_remote {name location} {
@@ -244,6 +295,8 @@ proc add_single_remote {name location} {
 
        add_fetch_entry $name
        add_push_entry $name
+
+       update_all_remotes_menu_entry
 }
 
 proc delete_from_menu {menu name} {
@@ -264,8 +317,8 @@ proc remove_remote {name} {
                unset repo_config(remote.$name.push)
        }
 
-       set i [lsearch -exact all_remotes $name]
-       lreplace all_remotes $i $i
+       set i [lsearch -exact $all_remotes $name]
+       set all_remotes [lreplace $all_remotes $i $i]
 
        set remote_m .mbar.remote
        delete_from_menu $remote_m.fetch $name
@@ -273,4 +326,6 @@ proc remove_remote {name} {
        delete_from_menu $remote_m.remove $name
        # Not all remotes are in the push menu
        catch { delete_from_menu $remote_m.push $name }
+
+       update_all_remotes_menu_entry
 }
index f872a3d89d89bc861ea3729ec7974833bdac277f..fcc06d03a1dfc4919f762d70e2809f29dab77390 100644 (file)
@@ -251,7 +251,7 @@ method _write_url        {args} { set urltype url    }
 method _write_check_head {args} { set checktype head }
 
 method _write_head_list {args} {
-       global current_branch
+       global current_branch _last_merged_branch
 
        $head_m delete 0 end
        foreach abr $head_list {
@@ -267,6 +267,13 @@ method _write_head_list {args} {
                        set check_head $current_branch
                }
        }
+       set lmb [lsearch -exact -sorted $head_list $_last_merged_branch]
+       if {$lmb >= 0} {
+               $w.heads.l conf -state normal
+               $w.heads.l select set $lmb
+               $w.heads.l yview $lmb
+               $w.heads.l conf -state disabled
+       }
 }
 
 method _write_urltype {args} {
index 60e3a642c5fb7f1526c9feb1a1d3a495db7728f8..7fad9b7d91a6d6a0671ca7bac714dcc4fd022403 100644 (file)
@@ -20,6 +20,35 @@ proc prune_from {remote} {
        console::exec $w [list git remote prune $remote]
 }
 
+proc fetch_from_all {} {
+       set w [console::new \
+               [mc "fetch all remotes"] \
+               [mc "Fetching new changes from all remotes"]]
+
+       set cmd [list git fetch --all]
+       if {[is_config_true gui.pruneduringfetch]} {
+               lappend cmd --prune
+       }
+
+       console::exec $w $cmd
+}
+
+proc prune_from_all {} {
+       global all_remotes
+
+       set w [console::new \
+               [mc "remote prune all remotes"] \
+               [mc "Pruning tracking branches deleted from all remotes"]]
+
+       set cmd [list git remote prune]
+
+       foreach r $all_remotes {
+               lappend cmd $r
+       }
+
+       console::exec $w $cmd
+}
+
 proc push_to {remote} {
        set w [console::new \
                [mc "push %s" $remote] \
@@ -123,6 +152,7 @@ proc do_push_anywhere {} {
                $w.source.l insert end $h
                if {$h eq $current_branch} {
                        $w.source.l select set end
+                       $w.source.l yview end
                }
        }
        pack $w.source.l -side left -fill both -expand 1
@@ -135,7 +165,9 @@ proc do_push_anywhere {} {
                        -value remote \
                        -variable push_urltype
                if {$use_ttk} {
-                       ttk::combobox $w.dest.remote_m -textvariable push_remote \
+                       ttk::combobox $w.dest.remote_m -state readonly \
+                               -exportselection false \
+                               -textvariable push_remote \
                                -values $all_remotes
                } else {
                        eval tk_optionMenu $w.dest.remote_m push_remote $all_remotes
diff --git a/git-gui/po/glossary/pt_br.po b/git-gui/po/glossary/pt_br.po
new file mode 100644 (file)
index 0000000..eb039b2
--- /dev/null
@@ -0,0 +1,169 @@
+# Translation of git-gui to Brazilian Portuguese
+# Copyright (C) 2007 Shawn Pearce, et al.
+# This file is distributed under the same license as the git-gui package.
+#
+# Alexandre Erwin Ittner <alexandre@ittner.com.br>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: git-gui\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-01-26 15:47-0800\n"
+"PO-Revision-Date: 2010-09-18 11:09-0300\n"
+"Last-Translator: Alexandre Erwin Ittner <alexandre@ittner.com.br>\n"
+"Language-Team: Brazilian Portuguese <>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\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 ""
+
+#. ""
+msgid "amend"
+msgstr "corrigir"
+
+#. ""
+msgid "annotate"
+msgstr "anotar"
+
+#. "A 'branch' is an active line of development."
+msgid "branch [noun]"
+msgstr "ramo"
+
+#. ""
+msgid "branch [verb]"
+msgstr "ramificar"
+
+#. ""
+msgid "checkout [noun]"
+msgstr "checkout"
+
+#. "The action of updating the working tree to a revision which was stored in the object database."
+msgid "checkout [verb]"
+msgstr "efetuar checkout"
+
+#. ""
+msgid "clone [verb]"
+msgstr "clonar"
+
+#. "A single point in the git history."
+msgid "commit [noun]"
+msgstr "revisão"
+
+#. "The action of storing a new snapshot of the project's state in the git history."
+msgid "commit [verb]"
+msgstr "salvar revisão"
+
+#. ""
+msgid "diff [noun]"
+msgstr "diff"
+
+#. ""
+msgid "diff [verb]"
+msgstr "comparar"
+
+#. "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 "mesclagem rápida"
+
+#. "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 "receber"
+
+#. "One context of consecutive lines in a whole patch, which consists of many such hunks"
+msgid "hunk"
+msgstr "trecho"
+
+#. "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 "mesclagem"
+
+#. "To bring the contents of another branch into the current branch."
+msgid "merge [verb]"
+msgstr "mesclar"
+
+#. ""
+msgid "message"
+msgstr "descrição da revisão"
+
+#. "Deletes all stale tracking branches under <name>. These stale branches have already been removed from the remote repository referenced by <name>, but are still locally available in 'remotes/<name>'."
+msgid "prune"
+msgstr "limpar"
+
+#. "Pulling a branch means to fetch it and merge it."
+msgid "pull"
+msgstr "receber e mesclar"
+
+#. "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 "enviar"
+
+#. ""
+msgid "redo"
+msgstr "refazer"
+
+#. "An other repository ('remote'). One might have a set of remotes whose branches one tracks."
+msgid "remote"
+msgstr "repositório 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 "descartar, redefinir"
+
+#. ""
+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 embaixo"
+
+#. ""
+msgid "staging area"
+msgstr "???"
+
+#. ""
+msgid "status"
+msgstr "status"
+
+#. "A ref pointing to a tag or commit object"
+msgid "tag [noun]"
+msgstr "etiqueta"
+
+#. ""
+msgid "tag [verb]"
+msgstr "marcar etiqueta"
+
+#. "A regular git branch that is used to follow changes from another repository."
+msgid "tracking branch"
+msgstr "ramo de rastreamento"
+
+#. ""
+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"
diff --git a/git-gui/po/pt_br.po b/git-gui/po/pt_br.po
new file mode 100644 (file)
index 0000000..b175b97
--- /dev/null
@@ -0,0 +1,2568 @@
+# Translation of git-gui to Brazilian Portuguese
+# Copyright (C) 2007 Shawn Pearce, et al.
+# This file is distributed under the same license as the git-gui package.
+#
+# Alexandre Erwin Ittner <alexandre@ittner.com.br>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: git-gui\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-01-26 15:47-0800\n"
+"PO-Revision-Date: 2010-09-18 11:09-0300\n"
+"Last-Translator: Alexandre Erwin Ittner <alexandre@ittner.com.br>\n"
+"Language-Team: Brazilian Portuguese <>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\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
+msgid "git-gui: fatal error"
+msgstr "git-gui: erro fatal"
+
+#: git-gui.sh:743
+#, tcl-format
+msgid "Invalid font specified in %s:"
+msgstr "Fonte inválida indicada em %s:"
+
+#: git-gui.sh:779
+msgid "Main Font"
+msgstr "Fonte principal"
+
+#: git-gui.sh:780
+msgid "Diff/Console Font"
+msgstr "Fonte para o diff/console"
+
+#: git-gui.sh:794
+msgid "Cannot find git in PATH."
+msgstr "Impossível encontrar o git no \"PATH\""
+
+#: git-gui.sh:821
+msgid "Cannot parse Git version string:"
+msgstr "Impossível interpretar a versão do git:"
+
+#: git-gui.sh:839
+#, 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 ""
+"Não foi possível determinar a versão do git:\n"
+"\n"
+"%s afirmar que sua versão é \"%s\".\n"
+"\n"
+"%s exige o Git 1.5.0 ou posterior.\n"
+"\n"
+"Assumir que '%s' é a versão 1.5.0?\n"
+
+#: git-gui.sh:1128
+msgid "Git directory not found:"
+msgstr "Diretório do Git não encontrado:"
+
+#: git-gui.sh:1146
+msgid "Cannot move to top of working directory:"
+msgstr "Impossível mover para o início do diretório de trabalho:"
+
+#: git-gui.sh:1154
+msgid "Cannot use bare repository:"
+msgstr "Impossível usar repositório puro:"
+
+#: git-gui.sh:1162
+msgid "No working directory"
+msgstr "Sem diretório de trabalho"
+
+#: git-gui.sh:1334 lib/checkout_op.tcl:306
+msgid "Refreshing file status..."
+msgstr "Atualizando estado dos arquivos..."
+
+#: git-gui.sh:1390
+msgid "Scanning for modified files ..."
+msgstr "Procurando por arquivos modificados ..."
+
+#: git-gui.sh:1454
+msgid "Calling prepare-commit-msg hook..."
+msgstr "Executando hook \"prepare-commit-msg\"..."
+
+#: git-gui.sh:1471
+msgid "Commit declined by prepare-commit-msg hook."
+msgstr "O script \"prepare-commit-msg\" negou a criação de uma nova revisão"
+
+#: git-gui.sh:1629 lib/browser.tcl:246
+msgid "Ready."
+msgstr "Pronto."
+
+#: git-gui.sh:1787
+#, tcl-format
+msgid "Displaying only %s of %s files."
+msgstr "Exibindo apenas %s de %s arquivos."
+
+#: git-gui.sh:1913
+msgid "Unmodified"
+msgstr "Não modificado"
+
+#: git-gui.sh:1915
+msgid "Modified, not staged"
+msgstr "Modificado, não marcado"
+
+#: git-gui.sh:1916 git-gui.sh:1924
+msgid "Staged for commit"
+msgstr "Marcado para uma nova revisão"
+
+#: git-gui.sh:1917 git-gui.sh:1925
+msgid "Portions staged for commit"
+msgstr "Trechos marcados para revisão"
+
+#: git-gui.sh:1918 git-gui.sh:1926
+msgid "Staged for commit, missing"
+msgstr "Marcado para revisão, faltando"
+
+#: git-gui.sh:1920
+msgid "File type changed, not staged"
+msgstr "Tipo do arquivo modificado, não marcado"
+
+#: git-gui.sh:1921
+msgid "File type changed, staged"
+msgstr "Tipo do arquivo modificado, marcado"
+
+#: git-gui.sh:1923
+msgid "Untracked, not staged"
+msgstr "Não monitorado, não marcado"
+
+#: git-gui.sh:1928
+msgid "Missing"
+msgstr "Faltando"
+
+#: git-gui.sh:1929
+msgid "Staged for removal"
+msgstr "Marcado para remoção"
+
+#: git-gui.sh:1930
+msgid "Staged for removal, still present"
+msgstr "Marcado para remoção, ainda presente"
+
+#: git-gui.sh:1932 git-gui.sh:1933 git-gui.sh:1934 git-gui.sh:1935
+#: git-gui.sh:1936 git-gui.sh:1937
+msgid "Requires merge resolution"
+msgstr "Requer resolução de conflitos"
+
+#: git-gui.sh:1972
+msgid "Starting gitk... please wait..."
+msgstr "Iniciando gitk... Aguarde..."
+
+#: git-gui.sh:1984
+msgid "Couldn't find gitk in PATH"
+msgstr "Impossível encontrar o gitk no PATH"
+
+#: git-gui.sh:2043
+msgid "Couldn't find git gui in PATH"
+msgstr "Impossível encontrar o \"git gui\" no PATH"
+
+#: git-gui.sh:2455 lib/choose_repository.tcl:36
+msgid "Repository"
+msgstr "Repositório"
+
+#: git-gui.sh:2456
+msgid "Edit"
+msgstr "Editar"
+
+#: git-gui.sh:2458 lib/choose_rev.tcl:561
+msgid "Branch"
+msgstr "Ramo"
+
+#: git-gui.sh:2461 lib/choose_rev.tcl:548
+msgid "Commit@@noun"
+msgstr "Revisão"
+
+#: git-gui.sh:2464 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168
+msgid "Merge"
+msgstr "Mesclar"
+
+#: git-gui.sh:2465 lib/choose_rev.tcl:557
+msgid "Remote"
+msgstr "Remoto"
+
+#: git-gui.sh:2468
+msgid "Tools"
+msgstr "Ferramentas"
+
+#: git-gui.sh:2477
+msgid "Explore Working Copy"
+msgstr "Explorar cópia de trabalho"
+
+#: git-gui.sh:2483
+msgid "Browse Current Branch's Files"
+msgstr "Explorar arquivos do ramo atual"
+
+#: git-gui.sh:2487
+msgid "Browse Branch Files..."
+msgstr "Explorar arquivos do ramo..."
+
+#: git-gui.sh:2492
+msgid "Visualize Current Branch's History"
+msgstr "Visualizar histórico do ramo atual"
+
+#: git-gui.sh:2496
+msgid "Visualize All Branch History"
+msgstr "Visualizar histórico de todos os ramos"
+
+#: git-gui.sh:2503
+#, tcl-format
+msgid "Browse %s's Files"
+msgstr "Explorar arquivos de %s"
+
+#: git-gui.sh:2505
+#, tcl-format
+msgid "Visualize %s's History"
+msgstr "Visualizar histórico de %s"
+
+#: git-gui.sh:2510 lib/database.tcl:27 lib/database.tcl:67
+msgid "Database Statistics"
+msgstr "Estatísticas do banco de dados"
+
+#: git-gui.sh:2513 lib/database.tcl:34
+msgid "Compress Database"
+msgstr "Compactar banco de dados"
+
+#: git-gui.sh:2516
+msgid "Verify Database"
+msgstr "Verificar banco de dados"
+
+#: git-gui.sh:2523 git-gui.sh:2527 git-gui.sh:2531 lib/shortcut.tcl:8
+#: lib/shortcut.tcl:40 lib/shortcut.tcl:72
+msgid "Create Desktop Icon"
+msgstr "Criar ícone na área de trabalho"
+
+#: git-gui.sh:2539 lib/choose_repository.tcl:183 lib/choose_repository.tcl:191
+msgid "Quit"
+msgstr "Sair"
+
+#: git-gui.sh:2547
+msgid "Undo"
+msgstr "Desfazer"
+
+#: git-gui.sh:2550
+msgid "Redo"
+msgstr "Refazer"
+
+#: git-gui.sh:2554 git-gui.sh:3109
+msgid "Cut"
+msgstr "Recortar"
+
+#: git-gui.sh:2557 git-gui.sh:3112 git-gui.sh:3186 git-gui.sh:3259
+#: lib/console.tcl:69
+msgid "Copy"
+msgstr "Copiar"
+
+#: git-gui.sh:2560 git-gui.sh:3115
+msgid "Paste"
+msgstr "Colar"
+
+#: git-gui.sh:2563 git-gui.sh:3118 lib/branch_delete.tcl:26
+#: lib/remote_branch_delete.tcl:38
+msgid "Delete"
+msgstr "Apagar"
+
+#: git-gui.sh:2567 git-gui.sh:3122 git-gui.sh:3263 lib/console.tcl:71
+msgid "Select All"
+msgstr "Selecionar tudo"
+
+#: git-gui.sh:2576
+msgid "Create..."
+msgstr "Criar..."
+
+#: git-gui.sh:2582
+msgid "Checkout..."
+msgstr "Checkout..."
+
+#: git-gui.sh:2588
+msgid "Rename..."
+msgstr "Renomear..."
+
+#: git-gui.sh:2593
+msgid "Delete..."
+msgstr "Apagar..."
+
+#: git-gui.sh:2598
+msgid "Reset..."
+msgstr "Redefinir..."
+
+#: git-gui.sh:2608
+msgid "Done"
+msgstr "Pronto"
+
+#: git-gui.sh:2610
+msgid "Commit@@verb"
+msgstr "Salvar revisão"
+
+#: git-gui.sh:2619 git-gui.sh:3050
+msgid "New Commit"
+msgstr "Nova revisão"
+
+#: git-gui.sh:2627 git-gui.sh:3057
+msgid "Amend Last Commit"
+msgstr "Corrigir última revisão"
+
+#: git-gui.sh:2637 git-gui.sh:3011 lib/remote_branch_delete.tcl:99
+msgid "Rescan"
+msgstr "Atualizar"
+
+#: git-gui.sh:2643
+msgid "Stage To Commit"
+msgstr "Marcar para revisão"
+
+#: git-gui.sh:2649
+msgid "Stage Changed Files To Commit"
+msgstr "Marcar arquivos modificados"
+
+#: git-gui.sh:2655
+msgid "Unstage From Commit"
+msgstr "Desmarcar"
+
+#: git-gui.sh:2661 lib/index.tcl:412
+msgid "Revert Changes"
+msgstr "Reverter mudanças"
+
+#: git-gui.sh:2669 git-gui.sh:3310 git-gui.sh:3341
+msgid "Show Less Context"
+msgstr "Mostrar menos contexto"
+
+#: git-gui.sh:2673 git-gui.sh:3314 git-gui.sh:3345
+msgid "Show More Context"
+msgstr "Mostrar mais contexto"
+
+#: git-gui.sh:2680 git-gui.sh:3024 git-gui.sh:3133
+msgid "Sign Off"
+msgstr "Assinar embaixo"
+
+#: git-gui.sh:2696
+msgid "Local Merge..."
+msgstr "Mesclar localmente..."
+
+#: git-gui.sh:2701
+msgid "Abort Merge..."
+msgstr "Abortar mesclagem..."
+
+#: git-gui.sh:2713 git-gui.sh:2741
+msgid "Add..."
+msgstr "Adicionar..."
+
+#: git-gui.sh:2717
+msgid "Push..."
+msgstr "Enviar..."
+
+#: git-gui.sh:2721
+msgid "Delete Branch..."
+msgstr "Apagar ramo..."
+
+#: git-gui.sh:2731 git-gui.sh:3292
+msgid "Options..."
+msgstr "Opções..."
+
+#: git-gui.sh:2742
+msgid "Remove..."
+msgstr "Remover..."
+
+#: git-gui.sh:2751 lib/choose_repository.tcl:50
+msgid "Help"
+msgstr "Ajuda"
+
+#: git-gui.sh:2755 git-gui.sh:2759 lib/about.tcl:14
+#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:53
+#, tcl-format
+msgid "About %s"
+msgstr "Sobre o %s"
+
+#: git-gui.sh:2783
+msgid "Online Documentation"
+msgstr "Ajuda online"
+
+#: git-gui.sh:2786 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
+msgid "Show SSH Key"
+msgstr "Mostrar chave SSH"
+
+#: git-gui.sh:2893
+#, tcl-format
+msgid "fatal: cannot stat path %s: No such file or directory"
+msgstr ""
+"erro fatal: impossível executar \"stat\" em  %s: Arquivo ou diretório não "
+"encontrado"
+
+#: git-gui.sh:2926
+msgid "Current Branch:"
+msgstr "Ramo atual:"
+
+#: git-gui.sh:2947
+msgid "Staged Changes (Will Commit)"
+msgstr "Mudanças marcadas"
+
+#: git-gui.sh:2967
+msgid "Unstaged Changes"
+msgstr "Mudanças não marcadas"
+
+#: git-gui.sh:3017
+msgid "Stage Changed"
+msgstr "Marcar alterados"
+
+#: git-gui.sh:3036 lib/transport.tcl:104 lib/transport.tcl:193
+msgid "Push"
+msgstr "Enviar"
+
+#: git-gui.sh:3071
+msgid "Initial Commit Message:"
+msgstr "Descrição da revisão inicial:"
+
+#: git-gui.sh:3072
+msgid "Amended Commit Message:"
+msgstr "Descrição da revisão corrigida:"
+
+#: git-gui.sh:3073
+msgid "Amended Initial Commit Message:"
+msgstr "Descrição da revisão inicial corrigida:"
+
+#: git-gui.sh:3074
+msgid "Amended Merge Commit Message:"
+msgstr "Descrição da revisão de mescla corrigida:"
+
+#: git-gui.sh:3075
+msgid "Merge Commit Message:"
+msgstr "Descrição da revisão de mescla:"
+
+#: git-gui.sh:3076
+msgid "Commit Message:"
+msgstr "Descrição da revisão:"
+
+#: git-gui.sh:3125 git-gui.sh:3267 lib/console.tcl:73
+msgid "Copy All"
+msgstr "Copiar todos"
+
+#: git-gui.sh:3149 lib/blame.tcl:104
+msgid "File:"
+msgstr "Arquivo:"
+
+#: git-gui.sh:3255
+msgid "Refresh"
+msgstr "Atualizar"
+
+#: git-gui.sh:3276
+msgid "Decrease Font Size"
+msgstr "Reduzir tamanho da fonte"
+
+#: git-gui.sh:3280
+msgid "Increase Font Size"
+msgstr "Aumentar tamanho da fonte"
+
+#: git-gui.sh:3288 lib/blame.tcl:281
+msgid "Encoding"
+msgstr "Codificação"
+
+#: git-gui.sh:3299
+msgid "Apply/Reverse Hunk"
+msgstr "Aplicar/reverter trecho"
+
+#: git-gui.sh:3304
+msgid "Apply/Reverse Line"
+msgstr "Aplicar/reverter linha"
+
+#: git-gui.sh:3323
+msgid "Run Merge Tool"
+msgstr "Executar ferramenta de mescla"
+
+#: git-gui.sh:3328
+msgid "Use Remote Version"
+msgstr "Usar versão remota"
+
+#: git-gui.sh:3332
+msgid "Use Local Version"
+msgstr "Usar versão local"
+
+#: git-gui.sh:3336
+msgid "Revert To Base"
+msgstr "Reverter para a versão-base"
+
+#: git-gui.sh:3354
+msgid "Visualize These Changes In The Submodule"
+msgstr "Visualizar estas mudanças no sub-módulo"
+
+#: git-gui.sh:3358
+msgid "Visualize Current Branch History In The Submodule"
+msgstr "Visualizar histórico do ramo atual no sub-módulo"
+
+#: git-gui.sh:3362
+msgid "Visualize All Branch History In The Submodule"
+msgstr "Visualizar histórico de todos os camos no sub-módulo"
+
+#: git-gui.sh:3367
+msgid "Start git gui In The Submodule"
+msgstr "Iniciar \"git gui\" no sub-módulo"
+
+#: git-gui.sh:3389
+msgid "Unstage Hunk From Commit"
+msgstr "Desmarcar trecho para revisão"
+
+#: git-gui.sh:3391
+msgid "Unstage Lines From Commit"
+msgstr "Desmarcar linhas para revisão"
+
+#: git-gui.sh:3393
+msgid "Unstage Line From Commit"
+msgstr "Desmarcar linha para revisão"
+
+#: git-gui.sh:3396
+msgid "Stage Hunk For Commit"
+msgstr "Marcar trecho para revisão"
+
+#: git-gui.sh:3398
+msgid "Stage Lines For Commit"
+msgstr "Marcar linhas para revisão"
+
+#: git-gui.sh:3400
+msgid "Stage Line For Commit"
+msgstr "Marcar linha para revisão"
+
+#: git-gui.sh:3424
+msgid "Initializing..."
+msgstr "Iniciando..."
+
+#: git-gui.sh:3541
+#, 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 ""
+"Possíveis problemas com as variáveis de ambiente.\n"
+"\n"
+"As seguintes variáveis de ambiente provavelmente serão\n"
+"ignoradas por qualquer sub-processo do Git executado por\n"
+"%s:\n"
+
+#: git-gui.sh:3570
+msgid ""
+"\n"
+"This is due to a known issue with the\n"
+"Tcl binary distributed by Cygwin."
+msgstr ""
+"\n"
+"Isto se deve a um problema conhecido com os binários da Tcl \n"
+"distribuídos com o Cygwin"
+
+#: git-gui.sh:3575
+#, 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"
+"Uma boa alternativa para %s\n"
+"é colocar os valores para o nome de usuário e e-mail\n"
+"no seu arquivo \"~/.gitconfig\"\n"
+
+#: lib/about.tcl:26
+msgid "git-gui - a graphical user interface for Git."
+msgstr "git-gui - uma interface gráfica para o Git"
+
+#: lib/blame.tcl:72
+msgid "File Viewer"
+msgstr "Visualizador de arquivos"
+
+#: lib/blame.tcl:78
+msgid "Commit:"
+msgstr "Revisão:"
+
+#: lib/blame.tcl:271
+msgid "Copy Commit"
+msgstr "Copiar revisão"
+
+#: lib/blame.tcl:275
+msgid "Find Text..."
+msgstr "Procurar texto..."
+
+#: lib/blame.tcl:284
+msgid "Do Full Copy Detection"
+msgstr "Executar detecção completa de cópias"
+
+#: lib/blame.tcl:288
+msgid "Show History Context"
+msgstr "Mostrar contexto do histórico"
+
+#: lib/blame.tcl:291
+msgid "Blame Parent Commit"
+msgstr "Anotar revisão anterior"
+
+#: lib/blame.tcl:450
+#, tcl-format
+msgid "Reading %s..."
+msgstr "Lendo %s..."
+
+#: lib/blame.tcl:557
+msgid "Loading copy/move tracking annotations..."
+msgstr "Carregando anotações de cópia/movimentação..."
+
+#: lib/blame.tcl:577
+msgid "lines annotated"
+msgstr "linhas anotadas"
+
+#: lib/blame.tcl:769
+msgid "Loading original location annotations..."
+msgstr "Carregando anotações originais..."
+
+#: lib/blame.tcl:772
+msgid "Annotation complete."
+msgstr "Anotação completa."
+
+#: lib/blame.tcl:802
+msgid "Busy"
+msgstr "Ocupado"
+
+#: lib/blame.tcl:803
+msgid "Annotation process is already running."
+msgstr "O processo de anotação já está em execução"
+
+#: lib/blame.tcl:842
+msgid "Running thorough copy detection..."
+msgstr "Executando detecção de cópia..."
+
+#: lib/blame.tcl:910
+msgid "Loading annotation..."
+msgstr "Carregando anotações..."
+
+#: lib/blame.tcl:963
+msgid "Author:"
+msgstr "Autor:"
+
+#: lib/blame.tcl:967
+msgid "Committer:"
+msgstr "Revisor:"
+
+#: lib/blame.tcl:972
+msgid "Original File:"
+msgstr "Arquivo original:"
+
+#: lib/blame.tcl:1020
+msgid "Cannot find HEAD commit:"
+msgstr "Impossível encontrar revisão HEAD:"
+
+#: lib/blame.tcl:1075
+msgid "Cannot find parent commit:"
+msgstr "Impossível encontrar revisão anterior:"
+
+#: lib/blame.tcl:1090
+msgid "Unable to display parent"
+msgstr "Impossível exibir revisão anterior"
+
+#: lib/blame.tcl:1091 lib/diff.tcl:320
+msgid "Error loading diff:"
+msgstr "Erro ao carregar as diferenças:"
+
+#: lib/blame.tcl:1231
+msgid "Originally By:"
+msgstr "Originalmente por:"
+
+#: lib/blame.tcl:1237
+msgid "In File:"
+msgstr "No arquivo:"
+
+#: lib/blame.tcl:1242
+msgid "Copied Or Moved Here By:"
+msgstr "Copiado ou movido para cá por:"
+
+#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19
+msgid "Checkout Branch"
+msgstr "Efetuar checkout do ramo"
+
+#: lib/branch_checkout.tcl:23
+msgid "Checkout"
+msgstr "Checkout"
+
+#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
+#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
+#: lib/checkout_op.tcl:579 lib/choose_font.tcl:43 lib/merge.tcl:172
+#: lib/option.tcl:125 lib/remote_add.tcl:32 lib/remote_branch_delete.tcl:42
+#: lib/tools_dlg.tcl:40 lib/tools_dlg.tcl:204 lib/tools_dlg.tcl:352
+#: lib/transport.tcl:108
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: lib/branch_checkout.tcl:32 lib/browser.tcl:287 lib/tools_dlg.tcl:328
+msgid "Revision"
+msgstr "Revisão"
+
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:280
+msgid "Options"
+msgstr "Opções"
+
+#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92
+msgid "Fetch Tracking Branch"
+msgstr "Obter ramo de rastreamento"
+
+#: lib/branch_checkout.tcl:44
+msgid "Detach From Local Branch"
+msgstr "Separar do ramo local"
+
+#: lib/branch_create.tcl:22
+msgid "Create Branch"
+msgstr "Criar ramo"
+
+#: lib/branch_create.tcl:27
+msgid "Create New Branch"
+msgstr "Criar novo ramo"
+
+#: lib/branch_create.tcl:31 lib/choose_repository.tcl:381
+msgid "Create"
+msgstr "Criar"
+
+#: lib/branch_create.tcl:40
+msgid "Branch Name"
+msgstr "Nome do ramo"
+
+#: lib/branch_create.tcl:43 lib/remote_add.tcl:39 lib/tools_dlg.tcl:50
+msgid "Name:"
+msgstr "Nome:"
+
+#: lib/branch_create.tcl:58
+msgid "Match Tracking Branch Name"
+msgstr "Coincidir nome do ramo de rastreamento"
+
+#: 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 "Somente se for um avanço rápido"
+
+#: lib/branch_create.tcl:85 lib/checkout_op.tcl:571
+msgid "Reset"
+msgstr "Redefinir"
+
+#: lib/branch_create.tcl:97
+msgid "Checkout After Creation"
+msgstr "Efetuar checkout após a criação"
+
+#: lib/branch_create.tcl:131
+msgid "Please select a tracking branch."
+msgstr "Selecione um ramo de rastreamento."
+
+#: lib/branch_create.tcl:140
+#, tcl-format
+msgid "Tracking branch %s is not a branch in the remote repository."
+msgstr "O ramo de rastreamento %s não é um ramo do repositório remoto."
+
+#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86
+msgid "Please supply a branch name."
+msgstr "Indique um nome para o ramo."
+
+#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106
+#, tcl-format
+msgid "'%s' is not an acceptable branch name."
+msgstr "\"%s\" não é um nome de ramo válido"
+
+#: lib/branch_delete.tcl:15
+msgid "Delete Branch"
+msgstr "Apagar ramo"
+
+#: lib/branch_delete.tcl:20
+msgid "Delete Local Branch"
+msgstr "Apagar ramo local"
+
+#: lib/branch_delete.tcl:37
+msgid "Local Branches"
+msgstr "Ramos locais"
+
+#: lib/branch_delete.tcl:52
+msgid "Delete Only If Merged Into"
+msgstr "Apagar somente se mesclado em"
+
+#: lib/branch_delete.tcl:54 lib/remote_branch_delete.tcl:119
+msgid "Always (Do not perform merge checks)"
+msgstr "Forçar exclusão (não verificar se o ramo foi mesclado)"
+
+#: lib/branch_delete.tcl:103
+#, tcl-format
+msgid "The following branches are not completely merged into %s:"
+msgstr "Os ramos seguintes não foram completamente mesclados em %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 ""
+"Recuperar ramos apagados é difícil.\n"
+"\n"
+"Apagar os ramos selecionados?"
+
+#: lib/branch_delete.tcl:141
+#, tcl-format
+msgid ""
+"Failed to delete branches:\n"
+"%s"
+msgstr ""
+"Erro ao apagar ramos:\n"
+"%s"
+
+#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22
+msgid "Rename Branch"
+msgstr "Renomear ramo"
+
+#: lib/branch_rename.tcl:26
+msgid "Rename"
+msgstr "Renomear"
+
+#: lib/branch_rename.tcl:36
+msgid "Branch:"
+msgstr "Ramo:"
+
+#: lib/branch_rename.tcl:39
+msgid "New Name:"
+msgstr "Novo nome:"
+
+#: lib/branch_rename.tcl:75
+msgid "Please select a branch to rename."
+msgstr "Selecione um ramo para renomear."
+
+#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:202
+#, tcl-format
+msgid "Branch '%s' already exists."
+msgstr "O ramo \"%s\" já existe."
+
+#: lib/branch_rename.tcl:117
+#, tcl-format
+msgid "Failed to rename '%s'."
+msgstr "Erro ao renomear \"%s\"."
+
+#: lib/browser.tcl:17
+msgid "Starting..."
+msgstr "Inciando..."
+
+#: lib/browser.tcl:26
+msgid "File Browser"
+msgstr "Navegador de arquivos"
+
+#: lib/browser.tcl:126 lib/browser.tcl:143
+#, tcl-format
+msgid "Loading %s..."
+msgstr "Carregando %s..."
+
+#: lib/browser.tcl:187
+msgid "[Up To Parent]"
+msgstr "[Subir]"
+
+#: lib/browser.tcl:267 lib/browser.tcl:273
+msgid "Browse Branch Files"
+msgstr "Explorar arquivos do ramo"
+
+#: lib/browser.tcl:278 lib/choose_repository.tcl:398
+#: lib/choose_repository.tcl:486 lib/choose_repository.tcl:497
+#: lib/choose_repository.tcl:1028
+msgid "Browse"
+msgstr "Explorar"
+
+#: lib/checkout_op.tcl:85
+#, tcl-format
+msgid "Fetching %s from %s"
+msgstr "Obtendo %s de %s"
+
+#: lib/checkout_op.tcl:133
+#, tcl-format
+msgid "fatal: Cannot resolve %s"
+msgstr "Erro fatal: impossível resolver %s"
+
+#: lib/checkout_op.tcl:146 lib/console.tcl:81 lib/database.tcl:31
+#: lib/sshkey.tcl:53
+msgid "Close"
+msgstr "Fechar"
+
+#: 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 "Erro ao configurar git-pull simplificado para \"%s\"."
+
+#: 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 é possível avançá-lo para %s.\n"
+"É preciso mesclar."
+
+#: lib/checkout_op.tcl:243
+#, tcl-format
+msgid "Merge strategy '%s' not supported."
+msgstr "Estratégia de mesclagem \"%s\" não suportada."
+
+#: lib/checkout_op.tcl:262
+#, tcl-format
+msgid "Failed to update '%s'."
+msgstr "Erro ao atualizar \"%s\"."
+
+#: lib/checkout_op.tcl:274
+msgid "Staging area (index) is already locked."
+msgstr "A área de marcação (staging area, index) 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 lido não confere com o estado atual.\n"
+"\n"
+"Outro programa do Git modificou o repositório desde a última leitura. Uma "
+"atualização deve ser executada antes de alterar o ramo atual.\n"
+"\n"
+"A atualização começará automaticamente agora.\n"
+
+#: lib/checkout_op.tcl:345
+#, tcl-format
+msgid "Updating working directory to '%s'..."
+msgstr "Atualizando diretório de trabalho para \"%s\"..."
+
+#: lib/checkout_op.tcl:346
+msgid "files checked out"
+msgstr "arquivos retirados"
+
+#: lib/checkout_op.tcl:376
+#, tcl-format
+msgid "Aborted checkout of '%s' (file level merging is required)."
+msgstr "Checkout de \"%s\" abortado (é preciso mesclar alguns arquivos)"
+
+#: lib/checkout_op.tcl:377
+msgid "File level merge required."
+msgstr "Mesclagem de arquivos necessária."
+
+#: lib/checkout_op.tcl:381
+#, tcl-format
+msgid "Staying on branch '%s'."
+msgstr "Permanecendo 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 ""
+"Você não está mais em um ramo local\n"
+"\n"
+"Se você deseja um ramo, crie um agora a partir deste checkout."
+
+#: lib/checkout_op.tcl:503 lib/checkout_op.tcl:507
+#, tcl-format
+msgid "Checked out '%s'."
+msgstr "Checkout de \"%s\" concluído."
+
+#: lib/checkout_op.tcl:535
+#, tcl-format
+msgid "Resetting '%s' to '%s' will lose the following commits:"
+msgstr "Redefinir \"%s\" para \"%s\" provocará a perda das seguintes revisões:"
+
+#: lib/checkout_op.tcl:557
+msgid "Recovering lost commits may not be easy."
+msgstr "Recuperar revisões perdidas pode não ser fácil."
+
+#: lib/checkout_op.tcl:562
+#, tcl-format
+msgid "Reset '%s'?"
+msgstr "Redefinir \"%s\"?"
+
+#: lib/checkout_op.tcl:567 lib/merge.tcl:164 lib/tools_dlg.tcl:343
+msgid "Visualize"
+msgstr "Visualizar"
+
+#: 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 ""
+"Erro ao definir o ramo atual.\n"
+"\n"
+"Este diretório de trabalho está incompleto. Foi possível atualizar seus "
+"arquivos, mas houve uma falha ao atualizar os arquivos internos do Git.\n"
+"\n"
+"Isto não deveria ter acontecido, %s terminará agora."
+
+#: lib/choose_font.tcl:39
+msgid "Select"
+msgstr "Selecionar"
+
+#: lib/choose_font.tcl:53
+msgid "Font Family"
+msgstr "Tipo da fonte"
+
+#: lib/choose_font.tcl:74
+msgid "Font Size"
+msgstr "Tamanho da fonte"
+
+#: lib/choose_font.tcl:91
+msgid "Font Example"
+msgstr "Exemplo"
+
+#: lib/choose_font.tcl:103
+msgid ""
+"This is example text.\n"
+"If you like this text, it can be your font."
+msgstr ""
+"Este é um texto de exemplo.\n"
+"Se você gostar deste texto, esta pode ser sua fonte."
+
+#: lib/choose_repository.tcl:28
+msgid "Git Gui"
+msgstr "Git Gui"
+
+#: lib/choose_repository.tcl:87 lib/choose_repository.tcl:386
+msgid "Create New Repository"
+msgstr "Criar novo repositório"
+
+#: lib/choose_repository.tcl:93
+msgid "New..."
+msgstr "Novo..."
+
+#: lib/choose_repository.tcl:100 lib/choose_repository.tcl:471
+msgid "Clone Existing Repository"
+msgstr "Clonar repositório existente"
+
+#: lib/choose_repository.tcl:106
+msgid "Clone..."
+msgstr "Clonar..."
+
+#: lib/choose_repository.tcl:113 lib/choose_repository.tcl:1016
+msgid "Open Existing Repository"
+msgstr "Abrir repositório existente"
+
+#: lib/choose_repository.tcl:119
+msgid "Open..."
+msgstr "Abrir..."
+
+#: lib/choose_repository.tcl:132
+msgid "Recent Repositories"
+msgstr "Repositórios recentes"
+
+#: lib/choose_repository.tcl:138
+msgid "Open Recent Repository:"
+msgstr "Abrir repositório recente:"
+
+#: lib/choose_repository.tcl:306 lib/choose_repository.tcl:313
+#: lib/choose_repository.tcl:320
+#, tcl-format
+msgid "Failed to create repository %s:"
+msgstr "Erro ao criar repositório %s:"
+
+#: lib/choose_repository.tcl:391
+msgid "Directory:"
+msgstr "Diretório:"
+
+#: lib/choose_repository.tcl:423 lib/choose_repository.tcl:550
+#: lib/choose_repository.tcl:1052
+msgid "Git Repository"
+msgstr "Repositório Git"
+
+#: lib/choose_repository.tcl:448
+#, tcl-format
+msgid "Directory %s already exists."
+msgstr "O diretório %s já existe."
+
+#: lib/choose_repository.tcl:452
+#, tcl-format
+msgid "File %s already exists."
+msgstr "O arquivo %s já existe."
+
+#: lib/choose_repository.tcl:466
+msgid "Clone"
+msgstr "Clonar"
+
+#: lib/choose_repository.tcl:479
+msgid "Source Location:"
+msgstr "Origem:"
+
+#: lib/choose_repository.tcl:490
+msgid "Target Directory:"
+msgstr "Diretório de destino:"
+
+#: lib/choose_repository.tcl:502
+msgid "Clone Type:"
+msgstr "Tipo de clonagem:"
+
+#: lib/choose_repository.tcl:508
+msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
+msgstr "Padrão (rápida, semi-redundante, com hardlinks)"
+
+#: lib/choose_repository.tcl:514
+msgid "Full Copy (Slower, Redundant Backup)"
+msgstr "Cópia completa (mais lenta, backup redundante)"
+
+#: lib/choose_repository.tcl:520
+msgid "Shared (Fastest, Not Recommended, No Backup)"
+msgstr "Compartilhada (A mais rápida, não recomendada, sem backup)"
+
+#: lib/choose_repository.tcl:556 lib/choose_repository.tcl:603
+#: lib/choose_repository.tcl:749 lib/choose_repository.tcl:819
+#: lib/choose_repository.tcl:1058 lib/choose_repository.tcl:1066
+#, tcl-format
+msgid "Not a Git repository: %s"
+msgstr "Este não é um repositório do Git: %s"
+
+#: lib/choose_repository.tcl:592
+msgid "Standard only available for local repository."
+msgstr "Clonagens padrões só são possíveis em repositórios locais."
+
+#: lib/choose_repository.tcl:596
+msgid "Shared only available for local repository."
+msgstr "Clonagens parciais só são possíveis em repositórios locais."
+
+#: lib/choose_repository.tcl:617
+#, tcl-format
+msgid "Location %s already exists."
+msgstr "O local %s já existe."
+
+#: lib/choose_repository.tcl:628
+msgid "Failed to configure origin"
+msgstr "Erro ao configurar origem"
+
+#: lib/choose_repository.tcl:640
+msgid "Counting objects"
+msgstr "Contando objetos"
+
+#: lib/choose_repository.tcl:641
+msgid "buckets"
+msgstr "buckets"
+
+#: lib/choose_repository.tcl:665
+#, tcl-format
+msgid "Unable to copy objects/info/alternates: %s"
+msgstr "Erro ao copiar objetos ou informações adicionais: %s"
+
+#: lib/choose_repository.tcl:701
+#, tcl-format
+msgid "Nothing to clone from %s."
+msgstr "Não há nada para clonar em %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 "O ramo \"master\" não foi inicializado."
+
+#: lib/choose_repository.tcl:716
+msgid "Hardlinks are unavailable.  Falling back to copying."
+msgstr "Não foi possível criar hardlinks, usando cópias convencionais."
+
+#: lib/choose_repository.tcl:728
+#, tcl-format
+msgid "Cloning from %s"
+msgstr "Clonando de %s"
+
+#: lib/choose_repository.tcl:759
+msgid "Copying objects"
+msgstr "Copiando objetos"
+
+#: lib/choose_repository.tcl:760
+msgid "KiB"
+msgstr "KiB"
+
+#: lib/choose_repository.tcl:784
+#, tcl-format
+msgid "Unable to copy object: %s"
+msgstr "Não foi possível copiar o objeto: %s"
+
+#: lib/choose_repository.tcl:794
+msgid "Linking objects"
+msgstr "Ligando objetos"
+
+#: lib/choose_repository.tcl:795
+msgid "objects"
+msgstr "objetos"
+
+#: lib/choose_repository.tcl:803
+#, tcl-format
+msgid "Unable to hardlink object: %s"
+msgstr "Não foi possível ligar o objeto: %s"
+
+#: lib/choose_repository.tcl:858
+msgid "Cannot fetch branches and objects.  See console output for details."
+msgstr ""
+"Não foi possível receber ramos ou objetos. Veja a saída do console para "
+"detalhes."
+
+#: lib/choose_repository.tcl:869
+msgid "Cannot fetch tags.  See console output for details."
+msgstr ""
+"Não foi possível receber as etiquetas. Veja a saída do console para detalhes."
+
+#: lib/choose_repository.tcl:893
+msgid "Cannot determine HEAD.  See console output for details."
+msgstr ""
+"Não foi possível determinar a etiqueta HEAD. Veja a saída do console para "
+"detalhes."
+
+#: lib/choose_repository.tcl:902
+#, tcl-format
+msgid "Unable to cleanup %s"
+msgstr "Não foi possível limpar %s"
+
+#: lib/choose_repository.tcl:908
+msgid "Clone failed."
+msgstr "A clonagem falhou."
+
+#: lib/choose_repository.tcl:915
+msgid "No default branch obtained."
+msgstr "O ramo padrão não foi recebido."
+
+#: lib/choose_repository.tcl:926
+#, tcl-format
+msgid "Cannot resolve %s as a commit."
+msgstr "Não foi possível resolver %s como uma revisão."
+
+#: lib/choose_repository.tcl:938
+msgid "Creating working directory"
+msgstr "Criando diretório de trabalho."
+
+#: lib/choose_repository.tcl:939 lib/index.tcl:67 lib/index.tcl:130
+#: lib/index.tcl:198
+msgid "files"
+msgstr "arquivos"
+
+#: lib/choose_repository.tcl:968
+msgid "Initial file checkout failed."
+msgstr "Erro ao efetuar checkout inicial."
+
+#: lib/choose_repository.tcl:1011
+msgid "Open"
+msgstr "Abrir"
+
+#: lib/choose_repository.tcl:1021
+msgid "Repository:"
+msgstr "Repositório:"
+
+#: lib/choose_repository.tcl:1072
+#, tcl-format
+msgid "Failed to open repository %s:"
+msgstr "Erro ao abrir o repositório %s:"
+
+#: lib/choose_rev.tcl:53
+msgid "This Detached Checkout"
+msgstr "Este checkout"
+
+#: lib/choose_rev.tcl:60
+msgid "Revision Expression:"
+msgstr "Expressão de revisão:"
+
+#: lib/choose_rev.tcl:74
+msgid "Local Branch"
+msgstr "Ramo local"
+
+#: lib/choose_rev.tcl:79
+msgid "Tracking Branch"
+msgstr "Ramo de rastreamento"
+
+#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:538
+msgid "Tag"
+msgstr "Etiqueta"
+
+#: lib/choose_rev.tcl:317
+#, tcl-format
+msgid "Invalid revision: %s"
+msgstr "Revisão inválida: %s"
+
+#: lib/choose_rev.tcl:338
+msgid "No revision selected."
+msgstr "Nenhuma revisão selecionada."
+
+#: lib/choose_rev.tcl:346
+msgid "Revision expression is empty."
+msgstr "A expressão de revisão está vazia."
+
+#: lib/choose_rev.tcl:531
+msgid "Updated"
+msgstr "Atualizado"
+
+#: lib/choose_rev.tcl:559
+msgid "URL"
+msgstr "URL"
+
+#: 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 corrigir.\n"
+"\n"
+"Você está prestes a criar uma revisão inicial. Não há revisão anterior para "
+"corrigir.\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 corrigir durante uma mesclagem.\n"
+"\n"
+"Você está em meio a uma operação de mesclagem que não foi completada. Não é "
+"possível corrigir a revisão anterior a menos que você aborte a mescla atual "
+"antes.\n"
+
+#: lib/commit.tcl:48
+msgid "Error loading commit data for amend:"
+msgstr "Erro ao carregar dados da revisão para corrigir:"
+
+#: lib/commit.tcl:75
+msgid "Unable to obtain your identity:"
+msgstr "Não foi possível obter a sua identidade:"
+
+#: lib/commit.tcl:80
+msgid "Invalid GIT_COMMITTER_IDENT:"
+msgstr "Variável \"GIT_COMMITTER_IDENT\" inválida:"
+
+#: lib/commit.tcl:129
+#, tcl-format
+msgid "warning: Tcl does not support encoding '%s'."
+msgstr "aviso: O 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 lido não confere com o estado atual.\n"
+"\n"
+"Outro programa do Git modificou o repositório desde a última leitura. Uma "
+"atualização deve ser executada antes de criar outra revisão.\n"
+"\n"
+"A atualização começará automaticamente agora.\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ão é possível salvar revisões para arquivos não mesclados.\n"
+"\n"
+"O arquivo %s possui conflitos de mesclagem. Você deve resolvê-los e marcar o "
+"arquivo antes de salvar a revisão.\n"
+
+#: lib/commit.tcl:180
+#, tcl-format
+msgid ""
+"Unknown file state %s detected.\n"
+"\n"
+"File %s cannot be committed by this program.\n"
+msgstr ""
+"Estado desconhecido detectado para o arquivo %s.\n"
+"\n"
+"Este programa não pode salvar uma revisão para o arquivo %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ão há mudanças para salvar.\n"
+"\n"
+"Você deve marcar ao menos um arquivo antes de salvar a revisão.\n"
+
+#: lib/commit.tcl:203
+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 ""
+"Por favor, indique uma descrição para a revisão.\n"
+"\n"
+"Uma boa descrição tem o seguinte formato:\n"
+"\n"
+"- Primeira linha: descreve, em uma única frase, o que você fez.\n"
+"- Segunda linha: em branco.\n"
+"- Demais linhas: Descreve detalhadamente a revisão.\n"
+
+#: lib/commit.tcl:234
+msgid "Calling pre-commit hook..."
+msgstr "Executando script \"pre-commit\"..."
+
+#: lib/commit.tcl:249
+msgid "Commit declined by pre-commit hook."
+msgstr "A revisão foi bloqueada pelo script \"pre-commit\"."
+
+#: lib/commit.tcl:272
+msgid "Calling commit-msg hook..."
+msgstr "Executando script \"commit-msg\"..."
+
+#: lib/commit.tcl:287
+msgid "Commit declined by commit-msg hook."
+msgstr "Revisão bloqueada pelo script \"commit-msg\"."
+
+#: lib/commit.tcl:300
+msgid "Committing changes..."
+msgstr "Salvando revisão..."
+
+#: lib/commit.tcl:316
+msgid "write-tree failed:"
+msgstr "write-tree falhou:"
+
+#: lib/commit.tcl:317 lib/commit.tcl:361 lib/commit.tcl:382
+msgid "Commit failed."
+msgstr "A revisão falhou."
+
+#: lib/commit.tcl:334
+#, tcl-format
+msgid "Commit %s appears to be corrupt"
+msgstr "A revisão %s parece estar corrompida."
+
+#: lib/commit.tcl:339
+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 salvar.\n"
+"\n"
+"Nenhum arquivo foi modificado e esta não é uma revisão de mesclagem.\n"
+"\n"
+"Uma atualização será executada automaticamente agora.\n"
+
+#: lib/commit.tcl:346
+msgid "No changes to commit."
+msgstr "Não há alterações para salvar."
+
+#: lib/commit.tcl:360
+msgid "commit-tree failed:"
+msgstr "commit-tree falhou:"
+
+#: lib/commit.tcl:381
+msgid "update-ref failed:"
+msgstr "update-ref falhou:"
+
+#: lib/commit.tcl:469
+#, tcl-format
+msgid "Created commit %s: %s"
+msgstr "Revisão %s criada: %s"
+
+#: lib/console.tcl:59
+msgid "Working... please wait..."
+msgstr "Trabalhando... aguarde..."
+
+#: lib/console.tcl:186
+msgid "Success"
+msgstr "Sucesso"
+
+#: lib/console.tcl:200
+msgid "Error: Command Failed"
+msgstr "Erro: o comando falhou"
+
+#: lib/database.tcl:43
+msgid "Number of loose objects"
+msgstr "Número de objetos soltos"
+
+#: lib/database.tcl:44
+msgid "Disk space used by loose objects"
+msgstr "Espaço ocupado pelos objetos soltos"
+
+#: lib/database.tcl:45
+msgid "Number of packed objects"
+msgstr "Número de objetos compactados"
+
+#: lib/database.tcl:46
+msgid "Number of packs"
+msgstr "Número de pacotes"
+
+#: lib/database.tcl:47
+msgid "Disk space used by packed objects"
+msgstr "Espaço ocupado pelos objetos compactados"
+
+#: lib/database.tcl:48
+msgid "Packed objects waiting for pruning"
+msgstr "Objetos compactados aguardando eliminação"
+
+#: lib/database.tcl:49
+msgid "Garbage files"
+msgstr "Arquivos de lixo"
+
+#: lib/database.tcl:72
+msgid "Compressing the object database"
+msgstr "Compactando banco de dados de objetos"
+
+#: lib/database.tcl:83
+msgid "Verifying the object database with fsck-objects"
+msgstr "Verificando banco 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 possui aproximadamente %i objetos soltos.\n"
+"\n"
+"Para manter o desempenho ótimo é altamente recomendado que você compacte o "
+"banco de dados.\n"
+"\n"
+"Compactar o banco de dados agora?"
+
+#: lib/date.tcl:25
+#, tcl-format
+msgid "Invalid date from Git: %s"
+msgstr "Data inválida recebida do Git: %s"
+
+#: lib/diff.tcl:64
+#, 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 ""
+"Nenhuma diferença foi detectada.\n"
+"\n"
+"%s não possui mudanças.\n"
+"\n"
+"A data de modificação deste arquivo foi atualizada por outro aplicativo, mas "
+"o conteúdo do arquivo não foi alterado.\n"
+"\n"
+"Uma atualização ser executada para encontrar outros arquivos que possam ter "
+"o mesmo estado."
+
+#: lib/diff.tcl:104
+#, tcl-format
+msgid "Loading diff of %s..."
+msgstr "Carregando diferenças de %s..."
+
+#: lib/diff.tcl:125
+msgid ""
+"LOCAL: deleted\n"
+"REMOTE:\n"
+msgstr ""
+"Local: apagado\n"
+"Remoto:\n"
+
+#: lib/diff.tcl:130
+msgid ""
+"REMOTE: deleted\n"
+"LOCAL:\n"
+msgstr ""
+"Remoto: apagado\n"
+"Local:\n"
+
+#: lib/diff.tcl:137
+msgid "LOCAL:\n"
+msgstr "Local:\n"
+
+#: lib/diff.tcl:140
+msgid "REMOTE:\n"
+msgstr "Remoto:\n"
+
+#: lib/diff.tcl:202 lib/diff.tcl:319
+#, tcl-format
+msgid "Unable to display %s"
+msgstr "Impossível exibir %s"
+
+#: lib/diff.tcl:203
+msgid "Error loading file:"
+msgstr "Erro ao carregar o arquivo:"
+
+#: lib/diff.tcl:210
+msgid "Git Repository (subproject)"
+msgstr "Repositório Git (sub-projeto)"
+
+#: lib/diff.tcl:222
+msgid "* Binary file (not showing content)."
+msgstr "* Arquivo binário (conteúdo não exibido)."
+
+#: lib/diff.tcl:227
+#, tcl-format
+msgid ""
+"* Untracked file is %d bytes.\n"
+"* Showing only first %d bytes.\n"
+msgstr ""
+"* O arquivo não rastreado possui %d bytes.\n"
+"* Exibindo apenas os primeiros %d bytes.\n"
+
+#: lib/diff.tcl:233
+#, tcl-format
+msgid ""
+"\n"
+"* Untracked file clipped here by %s.\n"
+"* To see the entire file, use an external editor.\n"
+msgstr ""
+"\n"
+"* O arquivo não rastreado foi cortado aqui por %s.\n"
+"* Para ver o arquivo completo, use um editor externo.\n"
+
+#: lib/diff.tcl:482
+msgid "Failed to unstage selected hunk."
+msgstr "Erro ao desmarcar o trecho selecionado."
+
+#: lib/diff.tcl:489
+msgid "Failed to stage selected hunk."
+msgstr "Erro ao marcar o trecho selecionado."
+
+#: lib/diff.tcl:568
+msgid "Failed to unstage selected line."
+msgstr "Erro ao desmarcar a linha selecionada."
+
+#: lib/diff.tcl:576
+msgid "Failed to stage selected line."
+msgstr "Erro ao marcar a linha selecionada."
+
+#: lib/encoding.tcl:443
+msgid "Default"
+msgstr "Padrã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/error.tcl:20 lib/error.tcl:114
+msgid "error"
+msgstr "Erro"
+
+#: lib/error.tcl:36
+msgid "warning"
+msgstr "aviso"
+
+#: lib/error.tcl:94
+msgid "You must correct the above errors before committing."
+msgstr "Você precisa corrigir os erros acima antes de salvar a revisão."
+
+#: lib/index.tcl:6
+msgid "Unable to unlock the index."
+msgstr "Impossível desbloquear o índice."
+
+#: lib/index.tcl:15
+msgid "Index Error"
+msgstr "Erro no índice"
+
+#: lib/index.tcl:17
+msgid ""
+"Updating the Git index failed.  A rescan will be automatically started to "
+"resynchronize git-gui."
+msgstr ""
+"A atualização do índice do Git falhou. Uma atualização será executada "
+"automaticamente para ressincronizar o Git GUI"
+
+#: lib/index.tcl:28
+msgid "Continue"
+msgstr "Continuar"
+
+#: lib/index.tcl:31
+msgid "Unlock Index"
+msgstr "Desbloquear índice"
+
+#: lib/index.tcl:289
+#, tcl-format
+msgid "Unstaging %s from commit"
+msgstr "Desmarcando %s para revisão"
+
+#: lib/index.tcl:328
+msgid "Ready to commit."
+msgstr "Pronto para salvar a revisão."
+
+#: lib/index.tcl:341
+#, tcl-format
+msgid "Adding %s"
+msgstr "Adicionando %s"
+
+#: lib/index.tcl:398
+#, tcl-format
+msgid "Revert changes in file %s?"
+msgstr "Reverter as alterações no arquivo %s?"
+
+#: lib/index.tcl:400
+#, tcl-format
+msgid "Revert changes in these %i files?"
+msgstr "Reverter as alterações nestes %i arquivos?"
+
+#: lib/index.tcl:408
+msgid "Any unstaged changes will be permanently lost by the revert."
+msgstr ""
+"Qualquer alteração não marcada será permanentemente perdida na reversão."
+
+#: lib/index.tcl:411
+msgid "Do Nothing"
+msgstr "Não fazer nada"
+
+#: lib/index.tcl:429
+msgid "Reverting selected files"
+msgstr "Revertendo os arquivos selecionados"
+
+#: lib/index.tcl:433
+#, tcl-format
+msgid "Reverting %s"
+msgstr "Revertendo %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ão é possível mesclar durante uma correção.\n"
+"\n"
+"Você deve concluir a correção antes de começar qualquer mesclagem.\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 lido não confere com o estado atual.\n"
+"\n"
+"Outro programa do Git modificou o repositório desde a última leitura. Uma "
+"atualização deve ser executada antes de efetuar uma mesclagem.\n"
+"\n"
+"A atualização começará automaticamente agora.\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 ""
+"Há uma mesclagem com conflitos em progresso.\n"
+"\n"
+"O arquivo %s possui conflitos de mesclagem.\n"
+"\n"
+"Você deve resolvê-los, marcar o arquivo e salvar a revisão para completar a "
+"mesclagem atual. Só então você poderá começar outra.\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 ""
+"Você está em meio a uma mudança.\n"
+"\n"
+"O arquivo %s foi modificado.\n"
+"\n"
+"Você deve completar e salvar a revisão atual antes de começar uma mesclagem. "
+"Ao fazê-lo, você poderá abortar a mesclagem caso haja algum erro.\n"
+
+#: lib/merge.tcl:107
+#, tcl-format
+msgid "%s of %s"
+msgstr "%s de %s"
+
+#: lib/merge.tcl:120
+#, tcl-format
+msgid "Merging %s and %s..."
+msgstr "Mesclando %s e %s..."
+
+#: lib/merge.tcl:131
+msgid "Merge completed successfully."
+msgstr "Mesclagem completada com sucesso."
+
+#: lib/merge.tcl:133
+msgid "Merge failed.  Conflict resolution is required."
+msgstr "A mesclagem falhou. É necessário resolver conflitos."
+
+#: lib/merge.tcl:158
+#, tcl-format
+msgid "Merge Into %s"
+msgstr "Mesclar em %s"
+
+#: lib/merge.tcl:177
+msgid "Revision To Merge"
+msgstr "Revisão para mesclar"
+
+#: lib/merge.tcl:212
+msgid ""
+"Cannot abort while amending.\n"
+"\n"
+"You must finish amending this commit.\n"
+msgstr ""
+"Não é possível abortar durante uma correção.\n"
+"\n"
+"Você precisa finalizar a correção desta revisão.\n"
+
+#: lib/merge.tcl:222
+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 mesclagem?\n"
+"\n"
+"Abortar a mesclagem atual implicará na perda de *TODAS* as mudanças não "
+"salvas.\n"
+"\n"
+"Abortar a mesclagem atual?"
+
+#: lib/merge.tcl:228
+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 ""
+"Descartar as mudanças?\n"
+"\n"
+"Ao fazê-lo, *TODAS* as alterações não salvas serão perdidas.\n"
+"\n"
+"Continuar e descartar as mudanças atuais?"
+
+#: lib/merge.tcl:239
+msgid "Aborting"
+msgstr "Abortando"
+
+#: lib/merge.tcl:239
+msgid "files reset"
+msgstr "arquivos redefindos"
+
+#: lib/merge.tcl:267
+msgid "Abort failed."
+msgstr "A tentativa de abortar a operação falhou"
+
+#: lib/merge.tcl:269
+msgid "Abort completed.  Ready."
+msgstr "Operação abortada com sucesso. Pronto."
+
+#: lib/mergetool.tcl:8
+msgid "Force resolution to the base version?"
+msgstr "Forçar a 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 o diff mostra apenas as mudanças conflitantes.\n"
+"\n"
+"%s será sobrescrito.\n"
+"\n"
+"Caso necessário, será preciso reiniciar a mesclagem para desfazer esta "
+"operação."
+
+#: lib/mergetool.tcl:45
+#, tcl-format
+msgid "File %s seems to have unresolved conflicts, still stage?"
+msgstr "O arquivo %s parece ter conflitos não resolvidos. Marcar mesmo assim?"
+
+#: lib/mergetool.tcl:60
+#, tcl-format
+msgid "Adding resolution for %s"
+msgstr "Adicionando resolução para %s"
+
+#: lib/mergetool.tcl:141
+msgid "Cannot resolve deletion or link conflicts using a tool"
+msgstr ""
+"Impossível resolver conflitos envolvendo exclusão ou links de arquivos com "
+"esta ferramenta."
+
+#: lib/mergetool.tcl:146
+msgid "Conflict file does not exist"
+msgstr "O arquivo conflitante não existe"
+
+#: lib/mergetool.tcl:264
+#, tcl-format
+msgid "Not a GUI merge tool: '%s'"
+msgstr "Não é uma ferramenta de mesclagem gráfica: \"%s\""
+
+#: lib/mergetool.tcl:268
+#, tcl-format
+msgid "Unsupported merge tool '%s'"
+msgstr "Ferramenta de mesclagem não suportada \"%s\""
+
+#: lib/mergetool.tcl:303
+msgid "Merge tool is already running, terminate it?"
+msgstr "A ferramenta de mesclagem já está em execução. Finalizar?"
+
+#: lib/mergetool.tcl:323
+#, tcl-format
+msgid ""
+"Error retrieving versions:\n"
+"%s"
+msgstr ""
+"Erro ao obter as versões:\n"
+"%s"
+
+#: lib/mergetool.tcl:343
+#, tcl-format
+msgid ""
+"Could not start the merge tool:\n"
+"\n"
+"%s"
+msgstr ""
+"Não foi possível iniciar a ferramenta de mesclagem:\n"
+"\n"
+"%s"
+
+#: lib/mergetool.tcl:347
+msgid "Running merge tool..."
+msgstr "Executando ferramenta de mesclagem..."
+
+#: lib/mergetool.tcl:375 lib/mergetool.tcl:383
+msgid "Merge tool failed."
+msgstr "Ferramenta de mesclagem falhou."
+
+#: lib/option.tcl:11
+#, tcl-format
+msgid "Invalid global encoding '%s'"
+msgstr "Codificação global inválida \"%s\""
+
+#: lib/option.tcl:19
+#, tcl-format
+msgid "Invalid repo encoding '%s'"
+msgstr "Codificação do repositório inválida \"%s\""
+
+#: lib/option.tcl:117
+msgid "Restore Defaults"
+msgstr "Restaurar padrões"
+
+#: lib/option.tcl:121
+msgid "Save"
+msgstr "Salvar"
+
+#: lib/option.tcl:131
+#, tcl-format
+msgid "%s Repository"
+msgstr "Repositório %s"
+
+#: lib/option.tcl:132
+msgid "Global (All Repositories)"
+msgstr "Global (todos os repositórios)"
+
+#: lib/option.tcl:138
+msgid "User Name"
+msgstr "Nome do usuário"
+
+#: lib/option.tcl:139
+msgid "Email Address"
+msgstr "Endereço de e-mail"
+
+#: lib/option.tcl:141
+msgid "Summarize Merge Commits"
+msgstr "Exibir sumário das revisões de mesclagem"
+
+#: lib/option.tcl:142
+msgid "Merge Verbosity"
+msgstr "Nível de detalhamento da mesclagem"
+
+#: lib/option.tcl:143
+msgid "Show Diffstat After Merge"
+msgstr "Exibir estatísticas após mesclagens"
+
+#: lib/option.tcl:144
+msgid "Use Merge Tool"
+msgstr "Usar ferramenta de mesclagem"
+
+#: lib/option.tcl:146
+msgid "Trust File Modification Timestamps"
+msgstr "Confiar nas datas de modificação dos arquivos"
+
+#: lib/option.tcl:147
+msgid "Prune Tracking Branches During Fetch"
+msgstr "Eliminar ramos de rastreamento ao receber"
+
+#: lib/option.tcl:148
+msgid "Match Tracking Branches"
+msgstr "Coincidir ramos de rastreamento"
+
+#: lib/option.tcl:149
+msgid "Blame Copy Only On Changed Files"
+msgstr "Detectar cópias somente em arquivos modificados"
+
+#: lib/option.tcl:150
+msgid "Minimum Letters To Blame Copy On"
+msgstr "Número mínimo de letras para detectar cópias"
+
+#: lib/option.tcl:151
+msgid "Blame History Context Radius (days)"
+msgstr "Extensão do contexto de detecção (em dias)"
+
+#: lib/option.tcl:152
+msgid "Number of Diff Context Lines"
+msgstr "Número de linhas para o diff contextual"
+
+#: lib/option.tcl:153
+msgid "Commit Message Text Width"
+msgstr "Largura do texto da descrição da revisão"
+
+#: lib/option.tcl:154
+msgid "New Branch Name Template"
+msgstr "Modelo de nome para novos ramos"
+
+#: lib/option.tcl:155
+msgid "Default File Contents Encoding"
+msgstr "Codificação padrão dos arquivos"
+
+#: lib/option.tcl:203
+msgid "Change"
+msgstr "Alterar"
+
+#: lib/option.tcl:230
+msgid "Spelling Dictionary:"
+msgstr "Dicionário para o verificador ortográfico:"
+
+#: lib/option.tcl:254
+msgid "Change Font"
+msgstr "Mudar fonte"
+
+#: lib/option.tcl:258
+#, tcl-format
+msgid "Choose %s"
+msgstr "Escolher %s"
+
+#: lib/option.tcl:264
+msgid "pt."
+msgstr "pt."
+
+#: lib/option.tcl:278
+msgid "Preferences"
+msgstr "Preferências"
+
+#: lib/option.tcl:314
+msgid "Failed to completely save options:"
+msgstr "Houve um erro ao salvar as opções:"
+
+#: lib/remote.tcl:163
+msgid "Remove Remote"
+msgstr "Excluir"
+
+#: lib/remote.tcl:168
+msgid "Prune from"
+msgstr "Limpar de"
+
+#: lib/remote.tcl:173
+msgid "Fetch from"
+msgstr "Receber de"
+
+#: lib/remote.tcl:215
+msgid "Push to"
+msgstr "Enviar para"
+
+#: lib/remote_add.tcl:19
+msgid "Add Remote"
+msgstr "Adicionar repositório remoto"
+
+#: lib/remote_add.tcl:24
+msgid "Add New Remote"
+msgstr "Adicionar novo repositório remoto"
+
+#: lib/remote_add.tcl:28 lib/tools_dlg.tcl:36
+msgid "Add"
+msgstr "Adicionar"
+
+#: lib/remote_add.tcl:37
+msgid "Remote Details"
+msgstr "Detalhes do repositório remoto"
+
+#: lib/remote_add.tcl:50
+msgid "Location:"
+msgstr "Local:"
+
+#: lib/remote_add.tcl:62
+msgid "Further Action"
+msgstr "Ações adicionais"
+
+#: lib/remote_add.tcl:65
+msgid "Fetch Immediately"
+msgstr "Receber imediatamente"
+
+#: lib/remote_add.tcl:71
+msgid "Initialize Remote Repository and Push"
+msgstr "Inicializar repositório remoto e enviar"
+
+#: lib/remote_add.tcl:77
+msgid "Do Nothing Else Now"
+msgstr "Não fazer nada agora"
+
+#: lib/remote_add.tcl:101
+msgid "Please supply a remote name."
+msgstr "Por favor, indique um nome para o repositório remoto."
+
+#: lib/remote_add.tcl:114
+#, tcl-format
+msgid "'%s' is not an acceptable remote name."
+msgstr "\"%s\" não é um nome válido para um repositório remoto."
+
+#: lib/remote_add.tcl:125
+#, tcl-format
+msgid "Failed to add remote '%s' of location '%s'."
+msgstr "Erro ao adicionar repositório remoto \"%s\" do local \"%s\":"
+
+#: lib/remote_add.tcl:133 lib/transport.tcl:6
+#, tcl-format
+msgid "fetch %s"
+msgstr "receber %s"
+
+#: lib/remote_add.tcl:134
+#, tcl-format
+msgid "Fetching the %s"
+msgstr "Recebendo o %s"
+
+#: lib/remote_add.tcl:157
+#, tcl-format
+msgid "Do not know how to initialize repository at location '%s'."
+msgstr "Não sabe como inicializar o repositório remoto em \"%s\"."
+
+#: lib/remote_add.tcl:163 lib/transport.tcl:25 lib/transport.tcl:63
+#: lib/transport.tcl:81
+#, tcl-format
+msgid "push %s"
+msgstr "enviar %s"
+
+#: lib/remote_add.tcl:164
+#, tcl-format
+msgid "Setting up the %s (at %s)"
+msgstr "Configurando %s (em %s)"
+
+#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
+msgid "Delete Branch Remotely"
+msgstr "Apagar ramo remoto"
+
+#: lib/remote_branch_delete.tcl:47
+msgid "From Repository"
+msgstr "Do repositório"
+
+#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:134
+msgid "Remote:"
+msgstr "Remoto:"
+
+#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:149
+msgid "Arbitrary Location:"
+msgstr "Outro local:"
+
+#: lib/remote_branch_delete.tcl:84
+msgid "Branches"
+msgstr "Ramos"
+
+#: lib/remote_branch_delete.tcl:109
+msgid "Delete Only If"
+msgstr "Apagar somente se"
+
+#: lib/remote_branch_delete.tcl:111
+msgid "Merged Into:"
+msgstr "Mesclado em:"
+
+#: lib/remote_branch_delete.tcl:152
+msgid "A branch is required for 'Merged Into'."
+msgstr "É preciso indicar um ramo para \"Mesclado em\"."
+
+#: lib/remote_branch_delete.tcl:184
+#, tcl-format
+msgid ""
+"The following branches are not completely merged into %s:\n"
+"\n"
+" - %s"
+msgstr ""
+"Os seguintes ramos não estão inteiramente mesclados em %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 ""
+"Um ou mais testes de mesclagem falharam porque você não possui as revisões "
+"necessárias. Tente receber revisões de %s primeiro."
+
+#: lib/remote_branch_delete.tcl:207
+msgid "Please select one or more branches to delete."
+msgstr "Por favor selecione um ou mais ramos para apagar."
+
+#: lib/remote_branch_delete.tcl:226
+#, tcl-format
+msgid "Deleting branches from %s"
+msgstr "Apagar ramos de %s"
+
+#: lib/remote_branch_delete.tcl:292
+msgid "No repository selected."
+msgstr "Nenhum repositório foi selecionado."
+
+#: lib/remote_branch_delete.tcl:297
+#, tcl-format
+msgid "Scanning %s..."
+msgstr "Atualizando %s..."
+
+#: lib/search.tcl:21
+msgid "Find:"
+msgstr "Encontrar:"
+
+#: lib/search.tcl:23
+msgid "Next"
+msgstr "Próximo"
+
+#: lib/search.tcl:24
+msgid "Prev"
+msgstr "Anterior"
+
+#: lib/search.tcl:25
+msgid "Case-Sensitive"
+msgstr "Sensível a maiúsculas/minúsculas"
+
+#: lib/shortcut.tcl:21 lib/shortcut.tcl:62
+msgid "Cannot write shortcut:"
+msgstr "Não foi possível gravar o atalho:"
+
+#: lib/shortcut.tcl:137
+msgid "Cannot write icon:"
+msgstr "Não foi possível gravar o ícone:"
+
+#: lib/spellcheck.tcl:57
+msgid "Unsupported spell checker"
+msgstr "Verificador ortográfico não suportado"
+
+#: lib/spellcheck.tcl:65
+msgid "Spell checking is unavailable"
+msgstr "Verificação ortográfica indisponível"
+
+#: lib/spellcheck.tcl:68
+msgid "Invalid spell checking configuration"
+msgstr "Configuração do verificador ortográfico inválida"
+
+#: lib/spellcheck.tcl:70
+#, tcl-format
+msgid "Reverting dictionary to %s."
+msgstr "Revertendo dicionário para %s."
+
+#: lib/spellcheck.tcl:73
+msgid "Spell checker silently failed on startup"
+msgstr "O verificador ortográfico falhou sem relatar nenhum erro"
+
+#: lib/spellcheck.tcl:80
+msgid "Unrecognized spell checker"
+msgstr "Verificador 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 "Final de arquivo inesperado recebido do verificador ortográfico"
+
+#: lib/spellcheck.tcl:392
+msgid "Spell Checker Failed"
+msgstr "A verificação ortográfica falhou"
+
+#: lib/sshkey.tcl:31
+msgid "No keys found."
+msgstr "Nenhuma 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:56
+msgid "Copy To Clipboard"
+msgstr "Copiar para a área de transferência"
+
+#: lib/sshkey.tcl:70
+msgid "Your OpenSSH Public Key"
+msgstr "Sua chave pública OpenSSH"
+
+#: lib/sshkey.tcl:78
+msgid "Generating..."
+msgstr "Gerando..."
+
+#: lib/sshkey.tcl:84
+#, tcl-format
+msgid ""
+"Could not start ssh-keygen:\n"
+"\n"
+"%s"
+msgstr ""
+"Impossível iniciar ssh-keygen:\n"
+"\n"
+"%s"
+
+#: lib/sshkey.tcl:111
+msgid "Generation failed."
+msgstr "A geração da chave falhou."
+
+#: lib/sshkey.tcl:118
+msgid "Generation succeded, but no keys found."
+msgstr "A geração da chave foi bem-sucedida, mas nenhuma chave foi encontrada."
+
+#: lib/sshkey.tcl:121
+#, tcl-format
+msgid "Your key is in: %s"
+msgstr "Sua chave em: %s"
+
+#: lib/status_bar.tcl:83
+#, tcl-format
+msgid "%s ... %*i of %*i %s (%3i%%)"
+msgstr "%s ... %*i de %*i %s (%3i%%)"
+
+#: lib/tools.tcl:75
+#, tcl-format
+msgid "Running %s requires a selected file."
+msgstr "É preciso selecionar um arquivo para executar %s."
+
+#: lib/tools.tcl:90
+#, tcl-format
+msgid "Are you sure you want to run %s?"
+msgstr "Você tem certeza que deseja executar %s?"
+
+#: lib/tools.tcl:110
+#, tcl-format
+msgid "Tool: %s"
+msgstr "Ferramenta: %s"
+
+#: lib/tools.tcl:111
+#, tcl-format
+msgid "Running: %s"
+msgstr "Executando: %s"
+
+#: lib/tools.tcl:149
+#, tcl-format
+msgid "Tool completed successfully: %s"
+msgstr "Execução completada com sucesso: %s"
+
+#: lib/tools.tcl:151
+#, tcl-format
+msgid "Tool failed: %s"
+msgstr "Ferramenta falhou: %s"
+
+#: 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:33
+msgid "Add globally"
+msgstr "Adicionar globalmente"
+
+#: lib/tools_dlg.tcl:45
+msgid "Tool Details"
+msgstr "Detalhes da ferramenta"
+
+#: lib/tools_dlg.tcl:48
+msgid "Use '/' separators to create a submenu tree:"
+msgstr "Use o separador \"/\" para criar uma árvore de sub-menus:"
+
+#: lib/tools_dlg.tcl:61
+msgid "Command:"
+msgstr "Comando:"
+
+#: lib/tools_dlg.tcl:74
+msgid "Show a dialog before running"
+msgstr "Exibir uma caixa de diálogo antes de executar"
+
+#: lib/tools_dlg.tcl:80
+msgid "Ask the user to select a revision (sets $REVISION)"
+msgstr "Solicitar a seleção de uma revisão (a variável $REVISION)"
+
+#: lib/tools_dlg.tcl:85
+msgid "Ask the user for additional arguments (sets $ARGS)"
+msgstr "Solicitar argumentos adicionais (define a variável $ARGS)"
+
+#: lib/tools_dlg.tcl:92
+msgid "Don't show the command output window"
+msgstr "Não exibir a janela de saída do comando"
+
+#: lib/tools_dlg.tcl:97
+msgid "Run only if a diff is selected ($FILENAME not empty)"
+msgstr "Executar apenas se houver um diff selecionado ($FILENAME não-vazio)"
+
+#: lib/tools_dlg.tcl:121
+msgid "Please supply a name for the tool."
+msgstr "Por favor, indique um nome para a ferramenta."
+
+#: lib/tools_dlg.tcl:129
+#, tcl-format
+msgid "Tool '%s' already exists."
+msgstr "A ferramenta \"%s\" já existe."
+
+#: lib/tools_dlg.tcl:151
+#, tcl-format
+msgid ""
+"Could not add tool:\n"
+"%s"
+msgstr ""
+"Não foi possível adicionar a ferramenta:\n"
+"%s"
+
+#: lib/tools_dlg.tcl:190
+msgid "Remove Tool"
+msgstr "Excluir ferramenta"
+
+#: lib/tools_dlg.tcl:196
+msgid "Remove Tool Commands"
+msgstr "Excluir comando de ferramenta"
+
+#: lib/tools_dlg.tcl:200
+msgid "Remove"
+msgstr "Excluir"
+
+#: lib/tools_dlg.tcl:236
+msgid "(Blue denotes repository-local tools)"
+msgstr "(Azul indica ferramentas do repositório local)"
+
+#: lib/tools_dlg.tcl:297
+#, tcl-format
+msgid "Run Command: %s"
+msgstr "Executar comando: %s"
+
+#: lib/tools_dlg.tcl:311
+msgid "Arguments"
+msgstr "Argumentos"
+
+#: lib/tools_dlg.tcl:348
+msgid "OK"
+msgstr "OK"
+
+#: lib/transport.tcl:7
+#, tcl-format
+msgid "Fetching new changes from %s"
+msgstr "Recebendo novas mudanças de %s"
+
+#: lib/transport.tcl:18
+#, tcl-format
+msgid "remote prune %s"
+msgstr "Limpar %s"
+
+#: lib/transport.tcl:19
+#, tcl-format
+msgid "Pruning tracking branches deleted from %s"
+msgstr "Limpando ramos excluídos de %s"
+
+#: lib/transport.tcl:26
+#, tcl-format
+msgid "Pushing changes to %s"
+msgstr "Enviando mudanças para %s"
+
+#: lib/transport.tcl:64
+#, tcl-format
+msgid "Mirroring to %s"
+msgstr "Duplicando para %s"
+
+#: lib/transport.tcl:82
+#, tcl-format
+msgid "Pushing %s %s to %s"
+msgstr "Enviando %s %s para %s"
+
+#: lib/transport.tcl:100
+msgid "Push Branches"
+msgstr "Enviar ramos"
+
+#: lib/transport.tcl:114
+msgid "Source Branches"
+msgstr "Ramos de origem"
+
+#: lib/transport.tcl:131
+msgid "Destination Repository"
+msgstr "Repositório de destino"
+
+#: lib/transport.tcl:169
+msgid "Transfer Options"
+msgstr "Opções de transferência"
+
+#: lib/transport.tcl:171
+msgid "Force overwrite existing branch (may discard changes)"
+msgstr "Sobrescrever ramos existentes (pode descartar mudanças)"
+
+#: lib/transport.tcl:175
+msgid "Use thin pack (for slow network connections)"
+msgstr "Usar compactação minimalista (para redes lentas)"
+
+#: lib/transport.tcl:179
+msgid "Include tags"
+msgstr "Incluir etiquetas"
index 364c074c504ce2150effdbf01927aa052107c1af..30f4b77dac08d9c69ea3d0009ec97d30b9349be8 100644 (file)
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: git-gui\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-12-08 08:31-0800\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 <raa.lkml@gmail.com>\n"
 "Language-Team: Russian Translation <git@vger.kernel.org>\n"
@@ -15,33 +15,33 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: git-gui.sh:41 git-gui.sh:737 git-gui.sh:751 git-gui.sh:764 git-gui.sh:847
-#: git-gui.sh:866
+#: git-gui.sh:41 git-gui.sh:793 git-gui.sh:807 git-gui.sh:820 git-gui.sh:903
+#: git-gui.sh:922
 msgid "git-gui: fatal error"
 msgstr "git-gui: критическая ошибка"
 
-#: git-gui.sh:689
+#: git-gui.sh:743
 #, tcl-format
 msgid "Invalid font specified in %s:"
 msgstr "В %s установлен неверный шрифт:"
 
-#: git-gui.sh:723
+#: git-gui.sh:779
 msgid "Main Font"
 msgstr "Шрифт интерфейса"
 
-#: git-gui.sh:724
+#: git-gui.sh:780
 msgid "Diff/Console Font"
 msgstr "Шрифт консоли и изменений (diff)"
 
-#: git-gui.sh:738
+#: git-gui.sh:794
 msgid "Cannot find git in PATH."
 msgstr "git не найден в PATH."
 
-#: git-gui.sh:765
+#: git-gui.sh:821
 msgid "Cannot parse Git version string:"
 msgstr "Невозможно распознать строку версии Git: "
 
-#: git-gui.sh:783
+#: git-gui.sh:839
 #, tcl-format
 msgid ""
 "Git version cannot be determined.\n"
@@ -60,450 +60,474 @@ msgstr ""
 "\n"
 "Принять '%s' как версию 1.5.0?\n"
 
-#: git-gui.sh:1062
+#: git-gui.sh:1128
 msgid "Git directory not found:"
 msgstr "Каталог Git не найден:"
 
-#: git-gui.sh:1069
+#: git-gui.sh:1146
 msgid "Cannot move to top of working directory:"
 msgstr "Невозможно перейти к корню рабочего каталога репозитория: "
 
-#: git-gui.sh:1076
-msgid "Cannot use funny .git directory:"
-msgstr "Ð\9aаÑ\82алог .git Ð¸Ñ\81поÑ\80Ñ\87ен: "
+#: git-gui.sh:1154
+msgid "Cannot use bare repository:"
+msgstr "Ð\9dевозможно Ð¸Ñ\81полÑ\8cзование Ñ\80епозиÑ\82оÑ\80иÑ\8f Ð±ÐµÐ· Ñ\80абоÑ\87его ÐºÐ°Ñ\82алога:"
 
-#: git-gui.sh:1081
+#: git-gui.sh:1162
 msgid "No working directory"
 msgstr "Отсутствует рабочий каталог"
 
-#: git-gui.sh:1247 lib/checkout_op.tcl:305
+#: git-gui.sh:1334 lib/checkout_op.tcl:306
 msgid "Refreshing file status..."
 msgstr "Обновление информации о состоянии файлов..."
 
-#: git-gui.sh:1303
+#: git-gui.sh:1390
 msgid "Scanning for modified files ..."
 msgstr "Поиск измененных файлов..."
 
-#: git-gui.sh:1367
+#: git-gui.sh:1454
 msgid "Calling prepare-commit-msg hook..."
 msgstr "Вызов программы поддержки репозитория prepare-commit-msg..."
 
-#: git-gui.sh:1384
+#: git-gui.sh:1471
 msgid "Commit declined by prepare-commit-msg hook."
 msgstr ""
 "Сохранение прервано программой поддержки репозитория prepare-commit-msg"
 
-#: git-gui.sh:1542 lib/browser.tcl:246
+#: git-gui.sh:1629 lib/browser.tcl:246
 msgid "Ready."
 msgstr "Готово."
 
-#: git-gui.sh:1726
+#: git-gui.sh:1787
 #, tcl-format
 msgid "Displaying only %s of %s files."
 msgstr "Показано %s из %s файлов."
 
-#: git-gui.sh:1819
+#: git-gui.sh:1913
 msgid "Unmodified"
 msgstr "Не изменено"
 
-#: git-gui.sh:1821
+#: git-gui.sh:1915
 msgid "Modified, not staged"
 msgstr "Изменено, не подготовлено"
 
-#: git-gui.sh:1822 git-gui.sh:1830
+#: git-gui.sh:1916 git-gui.sh:1924
 msgid "Staged for commit"
 msgstr "Подготовлено для сохранения"
 
-#: git-gui.sh:1823 git-gui.sh:1831
+#: git-gui.sh:1917 git-gui.sh:1925
 msgid "Portions staged for commit"
 msgstr "Части, подготовленные для сохранения"
 
-#: git-gui.sh:1824 git-gui.sh:1832
+#: git-gui.sh:1918 git-gui.sh:1926
 msgid "Staged for commit, missing"
 msgstr "Подготовлено для сохранения, отсутствует"
 
-#: git-gui.sh:1826
+#: git-gui.sh:1920
 msgid "File type changed, not staged"
 msgstr "Тип файла изменён, не подготовлено"
 
-#: git-gui.sh:1827
+#: git-gui.sh:1921
 msgid "File type changed, staged"
 msgstr "Тип файла изменён, подготовлено"
 
-#: git-gui.sh:1829
+#: git-gui.sh:1923
 msgid "Untracked, not staged"
 msgstr "Не отслеживается, не подготовлено"
 
-#: git-gui.sh:1834
+#: git-gui.sh:1928
 msgid "Missing"
 msgstr "Отсутствует"
 
-#: git-gui.sh:1835
+#: git-gui.sh:1929
 msgid "Staged for removal"
 msgstr "Подготовлено для удаления"
 
-#: git-gui.sh:1836
+#: git-gui.sh:1930
 msgid "Staged for removal, still present"
 msgstr "Подготовлено для удаления, еще не удалено"
 
-#: git-gui.sh:1838 git-gui.sh:1839 git-gui.sh:1840 git-gui.sh:1841
-#: git-gui.sh:1842 git-gui.sh:1843
+#: git-gui.sh:1932 git-gui.sh:1933 git-gui.sh:1934 git-gui.sh:1935
+#: git-gui.sh:1936 git-gui.sh:1937
 msgid "Requires merge resolution"
 msgstr "Требуется разрешение конфликта при слиянии"
 
-#: git-gui.sh:1878
+#: git-gui.sh:1972
 msgid "Starting gitk... please wait..."
 msgstr "Запускается gitk... Подождите, пожалуйста..."
 
-#: git-gui.sh:1887
+#: git-gui.sh:1984
 msgid "Couldn't find gitk in PATH"
 msgstr "gitk не найден в PATH."
 
-#: git-gui.sh:2280 lib/choose_repository.tcl:36
+#: git-gui.sh:2043
+msgid "Couldn't find git gui in PATH"
+msgstr "git gui не найден в PATH."
+
+#: git-gui.sh:2455 lib/choose_repository.tcl:36
 msgid "Repository"
 msgstr "Репозиторий"
 
-#: git-gui.sh:2281
+#: git-gui.sh:2456
 msgid "Edit"
 msgstr "Редактировать"
 
-#: git-gui.sh:2283 lib/choose_rev.tcl:561
+#: git-gui.sh:2458 lib/choose_rev.tcl:561
 msgid "Branch"
 msgstr "Ветвь"
 
-#: git-gui.sh:2286 lib/choose_rev.tcl:548
+#: git-gui.sh:2461 lib/choose_rev.tcl:548
 msgid "Commit@@noun"
 msgstr "Состояние"
 
-#: git-gui.sh:2289 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168
+#: git-gui.sh:2464 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168
 msgid "Merge"
 msgstr "Слияние"
 
-#: git-gui.sh:2290 lib/choose_rev.tcl:557
+#: git-gui.sh:2465 lib/choose_rev.tcl:557
 msgid "Remote"
 msgstr "Внешние репозитории"
 
-#: git-gui.sh:2293
+#: git-gui.sh:2468
 msgid "Tools"
 msgstr "Вспомогательные операции"
 
-#: git-gui.sh:2302
+#: git-gui.sh:2477
 msgid "Explore Working Copy"
 msgstr "Просмотр рабочего каталога"
 
-#: git-gui.sh:2307
+#: git-gui.sh:2483
 msgid "Browse Current Branch's Files"
 msgstr "Просмотреть файлы текущей ветви"
 
-#: git-gui.sh:2311
+#: git-gui.sh:2487
 msgid "Browse Branch Files..."
 msgstr "Показать файлы ветви..."
 
-#: git-gui.sh:2316
+#: git-gui.sh:2492
 msgid "Visualize Current Branch's History"
 msgstr "Показать историю текущей ветви"
 
-#: git-gui.sh:2320
+#: git-gui.sh:2496
 msgid "Visualize All Branch History"
 msgstr "Показать историю всех ветвей"
 
-#: git-gui.sh:2327
+#: git-gui.sh:2503
 #, tcl-format
 msgid "Browse %s's Files"
 msgstr "Показать файлы ветви %s"
 
-#: git-gui.sh:2329
+#: git-gui.sh:2505
 #, tcl-format
 msgid "Visualize %s's History"
 msgstr "Показать историю ветви %s"
 
-#: git-gui.sh:2334 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:2510 lib/database.tcl:27 lib/database.tcl:67
 msgid "Database Statistics"
 msgstr "Статистика базы данных"
 
-#: git-gui.sh:2337 lib/database.tcl:34
+#: git-gui.sh:2513 lib/database.tcl:34
 msgid "Compress Database"
 msgstr "Сжать базу данных"
 
-#: git-gui.sh:2340
+#: git-gui.sh:2516
 msgid "Verify Database"
 msgstr "Проверить базу данных"
 
-#: git-gui.sh:2347 git-gui.sh:2351 git-gui.sh:2355 lib/shortcut.tcl:7
-#: lib/shortcut.tcl:39 lib/shortcut.tcl:71
+#: git-gui.sh:2523 git-gui.sh:2527 git-gui.sh:2531 lib/shortcut.tcl:8
+#: lib/shortcut.tcl:40 lib/shortcut.tcl:72
 msgid "Create Desktop Icon"
 msgstr "Создать ярлык на рабочем столе"
 
-#: git-gui.sh:2363 lib/choose_repository.tcl:183 lib/choose_repository.tcl:191
+#: git-gui.sh:2539 lib/choose_repository.tcl:183 lib/choose_repository.tcl:191
 msgid "Quit"
 msgstr "Выход"
 
-#: git-gui.sh:2371
+#: git-gui.sh:2547
 msgid "Undo"
 msgstr "Отменить"
 
-#: git-gui.sh:2374
+#: git-gui.sh:2550
 msgid "Redo"
 msgstr "Повторить"
 
-#: git-gui.sh:2378 git-gui.sh:2937
+#: git-gui.sh:2554 git-gui.sh:3109
 msgid "Cut"
 msgstr "Вырезать"
 
-#: git-gui.sh:2381 git-gui.sh:2940 git-gui.sh:3014 git-gui.sh:3096
+#: git-gui.sh:2557 git-gui.sh:3112 git-gui.sh:3186 git-gui.sh:3259
 #: lib/console.tcl:69
 msgid "Copy"
 msgstr "Копировать"
 
-#: git-gui.sh:2384 git-gui.sh:2943
+#: git-gui.sh:2560 git-gui.sh:3115
 msgid "Paste"
 msgstr "Вставить"
 
-#: git-gui.sh:2387 git-gui.sh:2946 lib/branch_delete.tcl:26
+#: git-gui.sh:2563 git-gui.sh:3118 lib/branch_delete.tcl:26
 #: lib/remote_branch_delete.tcl:38
 msgid "Delete"
 msgstr "Удалить"
 
-#: git-gui.sh:2391 git-gui.sh:2950 git-gui.sh:3100 lib/console.tcl:71
+#: git-gui.sh:2567 git-gui.sh:3122 git-gui.sh:3263 lib/console.tcl:71
 msgid "Select All"
 msgstr "Выделить все"
 
-#: git-gui.sh:2400
+#: git-gui.sh:2576
 msgid "Create..."
 msgstr "Создать..."
 
-#: git-gui.sh:2406
+#: git-gui.sh:2582
 msgid "Checkout..."
 msgstr "Перейти..."
 
-#: git-gui.sh:2412
+#: git-gui.sh:2588
 msgid "Rename..."
 msgstr "Переименовать..."
 
-#: git-gui.sh:2417
+#: git-gui.sh:2593
 msgid "Delete..."
 msgstr "Удалить..."
 
-#: git-gui.sh:2422
+#: git-gui.sh:2598
 msgid "Reset..."
 msgstr "Сбросить..."
 
-#: git-gui.sh:2432
+#: git-gui.sh:2608
 msgid "Done"
 msgstr "Завершено"
 
-#: git-gui.sh:2434
+#: git-gui.sh:2610
 msgid "Commit@@verb"
 msgstr "Сохранить"
 
-#: git-gui.sh:2443 git-gui.sh:2878
+#: git-gui.sh:2619 git-gui.sh:3050
 msgid "New Commit"
 msgstr "Новое состояние"
 
-#: git-gui.sh:2451 git-gui.sh:2885
+#: git-gui.sh:2627 git-gui.sh:3057
 msgid "Amend Last Commit"
 msgstr "Исправить последнее состояние"
 
-#: git-gui.sh:2461 git-gui.sh:2839 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2637 git-gui.sh:3011 lib/remote_branch_delete.tcl:99
 msgid "Rescan"
 msgstr "Перечитать"
 
-#: git-gui.sh:2467
+#: git-gui.sh:2643
 msgid "Stage To Commit"
 msgstr "Подготовить для сохранения"
 
-#: git-gui.sh:2473
+#: git-gui.sh:2649
 msgid "Stage Changed Files To Commit"
 msgstr "Подготовить измененные файлы для сохранения"
 
-#: git-gui.sh:2479
+#: git-gui.sh:2655
 msgid "Unstage From Commit"
 msgstr "Убрать из подготовленного"
 
-#: git-gui.sh:2484 lib/index.tcl:410
+#: git-gui.sh:2661 lib/index.tcl:412
 msgid "Revert Changes"
 msgstr "Отменить изменения"
 
-#: git-gui.sh:2491 git-gui.sh:3083
+#: git-gui.sh:2669 git-gui.sh:3310 git-gui.sh:3341
 msgid "Show Less Context"
 msgstr "Меньше контекста"
 
-#: git-gui.sh:2495 git-gui.sh:3087
+#: git-gui.sh:2673 git-gui.sh:3314 git-gui.sh:3345
 msgid "Show More Context"
 msgstr "Больше контекста"
 
-#: git-gui.sh:2502 git-gui.sh:2852 git-gui.sh:2961
+#: git-gui.sh:2680 git-gui.sh:3024 git-gui.sh:3133
 msgid "Sign Off"
 msgstr "Вставить Signed-off-by"
 
-#: git-gui.sh:2518
+#: git-gui.sh:2696
 msgid "Local Merge..."
 msgstr "Локальное слияние..."
 
-#: git-gui.sh:2523
+#: git-gui.sh:2701
 msgid "Abort Merge..."
 msgstr "Прервать слияние..."
 
-#: git-gui.sh:2535 git-gui.sh:2575
+#: git-gui.sh:2713 git-gui.sh:2741
 msgid "Add..."
 msgstr "Добавить..."
 
-#: git-gui.sh:2539
+#: git-gui.sh:2717
 msgid "Push..."
 msgstr "Отправить..."
 
-#: git-gui.sh:2543
+#: git-gui.sh:2721
 msgid "Delete Branch..."
 msgstr "Удалить ветвь..."
 
-#: git-gui.sh:2553 git-gui.sh:2589 lib/about.tcl:14
-#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:53
-#, tcl-format
-msgid "About %s"
-msgstr "О %s"
-
-#: git-gui.sh:2557
-msgid "Preferences..."
-msgstr "Настройки..."
-
-#: git-gui.sh:2565 git-gui.sh:3129
+#: git-gui.sh:2731 git-gui.sh:3292
 msgid "Options..."
 msgstr "Настройки..."
 
-#: git-gui.sh:2576
+#: git-gui.sh:2742
 msgid "Remove..."
 msgstr "Удалить..."
 
-#: git-gui.sh:2585 lib/choose_repository.tcl:50
+#: git-gui.sh:2751 lib/choose_repository.tcl:50
 msgid "Help"
 msgstr "Помощь"
 
-#: git-gui.sh:2611
+#: git-gui.sh:2755 git-gui.sh:2759 lib/about.tcl:14
+#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:53
+#, tcl-format
+msgid "About %s"
+msgstr "О %s"
+
+#: git-gui.sh:2783
 msgid "Online Documentation"
 msgstr "Документация в интернете"
 
-#: git-gui.sh:2614 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
+#: git-gui.sh:2786 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
 msgid "Show SSH Key"
 msgstr "Показать ключ SSH"
 
-#: git-gui.sh:2721
+#: git-gui.sh:2893
 #, tcl-format
 msgid "fatal: cannot stat path %s: No such file or directory"
 msgstr "критическая ошибка: %s: нет такого файла или каталога"
 
-#: git-gui.sh:2754
+#: git-gui.sh:2926
 msgid "Current Branch:"
 msgstr "Текущая ветвь:"
 
-#: git-gui.sh:2775
+#: git-gui.sh:2947
 msgid "Staged Changes (Will Commit)"
 msgstr "Подготовлено (будет сохранено)"
 
-#: git-gui.sh:2795
+#: git-gui.sh:2967
 msgid "Unstaged Changes"
 msgstr "Изменено (не будет сохранено)"
 
-#: git-gui.sh:2845
+#: git-gui.sh:3017
 msgid "Stage Changed"
 msgstr "Подготовить все"
 
-#: git-gui.sh:2864 lib/transport.tcl:104 lib/transport.tcl:193
+#: git-gui.sh:3036 lib/transport.tcl:104 lib/transport.tcl:193
 msgid "Push"
 msgstr "Отправить"
 
-#: git-gui.sh:2899
+#: git-gui.sh:3071
 msgid "Initial Commit Message:"
 msgstr "Комментарий к первому состоянию:"
 
-#: git-gui.sh:2900
+#: git-gui.sh:3072
 msgid "Amended Commit Message:"
 msgstr "Комментарий к исправленному состоянию:"
 
-#: git-gui.sh:2901
+#: git-gui.sh:3073
 msgid "Amended Initial Commit Message:"
 msgstr "Комментарий к исправленному первоначальному состоянию:"
 
-#: git-gui.sh:2902
+#: git-gui.sh:3074
 msgid "Amended Merge Commit Message:"
 msgstr "Комментарий к исправленному слиянию:"
 
-#: git-gui.sh:2903
+#: git-gui.sh:3075
 msgid "Merge Commit Message:"
 msgstr "Комментарий к слиянию:"
 
-#: git-gui.sh:2904
+#: git-gui.sh:3076
 msgid "Commit Message:"
 msgstr "Комментарий к состоянию:"
 
-#: git-gui.sh:2953 git-gui.sh:3104 lib/console.tcl:73
+#: git-gui.sh:3125 git-gui.sh:3267 lib/console.tcl:73
 msgid "Copy All"
 msgstr "Копировать все"
 
-#: git-gui.sh:2977 lib/blame.tcl:104
+#: git-gui.sh:3149 lib/blame.tcl:104
 msgid "File:"
 msgstr "Файл:"
 
-#: git-gui.sh:3092
+#: git-gui.sh:3255
 msgid "Refresh"
 msgstr "Обновить"
 
-#: git-gui.sh:3113
+#: git-gui.sh:3276
 msgid "Decrease Font Size"
 msgstr "Уменьшить размер шрифта"
 
-#: git-gui.sh:3117
+#: git-gui.sh:3280
 msgid "Increase Font Size"
 msgstr "Увеличить размер шрифта"
 
-#: git-gui.sh:3125 lib/blame.tcl:281
+#: git-gui.sh:3288 lib/blame.tcl:281
 msgid "Encoding"
 msgstr "Кодировка"
 
-#: git-gui.sh:3136
+#: git-gui.sh:3299
 msgid "Apply/Reverse Hunk"
 msgstr "Применить/Убрать изменение"
 
-#: git-gui.sh:3141
+#: git-gui.sh:3304
 msgid "Apply/Reverse Line"
 msgstr "Применить/Убрать строку"
 
-#: git-gui.sh:3151
+#: git-gui.sh:3323
 msgid "Run Merge Tool"
 msgstr "Запустить программу слияния"
 
-#: git-gui.sh:3156
+#: git-gui.sh:3328
 msgid "Use Remote Version"
 msgstr "Взять внешнюю версию"
 
-#: git-gui.sh:3160
+#: git-gui.sh:3332
 msgid "Use Local Version"
 msgstr "Взять локальную версию"
 
-#: git-gui.sh:3164
+#: git-gui.sh:3336
 msgid "Revert To Base"
 msgstr "Отменить изменения"
 
-#: git-gui.sh:3183
+#: git-gui.sh:3354
+msgid "Visualize These Changes In The Submodule"
+msgstr ""
+
+#: git-gui.sh:3358
+msgid "Visualize Current Branch History In The Submodule"
+msgstr "Показать историю текущей ветви подмодуля"
+
+#: git-gui.sh:3362
+msgid "Visualize All Branch History In The Submodule"
+msgstr "Показать историю всех ветвей подмодуля"
+
+#: git-gui.sh:3367
+msgid "Start git gui In The Submodule"
+msgstr ""
+
+#: git-gui.sh:3389
 msgid "Unstage Hunk From Commit"
 msgstr "Не сохранять часть"
 
-#: git-gui.sh:3184
+#: git-gui.sh:3391
+msgid "Unstage Lines From Commit"
+msgstr "Убрать строки из подготовленного"
+
+#: git-gui.sh:3393
 msgid "Unstage Line From Commit"
 msgstr "Убрать строку из подготовленного"
 
-#: git-gui.sh:3186
+#: git-gui.sh:3396
 msgid "Stage Hunk For Commit"
 msgstr "Подготовить часть для сохранения"
 
-#: git-gui.sh:3187
+#: git-gui.sh:3398
+msgid "Stage Lines For Commit"
+msgstr "Подготовить строки для сохранения"
+
+#: git-gui.sh:3400
 msgid "Stage Line For Commit"
 msgstr "Подготовить строку для сохранения"
 
-#: git-gui.sh:3210
+#: git-gui.sh:3424
 msgid "Initializing..."
 msgstr "Инициализация..."
 
-#: git-gui.sh:3315
+#: git-gui.sh:3541
 #, tcl-format
 msgid ""
 "Possible environment issues exist.\n"
@@ -520,7 +544,7 @@ msgstr ""
 "запущенными из %s\n"
 "\n"
 
-#: git-gui.sh:3345
+#: git-gui.sh:3570
 msgid ""
 "\n"
 "This is due to a known issue with the\n"
@@ -530,7 +554,7 @@ msgstr ""
 "Это известная проблема с Tcl,\n"
 "распространяемым Cygwin."
 
-#: git-gui.sh:3350
+#: git-gui.sh:3575
 #, tcl-format
 msgid ""
 "\n"
@@ -640,7 +664,7 @@ msgstr "Невозможно найти состояние предка:"
 msgid "Unable to display parent"
 msgstr "Не могу показать предка"
 
-#: lib/blame.tcl:1091 lib/diff.tcl:297
+#: lib/blame.tcl:1091 lib/diff.tcl:320
 msgid "Error loading diff:"
 msgstr "Ошибка загрузки изменений:"
 
@@ -666,7 +690,7 @@ msgstr "Перейти"
 
 #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
 #: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
-#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:172
+#: lib/checkout_op.tcl:579 lib/choose_font.tcl:43 lib/merge.tcl:172
 #: lib/option.tcl:125 lib/remote_add.tcl:32 lib/remote_branch_delete.tcl:42
 #: lib/tools_dlg.tcl:40 lib/tools_dlg.tcl:204 lib/tools_dlg.tcl:352
 #: lib/transport.tcl:108
@@ -697,7 +721,7 @@ msgstr "Создание ветви"
 msgid "Create New Branch"
 msgstr "Создать новую ветвь"
 
-#: lib/branch_create.tcl:31 lib/choose_repository.tcl:377
+#: lib/branch_create.tcl:31 lib/choose_repository.tcl:381
 msgid "Create"
 msgstr "Создать"
 
@@ -729,7 +753,7 @@ msgstr "Нет"
 msgid "Fast Forward Only"
 msgstr "Только Fast Forward"
 
-#: lib/branch_create.tcl:85 lib/checkout_op.tcl:536
+#: lib/branch_create.tcl:85 lib/checkout_op.tcl:571
 msgid "Reset"
 msgstr "Сброс"
 
@@ -771,8 +795,8 @@ msgstr "Локальные ветви"
 msgid "Delete Only If Merged Into"
 msgstr "Удалить только в случае, если было слияние с"
 
-#: lib/branch_delete.tcl:54
-msgid "Always (Do not perform merge test.)"
+#: lib/branch_delete.tcl:54 lib/remote_branch_delete.tcl:119
+msgid "Always (Do not perform merge checks)"
 msgstr "Всегда (не выполнять проверку на слияние)"
 
 #: lib/branch_delete.tcl:103
@@ -780,6 +804,16 @@ msgstr "Всегда (не выполнять проверку на слияни
 msgid "The following branches are not completely merged into %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"
+"Продолжить?"
+
 #: lib/branch_delete.tcl:141
 #, tcl-format
 msgid ""
@@ -809,7 +843,7 @@ msgstr "Новое название:"
 msgid "Please select a branch to rename."
 msgstr "Укажите ветвь для переименования."
 
-#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:201
+#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:202
 #, tcl-format
 msgid "Branch '%s' already exists."
 msgstr "Ветвь '%s' уже существует."
@@ -840,38 +874,38 @@ msgstr "[На уровень выше]"
 msgid "Browse Branch Files"
 msgstr "Показать файлы ветви"
 
-#: lib/browser.tcl:278 lib/choose_repository.tcl:394
-#: lib/choose_repository.tcl:480 lib/choose_repository.tcl:491
-#: lib/choose_repository.tcl:995
+#: lib/browser.tcl:278 lib/choose_repository.tcl:398
+#: lib/choose_repository.tcl:486 lib/choose_repository.tcl:497
+#: lib/choose_repository.tcl:1028
 msgid "Browse"
 msgstr "Показать"
 
-#: lib/checkout_op.tcl:84
+#: lib/checkout_op.tcl:85
 #, tcl-format
 msgid "Fetching %s from %s"
 msgstr "Получение %s из %s "
 
-#: lib/checkout_op.tcl:132
+#: lib/checkout_op.tcl:133
 #, tcl-format
 msgid "fatal: Cannot resolve %s"
 msgstr "критическая ошибка: невозможно разрешить %s"
 
-#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
+#: lib/checkout_op.tcl:146 lib/console.tcl:81 lib/database.tcl:31
 #: lib/sshkey.tcl:53
 msgid "Close"
 msgstr "Закрыть"
 
-#: lib/checkout_op.tcl:174
+#: lib/checkout_op.tcl:175
 #, tcl-format
 msgid "Branch '%s' does not exist."
 msgstr "Ветвь '%s' не существует "
 
-#: lib/checkout_op.tcl:193
+#: lib/checkout_op.tcl:194
 #, tcl-format
 msgid "Failed to configure simplified git-pull for '%s'."
 msgstr "Ошибка создания упрощённой конфигурации git pull для '%s'."
 
-#: lib/checkout_op.tcl:228
+#: lib/checkout_op.tcl:229
 #, tcl-format
 msgid ""
 "Branch '%s' already exists.\n"
@@ -884,21 +918,21 @@ msgstr ""
 "Она не может быть прокручена(fast-forward) к %s.\n"
 "Требуется слияние."
 
-#: lib/checkout_op.tcl:242
+#: lib/checkout_op.tcl:243
 #, tcl-format
 msgid "Merge strategy '%s' not supported."
 msgstr "Неизвестная стратегия слияния: '%s'."
 
-#: lib/checkout_op.tcl:261
+#: lib/checkout_op.tcl:262
 #, tcl-format
 msgid "Failed to update '%s'."
 msgstr "Не удалось обновить '%s'."
 
-#: lib/checkout_op.tcl:273
+#: lib/checkout_op.tcl:274
 msgid "Staging area (index) is already locked."
 msgstr "Рабочая область заблокирована другим процессом."
 
-#: lib/checkout_op.tcl:288
+#: lib/checkout_op.tcl:289
 msgid ""
 "Last scanned state does not match repository state.\n"
 "\n"
@@ -914,30 +948,30 @@ msgstr ""
 "\n"
 "Это будет сделано сейчас автоматически.\n"
 
-#: lib/checkout_op.tcl:344
+#: lib/checkout_op.tcl:345
 #, tcl-format
 msgid "Updating working directory to '%s'..."
 msgstr "Обновление рабочего каталога из '%s'..."
 
-#: lib/checkout_op.tcl:345
+#: lib/checkout_op.tcl:346
 msgid "files checked out"
 msgstr "файлы извлечены"
 
-#: lib/checkout_op.tcl:375
+#: lib/checkout_op.tcl:376
 #, tcl-format
 msgid "Aborted checkout of '%s' (file level merging is required)."
 msgstr "Прерван переход на '%s' (требуется слияние содержания файлов)"
 
-#: lib/checkout_op.tcl:376
+#: lib/checkout_op.tcl:377
 msgid "File level merge required."
 msgstr "Требуется слияние содержания файлов."
 
-#: lib/checkout_op.tcl:380
+#: lib/checkout_op.tcl:381
 #, tcl-format
 msgid "Staying on branch '%s'."
 msgstr "Ветвь '%s' остается текущей."
 
-#: lib/checkout_op.tcl:451
+#: lib/checkout_op.tcl:452
 msgid ""
 "You are no longer on a local branch.\n"
 "\n"
@@ -949,30 +983,30 @@ msgstr ""
 "Если вы хотите снова вернуться к какой-нибудь ветви, создайте ее сейчас, "
 "начиная с 'Текущего отсоединенного состояния'."
 
-#: lib/checkout_op.tcl:468 lib/checkout_op.tcl:472
+#: lib/checkout_op.tcl:503 lib/checkout_op.tcl:507
 #, tcl-format
 msgid "Checked out '%s'."
 msgstr "Ветвь '%s' сделана текущей."
 
-#: lib/checkout_op.tcl:500
+#: lib/checkout_op.tcl:535
 #, tcl-format
 msgid "Resetting '%s' to '%s' will lose the following commits:"
 msgstr "Сброс '%s' в '%s' приведет к потере следующих сохраненных состояний: "
 
-#: lib/checkout_op.tcl:522
+#: lib/checkout_op.tcl:557
 msgid "Recovering lost commits may not be easy."
 msgstr "Восстановить потерянные сохраненные состояния будет сложно."
 
-#: lib/checkout_op.tcl:527
+#: lib/checkout_op.tcl:562
 #, tcl-format
 msgid "Reset '%s'?"
 msgstr "Сбросить '%s'?"
 
-#: lib/checkout_op.tcl:532 lib/merge.tcl:164 lib/tools_dlg.tcl:343
+#: lib/checkout_op.tcl:567 lib/merge.tcl:164 lib/tools_dlg.tcl:343
 msgid "Visualize"
 msgstr "Наглядно"
 
-#: lib/checkout_op.tcl:600
+#: lib/checkout_op.tcl:635
 #, tcl-format
 msgid ""
 "Failed to set current branch.\n"
@@ -1017,7 +1051,7 @@ msgstr ""
 msgid "Git Gui"
 msgstr "Git Gui"
 
-#: lib/choose_repository.tcl:87 lib/choose_repository.tcl:382
+#: lib/choose_repository.tcl:87 lib/choose_repository.tcl:386
 msgid "Create New Repository"
 msgstr "Создать новый репозиторий"
 
@@ -1025,7 +1059,7 @@ msgstr "Создать новый репозиторий"
 msgid "New..."
 msgstr "Новый..."
 
-#: lib/choose_repository.tcl:100 lib/choose_repository.tcl:465
+#: lib/choose_repository.tcl:100 lib/choose_repository.tcl:471
 msgid "Clone Existing Repository"
 msgstr "Склонировать существующий репозиторий"
 
@@ -1033,7 +1067,7 @@ msgstr "Склонировать существующий репозиторий
 msgid "Clone..."
 msgstr "Склонировать..."
 
-#: lib/choose_repository.tcl:113 lib/choose_repository.tcl:983
+#: lib/choose_repository.tcl:113 lib/choose_repository.tcl:1016
 msgid "Open Existing Repository"
 msgstr "Выбрать существующий репозиторий"
 
@@ -1049,194 +1083,194 @@ msgstr "Недавние репозитории"
 msgid "Open Recent Repository:"
 msgstr "Открыть последний репозиторий"
 
-#: lib/choose_repository.tcl:302 lib/choose_repository.tcl:309
-#: lib/choose_repository.tcl:316
+#: lib/choose_repository.tcl:306 lib/choose_repository.tcl:313
+#: lib/choose_repository.tcl:320
 #, tcl-format
 msgid "Failed to create repository %s:"
 msgstr "Не удалось создать репозиторий %s:"
 
-#: lib/choose_repository.tcl:387
+#: lib/choose_repository.tcl:391
 msgid "Directory:"
 msgstr "Каталог:"
 
-#: lib/choose_repository.tcl:417 lib/choose_repository.tcl:544
-#: lib/choose_repository.tcl:1017
+#: lib/choose_repository.tcl:423 lib/choose_repository.tcl:550
+#: lib/choose_repository.tcl:1052
 msgid "Git Repository"
 msgstr "Репозиторий"
 
-#: lib/choose_repository.tcl:442
+#: lib/choose_repository.tcl:448
 #, tcl-format
 msgid "Directory %s already exists."
 msgstr "Каталог '%s' уже существует."
 
-#: lib/choose_repository.tcl:446
+#: lib/choose_repository.tcl:452
 #, tcl-format
 msgid "File %s already exists."
 msgstr "Файл '%s' уже существует."
 
-#: lib/choose_repository.tcl:460
+#: lib/choose_repository.tcl:466
 msgid "Clone"
 msgstr "Склонировать"
 
-#: lib/choose_repository.tcl:473
+#: lib/choose_repository.tcl:479
 msgid "Source Location:"
 msgstr "Исходное положение:"
 
-#: lib/choose_repository.tcl:484
+#: lib/choose_repository.tcl:490
 msgid "Target Directory:"
 msgstr "Каталог назначения:"
 
-#: lib/choose_repository.tcl:496
+#: lib/choose_repository.tcl:502
 msgid "Clone Type:"
 msgstr "Тип клона:"
 
-#: lib/choose_repository.tcl:502
+#: lib/choose_repository.tcl:508
 msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
 msgstr "Стандартный (Быстрый, полуизбыточный, \"жесткие\" ссылки)"
 
-#: lib/choose_repository.tcl:508
+#: lib/choose_repository.tcl:514
 msgid "Full Copy (Slower, Redundant Backup)"
 msgstr "Полная копия (Медленный, создает резервную копию)"
 
-#: lib/choose_repository.tcl:514
+#: lib/choose_repository.tcl:520
 msgid "Shared (Fastest, Not Recommended, No Backup)"
 msgstr "Общий (Самый быстрый, не рекомендуется, без резервной копии)"
 
-#: lib/choose_repository.tcl:550 lib/choose_repository.tcl:597
-#: lib/choose_repository.tcl:743 lib/choose_repository.tcl:813
-#: lib/choose_repository.tcl:1023 lib/choose_repository.tcl:1031
+#: lib/choose_repository.tcl:556 lib/choose_repository.tcl:603
+#: lib/choose_repository.tcl:749 lib/choose_repository.tcl:819
+#: lib/choose_repository.tcl:1058 lib/choose_repository.tcl:1066
 #, tcl-format
 msgid "Not a Git repository: %s"
 msgstr "Каталог не является репозиторием: %s"
 
-#: lib/choose_repository.tcl:586
+#: lib/choose_repository.tcl:592
 msgid "Standard only available for local repository."
 msgstr "Стандартный клон возможен только для локального репозитория."
 
-#: lib/choose_repository.tcl:590
+#: lib/choose_repository.tcl:596
 msgid "Shared only available for local repository."
 msgstr "Общий клон возможен только для локального репозитория."
 
-#: lib/choose_repository.tcl:611
+#: lib/choose_repository.tcl:617
 #, tcl-format
 msgid "Location %s already exists."
 msgstr "Путь '%s' уже существует."
 
-#: lib/choose_repository.tcl:622
+#: lib/choose_repository.tcl:628
 msgid "Failed to configure origin"
 msgstr "Не могу сконфигурировать исходный репозиторий."
 
-#: lib/choose_repository.tcl:634
+#: lib/choose_repository.tcl:640
 msgid "Counting objects"
 msgstr "Считаю объекты"
 
-#: lib/choose_repository.tcl:635
+#: lib/choose_repository.tcl:641
 msgid "buckets"
 msgstr ""
 
-#: lib/choose_repository.tcl:659
+#: lib/choose_repository.tcl:665
 #, tcl-format
 msgid "Unable to copy objects/info/alternates: %s"
 msgstr "Не могу скопировать objects/info/alternates: %s"
 
-#: lib/choose_repository.tcl:695
+#: lib/choose_repository.tcl:701
 #, tcl-format
 msgid "Nothing to clone from %s."
 msgstr "Нечего клонировать с %s."
 
-#: lib/choose_repository.tcl:697 lib/choose_repository.tcl:911
-#: lib/choose_repository.tcl:923
+#: 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'."
 
-#: lib/choose_repository.tcl:710
+#: lib/choose_repository.tcl:716
 msgid "Hardlinks are unavailable.  Falling back to copying."
 msgstr "\"Жесткие ссылки\" недоступны. Будет использовано копирование."
 
-#: lib/choose_repository.tcl:722
+#: lib/choose_repository.tcl:728
 #, tcl-format
 msgid "Cloning from %s"
 msgstr "Клонирование %s"
 
-#: lib/choose_repository.tcl:753
+#: lib/choose_repository.tcl:759
 msgid "Copying objects"
 msgstr "Копирование objects"
 
-#: lib/choose_repository.tcl:754
+#: lib/choose_repository.tcl:760
 msgid "KiB"
 msgstr "КБ"
 
-#: lib/choose_repository.tcl:778
+#: lib/choose_repository.tcl:784
 #, tcl-format
 msgid "Unable to copy object: %s"
 msgstr "Не могу скопировать объект: %s"
 
-#: lib/choose_repository.tcl:788
+#: lib/choose_repository.tcl:794
 msgid "Linking objects"
 msgstr "Создание ссылок на objects"
 
-#: lib/choose_repository.tcl:789
+#: lib/choose_repository.tcl:795
 msgid "objects"
 msgstr "объекты"
 
-#: lib/choose_repository.tcl:797
+#: lib/choose_repository.tcl:803
 #, tcl-format
 msgid "Unable to hardlink object: %s"
 msgstr "Не могу \"жестко связать\" объект: %s"
 
-#: lib/choose_repository.tcl:852
+#: lib/choose_repository.tcl:858
 msgid "Cannot fetch branches and objects.  See console output for details."
 msgstr ""
 "Не могу получить ветви и объекты. Дополнительная информация на консоли."
 
-#: lib/choose_repository.tcl:863
+#: lib/choose_repository.tcl:869
 msgid "Cannot fetch tags.  See console output for details."
 msgstr "Не могу получить метки. Дополнительная информация на консоли."
 
-#: lib/choose_repository.tcl:887
+#: lib/choose_repository.tcl:893
 msgid "Cannot determine HEAD.  See console output for details."
 msgstr "Не могу определить HEAD. Дополнительная информация на консоли."
 
-#: lib/choose_repository.tcl:896
+#: lib/choose_repository.tcl:902
 #, tcl-format
 msgid "Unable to cleanup %s"
 msgstr "Не могу очистить %s"
 
-#: lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:908
 msgid "Clone failed."
 msgstr "Клонирование не удалось."
 
-#: lib/choose_repository.tcl:909
+#: lib/choose_repository.tcl:915
 msgid "No default branch obtained."
 msgstr "Не было получено ветви по умолчанию."
 
-#: lib/choose_repository.tcl:920
+#: lib/choose_repository.tcl:926
 #, tcl-format
 msgid "Cannot resolve %s as a commit."
 msgstr "Не могу распознать %s как состояние."
 
-#: lib/choose_repository.tcl:932
+#: lib/choose_repository.tcl:938
 msgid "Creating working directory"
 msgstr "Создаю рабочий каталог"
 
-#: lib/choose_repository.tcl:933 lib/index.tcl:65 lib/index.tcl:128
-#: lib/index.tcl:196
+#: lib/choose_repository.tcl:939 lib/index.tcl:67 lib/index.tcl:130
+#: lib/index.tcl:198
 msgid "files"
 msgstr "файлов"
 
-#: lib/choose_repository.tcl:962
+#: lib/choose_repository.tcl:968
 msgid "Initial file checkout failed."
 msgstr "Не удалось получить начальное состояние файлов репозитория."
 
-#: lib/choose_repository.tcl:978
+#: lib/choose_repository.tcl:1011
 msgid "Open"
 msgstr "Открыть"
 
-#: lib/choose_repository.tcl:988
+#: lib/choose_repository.tcl:1021
 msgid "Repository:"
 msgstr "Репозиторий:"
 
-#: lib/choose_repository.tcl:1037
+#: lib/choose_repository.tcl:1072
 #, tcl-format
 msgid "Failed to open repository %s:"
 msgstr "Не удалось открыть репозиторий %s:"
@@ -1318,7 +1352,12 @@ msgstr "Невозможно получить информацию об авто
 msgid "Invalid GIT_COMMITTER_IDENT:"
 msgstr "Неверный GIT_COMMITTER_IDENT:"
 
-#: lib/commit.tcl:132
+#: lib/commit.tcl:129
+#, tcl-format
+msgid "warning: Tcl does not support encoding '%s'."
+msgstr "предупреждение: Tcl не поддерживает кодировку '%s'."
+
+#: lib/commit.tcl:149
 msgid ""
 "Last scanned state does not match repository state.\n"
 "\n"
@@ -1334,7 +1373,7 @@ msgstr ""
 "\n"
 "Это будет сделано сейчас автоматически.\n"
 
-#: lib/commit.tcl:155
+#: lib/commit.tcl:172
 #, tcl-format
 msgid ""
 "Unmerged files cannot be committed.\n"
@@ -1342,12 +1381,12 @@ msgid ""
 "File %s has merge conflicts.  You must resolve them and stage the file "
 "before committing.\n"
 msgstr ""
-"Нельзя сохранить файлы с незавершённой операцей слияния.\n"
+"Ð\9dелÑ\8cзÑ\8f Ñ\81оÑ\85Ñ\80аниÑ\82Ñ\8c Ñ\84айлÑ\8b Ñ\81 Ð½ÐµÐ·Ð°Ð²ÐµÑ\80Ñ\88Ñ\91нной Ð¾Ð¿ÐµÑ\80аÑ\86ией Ñ\81лиÑ\8fниÑ\8f.\n"
 "\n"
 "Для файла %s возник конфликт слияния. Разрешите конфликт и добавьте к "
 "подготовленным файлам перед сохранением.\n"
 
-#: lib/commit.tcl:163
+#: lib/commit.tcl:180
 #, tcl-format
 msgid ""
 "Unknown file state %s detected.\n"
@@ -1358,7 +1397,7 @@ msgstr ""
 "\n"
 "Файл %s не может быть сохранен данной программой.\n"
 
-#: lib/commit.tcl:171
+#: lib/commit.tcl:188
 msgid ""
 "No changes to commit.\n"
 "\n"
@@ -1368,7 +1407,7 @@ msgstr ""
 "\n"
 "Подготовьте хотя бы один файл до создания сохраненного состояния.\n"
 
-#: lib/commit.tcl:186
+#: lib/commit.tcl:203
 msgid ""
 "Please supply a commit message.\n"
 "\n"
@@ -1386,45 +1425,40 @@ msgstr ""
 "- вторая строка пустая\n"
 "- оставшиеся строки: опишите, что дают ваши изменения.\n"
 
-#: lib/commit.tcl:210
-#, tcl-format
-msgid "warning: Tcl does not support encoding '%s'."
-msgstr "предупреждение: Tcl не поддерживает кодировку '%s'."
-
-#: lib/commit.tcl:226
+#: lib/commit.tcl:234
 msgid "Calling pre-commit hook..."
 msgstr "Вызов программы поддержки репозитория pre-commit..."
 
-#: lib/commit.tcl:241
+#: lib/commit.tcl:249
 msgid "Commit declined by pre-commit hook."
 msgstr "Сохранение прервано программой поддержки репозитория pre-commit"
 
-#: lib/commit.tcl:264
+#: lib/commit.tcl:272
 msgid "Calling commit-msg hook..."
 msgstr "Вызов программы поддержки репозитория commit-msg..."
 
-#: lib/commit.tcl:279
+#: lib/commit.tcl:287
 msgid "Commit declined by commit-msg hook."
 msgstr "Сохранение прервано программой поддержки репозитория commit-msg"
 
-#: lib/commit.tcl:292
+#: lib/commit.tcl:300
 msgid "Committing changes..."
 msgstr "Сохранение изменений..."
 
-#: lib/commit.tcl:308
+#: lib/commit.tcl:316
 msgid "write-tree failed:"
 msgstr "Программа write-tree завершилась с ошибкой:"
 
-#: lib/commit.tcl:309 lib/commit.tcl:353 lib/commit.tcl:373
+#: lib/commit.tcl:317 lib/commit.tcl:361 lib/commit.tcl:382
 msgid "Commit failed."
 msgstr "Сохранить состояние не удалось."
 
-#: lib/commit.tcl:326
+#: lib/commit.tcl:334
 #, tcl-format
 msgid "Commit %s appears to be corrupt"
 msgstr "Состояние %s выглядит поврежденным"
 
-#: lib/commit.tcl:331
+#: lib/commit.tcl:339
 msgid ""
 "No changes to commit.\n"
 "\n"
@@ -1438,19 +1472,19 @@ msgstr ""
 "\n"
 "Сейчас автоматически запустится перечитывание репозитория.\n"
 
-#: lib/commit.tcl:338
+#: lib/commit.tcl:346
 msgid "No changes to commit."
-msgstr "Ð\9eÑ\82Ñ\83Ñ\81Ñ\82вÑ\83Ñ\8eÑ\82 Ð¸Ð·Ð¼ения для сохранения."
+msgstr "Ð\9eÑ\82Ñ\81Ñ\83Ñ\82Ñ\81Ñ\82вÑ\83Ñ\8eÑ\82 Ð¸Ð·Ð¼ÐµÐ½ения для сохранения."
 
-#: lib/commit.tcl:352
+#: lib/commit.tcl:360
 msgid "commit-tree failed:"
 msgstr "Программа commit-tree завершилась с ошибкой:"
 
-#: lib/commit.tcl:372
+#: lib/commit.tcl:381
 msgid "update-ref failed:"
 msgstr "Программа update-ref завершилась с ошибкой:"
 
-#: lib/commit.tcl:460
+#: lib/commit.tcl:469
 #, tcl-format
 msgid "Created commit %s: %s"
 msgstr "Создано состояние %s: %s "
@@ -1503,20 +1537,19 @@ msgstr "Сжатие базы объектов"
 msgid "Verifying the object database with fsck-objects"
 msgstr "Проверка базы объектов при помощи fsck"
 
-#: lib/database.tcl:108
+#: 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 when more than %i loose objects exist.\n"
+"the database.\n"
 "\n"
 "Compress the database now?"
 msgstr ""
 "Этот репозиторий сейчас содержит примерно %i свободных объектов\n"
 "\n"
-"Для лучшей производительности рекомендуется сжать базу данных, когда есть "
-"более %i несвязанных объектов.\n"
+"Для лучшей производительности рекомендуется сжать базу данных.\n"
 "\n"
 "Сжать базу данных сейчас?"
 
@@ -1525,7 +1558,7 @@ msgstr ""
 msgid "Invalid date from Git: %s"
 msgstr "Неправильная дата в репозитории: %s"
 
-#: lib/diff.tcl:59
+#: lib/diff.tcl:64
 #, tcl-format
 msgid ""
 "No differences detected.\n"
@@ -1540,19 +1573,19 @@ msgid ""
 msgstr ""
 "Изменений не обнаружено.\n"
 "\n"
-"в %s отутствуют изменения.\n"
+"в %s Ð¾Ñ\82Ñ\81Ñ\83Ñ\82Ñ\81Ñ\82вÑ\83Ñ\8eÑ\82 Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ\8f.\n"
 "\n"
 "Дата изменения файла была обновлена другой программой, но содержимое файла "
 "осталось прежним.\n"
 "\n"
 "Сейчас будет запущено перечитывание репозитория, чтобы найти подобные файлы."
 
-#: lib/diff.tcl:99
+#: lib/diff.tcl:104
 #, tcl-format
 msgid "Loading diff of %s..."
 msgstr "Загрузка изменений в %s..."
 
-#: lib/diff.tcl:120
+#: lib/diff.tcl:125
 msgid ""
 "LOCAL: deleted\n"
 "REMOTE:\n"
@@ -1560,7 +1593,7 @@ msgstr ""
 "ЛОКАЛЬНО: удалён\n"
 "ВНЕШНИЙ:\n"
 
-#: lib/diff.tcl:125
+#: lib/diff.tcl:130
 msgid ""
 "REMOTE: deleted\n"
 "LOCAL:\n"
@@ -1568,41 +1601,41 @@ msgstr ""
 "ВНЕШНИЙ: удалён\n"
 "ЛОКАЛЬНО:\n"
 
-#: lib/diff.tcl:132
+#: lib/diff.tcl:137
 msgid "LOCAL:\n"
 msgstr "ЛОКАЛЬНО:\n"
 
-#: lib/diff.tcl:135
+#: lib/diff.tcl:140
 msgid "REMOTE:\n"
 msgstr "ВНЕШНИЙ:\n"
 
-#: lib/diff.tcl:197 lib/diff.tcl:296
+#: lib/diff.tcl:202 lib/diff.tcl:319
 #, tcl-format
 msgid "Unable to display %s"
 msgstr "Не могу показать %s"
 
-#: lib/diff.tcl:198
+#: lib/diff.tcl:203
 msgid "Error loading file:"
 msgstr "Ошибка загрузки файла:"
 
-#: lib/diff.tcl:205
+#: lib/diff.tcl:210
 msgid "Git Repository (subproject)"
 msgstr "Репозиторий Git (подпроект)"
 
-#: lib/diff.tcl:217
+#: lib/diff.tcl:222
 msgid "* Binary file (not showing content)."
 msgstr "* Двоичный файл (содержимое не показано)"
 
-#: lib/diff.tcl:222
+#: lib/diff.tcl:227
 #, tcl-format
 msgid ""
 "* Untracked file is %d bytes.\n"
 "* Showing only first %d bytes.\n"
 msgstr ""
-"* Размер неподготовленого файла %d байт.\n"
+"* Ð Ð°Ð·Ð¼ÐµÑ\80 Ð½ÐµÐ¿Ð¾Ð´Ð³Ð¾Ñ\82овленного Ñ\84айла %d Ð±Ð°Ð¹Ñ\82.\n"
 "* Показано первых %d байт.\n"
 
-#: lib/diff.tcl:228
+#: lib/diff.tcl:233
 #, tcl-format
 msgid ""
 "\n"
@@ -1610,22 +1643,22 @@ msgid ""
 "* To see the entire file, use an external editor.\n"
 msgstr ""
 "\n"
-"* Неподготовленый файл обрезан: %s.\n"
+"* Неподготовленный файл обрезан: %s.\n"
 "* Чтобы увидеть весь файл, используйте программу-редактор.\n"
 
-#: lib/diff.tcl:436
+#: lib/diff.tcl:482
 msgid "Failed to unstage selected hunk."
 msgstr "Не удалось исключить выбранную часть."
 
-#: lib/diff.tcl:443
+#: lib/diff.tcl:489
 msgid "Failed to stage selected hunk."
 msgstr "Не удалось подготовить к сохранению выбранную часть."
 
-#: lib/diff.tcl:509
+#: lib/diff.tcl:568
 msgid "Failed to unstage selected line."
 msgstr "Не удалось исключить выбранную строку."
 
-#: lib/diff.tcl:517
+#: lib/diff.tcl:576
 msgid "Failed to stage selected line."
 msgstr "Не удалось подготовить к сохранению выбранную строку."
 
@@ -1662,15 +1695,15 @@ msgstr "Не удалось разблокировать индекс"
 msgid "Index Error"
 msgstr "Ошибка в индексе"
 
-#: lib/index.tcl:21
+#: lib/index.tcl:17
 msgid ""
 "Updating the Git index failed.  A rescan will be automatically started to "
 "resynchronize git-gui."
 msgstr ""
-"Не удалось обновить индекс Git. Состояние репозитория будетперечитано "
+"Не удалось обновить индекс Git. Состояние репозитория будет перечитано "
 "автоматически."
 
-#: lib/index.tcl:27
+#: lib/index.tcl:28
 msgid "Continue"
 msgstr "Продолжить"
 
@@ -1678,45 +1711,45 @@ msgstr "Продолжить"
 msgid "Unlock Index"
 msgstr "Разблокировать индекс"
 
-#: lib/index.tcl:287
+#: lib/index.tcl:289
 #, tcl-format
 msgid "Unstaging %s from commit"
 msgstr "Удаление %s из подготовленного"
 
-#: lib/index.tcl:326
+#: lib/index.tcl:328
 msgid "Ready to commit."
 msgstr "Подготовлено для сохранения"
 
-#: lib/index.tcl:339
+#: lib/index.tcl:341
 #, tcl-format
 msgid "Adding %s"
 msgstr "Добавление %s..."
 
-#: lib/index.tcl:396
+#: lib/index.tcl:398
 #, tcl-format
 msgid "Revert changes in file %s?"
 msgstr "Отменить изменения в файле %s?"
 
-#: lib/index.tcl:398
+#: lib/index.tcl:400
 #, tcl-format
 msgid "Revert changes in these %i files?"
 msgstr "Отменить изменения в %i файле(-ах)?"
 
-#: lib/index.tcl:406
+#: lib/index.tcl:408
 msgid "Any unstaged changes will be permanently lost by the revert."
 msgstr ""
 "Любые изменения, не подготовленные к сохранению, будут потеряны при данной "
 "операции."
 
-#: lib/index.tcl:409
+#: lib/index.tcl:411
 msgid "Do Nothing"
 msgstr "Ничего не делать"
 
-#: lib/index.tcl:427
+#: lib/index.tcl:429
 msgid "Reverting selected files"
-msgstr "Удаление изменений в выбраных файлах"
+msgstr "Удаление изменений в выбранных файлах"
 
-#: lib/index.tcl:431
+#: lib/index.tcl:433
 #, tcl-format
 msgid "Reverting %s"
 msgstr "Отмена изменений в %s"
@@ -1778,7 +1811,7 @@ msgstr ""
 "\n"
 "Файл %s изменен.\n"
 "\n"
-"Подготовьте и сохраните измения перед началом слияния. В случае "
+"Ð\9fодгоÑ\82овÑ\8cÑ\82е Ð¸ Ñ\81оÑ\85Ñ\80аниÑ\82е Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ\8f Ð¿ÐµÑ\80ед Ð½Ð°Ñ\87алом Ñ\81лиÑ\8fниÑ\8f. Ð\92 Ñ\81лÑ\83Ñ\87ае "
 "необходимости это позволит прервать операцию слияния.\n"
 
 #: lib/merge.tcl:107
@@ -1893,7 +1926,7 @@ msgstr ""
 #, tcl-format
 msgid "File %s seems to have unresolved conflicts, still stage?"
 msgstr ""
-"Файл %s кажется содержит необработаные конфликты. Продолжить подготовку к "
+"Файл %s, похоже, содержит необработанные конфликты. Продолжить подготовку к "
 "сохранению?"
 
 #: lib/mergetool.tcl:60
@@ -2152,7 +2185,7 @@ 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
@@ -2179,7 +2212,7 @@ msgstr "внешний:"
 
 #: lib/remote_branch_delete.tcl:66 lib/transport.tcl:149
 msgid "Arbitrary Location:"
-msgstr "Указаное положение:"
+msgstr "Указанное Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ðµ:"
 
 #: lib/remote_branch_delete.tcl:84
 msgid "Branches"
@@ -2193,10 +2226,6 @@ msgstr "Удалить только в случае, если"
 msgid "Merged Into:"
 msgstr "Слияние с:"
 
-#: lib/remote_branch_delete.tcl:119
-msgid "Always (Do not perform merge checks)"
-msgstr "Всегда (не выполнять проверку на слияние)"
-
 #: lib/remote_branch_delete.tcl:152
 msgid "A branch is required for 'Merged Into'."
 msgstr "Для опции 'Слияние с' требуется указать ветвь."
@@ -2225,26 +2254,16 @@ msgstr ""
 msgid "Please select one or more branches to delete."
 msgstr "Укажите одну или несколько ветвей для удаления."
 
-#: lib/remote_branch_delete.tcl:216
-msgid ""
-"Recovering deleted branches is difficult.\n"
-"\n"
-"Delete the selected branches?"
-msgstr ""
-"Восстановить удаленные ветви сложно.\n"
-"\n"
-"Продолжить?"
-
 #: lib/remote_branch_delete.tcl:226
 #, tcl-format
 msgid "Deleting branches from %s"
 msgstr "Удаление ветвей из %s"
 
-#: lib/remote_branch_delete.tcl:286
+#: lib/remote_branch_delete.tcl:292
 msgid "No repository selected."
 msgstr "Не указан репозиторий."
 
-#: lib/remote_branch_delete.tcl:291
+#: lib/remote_branch_delete.tcl:297
 #, tcl-format
 msgid "Scanning %s..."
 msgstr "Перечитывание %s... "
@@ -2265,11 +2284,11 @@ msgstr "Обратно"
 msgid "Case-Sensitive"
 msgstr "Игн. большие/маленькие"
 
-#: lib/shortcut.tcl:20 lib/shortcut.tcl:61
+#: lib/shortcut.tcl:21 lib/shortcut.tcl:62
 msgid "Cannot write shortcut:"
 msgstr "Невозможно записать ссылку:"
 
-#: lib/shortcut.tcl:136
+#: lib/shortcut.tcl:137
 msgid "Cannot write icon:"
 msgstr "Невозможно записать значок:"
 
@@ -2292,11 +2311,11 @@ msgstr "Словарь вернут к %s."
 
 #: lib/spellcheck.tcl:73
 msgid "Spell checker silently failed on startup"
-msgstr "Программа проверки правописания не смогла запустится"
+msgstr "Ð\9fÑ\80огÑ\80амма Ð¿Ñ\80овеÑ\80ки Ð¿Ñ\80авопиÑ\81аниÑ\8f Ð½Ðµ Ñ\81могла Ð·Ð°Ð¿Ñ\83Ñ\81Ñ\82иÑ\82Ñ\8cÑ\81Ñ\8f"
 
 #: lib/spellcheck.tcl:80
 msgid "Unrecognized spell checker"
-msgstr "Нераспознаная программа проверки правописания"
+msgstr "Ð\9dеÑ\80аÑ\81познаннаÑ\8f Ð¿Ñ\80огÑ\80амма Ð¿Ñ\80овеÑ\80ки Ð¿Ñ\80авопиÑ\81аниÑ\8f"
 
 #: lib/spellcheck.tcl:186
 msgid "No Suggestions"
@@ -2412,7 +2431,7 @@ msgstr "Описание вспомогательной операции"
 
 #: lib/tools_dlg.tcl:48
 msgid "Use '/' separators to create a submenu tree:"
-msgstr "Испольуйте '/' для создания подменю"
+msgstr "Используйте '/' для создания подменю"
 
 #: lib/tools_dlg.tcl:61
 msgid "Command:"
index e7013f7ba72a64ab24b991846755b6d6c068b37a..ea093d251d98af6a3d4df19e900d56df34d51572 100644 (file)
@@ -5,7 +5,8 @@
 GIT_DIR=$(git rev-parse -q --git-dir) || :;
 
 get_default_remote () {
-       curr_branch=$(git symbolic-ref -q HEAD | sed -e 's|^refs/heads/||')
+       curr_branch=$(git symbolic-ref -q HEAD)
+       curr_branch="${curr_branch#refs/heads/}"
        origin=$(git config --get "branch.$curr_branch.remote")
        echo ${origin:-origin}
 }
index 7561b374d2ec90fe774e98e39a121a1a3a3cdfa9..a305fb19f11bc4ae80e585b102ecb5d982d1a0f5 100755 (executable)
@@ -12,12 +12,14 @@ USAGE="list [<options>]
 
 SUBDIRECTORY_OK=Yes
 OPTIONS_SPEC=
+START_DIR=`pwd`
 . git-sh-setup
 require_work_tree
 cd_to_toplevel
 
 TMP="$GIT_DIR/.git-stash.$$"
-trap 'rm -f "$TMP-*"' 0
+TMPindex=${GIT_INDEX_FILE-"$GIT_DIR/index"}.stash.$$
+trap 'rm -f "$TMP-"* "$TMPindex"' 0
 
 ref_stash=refs/stash
 
@@ -81,14 +83,12 @@ create_stash () {
 
                # state of the working tree
                w_tree=$( (
-                       rm -f "$TMP-index" &&
-                       cp -p ${GIT_INDEX_FILE-"$GIT_DIR/index"} "$TMP-index" &&
-                       GIT_INDEX_FILE="$TMP-index" &&
+                       git read-tree --index-output="$TMPindex" -m $i_tree &&
+                       GIT_INDEX_FILE="$TMPindex" &&
                        export GIT_INDEX_FILE &&
-                       git read-tree -m $i_tree &&
                        git diff --name-only -z HEAD | git update-index -z --add --remove --stdin &&
                        git write-tree &&
-                       rm -f "$TMP-index"
+                       rm -f "$TMPindex"
                ) ) ||
                        die "Cannot save the current worktree state"
 
@@ -394,7 +394,7 @@ apply_stash () {
                then
                        squelch='>/dev/null 2>&1'
                fi
-               eval "git status $squelch" || :
+               (cd "$START_DIR" && eval "git status $squelch") || :
        else
                # Merge conflict; keep the exit status from merge-recursive
                status=$?
index 177dd259cd53cde017d73db5ccbecc7ed7dfa573..a5857c1ad45b0462f168a4b3b9249ed8c3cf6e89 100755 (executable)
@@ -5734,7 +5734,7 @@ sub cmd_show_log {
        my (@k, $c, $d, $stat);
        my $esc_color = qr/(?:\033\[(?:(?:\d+;)*\d*)?m)*/;
        while (<$log>) {
-               if (/^${esc_color}commit -?($::sha1_short)/o) {
+               if (/^${esc_color}commit (- )?($::sha1_short)/o) {
                        my $cmt = $1;
                        if ($c && cmt_showable($c) && $c->{r} != $r_last) {
                                $r_last = $c->{r};
index 9dccfb01d6634febbb51fbadf10bed07bd97c804..ee69ea683aedf81cd6e6eec0f500bddf2ff54450 100755 (executable)
@@ -1199,11 +1199,15 @@ if (defined caller) {
 # -full => 0|1      - use absolute/full URL ($my_uri/$my_url as base)
 # -replay => 1      - start from a current view (replay with modifications)
 # -path_info => 0|1 - don't use/use path_info URL (if possible)
+# -anchor => ANCHOR - add #ANCHOR to end of URL, implies -replay if used alone
 sub href {
        my %params = @_;
        # default is to use -absolute url() i.e. $my_uri
        my $href = $params{-full} ? $my_url : $my_uri;
 
+       # implicit -replay, must be first of implicit params
+       $params{-replay} = 1 if (keys %params == 1 && $params{-anchor});
+
        $params{'project'} = $project unless exists $params{'project'};
 
        if ($params{-replay}) {
@@ -1314,6 +1318,10 @@ sub href {
        # final transformation: trailing spaces must be escaped (URI-encoded)
        $href =~ s/(\s+)$/CGI::escape($1)/e;
 
+       if ($params{-anchor}) {
+               $href .= "#".esc_param($params{-anchor});
+       }
+
        return $href;
 }
 
@@ -2913,8 +2921,10 @@ sub parse_date {
        $date{'iso-8601'}  = sprintf "%04d-%02d-%02dT%02d:%02d:%02dZ",
                             1900+$year, 1+$mon, $mday, $hour ,$min, $sec;
 
-       $tz =~ m/^([+\-][0-9][0-9])([0-9][0-9])$/;
-       my $local = $epoch + ((int $1 + ($2/60)) * 3600);
+       my ($tz_sign, $tz_hour, $tz_min) =
+               ($tz =~ m/^([-+])(\d\d)(\d\d)$/);
+       $tz_sign = ($tz_sign eq '-' ? -1 : +1);
+       my $local = $epoch + $tz_sign*((($tz_hour*60) + $tz_min)*60);
        ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($local);
        $date{'hour_local'} = $hour;
        $date{'minute_local'} = $min;
@@ -4335,7 +4345,8 @@ sub git_difftree_body {
                                # link to patch
                                $patchno++;
                                print "<td class=\"link\">" .
-                                     $cgi->a({-href => "#patch$patchno"}, "patch") .
+                                     $cgi->a({-href => href(-anchor=>"patch$patchno")},
+                                             "patch") .
                                      " | " .
                                      "</td>\n";
                        }
@@ -4432,8 +4443,9 @@ sub git_difftree_body {
                        if ($action eq 'commitdiff') {
                                # link to patch
                                $patchno++;
-                               print $cgi->a({-href => "#patch$patchno"}, "patch");
-                               print " | ";
+                               print $cgi->a({-href => href(-anchor=>"patch$patchno")},
+                                             "patch") .
+                                     " | ";
                        }
                        print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'to_id'},
                                                     hash_base=>$hash, file_name=>$diff->{'file'})},
@@ -4452,8 +4464,9 @@ sub git_difftree_body {
                        if ($action eq 'commitdiff') {
                                # link to patch
                                $patchno++;
-                               print $cgi->a({-href => "#patch$patchno"}, "patch");
-                               print " | ";
+                               print $cgi->a({-href => href(-anchor=>"patch$patchno")},
+                                             "patch") .
+                                     " | ";
                        }
                        print $cgi->a({-href => href(action=>"blob", hash=>$diff->{'from_id'},
                                                     hash_base=>$parent, file_name=>$diff->{'file'})},
@@ -4494,7 +4507,8 @@ sub git_difftree_body {
                        if ($action eq 'commitdiff') {
                                # link to patch
                                $patchno++;
-                               print $cgi->a({-href => "#patch$patchno"}, "patch") .
+                               print $cgi->a({-href => href(-anchor=>"patch$patchno")},
+                                             "patch") .
                                      " | ";
                        } elsif ($diff->{'to_id'} ne $diff->{'from_id'}) {
                                # "commit" view and modified file (not onlu mode changed)
@@ -4539,7 +4553,8 @@ sub git_difftree_body {
                        if ($action eq 'commitdiff') {
                                # link to patch
                                $patchno++;
-                               print $cgi->a({-href => "#patch$patchno"}, "patch") .
+                               print $cgi->a({-href => href(-anchor=>"patch$patchno")},
+                                             "patch") .
                                      " | ";
                        } elsif ($diff->{'to_id'} ne $diff->{'from_id'}) {
                                # "commit" view and modified file (not only pure rename or copy)
diff --git a/graph.c b/graph.c
index f1a63c2241a30cce0141b87b5e8005b1a899a8ef..ef2e24e85a41dc97cf00bb7b19985ec01b8662bf 100644 (file)
--- a/graph.c
+++ b/graph.c
@@ -798,22 +798,9 @@ static void graph_output_commit_char(struct git_graph *graph, struct strbuf *sb)
        }
 
        /*
-        * If revs->left_right is set, print '<' for commits that
-        * come from the left side, and '>' for commits from the right
-        * side.
+        * get_revision_mark() handles all other cases without assert()
         */
-       if (graph->revs && graph->revs->left_right) {
-               if (graph->commit->object.flags & SYMMETRIC_LEFT)
-                       strbuf_addch(sb, '<');
-               else
-                       strbuf_addch(sb, '>');
-               return;
-       }
-
-       /*
-        * Print '*' in all other cases
-        */
-       strbuf_addch(sb, '*');
+       strbuf_addstr(sb, get_revision_mark(graph->revs, graph->commit));
 }
 
 /*
index 71506a8dd3ed07fe44c487a644ce9a42b94a7578..9adf4b981953080676aa24907fead1038b920e60 100644 (file)
@@ -1069,7 +1069,7 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
 
        if (srvc->tunnel) {
                const char *argv[] = { srvc->tunnel, NULL };
-               struct child_process tunnel = {0};
+               struct child_process tunnel = {NULL};
 
                imap_info("Starting tunnel '%s'... ", srvc->tunnel);
 
index 61f6cc98d917c3e4395ec397ac74df6a40eeb07f..838b6a732e4758265432cbc9c8e8fc81568a2b50 100644 (file)
@@ -173,7 +173,12 @@ void traverse_commit_list(struct rev_info *revs,
 
        strbuf_init(&base, PATH_MAX);
        while ((commit = get_revision(revs)) != NULL) {
-               add_pending_tree(revs, commit->tree);
+               /*
+                * an uninteresting boundary commit may not have its tree
+                * parsed yet, but we are not going to show them anyway
+                */
+               if (commit->tree)
+                       add_pending_tree(revs, commit->tree);
                show_commit(commit, data);
        }
        for (i = 0; i < revs->pending.nr; i++) {
index b46ed3baef7d9d9971a3886d700059217fbe974a..2a1e3a94c910cd74e41303d8b7aefa539817c831 100644 (file)
@@ -380,18 +380,8 @@ void show_log(struct rev_info *opt)
        if (!opt->verbose_header) {
                graph_show_commit(opt->graph);
 
-               if (!opt->graph) {
-                       if (commit->object.flags & BOUNDARY)
-                               putchar('-');
-                       else if (commit->object.flags & UNINTERESTING)
-                               putchar('^');
-                       else if (opt->left_right) {
-                               if (commit->object.flags & SYMMETRIC_LEFT)
-                                       putchar('<');
-                               else
-                                       putchar('>');
-                       }
-               }
+               if (!opt->graph)
+                       put_revision_mark(opt, commit);
                fputs(find_unique_abbrev(commit->object.sha1, abbrev_commit), stdout);
                if (opt->print_parents)
                        show_parents(commit, abbrev_commit);
@@ -448,18 +438,8 @@ void show_log(struct rev_info *opt)
                if (opt->commit_format != CMIT_FMT_ONELINE)
                        fputs("commit ", stdout);
 
-               if (!opt->graph) {
-                       if (commit->object.flags & BOUNDARY)
-                               putchar('-');
-                       else if (commit->object.flags & UNINTERESTING)
-                               putchar('^');
-                       else if (opt->left_right) {
-                               if (commit->object.flags & SYMMETRIC_LEFT)
-                                       putchar('<');
-                               else
-                                       putchar('>');
-                       }
-               }
+               if (!opt->graph)
+                       put_revision_mark(opt, commit);
                fputs(find_unique_abbrev(commit->object.sha1, abbrev_commit),
                      stdout);
                if (opt->print_parents)
index 1467ad31795ae21896f1e608e7cb032df2bc94a8..28046a998426e88dec9ad6ab431624bb41a81ce1 100644 (file)
@@ -359,7 +359,7 @@ static int ll_merge_in_worktree(struct notes_merge_options *o,
        read_mmblob(&remote, p->remote);
 
        status = ll_merge(&result_buf, sha1_to_hex(p->obj), &base, NULL,
-                         &local, o->local_ref, &remote, o->remote_ref, 0);
+                         &local, o->local_ref, &remote, o->remote_ref, NULL);
 
        free(base.ptr);
        free(local.ptr);
index 42b51ef14514f3c3df454e4b718718a9b58f1612..73bd28ad90986af1618d82176076133186d045de 100644 (file)
@@ -561,14 +561,14 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *ctx,
        return PARSE_OPT_HELP;
 }
 
-void usage_with_options(const char * const *usagestr,
+void NORETURN usage_with_options(const char * const *usagestr,
                        const struct option *opts)
 {
        usage_with_options_internal(NULL, usagestr, opts, 0, 1);
        exit(129);
 }
 
-void usage_msg_opt(const char *msg,
+void NORETURN usage_msg_opt(const char *msg,
                   const char * const *usagestr,
                   const struct option *options)
 {
index 65d20a7a2e7cafd79ff95c02cab3303ebb72351c..e1d8a8f414bf052a59fbe78d022e611f44ed8361 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -876,11 +876,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
                                              c->abbrev_parent_hashes.off;
                return 1;
        case 'm':               /* left/right/bottom */
-               strbuf_addch(sb, (commit->object.flags & BOUNDARY)
-                                ? '-'
-                                : (commit->object.flags & SYMMETRIC_LEFT)
-                                ? '<'
-                                : '>');
+               strbuf_addstr(sb, get_revision_mark(NULL, commit));
                return 1;
        case 'd':
                format_decoration(sb, commit);
index a03fabf060081e9fa5e0d753cd0d9cf4bca5062e..3fc6b1d320faad3a528db016a0d800ff1bdde4f0 100644 (file)
@@ -70,16 +70,11 @@ static void process_tree(struct tree *tree,
 static void process_tag(struct tag *tag, struct object_array *p, const char *name)
 {
        struct object *obj = &tag->object;
-       struct name_path me;
 
        if (obj->flags & SEEN)
                return;
        obj->flags |= SEEN;
 
-       me.up = NULL;
-       me.elem = "tag:/";
-       me.elem_len = 5;
-
        if (parse_tag(tag) < 0)
                die("bad tag object %s", sha1_to_hex(obj->sha1));
        if (tag->tagged)
index 98d526bd48d2a0e764dd0efb4c6efe4965174c9a..f38471cac3ac57d8d52429cde2dcc4cf5b92557b 100644 (file)
@@ -1547,6 +1547,31 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce)
        return result;
 }
 
+static int has_racy_timestamp(struct index_state *istate)
+{
+       int entries = istate->cache_nr;
+       int i;
+
+       for (i = 0; i < entries; i++) {
+               struct cache_entry *ce = istate->cache[i];
+               if (is_racy_timestamp(istate, ce))
+                       return 1;
+       }
+       return 0;
+}
+
+/*
+ * Opportunisticly update the index but do not complain if we can't
+ */
+void update_index_if_able(struct index_state *istate, struct lock_file *lockfile)
+{
+       if ((istate->cache_changed || has_racy_timestamp(istate)) &&
+           !write_index(istate, lockfile->fd))
+               commit_locked_index(lockfile);
+       else
+               rollback_lock_file(lockfile);
+}
+
 int write_index(struct index_state *istate, int newfd)
 {
        git_SHA_CTX c;
index eb59604fd39e2beaf7d43802499c27305ac92132..7c6c7544ada4585e62341f0c0854a919f10c2277 100644 (file)
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "sha1-lookup.h"
 #include "refs.h"
+#include "commit.h"
 
 static struct replace_object {
        unsigned char sha1[2][20];
index 22996bd08b532fb8016f24391dd0e63010706385..3d00a71ff9730ed4a10114185f4360de698c1fbf 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -590,8 +590,7 @@ static int is_rerere_enabled(void)
        if (rerere_enabled < 0)
                return rr_cache_exists;
 
-       if (!rr_cache_exists &&
-           (mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache)))
+       if (!rr_cache_exists && mkdir_in_gitdir(rr_cache))
                die("Could not create directory %s", rr_cache);
        return 1;
 }
index 86d24704896d71de7bb554a3925ea88e2be3417b..0f38364cf3f81a9088305ca802adf8b7c9260e91 100644 (file)
@@ -535,6 +535,7 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
        int left_count = 0, right_count = 0;
        int left_first;
        struct patch_ids ids;
+       unsigned cherry_flag;
 
        /* First count the commits on the left and on the right */
        for (p = list; p; p = p->next) {
@@ -572,6 +573,9 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
                commit->util = add_commit_patch_id(commit, &ids);
        }
 
+       /* either cherry_mark or cherry_pick are true */
+       cherry_flag = revs->cherry_mark ? PATCHSAME : SHOWN;
+
        /* Check the other side */
        for (p = list; p; p = p->next) {
                struct commit *commit = p->item;
@@ -594,7 +598,7 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
                if (!id)
                        continue;
                id->seen = 1;
-               commit->object.flags |= SHOWN;
+               commit->object.flags |= cherry_flag;
        }
 
        /* Now check the original side for seen ones */
@@ -606,7 +610,7 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
                if (!ent)
                        continue;
                if (ent->seen)
-                       commit->object.flags |= SHOWN;
+                       commit->object.flags |= cherry_flag;
                commit->util = NULL;
        }
 
@@ -729,6 +733,23 @@ static struct commit_list *collect_bottom_commits(struct commit_list *list)
        return bottom;
 }
 
+/* Assumes either left_only or right_only is set */
+static void limit_left_right(struct commit_list *list, struct rev_info *revs)
+{
+       struct commit_list *p;
+
+       for (p = list; p; p = p->next) {
+               struct commit *commit = p->item;
+
+               if (revs->right_only) {
+                       if (commit->object.flags & SYMMETRIC_LEFT)
+                               commit->object.flags |= SHOWN;
+               } else  /* revs->left_only is set */
+                       if (!(commit->object.flags & SYMMETRIC_LEFT))
+                               commit->object.flags |= SHOWN;
+       }
+}
+
 static int limit_list(struct rev_info *revs)
 {
        int slop = SLOP;
@@ -781,9 +802,12 @@ static int limit_list(struct rev_info *revs)
                show(revs, newlist);
                show_early_output = NULL;
        }
-       if (revs->cherry_pick)
+       if (revs->cherry_pick || revs->cherry_mark)
                cherry_pick_list(newlist, revs);
 
+       if (revs->left_only || revs->right_only)
+               limit_left_right(newlist, revs);
+
        if (bottom) {
                limit_to_ancestry(bottom, newlist);
                free_commit_list(bottom);
@@ -917,6 +941,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)
        revs->min_age = -1;
        revs->skip_count = -1;
        revs->max_count = -1;
+       revs->max_parents = -1;
 
        revs->commit_format = CMIT_FMT_DEFAULT;
 
@@ -1253,16 +1278,47 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        } else if (!strcmp(arg, "--remove-empty")) {
                revs->remove_empty_trees = 1;
        } else if (!strcmp(arg, "--merges")) {
-               revs->merges_only = 1;
+               revs->min_parents = 2;
        } else if (!strcmp(arg, "--no-merges")) {
-               revs->no_merges = 1;
+               revs->max_parents = 1;
+       } else if (!prefixcmp(arg, "--min-parents=")) {
+               revs->min_parents = atoi(arg+14);
+       } else if (!prefixcmp(arg, "--no-min-parents")) {
+               revs->min_parents = 0;
+       } else if (!prefixcmp(arg, "--max-parents=")) {
+               revs->max_parents = atoi(arg+14);
+       } else if (!prefixcmp(arg, "--no-max-parents")) {
+               revs->max_parents = -1;
        } else if (!strcmp(arg, "--boundary")) {
                revs->boundary = 1;
        } else if (!strcmp(arg, "--left-right")) {
                revs->left_right = 1;
+       } else if (!strcmp(arg, "--left-only")) {
+               if (revs->right_only)
+                       die("--left-only is incompatible with --right-only"
+                           " or --cherry");
+               revs->left_only = 1;
+       } else if (!strcmp(arg, "--right-only")) {
+               if (revs->left_only)
+                       die("--right-only is incompatible with --left-only");
+               revs->right_only = 1;
+       } else if (!strcmp(arg, "--cherry")) {
+               if (revs->left_only)
+                       die("--cherry is incompatible with --left-only");
+               revs->cherry_mark = 1;
+               revs->right_only = 1;
+               revs->max_parents = 1;
+               revs->limited = 1;
        } else if (!strcmp(arg, "--count")) {
                revs->count = 1;
+       } else if (!strcmp(arg, "--cherry-mark")) {
+               if (revs->cherry_pick)
+                       die("--cherry-mark is incompatible with --cherry-pick");
+               revs->cherry_mark = 1;
+               revs->limited = 1; /* needs limit_list() */
        } else if (!strcmp(arg, "--cherry-pick")) {
+               if (revs->cherry_mark)
+                       die("--cherry-pick is incompatible with --cherry-mark");
                revs->cherry_pick = 1;
                revs->limited = 1;
        } else if (!strcmp(arg, "--objects")) {
@@ -1982,10 +2038,15 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi
                return commit_ignore;
        if (revs->min_age != -1 && (commit->date > revs->min_age))
                return commit_ignore;
-       if (revs->no_merges && commit->parents && commit->parents->next)
-               return commit_ignore;
-       if (revs->merges_only && !(commit->parents && commit->parents->next))
-               return commit_ignore;
+       if (revs->min_parents || (revs->max_parents >= 0)) {
+               int n = 0;
+               struct commit_list *p;
+               for (p = commit->parents; p; p = p->next)
+                       n++;
+               if ((n < revs->min_parents) ||
+                   ((revs->max_parents >= 0) && (n > revs->max_parents)))
+                       return commit_ignore;
+       }
        if (!commit_match(commit, revs))
                return commit_ignore;
        if (revs->prune && revs->dense) {
@@ -2232,3 +2293,32 @@ struct commit *get_revision(struct rev_info *revs)
                graph_update(revs->graph, c);
        return c;
 }
+
+char *get_revision_mark(const struct rev_info *revs, const struct commit *commit)
+{
+       if (commit->object.flags & BOUNDARY)
+               return "-";
+       else if (commit->object.flags & UNINTERESTING)
+               return "^";
+       else if (commit->object.flags & PATCHSAME)
+               return "=";
+       else if (!revs || revs->left_right) {
+               if (commit->object.flags & SYMMETRIC_LEFT)
+                       return "<";
+               else
+                       return ">";
+       } else if (revs->graph)
+               return "*";
+       else if (revs->cherry_mark)
+               return "+";
+       return "";
+}
+
+void put_revision_mark(const struct rev_info *revs, const struct commit *commit)
+{
+       char *mark = get_revision_mark(revs, commit);
+       if (!strlen(mark))
+               return;
+       fputs(mark, stdout);
+       putchar(' ');
+}
index 82509dd1d9ad7b1824971be4884409060f10aee3..9fd8f3016fe8f935f176f57c615f72df8ba8d157 100644 (file)
@@ -14,7 +14,8 @@
 #define CHILD_SHOWN    (1u<<6)
 #define ADDED          (1u<<7) /* Parents already parsed and added? */
 #define SYMMETRIC_LEFT (1u<<8)
-#define ALL_REV_FLAGS  ((1u<<9)-1)
+#define PATCHSAME      (1u<<9)
+#define ALL_REV_FLAGS  ((1u<<10)-1)
 
 #define DECORATE_SHORT_REFS    1
 #define DECORATE_FULL_REFS     2
@@ -40,8 +41,6 @@ struct rev_info {
        /* Traversal flags */
        unsigned int    dense:1,
                        prune:1,
-                       no_merges:1,
-                       merges_only:1,
                        no_walk:1,
                        show_all:1,
                        remove_empty_trees:1,
@@ -59,6 +58,8 @@ struct rev_info {
                        boundary:2,
                        count:1,
                        left_right:1,
+                       left_only:1,
+                       right_only:1,
                        rewrite_parents:1,
                        print_parents:1,
                        show_source:1,
@@ -66,6 +67,7 @@ struct rev_info {
                        reverse:1,
                        reverse_output_stage:1,
                        cherry_pick:1,
+                       cherry_mark:1,
                        bisect:1,
                        ancestry_path:1,
                        first_parent_only:1;
@@ -122,6 +124,8 @@ struct rev_info {
        int max_count;
        unsigned long max_age;
        unsigned long min_age;
+       int min_parents;
+       int max_parents;
 
        /* diff info for patches and for paths limiting */
        struct diff_options diffopt;
@@ -163,6 +167,8 @@ extern int handle_revision_arg(const char *arg, struct rev_info *revs,int flags,
 
 extern int prepare_revision_walk(struct rev_info *revs);
 extern struct commit *get_revision(struct rev_info *revs);
+extern char *get_revision_mark(const struct rev_info *revs, const struct commit *commit);
+extern void put_revision_mark(const struct rev_info *revs, const struct commit *commit);
 
 extern void mark_parents_uninteresting(struct commit *commit);
 extern void mark_tree_uninteresting(struct tree *tree);
index f91e446c86be8e27f98554567143d7ce6f934bd1..8619c769a93c48e724957c019af5765ebee6af9f 100644 (file)
@@ -67,21 +67,26 @@ static int child_notifier = -1;
 
 static void notify_parent(void)
 {
-       ssize_t unused;
-       unused = write(child_notifier, "", 1);
+       /*
+        * execvp failed.  If possible, we'd like to let start_command
+        * know, so failures like ENOENT can be handled right away; but
+        * otherwise, finish_command will still report the error.
+        */
+       if (write(child_notifier, "", 1))
+               ; /* yes, dear gcc -D_FORTIFY_SOURCE, there was an error. */
 }
 
 static NORETURN void die_child(const char *err, va_list params)
 {
        char msg[4096];
-       ssize_t unused;
        int len = vsnprintf(msg, sizeof(msg), err, params);
        if (len > sizeof(msg))
                len = sizeof(msg);
 
-       unused = write(child_err, "fatal: ", 7);
-       unused = write(child_err, msg, len);
-       unused = write(child_err, "\n", 1);
+       if (write(child_err, "fatal: ", 7) ||
+           write(child_err, msg, len) ||
+           write(child_err, "\n", 1))
+               ; /* yes, gcc -D_FORTIFY_SOURCE, we know there was an error. */
        exit(128);
 }
 #endif
index b4fcca8ffdbfe48b11478709c61eb90cd64de20d..df0edbad1e810727e384a5753001dc8c85d4ecf9 100644 (file)
 #endif
 #endif
 
-#ifdef NO_C99_FORMAT
-#define SZ_FMT "lu"
-static unsigned long sz_fmt(size_t s) { return (unsigned long)s; }
-#else
-#define SZ_FMT "zu"
-static size_t sz_fmt(size_t s) { return s; }
-#endif
+#define SZ_FMT PRIuMAX
+static inline uintmax_t sz_fmt(size_t s) { return s; }
 
 const unsigned char null_sha1[20];
 
@@ -73,6 +68,35 @@ static struct cached_object *find_cached_object(const unsigned char *sha1)
        return NULL;
 }
 
+int mkdir_in_gitdir(const char *path)
+{
+       if (mkdir(path, 0777)) {
+               int saved_errno = errno;
+               struct stat st;
+               struct strbuf sb = STRBUF_INIT;
+
+               if (errno != EEXIST)
+                       return -1;
+               /*
+                * Are we looking at a path in a symlinked worktree
+                * whose original repository does not yet have it?
+                * e.g. .git/rr-cache pointing at its original
+                * repository in which the user hasn't performed any
+                * conflict resolution yet?
+                */
+               if (lstat(path, &st) || !S_ISLNK(st.st_mode) ||
+                   strbuf_readlink(&sb, path, st.st_size) ||
+                   !is_absolute_path(sb.buf) ||
+                   mkdir(sb.buf, 0777)) {
+                       strbuf_release(&sb);
+                       errno = saved_errno;
+                       return -1;
+               }
+               strbuf_release(&sb);
+       }
+       return adjust_shared_perm(path);
+}
+
 int safe_create_leading_directories(char *path)
 {
        char *pos = path + offset_1st_component(path);
index f722331470065f448197ea461ef3af06d3623ff2..07060ce893d8303b7eb4d78db0f7a5575527f88f 100644 (file)
--- a/strbuf.h
+++ b/strbuf.h
@@ -1,42 +1,7 @@
 #ifndef STRBUF_H
 #define STRBUF_H
 
-/*
- * Strbuf's can be use in many ways: as a byte array, or to store arbitrary
- * long, overflow safe strings.
- *
- * Strbufs has some invariants that are very important to keep in mind:
- *
- * 1. the ->buf member is always malloc-ed, hence strbuf's can be used to
- *    build complex strings/buffers whose final size isn't easily known.
- *
- *    It is NOT legal to copy the ->buf pointer away.
- *    `strbuf_detach' is the operation that detaches a buffer from its shell
- *    while keeping the shell valid wrt its invariants.
- *
- * 2. the ->buf member is a byte array that has at least ->len + 1 bytes
- *    allocated. The extra byte is used to store a '\0', allowing the ->buf
- *    member to be a valid C-string. Every strbuf function ensures this
- *    invariant is preserved.
- *
- *    Note that it is OK to "play" with the buffer directly if you work it
- *    that way:
- *
- *    strbuf_grow(sb, SOME_SIZE);
- *       ... Here, the memory array starting at sb->buf, and of length
- *       ... strbuf_avail(sb) is all yours, and you are sure that
- *       ... strbuf_avail(sb) is at least SOME_SIZE.
- *    strbuf_setlen(sb, sb->len + SOME_OTHER_SIZE);
- *
- *    Of course, SOME_OTHER_SIZE must be smaller or equal to strbuf_avail(sb).
- *
- *    Doing so is safe, though if it has to be done in many places, adding the
- *    missing API to the strbuf module is the way to go.
- *
- *    XXX: do _not_ assume that the area that is yours is of size ->alloc - 1
- *         even if it's true in the current implementation. Alloc is somehow a
- *         "private" member that should not be messed with.
- */
+/* See Documentation/technical/api-strbuf.txt */
 
 #include <assert.h>
 
index e9f2b19e1c867b870b0b5f3ef3db3c871fe20689..0cb6d1829944b8a6d0f1a7ed1c228b61c31c7e0d 100644 (file)
@@ -9,9 +9,9 @@
 #include "refs.h"
 #include "string-list.h"
 
-struct string_list config_name_for_path;
-struct string_list config_fetch_recurse_submodules_for_name;
-struct string_list config_ignore_for_name;
+static struct string_list config_name_for_path;
+static struct string_list config_fetch_recurse_submodules_for_name;
+static struct string_list config_ignore_for_name;
 static int config_fetch_recurse_submodules;
 
 static int add_submodule_odb(const char *path)
index ccf6a53377804153f7a516031d5bab4ef6da4016..428ee05c4a5b844815ff4f9356b71bb147cb42a6 100644 (file)
--- a/t/README
+++ b/t/README
@@ -201,7 +201,7 @@ we are testing.
 If you create files under t/ directory (i.e. here) that is not
 the top-level test script, never name the file to match the above
 pattern.  The Makefile here considers all such files as the
-top-level test script and tries to run all of them.  A care is
+top-level test script and tries to run all of them.  Care is
 especially needed if you are creating a common test library
 file, similar to test-lib.sh, because such a library file may
 not be suitable for standalone execution.
@@ -285,9 +285,8 @@ Do:
  - Check the test coverage for your tests. See the "Test coverage"
    below.
 
-   Don't blindly follow test coverage metrics, they're a good way to
-   spot if you've missed something. If a new function you added
-   doesn't have any coverage you're probably doing something wrong,
+   Don't blindly follow test coverage metrics; if a new function you added
+   doesn't have any coverage, then you're probably doing something wrong,
    but having 100% coverage doesn't necessarily mean that you tested
    everything.
 
@@ -431,7 +430,7 @@ library for your script to use.
  - test_tick
 
    Make commit and tag names consistent by setting the author and
-   committer times to defined stated.  Subsequent calls will
+   committer times to defined state.  Subsequent calls will
    advance the times by a fixed amount.
 
  - test_commit <message> [<filename> [<contents>]]
index f6849932112f1bbea1dafad09150857a707b64e4..ce4ba1379ef05066cc697cdc7fdf53f8c40f58ee 100755 (executable)
@@ -47,7 +47,7 @@ test_expect_success 'plain nested in bare' '
 
 test_expect_success 'plain through aliased command, outside any git repo' '
        (
-               sane_unset GIT_DIR GIT_WORK_TREE GIT_CONFIG_NOGLOBAL &&
+               sane_unset GIT_DIR GIT_WORK_TREE &&
                HOME=$(pwd)/alias-config &&
                export HOME &&
                mkdir alias-config &&
@@ -231,7 +231,6 @@ test_expect_success 'init with init.templatedir set' '
                git config -f "$test_config"  init.templatedir "${HOME}/templatedir-source" &&
                mkdir templatedir-set &&
                cd templatedir-set &&
-               sane_unset GIT_CONFIG_NOGLOBAL &&
                sane_unset GIT_TEMPLATE_DIR &&
                NO_SET_GIT_TEMPLATE_DIR=t &&
                export NO_SET_GIT_TEMPLATE_DIR &&
@@ -243,7 +242,6 @@ test_expect_success 'init with init.templatedir set' '
 test_expect_success 'init --bare/--shared overrides system/global config' '
        (
                test_config="$HOME"/.gitconfig &&
-               sane_unset GIT_CONFIG_NOGLOBAL &&
                git config -f "$test_config" core.bare false &&
                git config -f "$test_config" core.sharedRepository 0640 &&
                mkdir init-bare-shared-override &&
@@ -258,7 +256,6 @@ test_expect_success 'init --bare/--shared overrides system/global config' '
 test_expect_success 'init honors global core.sharedRepository' '
        (
                test_config="$HOME"/.gitconfig &&
-               sane_unset GIT_CONFIG_NOGLOBAL &&
                git config -f "$test_config" core.sharedRepository 0666 &&
                mkdir shared-honor-global &&
                cd shared-honor-global &&
index 550fad0823a8d27cf1d49b1c55154ea7ce69de02..5067d1e15b566721c1a3ae79052cbcb023a03656 100755 (executable)
@@ -47,13 +47,13 @@ long_read_test () {
        rm -f input &&
        mkfifo input &&
        {
-               {
+               (
                        generate_tens_of_lines $tens_of_lines "$line" &&
-                       sleep 100
-               } >input &
+                       exec sleep 100
+               ) >input &
        } &&
        test-line-buffer input <<-EOF >output &&
-       read $readsize
+       binary $readsize
        copy $copysize
        EOF
        kill $! &&
@@ -71,23 +71,23 @@ test_expect_success 'setup: have pipes?' '
 '
 
 test_expect_success 'hello world' '
-       echo HELLO >expect &&
+       echo ">HELLO" >expect &&
        test-line-buffer <<-\EOF >actual &&
-       read 6
+       binary 6
        HELLO
        EOF
        test_cmp expect actual
 '
 
 test_expect_success PIPE '0-length read, no input available' '
-       >expect &&
+       printf ">" >expect &&
        rm -f input &&
        mkfifo input &&
        {
                sleep 100 >input &
        } &&
        test-line-buffer input <<-\EOF >actual &&
-       read 0
+       binary 0
        copy 0
        EOF
        kill $! &&
@@ -95,9 +95,9 @@ test_expect_success PIPE '0-length read, no input available' '
 '
 
 test_expect_success '0-length read, send along greeting' '
-       echo HELLO >expect &&
+       echo ">HELLO" >expect &&
        test-line-buffer <<-\EOF >actual &&
-       read 0
+       binary 0
        copy 6
        HELLO
        EOF
@@ -105,18 +105,18 @@ test_expect_success '0-length read, send along greeting' '
 '
 
 test_expect_success PIPE '1-byte read, no input available' '
-       printf "%s" ab >expect &&
+       printf ">%s" ab >expect &&
        rm -f input &&
        mkfifo input &&
        {
-               {
+               (
                        printf "%s" a &&
                        printf "%s" b &&
-                       sleep 100
-               } >input &
+                       exec sleep 100
+               ) >input &
        } &&
        test-line-buffer input <<-\EOF >actual &&
-       read 1
+       binary 1
        copy 1
        EOF
        kill $! &&
@@ -140,15 +140,6 @@ test_expect_success 'read from file descriptor' '
        test_cmp expect actual
 '
 
-test_expect_success 'buffer_read_string copes with null byte' '
-       >expect &&
-       q_to_nul <<-\EOF | test-line-buffer >actual &&
-       read 2
-       Q
-       EOF
-       test_cmp expect actual
-'
-
 test_expect_success 'skip, copy null byte' '
        echo Q | q_to_nul >expect &&
        q_to_nul <<-\EOF | test-line-buffer >actual &&
@@ -170,18 +161,18 @@ test_expect_success 'read null byte' '
 '
 
 test_expect_success 'long reads are truncated' '
-       echo foo >expect &&
+       echo ">foo" >expect &&
        test-line-buffer <<-\EOF >actual &&
-       read 5
+       binary 5
        foo
        EOF
        test_cmp expect actual
 '
 
 test_expect_success 'long copies are truncated' '
-       printf "%s\n" "" foo >expect &&
+       printf "%s\n" ">" foo >expect &&
        test-line-buffer <<-\EOF >actual &&
-       read 1
+       binary 1
 
        copy 5
        foo
diff --git a/t/t1021-rerere-in-workdir.sh b/t/t1021-rerere-in-workdir.sh
new file mode 100755 (executable)
index 0000000..301e071
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+test_description='rerere run in a workdir'
+. ./test-lib.sh
+
+test_expect_success SYMLINKS setup '
+       git config rerere.enabled true &&
+       >world &&
+       git add world &&
+       test_tick &&
+       git commit -m initial &&
+
+       echo hello >world &&
+       test_tick &&
+       git commit -a -m hello &&
+
+       git checkout -b side HEAD^ &&
+       echo goodbye >world &&
+       test_tick &&
+       git commit -a -m goodbye &&
+
+       git checkout master
+'
+
+test_expect_success SYMLINKS 'rerere in workdir' '
+       rm -rf .git/rr-cache &&
+       "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" . work &&
+       (
+               cd work &&
+               test_must_fail git merge side &&
+               git rerere status >actual &&
+               echo world >expect &&
+               test_cmp expect actual
+       )
+'
+
+# This fails because we don't resolve relative symlink in mkdir_in_gitdir()
+# For the purpose of helping contrib/workdir/git-new-workdir users, we do not
+# have to support relative symlinks, but it might be nicer to make this work
+# with a relative symbolic link someday.
+test_expect_failure SYMLINKS 'rerere in workdir (relative)' '
+       rm -rf .git/rr-cache &&
+       "$SHELL_PATH" "$TEST_DIRECTORY/../contrib/workdir/git-new-workdir" . krow &&
+       (
+               cd krow &&
+               rm -f .git/rr-cache &&
+               ln -s ../.git/rr-cache .git/rr-cache &&
+               test_must_fail git merge side &&
+               git rerere status >actual &&
+               echo world >expect &&
+               test_cmp expect actual
+       )
+'
+
+test_done
index 00421453ba26327b929fa7b5133a3072fce2bb03..569b27fe8d488833c3ec0d9952ae064764a0183f 100755 (executable)
@@ -11,6 +11,14 @@ check_not_detached () {
        git symbolic-ref -q HEAD >/dev/null
 }
 
+ORPHAN_WARNING='you are leaving .* commit.*behind'
+check_orphan_warning() {
+       grep "$ORPHAN_WARNING" "$1"
+}
+check_no_orphan_warning() {
+       ! grep "$ORPHAN_WARNING" "$1"
+}
+
 reset () {
        git checkout master &&
        check_not_detached
@@ -19,6 +27,8 @@ reset () {
 test_expect_success 'setup' '
        test_commit one &&
        test_commit two &&
+       test_commit three && git tag -d three &&
+       test_commit four && git tag -d four &&
        git branch branch &&
        git tag tag
 '
@@ -92,4 +102,41 @@ test_expect_success 'checkout --detach moves HEAD' '
        git diff --exit-code two
 '
 
+test_expect_success 'checkout warns on orphan commits' '
+       reset &&
+       git checkout --detach two &&
+       echo content >orphan &&
+       git add orphan &&
+       git commit -a -m orphan &&
+       git checkout master 2>stderr &&
+       check_orphan_warning stderr
+'
+
+test_expect_success 'checkout does not warn leaving ref tip' '
+       reset &&
+       git checkout --detach two &&
+       git checkout master 2>stderr &&
+       check_no_orphan_warning stderr
+'
+
+test_expect_success 'checkout does not warn leaving reachable commit' '
+       reset &&
+       git checkout --detach HEAD^ &&
+       git checkout master 2>stderr &&
+       check_no_orphan_warning stderr
+'
+
+cat >expect <<'EOF'
+Your branch is behind 'master' by 1 commit, and can be fast-forwarded.
+EOF
+test_expect_success 'tracking count is accurate after orphan check' '
+       reset &&
+       git branch child master^ &&
+       git config branch.child.remote . &&
+       git config branch.child.merge refs/heads/master &&
+       git checkout child^ &&
+       git checkout child >stdout &&
+       test_cmp expect stdout
+'
+
 test_done
index 6fd560ccf10db5d016a4f1dde9e5eacca70e6f5b..f62aaf5816f6ecf4e2c4e8fe5ae60925e61ccfcd 100755 (executable)
@@ -556,4 +556,23 @@ test_expect_success 'stash branch should not drop the stash if the branch exists
        git rev-parse stash@{0} --
 '
 
+test_expect_success 'stash apply shows status same as git status (relative to current directory)' '
+       git stash clear &&
+       echo 1 >subdir/subfile1 &&
+       echo 2 >subdir/subfile2 &&
+       git add subdir/subfile1 &&
+       git commit -m subdir &&
+       (
+               cd subdir &&
+               echo x >subfile1 &&
+               echo x >../file &&
+               git status >../expect &&
+               git stash &&
+               sane_unset GIT_MERGE_VERBOSITY &&
+               git stash apply
+       ) |
+       sed -e 1,2d >actual && # drop "Saved..." and "HEAD is now..."
+       test_cmp expect actual
+'
+
 test_done
index a30b03bcf27ba360c3761ade77ddf0ed00600470..abc49348b196cf0fec232b6f2399356e4fe324d5 100755 (executable)
@@ -60,4 +60,11 @@ test_expect_success 'diff-files -b -p --exit-code' '
        git diff-files -b -p --exit-code
 '
 
+test_expect_success 'diff-files --diff-filter --quiet' '
+       git reset --hard &&
+       rm a/d &&
+       echo x >>b/e &&
+       test_must_fail git diff-files --diff-filter=M --quiet
+'
+
 test_done
diff --git a/t/t5501-fetch-push-alternates.sh b/t/t5501-fetch-push-alternates.sh
new file mode 100755 (executable)
index 0000000..b5ced84
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+test_description='fetch/push involving alternates'
+. ./test-lib.sh
+
+count_objects () {
+       loose=0 inpack=0
+       eval "$(
+               git count-objects -v |
+               sed -n -e 's/^count: \(.*\)/loose=\1/p' \
+                   -e 's/^in-pack: \(.*\)/inpack=\1/p'
+       )" &&
+       echo $(( $loose + $inpack ))
+}
+
+
+test_expect_success setup '
+       (
+               git init original &&
+               cd original &&
+               i=0 &&
+               while test $i -le 100
+               do
+                       echo "$i" >count &&
+                       git add count &&
+                       git commit -m "$i" || exit
+                       i=$(($i + 1))
+               done
+       ) &&
+       (
+               git clone --reference=original "file:///$(pwd)/original" one &&
+               cd one &&
+               echo Z >count &&
+               git add count &&
+               git commit -m Z &&
+               count_objects >../one.count
+       ) &&
+       A=$(pwd)/original/.git/objects &&
+       git init receiver &&
+       echo "$A" >receiver/.git/objects/info/alternates &&
+       git init fetcher &&
+       echo "$A" >fetcher/.git/objects/info/alternates
+'
+
+test_expect_success 'pushing into a repository with the same alternate' '
+       (
+               cd one &&
+               git push ../receiver master:refs/heads/it
+       ) &&
+       (
+               cd receiver &&
+               count_objects >../receiver.count
+       ) &&
+       test_cmp one.count receiver.count
+'
+
+test_expect_success 'fetching from a repository with the same alternate' '
+       (
+               cd fetcher &&
+               git fetch ../one master:refs/heads/it &&
+               count_objects >../fetcher.count
+       ) &&
+       test_cmp one.count fetcher.count
+'
+
+test_done
index 987e0c846309a8a49dbe31ce292edd55342217b3..3ca275cc671502febd8397e1828c612f575c5b89 100755 (executable)
@@ -164,7 +164,6 @@ test_expect_success 'clone a void' '
 test_expect_success 'clone respects global branch.autosetuprebase' '
        (
                test_config="$HOME/.gitconfig" &&
-               unset GIT_CONFIG_NOGLOBAL &&
                git config -f "$test_config" branch.autosetuprebase remote &&
                rm -fr dst &&
                git clone src dst &&
index b565638e92655c12c841c29a108516a8b13cf8d2..cacf3de6c9f31889fd8df0bc0cebbbc74e3525bd 100755 (executable)
@@ -4,13 +4,14 @@ test_description='test git rev-list --cherry-pick -- file'
 
 . ./test-lib.sh
 
-# A---B
+# A---B---D---F
 #  \
 #   \
-#    C
+#    C---E
 #
 # B changes a file foo.c, adding a line of text.  C changes foo.c as
 # well as bar.c, but the change in foo.c was identical to change B.
+# D and C change bar in the same way, E and F differently.
 
 test_expect_success setup '
        echo Hallo > foo &&
@@ -25,11 +26,26 @@ test_expect_success setup '
        test_tick &&
        git commit -m "C" &&
        git tag C &&
+       echo Dello > bar &&
+       git add bar &&
+       test_tick &&
+       git commit -m "E" &&
+       git tag E &&
        git checkout master &&
        git checkout branch foo &&
        test_tick &&
        git commit -m "B" &&
-       git tag B
+       git tag B &&
+       echo Cello > bar &&
+       git add bar &&
+       test_tick &&
+       git commit -m "D" &&
+       git tag D &&
+       echo Nello > bar &&
+       git add bar &&
+       test_tick &&
+       git commit -m "F" &&
+       git tag F
 '
 
 cat >expect <<EOF
@@ -53,8 +69,92 @@ test_expect_success '--cherry-pick foo comes up empty' '
        test -z "$(git rev-list --left-right --cherry-pick B...C -- foo)"
 '
 
+cat >expect <<EOF
+>tags/C
+EOF
+
 test_expect_success '--cherry-pick bar does not come up empty' '
-       ! test -z "$(git rev-list --left-right --cherry-pick B...C -- bar)"
+       git rev-list --left-right --cherry-pick B...C -- bar > actual &&
+       git name-rev --stdin --name-only --refs="*tags/*" \
+               < actual > actual.named &&
+       test_cmp actual.named expect
+'
+
+test_expect_success 'bar does not come up empty' '
+       git rev-list --left-right B...C -- bar > actual &&
+       git name-rev --stdin --name-only --refs="*tags/*" \
+               < actual > actual.named &&
+       test_cmp actual.named expect
+'
+
+cat >expect <<EOF
+<tags/F
+>tags/E
+EOF
+
+test_expect_success '--cherry-pick bar does not come up empty (II)' '
+       git rev-list --left-right --cherry-pick F...E -- bar > actual &&
+       git name-rev --stdin --name-only --refs="*tags/*" \
+               < actual > actual.named &&
+       test_cmp actual.named expect
+'
+
+cat >expect <<EOF
++tags/F
+=tags/D
++tags/E
+=tags/C
+EOF
+
+test_expect_success '--cherry-mark' '
+       git rev-list --cherry-mark F...E -- bar > actual &&
+       git name-rev --stdin --name-only --refs="*tags/*" \
+               < actual > actual.named &&
+       test_cmp actual.named expect
+'
+
+cat >expect <<EOF
+<tags/F
+=tags/D
+>tags/E
+=tags/C
+EOF
+
+test_expect_success '--cherry-mark --left-right' '
+       git rev-list --cherry-mark --left-right F...E -- bar > actual &&
+       git name-rev --stdin --name-only --refs="*tags/*" \
+               < actual > actual.named &&
+       test_cmp actual.named expect
+'
+
+cat >expect <<EOF
+tags/E
+EOF
+
+test_expect_success '--cherry-pick --right-only' '
+       git rev-list --cherry-pick --right-only F...E -- bar > actual &&
+       git name-rev --stdin --name-only --refs="*tags/*" \
+               < actual > actual.named &&
+       test_cmp actual.named expect
+'
+
+test_expect_success '--cherry-pick --left-only' '
+       git rev-list --cherry-pick --left-only E...F -- bar > actual &&
+       git name-rev --stdin --name-only --refs="*tags/*" \
+               < actual > actual.named &&
+       test_cmp actual.named expect
+'
+
+cat >expect <<EOF
++tags/E
+=tags/C
+EOF
+
+test_expect_success '--cherry' '
+       git rev-list --cherry F...E -- bar > actual &&
+       git name-rev --stdin --name-only --refs="*tags/*" \
+               < actual > actual.named &&
+       test_cmp actual.named expect
 '
 
 test_expect_success '--cherry-pick with independent, but identical branches' '
@@ -75,11 +175,8 @@ cat >expect <<EOF
 1      2
 EOF
 
-# Insert an extra commit to break the symmetry
 test_expect_success '--count --left-right' '
-       git checkout branch &&
-       test_commit D &&
-       git rev-list --count --left-right B...D > actual &&
+       git rev-list --count --left-right C...D > actual &&
        test_cmp expect actual
 '
 
index 52f7b277ceae3ae183bc6082c01af9f76bd39a86..30507407ff6375f96c632c7c3f62ae3d338ed5ea 100755 (executable)
@@ -1,14 +1,15 @@
 #!/bin/sh
 
-test_description='properly cull all ancestors'
+test_description='ancestor culling and limiting by parent number'
 
 . ./test-lib.sh
 
-commit () {
-       test_tick &&
-       echo $1 >file &&
-       git commit -a -m $1 &&
-       git tag $1
+check_revlist () {
+       rev_list_args="$1" &&
+       shift &&
+       git rev-parse "$@" >expect &&
+       git rev-list $rev_list_args --all >actual &&
+       test_cmp expect actual
 }
 
 test_expect_success setup '
@@ -16,13 +17,13 @@ test_expect_success setup '
        touch file &&
        git add file &&
 
-       commit one &&
+       test_commit one &&
 
        test_tick=$(($test_tick - 2400)) &&
 
-       commit two &&
-       commit three &&
-       commit four &&
+       test_commit two &&
+       test_commit three &&
+       test_commit four &&
 
        git log --pretty=oneline --abbrev-commit
 '
@@ -35,4 +36,101 @@ test_expect_success 'one is ancestor of others and should not be shown' '
 
 '
 
+test_expect_success 'setup roots, merges and octopuses' '
+
+       git checkout --orphan newroot &&
+       test_commit five &&
+       git checkout -b sidebranch two &&
+       test_commit six &&
+       git checkout -b anotherbranch three &&
+       test_commit seven &&
+       git checkout -b yetanotherbranch four &&
+       test_commit eight &&
+       git checkout master &&
+       test_merge normalmerge newroot &&
+       test_tick &&
+       git merge -m tripus sidebranch anotherbranch &&
+       git tag tripus &&
+       git checkout -b tetrabranch normalmerge &&
+       test_tick &&
+       git merge -m tetrapus sidebranch anotherbranch yetanotherbranch &&
+       git tag tetrapus &&
+       git checkout master
+'
+
+test_expect_success 'rev-list roots' '
+
+       check_revlist "--max-parents=0" one five
+'
+
+test_expect_success 'rev-list no merges' '
+
+       check_revlist "--max-parents=1" one eight seven six five four three two &&
+       check_revlist "--no-merges" one eight seven six five four three two
+'
+
+test_expect_success 'rev-list no octopuses' '
+
+       check_revlist "--max-parents=2" one normalmerge eight seven six five four three two
+'
+
+test_expect_success 'rev-list no roots' '
+
+       check_revlist "--min-parents=1" tetrapus tripus normalmerge eight seven six four three two
+'
+
+test_expect_success 'rev-list merges' '
+
+       check_revlist "--min-parents=2" tetrapus tripus normalmerge &&
+       check_revlist "--merges" tetrapus tripus normalmerge
+'
+
+test_expect_success 'rev-list octopus' '
+
+       check_revlist "--min-parents=3" tetrapus tripus
+'
+
+test_expect_success 'rev-list ordinary commits' '
+
+       check_revlist "--min-parents=1 --max-parents=1" eight seven six four three two
+'
+
+test_expect_success 'rev-list --merges --no-merges yields empty set' '
+
+       check_revlist "--min-parents=2 --no-merges" &&
+       check_revlist "--merges --no-merges" &&
+       check_revlist "--no-merges --merges"
+'
+
+test_expect_success 'rev-list override and infinities' '
+
+       check_revlist "--min-parents=2 --max-parents=1 --max-parents=3" tripus normalmerge &&
+       check_revlist "--min-parents=1 --min-parents=2 --max-parents=7" tetrapus tripus normalmerge &&
+       check_revlist "--min-parents=2 --max-parents=8" tetrapus tripus normalmerge &&
+       check_revlist "--min-parents=2 --max-parents=-1" tetrapus tripus normalmerge &&
+       check_revlist "--min-parents=2 --no-max-parents" tetrapus tripus normalmerge &&
+       check_revlist "--max-parents=0 --min-parents=1 --no-min-parents" one five
+'
+
+test_expect_success 'dodecapus' '
+
+       roots= &&
+       for i in 1 2 3 4 5 6 7 8 9 10 11
+       do
+               git checkout -b root$i five &&
+               test_commit $i &&
+               roots="$roots root$i" ||
+               return
+       done &&
+       git checkout master &&
+       test_tick &&
+       git merge -m dodecapus $roots &&
+       git tag dodecapus &&
+
+       check_revlist "--min-parents=4" dodecapus tetrapus &&
+       check_revlist "--min-parents=8" dodecapus &&
+       check_revlist "--min-parents=12" dodecapus &&
+       check_revlist "--min-parents=13" &&
+       check_revlist "--min-parents=4 --max-parents=11" tetrapus
+'
 test_done
diff --git a/t/t6110-rev-list-sparse.sh b/t/t6110-rev-list-sparse.sh
new file mode 100755 (executable)
index 0000000..656ac7f
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+test_description='operations that cull histories in unusual ways'
+. ./test-lib.sh
+
+test_expect_success setup '
+       test_commit A &&
+       test_commit B &&
+       test_commit C &&
+       git checkout -b side HEAD^ &&
+       test_commit D &&
+       test_commit E &&
+       git merge master
+'
+
+test_expect_success 'rev-list --first-parent --boundary' '
+       git rev-list --first-parent --boundary HEAD^..
+'
+
+test_done
index 5f731a1177267e76f19dbe1605a4d0f2e8e749bd..c86e298d082316ff5a4de6f07c0faba85c65d4e1 100755 (executable)
@@ -122,7 +122,7 @@ test_expect_success 'will not overwrite untracked file in leading path' '
        rm -f sub sub2
 '
 
-test_expect_failure SYMLINKS 'will not overwrite untracked symlink in leading path' '
+test_expect_success SYMLINKS 'will not overwrite untracked symlink in leading path' '
        git reset --hard c0 &&
        rm -rf sub &&
        mkdir sub2 &&
@@ -150,6 +150,7 @@ test_expect_success 'will not overwrite untracked file on unborn branch' '
        git rm -fr . &&
        git checkout --orphan new &&
        cp important c0.c &&
+       test_when_finished "rm c0.c" &&
        test_must_fail git merge c0 2>out &&
        test_cmp out expect &&
        test_path_is_missing .git/MERGE_HEAD &&
@@ -164,7 +165,7 @@ test_expect_success 'set up unborn branch and content' '
        echo bar > untracked-file
 '
 
-test_expect_failure 'will not clobber WT/index when merging into unborn' '
+test_expect_success 'will not clobber WT/index when merging into unborn' '
        git merge master &&
        grep foo tracked-file &&
        git show :tracked-file >expect &&
index 45cb60ea4b167676b07ae1c847c0467f2a5e3d69..41962f04a715ea5250360766dc64986c4ecf7981 100755 (executable)
@@ -6,10 +6,11 @@ test_description='git annotate'
 PROG='git annotate'
 . "$TEST_DIRECTORY"/annotate-tests.sh
 
-test_expect_success \
-    'Annotating an old revision works' \
-    '[ $(git annotate file master | awk "{print \$3}" | grep -c "^A$") -eq 2 ] && \
-     [ $(git annotate file master | awk "{print \$3}" | grep -c "^B$") -eq 2 ]'
-
+test_expect_success 'Annotating an old revision works' '
+       git annotate file master >result &&
+       awk "{ print \$3; }" <result >authors &&
+       test 2 = $(grep A <authors | wc -l) &&
+       test 2 = $(grep B <authors | wc -l)
+'
 
 test_done
index 5a6a4b9b7a6e6abbb9570ddceaac68baf5c2690b..6f6175a8f7d9b0c6e6334f89ff21b74f067d6532 100755 (executable)
@@ -370,6 +370,114 @@ test_expect_failure 'change file mode but keep old content' '
        test_cmp hello actual.target
 '
 
+test_expect_success 'NUL in property value' '
+       reinit_git &&
+       echo "commit message" >expect.message &&
+       {
+               properties \
+                       unimportant "something with a NUL (Q)" \
+                       svn:log "commit message"&&
+               echo PROPS-END
+       } |
+       q_to_nul >props &&
+       {
+               cat <<-\EOF &&
+               SVN-fs-dump-format-version: 3
+
+               Revision-number: 1
+               EOF
+               echo Prop-content-length: $(wc -c <props) &&
+               echo Content-length: $(wc -c <props) &&
+               echo &&
+               cat props
+       } >nulprop.dump &&
+       test-svn-fe nulprop.dump >stream &&
+       git fast-import <stream &&
+       git diff-tree --always -s --format=%s HEAD >actual.message &&
+       test_cmp expect.message actual.message
+'
+
+test_expect_success 'NUL in log message, file content, and property name' '
+       # Caveat: svnadmin 1.6.16 (r1073529) truncates at \0 in the
+       # svn:specialQnotreally example.
+       reinit_git &&
+       cat >expect <<-\EOF &&
+       OBJID
+       :100644 100644 OBJID OBJID M    greeting
+       OBJID
+       :000000 100644 OBJID OBJID A    greeting
+       EOF
+       printf "\n%s\n" "something with an ASCII NUL (Q)" >expect.message &&
+       printf "%s\n" "helQo" >expect.hello1 &&
+       printf "%s\n" "link hello" >expect.hello2 &&
+       {
+               properties svn:log "something with an ASCII NUL (Q)" &&
+               echo PROPS-END
+       } |
+       q_to_nul >props &&
+       {
+               q_to_nul <<-\EOF &&
+               SVN-fs-dump-format-version: 3
+
+               Revision-number: 1
+               Prop-content-length: 10
+               Content-length: 10
+
+               PROPS-END
+
+               Node-path: greeting
+               Node-kind: file
+               Node-action: add
+               Prop-content-length: 10
+               Text-content-length: 6
+               Content-length: 16
+
+               PROPS-END
+               helQo
+
+               Revision-number: 2
+               EOF
+               echo Prop-content-length: $(wc -c <props) &&
+               echo Content-length: $(wc -c <props) &&
+               echo &&
+               cat props &&
+               q_to_nul <<-\EOF
+
+               Node-path: greeting
+               Node-kind: file
+               Node-action: change
+               Prop-content-length: 43
+               Text-content-length: 11
+               Content-length: 54
+
+               K 21
+               svn:specialQnotreally
+               V 1
+               *
+               PROPS-END
+               link hello
+               EOF
+       } >8bitclean.dump &&
+       test-svn-fe 8bitclean.dump >stream &&
+       git fast-import <stream &&
+       {
+               git rev-list HEAD |
+               git diff-tree --root --stdin |
+               sed "s/$_x40/OBJID/g"
+       } >actual &&
+       {
+               git cat-file commit HEAD | nul_to_q &&
+               echo
+       } |
+       sed -ne "/^\$/,\$ p" >actual.message &&
+       git cat-file blob HEAD^:greeting | nul_to_q >actual.hello1 &&
+       git cat-file blob HEAD:greeting | nul_to_q >actual.hello2 &&
+       test_cmp expect actual &&
+       test_cmp expect.message actual.message &&
+       test_cmp expect.hello1 actual.hello1 &&
+       test_cmp expect.hello2 actual.hello2
+'
+
 test_expect_success 'change file mode and reiterate content' '
        reinit_git &&
        cat >expect <<-\EOF &&
index ec0a10661409d24c77bf2061bd8a554bfb565d74..b324c491c52eb0fa39d713cc5f227d134c1adb01 100755 (executable)
@@ -96,7 +96,6 @@ test_expect_success 'fresh clone with svn.authors-file in config' '
                rm -r "$GIT_DIR" &&
                test x = x"$(git config svn.authorsfile)" &&
                test_config="$HOME"/.gitconfig &&
-               unset GIT_CONFIG_NOGLOBAL &&
                unset GIT_DIR &&
                unset GIT_CONFIG &&
                git config --global \
index abe7c64ba9ca8442f4c50d15fffeefd6bba02b5f..a523473954a43193e8111beb58027b6734cb664b 100755 (executable)
@@ -61,6 +61,29 @@ test_expect_success 'git-p4 clone @all' '
        rm -rf "$git" && mkdir "$git"
 '
 
+test_expect_success 'git-p4 sync uninitialized repo' '
+       test_create_repo "$git" &&
+       cd "$git" &&
+       test_must_fail "$GITP4" sync &&
+       rm -rf "$git" && mkdir "$git"
+'
+
+#
+# Create a git repo by hand.  Add a commit so that HEAD is valid.
+# Test imports a new p4 repository into a new git branch.
+#
+test_expect_success 'git-p4 sync new branch' '
+       test_create_repo "$git" &&
+       cd "$git" &&
+       test_commit head &&
+       "$GITP4" sync --branch=refs/remotes/p4/depot //depot@all &&
+       git log --oneline p4/depot >lines &&
+       cat lines &&
+       test_line_count = 2 lines &&
+       cd .. &&
+       rm -rf "$git" && mkdir "$git"
+'
+
 test_expect_success 'exit when p4 fails to produce marshaled output' '
        badp4dir="$TRASH_DIRECTORY/badp4dir" &&
        mkdir -p "$badp4dir" &&
index f4c1e04e4f26ca38b57fc6c47b05cf92111107b6..abc47f3abc5d925ed217d0d95f10bf078bc26034 100644 (file)
@@ -43,36 +43,25 @@ TERM=dumb
 export LANG LC_ALL PAGER TERM TZ
 EDITOR=:
 unset VISUAL
-unset GIT_EDITOR
-unset AUTHOR_DATE
-unset AUTHOR_EMAIL
-unset AUTHOR_NAME
-unset COMMIT_AUTHOR_EMAIL
-unset COMMIT_AUTHOR_NAME
 unset EMAIL
-unset GIT_ALTERNATE_OBJECT_DIRECTORIES
-unset GIT_AUTHOR_DATE
+unset $(perl -e '
+       my @env = keys %ENV;
+       my $ok = join("|", qw(
+               TRACE
+               DEBUG
+               USE_LOOKUP
+               TEST
+               .*_TEST
+               PROVE
+               VALGRIND
+       ));
+       my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env);
+       print join("\n", @vars);
+')
 GIT_AUTHOR_EMAIL=author@example.com
 GIT_AUTHOR_NAME='A U Thor'
-unset GIT_COMMITTER_DATE
 GIT_COMMITTER_EMAIL=committer@example.com
 GIT_COMMITTER_NAME='C O Mitter'
-unset GIT_DIFF_OPTS
-unset GIT_DIR
-unset GIT_WORK_TREE
-unset GIT_EXTERNAL_DIFF
-unset GIT_INDEX_FILE
-unset GIT_OBJECT_DIRECTORY
-unset GIT_CEILING_DIRECTORIES
-unset SHA1_FILE_DIRECTORIES
-unset SHA1_FILE_DIRECTORY
-unset GIT_NOTES_REF
-unset GIT_NOTES_DISPLAY_REF
-unset GIT_NOTES_REWRITE_REF
-unset GIT_NOTES_REWRITE_MODE
-unset GIT_REFLOG_ACTION
-unset GIT_CHERRY_PICK_HELP
-unset GIT_QUIET
 GIT_MERGE_VERBOSITY=5
 export GIT_MERGE_VERBOSITY
 export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
@@ -954,8 +943,8 @@ fi
 GIT_TEMPLATE_DIR="$GIT_BUILD_DIR"/templates/blt
 unset GIT_CONFIG
 GIT_CONFIG_NOSYSTEM=1
-GIT_CONFIG_NOGLOBAL=1
-export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL
+GIT_ATTR_NOSYSTEM=1
+export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_ATTR_NOSYSTEM
 
 . "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS
 
@@ -1004,14 +993,14 @@ rm -fr "$test" || {
        exit 1
 }
 
+HOME="$TRASH_DIRECTORY"
+export HOME
+
 test_create_repo "$test"
 # Use -P to resolve symlinks in our working directory so that the cwd
 # in subprocesses like git equals our $PWD (for pathname comparisons).
 cd -P "$test" || exit 1
 
-HOME=$(pwd)
-export HOME
-
 this_test=${0##*/}
 this_test=${this_test%%-*}
 for skp in $GIT_SKIP_TESTS
index 25b20b93fd4a1113629c99bd5a53dfee965119c1..7ec9b13c9b2ceb84fb6dd0dd229e9f6cb8c1a635 100644 (file)
@@ -32,12 +32,6 @@ static void handle_command(const char *command, const char *arg, struct line_buf
                        buffer_copy_bytes(buf, strtouint32(arg));
                        return;
                }
-       case 'r':
-               if (!prefixcmp(command, "read ")) {
-                       const char *s = buffer_read_string(buf, strtouint32(arg));
-                       fputs(s, stdout);
-                       return;
-               }
        case 's':
                if (!prefixcmp(command, "skip ")) {
                        buffer_skip_bytes(buf, strtouint32(arg));
index 667d3e5079bf06d540b214cd6f8e67922f141a02..8926bc52a9a6e2a16924664372a8af3ee2ed3136 100644 (file)
@@ -3,11 +3,10 @@
 
 int main(int argc, char **argv)
 {
-       const char *prefix;
        struct child_process cp;
        int nogit = 0;
 
-       prefix = setup_git_directory_gently(&nogit);
+       setup_git_directory_gently(&nogit);
        if (nogit)
                die("No git repo found");
        if (!strcmp(argv[1], "--setup-work-tree")) {
index 589f838f82b568195232ea81346d0049261b86b1..7f4b76a95899cc28aa1d42598d1649f126980ed9 100644 (file)
@@ -1,5 +1,5 @@
 #include "cache.h"
-#include <pthread.h>
+#include "thread-utils.h"
 
 #if defined(hpux) || defined(__hpux) || defined(_hpux)
 #  include <sys/pstat.h>
diff --git a/trace.c b/trace.c
index 8390bf7cbb82e8f1e9e6f7229516e43f288d6e41..d95341693fa9b27caed38ffe1308838bedb49f83 100644 (file)
--- a/trace.c
+++ b/trace.c
@@ -75,7 +75,7 @@ void trace_vprintf(const char *key, const char *fmt, va_list ap)
        strbuf_release(&buf);
 }
 
-void trace_printf_key(const char *key, const char *fmt, ...)
+static void trace_printf_key(const char *key, const char *fmt, ...)
 {
        va_list ap;
        va_start(ap, fmt);
index 0c5b1bd994d79cd6441a5c956a2d851b6bea7d5f..660147f9e96be7b69379a9040c4220c141c7be4c 100644 (file)
@@ -76,7 +76,7 @@ static void write_constant(int fd, const char *str)
                die_errno("Full write to remote helper failed");
 }
 
-const char *remove_ext_force(const char *url)
+static const char *remove_ext_force(const char *url)
 {
        if (url) {
                const char *colon = strchr(url, ':');
@@ -561,10 +561,9 @@ static int push_refs_with_push(struct transport *transport,
        int mirror = flags & TRANSPORT_PUSH_MIRROR;
        struct helper_data *data = transport->data;
        struct strbuf buf = STRBUF_INIT;
-       struct child_process *helper;
        struct ref *ref;
 
-       helper = get_helper(transport);
+       get_helper(transport);
        if (!data->push)
                return 1;
 
index 00786606117feea4b33b7e632b8ff8a3c26de4e4..a02f79aae3d91ea4109d21a9ed9ca2d962125375 100644 (file)
@@ -192,7 +192,7 @@ static const char *rsync_url(const char *url)
 static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
 {
        struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
-       struct ref dummy = {0}, *tail = &dummy;
+       struct ref dummy = {NULL}, *tail = &dummy;
        struct child_process rsync;
        const char *args[5];
        int temp_dir_len;
@@ -1189,3 +1189,37 @@ char *transport_anonymize_url(const char *url)
 literal_copy:
        return xstrdup(url);
 }
+
+int refs_from_alternate_cb(struct alternate_object_database *e, void *cb)
+{
+       char *other;
+       size_t len;
+       struct remote *remote;
+       struct transport *transport;
+       const struct ref *extra;
+       alternate_ref_fn *ref_fn = cb;
+
+       e->name[-1] = '\0';
+       other = xstrdup(real_path(e->base));
+       e->name[-1] = '/';
+       len = strlen(other);
+
+       while (other[len-1] == '/')
+               other[--len] = '\0';
+       if (len < 8 || memcmp(other + len - 8, "/objects", 8))
+               return 0;
+       /* Is this a git repository with refs? */
+       memcpy(other + len - 8, "/refs", 6);
+       if (!is_directory(other))
+               return 0;
+       other[len - 8] = '\0';
+       remote = remote_get(other);
+       transport = transport_get(remote, other);
+       for (extra = transport_get_remote_refs(transport);
+            extra;
+            extra = extra->next)
+               ref_fn(extra, NULL);
+       transport_disconnect(transport);
+       free(other);
+       return 0;
+}
index e803c0e7baf3785fac35fca64072e05e4f668a26..efb19688692b5f1be4fc085cc36d737ace2df417 100644 (file)
@@ -166,4 +166,7 @@ int transport_refs_pushed(struct ref *ref);
 void transport_print_push_status(const char *dest, struct ref *refs,
                  int verbose, int porcelain, int *nonfastforward);
 
+typedef void alternate_ref_fn(const struct ref *, void *);
+extern int refs_from_alternate_cb(struct alternate_object_database *e, void *cb);
+
 #endif
index 3954281f509bbed9a9b095ed92d24b67275fed82..76f83fcc27e50b12ddbc8f72badd8d29f5b4230d 100644 (file)
@@ -17,7 +17,6 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
        const unsigned char *sha1, *sha2;
        int cmp, pathlen1, pathlen2;
        int old_baselen = base->len;
-       int retval = 0;
 
        sha1 = tree_entry_extract(t1, &path1, &mode1);
        sha2 = tree_entry_extract(t2, &path2, &mode2);
@@ -53,7 +52,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
                                    sha1, sha2, base->buf, 0, 0);
                }
                strbuf_addch(base, '/');
-               retval = diff_tree_sha1(sha1, sha2, base->buf, opt);
+               diff_tree_sha1(sha1, sha2, base->buf, opt);
        } else {
                opt->change(opt, mode1, mode2, sha1, sha2, base->buf, 0, 0);
        }
index b68ec820dde935eb2578a8983c265290d0511add..500ebcfd545772fb17e5fb14bba42bf4be468b75 100644 (file)
@@ -16,7 +16,7 @@
  * situation better.  See how "git checkout" and "git merge" replaces
  * them using setup_unpack_trees_porcelain(), for example.
  */
-const char *unpack_plumbing_errors[NB_UNPACK_TREES_ERROR_TYPES] = {
+static const char *unpack_plumbing_errors[NB_UNPACK_TREES_ERROR_TYPES] = {
        /* ERROR_WOULD_OVERWRITE */
        "Entry '%s' would be overwritten by merge. Cannot merge.",
 
index 0c87bc00f0e06e57b10154a026d797fb1500b4fe..bba053f0aac8eef982d6779983dc6fd979d69d69 100644 (file)
@@ -27,6 +27,7 @@ static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=<
 static unsigned long oldest_have;
 
 static int multi_ack, nr_our_refs;
+static int no_done;
 static int use_thin_pack, use_ofs_delta, use_include_tag;
 static int no_progress, daemon_mode;
 static int shallow_nr;
@@ -429,6 +430,9 @@ static int get_common_commits(void)
        static char line[1000];
        unsigned char sha1[20];
        char last_hex[41];
+       int got_common = 0;
+       int got_other = 0;
+       int sent_ready = 0;
 
        save_commit_buffer = 0;
 
@@ -437,25 +441,40 @@ static int get_common_commits(void)
                reset_timeout();
 
                if (!len) {
+                       if (multi_ack == 2 && got_common
+                           && !got_other && ok_to_give_up()) {
+                               sent_ready = 1;
+                               packet_write(1, "ACK %s ready\n", last_hex);
+                       }
                        if (have_obj.nr == 0 || multi_ack)
                                packet_write(1, "NAK\n");
+
+                       if (no_done && sent_ready) {
+                               packet_write(1, "ACK %s\n", last_hex);
+                               return 0;
+                       }
                        if (stateless_rpc)
                                exit(0);
+                       got_common = 0;
+                       got_other = 0;
                        continue;
                }
                strip(line, len);
                if (!prefixcmp(line, "have ")) {
                        switch (got_sha1(line+5, sha1)) {
                        case -1: /* they have what we do not */
+                               got_other = 1;
                                if (multi_ack && ok_to_give_up()) {
                                        const char *hex = sha1_to_hex(sha1);
-                                       if (multi_ack == 2)
+                                       if (multi_ack == 2) {
+                                               sent_ready = 1;
                                                packet_write(1, "ACK %s ready\n", hex);
-                                       else
+                                       else
                                                packet_write(1, "ACK %s continue\n", hex);
                                }
                                break;
                        default:
+                               got_common = 1;
                                memcpy(last_hex, sha1_to_hex(sha1), 41);
                                if (multi_ack == 2)
                                        packet_write(1, "ACK %s common\n", last_hex);
@@ -526,6 +545,8 @@ static void receive_needs(void)
                        multi_ack = 2;
                else if (strstr(line+45, "multi_ack"))
                        multi_ack = 1;
+               if (strstr(line+45, "no-done"))
+                       no_done = 1;
                if (strstr(line+45, "thin-pack"))
                        use_thin_pack = 1;
                if (strstr(line+45, "ofs-delta"))
@@ -626,8 +647,9 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
                die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
 
        if (capabilities)
-               packet_write(1, "%s %s%c%s\n", sha1_to_hex(sha1), refname,
-                       0, capabilities);
+               packet_write(1, "%s %s%c%s%s\n", sha1_to_hex(sha1), refname,
+                            0, capabilities,
+                            stateless_rpc ? " no-done" : "");
        else
                packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname);
        capabilities = NULL;
diff --git a/url.c b/url.c
index 6a5495960f03ded65f0f5f8b8bd5c7cd98c0b05e..3e06fd34c46a00b41f4843ea87a151314ce0789c 100644 (file)
--- a/url.c
+++ b/url.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "url.h"
 
 int is_urlschemechar(int first_flag, int ch)
 {
diff --git a/usage.c b/usage.c
index ec4cf53b6bf16f7f9b3528a430891d6c68ef64cc..b5e67e3d0d4a46a69d72371f4c6a0002e40a0bf1 100644 (file)
--- a/usage.c
+++ b/usage.c
@@ -46,7 +46,7 @@ void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list param
        die_routine = routine;
 }
 
-void usagef(const char *err, ...)
+void NORETURN usagef(const char *err, ...)
 {
        va_list params;
 
@@ -55,12 +55,12 @@ void usagef(const char *err, ...)
        va_end(params);
 }
 
-void usage(const char *err)
+void NORETURN usage(const char *err)
 {
        usagef("%s", err);
 }
 
-void die(const char *err, ...)
+void NORETURN die(const char *err, ...)
 {
        va_list params;
 
@@ -69,7 +69,7 @@ void die(const char *err, ...)
        va_end(params);
 }
 
-void die_errno(const char *fmt, ...)
+void NORETURN die_errno(const char *fmt, ...)
 {
        va_list params;
        char fmt_with_err[1024];
index 260cf50e7725c9199fa44134a7f3408da7cad984..99ed70b88a5aaacbb48a9463f19ec198d7bedf84 100644 (file)
@@ -31,27 +31,30 @@ void fast_export_modify(uint32_t depth, uint32_t *path, uint32_t mode,
 }
 
 static char gitsvnline[MAX_GITSVN_LINE_LEN];
-void fast_export_commit(uint32_t revision, uint32_t author, char *log,
-                       uint32_t uuid, uint32_t url,
+void fast_export_commit(uint32_t revision, const char *author,
+                       const struct strbuf *log,
+                       const char *uuid, const char *url,
                        unsigned long timestamp)
 {
+       static const struct strbuf empty = STRBUF_INIT;
        if (!log)
-               log = "";
-       if (~uuid && ~url) {
+               log = &empty;
+       if (*uuid && *url) {
                snprintf(gitsvnline, MAX_GITSVN_LINE_LEN,
                                "\n\ngit-svn-id: %s@%"PRIu32" %s\n",
-                                pool_fetch(url), revision, pool_fetch(uuid));
+                                url, revision, uuid);
        } else {
                *gitsvnline = '\0';
        }
        printf("commit refs/heads/master\n");
        printf("committer %s <%s@%s> %ld +0000\n",
-                  ~author ? pool_fetch(author) : "nobody",
-                  ~author ? pool_fetch(author) : "nobody",
-                  ~uuid ? pool_fetch(uuid) : "local", timestamp);
-       printf("data %"PRIu32"\n%s%s\n",
-                  (uint32_t) (strlen(log) + strlen(gitsvnline)),
-                  log, gitsvnline);
+                  *author ? author : "nobody",
+                  *author ? author : "nobody",
+                  *uuid ? uuid : "local", timestamp);
+       printf("data %"PRIuMAX"\n",
+               (uintmax_t) (log->len + strlen(gitsvnline)));
+       fwrite(log->buf, log->len, 1, stdout);
+       printf("%s\n", gitsvnline);
        if (!first_commit_done) {
                if (revision > 1)
                        printf("from refs/heads/master^0\n");
@@ -63,14 +66,23 @@ void fast_export_commit(uint32_t revision, uint32_t author, char *log,
        printf("progress Imported commit %"PRIu32".\n\n", revision);
 }
 
+static void die_short_read(struct line_buffer *input)
+{
+       if (buffer_ferror(input))
+               die_errno("error reading dump file");
+       die("invalid dump: unexpected end of file");
+}
+
 void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len, struct line_buffer *input)
 {
        if (mode == REPO_MODE_LNK) {
                /* svn symlink blobs start with "link " */
-               buffer_skip_bytes(input, 5);
                len -= 5;
+               if (buffer_skip_bytes(input, 5) != 5)
+                       die_short_read(input);
        }
        printf("blob\nmark :%"PRIu32"\ndata %"PRIu32"\n", mark, len);
-       buffer_copy_bytes(input, len);
+       if (buffer_copy_bytes(input, len) != len)
+               die_short_read(input);
        fputc('\n', stdout);
 }
index 054e7d5eb1aeb4b2808acc0360e6371a376d40f7..33a8fe996f5fc025f587c1d09ae3f81e1786dbbb 100644 (file)
@@ -2,12 +2,14 @@
 #define FAST_EXPORT_H_
 
 #include "line_buffer.h"
+struct strbuf;
 
 void fast_export_delete(uint32_t depth, uint32_t *path);
 void fast_export_modify(uint32_t depth, uint32_t *path, uint32_t mode,
                        uint32_t mark);
-void fast_export_commit(uint32_t revision, uint32_t author, char *log,
-                       uint32_t uuid, uint32_t url, unsigned long timestamp);
+void fast_export_commit(uint32_t revision, const char *author,
+                       const struct strbuf *log, const char *uuid,
+                       const char *url, unsigned long timestamp);
 void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len,
                      struct line_buffer *input);
 
index aedf105b70586f2ef7567547426bb6622799b067..c39038723ed4a90f99f70a694eae58ba488556b6 100644 (file)
@@ -59,6 +59,11 @@ long buffer_tmpfile_prepare_to_read(struct line_buffer *buf)
        return pos;
 }
 
+int buffer_ferror(struct line_buffer *buf)
+{
+       return ferror(buf->infile);
+}
+
 int buffer_read_char(struct line_buffer *buf)
 {
        return fgetc(buf->infile);
@@ -86,47 +91,40 @@ char *buffer_read_line(struct line_buffer *buf)
        return buf->line_buffer;
 }
 
-char *buffer_read_string(struct line_buffer *buf, uint32_t len)
-{
-       strbuf_reset(&buf->blob_buffer);
-       strbuf_fread(&buf->blob_buffer, len, buf->infile);
-       return ferror(buf->infile) ? NULL : buf->blob_buffer.buf;
-}
-
 void buffer_read_binary(struct line_buffer *buf,
                                struct strbuf *sb, uint32_t size)
 {
        strbuf_fread(sb, size, buf->infile);
 }
 
-void buffer_copy_bytes(struct line_buffer *buf, uint32_t len)
+off_t buffer_copy_bytes(struct line_buffer *buf, off_t nbytes)
 {
        char byte_buffer[COPY_BUFFER_LEN];
-       uint32_t in;
-       while (len > 0 && !feof(buf->infile) && !ferror(buf->infile)) {
-               in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
+       off_t done = 0;
+       while (done < nbytes && !feof(buf->infile) && !ferror(buf->infile)) {
+               off_t len = nbytes - done;
+               size_t in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
                in = fread(byte_buffer, 1, in, buf->infile);
-               len -= in;
+               done += in;
                fwrite(byte_buffer, 1, in, stdout);
-               if (ferror(stdout)) {
-                       buffer_skip_bytes(buf, len);
-                       return;
-               }
+               if (ferror(stdout))
+                       return done + buffer_skip_bytes(buf, nbytes - done);
        }
+       return done;
 }
 
-void buffer_skip_bytes(struct line_buffer *buf, uint32_t len)
+off_t buffer_skip_bytes(struct line_buffer *buf, off_t nbytes)
 {
        char byte_buffer[COPY_BUFFER_LEN];
-       uint32_t in;
-       while (len > 0 && !feof(buf->infile) && !ferror(buf->infile)) {
-               in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
-               in = fread(byte_buffer, 1, in, buf->infile);
-               len -= in;
+       off_t done = 0;
+       while (done < nbytes && !feof(buf->infile) && !ferror(buf->infile)) {
+               off_t len = nbytes - done;
+               size_t in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
+               done += fread(byte_buffer, 1, in, buf->infile);
        }
+       return done;
 }
 
 void buffer_reset(struct line_buffer *buf)
 {
-       strbuf_release(&buf->blob_buffer);
 }
index 96ce966a229110e6775cd33ee01a93d5f133404e..d0b22dda76e8a193f15fa5483abd217cdde101da 100644 (file)
@@ -7,10 +7,9 @@
 
 struct line_buffer {
        char line_buffer[LINE_BUFFER_LEN];
-       struct strbuf blob_buffer;
        FILE *infile;
 };
-#define LINE_BUFFER_INIT {"", STRBUF_INIT, NULL}
+#define LINE_BUFFER_INIT { "", NULL }
 
 int buffer_init(struct line_buffer *buf, const char *filename);
 int buffer_fdinit(struct line_buffer *buf, int fd);
@@ -21,11 +20,12 @@ int buffer_tmpfile_init(struct line_buffer *buf);
 FILE *buffer_tmpfile_rewind(struct line_buffer *buf);  /* prepare to write. */
 long buffer_tmpfile_prepare_to_read(struct line_buffer *buf);
 
+int buffer_ferror(struct line_buffer *buf);
 char *buffer_read_line(struct line_buffer *buf);
-char *buffer_read_string(struct line_buffer *buf, uint32_t len);
 int buffer_read_char(struct line_buffer *buf);
 void buffer_read_binary(struct line_buffer *buf, struct strbuf *sb, uint32_t len);
-void buffer_copy_bytes(struct line_buffer *buf, uint32_t len);
-void buffer_skip_bytes(struct line_buffer *buf, uint32_t len);
+/* Returns number of bytes read (not necessarily written). */
+off_t buffer_copy_bytes(struct line_buffer *buf, off_t len);
+off_t buffer_skip_bytes(struct line_buffer *buf, off_t len);
 
 #endif
index e89cc41d562448ad65a42b039dcf06a8c38e3335..8e139eb22df0f44ba0b805b374943dd5d12e8437 100644 (file)
@@ -16,8 +16,8 @@ The calling program:
 
  - initializes a `struct line_buffer` to LINE_BUFFER_INIT
  - specifies a file to read with `buffer_init`
- - processes input with `buffer_read_line`, `buffer_read_string`,
-   `buffer_skip_bytes`, and `buffer_copy_bytes`
+ - processes input with `buffer_read_line`, `buffer_skip_bytes`,
+   and `buffer_copy_bytes`
  - closes the file with `buffer_deinit`, perhaps to start over and
    read another file.
 
@@ -37,7 +37,7 @@ the calling program.  A program
    the temporary file
  - declares writing is over with `buffer_tmpfile_prepare_to_read`
  - can re-read what was written with `buffer_read_line`,
-   `buffer_read_string`, and so on
+   `buffer_copy_bytes`, and so on
  - can reuse the temporary file by calling `buffer_tmpfile_rewind`
    again
  - removes the temporary file with `buffer_deinit`, perhaps to
@@ -64,19 +64,14 @@ Functions
        Read a line and strip off the trailing newline.
        On failure or end of file, returns NULL.
 
-`buffer_read_string`::
-       Read `len` characters of input or up to the end of the
-       file, whichever comes first.  Returns NULL on error.
-       Returns whatever characters were read (possibly "")
-       for end of file.
-
 `buffer_copy_bytes`::
        Read `len` bytes of input and dump them to the standard output
        stream.  Returns early for error or end of file.
 
 `buffer_skip_bytes`::
        Discards `len` bytes from the input stream (stopping early
-       if necessary because of an error or eof).
+       if necessary because of an error or eof).  Return value is
+       the number of bytes successfully read.
 
 `buffer_reset`::
        Deallocates non-static buffers.
index 207ffc3a831d31b1504838555c15a424c81754f5..a21d89de97404479ecf2ca46824f61acb7af56e6 100644 (file)
@@ -87,7 +87,8 @@ static struct repo_dir *repo_clone_dir(struct repo_dir *orig_dir)
        return dir_pointer(new_o);
 }
 
-static struct repo_dirent *repo_read_dirent(uint32_t revision, uint32_t *path)
+static struct repo_dirent *repo_read_dirent(uint32_t revision,
+                                           const uint32_t *path)
 {
        uint32_t name = 0;
        struct repo_dirent *key = dent_pointer(dent_alloc(1));
@@ -105,7 +106,7 @@ static struct repo_dirent *repo_read_dirent(uint32_t revision, uint32_t *path)
        return dent;
 }
 
-static void repo_write_dirent(uint32_t *path, uint32_t mode,
+static void repo_write_dirent(const uint32_t *path, uint32_t mode,
                              uint32_t content_offset, uint32_t del)
 {
        uint32_t name, revision, dir_o = ~0, parent_dir_o = ~0;
@@ -157,7 +158,24 @@ static void repo_write_dirent(uint32_t *path, uint32_t mode,
                dent_remove(&dir_pointer(parent_dir_o)->entries, dent);
 }
 
-uint32_t repo_copy(uint32_t revision, uint32_t *src, uint32_t *dst)
+uint32_t repo_read_path(const uint32_t *path)
+{
+       uint32_t content_offset = 0;
+       struct repo_dirent *dent = repo_read_dirent(active_commit, path);
+       if (dent != NULL)
+               content_offset = dent->content_offset;
+       return content_offset;
+}
+
+uint32_t repo_read_mode(const uint32_t *path)
+{
+       struct repo_dirent *dent = repo_read_dirent(active_commit, path);
+       if (dent == NULL)
+               die("invalid dump: path to be modified is missing");
+       return dent->mode;
+}
+
+void repo_copy(uint32_t revision, const uint32_t *src, const uint32_t *dst)
 {
        uint32_t mode = 0, content_offset = 0;
        struct repo_dirent *src_dent;
@@ -167,7 +185,6 @@ uint32_t repo_copy(uint32_t revision, uint32_t *src, uint32_t *dst)
                content_offset = src_dent->content_offset;
                repo_write_dirent(dst, mode, content_offset, 0);
        }
-       return mode;
 }
 
 void repo_add(uint32_t *path, uint32_t mode, uint32_t blob_mark)
@@ -175,20 +192,6 @@ void repo_add(uint32_t *path, uint32_t mode, uint32_t blob_mark)
        repo_write_dirent(path, mode, blob_mark, 0);
 }
 
-uint32_t repo_modify_path(uint32_t *path, uint32_t mode, uint32_t blob_mark)
-{
-       struct repo_dirent *src_dent;
-       src_dent = repo_read_dirent(active_commit, path);
-       if (!src_dent)
-               return 0;
-       if (!blob_mark)
-               blob_mark = src_dent->content_offset;
-       if (!mode)
-               mode = src_dent->mode;
-       repo_write_dirent(path, mode, blob_mark, 0);
-       return mode;
-}
-
 void repo_delete(uint32_t *path)
 {
        repo_write_dirent(path, 0, 0, 1);
@@ -275,8 +278,9 @@ void repo_diff(uint32_t r1, uint32_t r2)
                    repo_commit_root_dir(commit_pointer(r2)));
 }
 
-void repo_commit(uint32_t revision, uint32_t author, char *log, uint32_t uuid,
-                uint32_t url, unsigned long timestamp)
+void repo_commit(uint32_t revision, const char *author,
+               const struct strbuf *log, const char *uuid, const char *url,
+               unsigned long timestamp)
 {
        fast_export_commit(revision, author, log, uuid, url, timestamp);
        dent_commit();
index 68baeb582ff0ad8700061a78947cd186ff116536..37bde2e37484071998edbe790d38d7b19eb24fb5 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef REPO_TREE_H_
 #define REPO_TREE_H_
 
-#include "git-compat-util.h"
+struct strbuf;
 
 #define REPO_MODE_DIR 0040000
 #define REPO_MODE_BLB 0100644
 #define REPO_MAX_PATH_DEPTH 1000
 
 uint32_t next_blob_mark(void);
-uint32_t repo_copy(uint32_t revision, uint32_t *src, uint32_t *dst);
+void repo_copy(uint32_t revision, const uint32_t *src, const uint32_t *dst);
 void repo_add(uint32_t *path, uint32_t mode, uint32_t blob_mark);
-uint32_t repo_modify_path(uint32_t *path, uint32_t mode, uint32_t blob_mark);
+uint32_t repo_read_path(const uint32_t *path);
+uint32_t repo_read_mode(const uint32_t *path);
 void repo_delete(uint32_t *path);
-void repo_commit(uint32_t revision, uint32_t author, char *log, uint32_t uuid,
-                uint32_t url, long unsigned timestamp);
+void repo_commit(uint32_t revision, const char *author,
+               const struct strbuf *log, const char *uuid, const char *url,
+               long unsigned timestamp);
 void repo_diff(uint32_t r1, uint32_t r2);
 void repo_init(void);
 void repo_reset(void);
index ee7c0bb2ea869c66cdbab4f4f23a0d2207e6b27d..572a99596657b85cbda372a9107a43c6c2fb44b2 100644 (file)
 #include "repo_tree.h"
 #include "fast_export.h"
 #include "line_buffer.h"
-#include "obj_pool.h"
 #include "string_pool.h"
+#include "strbuf.h"
+
+/*
+ * Compare start of string to literal of equal length;
+ * must be guarded by length test.
+ */
+#define constcmp(s, ref) memcmp(s, ref, sizeof(ref) - 1)
 
 #define NODEACT_REPLACE 4
 #define NODEACT_DELETE 3
 #define LENGTH_UNKNOWN (~0)
 #define DATE_RFC2822_LEN 31
 
-/* Create memory pool for log messages */
-obj_pool_gen(log, char, 4096)
-
 static struct line_buffer input = LINE_BUFFER_INIT;
 
-static char *log_copy(uint32_t length, const char *log)
-{
-       char *buffer;
-       log_free(log_pool.size);
-       buffer = log_pointer(log_alloc(length));
-       strncpy(buffer, log, length);
-       return buffer;
-}
-
 static struct {
        uint32_t action, propLength, textLength, srcRev, type;
        uint32_t src[REPO_MAX_PATH_DEPTH], dst[REPO_MAX_PATH_DEPTH];
@@ -48,24 +42,16 @@ static struct {
 } node_ctx;
 
 static struct {
-       uint32_t revision, author;
+       uint32_t revision;
        unsigned long timestamp;
-       char *log;
+       struct strbuf log, author;
 } rev_ctx;
 
 static struct {
-       uint32_t version, uuid, url;
+       uint32_t version;
+       struct strbuf uuid, url;
 } dump_ctx;
 
-static struct {
-       uint32_t svn_log, svn_author, svn_date, svn_executable, svn_special, uuid,
-               revision_number, node_path, node_kind, node_action,
-               node_copyfrom_path, node_copyfrom_rev, text_content_length,
-               prop_content_length, content_length, svn_fs_dump_format_version,
-               /* version 3 format */
-               text_delta, prop_delta;
-} keys;
-
 static void reset_node_ctx(char *fname)
 {
        node_ctx.type = 0;
@@ -83,56 +69,58 @@ static void reset_rev_ctx(uint32_t revision)
 {
        rev_ctx.revision = revision;
        rev_ctx.timestamp = 0;
-       rev_ctx.log = NULL;
-       rev_ctx.author = ~0;
+       strbuf_reset(&rev_ctx.log);
+       strbuf_reset(&rev_ctx.author);
 }
 
-static void reset_dump_ctx(uint32_t url)
+static void reset_dump_ctx(const char *url)
 {
-       dump_ctx.url = url;
+       strbuf_reset(&dump_ctx.url);
+       if (url)
+               strbuf_addstr(&dump_ctx.url, url);
        dump_ctx.version = 1;
-       dump_ctx.uuid = ~0;
+       strbuf_reset(&dump_ctx.uuid);
 }
 
-static void init_keys(void)
-{
-       keys.svn_log = pool_intern("svn:log");
-       keys.svn_author = pool_intern("svn:author");
-       keys.svn_date = pool_intern("svn:date");
-       keys.svn_executable = pool_intern("svn:executable");
-       keys.svn_special = pool_intern("svn:special");
-       keys.uuid = pool_intern("UUID");
-       keys.revision_number = pool_intern("Revision-number");
-       keys.node_path = pool_intern("Node-path");
-       keys.node_kind = pool_intern("Node-kind");
-       keys.node_action = pool_intern("Node-action");
-       keys.node_copyfrom_path = pool_intern("Node-copyfrom-path");
-       keys.node_copyfrom_rev = pool_intern("Node-copyfrom-rev");
-       keys.text_content_length = pool_intern("Text-content-length");
-       keys.prop_content_length = pool_intern("Prop-content-length");
-       keys.content_length = pool_intern("Content-length");
-       keys.svn_fs_dump_format_version = pool_intern("SVN-fs-dump-format-version");
-       /* version 3 format (Subversion 1.1.0) */
-       keys.text_delta = pool_intern("Text-delta");
-       keys.prop_delta = pool_intern("Prop-delta");
-}
-
-static void handle_property(uint32_t key, const char *val, uint32_t len,
+static void handle_property(const struct strbuf *key_buf,
+                               struct strbuf *val,
                                uint32_t *type_set)
 {
-       if (key == keys.svn_log) {
+       const char *key = key_buf->buf;
+       size_t keylen = key_buf->len;
+
+       switch (keylen + 1) {
+       case sizeof("svn:log"):
+               if (constcmp(key, "svn:log"))
+                       break;
                if (!val)
                        die("invalid dump: unsets svn:log");
-               /* Value length excludes terminating nul. */
-               rev_ctx.log = log_copy(len + 1, val);
-       } else if (key == keys.svn_author) {
-               rev_ctx.author = pool_intern(val);
-       } else if (key == keys.svn_date) {
+               strbuf_swap(&rev_ctx.log, val);
+               break;
+       case sizeof("svn:author"):
+               if (constcmp(key, "svn:author"))
+                       break;
+               if (!val)
+                       strbuf_reset(&rev_ctx.author);
+               else
+                       strbuf_swap(&rev_ctx.author, val);
+               break;
+       case sizeof("svn:date"):
+               if (constcmp(key, "svn:date"))
+                       break;
                if (!val)
                        die("invalid dump: unsets svn:date");
-               if (parse_date_basic(val, &rev_ctx.timestamp, NULL))
-                       warning("invalid timestamp: %s", val);
-       } else if (key == keys.svn_executable || key == keys.svn_special) {
+               if (parse_date_basic(val->buf, &rev_ctx.timestamp, NULL))
+                       warning("invalid timestamp: %s", val->buf);
+               break;
+       case sizeof("svn:executable"):
+       case sizeof("svn:special"):
+               if (keylen == strlen("svn:executable") &&
+                   constcmp(key, "svn:executable"))
+                       break;
+               if (keylen == strlen("svn:special") &&
+                   constcmp(key, "svn:special"))
+                       break;
                if (*type_set) {
                        if (!val)
                                return;
@@ -143,15 +131,23 @@ static void handle_property(uint32_t key, const char *val, uint32_t len,
                        return;
                }
                *type_set = 1;
-               node_ctx.type = key == keys.svn_executable ?
+               node_ctx.type = keylen == strlen("svn:executable") ?
                                REPO_MODE_EXE :
                                REPO_MODE_LNK;
        }
 }
 
+static void die_short_read(void)
+{
+       if (buffer_ferror(&input))
+               die_errno("error reading dump file");
+       die("invalid dump: unexpected end of file");
+}
+
 static void read_props(void)
 {
-       uint32_t key = ~0;
+       static struct strbuf key = STRBUF_INIT;
+       static struct strbuf val = STRBUF_INIT;
        const char *t;
        /*
         * NEEDSWORK: to support simple mode changes like
@@ -168,27 +164,34 @@ static void read_props(void)
        uint32_t type_set = 0;
        while ((t = buffer_read_line(&input)) && strcmp(t, "PROPS-END")) {
                uint32_t len;
-               const char *val;
                const char type = t[0];
+               int ch;
 
                if (!type || t[1] != ' ')
                        die("invalid property line: %s\n", t);
                len = atoi(&t[2]);
-               val = buffer_read_string(&input, len);
-               buffer_skip_bytes(&input, 1);   /* Discard trailing newline. */
+               strbuf_reset(&val);
+               buffer_read_binary(&input, &val, len);
+               if (val.len < len)
+                       die_short_read();
+
+               /* Discard trailing newline. */
+               ch = buffer_read_char(&input);
+               if (ch == EOF)
+                       die_short_read();
+               if (ch != '\n')
+                       die("invalid dump: expected newline after %s", val.buf);
 
                switch (type) {
                case 'K':
-                       key = pool_intern(val);
+                       strbuf_swap(&key, &val);
                        continue;
                case 'D':
-                       key = pool_intern(val);
-                       val = NULL;
-                       len = 0;
-                       /* fall through */
+                       handle_property(&val, NULL, &type_set);
+                       continue;
                case 'V':
-                       handle_property(key, val, len, &type_set);
-                       key = ~0;
+                       handle_property(&key, &val, &type_set);
+                       strbuf_reset(&key);
                        continue;
                default:
                        die("invalid property line: %s\n", t);
@@ -201,16 +204,18 @@ static void handle_node(void)
        uint32_t mark = 0;
        const uint32_t type = node_ctx.type;
        const int have_props = node_ctx.propLength != LENGTH_UNKNOWN;
+       const int have_text = node_ctx.textLength != LENGTH_UNKNOWN;
 
        if (node_ctx.text_delta)
                die("text deltas not supported");
-       if (node_ctx.textLength != LENGTH_UNKNOWN)
+       if (have_text)
                mark = next_blob_mark();
        if (node_ctx.action == NODEACT_DELETE) {
-               if (mark || have_props || node_ctx.srcRev)
+               if (have_text || have_props || node_ctx.srcRev)
                        die("invalid dump: deletion node has "
                                "copyfrom info, text, or properties");
-               return repo_delete(node_ctx.dst);
+               repo_delete(node_ctx.dst);
+               return;
        }
        if (node_ctx.action == NODEACT_REPLACE) {
                repo_delete(node_ctx.dst);
@@ -221,37 +226,47 @@ static void handle_node(void)
                if (node_ctx.action == NODEACT_ADD)
                        node_ctx.action = NODEACT_CHANGE;
        }
-       if (mark && type == REPO_MODE_DIR)
+       if (have_text && type == REPO_MODE_DIR)
                die("invalid dump: directories cannot have text attached");
+
+       /*
+        * Decide on the new content (mark) and mode (node_ctx.type).
+        */
        if (node_ctx.action == NODEACT_CHANGE && !~*node_ctx.dst) {
                if (type != REPO_MODE_DIR)
                        die("invalid dump: root of tree is not a regular file");
        } else if (node_ctx.action == NODEACT_CHANGE) {
-               uint32_t mode = repo_modify_path(node_ctx.dst, 0, mark);
-               if (!mode)
-                       die("invalid dump: path to be modified is missing");
+               uint32_t mode;
+               if (!have_text)
+                       mark = repo_read_path(node_ctx.dst);
+               mode = repo_read_mode(node_ctx.dst);
                if (mode == REPO_MODE_DIR && type != REPO_MODE_DIR)
                        die("invalid dump: cannot modify a directory into a file");
                if (mode != REPO_MODE_DIR && type == REPO_MODE_DIR)
                        die("invalid dump: cannot modify a file into a directory");
                node_ctx.type = mode;
        } else if (node_ctx.action == NODEACT_ADD) {
-               if (!mark && type != REPO_MODE_DIR)
+               if (!have_text && type != REPO_MODE_DIR)
                        die("invalid dump: adds node without text");
-               repo_add(node_ctx.dst, type, mark);
        } else {
                die("invalid dump: Node-path block lacks Node-action");
        }
+
+       /*
+        * Adjust mode to reflect properties.
+        */
        if (have_props) {
-               const uint32_t old_mode = node_ctx.type;
                if (!node_ctx.prop_delta)
                        node_ctx.type = type;
                if (node_ctx.propLength)
                        read_props();
-               if (node_ctx.type != old_mode)
-                       repo_modify_path(node_ctx.dst, node_ctx.type, mark);
        }
-       if (mark)
+
+       /*
+        * Save the result.
+        */
+       repo_add(node_ctx.dst, node_ctx.type, mark);
+       if (have_text)
                fast_export_blob(node_ctx.type, mark,
                                 node_ctx.textLength, &input);
 }
@@ -259,8 +274,9 @@ static void handle_node(void)
 static void handle_revision(void)
 {
        if (rev_ctx.revision)
-               repo_commit(rev_ctx.revision, rev_ctx.author, rev_ctx.log,
-                       dump_ctx.uuid, dump_ctx.url, rev_ctx.timestamp);
+               repo_commit(rev_ctx.revision, rev_ctx.author.buf,
+                       &rev_ctx.log, dump_ctx.uuid.buf, dump_ctx.url.buf,
+                       rev_ctx.timestamp);
 }
 
 void svndump_read(const char *url)
@@ -269,44 +285,65 @@ void svndump_read(const char *url)
        char *t;
        uint32_t active_ctx = DUMP_CTX;
        uint32_t len;
-       uint32_t key;
 
-       reset_dump_ctx(pool_intern(url));
+       reset_dump_ctx(url);
        while ((t = buffer_read_line(&input))) {
-               val = strstr(t, ": ");
+               val = strchr(t, ':');
                if (!val)
                        continue;
-               *val++ = '\0';
-               *val++ = '\0';
-               key = pool_intern(t);
+               val++;
+               if (*val != ' ')
+                       continue;
+               val++;
 
-               if (key == keys.svn_fs_dump_format_version) {
+               /* strlen(key) + 1 */
+               switch (val - t - 1) {
+               case sizeof("SVN-fs-dump-format-version"):
+                       if (constcmp(t, "SVN-fs-dump-format-version"))
+                               continue;
                        dump_ctx.version = atoi(val);
                        if (dump_ctx.version > 3)
                                die("expected svn dump format version <= 3, found %"PRIu32,
                                    dump_ctx.version);
-               } else if (key == keys.uuid) {
-                       dump_ctx.uuid = pool_intern(val);
-               } else if (key == keys.revision_number) {
+                       break;
+               case sizeof("UUID"):
+                       if (constcmp(t, "UUID"))
+                               continue;
+                       strbuf_reset(&dump_ctx.uuid);
+                       strbuf_addstr(&dump_ctx.uuid, val);
+                       break;
+               case sizeof("Revision-number"):
+                       if (constcmp(t, "Revision-number"))
+                               continue;
                        if (active_ctx == NODE_CTX)
                                handle_node();
                        if (active_ctx != DUMP_CTX)
                                handle_revision();
                        active_ctx = REV_CTX;
                        reset_rev_ctx(atoi(val));
-               } else if (key == keys.node_path) {
-                       if (active_ctx == NODE_CTX)
-                               handle_node();
-                       active_ctx = NODE_CTX;
-                       reset_node_ctx(val);
-               } else if (key == keys.node_kind) {
+                       break;
+               case sizeof("Node-path"):
+                       if (prefixcmp(t, "Node-"))
+                               continue;
+                       if (!constcmp(t + strlen("Node-"), "path")) {
+                               if (active_ctx == NODE_CTX)
+                                       handle_node();
+                               active_ctx = NODE_CTX;
+                               reset_node_ctx(val);
+                               break;
+                       }
+                       if (constcmp(t + strlen("Node-"), "kind"))
+                               continue;
                        if (!strcmp(val, "dir"))
                                node_ctx.type = REPO_MODE_DIR;
                        else if (!strcmp(val, "file"))
                                node_ctx.type = REPO_MODE_BLB;
                        else
                                fprintf(stderr, "Unknown node-kind: %s\n", val);
-               } else if (key == keys.node_action) {
+                       break;
+               case sizeof("Node-action"):
+                       if (constcmp(t, "Node-action"))
+                               continue;
                        if (!strcmp(val, "delete")) {
                                node_ctx.action = NODEACT_DELETE;
                        } else if (!strcmp(val, "add")) {
@@ -319,21 +356,44 @@ void svndump_read(const char *url)
                                fprintf(stderr, "Unknown node-action: %s\n", val);
                                node_ctx.action = NODEACT_UNKNOWN;
                        }
-               } else if (key == keys.node_copyfrom_path) {
+                       break;
+               case sizeof("Node-copyfrom-path"):
+                       if (constcmp(t, "Node-copyfrom-path"))
+                               continue;
                        pool_tok_seq(REPO_MAX_PATH_DEPTH, node_ctx.src, "/", val);
-               } else if (key == keys.node_copyfrom_rev) {
+                       break;
+               case sizeof("Node-copyfrom-rev"):
+                       if (constcmp(t, "Node-copyfrom-rev"))
+                               continue;
                        node_ctx.srcRev = atoi(val);
-               } else if (key == keys.text_content_length) {
-                       node_ctx.textLength = atoi(val);
-               } else if (key == keys.prop_content_length) {
+                       break;
+               case sizeof("Text-content-length"):
+                       if (!constcmp(t, "Text-content-length")) {
+                               node_ctx.textLength = atoi(val);
+                               break;
+                       }
+                       if (constcmp(t, "Prop-content-length"))
+                               continue;
                        node_ctx.propLength = atoi(val);
-               } else if (key == keys.text_delta) {
-                       node_ctx.text_delta = !strcmp(val, "true");
-               } else if (key == keys.prop_delta) {
+                       break;
+               case sizeof("Text-delta"):
+                       if (!constcmp(t, "Text-delta")) {
+                               node_ctx.text_delta = !strcmp(val, "true");
+                               break;
+                       }
+                       if (constcmp(t, "Prop-delta"))
+                               continue;
                        node_ctx.prop_delta = !strcmp(val, "true");
-               } else if (key == keys.content_length) {
+                       break;
+               case sizeof("Content-length"):
+                       if (constcmp(t, "Content-length"))
+                               continue;
                        len = atoi(val);
-                       buffer_read_line(&input);
+                       t = buffer_read_line(&input);
+                       if (!t)
+                               die_short_read();
+                       if (*t)
+                               die("invalid dump: expected blank line after content length header");
                        if (active_ctx == REV_CTX) {
                                read_props();
                        } else if (active_ctx == NODE_CTX) {
@@ -341,10 +401,13 @@ void svndump_read(const char *url)
                                active_ctx = REV_CTX;
                        } else {
                                fprintf(stderr, "Unexpected content length header: %"PRIu32"\n", len);
-                               buffer_skip_bytes(&input, len);
+                               if (buffer_skip_bytes(&input, len) != len)
+                                       die_short_read();
                        }
                }
        }
+       if (buffer_ferror(&input))
+               die_short_read();
        if (active_ctx == NODE_CTX)
                handle_node();
        if (active_ctx != DUMP_CTX)
@@ -356,20 +419,23 @@ int svndump_init(const char *filename)
        if (buffer_init(&input, filename))
                return error("cannot open %s: %s", filename, strerror(errno));
        repo_init();
-       reset_dump_ctx(~0);
+       strbuf_init(&dump_ctx.uuid, 4096);
+       strbuf_init(&dump_ctx.url, 4096);
+       strbuf_init(&rev_ctx.log, 4096);
+       strbuf_init(&rev_ctx.author, 4096);
+       reset_dump_ctx(NULL);
        reset_rev_ctx(0);
        reset_node_ctx(NULL);
-       init_keys();
        return 0;
 }
 
 void svndump_deinit(void)
 {
-       log_reset();
        repo_reset();
-       reset_dump_ctx(~0);
+       reset_dump_ctx(NULL);
        reset_rev_ctx(0);
        reset_node_ctx(NULL);
+       strbuf_release(&rev_ctx.log);
        if (buffer_deinit(&input))
                fprintf(stderr, "Input error\n");
        if (ferror(stdout))
@@ -378,10 +444,10 @@ void svndump_deinit(void)
 
 void svndump_reset(void)
 {
-       log_reset();
        buffer_reset(&input);
        repo_reset();
-       reset_dump_ctx(~0);
-       reset_rev_ctx(0);
-       reset_node_ctx(NULL);
+       strbuf_release(&dump_ctx.uuid);
+       strbuf_release(&dump_ctx.url);
+       strbuf_release(&rev_ctx.log);
+       strbuf_release(&rev_ctx.author);
 }