Compare commits

...

154 Commits

Author SHA1 Message Date
ae6ec6124b Merge branch 'bw/searching' 2011-10-19 13:35:30 +01:00
8eaf24b93b git-gui: enable the smart case sensitive search only if gui.search.smartcase is true
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-19 13:29:52 +01:00
b66f4f7aa7 git-gui: catch invalid or complete regular expressions and treat as no match.
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-19 13:22:33 +01:00
3592767276 git-gui: theme the search and line-number entry fields on blame screen
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-19 12:44:39 +01:00
99665fc582 git-gui: include the number of untracked files to stage when asking the user
Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-18 09:44:10 +01:00
bb196e2619 git-gui: new config to control staging of untracked files
The default is the current "ask".

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-18 09:44:10 +01:00
526aa2b203 git-gui: use "untracked" for files which are not known to git
"untracked" is the right phrase for files new to git. For example
git-status uses this phrase. Also make the question shorter.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-18 09:44:10 +01:00
b020bbd5a0 git-gui: fix unintended line break in message string
Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-18 09:44:10 +01:00
1159971baa git-gui: add search history to searchbar
Use the up/down keys to browse the history.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-18 09:27:28 +01:00
e9144d5555 git-gui: add regexp search mode to the searchbar
It's off by default, but can be enabled via the config gui.search.regexp.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-18 09:27:28 +01:00
0a0243d733 git-gui: add smart case search mode in searchbar
Setting config gui.search.smartcase to true, the search mode in the
searchbar (from the blame view) is by default case-insensitive. But
entering an upper case letter into the search field activates the case-
sensitive search mode.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-18 09:27:28 +01:00
12b219f7f9 git-gui: handle config booleans without value
When git interprets a config variable without a value as bool it is considered
as true. But git-gui doesn't so until yet.

The value for boolean configs are also case-insensitive.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-18 09:27:28 +01:00
a8ca786991 git-gui: fix multi selected file operation
When staging a selection of files using Shift-Click to choose a range
of files then using Ctrl-T or the Stage To Commit menu item will stage
all the selected files. However if a non-sequential range is selected
using Ctrl-Click then all but the first name selected gets staged. This
commit fixes this to properly stage all selected files by explicitly
adding the path to the list before showing the diff.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-18 09:10:51 +01:00
843d6597fb git-gui: incremental goto line in blame view
The view jumps now to the given line number after each key press.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-15 23:14:13 +01:00
81a92e5205 git-gui: clear the goto line input when hiding
Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-15 23:14:13 +01:00
59252107ac git-gui: only accept numbers in the goto-line input
Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-15 23:13:32 +01:00
e0e0a6c64c git-gui: search and linenumber input are mutual exclusive in the blame view
It was possible to open the search input (Ctrl+S) and the goto-line input
(Ctrl+G) at the same time. Prevent this.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-15 09:13:33 +01:00
856c2d75c6 git-gui: deal with unknown files when pressing the "Stage Changed" button
As a shortcut the "Stage Changed" button can be used to stage all current
changes in the worktree which are not set to ignore. Previously unknown
files would be ignored. The user might want to say: "Just save everything
in my worktree". To support this workflow we now ask whether the user also
wants to stage the unknown files if there are some present.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-10-06 23:20:16 +01:00
29776c75d0 git-gui: drop the 'n' and 'Shift-n' bindings from the last patch.
The 'n' binding should cause the next match to be selected but results
in the search field gaining focus and additional 'n's being appended.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-07-19 15:33:34 +01:00
af9a4625fa git-gui: Add keyboard shortcuts for search and goto commands in blame view.
Use forward-slash or Control-S to bring up the search dialog.
In the blame view, Enter or 'n' jump to the next selected region while
Shift-Enter or Shift-n will jump to the previous selected region.
Within the search control, hitting Enter will now jump to the next matching
region.

Signed-off-by: David Fries <David@Fries.net>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-07-19 15:31:29 +01:00
9a483e5c09 git-gui: Enable jumping to a specific line number in blame view.
This patch adds a goto control similar to the search control currently
available. The goto control permits the user to specify a line number to
jump to.
When in blame, Control-G is bound to display this control.

Signed-off-by: David Fries <David@Fries.net>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-07-19 15:31:24 +01:00
768e300a50 Fix tooltip display with multiple monitors on windows.
On Windows the position of a window may be negative on a monitor to the
left of the primary display. A plus sign is used as the separator between
the width and height and the positional parts of the geometry so always
include the plus sign even for negative positions on this platform.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-07-11 13:55:38 +01:00
c5c45e1a2d Fix typo: existant->existent
This typo was discovered in core git sources.
Clean in it up in git-gui too.
There is just one occurence in a comment line.

Signed-off-by: Dmitry Ivankov <divanorama@gmail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-07-11 11:26:47 +01:00
8c0bf68353 git-gui: updated translator README for current procedures.
We do not have a mob branch and the i18n fork is no longer used. Suggest
translators simply send patches as per other contributors.

Reported-by: Rodrigo Rosenfeld <rr.rosas@gmail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-07-11 11:26:46 +01:00
e34789cc8b git-gui: warn when trying to commit on a detached head
The commandline is already warning when checking out a detached head.
Since the only thing thats potentially dangerous is to create commits
on a detached head lets warn in case the user is about to do that.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-05-20 22:49:15 +01:00
1cac41f8ea git-gui: Corrected a typo in the Swedish translation of 'Continue'
Reported-by: Christoffer Pettersson <corgrath@gmail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-05-16 10:36:00 +01:00
fbc9629e2f Merge branch 'ss/git-gui-mergetool' 2011-03-25 08:26:47 +00:00
35b6f72feb git-gui: detect the use of MUI langauge packs on Windows
The Tcl msgcat package doesn't detect the use of a multi-lingual language
pack on Windows 7. This means that a user may have their display language
set to Japanese but the system installed langauge was English.
This patch reads the relevent registry key to fix this before loading in
the locale specific parts of git-gui.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-03-25 08:26:31 +00:00
f3768a6714 mergetool--lib: Add Beyond Compare 3 as a tool
Signed-off-by: Sebastian Schuberth <sschuberth@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-02-27 00:47:34 -08:00
0e0f450427 mergetool--lib: Sort tools alphabetically for easier lookup
Signed-off-by: Sebastian Schuberth <sschuberth@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-02-27 00:47:13 -08:00
4c2519e5a2 git-gui: fetch/prune all entry appears last
The user might have got used to the order the remotes appeared previously.
Lets add the all entry last so the all entry does not confuse previous
users.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Tested-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-02-24 00:11:50 +00:00
4bfa2502f7 git-gui: fetch/prune all entry only for more than one entry
In case there is only one remote a fetch/prune all entry
is redundant.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Tested-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-02-24 00:11:45 +00:00
ba44692a2e git-gui: Include version check and test for tearoff menu entry
The --all option for git fetch was added in v1.6.6 so ensure we have a usable version before adding
the menu items.
Sometimes people use tearoff menus and these offset the entry indices by one.

Acked-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-02-15 00:20:36 +00:00
69e21b8392 git-gui: teach fetch/prune menu to do it for all remotes
The commandline fetch already has this option for some time.  Since this
was not available at the time git gui was written lets implement it now.

Signed-off-by: Heiko Voigt <heiko.voigt@mahr.de>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-02-14 12:15:36 +00:00
e8db4035df git-gui: refactor remote submenu creation into subroutine
Signed-off-by: Heiko Voigt <heiko.voigt@mahr.de>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-02-14 12:10:54 +00:00
9d04278a4d git-gui: always default to the last merged branch in remote delete
This is useful if you are directly working together with other
developers pushing feature branches on a shared remote. You typically
push feature branches to the remote so others can review. Once they are
satisfied and the branch is merged into the main branch it needs to be
deleted on the server.

Since we did not yet have a preselected default branch in the remote
delete dialog lets use the last merged branch if it is found on the
server.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-02-13 00:47:24 +00:00
8b92658206 git-gui: fix deleting item from all_remotes variable
lsearch and lreplace both take the variable content as argument and not
just their name.

Signed-off-by: Heiko Voigt <heiko.voigt@mahr.de>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-02-13 00:47:19 +00:00
df128139c6 git-gui: instead of defaulting to home directory use working directory
When starting git gui in a non-git directory it presents the user a
dialog which asks to create, clone or open a repository. The filedialogs
used to choose the path(s) would always default to the home directory of
the user. This patch changes this behavior and uses the current working
directory in which git gui was started as default.

This is useful in various cases. First being that the user starts the
gui in some directory and can go search to create, open or clone a
repository from there. Another use case is that tools like filemanager
context menues can transport a natural default when selected from a
folder.

Users who like to have their home folder as a default can fall back on
starting git gui with its working directory set to the home folder.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-02-06 22:43:35 +00:00
fb027e148a git-gui: scroll down to default selection for push dialog
If the list of remote/local branches is very long its inconvenient
to scroll down and find the selected branch. This patch makes the
widget automatically scroll down so its shown on the top.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-02-06 22:20:05 +00:00
9e34e62bcb git gui: keep selected branch when remote is changed in push dialog
The selection of the branch to be pushed would be cleared when
the remote was changed. This seems to be dependent on the fact that
the selected content in the combobox was exported to the clipboard. It
was only apparent when using the new ttk widget.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-02-06 22:03:39 +00:00
bf59439847 git-gui: handle meta diff header lines only in the header section
Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-28 09:01:17 +00:00
d1c7f8aa66 git-gui: handle special content lines only in the diff header section
These two also stop the diff header.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-28 09:01:17 +00:00
6459d7c046 git-gui: always reset the current tag
Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-28 09:01:17 +00:00
963ceab57e git-gui: move 3way diff autodetect up
Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-28 09:01:17 +00:00
3c9ae64c81 git-gui: there is no "mode *" diff header line
Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-28 09:01:17 +00:00
97b8ee1671 git-gui: name also new symlinks so
and rename them only in the diff header

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-28 09:01:17 +00:00
ebd143ff99 git-gui: handle index lines only in the diff header
Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-28 09:01:17 +00:00
c976bbff3c git-gui: rework handling of diff header
The fix in ca53c3f (Fix diff parsing for lines starting with "--" or "++",
2008-09-05) got a bug report from Johannes Sixt, that new files in the
index now looks like:

  new file mode 100644
  --- /dev/null
  +++ b/foo
  @@ -0,0 +1 @@
  +foo

The introduced problem was that the 'in-diff-header'-flag was unconditially
disabled. Now it is only disabled when a hunk line is detected. And also
re-enabled when we encounter a new diff header.

The second part solves also the issue reported by me for diffs with file
type changes (i.e. the ''error: Unhandled 2 way diff marker: {d}"', which
comes from the second 'diff --git' line).

Reported-by: Johannes Sixt <j.sixt@viscovery.net>
Reported-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-28 09:01:17 +00:00
7587f4d32f git-gui: learn more type change states
Support the following states with type change in git-gui: AT, MT, TD, TM

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-28 00:16:50 +00:00
4a065c8a6f git-gui: remove 'no such variable' for s error when encounter unknown file states
$s will be referenced in the error message. Which was broken since
"git-gui: Automatically update-index all included files before commit"
(bbe3b3b, 2006-11-16).

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-28 00:16:46 +00:00
bf5fe3f33c git-gui: fix typo in image data
Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-28 00:16:42 +00:00
7b3680f162 git-gui: add Brazilian Portuguese (pt-BR) translation
Translating a SCM is tricky due to amount of jargon, so, I tried to
keep the wording consistent with both the German and Italian git
translations and the pt-BR translation of other SCMs.

Signed-off-by: Alexandre Erwin Ittner <alexandre@ittner.com.br>
2011-01-27 16:22:10 +00:00
073291c476 git-gui: update russian translation
Improve the translation of warning given by mergetool when staging files with
conflict markers.

Suggested-by: Alexey Shumkin <zapped@mail.ru>
Tipping-vote-by: Dmitry Potapov <dpotapov@gmail.com>
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-24 23:46:38 +00:00
75e88a592f git-gui: update russian translation
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-24 23:46:33 +00:00
b6efd40d6c git-gui: spelling fixes in russian translation
Signed-off-by: Skip <bsvskip@rambler.ru>
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-24 23:46:29 +00:00
9673abc7cc git-gui: fix russian translation typos
Signed-off-by: Serge Ziryukin <ftrvxmtrx@gmail.com>
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2011-01-24 23:46:25 +00:00
673eb4a01f git-gui: use --exclude-standard to check for untracked files
This fixes git-gui failing to display untracked files that are listed
if core.excludefiles is set to ~/.gitexcludes

[PT: added expansion of core.excludesfile value by tcl]

Signed-off-by: Stefan Naewe <stefan.naewe@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-12-10 15:42:09 +00:00
88b21c2a40 git-gui: Fix use of hunk tag for non-hunk content.
The hunk tag d_@ lost its blue forground color in "apply color information
from git diff output" (2010-10-22, 8f85599). But this tag was also used
for non-hunk content like untracked file mime types or git submodules.

Introduce a new tag for this type of content which has the blue forground
again.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-12-06 22:01:01 +00:00
c7ec31a36e git-gui: Fix use of renamed tag.
The d======= was renamed to d= in 4590307.

Fix this.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-12-06 21:09:53 +00:00
1ab862862f git-gui: fix browsers [Up To Parent] in sub-sub-directories.
browser_path used to end with a slash, so the regexp matches the empty string
and therefore removes nothing.

Fix this.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-11-22 21:52:51 +00:00
4590307a33 git-gui: respect conflict marker size
Respect the conflict-marker-size attribute on paths when detecting merge
conflicts.

[PT: fixed problem with variable substitution in the regexps]

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-11-19 11:25:00 +00:00
46a0431b99 git-gui: fix ANSI-color parsing
git diff always outputs color reset commands, even when the color for the
current part is disabled (ie. normal). But the current ANSI-color parsing code
assumes that color start and reset commands appear in matching pairs.

Relax this assumption.

Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-11-19 09:32:58 +00:00
8f85599aba git-gui: apply color information from git diff output
This patch extracts the ANSI color sequences from git diff output and
applies these to the diff view window. This ensures that the gui view
makes use of the current git configuration for whitespace display.

ANSI codes may include attributes, foreground and background in a single
sequence. Handle this and support bold and reverse attributes. Ignore
all other attributes.

Suggested-by: Tor Arvid Lund <torarvid@gmail.com>
Suggested-by: Junio C Hamano <gitster@pobox.com>
Tested-by: Tor Arvid Lund <torarvid@gmail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-10-27 23:47:28 +01:00
c744086964 git-gui: use wordprocessor tab style to ensure tabs work as expected
The Tk text widget tab style is tabular where the first tab will align to
the first tabstop and if that position is left of the current location
then just a single character space is used. With the wordprocessor style
a tab moves the next character position to the next rightmost tabstop
as expected for viewing code.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-10-27 23:37:31 +01:00
38ec8d3e26 git-gui: correct assignment of work-tree
git-gui currently uses its own logic to determine the work-tree setting
but 'git rev-parse --toplevel' directly returns git's work-tree value
by calling get_git_work_tree() and is therefore always correct.

This fixes an inability to handle some repository configurations. In
particular where .git is a file containing a path to the real directory
(a cross-platform symbolic link).
To continue to support older versions than 1.7.0, setting the work-tree
by normalizing the --show-cdup value is more reliable as git-dir might be
outside the work-tree entirely.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-10-20 14:29:56 +01:00
4c56d1ddc0 git-gui: use full dialog width for old name when renaming branch
Let the combobox/option menu expand to fill the width of the dialog.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-10-07 23:00:33 +01:00
67112c484b git-gui: generic version trimming
Rather than attempting to trim off all the non-version number suffixes
from the 'git version' result, let us scan along from the beginning until
we find a non-numeric part and stop there. Any such dot-version number will
be compatible with the Tcl package version comparison command which is the
aim of this code.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-10-07 22:28:45 +01:00
c0d2c38d78 git-gui: enable the Tk console when tracing/debugging on Windows
Without any standard channels the trace option is pretty useless on Win32
unless you can show the Tk console which captures such output. This also
permits introspection of the running application to assist in debugging.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-10-05 23:51:34 +01:00
7ae1e72762 git-gui: show command-line errors in a messagebox on Windows
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-10-05 23:39:54 +01:00
ff9db6c79d On Windows, avoid git-gui to call Cygwin's nice utility
It's a common case for Windows developers to have both Cygwin and msysGit
installed. Unfortunately, some scenarios also require to have Cygwin in PATH.
By default, Cygwin comes with nice.exe, while msysGit does not. Since git-gui
calls nice if it is in PATH, this results in Cygwin's nice.exe being called
from msysGit's git-gui. Mixing Cygwin and msysGit generally is not a good idea,
and in this particular case it causes differences not being correctly detected.
So we only call nice.exe on Windows if it is in the same directory as git.exe.
This way, this work-around does neither affect a pure Cygwin environment, or
the case when nice.exe will be shipped with msysGit at some point in time.

This fixes msysGit issue 394.

Signed-off-by: Sebastian Schuberth <sschuberth@gmail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-10-05 10:58:14 +01:00
00e9de72c8 git-gui 0.13
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-09-14 22:42:37 +01:00
2473543caa git-gui: avoid mis-encoding the copyright message on Windows.
On Windows the tcl script file will use the system encoding and attempting
to convert the copyright mis-encodes the string. Instead, keep the message
as ASCII and substitute in the correct unicode character when running.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-09-13 20:41:42 +01:00
421a31e22d git-gui: Update Swedish translation (521t).
Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-09-13 19:25:55 +01:00
aef0b48ef0 git-gui: ensure correct application termination in git-gui--askpass
With Tk 8.5 the askpass utility can hang waiting for the wish shell
implicit event loop to exit. This patch uses an explicit event loop
to ensure correct application termination.

Reported-by: Anders Kaseorg <andersk@mit.edu>
Tested-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-08-18 23:19:24 +01:00
d5257fb3c1 git-gui: handle textconv filter on Windows and in development
When developing/testing we run git-gui.sh directly and the makefile
configured variables are not properly set. Configure the new shellpath
accessor to handle this case.

On Windows we may not find the shell so in this case revert to simply
executing the filter command without the shell intermediate.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-08-12 21:37:32 +01:00
62f9a632c8 git-gui: use shell to launch textconv filter in "blame"
The textconv filters may include multiple arguments and may make use
of unix shell features. To maintain compatibility with 'git blame'
ensure these commands are passed through bash.

Reported-by: Kirill Smelkov <kirr@landau.phys.spbu.ru>
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-08-12 21:35:09 +01:00
780777720a git-gui: display error launching blame as a message box.
This does not appear to Windows users and can follow the form of the fatal
error messages near the top of the script file.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-08-08 00:07:43 +01:00
ea47503d4d git-gui: Make usage statement visible on Windows.
On Windows stdout and stderr are not connected to anything so the usage
statement is never shown to the user when an error is made with a command
line like 'git gui browser'. Use a messagebox on windows.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-08-08 00:07:01 +01:00
2810a58dba git-gui: fix size and position of window panes on startup
The themed panedwindow needs to have the sash position set after the
widget has been mapped therefore apply this setting in the Map event
binding. To avoid visible redraws as the application is constructed
the main window should be withdrawn until all the widgets have been added

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-08-02 13:42:45 +01:00
9cb268c426 git-gui: mc cannot be used before msgcat has been loaded
If someone attempts to use an older version that Tk 8.4 the error was
masked by the lack of a mc command.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-08-02 12:13:05 +01:00
1fbaccad4d git-gui: use textconv filter for diff and blame
Create a checkbox "Use Textconv For Diffs and Blame" in git-gui options.
If checked and if the driver for the concerned file exists, git-gui calls diff
and blame with --textconv option

Signed-off-by: Clément Poulain <clement.poulain@ensimag.imag.fr>
Signed-off-by: Diane Gasselin <diane.gasselin@ensimag.imag.fr>
Signed-off-by: Axel Bonnet <axel.bonnet@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-07-30 10:05:27 +01:00
85123549f0 git-gui: Avoid using the <<Copy>> binding as a menu accelerator on win32
On Windows the Control-C binding is used to copy and is mapped to the Tk
virtual event <<Copy>>. In the initial git-gui dialog this is also bound
as an accelerator for the Clone menu item. The effect is that both bindings
run, copying the text but resetting the clone page or switching to the clone
page when the user tries to copy text from one of the entry fields.
This patch avoids this by using Control-L instead for Windows only.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-07-30 10:05:27 +01:00
fc17e5e5bd git-gui: fix shortcut creation on cygwin
When the user tried to create a desktop icon with git gui on cygwin
wscript was complaining about an unknown option and displaying the
non-native path as such.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-07-30 10:05:26 +01:00
4c79adc5c0 git-gui: fix PATH environment for mingw development environment
When creating a desktop shortcut from the gui the shortcut directly
starts wish with the git-gui script. In the msysgit development
environment some dll's reside in the mingw/bin directory which causes
that git can not start because libiconv2.dll is not found.

When using such a link the error is even more cryptic stating:
"child killed: unknown signal"

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-07-30 09:57:26 +01:00
a197b1e89a git-gui: fix usage of _gitworktree when creating shortcut for windows
This fixes msysGit issue 425.

Signed-off-by: Heiko Voigt <heiko.voigt@mahr.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-07-30 09:57:26 +01:00
2e0cda658e git-gui: fix "Explore Working Copy" for Windows again
It has already been fixed in commit 454efb47 (git-gui (Win): make
"Explore Working Copy" more robust, 2009-04-01), but has been broken in
commit 21985a11 (git-gui: handle non-standard worktree locations,
2010-01-23) by accidentally replacing too much with a new variable.

The problem can be reproduced when starting git-gui from within a
subdirectory. The solution is to convert the path name, explorer.exe is
invoked with, to a platform native name.

Signed-off-by: Markus Heidelberg <markus.heidelberg@web.de>
Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-07-30 09:57:26 +01:00
b963d11827 git-gui: fix usage of themed widgets variable
There was one forgotten global so NS was not visible to the method
which resulted in an error.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
2010-07-10 23:41:54 +01:00
13a3d637b2 git-gui: Handle failure of core.worktree to identify the working directory.
Commit 21985a11 'git-gui: handle non-standard worktree locations' attempts
to use either GIT_WORK_TREE or core.worktree to set the _gitworktree
variable but these may not be set which leads to a failure to launch
gitk to review history. Use _gitdir to set the location for a standard
git layout where the parent of the .git directory is the working tree.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
2010-07-10 23:40:59 +01:00
2a9edd0305 Merge branch 'maint'
* maint:
  git-gui: check whether systems nice command works or disable it
2010-02-08 07:57:37 -08:00
9c898a18ea git-gui: check whether systems nice command works or disable it
This fixes issue 394 from msysgit. It seems that the Gnuwin32 project
provides a nice command but it returns a "not implemented" error. To
help users we now try to execute once and disable it in case it fails.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-02-08 07:56:55 -08:00
89d61592bd git-gui: update french translation
Signed-off-by: Emmanuel Trillaud <etrillaud@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-02-02 07:34:04 -08:00
5bf46841c0 git-gui: update Japanese translation
Update ja.po to match 2010-01-26 version of pot file.

Signed-off-by: しらいし ななこ <nanako3@lavabit.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-02-02 06:59:06 -08:00
e1a3f28b14 Merge branch 'maint'
* maint:
  git-gui: fix shortcut for menu "Commit/Revert Changes"
2010-01-29 07:58:56 -08:00
d6db1bbe11 git-gui: fix shortcut for menu "Commit/Revert Changes"
The shortcut was not properly recognized previously.

Signed-off-by: Heiko Voigt <heiko.voigt@mahr.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-29 07:58:52 -08:00
831cc7ebb4 git-gui: Quote git path when starting another gui in a submodule
In do_git_gui the path of the git executable has to be put into a
list, otherwise calling it will fail when when spaces are present
in its path.

Reported-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-28 15:44:41 -08:00
cbdaf567c9 git-gui: update Italian translation
Signed-off-by: Michele Ballabio <barra_cuda@katamail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-28 07:18:29 -08:00
fe9c06b7c9 git-gui: Update Swedish translation (520t0f0u)
Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-28 07:17:47 -08:00
c80d7be5e1 git-gui: use themed tk widgets with Tk 8.5
This patch enables the use of themed Tk widgets with Tk 8.5 and above.
These make a significant difference on Windows in making the
application appear native. On Windows and MacOSX ttk defaults to the
native look as much as possible. On X11 the user may select a theme
using the TkTheme XRDB resource class by adding an line to the
.Xresources file. The set of installed theme names is available using
the Tk command 'ttk::themes'. The default on X11 is similar to the current
un-themed style - a kind of thin bordered motif look.

A new git config variable 'gui.usettk' may be set to disable this if
the user prefers the classic Tk look. Using Tk 8.4 will also avoid the
use of themed widgets as these are only available since 8.5.

Some support is included for Tk 8.6 features (themed spinbox and native
font chooser for MacOSX and Windows).

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-27 17:13:52 -08:00
ab2d3b0d7d git-gui: Update German translation (12 new or changed strings).
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-27 17:13:47 -08:00
60eb4f1bd0 git-gui: Update translation template
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-26 15:47:45 -08:00
73b3446b82 git-gui: Remove unused icon file_parttick
This icon hasn't been used in git gui.  I think it dates back to
the original set of icons I took from Paul Mackerras' prototype
that I turned into git gui.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-25 07:33:41 -08:00
0602de48f7 git-gui: use different icon for new and modified files in the index
This allows to quickly differentiate between new and modified files
in the index without selecting the file and looking at the diff.

Signed-off-by: Peter Oberndorfer <kumbayo84@arcor.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-25 07:31:38 -08:00
a9fa11fe5b git-gui: set GIT_DIR and GIT_WORK_TREE after setup
Rather than juggling with the env var GIT_DIR around the invocation of
gitk, set it and GIT_WORK_TREE after finishing setup, ensuring that any
external tool works with the setup we're running with.

This also allows us to remove a couple of conditionals when running gitk
or git gui in a submodule, as we know that the variables are present and
have to be unset and reset before and after the invocation.

Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 16:02:16 -08:00
3748b03d92 git-gui: update shortcut tools to use _gitworktree
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 15:15:55 -08:00
29e5573d1e git-gui: handle bare repos correctly
Refactor checking for a bare repository into its own proc, that relies
on git rev-parse --is-bare-repository if possible. For older versions of
git we fall back to a logic such that the repository is considered bare
if:
 * either the core.bare setting is true
 * or the worktree is not set and the directory name ends with .git
The error message for the case of an unhandled bare repository is also
updated to reflect the fact that the problem is not the funny name but
the bareness.

The new refactored proc is also used to disable the menu entry to
explore the working copy, and to skip changing to the worktree before
the gitk invocation.

Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 15:14:21 -08:00
21985a1136 git-gui: handle non-standard worktree locations
Don't rely on the git worktree being the updir of the gitdir, since it
might not be. Instead, define (and use) a new _gitworktree global
variable, setting it to $GIT_WORK_TREE if present, falling back to
core.worktree if defined, and finally to whatever we guess the correct
worktree is. Getting core.worktree requires the config from the alleged
git dir _gitdir to be loaded early.

Supporting non-standard worktree locations also breaks the git-gui
assumption (made when calling gitk) that the worktree was the dirname of
$_gitdir and that, by consequence, the git dir could be set to the tail
of $_gitdir once we changed to the worktree root directory. Therefore,
we need to export a GIT_DIR environment variable set to the full,
normalized path of $_gitdir instead. We also skip changing to the worktree
directory if it's empty (i.e. if we're working on a bare repository).

Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 15:14:21 -08:00
ff07c3b621 git-gui: Support applying a range of changes at once
Multiple lines can be selected in the diff viewer and applied all
at once, rather than selecting "Stage Line For Commit" on each
individual line.

Signed-off-by: Jeff Epler <jepler@unpythonic.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 15:14:15 -08:00
25476c63e7 git-gui: Add a special diff popup menu for submodules
To make it easier for users to deal with submodules, a special diff
popup menu has been added for submodules. The "Show Less Context"
and "Show More Context" entries have been removed, as they don't make
any sense for a submodule summary. Four new entries are added to the
top of the popup menu to gain access to more detailed information
about the changes in a submodule than the plain summary does offer.

These are:
- "Visualize These Changes In The Submodule"
  starts gitk showing the selected commit range

- "Visualize These Changes In The Submodule"
  starts gitk showing the whole submodule history of the current branch

- "Visualize All Branch History In The Submodule"
  starts gitk --all in the submodule

- "Start git gui In The Submodule"
  guess what :-)

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 15:14:15 -08:00
a9ae14a1c5 git-gui: Use git diff --submodule when available
Doing so is much faster and gives the same output.
Here are some numbers:

  $ time git submodule summary
  real	0m0.219s
  user	0m0.050s
  sys	0m0.111s

  $ time git diff --submodule
  real	0m0.012s
  user	0m0.003s
  sys	0m0.009s

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 15:14:15 -08:00
87cd09f43e git-gui: work from the .git dir
When git-gui is run from a .git dir, _gitdir would be set to "." by
rev-parse, something that confuses the worktree detection.

Fix by expanding the value of _gitdir to pwd in this special case.

Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 15:14:04 -08:00
390425bdef git-gui: Fix applying a line when all following lines are deletions
If a diff looked like:

 @@
  context
 -del1
 -del2

and you wanted to stage the deletion 'del1', the generated patch
wouldn't apply because it was missing the line 'del2' converted to
context, but this line was counted in the @@-line

Signed-off-by: Jeff Epler <jepler@unpythonic.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 15:00:09 -08:00
7ec2b69f1a git-gui: Correct file_states when unstaging partly staged entry
When unstaging a partly staged file or submodule, the file_states
list was not updated properly (unless unstaged linewise). Its
index_info part did not contain the former head_info as it should
have but kept its old value.

This seems not to have had any bad effects but diminishes the value
of the file_states list for future enhancements.

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 14:46:13 -08:00
e27d106ec4 git-gui: Fix gitk for branch whose name matches local file
When trying to run gitk on a branch name whose name matches a local
file, it will toss an error saying that the name is ambiguous. Adding
a pair of dashes will make gitk parse the options to the left of
it as branch names. Since wish eats the first pair of dashes we
throw at it, we need to add a second one to ensure they get through.

Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 14:46:12 -08:00
3c6a287027 git-gui: Keep repo_config(gui.recentrepos) and .gitconfig in sync
When the number of recent repo's gets to ten there can be a
situation where an item is removed from the .gitconfig file via
a call to git config --unset, but the internal representation of
that file (repo_config(gui.recentrepo)) is not updated.  Then a
subsequent attempt to remove an item from the list fails because
git-gui attempts to call --unset on a value that has already
been removed.  This leads to duplicates in the .gitconfig file,
which then also cause errors if the git-gui tries to --unset them
(rather than using --unset-all. --unset-all is not used because it
is not expected that duplicates should ever be allowed to exist.)

When loading the list of recent repositories (proc _get_recentrepos)
if a repo in the list is not considered a valid git reposoitory
then we should go ahead and remove it so it doesn't take up a slot
in the list (since we limit to 10 items). This will prevent a bunch
of invalid entries in the list (which are not shown) from making
valid entries dissapear off the list even when there are less than
ten valid entries.

See: http://code.google.com/p/msysgit/issues/detail?id=362
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 14:46:12 -08:00
ea888f84bd git-gui: handle really long error messages in updateindex.
As reported to msysGit (bug #340) it is possible to get some very
long error messages when updating the index. The use of a label to
display this prevents scrolling the output. This patch replaces the
label with a scrollable text widget configured to look like a label.

Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23 14:22:28 -08:00
b677c66e29 git-gui: Add hotkeys for "Unstage from commit" and "Revert changes"
Signed-off-by: Vitaly _Vi Shukela <public_vi@tut.by>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-06 18:21:11 -08:00
54350a2bb4 git-gui: Makefile: consolidate .FORCE-* targets
Providing multiple targets to force a rebuild is unnecessary
complication.

Avoid using a name that could conflict with future special
targets in GNU make (a leading period followed by uppercase
letters).

Cc: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-06 18:20:01 -08:00
60204ddb99 git-gui: suppress RenderBadPicture X error caused by Tk bug
Due to a bug in Tk, git-gui almost always (unless git-gui is closed
right after starting) produces an X window error message on exit,
something like:

X Error of failed request:  RenderBadPicture (invalid Picture parameter)
  Major opcode of failed request:  150 (RENDER)
  Minor opcode of failed request:  7 (RenderFreePicture)
  Picture id in failed request: 0x3a000dc
  Serial number of failed request:  1965
  Current serial number in output stream:  1980

Respective Tk bug report is here:

http://sourceforge.net/tracker/?func=detail&atid=112997&aid=1821174&group_id=12997

This bug is triggered only when the send command is blocked via
rename send {} . The following patch re-enables send just before
quiting git-gui to suppress the error.

Signed-off-by: Jindrich Makovicka <makovick@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-12-07 07:39:58 -08:00
10852086d4 git-gui: Increase blame viewer usability on MacOS.
On MacOS raising a window causes the focus to be transferred
to it -- although it may actually be a bug in the Tcl/Tk port.
When this happens with the blame viewer tooltips, it makes
the interface less usable, because Entry and Leave handlers
on the text view cause the tip to disappear once the mouse
is moved even 1 pixel.

This commit makes the code raise the main window on MacOS
when Tk 8.5 is used. This version seems to properly support
wm transient by making the tip stay on top of the master,
so reraising the master does not cause it to disappear. Thus
the only remaining sign of problems is slight UI flicker
when focus is momentarily transferred to the tip and back.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-12-05 14:26:59 -08:00
88520cadf9 git-gui: search 4 directories to improve statistic of gc hint
On Windows, git-gui suggests running the garbage collector if it finds
1 or more files in .git/objects/42 (as opposed to 8 files on other
platforms). The probability of that happening if the repo contains
about 100 loose objects is 32%. The probability for the same to happen
when searching 4 directories is only 8%, which is bit more reasonable.

Also remove $objects_limit from the message, because we already know
that we are above (or close to) that limit. Telling the user about
that number does not really give him any useful information.

The following octave script shows the probability for at least m*q
objects to be found in q subdirectories of .git/objects if n is the
total number of objects.

q = 4;
m = [1 2 8];
n = 0:10:2000;

P = zeros(length(n), length(m));
for k = 1:length(n)
        P(k, :) = 1-binocdf(q*m-1, n(k), q/(256-q));
end
plot(n, P);

n \ q   1       4
50      18%     1%
100     32%     8%
200     54%     39%
500     86%     96%

Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-12-05 13:48:03 -08:00
c0d153295c git gui: make current branch default in "remote delete branch" merge check
We already do the same when locally deleting a branch.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-12-05 13:17:51 -08:00
acb9108c19 git-gui: adjust the minimum height of diff pane for shorter screen height
When the main window is maximized, if the screen height is shorter (e.g.
Netbook screen 1024x600), both the partial commit pane and the status bar
are hidden. The diff pane is resizable, so that it can use less vertical
height, allowing the overall window to be shorter and still display both
the entire commit pane and status bar.

Signed-off-by: Vietor Liu <vietor@vxwo.org>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-10-27 11:25:59 -07:00
cd846aa183 git-gui: fix use of uninitialized variable
This fixes a bug introduced by the "display summary when showing diff of a
submodule" patch. It lead to a "no such variable" error when opening the
diff context menu while no diff was shown.

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-09-25 16:42:00 -07:00
ed7b603381 git-gui: store wm state and fix wm geometry
I often close git gui window when it is maximized, and when I reopen
it next time the it would usually become out of place (e.g. a huge
window with a top-left corner somewhere close to the center of the
screen). Fix it by storing and restoring wm state in config, as well
as setting wm state to normal before retrieving wm geometry info.

Signed-off-by: Alexey Borzenkov <snaury@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-09-12 11:35:29 -07:00
118d938812 git-gui: Ensure submodule path is quoted properly
When quoting an arbitrary user string in Tcl, its better to use
[list ...] than to use {...}, in case the user string has spaces
or { embedded within it.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-08-26 17:42:50 -07:00
af413de47b git-gui: fix diff for partially staged submodule changes
When a submodule commit had already been staged and another commit had
been checked out inside the submodule, the diff always displayed the
submodule commit log messages between the last supermodule commit and
the working tree, totally ignoring the commit in the index.

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-08-26 17:35:16 -07:00
b350e460da git-gui: Update russian translation
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-08-12 08:34:37 -07:00
dd6451f9c7 git-gui: Limit display to a maximum number of files
When there is a large number of new or modified files,
"display_all_files" takes a long time, and git-gui appears to hang.

This change limits the number of files that are displayed.  This
limit can be set as gui.maxfilesdisplayed, and is 5000 by default.

A warning is shown the first time the list of files is truncated
in this GUI session.  Subsequent truncations are not mentioned to
the user.

Signed-off-by: Dan Zwell <dzwell@zwell.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-08-12 07:41:52 -07:00
2112be7650 git-gui: remove warning when deleting correctly merged remote branch
If the user wants to delete a remote branch and selects the correct
"merged into" we should not warn that "Recovering deleted branches is
difficult". For local branches we do the same already.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-08-10 08:47:34 -07:00
2ee94d141e git-gui: Added Greek translation & glossary
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-08-10 08:43:07 -07:00
246295bdeb git-gui: display summary when showing diff of a submodule
As it is hard to say what changed in a submodule by looking at the hashes,
let's show the colored submodule summary instead.

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-08-10 08:30:26 -07:00
a91be3fcbe git-gui: Fixes for Mac OS X TkAqua
- detect more Tk.framework variants
- fix apple menu setup, use native preferences menu item
- don't set menu font

Signed-off-by: Daniel A. Steffen <das@users.sourceforge.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-05-01 15:04:52 -07:00
c736b4c83b git-gui: Update Russian translation
Also, the previous translations of the words 'tag' and 'merge' were
changed. Added translation of the 'Tool' submenu.

Thanks go to Alexander Gavrilov and Dmitry Potapov for proofreading
and suggestions.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-04-29 08:37:23 -07:00
b4c813bc71 git-gui: run post-checkout hook after clone
git-gui is using "git-read-tree -u" when cloning which doesn't
invoke the post-checkout hook as a plain git-clone would.
So git-gui must call the hook itself.

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-04-08 07:42:54 -07:00
4339d5109c Merge branch 'maint'
* maint:
  git-gui: Ensure consistent usage of mergetool.keepBackup
  git-gui: fix use of undeclared variable diff_empty_count
2009-04-08 07:41:13 -07:00
fb25092a88 git-gui: Ensure consistent usage of mergetool.keepBackup
In several places merge.keepBackup is used i.s.o.
mergetool.keepBackup. This patch makes it all
consistent.

Signed-off-by: Ferry Huberts <ferry.huberts@pelagic.nl>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-04-08 07:40:58 -07:00
8052e788b5 git-gui: fix use of undeclared variable diff_empty_count
Commit 584fa9cc introduced the global variable diff_empty_count, which
is used in diff.tcl. This variable wasn't declared anywhere which
resulted in an ugly error message box instead of the intended
informative message.

Signed-off-by: Joerg Bornemann <joerg.bornemann@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-04-08 07:38:11 -07:00
b01d432604 git-gui (Win): make starting via "Git GUI Here" on .git/ possible
This works around git-gui's error message

    Cannot use funny .git directory: .

when started from the .git/ directory, which is useful in repositories
without any directories for the right click.

Now git-gui can be started via Windows Explorer shell extension (Git GUI
Here) from the .git/ directory.

Signed-off-by: Markus Heidelberg <markus.heidelberg@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-04-05 13:06:24 -07:00
454efb47b6 git-gui (Win): make "Explore Working Copy" more robust
Starting the Explorer from the git-gui menu "Explore Working Copy"
didn't work, when git-gui was started via Windows Explorer shell
extension (Git GUI Here) from a directory within the project.
The Explorer raised an error message like this:

    Path "C:/somedir/worktree" is not available or not a directory

It worked when started from the project directory itself, because then
the path argument for the Explorer was just '.' (current directory)
without any problematic forward slashes.

To make it work, convert the path given as argument to explorer.exe to
its native format with backslashes.

Signed-off-by: Markus Heidelberg <markus.heidelberg@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-04-05 13:05:29 -07:00
c9498339a4 git-gui: run post-checkout hook on checkout
git-gui is using "git-read-tree -u" for checkout which doesn't
invoke the post-checkout hook as a plain git-checkout would.
So git-gui must call the hook itself.

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-04-05 12:58:26 -07:00
f0d4eec99f git-gui: When calling post-commit hook wrong variable was cleared.
Before calling the post-commit hook, the variable "pc_err" is cleared
while later only "pch_error" is used. "pch_error$cmt_id" only appeared in
"upvar"-Statements (which were changed to "global") and was removed.

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-04-05 12:45:40 -07:00
3eb5682b0b git-gui: use git --html-path to get the location of installed HTML docs
Previously a hardcoded path $GIT_EXEC_PATH/../Documentation/ was used to
search for the documentation, when the user has asked for it via menu
"Help -> Online Documentation".
This didn't work for the default directory structure.

To find the path reliably, use the new git command line option, which
returns the correct path.

If the output of `git --html-path` is empty because git is not found or
the option is not yet supported in the installed git, the documentation
from kernel.org is launched. There is no additional guessing of the
right location of the installed docs.

Signed-off-by: Markus Heidelberg <markus.heidelberg@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-04-05 12:29:10 -07:00
122ee54420 Merge branch 'maint'
* maint:
  git-gui: fix deleting from the context menu with empty selection
2009-03-30 07:09:28 -07:00
bf516ecaac git-gui: fix deleting from the context menu with empty selection
An "Application Error" was raised when trying to delete text from the
commit message field when no text was selected.

Signed-off-by: Markus Heidelberg <markus.heidelberg@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-03-30 07:06:37 -07:00
966d0778db git-gui: minor spelling fix and string factorisation.
Properly spell "successful" and slightly rewrite a couple of strings
that actually say the same thing in order to reduce translation work.

Update .pot and .po files accordingly since no new translation is
required.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-03-24 16:17:30 -07:00
b59f091d80 git-gui: various French translation fixes
Mostly grammar, spelling and typography fixes, but also a few wording
enhancements here and there.

Signed-off-by: Sam Hocevar <sam@zoy.org>
Acked-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-03-24 16:16:42 -07:00
b0d644b658 Merge branch 'maint' 2009-03-20 14:44:48 -07:00
e27430e777 git-gui: Fix merge conflict display error when filename contains spaces
When a merge conflict occurs in a file with spaces in the filename,
git-gui showed wrongly "LOCAL: deleted".

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-03-20 14:44:28 -07:00
73fea17364 Merge branch 'maint'
* maint:
  git-gui: don't hide the Browse button when resizing the repo chooser
2009-03-16 20:01:27 -07:00
379f84b8d1 git-gui: don't hide the Browse button when resizing the repo chooser
Rather shrink the input field for "Create New Repository" and "Open
Existing Repository" as it's already done for "Clone Existing
Repository".

Signed-off-by: Markus Heidelberg <markus.heidelberg@web.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-03-16 19:57:48 -07:00
880fa117f1 Append ampersand to "Target" of lnk files created by do_cygwin_shortcut
The git-gui menu item "Repository | Create Desktop Icon" creates a
shortcut (.lnk file) on the Windows desktop.  The purpose of the
created shortcut is to make it easy for a user to launch git-gui
for a particular repo in the future.

A Windows user would expect to see git gui launch when they click
the shortcut; they would not expect (nor want) to see a cmd window
open and remain open in the background.

msysGit avoids opening a command window altogether when it's Git GUI
shortcut is used.  Ideally, git on cygwin would also have shortcuts
that simply open the GUI, but as a first step, this change allows
the shell window to politely disappear after starting git gui as a
background process.

Signed-off-by: Phil Lawrence <prlawrence@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-03-09 16:21:17 -07:00
764369c5ea git-gui: Support more git version notations.
Recently the msysgit repository has got a '1.6.1-msysgit1'
tag, which, when used to build the git version, is not
handled gracefully by the git-gui version code.

This patch changes the regular expressions to fix it, and
removes the hardcoded 'rc' string. Now git-gui can accept
a version tail like '.foo123.GIT.bar.456.7.g89ab'

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-02-08 11:50:58 -08:00
584fa9ccf4 git-gui: Avoid an infinite rescan loop in handle_empty_diff.
If the index update machinery and git diff happen to disagree
on whether a particular file is modified, it may cause git-gui
to enter an infinite index rescan loop, where an empty diff
starts a rescan, which finds the same set of files modified,
and tries to display the diff for the first one, which happens
to be the empty one. A current example of a possible disagreement
point is the autocrlf filter.

This patch breaks the loop by using a global counter to track
the auto-rescans. The variable is reset whenever a non-empty
diff is displayed.

Another suggested approach, which is based on giving the
--exit-code argument to git diff, cannot be used, because
diff-files seems to trust the timestamps in the index, and
returns a non-zero code even if the file is actually
unchanged, which essentially defeats the purpose of the
auto-rescan logic.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-02-08 11:50:11 -08:00
06569cd5be git-gui: Fix post-commit status with subject in non-locale encoding
As pointed out in msysgit bug #181, when a non-locale encoding is
used for commits, post-commit status messages display the subject
incorrectly.  It happens because the file handle is not properly
configured before the subject is read back.

This patch fixes it by factoring out the code that is used to setup
the output handle into a separate function, and calling it from
the reading code.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Acked-by: Robin Rosenberg <robin.rosenberg@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-02-01 14:56:54 -08:00
54 changed files with 10827 additions and 3841 deletions

View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
GVF=GIT-VERSION-FILE GVF=GIT-VERSION-FILE
DEF_VER=0.12.GITGUI DEF_VER=0.13.GITGUI
LF=' LF='
' '

View File

@ -7,7 +7,7 @@ all::
# TCL_PATH must be vaild for this to work. # TCL_PATH must be vaild for this to work.
# #
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE GIT-VERSION-FILE: FORCE
@$(SHELL_PATH) ./GIT-VERSION-GEN @$(SHELL_PATH) ./GIT-VERSION-GEN
-include GIT-VERSION-FILE -include GIT-VERSION-FILE
@ -105,9 +105,12 @@ endif
ifeq ($(uname_S),Darwin) ifeq ($(uname_S),Darwin)
TKFRAMEWORK = /Library/Frameworks/Tk.framework/Resources/Wish.app TKFRAMEWORK = /Library/Frameworks/Tk.framework/Resources/Wish.app
ifeq ($(shell expr "$(uname_R)" : '9\.'),2) ifeq ($(shell echo "$(uname_R)" | awk -F. '{if ($$1 >= 9) print "y"}')_$(shell test -d $(TKFRAMEWORK) || echo n),y_n)
TKFRAMEWORK = /System/Library/Frameworks/Tk.framework/Resources/Wish.app
ifeq ($(shell test -d $(TKFRAMEWORK) || echo n),n)
TKFRAMEWORK = /System/Library/Frameworks/Tk.framework/Resources/Wish\ Shell.app TKFRAMEWORK = /System/Library/Frameworks/Tk.framework/Resources/Wish\ Shell.app
endif endif
endif
TKEXECUTABLE = $(shell basename "$(TKFRAMEWORK)" .app) TKEXECUTABLE = $(shell basename "$(TKFRAMEWORK)" .app)
endif endif
@ -212,6 +215,7 @@ endif
$(GITGUI_MAIN): git-gui.sh GIT-VERSION-FILE GIT-GUI-VARS $(GITGUI_MAIN): git-gui.sh GIT-VERSION-FILE GIT-GUI-VARS
$(QUIET_GEN)rm -f $@ $@+ && \ $(QUIET_GEN)rm -f $@ $@+ && \
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
-e 's|@@SHELL_PATH@@|$(SHELL_PATH_SQ)|' \
-e '1,30s|^ argv0=$$0| argv0=$(GITGUI_SCRIPT)|' \ -e '1,30s|^ argv0=$$0| argv0=$(GITGUI_SCRIPT)|' \
-e '1,30s|^ exec wish | exec '\''$(TCLTK_PATH_SED)'\'' |' \ -e '1,30s|^ exec wish | exec '\''$(TCLTK_PATH_SED)'\'' |' \
-e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \ -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \
@ -267,7 +271,7 @@ TRACK_VARS = \
GITGUI_MACOSXAPP=$(GITGUI_MACOSXAPP) \ GITGUI_MACOSXAPP=$(GITGUI_MACOSXAPP) \
#end TRACK_VARS #end TRACK_VARS
GIT-GUI-VARS: .FORCE-GIT-GUI-VARS GIT-GUI-VARS: FORCE
@VARS='$(TRACK_VARS)'; \ @VARS='$(TRACK_VARS)'; \
if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \ if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
echo 1>&2 " * new locations or Tcl/Tk interpreter"; \ echo 1>&2 " * new locations or Tcl/Tk interpreter"; \
@ -337,5 +341,4 @@ ifdef GITGUI_WINDOWS_WRAPPER
endif endif
.PHONY: all install uninstall dist-version clean .PHONY: all install uninstall dist-version clean
.PHONY: .FORCE-GIT-VERSION-FILE .PHONY: FORCE
.PHONY: .FORCE-GIT-GUI-VARS

View File

@ -5,6 +5,8 @@ exec wish "$0" -- "$@"
# This is a trivial implementation of an SSH_ASKPASS handler. # This is a trivial implementation of an SSH_ASKPASS handler.
# Git-gui uses this script if none are already configured. # Git-gui uses this script if none are already configured.
package require Tk
set answer {} set answer {}
set yesno 0 set yesno 0
set rc 255 set rc 255
@ -30,16 +32,20 @@ if {!$yesno} {
frame .b frame .b
button .b.ok -text OK -command finish button .b.ok -text OK -command finish
button .b.cancel -text Cancel -command {destroy .} button .b.cancel -text Cancel -command cancel
pack .b.ok -side left -expand 1 pack .b.ok -side left -expand 1
pack .b.cancel -side right -expand 1 pack .b.cancel -side right -expand 1
pack .b -side bottom -fill x -padx 10 -pady 10 pack .b -side bottom -fill x -padx 10 -pady 10
bind . <Visibility> {focus -force .e} bind . <Visibility> {focus -force .e}
bind . <Key-Return> finish bind . <Key-Return> [list .b.ok invoke]
bind . <Key-Escape> {destroy .} bind . <Key-Escape> [list .b.cancel invoke]
bind . <Destroy> {exit $rc} bind . <Destroy> {set rc $rc}
proc cancel {} {
set ::rc 255
}
proc finish {} { proc finish {} {
if {$::yesno} { if {$::yesno} {
@ -50,10 +56,11 @@ proc finish {} {
} }
} }
set ::rc 0
puts $::answer puts $::answer
destroy . set ::rc 0
} }
wm title . "OpenSSH" wm title . "OpenSSH"
tk::PlaceWindow . tk::PlaceWindow .
vwait rc
exit $rc

File diff suppressed because it is too large Load Diff

View File

@ -4,31 +4,26 @@
proc do_about {} { proc do_about {} {
global appvers copyright oguilib global appvers copyright oguilib
global tcl_patchLevel tk_patchLevel global tcl_patchLevel tk_patchLevel
global ui_comm_spell global ui_comm_spell NS use_ttk
set w .about_dialog set w .about_dialog
toplevel $w Dialog $w
wm geometry $w "+[winfo rootx .]+[winfo rooty .]" wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
pack [git_logo $w.git_logo] -side left -fill y -padx 10 -pady 10 pack [git_logo $w.git_logo] -side left -fill y -padx 10 -pady 10
label $w.header -text [mc "About %s" [appname]] \ ${NS}::label $w.header -text [mc "About %s" [appname]] \
-font font_uibold -font font_uibold -anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.close -text {Close} \ ${NS}::button $w.buttons.close -text {Close} \
-default active \ -default active \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.close -side right pack $w.buttons.close -side right
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
label $w.desc \ paddedlabel $w.desc \
-text "[mc "git-gui - a graphical user interface for Git."]\n$copyright" \ -text "[mc "git-gui - a graphical user interface for Git."]\n$copyright"
-padx 5 -pady 5 \
-justify left \
-anchor w \
-borderwidth 1 \
-relief solid
pack $w.desc -side top -fill x -padx 5 -pady 5 pack $w.desc -side top -fill x -padx 5 -pady 5
set v {} set v {}
@ -52,22 +47,10 @@ proc do_about {} {
append d "git exec dir: [gitexec]\n" append d "git exec dir: [gitexec]\n"
append d "git-gui lib: $oguilib" append d "git-gui lib: $oguilib"
label $w.vers \ paddedlabel $w.vers -text $v
-text $v \
-padx 5 -pady 5 \
-justify left \
-anchor w \
-borderwidth 1 \
-relief solid
pack $w.vers -side top -fill x -padx 5 -pady 5 pack $w.vers -side top -fill x -padx 5 -pady 5
label $w.dirs \ paddedlabel $w.dirs -text $d
-text $d \
-padx 5 -pady 5 \
-justify left \
-anchor w \
-borderwidth 1 \
-relief solid
pack $w.dirs -side top -fill x -padx 5 -pady 5 pack $w.dirs -side top -fill x -padx 5 -pady 5
menu $w.ctxm -tearoff 0 menu $w.ctxm -tearoff 0

View File

@ -22,6 +22,7 @@ field w_asim ; # text column: annotations (simple computation)
field w_file ; # text column: actual file data field w_file ; # text column: actual file data
field w_cviewer ; # pane showing commit message field w_cviewer ; # pane showing commit message
field finder ; # find mini-dialog frame field finder ; # find mini-dialog frame
field gotoline ; # line goto mini-dialog frame
field status ; # status mega-widget instance field status ; # status mega-widget instance
field old_height ; # last known height of $w.file_pane field old_height ; # last known height of $w.file_pane
@ -61,7 +62,7 @@ field tooltip_timer {} ; # Current timer event for our tooltip
field tooltip_commit {} ; # Commit(s) in tooltip field tooltip_commit {} ; # Commit(s) in tooltip
constructor new {i_commit i_path i_jump} { constructor new {i_commit i_path i_jump} {
global cursor_ptr M1B M1T have_tk85 global cursor_ptr M1B M1T have_tk85 use_ttk NS
variable active_color variable active_color
variable group_colors variable group_colors
@ -73,15 +74,15 @@ constructor new {i_commit i_path i_jump} {
set font_w [font measure font_diff "0"] set font_w [font measure font_diff "0"]
frame $w.header -background gold gold_frame $w.header
label $w.header.commit_l \ tlabel $w.header.commit_l \
-text [mc "Commit:"] \ -text [mc "Commit:"] \
-background gold \ -background gold \
-foreground black \ -foreground black \
-anchor w \ -anchor w \
-justify left -justify left
set w_back $w.header.commit_b set w_back $w.header.commit_b
label $w_back \ tlabel $w_back \
-image ::blame::img_back_arrow \ -image ::blame::img_back_arrow \
-borderwidth 0 \ -borderwidth 0 \
-relief flat \ -relief flat \
@ -94,20 +95,20 @@ constructor new {i_commit i_path i_jump} {
[cb _history_menu] [cb _history_menu]
} }
" "
label $w.header.commit \ tlabel $w.header.commit \
-textvariable @commit \ -textvariable @commit \
-background gold \ -background gold \
-foreground black \ -foreground black \
-anchor w \ -anchor w \
-justify left -justify left
label $w.header.path_l \ tlabel $w.header.path_l \
-text [mc "File:"] \ -text [mc "File:"] \
-background gold \ -background gold \
-foreground black \ -foreground black \
-anchor w \ -anchor w \
-justify left -justify left
set w_path $w.header.path set w_path $w.header.path
label $w_path \ tlabel $w_path \
-background gold \ -background gold \
-foreground black \ -foreground black \
-anchor w \ -anchor w \
@ -209,10 +210,10 @@ constructor new {i_commit i_path i_jump} {
set w_columns [list $w_amov $w_asim $w_line $w_file] set w_columns [list $w_amov $w_asim $w_line $w_file]
scrollbar $w.file_pane.out.sbx \ ${NS}::scrollbar $w.file_pane.out.sbx \
-orient h \ -orient h \
-command [list $w_file xview] -command [list $w_file xview]
scrollbar $w.file_pane.out.sby \ ${NS}::scrollbar $w.file_pane.out.sby \
-orient v \ -orient v \
-command [list scrollbar2many $w_columns yview] -command [list scrollbar2many $w_columns yview]
eval grid $w_columns $w.file_pane.out.sby -sticky nsew eval grid $w_columns $w.file_pane.out.sby -sticky nsew
@ -231,6 +232,11 @@ constructor new {i_commit i_path i_jump} {
-column [expr {[llength $w_columns] - 1}] \ -column [expr {[llength $w_columns] - 1}] \
] ]
set gotoline [::linebar::new \
$w.file_pane.out.lf $w_file \
-column [expr {[llength $w_columns] - 1}] \
]
set w_cviewer $w.file_pane.cm.t set w_cviewer $w.file_pane.cm.t
text $w_cviewer \ text $w_cviewer \
-background white \ -background white \
@ -254,10 +260,10 @@ constructor new {i_commit i_path i_jump} {
-background $active_color \ -background $active_color \
-font font_ui -font font_ui
$w_cviewer tag raise sel $w_cviewer tag raise sel
scrollbar $w.file_pane.cm.sbx \ ${NS}::scrollbar $w.file_pane.cm.sbx \
-orient h \ -orient h \
-command [list $w_cviewer xview] -command [list $w_cviewer xview]
scrollbar $w.file_pane.cm.sby \ ${NS}::scrollbar $w.file_pane.cm.sby \
-orient v \ -orient v \
-command [list $w_cviewer yview] -command [list $w_cviewer yview]
pack $w.file_pane.cm.sby -side right -fill y pack $w.file_pane.cm.sby -side right -fill y
@ -274,7 +280,11 @@ constructor new {i_commit i_path i_jump} {
$w.ctxm add command \ $w.ctxm add command \
-label [mc "Find Text..."] \ -label [mc "Find Text..."] \
-accelerator F7 \ -accelerator F7 \
-command [list searchbar::show $finder] -command [cb _show_finder]
$w.ctxm add command \
-label [mc "Goto Line..."] \
-accelerator "Ctrl-G" \
-command [cb _show_linebar]
menu $w.ctxm.enc menu $w.ctxm.enc
build_encoding_menu $w.ctxm.enc [cb _setencoding] build_encoding_menu $w.ctxm.enc [cb _setencoding]
$w.ctxm add cascade \ $w.ctxm add cascade \
@ -341,10 +351,13 @@ constructor new {i_commit i_path i_jump} {
bind $w_cviewer <Tab> "[list focus $w_file];break" bind $w_cviewer <Tab> "[list focus $w_file];break"
bind $w_cviewer <Button-1> [list focus $w_cviewer] bind $w_cviewer <Button-1> [list focus $w_cviewer]
bind $w_file <Visibility> [cb _focus_search $w_file] bind $w_file <Visibility> [cb _focus_search $w_file]
bind $top <F7> [list searchbar::show $finder] bind $top <F7> [cb _show_finder]
bind $top <Key-slash> [cb _show_finder]
bind $top <Control-Key-s> [cb _show_finder]
bind $top <Escape> [list searchbar::hide $finder] bind $top <Escape> [list searchbar::hide $finder]
bind $top <F3> [list searchbar::find_next $finder] bind $top <F3> [list searchbar::find_next $finder]
bind $top <Shift-F3> [list searchbar::find_prev $finder] bind $top <Shift-F3> [list searchbar::find_prev $finder]
bind $top <Control-Key-g> [cb _show_linebar]
catch { bind $top <Shift-Key-XF86_Switch_VT_3> [list searchbar::find_prev $finder] } catch { bind $top <Shift-Key-XF86_Switch_VT_3> [list searchbar::find_prev $finder] }
grid configure $w.header -sticky ew grid configure $w.header -sticky ew
@ -449,12 +462,36 @@ method _load {jump} {
$status show [mc "Reading %s..." "$commit:[escape_path $path]"] $status show [mc "Reading %s..." "$commit:[escape_path $path]"]
$w_path conf -text [escape_path $path] $w_path conf -text [escape_path $path]
set do_textconv 0
if {![is_config_false gui.textconv] && [git-version >= 1.7.2]} {
set filter [gitattr $path diff set]
set textconv [get_config [join [list diff $filter textconv] .]]
if {$filter ne {set} && $textconv ne {}} {
set do_textconv 1
}
}
if {$commit eq {}} { if {$commit eq {}} {
if {$do_textconv ne 0} {
# Run textconv with sh -c "..." to allow it to
# contain command + arguments. On windows, just
# call the filter command.
if {![file executable [shellpath]]} {
set fd [open |[linsert $textconv end $path] r]
} else {
set fd [open |[list [shellpath] -c "$textconv \"\$0\"" $path] r]
}
} else {
set fd [open $path r] set fd [open $path r]
}
fconfigure $fd -eofchar {} fconfigure $fd -eofchar {}
} else {
if {$do_textconv ne 0} {
set fd [git_read cat-file --textconv "$commit:$path"]
} else { } else {
set fd [git_read cat-file blob "$commit:$path"] set fd [git_read cat-file blob "$commit:$path"]
} }
}
fconfigure $fd \ fconfigure $fd \
-blocking 0 \ -blocking 0 \
-translation lf \ -translation lf \
@ -1245,6 +1282,18 @@ method _open_tooltip {cur_w} {
$tooltip_t conf -state disabled $tooltip_t conf -state disabled
_position_tooltip $this _position_tooltip $this
# On MacOS raising a window causes it to acquire focus.
# Tk 8.5 on MacOS seems to properly support wm transient,
# so we can safely counter the effect there.
if {$::have_tk85 && [is_MacOSX]} {
update
if {$w eq {}} {
raise .
} else {
raise $w
}
}
} }
method _position_tooltip {} { method _position_tooltip {} {
@ -1262,13 +1311,15 @@ method _position_tooltip {} {
set pos_y [expr {[winfo pointery .] + 10}] set pos_y [expr {[winfo pointery .] + 10}]
set g "${req_w}x${req_h}" set g "${req_w}x${req_h}"
if {$pos_x >= 0} {append g +} if {[tk windowingsystem] eq "win32" || $pos_x >= 0} {append g +}
append g $pos_x append g $pos_x
if {$pos_y >= 0} {append g +} if {[tk windowingsystem] eq "win32" || $pos_y >= 0} {append g +}
append g $pos_y append g $pos_y
wm geometry $tooltip_wm $g wm geometry $tooltip_wm $g
if {![is_MacOSX]} {
raise $tooltip_wm raise $tooltip_wm
}
} }
method _hide_tooltip {} { method _hide_tooltip {} {
@ -1298,4 +1349,14 @@ method _resize {new_height} {
set old_height $new_height set old_height $new_height
} }
method _show_finder {} {
linebar::hide $gotoline
searchbar::show $finder
}
method _show_linebar {} {
searchbar::hide $finder
linebar::show $gotoline
}
} }

View File

@ -10,21 +10,24 @@ field opt_fetch 1; # refetch tracking branch if used?
field opt_detach 0; # force a detached head case? field opt_detach 0; # force a detached head case?
constructor dialog {} { constructor dialog {} {
make_toplevel top w global use_ttk NS
make_dialog top w
wm withdraw $w
wm title $top [append "[appname] ([reponame]): " [mc "Checkout Branch"]] wm title $top [append "[appname] ([reponame]): " [mc "Checkout Branch"]]
if {$top ne {.}} { if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
} }
label $w.header -text [mc "Checkout Branch"] -font font_uibold ${NS}::label $w.header -text [mc "Checkout Branch"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.create -text [mc Checkout] \ ${NS}::button $w.buttons.create -text [mc Checkout] \
-default active \ -default active \
-command [cb _checkout] -command [cb _checkout]
pack $w.buttons.create -side right pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc Cancel] \ ${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
@ -33,14 +36,14 @@ constructor dialog {} {
$w_rev bind_listbox <Double-Button-1> [cb _checkout] $w_rev bind_listbox <Double-Button-1> [cb _checkout]
pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5 pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5
labelframe $w.options -text [mc Options] ${NS}::labelframe $w.options -text [mc Options]
checkbutton $w.options.fetch \ ${NS}::checkbutton $w.options.fetch \
-text [mc "Fetch Tracking Branch"] \ -text [mc "Fetch Tracking Branch"] \
-variable @opt_fetch -variable @opt_fetch
pack $w.options.fetch -anchor nw pack $w.options.fetch -anchor nw
checkbutton $w.options.detach \ ${NS}::checkbutton $w.options.detach \
-text [mc "Detach From Local Branch"] \ -text [mc "Detach From Local Branch"] \
-variable @opt_detach -variable @opt_detach
pack $w.options.detach -anchor nw pack $w.options.detach -anchor nw
@ -50,6 +53,7 @@ constructor dialog {} {
bind $w <Visibility> [cb _visible] bind $w <Visibility> [cb _visible]
bind $w <Key-Escape> [list destroy $w] bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [cb _checkout]\;break bind $w <Key-Return> [cb _checkout]\;break
wm deiconify $w
tkwait window $w tkwait window $w
} }

View File

@ -16,48 +16,48 @@ field opt_fetch 1; # refetch tracking branch if used?
field reset_ok 0; # did the user agree to reset? field reset_ok 0; # did the user agree to reset?
constructor dialog {} { constructor dialog {} {
global repo_config global repo_config use_ttk NS
make_toplevel top w make_dialog top w
wm withdraw $w
wm title $top [append "[appname] ([reponame]): " [mc "Create Branch"]] wm title $top [append "[appname] ([reponame]): " [mc "Create Branch"]]
if {$top ne {.}} { if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
} }
label $w.header -text [mc "Create New Branch"] -font font_uibold ${NS}::label $w.header -text [mc "Create New Branch"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.create -text [mc Create] \ ${NS}::button $w.buttons.create -text [mc Create] \
-default active \ -default active \
-command [cb _create] -command [cb _create]
pack $w.buttons.create -side right pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc Cancel] \ ${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.desc -text [mc "Branch Name"] ${NS}::labelframe $w.desc -text [mc "Branch Name"]
radiobutton $w.desc.name_r \ ${NS}::radiobutton $w.desc.name_r \
-anchor w \
-text [mc "Name:"] \ -text [mc "Name:"] \
-value user \ -value user \
-variable @name_type -variable @name_type
if {!$use_ttk} {$w.desc.name_r configure -anchor w}
set w_name $w.desc.name_t set w_name $w.desc.name_t
entry $w_name \ ${NS}::entry $w_name \
-borderwidth 1 \
-relief sunken \
-width 40 \ -width 40 \
-textvariable @name \ -textvariable @name \
-validate key \ -validate key \
-validatecommand [cb _validate %d %S] -validatecommand [cb _validate %d %S]
grid $w.desc.name_r $w_name -sticky we -padx {0 5} grid $w.desc.name_r $w_name -sticky we -padx {0 5}
radiobutton $w.desc.match_r \ ${NS}::radiobutton $w.desc.match_r \
-anchor w \
-text [mc "Match Tracking Branch Name"] \ -text [mc "Match Tracking Branch Name"] \
-value match \ -value match \
-variable @name_type -variable @name_type
if {!$use_ttk} {$w.desc.match_r configure -anchor w}
grid $w.desc.match_r -sticky we -padx {0 5} -columnspan 2 grid $w.desc.match_r -sticky we -padx {0 5} -columnspan 2
grid columnconfigure $w.desc 1 -weight 1 grid columnconfigure $w.desc 1 -weight 1
@ -66,34 +66,34 @@ constructor dialog {} {
set w_rev [::choose_rev::new $w.rev [mc "Starting Revision"]] set w_rev [::choose_rev::new $w.rev [mc "Starting Revision"]]
pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5 pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5
labelframe $w.options -text [mc Options] ${NS}::labelframe $w.options -text [mc Options]
frame $w.options.merge ${NS}::frame $w.options.merge
label $w.options.merge.l -text [mc "Update Existing Branch:"] ${NS}::label $w.options.merge.l -text [mc "Update Existing Branch:"]
pack $w.options.merge.l -side left pack $w.options.merge.l -side left
radiobutton $w.options.merge.no \ ${NS}::radiobutton $w.options.merge.no \
-text [mc No] \ -text [mc No] \
-value none \ -value none \
-variable @opt_merge -variable @opt_merge
pack $w.options.merge.no -side left pack $w.options.merge.no -side left
radiobutton $w.options.merge.ff \ ${NS}::radiobutton $w.options.merge.ff \
-text [mc "Fast Forward Only"] \ -text [mc "Fast Forward Only"] \
-value ff \ -value ff \
-variable @opt_merge -variable @opt_merge
pack $w.options.merge.ff -side left pack $w.options.merge.ff -side left
radiobutton $w.options.merge.reset \ ${NS}::radiobutton $w.options.merge.reset \
-text [mc Reset] \ -text [mc Reset] \
-value reset \ -value reset \
-variable @opt_merge -variable @opt_merge
pack $w.options.merge.reset -side left pack $w.options.merge.reset -side left
pack $w.options.merge -anchor nw pack $w.options.merge -anchor nw
checkbutton $w.options.fetch \ ${NS}::checkbutton $w.options.fetch \
-text [mc "Fetch Tracking Branch"] \ -text [mc "Fetch Tracking Branch"] \
-variable @opt_fetch -variable @opt_fetch
pack $w.options.fetch -anchor nw pack $w.options.fetch -anchor nw
checkbutton $w.options.checkout \ ${NS}::checkbutton $w.options.checkout \
-text [mc "Checkout After Creation"] \ -text [mc "Checkout After Creation"] \
-variable @opt_checkout -variable @opt_checkout
pack $w.options.checkout -anchor nw pack $w.options.checkout -anchor nw
@ -109,6 +109,7 @@ constructor dialog {} {
bind $w <Visibility> [cb _visible] bind $w <Visibility> [cb _visible]
bind $w <Key-Escape> [list destroy $w] bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [cb _create]\;break bind $w <Key-Return> [cb _create]\;break
wm deiconify $w
tkwait window $w tkwait window $w
} }

View File

@ -9,41 +9,40 @@ field w_check ; # revision picker for merge test
field w_delete ; # delete button field w_delete ; # delete button
constructor dialog {} { constructor dialog {} {
global current_branch global current_branch use_ttk NS
make_toplevel top w make_dialog top w
wm withdraw $w
wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch"]] wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch"]]
if {$top ne {.}} { if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
} }
label $w.header -text [mc "Delete Local Branch"] -font font_uibold ${NS}::label $w.header -text [mc "Delete Local Branch"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
set w_delete $w.buttons.delete set w_delete $w.buttons.delete
button $w_delete \ ${NS}::button $w_delete \
-text [mc Delete] \ -text [mc Delete] \
-default active \ -default active \
-state disabled \ -state disabled \
-command [cb _delete] -command [cb _delete]
pack $w_delete -side right pack $w_delete -side right
button $w.buttons.cancel \ ${NS}::button $w.buttons.cancel \
-text [mc Cancel] \ -text [mc Cancel] \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.list -text [mc "Local Branches"] ${NS}::labelframe $w.list -text [mc "Local Branches"]
set w_heads $w.list.l set w_heads $w.list.l
listbox $w_heads \ slistbox $w_heads \
-height 10 \ -height 10 \
-width 70 \ -width 70 \
-selectmode extended \ -selectmode extended \
-exportselection false \ -exportselection false
-yscrollcommand [list $w.list.sby set]
scrollbar $w.list.sby -command [list $w.list.l yview]
pack $w.list.sby -side right -fill y
pack $w.list.l -side left -fill both -expand 1 pack $w.list.l -side left -fill both -expand 1
pack $w.list -fill both -expand 1 -pady 5 -padx 5 pack $w.list -fill both -expand 1 -pady 5 -padx 5
@ -51,7 +50,7 @@ constructor dialog {} {
$w.check \ $w.check \
[mc "Delete Only If Merged Into"] \ [mc "Delete Only If Merged Into"] \
] ]
$w_check none [mc "Always (Do not perform merge test.)"] $w_check none [mc "Always (Do not perform merge checks)"]
pack $w.check -anchor nw -fill x -pady 5 -padx 5 pack $w.check -anchor nw -fill x -pady 5 -padx 5
foreach h [load_all_heads] { foreach h [load_all_heads] {
@ -67,6 +66,7 @@ constructor dialog {} {
" "
bind $w <Key-Escape> [list destroy $w] bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [cb _delete]\;break bind $w <Key-Return> [cb _delete]\;break
wm deiconify $w
tkwait window $w tkwait window $w
} }
@ -112,7 +112,7 @@ method _delete {} {
} }
if {$to_delete eq {}} return if {$to_delete eq {}} return
if {$check_cmt eq {}} { if {$check_cmt eq {}} {
set msg [mc "Recovering deleted branches is difficult. \n\n Delete the selected branches?"] set msg [mc "Recovering deleted branches is difficult.\n\nDelete the selected branches?"]
if {[tk_messageBox \ if {[tk_messageBox \
-icon warning \ -icon warning \
-type yesno \ -type yesno \

View File

@ -8,9 +8,10 @@ field oldname
field newname field newname
constructor dialog {} { constructor dialog {} {
global current_branch global current_branch use_ttk NS
make_toplevel top w make_dialog top w
wm withdraw $w
wm title $top [append "[appname] ([reponame]): " [mc "Rename Branch"]] wm title $top [append "[appname] ([reponame]): " [mc "Rename Branch"]]
if {$top ne {.}} { if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
@ -19,27 +20,31 @@ constructor dialog {} {
set oldname $current_branch set oldname $current_branch
set newname [get_config gui.newbranchtemplate] set newname [get_config gui.newbranchtemplate]
label $w.header -text [mc "Rename Branch"] -font font_uibold ${NS}::label $w.header -text [mc "Rename Branch"]\
-font font_uibold -anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.rename -text [mc Rename] \ ${NS}::button $w.buttons.rename -text [mc Rename] \
-default active \ -default active \
-command [cb _rename] -command [cb _rename]
pack $w.buttons.rename -side right pack $w.buttons.rename -side right
button $w.buttons.cancel -text [mc Cancel] \ ${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
frame $w.rename ${NS}::frame $w.rename
label $w.rename.oldname_l -text [mc "Branch:"] ${NS}::label $w.rename.oldname_l -text [mc "Branch:"]
if {$use_ttk} {
ttk::combobox $w.rename.oldname_m -textvariable @oldname \
-values [load_all_heads] -state readonly
} else {
eval tk_optionMenu $w.rename.oldname_m @oldname [load_all_heads] eval tk_optionMenu $w.rename.oldname_m @oldname [load_all_heads]
}
label $w.rename.newname_l -text [mc "New Name:"] ${NS}::label $w.rename.newname_l -text [mc "New Name:"]
entry $w.rename.newname_t \ ${NS}::entry $w.rename.newname_t \
-borderwidth 1 \
-relief sunken \
-width 40 \ -width 40 \
-textvariable @newname \ -textvariable @newname \
-validate key \ -validate key \
@ -48,7 +53,7 @@ constructor dialog {} {
return 1 return 1
} }
grid $w.rename.oldname_l $w.rename.oldname_m -sticky w -padx {0 5} grid $w.rename.oldname_l $w.rename.oldname_m -sticky we -padx {0 5}
grid $w.rename.newname_l $w.rename.newname_t -sticky we -padx {0 5} grid $w.rename.newname_l $w.rename.newname_t -sticky we -padx {0 5}
grid columnconfigure $w.rename 1 -weight 1 grid columnconfigure $w.rename 1 -weight 1
pack $w.rename -anchor nw -fill x -pady 5 -padx 5 pack $w.rename -anchor nw -fill x -pady 5 -padx 5
@ -60,6 +65,7 @@ constructor dialog {} {
$w.rename.newname_t icursor end $w.rename.newname_t icursor end
focus $w.rename.newname_t focus $w.rename.newname_t
" "
wm deiconify $w
tkwait window $w tkwait window $w
} }

View File

@ -21,23 +21,23 @@ field browser_busy 1
field ls_buf {}; # Buffered record output from ls-tree field ls_buf {}; # Buffered record output from ls-tree
constructor new {commit {path {}}} { constructor new {commit {path {}}} {
global cursor_ptr M1B global cursor_ptr M1B use_ttk NS
make_toplevel top w make_dialog top w
wm withdraw $top
wm title $top [append "[appname] ([reponame]): " [mc "File Browser"]] wm title $top [append "[appname] ([reponame]): " [mc "File Browser"]]
set browser_commit $commit set browser_commit $commit
set browser_path $browser_commit:$path set browser_path $browser_commit:$path
label $w.path \ ${NS}::label $w.path \
-textvariable @browser_path \ -textvariable @browser_path \
-anchor w \ -anchor w \
-justify left \ -justify left \
-borderwidth 1 \
-relief sunken \
-font font_uibold -font font_uibold
if {!$use_ttk} { $w.path configure -borderwidth 1 -relief sunken}
pack $w.path -anchor w -side top -fill x pack $w.path -anchor w -side top -fill x
frame $w.list ${NS}::frame $w.list
set w_list $w.list.l set w_list $w.list.l
text $w_list -background white -foreground black \ text $w_list -background white -foreground black \
-borderwidth 0 \ -borderwidth 0 \
@ -49,19 +49,18 @@ constructor new {commit {path {}}} {
-xscrollcommand [list $w.list.sbx set] \ -xscrollcommand [list $w.list.sbx set] \
-yscrollcommand [list $w.list.sby set] -yscrollcommand [list $w.list.sby set]
rmsel_tag $w_list rmsel_tag $w_list
scrollbar $w.list.sbx -orient h -command [list $w_list xview] ${NS}::scrollbar $w.list.sbx -orient h -command [list $w_list xview]
scrollbar $w.list.sby -orient v -command [list $w_list yview] ${NS}::scrollbar $w.list.sby -orient v -command [list $w_list yview]
pack $w.list.sbx -side bottom -fill x pack $w.list.sbx -side bottom -fill x
pack $w.list.sby -side right -fill y pack $w.list.sby -side right -fill y
pack $w_list -side left -fill both -expand 1 pack $w_list -side left -fill both -expand 1
pack $w.list -side top -fill both -expand 1 pack $w.list -side top -fill both -expand 1
label $w.status \ ${NS}::label $w.status \
-textvariable @browser_status \ -textvariable @browser_status \
-anchor w \ -anchor w \
-justify left \ -justify left
-borderwidth 1 \ if {!$use_ttk} { $w.status configure -borderwidth 1 -relief sunken}
-relief sunken
pack $w.status -anchor w -side bottom -fill x pack $w.status -anchor w -side bottom -fill x
bind $w_list <Button-1> "[cb _click 0 @%x,%y];break" bind $w_list <Button-1> "[cb _click 0 @%x,%y];break"
@ -78,6 +77,7 @@ constructor new {commit {path {}}} {
bind $w_list <Right> break bind $w_list <Right> break
bind $w_list <Visibility> [list focus $w_list] bind $w_list <Visibility> [list focus $w_list]
wm deiconify $top
set w $w_list set w $w_list
if {$path ne {}} { if {$path ne {}} {
_ls $this $browser_commit:$path $path _ls $this $browser_commit:$path $path
@ -121,7 +121,7 @@ method _parent {} {
if {$browser_stack eq {}} { if {$browser_stack eq {}} {
regsub {:.*$} $browser_path {:} browser_path regsub {:.*$} $browser_path {:} browser_path
} else { } else {
regsub {/[^/]+$} $browser_path {} browser_path regsub {/[^/]+/$} $browser_path {/} browser_path
} }
set browser_status [mc "Loading %s..." $browser_path] set browser_status [mc "Loading %s..." $browser_path]
_ls $this [lindex $parent 0] [lindex $parent 1] _ls $this [lindex $parent 0] [lindex $parent 1]
@ -263,23 +263,27 @@ field w ; # widget path
field w_rev ; # mega-widget to pick the initial revision field w_rev ; # mega-widget to pick the initial revision
constructor dialog {} { constructor dialog {} {
make_toplevel top w global use_ttk NS
make_dialog top w
wm withdraw $top
wm title $top [append "[appname] ([reponame]): " [mc "Browse Branch Files"]] wm title $top [append "[appname] ([reponame]): " [mc "Browse Branch Files"]]
if {$top ne {.}} { if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
wm transient $top .
} }
label $w.header \ ${NS}::label $w.header \
-text [mc "Browse Branch Files"] \ -text [mc "Browse Branch Files"] \
-font font_uibold -font font_uibold \
-anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.browse -text [mc Browse] \ ${NS}::button $w.buttons.browse -text [mc Browse] \
-default active \ -default active \
-command [cb _open] -command [cb _open]
pack $w.buttons.browse -side right pack $w.buttons.browse -side right
button $w.buttons.cancel -text [mc Cancel] \ ${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
@ -291,6 +295,7 @@ constructor dialog {} {
bind $w <Visibility> [cb _visible] bind $w <Visibility> [cb _visible]
bind $w <Key-Escape> [list destroy $w] bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [cb _open]\;break bind $w <Key-Return> [cb _open]\;break
wm deiconify $top
tkwait window $w tkwait window $w
} }

View File

@ -9,6 +9,7 @@ field w_cons {}; # embedded console window object
field new_expr ; # expression the user saw/thinks this is field new_expr ; # expression the user saw/thinks this is
field new_hash ; # commit SHA-1 we are switching to field new_hash ; # commit SHA-1 we are switching to
field new_ref ; # ref we are updating/creating field new_ref ; # ref we are updating/creating
field old_hash ; # commit SHA-1 that was checked out when we started
field parent_w .; # window that started us field parent_w .; # window that started us
field merge_type none; # type of merge to apply to existing branch field merge_type none; # type of merge to apply to existing branch
@ -280,11 +281,11 @@ method _start_checkout {} {
# -- Our in memory state should match the repository. # -- Our in memory state should match the repository.
# #
repository_state curType curHEAD curMERGE_HEAD repository_state curType old_hash curMERGE_HEAD
if {[string match amend* $commit_type] if {[string match amend* $commit_type]
&& $curType eq {normal} && $curType eq {normal}
&& $curHEAD eq $HEAD} { && $old_hash eq $HEAD} {
} elseif {$commit_type ne $curType || $HEAD ne $curHEAD} { } elseif {$commit_type ne $curType || $HEAD ne $old_hash} {
info_popup [mc "Last scanned state does not match repository state. info_popup [mc "Last scanned state does not match repository state.
Another Git program has modified this repository since the last scan. A rescan must be performed before the current branch can be changed. Another Git program has modified this repository since the last scan. A rescan must be performed before the current branch can be changed.
@ -297,7 +298,7 @@ The rescan will be automatically started now.
return return
} }
if {$curHEAD eq $new_hash} { if {$old_hash eq $new_hash} {
_after_readtree $this _after_readtree $this
} elseif {[is_config_true gui.trustmtime]} { } elseif {[is_config_true gui.trustmtime]} {
_readtree $this _readtree $this
@ -453,13 +454,47 @@ method _after_readtree {} {
If you wanted to be on a branch, create one now starting from 'This Detached Checkout'."] If you wanted to be on a branch, create one now starting from 'This Detached Checkout'."]
} }
# -- Run the post-checkout hook.
#
set fd_ph [githook_read post-checkout $old_hash $new_hash 1]
if {$fd_ph ne {}} {
global pch_error
set pch_error {}
fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
fileevent $fd_ph readable [cb _postcheckout_wait $fd_ph]
} else {
_update_repo_state $this
}
}
method _postcheckout_wait {fd_ph} {
global pch_error
append pch_error [read $fd_ph]
fconfigure $fd_ph -blocking 1
if {[eof $fd_ph]} {
if {[catch {close $fd_ph}]} {
hook_failed_popup post-checkout $pch_error 0
}
unset pch_error
_update_repo_state $this
return
}
fconfigure $fd_ph -blocking 0
}
method _update_repo_state {} {
# -- Update our repository state. If we were previously in # -- Update our repository state. If we were previously in
# amend mode we need to toss the current buffer and do a # amend mode we need to toss the current buffer and do a
# full rescan to update our file lists. If we weren't in # full rescan to update our file lists. If we weren't in
# amend mode our file lists are accurate and we can avoid # amend mode our file lists are accurate and we can avoid
# the rescan. # the rescan.
# #
global selected_commit_type commit_type HEAD MERGE_HEAD PARENT
global ui_comm
unlock_index unlock_index
set name [_name $this]
set selected_commit_type new set selected_commit_type new
if {[string match amend* $commit_type]} { if {[string match amend* $commit_type]} {
$ui_comm delete 0.0 end $ui_comm delete 0.0 end

View File

@ -17,6 +17,7 @@ variable all_families [list] ; # All fonts known to Tk
constructor pick {path title a_family a_size} { constructor pick {path title a_family a_size} {
variable all_families variable all_families
global use_ttk NS
set v_family $a_family set v_family $a_family
set v_size $a_size set v_size $a_size
@ -27,29 +28,30 @@ constructor pick {path title a_family a_size} {
set f_family $pv_family set f_family $pv_family
set f_size $pv_size set f_size $pv_size
make_toplevel top w make_dialog top w
wm withdraw $top
wm title $top "[appname] ([reponame]): $title" wm title $top "[appname] ([reponame]): $title"
wm geometry $top "+[winfo rootx $path]+[winfo rooty $path]" wm geometry $top "+[winfo rootx $path]+[winfo rooty $path]"
label $w.header -text $title -font font_uibold ${NS}::label $w.header -text $title -font font_uibold -anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.select \ ${NS}::button $w.buttons.select \
-text [mc Select] \ -text [mc Select] \
-default active \ -default active \
-command [cb _select] -command [cb _select]
button $w.buttons.cancel \ ${NS}::button $w.buttons.cancel \
-text [mc Cancel] \ -text [mc Cancel] \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.select -side right pack $w.buttons.select -side right
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
frame $w.inner ${NS}::frame $w.inner
frame $w.inner.family ${NS}::frame $w.inner.family
label $w.inner.family.l \ ${NS}::label $w.inner.family.l \
-text [mc "Font Family"] \ -text [mc "Font Family"] \
-anchor w -anchor w
set w_family $w.inner.family.v set w_family $w.inner.family.v
@ -64,16 +66,16 @@ constructor pick {path title a_family a_size} {
-height 10 \ -height 10 \
-yscrollcommand [list $w.inner.family.sby set] -yscrollcommand [list $w.inner.family.sby set]
rmsel_tag $w_family rmsel_tag $w_family
scrollbar $w.inner.family.sby -command [list $w_family yview] ${NS}::scrollbar $w.inner.family.sby -command [list $w_family yview]
pack $w.inner.family.l -side top -fill x pack $w.inner.family.l -side top -fill x
pack $w.inner.family.sby -side right -fill y pack $w.inner.family.sby -side right -fill y
pack $w_family -fill both -expand 1 pack $w_family -fill both -expand 1
frame $w.inner.size ${NS}::frame $w.inner.size
label $w.inner.size.l \ ${NS}::label $w.inner.size.l \
-text [mc "Font Size"] \ -text [mc "Font Size"] \
-anchor w -anchor w
spinbox $w.inner.size.v \ tspinbox $w.inner.size.v \
-textvariable @f_size \ -textvariable @f_size \
-from 2 -to 80 -increment 1 \ -from 2 -to 80 -increment 1 \
-width 3 -width 3
@ -86,8 +88,8 @@ constructor pick {path title a_family a_size} {
grid columnconfigure $w.inner 0 -weight 1 grid columnconfigure $w.inner 0 -weight 1
pack $w.inner -fill both -expand 1 -padx 5 -pady 5 pack $w.inner -fill both -expand 1 -padx 5 -pady 5
frame $w.example ${NS}::frame $w.example
label $w.example.l \ ${NS}::label $w.example.l \
-text [mc "Font Example"] \ -text [mc "Font Example"] \
-anchor w -anchor w
set w_example $w.example.t set w_example $w.example.t
@ -129,6 +131,7 @@ constructor pick {path title a_family a_size} {
grab $w grab $w
focus $w focus $w
" "
wm deiconify $w
tkwait window $w tkwait window $w
} }

View File

@ -22,9 +22,9 @@ field readtree_err ; # Error output from read-tree (if any)
field sorted_recent ; # recent repositories (sorted) field sorted_recent ; # recent repositories (sorted)
constructor pick {} { constructor pick {} {
global M1T M1B global M1T M1B use_ttk NS
make_toplevel top w make_dialog top w
wm title $top [mc "Git Gui"] wm title $top [mc "Git Gui"]
if {$top eq {.}} { if {$top eq {.}} {
@ -71,11 +71,11 @@ constructor pick {} {
set w_body $w.body set w_body $w.body
set opts $w_body.options set opts $w_body.options
frame $w_body ${NS}::frame $w_body
text $opts \ text $opts \
-cursor $::cursor_ptr \ -cursor $::cursor_ptr \
-relief flat \ -relief flat \
-background [$w_body cget -background] \ -background [get_bg_color $w_body] \
-wrap none \ -wrap none \
-spacing1 5 \ -spacing1 5 \
-width 50 \ -width 50 \
@ -100,12 +100,17 @@ constructor pick {} {
$opts insert end [mc "Clone Existing Repository"] link_clone $opts insert end [mc "Clone Existing Repository"] link_clone
$opts insert end "\n" $opts insert end "\n"
if {$m_repo ne {}} { if {$m_repo ne {}} {
if {[tk windowingsystem] eq "win32"} {
set key L
} else {
set key C
}
$m_repo add command \ $m_repo add command \
-command [cb _next clone] \ -command [cb _next clone] \
-accelerator $M1T-C \ -accelerator $M1T-$key \
-label [mc "Clone..."] -label [mc "Clone..."]
bind $top <$M1B-c> [cb _next clone] bind $top <$M1B-[string tolower $key]> [cb _next clone]
bind $top <$M1B-C> [cb _next clone] bind $top <$M1B-[string toupper $key]> [cb _next clone]
} }
$opts tag conf link_open -foreground blue -underline 1 $opts tag conf link_open -foreground blue -underline 1
@ -132,15 +137,15 @@ constructor pick {} {
-label [mc "Recent Repositories"] -label [mc "Recent Repositories"]
} }
label $w_body.space ${NS}::label $w_body.space
label $w_body.recentlabel \ ${NS}::label $w_body.recentlabel \
-anchor w \ -anchor w \
-text [mc "Open Recent Repository:"] -text [mc "Open Recent Repository:"]
set w_recentlist $w_body.recentlist set w_recentlist $w_body.recentlist
text $w_recentlist \ text $w_recentlist \
-cursor $::cursor_ptr \ -cursor $::cursor_ptr \
-relief flat \ -relief flat \
-background [$w_body.recentlabel cget -background] \ -background [get_bg_color $w_body.recentlabel] \
-wrap none \ -wrap none \
-width 50 \ -width 50 \
-height 10 -height 10
@ -176,10 +181,10 @@ constructor pick {} {
} }
pack $w_body -fill x -padx 10 -pady 10 pack $w_body -fill x -padx 10 -pady 10
frame $w.buttons ${NS}::frame $w.buttons
set w_next $w.buttons.next set w_next $w.buttons.next
set w_quit $w.buttons.quit set w_quit $w.buttons.quit
button $w_quit \ ${NS}::button $w_quit \
-text [mc "Quit"] \ -text [mc "Quit"] \
-command exit -command exit
pack $w_quit -side right -padx 5 pack $w_quit -side right -padx 5
@ -203,19 +208,12 @@ constructor pick {} {
wm deiconify $top wm deiconify $top
tkwait variable @done tkwait variable @done
grab release $top
if {$top eq {.}} { if {$top eq {.}} {
eval destroy [winfo children $top] eval destroy [winfo children $top]
} }
} }
proc _home {} {
if {[catch {set h $::env(HOME)}]
|| ![file isdirectory $h]} {
set h .
}
return $h
}
method _center {} { method _center {} {
set nx [winfo reqwidth $top] set nx [winfo reqwidth $top]
set ny [winfo reqheight $top] set ny [winfo reqheight $top]
@ -235,6 +233,8 @@ proc _get_recentrepos {} {
foreach p [get_config gui.recentrepo] { foreach p [get_config gui.recentrepo] {
if {[_is_git [file join $p .git]]} { if {[_is_git [file join $p .git]]} {
lappend recent $p lappend recent $p
} else {
_unset_recentrepo $p
} }
} }
return [lsort $recent] return [lsort $recent]
@ -243,6 +243,7 @@ proc _get_recentrepos {} {
proc _unset_recentrepo {p} { proc _unset_recentrepo {p} {
regsub -all -- {([()\[\]{}\.^$+*?\\])} $p {\\\1} p regsub -all -- {([()\[\]{}\.^$+*?\\])} $p {\\\1} p
git config --global --unset gui.recentrepo "^$p\$" git config --global --unset gui.recentrepo "^$p\$"
load_config 1
} }
proc _append_recentrepos {path} { proc _append_recentrepos {path} {
@ -261,6 +262,7 @@ proc _append_recentrepos {path} {
lappend recent $path lappend recent $path
git config --global --add gui.recentrepo $path git config --global --add gui.recentrepo $path
load_config 1
while {[llength $recent] > 10} { while {[llength $recent] > 10} {
_unset_recentrepo [lindex $recent 0] _unset_recentrepo [lindex $recent 0]
@ -280,9 +282,10 @@ method _open_recent_path {p} {
} }
method _next {action} { method _next {action} {
global NS
destroy $w_body destroy $w_body
if {![winfo exists $w_next]} { if {![winfo exists $w_next]} {
button $w_next -default active ${NS}::button $w_next -default active
pack $w_next -side right -padx 5 -before $w_quit pack $w_next -side right -padx 5 -before $w_quit
} }
_do_$action $this _do_$action $this
@ -371,26 +374,25 @@ proc _objdir {path} {
## Create New Repository ## Create New Repository
method _do_new {} { method _do_new {} {
global use_ttk NS
$w_next conf \ $w_next conf \
-state disabled \ -state disabled \
-command [cb _do_new2] \ -command [cb _do_new2] \
-text [mc "Create"] -text [mc "Create"]
frame $w_body ${NS}::frame $w_body
label $w_body.h \ ${NS}::label $w_body.h \
-font font_uibold \ -font font_uibold -anchor center \
-text [mc "Create New Repository"] -text [mc "Create New Repository"]
pack $w_body.h -side top -fill x -pady 10 pack $w_body.h -side top -fill x -pady 10
pack $w_body -fill x -padx 10 pack $w_body -fill x -padx 10
frame $w_body.where ${NS}::frame $w_body.where
label $w_body.where.l -text [mc "Directory:"] ${NS}::label $w_body.where.l -text [mc "Directory:"]
entry $w_body.where.t \ ${NS}::entry $w_body.where.t \
-textvariable @local_path \ -textvariable @local_path \
-borderwidth 1 \
-relief sunken \
-width 50 -width 50
button $w_body.where.b \ ${NS}::button $w_body.where.b \
-text [mc "Browse"] \ -text [mc "Browse"] \
-command [cb _new_local_path] -command [cb _new_local_path]
set w_localpath $w_body.where.t set w_localpath $w_body.where.t
@ -398,6 +400,8 @@ method _do_new {} {
grid $w_body.where.l $w_body.where.t $w_body.where.b -sticky ew grid $w_body.where.l $w_body.where.t $w_body.where.b -sticky ew
pack $w_body.where -fill x pack $w_body.where -fill x
grid columnconfigure $w_body.where 1 -weight 1
trace add variable @local_path write [cb _write_local_path] trace add variable @local_path write [cb _write_local_path]
bind $w_body.h <Destroy> [list trace remove variable @local_path write [cb _write_local_path]] bind $w_body.h <Destroy> [list trace remove variable @local_path write [cb _write_local_path]]
update update
@ -408,7 +412,7 @@ method _new_local_path {} {
if {$local_path ne {}} { if {$local_path ne {}} {
set p [file dirname $local_path] set p [file dirname $local_path]
} else { } else {
set p [_home] set p [pwd]
} }
set p [tk_chooseDirectory \ set p [tk_chooseDirectory \
@ -454,63 +458,57 @@ proc _new_ok {p} {
## Clone Existing Repository ## Clone Existing Repository
method _do_clone {} { method _do_clone {} {
global use_ttk NS
$w_next conf \ $w_next conf \
-state disabled \ -state disabled \
-command [cb _do_clone2] \ -command [cb _do_clone2] \
-text [mc "Clone"] -text [mc "Clone"]
frame $w_body ${NS}::frame $w_body
label $w_body.h \ ${NS}::label $w_body.h \
-font font_uibold \ -font font_uibold -anchor center \
-text [mc "Clone Existing Repository"] -text [mc "Clone Existing Repository"]
pack $w_body.h -side top -fill x -pady 10 pack $w_body.h -side top -fill x -pady 10
pack $w_body -fill x -padx 10 pack $w_body -fill x -padx 10
set args $w_body.args set args $w_body.args
frame $w_body.args ${NS}::frame $w_body.args
pack $args -fill both pack $args -fill both
label $args.origin_l -text [mc "Source Location:"] ${NS}::label $args.origin_l -text [mc "Source Location:"]
entry $args.origin_t \ ${NS}::entry $args.origin_t \
-textvariable @origin_url \ -textvariable @origin_url \
-borderwidth 1 \
-relief sunken \
-width 50 -width 50
button $args.origin_b \ ${NS}::button $args.origin_b \
-text [mc "Browse"] \ -text [mc "Browse"] \
-command [cb _open_origin] -command [cb _open_origin]
grid $args.origin_l $args.origin_t $args.origin_b -sticky ew grid $args.origin_l $args.origin_t $args.origin_b -sticky ew
label $args.where_l -text [mc "Target Directory:"] ${NS}::label $args.where_l -text [mc "Target Directory:"]
entry $args.where_t \ ${NS}::entry $args.where_t \
-textvariable @local_path \ -textvariable @local_path \
-borderwidth 1 \
-relief sunken \
-width 50 -width 50
button $args.where_b \ ${NS}::button $args.where_b \
-text [mc "Browse"] \ -text [mc "Browse"] \
-command [cb _new_local_path] -command [cb _new_local_path]
grid $args.where_l $args.where_t $args.where_b -sticky ew grid $args.where_l $args.where_t $args.where_b -sticky ew
set w_localpath $args.where_t set w_localpath $args.where_t
label $args.type_l -text [mc "Clone Type:"] ${NS}::label $args.type_l -text [mc "Clone Type:"]
frame $args.type_f ${NS}::frame $args.type_f
set w_types [list] set w_types [list]
lappend w_types [radiobutton $args.type_f.hardlink \ lappend w_types [${NS}::radiobutton $args.type_f.hardlink \
-state disabled \ -state disabled \
-anchor w \
-text [mc "Standard (Fast, Semi-Redundant, Hardlinks)"] \ -text [mc "Standard (Fast, Semi-Redundant, Hardlinks)"] \
-variable @clone_type \ -variable @clone_type \
-value hardlink] -value hardlink]
lappend w_types [radiobutton $args.type_f.full \ lappend w_types [${NS}::radiobutton $args.type_f.full \
-state disabled \ -state disabled \
-anchor w \
-text [mc "Full Copy (Slower, Redundant Backup)"] \ -text [mc "Full Copy (Slower, Redundant Backup)"] \
-variable @clone_type \ -variable @clone_type \
-value full] -value full]
lappend w_types [radiobutton $args.type_f.shared \ lappend w_types [${NS}::radiobutton $args.type_f.shared \
-state disabled \ -state disabled \
-anchor w \
-text [mc "Shared (Fastest, Not Recommended, No Backup)"] \ -text [mc "Shared (Fastest, Not Recommended, No Backup)"] \
-variable @clone_type \ -variable @clone_type \
-value shared] -value shared]
@ -535,7 +533,7 @@ method _open_origin {} {
if {$origin_url ne {} && [file isdirectory $origin_url]} { if {$origin_url ne {} && [file isdirectory $origin_url]} {
set p $origin_url set p $origin_url
} else { } else {
set p [_home] set p [pwd]
} }
set p [tk_chooseDirectory \ set p [tk_chooseDirectory \
@ -964,7 +962,34 @@ method _readtree_wait {fd} {
return return
} }
# -- Run the post-checkout hook.
#
set fd_ph [githook_read post-checkout [string repeat 0 40] \
[git rev-parse HEAD] 1]
if {$fd_ph ne {}} {
global pch_error
set pch_error {}
fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
fileevent $fd_ph readable [cb _postcheckout_wait $fd_ph]
} else {
set done 1 set done 1
}
}
method _postcheckout_wait {fd_ph} {
global pch_error
append pch_error [read $fd_ph]
fconfigure $fd_ph -blocking 1
if {[eof $fd_ph]} {
if {[catch {close $fd_ph}]} {
hook_failed_popup post-checkout $pch_error 0
}
unset pch_error
set done 1
return
}
fconfigure $fd_ph -blocking 0
} }
###################################################################### ######################################################################
@ -972,32 +997,33 @@ method _readtree_wait {fd} {
## Open Existing Repository ## Open Existing Repository
method _do_open {} { method _do_open {} {
global NS
$w_next conf \ $w_next conf \
-state disabled \ -state disabled \
-command [cb _do_open2] \ -command [cb _do_open2] \
-text [mc "Open"] -text [mc "Open"]
frame $w_body ${NS}::frame $w_body
label $w_body.h \ ${NS}::label $w_body.h \
-font font_uibold \ -font font_uibold -anchor center \
-text [mc "Open Existing Repository"] -text [mc "Open Existing Repository"]
pack $w_body.h -side top -fill x -pady 10 pack $w_body.h -side top -fill x -pady 10
pack $w_body -fill x -padx 10 pack $w_body -fill x -padx 10
frame $w_body.where ${NS}::frame $w_body.where
label $w_body.where.l -text [mc "Repository:"] ${NS}::label $w_body.where.l -text [mc "Repository:"]
entry $w_body.where.t \ ${NS}::entry $w_body.where.t \
-textvariable @local_path \ -textvariable @local_path \
-borderwidth 1 \
-relief sunken \
-width 50 -width 50
button $w_body.where.b \ ${NS}::button $w_body.where.b \
-text [mc "Browse"] \ -text [mc "Browse"] \
-command [cb _open_local_path] -command [cb _open_local_path]
grid $w_body.where.l $w_body.where.t $w_body.where.b -sticky ew grid $w_body.where.l $w_body.where.t $w_body.where.b -sticky ew
pack $w_body.where -fill x pack $w_body.where -fill x
grid columnconfigure $w_body.where 1 -weight 1
trace add variable @local_path write [cb _write_local_path] trace add variable @local_path write [cb _write_local_path]
bind $w_body.h <Destroy> [list trace remove variable @local_path write [cb _write_local_path]] bind $w_body.h <Destroy> [list trace remove variable @local_path write [cb _write_local_path]]
update update
@ -1008,7 +1034,7 @@ method _open_local_path {} {
if {$local_path ne {}} { if {$local_path ne {}} {
set p $local_path set p $local_path
} else { } else {
set p [_home] set p [pwd]
} }
set p [tk_chooseDirectory \ set p [tk_chooseDirectory \

View File

@ -10,7 +10,7 @@ field w_list ; # list of currently filtered specs
field w_filter ; # filter entry for $w_list field w_filter ; # filter entry for $w_list
field c_expr {}; # current revision expression field c_expr {}; # current revision expression
field filter ; # current filter string field filter ""; # current filter string
field revtype head; # type of revision chosen field revtype head; # type of revision chosen
field cur_specs [list]; # list of specs for $revtype field cur_specs [list]; # list of specs for $revtype
field spec_head ; # list of all head specs field spec_head ; # list of all head specs
@ -32,7 +32,7 @@ proc new_unmerged {path {title {}}} {
} }
constructor _new {path unmerged_only title} { constructor _new {path unmerged_only title} {
global current_branch is_detached global current_branch is_detached use_ttk NS
if {![info exists ::all_remotes]} { if {![info exists ::all_remotes]} {
load_all_remotes load_all_remotes
@ -41,65 +41,65 @@ constructor _new {path unmerged_only title} {
set w $path set w $path
if {$title ne {}} { if {$title ne {}} {
labelframe $w -text $title ${NS}::labelframe $w -text $title
} else { } else {
frame $w ${NS}::frame $w
} }
bind $w <Destroy> [cb _delete %W] bind $w <Destroy> [cb _delete %W]
if {$is_detached} { if {$is_detached} {
radiobutton $w.detachedhead_r \ ${NS}::radiobutton $w.detachedhead_r \
-anchor w \
-text [mc "This Detached Checkout"] \ -text [mc "This Detached Checkout"] \
-value HEAD \ -value HEAD \
-variable @revtype -variable @revtype
if {!$use_ttk} {$w.detachedhead_r configure -anchor w}
grid $w.detachedhead_r -sticky we -padx {0 5} -columnspan 2 grid $w.detachedhead_r -sticky we -padx {0 5} -columnspan 2
} }
radiobutton $w.expr_r \ ${NS}::radiobutton $w.expr_r \
-text [mc "Revision Expression:"] \ -text [mc "Revision Expression:"] \
-value expr \ -value expr \
-variable @revtype -variable @revtype
entry $w.expr_t \ ${NS}::entry $w.expr_t \
-borderwidth 1 \
-relief sunken \
-width 50 \ -width 50 \
-textvariable @c_expr \ -textvariable @c_expr \
-validate key \ -validate key \
-validatecommand [cb _validate %d %S] -validatecommand [cb _validate %d %S]
grid $w.expr_r $w.expr_t -sticky we -padx {0 5} grid $w.expr_r $w.expr_t -sticky we -padx {0 5}
frame $w.types ${NS}::frame $w.types
radiobutton $w.types.head_r \ ${NS}::radiobutton $w.types.head_r \
-text [mc "Local Branch"] \ -text [mc "Local Branch"] \
-value head \ -value head \
-variable @revtype -variable @revtype
pack $w.types.head_r -side left pack $w.types.head_r -side left
radiobutton $w.types.trck_r \ ${NS}::radiobutton $w.types.trck_r \
-text [mc "Tracking Branch"] \ -text [mc "Tracking Branch"] \
-value trck \ -value trck \
-variable @revtype -variable @revtype
pack $w.types.trck_r -side left pack $w.types.trck_r -side left
radiobutton $w.types.tag_r \ ${NS}::radiobutton $w.types.tag_r \
-text [mc "Tag"] \ -text [mc "Tag"] \
-value tag \ -value tag \
-variable @revtype -variable @revtype
pack $w.types.tag_r -side left pack $w.types.tag_r -side left
set w_filter $w.types.filter set w_filter $w.types.filter
entry $w_filter \ ${NS}::entry $w_filter \
-borderwidth 1 \
-relief sunken \
-width 12 \ -width 12 \
-textvariable @filter \ -textvariable @filter \
-validate key \ -validate key \
-validatecommand [cb _filter %P] -validatecommand [cb _filter %P]
pack $w_filter -side right pack $w_filter -side right
pack [label $w.types.filter_icon \ pack [${NS}::label $w.types.filter_icon \
-image ::choose_rev::img_find \ -image ::choose_rev::img_find \
] -side right ] -side right
grid $w.types -sticky we -padx {0 5} -columnspan 2 grid $w.types -sticky we -padx {0 5} -columnspan 2
if {$use_ttk} {
ttk::frame $w.list -style SListbox.TFrame -padding 2
} else {
frame $w.list frame $w.list
}
set w_list $w.list.l set w_list $w.list.l
listbox $w_list \ listbox $w_list \
-font font_diff \ -font font_diff \
@ -109,6 +109,9 @@ constructor _new {path unmerged_only title} {
-exportselection false \ -exportselection false \
-xscrollcommand [cb _sb_set $w.list.sbx h] \ -xscrollcommand [cb _sb_set $w.list.sbx h] \
-yscrollcommand [cb _sb_set $w.list.sby v] -yscrollcommand [cb _sb_set $w.list.sby v]
if {$use_ttk} {
$w_list configure -relief flat -highlightthickness 0 -borderwidth 0
}
pack $w_list -fill both -expand 1 pack $w_list -fill both -expand 1
grid $w.list -sticky nswe -padx {20 5} -columnspan 2 grid $w.list -sticky nswe -padx {20 5} -columnspan 2
bind $w_list <Any-Motion> [cb _show_tooltip @%x,%y] bind $w_list <Any-Motion> [cb _show_tooltip @%x,%y]
@ -235,11 +238,12 @@ constructor _new {path unmerged_only title} {
} }
method none {text} { method none {text} {
global NS use_ttk
if {![winfo exists $w.none_r]} { if {![winfo exists $w.none_r]} {
radiobutton $w.none_r \ ${NS}::radiobutton $w.none_r \
-anchor w \
-value none \ -value none \
-variable @revtype -variable @revtype
if {!$use_ttk} {$w.none_r configure -anchor w}
grid $w.none_r -sticky we -padx {0 5} -columnspan 2 grid $w.none_r -sticky we -padx {0 5} -columnspan 2
} }
$w.none_r configure -text $text $w.none_r configure -text $text
@ -425,6 +429,7 @@ method _delete {current} {
} }
method _sb_set {sb orient first last} { method _sb_set {sb orient first last} {
global NS
set old_focus [focus -lastfor $w] set old_focus [focus -lastfor $w]
if {$first == 0 && $last == 1} { if {$first == 0 && $last == 1} {
@ -440,10 +445,10 @@ method _sb_set {sb orient first last} {
if {![winfo exists $sb]} { if {![winfo exists $sb]} {
if {$orient eq {h}} { if {$orient eq {h}} {
scrollbar $sb -orient h -command [list $w_list xview] ${NS}::scrollbar $sb -orient h -command [list $w_list xview]
pack $sb -fill x -side bottom -before $w_list pack $sb -fill x -side bottom -before $w_list
} else { } else {
scrollbar $sb -orient v -command [list $w_list yview] ${NS}::scrollbar $sb -orient v -command [list $w_list yview]
pack $sb -fill y -side right -before $w_list pack $sb -fill y -side right -before $w_list
} }
if {$old_focus ne {}} { if {$old_focus ne {}} {
@ -605,9 +610,9 @@ method _position_tooltip {} {
set pos_y [expr {[winfo pointery .] + 10}] set pos_y [expr {[winfo pointery .] + 10}]
set g "${req_w}x${req_h}" set g "${req_w}x${req_h}"
if {$pos_x >= 0} {append g +} if {[tk windowingsystem] eq "win32" || $pos_x >= 0} {append g +}
append g $pos_x append g $pos_x
if {$pos_y >= 0} {append g +} if {[tk windowingsystem] eq "win32" || $pos_y >= 0} {append g +}
append g $pos_y append g $pos_y
wm geometry $tooltip_wm $g wm geometry $tooltip_wm $g

View File

@ -134,6 +134,13 @@ proc delete_this {{t {}}} {
if {[namespace exists $t]} {namespace delete $t} if {[namespace exists $t]} {namespace delete $t}
} }
proc make_dialog {t w args} {
upvar $t top $w pfx this this
global use_ttk
uplevel [linsert $args 0 make_toplevel $t $w]
pave_toplevel $pfx
}
proc make_toplevel {t w args} { proc make_toplevel {t w args} {
upvar $t top $w pfx this this upvar $t top $w pfx this this

View File

@ -115,6 +115,23 @@ proc create_new_commit {} {
rescan ui_ready rescan ui_ready
} }
proc setup_commit_encoding {msg_wt {quiet 0}} {
global repo_config
if {[catch {set enc $repo_config(i18n.commitencoding)}]} {
set enc utf-8
}
set use_enc [tcl_encoding $enc]
if {$use_enc ne {}} {
fconfigure $msg_wt -encoding $use_enc
} else {
if {!$quiet} {
error_popup [mc "warning: Tcl does not support encoding '%s'." $enc]
}
fconfigure $msg_wt -encoding utf-8
}
}
proc commit_tree {} { proc commit_tree {} {
global HEAD commit_type file_states ui_comm repo_config global HEAD commit_type file_states ui_comm repo_config
global pch_error global pch_error
@ -144,11 +161,12 @@ The rescan will be automatically started now.
# #
set files_ready 0 set files_ready 0
foreach path [array names file_states] { foreach path [array names file_states] {
switch -glob -- [lindex $file_states($path) 0] { set s $file_states($path)
switch -glob -- [lindex $s 0] {
_? {continue} _? {continue}
A? - A? -
D? - D? -
T_ - T? -
M? {set files_ready 1} M? {set files_ready 1}
_U - _U -
U? { U? {
@ -200,16 +218,7 @@ A good commit message has the following format:
set msg_p [gitdir GITGUI_EDITMSG] set msg_p [gitdir GITGUI_EDITMSG]
set msg_wt [open $msg_p w] set msg_wt [open $msg_p w]
fconfigure $msg_wt -translation lf fconfigure $msg_wt -translation lf
if {[catch {set enc $repo_config(i18n.commitencoding)}]} { setup_commit_encoding $msg_wt
set enc utf-8
}
set use_enc [tcl_encoding $enc]
if {$use_enc ne {}} {
fconfigure $msg_wt -encoding $use_enc
} else {
error_popup [mc "warning: Tcl does not support encoding '%s'." $enc]
fconfigure $msg_wt -encoding utf-8
}
puts $msg_wt $msg puts $msg_wt $msg
close $msg_wt close $msg_wt
@ -251,8 +260,23 @@ proc commit_prehook_wait {fd_ph curHEAD msg_p} {
} }
proc commit_commitmsg {curHEAD msg_p} { proc commit_commitmsg {curHEAD msg_p} {
global is_detached repo_config
global pch_error global pch_error
if {$is_detached && $repo_config(gui.warndetachedcommit)} {
set msg [mc "You are about to commit on a detached head.\
This is a potentially dangerous thing to do because if you switch\
to another branch you will loose your changes and it can be difficult\
to retrieve them later from the reflog. You should probably cancel this\
commit and create a new branch to continue.\n\
\n\
Do you really want to proceed with your Commit?"]
if {[ask_popup $msg] ne yes} {
unlock_index
return
}
}
# -- Run the commit-msg hook. # -- Run the commit-msg hook.
# #
set fd_ph [githook_read commit-msg $msg_p] set fd_ph [githook_read commit-msg $msg_p]
@ -362,6 +386,7 @@ A rescan will be automatically started now.
append reflogm " ($commit_type)" append reflogm " ($commit_type)"
} }
set msg_fd [open $msg_p r] set msg_fd [open $msg_p r]
setup_commit_encoding $msg_fd 1
gets $msg_fd subject gets $msg_fd subject
close $msg_fd close $msg_fd
append reflogm {: } $subject append reflogm {: } $subject
@ -398,8 +423,8 @@ A rescan will be automatically started now.
# #
set fd_ph [githook_read post-commit] set fd_ph [githook_read post-commit]
if {$fd_ph ne {}} { if {$fd_ph ne {}} {
upvar #0 pch_error$cmt_id pc_err global pch_error
set pc_err {} set pch_error {}
fconfigure $fd_ph -blocking 0 -translation binary -eofchar {} fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
fileevent $fd_ph readable \ fileevent $fd_ph readable \
[list commit_postcommit_wait $fd_ph $cmt_id] [list commit_postcommit_wait $fd_ph $cmt_id]
@ -443,7 +468,11 @@ A rescan will be automatically started now.
} }
AM - AM -
AD - AD -
AT -
TM -
TD -
MM - MM -
MT -
MD { MD {
set file_states($path) [list \ set file_states($path) [list \
_[string index $m 1] \ _[string index $m 1] \
@ -461,7 +490,7 @@ A rescan will be automatically started now.
} }
proc commit_postcommit_wait {fd_ph cmt_id} { proc commit_postcommit_wait {fd_ph cmt_id} {
upvar #0 pch_error$cmt_id pch_error global pch_error
append pch_error [read $fd_ph] append pch_error [read $fd_ph]
fconfigure $fd_ph -blocking 1 fconfigure $fd_ph -blocking 1

View File

@ -27,20 +27,20 @@ constructor embed {path title} {
} }
method _init {} { method _init {} {
global M1B global M1B use_ttk NS
if {$is_toplevel} { if {$is_toplevel} {
make_toplevel top w -autodelete 0 make_dialog top w -autodelete 0
wm title $top "[appname] ([reponame]): $t_short" wm title $top "[appname] ([reponame]): $t_short"
} else { } else {
frame $w ${NS}::frame $w
} }
set console_cr 1.0 set console_cr 1.0
set w_t $w.m.t set w_t $w.m.t
frame $w.m ${NS}::frame $w.m
label $w.m.l1 \ ${NS}::label $w.m.l1 \
-textvariable @t_long \ -textvariable @t_long \
-anchor w \ -anchor w \
-justify left \ -justify left \
@ -78,7 +78,7 @@ method _init {} {
" "
if {$is_toplevel} { if {$is_toplevel} {
button $w.ok -text [mc "Close"] \ ${NS}::button $w.ok -text [mc "Close"] \
-state disabled \ -state disabled \
-command [list destroy $w] -command [list destroy $w]
pack $w.ok -side bottom -anchor e -pady 10 -padx 10 pack $w.ok -side bottom -anchor e -pady 10 -padx 10
@ -206,13 +206,14 @@ method done {ok} {
} }
method _sb_set {sb orient first last} { method _sb_set {sb orient first last} {
global NS
if {![winfo exists $sb]} { if {![winfo exists $sb]} {
if {$first == $last || ($first == 0 && $last == 1)} return if {$first == $last || ($first == 0 && $last == 1)} return
if {$orient eq {h}} { if {$orient eq {h}} {
scrollbar $sb -orient h -command [list $w_t xview] ${NS}::scrollbar $sb -orient h -command [list $w_t xview]
pack $sb -fill x -side bottom -before $w_t pack $sb -fill x -side bottom -before $w_t
} else { } else {
scrollbar $sb -orient v -command [list $w_t yview] ${NS}::scrollbar $sb -orient v -command [list $w_t yview]
pack $sb -fill y -side right -before $w_t pack $sb -fill y -side right -before $w_t
} }
} }

View File

@ -2,6 +2,7 @@
# Copyright (C) 2006, 2007 Shawn Pearce # Copyright (C) 2006, 2007 Shawn Pearce
proc do_stats {} { proc do_stats {} {
global use_ttk NS
set fd [git_read count-objects -v] set fd [git_read count-objects -v]
while {[gets $fd line] > 0} { while {[gets $fd line] > 0} {
if {[regexp {^([^:]+): (\d+)$} $line _ name value]} { if {[regexp {^([^:]+): (\d+)$} $line _ name value]} {
@ -21,24 +22,22 @@ proc do_stats {} {
} }
set w .stats_view set w .stats_view
toplevel $w Dialog $w
wm withdraw $w
wm geometry $w "+[winfo rootx .]+[winfo rooty .]" wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
label $w.header -text [mc "Database Statistics"] ${NS}::frame $w.buttons
pack $w.header -side top -fill x ${NS}::button $w.buttons.close -text [mc Close] \
frame $w.buttons -border 1
button $w.buttons.close -text [mc Close] \
-default active \ -default active \
-command [list destroy $w] -command [list destroy $w]
button $w.buttons.gc -text [mc "Compress Database"] \ ${NS}::button $w.buttons.gc -text [mc "Compress Database"] \
-default normal \ -default normal \
-command "destroy $w;do_gc" -command "destroy $w;do_gc"
pack $w.buttons.close -side right pack $w.buttons.close -side right
pack $w.buttons.gc -side left pack $w.buttons.gc -side left
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
frame $w.stat -borderwidth 1 -relief solid ${NS}::labelframe $w.stat -text [mc "Database Statistics"]
foreach s { foreach s {
{count {mc "Number of loose objects"}} {count {mc "Number of loose objects"}}
{size {mc "Disk space used by loose objects"} { KiB}} {size {mc "Disk space used by loose objects"} { KiB}}
@ -55,8 +54,8 @@ proc do_stats {} {
set value "$value[lindex $s 2]" set value "$value[lindex $s 2]"
} }
label $w.stat.l_$name -text "$label:" -anchor w ${NS}::label $w.stat.l_$name -text "$label:" -anchor w
label $w.stat.v_$name -text $value -anchor w ${NS}::label $w.stat.v_$name -text $value -anchor w
grid $w.stat.l_$name $w.stat.v_$name -sticky we -padx {0 5} grid $w.stat.l_$name $w.stat.v_$name -sticky we -padx {0 5}
} }
pack $w.stat -pady 10 -padx 10 pack $w.stat -pady 10 -padx 10
@ -65,6 +64,7 @@ proc do_stats {} {
bind $w <Key-Escape> [list destroy $w] bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [list destroy $w] bind $w <Key-Return> [list destroy $w]
wm title $w [append "[appname] ([reponame]): " [mc "Database Statistics"]] wm title $w [append "[appname] ([reponame]): " [mc "Database Statistics"]]
wm deiconify $w
tkwait window $w tkwait window $w
} }
@ -89,27 +89,26 @@ proc do_fsck_objects {} {
} }
proc hint_gc {} { proc hint_gc {} {
set object_limit 8 set ndirs 1
set limit 8
if {[is_Windows]} { if {[is_Windows]} {
set object_limit 1 set ndirs 4
set limit 1
} }
set objects_current [llength [glob \ set count [llength [glob \
-directory [gitdir objects 42] \
-nocomplain \ -nocomplain \
-tails \
-- \ -- \
*]] [gitdir objects 4\[0-[expr {$ndirs-1}]\]/*]]]
if {$objects_current >= $object_limit} { if {$count >= $limit * $ndirs} {
set objects_current [expr {$objects_current * 250}] set objects_current [expr {$count * 256/$ndirs}]
set object_limit [expr {$object_limit * 250}]
if {[ask_popup \ if {[ask_popup \
[mc "This repository currently has approximately %i loose objects. [mc "This repository currently has approximately %i loose objects.
To maintain optimal performance it is strongly recommended that you compress the database when more than %i loose objects exist. To maintain optimal performance it is strongly recommended that you compress the database.
Compress the database now?" $objects_current $object_limit]] eq yes} { Compress the database now?" $objects_current]] eq yes} {
do_gc do_gc
} }
} }

View File

@ -51,10 +51,15 @@ proc force_diff_encoding {enc} {
proc handle_empty_diff {} { proc handle_empty_diff {} {
global current_diff_path file_states file_lists global current_diff_path file_states file_lists
global diff_empty_count
set path $current_diff_path set path $current_diff_path
set s $file_states($path) set s $file_states($path)
if {[lindex $s 0] ne {_M}} return if {[lindex $s 0] ne {_M} || [has_textconv $path]} return
# Prevent infinite rescan loops
incr diff_empty_count
if {$diff_empty_count > 1} return
info_popup [mc "No differences detected. info_popup [mc "No differences detected.
@ -117,22 +122,22 @@ proc show_unmerged_diff {cont_info} {
if {$merge_stages(2) eq {}} { if {$merge_stages(2) eq {}} {
set is_conflict_diff 1 set is_conflict_diff 1
lappend current_diff_queue \ 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"]] [list ":1:$current_diff_path" ":3:$current_diff_path"]]
} elseif {$merge_stages(3) eq {}} { } elseif {$merge_stages(3) eq {}} {
set is_conflict_diff 1 set is_conflict_diff 1
lappend current_diff_queue \ 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"]] [list ":1:$current_diff_path" ":2:$current_diff_path"]]
} elseif {[lindex $merge_stages(1) 0] eq {120000} } elseif {[lindex $merge_stages(1) 0] eq {120000}
|| [lindex $merge_stages(2) 0] eq {120000} || [lindex $merge_stages(2) 0] eq {120000}
|| [lindex $merge_stages(3) 0] eq {120000}} { || [lindex $merge_stages(3) 0] eq {120000}} {
set is_conflict_diff 1 set is_conflict_diff 1
lappend current_diff_queue \ lappend current_diff_queue \
[list [mc "LOCAL:\n"] d======= \ [list [mc "LOCAL:\n"] d= \
[list ":1:$current_diff_path" ":2:$current_diff_path"]] [list ":1:$current_diff_path" ":2:$current_diff_path"]]
lappend current_diff_queue \ lappend current_diff_queue \
[list [mc "REMOTE:\n"] d======= \ [list [mc "REMOTE:\n"] d= \
[list ":1:$current_diff_path" ":3:$current_diff_path"]] [list ":1:$current_diff_path" ":3:$current_diff_path"]]
} else { } else {
start_show_diff $cont_info start_show_diff $cont_info
@ -203,32 +208,32 @@ proc show_other_diff {path w m cont_info} {
$ui_diff insert end [append \ $ui_diff insert end [append \
"* " \ "* " \
[mc "Git Repository (subproject)"] \ [mc "Git Repository (subproject)"] \
"\n"] d_@ "\n"] d_info
} elseif {![catch {set type [exec file $path]}]} { } elseif {![catch {set type [exec file $path]}]} {
set n [string length $path] set n [string length $path]
if {[string equal -length $n $path $type]} { if {[string equal -length $n $path $type]} {
set type [string range $type $n end] set type [string range $type $n end]
regsub {^:?\s*} $type {} type 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} { if {[string first "\0" $content] != -1} {
$ui_diff insert end \ $ui_diff insert end \
[mc "* Binary file (not showing content)."] \ [mc "* Binary file (not showing content)."] \
d_@ d_info
} else { } else {
if {$sz > $max_sz} { if {$sz > $max_sz} {
$ui_diff insert end [mc \ $ui_diff insert end [mc \
"* Untracked file is %d bytes. "* Untracked file is %d bytes.
* Showing only first %d bytes. * Showing only first %d bytes.
" $sz $max_sz] d_@ " $sz $max_sz] d_info
} }
$ui_diff insert end $content $ui_diff insert end $content
if {$sz > $max_sz} { if {$sz > $max_sz} {
$ui_diff insert end [mc " $ui_diff insert end [mc "
* Untracked file clipped here by %s. * Untracked file clipped here by %s.
* To see the entire file, use an external editor. * To see the entire file, use an external editor.
" [appname]] d_@ " [appname]] d_info
} }
} }
$ui_diff conf -state disabled $ui_diff conf -state disabled
@ -248,9 +253,22 @@ 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 {}}} { proc start_show_diff {cont_info {add_opts {}}} {
global file_states file_lists global file_states file_lists
global is_3way_diff diff_active repo_config global is_3way_diff is_submodule_diff diff_active repo_config
global ui_diff ui_index ui_workdir global ui_diff ui_index ui_workdir
global current_diff_path current_diff_side current_diff_header global current_diff_path current_diff_side current_diff_header
@ -260,8 +278,10 @@ proc start_show_diff {cont_info {add_opts {}}} {
set s $file_states($path) set s $file_states($path)
set m [lindex $s 0] set m [lindex $s 0]
set is_3way_diff 0 set is_3way_diff 0
set is_submodule_diff 0
set diff_active 1 set diff_active 1
set current_diff_header {} set current_diff_header {}
set conflict_size [get_conflict_marker_size $path]
set cmd [list] set cmd [list]
if {$w eq $ui_index} { if {$w eq $ui_index} {
@ -274,9 +294,21 @@ proc start_show_diff {cont_info {add_opts {}}} {
lappend cmd diff-files lappend cmd diff-files
} }
} }
if {![is_config_false gui.textconv] && [git-version >= 1.6.1]} {
lappend cmd --textconv
}
if {[string match {160000 *} [lindex $s 2]]
|| [string match {160000 *} [lindex $s 3]]} {
set is_submodule_diff 1
if {[git-version >= "1.6.6"]} {
lappend cmd --submodule
}
}
lappend cmd -p lappend cmd -p
lappend cmd --no-color lappend cmd --color
if {$repo_config(gui.diffcontext) >= 1} { if {$repo_config(gui.diffcontext) >= 1} {
lappend cmd "-U$repo_config(gui.diffcontext)" lappend cmd "-U$repo_config(gui.diffcontext)"
} }
@ -290,6 +322,14 @@ proc start_show_diff {cont_info {add_opts {}}} {
lappend cmd $path lappend cmd $path
} }
if {$is_submodule_diff && [git-version < "1.6.6"]} {
if {$w eq $ui_index} {
set cmd [list submodule summary --cached -- $path]
} else {
set cmd [list submodule summary --files -- $path]
}
}
if {[catch {set fd [eval git_read --nice $cmd]} err]} { if {[catch {set fd [eval git_read --nice $cmd]} err]} {
set diff_active 0 set diff_active 0
unlock_index unlock_index
@ -303,47 +343,89 @@ proc start_show_diff {cont_info {add_opts {}}} {
-blocking 0 \ -blocking 0 \
-encoding [get_path_encoding $path] \ -encoding [get_path_encoding $path] \
-translation lf -translation lf
fileevent $fd readable [list read_diff $fd $cont_info] fileevent $fd readable [list read_diff $fd $conflict_size $cont_info]
} }
proc read_diff {fd cont_info} { proc parse_color_line {line} {
global ui_diff diff_active set start 0
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}]]
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 conflict_size cont_info} {
global ui_diff diff_active is_submodule_diff
global is_3way_diff is_conflict_diff current_diff_header global is_3way_diff is_conflict_diff current_diff_header
global current_diff_queue global current_diff_queue
global diff_empty_count
$ui_diff conf -state normal $ui_diff conf -state normal
while {[gets $fd line] >= 0} { while {[gets $fd line] >= 0} {
# -- Cleanup uninteresting diff header lines. foreach {line markup} [parse_color_line $line] break
# set line [string map {\033 ^} $line]
if {$::current_diff_inheader} {
set tags {}
# -- Check for start of diff header.
if { [string match {diff --git *} $line] if { [string match {diff --git *} $line]
|| [string match {diff --cc *} $line] || [string match {diff --cc *} $line]
|| [string match {diff --combined *} $line] || [string match {diff --combined *} $line]} {
|| [string match {--- *} $line] set ::current_diff_inheader 1
|| [string match {+++ *} $line]} {
append current_diff_header $line "\n"
continue
} }
}
if {[string match {index *} $line]} continue # -- Check for end of diff header (any hunk line will do this).
if {$line eq {deleted file mode 120000}} { #
set line "deleted symlink" if {[regexp {^@@+ } $line]} {set ::current_diff_inheader 0}
}
set ::current_diff_inheader 0
# -- Automatically detect if this is a 3 way diff. # -- Automatically detect if this is a 3 way diff.
# #
if {[string match {@@@ *} $line]} {set is_3way_diff 1} if {[string match {@@@ *} $line]} {set is_3way_diff 1}
if {[string match {mode *} $line] if {$::current_diff_inheader} {
|| [string match {new file *} $line]
|| [regexp {^(old|new) mode *} $line] # -- These two lines stop a diff header and shouldn't be in there
|| [string match {deleted file *} $line] if { [string match {Binary files * and * differ} $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]} { || [regexp {^\* Unmerged path } $line]} {
set tags {} 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]
|| [string match {index *} $line]} {
continue
}
# -- 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
} elseif { $line eq {\ No newline at end of file}} {
# -- Handle some special lines
} elseif {$is_3way_diff} { } elseif {$is_3way_diff} {
set op [string range $line 0 1] set op [string range $line 0 1]
switch -- $op { switch -- $op {
@ -355,7 +437,9 @@ proc read_diff {fd cont_info} {
{- } {set tags d_-s} {- } {set tags d_-s}
{--} {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 is_conflict_diff 1
set line [string replace $line 0 1 { }] set line [string replace $line 0 1 { }]
set tags d$op set tags d$op
@ -368,6 +452,25 @@ proc read_diff {fd cont_info} {
set tags {} set tags {}
} }
} }
} elseif {$is_submodule_diff} {
if {$line == ""} continue
if {[regexp {^Submodule } $line]} {
set tags d_info
} elseif {[regexp {^\* } $line]} {
set line [string replace $line 0 1 {Submodule }]
set tags d_info
} else {
set op [string range $line 0 2]
switch -- $op {
{ <} {set tags d_-}
{ >} {set tags d_+}
{ W} {set tags {}}
default {
puts "error: Unhandled submodule diff marker: {$op}"
set tags {}
}
}
}
} else { } else {
set op [string index $line 0] set op [string index $line 0]
switch -- $op { switch -- $op {
@ -375,7 +478,9 @@ proc read_diff {fd cont_info} {
{@} {set tags d_@} {@} {set tags d_@}
{-} {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 is_conflict_diff 1
set tags d$op set tags d$op
} else { } else {
@ -388,11 +493,23 @@ proc read_diff {fd cont_info} {
} }
} }
} }
set mark [$ui_diff index "end - 1 line linestart"]
$ui_diff insert end $line $tags $ui_diff insert end $line $tags
if {[string index $line end] eq "\r"} { if {[string index $line end] eq "\r"} {
$ui_diff tag add d_cr {end - 2c} $ui_diff tag add d_cr {end - 2c}
} }
$ui_diff insert end "\n" $tags $ui_diff insert end "\n" $tags
foreach {posbegin colbegin posend colend} $markup {
set prefix clr
foreach style [split $colbegin ";"] {
if {$style eq "7"} {append prefix i; continue}
if {$style < 30 || $style > 47} {continue}
set a "$mark linestart + $posbegin chars"
set b "$mark linestart + $posend chars"
catch {$ui_diff tag add $prefix$style $a $b}
}
}
} }
$ui_diff conf -state disabled $ui_diff conf -state disabled
@ -415,7 +532,10 @@ proc read_diff {fd cont_info} {
if {[$ui_diff index end] eq {2.0}} { if {[$ui_diff index end] eq {2.0}} {
handle_empty_diff handle_empty_diff
} else {
set diff_empty_count 0
} }
set callback [lindex $cont_info 1] set callback [lindex $cont_info 1]
if {$callback ne {}} { if {$callback ne {}} {
eval $callback eval $callback
@ -496,10 +616,23 @@ proc apply_hunk {x y} {
} }
} }
proc apply_line {x y} { proc apply_range_or_line {x y} {
global current_diff_path current_diff_header current_diff_side global current_diff_path current_diff_header current_diff_side
global ui_diff ui_index file_states global ui_diff ui_index file_states
set selected [$ui_diff tag nextrange sel 0.0]
if {$selected == {}} {
set first [$ui_diff index "@$x,$y"]
set last $first
} else {
set first [lindex $selected 0]
set last [lindex $selected 1]
}
set first_l [$ui_diff index "$first linestart"]
set last_l [$ui_diff index "$last lineend"]
if {$current_diff_path eq {} || $current_diff_header eq {}} return if {$current_diff_path eq {} || $current_diff_header eq {}} return
if {![lock_index apply_hunk]} return if {![lock_index apply_hunk]} return
@ -522,17 +655,15 @@ proc apply_line {x y} {
} }
} }
set the_l [$ui_diff index @$x,$y] set wholepatch {}
# operate only on change lines while {$first_l < $last_l} {
set c1 [$ui_diff get "$the_l linestart"] set i_l [$ui_diff search -backwards -regexp ^@@ $first_l 0.0]
if {$c1 ne {+} && $c1 ne {-}} { if {$i_l eq {}} {
unlock_index # If there's not a @@ above, then the selected range
return # must have come before the first_l @@
set i_l [$ui_diff search -regexp ^@@ $first_l $last_l]
} }
set sign $c1
set i_l [$ui_diff search -backwards -regexp ^@@ $the_l 0.0]
if {$i_l eq {}} { if {$i_l eq {}} {
unlock_index unlock_index
return return
@ -544,7 +675,8 @@ proc apply_line {x y} {
set hh [lindex [split $hh ,] 0] set hh [lindex [split $hh ,] 0]
set hln [lindex [split $hh -] 1] set hln [lindex [split $hh -] 1]
# There is a special situation to take care of. Consider this hunk: # There is a special situation to take care of. Consider this
# hunk:
# #
# @@ -10,4 +10,4 @@ # @@ -10,4 +10,4 @@
# context before # context before
@ -554,8 +686,8 @@ proc apply_line {x y} {
# +new 2 # +new 2
# context after # context after
# #
# We used to keep the context lines in the order they appear in the # We used to keep the context lines in the order they appear in
# hunk. But then it is not possible to correctly stage only # the hunk. But then it is not possible to correctly stage only
# "-old 1" and "+new 1" - it would result in this staged text: # "-old 1" and "+new 1" - it would result in this staged text:
# #
# context before # context before
@ -563,12 +695,14 @@ proc apply_line {x y} {
# new 1 # new 1
# context after # context after
# #
# (By symmetry it is not possible to *un*stage "old 2" and "new 2".) # (By symmetry it is not possible to *un*stage "old 2" and "new
# 2".)
# #
# We resolve the problem by introducing an asymmetry, namely, when # We resolve the problem by introducing an asymmetry, namely,
# a "+" line is *staged*, it is moved in front of the context lines # when a "+" line is *staged*, it is moved in front of the
# that are generated from the "-" lines that are immediately before # context lines that are generated from the "-" lines that are
# the "+" block. That is, we construct this patch: # immediately before the "+" block. That is, we construct this
# patch:
# #
# @@ -10,4 +10,5 @@ # @@ -10,4 +10,5 @@
# context before # context before
@ -577,43 +711,60 @@ proc apply_line {x y} {
# old 2 # old 2
# context after # context after
# #
# But we do *not* treat "-" lines that are *un*staged in a special # But we do *not* treat "-" lines that are *un*staged in a
# way. # special way.
# #
# With this asymmetry it is possible to stage the change # With this asymmetry it is possible to stage the change "old
# "old 1" -> "new 1" directly, and to stage the change # 1" -> "new 1" directly, and to stage the change "old 2" ->
# "old 2" -> "new 2" by first staging the entire hunk and # "new 2" by first staging the entire hunk and then unstaging
# then unstaging the change "old 1" -> "new 1". # the change "old 1" -> "new 1".
#
# Applying multiple lines adds complexity to the special
# situation. The pre_context must be moved after the entire
# first block of consecutive staged "+" lines, so that
# staging both additions gives the following patch:
#
# @@ -10,4 +10,6 @@
# context before
# +new 1
# +new 2
# old 1
# old 2
# context after
# This is non-empty if and only if we are _staging_ changes; # This is non-empty if and only if we are _staging_ changes;
# then it accumulates the consecutive "-" lines (after converting # then it accumulates the consecutive "-" lines (after
# them to context lines) in order to be moved after the "+" change # converting them to context lines) in order to be moved after
# line. # "+" change lines.
set pre_context {} set pre_context {}
set n 0 set n 0
set m 0
set i_l [$ui_diff index "$i_l + 1 lines"] set i_l [$ui_diff index "$i_l + 1 lines"]
set patch {} set patch {}
while {[$ui_diff compare $i_l < "end - 1 chars"] && while {[$ui_diff compare $i_l < "end - 1 chars"] &&
[$ui_diff get $i_l "$i_l + 2 chars"] ne {@@}} { [$ui_diff get $i_l "$i_l + 2 chars"] ne {@@}} {
set next_l [$ui_diff index "$i_l + 1 lines"] set next_l [$ui_diff index "$i_l + 1 lines"]
set c1 [$ui_diff get $i_l] set c1 [$ui_diff get $i_l]
if {[$ui_diff compare $i_l <= $the_l] && if {[$ui_diff compare $first_l <= $i_l] &&
[$ui_diff compare $the_l < $next_l]} { [$ui_diff compare $i_l < $last_l] &&
# the line to stage/unstage ($c1 eq {-} || $c1 eq {+})} {
# a line to stage/unstage
set ln [$ui_diff get $i_l $next_l] set ln [$ui_diff get $i_l $next_l]
if {$c1 eq {-}} { if {$c1 eq {-}} {
set n [expr $n+1] set n [expr $n+1]
set patch "$patch$pre_context$ln" set patch "$patch$pre_context$ln"
} else {
set patch "$patch$ln$pre_context"
}
set pre_context {} set pre_context {}
} else {
set m [expr $m+1]
set patch "$patch$ln"
}
} elseif {$c1 ne {-} && $c1 ne {+}} { } elseif {$c1 ne {-} && $c1 ne {+}} {
# context line # context line
set ln [$ui_diff get $i_l $next_l] set ln [$ui_diff get $i_l $next_l]
set patch "$patch$pre_context$ln" set patch "$patch$pre_context$ln"
set n [expr $n+1] set n [expr $n+1]
set m [expr $m+1]
set pre_context {} set pre_context {}
} elseif {$c1 eq $to_context} { } elseif {$c1 eq $to_context} {
# turn change line into context line # turn change line into context line
@ -624,17 +775,27 @@ proc apply_line {x y} {
set patch "$patch $ln" set patch "$patch $ln"
} }
set n [expr $n+1] set n [expr $n+1]
set m [expr $m+1]
} else {
# a change in the opposite direction of
# to_context which is outside the range of
# lines to apply.
set patch "$patch$pre_context"
set pre_context {}
} }
set i_l $next_l set i_l $next_l
} }
set patch "@@ -$hln,$n +$hln,[eval expr $n $sign 1] @@\n$patch" set patch "$patch$pre_context"
set wholepatch "$wholepatch@@ -$hln,$n +$hln,$m @@\n$patch"
set first_l [$ui_diff index "$next_l + 1 lines"]
}
if {[catch { if {[catch {
set enc [get_path_encoding $current_diff_path] set enc [get_path_encoding $current_diff_path]
set p [eval git_write $apply_cmd] set p [eval git_write $apply_cmd]
fconfigure $p -translation binary -encoding $enc fconfigure $p -translation binary -encoding $enc
puts -nonewline $p $current_diff_header puts -nonewline $p $current_diff_header
puts -nonewline $p $patch puts -nonewline $p $wholepatch
close $p} err]} { close $p} err]} {
error_popup [append $failed_msg "\n\n$err"] error_popup [append $failed_msg "\n\n$err"]
} }

View File

@ -71,11 +71,13 @@ proc ask_popup {msg} {
} }
proc hook_failed_popup {hook msg {is_fatal 1}} { proc hook_failed_popup {hook msg {is_fatal 1}} {
global use_ttk NS
set w .hookfail set w .hookfail
toplevel $w Dialog $w
wm withdraw $w
frame $w.m ${NS}::frame $w.m
label $w.m.l1 -text "$hook hook failed:" \ ${NS}::label $w.m.l1 -text "$hook hook failed:" \
-anchor w \ -anchor w \
-justify left \ -justify left \
-font font_uibold -font font_uibold
@ -87,10 +89,10 @@ proc hook_failed_popup {hook msg {is_fatal 1}} {
-width 80 -height 10 \ -width 80 -height 10 \
-font font_diff \ -font font_diff \
-yscrollcommand [list $w.m.sby set] -yscrollcommand [list $w.m.sby set]
scrollbar $w.m.sby -command [list $w.m.t yview] ${NS}::scrollbar $w.m.sby -command [list $w.m.t yview]
pack $w.m.l1 -side top -fill x pack $w.m.l1 -side top -fill x
if {$is_fatal} { if {$is_fatal} {
label $w.m.l2 \ ${NS}::label $w.m.l2 \
-text [mc "You must correct the above errors before committing."] \ -text [mc "You must correct the above errors before committing."] \
-anchor w \ -anchor w \
-justify left \ -justify left \
@ -104,7 +106,7 @@ proc hook_failed_popup {hook msg {is_fatal 1}} {
$w.m.t insert 1.0 $msg $w.m.t insert 1.0 $msg
$w.m.t conf -state disabled $w.m.t conf -state disabled
button $w.ok -text OK \ ${NS}::button $w.ok -text OK \
-width 15 \ -width 15 \
-command "destroy $w" -command "destroy $w"
pack $w.ok -side bottom -anchor e -pady 10 -padx 10 pack $w.ok -side bottom -anchor e -pady 10 -padx 10
@ -112,5 +114,6 @@ proc hook_failed_popup {hook msg {is_fatal 1}} {
bind $w <Visibility> "grab $w; focus $w" bind $w <Visibility> "grab $w; focus $w"
bind $w <Key-Return> "destroy $w" bind $w <Key-Return> "destroy $w"
wm title $w [strcat "[appname] ([reponame]): " [mc "error"]] wm title $w [strcat "[appname] ([reponame]): " [mc "error"]]
wm deiconify $w
tkwait window $w tkwait window $w
} }

View File

@ -8,36 +8,41 @@ proc _delete_indexlock {} {
} }
proc _close_updateindex {fd after} { proc _close_updateindex {fd after} {
global use_ttk NS
fconfigure $fd -blocking 1 fconfigure $fd -blocking 1
if {[catch {close $fd} err]} { if {[catch {close $fd} err]} {
set w .indexfried set w .indexfried
toplevel $w Dialog $w
wm withdraw $w
wm title $w [strcat "[appname] ([reponame]): " [mc "Index Error"]] wm title $w [strcat "[appname] ([reponame]): " [mc "Index Error"]]
wm geometry $w "+[winfo rootx .]+[winfo rooty .]" wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
pack [label $w.msg \ set s [mc "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui."]
-justify left \ text $w.msg -yscrollcommand [list $w.vs set] \
-anchor w \ -width [string length $s] -relief flat \
-text [strcat \ -borderwidth 0 -highlightthickness 0 \
[mc "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui."] \ -background [get_bg_color $w]
"\n\n$err"] \ $w.msg tag configure bold -font font_uibold -justify center
] -anchor w ${NS}::scrollbar $w.vs -command [list $w.msg yview]
$w.msg insert end $s bold \n\n$err {}
$w.msg configure -state disabled
frame $w.buttons ${NS}::button $w.continue \
button $w.buttons.continue \
-text [mc "Continue"] \ -text [mc "Continue"] \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.continue -side right -padx 5 ${NS}::button $w.unlock \
button $w.buttons.unlock \
-text [mc "Unlock Index"] \ -text [mc "Unlock Index"] \
-command "destroy $w; _delete_indexlock" -command "destroy $w; _delete_indexlock"
pack $w.buttons.unlock -side right grid $w.msg - $w.vs -sticky news
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 grid $w.unlock $w.continue - -sticky se -padx 2 -pady 2
grid columnconfigure $w 0 -weight 1
grid rowconfigure $w 0 -weight 1
wm protocol $w WM_DELETE_WINDOW update wm protocol $w WM_DELETE_WINDOW update
bind $w.buttons.continue <Visibility> " bind $w.continue <Visibility> "
grab $w grab $w
focus $w.buttons.continue focus %W
" "
wm deiconify $w
tkwait window $w tkwait window $w
$::main_status stop $::main_status stop
@ -98,8 +103,11 @@ proc write_update_indexinfo {fd pathList totalCnt batch after} {
set s $file_states($path) set s $file_states($path)
switch -glob -- [lindex $s 0] { switch -glob -- [lindex $s 0] {
A? {set new _O} A? {set new _O}
M? {set new _M} MT -
TM -
T_ {set new _T} T_ {set new _T}
M? {set new _M}
TD -
D_ {set new _D} D_ {set new _D}
D? {set new _?} D? {set new _?}
?? {continue} ?? {continue}
@ -162,7 +170,10 @@ proc write_update_index {fd pathList totalCnt batch after} {
AD {set new __} AD {set new __}
?D {set new D_} ?D {set new D_}
_O - _O -
AT -
AM {set new A_} AM {set new A_}
TM -
MT -
_T {set new T_} _T {set new T_}
_U - _U -
U? { U? {
@ -256,7 +267,7 @@ proc unstage_helper {txt paths} {
switch -glob -- [lindex $file_states($path) 0] { switch -glob -- [lindex $file_states($path) 0] {
A? - A? -
M? - M? -
T_ - T? -
D? { D? {
lappend pathList $path lappend pathList $path
if {$path eq $current_diff_path} { if {$path eq $current_diff_path} {
@ -345,12 +356,33 @@ proc do_add_all {} {
global file_states global file_states
set paths [list] set paths [list]
set untracked_paths [list]
foreach path [array names file_states] { foreach path [array names file_states] {
switch -glob -- [lindex $file_states($path) 0] { switch -glob -- [lindex $file_states($path) 0] {
U? {continue} U? {continue}
?M - ?M -
?T - ?T -
?D {lappend paths $path} ?D {lappend paths $path}
?O {lappend untracked_paths $path}
}
}
if {[llength $untracked_paths]} {
set reply 0
switch -- [get_config gui.stageuntracked] {
no {
set reply 0
}
yes {
set reply 1
}
ask -
default {
set reply [ask_popup [mc "Stage %d untracked files?" \
[llength $untracked_paths]]]
}
}
if {$reply} {
set paths [concat $paths $untracked_paths]
} }
} }
add_helper {Adding all changed files} $paths add_helper {Adding all changed files} $paths

81
lib/line.tcl Normal file
View File

@ -0,0 +1,81 @@
# goto line number
# based on code from gitk, Copyright (C) Paul Mackerras
class linebar {
field w
field ctext
field linenum {}
constructor new {i_w i_text args} {
global use_ttk NS
set w $i_w
set ctext $i_text
${NS}::frame $w
${NS}::label $w.l -text [mc "Goto Line:"]
tentry $w.ent \
-textvariable ${__this}::linenum \
-background lightgreen \
-validate key \
-validatecommand [cb _validate %P]
${NS}::button $w.bn -text [mc Go] -command [cb _goto]
pack $w.l -side left
pack $w.bn -side right
pack $w.ent -side left -expand 1 -fill x
eval grid conf $w -sticky we $args
grid remove $w
trace add variable linenum write [cb _goto_cb]
bind $w.ent <Return> [cb _goto]
bind $w.ent <Escape> [cb hide]
bind $w <Destroy> [list delete_this $this]
return $this
}
method show {} {
if {![visible $this]} {
grid $w
}
focus -force $w.ent
}
method hide {} {
if {[visible $this]} {
$w.ent delete 0 end
focus $ctext
grid remove $w
}
}
method visible {} {
return [winfo ismapped $w]
}
method editor {} {
return $w.ent
}
method _validate {P} {
# only accept numbers as input
string is integer $P
}
method _goto_cb {name ix op} {
after idle [cb _goto 1]
}
method _goto {{nohide {0}}} {
if {$linenum ne {}} {
$ctext see $linenum.0
if {!$nohide} {
hide $this
}
}
}
}

View File

@ -83,6 +83,7 @@ method _visualize {} {
method _start {} { method _start {} {
global HEAD current_branch remote_url global HEAD current_branch remote_url
global _last_merged_branch
set name [_rev $this] set name [_rev $this]
if {$name eq {}} { if {$name eq {}} {
@ -109,6 +110,7 @@ method _start {} {
regsub ^refs/heads/ $branch {} branch regsub ^refs/heads/ $branch {} branch
puts $fh "$cmit\t\tbranch '$branch' of $remote" puts $fh "$cmit\t\tbranch '$branch' of $remote"
close $fh close $fh
set _last_merged_branch $branch
set cmd [list git] set cmd [list git]
lappend cmd merge lappend cmd merge
@ -139,14 +141,14 @@ method _finish {cons ok} {
constructor dialog {} { constructor dialog {} {
global current_branch global current_branch
global M1B global M1B use_ttk NS
if {![_can_merge $this]} { if {![_can_merge $this]} {
delete_this delete_this
return return
} }
make_toplevel top w make_dialog top w
wm title $top [append "[appname] ([reponame]): " [mc "Merge"]] wm title $top [append "[appname] ([reponame]): " [mc "Merge"]]
if {$top ne {.}} { if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
@ -154,21 +156,21 @@ constructor dialog {} {
set _start [cb _start] set _start [cb _start]
label $w.header \ ${NS}::label $w.header \
-text [mc "Merge Into %s" $current_branch] \ -text [mc "Merge Into %s" $current_branch] \
-font font_uibold -font font_uibold
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.visualize \ ${NS}::button $w.buttons.visualize \
-text [mc Visualize] \ -text [mc Visualize] \
-command [cb _visualize] -command [cb _visualize]
pack $w.buttons.visualize -side left pack $w.buttons.visualize -side left
button $w.buttons.merge \ ${NS}::button $w.buttons.merge \
-text [mc Merge] \ -text [mc Merge] \
-command $_start -command $_start
pack $w.buttons.merge -side right pack $w.buttons.merge -side right
button $w.buttons.cancel \ ${NS}::button $w.buttons.cancel \
-text [mc "Cancel"] \ -text [mc "Cancel"] \
-command [cb _cancel] -command [cb _cancel]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5

View File

@ -88,7 +88,7 @@ proc merge_load_stages {path cont} {
set merge_stages(3) {} set merge_stages(3) {}
set merge_stages_buf {} set merge_stages_buf {}
set merge_stages_fd [eval git_read ls-files -u -z -- $path] set merge_stages_fd [eval git_read ls-files -u -z -- {$path}]
fconfigure $merge_stages_fd -blocking 0 -translation binary -encoding binary fconfigure $merge_stages_fd -blocking 0 -translation binary -encoding binary
fileevent $merge_stages_fd readable [list read_merge_stages $merge_stages_fd $cont] fileevent $merge_stages_fd readable [list read_merge_stages $merge_stages_fd $cont]
@ -175,48 +175,23 @@ proc merge_resolve_tool2 {} {
# Build the command line # Build the command line
switch -- $tool { switch -- $tool {
kdiff3 { araxis {
if {$base_stage ne {}} { if {$base_stage ne {}} {
set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Base)" \ set cmdline [list "$merge_tool_path" -wait -merge -3 -a1 \
--L2 "$MERGED (Local)" --L3 "$MERGED (Remote)" -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE"] -title1:"'$MERGED (Base)'" -title2:"'$MERGED (Local)'" \
-title3:"'$MERGED (Remote)'" \
"$BASE" "$LOCAL" "$REMOTE" "$MERGED"]
} else { } else {
set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Local)" \ set cmdline [list "$merge_tool_path" -wait -2 \
--L2 "$MERGED (Remote)" -o "$MERGED" "$LOCAL" "$REMOTE"] -title1:"'$MERGED (Local)'" -title2:"'$MERGED (Remote)'" \
"$LOCAL" "$REMOTE" "$MERGED"]
} }
} }
tkdiff { bc3 {
if {$base_stage ne {}} { 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 { } 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"]
}
gvimdiff {
set cmdline [list "$merge_tool_path" -f "$LOCAL" "$MERGED" "$REMOTE"]
}
xxdiff {
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"]
} 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"]
}
}
opendiff {
if {$base_stage ne {}} {
set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED"]
} else {
set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -merge "$MERGED"]
} }
} }
ecmerge { ecmerge {
@ -235,6 +210,42 @@ proc merge_resolve_tool2 {} {
"$LOCAL" "$REMOTE" "$basename"] "$LOCAL" "$REMOTE" "$basename"]
} }
} }
gvimdiff {
set cmdline [list "$merge_tool_path" -f "$LOCAL" "$MERGED" "$REMOTE"]
}
kdiff3 {
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"]
} else {
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"]
} else {
set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -merge "$MERGED"]
}
}
p4merge {
set cmdline [list "$merge_tool_path" "$BASE" "$REMOTE" "$LOCAL" "$MERGED"]
}
tkdiff {
if {$base_stage ne {}} {
set cmdline [list "$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE"]
} else {
set cmdline [list "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"]
}
}
vimdiff {
error_popup [mc "Not a GUI merge tool: '%s'" $tool]
return
}
winmerge { winmerge {
if {$base_stage ne {}} { if {$base_stage ne {}} {
# This tool does not support 3-way merges. # 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"] -dl "Theirs File" -dr "Mine File" "$REMOTE" "$LOCAL" "$MERGED"]
} }
} }
araxis { xxdiff {
if {$base_stage ne {}} { if {$base_stage ne {}} {
set cmdline [list "$merge_tool_path" -wait -merge -3 -a1 \ set cmdline [list "$merge_tool_path" -X --show-merged-pane \
-title1:"'$MERGED (Base)'" -title2:"'$MERGED (Local)'" \ -R {Accel.SaveAsMerged: "Ctrl-S"} \
-title3:"'$MERGED (Remote)'" \ -R {Accel.Search: "Ctrl+F"} \
"$BASE" "$LOCAL" "$REMOTE" "$MERGED"] -R {Accel.SearchForward: "Ctrl-G"} \
--merged-file "$MERGED" "$LOCAL" "$BASE" "$REMOTE"]
} else { } else {
set cmdline [list "$merge_tool_path" -wait -2 \ set cmdline [list "$merge_tool_path" -X --show-merged-pane \
-title1:"'$MERGED (Local)'" -title2:"'$MERGED (Remote)'" \ -R {Accel.SaveAsMerged: "Ctrl-S"} \
"$LOCAL" "$REMOTE" "$MERGED"] -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 { default {
error_popup [mc "Unsupported merge tool '%s'" $tool] error_popup [mc "Unsupported merge tool '%s'" $tool]
return return
@ -382,7 +389,7 @@ proc merge_tool_finish {fd} {
delete_temp_files $mtool_tmpfiles delete_temp_files $mtool_tmpfiles
ui_status [mc "Merge tool failed."] ui_status [mc "Merge tool failed."]
} else { } else {
if {[is_config_true merge.keepbackup]} { if {[is_config_true mergetool.keepbackup]} {
file rename -force -- $backup "$mtool_target.orig" file rename -force -- $backup "$mtool_target.orig"
} }

View File

@ -91,7 +91,7 @@ proc save_config {} {
proc do_options {} { proc do_options {} {
global repo_config global_config font_descs global repo_config global_config font_descs
global repo_config_new global_config_new global repo_config_new global_config_new
global ui_comm_spell global ui_comm_spell use_ttk NS
array unset repo_config_new array unset repo_config_new
array unset global_config_new array unset global_config_new
@ -110,26 +110,28 @@ proc do_options {} {
} }
set w .options_editor set w .options_editor
toplevel $w Dialog $w
wm withdraw $w
wm transient $w [winfo parent $w]
wm geometry $w "+[winfo rootx .]+[winfo rooty .]" wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.restore -text [mc "Restore Defaults"] \ ${NS}::button $w.buttons.restore -text [mc "Restore Defaults"] \
-default normal \ -default normal \
-command do_restore_defaults -command do_restore_defaults
pack $w.buttons.restore -side left pack $w.buttons.restore -side left
button $w.buttons.save -text [mc Save] \ ${NS}::button $w.buttons.save -text [mc Save] \
-default active \ -default active \
-command [list do_save_config $w] -command [list do_save_config $w]
pack $w.buttons.save -side right pack $w.buttons.save -side right
button $w.buttons.cancel -text [mc "Cancel"] \ ${NS}::button $w.buttons.cancel -text [mc "Cancel"] \
-default normal \ -default normal \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.repo -text [mc "%s Repository" [reponame]] ${NS}::labelframe $w.repo -text [mc "%s Repository" [reponame]]
labelframe $w.global -text [mc "Global (All Repositories)"] ${NS}::labelframe $w.global -text [mc "Global (All Repositories)"]
pack $w.repo -side left -fill both -expand 1 -pady 5 -padx 5 pack $w.repo -side left -fill both -expand 1 -pady 5 -padx 5
pack $w.global -side right -fill both -expand 1 -pady 5 -padx 5 pack $w.global -side right -fill both -expand 1 -pady 5 -padx 5
@ -146,6 +148,7 @@ proc do_options {} {
{b gui.trustmtime {mc "Trust File Modification Timestamps"}} {b gui.trustmtime {mc "Trust File Modification Timestamps"}}
{b gui.pruneduringfetch {mc "Prune Tracking Branches During Fetch"}} {b gui.pruneduringfetch {mc "Prune Tracking Branches During Fetch"}}
{b gui.matchtrackingbranch {mc "Match Tracking Branches"}} {b gui.matchtrackingbranch {mc "Match Tracking Branches"}}
{b gui.textconv {mc "Use Textconv For Diffs and Blames"}}
{b gui.fastcopyblame {mc "Blame Copy Only On Changed Files"}} {b gui.fastcopyblame {mc "Blame Copy Only On Changed Files"}}
{i-20..200 gui.copyblamethreshold {mc "Minimum Letters To Blame Copy On"}} {i-20..200 gui.copyblamethreshold {mc "Minimum Letters To Blame Copy On"}}
{i-0..300 gui.blamehistoryctx {mc "Blame History Context Radius (days)"}} {i-0..300 gui.blamehistoryctx {mc "Blame History Context Radius (days)"}}
@ -153,6 +156,7 @@ proc do_options {} {
{i-0..99 gui.commitmsgwidth {mc "Commit Message Text Width"}} {i-0..99 gui.commitmsgwidth {mc "Commit Message Text Width"}}
{t gui.newbranchtemplate {mc "New Branch Name Template"}} {t gui.newbranchtemplate {mc "New Branch Name Template"}}
{c gui.encoding {mc "Default File Contents Encoding"}} {c gui.encoding {mc "Default File Contents Encoding"}}
{s gui.stageuntracked {mc "Staging of untracked files"} {list "yes" "no" "ask"}}
} { } {
set type [lindex $option 0] set type [lindex $option 0]
set name [lindex $option 1] set name [lindex $option 1]
@ -161,7 +165,7 @@ proc do_options {} {
foreach f {repo global} { foreach f {repo global} {
switch -glob -- $type { switch -glob -- $type {
b { b {
checkbutton $w.$f.$optid -text $text \ ${NS}::checkbutton $w.$f.$optid -text $text \
-variable ${f}_config_new($name) \ -variable ${f}_config_new($name) \
-onvalue true \ -onvalue true \
-offvalue false -offvalue false
@ -169,10 +173,10 @@ proc do_options {} {
} }
i-* { i-* {
regexp -- {-(\d+)\.\.(\d+)$} $type _junk min max regexp -- {-(\d+)\.\.(\d+)$} $type _junk min max
frame $w.$f.$optid ${NS}::frame $w.$f.$optid
label $w.$f.$optid.l -text "$text:" ${NS}::label $w.$f.$optid.l -text "$text:"
pack $w.$f.$optid.l -side left -anchor w -fill x pack $w.$f.$optid.l -side left -anchor w -fill x
spinbox $w.$f.$optid.v \ tspinbox $w.$f.$optid.v \
-textvariable ${f}_config_new($name) \ -textvariable ${f}_config_new($name) \
-from $min \ -from $min \
-to $max \ -to $max \
@ -184,11 +188,9 @@ proc do_options {} {
} }
c - c -
t { t {
frame $w.$f.$optid ${NS}::frame $w.$f.$optid
label $w.$f.$optid.l -text "$text:" ${NS}::label $w.$f.$optid.l -text "$text:"
entry $w.$f.$optid.v \ ${NS}::entry $w.$f.$optid.v \
-borderwidth 1 \
-relief sunken \
-width 20 \ -width 20 \
-textvariable ${f}_config_new($name) -textvariable ${f}_config_new($name)
pack $w.$f.$optid.l -side left -anchor w pack $w.$f.$optid.l -side left -anchor w
@ -199,7 +201,7 @@ proc do_options {} {
menu $w.$f.$optid.m menu $w.$f.$optid.m
build_encoding_menu $w.$f.$optid.m \ build_encoding_menu $w.$f.$optid.m \
[list set ${f}_config_new($name)] 1 [list set ${f}_config_new($name)] 1
button $w.$f.$optid.b \ ${NS}::button $w.$f.$optid.b \
-text [mc "Change"] \ -text [mc "Change"] \
-command [list popup_btn_menu \ -command [list popup_btn_menu \
$w.$f.$optid.m $w.$f.$optid.b] $w.$f.$optid.m $w.$f.$optid.b]
@ -207,6 +209,23 @@ proc do_options {} {
} }
pack $w.$f.$optid -side top -anchor w -fill x pack $w.$f.$optid -side top -anchor w -fill x
} }
s {
set opts [eval [lindex $option 3]]
${NS}::frame $w.$f.$optid
${NS}::label $w.$f.$optid.l -text "$text:"
if {$use_ttk} {
ttk::combobox $w.$f.$optid.v \
-textvariable ${f}_config_new($name) \
-values $opts -state readonly
} else {
eval tk_optionMenu $w.$f.$optid.v \
${f}_config_new($name) \
$opts
}
pack $w.$f.$optid.l -side left -anchor w -fill x
pack $w.$f.$optid.v -side right -anchor e -padx 5
pack $w.$f.$optid -side top -anchor w -fill x
}
} }
} }
} }
@ -226,11 +245,17 @@ proc do_options {} {
set ${f}_config_new(gui.spellingdictionary) $value set ${f}_config_new(gui.spellingdictionary) $value
} }
frame $w.$f.$optid ${NS}::frame $w.$f.$optid
label $w.$f.$optid.l -text [mc "Spelling Dictionary:"] ${NS}::label $w.$f.$optid.l -text [mc "Spelling Dictionary:"]
if {$use_ttk} {
ttk::combobox $w.$f.$optid.v \
-textvariable ${f}_config_new(gui.spellingdictionary) \
-values $all_dicts -state readonly
} else {
eval tk_optionMenu $w.$f.$optid.v \ eval tk_optionMenu $w.$f.$optid.v \
${f}_config_new(gui.spellingdictionary) \ ${f}_config_new(gui.spellingdictionary) \
$all_dicts $all_dicts
}
pack $w.$f.$optid.l -side left -anchor w -fill x pack $w.$f.$optid.l -side left -anchor w -fill x
pack $w.$f.$optid.v -side right -anchor e -padx 5 pack $w.$f.$optid.v -side right -anchor e -padx 5
pack $w.$f.$optid -side top -anchor w -fill x pack $w.$f.$optid -side top -anchor w -fill x
@ -248,20 +273,20 @@ proc do_options {} {
set global_config_new(gui.$font^^size) \ set global_config_new(gui.$font^^size) \
[font configure $font -size] [font configure $font -size]
frame $w.global.$name ${NS}::frame $w.global.$name
label $w.global.$name.l -text "$text:" ${NS}::label $w.global.$name.l -text "$text:"
button $w.global.$name.b \ ${NS}::button $w.global.$name.b \
-text [mc "Change Font"] \ -text [mc "Change Font"] \
-command [list \ -command [list \
choose_font::pick \ tchoosefont \
$w \ $w \
[mc "Choose %s" $text] \ [mc "Choose %s" $text] \
global_config_new(gui.$font^^family) \ global_config_new(gui.$font^^family) \
global_config_new(gui.$font^^size) \ global_config_new(gui.$font^^size) \
] ]
label $w.global.$name.f -textvariable global_config_new(gui.$font^^family) ${NS}::label $w.global.$name.f -textvariable global_config_new(gui.$font^^family)
label $w.global.$name.s -textvariable global_config_new(gui.$font^^size) ${NS}::label $w.global.$name.s -textvariable global_config_new(gui.$font^^size)
label $w.global.$name.pt -text [mc "pt."] ${NS}::label $w.global.$name.pt -text [mc "pt."]
pack $w.global.$name.l -side left -anchor w pack $w.global.$name.l -side left -anchor w
pack $w.global.$name.b -side right -anchor e pack $w.global.$name.b -side right -anchor e
pack $w.global.$name.pt -side right -anchor w pack $w.global.$name.pt -side right -anchor w
@ -280,6 +305,7 @@ proc do_options {} {
set t [mc "Options"] set t [mc "Options"]
} }
wm title $w "[appname] ([reponame]): $t" wm title $w "[appname] ([reponame]): $t"
wm deiconify $w
tkwait window $w tkwait window $w
} }

View File

@ -157,22 +157,7 @@ proc add_fetch_entry {r} {
} }
if {$enable} { if {$enable} {
if {![winfo exists $fetch_m]} { make_sure_remote_submenues_exist $remote_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
}
$fetch_m add command \ $fetch_m add command \
-label $r \ -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 {} { proc populate_remotes_menu {} {
global all_remotes global all_remotes
@ -229,6 +278,8 @@ proc populate_remotes_menu {} {
add_fetch_entry $r add_fetch_entry $r
add_push_entry $r add_push_entry $r
} }
update_all_remotes_menu_entry
} }
proc add_single_remote {name location} { proc add_single_remote {name location} {
@ -244,6 +295,8 @@ proc add_single_remote {name location} {
add_fetch_entry $name add_fetch_entry $name
add_push_entry $name add_push_entry $name
update_all_remotes_menu_entry
} }
proc delete_from_menu {menu name} { proc delete_from_menu {menu name} {
@ -264,8 +317,8 @@ proc remove_remote {name} {
unset repo_config(remote.$name.push) unset repo_config(remote.$name.push)
} }
set i [lsearch -exact all_remotes $name] set i [lsearch -exact $all_remotes $name]
lreplace all_remotes $i $i set all_remotes [lreplace $all_remotes $i $i]
set remote_m .mbar.remote set remote_m .mbar.remote
delete_from_menu $remote_m.fetch $name delete_from_menu $remote_m.fetch $name
@ -273,4 +326,6 @@ proc remove_remote {name} {
delete_from_menu $remote_m.remove $name delete_from_menu $remote_m.remove $name
# Not all remotes are in the push menu # Not all remotes are in the push menu
catch { delete_from_menu $remote_m.push $name } catch { delete_from_menu $remote_m.push $name }
update_all_remotes_menu_entry
} }

View File

@ -13,45 +13,43 @@ field location {}; # location of the remote the user has chosen
field opt_action fetch; # action to do after registering the remote locally field opt_action fetch; # action to do after registering the remote locally
constructor dialog {} { constructor dialog {} {
global repo_config global repo_config use_ttk NS
make_toplevel top w make_dialog top w
wm withdraw $top
wm title $top [append "[appname] ([reponame]): " [mc "Add Remote"]] wm title $top [append "[appname] ([reponame]): " [mc "Add Remote"]]
if {$top ne {.}} { if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
} }
label $w.header -text [mc "Add New Remote"] -font font_uibold ${NS}::label $w.header -text [mc "Add New Remote"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.create -text [mc Add] \ ${NS}::button $w.buttons.create -text [mc Add] \
-default active \ -default active \
-command [cb _add] -command [cb _add]
pack $w.buttons.create -side right pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc Cancel] \ ${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.desc -text [mc "Remote Details"] ${NS}::labelframe $w.desc -text [mc "Remote Details"]
label $w.desc.name_l -text [mc "Name:"] ${NS}::label $w.desc.name_l -text [mc "Name:"]
set w_name $w.desc.name_t set w_name $w.desc.name_t
entry $w_name \ ${NS}::entry $w_name \
-borderwidth 1 \
-relief sunken \
-width 40 \ -width 40 \
-textvariable @name \ -textvariable @name \
-validate key \ -validate key \
-validatecommand [cb _validate_name %d %S] -validatecommand [cb _validate_name %d %S]
grid $w.desc.name_l $w_name -sticky we -padx {0 5} grid $w.desc.name_l $w_name -sticky we -padx {0 5}
label $w.desc.loc_l -text [mc "Location:"] ${NS}::label $w.desc.loc_l -text [mc "Location:"]
set w_loc $w.desc.loc_t set w_loc $w.desc.loc_t
entry $w_loc \ ${NS}::entry $w_loc \
-borderwidth 1 \
-relief sunken \
-width 40 \ -width 40 \
-textvariable @location -textvariable @location
grid $w.desc.loc_l $w_loc -sticky we -padx {0 5} grid $w.desc.loc_l $w_loc -sticky we -padx {0 5}
@ -59,21 +57,21 @@ constructor dialog {} {
grid columnconfigure $w.desc 1 -weight 1 grid columnconfigure $w.desc 1 -weight 1
pack $w.desc -anchor nw -fill x -pady 5 -padx 5 pack $w.desc -anchor nw -fill x -pady 5 -padx 5
labelframe $w.action -text [mc "Further Action"] ${NS}::labelframe $w.action -text [mc "Further Action"]
radiobutton $w.action.fetch \ ${NS}::radiobutton $w.action.fetch \
-text [mc "Fetch Immediately"] \ -text [mc "Fetch Immediately"] \
-value fetch \ -value fetch \
-variable @opt_action -variable @opt_action
pack $w.action.fetch -anchor nw pack $w.action.fetch -anchor nw
radiobutton $w.action.push \ ${NS}::radiobutton $w.action.push \
-text [mc "Initialize Remote Repository and Push"] \ -text [mc "Initialize Remote Repository and Push"] \
-value push \ -value push \
-variable @opt_action -variable @opt_action
pack $w.action.push -anchor nw pack $w.action.push -anchor nw
radiobutton $w.action.none \ ${NS}::radiobutton $w.action.none \
-text [mc "Do Nothing Else Now"] \ -text [mc "Do Nothing Else Now"] \
-value none \ -value none \
-variable @opt_action -variable @opt_action
@ -85,6 +83,7 @@ constructor dialog {} {
bind $w <Visibility> [cb _visible] bind $w <Visibility> [cb _visible]
bind $w <Key-Escape> [list destroy $w] bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [cb _add]\;break bind $w <Key-Return> [cb _add]\;break
wm deiconify $top
tkwait window $w tkwait window $w
} }

View File

@ -23,34 +23,40 @@ field full_cache
field cached field cached
constructor dialog {} { constructor dialog {} {
global all_remotes M1B global all_remotes M1B use_ttk NS
make_toplevel top w make_dialog top w
wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch Remotely"]] wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch Remotely"]]
if {$top ne {.}} { if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
} }
label $w.header -text [mc "Delete Branch Remotely"] -font font_uibold ${NS}::label $w.header -text [mc "Delete Branch Remotely"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.delete -text [mc Delete] \ ${NS}::button $w.buttons.delete -text [mc Delete] \
-default active \ -default active \
-command [cb _delete] -command [cb _delete]
pack $w.buttons.delete -side right pack $w.buttons.delete -side right
button $w.buttons.cancel -text [mc "Cancel"] \ ${NS}::button $w.buttons.cancel -text [mc "Cancel"] \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.dest -text [mc "From Repository"] ${NS}::labelframe $w.dest -text [mc "From Repository"]
if {$all_remotes ne {}} { if {$all_remotes ne {}} {
radiobutton $w.dest.remote_r \ ${NS}::radiobutton $w.dest.remote_r \
-text [mc "Remote:"] \ -text [mc "Remote:"] \
-value remote \ -value remote \
-variable @urltype -variable @urltype
if {$use_ttk} {
ttk::combobox $w.dest.remote_m -textvariable @remote \
-values $all_remotes -state readonly
} else {
eval tk_optionMenu $w.dest.remote_m @remote $all_remotes eval tk_optionMenu $w.dest.remote_m @remote $all_remotes
}
grid $w.dest.remote_r $w.dest.remote_m -sticky w grid $w.dest.remote_r $w.dest.remote_m -sticky w
if {[lsearch -sorted -exact $all_remotes origin] != -1} { if {[lsearch -sorted -exact $all_remotes origin] != -1} {
set remote origin set remote origin
@ -62,13 +68,11 @@ constructor dialog {} {
} else { } else {
set urltype url set urltype url
} }
radiobutton $w.dest.url_r \ ${NS}::radiobutton $w.dest.url_r \
-text [mc "Arbitrary Location:"] \ -text [mc "Arbitrary Location:"] \
-value url \ -value url \
-variable @urltype -variable @urltype
entry $w.dest.url_t \ ${NS}::entry $w.dest.url_t \
-borderwidth 1 \
-relief sunken \
-width 50 \ -width 50 \
-textvariable @url \ -textvariable @url \
-validate key \ -validate key \
@ -81,33 +85,30 @@ constructor dialog {} {
grid columnconfigure $w.dest 1 -weight 1 grid columnconfigure $w.dest 1 -weight 1
pack $w.dest -anchor nw -fill x -pady 5 -padx 5 pack $w.dest -anchor nw -fill x -pady 5 -padx 5
labelframe $w.heads -text [mc "Branches"] ${NS}::labelframe $w.heads -text [mc "Branches"]
listbox $w.heads.l \ slistbox $w.heads.l \
-height 10 \ -height 10 \
-width 70 \ -width 70 \
-listvariable @head_list \ -listvariable @head_list \
-selectmode extended \ -selectmode extended
-yscrollcommand [list $w.heads.sby set]
scrollbar $w.heads.sby -command [list $w.heads.l yview]
frame $w.heads.footer ${NS}::frame $w.heads.footer
label $w.heads.footer.status \ ${NS}::label $w.heads.footer.status \
-textvariable @status \ -textvariable @status \
-anchor w \ -anchor w \
-justify left -justify left
button $w.heads.footer.rescan \ ${NS}::button $w.heads.footer.rescan \
-text [mc "Rescan"] \ -text [mc "Rescan"] \
-command [cb _rescan] -command [cb _rescan]
pack $w.heads.footer.status -side left -fill x pack $w.heads.footer.status -side left -fill x
pack $w.heads.footer.rescan -side right pack $w.heads.footer.rescan -side right
pack $w.heads.footer -side bottom -fill x pack $w.heads.footer -side bottom -fill x
pack $w.heads.sby -side right -fill y
pack $w.heads.l -side left -fill both -expand 1 pack $w.heads.l -side left -fill both -expand 1
pack $w.heads -fill both -expand 1 -pady 5 -padx 5 pack $w.heads -fill both -expand 1 -pady 5 -padx 5
labelframe $w.validate -text [mc "Delete Only If"] ${NS}::labelframe $w.validate -text [mc "Delete Only If"]
radiobutton $w.validate.head_r \ ${NS}::radiobutton $w.validate.head_r \
-text [mc "Merged Into:"] \ -text [mc "Merged Into:"] \
-value head \ -value head \
-variable @checktype -variable @checktype
@ -115,7 +116,7 @@ constructor dialog {} {
trace add variable @head_list write [cb _write_head_list] trace add variable @head_list write [cb _write_head_list]
trace add variable @check_head write [cb _write_check_head] trace add variable @check_head write [cb _write_check_head]
grid $w.validate.head_r $w.validate.head_m -sticky w grid $w.validate.head_r $w.validate.head_m -sticky w
radiobutton $w.validate.always_r \ ${NS}::radiobutton $w.validate.always_r \
-text [mc "Always (Do not perform merge checks)"] \ -text [mc "Always (Do not perform merge checks)"] \
-value always \ -value always \
-variable @checktype -variable @checktype
@ -208,16 +209,16 @@ method _delete {} {
return return
} }
if {$checktype ne {head}} {
if {[tk_messageBox \ if {[tk_messageBox \
-icon warning \ -icon warning \
-type yesno \ -type yesno \
-title [wm title $w] \ -title [wm title $w] \
-parent $w \ -parent $w \
-message [mc "Recovering deleted branches is difficult. -message [mc "Recovering deleted branches is difficult.\n\nDelete the selected branches?"]] ne yes} {
Delete the selected branches?"]] ne yes} {
return return
} }
}
destroy $w destroy $w
@ -250,6 +251,8 @@ method _write_url {args} { set urltype url }
method _write_check_head {args} { set checktype head } method _write_check_head {args} { set checktype head }
method _write_head_list {args} { method _write_head_list {args} {
global current_branch _last_merged_branch
$head_m delete 0 end $head_m delete 0 end
foreach abr $head_list { foreach abr $head_list {
$head_m insert end radiobutton \ $head_m insert end radiobutton \
@ -258,7 +261,18 @@ method _write_head_list {args} {
-variable @check_head -variable @check_head
} }
if {[lsearch -exact -sorted $head_list $check_head] < 0} { if {[lsearch -exact -sorted $head_list $check_head] < 0} {
if {[lsearch -exact -sorted $head_list $current_branch] < 0} {
set check_head {} set check_head {}
} else {
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
} }
} }

View File

@ -7,25 +7,46 @@ field w
field ctext field ctext
field searchstring {} field searchstring {}
field casesensitive 1 field regexpsearch
field default_regexpsearch
field casesensitive
field default_casesensitive
field smartcase
field searchdirn -forwards field searchdirn -forwards
field history
field history_index
field smarktop field smarktop
field smarkbot field smarkbot
constructor new {i_w i_text args} { constructor new {i_w i_text args} {
global use_ttk NS
set w $i_w set w $i_w
set ctext $i_text set ctext $i_text
frame $w set default_regexpsearch [is_config_true gui.search.regexp]
label $w.l -text [mc Find:] set smartcase [is_config_true gui.search.smartcase]
entry $w.ent -textvariable ${__this}::searchstring -background lightgreen if {$smartcase} {
button $w.bn -text [mc Next] -command [cb find_next] set default_casesensitive 0
button $w.bp -text [mc Prev] -command [cb find_prev] } else {
checkbutton $w.cs -text [mc Case-Sensitive] \ set default_casesensitive 1
}
set history [list]
${NS}::frame $w
${NS}::label $w.l -text [mc Find:]
tentry $w.ent -textvariable ${__this}::searchstring -background lightgreen
${NS}::button $w.bn -text [mc Next] -command [cb find_next]
${NS}::button $w.bp -text [mc Prev] -command [cb find_prev]
${NS}::checkbutton $w.re -text [mc RegExp] \
-variable ${__this}::regexpsearch -command [cb _incrsearch]
${NS}::checkbutton $w.cs -text [mc Case] \
-variable ${__this}::casesensitive -command [cb _incrsearch] -variable ${__this}::casesensitive -command [cb _incrsearch]
pack $w.l -side left pack $w.l -side left
pack $w.cs -side right pack $w.cs -side right
pack $w.re -side right
pack $w.bp -side right pack $w.bp -side right
pack $w.bn -side right pack $w.bn -side right
pack $w.ent -side left -expand 1 -fill x pack $w.ent -side left -expand 1 -fill x
@ -34,6 +55,10 @@ constructor new {i_w i_text args} {
grid remove $w grid remove $w
trace add variable searchstring write [cb _incrsearch_cb] trace add variable searchstring write [cb _incrsearch_cb]
bind $w.ent <Return> [cb find_next]
bind $w.ent <Shift-Return> [cb find_prev]
bind $w.ent <Key-Up> [cb _prev_search]
bind $w.ent <Key-Down> [cb _next_search]
bind $w <Destroy> [list delete_this $this] bind $w <Destroy> [list delete_this $this]
return $this return $this
@ -42,6 +67,10 @@ constructor new {i_w i_text args} {
method show {} { method show {} {
if {![visible $this]} { if {![visible $this]} {
grid $w grid $w
$w.ent delete 0 end
set regexpsearch $default_regexpsearch
set casesensitive $default_casesensitive
set history_index [llength $history]
} }
focus -force $w.ent focus -force $w.ent
} }
@ -50,6 +79,7 @@ method hide {} {
if {[visible $this]} { if {[visible $this]} {
focus $ctext focus $ctext
grid remove $w grid remove $w
_save_search $this
} }
} }
@ -95,6 +125,9 @@ method _do_search {start {mlenvar {}} {dir {}} {endbound {}}} {
upvar $mlenvar mlen upvar $mlenvar mlen
lappend cmd -count mlen lappend cmd -count mlen
} }
if {$regexpsearch} {
lappend cmd -regexp
}
if {!$casesensitive} { if {!$casesensitive} {
lappend cmd -nocase lappend cmd -nocase
} }
@ -102,6 +135,7 @@ method _do_search {start {mlenvar {}} {dir {}} {endbound {}}} {
set dir $searchdirn set dir $searchdirn
} }
lappend cmd $dir -- $searchstring lappend cmd $dir -- $searchstring
if {[catch {
if {$endbound ne {}} { if {$endbound ne {}} {
set here [eval $cmd [list $start] [list $endbound]] set here [eval $cmd [list $start] [list $endbound]]
} else { } else {
@ -110,6 +144,7 @@ method _do_search {start {mlenvar {}} {dir {}} {endbound {}}} {
set here [eval $cmd [_get_wrap_anchor $this $dir]] set here [eval $cmd [_get_wrap_anchor $this $dir]]
} }
} }
} err]} { set here {} }
return $here return $here
} }
@ -122,20 +157,76 @@ method _incrsearch {} {
if {[catch {$ctext index anchor}]} { if {[catch {$ctext index anchor}]} {
$ctext mark set anchor [_get_new_anchor $this] $ctext mark set anchor [_get_new_anchor $this]
} }
if {$smartcase} {
if {[regexp {[[:upper:]]} $searchstring]} {
set casesensitive 1
}
}
if {$searchstring ne {}} { if {$searchstring ne {}} {
set here [_do_search $this anchor mlen] set here [_do_search $this anchor mlen]
if {$here ne {}} { if {$here ne {}} {
$ctext see $here $ctext see $here
$ctext tag remove sel 1.0 end $ctext tag remove sel 1.0 end
$ctext tag add sel $here "$here + $mlen c" $ctext tag add sel $here "$here + $mlen c"
$w.ent configure -background lightgreen #$w.ent configure -background lightgreen
$w.ent state !pressed
_set_marks $this 1 _set_marks $this 1
} else { } else {
$w.ent configure -background lightpink #$w.ent configure -background lightpink
$w.ent state pressed
} }
} }
} }
method _save_search {} {
if {$searchstring eq {}} {
return
}
if {[llength $history] > 0} {
foreach {s_regexp s_case s_expr} [lindex $history end] break
} else {
set s_regexp $regexpsearch
set s_case $casesensitive
set s_expr ""
}
if {$searchstring eq $s_expr} {
# update modes
set history [lreplace $history end end \
[list $regexpsearch $casesensitive $searchstring]]
} else {
lappend history [list $regexpsearch $casesensitive $searchstring]
}
set history_index [llength $history]
}
method _prev_search {} {
if {$history_index > 0} {
incr history_index -1
foreach {s_regexp s_case s_expr} [lindex $history $history_index] break
$w.ent delete 0 end
$w.ent insert 0 $s_expr
set regexpsearch $s_regexp
set casesensitive $s_case
}
}
method _next_search {} {
if {$history_index < [llength $history]} {
incr history_index
}
if {$history_index < [llength $history]} {
foreach {s_regexp s_case s_expr} [lindex $history $history_index] break
} else {
set s_regexp $default_regexpsearch
set s_case $default_casesensitive
set s_expr ""
}
$w.ent delete 0 end
$w.ent insert 0 $s_expr
set regexpsearch $s_regexp
set casesensitive $s_case
}
method find_prev {} { method find_prev {} {
find_next $this -backwards find_next $this -backwards
} }
@ -146,6 +237,7 @@ method find_next {{dir -forwards}} {
set searchdirn $dir set searchdirn $dir
$ctext mark unset anchor $ctext mark unset anchor
if {$searchstring ne {}} { if {$searchstring ne {}} {
_save_search $this
set start [_get_new_anchor $this] set start [_get_new_anchor $this]
if {$dir eq "-forwards"} { if {$dir eq "-forwards"} {
set start "$start + 1c" set start "$start + 1c"

View File

@ -2,6 +2,7 @@
# Copyright (C) 2006, 2007 Shawn Pearce # Copyright (C) 2006, 2007 Shawn Pearce
proc do_windows_shortcut {} { proc do_windows_shortcut {} {
global _gitworktree
set fn [tk_getSaveFile \ set fn [tk_getSaveFile \
-parent . \ -parent . \
-title [append "[appname] ([reponame]): " [mc "Create Desktop Icon"]] \ -title [append "[appname] ([reponame]): " [mc "Create Desktop Icon"]] \
@ -15,7 +16,7 @@ proc do_windows_shortcut {} {
[info nameofexecutable] \ [info nameofexecutable] \
[file normalize $::argv0] \ [file normalize $::argv0] \
] \ ] \
[file dirname [file normalize [gitdir]]] [file normalize $_gitworktree]
} err]} { } err]} {
error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"] error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"]
} }
@ -23,7 +24,7 @@ proc do_windows_shortcut {} {
} }
proc do_cygwin_shortcut {} { proc do_cygwin_shortcut {} {
global argv0 global argv0 _gitworktree
if {[catch { if {[catch {
set desktop [exec cygpath \ set desktop [exec cygpath \
@ -54,9 +55,9 @@ proc do_cygwin_shortcut {} {
$argv0] $argv0]
win32_create_lnk $fn [list \ win32_create_lnk $fn [list \
$sh -c \ $sh -c \
"CHERE_INVOKING=1 source /etc/profile;[sq $me]" \ "CHERE_INVOKING=1 source /etc/profile;[sq $me] &" \
] \ ] \
[file dirname [file normalize [gitdir]]] [file normalize $_gitworktree]
} err]} { } err]} {
error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"] error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"]
} }

View File

@ -15,7 +15,7 @@ proc find_ssh_key {} {
} }
proc do_ssh_key {} { proc do_ssh_key {} {
global sshkey_title have_tk85 sshkey_fd global sshkey_title have_tk85 sshkey_fd use_ttk NS
set w .sshkey_dialog set w .sshkey_dialog
if {[winfo exists $w]} { if {[winfo exists $w]} {
@ -23,7 +23,7 @@ proc do_ssh_key {} {
return return
} }
toplevel $w Dialog $w
wm transient $w . wm transient $w .
set finfo [find_ssh_key] set finfo [find_ssh_key]
@ -35,9 +35,9 @@ proc do_ssh_key {} {
set gen_state disabled set gen_state disabled
} }
frame $w.header -relief flat ${NS}::frame $w.header
label $w.header.lbl -textvariable sshkey_title -anchor w ${NS}::label $w.header.lbl -textvariable sshkey_title -anchor w
button $w.header.gen -text [mc "Generate Key"] \ ${NS}::button $w.header.gen -text [mc "Generate Key"] \
-command [list make_ssh_key $w] -state $gen_state -command [list make_ssh_key $w] -state $gen_state
pack $w.header.lbl -side left -expand 1 -fill x pack $w.header.lbl -side left -expand 1 -fill x
pack $w.header.gen -side right pack $w.header.gen -side right
@ -46,14 +46,16 @@ proc do_ssh_key {} {
text $w.contents -width 60 -height 10 -wrap char -relief sunken text $w.contents -width 60 -height 10 -wrap char -relief sunken
pack $w.contents -fill both -expand 1 pack $w.contents -fill both -expand 1
if {$have_tk85} { if {$have_tk85} {
$w.contents configure -inactiveselectbackground darkblue set clr darkblue
if {$use_ttk} { set clr [ttk::style lookup . -selectbackground] }
$w.contents configure -inactiveselectbackground $clr
} }
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.close -text [mc Close] \ ${NS}::button $w.buttons.close -text [mc Close] \
-default active -command [list destroy $w] -default active -command [list destroy $w]
pack $w.buttons.close -side right pack $w.buttons.close -side right
button $w.buttons.copy -text [mc "Copy To Clipboard"] \ ${NS}::button $w.buttons.copy -text [mc "Copy To Clipboard"] \
-command [list tk_textCopy $w.contents] -command [list tk_textCopy $w.contents]
pack $w.buttons.copy -side left pack $w.buttons.copy -side left
pack $w.buttons -side bottom -fill x -pady 5 -padx 5 pack $w.buttons -side bottom -fill x -pady 5 -padx 5

View File

@ -13,14 +13,16 @@ field units {}; # unit of progress
field meter {}; # current core git progress meter (if active) field meter {}; # current core git progress meter (if active)
constructor new {path} { constructor new {path} {
global use_ttk NS
set w $path set w $path
set w_l $w.l set w_l $w.l
set w_c $w.c set w_c $w.c
frame $w \ ${NS}::frame $w
-borderwidth 1 \ if {!$use_ttk} {
-relief sunken $w configure -borderwidth 1 -relief sunken
label $w_l \ }
${NS}::label $w_l \
-textvariable @status \ -textvariable @status \
-anchor w \ -anchor w \
-justify left -justify left
@ -37,12 +39,13 @@ method _oneline_pack {} {
} }
constructor two_line {path} { constructor two_line {path} {
global NS
set w $path set w $path
set w_l $w.l set w_l $w.l
set w_c $w.c set w_c $w.c
frame $w ${NS}::frame $w
label $w_l \ ${NS}::label $w_l \
-textvariable @status \ -textvariable @status \
-anchor w \ -anchor w \
-justify left -justify left

264
lib/themed.tcl Normal file
View File

@ -0,0 +1,264 @@
# Functions for supporting the use of themed Tk widgets in git-gui.
# Copyright (C) 2009 Pat Thoyts <patthoyts@users.sourceforge.net>
proc InitTheme {} {
# Create a color label style (bg can be overridden by widget option)
ttk::style layout Color.TLabel {
Color.Label.border -sticky news -children {
Color.label.fill -sticky news -children {
Color.Label.padding -sticky news -children {
Color.Label.label -sticky news}}}}
eval [linsert [ttk::style configure TLabel] 0 \
ttk::style configure Color.TLabel]
ttk::style configure Color.TLabel \
-borderwidth 0 -relief flat -padding 2
ttk::style map Color.TLabel -background {{} gold}
# We also need a padded label.
ttk::style configure Padded.TLabel \
-padding {5 5} -borderwidth 1 -relief solid
# We need a gold frame.
ttk::style layout Gold.TFrame {
Gold.Frame.border -sticky nswe -children {
Gold.Frame.fill -sticky nswe}}
ttk::style configure Gold.TFrame -background gold -relief flat
# listboxes should have a theme border so embed in ttk::frame
ttk::style layout SListbox.TFrame {
SListbox.Frame.Entry.field -sticky news -border true -children {
SListbox.Frame.padding -sticky news
}
}
# Handle either current Tk or older versions of 8.5
if {[catch {set theme [ttk::style theme use]}]} {
set theme $::ttk::currentTheme
}
if {[lsearch -exact {default alt classic clam} $theme] != -1} {
# Simple override of standard ttk::entry to change the field
# packground according to a state flag. We should use 'user1'
# but not all versions of 8.5 support that so make use of 'pressed'
# which is not normally in use for entry widgets.
ttk::style layout Edged.Entry [ttk::style layout TEntry]
ttk::style map Edged.Entry {*}[ttk::style map TEntry]
ttk::style configure Edged.Entry {*}[ttk::style configure TEntry] \
-fieldbackground lightgreen
ttk::style map Edged.Entry -fieldbackground {
{pressed !disabled} lightpink
}
} else {
# For fancier themes, in particular the Windows ones, the field
# element may not support changing the background color. So instead
# override the fill using the default fill element. If we overrode
# the vista theme field element we would loose the themed border
# of the widget.
catch {
ttk::style element create color.fill from default
}
ttk::style layout Edged.Entry {
Edged.Entry.field -sticky nswe -border 0 -children {
Edged.Entry.border -sticky nswe -border 1 -children {
Edged.Entry.padding -sticky nswe -children {
Edged.Entry.color.fill -sticky nswe -children {
Edged.Entry.textarea -sticky nswe
}
}
}
}
}
ttk::style configure Edged.Entry {*}[ttk::style configure TEntry] \
-background lightgreen -padding 0 -borderwidth 0
ttk::style map Edged.Entry {*}[ttk::style map TEntry] \
-background {{pressed !disabled} lightpink}
}
if {[lsearch [bind . <<ThemeChanged>>] InitTheme] == -1} {
bind . <<ThemeChanged>> +[namespace code [list InitTheme]]
}
}
proc gold_frame {w args} {
global use_ttk
if {$use_ttk} {
eval [linsert $args 0 ttk::frame $w -style Gold.TFrame]
} else {
eval [linsert $args 0 frame $w -background gold]
}
}
proc tlabel {w args} {
global use_ttk
if {$use_ttk} {
set cmd [list ttk::label $w -style Color.TLabel]
foreach {k v} $args {
switch -glob -- $k {
-activebackground {}
default { lappend cmd $k $v }
}
}
eval $cmd
} else {
eval [linsert $args 0 label $w]
}
}
# The padded label gets used in the about class.
proc paddedlabel {w args} {
global use_ttk
if {$use_ttk} {
eval [linsert $args 0 ttk::label $w -style Padded.TLabel]
} else {
eval [linsert $args 0 label $w \
-padx 5 -pady 5 \
-justify left \
-anchor w \
-borderwidth 1 \
-relief solid]
}
}
# Create a toplevel for use as a dialog.
# If available, sets the EWMH dialog hint and if ttk is enabled
# place a themed frame over the surface.
proc Dialog {w args} {
eval [linsert $args 0 toplevel $w -class Dialog]
pave_toplevel $w
return $w
}
# Tk toplevels are not themed - so pave it over with a themed frame to get
# the base color correct per theme.
proc pave_toplevel {w} {
global use_ttk
if {$use_ttk && ![winfo exists $w.!paving]} {
set paving [ttk::frame $w.!paving]
place $paving -x 0 -y 0 -relwidth 1 -relheight 1
lower $paving
}
}
# Create a scrolled listbox with appropriate border for the current theme.
# On many themes the border for a scrolled listbox needs to go around the
# listbox and the scrollbar.
proc slistbox {w args} {
global use_ttk NS
if {$use_ttk} {
set f [ttk::frame $w -style SListbox.TFrame -padding 2]
} else {
set f [frame $w -relief flat]
}
if {[catch {
if {$use_ttk} {
eval [linsert $args 0 listbox $f.list -relief flat \
-highlightthickness 0 -borderwidth 0]
} else {
eval [linsert $args 0 listbox $f.list]
}
${NS}::scrollbar $f.vs -command [list $f.list yview]
$f.list configure -yscrollcommand [list $f.vs set]
grid $f.list $f.vs -sticky news
grid rowconfigure $f 0 -weight 1
grid columnconfigure $f 0 -weight 1
bind $f.list <<ListboxSelect>> \
[list event generate $w <<ListboxSelect>>]
interp hide {} $w
interp alias {} $w {} $f.list
} err]} {
destroy $f
return -code error $err
}
return $w
}
# fetch the background color from a widget.
proc get_bg_color {w} {
global use_ttk
if {$use_ttk} {
set bg [ttk::style lookup [winfo class $w] -background]
} else {
set bg [$w cget -background]
}
return $bg
}
# ttk::spinbox didn't get added until 8.6
proc tspinbox {w args} {
global use_ttk
if {$use_ttk && [llength [info commands ttk::spinbox]] > 0} {
eval [linsert $args 0 ttk::spinbox $w]
} else {
eval [linsert $args 0 spinbox $w]
}
}
proc tentry {w args} {
global use_ttk
if {$use_ttk} {
InitTheme
ttk::entry $w -style Edged.Entry
} else {
entry $w
}
rename $w _$w
interp alias {} $w {} tentry_widgetproc $w
eval [linsert $args 0 tentry_widgetproc $w configure]
return $w
}
proc tentry_widgetproc {w cmd args} {
global use_ttk
switch -- $cmd {
state {
if {$use_ttk} {
return [uplevel 1 [list _$w $cmd] $args]
} else {
if {[lsearch -exact $args pressed] != -1} {
_$w configure -background lightpink
} else {
_$w configure -background lightgreen
}
}
}
configure {
if {$use_ttk} {
if {[set n [lsearch -exact $args -background]] != -1} {
set args [lreplace $args $n [incr n]]
if {[llength $args] == 0} {return}
}
}
return [uplevel 1 [list _$w $cmd] $args]
}
default { return [uplevel 1 [list _$w $cmd] $args] }
}
}
# Tk 8.6 provides a standard font selection dialog. This uses the native
# dialogs on Windows and MacOSX or a standard Tk dialog on X11.
proc tchoosefont {w title familyvar sizevar} {
if {[package vsatisfies [package provide Tk] 8.6]} {
upvar #0 $familyvar family
upvar #0 $sizevar size
tk fontchooser configure -parent $w -title $title \
-font [list $family $size] \
-command [list on_choosefont $familyvar $sizevar]
tk fontchooser show
} else {
choose_font::pick $w $title $familyvar $sizevar
}
}
# Called when the Tk 8.6 fontchooser selects a font.
proc on_choosefont {familyvar sizevar font} {
upvar #0 $familyvar family
upvar #0 $sizevar size
set font [font actual $font]
set family [dict get $font -family]
set size [dict get $font -size]
}
# Local variables:
# mode: tcl
# indent-tabs-mode: t
# tab-width: 4
# End:

View File

@ -146,7 +146,7 @@ proc tools_complete {fullname w {ok 1}} {
} }
if {$ok} { if {$ok} {
set msg [mc "Tool completed succesfully: %s" $fullname] set msg [mc "Tool completed successfully: %s" $fullname]
} else { } else {
set msg [mc "Tool failed: %s" $fullname] set msg [mc "Tool failed: %s" $fullname]
} }

View File

@ -16,53 +16,50 @@ field ask_branch 0; # ask for a revision
field ask_args 0; # ask for additional args field ask_args 0; # ask for additional args
constructor dialog {} { constructor dialog {} {
global repo_config global repo_config use_ttk NS
make_toplevel top w make_dialog top w
wm title $top [append "[appname] ([reponame]): " [mc "Add Tool"]] wm title $top [append "[appname] ([reponame]): " [mc "Add Tool"]]
if {$top ne {.}} { if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
wm transient $top . wm transient $top .
} }
label $w.header -text [mc "Add New Tool Command"] -font font_uibold ${NS}::label $w.header -text [mc "Add New Tool Command"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
checkbutton $w.buttons.global \ ${NS}::checkbutton $w.buttons.global \
-text [mc "Add globally"] \ -text [mc "Add globally"] \
-variable @add_global -variable @add_global
pack $w.buttons.global -side left -padx 5 pack $w.buttons.global -side left -padx 5
button $w.buttons.create -text [mc Add] \ ${NS}::button $w.buttons.create -text [mc Add] \
-default active \ -default active \
-command [cb _add] -command [cb _add]
pack $w.buttons.create -side right pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc Cancel] \ ${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.desc -text [mc "Tool Details"] ${NS}::labelframe $w.desc -text [mc "Tool Details"]
label $w.desc.name_cmnt -anchor w\ ${NS}::label $w.desc.name_cmnt -anchor w\
-text [mc "Use '/' separators to create a submenu tree:"] -text [mc "Use '/' separators to create a submenu tree:"]
grid x $w.desc.name_cmnt -sticky we -padx {0 5} -pady {0 2} grid x $w.desc.name_cmnt -sticky we -padx {0 5} -pady {0 2}
label $w.desc.name_l -text [mc "Name:"] ${NS}::label $w.desc.name_l -text [mc "Name:"]
set w_name $w.desc.name_t set w_name $w.desc.name_t
entry $w_name \ ${NS}::entry $w_name \
-borderwidth 1 \
-relief sunken \
-width 40 \ -width 40 \
-textvariable @name \ -textvariable @name \
-validate key \ -validate key \
-validatecommand [cb _validate_name %d %S] -validatecommand [cb _validate_name %d %S]
grid $w.desc.name_l $w_name -sticky we -padx {0 5} grid $w.desc.name_l $w_name -sticky we -padx {0 5}
label $w.desc.cmd_l -text [mc "Command:"] ${NS}::label $w.desc.cmd_l -text [mc "Command:"]
set w_cmd $w.desc.cmd_t set w_cmd $w.desc.cmd_t
entry $w_cmd \ ${NS}::entry $w_cmd \
-borderwidth 1 \
-relief sunken \
-width 40 \ -width 40 \
-textvariable @command -textvariable @command
grid $w.desc.cmd_l $w_cmd -sticky we -padx {0 5} -pady {0 3} grid $w.desc.cmd_l $w_cmd -sticky we -padx {0 5} -pady {0 3}
@ -70,30 +67,30 @@ constructor dialog {} {
grid columnconfigure $w.desc 1 -weight 1 grid columnconfigure $w.desc 1 -weight 1
pack $w.desc -anchor nw -fill x -pady 5 -padx 5 pack $w.desc -anchor nw -fill x -pady 5 -padx 5
checkbutton $w.confirm \ ${NS}::checkbutton $w.confirm \
-text [mc "Show a dialog before running"] \ -text [mc "Show a dialog before running"] \
-variable @confirm -command [cb _check_enable_dlg] -variable @confirm -command [cb _check_enable_dlg]
labelframe $w.dlg -labelwidget $w.confirm ${NS}::labelframe $w.dlg -labelwidget $w.confirm
checkbutton $w.dlg.askbranch \ ${NS}::checkbutton $w.dlg.askbranch \
-text [mc "Ask the user to select a revision (sets \$REVISION)"] \ -text [mc "Ask the user to select a revision (sets \$REVISION)"] \
-variable @ask_branch -state disabled -variable @ask_branch -state disabled
pack $w.dlg.askbranch -anchor w -padx 15 pack $w.dlg.askbranch -anchor w -padx 15
checkbutton $w.dlg.askargs \ ${NS}::checkbutton $w.dlg.askargs \
-text [mc "Ask the user for additional arguments (sets \$ARGS)"] \ -text [mc "Ask the user for additional arguments (sets \$ARGS)"] \
-variable @ask_args -state disabled -variable @ask_args -state disabled
pack $w.dlg.askargs -anchor w -padx 15 pack $w.dlg.askargs -anchor w -padx 15
pack $w.dlg -anchor nw -fill x -pady {0 8} -padx 5 pack $w.dlg -anchor nw -fill x -pady {0 8} -padx 5
checkbutton $w.noconsole \ ${NS}::checkbutton $w.noconsole \
-text [mc "Don't show the command output window"] \ -text [mc "Don't show the command output window"] \
-variable @no_console -variable @no_console
pack $w.noconsole -anchor w -padx 5 pack $w.noconsole -anchor w -padx 5
checkbutton $w.needsfile \ ${NS}::checkbutton $w.needsfile \
-text [mc "Run only if a diff is selected (\$FILENAME not empty)"] \ -text [mc "Run only if a diff is selected (\$FILENAME not empty)"] \
-variable @needs_file -variable @needs_file
pack $w.needsfile -anchor w -padx 5 pack $w.needsfile -anchor w -padx 5
@ -182,40 +179,38 @@ field w ; # widget path
field w_names ; # name list field w_names ; # name list
constructor dialog {} { constructor dialog {} {
global repo_config global_config system_config global repo_config global_config system_config use_ttk NS
load_config 1 load_config 1
make_toplevel top w make_dialog top w
wm title $top [append "[appname] ([reponame]): " [mc "Remove Tool"]] wm title $top [append "[appname] ([reponame]): " [mc "Remove Tool"]]
if {$top ne {.}} { if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
wm transient $top . wm transient $top .
} }
label $w.header -text [mc "Remove Tool Commands"] -font font_uibold ${NS}::label $w.header -text [mc "Remove Tool Commands"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.create -text [mc Remove] \ ${NS}::button $w.buttons.create -text [mc Remove] \
-default active \ -default active \
-command [cb _remove] -command [cb _remove]
pack $w.buttons.create -side right pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc Cancel] \ ${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
frame $w.list ${NS}::frame $w.list
set w_names $w.list.l set w_names $w.list.l
listbox $w_names \ slistbox $w_names \
-height 10 \ -height 10 \
-width 30 \ -width 30 \
-selectmode extended \ -selectmode extended \
-exportselection false \ -exportselection false
-yscrollcommand [list $w.list.sby set]
scrollbar $w.list.sby -command [list $w.list.l yview]
pack $w.list.sby -side right -fill y
pack $w.list.l -side left -fill both -expand 1 pack $w.list.l -side left -fill both -expand 1
pack $w.list -fill both -expand 1 -pady 5 -padx 5 pack $w.list -fill both -expand 1 -pady 5 -padx 5
@ -232,7 +227,7 @@ constructor dialog {} {
} }
if {$local_cnt > 0} { if {$local_cnt > 0} {
label $w.colorlbl -foreground blue \ ${NS}::label $w.colorlbl -foreground blue \
-text [mc "(Blue denotes repository-local tools)"] -text [mc "(Blue denotes repository-local tools)"]
pack $w.colorlbl -fill x -pady 5 -padx 5 pack $w.colorlbl -fill x -pady 5 -padx 5
} }
@ -277,14 +272,14 @@ field is_ok 0; # ok to start
field argstr {}; # arguments field argstr {}; # arguments
constructor dialog {fullname} { constructor dialog {fullname} {
global M1B global M1B use_ttk NS
set title [get_config "guitool.$fullname.title"] set title [get_config "guitool.$fullname.title"]
if {$title eq {}} { if {$title eq {}} {
regsub {/} $fullname { / } title regsub {/} $fullname { / } title
} }
make_toplevel top w -autodelete 0 make_dialog top w -autodelete 0
wm title $top [append "[appname] ([reponame]): " $title] wm title $top [append "[appname] ([reponame]): " $title]
if {$top ne {.}} { if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]" wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
@ -297,7 +292,7 @@ constructor dialog {fullname} {
set prompt [mc "Run Command: %s" $command] set prompt [mc "Run Command: %s" $command]
} }
label $w.header -text $prompt -font font_uibold ${NS}::label $w.header -text $prompt -font font_uibold -anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
set argprompt [get_config "guitool.$fullname.argprompt"] set argprompt [get_config "guitool.$fullname.argprompt"]
@ -311,12 +306,10 @@ constructor dialog {fullname} {
set argprompt [mc "Arguments"] set argprompt [mc "Arguments"]
} }
labelframe $w.arg -text $argprompt ${NS}::labelframe $w.arg -text $argprompt
set w_args $w.arg.txt set w_args $w.arg.txt
entry $w_args \ ${NS}::entry $w_args \
-borderwidth 1 \
-relief sunken \
-width 40 \ -width 40 \
-textvariable @argstr -textvariable @argstr
pack $w_args -padx 5 -pady 5 -fill both pack $w_args -padx 5 -pady 5 -fill both
@ -337,18 +330,18 @@ constructor dialog {fullname} {
pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5 pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5
} }
frame $w.buttons ${NS}::frame $w.buttons
if {$is_ask_revs} { if {$is_ask_revs} {
button $w.buttons.visualize \ ${NS}::button $w.buttons.visualize \
-text [mc Visualize] \ -text [mc Visualize] \
-command [cb _visualize] -command [cb _visualize]
pack $w.buttons.visualize -side left pack $w.buttons.visualize -side left
} }
button $w.buttons.ok \ ${NS}::button $w.buttons.ok \
-text [mc OK] \ -text [mc OK] \
-command [cb _start] -command [cb _start]
pack $w.buttons.ok -side right pack $w.buttons.ok -side right
button $w.buttons.cancel \ ${NS}::button $w.buttons.cancel \
-text [mc "Cancel"] \ -text [mc "Cancel"] \
-command [cb _cancel] -command [cb _cancel]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5

View File

@ -20,6 +20,35 @@ proc prune_from {remote} {
console::exec $w [list git remote prune $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} { proc push_to {remote} {
set w [console::new \ set w [console::new \
[mc "push %s" $remote] \ [mc "push %s" $remote] \
@ -91,50 +120,58 @@ trace add variable push_remote write \
proc do_push_anywhere {} { proc do_push_anywhere {} {
global all_remotes current_branch global all_remotes current_branch
global push_urltype push_remote push_url push_thin push_tags global push_urltype push_remote push_url push_thin push_tags
global push_force global push_force use_ttk NS
set w .push_setup set w .push_setup
toplevel $w toplevel $w
wm withdraw $w
wm geometry $w "+[winfo rootx .]+[winfo rooty .]" wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
pave_toplevel $w
label $w.header -text [mc "Push Branches"] -font font_uibold ${NS}::label $w.header -text [mc "Push Branches"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x pack $w.header -side top -fill x
frame $w.buttons ${NS}::frame $w.buttons
button $w.buttons.create -text [mc Push] \ ${NS}::button $w.buttons.create -text [mc Push] \
-default active \ -default active \
-command [list start_push_anywhere_action $w] -command [list start_push_anywhere_action $w]
pack $w.buttons.create -side right pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc "Cancel"] \ ${NS}::button $w.buttons.cancel -text [mc "Cancel"] \
-default normal \ -default normal \
-command [list destroy $w] -command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5 pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.source -text [mc "Source Branches"] ${NS}::labelframe $w.source -text [mc "Source Branches"]
listbox $w.source.l \ slistbox $w.source.l \
-height 10 \ -height 10 \
-width 70 \ -width 70 \
-selectmode extended \ -selectmode extended
-yscrollcommand [list $w.source.sby set]
foreach h [load_all_heads] { foreach h [load_all_heads] {
$w.source.l insert end $h $w.source.l insert end $h
if {$h eq $current_branch} { if {$h eq $current_branch} {
$w.source.l select set end $w.source.l select set end
$w.source.l yview end
} }
} }
scrollbar $w.source.sby -command [list $w.source.l yview]
pack $w.source.sby -side right -fill y
pack $w.source.l -side left -fill both -expand 1 pack $w.source.l -side left -fill both -expand 1
pack $w.source -fill both -expand 1 -pady 5 -padx 5 pack $w.source -fill both -expand 1 -pady 5 -padx 5
labelframe $w.dest -text [mc "Destination Repository"] ${NS}::labelframe $w.dest -text [mc "Destination Repository"]
if {$all_remotes ne {}} { if {$all_remotes ne {}} {
radiobutton $w.dest.remote_r \ ${NS}::radiobutton $w.dest.remote_r \
-text [mc "Remote:"] \ -text [mc "Remote:"] \
-value remote \ -value remote \
-variable push_urltype -variable push_urltype
if {$use_ttk} {
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 eval tk_optionMenu $w.dest.remote_m push_remote $all_remotes
}
grid $w.dest.remote_r $w.dest.remote_m -sticky w grid $w.dest.remote_r $w.dest.remote_m -sticky w
if {[lsearch -sorted -exact $all_remotes origin] != -1} { if {[lsearch -sorted -exact $all_remotes origin] != -1} {
set push_remote origin set push_remote origin
@ -145,13 +182,11 @@ proc do_push_anywhere {} {
} else { } else {
set push_urltype url set push_urltype url
} }
radiobutton $w.dest.url_r \ ${NS}::radiobutton $w.dest.url_r \
-text [mc "Arbitrary Location:"] \ -text [mc "Arbitrary Location:"] \
-value url \ -value url \
-variable push_urltype -variable push_urltype
entry $w.dest.url_t \ ${NS}::entry $w.dest.url_t \
-borderwidth 1 \
-relief sunken \
-width 50 \ -width 50 \
-textvariable push_url \ -textvariable push_url \
-validate key \ -validate key \
@ -166,16 +201,16 @@ proc do_push_anywhere {} {
grid columnconfigure $w.dest 1 -weight 1 grid columnconfigure $w.dest 1 -weight 1
pack $w.dest -anchor nw -fill x -pady 5 -padx 5 pack $w.dest -anchor nw -fill x -pady 5 -padx 5
labelframe $w.options -text [mc "Transfer Options"] ${NS}::labelframe $w.options -text [mc "Transfer Options"]
checkbutton $w.options.force \ ${NS}::checkbutton $w.options.force \
-text [mc "Force overwrite existing branch (may discard changes)"] \ -text [mc "Force overwrite existing branch (may discard changes)"] \
-variable push_force -variable push_force
grid $w.options.force -columnspan 2 -sticky w grid $w.options.force -columnspan 2 -sticky w
checkbutton $w.options.thin \ ${NS}::checkbutton $w.options.thin \
-text [mc "Use thin pack (for slow network connections)"] \ -text [mc "Use thin pack (for slow network connections)"] \
-variable push_thin -variable push_thin
grid $w.options.thin -columnspan 2 -sticky w grid $w.options.thin -columnspan 2 -sticky w
checkbutton $w.options.tags \ ${NS}::checkbutton $w.options.tags \
-text [mc "Include tags"] \ -text [mc "Include tags"] \
-variable push_tags -variable push_tags
grid $w.options.tags -columnspan 2 -sticky w grid $w.options.tags -columnspan 2 -sticky w
@ -191,5 +226,6 @@ proc do_push_anywhere {} {
bind $w <Key-Escape> "destroy $w" bind $w <Key-Escape> "destroy $w"
bind $w <Key-Return> [list start_push_anywhere_action $w] bind $w <Key-Return> [list start_push_anywhere_action $w]
wm title $w [append "[appname] ([reponame]): " [mc "Push"]] wm title $w [append "[appname] ([reponame]): " [mc "Push"]]
wm deiconify $w
tkwait window $w tkwait window $w
} }

View File

@ -18,9 +18,9 @@ proc win32_create_lnk {lnk_path lnk_exec lnk_dir} {
eval [list exec wscript.exe \ eval [list exec wscript.exe \
/E:jscript \ /E:jscript \
/nologo \ /nologo \
[file join $oguilib win32_shortcut.js] \ [file nativename [file join $oguilib win32_shortcut.js]] \
$lnk_path \ $lnk_path \
[file join $oguilib git-gui.ico] \ [file nativename [file join $oguilib git-gui.ico]] \
$lnk_dir \ $lnk_dir \
$lnk_exec] $lnk_args $lnk_exec] $lnk_args
} }

View File

@ -18,28 +18,23 @@ specialized so-called "po file editors" (e.g. emacs po-mode, KBabel,
poedit, GTranslator --- any of them would work well). Please install poedit, GTranslator --- any of them would work well). Please install
them. them.
You would then need to clone the git-gui internationalization project You would then need to clone the git-gui project repository and create
repository, so that you can work on it: a feature branch to begin working:
$ git clone mob@repo.or.cz:/srv/git/git-gui/git-gui-i18n.git/ $ git clone git://repo.or.cz/git-gui.git
$ cd git-gui-i18n $ cd git-gui.git
$ git checkout --track -b mob origin/mob $ git checkout -b my-translation
$ git config remote.origin.push mob
The "git checkout" command creates a 'mob' branch from upstream's The "git checkout" command creates a new branch to keep your work
corresponding branch and makes it your current branch. You will be isolated and to make it simple to post your patch series when
working on this branch. completed. You will be working on this branch.
The "git config" command records in your repository configuration file
that you would push "mob" branch to the upstream when you say "git
push".
2. Starting a new language. 2. Starting a new language.
In the git-gui-i18n directory is a po/ subdirectory. It has a In the git-gui directory is a po/ subdirectory. It has a handful of
handful files whose names end with ".po". Is there a file that has files whose names end with ".po". Is there a file that has messages
messages in your language? in your language?
If you do not know what your language should be named, you need to find If you do not know what your language should be named, you need to find
it. This currently follows ISO 639-1 two letter codes: it. This currently follows ISO 639-1 two letter codes:
@ -149,15 +144,18 @@ There is a trick to test your translation without first installing:
$ make $ make
$ LANG=af ./git-gui.sh $ LANG=af ./git-gui.sh
When you are satisfied with your translation, commit your changes, and When you are satisfied with your translation, commit your changes then submit
push it back to the 'mob' branch: your patch series to the maintainer and the Git mailing list:
$ edit po/af.po $ edit po/af.po
... be sure to update Last-Translator: and ... be sure to update Last-Translator: and
... PO-Revision-Date: lines. ... PO-Revision-Date: lines.
$ git add po/af.po $ git add po/af.po
$ git commit -m 'Started Afrikaans translation.' $ git commit -s -m 'git-gui: added Afrikaans translation.'
$ git push $ git send-email --to 'git@vger.kernel.org' \
--cc 'Pat Thoyts <patthoyts@users.sourceforge.net>' \
--subject 'git-gui: Afrikaans translation' \
master..
3. Updating your translation. 3. Updating your translation.
@ -169,6 +167,7 @@ itself was updated and there are new messages that need translation.
In any case, make sure you are up-to-date before starting your work: In any case, make sure you are up-to-date before starting your work:
$ git checkout master
$ git pull $ git pull
In the former case, you will edit po/af.po (again, replace "af" with In the former case, you will edit po/af.po (again, replace "af" with

836
po/de.po

File diff suppressed because it is too large Load Diff

2005
po/el.po Normal file

File diff suppressed because it is too large Load Diff

872
po/fr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

171
po/glossary/el.po Normal file
View File

@ -0,0 +1,171 @@
# Translation of git-gui glossary to Greek
# Copyright (C) 2009 Jimmy Angelakos
# This file is distributed under the same license as the git-gui package.
# Jimmy Angelakos <vyruss@hellug.gr>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: git-gui-glossary\n"
"POT-Creation-Date: 2008-01-07 21:20+0100\n"
"PO-Revision-Date: 2009-06-23 20:41+0300\n"
"Last-Translator: Jimmy Angelakos <vyruss@hellug.gr>\n"
"Language-Team: Greek <i18n@lists.hellug.gr>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Lokalize 0.3\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)"
msgid "English Term (Dear translator: This file will never be visible to the user!)"
msgstr ""
#. ""
msgid "amend"
msgstr "διόρθωση"
#. ""
msgid "annotate"
msgstr "σχολιασμός"
#. "A 'branch' is an active line of development."
msgid "branch [noun]"
msgstr "κλάδος [αντικείμενο]"
#. ""
msgid "branch [verb]"
msgstr "διακλάδωση [ενέργεια]"
#. ""
msgid "checkout [noun]"
msgstr "εξαγωγή [αντικείμενο]"
#. "The action of updating the working tree to a revision which was stored in the object database."
msgid "checkout [verb]"
msgstr "εξαγωγή [ενέργεια]"
#. ""
msgid "clone [verb]"
msgstr "κλωνοποίηση [ενέργεια]"
#. "A single point in the git history."
msgid "commit [noun]"
msgstr "υποβολή [αντικείμενο] "
#. "The action of storing a new snapshot of the project's state in the git history."
msgid "commit [verb]"
msgstr "υποβολή [ενέργεια]"
#. ""
msgid "diff [noun]"
msgstr "διαφορά [αντικείμενο] "
#. ""
msgid "diff [verb]"
msgstr "διαφορά [ενέργεια]"
#. "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 "συγχώνευση επιτάχυνσης"
#. "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 "ανάκτηση"
#. "One context of consecutive lines in a whole patch, which consists of many such hunks"
msgid "hunk"
msgstr "κομμάτι"
#. "A collection of files. The index is a stored version of your working tree."
msgid "index (in git-gui: staging area)"
msgstr "ευρετήριο (στο git-gui: περιοχή σταδιοποίησης)"
#. "A successful merge results in the creation of a new commit representing the result of the merge."
msgid "merge [noun]"
msgstr "συγχώνευση [αντικείμενο]"
#. "To bring the contents of another branch into the current branch."
msgid "merge [verb]"
msgstr "συγχώνευση [ενέργεια]"
#. ""
msgid "message"
msgstr "μήνυμα"
#. "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 "κλάδεμα"
#. "Pulling a branch means to fetch it and merge it."
msgid "pull"
msgstr "λήψη"
#. "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 "ώθηση"
#. ""
msgid "redo"
msgstr "ξανά"
#. "An other repository ('remote'). One might have a set of remotes whose branches one tracks."
msgid "remote"
msgstr "απομακρυσμένο"
#. "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 "αποθετήριο"
#. ""
msgid "reset"
msgstr "επαναφορά"
#. ""
msgid "revert"
msgstr "αναίρεση"
#. "A particular state of files and directories which was stored in the object database."
msgid "revision"
msgstr "αναθεώρηση"
#. ""
#, fuzzy
msgid "sign off"
msgstr "αποσύνδεση"
#. ""
msgid "staging area"
msgstr "περιοχή σταδιοποίησης"
#. ""
msgid "status"
msgstr "κατάσταση"
#. "A ref pointing to a tag or commit object"
msgid "tag [noun]"
msgstr "ετικέτα [αντικείμενο]"
#. ""
msgid "tag [verb]"
msgstr "ετικέτα [ενέργεια]"
#. "A regular git branch that is used to follow changes from another repository."
msgid "tracking branch"
msgstr "κλάδος παρακολούθησης"
#. ""
msgid "undo"
msgstr "αναίρεση"
#. ""
msgid "update"
msgstr "ενημέρωση"
#. ""
msgid "verify"
msgstr "επαλήθευση"
#. "The tree of actual checked out files."
msgid "working copy, working tree"
msgstr "αντίγραφο εργασίας"

169
po/glossary/pt_br.po Normal file
View File

@ -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"

View File

@ -776,16 +776,6 @@ msgstr "Mindig (Ne legyen merge teszt.)"
msgid "The following branches are not completely merged into %s:" msgid "The following branches are not completely merged into %s:"
msgstr "A következő branchek nem teljesen lettek merge-ölve ebbe: %s:" msgstr "A következő branchek nem teljesen lettek merge-ölve ebbe: %s:"
#: lib/branch_delete.tcl:115
msgid ""
"Recovering deleted branches is difficult. \n"
"\n"
" Delete the selected branches?"
msgstr ""
"A törölt branchek visszaállítása bonyolult. \n"
"\n"
" Biztosan törli a kiválasztott brancheket?"
#: lib/branch_delete.tcl:141 #: lib/branch_delete.tcl:141
#, tcl-format #, tcl-format
msgid "" msgid ""
@ -2399,7 +2389,7 @@ msgstr "Futtatás: %s..."
#: lib/tools.tcl:149 #: lib/tools.tcl:149
#, tcl-format #, tcl-format
msgid "Tool completed succesfully: %s" msgid "Tool completed successfully: %s"
msgstr "Az eszköz sikeresen befejeződött: %s" msgstr "Az eszköz sikeresen befejeződött: %s"
#: lib/tools.tcl:151 #: lib/tools.tcl:151

632
po/it.po

File diff suppressed because it is too large Load Diff

663
po/ja.po

File diff suppressed because it is too large Load Diff

View File

@ -761,16 +761,6 @@ msgstr "Alltid (Ikke utfør sammenslåingstest.)"
msgid "The following branches are not completely merged into %s:" msgid "The following branches are not completely merged into %s:"
msgstr "Følgende grener er ikke fullstendig slått sammen med %s:" msgstr "Følgende grener er ikke fullstendig slått sammen med %s:"
#: lib/branch_delete.tcl:115
msgid ""
"Recovering deleted branches is difficult. \n"
"\n"
" Delete the selected branches?"
msgstr ""
"Gjenoppretting av fjernede grener er vanskelig. \n"
"\n"
" Fjern valgte grener?"
#: lib/branch_delete.tcl:141 #: lib/branch_delete.tcl:141
#, tcl-format #, tcl-format
msgid "" msgid ""
@ -2331,7 +2321,7 @@ msgstr "Kjører: %s"
#: lib/tools.tcl:149 #: lib/tools.tcl:149
#, tcl-format #, tcl-format
msgid "Tool completed succesfully: %s" msgid "Tool completed successfully: %s"
msgstr "Verktøyet ble fullført med suksess: %s" msgstr "Verktøyet ble fullført med suksess: %s"
#: lib/tools.tcl:151 #: lib/tools.tcl:151

2568
po/pt_br.po Normal file

File diff suppressed because it is too large Load Diff

1537
po/ru.po

File diff suppressed because it is too large Load Diff

1356
po/sv.po

File diff suppressed because it is too large Load Diff

View File

@ -676,16 +676,6 @@ msgstr "总是合并 (不作合并测试.)"
msgid "The following branches are not completely merged into %s:" msgid "The following branches are not completely merged into %s:"
msgstr "下列分支没有完全被合并到 %s:" msgstr "下列分支没有完全被合并到 %s:"
#: lib/branch_delete.tcl:115
msgid ""
"Recovering deleted branches is difficult. \n"
"\n"
" Delete the selected branches?"
msgstr ""
"恢复被删除的分支非常困难.\n"
"\n"
"是否要删除所选分支?"
#: lib/branch_delete.tcl:141 #: lib/branch_delete.tcl:141
#, tcl-format #, tcl-format
msgid "" msgid ""

View File

@ -3,15 +3,21 @@
exec wish "$0" -- "$@" exec wish "$0" -- "$@"
if { $argc >=2 && [lindex $argv 0] == "--working-dir" } { if { $argc >=2 && [lindex $argv 0] == "--working-dir" } {
cd [lindex $argv 1] set workdir [lindex $argv 1]
cd $workdir
if {[lindex [file split $workdir] end] eq {.git}} {
# Workaround for Explorer right click "Git GUI Here" on .git/
cd ..
}
set argv [lrange $argv 2 end] set argv [lrange $argv 2 end]
incr argc -2 incr argc -2
} }
set bindir [file dirname \ set basedir [file dirname \
[file dirname \ [file dirname \
[file dirname [info script]]]] [file dirname [info script]]]]
set bindir [file join $bindir bin] set bindir [file join $basedir bin]
set bindir "$bindir;[file join $basedir mingw bin]"
regsub -all ";" $bindir "\\;" bindir regsub -all ";" $bindir "\\;" bindir
set env(PATH) "$bindir;$env(PATH)" set env(PATH) "$bindir;$env(PATH)"
unset bindir unset bindir