Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2657c59ad | ||
|
|
c6b12a1442 | ||
|
|
fc805e5dd3 | ||
|
|
e7a80fee43 | ||
|
|
44ed8ab3bf | ||
|
|
c5b0ecd991 | ||
|
|
5d437b618b | ||
|
|
9a1f2a7fa6 | ||
|
|
73ecfad626 | ||
|
|
dc7d7b0edf | ||
|
|
166b38543b | ||
|
|
d1d3b93da3 | ||
|
|
369ae9fbc3 | ||
|
|
761ede3ce3 | ||
|
|
37a01c1372 | ||
|
|
273be07870 | ||
|
|
789cdd388f | ||
|
|
540bb69c65 | ||
|
|
35e9fb7e8f | ||
|
|
2459017e15 | ||
|
|
8cfbdc740a | ||
|
|
3c3a08081b | ||
|
|
b272078cf6 | ||
|
|
80f22bf71f | ||
|
|
30a6c67d05 | ||
|
|
ae43deba34 | ||
|
|
bd0f10bd4e | ||
|
|
95dec436a8 | ||
|
|
aed58632e7 | ||
|
|
9cde7c554b | ||
|
|
7715361133 | ||
|
|
38be16d8bb | ||
|
|
43d9101681 | ||
|
|
52a0d1fd07 | ||
|
|
5735f747f7 | ||
|
|
44a508004d | ||
|
|
5cbaed0f64 | ||
|
|
9bf49779f2 | ||
|
|
9448492a74 | ||
|
|
a542351b8d | ||
|
|
62a7ab1be1 | ||
|
|
be70329b11 | ||
|
|
8a1ecb8743 | ||
|
|
8d8922f52b | ||
|
|
88ad1302c7 | ||
|
|
fd3a43bef1 | ||
|
|
90e23ce2fd | ||
|
|
250282933a | ||
|
|
27a7e19a1e | ||
|
|
f18b101db0 | ||
|
|
88e9431a62 | ||
|
|
3ed716233b | ||
|
|
09b4384705 | ||
|
|
f31d7bd3b9 | ||
|
|
ddb19ffee5 | ||
|
|
95bd9b73d7 | ||
|
|
cffa5f4894 | ||
|
|
117aa32f12 | ||
|
|
4c218fe4c1 | ||
|
|
e2efc30125 | ||
|
|
aecfd3dbd9 | ||
|
|
2612b3a3d9 | ||
|
|
dda2f83805 | ||
|
|
c8c4838f48 | ||
|
|
1e35239366 | ||
|
|
2e52b5735d | ||
|
|
07bd56e25c | ||
|
|
28f2099bc2 | ||
|
|
a8ce54473c | ||
|
|
3631deb20c | ||
|
|
854e1cb81d | ||
|
|
7a49d47d86 | ||
|
|
dd8cd024e1 | ||
|
|
6d8bbd16bd | ||
|
|
0fe0bd3828 | ||
|
|
6d04408ecc | ||
|
|
04def89eb2 |
@@ -0,0 +1,2 @@
|
||||
David Martínez Martí <deavidsedice@gmail.com>
|
||||
David Aguilar <davvid@gmail.com>
|
||||
@@ -9,28 +9,28 @@ If you downloaded a tarball add /path/to/cola/bin to your $PATH.
|
||||
|
||||
|
||||
REQUIREMENTS
|
||||
# apt-get install git-core python python-qt4
|
||||
|
||||
Python 2.4 or newer
|
||||
http://python.org/
|
||||
apt-get install python
|
||||
|
||||
PyQt 4.3 or newer
|
||||
http://www.riverbankcomputing.co.uk/software/pyqt/intro
|
||||
apt-get install pyqt4-dev-tools
|
||||
|
||||
|
||||
ADDITIONAL REQUIREMENTS (optional)
|
||||
# apt-get install python-pyinotify simplejson
|
||||
|
||||
pyinotify (enables inotify support on Linux -- highly recommended)
|
||||
http://pyinotify.sourceforge.net/
|
||||
apt-get install python-pyinotify
|
||||
|
||||
simplejson (enables bookmarks)
|
||||
http://pypi.python.org/pypi/simplejson
|
||||
apt-get install python-simplejson
|
||||
|
||||
|
||||
|
||||
BUILDING FROM SOURCE
|
||||
# apt-get install pyqt4-dev-tools
|
||||
|
||||
Normally you can just do "make install" to install git-cola
|
||||
in your $HOME directory ($HOME/bin, $HOME/lib, etc).
|
||||
@@ -46,87 +46,31 @@ modifying the code.
|
||||
$ make
|
||||
$ bin/git-cola
|
||||
|
||||
If you're developing cola on windows then you can do:
|
||||
|
||||
BUILD ISSUES
|
||||
|
||||
Some systems have pyuic4 scripts that are missing the shebang line.
|
||||
If your version of $(wich pyuic4) looks like:
|
||||
|
||||
exec python /path/to/pyuic4.py ...
|
||||
|
||||
Then simply add this line to the top of the file:
|
||||
|
||||
#!/bin/sh
|
||||
|
||||
That will fix the build by making pyuic4 a proper shell script.
|
||||
|
||||
|
||||
PYQT4 ISSUES
|
||||
|
||||
An older version of pyuic4 generated code that could not be
|
||||
run by PyQt4. This problem has been fixed in the latest
|
||||
versions of PyQt4 (4.4.x), but you might encounter it if
|
||||
you are not running the latest version of PyQt4.
|
||||
|
||||
If you try to run git-cola and see error messages
|
||||
about "setSortingEnabled(..)" then your pyuic4/PyQt4
|
||||
version is affected. There's a simple workaround, though:
|
||||
remove the line of code listed in the traceback and
|
||||
everything should work fine.
|
||||
|
||||
|
||||
PYUIC4 AND WINDOWS
|
||||
|
||||
To build cola on windows you'll need to add the following
|
||||
shell script to a directory in your path and name it 'pyuic4':
|
||||
|
||||
#+-------------------------------------------------------------
|
||||
|
||||
#!/bin/sh
|
||||
/c/Python25/python.exe \
|
||||
/c/Python25/Lib/site-packages/PyQt4/uic/pyuic.py "$@"
|
||||
|
||||
#+-------------------------------------------------------------
|
||||
$ python setup.py build
|
||||
$ win32/cola
|
||||
|
||||
|
||||
WINDOWS INSTALLATION
|
||||
|
||||
1) Install the native Python2.5 and PyQt4 installers (in that order):
|
||||
|
||||
Install Git, Python, and PyQt4
|
||||
http://git.or.cz/gitwiki/WindowsInstall
|
||||
http://python.org/download/
|
||||
http://www.riverbankcomputing.co.uk/pyqt/download.php
|
||||
|
||||
3) Install msysgit:
|
||||
|
||||
http://git.or.cz/gitwiki/WindowsInstall
|
||||
|
||||
4) Install the GnuWin32 'file' command:
|
||||
|
||||
http://gnuwin32.sourceforge.net/packages/file.htm
|
||||
|
||||
Add the installed directory (default: c:\GnuWin32\bin) to your path.
|
||||
|
||||
5) Install simplejson
|
||||
|
||||
Install simplejson (optional)
|
||||
http://pypi.python.org/pypi/simplejson
|
||||
|
||||
6) Download cola:
|
||||
Install and run cola from a Git bash:
|
||||
http://cola.tuxfamily.org/releases/win32/
|
||||
|
||||
http://cola.tuxfamily.org/releases/
|
||||
$ tar xvfz cola-*.tar.gz
|
||||
$ cola-*/bin/cola
|
||||
|
||||
7) Install cola (from a Git Bash):
|
||||
If you add the cola-*/bin directory to your $PATH then
|
||||
you can launch cola by simply typing 'cola'.
|
||||
|
||||
cd /c/Python25/Lib/site-packages
|
||||
tar xvfz /path/to/cola-*-win32.tar.gz
|
||||
mv cola-*-win32 cola
|
||||
|
||||
8) Create an executable in your path for bash, cmd.exe, or both:
|
||||
|
||||
echo '/c/Python25/python.exe /c/Python25/Lib/site-packages/cola/bin/git-cola' >> /usr/bin/cola
|
||||
echo 'c:\\Python25\\python.exe c:\\Python25\\Lib\\site-packages\\cola\\bin\\git-cola' > /c/Windows/System32/cola.bat
|
||||
|
||||
This assumes the you have Python/PyQt4 installed in C:/Python25.
|
||||
If this is not the case simply edit the commands accordingly.
|
||||
|
||||
voila, cola on Windows.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ all:
|
||||
|
||||
install:
|
||||
$(PYTHON) setup.py install --prefix=$(prefix) --root=$(DESTDIR) --force
|
||||
cd $(DESTDIR)$(prefix)/bin && rm -f cola && ln -s git-cola cola
|
||||
cd $(DESTDIR)$(prefix)/bin && ((! test -e cola && ln -s git-cola cola) || true)
|
||||
|
||||
doc:
|
||||
cd share/doc/cola && $(MAKE) all
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
git cola: a highly caffeinated git gui
|
||||
|
||||
Cola is a sweet, carbonated git gui known for its
|
||||
cola is a sweet, carbonated git gui known for its
|
||||
sugary flavour and caffeine-inspired features.
|
||||
|
||||
|
||||
Copyright (C) 2008 David Aguilar and contributors
|
||||
Copyright (C) 2009 David Aguilar and contributors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
# This should work if used with both the default Python2.5
|
||||
# from python.org and the default PyQt4 binary package
|
||||
# from Riverbank. Adjust accordingly.
|
||||
DIR=$(dirname "$0")
|
||||
c:/Python25/python.exe "$DIR"/git-cola
|
||||
+9
-7
@@ -39,13 +39,15 @@ if bin in ('bin', 'Scripts') and prefix != sys.prefix:
|
||||
sys.prefix = prefix
|
||||
sys.exec_prefix = prefix
|
||||
|
||||
major, minor = sys.version_info[0:2]
|
||||
local_path = [os.path.join(prefix, 'lib', 'python%s.%s' % (major, minor),
|
||||
'site-packages'),
|
||||
os.path.join(prefix, 'Lib', 'site-packages'),
|
||||
prefix,
|
||||
os.getcwd(),
|
||||
]
|
||||
paths_to_try = [
|
||||
os.path.join(prefix, 'lib', 'python2.6', 'site-packages'),
|
||||
os.path.join(prefix, 'lib', 'python2.5', 'site-packages'),
|
||||
os.path.join(prefix, 'lib', 'python2.4', 'site-packages'),
|
||||
prefix,
|
||||
os.getcwd(),
|
||||
]
|
||||
|
||||
local_path = [p for p in paths_to_try if os.path.exists(p)]
|
||||
sys.path = local_path + sys.path
|
||||
|
||||
from cola.main import main
|
||||
|
||||
+62
-565
@@ -1,576 +1,73 @@
|
||||
#!/bin/sh
|
||||
#!/usr/bin/env perl
|
||||
# Copyright (c) 2009 David Aguilar
|
||||
#
|
||||
# This program uses merge tools to stage and compare commits
|
||||
#
|
||||
# Copyright (c) 2008 David Aguilar
|
||||
#
|
||||
# Adapted from git-mergetool.sh
|
||||
# Copyright (c) 2006 Theodore Y. Ts'o
|
||||
#
|
||||
# This file is licensed under the GPL v2, or a later version
|
||||
#
|
||||
USAGE='
|
||||
[--tool=tool] [--no-prompt]
|
||||
[--commit=ref] [--start=ref --end=ref]
|
||||
[--] [file to view] ...'
|
||||
SUBDIRECTORY_OK=Yes
|
||||
OPTIONS_SPEC=
|
||||
. git-sh-setup
|
||||
require_work_tree
|
||||
cd_to_toplevel
|
||||
# This is a wrapper around the GIT_EXTERNAL_DIFF-compatible
|
||||
# git-difftool-helper script. This script exports
|
||||
# GIT_EXTERNAL_DIFF and GIT_PAGER for use by git, and
|
||||
# GIT_DIFFTOOL_NO_PROMPT and GIT_MERGE_TOOL for use by git-difftool-helper.
|
||||
# Any arguments that are unknown to this script are forwarded to 'git diff'.
|
||||
|
||||
keep_backup_mode="$(git config --bool merge.keepBackup || echo true)"
|
||||
PREFIX=.git-difftool."$$"."$(date +%N)".
|
||||
FILEDIR=
|
||||
use strict;
|
||||
use warnings;
|
||||
use Cwd qw(abs_path);
|
||||
use File::Basename qw(dirname);
|
||||
|
||||
keep_backup () {
|
||||
# whether to keep the .orig file
|
||||
test "$keep_backup_mode" = "true"
|
||||
my $DIR = abs_path(dirname($0));
|
||||
|
||||
|
||||
sub usage
|
||||
{
|
||||
print << 'USAGE';
|
||||
usage: git difftool [--tool=<tool>] [--no-prompt] ["git diff" options]
|
||||
USAGE
|
||||
exit 1;
|
||||
}
|
||||
|
||||
parse_arg () {
|
||||
# parses --foo=BAR
|
||||
expr "z$1" : 'z-[^=]*=\(.*\)'
|
||||
sub setup_environment
|
||||
{
|
||||
$ENV{PATH} = "$DIR:$ENV{PATH}";
|
||||
$ENV{GIT_PAGER} = '';
|
||||
$ENV{GIT_EXTERNAL_DIFF} = 'git-difftool-helper';
|
||||
}
|
||||
|
||||
index_present () {
|
||||
# does the index contain staged changes?
|
||||
test -n "$index_mode"
|
||||
sub exe
|
||||
{
|
||||
my $exe = shift;
|
||||
return defined $ENV{COMSPEC} ? "$exe.exe" : $exe;
|
||||
}
|
||||
|
||||
modified_present () {
|
||||
# are there changes in the requested comparison?
|
||||
test -n "$modified_mode"
|
||||
sub generate_command
|
||||
{
|
||||
my @command = (exe('git'), 'diff');
|
||||
my $skip_next = 0;
|
||||
my $idx = -1;
|
||||
for my $arg (@ARGV) {
|
||||
$idx++;
|
||||
if ($skip_next) {
|
||||
$skip_next = 0;
|
||||
next;
|
||||
}
|
||||
if ($arg eq '-t' or $arg eq '--tool') {
|
||||
usage() if $#ARGV <= $idx;
|
||||
$ENV{GIT_MERGE_TOOL} = $ARGV[$idx + 1];
|
||||
$skip_next = 1;
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^--tool=/) {
|
||||
$ENV{GIT_MERGE_TOOL} = substr($arg, 7);
|
||||
next;
|
||||
}
|
||||
if ($arg eq '--no-prompt') {
|
||||
$ENV{GIT_DIFFTOOL_NO_PROMPT} = 'true';
|
||||
next;
|
||||
}
|
||||
if ($arg eq '-h' or $arg eq '--help') {
|
||||
usage();
|
||||
}
|
||||
push @command, $arg;
|
||||
}
|
||||
return @command
|
||||
}
|
||||
|
||||
commitish_present () {
|
||||
# are we comparing against an arbitrary commit?
|
||||
test -n "$commitish"
|
||||
}
|
||||
|
||||
should_prompt () {
|
||||
# are we running interactively?
|
||||
! test -n "$no_prompt"
|
||||
}
|
||||
|
||||
use_rev_range () {
|
||||
# are we using --start=REF and --end=REF
|
||||
test -n "$start" && test -n "$end"
|
||||
}
|
||||
|
||||
merge_dir_missing () {
|
||||
# does dirname($MERGED) exist in the work tree?
|
||||
test -n "$non_existant_dir"
|
||||
}
|
||||
|
||||
base_present () {
|
||||
# whether we have 3 things to compare (index, worktree, other)
|
||||
index_present && modified_present && ! use_rev_range
|
||||
}
|
||||
|
||||
modified_files () {
|
||||
# returns the appopriate list of differences based on the mode
|
||||
if use_rev_range; then
|
||||
git diff --name-only "$start".."$end" -- "$@" 2>/dev/null
|
||||
elif commitish_present; then
|
||||
git diff --name-only "$commitish" -- "$@" 2>/dev/null
|
||||
else
|
||||
git diff --name-only -- "$@" 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
staged_files() {
|
||||
# returns any staged changes
|
||||
git diff --name-only --cached "$@" 2>/dev/null
|
||||
}
|
||||
|
||||
cleanup_temp_files () {
|
||||
# removes temporary files
|
||||
if test -n "$MERGED"; then
|
||||
if keep_backup && test "$MERGED" -nt "$BACKUP"; then
|
||||
test -f "$BACKUP" && mv -- "$BACKUP" "$MERGED.orig"
|
||||
rm -f -- "$LOCAL" "$REMOTE" "$BASE"
|
||||
else
|
||||
rm -f -- "$LOCAL" "$REMOTE" "$BASE" "$BACKUP"
|
||||
fi
|
||||
test -n "$MERGEDIR" && rmdir -p "$MERGEDIR"
|
||||
fi
|
||||
}
|
||||
|
||||
sigint_handler () {
|
||||
echo
|
||||
cleanup_temp_files
|
||||
exit 1
|
||||
}
|
||||
|
||||
merge_file () {
|
||||
# prepares temporary files and launches the appropriate merge tool
|
||||
MERGED="$1"
|
||||
|
||||
modified_mode=$(modified_files "$MERGED")
|
||||
index_mode=$(staged_files "$MERGED")
|
||||
|
||||
if ! modified_present && use_rev_range; then
|
||||
echo "$MERGED: no changes between '$start' and '$end'."
|
||||
exit 1
|
||||
elif ! modified_present && ! index_present; then
|
||||
if ! test -f "$MERGED"; then
|
||||
echo "$MERGED: file not found"
|
||||
else
|
||||
echo "$MERGED: file is unchanged."
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# handle comparing a file that doesn't exist in the current checkout
|
||||
MERGEDIR=$(dirname "$MERGED")
|
||||
non_existant_dir=
|
||||
test -d "$MERGEDIR" || non_existant_dir=true
|
||||
if merge_dir_missing; then
|
||||
mkdir -p -- "$MERGEDIR"
|
||||
else
|
||||
MERGEDIR=
|
||||
fi
|
||||
|
||||
ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
|
||||
BACKUP="./$MERGED.BACKUP.$ext"
|
||||
test -f "$MERGED" && cp -- "$MERGED" "$BACKUP"
|
||||
|
||||
if use_rev_range; then
|
||||
# we're comparing two arbitrary commits
|
||||
BASE="./$MERGED.CURRENT.$ext"
|
||||
LOCAL="./$MERGED.START.$ext"
|
||||
REMOTE="./$MERGED.END.$ext"
|
||||
base=current
|
||||
local=start
|
||||
remote=end
|
||||
touch "$BASE"
|
||||
touch "$LOCAL"
|
||||
touch "$REMOTE"
|
||||
|
||||
# detects renames.. sweet!
|
||||
oldname=$(git diff --follow "$start".."$end" -- "$MERGED" |
|
||||
head -n9 |
|
||||
grep '^rename from' |
|
||||
sed -e 's/rename from //')
|
||||
startname="$MERGED"
|
||||
test -n "$oldname" && startname="$oldname"
|
||||
|
||||
if ! git show "$start":"$startname" > "$LOCAL" 2>/dev/null; then
|
||||
if should_prompt; then
|
||||
printf "\nWarning: "
|
||||
printf "'$startname' does not exist at $start.\n"
|
||||
fi
|
||||
else
|
||||
cp -- "$LOCAL" "$BASE"
|
||||
fi
|
||||
if ! git show "$end":"$MERGED" > "$REMOTE" 2>/dev/null; then
|
||||
if should_prompt; then
|
||||
printf "\nWarning: "
|
||||
printf "'$MERGED' does not exist at $end.\n"
|
||||
fi
|
||||
else
|
||||
! test -f "$BASE" && cp -- "$REMOTE" "$BASE"
|
||||
fi
|
||||
|
||||
# $BASE could be used by custom mergetool commands
|
||||
if test -f "$MERGED"; then
|
||||
cp -- "$MERGED" "$BASE"
|
||||
fi
|
||||
else
|
||||
# We're either comparing against the index or an
|
||||
# arbitrary commit.
|
||||
# The goal is to re-use existing mergetool.$tool.cmd
|
||||
# configurations so we provide $BASE $LOCAL and $REMOTE
|
||||
if commitish_present; then
|
||||
HEAD=OTHER
|
||||
local=Other
|
||||
else
|
||||
HEAD=HEAD
|
||||
local=Index
|
||||
fi
|
||||
base=${commitish-HEAD}
|
||||
remote=Current
|
||||
BASE="./$MERGED.$HEAD.$ext"
|
||||
LOCAL="./$MERGED.INDEX.$ext"
|
||||
REMOTE="./$MERGED.CURRENT.$ext"
|
||||
touch "$BASE"
|
||||
touch "$LOCAL"
|
||||
touch "$REMOTE"
|
||||
if ! git show "$base":"$MERGED" > "$BASE" 2>&1; then
|
||||
printf "\nWarning: "
|
||||
printf "'$MERGED' does not exist at $base.\n"
|
||||
else
|
||||
cp "$BASE" "$LOCAL"
|
||||
if commitish_present; then
|
||||
rm -f "$LOCAL"
|
||||
LOCAL="$BASE"
|
||||
fi
|
||||
fi
|
||||
# If changes are present in the index use them as $LOCAL
|
||||
# but only if $MERGED exists at $base
|
||||
if ! commitish_present; then
|
||||
git checkout-index --prefix="$PREFIX" "$MERGED"
|
||||
if test -f "$PREFIX""$MERGED"; then
|
||||
mv -- "$PREFIX""$MERGED" "$LOCAL"
|
||||
tmpdir=$(dirname "$PREFIX""$MERGED")
|
||||
test -d "$tmpdir" &&
|
||||
test "$tmpdir" != "." &&
|
||||
rmdir -p "$tmpdir"
|
||||
else
|
||||
index_mode=
|
||||
fi
|
||||
else
|
||||
index_mode=
|
||||
fi
|
||||
if test -f "$MERGED"; then
|
||||
cp -- "$MERGED" "$REMOTE"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ensure that we clean up after ourselves
|
||||
trap sigint_handler SIGINT
|
||||
|
||||
if should_prompt; then
|
||||
printf "\nEditing: '$MERGED'\n"
|
||||
printf "Hit return to launch '%s': " "$merge_tool"
|
||||
read ans
|
||||
fi
|
||||
|
||||
case "$merge_tool" in
|
||||
kdiff3)
|
||||
basename=$(basename "$MERGED")
|
||||
if base_present; then
|
||||
(
|
||||
"$merge_tool_path" --auto \
|
||||
--L1 "($base) $basename" \
|
||||
--L2 "($local) $basename" \
|
||||
--L3 "($remote) $basename" \
|
||||
-o "$MERGED" "$BASE" "$LOCAL" "$REMOTE" \
|
||||
> /dev/null 2>&1
|
||||
)
|
||||
else
|
||||
(
|
||||
"$merge_tool_path" --auto \
|
||||
--L1 "($local) $basename" \
|
||||
--L2 "($remote) $basename" \
|
||||
-o "$MERGED" "$LOCAL" "$REMOTE" \
|
||||
> /dev/null 2>&1
|
||||
)
|
||||
fi
|
||||
;;
|
||||
|
||||
tkdiff)
|
||||
if base_present; then
|
||||
"$merge_tool_path" \
|
||||
-a "$BASE" \
|
||||
-o "$MERGED" "$LOCAL" "$REMOTE"
|
||||
else
|
||||
"$merge_tool_path" \
|
||||
-o "$MERGED" "$LOCAL" "$REMOTE"
|
||||
fi
|
||||
;;
|
||||
|
||||
meld)
|
||||
"$merge_tool_path" "$LOCAL" "$MERGED"
|
||||
;;
|
||||
|
||||
vimdiff)
|
||||
if base_present; then
|
||||
"$merge_tool_path" "$BASE" "$LOCAL" "$MERGED"
|
||||
else
|
||||
"$merge_tool_path" "$LOCAL" "$MERGED"
|
||||
fi
|
||||
;;
|
||||
|
||||
gvimdiff)
|
||||
if base_present; then
|
||||
"$merge_tool_path" -f "$BASE" "$LOCAL" "$MERGED"
|
||||
else
|
||||
"$merge_tool_path" -f "$LOCAL" "$MERGED"
|
||||
fi
|
||||
;;
|
||||
|
||||
xxdiff)
|
||||
if base_present; then
|
||||
"$merge_tool_path" -X --show-merged-pane \
|
||||
-R 'Accel.SaveAsMerged: "Ctrl-S"' \
|
||||
-R 'Accel.Search: "Ctrl+F"' \
|
||||
-R 'Accel.SearchForward: "Ctrl-G"' \
|
||||
--merged-file "$MERGED" \
|
||||
"$BASE" "$LOCAL" "$REMOTE"
|
||||
else
|
||||
"$merge_tool_path" -X --show-merged-pane \
|
||||
-R 'Accel.SaveAsMerged: "Ctrl-S"' \
|
||||
-R 'Accel.Search: "Ctrl+F"' \
|
||||
-R 'Accel.SearchForward: "Ctrl-G"' \
|
||||
--merged-file "$MERGED" \
|
||||
"$LOCAL" "$REMOTE"
|
||||
fi
|
||||
;;
|
||||
|
||||
opendiff)
|
||||
if base_present; then
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE" \
|
||||
-ancestor "$BASE" \
|
||||
-merge "$MERGED" | cat
|
||||
else
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE" \
|
||||
-merge "$MERGED" | cat
|
||||
fi
|
||||
;;
|
||||
|
||||
ecmerge)
|
||||
if base_present; then
|
||||
"$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" \
|
||||
--default --mode=merge3 --to="$MERGED"
|
||||
else
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE" \
|
||||
--default --mode=merge2 --to="$MERGED"
|
||||
fi
|
||||
;;
|
||||
|
||||
emerge)
|
||||
if base_present; then
|
||||
"$merge_tool_path" \
|
||||
-f emerge-files-with-ancestor-command \
|
||||
"$LOCAL" "$REMOTE" "$BASE" \
|
||||
"$(basename "$MERGED")"
|
||||
else
|
||||
"$merge_tool_path" -f emerge-files-command \
|
||||
"$LOCAL" "$REMOTE" "$(basename "$MERGED")"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if test -n "$merge_tool_cmd"; then
|
||||
if test "$merge_tool_trust_exit_code" = "false"; then
|
||||
( eval $merge_tool_cmd )
|
||||
else
|
||||
( eval $merge_tool_cmd )
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
cleanup_temp_files
|
||||
}
|
||||
|
||||
while test $# != 0
|
||||
do
|
||||
case "$1" in
|
||||
-t|--tool*)
|
||||
case "$#,$1" in
|
||||
*,*=*)
|
||||
merge_tool=$(parse_arg "$1")
|
||||
shift
|
||||
;;
|
||||
1,*)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
merge_tool="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-c|--commit*)
|
||||
case "$#,$1" in
|
||||
*,*=*)
|
||||
commitish=$(parse_arg "$1")
|
||||
shift
|
||||
;;
|
||||
1,*)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
commitish="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-s|--start*)
|
||||
case "$#,$1" in
|
||||
*,*=*)
|
||||
start=$(parse_arg "$1")
|
||||
shift
|
||||
;;
|
||||
1,*)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
start="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-e|--end*)
|
||||
case "$#,$1" in
|
||||
*,*=*)
|
||||
end=$(parse_arg "$1")
|
||||
shift
|
||||
;;
|
||||
1,*)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
end="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
--no-prompt)
|
||||
no_prompt=true
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
valid_custom_tool() {
|
||||
merge_tool_cmd="$(git config mergetool.$1.cmd)"
|
||||
test -n "$merge_tool_cmd"
|
||||
}
|
||||
|
||||
valid_tool() {
|
||||
case "$1" in
|
||||
kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge)
|
||||
;; # happy
|
||||
*)
|
||||
if ! valid_custom_tool "$1"
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
init_merge_tool_path() {
|
||||
merge_tool_path=$(git config mergetool."$1".path)
|
||||
if test -z "$merge_tool_path"; then
|
||||
case "$1" in
|
||||
emerge)
|
||||
merge_tool_path=emacs
|
||||
;;
|
||||
*)
|
||||
merge_tool_path="$1"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
if test -z "$merge_tool"; then
|
||||
merge_tool=$(git config merge.tool)
|
||||
if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
|
||||
echo >&2 "git config option merge.tool set to unknown tool: $merge_tool"
|
||||
echo >&2 "Resetting to default..."
|
||||
unset merge_tool
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$merge_tool"; then
|
||||
if test -n "$DISPLAY"; then
|
||||
merge_tool_candidates="kdiff3 tkdiff xxdiff meld gvimdiff"
|
||||
if test -n "$GNOME_DESKTOP_SESSION_ID"; then
|
||||
merge_tool_candidates="meld $merge_tool_candidates"
|
||||
fi
|
||||
if test "$KDE_FULL_SESSION" = "true"; then
|
||||
merge_tool_candidates="kdiff3 $merge_tool_candidates"
|
||||
fi
|
||||
fi
|
||||
|
||||
if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then
|
||||
merge_tool_candidates="$merge_tool_candidates emerge"
|
||||
fi
|
||||
|
||||
if echo "${VISUAL:-$EDITOR}" | grep 'vim' > /dev/null 2>&1; then
|
||||
merge_tool_candidates="$merge_tool_candidates vimdiff"
|
||||
fi
|
||||
|
||||
merge_tool_candidates="$merge_tool_candidates opendiff emerge vimdiff"
|
||||
echo "merge tool candidates: $merge_tool_candidates"
|
||||
|
||||
for i in $merge_tool_candidates
|
||||
do
|
||||
init_merge_tool_path $i
|
||||
if type "$merge_tool_path" > /dev/null 2>&1; then
|
||||
merge_tool=$i
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if test -z "$merge_tool" ; then
|
||||
echo "No known merge resolution program available."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
if ! valid_tool "$merge_tool"; then
|
||||
echo >&2 "Unknown merge tool $merge_tool"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
init_merge_tool_path "$merge_tool"
|
||||
|
||||
if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then
|
||||
echo "The merge tool $merge_tool is not available as '$merge_tool_path'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! test -z "$merge_tool_cmd"; then
|
||||
merge_tool_trust_exit_code="$(git config --bool mergetool.$merge_tool.trustExitCode || echo false)"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if test $# -eq 0; then
|
||||
use_index=0
|
||||
files=$(modified_files)
|
||||
|
||||
if test -z "$files"; then
|
||||
use_index=1
|
||||
files=$(staged_files)
|
||||
fi
|
||||
|
||||
if test -z "$files"; then
|
||||
echo "No modified files exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
if test $use_index -eq 0; then
|
||||
modified_files |
|
||||
while IFS= read i
|
||||
do
|
||||
merge_file "$i" < /dev/tty > /dev/tty
|
||||
done
|
||||
elif ! use_rev_range; then
|
||||
staged_files |
|
||||
while IFS= read i
|
||||
do
|
||||
merge_file "$i" < /dev/tty > /dev/tty
|
||||
done
|
||||
else
|
||||
echo "Nothing to compare."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
while test $# -gt 0
|
||||
do
|
||||
merge_file "$1"
|
||||
shift
|
||||
done
|
||||
fi
|
||||
exit 0
|
||||
setup_environment();
|
||||
exec(generate_command());
|
||||
|
||||
Executable
+243
@@ -0,0 +1,243 @@
|
||||
#!/bin/sh
|
||||
# git-difftool-helper is a GIT_EXTERNAL_DIFF-compatible diff tool launcher.
|
||||
# It supports kdiff3, tkdiff, xxdiff, meld, opendiff, emerge, ecmerge,
|
||||
# vimdiff, gvimdiff, and custom user-configurable tools.
|
||||
# This script is typically launched by using the 'git difftool'
|
||||
# convenience command.
|
||||
#
|
||||
# Copyright (c) 2009 David Aguilar
|
||||
|
||||
# Set GIT_DIFFTOOL_NO_PROMPT to bypass the per-file prompt.
|
||||
should_prompt () {
|
||||
! test -n "$GIT_DIFFTOOL_NO_PROMPT"
|
||||
}
|
||||
|
||||
# Should we keep the backup .orig file?
|
||||
keep_backup_mode="$(git config --bool merge.keepBackup || echo true)"
|
||||
keep_backup () {
|
||||
test "$keep_backup_mode" = "true"
|
||||
}
|
||||
|
||||
# This function manages the backup .orig file.
|
||||
# A backup $MERGED.orig file is created if changes are detected.
|
||||
cleanup_temp_files () {
|
||||
if test -n "$MERGED"; then
|
||||
if keep_backup && test "$MERGED" -nt "$BACKUP"; then
|
||||
test -f "$BACKUP" && mv -- "$BACKUP" "$MERGED.orig"
|
||||
else
|
||||
rm -f -- "$BACKUP"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# This is called when users Ctrl-C out of git-difftool-helper
|
||||
sigint_handler () {
|
||||
cleanup_temp_files
|
||||
exit 1
|
||||
}
|
||||
|
||||
# This function prepares temporary files and launches the appropriate
|
||||
# merge tool.
|
||||
launch_merge_tool () {
|
||||
# Merged is the filename as it appears in the work tree
|
||||
# Local is the contents of a/filename
|
||||
# Remote is the contents of b/filename
|
||||
# Custom merge tool commands might use $BASE so we provide it
|
||||
MERGED="$1"
|
||||
LOCAL="$2"
|
||||
REMOTE="$3"
|
||||
BASE="$1"
|
||||
ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
|
||||
BACKUP="$MERGED.BACKUP.$ext"
|
||||
|
||||
# Create and ensure that we clean up $BACKUP
|
||||
test -f "$MERGED" && cp -- "$MERGED" "$BACKUP"
|
||||
trap sigint_handler INT
|
||||
|
||||
# $LOCAL and $REMOTE are temporary files so prompt
|
||||
# the user with the real $MERGED name before launching $merge_tool.
|
||||
if should_prompt; then
|
||||
printf "\nViewing: '$MERGED'\n"
|
||||
printf "Hit return to launch '%s': " "$merge_tool"
|
||||
read ans
|
||||
fi
|
||||
|
||||
# Run the appropriate merge tool command
|
||||
case "$merge_tool" in
|
||||
kdiff3)
|
||||
basename=$(basename "$MERGED")
|
||||
"$merge_tool_path" --auto \
|
||||
--L1 "$basename (A)" \
|
||||
--L2 "$basename (B)" \
|
||||
-o "$MERGED" "$LOCAL" "$REMOTE" \
|
||||
> /dev/null 2>&1
|
||||
;;
|
||||
|
||||
tkdiff)
|
||||
"$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"
|
||||
;;
|
||||
|
||||
meld)
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE"
|
||||
;;
|
||||
|
||||
vimdiff)
|
||||
"$merge_tool_path" -c "wincmd r" "$LOCAL" "$REMOTE"
|
||||
;;
|
||||
|
||||
gvimdiff)
|
||||
"$merge_tool_path" -c "wincmd r" -f "$LOCAL" "$REMOTE"
|
||||
;;
|
||||
|
||||
xxdiff)
|
||||
"$merge_tool_path" \
|
||||
-X \
|
||||
-R 'Accel.SaveAsMerged: "Ctrl-S"' \
|
||||
-R 'Accel.Search: "Ctrl+F"' \
|
||||
-R 'Accel.SearchForward: "Ctrl-G"' \
|
||||
--merged-file "$MERGED" \
|
||||
"$LOCAL" "$REMOTE"
|
||||
;;
|
||||
|
||||
opendiff)
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE" \
|
||||
-merge "$MERGED" | cat
|
||||
;;
|
||||
|
||||
ecmerge)
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE" \
|
||||
--default --mode=merge2 --to="$MERGED"
|
||||
;;
|
||||
|
||||
emerge)
|
||||
"$merge_tool_path" -f emerge-files-command \
|
||||
"$LOCAL" "$REMOTE" "$(basename "$MERGED")"
|
||||
;;
|
||||
|
||||
*)
|
||||
if test -n "$merge_tool_cmd"; then
|
||||
( eval $merge_tool_cmd )
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
cleanup_temp_files
|
||||
}
|
||||
|
||||
# Verifies that mergetool.<tool>.cmd exists
|
||||
valid_custom_tool() {
|
||||
merge_tool_cmd="$(git config mergetool.$1.cmd)"
|
||||
test -n "$merge_tool_cmd"
|
||||
}
|
||||
|
||||
# Verifies that the chosen merge tool is properly setup.
|
||||
# Built-in merge tools are always valid.
|
||||
valid_tool() {
|
||||
case "$1" in
|
||||
kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge)
|
||||
;; # happy
|
||||
*)
|
||||
if ! valid_custom_tool "$1"
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Sets up the merge_tool_path variable.
|
||||
# This handles the mergetool.<tool>.path configuration.
|
||||
init_merge_tool_path() {
|
||||
merge_tool_path=$(git config mergetool."$1".path)
|
||||
if test -z "$merge_tool_path"; then
|
||||
case "$1" in
|
||||
emerge)
|
||||
merge_tool_path=emacs
|
||||
;;
|
||||
*)
|
||||
merge_tool_path="$1"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
# Allow the GIT_MERGE_TOOL variable to provide a default value
|
||||
test -n "$GIT_MERGE_TOOL" && merge_tool="$GIT_MERGE_TOOL"
|
||||
|
||||
# If not merge tool was specified then use the merge.tool
|
||||
# configuration variable. If that's invalid then reset merge_tool.
|
||||
if test -z "$merge_tool"; then
|
||||
merge_tool=$(git config merge.tool)
|
||||
if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
|
||||
echo >&2 "git config option merge.tool set to unknown tool: $merge_tool"
|
||||
echo >&2 "Resetting to default..."
|
||||
unset merge_tool
|
||||
fi
|
||||
fi
|
||||
|
||||
# Try to guess an appropriate merge tool if no tool has been set.
|
||||
if test -z "$merge_tool"; then
|
||||
|
||||
# We have a $DISPLAY so try some common UNIX merge tools
|
||||
if test -n "$DISPLAY"; then
|
||||
merge_tool_candidates="kdiff3 tkdiff xxdiff meld gvimdiff"
|
||||
# If gnome then prefer meld
|
||||
if test -n "$GNOME_DESKTOP_SESSION_ID"; then
|
||||
merge_tool_candidates="meld $merge_tool_candidates"
|
||||
fi
|
||||
# If KDE then prefer kdiff3
|
||||
if test "$KDE_FULL_SESSION" = "true"; then
|
||||
merge_tool_candidates="kdiff3 $merge_tool_candidates"
|
||||
fi
|
||||
fi
|
||||
|
||||
# $EDITOR is emacs so add emerge as a candidate
|
||||
if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then
|
||||
merge_tool_candidates="$merge_tool_candidates emerge"
|
||||
fi
|
||||
|
||||
# $EDITOR is vim so add vimdiff as a candidate
|
||||
if echo "${VISUAL:-$EDITOR}" | grep 'vim' > /dev/null 2>&1; then
|
||||
merge_tool_candidates="$merge_tool_candidates vimdiff"
|
||||
fi
|
||||
|
||||
merge_tool_candidates="$merge_tool_candidates opendiff emerge vimdiff"
|
||||
echo "merge tool candidates: $merge_tool_candidates"
|
||||
|
||||
# Loop over each candidate and stop when a valid merge tool is found.
|
||||
for i in $merge_tool_candidates
|
||||
do
|
||||
init_merge_tool_path $i
|
||||
if type "$merge_tool_path" > /dev/null 2>&1; then
|
||||
merge_tool=$i
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if test -z "$merge_tool" ; then
|
||||
echo "No known merge resolution program available."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
# A merge tool has been set, so verify that it's valid.
|
||||
if ! valid_tool "$merge_tool"; then
|
||||
echo >&2 "Unknown merge tool $merge_tool"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
init_merge_tool_path "$merge_tool"
|
||||
|
||||
if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then
|
||||
echo "The merge tool $merge_tool is not available as '$merge_tool_path'"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# Launch the merge tool on each path provided by 'git diff'
|
||||
while test $# -gt 6
|
||||
do
|
||||
launch_merge_tool "$1" "$2" "$5"
|
||||
shift 7
|
||||
done
|
||||
@@ -42,8 +42,9 @@ from bookmark import save_bookmark
|
||||
from bookmark import manage_bookmarks
|
||||
from stash import stash
|
||||
from compare import compare
|
||||
from compare import compare_file
|
||||
from compare import branch_compare
|
||||
|
||||
from cola.views import AboutView
|
||||
|
||||
class Controller(QObserver):
|
||||
"""Manages the interaction between models and views."""
|
||||
@@ -86,11 +87,14 @@ class Controller(QObserver):
|
||||
# When a model attribute changes, this runs a specific action
|
||||
self.add_actions(global_cola_fontdiff = self.update_diff_font)
|
||||
self.add_actions(global_cola_fontui = self.update_ui_font)
|
||||
self.add_actions(global_cola_tabwidth = self.update_tab_width)
|
||||
|
||||
self.add_callbacks(
|
||||
# Push Buttons
|
||||
rescan_button = self.rescan,
|
||||
signoff_button = self.model.add_signoff,
|
||||
stage_button = self.stage_selected,
|
||||
stash_button = lambda: stash(self.model, self.view),
|
||||
commit_button = self.commit,
|
||||
fetch_button = self.fetch,
|
||||
push_button = self.push,
|
||||
@@ -171,14 +175,18 @@ class Controller(QObserver):
|
||||
lambda: stash(self.model, self.view),
|
||||
menu_commit_compare =
|
||||
lambda: compare(self.model, self.view),
|
||||
menu_commit_compare_file =
|
||||
lambda: compare_file(self.model, self.view),
|
||||
menu_stage_modified =
|
||||
lambda: self.log(self.model.stage_modified()),
|
||||
menu_stage_untracked =
|
||||
lambda: self.log(self.model.stage_untracked()),
|
||||
menu_unstage_all =
|
||||
lambda: self.log(self.model.unstage_all()),
|
||||
menu_view_log = self.view_log,
|
||||
|
||||
# Help Menu
|
||||
menu_help_about = self.about,
|
||||
menu_help_docs =
|
||||
lambda: self.model.git.web__browse(utils.get_htmldocs()),
|
||||
)
|
||||
@@ -191,16 +199,14 @@ class Controller(QObserver):
|
||||
'itemDoubleClicked(QTreeWidgetItem*, int)',
|
||||
self.doubleclick_tree)
|
||||
|
||||
# Toolbar log button
|
||||
self.connect(view.toolbar_show_log,
|
||||
'triggered()', self.show_log)
|
||||
|
||||
self.merge_msg_hash = ''
|
||||
self.load_gui_settings()
|
||||
self.rescan()
|
||||
self.init_log_window()
|
||||
self.refresh_view('global_cola_fontdiff', 'global_cola_fontui')
|
||||
self.start_inotify_thread()
|
||||
if self.has_inotify():
|
||||
self.view.rescan_button.hide()
|
||||
|
||||
#####################################################################
|
||||
# handle when the status tree is clicked
|
||||
@@ -282,12 +288,14 @@ class Controller(QObserver):
|
||||
diff = 'no diff'
|
||||
if idx == self.view.IDX_STAGED:
|
||||
diff = (self.model.git.diff(cached=True, stat=True,
|
||||
no_color=True,
|
||||
with_raw_output=True) + '\n\n' +
|
||||
self.model.git.diff(cached=True))
|
||||
elif idx == self.view.IDX_MODIFIED:
|
||||
diff = (self.model.git.diff(stat=True,
|
||||
no_color=True,
|
||||
with_raw_output=True) + '\n\n' +
|
||||
self.model.git.diff())
|
||||
self.model.git.diff(no_color=True))
|
||||
elif idx == self.view.IDX_UNMERGED:
|
||||
diff = '%s unmerged file(s)' % len(self.model.get_unmerged())
|
||||
elif idx == self.view.IDX_UNTRACKED:
|
||||
@@ -359,8 +367,17 @@ class Controller(QObserver):
|
||||
|
||||
#####################################################################
|
||||
# Qt callbacks
|
||||
def about(self):
|
||||
view = AboutView(self.view)
|
||||
style = QtGui.QApplication.instance().styleSheet()
|
||||
if style:
|
||||
view.setStyleSheet(style)
|
||||
view.show()
|
||||
view.set_version(version.version)
|
||||
|
||||
def tr(self, fortr):
|
||||
return qtutils.tr(fortr)
|
||||
|
||||
def goto_grep(self):
|
||||
line = self.view.selected_line()
|
||||
filename, lineno, contents = line.split(':', 2)
|
||||
@@ -374,7 +391,7 @@ class Controller(QObserver):
|
||||
|
||||
def gen_search(self, searchtype, browse=False):
|
||||
def search_handler():
|
||||
search_commits(self.model, searchtype, browse)
|
||||
search_commits(self.model, self.view, searchtype, browse)
|
||||
return search_handler
|
||||
|
||||
def grep(self):
|
||||
@@ -386,8 +403,8 @@ class Controller(QObserver):
|
||||
self.view.display_text.setText(stuff)
|
||||
self.view.show_diff()
|
||||
|
||||
def show_log(self, *rest):
|
||||
qtutils.toggle_log_window()
|
||||
def view_log(self, *rest):
|
||||
qtutils.show_logger()
|
||||
|
||||
def options(self):
|
||||
update_options(self.model, self.view)
|
||||
@@ -424,9 +441,7 @@ class Controller(QObserver):
|
||||
self.model.get_local_branches())
|
||||
if not branch:
|
||||
return
|
||||
status, out, err = self.model.git.checkout(branch,
|
||||
with_extended_output=True)
|
||||
self.log(out+err)
|
||||
self.log(self.model.git.checkout(branch, with_stderr=True))
|
||||
|
||||
def browse_commits(self):
|
||||
self.select_commits_gui('Browse Commits',
|
||||
@@ -489,13 +504,16 @@ class Controller(QObserver):
|
||||
else:
|
||||
self.mode = Controller.MODE_WORKTREE
|
||||
|
||||
def view_diff(self, staged=True):
|
||||
def view_diff(self, staged=True, scrollvalue=None):
|
||||
idx, selected = self.view.get_selection()
|
||||
if not selected:
|
||||
self.reset_mode()
|
||||
self.view.reset_display()
|
||||
return
|
||||
self.view_diff_for_row(idx, staged)
|
||||
if scrollvalue is not None:
|
||||
scrollbar = self.view.display_text.verticalScrollBar()
|
||||
scrollbar.setValue(scrollvalue)
|
||||
|
||||
def view_diff_for_row(self, idx, staged):
|
||||
self.set_mode(staged)
|
||||
@@ -524,12 +542,12 @@ class Controller(QObserver):
|
||||
def edit_diff(self, staged=True):
|
||||
filename = self.get_selected_filename(staged=staged)
|
||||
if filename:
|
||||
args = ['git', 'difftool', '--no-prompt',
|
||||
'-t', self.model.get_mergetool()]
|
||||
if (self.view.amend_is_checked()
|
||||
or (staged and
|
||||
filename not in self.model.partially_staged)):
|
||||
args.extend(['-c', 'HEAD^'])
|
||||
args = ['perl', utils.get_libexec('git-difftool'),
|
||||
'--no-prompt', '-t', self.model.get_mergetool()]
|
||||
if staged:
|
||||
args.append('--cached')
|
||||
if self.view.amend_is_checked():
|
||||
args.append('HEAD^')
|
||||
args.extend(['--', filename])
|
||||
utils.fork(*args)
|
||||
|
||||
@@ -566,30 +584,63 @@ class Controller(QObserver):
|
||||
revs,
|
||||
output='patches'))
|
||||
|
||||
def _quote_repopath(self, repopath):
|
||||
if os.name in ('nt', 'dos'):
|
||||
repopath = '"%s"' % repopath
|
||||
return repopath
|
||||
|
||||
def open_repo(self):
|
||||
"""Spawns a new cola session"""
|
||||
dirname = qtutils.opendir_dialog(self.view,
|
||||
'Open Git Repository...',
|
||||
os.getcwd())
|
||||
if dirname:
|
||||
utils.fork(sys.argv[0], dirname)
|
||||
if not dirname:
|
||||
return
|
||||
utils.fork('python', sys.argv[0],
|
||||
'--repo', self._quote_repopath(dirname))
|
||||
|
||||
def clone_repo(self):
|
||||
"""Clones a git repository"""
|
||||
url, ok = qtutils.input('Path or URL to clone (Env. $VARS okay)')
|
||||
url = os.path.expandvars(url)
|
||||
if not ok or not url:
|
||||
return
|
||||
url = os.path.expandvars(url)
|
||||
msg = 'Enter a directory name for the new repository'
|
||||
dirname = qtutils.new_dir_dialog(self.view, msg)
|
||||
while dirname and os.path.exists(dirname):
|
||||
qtutils.information('Directory Exists',
|
||||
'Please enter a non-existent path name.')
|
||||
dirname = qtutils.new_dir_dialog(self.view, msg)
|
||||
try:
|
||||
newurl = url.replace('\\', '/')
|
||||
default = newurl.rsplit('/', 1)[-1]
|
||||
if default == '.git':
|
||||
default = os.path.basename(os.path.dirname(newurl))
|
||||
if default.endswith('.git'):
|
||||
default = default[:-4]
|
||||
if url == '.':
|
||||
default = os.path.basename(os.getcwd())
|
||||
if not default:
|
||||
raise
|
||||
except:
|
||||
self.log('Oops, could not parse git url: "%s"' % url)
|
||||
return
|
||||
|
||||
msg = 'Select a parent directory for the new clone'
|
||||
dirname = qtutils.opendir_dialog(self.view, msg, os.getcwd())
|
||||
if not dirname:
|
||||
return
|
||||
self.log(self.model.git.clone(url, dirname))
|
||||
utils.fork(sys.argv[0], dirname)
|
||||
count = 1
|
||||
destdir = os.path.join(dirname, default)
|
||||
olddestdir = destdir
|
||||
if os.path.exists(destdir):
|
||||
qtutils.information(destdir + ' already exists, cola will '
|
||||
'create a new directory')
|
||||
|
||||
while os.path.exists(destdir):
|
||||
destdir = olddestdir + str(count)
|
||||
count += 1
|
||||
|
||||
self.log(self.model.git.clone(url, destdir))
|
||||
utils.fork('python', sys.argv[0],
|
||||
'--repo', self._quote_repopath(destdir))
|
||||
|
||||
def has_inotify(self):
|
||||
return self.inotify_thread and self.inotify_thread.isRunning()
|
||||
|
||||
def quit_app(self, *args):
|
||||
"""Save config settings and cleanup any inotify threads."""
|
||||
@@ -600,7 +651,7 @@ class Controller(QObserver):
|
||||
pattern = self.model.get_tmp_file_pattern()
|
||||
for filename in glob.glob(pattern):
|
||||
os.unlink(filename)
|
||||
if self.inotify_thread and self.inotify_thread.isRunning():
|
||||
if self.has_inotify():
|
||||
self.inotify_thread.abort = True
|
||||
self.inotify_thread.wait()
|
||||
self.view.close()
|
||||
@@ -618,7 +669,7 @@ class Controller(QObserver):
|
||||
def rebase(self):
|
||||
branch = choose_from_combo('Rebase Branch',
|
||||
self.view,
|
||||
self.model.get_local_branches())
|
||||
self.model.get_all_branches())
|
||||
if not branch:
|
||||
return
|
||||
self.log(self.model.git.rebase(branch))
|
||||
@@ -695,9 +746,8 @@ class Controller(QObserver):
|
||||
item.setSelected(True)
|
||||
self.view.status_tree.setCurrentItem(item)
|
||||
self.view.status_tree.setItemSelected(item, True)
|
||||
scrollbar.setValue(scrollvalue)
|
||||
if showdiff:
|
||||
self.view_diff(False)
|
||||
self.view_diff(staged=False, scrollvalue=scrollvalue)
|
||||
else:
|
||||
self.reset_mode()
|
||||
self.view.reset_display()
|
||||
@@ -713,9 +763,8 @@ class Controller(QObserver):
|
||||
item.setSelected(True)
|
||||
self.view.status_tree.setCurrentItem(item)
|
||||
self.view.status_tree.setItemSelected(item, True)
|
||||
scrollbar.setValue(scrollvalue)
|
||||
if showdiff:
|
||||
self.view_diff(True)
|
||||
self.view_diff(staged=True, scrollvalue=scrollvalue)
|
||||
else:
|
||||
self.reset_mode()
|
||||
self.view.reset_display()
|
||||
@@ -772,6 +821,7 @@ class Controller(QObserver):
|
||||
if not branch:
|
||||
return
|
||||
zfiles_str = self.model.git.diff(branch, name_only=True,
|
||||
no_color=True,
|
||||
z=True).rstrip('\0')
|
||||
files = zfiles_str.split('\0')
|
||||
filename = choose_from_list('Select File', self.view, files)
|
||||
@@ -900,12 +950,12 @@ class Controller(QObserver):
|
||||
def viz_all(self):
|
||||
"""Visualizes the entire git history using gitk."""
|
||||
browser = self.model.get_history_browser()
|
||||
utils.fork(browser, '--all')
|
||||
utils.fork('sh', '-c', browser, '--all')
|
||||
|
||||
def viz_current(self):
|
||||
"""Visualizes the current branch's history using gitk."""
|
||||
browser = self.model.get_history_browser()
|
||||
utils.fork(browser, self.model.get_currentbranch())
|
||||
utils.fork('sh', '-c', browser, self.model.get_currentbranch())
|
||||
|
||||
def load_gui_settings(self):
|
||||
try:
|
||||
@@ -1033,6 +1083,12 @@ class Controller(QObserver):
|
||||
qfont.fromString(font)
|
||||
QtGui.qApp.setFont(qfont)
|
||||
|
||||
def update_tab_width(self):
|
||||
tab_width = self.model.get_cola_config('tabwidth')
|
||||
display_font = self.view.display_text.font()
|
||||
space_width = QtGui.QFontMetrics(display_font).width(' ')
|
||||
self.view.display_text.setTabStopWidth(tab_width * space_width)
|
||||
|
||||
def init_log_window(self):
|
||||
branch = self.model.get_currentbranch()
|
||||
qtutils.log(self.model.get_git_version()
|
||||
|
||||
@@ -25,15 +25,18 @@ def manage_bookmarks():
|
||||
view = BookmarkView(QtGui.qApp.activeWindow())
|
||||
ctl = BookmarkController(model, view)
|
||||
view.show()
|
||||
if view.exec_() == QtGui.QDialog.Accepted:
|
||||
model.save_all_settings()
|
||||
|
||||
class BookmarkController(QObserver):
|
||||
def init(self, model, view):
|
||||
self.add_observables( 'bookmarks' )
|
||||
self.add_callbacks(button_open = self.open,
|
||||
button_delete = self.delete)
|
||||
button_delete = self.delete,
|
||||
button_save = self.save)
|
||||
self.refresh_view()
|
||||
|
||||
def save(self):
|
||||
self.model.save_all_settings()
|
||||
self.view.accept()
|
||||
|
||||
def open(self):
|
||||
selection = qtutils.get_selection_list(self.view.bookmarks,
|
||||
|
||||
+31
-21
@@ -10,7 +10,13 @@ from cola.views import BranchCompareView
|
||||
from cola.controllers.repobrowser import select_file_from_repo
|
||||
from cola.controllers.util import choose_from_list
|
||||
|
||||
def compare(model, parent):
|
||||
def compare_file(model, parent):
|
||||
filename = select_file_from_repo(model, parent)
|
||||
if not filename:
|
||||
return
|
||||
compare(model, parent, filename)
|
||||
|
||||
def compare(model, parent, filename=None):
|
||||
model = model.clone()
|
||||
model.create(descriptions_start=[], descriptions_end=[],
|
||||
revisions_start=[], revisions_end=[],
|
||||
@@ -18,7 +24,7 @@ def compare(model, parent):
|
||||
compare_files=[], num_results=100,
|
||||
show_versions=False)
|
||||
view = CompareView(parent)
|
||||
ctl = CompareController(model, view)
|
||||
ctl = CompareController(model, view, filename)
|
||||
view.show()
|
||||
|
||||
def branch_compare(model, parent):
|
||||
@@ -158,23 +164,23 @@ class BranchCompareController(QObserver):
|
||||
|
||||
def __compare_file(self, filename):
|
||||
git = self.model.git
|
||||
args = git.transform_kwargs(no_prompt=True,
|
||||
tool=self.model.get_mergetool())
|
||||
if self.use_sandbox:
|
||||
kwargs = git.transform_kwargs(no_prompt=True,
|
||||
tool=self.model.get_mergetool(),
|
||||
commit=self.diff_arg)
|
||||
args.append(self.diff_arg)
|
||||
else:
|
||||
kwargs = git.transform_kwargs(no_prompt=True,
|
||||
tool=self.model.get_mergetool(),
|
||||
start=self.start,
|
||||
end=self.end)
|
||||
args = (['git', 'difftool'] + kwargs + ['--', filename])
|
||||
utils.fork(*args)
|
||||
args.append('%s..%s' % (self.start, self.end))
|
||||
|
||||
command = (['perl', utils.get_libexec('git-difftool')] +
|
||||
args + ['--', filename])
|
||||
utils.fork(*command)
|
||||
|
||||
|
||||
class CompareController(QObserver):
|
||||
"""Drives the Commit->Compare Commits dialog.
|
||||
"""
|
||||
def init (self, model, view):
|
||||
def init (self, model, view, filename=None):
|
||||
self.filename = filename
|
||||
self.add_observables('descriptions_start', 'descriptions_end',
|
||||
'revision_start', 'revision_end',
|
||||
'compare_files', 'num_results',
|
||||
@@ -232,7 +238,8 @@ class CompareController(QObserver):
|
||||
|
||||
self.model.set_notify(True)
|
||||
show_versions = self.model.get_show_versions()
|
||||
revs = self.model.update_revision_lists(show_versions=show_versions)
|
||||
revs = self.model.update_revision_lists(filename=self.filename,
|
||||
show_versions=show_versions)
|
||||
if start_selected:
|
||||
tree_widget = self.view.descriptions_start
|
||||
self.select_nth_item_from_end(tree_widget, start_delta)
|
||||
@@ -261,8 +268,11 @@ class CompareController(QObserver):
|
||||
id_num, selected = qtutils.get_selected_treeitem(tree_widget)
|
||||
if not selected:
|
||||
return
|
||||
revision = self.model.get_param(revisions_param)[id_num]
|
||||
self.model.set_param(revision_param, revision)
|
||||
|
||||
revisionlist = self.model.get_param(revisions_param)
|
||||
if id_num < len(revisionlist):
|
||||
revision = self.model.get_param(revisions_param)[id_num]
|
||||
self.model.set_param(revision_param, revision)
|
||||
|
||||
# get the changed files list
|
||||
start = self.model.get_revision_start()
|
||||
@@ -302,9 +312,9 @@ class CompareController(QObserver):
|
||||
git = self.model.git
|
||||
start = self.model.get_revision_start()
|
||||
end = self.model.get_revision_end()
|
||||
kwargs = git.transform_kwargs(no_prompt=True,
|
||||
tool=self.model.get_mergetool(),
|
||||
start=start,
|
||||
end=end)
|
||||
args = (['git', 'difftool'] + kwargs + ['--', filename])
|
||||
utils.fork(*args)
|
||||
args = git.transform_kwargs(no_prompt=True,
|
||||
tool=self.model.get_mergetool())
|
||||
args.append('%s..%s' % (start, end))
|
||||
command = (['perl', utils.get_libexec('git-difftool')] +
|
||||
args + ['--', filename])
|
||||
utils.fork(*command)
|
||||
|
||||
@@ -10,15 +10,16 @@ from cola import qtutils
|
||||
from cola.views import CreateBranchView
|
||||
from cola.qobserver import QObserver
|
||||
|
||||
def create_new_branch(model,parent):
|
||||
def create_new_branch(model,parent,revision=''):
|
||||
model = model.clone()
|
||||
view = CreateBranchView(parent)
|
||||
ctl = CreateBranchController(model, view)
|
||||
model.set_revision(revision)
|
||||
view.show()
|
||||
return view.exec_() == QDialog.Accepted
|
||||
|
||||
class CreateBranchController(QObserver):
|
||||
def init(self, model, view):
|
||||
self._remoteclicked = False
|
||||
self.add_observables('revision', 'local_branch')
|
||||
self.add_callbacks(branch_list = self.item_changed,
|
||||
create_button = self.create_branch,
|
||||
@@ -90,10 +91,8 @@ class CreateBranchController(QObserver):
|
||||
output = self.model.create_branch(branch, revision, track=track)
|
||||
qtutils.show_output(output)
|
||||
if chkout:
|
||||
status, out, err = self.model.git.checkout(branch,
|
||||
with_extended_output=True)
|
||||
qtutils.show_output(out+err)
|
||||
|
||||
qtutils.show_output(self.model.git.checkout(branch,
|
||||
with_stderr=True))
|
||||
self.view.accept()
|
||||
|
||||
def item_changed(self, *rest):
|
||||
@@ -117,7 +116,10 @@ class CreateBranchController(QObserver):
|
||||
branch = utils.basename(rev)
|
||||
if branch == 'HEAD':
|
||||
return
|
||||
# Signal that we've clicked on a remote branch
|
||||
self._remoteclicked = True
|
||||
self.model.set_local_branch(branch)
|
||||
self._remoteclicked = False
|
||||
|
||||
######################################################################
|
||||
|
||||
|
||||
@@ -13,15 +13,17 @@ def remote_action(model, parent, action):
|
||||
model = model.clone()
|
||||
model.create(remotename='',
|
||||
tags_checkbox=False,
|
||||
rebase_checkbox=False,
|
||||
ffwd_only_checkbox=True)
|
||||
view = RemoteView(parent, action)
|
||||
if action == 'Fetch' or action == 'Pull':
|
||||
model.set_tags_checkbox(False)
|
||||
if action == 'Pull':
|
||||
view.tags_checkbox.hide()
|
||||
if action != 'Pull':
|
||||
view.rebase_checkbox.hide()
|
||||
controller = RemoteController(model, view, action)
|
||||
view.show()
|
||||
return view.exec_() == QDialog.Accepted
|
||||
|
||||
class RemoteController(QObserver):
|
||||
def init(self, model, view, action):
|
||||
@@ -32,6 +34,7 @@ class RemoteController(QObserver):
|
||||
'remote_branch',
|
||||
'remote_branches',
|
||||
'tags_checkbox',
|
||||
'rebase_checkbox',
|
||||
'ffwd_only_checkbox')
|
||||
self.action_method = {
|
||||
'Fetch': self.gen_remote_callback(self.model.fetch_helper),
|
||||
@@ -106,12 +109,13 @@ class RemoteController(QObserver):
|
||||
'remote_branch': self.model.get_remote_branch(),
|
||||
'ffwd': self.model.get_ffwd_only_checkbox(),
|
||||
'tags': self.model.get_tags_checkbox(),
|
||||
'rebase': self.model.get_rebase_checkbox(),
|
||||
})
|
||||
|
||||
def show_results(self, output):
|
||||
qtutils.show_output(output)
|
||||
self.view.accept()
|
||||
qtutils.raise_logger()
|
||||
qtutils.show_logger()
|
||||
|
||||
#+-------------------------------------------------------------
|
||||
#+ Actions
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import os
|
||||
from PyQt4.QtGui import QDialog
|
||||
from PyQt4.QtGui import QMenu
|
||||
|
||||
from cola import utils
|
||||
from cola import qtutils
|
||||
@@ -42,9 +43,37 @@ class RepoBrowserController(QObserver):
|
||||
self.add_signals('itemSelectionChanged()', view.commit_list,)
|
||||
self.add_actions(directory = self.action_directory_changed)
|
||||
self.add_callbacks(commit_list = self.item_changed)
|
||||
view.commit_list.contextMenuEvent = self.context_menu_event
|
||||
# Start at the root of the tree
|
||||
model.set_directory('')
|
||||
|
||||
def context_menu_event(self, event):
|
||||
menu = QMenu(self.view);
|
||||
menu.addAction(self.tr('Blame'), self.blame)
|
||||
menu.exec_(self.view.commit_list.mapToGlobal(event.pos()))
|
||||
|
||||
def blame(self):
|
||||
current = self.view.commit_list.currentRow()
|
||||
item = self.view.commit_list.item(current)
|
||||
if item is None or not item.isSelected():
|
||||
return
|
||||
directories = self.model.get_directories()
|
||||
directory_entries = self.model.get_directory_entries()
|
||||
if current < len(directories):
|
||||
# ignore directories
|
||||
return
|
||||
idx = current - len(directories)
|
||||
if idx >= len(self.model.get_subtree_sha1s()):
|
||||
return
|
||||
objtype, sha1, name = self.model.get_subtree_node(idx)
|
||||
curdir = self.model.get_directory()
|
||||
if curdir:
|
||||
filename = os.path.join(curdir, name)
|
||||
else:
|
||||
filename = name
|
||||
blame = self.model.git.blame(self.model.get_currentbranch(), filename)
|
||||
self.view.commit_text.setText(blame)
|
||||
|
||||
######################################################################
|
||||
# Actions
|
||||
def action_directory_changed(self):
|
||||
|
||||
@@ -21,7 +21,7 @@ class SearchEngine(object):
|
||||
pass
|
||||
def get_rev_args(self):
|
||||
max = self.model.get_max_results()
|
||||
return { "max-count": max, "pretty": "oneline" }
|
||||
return { 'max-count': max, 'pretty': 'format:%H %aN - %s - %ar' }
|
||||
def get_common_args(self):
|
||||
return (self.model.get_input(), self.get_rev_args())
|
||||
def search(self):
|
||||
@@ -31,7 +31,7 @@ class SearchEngine(object):
|
||||
def validate(self):
|
||||
return len(self.model.get_input()) > 1
|
||||
def get_revisions(self, *args, **kwargs):
|
||||
revlist = self.model.git.rev_list(*args, **kwargs)
|
||||
revlist = self.model.git.log(*args, **kwargs)
|
||||
return self.model.parse_rev_list(revlist)
|
||||
def get_results(self):
|
||||
pass
|
||||
@@ -233,7 +233,7 @@ class SearchController(QObserver):
|
||||
doraise=True,
|
||||
quiet=False)
|
||||
|
||||
def search_commits(model, mode, browse):
|
||||
def search_commits(model, parent, mode, browse):
|
||||
def get_date(timespec):
|
||||
return '%04d-%02d-%02d' % time.localtime(timespec)[:3]
|
||||
|
||||
@@ -242,8 +242,8 @@ def search_commits(model, mode, browse):
|
||||
max_results=500,
|
||||
start_date='',
|
||||
end_date='',
|
||||
commit_list=None)
|
||||
view = SearchView(None)
|
||||
commit_list=[])
|
||||
view = SearchView(parent)
|
||||
ctl = SearchController(model, view)
|
||||
ctl.set_mode(mode)
|
||||
model.set_start_date(get_date(time.time()-(87640*7)))
|
||||
@@ -251,4 +251,3 @@ def search_commits(model, mode, browse):
|
||||
view.show()
|
||||
if browse:
|
||||
ctl.browse_callback()
|
||||
view.exec_()
|
||||
|
||||
@@ -70,19 +70,16 @@ class StashController(QObserver):
|
||||
if not selection:
|
||||
return
|
||||
diffstat = self.model.git.stash('show', selection)
|
||||
diff = self.model.stash('show', '-p', selection)
|
||||
diff = self.model.git.stash('show', '-p', selection)
|
||||
self.view.parent_view.display('%s\n\n%s' % (diffstat, diff))
|
||||
|
||||
def stash_apply(self):
|
||||
selection = self.get_selected_stash()
|
||||
if not selection:
|
||||
return
|
||||
(status, stdout, stderr) =\
|
||||
self.model.git.stash('apply', selection,
|
||||
with_extended_output=True)
|
||||
qtutils.log(stdout + stderr,
|
||||
quiet=False,
|
||||
doraise=True)
|
||||
out = self.model.git.stash('apply', '--index', selection,
|
||||
with_stderr=True)
|
||||
qtutils.log(out, quiet=False, doraise=True)
|
||||
self.view.accept()
|
||||
|
||||
def stash_drop(self):
|
||||
|
||||
+44
-12
@@ -7,6 +7,8 @@ import os
|
||||
import time
|
||||
from PyQt4.QtGui import QDialog
|
||||
from PyQt4.QtGui import QFont
|
||||
from PyQt4.QtGui import QMenu
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from cola import utils
|
||||
from cola import qtutils
|
||||
@@ -17,6 +19,7 @@ from cola.views import CommitView
|
||||
from cola.views import OptionsView
|
||||
from cola.views import LogView
|
||||
from cola.qobserver import QObserver
|
||||
from createbranch import create_new_branch
|
||||
|
||||
def set_diff_font(model, widget):
|
||||
if model.has_param('global_cola_fontdiff'):
|
||||
@@ -41,11 +44,13 @@ def choose_from_list(title, parent, items=[], dblclick=None):
|
||||
#+-------------------------------------------------------------
|
||||
def select_commits(model, parent, title, revs, summaries):
|
||||
"""Use the CommitView to select commits from a list."""
|
||||
original_model = model
|
||||
model = model.clone()
|
||||
model.set_revisions(revs)
|
||||
model.set_summaries(summaries)
|
||||
view = CommitView(parent, title)
|
||||
ctl = SelectCommitsController(model, view)
|
||||
ctl.original_model = original_model
|
||||
return ctl.select_commits()
|
||||
|
||||
class SelectCommitsController(QObserver):
|
||||
@@ -54,6 +59,7 @@ class SelectCommitsController(QObserver):
|
||||
self.connect(view.commit_list,
|
||||
'itemSelectionChanged()',
|
||||
self.commit_sha1_selected)
|
||||
view.commit_list.contextMenuEvent = self.context_menu_event
|
||||
|
||||
def select_commits(self):
|
||||
summaries = self.model.get_summaries()
|
||||
@@ -69,6 +75,36 @@ class SelectCommitsController(QObserver):
|
||||
list_widget = self.view.commit_list
|
||||
return qtutils.get_selection_list(list_widget, revs)
|
||||
|
||||
def context_menu_event(self, event):
|
||||
menu = QMenu(self.view);
|
||||
menu.addAction(self.tr('Checkout'), self.checkout_commit)
|
||||
menu.addAction(self.tr('Create Branch here'), self.create_branch_at)
|
||||
menu.addAction(self.tr('Cherry Pick'), self.cherry_pick)
|
||||
menu.exec_(self.view.commit_list.mapToGlobal(event.pos()))
|
||||
|
||||
def checkout_commit(self):
|
||||
row, selected = qtutils.get_selected_row(self.view.commit_list)
|
||||
if not selected:
|
||||
return
|
||||
sha1 = self.model.get_revision_sha1(row)
|
||||
out = self.model.git.checkout(sha1, with_stderr=True)
|
||||
qtutils.show_output(out)
|
||||
|
||||
def create_branch_at(self):
|
||||
row, selected = qtutils.get_selected_row(self.view.commit_list)
|
||||
if not selected:
|
||||
return
|
||||
create_new_branch(self.original_model, self.view,
|
||||
revision=self.model.get_revision_sha1(row))
|
||||
|
||||
def cherry_pick(self):
|
||||
row, selected = qtutils.get_selected_row(self.view.commit_list)
|
||||
if not selected:
|
||||
return
|
||||
sha1 = self.model.get_revision_sha1(row)
|
||||
out = self.model.git.cherry_pick(sha1, with_stderr=True)
|
||||
qtutils.show_output(out)
|
||||
|
||||
def commit_sha1_selected(self):
|
||||
row, selected = qtutils.get_selected_row(self.view.commit_list)
|
||||
if not selected:
|
||||
@@ -120,17 +156,18 @@ class OptionsController(QObserver):
|
||||
'global_merge_tool',
|
||||
'global_gui_diffcontext',
|
||||
'global_gui_historybrowser',
|
||||
'global_cola_fontdiffsize',
|
||||
'global_cola_fontdiff_size',
|
||||
'global_cola_fontdiff',
|
||||
'global_cola_fontuisize',
|
||||
'global_cola_fontui_size',
|
||||
'global_cola_fontui',
|
||||
'global_cola_savewindowsettings',
|
||||
'global_cola_tabwidth',
|
||||
)
|
||||
self.add_actions(global_cola_fontdiffsize = self.update_size)
|
||||
self.add_actions(global_cola_fontuisize = self.update_size)
|
||||
self.add_actions(global_cola_fontdiff = self.tell_parent_model)
|
||||
self.add_actions(global_cola_fontui = self.tell_parent_model)
|
||||
self.add_callbacks(save_button = self.save_settings)
|
||||
self.add_callbacks(global_cola_fontdiff_size = self.update_size)
|
||||
self.add_callbacks(global_cola_fontui_size = self.update_size)
|
||||
self.connect(self.view, 'rejected()', self.restore_settings)
|
||||
|
||||
self.refresh_view()
|
||||
@@ -139,18 +176,12 @@ class OptionsController(QObserver):
|
||||
def refresh_view(self):
|
||||
font = self.model.get_cola_config('fontui')
|
||||
if font:
|
||||
size = int(font.split(',')[1])
|
||||
self.view.global_cola_fontuisize.setValue(size)
|
||||
self.model.set_global_cola_fontuisize(size)
|
||||
fontui = QFont()
|
||||
fontui.fromString(font)
|
||||
self.view.global_cola_fontui.setCurrentFont(fontui)
|
||||
|
||||
font = self.model.get_cola_config('fontdiff')
|
||||
if font:
|
||||
size = int(font.split(',')[1])
|
||||
self.view.global_cola_fontdiffsize.setValue(size)
|
||||
self.model.set_global_cola_fontdiffsize(size)
|
||||
fontdiff = QFont()
|
||||
fontdiff.fromString(font)
|
||||
self.view.global_cola_fontdiff.setCurrentFont(fontdiff)
|
||||
@@ -183,9 +214,10 @@ class OptionsController(QObserver):
|
||||
def tell_parent_model(self,*rest):
|
||||
params= ('global_cola_fontdiff',
|
||||
'global_cola_fontui',
|
||||
'global_cola_fontdiffsize',
|
||||
'global_cola_fontuisize',
|
||||
'global_cola_fontdiff_size',
|
||||
'global_cola_fontui_size',
|
||||
'global_cola_savewindowsettings',
|
||||
'global_cola_tabwidth',
|
||||
)
|
||||
for param in params:
|
||||
self.original_model.set_param(
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
# Some files are not in UTF-8; some other aren't in any codification.
|
||||
# Remember that GIT doesn't care about encodings (saves binary data)
|
||||
_encoding_tests = [
|
||||
"utf8",
|
||||
"utf-8",
|
||||
"iso-8859-15",
|
||||
"windows1252",
|
||||
"ascii",
|
||||
|
||||
+21
-26
@@ -20,7 +20,7 @@ def dashify(string):
|
||||
# Enables debugging of GitPython's git commands
|
||||
GIT_PYTHON_TRACE = os.environ.get("GIT_PYTHON_TRACE", False)
|
||||
|
||||
execute_kwargs = ('istream', 'with_keep_cwd', 'with_extended_output',
|
||||
execute_kwargs = ('istream', 'with_keep_cwd', 'with_extended_output', 'with_stderr',
|
||||
'with_exceptions', 'with_raw_output')
|
||||
|
||||
class Git(object):
|
||||
@@ -47,6 +47,7 @@ class Git(object):
|
||||
istream=None,
|
||||
with_keep_cwd=False,
|
||||
with_extended_output=False,
|
||||
with_stderr=False,
|
||||
with_exceptions=False,
|
||||
with_raw_output=False):
|
||||
"""
|
||||
@@ -59,12 +60,17 @@ class Git(object):
|
||||
``istream``
|
||||
Standard input filehandle passed to subprocess.Popen.
|
||||
|
||||
The following option all default to False.
|
||||
|
||||
``with_keep_cwd``
|
||||
Whether to use the current working directory from os.getcwd().
|
||||
GitPython uses the cwd set by set_cwd() by default.
|
||||
|
||||
``with_extended_output``
|
||||
Whether to return a (status, stdout, stderr) tuple.
|
||||
Whether to return a (status, output) tuple.
|
||||
|
||||
``with_stderr``
|
||||
Whether to include stderr in the output.
|
||||
|
||||
``with_exceptions``
|
||||
Whether to raise an exception when git returns a non-zero status.
|
||||
@@ -82,7 +88,12 @@ class Git(object):
|
||||
|
||||
# Allow the user to have the command executed in their working dir.
|
||||
if with_keep_cwd or not cwd:
|
||||
cwd = os.getcwd()
|
||||
cwd = os.getcwd()
|
||||
|
||||
# Ignore stderr unless with_extended_output is provided
|
||||
stderr = None
|
||||
if with_stderr:
|
||||
stderr = subprocess.STDOUT
|
||||
|
||||
# Start the process
|
||||
use_shell = sys.platform in ('win32')
|
||||
@@ -92,12 +103,12 @@ class Git(object):
|
||||
cwd=cwd,
|
||||
shell=use_shell,
|
||||
stdin=istream,
|
||||
stderr=subprocess.PIPE,
|
||||
stderr=stderr,
|
||||
stdout=subprocess.PIPE)
|
||||
while True:
|
||||
try:
|
||||
stdout_value = proc.stdout.read()
|
||||
stderr_value = proc.stderr.read()
|
||||
proc.stdout.close()
|
||||
status = proc.wait()
|
||||
break
|
||||
except IOError, e:
|
||||
@@ -107,40 +118,24 @@ class Git(object):
|
||||
if e.errno == errno.EINTR:
|
||||
continue
|
||||
else:
|
||||
stdout_value = None
|
||||
stderr_value = None
|
||||
stdout_value = ''
|
||||
status = 42
|
||||
break
|
||||
|
||||
if with_exceptions and status:
|
||||
raise GitCommandError(command, status, stderr_value)
|
||||
raise GitCommandError(command, status, stdout_value)
|
||||
|
||||
if not stdout_value:
|
||||
stdout_value = ''
|
||||
if not stderr_value:
|
||||
stderr_value = ''
|
||||
if not with_raw_output:
|
||||
stdout_value = stdout_value.strip()
|
||||
stderr_value = stderr_value.strip()
|
||||
|
||||
if GIT_PYTHON_TRACE == 'full':
|
||||
if stderr_value:
|
||||
print "%s -> %d: '%s' !! '%s'" % (command, status, stdout_value, stderr_value)
|
||||
elif stdout_value:
|
||||
print "%s -> %d: '%s'" % (command, status, stdout_value)
|
||||
else:
|
||||
print "%s -> %d" % (command, status)
|
||||
print "%s -> %d: '%s'" % (command, status, stdout_value)
|
||||
|
||||
# Allow access to the command's status code
|
||||
if with_extended_output:
|
||||
return (status, stdout_value, stderr_value)
|
||||
return status, stdout_value
|
||||
else:
|
||||
if stdout_value and stderr_value:
|
||||
return stderr_value + '\n' + stdout_value
|
||||
elif stdout_value:
|
||||
return stdout_value
|
||||
else:
|
||||
return stderr_value
|
||||
return stdout_value
|
||||
|
||||
def transform_kwargs(self, **kwargs):
|
||||
"""
|
||||
|
||||
+29
-9
@@ -11,10 +11,12 @@ from PyQt4.QtCore import QCoreApplication
|
||||
from PyQt4.QtCore import QThread
|
||||
from PyQt4.QtCore import QEvent
|
||||
from PyQt4.QtCore import SIGNAL
|
||||
|
||||
import pyinotify
|
||||
from pyinotify import ProcessEvent
|
||||
from pyinotify import WatchManager, Notifier, EventsCodes
|
||||
|
||||
INOTIFY_EVENT_TYPE = QEvent.User + 0
|
||||
INOTIFY_EVENT = QEvent.User + 0
|
||||
|
||||
class FileSysEvent(ProcessEvent):
|
||||
"""FileSysEvents are generated by the GitNotifier thread
|
||||
@@ -44,16 +46,18 @@ class GitNotifier(QThread):
|
||||
self.git = git # A: git command object
|
||||
self.path = git.get_work_tree() #: Path to monitor
|
||||
self.abort = False #: Whether to abort (using during destruction)
|
||||
self.dirs_seen = {} #: Directories we're watching
|
||||
self.dirs_seen = set() #: Directories we're watching
|
||||
#: Events we capture
|
||||
self.mask = (EventsCodes.IN_CREATE | EventsCodes.IN_DELETE |
|
||||
EventsCodes.IN_MODIFY | EventsCodes.IN_MOVED_TO)
|
||||
self.mask = (EventsCodes.ALL_FLAGS['IN_CREATE'] |
|
||||
EventsCodes.ALL_FLAGS['IN_DELETE'] |
|
||||
EventsCodes.ALL_FLAGS['IN_MODIFY'] |
|
||||
EventsCodes.ALL_FLAGS['IN_MOVED_TO'])
|
||||
|
||||
def notify(self):
|
||||
"""Posts a Qt event in response to inotify updates.
|
||||
"""
|
||||
if not self.abort:
|
||||
event_type = QEvent.Type(INOTIFY_EVENT_TYPE)
|
||||
event_type = QEvent.Type(INOTIFY_EVENT)
|
||||
event = QEvent(event_type)
|
||||
QCoreApplication.postEvent(self.receiver, event)
|
||||
|
||||
@@ -63,15 +67,27 @@ class GitNotifier(QThread):
|
||||
directory = os.path.realpath(directory)
|
||||
if directory not in self.dirs_seen:
|
||||
self.wm.add_watch(directory, self.mask)
|
||||
self.dirs_seen[directory] = True
|
||||
self.dirs_seen.add(directory)
|
||||
|
||||
def _is_pyinotify_08x(self):
|
||||
"""The pyinotify API changed between 0.7.x and 0.8.x.
|
||||
This allows us to maintain backwards compatibility.
|
||||
"""
|
||||
if hasattr(pyinotify, '__version__'):
|
||||
if pyinotify.__version__[:3] == '0.8':
|
||||
return True
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
"""This creates the inotify WatchManager and generates
|
||||
FileSysEvents."""
|
||||
# Only capture those events that git cares about
|
||||
self.wm = WatchManager()
|
||||
notifier = Notifier(self.wm, FileSysEvent(self))
|
||||
dirs_seen = {}
|
||||
if self._is_pyinotify_08x():
|
||||
notifier = Notifier(self.wm, FileSysEvent(self), timeout=250)
|
||||
else:
|
||||
notifier = Notifier(self.wm, FileSysEvent(self))
|
||||
dirs_seen = set()
|
||||
added_flag = False
|
||||
# self.abort signals app termination. The timeout is a tradeoff
|
||||
# between fast notification response and waiting too long to exit.
|
||||
@@ -84,6 +100,10 @@ class GitNotifier(QThread):
|
||||
self.watch_directory(directory)
|
||||
added_flag = True
|
||||
notifier.process_events()
|
||||
if notifier.check_events(timeout=250):
|
||||
if self._is_pyinotify_08x():
|
||||
check = notifier.check_events()
|
||||
else:
|
||||
check = notifier.check_events(timeout=250)
|
||||
if check:
|
||||
notifier.read_events()
|
||||
notifier.stop()
|
||||
|
||||
+13
-5
@@ -79,6 +79,7 @@ def main():
|
||||
translator.load(qmfile)
|
||||
app.installTranslator(translator)
|
||||
|
||||
style = None
|
||||
if opts.style:
|
||||
# This loads the built-in and user-specified stylesheets.
|
||||
# We allows absolute and relative paths to a stylesheet
|
||||
@@ -92,11 +93,7 @@ def main():
|
||||
# Automatically register each subdirectory in the style dir
|
||||
# as a Qt resource directory.
|
||||
dirname = os.path.dirname(filename)
|
||||
resource_paths = []
|
||||
resource_paths.extend(utils.get_resource_dirs(dirname))
|
||||
for r in resource_paths:
|
||||
basename = os.path.basename(r)
|
||||
QtCore.QDir.setSearchPaths(basename, [r])
|
||||
setup_resource_dir(dirname)
|
||||
stylesheet = open(filename, 'r')
|
||||
style = stylesheet.read()
|
||||
stylesheet.close()
|
||||
@@ -104,6 +101,9 @@ def main():
|
||||
except:
|
||||
print >> sys.stderr, ("warn: '%s' is not a valid style."
|
||||
% opts.style)
|
||||
else:
|
||||
setup_resource_dir(utils.get_style_dir())
|
||||
|
||||
|
||||
# Initialize the model/view/controller framework
|
||||
from cola.models import Model
|
||||
@@ -127,3 +127,11 @@ def main():
|
||||
view.show()
|
||||
ctl = Controller(model, view)
|
||||
sys.exit(app.exec_())
|
||||
|
||||
|
||||
def setup_resource_dir(dirname):
|
||||
from PyQt4 import QtCore
|
||||
resource_paths = utils.get_resource_dirs(dirname)
|
||||
for r in resource_paths:
|
||||
basename = os.path.basename(r)
|
||||
QtCore.QDir.setSearchPaths(basename, [r])
|
||||
|
||||
+4
-15
@@ -5,6 +5,7 @@ data model.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import imp
|
||||
from cStringIO import StringIO
|
||||
from types import DictType
|
||||
@@ -357,20 +358,11 @@ class Model(Observable):
|
||||
modules = items[:-1]
|
||||
classname = items[-1]
|
||||
path = None
|
||||
module = None
|
||||
for mod in modules:
|
||||
search = imp.find_module(mod, path)
|
||||
try:
|
||||
module = imp.load_module(mod, *search)
|
||||
if hasattr(module, "__path__"):
|
||||
path = module.__path__
|
||||
finally:
|
||||
if search and search[0]:
|
||||
search[0].close()
|
||||
module = __import__('.'.join(modules))
|
||||
for mod in modules[1:]:
|
||||
module = getattr(module, mod)
|
||||
if module:
|
||||
return getattr(module, classname)
|
||||
else:
|
||||
raise Exception("No class found for: %s" % clstr)
|
||||
|
||||
@staticmethod
|
||||
def class_to_str(instance):
|
||||
@@ -385,9 +377,6 @@ def has_json():
|
||||
import simplejson
|
||||
return True
|
||||
except ImportError:
|
||||
print "Unable to import simplejson." % action
|
||||
print "You do not have simplejson installed."
|
||||
print "try: sudo apt-get install simplejson"
|
||||
return False
|
||||
|
||||
#############################################################################
|
||||
|
||||
+54
-40
@@ -199,10 +199,11 @@ class Model(model.Model):
|
||||
self.__global_defaults = {
|
||||
'cola_geometry':'',
|
||||
'cola_fontui': '',
|
||||
'cola_fontuisize': 12,
|
||||
'cola_fontui_size': 12,
|
||||
'cola_fontdiff': '',
|
||||
'cola_fontdiffsize': 12,
|
||||
'cola_fontdiff_size': 12,
|
||||
'cola_savewindowsettings': False,
|
||||
'cola_tabwidth': 8,
|
||||
'merge_keepbackup': True,
|
||||
'merge_tool': os.getenv('MERGETOOL', 'xxdiff'),
|
||||
'gui_editor': os.getenv('EDITOR', 'gvim'),
|
||||
@@ -228,10 +229,10 @@ class Model(model.Model):
|
||||
if font:
|
||||
setdefault = False
|
||||
size = int(font.split(',')[1])
|
||||
self.set_param(param+'size', size)
|
||||
self.set_param(param+'_size', size)
|
||||
param = param[len('global_'):]
|
||||
global_dict[param] = font
|
||||
global_dict[param+'size'] = size
|
||||
global_dict[param+'_size'] = size
|
||||
|
||||
# Load defaults for all undefined items
|
||||
local_and_global_defaults = self.__local_and_global_defaults
|
||||
@@ -303,7 +304,7 @@ class Model(model.Model):
|
||||
self.__local_and_global_defaults.keys()))
|
||||
params.extend(map(lambda x: 'global_' + x,
|
||||
self.__global_defaults.keys()))
|
||||
return [ p for p in params if not p.endswith('size') ]
|
||||
return [ p for p in params if not p.endswith('_size') ]
|
||||
|
||||
def save_config_param(self, param):
|
||||
if param not in self.get_config_params():
|
||||
@@ -525,7 +526,7 @@ class Model(model.Model):
|
||||
old_font = self.get_param(param)
|
||||
if not old_font:
|
||||
old_font = default
|
||||
size = self.get_param(param+'size')
|
||||
size = self.get_param(param+'_size')
|
||||
props = old_font.split(',')
|
||||
props[1] = str(size)
|
||||
new_font = ','.join(props)
|
||||
@@ -536,12 +537,12 @@ class Model(model.Model):
|
||||
commit = self.git.show(sha1)
|
||||
first_newline = commit.index('\n')
|
||||
if commit[first_newline+1:].startswith('Merge:'):
|
||||
return (commit + '\n\n'
|
||||
+ self.diff_helper(commit=sha1,
|
||||
cached=False,
|
||||
suppress_header=False))
|
||||
return (decode(commit) + '\n\n' +
|
||||
decode(self.diff_helper(commit=sha1,
|
||||
cached=False,
|
||||
suppress_header=False)))
|
||||
else:
|
||||
return commit
|
||||
return decode(commit)
|
||||
|
||||
def get_filename(self, idx, staged=True):
|
||||
try:
|
||||
@@ -661,7 +662,11 @@ class Model(model.Model):
|
||||
config_lines = self.git.config(**kwargs).splitlines()
|
||||
newdict = {}
|
||||
for line in config_lines:
|
||||
k, v = line.split('=', 1)
|
||||
try:
|
||||
k, v = line.split('=', 1)
|
||||
except:
|
||||
# the user has an invalid entry in their git config
|
||||
continue
|
||||
v = decode(v)
|
||||
k = k.replace('.','_') # git -> model
|
||||
if v == 'true' or v == 'false':
|
||||
@@ -689,17 +694,15 @@ class Model(model.Model):
|
||||
fh.close()
|
||||
|
||||
# Run 'git commit'
|
||||
(status, stdout, stderr) = self.git.commit(F=tmpfile,
|
||||
v=True,
|
||||
amend=amend,
|
||||
with_extended_output=True)
|
||||
status, out = self.git.commit(F=tmpfile, v=True, amend=amend,
|
||||
with_extended_output=True,
|
||||
with_stderr=True)
|
||||
os.unlink(tmpfile)
|
||||
|
||||
return (status, stdout+stderr)
|
||||
|
||||
return status, out
|
||||
|
||||
def diffindex(self):
|
||||
return self.git.diff(unified=self.diff_context,
|
||||
no_color=True,
|
||||
stat=True,
|
||||
cached=True)
|
||||
|
||||
@@ -727,7 +730,7 @@ class Model(model.Model):
|
||||
summaries = []
|
||||
regex = REV_LIST_REGEX
|
||||
output = self.git.log(pretty='oneline', all=all)
|
||||
for line in output.splitlines():
|
||||
for line in map(decode, output.splitlines()):
|
||||
match = regex.match(line)
|
||||
if match:
|
||||
revs.append(match.group(1))
|
||||
@@ -736,7 +739,7 @@ class Model(model.Model):
|
||||
|
||||
def parse_rev_list(self, raw_revs):
|
||||
revs = []
|
||||
for line in raw_revs.splitlines():
|
||||
for line in map(decode, raw_revs.splitlines()):
|
||||
match = REV_LIST_REGEX.match(line)
|
||||
if match:
|
||||
rev_id = match.group(1)
|
||||
@@ -786,20 +789,21 @@ class Model(model.Model):
|
||||
deleted = cached and not os.path.exists(encode(filename))
|
||||
|
||||
diffoutput = self.git.diff(R=reverse,
|
||||
no_color=True,
|
||||
cached=cached,
|
||||
patch_with_raw=patch_with_raw,
|
||||
unified=self.diff_context,
|
||||
with_raw_output=True,
|
||||
*argv)
|
||||
diff = diffoutput.splitlines()
|
||||
diff = diffoutput.split('\n')
|
||||
for line in map(decode, diff):
|
||||
if not start and '@@' == line[:2] and '@@' in line[2:]:
|
||||
start = True
|
||||
if start or(deleted and del_tag in line):
|
||||
if start or (deleted and del_tag in line):
|
||||
output.write(encode(line) + '\n')
|
||||
else:
|
||||
if with_diff_header:
|
||||
headers.append(line)
|
||||
headers.append(encode(line))
|
||||
elif not suppress_header:
|
||||
output.write(encode(line) + '\n')
|
||||
|
||||
@@ -844,18 +848,20 @@ class Model(model.Model):
|
||||
"""RETURNS: A tuple of staged, unstaged untracked, and unmerged
|
||||
file lists.
|
||||
"""
|
||||
self.git.update_index(refresh=True)
|
||||
self.partially_staged = set()
|
||||
head = 'HEAD'
|
||||
if amend:
|
||||
head = 'HEAD^'
|
||||
(staged, modified, unmerged, untracked) = ([], [], [], [])
|
||||
try:
|
||||
for name in self.git.diff_index(head).splitlines():
|
||||
rest, name = name.split('\t')
|
||||
for line in self.git.diff_index(head).splitlines():
|
||||
rest, name = line.split('\t')
|
||||
status = rest[-1]
|
||||
name = eval_path(name)
|
||||
if status == 'M' or status == 'D':
|
||||
modified.append(name)
|
||||
modified.append(eval_path(name))
|
||||
elif status == 'A':
|
||||
unmerged.append(eval_path(name))
|
||||
except:
|
||||
# handle git init
|
||||
for name in (self.git.ls_files(modified=True, z=True)
|
||||
@@ -864,26 +870,31 @@ class Model(model.Model):
|
||||
modified.append(decode(name))
|
||||
|
||||
try:
|
||||
for name in (self.git.diff_index(head, cached=True)
|
||||
for line in (self.git.diff_index(head, cached=True)
|
||||
.splitlines()):
|
||||
rest, name = name.split('\t')
|
||||
rest, name = line.split('\t')
|
||||
status = rest[-1]
|
||||
name = eval_path(name)
|
||||
if status == 'M':
|
||||
staged.append(name)
|
||||
# is this file partially staged?
|
||||
diff = self.git.diff('--', name, name_only=True, z=True)
|
||||
if not diff.strip():
|
||||
status, out = self.git.diff('--', name,
|
||||
name_only=True, exit_code=True,
|
||||
with_extended_output=True)
|
||||
if status == 0:
|
||||
modified.remove(name)
|
||||
else:
|
||||
self.partially_staged.add(name)
|
||||
elif status == 'A':
|
||||
staged.append(name)
|
||||
if name in unmerged:
|
||||
unmerged.remove(name)
|
||||
elif status == 'D':
|
||||
staged.append(name)
|
||||
modified.remove(name)
|
||||
elif status == 'U':
|
||||
unmerged.append(name)
|
||||
modified.remove(name)
|
||||
except:
|
||||
# handle git init
|
||||
for name in self.git.ls_files(z=True).strip('\0').split('\0'):
|
||||
@@ -895,11 +906,6 @@ class Model(model.Model):
|
||||
if name:
|
||||
untracked.append(decode(name))
|
||||
|
||||
# remove duplicate merged and modified entries
|
||||
for u in unmerged:
|
||||
if u in modified:
|
||||
modified.remove(u)
|
||||
|
||||
return (staged, modified, unmerged, untracked)
|
||||
|
||||
def reset_helper(self, args):
|
||||
@@ -924,8 +930,11 @@ class Model(model.Model):
|
||||
return self.git.config('remote.%s.url' % name, get=True)
|
||||
|
||||
def get_remote_args(self, remote,
|
||||
local_branch='', remote_branch='',
|
||||
ffwd=True, tags=False):
|
||||
local_branch='',
|
||||
remote_branch='',
|
||||
ffwd=True,
|
||||
tags=False,
|
||||
rebase=False):
|
||||
if ffwd:
|
||||
branch_arg = '%s:%s' % ( remote_branch, local_branch )
|
||||
else:
|
||||
@@ -936,6 +945,8 @@ class Model(model.Model):
|
||||
kwargs = {
|
||||
'verbose': True,
|
||||
'tags': tags,
|
||||
'rebase': rebase,
|
||||
'with_stderr': True,
|
||||
}
|
||||
return (args, kwargs)
|
||||
|
||||
@@ -1038,6 +1049,7 @@ class Model(model.Model):
|
||||
return self.git.diff(
|
||||
'HEAD^',
|
||||
unified=self.diff_context,
|
||||
no_color=True,
|
||||
stat=True)
|
||||
|
||||
def pad(self, pstr, num=22):
|
||||
@@ -1086,6 +1098,8 @@ class Model(model.Model):
|
||||
|
||||
def get_renamed_files(self, start, end):
|
||||
files = []
|
||||
difflines = self.git.diff('%s..%s' % (start, end), M=True).splitlines()
|
||||
difflines = self.git.diff('%s..%s' % (start, end),
|
||||
no_color=True,
|
||||
M=True).splitlines()
|
||||
return [ eval_path(r[12:].rstrip())
|
||||
for r in difflines if r.startswith('rename from ') ]
|
||||
|
||||
+21
-1
@@ -49,6 +49,8 @@ class QObserver(Observer, QObject):
|
||||
self.__model_to_view = {}
|
||||
self.__view_to_model = {}
|
||||
self.__connected = set()
|
||||
self.__in_textfield = False
|
||||
self.__in_callback = False
|
||||
|
||||
# Call the subclass's startup routine
|
||||
self.init(model, view, *args, **kwargs)
|
||||
@@ -60,6 +62,8 @@ class QObserver(Observer, QObject):
|
||||
"""Default slot to handle all Qt callbacks.
|
||||
This method delegates to callbacks from add_signals."""
|
||||
|
||||
self.__in_textfield = False
|
||||
|
||||
widget = self.sender()
|
||||
sender = str(widget.objectName())
|
||||
|
||||
@@ -67,10 +71,12 @@ class QObserver(Observer, QObject):
|
||||
model = self.model
|
||||
model_param = self.__view_to_model[sender]
|
||||
if isinstance(widget, QTextEdit):
|
||||
self.__in_textfield = True
|
||||
value = unicode(widget.toPlainText())
|
||||
model.set_param(model_param, value,
|
||||
notify=False)
|
||||
elif isinstance(widget, QLineEdit):
|
||||
self.__in_textfield = True
|
||||
value = unicode(widget.text())
|
||||
model.set_param(model_param, value)
|
||||
elif isinstance(widget, QCheckBox):
|
||||
@@ -79,6 +85,11 @@ class QObserver(Observer, QObject):
|
||||
model.set_param(model_param, widget.value())
|
||||
elif isinstance(widget, QFontComboBox):
|
||||
value = unicode(widget.currentFont().toString())
|
||||
if model.has_param(model_param+'_size'):
|
||||
size = model.get_param(model_param+'_size')
|
||||
props = value.split(',')
|
||||
props[1] = str(size)
|
||||
value = ','.join(props)
|
||||
model.set_param(model_param, value)
|
||||
elif isinstance(widget, QDateEdit):
|
||||
fmt = Qt.ISODate
|
||||
@@ -121,12 +132,15 @@ class QObserver(Observer, QObject):
|
||||
model.get_param(model_param)[idx])
|
||||
else:
|
||||
model.set_param(model_param+'_item', '')
|
||||
|
||||
|
||||
else:
|
||||
print("SLOT(): Unknown widget:", sender, widget)
|
||||
|
||||
self.__in_callback = True
|
||||
if sender in self.__callbacks:
|
||||
self.__callbacks[sender](*args)
|
||||
self.__in_callback = False
|
||||
self.__in_textfield = False
|
||||
|
||||
def connect(self, obj, signal_str, *args):
|
||||
"""Convenience function so that subclasses do not have
|
||||
@@ -223,6 +237,12 @@ class QObserver(Observer, QObject):
|
||||
def subject_changed(self, param, value):
|
||||
"""Sends a model param to the view(model->view)"""
|
||||
|
||||
if self.__in_textfield and not self.__in_callback:
|
||||
# A slot has changed the model and we're not in
|
||||
# a user callback. In this case the event is causing
|
||||
# a feedback loop so skip redundant work and return.
|
||||
return
|
||||
|
||||
if param in self.__model_to_view:
|
||||
notify = self.model.get_notify()
|
||||
self.model.set_notify(False)
|
||||
|
||||
+4
-11
@@ -30,10 +30,11 @@ def log(output, quiet=True, doraise=False):
|
||||
LOGGER.show()
|
||||
if not doraise:
|
||||
return
|
||||
raise_logger()
|
||||
LOGGER.raise_()
|
||||
|
||||
def raise_logger():
|
||||
def show_logger():
|
||||
"""Raises the log window."""
|
||||
LOGGER.show()
|
||||
LOGGER.raise_()
|
||||
|
||||
def input(msg, title=None):
|
||||
@@ -142,7 +143,7 @@ def open_dialog(parent, title, filename=None):
|
||||
|
||||
def opendir_dialog(parent, title, directory):
|
||||
"""Creates an Open Directory dialog and returns the file path."""
|
||||
flags = QtGui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontResolveSymlinks
|
||||
flags = QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks
|
||||
return unicode(QFileDialog.getExistingDirectory(parent, parent.tr(title),
|
||||
directory, flags))
|
||||
|
||||
@@ -152,14 +153,6 @@ def save_dialog(parent, title, filename=''):
|
||||
parent.tr(title),
|
||||
filename))
|
||||
|
||||
def new_dir_dialog(parent, title, filename=''):
|
||||
"""Creates a New Directory dialog and returns the file path."""
|
||||
return unicode(QFileDialog.getSaveFileName(parent,
|
||||
parent.tr(title),
|
||||
filename,
|
||||
os.getcwd(),
|
||||
parent.tr('New Directory ()')))
|
||||
|
||||
def get_icon(filename):
|
||||
"""Given a basename returns a QIcon from the corresponding cola icon."""
|
||||
return QIcon(utils.get_icon(filename))
|
||||
|
||||
+45
-12
@@ -7,6 +7,8 @@ import re
|
||||
import sys
|
||||
import platform
|
||||
import subprocess
|
||||
import mimetypes
|
||||
|
||||
from glob import glob
|
||||
from cStringIO import StringIO
|
||||
|
||||
@@ -21,17 +23,23 @@ ICONSDIR = os.path.join(PREFIX, 'share', 'cola', 'icons')
|
||||
STYLEDIR = os.path.join(PREFIX, 'share', 'cola', 'styles')
|
||||
DOCDIR = os.path.join(PREFIX, 'share', 'doc', 'cola')
|
||||
|
||||
KNOWN_FILE_TYPES = {
|
||||
'ascii c': 'c.png',
|
||||
KNOWN_FILE_MIME_TYPES = {
|
||||
'text': 'script.png',
|
||||
'image': 'image.png',
|
||||
'python': 'script.png',
|
||||
'ruby': 'script.png',
|
||||
'shell': 'script.png',
|
||||
'perl': 'script.png',
|
||||
'java': 'script.png',
|
||||
'assembler': 'binary.png',
|
||||
'binary': 'binary.png',
|
||||
'byte': 'binary.png',
|
||||
'image': 'image.png',
|
||||
'octet': 'binary.png',
|
||||
}
|
||||
|
||||
KNOWN_FILE_EXTENSION = {
|
||||
'.java': 'script.png',
|
||||
'.groovy': 'script.png',
|
||||
'.cpp': 'script.png',
|
||||
'.c': 'script.png',
|
||||
'.h': 'script.png',
|
||||
'.cxx': 'script.png',
|
||||
}
|
||||
|
||||
def run_cmd(*command):
|
||||
@@ -64,6 +72,17 @@ def get_stylesheet(name):
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_libexec(*args):
|
||||
"""Returns the path to the libexec scripts dir.
|
||||
This currently == 'bin' but it may change in the future.
|
||||
"""
|
||||
libexec = os.path.dirname(os.path.abspath(sys.argv[0]))
|
||||
return os.path.join(libexec, *args)
|
||||
|
||||
def get_style_dir():
|
||||
"""Returns the path to the style dir within the cola install tree."""
|
||||
return STYLEDIR
|
||||
|
||||
def get_htmldocs():
|
||||
"""Returns the path to the cola html documentation."""
|
||||
return os.path.join(DOCDIR, 'git-cola.html')
|
||||
@@ -71,10 +90,16 @@ def get_htmldocs():
|
||||
def ident_file_type(filename):
|
||||
"""Returns an icon based on the contents of filename."""
|
||||
if os.path.exists(filename):
|
||||
fileinfo = run_cmd('file','-b',filename)
|
||||
for filetype, iconname in KNOWN_FILE_TYPES.iteritems():
|
||||
if filetype in fileinfo.lower():
|
||||
filemimetype = mimetypes.guess_type(filename)
|
||||
if filemimetype[0] != None:
|
||||
for filetype, iconname in KNOWN_FILE_MIME_TYPES.iteritems():
|
||||
if filetype in filemimetype[0].lower():
|
||||
return iconname
|
||||
filename = filename.lower()
|
||||
for fileext, iconname in KNOWN_FILE_EXTENSION.iteritems():
|
||||
if filename.endswith(fileext):
|
||||
return iconname
|
||||
return 'generic.png'
|
||||
else:
|
||||
return 'removed.png'
|
||||
# Fallback for modified files of an unknown type
|
||||
@@ -103,7 +128,7 @@ def fork(*args):
|
||||
return os.spawnv(os.P_NOWAIT, filename, args)
|
||||
except os.error:
|
||||
pass
|
||||
raise IOError('cannot find executable: %s' % program)
|
||||
raise IOError('cannot find executable: %s' % args[0])
|
||||
else:
|
||||
argv = map(shell_quote, args)
|
||||
return os.system(' '.join(argv) + '&')
|
||||
@@ -340,7 +365,7 @@ class DiffParser(object):
|
||||
self.__idx = -1
|
||||
self.__headers = []
|
||||
|
||||
for idx, line in enumerate(diff.splitlines()):
|
||||
for idx, line in enumerate(diff.split('\n')):
|
||||
match = self.__header_re.match(line)
|
||||
if match:
|
||||
self.__headers.append([
|
||||
@@ -373,6 +398,14 @@ class DiffParser(object):
|
||||
"""Processes a diff selection and applies changes to the work tree
|
||||
or index."""
|
||||
if selection:
|
||||
# qt destroys \r\n and makes it \n with no way of going back.
|
||||
# boo! we work around that here
|
||||
if selection not in self.fwd_diff:
|
||||
special_selection = selection.replace('\n', '\r\n')
|
||||
if special_selection in self.fwd_diff:
|
||||
selection = special_selection
|
||||
else:
|
||||
return
|
||||
start = self.fwd_diff.index(selection)
|
||||
end = start + len(selection)
|
||||
self.set_diffs_to_range(start, end)
|
||||
|
||||
+26
-17
@@ -6,18 +6,20 @@
|
||||
import sys
|
||||
import time
|
||||
|
||||
from PyQt4 import QtCore
|
||||
from PyQt4.QtGui import QDialog
|
||||
from PyQt4.QtGui import QListWidget
|
||||
from PyQt4.QtGui import qApp
|
||||
from PyQt4.QtCore import SIGNAL
|
||||
|
||||
from cola.syntax import DiffSyntaxHighlighter
|
||||
from cola.syntax import LogSyntaxHighlighter
|
||||
from cola.views.standard import create_standard_view
|
||||
from cola.views.syntax import DiffSyntaxHighlighter
|
||||
from cola.views.syntax import LogSyntaxHighlighter
|
||||
from cola.core import decode
|
||||
|
||||
try:
|
||||
from main import View
|
||||
from main import CreateStandardView
|
||||
from cola.gui.about import Ui_about
|
||||
from cola.gui.bookmark import Ui_bookmark
|
||||
from cola.gui.branchview import Ui_branchview
|
||||
from cola.gui.combo import Ui_combo
|
||||
@@ -36,15 +38,22 @@ except ImportError:
|
||||
'Try running "make" in the cola source tree.\n')
|
||||
sys.exit(-1)
|
||||
|
||||
# These are views that do not contain any custom methods
|
||||
OptionsView = CreateStandardView(Ui_options, QDialog)
|
||||
BranchCompareView = CreateStandardView(Ui_branchview, QDialog)
|
||||
CreateBranchView = CreateStandardView(Ui_createbranch, QDialog)
|
||||
BookmarkView = CreateStandardView(Ui_bookmark, QDialog)
|
||||
StashView = CreateStandardView(Ui_stash, QDialog)
|
||||
CompareView = CreateStandardView(Ui_compare, QDialog)
|
||||
class AboutView(Ui_about, QDialog):
|
||||
def __init__(self, parent):
|
||||
QDialog.__init__(self, parent)
|
||||
Ui_about.__init__(self)
|
||||
self.setupUi(self)
|
||||
def set_version(self, version):
|
||||
self.spam.setText(self.spam.text().replace('$VERSION', version))
|
||||
|
||||
class LogView(CreateStandardView(Ui_logger, QDialog)):
|
||||
OptionsView = create_standard_view(Ui_options, QDialog)
|
||||
BranchCompareView = create_standard_view(Ui_branchview, QDialog)
|
||||
CreateBranchView = create_standard_view(Ui_createbranch, QDialog)
|
||||
BookmarkView = create_standard_view(Ui_bookmark, QDialog)
|
||||
StashView = create_standard_view(Ui_stash, QDialog)
|
||||
CompareView = create_standard_view(Ui_compare, QDialog)
|
||||
|
||||
class LogView(create_standard_view(Ui_logger, QDialog)):
|
||||
"""A simple dialog to display command logs."""
|
||||
def init(self, parent=None, output=None):
|
||||
self.setWindowTitle(self.tr('Git Command Log'))
|
||||
@@ -91,14 +100,14 @@ class ItemView(object):
|
||||
else:
|
||||
return None
|
||||
|
||||
class ComboView(CreateStandardView(Ui_combo, QDialog, ItemView), ItemView):
|
||||
class ComboView(create_standard_view(Ui_combo, QDialog, ItemView), ItemView):
|
||||
"""A dialog for choosing branches."""
|
||||
def idx(self):
|
||||
return self.items_widget.currentIndex()
|
||||
def value(self):
|
||||
return str(self.items_widget.currentText())
|
||||
|
||||
class ListView(CreateStandardView(Ui_items, QDialog, ItemView), ItemView):
|
||||
class ListView(create_standard_view(Ui_items, QDialog, ItemView), ItemView):
|
||||
"""A dialog for an item from a list."""
|
||||
def idx(self):
|
||||
return self.items_widget.currentRow()
|
||||
@@ -108,7 +117,7 @@ class ListView(CreateStandardView(Ui_items, QDialog, ItemView), ItemView):
|
||||
return None
|
||||
return str(item.text())
|
||||
|
||||
class CommitView(CreateStandardView(Ui_commit, QDialog)):
|
||||
class CommitView(create_standard_view(Ui_commit, QDialog)):
|
||||
def init(self, parent=None, title=None):
|
||||
if title: self.setWindowTitle(title)
|
||||
# Make the list widget slighty larger
|
||||
@@ -116,17 +125,17 @@ class CommitView(CreateStandardView(Ui_commit, QDialog)):
|
||||
self.syntax = DiffSyntaxHighlighter(self.commit_text.document(),
|
||||
whitespace=False)
|
||||
|
||||
class SearchView(CreateStandardView(Ui_search, QDialog)):
|
||||
class SearchView(create_standard_view(Ui_search, QDialog)):
|
||||
def init(self, parent=None):
|
||||
self.input.setFocus()
|
||||
self.syntax = DiffSyntaxHighlighter(self.commit_text.document(),
|
||||
whitespace=False)
|
||||
|
||||
class MergeView(CreateStandardView(Ui_merge, QDialog)):
|
||||
class MergeView(create_standard_view(Ui_merge, QDialog)):
|
||||
def init(self, parent=None):
|
||||
self.revision.setFocus()
|
||||
|
||||
class RemoteView(CreateStandardView(Ui_remote, QDialog)):
|
||||
class RemoteView(create_standard_view(Ui_remote, QDialog)):
|
||||
def init(self, parent=None, button_text=''):
|
||||
if button_text:
|
||||
self.action_button.setText(button_text)
|
||||
|
||||
+5
-36
@@ -6,39 +6,12 @@ from PyQt4.QtCore import SIGNAL
|
||||
from PyQt4.QtGui import QMainWindow
|
||||
|
||||
from cola import qtutils
|
||||
from cola import syntax
|
||||
from cola.syntax import DiffSyntaxHighlighter
|
||||
from cola.views.standard import create_standard_view
|
||||
from cola.views.syntax import DiffSyntaxHighlighter
|
||||
from cola.gui.main import Ui_main
|
||||
|
||||
def CreateStandardView(uiclass, qtclass, *classes):
|
||||
"""CreateStandardView returns a class closure of uiclass and qtclass.
|
||||
This class performs the standard setup common to all view classes."""
|
||||
class StandardView(uiclass, qtclass):
|
||||
def __init__(self, parent=None, *args, **kwargs):
|
||||
qtclass.__init__(self, parent)
|
||||
uiclass.__init__(self)
|
||||
self.parent_view = parent
|
||||
syntax.set_theme_properties(self)
|
||||
self.setupUi(self)
|
||||
self.init(parent, *args, **kwargs)
|
||||
for cls in classes:
|
||||
cls.init(self, parent, *args, **kwargs)
|
||||
def init(self, parent, *args, **kwargs):
|
||||
pass
|
||||
def get_properties(self):
|
||||
# user-definable color properties
|
||||
props = {}
|
||||
for name in syntax.default_colors:
|
||||
props[name] = getattr(self, '_'+name)
|
||||
return props
|
||||
def reset_syntax(self):
|
||||
if hasattr(self, 'syntax') and self.syntax:
|
||||
self.syntax.set_colors(self.get_properties())
|
||||
self.syntax.reset()
|
||||
syntax.install_theme_properties(StandardView)
|
||||
return StandardView
|
||||
|
||||
class View(CreateStandardView(Ui_main, QMainWindow)):
|
||||
class View(create_standard_view(Ui_main, QMainWindow)):
|
||||
"""The main cola interface."""
|
||||
IDX_STAGED = 0
|
||||
IDX_MODIFIED = 1
|
||||
@@ -60,10 +33,6 @@ class View(CreateStandardView(Ui_main, QMainWindow)):
|
||||
|
||||
# Default to creating a new commit(i.e. not an amend commit)
|
||||
self.new_commit_radio.setChecked(True)
|
||||
self.toolbar_show_log =\
|
||||
self.toolbar.addAction(qtutils.get_icon('git.png'),
|
||||
'Show/Hide Log Window')
|
||||
self.toolbar_show_log.setEnabled(True)
|
||||
|
||||
# Diff/patch syntax highlighter
|
||||
self.syntax = DiffSyntaxHighlighter(self.display_text.document())
|
||||
@@ -239,7 +208,7 @@ class View(CreateStandardView(Ui_main, QMainWindow)):
|
||||
translated = unicode(txt)
|
||||
self.statusBar().showMessage(translated)
|
||||
def show_editor(self):
|
||||
self.editor_dock.raise_()
|
||||
self.tabwidget.setCurrentIndex(1)
|
||||
def show_diff(self):
|
||||
self.tabwidget.setCurrentIndex(0)
|
||||
def action_cut(self):
|
||||
@@ -282,7 +251,7 @@ class View(CreateStandardView(Ui_main, QMainWindow)):
|
||||
return line
|
||||
def display(self, text):
|
||||
self.set_display(text)
|
||||
self.diff_dock.raise_()
|
||||
self.show_diff()
|
||||
def show_current_column(self):
|
||||
cursor = self.commitmsg.textCursor()
|
||||
colnum = cursor.columnNumber()
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
from PyQt4 import QtCore
|
||||
|
||||
from cola.views import syntax
|
||||
|
||||
|
||||
def create_standard_view(uiclass, qtclass, *classes):
|
||||
"""create_standard_view returns a class closure of uiclass and qtclass.
|
||||
This class performs the standard setup common to all view classes.
|
||||
|
||||
The reason we use a closure is because uiclass and qtclass are
|
||||
both dynamic.
|
||||
|
||||
"""
|
||||
class StandardView(uiclass, qtclass):
|
||||
def __init__(self, parent=None, *args, **kwargs):
|
||||
qtclass.__init__(self, parent)
|
||||
uiclass.__init__(self)
|
||||
self.__qtclass = qtclass
|
||||
self.setWindowFlags(QtCore.Qt.Window)
|
||||
self.parent_view = parent
|
||||
syntax.set_theme_properties(self)
|
||||
self.setupUi(self)
|
||||
self.init(parent, *args, **kwargs)
|
||||
for cls in classes:
|
||||
cls.init(self, parent, *args, **kwargs)
|
||||
def init(self, parent, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def show(self):
|
||||
"""Automatically centers dialogs relative to their
|
||||
parent window.
|
||||
|
||||
"""
|
||||
if self.parent_view:
|
||||
left = self.parent_view.x()
|
||||
width = self.parent_view.width()
|
||||
center_x = left + width/2
|
||||
|
||||
x = center_x - self.width()/2
|
||||
y = self.parent_view.y()
|
||||
|
||||
self.move(x, y)
|
||||
# Call the base Qt show()
|
||||
self.__qtclass.show(self)
|
||||
def get_properties(self):
|
||||
# user-definable color properties
|
||||
props = {}
|
||||
for name in syntax.default_colors:
|
||||
props[name] = getattr(self, '_'+name)
|
||||
return props
|
||||
def reset_syntax(self):
|
||||
if hasattr(self, 'syntax') and self.syntax:
|
||||
self.syntax.set_colors(self.get_properties())
|
||||
self.syntax.reset()
|
||||
syntax.install_theme_properties(StandardView)
|
||||
return StandardView
|
||||
@@ -16,6 +16,7 @@ def main():
|
||||
# ensure readable files
|
||||
old_mask = os.umask(0022)
|
||||
if sys.argv[1] in ['install', 'build']:
|
||||
__setup_environment()
|
||||
__check_python_version()
|
||||
__check_git_version()
|
||||
__check_pyqt_version()
|
||||
@@ -29,7 +30,22 @@ def main():
|
||||
# restore the old mask
|
||||
os.umask(old_mask)
|
||||
|
||||
def __setup_environment():
|
||||
if sys.platform != 'win32':
|
||||
return
|
||||
path = os.environ['PATH']
|
||||
win32 = os.path.join(os.path.dirname(__file__), 'win32')
|
||||
os.environ['PATH'] = win32 + os.pathsep + path
|
||||
|
||||
def __run_setup():
|
||||
|
||||
scripts = ['bin/git-cola', 'bin/git-difftool', 'bin/git-difftool-helper']
|
||||
if sys.platform == 'win32':
|
||||
scripts.append('win32/cola')
|
||||
scripts.append('win32/dirname')
|
||||
scripts.append('win32/py2exe-setup.py')
|
||||
scripts.append('win32/py2exe-setup.cmd')
|
||||
|
||||
setup(name = 'cola',
|
||||
version = version.version,
|
||||
license = 'GPLv2',
|
||||
@@ -38,7 +54,7 @@ def __run_setup():
|
||||
url = 'http://cola.tuxfamily.org/',
|
||||
description = 'GIT Cola',
|
||||
long_description = 'A highly caffeinated GIT GUI',
|
||||
scripts = ['bin/git-cola', 'bin/git-difftool'],
|
||||
scripts = scripts,
|
||||
packages = ['cola', 'cola.gui', 'cola.views', 'cola.controllers'],
|
||||
data_files = [
|
||||
__app_path('share/cola/qm', '*.qm'),
|
||||
@@ -95,8 +111,13 @@ def __check_git_version():
|
||||
def __check_pyqt_version():
|
||||
"""Check the minimum PYQT version
|
||||
"""
|
||||
pyqtver = utils.run_cmd('pyuic4', '--version').split()[-1]
|
||||
if not __check_min_version(version.pyqt_min_ver, pyqtver):
|
||||
fail = False
|
||||
try:
|
||||
pyqtver = __run_cmd('pyuic4', '--version').split()[-1]
|
||||
except IndexError:
|
||||
pyqtver = 'nothing'
|
||||
fail = True
|
||||
if fail or not __check_min_version(version.pyqt_min_ver, pyqtver):
|
||||
print >> sys.stderr, 'PYQT version %s or newer required. Found %s' \
|
||||
% (version.pyqt_min_ver, pyqtver)
|
||||
sys.exit(1)
|
||||
@@ -108,15 +129,29 @@ def __dirty(src, dst):
|
||||
dststat = os.stat(dst)
|
||||
return srcstat[stat.ST_MTIME] > dststat[stat.ST_MTIME]
|
||||
|
||||
def __workaround_pyuic4(src, dst):
|
||||
fh = open(src, 'r')
|
||||
contents = fh.read()
|
||||
fh.close()
|
||||
fh = open(dst, 'w')
|
||||
for line in contents.splitlines():
|
||||
if 'sortingenabled' in line.lower():
|
||||
continue
|
||||
fh.write(line+os.linesep)
|
||||
fh.close()
|
||||
os.unlink(src)
|
||||
|
||||
def __build_views():
|
||||
print 'running build_views'
|
||||
views = os.path.join('cola', 'gui')
|
||||
sources = glob('ui/*.ui')
|
||||
for src in sources:
|
||||
dst = os.path.join(views, os.path.basename(src)[:-3] + '.py')
|
||||
dsttmp = dst + '.tmp'
|
||||
if __dirty(src, dst):
|
||||
print '\tpyuic4 -x %s -o %s' % (src, dst)
|
||||
utils.run_cmd('pyuic4', '-x', src, '-o', dst)
|
||||
print '\tpyuic4 -x %s -o %s' % (src, dsttmp)
|
||||
utils.run_cmd('pyuic4', '-x', src, '-o', dsttmp)
|
||||
__workaround_pyuic4(dsttmp, dst)
|
||||
|
||||
def __build_translations():
|
||||
print 'running build_translations'
|
||||
@@ -128,4 +163,12 @@ def __build_translations():
|
||||
print '\tmsgfmt --qt %s -o %s' % (src, dst)
|
||||
utils.run_cmd('msgfmt', '--qt', src, '-o', dst)
|
||||
|
||||
def __run_cmd(*args):
|
||||
argstr = utils.shell_quote(*args)
|
||||
pipe = os.popen(argstr)
|
||||
contents = pipe.read().strip()
|
||||
pipe.close()
|
||||
return contents
|
||||
|
||||
|
||||
main()
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
@@ -85,7 +85,7 @@ SOURCE
|
||||
|
||||
A 'git-cola' development repository can be obtained via git:
|
||||
|
||||
git clone git://gitorious.org/git-cola/mainline.git cola
|
||||
git clone git://github.com/davvid/git-cola.git
|
||||
|
||||
|
||||
STYLESHEETS
|
||||
@@ -105,8 +105,8 @@ LINKS
|
||||
'git-cola' homepage::
|
||||
http://cola.tuxfamily.org/
|
||||
|
||||
'git-cola' sources on gitorious.org::
|
||||
http://gitorious.org/projects/git-cola/
|
||||
'git-cola' sources on github::
|
||||
http://github.com/davvid/git-cola/tree/master
|
||||
|
||||
|
||||
SEE ALSO
|
||||
|
||||
@@ -3,38 +3,36 @@ git-difftool(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-difftool - compare changes using standard git merge tools
|
||||
git-difftool - compare changes using common merge tools
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git difftool' [--tool=<tool>]
|
||||
[--commit=<ref> | --start=<ref> --end=<ref>]
|
||||
[--no-prompt]
|
||||
[--] [<file>]...
|
||||
'git difftool' [--tool=<tool>] [--no-prompt] ['git diff' options]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
'git-difftool' is a git command that allows you to compare and edit files
|
||||
between revisions using standard git merge tools. At its most basic level,
|
||||
between revisions using common merge tools. At its most basic level,
|
||||
'git-difftool' does what 'git-mergetool' does but its use is for non-merge
|
||||
situations, such as when preparing commits or comparing changes against
|
||||
situations such as when preparing commits or comparing changes against
|
||||
the index.
|
||||
|
||||
'git-difftool' shows differences between the work tree and the index by
|
||||
default but can also show differences between arbitrary commits by using
|
||||
the --start and --end options.
|
||||
'git difftool' is a frontend to 'git diff' and accepts the same
|
||||
arguments and options.
|
||||
|
||||
See linkgit:git-diff[1] for the full list of supported options.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
-t or --tool=<tool>::
|
||||
-t <tool>::
|
||||
--tool=<tool>::
|
||||
Use the merge resolution program specified by <tool>.
|
||||
Valid merge tools are:
|
||||
kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, and opendiff
|
||||
+
|
||||
If a merge resolution program is not specified, 'git-difftool'
|
||||
will use the configuration variable `merge.tool`. If the
|
||||
configuration variable `merge.tool` is not set, 'git-difftool'
|
||||
configuration variable `merge.tool` is not set, 'git difftool'
|
||||
will pick a suitable default.
|
||||
+
|
||||
You can explicitly provide a full path to the tool by setting the
|
||||
@@ -51,41 +49,17 @@ variable `mergetool.<tool>.cmd`.
|
||||
When 'git-difftool' is invoked with this tool (either through the
|
||||
`-t` or `--tool` option or the `merge.tool` configuration variable)
|
||||
the configured command line will be invoked with the following
|
||||
variables available: `$BASE` is set to the name of a temporary file
|
||||
containing the contents of the index; `$LOCAL` set to the name of a
|
||||
temporary file containing the contents of the file as it appears in
|
||||
the work tree; `$REMOTE` set to the name of a temporary file
|
||||
containing the contents of the file to be merged, and `$MERGED` set
|
||||
to the name of the file to which the merge tool should write the
|
||||
result of the merge resolution.
|
||||
+
|
||||
When `--start=<ref>` and `--end=<ref>` are specified
|
||||
`$LOCAL` contains the contents of the file from the
|
||||
starting revision and `$REMOTE` contains the contents
|
||||
of the file in the ending revision. `$BASE` contains
|
||||
the contents of the file in the work tree if it exists,
|
||||
and the starting revision otherwise.
|
||||
+
|
||||
If the custom merge tool correctly indicates the success of a
|
||||
merge resolution with its exit code then the configuration
|
||||
variable `mergetool.<tool>.trustExitCode` can be set to `true`.
|
||||
Otherwise, 'git-difftool' will prompt the user to indicate the
|
||||
success of the resolution after the custom tool has exited.
|
||||
|
||||
-c or --commit=<ref>::
|
||||
Specifies a commit reference for comparing against.
|
||||
'git-difftool' compares against the index by default.
|
||||
variables available: `$LOCAL` is set to the name of the temporary
|
||||
file containing the contents of the diff pre-image and `$REMOTE`
|
||||
is set to the name of the temporary file containing the contents
|
||||
of the diff post-image. `$BASE` is provided for compatibility
|
||||
with custom merge tool commands and has the same value as `$LOCAL`.
|
||||
|
||||
--no-prompt::
|
||||
Do not prompt before and after launching a merge tool.
|
||||
|
||||
-s or --start=<ref> and -e or --end=<ref>::
|
||||
See changes between commits start and end.
|
||||
This example shows the latest commit: `--start=HEAD^ --end=HEAD`.
|
||||
Do not prompt before launching a diff tool.
|
||||
|
||||
CONFIG VARIABLES
|
||||
----------------
|
||||
|
||||
merge.tool::
|
||||
The default merge tool to use.
|
||||
+
|
||||
@@ -104,28 +78,38 @@ mergetool.<tool>.cmd::
|
||||
+
|
||||
See the `--tool=<tool>` option above for more details.
|
||||
|
||||
mergetool.<tool>.trustExitCode::
|
||||
For a custom merge command, specify whether the exit code of
|
||||
the merge command can be used to determine whether the merge was
|
||||
successful. If this is not set to true then the merge target file
|
||||
timestamp is checked and the merge assumed to have been successful
|
||||
if the file has been updated, otherwise the user is prompted to
|
||||
indicate the success of the merge.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkgit:git-diff[1]::
|
||||
Show changes between commits, commit and working tree, etc
|
||||
|
||||
linkcola:git-cola[1]::
|
||||
'git-difftool' is part of the 'git-cola' project.
|
||||
|
||||
linkgit:git-mergetool[1]::
|
||||
'git-difftool' uses many of the same concepts as the core
|
||||
'git-mergetool' command.
|
||||
Run merge conflict resolution tools to resolve merge conflicts
|
||||
|
||||
linkgit:git-config[1]::
|
||||
Get and set repository or global options
|
||||
|
||||
linkgit:git-config[7]::
|
||||
Get and set repository or global options.
|
||||
|
||||
AUTHOR
|
||||
------
|
||||
Written by David Aguilar <davvid@gmail.com>.
|
||||
|
||||
Documentation
|
||||
--------------
|
||||
Documentation by David Aguilar and the git-list <git@vger.kernel.org>.
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the linkgit:git[1] suite
|
||||
|
||||
|
||||
NOTE: Patches to add 'git-difftool' to git.git's contrib area
|
||||
have been sent to the git mailing list. Packagers are encouraged
|
||||
to use git.git's contrib/difftool/ scripts instead of the ones
|
||||
distributed with cola. If git decides to make difftool part of
|
||||
its core command set then cola will promptly add build rules to
|
||||
conditionally install difftool based on the user's git version.
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
import sys
|
||||
sys.stderr.write('\0' * int(sys.argv[1]))
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
import sys
|
||||
sys.stdout.write('\0' * int(sys.argv[1]))
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
import sys
|
||||
if sys.argv[2] == 'stdout':
|
||||
sys.stdout.write('\0' * int(sys.argv[1]))
|
||||
sys.stderr.write('\0' * int(sys.argv[1]))
|
||||
else:
|
||||
sys.stderr.write('\0' * int(sys.argv[1]))
|
||||
sys.stdout.write('\0' * int(sys.argv[1]))
|
||||
@@ -0,0 +1,4 @@
|
||||
import os
|
||||
|
||||
def fixture(*paths):
|
||||
return os.path.join(os.path.dirname(__file__), 'fixtures', *paths)
|
||||
+77
-5
@@ -4,22 +4,94 @@ import unittest
|
||||
|
||||
from cola import git
|
||||
|
||||
import helper
|
||||
|
||||
class GitCommandTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.git = git.Git()
|
||||
|
||||
def testGitVersion(self):
|
||||
def test_version(self):
|
||||
version = self.git.version()
|
||||
self.failUnless(version.startswith('git version'))
|
||||
|
||||
def testGitTag(self):
|
||||
def test_tag(self):
|
||||
tags = self.git.tag().splitlines()
|
||||
self.failUnless( 'v1.0.0' in tags )
|
||||
|
||||
def testGitShow(self):
|
||||
id = '1b9742bda5d26a4f250fa64657f66ed20624a084'
|
||||
contents = self.git.show(id).splitlines()
|
||||
def test_show(self):
|
||||
sha = '1b9742bda5d26a4f250fa64657f66ed20624a084'
|
||||
contents = self.git.show(sha).splitlines()
|
||||
self.failUnless(contents[0] == '/build')
|
||||
|
||||
def test_stdout(self):
|
||||
status, out = git.Git.execute([helper.fixture('stdout.py'), '65536'],
|
||||
with_extended_output=True,
|
||||
with_raw_output=True)
|
||||
self.assertEqual(status, 0)
|
||||
self.assertEqual(len(out), 65536)
|
||||
|
||||
def test_stderr_empty(self):
|
||||
"""Test that stderr is ignored by Git.execute() without the with_stderr option."""
|
||||
status, out = git.Git.execute([helper.fixture('stderr.py'), '65536'],
|
||||
with_extended_output=True,
|
||||
with_raw_output=True)
|
||||
self.assertEqual(status, 0)
|
||||
self.assertEqual(len(out), 0)
|
||||
|
||||
def test_stderr_nonempty_with_stderr(self):
|
||||
"""Test that with_stderr makes Git.execute() see stderr."""
|
||||
status, out = git.Git.execute([helper.fixture('stderr.py'), '65536'],
|
||||
with_extended_output=True,
|
||||
with_stderr=True,
|
||||
with_raw_output=True)
|
||||
self.assertEqual(status, 0)
|
||||
self.assertEqual(len(out), 65536)
|
||||
|
||||
def test_stdout_and_stderr_ignores_stderr(self):
|
||||
"""Test ignoring stderr when both are provided."""
|
||||
status, out = git.Git.execute([helper.fixture('stdout_and_stderr.py'),
|
||||
'65536',
|
||||
'stdout'], # otherwise, same as below
|
||||
with_extended_output=True,
|
||||
with_raw_output=True)
|
||||
self.assertEqual(status, 0)
|
||||
self.assertEqual(len(out), 65536)
|
||||
|
||||
def test_stdout_and_stderr_ignores_stderr_v2(self):
|
||||
"""Test ignoring stderr when both are provided. (v2)"""
|
||||
# stdout_and_stderr.py swaps the order of the stdout, stderr write()
|
||||
# calls when argv[1] == 'stderr'.
|
||||
status, out = git.Git.execute([helper.fixture('stdout_and_stderr.py'),
|
||||
'65536',
|
||||
'stderr'], # otherwise, same as above
|
||||
with_extended_output=True,
|
||||
with_raw_output=True)
|
||||
self.assertEqual(status, 0)
|
||||
self.assertEqual(len(out), 65536)
|
||||
|
||||
def test_stdout_and_stderr_sees_stderr(self):
|
||||
"""Test seeing both stderr and stdout when both are available."""
|
||||
status, out = git.Git.execute([helper.fixture('stdout_and_stderr.py'),
|
||||
'65536',
|
||||
'stdout'], # otherwise, same as below
|
||||
with_extended_output=True,
|
||||
with_stderr=True,
|
||||
with_raw_output=True)
|
||||
self.assertEqual(status, 0)
|
||||
self.assertEqual(len(out), 65536 * 2)
|
||||
|
||||
def test_stdout_and_stderr_sees_stderr_v2(self):
|
||||
"""Test seeing both stderr and stdout when both are available (v2)."""
|
||||
# stdout_and_stderr.py swaps the order of the stdout, stderr write()
|
||||
# calls when argv[1] == 'stderr'.
|
||||
status, out = git.Git.execute([helper.fixture('stdout_and_stderr.py'),
|
||||
'65536',
|
||||
'stderr'], # otherwise, same as above
|
||||
with_extended_output=True,
|
||||
with_stderr=True,
|
||||
with_raw_output=True)
|
||||
self.assertEqual(status, 0)
|
||||
self.assertEqual(len(out), 65536 * 2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import testlib
|
||||
from testlib import InnerModel
|
||||
from testlib import NestedModel
|
||||
|
||||
import cola.model
|
||||
from cola.model import Model
|
||||
|
||||
class TestSaveRestore(unittest.TestCase):
|
||||
def setUp(self):
|
||||
testlib.create_test_dir()
|
||||
|
||||
self.nested = NestedModel()
|
||||
path = os.path.join(testlib.get_test_dir(), 'test.data')
|
||||
# save & reconstitute
|
||||
self.nested.save(path)
|
||||
self.clone = Model.instance(path)
|
||||
self._has_json = cola.model.has_json()
|
||||
if self._has_json:
|
||||
testlib.create_test_dir()
|
||||
self.nested = NestedModel()
|
||||
path = os.path.join(testlib.get_test_dir(), 'test.data')
|
||||
# save & reconstitute
|
||||
self.nested.save(path)
|
||||
self.clone = Model.instance(path)
|
||||
|
||||
def tearDown(self):
|
||||
testdir = testlib.get_test_dir()
|
||||
if os.path.exists(testdir):
|
||||
testlib.remove_test_dir()
|
||||
if self._has_json:
|
||||
testdir = testlib.get_test_dir()
|
||||
if os.path.exists(testdir):
|
||||
testlib.remove_test_dir()
|
||||
|
||||
def testCloneToClass(self):
|
||||
self.failUnless( str(NestedModel) ==
|
||||
@@ -55,5 +59,13 @@ class TestSaveRestore(unittest.TestCase):
|
||||
self.failUnless( str(InnerModel) ==
|
||||
str(self.clone.innerList[-1]["foo"].__class__))
|
||||
|
||||
# All of these tests require simplejson.
|
||||
# Replace all test methods with a stub lambda function
|
||||
# if simplejson is not available.
|
||||
if not cola.model.has_json():
|
||||
for thing in dir(TestSaveRestore):
|
||||
if thing.startswith('test'):
|
||||
setattr(TestSaveRestore, thing, lambda x: True)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -8,17 +8,10 @@ import testlib
|
||||
class ImportTest(testlib.TestCase):
|
||||
pass
|
||||
|
||||
def gen_class(module):
|
||||
def gen_class(themodule):
|
||||
def import_test(self):
|
||||
modinfo = None
|
||||
for idx, path in enumerate(module.split('.')):
|
||||
if idx == 0:
|
||||
modinfo = imp.find_module(path)
|
||||
mod = imp.load_module(module, *modinfo)
|
||||
else:
|
||||
modinfo = imp.find_module('cola/'+path, modinfo[0])
|
||||
mod = imp.load_module(path, *modinfo)
|
||||
self.failUnless(mod)
|
||||
mod = __import__(themodule)
|
||||
self.failUnless(mod)
|
||||
return import_test
|
||||
|
||||
def __create_tests():
|
||||
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
<ui version="4.0" >
|
||||
<class>about</class>
|
||||
<widget class="QDialog" name="about" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>280</width>
|
||||
<height>420</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>280</width>
|
||||
<height>420</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize" >
|
||||
<size>
|
||||
<width>280</width>
|
||||
<height>420</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>about git cola</string>
|
||||
</property>
|
||||
<property name="styleSheet" >
|
||||
<string notr="true" >QWidget { background-color: white; color: #666; }</string>
|
||||
</property>
|
||||
<widget class="QLabel" name="ham" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-10</y>
|
||||
<width>291</width>
|
||||
<height>121</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap" >
|
||||
<pixmap>images:logo-cola.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="spam" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>110</y>
|
||||
<width>261</width>
|
||||
<height>261</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font" >
|
||||
<font>
|
||||
<family>Sans Serif</family>
|
||||
<pointsize>7</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>git cola: a highly caffeinated git gui v$VERSION
|
||||
|
||||
cola is a sweet, carbonated git gui known for its
|
||||
sugary flavour and caffeine-inspired features.
|
||||
|
||||
|
||||
Copyright (C) 2009 David Aguilar and contributors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
</string>
|
||||
</property>
|
||||
<property name="textFormat" >
|
||||
<enum>Qt::LogText</enum>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags" >
|
||||
<set>Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="kthx" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>60</x>
|
||||
<y>380</y>
|
||||
<width>160</width>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>kthx bye</string>
|
||||
</property>
|
||||
<property name="default" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>kthx</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>about</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>139</x>
|
||||
<y>391</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>140</x>
|
||||
<y>209</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
+3
-19
@@ -5,8 +5,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>531</width>
|
||||
<height>513</height>
|
||||
<width>494</width>
|
||||
<height>238</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
@@ -44,7 +44,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>91</width>
|
||||
<height>20</height>
|
||||
@@ -72,22 +72,6 @@
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>button_save</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>bookmark</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>398</x>
|
||||
<y>490</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>265</x>
|
||||
<y>256</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>button_cancel</sender>
|
||||
<signal>clicked()</signal>
|
||||
|
||||
+2
-2
@@ -5,8 +5,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>680</width>
|
||||
<height>537</height>
|
||||
<width>658</width>
|
||||
<height>350</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
|
||||
+3
-3
@@ -5,8 +5,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>780</width>
|
||||
<height>512</height>
|
||||
<width>531</width>
|
||||
<height>467</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
@@ -97,7 +97,7 @@
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="button_box" >
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
+2
-2
@@ -5,8 +5,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>775</width>
|
||||
<height>454</height>
|
||||
<width>649</width>
|
||||
<height>372</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
|
||||
+9
-54
@@ -5,8 +5,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>621</width>
|
||||
<height>402</height>
|
||||
<width>527</width>
|
||||
<height>304</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
@@ -16,16 +16,7 @@
|
||||
<property name="spacing" >
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<property name="margin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -51,16 +42,7 @@
|
||||
<property name="spacing" >
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<property name="margin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -111,7 +93,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>201</width>
|
||||
<height>20</height>
|
||||
@@ -132,16 +114,7 @@
|
||||
<property name="spacing" >
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<property name="margin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -153,16 +126,7 @@
|
||||
<property name="spacing" >
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<property name="margin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -231,7 +195,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>328</width>
|
||||
<height>46</height>
|
||||
@@ -249,16 +213,7 @@
|
||||
<property name="spacing" >
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<property name="margin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
|
||||
+2
-2
@@ -5,8 +5,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>490</width>
|
||||
<height>372</height>
|
||||
<width>523</width>
|
||||
<height>299</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
|
||||
+7
-16
@@ -5,32 +5,23 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>830</width>
|
||||
<height>390</height>
|
||||
<width>715</width>
|
||||
<height>306</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="leftMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="horizontalSpacing" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="verticalSpacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="4" >
|
||||
<widget class="QTextEdit" name="output_text" >
|
||||
<property name="font" >
|
||||
@@ -55,7 +46,7 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags" >
|
||||
<set>Qt::NoTextInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -105,7 +96,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>217</width>
|
||||
<height>24</height>
|
||||
|
||||
+37
-42
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>621</width>
|
||||
<height>281</height>
|
||||
<width>630</width>
|
||||
<height>295</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="dockOptions" >
|
||||
@@ -52,7 +52,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex" >
|
||||
<number>0</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="diffwidget" >
|
||||
<attribute name="title" >
|
||||
@@ -154,6 +154,13 @@
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="rescan_button" >
|
||||
<property name="text" >
|
||||
<string>Rescan</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="stage_button" >
|
||||
<property name="sizePolicy" >
|
||||
@@ -271,6 +278,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="stash_button" >
|
||||
<property name="text" >
|
||||
<string>Stash</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
@@ -298,14 +312,6 @@
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>stage_button</zorder>
|
||||
<zorder>signoff_button</zorder>
|
||||
<zorder>commit_button</zorder>
|
||||
<zorder>fetch_button</zorder>
|
||||
<zorder>push_button</zorder>
|
||||
<zorder>pull_button</zorder>
|
||||
<zorder>column_label</zorder>
|
||||
<zorder></zorder>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -424,8 +430,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>621</width>
|
||||
<height>22</height>
|
||||
<width>630</width>
|
||||
<height>26</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="commit_menu" >
|
||||
@@ -461,6 +467,7 @@
|
||||
<addaction name="menuPrepare" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="menu_commit_compare" />
|
||||
<addaction name="menu_commit_compare_file" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="menu_stash" />
|
||||
<addaction name="menu_export_patches" />
|
||||
@@ -540,6 +547,7 @@
|
||||
<addaction name="menu_clone_repo" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="menu_rescan" />
|
||||
<addaction name="menu_view_log" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="menu_manage_bookmarks" />
|
||||
<addaction name="menu_save_bookmark" />
|
||||
@@ -562,6 +570,7 @@
|
||||
<string>Help</string>
|
||||
</property>
|
||||
<addaction name="menu_help_docs" />
|
||||
<addaction name="menu_help_about" />
|
||||
</widget>
|
||||
<addaction name="file_menu" />
|
||||
<addaction name="edit_menu" />
|
||||
@@ -571,35 +580,6 @@
|
||||
<addaction name="merge_menu" />
|
||||
<addaction name="help_menu" />
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolbar" >
|
||||
<property name="enabled" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>toolbar</string>
|
||||
</property>
|
||||
<property name="movable" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="allowedAreas" >
|
||||
<set>Qt::BottomToolBarArea|Qt::TopToolBarArea</set>
|
||||
</property>
|
||||
<property name="iconSize" >
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="floatable" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="toolBarArea" >
|
||||
<enum>BottomToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak" >
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<action name="menu_unstage_selected" >
|
||||
<property name="text" >
|
||||
<string>Unstage From Commit</string>
|
||||
@@ -915,6 +895,21 @@
|
||||
<string>Get Commit Message Template</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_commit_compare_file" >
|
||||
<property name="text" >
|
||||
<string>Compare File...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_view_log" >
|
||||
<property name="text" >
|
||||
<string>VIew Log</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_help_about" >
|
||||
<property name="text" >
|
||||
<string>About</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="2" margin="2" />
|
||||
<resources/>
|
||||
|
||||
+2
-5
@@ -41,10 +41,7 @@
|
||||
<property name="bottomMargin" >
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="horizontalSpacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing" >
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0" >
|
||||
@@ -102,7 +99,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>231</width>
|
||||
<height>24</height>
|
||||
|
||||
+130
-92
@@ -8,16 +8,31 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>654</width>
|
||||
<height>370</height>
|
||||
<width>469</width>
|
||||
<height>384</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_2" >
|
||||
<layout class="QGridLayout" name="gridLayout_4" >
|
||||
<property name="leftMargin" >
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item row="0" column="0" >
|
||||
<layout class="QGridLayout" name="gridLayout" >
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
@@ -25,16 +40,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QSpinBox" name="global_cola_fontuisize" >
|
||||
<property name="minimum" >
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>12</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2" >
|
||||
<widget class="QFontComboBox" name="global_cola_fontui" >
|
||||
<property name="currentFont" >
|
||||
@@ -52,7 +57,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QSpinBox" name="global_cola_fontdiffsize" >
|
||||
<widget class="QSpinBox" name="global_cola_fontdiff_size" >
|
||||
<property name="minimum" >
|
||||
<number>8</number>
|
||||
</property>
|
||||
@@ -74,71 +79,111 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_13" >
|
||||
<widget class="QLabel" name="label_14" >
|
||||
<property name="text" >
|
||||
<string>Editor</string>
|
||||
<string>Tab Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLineEdit" name="global_gui_editor" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
<widget class="QSpinBox" name="global_cola_tabwidth" >
|
||||
<property name="wrapping" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>42</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" >
|
||||
<widget class="QLabel" name="label_11" >
|
||||
<property name="text" >
|
||||
<string>History browser</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3" >
|
||||
<widget class="QLineEdit" name="global_gui_historybrowser" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_12" >
|
||||
<property name="text" >
|
||||
<string>Merge Tool</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QLineEdit" name="global_merge_tool" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" >
|
||||
<widget class="QCheckBox" name="global_cola_savewindowsettings" >
|
||||
<property name="text" >
|
||||
<string>Save GUI Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3" >
|
||||
<item row="2" column="3" >
|
||||
<widget class="QCheckBox" name="global_merge_keepbackup" >
|
||||
<property name="text" >
|
||||
<string>Save *.orig Merge Backups</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_13" >
|
||||
<property name="text" >
|
||||
<string>Editor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="3" >
|
||||
<widget class="QLineEdit" name="global_gui_editor" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" >
|
||||
<widget class="QLabel" name="label_11" >
|
||||
<property name="text" >
|
||||
<string>History Browser</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="3" >
|
||||
<widget class="QLineEdit" name="global_gui_historybrowser" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" >
|
||||
<widget class="QLabel" name="label_12" >
|
||||
<property name="text" >
|
||||
<string>Merge Tool</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="3" >
|
||||
<widget class="QLineEdit" name="global_merge_tool" >
|
||||
<property name="text" >
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QSpinBox" name="global_cola_fontui_size" >
|
||||
<property name="minimum" >
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>12</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8" >
|
||||
<item row="1" column="0" >
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" >
|
||||
<property name="spacing" >
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="local_groupbox" >
|
||||
<property name="title" >
|
||||
<string>Local Repository</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" >
|
||||
<layout class="QGridLayout" name="gridLayout_2" >
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="text" >
|
||||
<string>User Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2" >
|
||||
<widget class="QLineEdit" name="local_user_name" />
|
||||
</item>
|
||||
@@ -153,27 +198,13 @@
|
||||
<widget class="QLineEdit" name="local_user_email" />
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2" >
|
||||
<widget class="QCheckBox" name="local_merge_summary" >
|
||||
<property name="text" >
|
||||
<string>Summarize Merge Commits</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3" >
|
||||
<widget class="QCheckBox" name="local_merge_diffstat" >
|
||||
<property name="text" >
|
||||
<string>Show Diffstat After Merge</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2" >
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="text" >
|
||||
<string>Merge Verbosity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2" >
|
||||
<item row="2" column="2" >
|
||||
<widget class="QSpinBox" name="local_merge_verbosity" >
|
||||
<property name="minimum" >
|
||||
<number>0</number>
|
||||
@@ -186,14 +217,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2" >
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Number of Diff Context Lines</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2" >
|
||||
<item row="3" column="2" >
|
||||
<widget class="QSpinBox" name="local_gui_diffcontext" >
|
||||
<property name="minimum" >
|
||||
<number>2</number>
|
||||
@@ -203,10 +234,17 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<item row="4" column="0" colspan="2" >
|
||||
<widget class="QCheckBox" name="local_merge_summary" >
|
||||
<property name="text" >
|
||||
<string>User Name</string>
|
||||
<string>Summarize Merge Commits</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2" >
|
||||
<widget class="QCheckBox" name="local_merge_diffstat" >
|
||||
<property name="text" >
|
||||
<string>Show Diffstat After Merge</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -218,7 +256,7 @@
|
||||
<property name="title" >
|
||||
<string>Global (All Repositories)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<layout class="QGridLayout" name="gridLayout_3" >
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_7" >
|
||||
<property name="text" >
|
||||
@@ -240,27 +278,13 @@
|
||||
<widget class="QLineEdit" name="global_user_email" />
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2" >
|
||||
<widget class="QCheckBox" name="global_merge_summary" >
|
||||
<property name="text" >
|
||||
<string>Summarize Merge Commits</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3" >
|
||||
<widget class="QCheckBox" name="global_merge_diffstat" >
|
||||
<property name="text" >
|
||||
<string>Show Diffstat After Merge</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2" >
|
||||
<widget class="QLabel" name="label_10" >
|
||||
<property name="text" >
|
||||
<string>Merge Verbosity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2" >
|
||||
<item row="2" column="2" >
|
||||
<widget class="QSpinBox" name="global_merge_verbosity" >
|
||||
<property name="minimum" >
|
||||
<number>0</number>
|
||||
@@ -273,14 +297,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2" >
|
||||
<item row="3" column="0" colspan="2" >
|
||||
<widget class="QLabel" name="label_9" >
|
||||
<property name="text" >
|
||||
<string>Number of Diff Context Lines</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2" >
|
||||
<item row="3" column="2" >
|
||||
<widget class="QSpinBox" name="global_gui_diffcontext" >
|
||||
<property name="minimum" >
|
||||
<number>2</number>
|
||||
@@ -290,12 +314,26 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2" >
|
||||
<widget class="QCheckBox" name="global_merge_summary" >
|
||||
<property name="text" >
|
||||
<string>Summarize Merge Commits</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2" >
|
||||
<widget class="QCheckBox" name="global_merge_diffstat" >
|
||||
<property name="text" >
|
||||
<string>Show Diffstat After Merge</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<item row="2" column="0" >
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9" >
|
||||
<item>
|
||||
<spacer name="horizontalSpacer" >
|
||||
|
||||
+8
-1
@@ -83,12 +83,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="rebase_checkbox" >
|
||||
<property name="text" >
|
||||
<string>Rebase</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
|
||||
+4
-4
@@ -6,7 +6,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>550</height>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
@@ -97,7 +97,7 @@
|
||||
<item row="2" column="3" >
|
||||
<widget class="QDateEdit" name="start_date" >
|
||||
<property name="currentSection" >
|
||||
<enum>QDateTimeEdit::DaySection</enum>
|
||||
<enum>QDateTimeEdit::YearSection</enum>
|
||||
</property>
|
||||
<property name="displayFormat" >
|
||||
<string>yyyy-MM-dd</string>
|
||||
@@ -110,7 +110,7 @@
|
||||
<item row="2" column="4" >
|
||||
<widget class="QDateEdit" name="end_date" >
|
||||
<property name="currentSection" >
|
||||
<enum>QDateTimeEdit::DaySection</enum>
|
||||
<enum>QDateTimeEdit::YearSection</enum>
|
||||
</property>
|
||||
<property name="displayFormat" >
|
||||
<string>yyyy-MM-dd</string>
|
||||
@@ -216,7 +216,7 @@
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>111</width>
|
||||
<height>20</height>
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
# This should work with either Python2.5 or Python2.6.
|
||||
|
||||
dirname() {
|
||||
dir=$(echo "$1" | perl -pe 's,(.*)/[^/]+,\1,')
|
||||
test "$dir" = "$1" && dir=.
|
||||
echo "$dir"
|
||||
}
|
||||
|
||||
mydir="$(dirname $0)"
|
||||
parentdir="$(dirname $mydir)"
|
||||
|
||||
for python in /c/Python26 /c/Python25; do
|
||||
if test -d "$python"; then
|
||||
PATH="$PATH":$python
|
||||
exec $python/python.exe "$parentdir"/bin/git-cola "$@"
|
||||
fi
|
||||
done
|
||||
exit 1
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
""":"
|
||||
exec python $0 ${1+"$@"}; exit
|
||||
"""
|
||||
# msysgit does not include dirname.exe, so this simple python
|
||||
# script should do the trick.
|
||||
import sys
|
||||
if len(sys.argv) > 1:
|
||||
item = sys.argv[1]
|
||||
if '\\' in item:
|
||||
joinchar = '\\' # allow win32..
|
||||
else:
|
||||
joinchar = '/' # but assume unix
|
||||
item = item.rstrip(joinchar)
|
||||
while joinchar+joinchar in item:
|
||||
item = item.replace(joinchar+joinchar, joinchar)
|
||||
items = item.split(joinchar)
|
||||
dirname = joinchar.join(items[:-1])
|
||||
print dirname or '.'
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(1)
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
for python in /c/Python26 /c/Python25; do
|
||||
if test -d "$python"; then
|
||||
exec $python/python.exe \
|
||||
$python/Lib/site-packages/PyQt4/uic/pyuic.py "$@"
|
||||
fi
|
||||
done
|
||||
exit 1
|
||||
Reference in New Issue
Block a user