Compare commits

...

87 Commits

Author SHA1 Message Date
1c1fe1005c git-gui 0.11
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-08-10 00:02:08 -07:00
9534c9fb31 git-gui: Adapt discovery of oguilib to execdir 'libexec/git-core'
The new execdir is two levels below the root directory, while
the old execdir 'bin' was only one level below.  This commit
adapts the discovery of oguilib that uses relative paths
accordingly. We determine whether we have the extra level in the same
way in which the Makefile defines sharedir, i.e. whether the last
directory part is 'git-core'.

Inspired-by: Steffen Prohaska <prohaska@zib.de>
Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-08-04 17:38:17 -07:00
fbbdaa5f42 git-gui: add a part about format strings in po/README
This should help tranlators that need to reorder words and strings.
Original explanation by Christian Stimming.

Also remove unneeded backslashes.

Signed-off-by: Michele Ballabio <barra_cuda@katamail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-08-03 13:53:42 -07:00
7cce5b2cbc git-gui: update po/it.po
Signed-off-by: Michele Ballabio <barra_cuda@katamail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-08-03 13:51:26 -07:00
6b312253cb git-gui: update Japanese translation
This updates Japanese translation to match the updated git-gui.pot.

Signed-off-by: しらいしななこ <nanako3@lavabit.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-08-03 13:49:53 -07:00
d049f6c27a git-gui: Update swedish translation.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-08-02 16:53:15 -07:00
1be7bf6e33 git-gui: Update git-gui.pot for 0.11 nearing release
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-08-02 14:48:33 -07:00
1e5ed425f3 git-gui: Update German translation
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-08-02 14:09:41 -07:00
5fc6edab76 git-gui (Windows): Change wrapper to execdir 'libexec/git-core'
git-gui needs bindir in PATH to be able to run 'git'.  bindir
however is not necessarily in PATH if started directly through a
Windows shortcut.  Therefore, we used to add the directory
git-gui is located in.  But with the new 'libexec/git-core'
layout this directory is no longer identical to bindir.

This commit modifies the wrapper script to discover the bindir
and add it to PATH.

Signed-off-by: Steffen Prohaska <prohaska@zib.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-29 22:43:37 -07:00
f57ddcc5ec git-gui (Windows): Switch to relative discovery of oguilib
Instead of using an absolute path, git-gui can discover its
gui library using a relative path from execdir.  We want to
use the relative path discovery on MinGW to avoid issues
with translation of absolute paths.

Signed-off-by: Steffen Prohaska <prohaska@zib.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-29 22:43:37 -07:00
f8f1acf339 git-gui: Correct installation of library to be $prefix/share
We always wanted the library for git-gui to install into the
$prefix/share directory, not $prefix/libexec/share.  All of
the files in our library are platform independent and may
be reused across systems, like any other content stored in
the share directory.

Our computation of where our library should install to was broken
when git itself started installing to $prefix/libexec/git-core,
which was one level down from where we expected it to be.

Signed-off-by: Steffen Prohaska <prohaska@zib.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-29 22:43:37 -07:00
79317e5df1 git-gui: Fix gitk search in $PATH to work on Windows
Back in 15430be5a1 ("Look for gitk in $PATH, not $LIBEXEC/git-core")
git-gui learned to use [_which gitk] to locate where gitk's script
is as Git 1.6 will install gitk to $prefix/bin (in $PATH) and all
of the other tools are in $gitexecdir.

This failed on Windows because _which adds the ".exe" suffix as it
searches for the program on $PATH, under the assumption that we can
only execute something from Tcl if it is a proper Windows executable.

When scanning for gitk on Windows we need to omit the ".exe" suffix.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-29 22:41:23 -07:00
25b8fb1e49 git-gui: Preserve scroll position on reshow_diff.
It is especially useful for Stage/Unstage Line, because
they invoke full state scan and diff reload, which originally
would reset the scroll position to the top of the file.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-27 08:08:10 -07:00
7e09b1531f git-gui: Fix the Remote menu separator.
It was positioned incorrectly (offset by one position)
if the menu had a tear-off handle.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-27 08:08:09 -07:00
c7f7457026 git-gui: "Stage Line": Treat independent changes in adjacent lines better
Assume that we want to commit these states:

  Old state == HEAD    Intermediate state   New state
  --------------------------------------------------------
  context before       context before       context before
  old 1                new 1                new 1
  old 2                old 2                new 2
  context after        context after        context after

that is, want to commit two changes in this order:

  1. transform "old 1" into "new 1"
  2. transform "old 2" into "new 2"

[This discussion and this patch is about this very case and one other case
as outlined below; any other intermediate states that one could imagine are
not affected by this patch.]

Now assume further, that we have not staged and commited anything, but we
have already changed the working file to the new state. Then we will see
this hunk in the "Unstaged Changes":

  @@ -1,4 +1,4 @@
   context before
  -old 1
  -old 2
  +new 1
  +new 2
   context after

The obvious way to stage the intermediate state is to apply "Stage This
Line" to "-old 1" and "+new 1". Unfortunately, this resulted in this
intermediate state:

  context before
  old 2
  new 1
  context after

which is not what we wanted. In fact, it was impossible to stage the
intermediate state using "Stage Line". The crux was that if a "+" line was
staged, then the "-" lines were converted to context lines and arranged
*before* the "+" line in the forged hunk that we fed to 'git apply'.

With this patch we now treat "+" lines that are staged differently. In
particular, the "-" lines before the "+" block are moved *after* the
staged "+" line. Now it is possible to get the correct intermediate state
by staging "-old 1" and "+new 1". Problem solved.

But there is a catch.

Noticing that we didn't get the right intermediate state by staging
"-old 1" and "+new 1", we could have had the idea to stage the complete
hunk and to *unstage* "-old 2" and "+new 2". But... the result is the same.
The reason is that there is the exact symmetric problem with unstaging the
last "-" and "+" line that are in adjacent blocks of "-" and "+" lines.

This patch does *not* change the way in which "-" lines are *unstaged*.

Why? Because if we did (i.e. move "+" lines before the "-" line after
converting them to context lines), then it would be impossible to stage
this intermediate state:

  context before
  old 1
  new 2
  context after

that is, it would be impossible to stage the two independet changes in the
opposite order.

Let's look at this case a bit further: The obvious way to get this
intermediate state would be to apply "Stage This Line" to "-old 2" and
"+new 2". Before this patch, this worked as expected. With this patch, it
does not work as expected, but it can still be achieved by first staging
the entire hunk, then *unstaging* "-old 1" and "+new 1".

In summary, this patch makes a common case possible, at the expense that
a less common case is made more complicated for the user.

Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-26 16:43:08 -07:00
fa6b5b3944 git-gui: Fix "Stage/Unstage Line" with one line of context.
To "Stage/Unstage Line" we construct a patch that contains exactly one
change (either addition or removal); the hunk header was forged by counting
the old side and adjusting the count by +/-1 for the new side. But when we
counted the context we never counted the changed line itself. If the hunk
had only one removal line and one line of context, like this:

    @@ -1,3 +1,2 @@
     context 1
    -removal
     context 2

We had constructed this patch:

    @@ -1,2 +1,1 @@
     context 1
    -removal
     context 2

which does not apply because git apply deduces that it must apply at the
end of the file. ("context 2" is considered garbage and ignored.) The fix
is that removal lines must be counted towards the context of the old side.

Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-26 16:43:08 -07:00
7838d3fb41 git-gui: Correct 'Visualize Branches' on Mac OS X to start gitk
In Git 1.6 and later gitk is in $prefix/bin while git-gui and all
of the other commands are in $gitexecdir, which is typically not
the same as $prefix/bin.  So we cannot launch $gitexecdir/gitk and
expect it to actually start gitk properly.

By allowing git-gui to locate the script via $PATH and then using
exactly that path when we source it during the application start
we can correctly run gitk on any Git 1.5 or later.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-25 15:08:33 -07:00
15430be5a1 git-gui: Look for gitk in $PATH, not $LIBEXEC/git-core
Signed-off-by: Abhijit Menon-Sen <ams@toroid.org>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-25 14:58:31 -07:00
a01fe996a2 Add a menu item to invoke full copy detection in blame.
Add a context menu item to invoke blame -C -C -C on a chunk
of the file. The results are used to update the 'original
location' column of the blame display.

The chunk is computed as the smallest line range that covers
both the 'last change' and 'original location' ranges of the
line that was clicked to open the menu.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-16 22:09:28 -04:00
e6131d30c2 Kill the blame back-end on window close.
Currently 'git-gui blame' does not kill its back-end
process, hoping that it will die anyway when the pipe
is closed. However, in some cases the process works
for a long time without producing any output. This
behavior results in a runaway CPU hog.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-16 22:09:28 -04:00
57cae87b77 Add options to control the search for copies in blame.
On huge repositories, -C -C can be way too slow to be
unconditionally enabled, and it can also be useful to control
its precision.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-16 22:09:28 -04:00
fbc0e7ac14 Fix pre-commit hooks under MinGW/MSYS
Apply the work-around for checking the executable
permission of hook files not only on Cygwin, but on
Windows in general.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-16 21:17:27 -04:00
f049e0944d git-gui: MERGE_RR lives in .git/ directly with newer Git versions
Now that MERGE_RR was moved out of .git/rr-cache/, we have to delete
it somewhere else.  Just in case somebody wants to use a newer git-gui
with an older Git, the file .git/rr-cache/MERGE_RR is removed, too (if
it exists).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-13 17:58:40 -04:00
af894943cb git-gui: Exit shortcut in MacOSX repaired
Now, as in all OSX apps, there is only one quit menu entry.
It's automatically in the wish menu and calls ::tk::mac::Quit when used.

Signed-off-by: Soeren Finster <sf@9by6.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-08 00:51:04 -04:00
5821988f97 git-gui: Implement "Stage/Unstage Line"
This adds a context menu entry below "Stage/Unstage Hunk" that stages or
unstages just the line under the mouse pointer.

This is by itself useful, for example, if there are unrelated changes in
the same hunk and the hunk cannot be split by reducing the context.

The feature can also be used to split a hunk by staging a number of
additions (or unstaging a number of removals) until there are enough
context lines that the hunk gets split.

The implementation reads the complete hunk that the line lives in, and
constructs a new hunk by picking existing context lines, removing unneeded
change lines and transforming other change lines to context lines. The
resulting hunk is fed through 'git apply' just like in the "Stage/Unstage
Hunk" case.

Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-02 01:06:38 -04:00
f531e463f0 git-gui: Don't select the wrong file if the last listed file is staged.
Johannes Sixt noticed that if the last file in the list was staged, my
earlier patch would display the diff for the penultimate file, but show
the file _before_ that as being selected.

This was due to my misunderstanding the lno argument to show_diff.

This patch fixes the problem: lno is not decremented in the special case
to handle the last item in the list (though we still need to use $lno-1
to find the right path for the next diff).

Signed-off-by: Abhijit Menon-Sen <ams@toroid.org>
Tested-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-06-25 16:55:10 -04:00
cead78edef git-gui: Fix accidental staged state toggle when clicking top pixel row
If a text widget is asked the index at x,y with y == 0 or y == 1 it will
always return 1.0 as the nearest index, regardless of the x position.

This means that clicking the top 2 pixels of the Unstaged/Staged Changes
lists caused the state of the file there to be toggled. This patch
checks that the pixel clicked is greater than 1, so there is less chance
of accidentally staging or unstaging changes.

Signed-off-by: Richard Quirk <richard.quirk@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-06-20 23:19:52 -04:00
8a965b8ee2 git-gui: Move on to the next filename after staging/unstaging a change
Suppose the "Unstaged Changes" pane contains a list of files, and one of
them is selected (i.e., that diff is currently being displayed). If one
clicks on the icon to stage the change, git-gui clears the diff and one
has to click on another filename to see the next diff in the list.

This patch changes that behaviour. If one clicks on the icon to stage
(or unstage) the file whose diff is being displayed, git-gui will move
on to the next filename in the list and display that diff instead of a
blank diff pane. If the selected file was at the end of the list, the
diff pane will display the previous diff instead; if the selected file
was the only one listed, the diff pane will become blank.

If no diff is currently being displayed, this patch changes nothing.

Signed-off-by: Abhijit Menon-Sen <ams@toroid.org>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-06-13 17:58:00 -04:00
95dcfa3633 git-gui: Vertically align textboxes with labels
In git-gui after clicking either on 'Create New Repository' or
'Open Existing Repository' the form elements aren't centered like
they are pretty much everywhere else in the app. At least when ran
on a mac, haven't checked on other platforms.

Using grid instead of pack seems to fix this.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-05-26 21:05:20 -04:00
7f83aa2d3d git-gui: Handle workdir detection when CYGWIN=nowinsymlinks
If the user has put nowinsymlinks into their CYGWIN environment
variable any symlinks created by a Cygwin process (e.g. ln -s)
will not have the ".lnk" suffix.  In this case workdir is still
a workdir, but our detection of looking for "info.lnk" fails
as the symlink is actually a normal file called "info".

Instead we just always use Cygwin's test executable to see if
info/exclude is a file.  If it is, we assume from there on it
can be read by git-ls-files --others and is thus safe to use
on the command line.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-05-22 08:34:00 -04:00
16dd62ac4d git-gui: Add a --trace command line option
Often new Git users want to know what commands git-gui uses to make
changes, so they can learn the command line interface by mimicking
what git-gui does in response to GUI actions.  Showing the direct
commands being executed is easy enough to implement but this is of
little value to end-users because git-gui frequently directly calls
plumbing, not porcelain.

Since the code is already written and tested, its fairly harmless
to include.  It may not help a new end-user, but it can help with
debugging git-gui or reverse-engineering its logic to further make
changes to it or implement another GUI for Git.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-05-20 15:44:46 -04:00
76bb40cde0 git-gui: Delete branches with 'git branch -D' to clear config
If we are deleting a local branch from refs/heads/ we need to
make sure any associated configuration stored in .git/config is
also removed (such as branch.$name.remote and branch.$name.merge).
The easiest way to do this is to use git-branch as that automatically
will look for and delete configuration keys as necessary.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-05-08 20:29:42 -04:00
fe70225dc7 git-gui: Setup branch.remote,merge for shorthand git-pull
When creating new branches if branch.autosetupmerge is not set, or
is set to true or always and we have been given a remote tracking
branch as the starting point for a new branch we want to create the
necessary configuration options in .git/config for the new branch
so that a no argument git-pull on the command line pulls from the
remote repository's branch.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-05-08 20:20:27 -04:00
259cd0fddb git-gui: Update German translation
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-05-01 18:13:14 -04:00
ca19404876 Merge branch 'maint'
* maint:
  git-gui: Don't use '$$cr master' with aspell earlier than 0.60
2008-04-23 21:38:30 -04:00
ddc3603145 git-gui: Don't use '$$cr master' with aspell earlier than 0.60
Apparently aspell 0.50 does not recognize "$$cr master" as a command,
but instead tries to offer suggestions for how to correctly spell
the word "cr".  This is not quite what we are after when we want
the name of the current dictionary.

Instead of locking up git-gui waiting for a response that may never
come back from aspell we avoid sending this command if the binary
we have started claims to be before version 0.60.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-04-23 21:34:58 -04:00
dd70f3dbe4 git-gui: Report less precise object estimates for database compression
On startup, git-gui warns if there are many loose objects. It does so by
saying, e.g., that there are "approximately 768 loose objects". But isn't
"768" a very accurate number? Lets say "750", which (while still being a
very precise number) sounds much more like an estimation.

Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-04-14 19:34:23 -04:00
729ffa50f7 git-gui: use +/- instead of ]/[ to show more/less context in diff
On some systems, brackets cannot be used as event details
(they don't have a keysym), so use +/- instead (both on
keyboard and keypad) and add ctrl-= as a synonym of ctrl-+
for convenience.

[sp: Had to change accelerator to show only "$M1T-="; the
     original version included "$M1T-+ $M1T-=" but this is
	 not drawn at all on Mac OS X.]

Signed-off-by: Michele Ballabio <barra_cuda@katamail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-04-05 00:03:19 -04:00
ccb3b537cc git-gui: Update french translation
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-04-04 23:53:50 -04:00
54906addfa git-gui: Switch keybindings for [ and ] to bracketleft and bracketright
Thanks to Michele Ballabio for the quick fix.
This resolves the error introduced by c91ee2bd61.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-04-03 21:38:12 -04:00
3d654be48f git-gui 0.10
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-04-02 02:17:11 -04:00
c91ee2bd61 git-gui: Add shortcut keys for Show More/Less Context
Bound to Ctrl/Cmd + left & right square brackets, depending on
your platform.

[sp: Added missing binds for . to allow shortcuts to work when
     not focused in the commit message area.]

Signed-off-by: Jonathan del Strother <jon.delStrother@bestbefore.tv>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-04-02 01:33:32 -04:00
739a6d4970 git-gui: Improve directions regarding POT update in po/README
Keeping POT up to date relative to the software is absolutely
necessary.  What is unwarranted is updating language files at
the same time by running msgmerge without checking if there is
any outstanding translation work first.  If we assume that the
translators do not have access to msgmerge, that is a good service
to them (the less they have to do, the better), but otherwise,
it is better to be leave po/${language}.po files alone.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-16 02:06:12 -04:00
477ef326a3 git-gui: Update Japanese translation
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-15 23:57:28 -04:00
02a8b27645 git-gui: Adjusted Japanese translation to updated POT
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-15 02:23:06 -04:00
45e53d17ee git-gui: Update Japanese translation
I updated Japanese translation for the latest git-gui.

Signed-off-by: しらいしななこ <nanako3@bluebottle.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-15 02:22:08 -04:00
442b3caaee git-gui: Don't translate the special Apple menu
Peter Karlsson pointed out there is no value in translating the
string "Apple", as this is used as the dummy label for the Apple
menu on Mac OS X systems.

The Apple menu is actually not the menu with the Apple corporate
logo, but the menu next to it, which shows the name of the
application and is typically called the application menu.  Most users
of git-gui see this menu titled as "Git Gui".  The actual label of
this menu comes from our Info.plist file and cannot be specified
by any other means.  Translating this string in the Tcl PO files
is not necessary.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-15 01:11:08 -04:00
427f48603e git-gui: Updated Hungarian translation (e5fba18)
Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-15 01:02:25 -04:00
b79f5ffc9b git-gui: update russian translation
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-15 01:00:57 -04:00
4f994937c8 git-gui: remove spurious "fuzzy" attributes in po/it.po
Signed-off-by: Michele Ballabio <barra_cuda@katamail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-15 01:00:09 -04:00
9065c36ea3 git-gui: updated Swedish translation
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-14 02:36:44 -04:00
0212242d66 git-gui: Regenerated po template and merged translations with it
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-14 02:36:18 -04:00
48ed49f2eb Update Hungarian translation. 100% completed. 2008-03-13 13:31:10 +01:00
0c87a951c2 git-gui: update Italian translation
Signed-off-by: Michele Ballabio <barra_cuda@katamail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-13 01:23:22 -04:00
7276607886 git-gui: Simplify MSGFMT setting in Makefile
To prepare msg files for Tcl scripts, the command that is set to MSGFMT
make variable needs to be able to grok "--tcl -l <lang> -d <here>" options
correctly.  This patch simplifies the tests done in git-gui's Makefile to
directly test this condition.  If the test run does not exit properly with
zero status (either because you do not have "msgfmt" itself, or your
"msgfmt" is too old to grok --tcl option --- the reason does not matter),
have it fall back to po/po2msg.sh

Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-12 01:48:32 -04:00
11027d544b git-gui: Add option for changing the width of the commit message text box
The width of the commit message text area is currently hard-coded
to 75 characters. This value might be not optimal for some projects.
For instance users who would like to generate GNU-style ChangeLog
file from git commit message might prefer commit messages of width
no longer than 70 characters.

This patch adds a global and per repository option "Commit Message
Text Width", which could be used to change the width of the commit
message text area.

Signed-off-by: Adam Piątyszek <ediap@users.sourceforge.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-07 20:59:35 -05:00
c382fdd795 git-gui: if a background colour is set, set foreground colour as well
In several places, only the background colour is set to an explicit
value, sometimes even "white".  This does not work well with dark
colour themes.

This patch tries to set the foreground colour to "black" in those
situations, where an explicit background colour is set without defining
any foreground colour.

Signed-off-by: Philipp A. Hartmann <ph@sorgh.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-05 23:47:11 -05:00
312fd92b06 git-gui: translate the remaining messages in zh_cn.po to chinese
'make' shows:
  MSGFMT po/zh_cn.msg 368 translated, 2 fuzzy, 1 untranslated message.

1. update the zh_cn.po and translate the remaining messages in chinese

2. correct some of the previously mis-translated messages

3. add a list of word interpretation in the head as a guideline for
   subsequent updatings and translations

Signed-off-by: eric miao <eric.miao@marvell.com>
Acked-by: Xudong Guan <xudong.guan@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-05 23:45:19 -05:00
f15b75855f Merge branch 'maint'
* maint:
  git-gui: Gracefully fall back to po2msg.sh if msgfmt --tcl fails
2008-03-05 02:13:37 -05:00
21623062ab git-gui: Gracefully fall back to po2msg.sh if msgfmt --tcl fails
Mac OS X Tiger may have a msgfmt available but it doesn't understand
how to implement --tcl.  Falling back to po2msg.sh on such systems
is a reasonable behavior.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-03-05 02:13:16 -05:00
f49b6c10b7 Merge branch 'maint'
* maint:
  git-gui: Paper bag fix info dialog when no files are staged at commit
2008-02-28 01:29:19 -05:00
094fbbf964 git-gui: Paper bag fix info dialog when no files are staged at commit
If the user tries to commit their changes without actually staging
anything we used to display an informational dialog suggesting they
first stage those changes, then retry the commit feature.

Unfortunately I broke this in aba15f7 ("Ensure error dialogs always
appear over all other windows") and failed to fix it in the paper
bag fix that came one day after it.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-28 01:28:45 -05:00
b5e2f805e6 Merge branch 'maint'
* maint:
  git-gui: Focus insertion point at end of strings in repository chooser
  git-gui: Avoid hardcoded Windows paths in Cygwin package files
  git-gui: Default TCL_PATH to same location as TCLTK_PATH
  git-gui: Paper bag fix error dialogs opening over the main window
2008-02-22 01:40:25 -05:00
3baee1f3bf git-gui: Focus insertion point at end of strings in repository chooser
When selecting a local working directory for a new repository or a
location to clone an existing repository into we now set the insert
point at the end of the selected path, allowing the user to type in
any additional parts of the path if they so desire.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-22 01:39:36 -05:00
df4ec4cf6f git-gui: Avoid hardcoded Windows paths in Cygwin package files
When we are being built by the Cygwin package maintainers we need to
embed the POSIX path to our library files and not the Windows path.
Embedding the Windows path means all end-users who install our Cygwin
package would be required to install Cygwin at the same Windows path
as the package maintainer had Cygwin installed to.  This requirement
is simply not user-friendly and may be infeasible for a large number
of our users.

We now try to auto-detect if the Tcl/Tk binary we will use at runtime
is capable of translating POSIX paths into Windows paths the same way
that cygpath does the translations.  If the Tcl/Tk binary gives us the
same results then it understands the Cygwin path translation process
and should be able to read our library files from a POSIX path name.

If it does not give us the same answer as cygpath then the Tcl/Tk
binary might actually be a native Win32 build (one that is not
linked against Cygwin) and thus requires the native Windows path
to our library files.  We can assume this is not a Cygwin package
as the Cygwin maintainers do not currently ship a pure Win32 build
of Tcl/Tk.

Reported on the git mailing list by Jurko Gospodnetić.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-22 01:38:32 -05:00
651fbba2d3 git-gui: Default TCL_PATH to same location as TCLTK_PATH
Most users set TCLTK_PATH to tell git-gui where to find wish, but they
fail to set TCL_PATH to the same Tcl installation.  We use the non-GUI
tclsh during builds so headless systems are still able to create an
index file and create message files without GNU msgfmt.  So it matters
to us that we find a working TCL_PATH at build time.

If TCL_PATH hasn't been set yet we can take a better guess about what
tclsh executable to use by replacing 'wish' in the executable path with
'tclsh'.  We only do this replacement on the filename part of the path,
just in case the string "wish" appears in the directory paths.  Most of
the time the tclsh will be installed alongside wish so this replacement
is a sensible and safe default.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-22 01:35:44 -05:00
85ec3e7778 git-gui: Paper bag fix error dialogs opening over the main window
If the main window is the only toplevel we have open then we
don't have a valid grab right now, so we need to assume the
best toplevel to use for the parent is ".".

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-22 01:35:23 -05:00
afdb4be0fc git-gui: fix typo in lib/spellcheck.tcl
Signed-off-by: Michele Ballabio <barra_cuda@katamail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-22 01:33:07 -05:00
bb760f0257 git-gui: Shorten Aspell version strings to just Aspell version number
We really only support Aspell, so showing the compatibility line from
ispell is of little value to end users.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-21 00:22:07 -05:00
827743b2e8 git-gui: Gracefully display non-aspell version errors to users
If the user has somehow managed to make us execute ispell instead
of aspell, even though our code is invoking aspell, and ispell is
not recognizing the aspell command line options we use to invoke
it then we don't want a giant usage message back from ispell.

Instead we show the ispell version number, letting the user know
we don't actually support that spell checker.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-21 00:22:07 -05:00
de83f8cc4c git-gui: Catch and display aspell startup failures to the user
If we feed a bad dictionary name to aspell on startup it may appear
to start (as Tcl found the executable in our $PATH) but it fails to
give us the version string.  In such a case the close of the pipe
will report the exit status of the process (failure) and that is
an error in Tcl.

We now trap the subprocess failure and display the stderr message
from it, letting the user know why the failure is happening.  We then
disable the spell checker, but keep our object instance so the user
can alter their preferred dictionary through the options dialog, and
possibly restart the spell checker.

I was also originally wrong to use "error" here for the display
of the problem to the user.  I meant to use "error_popup", which
will open a message box and show the failure in a GUI context,
rather than killing git-gui and showing the message on the console.

Noticed by Ilari on #git.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-21 00:22:06 -05:00
35d04b3b11 git-gui: Only bind the spellcheck popup suggestion hook once
If we reconnect to the spellchecker there is no reason to resetup
the binding for button 3 on our text widget to show the suggestion
list (if available).

Plus, by moving it out of _connect and into init we can now break
out of _connect earlier if there is something wrong with the pipe,
for example if the dictionary we were asked to load is not valid.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-21 00:22:06 -05:00
dd0962883b git-gui: Remove explicit references to 'aspell' in message strings
Users may or may not be using aspell here.  About the only thing
we are using that is aspell specific (and not supported by ispell
or an ispell variant) is some command line options when we start
up aspell, and a forced encoding of UTF-8.  Both of these can be
corrected and/or cleaned up by users through an aspell wrapper
script, or through further improvements to git-gui.  There is no
reason to require our translated strings to reference a specific
spell checker, especially if that spell checker implementation is
not very suitable for the language being translated.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-21 00:22:06 -05:00
f57ca1efe5 git-gui: Ensure all spellchecker 'class' variables are initialized
If we somehow managed to get our spellchecker instance created but
aspell wasn't startable we may not finish _connect and thus may
find one or more of our fields was not initialized in the instance.

If we have an instance but no version, there is no reason to show
a version to the user in our about dialog.  We effectively have no
spellchecker available.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-21 00:22:06 -05:00
f4d93486ae Merge branch 'maint'
* maint:
  git-gui: Ensure error dialogs always appear over all other windows
2008-02-21 00:21:54 -05:00
aba15f7f59 git-gui: Ensure error dialogs always appear over all other windows
If we are opening an error dialog we want it to appear above all of
the other windows, even those that we may have opened with a grab
to make the window modal.  Failure to do so may allow an error
dialog to open up (and grab focus!) under an existing toplevel,
making the user think git-gui has frozen up and is unresponsive,
as they cannot get to the dialog.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-20 23:39:32 -05:00
cec8f51bd6 Merge branch 'maint'
* maint:
  git-gui: relax "dirty" version detection
2008-02-20 00:40:13 -05:00
2c2a3782c5 git-gui: relax "dirty" version detection
"git gui" would complain at launch if the local version of Git was
"1.5.4.2.dirty". Loosen the regular expression to look for either
"-dirty" or ".dirty", thus eliminating spurious warnings.

Signed-off-by: Wincent Colaiuta <win@wincent.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-19 20:50:29 -05:00
c548f86273 git-gui: Update German translation.
Signed-off-by: Christian Stimming <stimming@tuhh.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-17 02:23:48 -05:00
b8331e1567 git-gui: (i18n) Add newly added translation strings to template.
And markup one missing string for translation.

Signed-off-by: Christian Stimming <stimming@tuhh.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-17 02:22:07 -05:00
740b9b9ff4 git-gui: Correct size of dictionary name widget in options dialog
We don't need to fill this entire horizontal cavity, it looks really
bad on some platforms to stretch the widget out to fill the window.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-14 01:07:39 -05:00
765239e9d2 git-gui: Paper bag fix bad string length call in spellchecker
We don't want the list length, we need the string length.

Found due to a bad " character discovered in the text and
Tcl throwing 'unmatched open quote in list'.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-14 01:05:04 -05:00
95b002eeb3 git-gui: Automatically spell check commit messages as the user types
Many user friendly tools like word processors, email editors and web
browsers allow users to spell check the message they are writing
as they type it, making it easy to identify a common misspelling
of a word and correct it on the fly.

We now open a bi-directional pipe to Aspell and feed the message
text the user is editing off to the program about once every 300
milliseconds.  This is frequent enough that the user sees the results
almost immediately, but is not so frequent as to cause significant
additional load on the system.  If the user has modified the message
text during the last 300 milliseconds we delay until the next period,
ensuring that we avoid flooding the Aspell process with a lot of
text while the user is actively typing their message.

We wait to send the current message buffer to Aspell until the user
is at a word boundary, thus ensuring that we are not likely to ask
for misspelled word detection on a word that the user is actively
typing, as most words are misspelled when only partially typed,
even if the user has thus far typed it correctly.

Misspelled words are highlighted in red and are given an underline,
causing the word to stand out from the others in the buffer.  This is
a very common user interface idiom for displaying misspelled words,
but differs from one platform to the next in slight variations.
For example the Mac OS X system prefers using a dashed red underline,
leaving the word in the original text color.  Unfortunately the
control that Tk gives us over text display is not powerful enough
to handle such formatting so we have to work with the least common
denominator.

The top suggestions for a misspelling are saved in an array and
offered to the user when they right-click (or on the Mac ctrl-click)
a misspelled word.  Selecting an entry from this menu will replace
the misspelling with the correction shown.  Replacement is integrated
with the undo/redo stack so undoing a replacement will restore the
misspelled original text.

If Aspell could not be started during git-gui launch we silently eat
the error and run without spell checking support.  This way users
who do not have Aspell in their $PATH can continue to use git-gui,
although they will not get the advanced spelling functionality.

If Aspell started successfully the version line and language are
shown in git-gui's about box, below the Tcl/Tk versions.  This way
the user can verify the Aspell function has been activated.

If Aspell crashes while we are running we inform the user with an
error dialog and then disable Aspell entirely for the rest of this
git-gui session.  This prevents us from fork-bombing the system
with Aspell instances that always crash when presented with the
current message text, should there be a bug in either Aspell or in
git-gui's output to it.

We escape all input lines with ^, as recommended by the Aspell manual
page, as this allows Aspell to properly ignore any input line that is
otherwise looking like a command (e.g. ! to enable terse output).  By
using this escape however we need to correct all word offsets by -1 as
Aspell is apparently considering the ^ escape to be part of the line's
character count, but our Tk text widget obviously does not.

Available dictionaries are offered in the Options dialog, allowing
the user to select the language they want to spellcheck commit
messages with for the current repository, as well as the global
user setting that all repositories inherit.

Special thanks to Adam Flott for suggesting connecting git-gui
to Aspell for the purpose of spell checking the commit message,
and to Wincent Colaiuta for the idea to wait for a word boundary
before passing the message over for checking.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-12 02:35:18 -05:00
88965d198f Merge branch 'maint'
* maint:
  git-gui: support Git Gui.app under OS X 10.5
2008-02-12 02:35:03 -05:00
20a87ecc58 git-gui: support Git Gui.app under OS X 10.5
The Tk Framework moved its location in 10.5 compared to 10.4

Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
Tested-by: Seth Falcon <seth@userprimary.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-12 02:34:45 -05:00
5f09a37bbb git-gui: Update German translation.
Signed-off-by: Christian Stimming <stimming@tuhh.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-03 21:27:20 -05:00
5e6d7768e1 git-gui: (i18n) Fix a bunch of still untranslated strings.
Signed-off-by: Christian Stimming <stimming@tuhh.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-02-03 21:25:29 -05:00
34 changed files with 5283 additions and 3170 deletions

View File

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

View File

@ -13,6 +13,7 @@ GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
SCRIPT_SH = git-gui.sh SCRIPT_SH = git-gui.sh
GITGUI_MAIN := git-gui GITGUI_MAIN := git-gui
@ -33,8 +34,12 @@ ifndef gitexecdir
endif endif
ifndef sharedir ifndef sharedir
ifeq (git-core,$(notdir $(gitexecdir)))
sharedir := $(dir $(patsubst %/,%,$(dir $(gitexecdir))))share
else
sharedir := $(dir $(gitexecdir))share sharedir := $(dir $(gitexecdir))share
endif endif
endif
ifndef INSTALL ifndef INSTALL
INSTALL = install INSTALL = install
@ -91,9 +96,20 @@ ifndef V
REMOVE_F1 = && echo ' ' REMOVE `basename "$$dst"` && $(RM_RF) "$$dst" REMOVE_F1 = && echo ' ' REMOVE `basename "$$dst"` && $(RM_RF) "$$dst"
endif endif
TCL_PATH ?= tclsh
TCLTK_PATH ?= wish TCLTK_PATH ?= wish
TKFRAMEWORK = /Library/Frameworks/Tk.framework/Resources/Wish.app ifeq (./,$(dir $(TCLTK_PATH)))
TCL_PATH ?= $(subst wish,tclsh,$(TCLTK_PATH))
else
TCL_PATH ?= $(dir $(TCLTK_PATH))$(notdir $(subst wish,tclsh,$(TCLTK_PATH)))
endif
ifeq ($(uname_S),Darwin)
TKFRAMEWORK = /Library/Frameworks/Tk.framework/Resources/Wish.app
ifeq ($(shell expr "$(uname_R)" : '9\.'),2)
TKFRAMEWORK = /System/Library/Frameworks/Tk.framework/Resources/Wish\ Shell.app
endif
TKEXECUTABLE = $(shell basename "$(TKFRAMEWORK)" .app)
endif
ifeq ($(findstring $(MAKEFLAGS),s),s) ifeq ($(findstring $(MAKEFLAGS),s),s)
QUIET_GEN = QUIET_GEN =
@ -119,7 +135,17 @@ GITGUI_MACOSXAPP :=
ifeq ($(uname_O),Cygwin) ifeq ($(uname_O),Cygwin)
GITGUI_SCRIPT := `cygpath --windows --absolute "$(GITGUI_SCRIPT)"` GITGUI_SCRIPT := `cygpath --windows --absolute "$(GITGUI_SCRIPT)"`
gg_libdir_sed_in := $(shell cygpath --windows --absolute "$(gg_libdir)")
# Is this a Cygwin Tcl/Tk binary? If so it knows how to do
# POSIX path translation just like cygpath does and we must
# keep libdir in POSIX format so Cygwin packages of git-gui
# work no matter where the user installs them.
#
ifeq ($(shell echo 'puts [file normalize /]' | '$(TCL_PATH_SQ)'),$(shell cygpath --mixed --absolute /))
gg_libdir_sed_in := $(gg_libdir)
else
gg_libdir_sed_in := $(shell cygpath --windows --absolute "$(gg_libdir)")
endif
else else
ifeq ($(exedir),$(gg_libdir)) ifeq ($(exedir),$(gg_libdir))
GITGUI_RELATIVE := 1 GITGUI_RELATIVE := 1
@ -134,6 +160,7 @@ endif
ifneq (,$(findstring MINGW,$(uname_S))) ifneq (,$(findstring MINGW,$(uname_S)))
NO_MSGFMT=1 NO_MSGFMT=1
GITGUI_WINDOWS_WRAPPER := YesPlease GITGUI_WINDOWS_WRAPPER := YesPlease
GITGUI_RELATIVE := 1
endif endif
ifdef GITGUI_MACOSXAPP ifdef GITGUI_MACOSXAPP
@ -147,7 +174,7 @@ git-gui: GIT-VERSION-FILE GIT-GUI-VARS
echo then >>$@+ && \ echo then >>$@+ && \
echo ' 'echo \'git-gui version '$(GITGUI_VERSION)'\' >>$@+ && \ echo ' 'echo \'git-gui version '$(GITGUI_VERSION)'\' >>$@+ && \
echo else >>$@+ && \ echo else >>$@+ && \
echo ' 'exec \''$(libdir_SQ)/Git Gui.app/Contents/MacOS/Wish'\' \ echo ' 'exec \''$(libdir_SQ)/Git Gui.app/Contents/MacOS/$(subst \,,$(TKEXECUTABLE))'\' \
'"$$0" "$$@"' >>$@+ && \ '"$$0" "$$@"' >>$@+ && \
echo fi >>$@+ && \ echo fi >>$@+ && \
chmod +x $@+ && \ chmod +x $@+ && \
@ -157,14 +184,15 @@ Git\ Gui.app: GIT-VERSION-FILE GIT-GUI-VARS \
macosx/Info.plist \ macosx/Info.plist \
macosx/git-gui.icns \ macosx/git-gui.icns \
macosx/AppMain.tcl \ macosx/AppMain.tcl \
$(TKFRAMEWORK)/Contents/MacOS/Wish $(TKFRAMEWORK)/Contents/MacOS/$(TKEXECUTABLE)
$(QUIET_GEN)rm -rf '$@' '$@'+ && \ $(QUIET_GEN)rm -rf '$@' '$@'+ && \
mkdir -p '$@'+/Contents/MacOS && \ mkdir -p '$@'+/Contents/MacOS && \
mkdir -p '$@'+/Contents/Resources/Scripts && \ mkdir -p '$@'+/Contents/Resources/Scripts && \
cp '$(subst ','\'',$(TKFRAMEWORK))/Contents/MacOS/Wish' \ cp '$(subst ','\'',$(subst \,,$(TKFRAMEWORK)/Contents/MacOS/$(TKEXECUTABLE)))' \
'$@'+/Contents/MacOS && \ '$@'+/Contents/MacOS && \
cp macosx/git-gui.icns '$@'+/Contents/Resources && \ cp macosx/git-gui.icns '$@'+/Contents/Resources && \
sed -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \ sed -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \
-e 's/@@GITGUI_TKEXECUTABLE@@/$(TKEXECUTABLE)/g' \
macosx/Info.plist \ macosx/Info.plist \
>'$@'+/Contents/Info.plist && \ >'$@'+/Contents/Info.plist && \
sed -e 's|@@gitexecdir@@|$(gitexecdir_SQ)|' \ sed -e 's|@@gitexecdir@@|$(gitexecdir_SQ)|' \
@ -198,7 +226,7 @@ ifdef NO_MSGFMT
MSGFMT ?= $(TCL_PATH) po/po2msg.sh MSGFMT ?= $(TCL_PATH) po/po2msg.sh
else else
MSGFMT ?= msgfmt MSGFMT ?= msgfmt
ifeq ($(shell $(MSGFMT) >/dev/null 2>&1 || echo $$?),127) ifneq ($(shell $(MSGFMT) --tcl -l C -d . /dev/null 2>/dev/null; echo $$?),0)
MSGFMT := $(TCL_PATH) po/po2msg.sh MSGFMT := $(TCL_PATH) po/po2msg.sh
endif endif
endif endif

View File

@ -52,7 +52,11 @@ catch {rename send {}} ; # What an evil concept...
set oguilib {@@GITGUI_LIBDIR@@} set oguilib {@@GITGUI_LIBDIR@@}
set oguirel {@@GITGUI_RELATIVE@@} set oguirel {@@GITGUI_RELATIVE@@}
if {$oguirel eq {1}} { if {$oguirel eq {1}} {
set oguilib [file dirname [file dirname [file normalize $argv0]]] set oguilib [file dirname [file normalize $argv0]]
if {[file tail $oguilib] eq {git-core}} {
set oguilib [file dirname $oguilib]
}
set oguilib [file dirname $oguilib]
set oguilib [file join $oguilib share git-gui lib] set oguilib [file join $oguilib share git-gui lib]
set oguimsg [file join $oguilib msgs] set oguimsg [file join $oguilib msgs]
} elseif {[string match @@* $oguirel]} { } elseif {[string match @@* $oguirel]} {
@ -122,6 +126,14 @@ set _reponame {}
set _iscygwin {} set _iscygwin {}
set _search_path {} set _search_path {}
set _trace [lsearch -exact $argv --trace]
if {$_trace >= 0} {
set argv [lreplace $argv $_trace $_trace]
set _trace 1
} else {
set _trace 0
}
proc appname {} { proc appname {} {
global _appname global _appname
return $_appname return $_appname
@ -245,6 +257,21 @@ proc get_config {name} {
## ##
## handy utils ## handy utils
proc _trace_exec {cmd} {
if {!$::_trace} return
set d {}
foreach v $cmd {
if {$d ne {}} {
append d { }
}
if {[regexp {[ \t\r\n'"$?*]} $v]} {
set v [sq $v]
}
append d $v
}
puts stderr $d
}
proc _git_cmd {name} { proc _git_cmd {name} {
global _git_cmd_path global _git_cmd_path
@ -294,7 +321,7 @@ proc _git_cmd {name} {
return $v return $v
} }
proc _which {what} { proc _which {what args} {
global env _search_exe _search_path global env _search_exe _search_path
if {$_search_path eq {}} { if {$_search_path eq {}} {
@ -317,8 +344,14 @@ proc _which {what} {
} }
} }
if {[is_Windows] && [lsearch -exact $args -script] >= 0} {
set suffix {}
} else {
set suffix $_search_exe
}
foreach p $_search_path { foreach p $_search_path {
set p [file join $p $what$_search_exe] set p [file join $p $what$suffix]
if {[file exists $p]} { if {[file exists $p]} {
return [file normalize $p] return [file normalize $p]
} }
@ -339,7 +372,7 @@ proc _lappend_nice {cmd_var} {
} }
proc git {args} { proc git {args} {
set opt [list exec] set opt [list]
while {1} { while {1} {
switch -- [lindex $args 0] { switch -- [lindex $args 0] {
@ -359,12 +392,18 @@ proc git {args} {
set cmdp [_git_cmd [lindex $args 0]] set cmdp [_git_cmd [lindex $args 0]]
set args [lrange $args 1 end] set args [lrange $args 1 end]
return [eval $opt $cmdp $args] _trace_exec [concat $opt $cmdp $args]
set result [eval exec $opt $cmdp $args]
if {$::_trace} {
puts stderr "< $result"
}
return $result
} }
proc _open_stdout_stderr {cmd} { proc _open_stdout_stderr {cmd} {
_trace_exec $cmd
if {[catch { if {[catch {
set fd [open $cmd r] set fd [open [concat [list | ] $cmd] r]
} err]} { } err]} {
if { [lindex $cmd end] eq {2>@1} if { [lindex $cmd end] eq {2>@1}
&& $err eq {can not find channel named "1"} && $err eq {can not find channel named "1"}
@ -375,6 +414,7 @@ proc _open_stdout_stderr {cmd} {
# to try to start it a second time. # to try to start it a second time.
# #
set fd [open [concat \ set fd [open [concat \
[list | ] \
[lrange $cmd 0 end-1] \ [lrange $cmd 0 end-1] \
[list |& cat] \ [list |& cat] \
] r] ] r]
@ -387,7 +427,7 @@ proc _open_stdout_stderr {cmd} {
} }
proc git_read {args} { proc git_read {args} {
set opt [list |] set opt [list]
while {1} { while {1} {
switch -- [lindex $args 0] { switch -- [lindex $args 0] {
@ -415,7 +455,7 @@ proc git_read {args} {
} }
proc git_write {args} { proc git_write {args} {
set opt [list |] set opt [list]
while {1} { while {1} {
switch -- [lindex $args 0] { switch -- [lindex $args 0] {
@ -435,17 +475,18 @@ proc git_write {args} {
set cmdp [_git_cmd [lindex $args 0]] set cmdp [_git_cmd [lindex $args 0]]
set args [lrange $args 1 end] set args [lrange $args 1 end]
return [open [concat $opt $cmdp $args] w] _trace_exec [concat $opt $cmdp $args]
return [open [concat [list | ] $opt $cmdp $args] w]
} }
proc githook_read {hook_name args} { proc githook_read {hook_name args} {
set pchook [gitdir hooks $hook_name] set pchook [gitdir hooks $hook_name]
lappend args 2>@1 lappend args 2>@1
# On Cygwin [file executable] might lie so we need to ask # On Windows [file executable] might lie so we need to ask
# the shell if the hook is executable. Yes that's annoying. # the shell if the hook is executable. Yes that's annoying.
# #
if {[is_Cygwin]} { if {[is_Windows]} {
upvar #0 _sh interp upvar #0 _sh interp
if {![info exists interp]} { if {![info exists interp]} {
set interp [_which sh] set interp [_which sh]
@ -455,17 +496,31 @@ proc githook_read {hook_name args} {
} }
set scr {if test -x "$1";then exec "$@";fi} set scr {if test -x "$1";then exec "$@";fi}
set sh_c [list | $interp -c $scr $interp $pchook] set sh_c [list $interp -c $scr $interp $pchook]
return [_open_stdout_stderr [concat $sh_c $args]] return [_open_stdout_stderr [concat $sh_c $args]]
} }
if {[file executable $pchook]} { if {[file executable $pchook]} {
return [_open_stdout_stderr [concat [list | $pchook] $args]] return [_open_stdout_stderr [concat [list $pchook] $args]]
} }
return {} return {}
} }
proc kill_file_process {fd} {
set process [pid $fd]
catch {
if {[is_Windows]} {
# Use a Cygwin-specific flag to allow killing
# native Windows processes
exec kill -f $process
} else {
exec kill $process
}
}
}
proc sq {value} { proc sq {value} {
regsub -all ' $value "'\\''" value regsub -all ' $value "'\\''" value
return "'$value'" return "'$value'"
@ -601,6 +656,7 @@ proc apply_config {} {
} }
} }
set default_config(branch.autosetupmerge) true
set default_config(merge.diffstat) true set default_config(merge.diffstat) true
set default_config(merge.summary) false set default_config(merge.summary) false
set default_config(merge.verbosity) 2 set default_config(merge.verbosity) 2
@ -610,8 +666,12 @@ set default_config(user.email) {}
set default_config(gui.matchtrackingbranch) false set default_config(gui.matchtrackingbranch) false
set default_config(gui.pruneduringfetch) false set default_config(gui.pruneduringfetch) false
set default_config(gui.trustmtime) false set default_config(gui.trustmtime) false
set default_config(gui.fastcopyblame) false
set default_config(gui.copyblamethreshold) 40
set default_config(gui.diffcontext) 5 set default_config(gui.diffcontext) 5
set default_config(gui.commitmsgwidth) 75
set default_config(gui.newbranchtemplate) {} set default_config(gui.newbranchtemplate) {}
set default_config(gui.spellingdictionary) {}
set default_config(gui.fontui) [font configure font_ui] set default_config(gui.fontui) [font configure font_ui]
set default_config(gui.fontdiff) [font configure font_diff] set default_config(gui.fontdiff) [font configure font_diff]
set font_descs { set font_descs {
@ -662,7 +722,7 @@ if {![regsub {^git version } $_git_version {} _git_version]} {
} }
set _real_git_version $_git_version set _real_git_version $_git_version
regsub -- {-dirty$} $_git_version {} _git_version regsub -- {[\-\.]dirty$} $_git_version {} _git_version
regsub {\.[0-9]+\.g[0-9a-f]+$} $_git_version {} _git_version regsub {\.[0-9]+\.g[0-9a-f]+$} $_git_version {} _git_version
regsub {\.rc[0-9]+$} $_git_version {} _git_version regsub {\.rc[0-9]+$} $_git_version {} _git_version
regsub {\.GIT$} $_git_version {} _git_version regsub {\.GIT$} $_git_version {} _git_version
@ -1093,27 +1153,18 @@ proc rescan {after {honor_trustmtime 1}} {
} }
if {[is_Cygwin]} { if {[is_Cygwin]} {
set is_git_info_link {}
set is_git_info_exclude {} set is_git_info_exclude {}
proc have_info_exclude {} { proc have_info_exclude {} {
global is_git_info_link is_git_info_exclude global is_git_info_exclude
if {$is_git_info_link eq {}} { if {$is_git_info_exclude eq {}} {
set is_git_info_link [file isfile [gitdir info.lnk]] if {[catch {exec test -f [gitdir info exclude]}]} {
} set is_git_info_exclude 0
} else {
if {$is_git_info_link} { set is_git_info_exclude 1
if {$is_git_info_exclude eq {}} {
if {[catch {exec test -f [gitdir info exclude]}]} {
set is_git_info_exclude 0
} else {
set is_git_info_exclude 1
}
} }
return $is_git_info_exclude
} else {
return [file readable [gitdir info exclude]]
} }
return $is_git_info_exclude
} }
} else { } else {
proc have_info_exclude {} { proc have_info_exclude {} {
@ -1645,10 +1696,10 @@ proc do_gitk {revs} {
# -- Always start gitk through whatever we were loaded with. This # -- Always start gitk through whatever we were loaded with. This
# lets us bypass using shell process on Windows systems. # lets us bypass using shell process on Windows systems.
# #
set exe [file join [file dirname $::_git] gitk] set exe [_which gitk -script]
set cmd [list [info nameofexecutable] $exe] set cmd [list [info nameofexecutable] $exe]
if {! [file exists $exe]} { if {$exe eq {}} {
error_popup [mc "Unable to start gitk:\n\n%s does not exist" $exe] error_popup [mc "Couldn't find gitk in PATH"]
} else { } else {
global env global env
@ -1683,6 +1734,7 @@ set is_quitting 0
proc do_quit {} { proc do_quit {} {
global ui_comm is_quitting repo_config commit_type global ui_comm is_quitting repo_config commit_type
global GITGUI_BCK_exists GITGUI_BCK_i global GITGUI_BCK_exists GITGUI_BCK_i
global ui_comm_spell
if {$is_quitting} return if {$is_quitting} return
set is_quitting 1 set is_quitting 1
@ -1710,6 +1762,12 @@ proc do_quit {} {
} }
} }
# -- Cancel our spellchecker if its running.
#
if {[info exists ui_comm_spell]} {
$ui_comm_spell stop
}
# -- Remove our editor backup, its not needed. # -- Remove our editor backup, its not needed.
# #
after cancel $GITGUI_BCK_i after cancel $GITGUI_BCK_i
@ -1742,6 +1800,11 @@ proc do_commit {} {
commit_tree commit_tree
} }
proc next_diff {} {
global next_diff_p next_diff_w next_diff_i
show_diff $next_diff_p $next_diff_w $next_diff_i
}
proc toggle_or_diff {w x y} { proc toggle_or_diff {w x y} {
global file_states file_lists current_diff_path ui_index ui_workdir global file_states file_lists current_diff_path ui_index ui_workdir
global last_clicked selected_paths global last_clicked selected_paths
@ -1760,12 +1823,34 @@ proc toggle_or_diff {w x y} {
$ui_index tag remove in_sel 0.0 end $ui_index tag remove in_sel 0.0 end
$ui_workdir tag remove in_sel 0.0 end $ui_workdir tag remove in_sel 0.0 end
if {$col == 0} { if {$col == 0 && $y > 1} {
if {$current_diff_path eq $path} { set i [expr {$lno-1}]
set ll [expr {[llength $file_lists($w)]-1}]
if {$i == $ll && $i == 0} {
set after {reshow_diff;} set after {reshow_diff;}
} else { } else {
set after {} global next_diff_p next_diff_w next_diff_i
set next_diff_w $w
if {$i < $ll} {
set i [expr {$i + 1}]
set next_diff_i $i
} else {
set next_diff_i $i
set i [expr {$i - 1}]
}
set next_diff_p [lindex $file_lists($w) $i]
if {$next_diff_p ne {} && $current_diff_path ne {}} {
set after {next_diff;}
} else {
set after {}
}
} }
if {$w eq $ui_index} { if {$w eq $ui_index} {
update_indexinfo \ update_indexinfo \
"Unstaging [short_path $path] from commit" \ "Unstaging [short_path $path] from commit" \
@ -1837,6 +1922,22 @@ proc add_range_to_selection {w x y} {
$w tag add in_sel $begin.0 [expr {$end + 1}].0 $w tag add in_sel $begin.0 [expr {$end + 1}].0
} }
proc show_more_context {} {
global repo_config
if {$repo_config(gui.diffcontext) < 99} {
incr repo_config(gui.diffcontext)
reshow_diff
}
}
proc show_less_context {} {
global repo_config
if {$repo_config(gui.diffcontext) >= 1} {
incr repo_config(gui.diffcontext) -1
reshow_diff
}
}
###################################################################### ######################################################################
## ##
## ui construction ## ui construction
@ -1920,9 +2021,13 @@ if {[is_enabled multicommit]} {
} }
} }
.mbar.repository add command -label [mc Quit] \ if {[is_MacOSX]} {
-command do_quit \ proc ::tk::mac::Quit {args} { do_quit }
-accelerator $M1T-Q } else {
.mbar.repository add command -label [mc Quit] \
-command do_quit \
-accelerator $M1T-Q
}
# -- Edit Menu # -- Edit Menu
# #
@ -2037,6 +2142,16 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} {
.mbar.commit add separator .mbar.commit add separator
.mbar.commit add command -label [mc "Show Less Context"] \
-command show_less_context \
-accelerator $M1T-\-
.mbar.commit add command -label [mc "Show More Context"] \
-command show_more_context \
-accelerator $M1T-=
.mbar.commit add separator
.mbar.commit add command -label [mc "Sign Off"] \ .mbar.commit add command -label [mc "Sign Off"] \
-command do_signoff \ -command do_signoff \
-accelerator $M1T-S -accelerator $M1T-S
@ -2080,7 +2195,7 @@ if {[is_enabled transport]} {
if {[is_MacOSX]} { if {[is_MacOSX]} {
# -- Apple Menu (Mac OS X only) # -- Apple Menu (Mac OS X only)
# #
.mbar add cascade -label [mc Apple] -menu .mbar.apple .mbar add cascade -label Apple -menu .mbar.apple
menu .mbar.apple menu .mbar.apple
.mbar.apple add command -label [mc "About %s" [appname]] \ .mbar.apple add command -label [mc "About %s" [appname]] \
@ -2281,8 +2396,9 @@ pack .vpane -anchor n -side top -fill both -expand 1
# #
frame .vpane.files.index -height 100 -width 200 frame .vpane.files.index -height 100 -width 200
label .vpane.files.index.title -text [mc "Staged Changes (Will Commit)"] \ label .vpane.files.index.title -text [mc "Staged Changes (Will Commit)"] \
-background lightgreen -background lightgreen -foreground black
text $ui_index -background white -borderwidth 0 \ text $ui_index -background white -foreground black \
-borderwidth 0 \
-width 20 -height 10 \ -width 20 -height 10 \
-wrap none \ -wrap none \
-cursor $cursor_ptr \ -cursor $cursor_ptr \
@ -2300,8 +2416,9 @@ pack $ui_index -side left -fill both -expand 1
# #
frame .vpane.files.workdir -height 100 -width 200 frame .vpane.files.workdir -height 100 -width 200
label .vpane.files.workdir.title -text [mc "Unstaged Changes"] \ label .vpane.files.workdir.title -text [mc "Unstaged Changes"] \
-background lightsalmon -background lightsalmon -foreground black
text $ui_workdir -background white -borderwidth 0 \ text $ui_workdir -background white -foreground black \
-borderwidth 0 \
-width 20 -height 10 \ -width 20 -height 10 \
-wrap none \ -wrap none \
-cursor $cursor_ptr \ -cursor $cursor_ptr \
@ -2408,12 +2525,13 @@ pack $ui_coml -side left -fill x
pack .vpane.lower.commarea.buffer.header.amend -side right pack .vpane.lower.commarea.buffer.header.amend -side right
pack .vpane.lower.commarea.buffer.header.new -side right pack .vpane.lower.commarea.buffer.header.new -side right
text $ui_comm -background white -borderwidth 1 \ text $ui_comm -background white -foreground black \
-borderwidth 1 \
-undo true \ -undo true \
-maxundo 20 \ -maxundo 20 \
-autoseparators true \ -autoseparators true \
-relief sunken \ -relief sunken \
-width 75 -height 9 -wrap none \ -width $repo_config(gui.commitmsgwidth) -height 9 -wrap none \
-font font_diff \ -font font_diff \
-yscrollcommand {.vpane.lower.commarea.buffer.sby set} -yscrollcommand {.vpane.lower.commarea.buffer.sby set}
scrollbar .vpane.lower.commarea.buffer.sby \ scrollbar .vpane.lower.commarea.buffer.sby \
@ -2454,7 +2572,7 @@ $ctxm add separator
$ctxm add command \ $ctxm add command \
-label [mc "Sign Off"] \ -label [mc "Sign Off"] \
-command do_signoff -command do_signoff
bind_button3 $ui_comm "tk_popup $ctxm %X %Y" set ui_comm_ctxm $ctxm
# -- Diff Header # -- Diff Header
# #
@ -2485,15 +2603,18 @@ trace add variable current_diff_path write trace_current_diff_path
frame .vpane.lower.diff.header -background gold frame .vpane.lower.diff.header -background gold
label .vpane.lower.diff.header.status \ label .vpane.lower.diff.header.status \
-background gold \ -background gold \
-foreground black \
-width $max_status_desc \ -width $max_status_desc \
-anchor w \ -anchor w \
-justify left -justify left
label .vpane.lower.diff.header.file \ label .vpane.lower.diff.header.file \
-background gold \ -background gold \
-foreground black \
-anchor w \ -anchor w \
-justify left -justify left
label .vpane.lower.diff.header.path \ label .vpane.lower.diff.header.path \
-background gold \ -background gold \
-foreground black \
-anchor w \ -anchor w \
-justify left -justify left
pack .vpane.lower.diff.header.status -side left pack .vpane.lower.diff.header.status -side left
@ -2517,7 +2638,8 @@ bind_button3 .vpane.lower.diff.header.path "tk_popup $ctxm %X %Y"
# #
frame .vpane.lower.diff.body frame .vpane.lower.diff.body
set ui_diff .vpane.lower.diff.body.t set ui_diff .vpane.lower.diff.body.t
text $ui_diff -background white -borderwidth 0 \ text $ui_diff -background white -foreground black \
-borderwidth 0 \
-width 80 -height 15 -wrap none \ -width 80 -height 15 -wrap none \
-font font_diff \ -font font_diff \
-xscrollcommand {.vpane.lower.diff.body.sbx set} \ -xscrollcommand {.vpane.lower.diff.body.sbx set} \
@ -2574,20 +2696,19 @@ $ctxm add command \
-command {apply_hunk $cursorX $cursorY} -command {apply_hunk $cursorX $cursorY}
set ui_diff_applyhunk [$ctxm index last] set ui_diff_applyhunk [$ctxm index last]
lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state] lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state]
$ctxm add command \
-label [mc "Apply/Reverse Line"] \
-command {apply_line $cursorX $cursorY; do_rescan}
set ui_diff_applyline [$ctxm index last]
lappend diff_actions [list $ctxm entryconf $ui_diff_applyline -state]
$ctxm add separator $ctxm add separator
$ctxm add command \ $ctxm add command \
-label [mc "Show Less Context"] \ -label [mc "Show Less Context"] \
-command {if {$repo_config(gui.diffcontext) >= 1} { -command show_less_context
incr repo_config(gui.diffcontext) -1
reshow_diff
}}
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
$ctxm add command \ $ctxm add command \
-label [mc "Show More Context"] \ -label [mc "Show More Context"] \
-command {if {$repo_config(gui.diffcontext) < 99} { -command show_more_context
incr repo_config(gui.diffcontext)
reshow_diff
}}
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
$ctxm add separator $ctxm add separator
$ctxm add command \ $ctxm add command \
@ -2628,8 +2749,10 @@ proc popup_diff_menu {ctxm x y X Y} {
set ::cursorY $y set ::cursorY $y
if {$::ui_index eq $::current_diff_side} { if {$::ui_index eq $::current_diff_side} {
set l [mc "Unstage Hunk From Commit"] set l [mc "Unstage Hunk From Commit"]
set t [mc "Unstage Line From Commit"]
} else { } else {
set l [mc "Stage Hunk For Commit"] set l [mc "Stage Hunk For Commit"]
set t [mc "Stage Line For Commit"]
} }
if {$::is_3way_diff if {$::is_3way_diff
|| $current_diff_path eq {} || $current_diff_path eq {}
@ -2640,6 +2763,7 @@ proc popup_diff_menu {ctxm x y X Y} {
set s normal set s normal
} }
$ctxm entryconf $::ui_diff_applyhunk -state $s -label $l $ctxm entryconf $::ui_diff_applyhunk -state $s -label $l
$ctxm entryconf $::ui_diff_applyline -state $s -label $t
tk_popup $ctxm $X $Y tk_popup $ctxm $X $Y
} }
bind_button3 $ui_diff [list popup_diff_menu $ctxm %x %y %X %Y] bind_button3 $ui_diff [list popup_diff_menu $ctxm %x %y %X %Y]
@ -2679,6 +2803,11 @@ bind $ui_comm <$M1B-Key-v> {tk_textPaste %W; %W see insert; break}
bind $ui_comm <$M1B-Key-V> {tk_textPaste %W; %W see insert; break} bind $ui_comm <$M1B-Key-V> {tk_textPaste %W; %W see insert; break}
bind $ui_comm <$M1B-Key-a> {%W tag add sel 0.0 end;break} bind $ui_comm <$M1B-Key-a> {%W tag add sel 0.0 end;break}
bind $ui_comm <$M1B-Key-A> {%W tag add sel 0.0 end;break} bind $ui_comm <$M1B-Key-A> {%W tag add sel 0.0 end;break}
bind $ui_comm <$M1B-Key-minus> {show_less_context;break}
bind $ui_comm <$M1B-Key-KP_Subtract> {show_less_context;break}
bind $ui_comm <$M1B-Key-equal> {show_more_context;break}
bind $ui_comm <$M1B-Key-plus> {show_more_context;break}
bind $ui_comm <$M1B-Key-KP_Add> {show_more_context;break}
bind $ui_diff <$M1B-Key-x> {tk_textCopy %W;break} bind $ui_diff <$M1B-Key-x> {tk_textCopy %W;break}
bind $ui_diff <$M1B-Key-X> {tk_textCopy %W;break} bind $ui_diff <$M1B-Key-X> {tk_textCopy %W;break}
@ -2722,6 +2851,11 @@ bind . <$M1B-Key-t> do_add_selection
bind . <$M1B-Key-T> do_add_selection bind . <$M1B-Key-T> do_add_selection
bind . <$M1B-Key-i> do_add_all bind . <$M1B-Key-i> do_add_all
bind . <$M1B-Key-I> do_add_all bind . <$M1B-Key-I> do_add_all
bind . <$M1B-Key-minus> {show_less_context;break}
bind . <$M1B-Key-KP_Subtract> {show_less_context;break}
bind . <$M1B-Key-equal> {show_more_context;break}
bind . <$M1B-Key-plus> {show_more_context;break}
bind . <$M1B-Key-KP_Add> {show_more_context;break}
bind . <$M1B-Key-Return> do_commit bind . <$M1B-Key-Return> do_commit
foreach i [list $ui_index $ui_workdir] { foreach i [list $ui_index $ui_workdir] {
bind $i <Button-1> "toggle_or_diff $i %x %y; break" bind $i <Button-1> "toggle_or_diff $i %x %y; break"
@ -2801,6 +2935,7 @@ if {[is_enabled transport]} {
populate_fetch_menu populate_fetch_menu
set n [expr {[.mbar.remote index end] - $n}] set n [expr {[.mbar.remote index end] - $n}]
if {$n > 0} { if {$n > 0} {
if {[.mbar.remote type 0] eq "tearoff"} { incr n }
.mbar.remote insert $n separator .mbar.remote insert $n separator
} }
unset n unset n
@ -2857,6 +2992,30 @@ if {[winfo exists $ui_comm]} {
} }
backup_commit_buffer backup_commit_buffer
# -- If the user has aspell available we can drive it
# in pipe mode to spellcheck the commit message.
#
set spell_cmd [list |]
set spell_dict [get_config gui.spellingdictionary]
lappend spell_cmd aspell
if {$spell_dict ne {}} {
lappend spell_cmd --master=$spell_dict
}
lappend spell_cmd --mode=none
lappend spell_cmd --encoding=utf-8
lappend spell_cmd pipe
if {$spell_dict eq {none}
|| [catch {set spell_fd [open $spell_cmd r+]} spell_err]} {
bind_button3 $ui_comm [list tk_popup $ui_comm_ctxm %X %Y]
} else {
set ui_comm_spell [spellcheck::init \
$spell_fd \
$ui_comm \
$ui_comm_ctxm \
]
}
unset -nocomplain spell_cmd spell_fd spell_err spell_dict
} }
lock_index begin-read lock_index begin-read

View File

@ -4,6 +4,7 @@
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
set w .about_dialog set w .about_dialog
toplevel $w toplevel $w
@ -40,6 +41,11 @@ proc do_about {} {
append v "Tcl version $tcl_patchLevel" append v "Tcl version $tcl_patchLevel"
append v ", Tk version $tk_patchLevel" append v ", Tk version $tk_patchLevel"
} }
if {[info exists ui_comm_spell]
&& [$ui_comm_spell version] ne {}} {
append v "\n"
append v [$ui_comm_spell version]
}
set d {} set d {}
append d "git wrapper: $::_git\n" append d "git wrapper: $::_git\n"

View File

@ -33,13 +33,6 @@ variable group_colors {
#ececec #ececec
} }
# Switches for original location detection
#
variable original_options [list -C -C]
if {[git-version >= 1.5.3]} {
lappend original_options -w ; # ignore indentation changes
}
# Current blame data; cleared/reset on each load # Current blame data; cleared/reset on each load
# #
field commit ; # input commit to blame field commit ; # input commit to blame
@ -80,6 +73,7 @@ constructor new {i_commit i_path} {
label $w.header.commit_l \ label $w.header.commit_l \
-text [mc "Commit:"] \ -text [mc "Commit:"] \
-background gold \ -background gold \
-foreground black \
-anchor w \ -anchor w \
-justify left -justify left
set w_back $w.header.commit_b set w_back $w.header.commit_b
@ -89,6 +83,7 @@ constructor new {i_commit i_path} {
-relief flat \ -relief flat \
-state disabled \ -state disabled \
-background gold \ -background gold \
-foreground black \
-activebackground gold -activebackground gold
bind $w_back <Button-1> " bind $w_back <Button-1> "
if {\[$w_back cget -state\] eq {normal}} { if {\[$w_back cget -state\] eq {normal}} {
@ -98,16 +93,19 @@ constructor new {i_commit i_path} {
label $w.header.commit \ label $w.header.commit \
-textvariable @commit \ -textvariable @commit \
-background gold \ -background gold \
-foreground black \
-anchor w \ -anchor w \
-justify left -justify left
label $w.header.path_l \ label $w.header.path_l \
-text [mc "File:"] \ -text [mc "File:"] \
-background gold \ -background gold \
-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 \ label $w_path \
-background gold \ -background gold \
-foreground black \
-anchor w \ -anchor w \
-justify left -justify left
pack $w.header.commit_l -side left pack $w.header.commit_l -side left
@ -135,7 +133,9 @@ constructor new {i_commit i_path} {
-takefocus 0 \ -takefocus 0 \
-highlightthickness 0 \ -highlightthickness 0 \
-padx 0 -pady 0 \ -padx 0 -pady 0 \
-background white -borderwidth 0 \ -background white \
-foreground black \
-borderwidth 0 \
-state disabled \ -state disabled \
-wrap none \ -wrap none \
-height 40 \ -height 40 \
@ -148,7 +148,9 @@ constructor new {i_commit i_path} {
-takefocus 0 \ -takefocus 0 \
-highlightthickness 0 \ -highlightthickness 0 \
-padx 0 -pady 0 \ -padx 0 -pady 0 \
-background white -borderwidth 0 \ -background white \
-foreground black \
-borderwidth 0 \
-state disabled \ -state disabled \
-wrap none \ -wrap none \
-height 40 \ -height 40 \
@ -166,7 +168,9 @@ constructor new {i_commit i_path} {
-takefocus 0 \ -takefocus 0 \
-highlightthickness 0 \ -highlightthickness 0 \
-padx 0 -pady 0 \ -padx 0 -pady 0 \
-background white -borderwidth 0 \ -background white \
-foreground black \
-borderwidth 0 \
-state disabled \ -state disabled \
-wrap none \ -wrap none \
-height 40 \ -height 40 \
@ -184,7 +188,9 @@ constructor new {i_commit i_path} {
-takefocus 0 \ -takefocus 0 \
-highlightthickness 0 \ -highlightthickness 0 \
-padx 0 -pady 0 \ -padx 0 -pady 0 \
-background white -borderwidth 0 \ -background white \
-foreground black \
-borderwidth 0 \
-state disabled \ -state disabled \
-wrap none \ -wrap none \
-height 40 \ -height 40 \
@ -213,7 +219,9 @@ constructor new {i_commit i_path} {
set w_cviewer $w.file_pane.cm.t set w_cviewer $w.file_pane.cm.t
text $w_cviewer \ text $w_cviewer \
-background white -borderwidth 0 \ -background white \
-foreground black \
-borderwidth 0 \
-state disabled \ -state disabled \
-wrap none \ -wrap none \
-height 10 \ -height 10 \
@ -248,6 +256,9 @@ constructor new {i_commit i_path} {
$w.ctxm add command \ $w.ctxm add command \
-label [mc "Copy Commit"] \ -label [mc "Copy Commit"] \
-command [cb _copycommit] -command [cb _copycommit]
$w.ctxm add command \
-label [mc "Do Full Copy Detection"] \
-command [cb _fullcopyblame]
foreach i $w_columns { foreach i $w_columns {
for {set g 0} {$g < [llength $group_colors]} {incr g} { for {set g 0} {$g < [llength $group_colors]} {incr g} {
@ -318,19 +329,27 @@ constructor new {i_commit i_path} {
bind $w.file_pane <Configure> \ bind $w.file_pane <Configure> \
"if {{$w.file_pane} eq {%W}} {[cb _resize %h]}" "if {{$w.file_pane} eq {%W}} {[cb _resize %h]}"
wm protocol $top WM_DELETE_WINDOW "destroy $top"
bind $top <Destroy> [cb _kill]
_load $this {} _load $this {}
} }
method _kill {} {
if {$current_fd ne {}} {
kill_file_process $current_fd
catch {close $current_fd}
set current_fd {}
}
}
method _load {jump} { method _load {jump} {
variable group_colors variable group_colors
_hide_tooltip $this _hide_tooltip $this
if {$total_lines != 0 || $current_fd ne {}} { if {$total_lines != 0 || $current_fd ne {}} {
if {$current_fd ne {}} { _kill $this
catch {close $current_fd}
set current_fd {}
}
foreach i $w_columns { foreach i $w_columns {
$i conf -state normal $i conf -state normal
@ -496,7 +515,6 @@ method _exec_blame {cur_w cur_d options cur_s} {
method _read_blame {fd cur_w cur_d} { method _read_blame {fd cur_w cur_d} {
upvar #0 $cur_d line_data upvar #0 $cur_d line_data
variable group_colors variable group_colors
variable original_options
if {$fd ne $current_fd} { if {$fd ne $current_fd} {
catch {close $fd} catch {close $fd}
@ -669,6 +687,18 @@ method _read_blame {fd cur_w cur_d} {
if {[eof $fd]} { if {[eof $fd]} {
close $fd close $fd
if {$cur_w eq $w_asim} { if {$cur_w eq $w_asim} {
# Switches for original location detection
set threshold [get_config gui.copyblamethreshold]
set original_options [list "-C$threshold"]
if {![is_config_true gui.fastcopyblame]} {
# thorough copy search; insert before the threshold
set original_options [linsert $original_options 0 -C]
}
if {[git-version >= 1.5.3]} {
lappend original_options -w ; # ignore indentation changes
}
_exec_blame $this $w_amov @amov_data \ _exec_blame $this $w_amov @amov_data \
$original_options \ $original_options \
[mc "Loading original location annotations..."] [mc "Loading original location annotations..."]
@ -681,6 +711,72 @@ method _read_blame {fd cur_w cur_d} {
} }
} ifdeleted { catch {close $fd} } } ifdeleted { catch {close $fd} }
method _find_commit_bound {data_list start_idx delta} {
upvar #0 $data_list line_data
set pos $start_idx
set limit [expr {[llength $line_data] - 1}]
set base_commit [lindex $line_data $pos 0]
while {$pos > 0 && $pos < $limit} {
set new_pos [expr {$pos + $delta}]
if {[lindex $line_data $new_pos 0] ne $base_commit} {
return $pos
}
set pos $new_pos
}
return $pos
}
method _fullcopyblame {} {
if {$current_fd ne {}} {
tk_messageBox \
-icon error \
-type ok \
-title [mc "Busy"] \
-message [mc "Annotation process is already running."]
return
}
# Switches for original location detection
set threshold [get_config gui.copyblamethreshold]
set original_options [list -C -C "-C$threshold"]
if {[git-version >= 1.5.3]} {
lappend original_options -w ; # ignore indentation changes
}
# Find the line range
set pos @$::cursorX,$::cursorY
set lno [lindex [split [$::cursorW index $pos] .] 0]
set min_amov_lno [_find_commit_bound $this @amov_data $lno -1]
set max_amov_lno [_find_commit_bound $this @amov_data $lno 1]
set min_asim_lno [_find_commit_bound $this @asim_data $lno -1]
set max_asim_lno [_find_commit_bound $this @asim_data $lno 1]
if {$min_asim_lno < $min_amov_lno} {
set min_amov_lno $min_asim_lno
}
if {$max_asim_lno > $max_amov_lno} {
set max_amov_lno $max_asim_lno
}
lappend original_options -L "$min_amov_lno,$max_amov_lno"
# Clear lines
for {set i $min_amov_lno} {$i <= $max_amov_lno} {incr i} {
lset amov_data $i [list ]
}
# Start the back-end process
_exec_blame $this $w_amov @amov_data \
$original_options \
[mc "Running thorough copy detection..."]
}
method _click {cur_w pos} { method _click {cur_w pos} {
set lno [lindex [split [$cur_w index $pos] .] 0] set lno [lindex [split [$cur_w index $pos] .] 0]
_showcommit $this $cur_w $lno _showcommit $this $cur_w $lno

View File

@ -183,6 +183,9 @@ method _create {} {
if {$spec ne {} && $opt_fetch} { if {$spec ne {} && $opt_fetch} {
$co enable_fetch $spec $co enable_fetch $spec
} }
if {$spec ne {}} {
$co remote_source $spec
}
if {[$co run]} { if {[$co run]} {
destroy $w destroy $w

View File

@ -127,7 +127,7 @@ method _delete {} {
foreach i $to_delete { foreach i $to_delete {
set b [lindex $i 0] set b [lindex $i 0]
set o [lindex $i 1] set o [lindex $i 1]
if {[catch {git update-ref -d "refs/heads/$b" $o} err]} { if {[catch {git branch -D $b} err]} {
append failed " - $b: $err\n" append failed " - $b: $err\n"
} }
} }

View File

@ -39,7 +39,8 @@ constructor new {commit {path {}}} {
frame $w.list frame $w.list
set w_list $w.list.l set w_list $w.list.l
text $w_list -background white -borderwidth 0 \ text $w_list -background white -foreground black \
-borderwidth 0 \
-cursor $cursor_ptr \ -cursor $cursor_ptr \
-state disabled \ -state disabled \
-wrap none \ -wrap none \

View File

@ -16,6 +16,7 @@ field merge_base {}; # merge base if we have another ref involved
field fetch_spec {}; # refetch tracking branch if used? field fetch_spec {}; # refetch tracking branch if used?
field checkout 1; # actually checkout the branch? field checkout 1; # actually checkout the branch?
field create 0; # create the branch if it doesn't exist? field create 0; # create the branch if it doesn't exist?
field remote_source {}; # same as fetch_spec, to setup tracking
field reset_ok 0; # did the user agree to reset? field reset_ok 0; # did the user agree to reset?
field fetch_ok 0; # did the fetch succeed? field fetch_ok 0; # did the fetch succeed?
@ -44,6 +45,10 @@ method enable_fetch {spec} {
set fetch_spec $spec set fetch_spec $spec
} }
method remote_source {spec} {
set remote_source $spec
}
method enable_checkout {co} { method enable_checkout {co} {
set checkout $co set checkout $co
} }
@ -145,7 +150,7 @@ method _finish_fetch {ok} {
} }
method _update_ref {} { method _update_ref {} {
global null_sha1 current_branch global null_sha1 current_branch repo_config
set ref $new_ref set ref $new_ref
set new $new_hash set new $new_hash
@ -172,6 +177,23 @@ method _update_ref {} {
set reflog_msg "branch: Created from $new_expr" set reflog_msg "branch: Created from $new_expr"
set cur $null_sha1 set cur $null_sha1
if {($repo_config(branch.autosetupmerge) eq {true}
|| $repo_config(branch.autosetupmerge) eq {always})
&& $remote_source ne {}
&& "refs/heads/$newbranch" eq $ref} {
set c_remote [lindex $remote_source 1]
set c_merge [lindex $remote_source 2]
if {[catch {
git config branch.$newbranch.remote $c_remote
git config branch.$newbranch.merge $c_merge
} err]} {
_error $this [strcat \
[mc "Failed to configure simplified git-pull for '%s'." $newbranch] \
"\n\n$err"]
}
}
} elseif {$create && $merge_type eq {none}} { } elseif {$create && $merge_type eq {none}} {
# We were told to create it, but not do a merge. # We were told to create it, but not do a merge.
# Bad. Name shouldn't have existed. # Bad. Name shouldn't have existed.
@ -280,7 +302,7 @@ The rescan will be automatically started now.
} elseif {[is_config_true gui.trustmtime]} { } elseif {[is_config_true gui.trustmtime]} {
_readtree $this _readtree $this
} else { } else {
ui_status {Refreshing file status...} ui_status [mc "Refreshing file status..."]
set fd [git_read update-index \ set fd [git_read update-index \
-q \ -q \
--unmerged \ --unmerged \
@ -320,7 +342,7 @@ method _readtree {} {
set readtree_d {} set readtree_d {}
$::main_status start \ $::main_status start \
[mc "Updating working directory to '%s'..." [_name $this]] \ [mc "Updating working directory to '%s'..." [_name $this]] \
{files checked out} [mc "files checked out"]
set fd [git_read --stderr read-tree \ set fd [git_read --stderr read-tree \
-m \ -m \
@ -447,7 +469,7 @@ If you wanted to be on a branch, create one now starting from 'This Detached Che
} else { } else {
repository_state commit_type HEAD MERGE_HEAD repository_state commit_type HEAD MERGE_HEAD
set PARENT $HEAD set PARENT $HEAD
ui_status "Checked out '$name'." ui_status [mc "Checked out '%s'." $name]
} }
delete_this delete_this
} }

View File

@ -55,6 +55,7 @@ constructor pick {path title a_family a_size} {
set w_family $w.inner.family.v set w_family $w.inner.family.v
text $w_family \ text $w_family \
-background white \ -background white \
-foreground black \
-borderwidth 1 \ -borderwidth 1 \
-relief sunken \ -relief sunken \
-cursor $::cursor_ptr \ -cursor $::cursor_ptr \
@ -92,6 +93,7 @@ constructor pick {path title a_family a_size} {
set w_example $w.example.t set w_example $w.example.t
text $w_example \ text $w_example \
-background white \ -background white \
-foreground black \
-borderwidth 1 \ -borderwidth 1 \
-relief sunken \ -relief sunken \
-height 3 \ -height 3 \

View File

@ -11,6 +11,7 @@ field w_quit ; # Quit button
field o_cons ; # Console object (if active) field o_cons ; # Console object (if active)
field w_types ; # List of type buttons in clone field w_types ; # List of type buttons in clone
field w_recentlist ; # Listbox containing recent repositories field w_recentlist ; # Listbox containing recent repositories
field w_localpath ; # Entry widget bound to local_path
field done 0 ; # Finished picking the repository? field done 0 ; # Finished picking the repository?
field local_path {} ; # Where this repository is locally field local_path {} ; # Where this repository is locally
@ -37,7 +38,7 @@ constructor pick {} {
menu $m_repo menu $m_repo
if {[is_MacOSX]} { if {[is_MacOSX]} {
$w.mbar add cascade -label [mc Apple] -menu .mbar.apple $w.mbar add cascade -label Apple -menu .mbar.apple
menu $w.mbar.apple menu $w.mbar.apple
$w.mbar.apple add command \ $w.mbar.apple add command \
-label [mc "About %s" [appname]] \ -label [mc "About %s" [appname]] \
@ -385,10 +386,9 @@ method _do_new {} {
button $w_body.where.b \ 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
pack $w_body.where.b -side right grid $w_body.where.l $w_body.where.t $w_body.where.b -sticky ew
pack $w_body.where.l -side left
pack $w_body.where.t -fill x
pack $w_body.where -fill x pack $w_body.where -fill x
trace add variable @local_path write [cb _write_local_path] trace add variable @local_path write [cb _write_local_path]
@ -416,6 +416,7 @@ method _new_local_path {} {
return return
} }
set local_path $p set local_path $p
$w_localpath icursor end
} }
method _do_new2 {} { method _do_new2 {} {
@ -481,6 +482,7 @@ method _do_clone {} {
-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
label $args.type_l -text [mc "Clone Type:"] label $args.type_l -text [mc "Clone Type:"]
frame $args.type_f frame $args.type_f
@ -983,9 +985,7 @@ method _do_open {} {
-text [mc "Browse"] \ -text [mc "Browse"] \
-command [cb _open_local_path] -command [cb _open_local_path]
pack $w_body.where.b -side right grid $w_body.where.l $w_body.where.t $w_body.where.b -sticky ew
pack $w_body.where.l -side left
pack $w_body.where.t -fill x
pack $w_body.where -fill x pack $w_body.where -fill x
trace add variable @local_path write [cb _write_local_path] trace add variable @local_path write [cb _write_local_path]

View File

@ -218,7 +218,7 @@ A good commit message has the following format:
return return
} }
ui_status {Calling pre-commit hook...} ui_status [mc "Calling pre-commit hook..."]
set pch_error {} 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 \
@ -233,7 +233,7 @@ proc commit_prehook_wait {fd_ph curHEAD msg_p} {
if {[eof $fd_ph]} { if {[eof $fd_ph]} {
if {[catch {close $fd_ph}]} { if {[catch {close $fd_ph}]} {
catch {file delete $msg_p} catch {file delete $msg_p}
ui_status {Commit declined by pre-commit hook.} ui_status [mc "Commit declined by pre-commit hook."]
hook_failed_popup pre-commit $pch_error hook_failed_popup pre-commit $pch_error
unlock_index unlock_index
} else { } else {
@ -256,7 +256,7 @@ proc commit_commitmsg {curHEAD msg_p} {
return return
} }
ui_status {Calling commit-msg hook...} ui_status [mc "Calling commit-msg hook..."]
set pch_error {} 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 \
@ -271,7 +271,7 @@ proc commit_commitmsg_wait {fd_ph curHEAD msg_p} {
if {[eof $fd_ph]} { if {[eof $fd_ph]} {
if {[catch {close $fd_ph}]} { if {[catch {close $fd_ph}]} {
catch {file delete $msg_p} catch {file delete $msg_p}
ui_status {Commit declined by commit-msg hook.} ui_status [mc "Commit declined by commit-msg hook."]
hook_failed_popup commit-msg $pch_error hook_failed_popup commit-msg $pch_error
unlock_index unlock_index
} else { } else {
@ -284,7 +284,7 @@ proc commit_commitmsg_wait {fd_ph curHEAD msg_p} {
} }
proc commit_writetree {curHEAD msg_p} { proc commit_writetree {curHEAD msg_p} {
ui_status {Committing changes...} ui_status [mc "Committing changes..."]
set fd_wt [git_read write-tree] set fd_wt [git_read write-tree]
fileevent $fd_wt readable \ fileevent $fd_wt readable \
[list commit_committree $fd_wt $curHEAD $msg_p] [list commit_committree $fd_wt $curHEAD $msg_p]
@ -301,7 +301,7 @@ proc commit_committree {fd_wt curHEAD msg_p} {
if {[catch {close $fd_wt} err]} { if {[catch {close $fd_wt} err]} {
catch {file delete $msg_p} catch {file delete $msg_p}
error_popup [strcat [mc "write-tree failed:"] "\n\n$err"] error_popup [strcat [mc "write-tree failed:"] "\n\n$err"]
ui_status {Commit failed.} ui_status [mc "Commit failed."]
unlock_index unlock_index
return return
} }
@ -345,7 +345,7 @@ A rescan will be automatically started now.
if {[catch {set cmt_id [eval git $cmd]} err]} { if {[catch {set cmt_id [eval git $cmd]} err]} {
catch {file delete $msg_p} catch {file delete $msg_p}
error_popup [strcat [mc "commit-tree failed:"] "\n\n$err"] error_popup [strcat [mc "commit-tree failed:"] "\n\n$err"]
ui_status {Commit failed.} ui_status [mc "Commit failed."]
unlock_index unlock_index
return return
} }
@ -365,7 +365,7 @@ A rescan will be automatically started now.
} err]} { } err]} {
catch {file delete $msg_p} catch {file delete $msg_p}
error_popup [strcat [mc "update-ref failed:"] "\n\n$err"] error_popup [strcat [mc "update-ref failed:"] "\n\n$err"]
ui_status {Commit failed.} ui_status [mc "Commit failed."]
unlock_index unlock_index
return return
} }

View File

@ -46,7 +46,9 @@ method _init {} {
-justify left \ -justify left \
-font font_uibold -font font_uibold
text $w_t \ text $w_t \
-background white -borderwidth 1 \ -background white \
-foreground black \
-borderwidth 1 \
-relief sunken \ -relief sunken \
-width 80 -height 10 \ -width 80 -height 10 \
-wrap none \ -wrap none \
@ -180,7 +182,8 @@ method done {ok} {
if {$ok} { if {$ok} {
if {[winfo exists $w.m.s]} { if {[winfo exists $w.m.s]} {
bind $w.m.s <Destroy> [list delete_this $this] bind $w.m.s <Destroy> [list delete_this $this]
$w.m.s conf -background green -text [mc "Success"] $w.m.s conf -background green -foreground black \
-text [mc "Success"]
if {$is_toplevel} { if {$is_toplevel} {
$w.ok conf -state normal $w.ok conf -state normal
focus $w.ok focus $w.ok
@ -193,7 +196,8 @@ method done {ok} {
_init $this _init $this
} }
bind $w.m.s <Destroy> [list delete_this $this] bind $w.m.s <Destroy> [list delete_this $this]
$w.m.s conf -background red -text [mc "Error: Command Failed"] $w.m.s conf -background red -foreground black \
-text [mc "Error: Command Failed"]
if {$is_toplevel} { if {$is_toplevel} {
$w.ok conf -state normal $w.ok conf -state normal
focus $w.ok focus $w.ok

View File

@ -102,8 +102,8 @@ proc hint_gc {} {
*]] *]]
if {$objects_current >= $object_limit} { if {$objects_current >= $object_limit} {
set objects_current [expr {$objects_current * 256}] set objects_current [expr {$objects_current * 250}]
set object_limit [expr {$object_limit * 256}] 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.

View File

@ -19,6 +19,7 @@ proc clear_diff {} {
proc reshow_diff {} { proc reshow_diff {} {
global file_states file_lists global file_states file_lists
global current_diff_path current_diff_side global current_diff_path current_diff_side
global ui_diff
set p $current_diff_path set p $current_diff_path
if {$p eq {}} { if {$p eq {}} {
@ -28,7 +29,8 @@ proc reshow_diff {} {
|| [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} { || [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
clear_diff clear_diff
} else { } else {
show_diff $p $current_diff_side set save_pos [lindex [$ui_diff yview] 0]
show_diff $p $current_diff_side {} $save_pos
} }
} }
@ -52,7 +54,7 @@ A rescan will be automatically started to find other files which may have the sa
rescan ui_ready 0 rescan ui_ready 0
} }
proc show_diff {path w {lno {}}} { proc show_diff {path w {lno {}} {scroll_pos {}}} {
global file_states file_lists global file_states file_lists
global is_3way_diff diff_active repo_config global is_3way_diff diff_active repo_config
global ui_diff ui_index ui_workdir global ui_diff ui_index ui_workdir
@ -151,6 +153,10 @@ proc show_diff {path w {lno {}}} {
$ui_diff conf -state disabled $ui_diff conf -state disabled
set diff_active 0 set diff_active 0
unlock_index unlock_index
if {$scroll_pos ne {}} {
update
$ui_diff yview moveto $scroll_pos
}
ui_ready ui_ready
return return
} }
@ -190,10 +196,10 @@ proc show_diff {path w {lno {}}} {
-blocking 0 \ -blocking 0 \
-encoding binary \ -encoding binary \
-translation binary -translation binary
fileevent $fd readable [list read_diff $fd] fileevent $fd readable [list read_diff $fd $scroll_pos]
} }
proc read_diff {fd} { proc read_diff {fd scroll_pos} {
global ui_diff diff_active global ui_diff diff_active
global is_3way_diff current_diff_header global is_3way_diff current_diff_header
@ -282,6 +288,10 @@ proc read_diff {fd} {
close $fd close $fd
set diff_active 0 set diff_active 0
unlock_index unlock_index
if {$scroll_pos ne {}} {
update
$ui_diff yview moveto $scroll_pos
}
ui_ready ui_ready
if {[$ui_diff index end] eq {2.0}} { if {[$ui_diff index end] eq {2.0}} {
@ -362,3 +372,148 @@ proc apply_hunk {x y} {
set current_diff_path $current_diff_path set current_diff_path $current_diff_path
} }
} }
proc apply_line {x y} {
global current_diff_path current_diff_header current_diff_side
global ui_diff ui_index file_states
if {$current_diff_path eq {} || $current_diff_header eq {}} return
if {![lock_index apply_hunk]} return
set apply_cmd {apply --cached --whitespace=nowarn}
set mi [lindex $file_states($current_diff_path) 0]
if {$current_diff_side eq $ui_index} {
set failed_msg [mc "Failed to unstage selected line."]
set to_context {+}
lappend apply_cmd --reverse
if {[string index $mi 0] ne {M}} {
unlock_index
return
}
} else {
set failed_msg [mc "Failed to stage selected line."]
set to_context {-}
if {[string index $mi 1] ne {M}} {
unlock_index
return
}
}
set the_l [$ui_diff index @$x,$y]
# operate only on change lines
set c1 [$ui_diff get "$the_l linestart"]
if {$c1 ne {+} && $c1 ne {-}} {
unlock_index
return
}
set sign $c1
set i_l [$ui_diff search -backwards -regexp ^@@ $the_l 0.0]
if {$i_l eq {}} {
unlock_index
return
}
# $i_l is now at the beginning of a line
# pick start line number from hunk header
set hh [$ui_diff get $i_l "$i_l + 1 lines"]
set hh [lindex [split $hh ,] 0]
set hln [lindex [split $hh -] 1]
# There is a special situation to take care of. Consider this hunk:
#
# @@ -10,4 +10,4 @@
# context before
# -old 1
# -old 2
# +new 1
# +new 2
# context after
#
# We used to keep the context lines in the order they appear in the
# hunk. But then it is not possible to correctly stage only
# "-old 1" and "+new 1" - it would result in this staged text:
#
# context before
# old 2
# new 1
# context after
#
# (By symmetry it is not possible to *un*stage "old 2" and "new 2".)
#
# We resolve the problem by introducing an asymmetry, namely, when
# a "+" line is *staged*, it is moved in front of the context lines
# that are generated from the "-" lines that are immediately before
# the "+" block. That is, we construct this patch:
#
# @@ -10,4 +10,5 @@
# context before
# +new 1
# old 1
# old 2
# context after
#
# But we do *not* treat "-" lines that are *un*staged in a special
# way.
#
# With this asymmetry it is possible to stage the change
# "old 1" -> "new 1" directly, and to stage the change
# "old 2" -> "new 2" by first staging the entire hunk and
# then unstaging the change "old 1" -> "new 1".
# This is non-empty if and only if we are _staging_ changes;
# then it accumulates the consecutive "-" lines (after converting
# them to context lines) in order to be moved after the "+" change
# line.
set pre_context {}
set n 0
set i_l [$ui_diff index "$i_l + 1 lines"]
set patch {}
while {[$ui_diff compare $i_l < "end - 1 chars"] &&
[$ui_diff get $i_l "$i_l + 2 chars"] ne {@@}} {
set next_l [$ui_diff index "$i_l + 1 lines"]
set c1 [$ui_diff get $i_l]
if {[$ui_diff compare $i_l <= $the_l] &&
[$ui_diff compare $the_l < $next_l]} {
# the line to stage/unstage
set ln [$ui_diff get $i_l $next_l]
if {$c1 eq {-}} {
set n [expr $n+1]
set patch "$patch$pre_context$ln"
} else {
set patch "$patch$ln$pre_context"
}
set pre_context {}
} elseif {$c1 ne {-} && $c1 ne {+}} {
# context line
set ln [$ui_diff get $i_l $next_l]
set patch "$patch$pre_context$ln"
set n [expr $n+1]
set pre_context {}
} elseif {$c1 eq $to_context} {
# turn change line into context line
set ln [$ui_diff get "$i_l + 1 chars" $next_l]
if {$c1 eq {-}} {
set pre_context "$pre_context $ln"
} else {
set patch "$patch $ln"
}
set n [expr $n+1]
}
set i_l $next_l
}
set patch "@@ -$hln,$n +$hln,[eval expr $n $sign 1] @@\n$patch"
if {[catch {
set p [eval git_write $apply_cmd]
fconfigure $p -translation binary -encoding binary
puts -nonewline $p $current_diff_header
puts -nonewline $p $patch
close $p} err]} {
error_popup [append $failed_msg "\n\n$err"]
}
unlock_index
}

View File

@ -1,6 +1,14 @@
# git-gui branch (create/delete) support # git-gui branch (create/delete) support
# Copyright (C) 2006, 2007 Shawn Pearce # Copyright (C) 2006, 2007 Shawn Pearce
proc _error_parent {} {
set p [grab current .]
if {$p eq {}} {
return .
}
return $p
}
proc error_popup {msg} { proc error_popup {msg} {
set title [appname] set title [appname]
if {[reponame] ne {}} { if {[reponame] ne {}} {
@ -11,8 +19,8 @@ proc error_popup {msg} {
-type ok \ -type ok \
-title [append "$title: " [mc "error"]] \ -title [append "$title: " [mc "error"]] \
-message $msg] -message $msg]
if {[winfo ismapped .]} { if {[winfo ismapped [_error_parent]]} {
lappend cmd -parent . lappend cmd -parent [_error_parent]
} }
eval $cmd eval $cmd
} }
@ -27,19 +35,19 @@ proc warn_popup {msg} {
-type ok \ -type ok \
-title [append "$title: " [mc "warning"]] \ -title [append "$title: " [mc "warning"]] \
-message $msg] -message $msg]
if {[winfo ismapped .]} { if {[winfo ismapped [_error_parent]]} {
lappend cmd -parent . lappend cmd -parent [_error_parent]
} }
eval $cmd eval $cmd
} }
proc info_popup {msg {parent .}} { proc info_popup {msg} {
set title [appname] set title [appname]
if {[reponame] ne {}} { if {[reponame] ne {}} {
append title " ([reponame])" append title " ([reponame])"
} }
tk_messageBox \ tk_messageBox \
-parent $parent \ -parent [_error_parent] \
-icon info \ -icon info \
-type ok \ -type ok \
-title $title \ -title $title \
@ -56,8 +64,8 @@ proc ask_popup {msg} {
-type yesno \ -type yesno \
-title $title \ -title $title \
-message $msg] -message $msg]
if {[winfo ismapped .]} { if {[winfo ismapped [_error_parent]]} {
lappend cmd -parent . lappend cmd -parent [_error_parent]
} }
eval $cmd eval $cmd
} }
@ -72,7 +80,9 @@ proc hook_failed_popup {hook msg {is_fatal 1}} {
-justify left \ -justify left \
-font font_uibold -font font_uibold
text $w.m.t \ text $w.m.t \
-background white -borderwidth 1 \ -background white \
-foreground black \
-borderwidth 1 \
-relief sunken \ -relief sunken \
-width 80 -height 10 \ -width 80 -height 10 \
-font font_diff \ -font font_diff \

View File

@ -310,7 +310,7 @@ proc add_helper {txt paths} {
update_index \ update_index \
$txt \ $txt \
$pathList \ $pathList \
[concat $after {ui_status {Ready to commit.}}] [concat $after {ui_status [mc "Ready to commit."]}]
} }
} }

View File

@ -116,8 +116,7 @@ method _start {} {
lappend cmd HEAD lappend cmd HEAD
lappend cmd $name lappend cmd $name
set msg [mc "Merging %s and %s" $current_branch $stitle] ui_status [mc "Merging %s and %s..." $current_branch $stitle]
ui_status "$msg..."
set cons [console::new [mc "Merge"] "merge $stitle"] set cons [console::new [mc "Merge"] "merge $stitle"]
console::exec $cons $cmd [cb _finish $cons] console::exec $cons $cmd [cb _finish $cons]
@ -236,7 +235,7 @@ Continue with resetting the current changes?"]
set fd [git_read --stderr read-tree --reset -u -v HEAD] set fd [git_read --stderr read-tree --reset -u -v HEAD]
fconfigure $fd -blocking 0 -translation binary fconfigure $fd -blocking 0 -translation binary
fileevent $fd readable [namespace code [list _reset_wait $fd]] fileevent $fd readable [namespace code [list _reset_wait $fd]]
$::main_status start [mc "Aborting"] {files reset} $::main_status start [mc "Aborting"] [mc "files reset"]
} else { } else {
unlock_index unlock_index
} }
@ -258,6 +257,7 @@ proc _reset_wait {fd} {
catch {file delete [gitdir MERGE_HEAD]} catch {file delete [gitdir MERGE_HEAD]}
catch {file delete [gitdir rr-cache MERGE_RR]} catch {file delete [gitdir rr-cache MERGE_RR]}
catch {file delete [gitdir MERGE_RR]}
catch {file delete [gitdir SQUASH_MSG]} catch {file delete [gitdir SQUASH_MSG]}
catch {file delete [gitdir MERGE_MSG]} catch {file delete [gitdir MERGE_MSG]}
catch {file delete [gitdir GITGUI_MSG]} catch {file delete [gitdir GITGUI_MSG]}

View File

@ -5,6 +5,7 @@ proc save_config {} {
global default_config font_descs global default_config font_descs
global repo_config global_config global repo_config global_config
global repo_config_new global_config_new global repo_config_new global_config_new
global ui_comm_spell
foreach option $font_descs { foreach option $font_descs {
set name [lindex $option 0] set name [lindex $option 0]
@ -52,11 +53,23 @@ proc save_config {} {
set repo_config($name) $value set repo_config($name) $value
} }
} }
if {[info exists repo_config(gui.spellingdictionary)]} {
set value $repo_config(gui.spellingdictionary)
if {$value eq {none}} {
if {[info exists ui_comm_spell]} {
$ui_comm_spell stop
}
} elseif {[info exists ui_comm_spell]} {
$ui_comm_spell lang $value
}
}
} }
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
array unset repo_config_new array unset repo_config_new
array unset global_config_new array unset global_config_new
@ -110,7 +123,10 @@ 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.fastcopyblame {mc "Blame Copy Only On Changed Files"}}
{i-20..200 gui.copyblamethreshold {mc "Minimum Letters To Blame Copy On"}}
{i-0..99 gui.diffcontext {mc "Number of Diff Context Lines"}} {i-0..99 gui.diffcontext {mc "Number of Diff Context Lines"}}
{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"}}
} { } {
set type [lindex $option 0] set type [lindex $option 0]
@ -159,6 +175,32 @@ proc do_options {} {
} }
} }
set all_dicts [linsert \
[spellcheck::available_langs] \
0 \
none]
incr optid
foreach f {repo global} {
if {![info exists ${f}_config_new(gui.spellingdictionary)]} {
if {[info exists ui_comm_spell]} {
set value [$ui_comm_spell lang]
} else {
set value none
}
set ${f}_config_new(gui.spellingdictionary) $value
}
frame $w.$f.$optid
label $w.$f.$optid.l -text [mc "Spelling Dictionary:"]
eval tk_optionMenu $w.$f.$optid.v \
${f}_config_new(gui.spellingdictionary) \
$all_dicts
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
}
unset all_dicts
set all_fonts [lsort [font families]] set all_fonts [lsort [font families]]
foreach option $font_descs { foreach option $font_descs {
set name [lindex $option 0] set name [lindex $option 0]

414
lib/spellcheck.tcl Normal file
View File

@ -0,0 +1,414 @@
# git-gui spellchecking support through ispell/aspell
# Copyright (C) 2008 Shawn Pearce
class spellcheck {
field s_fd {} ; # pipe to ispell/aspell
field s_version {} ; # ispell/aspell version string
field s_lang {} ; # current language code
field s_prog aspell; # are we actually old ispell?
field s_failed 0 ; # is $s_prog bogus and not working?
field w_text ; # text widget we are spelling
field w_menu ; # context menu for the widget
field s_menuidx 0 ; # last index of insertion into $w_menu
field s_i {} ; # timer registration for _run callbacks
field s_clear 0 ; # did we erase mispelled tags yet?
field s_seen [list] ; # lines last seen from $w_text in _run
field s_checked [list] ; # lines already checked
field s_pending [list] ; # [$line $data] sent to ispell/aspell
field s_suggest ; # array, list of suggestions, keyed by misspelling
constructor init {pipe_fd ui_text ui_menu} {
set w_text $ui_text
set w_menu $ui_menu
array unset s_suggest
bind_button3 $w_text [cb _popup_suggest %X %Y @%x,%y]
_connect $this $pipe_fd
return $this
}
method _connect {pipe_fd} {
fconfigure $pipe_fd \
-encoding utf-8 \
-eofchar {} \
-translation lf
if {[gets $pipe_fd s_version] <= 0} {
if {[catch {close $pipe_fd} err]} {
# Eh? Is this actually ispell choking on aspell options?
#
if {$s_prog eq {aspell}
&& [regexp -nocase {^Usage: } $err]
&& ![catch {
set pipe_fd [open [list | $s_prog -v] r]
gets $pipe_fd s_version
close $pipe_fd
}]
&& $s_version ne {}} {
if {{@(#) } eq [string range $s_version 0 4]} {
set s_version [string range $s_version 5 end]
}
set s_failed 1
error_popup [strcat \
[mc "Unsupported spell checker"] \
":\n\n$s_version"]
set s_version {}
return
}
regsub -nocase {^Error: } $err {} err
if {$s_fd eq {}} {
error_popup [strcat [mc "Spell checking is unavailable"] ":\n\n$err"]
} else {
error_popup [strcat \
[mc "Invalid spell checking configuration"] \
":\n\n$err\n\n" \
[mc "Reverting dictionary to %s." $s_lang]]
}
} else {
error_popup [mc "Spell checker silently failed on startup"]
}
return
}
if {{@(#) } ne [string range $s_version 0 4]} {
catch {close $pipe_fd}
error_popup [strcat [mc "Unrecognized spell checker"] ":\n\n$s_version"]
return
}
set s_version [string range $s_version 5 end]
regexp \
{International Ispell Version .* \(but really (Aspell .*?)\)$} \
$s_version _junk s_version
regexp {^Aspell (\d)+\.(\d+)} $s_version _junk major minor
puts $pipe_fd ! ; # enable terse mode
# fetch the language
if {$major > 0 || ($major == 0 && $minor >= 60)} {
puts $pipe_fd {$$cr master}
flush $pipe_fd
gets $pipe_fd s_lang
regexp {[/\\]([^/\\]+)\.[^\.]+$} $s_lang _ s_lang
} else {
set s_lang {}
}
if {$::default_config(gui.spellingdictionary) eq {}
&& [get_config gui.spellingdictionary] eq {}} {
set ::default_config(gui.spellingdictionary) $s_lang
}
if {$s_fd ne {}} {
catch {close $s_fd}
}
set s_fd $pipe_fd
fconfigure $s_fd -blocking 0
fileevent $s_fd readable [cb _read]
$w_text tag conf misspelled \
-foreground red \
-underline 1
array unset s_suggest
set s_seen [list]
set s_checked [list]
set s_pending [list]
_run $this
}
method lang {{n {}}} {
if {$n ne {} && $s_lang ne $n && !$s_failed} {
set spell_cmd [list |]
lappend spell_cmd aspell
lappend spell_cmd --master=$n
lappend spell_cmd --mode=none
lappend spell_cmd --encoding=UTF-8
lappend spell_cmd pipe
_connect $this [open $spell_cmd r+]
}
return $s_lang
}
method version {} {
if {$s_version ne {}} {
return "$s_version, $s_lang"
}
return {}
}
method stop {} {
while {$s_menuidx > 0} {
$w_menu delete 0
incr s_menuidx -1
}
$w_text tag delete misspelled
catch {close $s_fd}
catch {after cancel $s_i}
set s_fd {}
set s_i {}
set s_lang {}
}
method _popup_suggest {X Y pos} {
while {$s_menuidx > 0} {
$w_menu delete 0
incr s_menuidx -1
}
set b_loc [$w_text index "$pos wordstart"]
set e_loc [_wordend $this $b_loc]
set orig [$w_text get $b_loc $e_loc]
set tags [$w_text tag names $b_loc]
if {[lsearch -exact $tags misspelled] >= 0} {
if {[info exists s_suggest($orig)]} {
set cnt 0
foreach s $s_suggest($orig) {
if {$cnt < 5} {
$w_menu insert $s_menuidx command \
-label $s \
-command [cb _replace $b_loc $e_loc $s]
incr s_menuidx
incr cnt
} else {
break
}
}
} else {
$w_menu insert $s_menuidx command \
-label [mc "No Suggestions"] \
-state disabled
incr s_menuidx
}
$w_menu insert $s_menuidx separator
incr s_menuidx
}
$w_text mark set saved-insert insert
tk_popup $w_menu $X $Y
}
method _replace {b_loc e_loc word} {
$w_text configure -autoseparators 0
$w_text edit separator
$w_text delete $b_loc $e_loc
$w_text insert $b_loc $word
$w_text edit separator
$w_text configure -autoseparators 1
$w_text mark set insert saved-insert
}
method _restart_timer {} {
set s_i [after 300 [cb _run]]
}
proc _match_length {max_line arr_name} {
upvar $arr_name a
if {[llength $a] > $max_line} {
set a [lrange $a 0 $max_line]
}
while {[llength $a] <= $max_line} {
lappend a {}
}
}
method _wordend {pos} {
set pos [$w_text index "$pos wordend"]
set tags [$w_text tag names $pos]
while {[lsearch -exact $tags misspelled] >= 0} {
set pos [$w_text index "$pos +1c"]
set tags [$w_text tag names $pos]
}
return $pos
}
method _run {} {
set cur_pos [$w_text index {insert -1c}]
set cur_line [lindex [split $cur_pos .] 0]
set max_line [lindex [split [$w_text index end] .] 0]
_match_length $max_line s_seen
_match_length $max_line s_checked
# Nothing in the message buffer? Nothing to spellcheck.
#
if {$cur_line == 1
&& $max_line == 2
&& [$w_text get 1.0 end] eq "\n"} {
array unset s_suggest
_restart_timer $this
return
}
set active 0
for {set n 1} {$n <= $max_line} {incr n} {
set s [$w_text get "$n.0" "$n.end"]
# Don't spellcheck the current line unless we are at
# a word boundary. The user might be typing on it.
#
if {$n == $cur_line
&& ![regexp {^\W$} [$w_text get $cur_pos insert]]} {
# If the current word is mispelled remove the tag
# but force a spellcheck later.
#
set tags [$w_text tag names $cur_pos]
if {[lsearch -exact $tags misspelled] >= 0} {
$w_text tag remove misspelled \
"$cur_pos wordstart" \
[_wordend $this $cur_pos]
lset s_seen $n $s
lset s_checked $n {}
}
continue
}
if {[lindex $s_seen $n] eq $s
&& [lindex $s_checked $n] ne $s} {
# Don't send empty lines to Aspell it doesn't check them.
#
if {$s eq {}} {
lset s_checked $n $s
continue
}
# Don't send typical s-b-o lines as the emails are
# almost always misspelled according to Aspell.
#
if {[regexp -nocase {^[a-z-]+-by:.*<.*@.*>$} $s]} {
$w_text tag remove misspelled "$n.0" "$n.end"
lset s_checked $n $s
continue
}
puts $s_fd ^$s
lappend s_pending [list $n $s]
set active 1
} else {
# Delay until another idle loop to make sure we don't
# spellcheck lines the user is actively changing.
#
lset s_seen $n $s
}
}
if {$active} {
set s_clear 1
flush $s_fd
} else {
_restart_timer $this
}
}
method _read {} {
while {[gets $s_fd line] >= 0} {
set lineno [lindex $s_pending 0 0]
if {$s_clear} {
$w_text tag remove misspelled "$lineno.0" "$lineno.end"
set s_clear 0
}
if {$line eq {}} {
lset s_checked $lineno [lindex $s_pending 0 1]
set s_pending [lrange $s_pending 1 end]
set s_clear 1
continue
}
set sugg [list]
switch -- [string range $line 0 1] {
{& } {
set line [split [string range $line 2 end] :]
set info [split [lindex $line 0] { }]
set orig [lindex $info 0]
set offs [lindex $info 2]
foreach s [split [lindex $line 1] ,] {
lappend sugg [string range $s 1 end]
}
}
{# } {
set info [split [string range $line 2 end] { }]
set orig [lindex $info 0]
set offs [lindex $info 1]
}
default {
puts stderr "<spell> $line"
continue
}
}
incr offs -1
set b_loc "$lineno.$offs"
set e_loc [$w_text index "$lineno.$offs wordend"]
set curr [$w_text get $b_loc $e_loc]
# At least for English curr = "bob", orig = "bob's"
# so Tk didn't include the 's but Aspell did. We
# try to round out the word.
#
while {$curr ne $orig
&& [string equal -length [string length $curr] $curr $orig]} {
set n_loc [$w_text index "$e_loc +1c"]
set n_curr [$w_text get $b_loc $n_loc]
if {$n_curr eq $curr} {
break
}
set curr $n_curr
set e_loc $n_loc
}
if {$curr eq $orig} {
$w_text tag add misspelled $b_loc $e_loc
if {[llength $sugg] > 0} {
set s_suggest($orig) $sugg
} else {
unset -nocomplain s_suggest($orig)
}
} else {
unset -nocomplain s_suggest($orig)
}
}
fconfigure $s_fd -block 1
if {[eof $s_fd]} {
if {![catch {close $s_fd} err]} {
set err [mc "Unexpected EOF from spell checker"]
}
catch {after cancel $s_i}
$w_text tag remove misspelled 1.0 end
error_popup [strcat [mc "Spell Checker Failed"] "\n\n" $err]
return
}
fconfigure $s_fd -block 0
if {[llength $s_pending] == 0} {
_restart_timer $this
}
}
proc available_langs {} {
set langs [list]
catch {
set fd [open [list | aspell dump dicts] r]
while {[gets $fd line] >= 0} {
if {$line eq {}} continue
lappend langs $line
}
close $fd
}
return $langs
}
}

View File

@ -7,7 +7,7 @@ if {[string first -psn [lindex $argv 0]] == 0} {
} }
if {[file tail [lindex $argv 0]] eq {gitk}} { if {[file tail [lindex $argv 0]] eq {gitk}} {
set argv0 [file join $gitexecdir gitk] set argv0 [lindex $argv 0]
set AppMain_source $argv0 set AppMain_source $argv0
} else { } else {
set argv0 [file join $gitexecdir [file tail [lindex $argv 0]]] set argv0 [file join $gitexecdir [file tail [lindex $argv 0]]]

View File

@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>English</string> <string>English</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>Wish</string> <string>@@GITGUI_TKEXECUTABLE@@</string>
<key>CFBundleGetInfoString</key> <key>CFBundleGetInfoString</key>
<string>Git Gui @@GITGUI_VERSION@@ © 2006-2007 Shawn Pearce, et. al.</string> <string>Git Gui @@GITGUI_VERSION@@ © 2006-2007 Shawn Pearce, et. al.</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>

View File

@ -101,7 +101,7 @@ matching msgid lines. A few tips:
"printf()"-like functions. Make sure "%s", "%d", and "%%" in your "printf()"-like functions. Make sure "%s", "%d", and "%%" in your
translated messages match the original. translated messages match the original.
When you have to change the order of words, you can add "<number>\$" When you have to change the order of words, you can add "<number>$"
between '%' and the conversion ('s', 'd', etc.) to say "<number>-th between '%' and the conversion ('s', 'd', etc.) to say "<number>-th
parameter to the format string is used at this point". For example, parameter to the format string is used at this point". For example,
if the original message is like this: if the original message is like this:
@ -111,12 +111,17 @@ matching msgid lines. A few tips:
and if for whatever reason your translation needs to say weight first and if for whatever reason your translation needs to say weight first
and then length, you can say something like: and then length, you can say something like:
"WEIGHT IS %2\$d, LENGTH IS %1\$d" "WEIGHT IS %2$d, LENGTH IS %1$d"
The reason you need a backslash before dollar sign is because A format specification with a '*' (asterisk) refers to *two* arguments
this is a double quoted string in Tcl language, and without instead of one, hence the succeeding argument number is two higher
it the letter introduces a variable interpolation, which you instead of one. So, a message like this
do not want here.
"%s ... %*i of %*i %s (%3i%%)"
is equivalent to
"%1$s ... %2$*i of %4$*i %6$s (%7$3i%%)"
- A long message can be split across multiple lines by ending the - A long message can be split across multiple lines by ending the
string with a double quote, and starting another string on the next string with a double quote, and starting another string on the next
@ -178,18 +183,6 @@ step.
$ msgmerge -U po/af.po po/git-gui.pot $ msgmerge -U po/af.po po/git-gui.pot
[NEEDSWORK: who is responsible for updating po/git-gui.pot file by
running xgettext? IIRC, Christian recommended against running it
nilly-willy because it can become a source of unnecessary merge
conflicts. Perhaps we should mention something like "
The po/git-gui.pot file is updated by the internationalization
coordinator from time to time. You _could_ update it yourself, but
translators are discouraged from doing so because we would want all
language teams to be working off of the same version of git-gui.pot.
" here?]
This updates po/af.po (again, replace "af" with your language This updates po/af.po (again, replace "af" with your language
code) so that it contains msgid lines (i.e. the original) that code) so that it contains msgid lines (i.e. the original) that
your translation did not have before. There are a few things to your translation did not have before. There are a few things to
@ -207,3 +200,53 @@ watch out for:
- New messages added to the software will have msgstr lines with empty - New messages added to the software will have msgstr lines with empty
strings. You would need to translate them. strings. You would need to translate them.
The po/git-gui.pot file is updated by the internationalization
coordinator from time to time. You _could_ update it yourself, but
translators are discouraged from doing so because we would want all
language teams to be working off of the same version of git-gui.pot.
****************************************************************
This section is a note to the internationalization coordinator, and
translators do not have to worry about it too much.
The message template file po/git-gui.pot needs to be kept up to date
relative to the software the translations apply to, and it is the
responsibility of the internationalization coordinator.
When updating po/git-gui.pot file, however, _never_ run "msgmerge -U
po/xx.po" for individual language translations, unless you are absolutely
sure that there is no outstanding work on translation for language xx.
Doing so will create unnecessary merge conflicts and force needless
re-translation on translators. The translator however may not have access
to the msgmerge tool, in which case the coordinator may run it for the
translator as a service.
But mistakes do happen. Suppose a translation was based on an older
version X, the POT file was updated at version Y and then msgmerge was run
at version Z for the language, and the translator sent in a patch based on
version X:
? translated
/
---X---Y---Z (master)
The coordinator could recover from such a mistake by first applying the
patch to X, replace the translated file in Z, and then running msgmerge
again based on the updated POT file and commit the result. The sequence
would look like this:
$ git checkout X
$ git am -s xx.patch
$ git checkout master
$ git checkout HEAD@{1} po/xx.po
$ msgmerge -U po/xx.po po/git-gui.pot
$ git commit -c HEAD@{1} po/xx.po
State in the message that the translated messages are based on a slightly
older version, and msgmerge was run to incorporate changes to message
templates from the updated POT file. The result needs to be further
translated, but at least the messages that were updated by the patch that
were not changed by the POT update will survive the process and do not
need to be re-translated.

734
po/de.po

File diff suppressed because it is too large Load Diff

693
po/fr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: git-gui glossary\n" "Project-Id-Version: git-gui glossary\n"
"POT-Creation-Date: 2008-01-07 21:20+0100\n" "POT-Creation-Date: 2008-01-07 21:20+0100\n"
"PO-Revision-Date: 2008-01-15 20:32+0100\n" "PO-Revision-Date: 2008-02-16 21:48+0100\n"
"Last-Translator: Christian Stimming <stimming@tuhh.de>\n" "Last-Translator: Christian Stimming <stimming@tuhh.de>\n"
"Language-Team: German \n" "Language-Team: German \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -114,7 +114,7 @@ msgstr "Beschreibung (Meldung?, Nachricht?; Source Safe: Kommentar)"
#. "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>'." #. "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" msgid "prune"
msgstr "entfernen" msgstr "aufräumen (entfernen?)"
#. "Pulling a branch means to fetch it and merge it." #. "Pulling a branch means to fetch it and merge it."
msgid "pull" msgid "pull"

624
po/hu.po

File diff suppressed because it is too large Load Diff

731
po/it.po

File diff suppressed because it is too large Load Diff

747
po/ja.po

File diff suppressed because it is too large Load Diff

610
po/ru.po

File diff suppressed because it is too large Load Diff

792
po/sv.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -8,9 +8,12 @@ if { $argc >=2 && [lindex $argv 0] == "--working-dir" } {
incr argc -2 incr argc -2
} }
set gitguidir [file dirname [info script]] set bindir [file dirname \
regsub -all ";" $gitguidir "\\;" gitguidir [file dirname \
set env(PATH) "$gitguidir;$env(PATH)" [file dirname [info script]]]]
unset gitguidir set bindir [file join $bindir bin]
regsub -all ";" $bindir "\\;" bindir
set env(PATH) "$bindir;$env(PATH)"
unset bindir
source [file join [file dirname [info script]] git-gui.tcl] source [file join [file dirname [info script]] git-gui.tcl]