by
Changes to 18 files · Browse files at 657f21d0ebde Showing diff from parent fe5430688149 1117c57543f4 Diff from another changeset...
|
|
|
|
@@ -0,0 +1,52 @@ + # 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 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 promptForBfiles(parent, ui, repo, files):
+ bfiles = []
+ usekbf = os.path.exists(repo.wjoin('.kbf'))
+ minsize = int(ui.config('kilnbfiles', 'size', default='10'))
+ patterns = ui.config('kilnbfiles', '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 not usekbf:
+ filesize = os.path.getsize(repo.wjoin(wfile))
+ if filesize >= 10*1024*1024 and (filesize < minsize*1024*1024 or not usekbf):
+ bfiles.append(wfile)
+ if bfiles:
+ ret = BfilesPrompt(parent, files).run()
+ if ret == 0:
+ # add as bfiles
+ for bfile in bfiles:
+ files.remove(bfile)
+ elif ret == 1:
+ # add as normal files
+ bfiles = []
+ elif ret == 2:
+ return None
+ return files, bfiles
|
@@ -6,6 +6,7 @@ # GNU General Public License version 2, incorporated herein by reference.
import os
+import re
from mercurial import error, match, patch, util, mdiff
from mercurial import ui as uimod
@@ -47,7 +48,7 @@ return None
try:
data = fctx.data()
- if '\0' in data:
+ if '\0' in data or re.match(r'^\.kbf/', wfile):
self.error = p + _('File is binary.\n')
return None
except (EnvironmentError, util.Abort), e:
@@ -72,6 +73,7 @@ return 'C'
return None
+ isbfile = False
repo = ctx._repo
self.flabel += u'<b>%s</b>' % hglib.tounicode(wfile)
@@ -301,6 +303,9 @@ else:
self.contents = olddata
self.flabel += _(' <i>(was deleted)</i>')
+ elif '.kbf/' + wfile in ctx.p1():
+ self.error = 'binary file'
+ self.flabel += _(' <i>(was deleted)</i>')
else:
self.flabel += _(' <i>(was added, now missing)</i>')
return
@@ -323,6 +328,9 @@ return
if status in ('M', 'A'):
+ if '.kbf/' + wfile in ctx:
+ wfile = '.kbf/' + wfile
+ isbfile = True
res = self.checkMaxDiff(ctx, wfile, maxdiff)
if res is None:
if status == 'A':
@@ -366,5 +374,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)
|
@@ -14,6 +14,8 @@ # this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+import re
+
from tortoisehg.util import hglib, patchctx
from tortoisehg.hgqt.qtlib import geticon, getoverlaidicon
@@ -144,6 +146,7 @@ for lst, flag in ((added, 'A'), (modified, 'M'), (removed, 'R')):
for f in filter(func, lst):
wasmerged = ismerge and f in ctxfiles
+ f = re.sub(r'^\.kbf/', '', f)
files.append({'path': f, 'status': flag, 'parent': parent,
'wasmerged': wasmerged})
return files
|
@@ -472,6 +472,8 @@ for wfile in ctx: # walk manifest
if self.canceled:
break
+ if re.match(r'^\.kbf/', wfile):
+ continue
self.progress.emit(topic, count, wfile, unit, total)
count += 1
if not matchfn(wfile):
|
@@ -9,6 +9,7 @@ # version.
import os, itertools
+import re
from PyQt4.QtCore import *
from PyQt4.QtGui import *
@@ -251,6 +252,9 @@ if not pathinstatus(path, status, uncleanpaths):
continue
+ origpath = path
+ path = re.sub(r'^\.kbf/', '', path)
+
e = treeroot
for p in hglib.tounicode(path).split('/'):
if not p in e:
@@ -258,7 +262,7 @@ e = e[p]
for st, filesofst in status.iteritems():
- if path in filesofst:
+ if origpath in filesofst:
e.setstatus(st)
break
else:
|
|
|
@@ -1,145 +1,145 @@ - # messageentry.py - TortoiseHg's commit message editng widget
-#
-# Copyright 2011 Steve Borho <steve@borho.org>
-#
-# This software may be used and distributed according to the terms of the
-# GNU General Public License version 2, incorporated herein by reference.
-
-import os
-
-from PyQt4.QtCore import *
-from PyQt4.QtGui import *
-from PyQt4.Qsci import QsciScintilla, QsciLexerMakefile
-
-from tortoisehg.hgqt.i18n import _
-from tortoisehg.hgqt import qtlib, qscilib
-
-class MessageEntry(qscilib.Scintilla):
-
- def __init__(self, parent, getCheckedFunc=None):
- super(MessageEntry, self).__init__(parent)
- self.setEdgeColor(QColor('LightSalmon'))
- self.setEdgeMode(QsciScintilla.EdgeLine)
- self.setReadOnly(False)
- self.setMarginWidth(1, 0)
- self.setFont(qtlib.getfont('fontcomment').font())
- self.setCaretWidth(10)
- self.setCaretLineBackgroundColor(QColor("#e6fff0"))
- self.setCaretLineVisible(True)
- self.setAutoIndent(True)
- self.setAutoCompletionThreshold(2)
- self.setAutoCompletionSource(QsciScintilla.AcsAPIs)
- self.setAutoCompletionFillupsEnabled(True)
- self.setLexer(QsciLexerMakefile(self))
- self.lexer().setFont(qtlib.getfont('fontcomment').font())
- self.lexer().setColor(QColor(Qt.red), QsciLexerMakefile.Error)
- self.setMatchedBraceBackgroundColor(Qt.yellow)
- self.setIndentationsUseTabs(False)
- self.setBraceMatching(QsciScintilla.SloppyBraceMatch)
- #self.setIndentationGuidesBackgroundColor(QColor("#e6e6de"))
- #self.setFolding(QsciScintilla.BoxedFoldStyle)
- # http://www.riverbankcomputing.com/pipermail/qscintilla/2009-February/000461.html
- self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
- self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
- # default message entry widgets to word wrap, user may override
- self.setWrapMode(QsciScintilla.WrapWord)
-
- self.getChecked = getCheckedFunc
- self.setContextMenuPolicy(Qt.CustomContextMenu)
- self.customContextMenuRequested.connect(self.menuRequested)
-
- def menuRequested(self, point):
- line = self.lineAt(point)
- point = self.viewport().mapToGlobal(point)
-
- def apply():
- line = 0
- while True:
- line = self.reflowBlock(line)
- if line is None:
- break;
- def paste():
- files = self.getChecked()
- self.insert(', '.join(files))
- def settings():
- from tortoisehg.hgqt.settings import SettingsDialog
- dlg = SettingsDialog(True, focus='tortoisehg.summarylen')
- dlg.exec_()
-
- menu = self.createStandardContextMenu()
- menu.addSeparator()
- if self.getChecked:
- action = menu.addAction(_('Paste &Filenames'))
- action.triggered.connect(paste)
- for name, func in [(_('App&ly Format'), apply),
- (_('C&onfigure Format'), settings)]:
- def add(name, func):
- action = menu.addAction(name)
- action.triggered.connect(func)
- add(name, func)
- return menu.exec_(point)
-
- def refresh(self, repo):
- self.setEdgeColumn(repo.summarylen)
- self.setIndentationWidth(repo.tabwidth)
- self.setTabWidth(repo.tabwidth)
- self.summarylen = repo.summarylen
-
- def reflowBlock(self, line):
- lines = self.text().split('\n', QString.KeepEmptyParts)
- if line >= len(lines):
- return None
- if not len(lines[line]) > 1:
- return line+1
-
- # find boundaries (empty lines or bounds)
- b = line
- while b and len(lines[b-1]) > 1:
- b = b - 1
- e = line
- while e+1 < len(lines) and len(lines[e+1]) > 1:
- e = e + 1
- group = QStringList([lines[l].simplified() for l in xrange(b, e+1)])
- sentence = group.join(' ')
- parts = sentence.split(' ', QString.SkipEmptyParts)
-
- outlines = QStringList()
- line = QStringList()
- partslen = 0
- for part in parts:
- if partslen + len(line) + len(part) + 1 > self.summarylen:
- if line:
- outlines.append(line.join(' '))
- line, partslen = QStringList(), 0
- line.append(part)
- partslen += len(part)
- if line:
- outlines.append(line.join(' '))
-
- self.beginUndoAction()
- self.setSelection(b, 0, e+1, 0)
- self.removeSelectedText()
- self.insertAt(outlines.join('\n')+'\n', b, 0)
- self.endUndoAction()
- self.setCursorPosition(b, 0)
- return b + len(outlines) + 1
-
- def moveCursorToEnd(self):
- lines = self.lines()
- if lines:
- lines -= 1
- pos = self.lineLength(lines)
- self.setCursorPosition(lines, pos)
- self.ensureLineVisible(lines)
- self.horizontalScrollBar().setSliderPosition(0)
-
- def keyPressEvent(self, event):
- if event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_E:
- line, col = self.getCursorPosition()
- self.reflowBlock(line)
- elif event.key() == Qt.Key_Backtab:
- event.accept()
- newev = QKeyEvent(event.type(), Qt.Key_Tab, Qt.ShiftModifier)
- super(MessageEntry, self).keyPressEvent(newev)
- else:
- super(MessageEntry, self).keyPressEvent(event)
+# messageentry.py - TortoiseHg's commit message editng widget
+#
+# Copyright 2011 Steve Borho <steve@borho.org>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2, incorporated herein by reference.
+
+import os
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+from PyQt4.Qsci import QsciScintilla, QsciLexerMakefile
+
+from tortoisehg.hgqt.i18n import _
+from tortoisehg.hgqt import qtlib, qscilib
+
+class MessageEntry(qscilib.Scintilla):
+
+ def __init__(self, parent, getCheckedFunc=None):
+ super(MessageEntry, self).__init__(parent)
+ self.setEdgeColor(QColor('LightSalmon'))
+ self.setEdgeMode(QsciScintilla.EdgeLine)
+ self.setReadOnly(False)
+ self.setMarginWidth(1, 0)
+ self.setFont(qtlib.getfont('fontcomment').font())
+ self.setCaretWidth(10)
+ self.setCaretLineBackgroundColor(QColor("#e6fff0"))
+ self.setCaretLineVisible(True)
+ self.setAutoIndent(True)
+ self.setAutoCompletionThreshold(2)
+ self.setAutoCompletionSource(QsciScintilla.AcsAPIs)
+ self.setAutoCompletionFillupsEnabled(True)
+ self.setLexer(QsciLexerMakefile(self))
+ self.lexer().setFont(qtlib.getfont('fontcomment').font())
+ self.lexer().setColor(QColor(Qt.red), QsciLexerMakefile.Error)
+ self.setMatchedBraceBackgroundColor(Qt.yellow)
+ self.setIndentationsUseTabs(False)
+ self.setBraceMatching(QsciScintilla.SloppyBraceMatch)
+ #self.setIndentationGuidesBackgroundColor(QColor("#e6e6de"))
+ #self.setFolding(QsciScintilla.BoxedFoldStyle)
+ # http://www.riverbankcomputing.com/pipermail/qscintilla/2009-February/000461.html
+ self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
+ # default message entry widgets to word wrap, user may override
+ self.setWrapMode(QsciScintilla.WrapWord)
+
+ self.getChecked = getCheckedFunc
+ self.setContextMenuPolicy(Qt.CustomContextMenu)
+ self.customContextMenuRequested.connect(self.menuRequested)
+
+ def menuRequested(self, point):
+ line = self.lineAt(point)
+ point = self.viewport().mapToGlobal(point)
+
+ def apply():
+ line = 0
+ while True:
+ line = self.reflowBlock(line)
+ if line is None:
+ break;
+ def paste():
+ files = self.getChecked()
+ self.insert(', '.join(files))
+ def settings():
+ from tortoisehg.hgqt.settings import SettingsDialog
+ dlg = SettingsDialog(True, focus='tortoisehg.summarylen')
+ dlg.exec_()
+
+ menu = self.createStandardContextMenu()
+ menu.addSeparator()
+ if self.getChecked:
+ action = menu.addAction(_('Paste &Filenames'))
+ action.triggered.connect(paste)
+ for name, func in [(_('App&ly Format'), apply),
+ (_('C&onfigure Format'), settings)]:
+ def add(name, func):
+ action = menu.addAction(name)
+ action.triggered.connect(func)
+ add(name, func)
+ return menu.exec_(point)
+
+ def refresh(self, repo):
+ self.setEdgeColumn(repo.summarylen)
+ self.setIndentationWidth(repo.tabwidth)
+ self.setTabWidth(repo.tabwidth)
+ self.summarylen = repo.summarylen
+
+ def reflowBlock(self, line):
+ lines = self.text().split('\n', QString.KeepEmptyParts)
+ if line >= len(lines):
+ return None
+ if not len(lines[line]) > 1:
+ return line+1
+
+ # find boundaries (empty lines or bounds)
+ b = line
+ while b and len(lines[b-1]) > 1:
+ b = b - 1
+ e = line
+ while e+1 < len(lines) and len(lines[e+1]) > 1:
+ e = e + 1
+ group = QStringList([lines[l].simplified() for l in xrange(b, e+1)])
+ sentence = group.join(' ')
+ parts = sentence.split(' ', QString.SkipEmptyParts)
+
+ outlines = QStringList()
+ line = QStringList()
+ partslen = 0
+ for part in parts:
+ if partslen + len(line) + len(part) + 1 > self.summarylen:
+ if line:
+ outlines.append(line.join(' '))
+ line, partslen = QStringList(), 0
+ line.append(part)
+ partslen += len(part)
+ if line:
+ outlines.append(line.join(' '))
+
+ self.beginUndoAction()
+ self.setSelection(b, 0, e+1, 0)
+ self.removeSelectedText()
+ self.insertAt(outlines.join('\n')+'\n', b, 0)
+ self.endUndoAction()
+ self.setCursorPosition(b, 0)
+ return b + len(outlines) + 1
+
+ def moveCursorToEnd(self):
+ lines = self.lines()
+ if lines:
+ lines -= 1
+ pos = self.lineLength(lines)
+ self.setCursorPosition(lines, pos)
+ self.ensureLineVisible(lines)
+ self.horizontalScrollBar().setSliderPosition(0)
+
+ def keyPressEvent(self, event):
+ if event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_E:
+ line, col = self.getCursorPosition()
+ self.reflowBlock(line)
+ elif event.key() == Qt.Key_Backtab:
+ event.accept()
+ newev = QKeyEvent(event.type(), Qt.Key_Tab, Qt.ShiftModifier)
+ super(MessageEntry, self).keyPressEvent(newev)
+ else:
+ super(MessageEntry, self).keyPressEvent(event)
|
@@ -89,14 +89,15 @@
def run(self):
try:
- wctx = repo[None]
- wctx.status(ignored=True, unknown=True)
+ repo.bfstatus = True
+ stat = repo.status(ignored=True, unknown=True)
+ repo.bfstatus = 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)
@@ -205,8 +206,10 @@ self.showMessage.emit('')
match = hglib.matchall(repo)
match.dir = directories.append
+ repo.bfstatus = True
status = repo.status(match=match, ignored=opts['ignored'],
unknown=opts['unknown'], clean=False)
+ repo.bfstatus = False
files = status[4] + status[5]
def remove(remove_func, name):
|
@@ -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, bfprompt
from PyQt4.QtCore import *
from PyQt4.QtGui import *
@@ -96,6 +96,11 @@ bb.button(BB.Ok).setText(LABELS[command][1])
layout.addWidget(bb)
self.bb = bb
+
+ if self.command == 'add' and 'kbfiles' in self.repo.extensions():
+ self.addBfilesButton = QPushButton(_("Add &Bfiles"))
+ self.addBfilesButton.clicked.connect(self.addBfiles)
+ bb.addButton(self.addBfilesButton, BB.ActionRole)
hbox = QHBoxLayout()
hbox.setMargin(0)
@@ -136,14 +141,20 @@ parent=self)
return
if self.command == 'remove':
- wctx = self.repo[None]
+ self.repo.bfstatus = True
+ repostate = self.repo.status()
+ self.repo.bfstatus = False
+ 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' and 'kbfiles' in self.repo.extensions():
+ self.addWithPrompt(files)
+ return
if files:
cmdline.extend(files)
self.files = files
@@ -164,6 +175,33 @@ s.setValue('quickop/nobackup', self.chk.isChecked())
QDialog.reject(self)
+ def addBfiles(self):
+ cmdline = ['add', '--bf']
+ 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 = bfprompt.promptForBfiles(self, self.repo.ui, self.repo, files)
+ if not result:
+ return
+ files, bfiles = result
+ if files:
+ cmdline = ['add']
+ cmdline.extend(files)
+ self.files = files
+ self.cmd.run(cmdline)
+ if bfiles:
+ cmdline = ['add', '--bf']
+ cmdline.extend(bfiles)
+ self.files = bfiles
+ self.cmd.run(cmdline)
instance = None
class HeadlessQuickop(QWidget):
|
|
@@ -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'])
@@ -258,6 +264,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
@@ -297,6 +343,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]
@@ -678,6 +727,16 @@ _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')),
+ )),
)
@@ -856,6 +915,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:
|
@@ -413,7 +413,9 @@ # 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
status = self.repo.status(match=m, **stopts)
+ self.repo.bfstatus = False
# Record all matched files as initially checked
for i, stat in enumerate(StatusType.preferredOrder):
if stat == 'S':
@@ -425,11 +427,15 @@ wctx = context.workingctx(self.repo, changes=status)
self.patchecked = patchecked
elif self.pctx:
+ self.repo.bfstatus = True
status = self.repo.status(node1=self.pctx.p1().node(), **stopts)
+ self.repo.bfstatus = False
wctx = context.workingctx(self.repo, changes=status)
else:
wctx = self.repo[None]
+ self.repo.bfstatus = True
wctx.status(**stopts)
+ self.repo.bfstatus = False
self.wctx = wctx
wctx.dirtySubrepos = []
|
@@ -8,8 +8,8 @@ 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, bfprompt
from tortoisehg.util import hglib, shlib
from tortoisehg.hgqt.i18n import _
@@ -52,6 +52,8 @@ allactions.append(None)
make(_('&Forget'), forget, frozenset('MAC!'), 'filedelete')
make(_('&Add'), add, frozenset('I?'), 'fileadd')
+ if 'kbfiles' in self.repo.extensions():
+ make(_('Add &Bfiles'), addbf, frozenset('I?'))
make(_('&Detect Renames...'), guessRename, frozenset('A?!'),
'detect_rename')
make(_('&Ignore...'), ignore, frozenset('?'), 'ignore')
@@ -268,9 +270,30 @@ return True
def add(parent, ui, repo, files):
+ if 'kbfiles' in repo.extensions():
+ result = bfprompt.promptForBfiles(parent, ui, repo, files)
+ if not result:
+ return False
+ files, bfiles = result
+ for name, module in extensions.extensions():
+ if name == 'kbfiles':
+ override_add = module.bfsetup.override_add
+ if files:
+ override_add(commands.add, ui, repo, *files)
+ if bfiles:
+ override_add(commands.add, ui, repo, *bfiles, bf=1)
+ return True
commands.add(ui, repo, *files)
return True
+def addbf(parent, ui, repo, files):
+ for name, module in extensions.extensions():
+ if name == 'kbfiles':
+ override_add = module.bfsetup.override_add
+ override_add(commands.add, ui, repo, *files, bf=True)
+ return True
+ return False
+
def guessRename(parent, ui, repo, files):
from tortoisehg.hgqt.guess import DetectRenameDialog
dlg = DetectRenameDialog(repo, parent, *files)
|
@@ -90,7 +90,9 @@ time.sleep(tdelta)
repo = hg.repository(ui, root) # a fresh repo object is needed
+ repo.bfstatus = True
repostate = repo.status() # will update .hg/dirstate as a side effect
+ repo.bfstatus = False
modified, added, removed, deleted = repostate[:4]
dirstatus = {}
|
@@ -31,7 +31,8 @@
Dirstate* Dirstatecache::get(
- const std::string& hgroot, const std::string& cwd, bool& unset)
+ const std::string& hgroot, const std::string& cwd, bool& unset,
+ bool usekbfiles)
{
unset = false;
@@ -40,12 +41,13 @@ Iter iter = cache().begin();
for (;iter != cache().end(); ++iter)
{
- if (hgroot == iter->hgroot)
+ if (hgroot == iter->hgroot && usekbfiles == iter->usekbfiles)
break;
}
Winstat64 stat;
- std::string path = hgroot + "\\.hg\\dirstate";
+ std::string path = hgroot + (usekbfiles ? "\\.hg\\kilnbfiles\\dirstate"
+ : "\\.hg\\dirstate");
unsigned tc = GetTickCount();
bool new_stat = false;
@@ -71,6 +73,7 @@
E e;
e.hgroot = hgroot;
+ e.usekbfiles = usekbfiles;
cache().push_front(e);
iter = cache().begin();
iter->tickcount = tc;
@@ -159,7 +162,7 @@}
-void Dirstatecache::invalidate(const std::string& hgroot)
+void Dirstatecache::invalidate(const std::string& hgroot, bool usekbfiles)
{
typedef std::list<E>::iterator Iter;
@@ -168,7 +171,7 @@
for (Iter i = cache().begin(); i != cache().end(); ++i)
{
- if (hgroot == i->hgroot)
+ if (hgroot == i->hgroot && usekbfiles == i->usekbfiles)
{
delete i->dstate;
i->dstate = 0;
|
@@ -34,13 +34,15 @@ std::string hgroot;
unsigned tickcount;
bool unset;
+ bool usekbfiles;
E():
dstate(0),
dstate_mtime(0),
dstate_size(0),
tickcount(0),
- unset(false)
+ unset(false),
+ usekbfiles(false)
{}
};
@@ -48,8 +50,9 @@
public:
static Dirstate* get(
- const std::string& hgroot, const std::string& cwd, bool& unset);
- static void invalidate(const std::string& hgroot);
+ const std::string& hgroot, const std::string& cwd, bool& unset,
+ bool usekbfiles = false);
+ static void invalidate(const std::string& hgroot, bool usekbfiles = false);
};
#endif
|
@@ -83,9 +83,9 @@ {
std::string p = cur.path;
p.push_back('\\');
- if (p.find("\\.hg\\") != std::string::npos)
+ if (p.find("\\.hg\\") != std::string::npos || p.find("\\.kbf\\") != std::string::npos)
{
- // ignore files and dirs named '.hg'
+ // ignore files and dirs named '.hg' or '.kbf'
last = cur;
return 0;
}
@@ -301,8 +301,13 @@ {
if (!relpath.empty() && !pds->root().getdir(relpath))
{
- last = cur;
- return 0; // unknown dir -> no icon
+ // attempt to get status from kbfiles
+ pds = Dirstatecache::get(cur.hgroot, cur.basedir, unset, true);
+ if (!pds || !pds->root().getdir(relpath))
+ {
+ last = cur;
+ return 0; // unknown dir -> no icon
+ }
}
outStatus = (pdirsta ? pdirsta->status(relpath) : '?');
@@ -312,11 +317,20 @@ return 1;
}
- const Direntry* const e = pds->root().get(relpath);
+ const Direntry* e = pds->root().get(relpath);
if (!e)
{
- last = cur;
- return 0;
+ // attempt to get status from kbfiles
+ pds = Dirstatecache::get(cur.hgroot, cur.basedir, unset, true);
+ if (pds)
+ {
+ e = pds->root().get(relpath);
+ }
+ if (!e)
+ {
+ last = cur;
+ return 0;
+ }
}
outStatus = e->status(stat);
|
Loading...