[PATCH default] rupdate - Add dialog for Remote Update

4 views
Skip to first unread message

Ryan Seto

unread,
Mar 14, 2011, 3:53:51 PM3/14/11
to thg...@googlegroups.com
# HG changeset patch
# User Ryan Seto <ryan...@connectcorp.com>
# Date 1300131723 14400
# Node ID 437740e770d4683ed199e3eafbfb496f75c87ce0
# Parent 9ba2ff2d944a964cf5c1453c21ae26febfd341d3
rupdate - Add dialog for Remote Update.

Requires rupdate: http://bitbucket.org/MrWerewolf/rupdate

Remote Update is adds the ability to update a remote repository to a
specified revision if the remote repository is accessed through ssh.

Note: The default TortoisePlink.exe will give you a "Not enough storage is
available to process this command" error when you try to run this. To get around
this, use another version of plink. I use a copy of the TortoisePlink.exe from
TortoiseCVS.

diff --git a/tortoisehg/hgqt/repowidget.py b/tortoisehg/hgqt/repowidget.py
--- a/tortoisehg/hgqt/repowidget.py
+++ b/tortoisehg/hgqt/repowidget.py
@@ -1010,6 +1010,9 @@
entry(menu, 'reviewboard', fixed, _('Post to Review Board...'), 'reviewboard',
self.sendToReviewBoard)

+ entry(menu, 'rupdate', fixed, _('Remote Update...'), 'hg-update',
+ self.rupdate)
+
self.singlecmenu = menu
self.singlecmenuitems = items

@@ -1252,6 +1255,10 @@
run.postreview(self.repo.ui, rev=self.repoview.selectedRevisions(),
repo=self.repo)

+ def rupdate(self):
+ run.rupdate(self.repo.ui, rev=self.rev,
+ repo=self.repo)
+
def emailRevision(self):
run.email(self.repo.ui, rev=self.repoview.selectedRevisions(),
repo=self.repo)
diff --git a/tortoisehg/hgqt/run.py b/tortoisehg/hgqt/run.py
--- a/tortoisehg/hgqt/run.py
+++ b/tortoisehg/hgqt/run.py
@@ -565,6 +565,11 @@
from tortoisehg.hgqt.postreview import run
return qtrun(run, ui, *pats, **opts)

+def rupdate(ui, *pats, **opts):
+ """update a remote repository"""
+ from tortoisehg.hgqt.rupdate import run
+ return qtrun(run, ui, *pats, **opts)
+
def merge(ui, *pats, **opts):
"""merge wizard"""
from tortoisehg.hgqt.merge import run
diff --git a/tortoisehg/hgqt/rupdate.py b/tortoisehg/hgqt/rupdate.py
new file mode 100644
--- /dev/null
+++ b/tortoisehg/hgqt/rupdate.py
@@ -0,0 +1,268 @@
+# Copyright 2011 Ryan Seto <mr.we...@gmail.com>
+#
+# rupdate.py - Remote Update dialog for TortoiseHg
+#
+# This dialog lets users update a remote ssh repository.
+#
+# Requires a copy of the rupdate plugin found at:
+# http://bitbucket.org/MrWerewolf/rupdate
+#
+# Also, enable the plugin with the following in mercurial.ini:
+#
+# [extensions]
+# rupdate = /path/to/rupdate
+#
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2, incorporated herein by reference.
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from mercurial import error, node, merge as mergemod
+
+from tortoisehg.util import hglib, paths, settings
+from tortoisehg.hgqt.i18n import _
+from tortoisehg.hgqt import cmdui, csinfo, qtlib, thgrepo, resolve
+
+class rUpdateDialog(QDialog):
+
+ output = pyqtSignal(QString, QString)
+ progress = pyqtSignal(QString, object, QString, QString, object)
+ makeLogVisible = pyqtSignal(bool)
+
+ def __init__(self, repo, rev=None, parent=None, opts={}):
+ super(rUpdateDialog, self).__init__(parent)
+ self.setWindowFlags(self.windowFlags() & \
+ ~Qt.WindowContextHelpButtonHint)
+
+ self._finished = False
+ self.repo = repo
+
+ # base layout box
+ box = QVBoxLayout()
+ box.setSpacing(6)
+
+ ## main layout grid
+ grid = QGridLayout()
+ grid.setSpacing(6)
+ box.addLayout(grid)
+
+ # Get configured paths
+ self.paths = {}
+ fn = self.repo.join('hgrc')
+ fn, cfg = qtlib.loadIniFile([fn], self)
+ if 'paths' in cfg:
+ for alias in cfg['paths']:
+ self.paths[ alias ] = cfg['paths'][alias]
+
+ ### target path combo
+
+ self.path_combo = pcombo = QComboBox()
+ pcombo.setEditable(True)
+ grid.addWidget(QLabel(_('Location:')), 0, 0)
+ grid.addWidget(pcombo, 0, 1)
+
+ for alias in self.paths:
+ pcombo.addItem(hglib.tounicode(self.paths[alias]))
+
+ ### target revision combo
+ self.rev_combo = combo = QComboBox()
+ combo.setEditable(True)
+ grid.addWidget(QLabel(_('Update to:')), 1, 0)
+ grid.addWidget(combo, 1, 1)
+
+ if rev is None:
+ rev = self.repo.dirstate.branch()
+ else:
+ rev = str(rev)
+ combo.addItem(hglib.tounicode(rev))
+ combo.setCurrentIndex(0)
+
+ for name in repo.namedbranches:
+ combo.addItem(name)
+
+ tags = list(self.repo.tags()) + repo._bookmarks.keys()
+ tags.sort(reverse=True)
+ for tag in tags:
+ combo.addItem(hglib.tounicode(tag))
+
+ ### target revision info
+ items = ('%(rev)s', ' %(branch)s', ' %(tags)s', '<br />%(summary)s')
+ style = csinfo.labelstyle(contents=items, width=350, selectable=True)
+ factory = csinfo.factory(self.repo, style=style)
+ self.target_info = factory()
+ grid.addWidget(QLabel(_('Target:')), 3, 0, Qt.AlignLeft | Qt.AlignTop)
+ grid.addWidget(self.target_info, 3, 1)
+
+ ### options
+ optbox = QVBoxLayout()
+ optbox.setSpacing(6)
+ expander = qtlib.ExpanderLabel(_('Options:'), False)
+ expander.expanded.connect(self.show_options)
+ row = grid.rowCount()
+ grid.addWidget(expander, row, 0, Qt.AlignLeft | Qt.AlignTop)
+ grid.addLayout(optbox, row, 1)
+
+ self.discard_chk = QCheckBox(_('Discard local changes, no backup'
+ ' (-C/--clean)'))
+ self.push_chk = QCheckBox(_('Perform a push before updating'
+ ' (-p/--push)'))
+ self.newbranch_chk = QCheckBox(_('Allow pushing new branches'
+ ' (--new-branch)'))
+ self.force_chk = QCheckBox(_('Force push to remote location'
+ ' (-f/--force)'))
+ self.showlog_chk = QCheckBox(_('Always show command log'))
+ optbox.addWidget(self.discard_chk)
+ optbox.addWidget(self.push_chk)
+ optbox.addWidget(self.newbranch_chk)
+ optbox.addWidget(self.force_chk)
+ optbox.addWidget(self.showlog_chk)
+
+ self.discard_chk.setChecked(bool(opts.get('clean')))
+
+ ## command widget
+ self.cmd = cmdui.Widget(True, True, self)
+ self.cmd.commandStarted.connect(self.command_started)
+ self.cmd.commandFinished.connect(self.command_finished)
+ self.cmd.commandCanceling.connect(self.command_canceling)
+ self.cmd.output.connect(self.output)
+ self.cmd.makeLogVisible.connect(self.makeLogVisible)
+ self.cmd.progress.connect(self.progress)
+ box.addWidget(self.cmd)
+
+ ## bottom buttons
+ buttons = QDialogButtonBox()
+ self.cancel_btn = buttons.addButton(QDialogButtonBox.Cancel)
+ self.cancel_btn.clicked.connect(self.cancel_clicked)
+ self.close_btn = buttons.addButton(QDialogButtonBox.Close)
+ self.close_btn.clicked.connect(self.reject)
+ self.close_btn.setAutoDefault(False)
+ self.update_btn = buttons.addButton(_('&Update'),
+ QDialogButtonBox.ActionRole)
+ self.update_btn.clicked.connect(self.update)
+ self.detail_btn = buttons.addButton(_('Detail'),
+ QDialogButtonBox.ResetRole)
+ self.detail_btn.setAutoDefault(False)
+ self.detail_btn.setCheckable(True)
+ self.detail_btn.toggled.connect(self.detail_toggled)
+ box.addWidget(buttons)
+
+ # signal handlers
+ self.rev_combo.editTextChanged.connect(lambda *a: self.update_info())
+ self.discard_chk.toggled.connect(lambda *a: self.update_info())
+
+ # dialog setting
+ self.setLayout(box)
+ self.layout().setSizeConstraint(QLayout.SetFixedSize)
+ self.setWindowTitle(_('Update - %s') % self.repo.displayname)
+ self.setWindowIcon(qtlib.geticon('hg-update'))
+
+ # prepare to show
+ self.rev_combo.lineEdit().selectAll()
+ self.cmd.setHidden(True)
+ self.cancel_btn.setHidden(True)
+ self.detail_btn.setHidden(True)
+ self.push_chk.setHidden(True)
+ self.newbranch_chk.setHidden(True)
+ self.force_chk.setHidden(True)
+ self.showlog_chk.setHidden(True)
+ self.update_info()
+
+ ### Private Methods ###
+
+ def update_info(self):
+ new_rev = hglib.fromunicode(self.rev_combo.currentText())
+ if new_rev.lower() == 'null':
+ self.update_btn.setEnabled(True)
+ return
+ try:
+ new_ctx = self.repo[new_rev]
+ self.target_info.update(self.repo[new_rev])
+ self.update_btn.setEnabled(True)
+ except (error.LookupError, error.RepoLookupError, error.RepoError):
+ self.target_info.setText(_('unknown revision!'))
+ self.update_btn.setDisabled(True)
+
+ def update(self):
+ cmdline = ['rupdate']
+
+ if self.discard_chk.isChecked():
+ cmdline.append('--clean')
+ if self.push_chk.isChecked():
+ cmdline.append('--push')
+ if self.newbranch_chk.isChecked():
+ cmdline.append('--new-branch')
+ if self.force_chk.isChecked():
+ cmdline.append('--force')
+
+ dest = hglib.fromunicode(self.path_combo.currentText())
+ cmdline.append('-d')
+ cmdline.append(dest)
+
+ # Refer to the revision by the short hash.
+ rev = hglib.fromunicode(self.rev_combo.currentText())
+ revShortHash = node.short(self.repo[rev].node())
+ cmdline.append(revShortHash)
+
+ # start updating
+ self.repo.incrementBusyCount()
+ self.cmd.run(cmdline)
+
+ ### Signal Handlers ###
+
+ def cancel_clicked(self):
+ self.cmd.cancel()
+ self.reject()
+
+ def detail_toggled(self, checked):
+ self.cmd.setShowOutput(checked)
+
+ def show_options(self, visible):
+ self.push_chk.setShown(visible)
+ self.newbranch_chk.setShown(visible)
+ self.force_chk.setShown(visible)
+ self.showlog_chk.setShown(visible)
+
+ def command_started(self):
+ self.cmd.setShown(True)
+ if self.showlog_chk.isChecked():
+ self.detail_btn.setChecked(True)
+ self.close_btn.setHidden(True)
+ self.cancel_btn.setShown(True)
+ self.detail_btn.setShown(True)
+
+ def command_finished(self, ret):
+ self.repo.decrementBusyCount()
+ if ret not in (0, 1) or self.cmd.outputShown():
+ self.detail_btn.setChecked(True)
+ self.close_btn.setShown(True)
+ self.close_btn.setAutoDefault(True)
+ self.close_btn.setFocus()
+ self.cancel_btn.setHidden(True)
+ else:
+ self.accept()
+
+ def accept(self):
+ for root, path, status in thgrepo.recursiveMergeStatus(self.repo):
+ if status == 'u':
+ qtlib.InfoMsgBox(_('Merge caused file conflicts'),
+ _('File conflicts need to be resolved'))
+ dlg = resolve.ResolveDialog(self.repo, self)
+ dlg.finished.connect(dlg.deleteLater)
+ dlg.exec_()
+ break
+ super(rUpdateDialog, self).accept()
+
+ def command_canceling(self):
+ self.cancel_btn.setDisabled(True)
+
+def run(ui, *pats, **opts):
+ from tortoisehg.util import paths
+ repo = thgrepo.repository(ui, path=paths.find_root())
+ rev = None
+ if opts.get('rev'):
+ rev = opts.get('rev')
+ elif len(pats) == 1:
+ rev = pats[0]
+ return rUpdateDialog(repo, rev, None, opts)

Steve Borho

unread,
Mar 14, 2011, 4:35:36 PM3/14/11
to thg...@googlegroups.com
On Mon, Mar 14, 2011 at 2:53 PM, Ryan Seto <mr.we...@gmail.com> wrote:
> # HG changeset patch
> # User Ryan Seto <ryan...@connectcorp.com>
> # Date 1300131723 14400
> # Node ID 437740e770d4683ed199e3eafbfb496f75c87ce0
> # Parent  9ba2ff2d944a964cf5c1453c21ae26febfd341d3
> rupdate - Add dialog for Remote Update.
>
> Requires rupdate: http://bitbucket.org/MrWerewolf/rupdate

Interesting

> Remote Update is adds the ability to update a remote repository to a
> specified revision if the remote repository is accessed through ssh.
>
> Note: The default TortoisePlink.exe will give you a "Not enough storage is
> available to process this command" error when you try to run this. To get around
> this, use another version of plink.  I use a copy of the TortoisePlink.exe from
> TortoiseCVS.

That is odd. Our TortoisePlink.exe came from TortoiseSVN. Perhaps
TortoiseCVS has updated there's more recently.

I'm mostly ok with this except that it's a near duplication of the
update dialog. Would it be possible to make your dialog class derive
from UpdateDialog and simply override a few methods?

--
Steve Borho

MrWerewolf

unread,
Mar 16, 2011, 12:19:04 PM3/16/11
to TortoiseHg Developers
Yes, I can certainly get my dialog class derived from the
UpdateDialog. Sorry I didn't think to do that in the first place.

I noticed that the TortoisePlink.exe was from the TortoiseSVN project,
so I tried the latest version from the TortoiseSVN, but that had the
same issue. I realized that they derived theirs from the TortoiseCVS
project, so I tried that one and it worked. I think they do use a
more recent version from the putty project that doesn't have this
issue. I did find it odd that the "hg serve" command doesn't have
this issue, but running the "hg update" command remotely does.

Thank you for looking over my patch. I'll get you an updated patch
soon.

On Mar 14, 4:35 pm, Steve Borho <st...@borho.org> wrote:
> On Mon, Mar 14, 2011 at 2:53 PM, Ryan Seto <mr.werew...@gmail.com> wrote:
> > # HG changeset patch
> > # User Ryan Seto <ryan.s...@connectcorp.com>
> > +# Copyright 2011 Ryan Seto <mr.werew...@gmail.com>
> ...
>
> read more »

Ryan Seto

unread,
Mar 17, 2011, 9:16:36 AM3/17/11
to thg...@googlegroups.com
# HG changeset patch
# User Ryan Seto <mr.we...@gmail.com>
# Date 1300367516 14400
# Node ID 0f46c77c5a833fb76ae5f5bbc7abe695b8b6ba24

# Parent 9ba2ff2d944a964cf5c1453c21ae26febfd341d3
rupdate - Add dialog for Remote Update.

Requires rupdate: http://bitbucket.org/MrWerewolf/rupdate

Remote Update is adds the ability to update a remote repository to a


specified revision if the remote repository is accessed through ssh.

Note: The default TortoisePlink.exe will give you a "Not enough storage is
available to process this command" error when you try to run this. To get around
this, use another version of plink. I use a copy of the TortoisePlink.exe from
TortoiseCVS.

diff --git a/tortoisehg/hgqt/repowidget.py b/tortoisehg/hgqt/repowidget.py

@@ -0,0 +1,132 @@
+# Copyright 2011 Ryan Seto <mr.we...@gmail.com>


+#
+# rupdate.py - Remote Update dialog for TortoiseHg
+#
+# This dialog lets users update a remote ssh repository.
+#
+# Requires a copy of the rupdate plugin found at:
+# http://bitbucket.org/MrWerewolf/rupdate
+#
+# Also, enable the plugin with the following in mercurial.ini:
+#
+# [extensions]
+# rupdate = /path/to/rupdate
+#
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2, incorporated herein by reference.
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from mercurial import error, node, merge as mergemod
+
+from tortoisehg.util import hglib, paths

+from tortoisehg.hgqt.i18n import _
+from tortoisehg.hgqt import cmdui, csinfo, qtlib, thgrepo, resolve

+from tortoisehg.hgqt.update import UpdateDialog
+
+class rUpdateDialog(UpdateDialog):


+
+ def __init__(self, repo, rev=None, parent=None, opts={}):

+ super(rUpdateDialog, self).__init__(repo, rev, parent, opts)


+
+ # Get configured paths
+ self.paths = {}
+ fn = self.repo.join('hgrc')
+ fn, cfg = qtlib.loadIniFile([fn], self)
+ if 'paths' in cfg:
+ for alias in cfg['paths']:
+ self.paths[ alias ] = cfg['paths'][alias]
+
+ ### target path combo
+ self.path_combo = pcombo = QComboBox()
+ pcombo.setEditable(True)
+

+ for alias in self.paths:
+ pcombo.addItem(hglib.tounicode(self.paths[alias]))
+

+ ### shift existing items down a row.
+ for i in range(self.grid.count()-1, -1, -1):
+ row, col, rowSp, colSp = self.grid.getItemPosition(i)
+ item = self.grid.takeAt(i)
+ self.grid.removeItem(item)
+ self.grid.addItem(item, row + 1, col, rowSp, colSp, item.alignment())
+
+ ### add target path combo to grid
+ self.grid.addWidget(QLabel(_('Location:')), 0, 0)
+ self.grid.addWidget(pcombo, 0, 1)
+
+ ### Options


+ self.push_chk = QCheckBox(_('Perform a push before updating'
+ ' (-p/--push)'))
+ self.newbranch_chk = QCheckBox(_('Allow pushing new branches'
+ ' (--new-branch)'))
+ self.force_chk = QCheckBox(_('Force push to remote location'
+ ' (-f/--force)'))

+ self.optbox.removeWidget(self.showlog_chk)
+ self.optbox.addWidget(self.push_chk)
+ self.optbox.addWidget(self.newbranch_chk)
+ self.optbox.addWidget(self.force_chk)
+ self.optbox.addWidget(self.showlog_chk)


+
+ # prepare to show

+ self.push_chk.setHidden(True)
+ self.newbranch_chk.setHidden(True)
+ self.force_chk.setHidden(True)

+ self.update_info()
+
+ ### Private Methods ###
+
+ def update_info(self):

+ super(rUpdateDialog, self).update_info()
+
+ # Keep update button enabled.
+ self.update_btn.setDisabled(False)

+ def show_options(self, visible):
+ self.push_chk.setShown(visible)
+ self.newbranch_chk.setShown(visible)
+ self.force_chk.setShown(visible)
+ self.showlog_chk.setShown(visible)
+
+ def command_started(self):

+ super(rUpdateDialog, self).command_started()
+ self.update_btn.setHidden(False)


+
+def run(ui, *pats, **opts):
+ from tortoisehg.util import paths
+ repo = thgrepo.repository(ui, path=paths.find_root())
+ rev = None
+ if opts.get('rev'):
+ rev = opts.get('rev')
+ elif len(pats) == 1:
+ rev = pats[0]
+ return rUpdateDialog(repo, rev, None, opts)

diff --git a/tortoisehg/hgqt/update.py b/tortoisehg/hgqt/update.py
--- a/tortoisehg/hgqt/update.py
+++ b/tortoisehg/hgqt/update.py
@@ -35,15 +35,15 @@
box.setSpacing(6)

## main layout grid
- grid = QGridLayout()
- grid.setSpacing(6)
- box.addLayout(grid)
+ self.grid = QGridLayout()
+ self.grid.setSpacing(6)
+ box.addLayout(self.grid)

### target revision combo


self.rev_combo = combo = QComboBox()

combo.setEditable(True)
- grid.addWidget(QLabel(_('Update to:')), 0, 0)
- grid.addWidget(combo, 0, 1)
+ self.grid.addWidget(QLabel(_('Update to:')), 0, 0)
+ self.grid.addWidget(combo, 0, 1)

if rev is None:
rev = self.repo.dirstate.branch()
@@ -65,31 +65,31 @@


style = csinfo.labelstyle(contents=items, width=350, selectable=True)

factory = csinfo.factory(self.repo, style=style)
self.target_info = factory()
- grid.addWidget(QLabel(_('Target:')), 1, 0, Qt.AlignLeft | Qt.AlignTop)
- grid.addWidget(self.target_info, 1, 1)
+ self.grid.addWidget(QLabel(_('Target:')), 1, 0, Qt.AlignLeft | Qt.AlignTop)
+ self.grid.addWidget(self.target_info, 1, 1)

### parent revision info
self.ctxs = self.repo[None].parents()
if len(self.ctxs) == 2:
self.p1_info = factory()
- grid.addWidget(QLabel(_('Parent 1:')), 2, 0, Qt.AlignLeft | Qt.AlignTop)
- grid.addWidget(self.p1_info, 2, 1)
+ self.grid.addWidget(QLabel(_('Parent 1:')), 2, 0, Qt.AlignLeft | Qt.AlignTop)
+ self.grid.addWidget(self.p1_info, 2, 1)
self.p2_info = factory()
- grid.addWidget(QLabel(_('Parent 2:')), 3, 0, Qt.AlignLeft | Qt.AlignTop)
- grid.addWidget(self.p2_info, 3, 1)
+ self.grid.addWidget(QLabel(_('Parent 2:')), 3, 0, Qt.AlignLeft | Qt.AlignTop)
+ self.grid.addWidget(self.p2_info, 3, 1)
else:
self.p1_info = factory()
- grid.addWidget(QLabel(_('Parent:')), 2, 0, Qt.AlignLeft | Qt.AlignTop)
- grid.addWidget(self.p1_info, 2, 1)
+ self.grid.addWidget(QLabel(_('Parent:')), 2, 0, Qt.AlignLeft | Qt.AlignTop)
+ self.grid.addWidget(self.p1_info, 2, 1)

### options
- optbox = QVBoxLayout()
- optbox.setSpacing(6)
+ self.optbox = QVBoxLayout()
+ self.optbox.setSpacing(6)


expander = qtlib.ExpanderLabel(_('Options:'), False)

expander.expanded.connect(self.show_options)
- row = grid.rowCount()
- grid.addWidget(expander, row, 0, Qt.AlignLeft | Qt.AlignTop)
- grid.addLayout(optbox, row, 1)
+ row = self.grid.rowCount()
+ self.grid.addWidget(expander, row, 0, Qt.AlignLeft | Qt.AlignTop)
+ self.grid.addLayout(self.optbox, row, 1)



self.discard_chk = QCheckBox(_('Discard local changes, no backup '

'(-C/--clean)'))
@@ -97,10 +97,10 @@
self.autoresolve_chk = QCheckBox(_('Automatically resolve merge conflicts '
'where possible'))


self.showlog_chk = QCheckBox(_('Always show command log'))

- optbox.addWidget(self.discard_chk)
- optbox.addWidget(self.merge_chk)
- optbox.addWidget(self.autoresolve_chk)
- optbox.addWidget(self.showlog_chk)
+ self.optbox.addWidget(self.discard_chk)
+ self.optbox.addWidget(self.merge_chk)
+ self.optbox.addWidget(self.autoresolve_chk)
+ self.optbox.addWidget(self.showlog_chk)

self.discard_chk.setChecked(bool(opts.get('clean')))
self.autoresolve_chk.setChecked(

MrWerewolf

unread,
Mar 17, 2011, 9:20:23 AM3/17/11
to TortoiseHg Developers
As a note, I had to modify the UpdateDialog to expose it's grid and
option box so I could modify them from a subclass in rupdate.py.

On Mar 17, 9:16 am, Ryan Seto <mr.werew...@gmail.com> wrote:
> # HG changeset patch
> # User Ryan Seto <mr.werew...@gmail.com>
> +# Copyright 2011 Ryan Seto <mr.werew...@gmail.com>
> ...
>
> read more »

Steve Borho

unread,
Mar 17, 2011, 10:52:47 AM3/17/11
to thg...@googlegroups.com
On Thu, Mar 17, 2011 at 8:16 AM, Ryan Seto <mr.we...@gmail.com> wrote:
> # HG changeset patch
> # User Ryan Seto <mr.we...@gmail.com>
> # Date 1300367516 14400
> # Node ID 0f46c77c5a833fb76ae5f5bbc7abe695b8b6ba24
> # Parent  9ba2ff2d944a964cf5c1453c21ae26febfd341d3
> rupdate - Add dialog for Remote Update.

Queued for default, thanks.

--
Steve Borho

MrWerewolf

unread,
Mar 17, 2011, 12:23:30 PM3/17/11
to TortoiseHg Developers
Thank you!

On Mar 17, 10:52 am, Steve Borho <st...@borho.org> wrote:
> On Thu, Mar 17, 2011 at 8:16 AM, Ryan Seto <mr.werew...@gmail.com> wrote:
> > # HG changeset patch
> > # User Ryan Seto <mr.werew...@gmail.com>
> > +# Copyright 2011 Ryan Seto <mr.werew...@gmail.com>
> ...
>
> read more »
Reply all
Reply to author
Forward
0 new messages