by
Changes to 21 files · Browse files at 8cf34332ed01 Showing diff from parent 57fa0272f191 c5b82b5a2bc7 Diff from another changeset...
@@ -262,10 +262,14 @@ _stderr = sys.stderr
sys.stderr = errorstream
try:
+ # Ensure that all unset dirstate entries can be updated.
+ time.sleep(2)
+ updated_any = False
for r in sorted(roots):
try:
- shlib.update_thgstatus(_ui, r, wait=False)
- shlib.shell_notify([r])
+ if shlib.update_thgstatus(_ui, r, wait=False):
+ updated_any = True
+ shlib.shell_notify([r], noassoc=True)
logger.msg('Updated ' + r)
except (IOError, OSError):
print "IOError or OSError on updating %s (check permissions)" % r
@@ -277,8 +281,7 @@ failedroots.add(r)
notifypaths -= failedroots
if notifypaths:
- time.sleep(2)
- shlib.shell_notify(list(notifypaths))
+ shlib.shell_notify(list(notifypaths), noassoc=not updated_any)
logger.msg('Shell notified')
errmsg = errorstream.getvalue()
if errmsg:
|
|
@@ -6,6 +6,7 @@ # GNU General Public License version 2, incorporated herein by reference.
import os
+import re
from mercurial import ui, util, error
@@ -14,7 +15,7 @@from tortoisehg.hgqt.i18n import _
from tortoisehg.hgqt.messageentry import MessageEntry
from tortoisehg.hgqt import qtlib, qscilib, status, cmdui, branchop, revpanel
-from tortoisehg.hgqt import hgrcutil, mq
+from tortoisehg.hgqt import hgrcutil, mq, lfprompt
from PyQt4.QtCore import *
from PyQt4.QtGui import *
@@ -676,6 +677,22 @@ self.msgte.setFocus()
return
+ linkmandatory = self.repo.ui.config('tortoisehg',
+ 'issue.linkmandatory', False)
+ if linkmandatory:
+ issueregex = self.repo.ui.config('tortoisehg', 'issue.regex')
+ if issueregex:
+ m = re.search(issueregex, msg)
+ if not m:
+ qtlib.WarningMsgBox(_('Nothing Commited'),
+ _('No issue link was found in the commit message. '
+ 'The commit message should contain an issue '
+ 'link. Configure this in the \'Issue Tracking\' '
+ 'section of the settings.'),
+ parent=self)
+ self.msgte.setFocus()
+ return False
+
commandlines = []
brcmd = []
@@ -712,6 +729,22 @@ (_('&Add'), _('Cancel')), 0, 1,
checkedUnknowns).run()
if res == 0:
+ haslf = 'largefiles' in repo.extensions()
+ haskbf = 'kbfiles' in repo.extensions()
+ if haslf or haskbf:
+ result = lfprompt.promptForLfiles(self, repo.ui, repo,
+ checkedUnknowns, haskbf)
+ if not result:
+ return
+ checkedUnknowns, lfiles = result
+ if lfiles:
+ if haslf:
+ cmd = ['add', '--repository', repo.root, '--large'] + \
+ [repo.wjoin(f) for f in lfiles]
+ else:
+ cmd = ['add', '--repository', repo.root, '--bf'] + \
+ [repo.wjoin(f) for f in lfiles]
+ commandlines.append(cmd)
cmd = ['add', '--repository', repo.root] + \
[repo.wjoin(f) for f in checkedUnknowns]
commandlines.append(cmd)
|
@@ -47,7 +47,7 @@ return None
try:
data = fctx.data()
- if '\0' in data:
+ if '\0' in data or ctx.isStandin(wfile):
self.error = p + _('File is binary.\n')
return None
except (EnvironmentError, util.Abort), e:
@@ -72,6 +72,7 @@ return 'C'
return None
+ isbfile = False
repo = ctx._repo
self.flabel += u'<b>%s</b>' % hglib.tounicode(wfile)
@@ -302,6 +303,9 @@ else:
self.contents = olddata
self.flabel += _(' <i>(was deleted)</i>')
+ elif hasattr(ctx.p1(), 'hasStandin') and ctx.p1().hasStandin(wfile):
+ self.error = 'binary file'
+ self.flabel += _(' <i>(was deleted)</i>')
else:
self.flabel += _(' <i>(was added, now missing)</i>')
return
@@ -315,6 +319,8 @@ return
else:
data = util.posixfile(absfile, 'r').read()
+ elif ctx.hasStandin(wfile):
+ data = '\0'
else:
data = ctx.filectx(wfile).data()
if '\0' in data:
@@ -324,6 +330,9 @@ return
if status in ('M', 'A'):
+ if ctx.hasStandin(wfile):
+ wfile = ctx.findStandin(wfile)
+ isbfile = True
res = self.checkMaxDiff(ctx, wfile, maxdiff)
if res is None:
if status == 'A':
@@ -367,5 +376,8 @@ revs = [str(ctx), str(ctx2)]
diffopts = patch.diffopts(repo.ui, {})
diffopts.git = False
+ if isbfile:
+ olddata += '\0'
+ newdata += '\0'
self.diff = mdiff.unidiff(olddata, olddate, newdata, newdate,
oldname, wfile, revs, diffopts)
|
@@ -144,6 +144,7 @@ for lst, flag in ((added, 'A'), (modified, 'M'), (removed, 'R')):
for f in filter(func, lst):
wasmerged = ismerge and f in ctxfiles
+ f = self._ctx.removeStandin(f)
files.append({'path': f, 'status': flag, 'parent': parent,
'wasmerged': wasmerged})
return files
|
@@ -309,6 +309,9 @@ self.actionNextDiff.setEnabled(False)
self.actionPrevDiff.setEnabled(False)
+ self.maxWidth = 0
+ self.sci.showHScrollBar(False)
+
def displayFile(self, filename=None, status=None):
if isinstance(filename, (unicode, QString)):
filename = hglib.fromunicode(filename)
@@ -434,6 +437,20 @@ self.actionNextDiff.setEnabled(bool(self._diffs))
self.actionPrevDiff.setEnabled(bool(self._diffs))
+ lexer = self.sci.lexer()
+
+ if lexer:
+ font = self.sci.lexer().font(0)
+ else:
+ font = self.sci.font()
+
+ fm = QFontMetrics(font)
+ maxWidth = fm.maxWidth()
+ lines = self.sci.text().split('\n')
+ widths = [fm.width(line) + maxWidth for line in lines]
+ self.maxWidth = max(widths)
+ self.updateScrollBar()
+
#
# These four functions are used by Shift+Cursor actions in revdetails
#
@@ -674,6 +691,15 @@ add(name, func)
menu.exec_(point)
+ def resizeEvent(self, event):
+ super(HgFileView, self).resizeEvent(event)
+ self.updateScrollBar()
+
+ def updateScrollBar(self):
+ sbWidth = self.sci.verticalScrollBar().width()
+ scrollWidth = self.maxWidth + sbWidth - self.sci.width()
+ self.sci.showHScrollBar(scrollWidth > 0)
+ self.sci.horizontalScrollBar().setRange(0, scrollWidth)
class AnnotateView(qscilib.Scintilla):
'QScintilla widget capable of displaying annotations'
|
@@ -10,7 +10,7 @@
from mercurial import ui, hg, error, commands, match, util, subrepo
-from tortoisehg.hgqt import htmlui, visdiff, qtlib, htmldelegate, thgrepo, cmdui
+from tortoisehg.hgqt import htmlui, visdiff, qtlib, htmldelegate, thgrepo, cmdui, settings
from tortoisehg.util import paths, hglib, thread2
from tortoisehg.hgqt.i18n import _
@@ -385,6 +385,8 @@ pass
def run(self):
+ haskbf = settings.hasExtension('kbfiles')
+ haslf = settings.hasExtension('largefiles')
self.thread_id = int(QThread.currentThreadId())
def emitrow(row):
@@ -400,6 +402,10 @@ try:
fname, line, rev, addremove, user, text, tail = \
self.fullmsg.split('\0', 6)
+ if haslf and thgrepo.isLfStandin(fname):
+ raise ValueError
+ if (haslf or haskbf) and thgrepo.isBfStandin(fname):
+ raise ValueError
text = hglib.tounicode(text)
text = Qt.escape(text)
text = '<b>%s</b> <span>%s</span>' % (addremove, text)
@@ -469,9 +475,15 @@ unit = _('files')
total = len(ctx.manifest())
count = 0
+ haskbf = settings.hasExtension('kbfiles')
+ haslf = settings.hasExtension('largefiles')
for wfile in ctx: # walk manifest
if self.canceled:
break
+ if haslf and thgrepo.isLfStandin(wfile):
+ continue
+ if (haslf or haskbf) and thgrepo.isBfStandin(wfile):
+ continue
self.progress.emit(topic, count, wfile, unit, total)
count += 1
if not matchfn(wfile):
|
|
@@ -0,0 +1,73 @@ + # bfprompt.py - prompt to add large files as bfiles
+#
+# Copyright 2011 Fog Creek Software
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+import os
+
+from mercurial import match
+from tortoisehg.hgqt import qtlib
+from tortoisehg.hgqt.i18n import _
+
+class LfilesPrompt(qtlib.CustomPrompt):
+ def __init__(self, parent, files=None):
+ qtlib.CustomPrompt.__init__(self, _('Confirm Add'),
+ _('Some of the files that you have selected are of a size '
+ 'over 10 MB. You may make more efficient use of disk space '
+ 'by adding these files as largefiles, which will store only the '
+ 'most recent revision of each file in your local repository, '
+ 'with older revisions available on the server. Do you wish '
+ 'to add these files as largefiles?'), parent,
+ (_('Add as &Largefiles'), _('Add as &Normal Files'), _('Cancel')),
+ 0, 2, files)
+
+class BfilesPrompt(qtlib.CustomPrompt):
+ def __init__(self, parent, files=None):
+ qtlib.CustomPrompt.__init__(self, _('Confirm Add'),
+ _('Some of the files that you have selected are of a size '
+ 'over 10 MB. You may make more efficient use of disk space '
+ 'by adding these files as bfiles, which will store only the '
+ 'most recent revision of each file in your local repository, '
+ 'with older revisions available on the server. Do you wish '
+ 'to add these files as bfiles?'), parent,
+ (_('Add as &Bfiles'), _('Add as &Normal Files'), _('Cancel')),
+ 0, 2, files)
+
+def promptForLfiles(parent, ui, repo, files, haskbf=False):
+ lfiles = []
+ usekbf = os.path.exists('.kbf')
+ uself = os.path.exists('.hglf')
+ useneither = not usekbf and not uself
+ if haskbf:
+ section = 'kilnbfiles'
+ else:
+ section = 'largefiles'
+ minsize = int(ui.config(section, 'size', default='10'))
+ patterns = ui.config(section, 'patterns', default=())
+ if patterns:
+ patterns = patterns.split(' ')
+ matcher = match.match(repo.root, '', list(patterns))
+ else:
+ matcher = None
+ for wfile in files:
+ if not matcher or not matcher(wfile) or useneither:
+ filesize = os.path.getsize(repo.wjoin(wfile))
+ if filesize >= 10*1024*1024 and (filesize < minsize*1024*1024 or useneither):
+ lfiles.append(wfile)
+ if lfiles:
+ if haskbf:
+ ret = BfilesPrompt(parent, files).run()
+ else:
+ ret = LfilesPrompt(parent, files).run()
+ if ret == 0:
+ # add as largefiles/bfiles
+ for lfile in lfiles:
+ files.remove(lfile)
+ elif ret == 1:
+ # add as normal files
+ lfiles = []
+ elif ret == 2:
+ return None
+ return files, lfiles
|
@@ -251,6 +251,9 @@ if not pathinstatus(path, status, uncleanpaths):
continue
+ origpath = path
+ path = self._repo.removeStandin(path)
+
e = treeroot
for p in hglib.tounicode(path).split('/'):
if not p in e:
@@ -258,7 +261,7 @@ e = e[p]
for st, filesofst in status.iteritems():
- if path in filesofst:
+ if origpath in filesofst:
e.setstatus(st)
break
else:
|
@@ -97,14 +97,17 @@
def run(self):
try:
- wctx = repo[None]
- wctx.status(ignored=True, unknown=True)
+ repo.bfstatus = True
+ repo.lfstatus = True
+ stat = repo.status(ignored=True, unknown=True)
+ repo.bfstatus = False
+ repo.lfstatus = False
trashcan = repo.join('Trashcan')
if os.path.isdir(trashcan):
trash = os.listdir(trashcan)
else:
trash = []
- self.files = wctx.unknown(), wctx.ignored(), trash
+ self.files = stat[4], stat[5], trash
except Exception, e:
self.error = str(e)
@@ -213,8 +216,12 @@ self.showMessage.emit('')
match = hglib.matchall(repo)
match.dir = directories.append
+ repo.bfstatus = True
+ repo.lfstatus = True
status = repo.status(match=match, ignored=opts['ignored'],
unknown=opts['unknown'], clean=False)
+ repo.bfstatus = False
+ repo.lfstatus = False
files = status[4] + status[5]
def remove(remove_func, name):
|
@@ -64,10 +64,35 @@ chm = os.path.join(paths.bin_path, 'doc', 'TortoiseHg.chm')
if os.path.exists(chm):
fullurl = (r'mk:@MSITStore:%s::/' % chm) + url
- QDesktopServices.openUrl(QUrl.fromLocalFile(fullurl))
+ openlocalurl(fullurl)
return
QDesktopServices.openUrl(QUrl(fullurl))
+def startswith(strQstring, startstr):
+ '''calls startsWith of QString or startswith for others
+
+ takes st, unicode or QString as strQstring'''
+
+ if isinstance(strQstring, QString):
+ return strQstring.startsWith(startstr)
+ else:
+ return strQstring.startswith(startstr)
+
+def openlocalurl(path):
+ '''open the given path with the default application
+
+ takes str, unicode or QString as argument'''
+
+ if isinstance(path, str):
+ path = hglib.tounicode(path)
+ if os.name == 'nt' and startswith(path, '\\\\'):
+ # network share, special handling because of qt bug 13359
+ # see http://bugreports.qt.nokia.com/browse/QTBUG-13359
+ qurl = QUrl().setUrl(QDir.toNativeSeparators(path))
+ else:
+ qurl = QUrl.fromLocalFile(path)
+ return QDesktopServices.openUrl(qurl)
+
def editfiles(repo, files, lineno=None, search=None, parent=None):
if len(files) == 1:
path = repo.wjoin(files[0])
|
|
@@ -12,7 +12,7 @@
from tortoisehg.util import hglib, shlib
from tortoisehg.hgqt.i18n import _
-from tortoisehg.hgqt import qtlib, status, cmdui
+from tortoisehg.hgqt import qtlib, status, cmdui, lfprompt
from PyQt4.QtCore import *
from PyQt4.QtGui import *
@@ -107,6 +107,17 @@ hbox.addWidget(bb)
toplayout.addLayout(hbox)
self.bb = bb
+
+ if self.command == 'add':
+ if 'largefiles' in self.repo.extensions():
+ self.addLfilesButton = QPushButton(_('Add &Largefiles'))
+ elif 'kbfiles' in self.repo.extensions():
+ self.addLfilesButton = QPushButton(_("Add &Bfiles"))
+ else:
+ self.addLfilesButton = None
+ if self.addLfilesButton:
+ self.addLfilesButton.clicked.connect(self.addLfiles)
+ bb.addButton(self.addLfilesButton, BB.ActionRole)
layout.addWidget(self.statusbar)
@@ -147,9 +158,14 @@ _('No operation to perform'),
parent=self)
return
+ self.repo.bfstatus = True
+ self.repo.lfstatus = True
+ repostate = self.repo.status()
+ self.repo.bfstatus = False
+ self.repo.lfstatus = False
if self.command == 'remove':
if not self.chk.isChecked():
- modified = self.repo.status()[0]
+ modified = repostate[0]
selmodified = []
for wfile in files:
if wfile in modified:
@@ -167,14 +183,18 @@ cmdline.append('--force')
elif ret == 2:
return
- wctx = self.repo[None]
+ unknown, ignored = repostate[4:6]
for wfile in files:
- if wfile not in wctx:
+ if wfile in unknown or wfile in ignored:
try:
util.unlink(wfile)
except EnvironmentError:
pass
files.remove(wfile)
+ elif self.command == 'add':
+ if 'largefiles' in self.repo.extensions() or 'kbfiles' in self.repo.extensions():
+ self.addWithPrompt(files)
+ return
if files:
cmdline.extend(files)
self.files = files
@@ -198,6 +218,40 @@ s.setValue('quickop/forceremove', self.chk.isChecked())
QDialog.reject(self)
+ def addLfiles(self):
+ if 'kbfiles' in self.repo.extensions():
+ cmdline = ['add', '--bf']
+ else:
+ cmdline = ['add', '--large']
+ files = self.stwidget.getChecked()
+ if not files:
+ qtlib.WarningMsgBox(_('No files selected'),
+ _('No operation to perform'),
+ parent=self)
+ return
+ cmdline.extend(files)
+ self.files = files
+ self.cmd.run(cmdline)
+
+ def addWithPrompt(self, files):
+ result = lfprompt.promptForLfiles(self, self.repo.ui, self.repo, files,
+ 'kbfiles' in self.repo.extensions())
+ if not result:
+ return
+ files, bfiles = result
+ if files:
+ cmdline = ['add']
+ cmdline.extend(files)
+ self.files = files
+ self.cmd.run(cmdline)
+ if bfiles:
+ if 'kbfiles' in self.repo.extensions():
+ cmdline = ['add', '--bf']
+ else:
+ cmdline = ['add', '--large']
+ cmdline.extend(bfiles)
+ self.files = bfiles
+ self.cmd.run(cmdline)
instance = None
class HeadlessQuickop(QWidget):
|
@@ -224,6 +224,7 @@
showMessage = pyqtSignal(QString)
openRepo = pyqtSignal(QString, bool)
+ removeRepo = pyqtSignal(QString)
def __init__(self, parent, showSubrepos=False, showNetworkSubrepos=False,
showShortPaths=False):
@@ -644,7 +645,9 @@ self.tview.model().addGroup(_('New Group'))
def removeSelected(self):
+ root = self.selitem.internalPointer().rootpath()
self.tview.removeSelected()
+ self.removeRepo.emit(hglib.tounicode(root))
@pyqtSlot(QString, QString)
def shortNameChanged(self, uroot, uname):
|
|
@@ -7,7 +7,7 @@
import os
-from mercurial import ui, util, error
+from mercurial import ui, util, error, extensions
from tortoisehg.util import hglib, settings, paths, wconfig, i18n, bugtraq
from tortoisehg.hgqt.i18n import _
@@ -24,6 +24,12 @@_unspecstr = _('<unspecified>')
ENTRY_WIDTH = 300
+def hasExtension(extname):
+ for name, module in extensions.extensions():
+ if name == extname:
+ return True
+ return False
+
class SettingsCombo(QComboBox):
def __init__(self, parent=None, **opts):
QComboBox.__init__(self, parent, toolTip=opts['tooltip'])
@@ -315,6 +321,46 @@ return self.value() != self.curvalue
+class PathBrowser(QWidget):
+ def __init__(self, parent=None, **opts):
+ QWidget.__init__(self, parent, toolTip=opts['tooltip'])
+ self.opts = opts
+
+ self.lineEdit = QLineEdit()
+ completer = QCompleter(self)
+ completer.setModel(QDirModel(completer))
+ self.lineEdit.setCompleter(completer)
+
+ self.browseButton = QPushButton(_('&Browse...'))
+ self.browseButton.clicked.connect(self.browse)
+
+ layout = QHBoxLayout()
+ layout.setContentsMargins(0, 0, 0, 0)
+ layout.addWidget(self.lineEdit)
+ layout.addWidget(self.browseButton)
+ self.setLayout(layout)
+
+ def browse(self):
+ dir = QFileDialog.getExistingDirectory(self, directory=self.lineEdit.text(),
+ options=QFileDialog.ShowDirsOnly)
+ if dir:
+ self.lineEdit.setText(dir)
+
+ ## common APIs for all edit widgets
+ def setValue(self, curvalue):
+ self.curvalue = curvalue
+ if curvalue:
+ self.lineEdit.setText(hglib.tounicode(curvalue))
+ else:
+ self.lineEdit.setText('')
+
+ def value(self):
+ utext = self.lineEdit.text()
+ return utext and hglib.fromunicode(utext) or None
+
+ def isDirty(self):
+ return self.value() != self.curvalue
+
def genEditCombo(opts, defaults=[]):
opts['canedit'] = True
opts['defaults'] = defaults
@@ -352,6 +398,9 @@def genBugTraqEdit(opts):
return BugTraqConfigureEntry(**opts)
+def genPathBrowser(opts):
+ return PathBrowser(**opts)
+
def findIssueTrackerPlugins():
plugins = bugtraq.get_issue_plugins_with_names()
names = [("%s %s" % (key[0], key[1])) for key in plugins]
@@ -713,6 +762,10 @@ 'while {1} refers to the first group and so on. If no {n} tokens'
'are found in issue.link, the entire matched string is appended '
'instead.')),
+ _fi(_('Mandatory Issue Reference'), 'tortoisehg.issue.linkmandatory', genBoolRBGroup,
+ _('When committing, require that a reference to an issue be specified. '
+ 'If enabled, the regex configured in \'Issue Regex\' must find a match '
+ 'in the commit message.')),
_fi(_('Issue Tracker Plugin'), 'tortoisehg.issue.bugtraqplugin',
(genDeferredCombo, findIssueTrackerPlugins),
_('Configures a COM IBugTraqProvider or IBugTrackProvider2 issue '
@@ -737,6 +790,26 @@ _fi(_('Target People'), 'reviewboard.target_people', genEditCombo,
_('A comma separated list of target people')),
)),
+
+({'name': 'kbfiles', 'label': _('Kiln Bfiles'), 'icon': 'kiln', 'extension': 'kbfiles'}, (
+ _fi(_('Patterns'), 'kilnbfiles.patterns', genEditCombo,
+ _('Files with names meeting the specified patterns will be automatically '
+ 'added as bfiles')),
+ _fi(_('Size'), 'kilnbfiles.size', genEditCombo,
+ _('Files of at least the specified size (in megabytes) will be added as bfiles')),
+ _fi(_('System Cache'), 'kilnbfiles.systemcache', genPathBrowser,
+ _('Path to the directory where a system-wide cache of bfiles will be stored')),
+ )),
+
+({'name': 'largefiles', 'label': _('Largefiles'), 'icon': 'kiln', 'extension': 'largefiles'}, (
+ _fi(_('Patterns'), 'largefiles.patterns', genEditCombo,
+ _('Files with names meeting the specified patterns will be automatically '
+ 'added as largefiles')),
+ _fi(_('Size'), 'largefiles.size', genEditCombo,
+ _('Files of at least the specified size (in megabytes) will be added as largefiles')),
+ _fi(_('System Cache'), 'largefiles.systemcache', genPathBrowser,
+ _('Path to the directory where a system-wide cache of largefiles will be stored')),
+ )),
)
@@ -915,6 +988,8 @@
# add page items to treeview
for meta, info in INFO:
+ if 'extension' in meta and not hasExtension(meta['extension']):
+ continue
if isinstance(meta['icon'], str):
icon = qtlib.geticon(meta['icon'])
else:
|
@@ -11,7 +11,7 @@
from tortoisehg.util import paths, hglib
from tortoisehg.hgqt.i18n import _
-from tortoisehg.hgqt import qtlib, wctxactions, visdiff, cmdui, fileview
+from tortoisehg.hgqt import qtlib, wctxactions, visdiff, cmdui, fileview, thgrepo
from PyQt4.QtCore import *
from PyQt4.QtGui import *
@@ -413,7 +413,7 @@
def __init__(self, repo, pctx, pats, opts, parent=None):
super(StatusThread, self).__init__()
- self.repo = hg.repository(repo.ui, repo.root)
+ self.repo = thgrepo.repository(repo.ui, repo.root)
self.pctx = pctx
self.pats = pats
self.opts = opts
@@ -434,7 +434,11 @@ # status and commit only pre-check MAR files
precheckfn = lambda x: x < 4
m = hglib.match(self.repo[None], self.pats)
+ self.repo.bfstatus = True
+ self.repo.lfstatus = True
status = self.repo.status(match=m, **stopts)
+ self.repo.bfstatus = False
+ self.repo.lfstatus = False
# Record all matched files as initially checked
for i, stat in enumerate(StatusType.preferredOrder):
if stat == 'S':
@@ -446,11 +450,19 @@ wctx = context.workingctx(self.repo, changes=status)
self.patchecked = patchecked
elif self.pctx:
+ self.repo.bfstatus = True
+ self.repo.lfstatus = True
status = self.repo.status(node1=self.pctx.p1().node(), **stopts)
+ self.repo.bfstatus = False
+ self.repo.lfstatus = False
wctx = context.workingctx(self.repo, changes=status)
else:
wctx = self.repo[None]
+ self.repo.bfstatus = True
+ self.repo.lfstatus = True
wctx.status(**stopts)
+ self.repo.bfstatus = False
+ self.repo.lfstatus = False
self.wctx = wctx
wctx.dirtySubrepos = []
|
|
@@ -92,6 +92,16 @@ self.embedded = bool(parent)
self.targetargs = []
+ s = QSettings()
+ for opt in ('subrepos', 'force', 'new-branch', 'noproxy', 'debug'):
+ val = s.value('sync/' + opt, None).toBool()
+ if val:
+ self.opts[opt] = val
+ for opt in ('remotecmd', 'branch'):
+ val = str(s.value('sync/' + opt, None).toString())
+ if val:
+ self.opts[opt] = val
+
self.repo.configChanged.connect(self.configChanged)
if self.embedded:
@@ -388,6 +398,10 @@ self.opts.update(dlg.outopts)
self.refreshUrl()
+ s = QSettings()
+ for opt, val in self.opts.iteritems():
+ s.setValue('sync/' + opt, val)
+
def reload(self):
# Refresh configured paths
self.paths = {}
@@ -1506,41 +1520,50 @@ self.setWindowTitle(_('%s - sync options') % parent.repo.displayname)
self.repo = parent.repo
- layout = QFormLayout()
+ layout = QVBoxLayout()
self.setLayout(layout)
self.newbranchcb = QCheckBox(
_('Allow push of a new branch (--new-branch)'))
self.newbranchcb.setChecked(opts.get('new-branch', False))
- layout.addRow(self.newbranchcb, None)
+ layout.addWidget(self.newbranchcb)
self.forcecb = QCheckBox(
_('Force push or pull (override safety checks, --force)'))
self.forcecb.setChecked(opts.get('force', False))
- layout.addRow(self.forcecb, None)
+ layout.addWidget(self.forcecb)
self.subrepocb = QCheckBox(
_('Recurse into subrepositories') + u' (--subrepos)')
self.subrepocb.setChecked(opts.get('subrepos', False))
- layout.addRow(self.subrepocb, None)
+ layout.addWidget(self.subrepocb)
self.noproxycb = QCheckBox(
_('Temporarily disable configured HTTP proxy'))
self.noproxycb.setChecked(opts.get('noproxy', False))
- layout.addRow(self.noproxycb, None)
+ layout.addWidget(self.noproxycb)
proxy = self.repo.ui.config('http_proxy', 'host')
self.noproxycb.setEnabled(bool(proxy))
self.debugcb = QCheckBox(
_('Emit debugging output (--debug)'))
self.debugcb.setChecked(opts.get('debug', False))
- layout.addRow(self.debugcb, None)
+ layout.addWidget(self.debugcb)
+
+ form = QFormLayout()
+ layout.addLayout(form)
lbl = QLabel(_('Remote command:'))
self.remotele = QLineEdit()
if opts.get('remotecmd'):
self.remotele.setText(hglib.tounicode(opts['remotecmd']))
- layout.addRow(lbl, self.remotele)
+ form.addRow(lbl, self.remotele)
+
+ lbl = QLabel(_('Branch:'))
+ self.branchle = QLineEdit()
+ if opts.get('branch'):
+ self.branchle.setText(hglib.tounicode(opts['branch']))
+ form.addRow(lbl, self.branchle)
BB = QDialogButtonBox
bb = QDialogButtonBox(BB.Ok|BB.Cancel)
@@ -1551,7 +1574,8 @@
def accept(self):
outopts = {}
- for name, le in (('remotecmd', self.remotele),):
+ for name, le in (('remotecmd', self.remotele),
+ ('branch', self.branchle)):
outopts[name] = hglib.fromunicode(le.text()).strip()
outopts['subrepos'] = self.subrepocb.isChecked()
|
|
@@ -12,6 +12,7 @@ import sys
import shutil
import tempfile
+import re
from PyQt4.QtCore import *
@@ -24,6 +25,8 @@from tortoisehg.util.patchctx import patchctx
_repocache = {}
+_kbfregex = re.compile(r'^\.kbf/')
+_lfregex = re.compile(r'^\.hglf/')
if 'THGDEBUG' in os.environ:
def dbgoutput(*args):
@@ -262,8 +265,8 @@def _extendrepo(repo):
class thgrepository(repo.__class__):
- def changectx(self, changeid):
- '''Extends Mercurial's standard changectx() method to
+ def __getitem__(self, changeid):
+ '''Extends Mercurial's standard __getitem__() method to
a) return a thgchangectx with additional methods
b) return a patchctx if changeid is the name of an MQ
unapplied patch
@@ -282,7 +285,7 @@ os.path.isabs(changeid) and os.path.isfile(changeid):
return genPatchContext(repo, changeid)
- changectx = super(thgrepository, self).changectx(changeid)
+ changectx = super(thgrepository, self).__getitem__(changeid)
changectx.__class__ = _extendchangectx(changectx)
return changectx
@@ -535,6 +538,28 @@ dest = tempfile.mktemp(ext+'.bak', root+'_', trashcan)
shutil.copyfile(path, dest)
+ def isStandin(self, path):
+ if 'largefiles' in self.extensions():
+ if _lfregex.match(path):
+ return True
+ if 'largefiles' in self.extensions() or 'kbfiles' in self.extensions():
+ if _kbfregex.match(path):
+ return True
+ return False
+
+ def removeStandin(self, path):
+ if 'largefiles' in self.extensions():
+ path = _lfregex.sub('', path)
+ if 'largefiles' in self.extensions() or 'kbfiles' in self.extensions():
+ path = _kbfregex.sub('', path)
+ return path
+
+ def bfStandin(self, path):
+ return '.kbf/' + path
+
+ def lfStandin(self, path):
+ return '.hglf/' + path
+
return thgrepository
@@ -601,11 +626,30 @@ summary += u' \u2026' # ellipsis ...
return summary
+
+ def hasStandin(self, file):
+ if 'largefiles' in self._repo.extensions():
+ if self._repo.lfStandin(file) in self.manifest():
+ return True
+ elif 'largefiles' in self._repo.extensions() or 'kbfiles' in self._repo.extensions():
+ if self._repo.bfStandin(file) in self.manifest():
+ return True
+ return False
+ def isStandin(self, path):
+ return self._repo.isStandin(path)
+
+ def removeStandin(self, path):
+ return self._repo.removeStandin(path)
+
+ def findStandin(self, file):
+ if 'largefiles' in self._repo.extensions():
+ if self._repo.lfStandin(file) in self.manifest():
+ return self._repo.lfStandin(file)
+ return self._repo.bfStandin(file)
+
return thgchangectx
-
-
_pctxcache = {}
def genPatchContext(repo, patchpath, rev=None):
global _pctxcache
@@ -650,3 +694,9 @@ raise
else:
f.close()
+
+def isBfStandin(path):
+ return _kbfregex.match(path)
+
+def isLfStandin(path):
+ return _lfregex.match(path)
|
@@ -6,10 +6,9 @@ # GNU General Public License version 2, incorporated herein by reference.
import os
-import re
-from mercurial import util, error, merge, commands
-from tortoisehg.hgqt import qtlib, htmlui, visdiff
+from mercurial import util, error, merge, commands, extensions
+from tortoisehg.hgqt import qtlib, htmlui, visdiff, lfprompt
from tortoisehg.util import hglib, shlib
from tortoisehg.hgqt.i18n import _
@@ -52,6 +51,10 @@ allactions.append(None)
make(_('&Forget'), forget, frozenset('MAC!'), 'filedelete')
make(_('&Add'), add, frozenset('I?'), 'fileadd')
+ if 'largefiles' in self.repo.extensions():
+ make(_('Add &Largefiles...'), addlf, frozenset('I?'))
+ elif 'kbfiles' in self.repo.extensions():
+ make(_('Add &Bfiles'), addlf, frozenset('I?'))
make(_('&Detect Renames...'), guessRename, frozenset('A?!'),
'detect_rename')
make(_('&Ignore...'), ignore, frozenset('?'), 'ignore')
@@ -266,9 +269,43 @@ return True
def add(parent, ui, repo, files):
+ haslf = 'largefiles' in repo.extensions()
+ haskbf = 'kbfiles' in repo.extensions()
+ if haslf or haskbf:
+ result = lfprompt.promptForLfiles(parent, ui, repo, files, haskbf)
+ if not result:
+ return False
+ files, lfiles = result
+ for name, module in extensions.extensions():
+ if name == 'largefiles':
+ override_add = module.overrides.override_add
+ if files:
+ override_add(commands.add, ui, repo, *files)
+ if lfiles:
+ override_add(commands.add, ui, repo, large=True, *lfiles)
+ return True
+ if name == 'kbfiles':
+ override_add = module.bfsetup.override_add
+ if files:
+ override_add(commands.add, ui, repo, *files)
+ if lfiles:
+ override_add(commands.add, ui, repo, bf=True, *lfiles)
+ return True
commands.add(ui, repo, *files)
return True
+def addlf(parent, ui, repo, files):
+ for name, module in extensions.extensions():
+ if name == 'largefiles':
+ override_add = module.overrides.override_add
+ override_add(commands.add, ui, repo, large=True, *files)
+ return True
+ if name == 'kbfiles':
+ override_add = module.bfsetup.override_add
+ override_add(commands.add, ui, repo, bf=True, *files)
+ return True
+ return False
+
def guessRename(parent, ui, repo, files):
from tortoisehg.hgqt.guess import DetectRenameDialog
dlg = DetectRenameDialog(repo, parent, *files)
|
@@ -48,6 +48,7 @@ rr.setObjectName('RepoRegistryView')
rr.showMessage.connect(self.showMessage)
rr.openRepo.connect(self.openRepo)
+ rr.removeRepo.connect(self.removeRepo)
rr.hide()
self.addDockWidget(Qt.LeftDockWidgetArea, rr)
self.activeRepoChanged.connect(rr.setActiveTabRepo)
@@ -473,6 +474,15 @@ root = hglib.fromunicode(root)
self._openRepo(root, reuse)
+ def removeRepo(self, root):
+ """ Close tab if the repo is removed from reporegistry [unicode] """
+ root = hglib.fromunicode(root)
+ for i in xrange(self.repoTabsWidget.count()):
+ w = self.repoTabsWidget.widget(i)
+ if hglib.tounicode(w.repo.root) == os.path.normpath(root):
+ self.repoTabCloseRequested(i)
+ return
+
@pyqtSlot(QString)
def openLinkedRepo(self, path):
self.showRepo(path)
|
@@ -128,6 +128,11 @@ def thgmqunappliedpatch(self): return True
def thgid(self): return self._identity
+ # largefiles/kbfiles methods
+ def hasStandin(self, file): return False
+ def isStandin(self, path): return False
+ def removeStandin(self, path): return path
+
def longsummary(self):
summary = hglib.tounicode(self.description())
if self._repo.ui.configbool('tortoisehg', 'longsummary'):
|
@@ -32,7 +32,7 @@ pass
threading.Thread(target=start_browser).start()
- def shell_notify(paths):
+ def shell_notify(paths, noassoc=False):
try:
from win32com.shell import shell, shellcon
import pywintypes
@@ -57,6 +57,10 @@ shell.SHChangeNotify(shellcon.SHCNE_UPDATEITEM,
shellcon.SHCNF_IDLIST | shellcon.SHCNF_FLUSH,
pidl, None)
+ if not noassoc:
+ shell.SHChangeNotify(shellcon.SHCNE_ASSOCCHANGED,
+ shellcon.SHCNF_FLUSH,
+ None, None)
def update_thgstatus(ui, root, wait=False):
'''Rewrite the file .hg/thgstatus
@@ -90,7 +94,11 @@ time.sleep(tdelta)
repo = hg.repository(ui, root) # a fresh repo object is needed
+ repo.bfstatus = True
+ repo.lfstatus = True
repostate = repo.status() # will update .hg/dirstate as a side effect
+ repo.bfstatus = False
+ repo.lfstatus = False
modified, added, removed, deleted = repostate[:4]
dirstatus = {}
@@ -132,9 +140,10 @@ f.write(s + dn + '\n')
ui.note("%s %s\n" % (s, dn))
f.rename()
+ return update
else:
- def shell_notify(paths):
+ def shell_notify(paths, noassoc=False):
if not paths:
return
notify = os.environ.get('THG_NOTIFY', '.tortoisehg/notify')
|
Loading...