by
Changes to 60 files · Browse files at 4aef84ddfc38 Showing diff from parent 948eecf30fb6 40846ddb2223 Diff from another changeset...
@@ -56,3 +56,4 @@ d5cd872f61fde0c1d1b279af4f3b90ff6ade3161 2.0.3
26a8187ef879c83c2055044fa2080a640145d542 2.0.4
f2165388e6870c643636a0a74f1ebd1d008bdf3e 2.0.5
+2a970d5e40fe4f757347464d820218809d58251b 2.1
|
@@ -2,9 +2,9 @@
* hg status -ar --rev 1.6:tip # find new files that WiX needs to know about
* Pull latest translations from Launchpad
+* update url in qtlib.openhelpcontents() (major release only)
* set revision number in doc/source/conf.py
* tag stable branch of repository, push
-* update url in qtlib.openhelpcontents() (major release only)
* build pdf hgbook, check into thg-winbuild (major release only)
* build release installer
* commit extension versions, tag, push thg-winbuild
|
@@ -49,9 +49,9 @@ # built documents.
#
# The short X.Y version.
-version = '2.0'
+version = '2.1'
# The full version, including alpha/beta/rc tags.
-release = '2.0.5'
+release = '2.1.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
|
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
@@ -60,14 +60,46 @@ from tortoisehg.util.hgversion import hgversion, checkhgversion
errmsg = checkhgversion(hgversion)
if errmsg:
+ from mercurial import ui
from tortoisehg.hgqt.bugreport import run
from tortoisehg.hgqt.run import qtrun
opts = {}
opts['cmd'] = ' '.join(sys.argv[1:])
opts['error'] = '\n' + errmsg + '\n'
opts['nofork'] = True
- qtrun(run, ui, **opts)
+ qtrun(run, ui.ui(), **opts)
sys.exit(1)
-ret = tortoisehg.hgqt.run.dispatch(sys.argv[1:])
-sys.exit(ret)
+if 'THGDEBUG' in os.environ or '--profile' in sys.argv:
+ sys.exit(tortoisehg.hgqt.run.dispatch(sys.argv[1:]))
+else:
+ import cStringIO
+ mystderr = cStringIO.StringIO()
+ origstderr = sys.stderr
+ sys.stderr = mystderr
+ ret = 0
+ try:
+ ret = tortoisehg.hgqt.run.dispatch(sys.argv[1:])
+ sys.stderr = origstderr
+ stderrout = mystderr.getvalue()
+ errors = ('Traceback', 'TypeError', 'NameError', 'AttributeError',
+ 'NotImplementedError')
+ for l in stderrout.splitlines():
+ if l.startswith(errors):
+ from mercurial import ui
+ from tortoisehg.hgqt.bugreport import run
+ from tortoisehg.hgqt.run import qtrun
+ opts = {}
+ opts['cmd'] = ' '.join(sys.argv[1:])
+ opts['error'] = 'Recoverable error (stderr):\n' + stderrout
+ opts['nofork'] = True
+ qtrun(run, ui.ui(), **opts)
+ break
+ sys.exit(ret)
+ except:
+ if sys.exc_info()[0] not in [SystemExit, KeyboardInterrupt]:
+ import traceback
+ sys.stderr = origstderr
+ traceback.print_exc()
+ else:
+ raise SystemExit(ret)
|
@@ -542,6 +542,7 @@ def __init__(self, repo, parent):
super(ResultPage, self).__init__(repo, parent)
self.setTitle(_('Finished'))
+ self.setSubTitle(' ')
self.setFinalPage(True)
self.setLayout(QVBoxLayout())
|
@@ -12,7 +12,7 @@ #
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
Qt4 widgets to display diffs as blocks
|
@@ -246,6 +246,8 @@ self.proxy_chk.setVisible(visible)
self.insecure_chk.setVisible(visible)
self.qclone_chk.setVisible(visible)
+ self.qclone_txt.setVisible(visible)
+ self.qclone_btn.setVisible(visible)
self.remote_chk.setVisible(visible)
self.remote_text.setVisible(visible)
self.startrev_chk.setVisible(visible and self.startrev_available())
|
@@ -12,7 +12,7 @@ #
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
Qt4 dialogs to display hg revisions of a file
"""
|
@@ -12,7 +12,7 @@ #
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import re
|
@@ -12,7 +12,7 @@ #
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os
|
@@ -12,7 +12,7 @@ #
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from tortoisehg.hgqt.repomodel import HgRepoListModel, COLUMNHEADERS
from tortoisehg.hgqt.graph import Graph, filelog_grapher
|
|
|
@@ -7,6 +7,7 @@
import os
import difflib
+import re
from mercurial import error, util
@@ -28,6 +29,8 @@class HgFileView(QFrame):
"file diff, content, and annotation viewer"
+ diffHeaderRegExp = re.compile("^@@ -[0-9]+,[0-9]+ \+[0-9]+,[0-9]+ @@$")
+
linkActivated = pyqtSignal(QString)
fileDisplayed = pyqtSignal(QString, QString)
showMessage = pyqtSignal(QString)
@@ -48,6 +51,8 @@ l.setSpacing(0)
self.repo = repo
+ self._diffs = []
+
self.topLayout = QVBoxLayout()
self.labelhbox = hbox = QHBoxLayout()
@@ -290,6 +295,7 @@ @pyqtSlot()
def clearDisplay(self):
self._filename = None
+ self._diffs = []
self.restrictModes(False, False, False)
self.sci.setMarginWidth(1, 0)
self.clearMarkup()
@@ -317,6 +323,7 @@ self._filename, self._status = filename, status
self.clearMarkup()
+ self._diffs = []
if filename is None:
self.restrictModes(False, False, False)
return
@@ -420,11 +427,13 @@ self.blk.setVisible(True)
self.blk.syncPageStep()
- if self._mode != DiffMode and fd.contents and fd.olddata:
+ if fd.contents and fd.olddata:
if self.timer.isActive():
self.timer.stop()
self._fd = fd
self.timer.start()
+ self.actionNextDiff.setEnabled(bool(self._diffs))
+ self.actionPrevDiff.setEnabled(bool(self._diffs))
#
# These four functions are used by Shift+Cursor actions in revdetails
@@ -462,34 +471,68 @@ #
def timerBuildDiffMarkers(self):
'show modified and added lines in the self.blk margin'
+ # The way the diff markers are generated differs between the DiffMode
+ # and the other modes
+ # In the DiffMode case, the marker positions are found by looking for
+ # lines matching a regular expression representing a diff header, while
+ # in all other cases we use the difflib.SequenceMatcher, which returns
+ # a set of opcodes that must be parsed
+ # In any case, the markers are generated incrementally. This function is
+ # run by a timer, which each time that is called processes a bunch of
+ # lines (when in DiffMode) or of opcodes (in all other modes).
+ # When there are no more lines or opcodes to consume the timer is
+ # stopped.
+
self.sci.setUpdatesEnabled(False)
self.blk.setUpdatesEnabled(False)
- if self._fd:
- olddata = self._fd.olddata.splitlines()
- newdata = self._fd.contents.splitlines()
- diff = difflib.SequenceMatcher(None, olddata, newdata)
- self._opcodes = diff.get_opcodes()
- self._fd = None
- self._diffs = []
+ if self._mode == DiffMode:
+ if self._fd:
+ self._fd = None
+ self._diffs = []
+ self._linestoprocess = unicode(self.sci.text()).splitlines()
+ self._firstlinetoprocess = 0
+ self._opcodes = True
+ # Process linesPerBlock lines at a time
+ linesPerBlock = 100
+ # Look for lines matching the "diff header"
+ for n, line in enumerate(self._linestoprocess[:linesPerBlock]):
+ if self.diffHeaderRegExp.match(line):
+ diffLine = self._firstlinetoprocess + n
+ self._diffs.append([diffLine, diffLine])
+ self.sci.markerAdd(diffLine, self.markerplus)
+ self._linestoprocess = self._linestoprocess[linesPerBlock:]
+ self._firstlinetoprocess += linesPerBlock
+ if not self._linestoprocess:
+ self._opcodes = False
+ self._firstlinetoprocess = 0
+ else:
+ if self._fd:
+ olddata = self._fd.olddata.splitlines()
+ newdata = self._fd.contents.splitlines()
+ diff = difflib.SequenceMatcher(None, olddata, newdata)
+ self._opcodes = diff.get_opcodes()
+ self._fd = None
+ self._diffs = []
- for tag, alo, ahi, blo, bhi in self._opcodes[:30]:
- if tag == 'replace':
- self._diffs.append([blo, bhi])
- self.blk.addBlock('x', blo, bhi)
- for i in range(blo, bhi):
- self.sci.markerAdd(i, self.markertriangle)
- elif tag == 'insert':
- self._diffs.append([blo, bhi])
- self.blk.addBlock('+', blo, bhi)
- for i in range(blo, bhi):
- self.sci.markerAdd(i, self.markerplus)
- elif tag in ('equal', 'delete'):
- pass
- else:
- raise ValueError, 'unknown tag %r' % (tag,)
+ for tag, alo, ahi, blo, bhi in self._opcodes[:30]:
+ if tag == 'replace':
+ self._diffs.append([blo, bhi])
+ self.blk.addBlock('x', blo, bhi)
+ for i in range(blo, bhi):
+ self.sci.markerAdd(i, self.markertriangle)
+ elif tag == 'insert':
+ self._diffs.append([blo, bhi])
+ self.blk.addBlock('+', blo, bhi)
+ for i in range(blo, bhi):
+ self.sci.markerAdd(i, self.markerplus)
+ elif tag in ('equal', 'delete'):
+ pass
+ else:
+ raise ValueError, 'unknown tag %r' % (tag,)
- self._opcodes = self._opcodes[30:]
+ self._opcodes = self._opcodes[30:]
+
if not self._opcodes:
self.actionNextDiff.setEnabled(bool(self._diffs))
self.actionPrevDiff.setEnabled(False)
@@ -499,36 +542,38 @@ self.blk.setUpdatesEnabled(True)
def nextDiff(self):
- if self._mode == DiffMode or not self._diffs:
+ if not self._diffs:
self.actionNextDiff.setEnabled(False)
self.actionPrevDiff.setEnabled(False)
return
- row, column = self.sci.getCursorPosition()
- for i, (lo, hi) in enumerate(self._diffs):
- if lo > row:
- last = (i == (len(self._diffs)-1))
- self.sci.setCursorPosition(lo, 0)
- self.sci.verticalScrollBar().setValue(lo)
- break
else:
- last = True
+ row, column = self.sci.getCursorPosition()
+ for i, (lo, hi) in enumerate(self._diffs):
+ if lo > row:
+ last = (i == (len(self._diffs)-1))
+ self.sci.setCursorPosition(lo, 0)
+ self.sci.verticalScrollBar().setValue(lo)
+ break
+ else:
+ last = True
self.actionNextDiff.setEnabled(not last)
self.actionPrevDiff.setEnabled(True)
def prevDiff(self):
- if self._mode == DiffMode or not self._diffs:
+ if not self._diffs:
self.actionNextDiff.setEnabled(False)
self.actionPrevDiff.setEnabled(False)
return
- row, column = self.sci.getCursorPosition()
- for i, (lo, hi) in enumerate(reversed(self._diffs)):
- if hi < row:
- first = (i == (len(self._diffs)-1))
- self.sci.setCursorPosition(lo, 0)
- self.sci.verticalScrollBar().setValue(lo)
- break
else:
- first = True
+ row, column = self.sci.getCursorPosition()
+ for i, (lo, hi) in enumerate(reversed(self._diffs)):
+ if hi < row:
+ first = (i == (len(self._diffs)-1))
+ self.sci.setCursorPosition(lo, 0)
+ self.sci.verticalScrollBar().setValue(lo)
+ break
+ else:
+ first = True
self.actionNextDiff.setEnabled(True)
self.actionPrevDiff.setEnabled(not first)
|
@@ -12,7 +12,7 @@ #
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""helper functions and classes to ease hg revision graph building
|
@@ -7,6 +7,7 @@
import os
+from tortoisehg.hgqt.i18n import _
from tortoisehg.hgqt import qtlib
from tortoisehg.util import wconfig
|
@@ -58,7 +58,7 @@ def openhelpcontents(url):
'Open online help, use local CHM file if available'
if not url.startswith('http'):
- fullurl = 'http://tortoisehg.org/manual/2.0/' + url
+ fullurl = 'http://tortoisehg.org/manual/2.1/' + url
# Use local CHM file if it can be found
if os.name == 'nt' and paths.bin_path:
chm = os.path.join(paths.bin_path, 'doc', 'TortoiseHg.chm')
|
@@ -12,7 +12,7 @@ #
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
Qt4 QToolBar-based class for quick bars XXX
"""
|
@@ -12,7 +12,7 @@ #
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from mercurial import util, error
from mercurial.util import propertycache
|
@@ -54,10 +54,11 @@ return itemread
def iterRepoItemFromXml(source):
+ 'Used by thgrepo.relatedRepositories to scan the XML file'
xr = QXmlStreamReader(source)
while not xr.atEnd():
t = xr.readNext()
- if t == QXmlStreamReader.StartElement and xr.name() == 'repo':
+ if t == QXmlStreamReader.StartElement and xr.name() in ('repo', 'subrepo'):
yield undumpObject(xr)
def getRepoItemList(root, includeSubRepos=False):
|
@@ -12,7 +12,7 @@ #
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from mercurial import error
|
@@ -265,8 +265,7 @@ qtlib.ErrorMsgBox(_('File already exists'),
_('A shelf file of that name already exists'))
return
- f = open(shelfpath, "wb")
- f.close()
+ self.repo.makeshelf(shelve)
self.showMessage(_('New shelf created'))
self.refreshCombos()
if shelfpath in self.shelves:
|
@@ -17,7 +17,7 @@ from mercurial import hg, ui, url, util, error, demandimport
from mercurial import merge as mergemod
-from tortoisehg.util import hglib, wconfig
+from tortoisehg.util import hglib, wconfig, paths
from tortoisehg.hgqt.i18n import _
from tortoisehg.hgqt import qtlib, cmdui, thgrepo, rebase, resolve, hgrcutil
@@ -387,11 +387,13 @@ # repositories already opened keep their ui instances in sync
repo = thgrepo._repocache[root]
ui = repo.ui
- else:
+ elif paths.is_on_fixed_drive(root):
# directly read the repository's configuration file
tempui = self.repo.ui.copy()
tempui.readconfig(os.path.join(root, '.hg', 'hgrc'))
ui = tempui
+ else:
+ continue
for alias, path in ui.configitems('paths'):
if hg.islocal(path):
abs = os.path.abspath(hglib.localpath(path)).lower()
@@ -1485,6 +1487,5 @@
def run(ui, *pats, **opts):
- from tortoisehg.util import paths
repo = thgrepo.repository(ui, path=paths.find_root())
return SyncWidget(repo, None, **opts)
|
@@ -476,6 +476,12 @@ os.path.isfile(os.path.join(self.shelfdir, s))]
return []
+ def makeshelf(self, patch):
+ if not os.path.exists(self.shelfdir):
+ os.mkdir(self.shelfdir)
+ f = open(os.path.join(self.shelfdir, patch), "wb")
+ f.close()
+
def thginvalidate(self):
'Should be called when mtime of repo store/dirstate are changed'
self.dirstate.invalidate()
|
@@ -308,7 +308,8 @@ nullfile = os.path.join(qtlib.gettempdir(), 'empty')
fp = open(nullfile, 'w')
fp.close()
- return _nonexistant+label, nullfile
+ return (hglib.fromunicode(_nonexistant, 'replace') + label,
+ nullfile)
# If only one change, diff the files instead of the directories
# Handle bogus modifies correctly by checking if the files exist
@@ -544,7 +545,7 @@ nullfile = os.path.join(qtlib.gettempdir(), 'empty')
fp = open(nullfile, 'w')
fp.close()
- return _nonexistant, nullfile
+ return hglib.fromunicode(_nonexistant, 'replace'), nullfile
local, file1a = getfile(ctx1a, dir1a, fname, source)
if ctx1b:
|
@@ -12,7 +12,7 @@ #
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import gtk
from tortoisehg.util.i18n import _
|
@@ -12,7 +12,7 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import sys, math
def _days(ctx, now):
@@ -94,7 +94,7 @@
def saturate_v(self, saturation, hv):
return int(255 - (saturation/3*(1-hv)))
-
+
def committer_angle(self, committer):
angle = float(abs(hash(committer))) / sys.maxint * 360.0
if self._maxhues is None:
|
@@ -18,7 +18,7 @@
def checkhgversion(v):
"""range check the Mercurial version"""
- reqver = ['1', '8']
+ reqver = ['1', '9']
v = v.split('+')[0]
if not v or v == 'unknown' or len(v) >= 12:
# can't make any intelligent decisions about unknown or hashes
@@ -27,7 +27,7 @@ if vers == reqver or len(vers) < 2:
return
nextver = list(reqver)
- nextver[1] = chr(ord(reqver[1])+1)
+ nextver[1] = str(int(reqver[1])+1)
if vers == nextver:
return
return (('This version of TortoiseHg requires Mercurial '
|
@@ -47,7 +47,8 @@ if os.name == 'nt':
import _winreg
import win32net
- USE_OK = 0 # network drive status
+ import win32api
+ import win32file
def find_in_path(pgmname):
"return first executable found in search path"
@@ -72,6 +73,20 @@ pass
return os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
+ def is_on_fixed_drive(path):
+ if hasattr(os.path, 'splitunc'):
+ unc, rest = os.path.splitunc(path)
+ if unc:
+ # All UNC paths (\\host\mount) are considered not-fixed
+ return False
+ drive, remain = os.path.splitdrive(path)
+ if drive:
+ return win32file.GetDriveType(drive) == win32file.DRIVE_FIXED
+ else:
+ return False
+
+ USE_OK = 0 # network drive status
+
def netdrive_status(drive):
"""
return True if a network drive is accessible (connected, ...),
@@ -112,3 +127,7 @@ or False if <drive> is not a network drive
"""
return False
+
+ def is_on_fixed_drive(path):
+ return True
+
|
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
This file's diff was not loaded because this changeset is very large. Load changes Loading... |
Loading...