Skip to content

Commit 5d6ece8

Browse files
committed
Convert Svn VCS
1 parent f314f46 commit 5d6ece8

File tree

3 files changed

+265
-239
lines changed

3 files changed

+265
-239
lines changed

src/main.py

Lines changed: 3 additions & 239 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
from diffuse.vcs.hg import Hg
6262
from diffuse.vcs.mtn import Mtn
6363
from diffuse.vcs.rcs import Rcs
64+
from diffuse.vcs.svn import Svn
6465

6566
if not hasattr(__builtins__, 'WindowsError'):
6667
# define 'WindowsError' so 'except' statements will work on all platforms
@@ -70,11 +71,6 @@
7071
# this is sorted based upon frequency to speed up code for stripping whitespace
7172
whitespace = ' \t\n\r\x0b\x0c'
7273

73-
# escape special glob characters
74-
def globEscape(s):
75-
m = dict([ (c, f'[{c}]') for c in '[]?*' ])
76-
return ''.join([ m.get(c, c) for c in s ])
77-
7874
# colour resources
7975
class Colour:
8076
def __init__(self, r, g, b, a=1.0):
@@ -495,7 +491,7 @@ def parse(self, file_name):
495491
if args[0] == 'import' and len(args) == 2:
496492
path = os.path.expanduser(args[1])
497493
# relative paths are relative to the parsed file
498-
path = os.path.join(globEscape(os.path.dirname(file_name)), path)
494+
path = os.path.join(utils.globEscape(os.path.dirname(file_name)), path)
499495
paths = glob.glob(path)
500496
if len(paths) == 0:
501497
paths = [ path ]
@@ -1290,242 +1286,10 @@ def _get_rcs_repo(path, prefs):
12901286
# the user specified an invalid folder name
12911287
pass
12921288

1293-
# Subversion support
1294-
# SVK support subclasses from this
1295-
class _Svn:
1296-
def __init__(self, root):
1297-
self.root = root
1298-
self.url = None
1299-
1300-
def _getVcs(self):
1301-
return 'svn'
1302-
1303-
def _getURLPrefix(self):
1304-
return 'URL: '
1305-
1306-
def _parseStatusLine(self, s):
1307-
if len(s) < 8 or s[0] not in 'ACDMR':
1308-
return
1309-
# subversion 1.6 adds a new column
1310-
k = 7
1311-
if k < len(s) and s[k] == ' ':
1312-
k += 1
1313-
return s[0], s[k:]
1314-
1315-
def _getPreviousRevision(self, rev):
1316-
if rev is None:
1317-
return 'BASE'
1318-
m = int(rev)
1319-
if m > 1:
1320-
return str(m - 1)
1321-
1322-
def _getURL(self, prefs):
1323-
if self.url is None:
1324-
vcs, prefix = self._getVcs(), self._getURLPrefix()
1325-
n = len(prefix)
1326-
args = [ prefs.getString(vcs + '_bin'), 'info' ]
1327-
for s in utils.popenReadLines(self.root, args, prefs, vcs + '_bash'):
1328-
if s.startswith(prefix):
1329-
self.url = s[n:]
1330-
break
1331-
return self.url
1332-
1333-
def getFileTemplate(self, prefs, name):
1334-
# FIXME: verify this
1335-
# merge conflict
1336-
escaped_name = globEscape(name)
1337-
left = glob.glob(escaped_name + '.merge-left.r*')
1338-
right = glob.glob(escaped_name + '.merge-right.r*')
1339-
if len(left) > 0 and len(right) > 0:
1340-
return [ (left[-1], None), (name, None), (right[-1], None) ]
1341-
# update conflict
1342-
left = sorted(glob.glob(escaped_name + '.r*'))
1343-
right = glob.glob(escaped_name + '.mine')
1344-
right.extend(glob.glob(escaped_name + '.working'))
1345-
if len(left) > 0 and len(right) > 0:
1346-
return [ (left[-1], None), (name, None), (right[0], None) ]
1347-
# default case
1348-
return [ (name, self._getPreviousRevision(None)), (name, None) ]
1349-
1350-
def _getCommitTemplate(self, prefs, rev, names):
1351-
result = []
1352-
try:
1353-
prev = self._getPreviousRevision(rev)
1354-
except ValueError:
1355-
utils.logError(_('Error parsing revision %s.') % (rev, ))
1356-
return result
1357-
1358-
# build command
1359-
vcs = self._getVcs()
1360-
vcs_bin, vcs_bash = prefs.getString(vcs + '_bin'), vcs + '_bash'
1361-
if rev is None:
1362-
args = [ vcs_bin, 'status', '-q' ]
1363-
else:
1364-
args = [ vcs_bin, 'diff', '--summarize', '-c', rev ]
1365-
# build list of interesting files
1366-
pwd, isabs = os.path.abspath(os.curdir), False
1367-
for name in names:
1368-
isabs |= os.path.isabs(name)
1369-
if rev is None:
1370-
args.append(utils.safeRelativePath(self.root, name, prefs, vcs + '_cygwin'))
1371-
# run command
1372-
fs = FolderSet(names)
1373-
modified, added, removed = {}, set(), set()
1374-
for s in utils.popenReadLines(self.root, args, prefs, vcs_bash):
1375-
status = self._parseStatusLine(s)
1376-
if status is None:
1377-
continue
1378-
v, k = status
1379-
rel = prefs.convertToNativePath(k)
1380-
k = os.path.join(self.root, rel)
1381-
if fs.contains(k):
1382-
if v == 'D':
1383-
# deleted file or directory
1384-
# the contents of deleted folders are not reported
1385-
# by "svn diff --summarize -c <rev>"
1386-
removed.add(rel)
1387-
elif v == 'A':
1388-
# new file or directory
1389-
added.add(rel)
1390-
elif v == 'M':
1391-
# modified file or merge conflict
1392-
k = os.path.join(self.root, k)
1393-
if not isabs:
1394-
k = utils.relpath(pwd, k)
1395-
modified[k] = [ (k, prev), (k, rev) ]
1396-
elif v == 'C':
1397-
# merge conflict
1398-
modified[k] = self.getFileTemplate(prefs, k)
1399-
elif v == 'R':
1400-
# replaced file
1401-
removed.add(rel)
1402-
added.add(rel)
1403-
# look for files in the added items
1404-
if rev is None:
1405-
m, added = added, {}
1406-
for k in m:
1407-
if not os.path.isdir(k):
1408-
# confirmed as added file
1409-
k = os.path.join(self.root, k)
1410-
if not isabs:
1411-
k = utils.relpath(pwd, k)
1412-
added[k] = [ (None, None), (k, None) ]
1413-
else:
1414-
m = {}
1415-
for k in added:
1416-
d, b = os.path.dirname(k), os.path.basename(k)
1417-
if d not in m:
1418-
m[d] = set()
1419-
m[d].add(b)
1420-
# remove items we can easily determine to be directories
1421-
for k in m.keys():
1422-
d = os.path.dirname(k)
1423-
if d in m:
1424-
m[d].discard(os.path.basename(k))
1425-
if not m[d]:
1426-
del m[d]
1427-
# determine which are directories
1428-
added = {}
1429-
for p, v in m.items():
1430-
for s in utils.popenReadLines(self.root, [ vcs_bin, 'list', '-r', rev, '{}/{}'.format(self._getURL(prefs), p.replace(os.sep, '/')) ], prefs, vcs_bash):
1431-
if s in v:
1432-
# confirmed as added file
1433-
k = os.path.join(self.root, os.path.join(p, s))
1434-
if not isabs:
1435-
k = utils.relpath(pwd, k)
1436-
added[k] = [ (None, None), (k, rev) ]
1437-
# determine if removed items are files or directories
1438-
if prev == 'BASE':
1439-
m, removed = removed, {}
1440-
for k in m:
1441-
if not os.path.isdir(k):
1442-
# confirmed item as file
1443-
k = os.path.join(self.root, k)
1444-
if not isabs:
1445-
k = utils.relpath(pwd, k)
1446-
removed[k] = [ (k, prev), (None, None) ]
1447-
else:
1448-
m = {}
1449-
for k in removed:
1450-
d, b = os.path.dirname(k), os.path.basename(k)
1451-
if d not in m:
1452-
m[d] = set()
1453-
m[d].add(b)
1454-
removed_dir, removed = set(), {}
1455-
for p, v in m.items():
1456-
for s in utils.popenReadLines(self.root, [ vcs_bin, 'list', '-r', prev, '{}/{}'.format(self._getURL(prefs), p.replace(os.sep, '/')) ], prefs, vcs_bash):
1457-
if s.endswith('/'):
1458-
s = s[:-1]
1459-
if s in v:
1460-
# confirmed item as directory
1461-
removed_dir.add(os.path.join(p, s))
1462-
else:
1463-
if s in v:
1464-
# confirmed item as file
1465-
k = os.path.join(self.root, os.path.join(p, s))
1466-
if not isabs:
1467-
k = utils.relpath(pwd, k)
1468-
removed[k] = [ (k, prev), (None, None) ]
1469-
# recursively find all unreported removed files
1470-
while removed_dir:
1471-
tmp = removed_dir
1472-
removed_dir = set()
1473-
for p in tmp:
1474-
for s in utils.popenReadLines(self.root, [ vcs_bin, 'list', '-r', prev, '{}/{}'.format(self._getURL(prefs), p.replace(os.sep, '/')) ], prefs, vcs_bash):
1475-
if s.endswith('/'):
1476-
# confirmed item as directory
1477-
removed_dir.add(os.path.join(p, s[:-1]))
1478-
else:
1479-
# confirmed item as file
1480-
k = os.path.join(self.root, os.path.join(p, s))
1481-
if not isabs:
1482-
k = utils.relpath(pwd, k)
1483-
removed[k] = [ (k, prev), (None, None) ]
1484-
# sort the results
1485-
r = set()
1486-
for m in removed, added, modified:
1487-
r.update(m.keys())
1488-
for k in sorted(r):
1489-
for m in removed, added, modified:
1490-
if k in m:
1491-
result.append(m[k])
1492-
return result
1493-
1494-
def getCommitTemplate(self, prefs, rev, names):
1495-
return self._getCommitTemplate(prefs, rev, names)
1496-
1497-
def getFolderTemplate(self, prefs, names):
1498-
return self._getCommitTemplate(prefs, None, names)
1499-
1500-
def getRevision(self, prefs, name, rev):
1501-
vcs_bin = prefs.getString('svn_bin')
1502-
if rev in [ 'BASE', 'COMMITTED', 'PREV' ]:
1503-
return utils.popenRead(
1504-
self.root,
1505-
[
1506-
vcs_bin,
1507-
'cat',
1508-
'{}@{}'.format(utils.safeRelativePath(self.root, name, prefs, 'svn_cygwin'), rev)
1509-
],
1510-
prefs,
1511-
'svn_bash')
1512-
return utils.popenRead(
1513-
self.root,
1514-
[
1515-
vcs_bin,
1516-
'cat',
1517-
'{}/{}@{}'.format(
1518-
self._getURL(prefs),
1519-
utils.relpath(self.root, os.path.abspath(name)).replace(os.sep, '/'),
1520-
rev)
1521-
],
1522-
prefs,
1523-
'svn_bash')
1524-
15251289
def _get_svn_repo(path, prefs):
15261290
p = _find_parent_dir_with(path, '.svn')
15271291
if p:
1528-
return _Svn(p)
1292+
return Svn(p)
15291293

15301294
class _Svk(_Svn):
15311295
def __init__(self, root):

src/utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ def popenXArgsReadLines(dn, cmd, args, prefs, bash_pref):
166166
s, a = 0, []
167167
return ss
168168

169+
# escape special glob characters
170+
def globEscape(s):
171+
m = dict([ (c, f'[{c}]') for c in '[]?*' ])
172+
return ''.join([ m.get(c, c) for c in s ])
173+
169174
# use the program's location as a starting place to search for supporting files
170175
# such as icon and help documentation
171176
if hasattr(sys, 'frozen'):

0 commit comments

Comments
 (0)