Convert Hg VCS

This commit is contained in:
Romain Failliot 2021-11-18 13:49:05 -05:00
parent 8577984373
commit 704579bf79
2 changed files with 102 additions and 77 deletions

View File

@ -58,6 +58,7 @@ from diffuse.vcs.bzr import Bzr
from diffuse.vcs.cvs import Cvs from diffuse.vcs.cvs import Cvs
from diffuse.vcs.darcs import Darcs from diffuse.vcs.darcs import Darcs
from diffuse.vcs.git import Git from diffuse.vcs.git import Git
from diffuse.vcs.hg import Hg
if not hasattr(__builtins__, 'WindowsError'): if not hasattr(__builtins__, 'WindowsError'):
# define 'WindowsError' so 'except' statements will work on all platforms # define 'WindowsError' so 'except' statements will work on all platforms
@ -1262,86 +1263,10 @@ def _get_git_repo(path, prefs):
break break
path = newpath path = newpath
# Mercurial support
class _Hg:
def __init__(self, root):
self.root = root
self.working_rev = None
def _getPreviousRevision(self, prefs, rev):
if rev is None:
if self.working_rev is None:
ss = utils.popenReadLines(self.root, [ prefs.getString('hg_bin'), 'id', '-i', '-t' ], prefs, 'hg_bash')
if len(ss) != 1:
raise IOError('Unknown working revision')
ss = ss[0].split(' ')
prev = ss[-1]
if len(ss) == 1 and prev.endswith('+'):
# remove local modifications indicator
prev = prev[:-1]
self.working_rev = prev
return self.working_rev
return f'p1({rev})'
def getFileTemplate(self, prefs, name):
return [ (name, self._getPreviousRevision(prefs, None)), (name, None) ]
def _getCommitTemplate(self, prefs, names, cmd, rev):
# build command
args = [ prefs.getString('hg_bin') ]
args.extend(cmd)
# build list of interesting files
pwd, isabs = os.path.abspath(os.curdir), False
for name in names:
isabs |= os.path.isabs(name)
args.append(utils.safeRelativePath(self.root, name, prefs, 'hg_cygwin'))
# run command
prev = self._getPreviousRevision(prefs, rev)
fs = FolderSet(names)
modified = {}
for s in utils.popenReadLines(self.root, args, prefs, 'hg_bash'):
# parse response
if len(s) < 3 or s[0] not in 'AMR':
continue
k = os.path.join(self.root, prefs.convertToNativePath(s[2:]))
if fs.contains(k):
if not isabs:
k = utils.relpath(pwd, k)
if s[0] == 'R':
# removed
modified[k] = [ (k, prev), (None, None) ]
elif s[0] == 'A':
# added
modified[k] = [ (None, None), (k, rev) ]
else:
# modified or merge conflict
modified[k] = [ (k, prev), (k, rev) ]
# sort the results
return [ modified[k] for k in sorted(modified.keys()) ]
def getCommitTemplate(self, prefs, rev, names):
return self._getCommitTemplate(prefs, names, [ 'log', '--template', 'A\t{file_adds}\nM\t{file_mods}\nR\t{file_dels}\n', '-r', rev ], rev)
def getFolderTemplate(self, prefs, names):
return self._getCommitTemplate(prefs, names, [ 'status', '-q' ], None)
def getRevision(self, prefs, name, rev):
return utils.popenRead(
self.root,
[
prefs.getString('hg_bin'),
'cat',
'-r',
rev,
utils.safeRelativePath(self.root, name, prefs, 'hg_cygwin')
],
prefs,
'hg_bash')
def _get_hg_repo(path, prefs): def _get_hg_repo(path, prefs):
p = _find_parent_dir_with(path, '.hg') p = _find_parent_dir_with(path, '.hg')
if p: if p:
return _Hg(p) return Hg(p)
# Monotone support # Monotone support
class _Mtn: class _Mtn:

100
src/vcs/hg.py Normal file
View File

@ -0,0 +1,100 @@
# Diffuse: a graphical tool for merging and comparing text files.
#
# Copyright (C) 2019 Derrick Moser <derrick_moser@yahoo.com>
# Copyright (C) 2021 Romain Failliot <romain.failliot@foolstep.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os
from diffuse import utils
from diffuse.vcs.folder_set import FolderSet
from diffuse.vcs.vcs_interface import VcsInterface
# Mercurial support
class Hg(VcsInterface):
def __init__(self, root):
VcsInterface.__init__(self, root)
self.working_rev = None
def _getPreviousRevision(self, prefs, rev):
if rev is None:
if self.working_rev is None:
ss = utils.popenReadLines(self.root, [ prefs.getString('hg_bin'), 'id', '-i', '-t' ], prefs, 'hg_bash')
if len(ss) != 1:
raise IOError('Unknown working revision')
ss = ss[0].split(' ')
prev = ss[-1]
if len(ss) == 1 and prev.endswith('+'):
# remove local modifications indicator
prev = prev[:-1]
self.working_rev = prev
return self.working_rev
return f'p1({rev})'
def getFileTemplate(self, prefs, name):
return [ (name, self._getPreviousRevision(prefs, None)), (name, None) ]
def _getCommitTemplate(self, prefs, names, cmd, rev):
# build command
args = [ prefs.getString('hg_bin') ]
args.extend(cmd)
# build list of interesting files
pwd, isabs = os.path.abspath(os.curdir), False
for name in names:
isabs |= os.path.isabs(name)
args.append(utils.safeRelativePath(self.root, name, prefs, 'hg_cygwin'))
# run command
prev = self._getPreviousRevision(prefs, rev)
fs = FolderSet(names)
modified = {}
for s in utils.popenReadLines(self.root, args, prefs, 'hg_bash'):
# parse response
if len(s) < 3 or s[0] not in 'AMR':
continue
k = os.path.join(self.root, prefs.convertToNativePath(s[2:]))
if fs.contains(k):
if not isabs:
k = utils.relpath(pwd, k)
if s[0] == 'R':
# removed
modified[k] = [ (k, prev), (None, None) ]
elif s[0] == 'A':
# added
modified[k] = [ (None, None), (k, rev) ]
else:
# modified or merge conflict
modified[k] = [ (k, prev), (k, rev) ]
# sort the results
return [ modified[k] for k in sorted(modified.keys()) ]
def getCommitTemplate(self, prefs, rev, names):
return self._getCommitTemplate(prefs, names, [ 'log', '--template', 'A\t{file_adds}\nM\t{file_mods}\nR\t{file_dels}\n', '-r', rev ], rev)
def getFolderTemplate(self, prefs, names):
return self._getCommitTemplate(prefs, names, [ 'status', '-q' ], None)
def getRevision(self, prefs, name, rev):
return utils.popenRead(
self.root,
[
prefs.getString('hg_bin'),
'cat',
'-r',
rev,
utils.safeRelativePath(self.root, name, prefs, 'hg_cygwin')
],
prefs,
'hg_bash')