diff --git a/src/main.py b/src/main.py index cab5108..22e4fcd 100644 --- a/src/main.py +++ b/src/main.py @@ -55,6 +55,7 @@ from diffuse import utils from diffuse import constants from diffuse.vcs.folder_set import FolderSet from diffuse.vcs.bzr import Bzr +from diffuse.vcs.cvs import Cvs from diffuse.vcs.git import Git if not hasattr(__builtins__, 'WindowsError'): @@ -1217,100 +1218,9 @@ def _get_bzr_repo(path, prefs): if p: return Bzr(p) -# CVS support -class _Cvs: - def __init__(self, root): - self.root = root - - def getFileTemplate(self, prefs, name): - return [ (name, 'BASE'), (name, None) ] - - def getCommitTemplate(self, prefs, rev, names): - result = [] - try: - r, prev = rev.split('.'), None - if len(r) > 1: - m = int(r.pop()) - if m > 1: - r.append(str(m - 1)) - else: - m = int(r.pop()) - if len(r): - prev = '.'.join(r) - for k in sorted(names): - if prev is None: - k0 = None - else: - k0 = k - result.append([ (k0, prev), (k, rev) ]) - except ValueError: - utils.logError(_('Error parsing revision %s.') % (rev, )) - return result - - def getFolderTemplate(self, prefs, names): - # build command - args = [ prefs.getString('cvs_bin'), '-nq', 'update', '-R' ] - # 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, 'cvs_cygwin')) - # run command - prev = 'BASE' - fs = FolderSet(names) - modified = {} - for s in utils.popenReadLines(self.root, args, prefs, 'cvs_bash'): - # parse response - if len(s) < 3 or s[0] not in 'ACMR': - 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) ] - pass - elif s[0] == 'A': - # added - modified[k] = [ (None, None), (k, None) ] - else: - # modified - modified[k] = [ (k, prev), (k, None) ] - # sort the results - return [ modified[k] for k in sorted(modified.keys()) ] - - def getRevision(self, prefs, name, rev): - if rev == 'BASE' and not os.path.exists(name): - # find revision for removed files - for s in utils.popenReadLines( - self.root, - [ - prefs.getString('cvs_bin'), - 'status', - utils.safeRelativePath(self.root, name, prefs, 'cvs_cygwin') - ], - prefs, - 'cvs_bash'): - if s.startswith(' Working revision:\t-'): - rev = s.split('\t')[1][1:] - return utils.popenRead( - self.root, - [ - prefs.getString('cvs_bin'), - '-Q', - 'update', - '-p', - '-r', - rev, - utils.safeRelativePath(self.root, name, prefs, 'cvs_cygwin') - ], - prefs, - 'cvs_bash') - def _get_cvs_repo(path, prefs): if os.path.isdir(os.path.join(path, 'CVS')): - return _Cvs(path) + return Cvs(path) # Darcs support class _Darcs: diff --git a/src/vcs/cvs.py b/src/vcs/cvs.py new file mode 100644 index 0000000..6b887bd --- /dev/null +++ b/src/vcs/cvs.py @@ -0,0 +1,112 @@ +# Diffuse: a graphical tool for merging and comparing text files. +# +# Copyright (C) 2019 Derrick Moser +# Copyright (C) 2021 Romain Failliot +# +# 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 + +# CVS support +class Cvs(VcsInterface): + def getFileTemplate(self, prefs, name): + return [ (name, 'BASE'), (name, None) ] + + def getCommitTemplate(self, prefs, rev, names): + result = [] + try: + r, prev = rev.split('.'), None + if len(r) > 1: + m = int(r.pop()) + if m > 1: + r.append(str(m - 1)) + else: + m = int(r.pop()) + if len(r): + prev = '.'.join(r) + for k in sorted(names): + if prev is None: + k0 = None + else: + k0 = k + result.append([ (k0, prev), (k, rev) ]) + except ValueError: + utils.logError(_('Error parsing revision %s.') % (rev, )) + return result + + def getFolderTemplate(self, prefs, names): + # build command + args = [ prefs.getString('cvs_bin'), '-nq', 'update', '-R' ] + # 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, 'cvs_cygwin')) + # run command + prev = 'BASE' + fs = FolderSet(names) + modified = {} + for s in utils.popenReadLines(self.root, args, prefs, 'cvs_bash'): + # parse response + if len(s) < 3 or s[0] not in 'ACMR': + 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) ] + pass + elif s[0] == 'A': + # added + modified[k] = [ (None, None), (k, None) ] + else: + # modified + modified[k] = [ (k, prev), (k, None) ] + # sort the results + return [ modified[k] for k in sorted(modified.keys()) ] + + def getRevision(self, prefs, name, rev): + if rev == 'BASE' and not os.path.exists(name): + # find revision for removed files + for s in utils.popenReadLines( + self.root, + [ + prefs.getString('cvs_bin'), + 'status', + utils.safeRelativePath(self.root, name, prefs, 'cvs_cygwin') + ], + prefs, + 'cvs_bash'): + if s.startswith(' Working revision:\t-'): + rev = s.split('\t')[1][1:] + return utils.popenRead( + self.root, + [ + prefs.getString('cvs_bin'), + '-Q', + 'update', + '-p', + '-r', + rev, + utils.safeRelativePath(self.root, name, prefs, 'cvs_cygwin') + ], + prefs, + 'cvs_bash')