eric6/Plugins/VcsPlugins/vcsSubversion/subversion.py

changeset 7775
4a1db75550bd
parent 7759
51aa6c6b66f7
child 7780
41420f82c0ac
equal deleted inserted replaced
7774:9eed155411f0 7775:4a1db75550bd
11 import os 11 import os
12 import re 12 import re
13 import shutil 13 import shutil
14 from urllib.parse import quote 14 from urllib.parse import quote
15 15
16 from PyQt5.QtCore import pyqtSignal, QProcess, QRegExp, QCoreApplication 16 from PyQt5.QtCore import pyqtSignal, QProcess, QCoreApplication
17 from PyQt5.QtWidgets import QLineEdit, QDialog, QInputDialog, QApplication 17 from PyQt5.QtWidgets import QLineEdit, QDialog, QInputDialog, QApplication
18 18
19 from E5Gui.E5Application import e5App 19 from E5Gui.E5Application import e5App
20 from E5Gui import E5MessageBox 20 from E5Gui import E5MessageBox
21 21
97 self.blame = None 97 self.blame = None
98 self.repoBrowser = None 98 self.repoBrowser = None
99 self.logBrowser = None 99 self.logBrowser = None
100 100
101 # regular expression object for evaluation of the status output 101 # regular expression object for evaluation of the status output
102 self.rx_status1 = QRegExp( 102 self.rx_status1 = re.compile(
103 '(.{8})\\s+([0-9-]+)\\s+([0-9?]+)\\s+(\\S+)\\s+(.+)') 103 '(.{8})\\s+([0-9-]+)\\s+([0-9?]+)\\s+(\\S+)\\s+(.+)')
104 self.rx_status2 = QRegExp('(.{8})\\s+(.+)\\s*') 104 self.rx_status2 = re.compile('(.{8})\\s+(.+)\\s*')
105 self.statusCache = {} 105 self.statusCache = {}
106 106
107 self.__commitData = {} 107 self.__commitData = {}
108 self.__commitDialog = None 108 self.__commitDialog = None
109 109
845 @param project reference to the project object 845 @param project reference to the project object
846 @param target new name of the file/directory (string) 846 @param target new name of the file/directory (string)
847 @param noDialog flag indicating quiet operations 847 @param noDialog flag indicating quiet operations
848 @return flag indicating successfull operation (boolean) 848 @return flag indicating successfull operation (boolean)
849 """ 849 """
850 rx_prot = QRegExp('(file:|svn:|svn+ssh:|http:|https:).+') 850 rx_prot = re.compile('(file:|svn:|svn+ssh:|http:|https:).+')
851 opts = self.options['global'][:] 851 opts = self.options['global'][:]
852 force = '--force' in opts 852 force = '--force' in opts
853 if force: 853 if force:
854 del opts[opts.index('--force')] 854 del opts[opts.index('--force')]
855 855
866 if accepted: 866 if accepted:
867 target, force = dlg.getData() 867 target, force = dlg.getData()
868 if not target: 868 if not target:
869 return False 869 return False
870 870
871 if not rx_prot.exactMatch(target): 871 if rx_prot.fullmatch(target) is None:
872 isDir = os.path.isdir(name) 872 isDir = os.path.isdir(name)
873 else: 873 else:
874 isDir = False 874 isDir = False
875 875
876 if accepted: 876 if accepted:
877 args = [] 877 args = []
878 args.append('move') 878 args.append('move')
879 self.addArguments(args, opts) 879 self.addArguments(args, opts)
880 if force: 880 if force:
881 args.append('--force') 881 args.append('--force')
882 if rx_prot.exactMatch(target): 882 if rx_prot.fullmatch(target) is not None:
883 args.append('--message') 883 args.append('--message')
884 args.append('Moving {0} to {1}'.format(name, target)) 884 args.append('Moving {0} to {1}'.format(name, target))
885 target = self.__svnURL(target) 885 target = self.__svnURL(target)
886 args.append(name) 886 args.append(name)
887 args.append(target) 887 args.append(target)
893 .format(name)) 893 .format(name))
894 res = dia.startProcess(args) 894 res = dia.startProcess(args)
895 if res: 895 if res:
896 dia.exec() 896 dia.exec()
897 res = dia.normalExit() 897 res = dia.normalExit()
898 if res and not rx_prot.exactMatch(target): 898 if res and rx_prot.fullmatch(target) is None:
899 if target.startswith(project.getProjectPath()): 899 if target.startswith(project.getProjectPath()):
900 if isDir: 900 if isDir:
901 project.moveDirectory(name, target) 901 project.moveDirectory(name, target)
902 else: 902 else:
903 project.renameFileInPdata(name, target) 903 project.renameFileInPdata(name, target)
990 self.allTagsBranchesList.insert(0, tag) 990 self.allTagsBranchesList.insert(0, tag)
991 else: 991 else:
992 return 992 return
993 993
994 if self.otherData["standardLayout"]: 994 if self.otherData["standardLayout"]:
995 rx_base = QRegExp('(.+)/(trunk|tags|branches).*') 995 rx_base = re.compile('(.+)/(trunk|tags|branches).*')
996 if not rx_base.exactMatch(reposURL): 996 match = rx_base.fullmatch(reposURL)
997 if match is None:
997 E5MessageBox.critical( 998 E5MessageBox.critical(
998 self.__ui, 999 self.__ui,
999 self.tr("Subversion Error"), 1000 self.tr("Subversion Error"),
1000 self.tr( 1001 self.tr(
1001 """The URL of the project repository has an""" 1002 """The URL of the project repository has an"""
1002 """ invalid format. The tag operation will""" 1003 """ invalid format. The tag operation will"""
1003 """ be aborted""")) 1004 """ be aborted"""))
1004 return 1005 return
1005 1006
1006 reposRoot = rx_base.cap(1) 1007 reposRoot = match.group(1)
1007 if tagOp in [1, 4]: 1008 if tagOp in [1, 4]:
1008 url = '{0}/tags/{1}'.format(reposRoot, quote(tag)) 1009 url = '{0}/tags/{1}'.format(reposRoot, quote(tag))
1009 elif tagOp in [2, 8]: 1010 elif tagOp in [2, 8]:
1010 url = '{0}/branches/{1}'.format(reposRoot, quote(tag)) 1011 url = '{0}/branches/{1}'.format(reposRoot, quote(tag))
1011 else: 1012 else:
1112 self.allTagsBranchesList.insert(0, tag) 1113 self.allTagsBranchesList.insert(0, tag)
1113 else: 1114 else:
1114 return False 1115 return False
1115 1116
1116 if self.otherData["standardLayout"]: 1117 if self.otherData["standardLayout"]:
1117 rx_base = QRegExp('(.+)/(trunk|tags|branches).*') 1118 rx_base = re.compile('(.+)/(trunk|tags|branches).*')
1118 if not rx_base.exactMatch(reposURL): 1119 match = rx_base.fullmatch(reposURL)
1120 if match is None:
1119 E5MessageBox.critical( 1121 E5MessageBox.critical(
1120 self.__ui, 1122 self.__ui,
1121 self.tr("Subversion Error"), 1123 self.tr("Subversion Error"),
1122 self.tr( 1124 self.tr(
1123 """The URL of the project repository has an""" 1125 """The URL of the project repository has an"""
1124 """ invalid format. The switch operation will""" 1126 """ invalid format. The switch operation will"""
1125 """ be aborted""")) 1127 """ be aborted"""))
1126 return False 1128 return False
1127 1129
1128 reposRoot = rx_base.cap(1) 1130 reposRoot = match.group(1)
1129 tn = tag 1131 tn = tag
1130 if tagType == 1: 1132 if tagType == 1:
1131 url = '{0}/tags/{1}'.format(reposRoot, quote(tag)) 1133 url = '{0}/tags/{1}'.format(reposRoot, quote(tag))
1132 elif tagType == 2: 1134 elif tagType == 2:
1133 url = '{0}/branches/{1}'.format(reposRoot, quote(tag)) 1135 url = '{0}/branches/{1}'.format(reposRoot, quote(tag))
1182 self.mergeList[0].insert(0, urlrev1) 1184 self.mergeList[0].insert(0, urlrev1)
1183 if urlrev2 in self.mergeList[1]: 1185 if urlrev2 in self.mergeList[1]:
1184 self.mergeList[1].remove(urlrev2) 1186 self.mergeList[1].remove(urlrev2)
1185 self.mergeList[1].insert(0, urlrev2) 1187 self.mergeList[1].insert(0, urlrev2)
1186 1188
1187 rx_rev = QRegExp('\\d+|HEAD') 1189 rx_rev = re.compile('\\d+|HEAD')
1188 1190
1189 args = [] 1191 args = []
1190 args.append('merge') 1192 args.append('merge')
1191 self.addArguments(args, opts) 1193 self.addArguments(args, opts)
1192 if self.version >= (1, 5, 0): 1194 if self.version >= (1, 5, 0):
1193 args.append('--accept') 1195 args.append('--accept')
1194 args.append('postpone') 1196 args.append('postpone')
1195 if force: 1197 if force:
1196 args.append('--force') 1198 args.append('--force')
1197 if rx_rev.exactMatch(urlrev1): 1199 if rx_rev.fullmatch(urlrev1) is not None:
1198 args.append('-r') 1200 args.append('-r')
1199 args.append('{0}:{1}'.format(urlrev1, urlrev2)) 1201 args.append('{0}:{1}'.format(urlrev1, urlrev2))
1200 if not target: 1202 if not target:
1201 args.append(name) 1203 args.append(name)
1202 else: 1204 else:
1352 finished = process.waitForFinished(30000) 1354 finished = process.waitForFinished(30000)
1353 if finished and process.exitCode() == 0: 1355 if finished and process.exitCode() == 0:
1354 output = str(process.readAllStandardOutput(), ioEncoding, 1356 output = str(process.readAllStandardOutput(), ioEncoding,
1355 'replace') 1357 'replace')
1356 for line in output.splitlines(): 1358 for line in output.splitlines():
1357 if self.rx_status1.exactMatch(line): 1359 match = self.rx_status1.fullmatch(line)
1358 flags = str(self.rx_status1.cap(1)) 1360 if match is not None:
1359 path = self.rx_status1.cap(5).strip() 1361 flags = self.rx_status1.group(1)
1360 elif self.rx_status2.exactMatch(line): 1362 path = self.rx_status1.group(5).strip()
1361 flags = str(self.rx_status2.cap(1))
1362 path = self.rx_status2.cap(2).strip()
1363 else: 1363 else:
1364 continue 1364 match = self.rx_status2.fullmatch(line)
1365 if match is not None:
1366 flags = self.rx_status2.group(1)
1367 path = self.rx_status2.group(2).strip()
1368 else:
1369 continue
1365 name = os.path.normcase(path) 1370 name = os.path.normcase(path)
1366 if flags[0] not in "?I": 1371 if flags[0] not in "?I":
1367 if name in names: 1372 if name in names:
1368 names[name] = self.canBeCommitted 1373 names[name] = self.canBeCommitted
1369 self.statusCache[name] = self.canBeCommitted 1374 self.statusCache[name] = self.canBeCommitted
1418 finished = process.waitForFinished(30000) 1423 finished = process.waitForFinished(30000)
1419 if finished and process.exitCode() == 0: 1424 if finished and process.exitCode() == 0:
1420 output = str(process.readAllStandardOutput(), ioEncoding, 1425 output = str(process.readAllStandardOutput(), ioEncoding,
1421 'replace') 1426 'replace')
1422 for line in output.splitlines(): 1427 for line in output.splitlines():
1423 if self.rx_status1.exactMatch(line): 1428 match = self.rx_status1.fullmatch(line)
1424 flags = self.rx_status1.cap(1) 1429 if match is not None:
1425 path = self.rx_status1.cap(5).strip() 1430 flags = self.rx_status1.group(1)
1426 elif self.rx_status2.exactMatch(line): 1431 path = self.rx_status1.group(5).strip()
1427 flags = self.rx_status2.cap(1)
1428 path = self.rx_status2.cap(2).strip()
1429 else: 1432 else:
1430 continue 1433 match = self.rx_status2.fullmatch(line)
1434 if match is not None:
1435 flags = self.rx_status2.group(1)
1436 path = self.rx_status2.group(2).strip()
1437 else:
1438 continue
1431 name = os.path.normcase(path) 1439 name = os.path.normcase(path)
1432 if flags[0] not in "?I": 1440 if flags[0] not in "?I":
1433 if name in names: 1441 if name in names:
1434 names[name] = self.canBeCommitted 1442 names[name] = self.canBeCommitted
1435 self.statusCache[name] = self.canBeCommitted 1443 self.statusCache[name] = self.canBeCommitted
1695 @param name file/directory name to be copied (string) 1703 @param name file/directory name to be copied (string)
1696 @param project reference to the project object 1704 @param project reference to the project object
1697 @return flag indicating successfull operation (boolean) 1705 @return flag indicating successfull operation (boolean)
1698 """ 1706 """
1699 from .SvnCopyDialog import SvnCopyDialog 1707 from .SvnCopyDialog import SvnCopyDialog
1700 rx_prot = QRegExp('(file:|svn:|svn+ssh:|http:|https:).+') 1708 rx_prot = re.compile('(file:|svn:|svn+ssh:|http:|https:).+')
1701 dlg = SvnCopyDialog(name) 1709 dlg = SvnCopyDialog(name)
1702 res = False 1710 res = False
1703 if dlg.exec() == QDialog.Accepted: 1711 if dlg.exec() == QDialog.Accepted:
1704 target, force = dlg.getData() 1712 target, force = dlg.getData()
1705 1713
1706 args = [] 1714 args = []
1707 args.append('copy') 1715 args.append('copy')
1708 self.addArguments(args, self.options['global']) 1716 self.addArguments(args, self.options['global'])
1709 if rx_prot.exactMatch(target): 1717 match = rx_prot.fullmatch(target)
1718 if match is not None:
1710 args.append('--message') 1719 args.append('--message')
1711 args.append('Copying {0} to {1}'.format(name, target)) 1720 args.append('Copying {0} to {1}'.format(name, target))
1712 target = self.__svnURL(target) 1721 target = self.__svnURL(target)
1713 args.append(name) 1722 args.append(name)
1714 args.append(target) 1723 args.append(target)
1719 if res: 1728 if res:
1720 dia.exec() 1729 dia.exec()
1721 res = dia.normalExit() 1730 res = dia.normalExit()
1722 if ( 1731 if (
1723 res and 1732 res and
1724 not rx_prot.exactMatch(target) and 1733 match is None and
1725 target.startswith(project.getProjectPath()) 1734 target.startswith(project.getProjectPath())
1726 ): 1735 ):
1727 if os.path.isdir(name): 1736 if os.path.isdir(name):
1728 project.copyDirectory(name, target) 1737 project.copyDirectory(name, target)
1729 else: 1738 else:
2260 Public method to get a list of all defined change lists. 2269 Public method to get a list of all defined change lists.
2261 2270
2262 @return list of defined change list names (list of strings) 2271 @return list of defined change list names (list of strings)
2263 """ 2272 """
2264 changelists = [] 2273 changelists = []
2265 rx_changelist = QRegExp('--- \\S+ .([\\w\\s]+).:\\s*') 2274 rx_changelist = re.compile('--- \\S+ .([\\w\\s]+).:\\s*')
2266 # three dashes, Changelist (translated), quote, 2275 # three dashes, Changelist (translated), quote,
2267 # changelist name, quote, : 2276 # changelist name, quote, :
2268 2277
2269 args = [] 2278 args = []
2270 args.append("status") 2279 args.append("status")
2282 output = str(process.readAllStandardOutput(), 2291 output = str(process.readAllStandardOutput(),
2283 Preferences.getSystem("IOEncoding"), 2292 Preferences.getSystem("IOEncoding"),
2284 'replace') 2293 'replace')
2285 if output: 2294 if output:
2286 for line in output.splitlines(): 2295 for line in output.splitlines():
2287 if rx_changelist.exactMatch(line): 2296 match = rx_changelist.fullmatch(line)
2288 changelist = rx_changelist.cap(1) 2297 if match is not None:
2298 changelist = match.group(1)
2289 if changelist not in changelists: 2299 if changelist not in changelists:
2290 changelists.append(changelist) 2300 changelists.append(changelist)
2291 2301
2292 return changelists 2302 return changelists
2293 2303

eric ide

mercurial