12 import shutil |
12 import shutil |
13 import time |
13 import time |
14 from urllib.parse import quote |
14 from urllib.parse import quote |
15 |
15 |
16 from PyQt5.QtCore import ( |
16 from PyQt5.QtCore import ( |
17 Qt, QMutexLocker, pyqtSignal, QRegExp, QDateTime, QCoreApplication |
17 pyqtSignal, Qt, QRegExp, QDateTime, QCoreApplication |
18 ) |
18 ) |
19 from PyQt5.QtWidgets import QLineEdit, QDialog, QInputDialog, QApplication |
19 from PyQt5.QtWidgets import QLineEdit, QDialog, QInputDialog, QApplication |
20 |
20 |
21 from E5Gui.E5Application import e5App |
21 from E5Gui.E5Application import e5App |
22 from E5Gui import E5MessageBox |
22 from E5Gui import E5MessageBox |
|
23 |
|
24 from E5Utilities.E5MutexLocker import E5MutexLocker |
23 |
25 |
24 from VCS.VersionControl import VersionControl |
26 from VCS.VersionControl import VersionControl |
25 |
27 |
26 import pysvn |
28 import pysvn |
27 |
29 |
299 except OSError: |
301 except OSError: |
300 if os.path.isdir(tmpDir): |
302 if os.path.isdir(tmpDir): |
301 shutil.rmtree(tmpDir, True) |
303 shutil.rmtree(tmpDir, True) |
302 return False, False |
304 return False, False |
303 |
305 |
304 locker = QMutexLocker(self.vcsExecutionMutex) |
|
305 cwd = os.getcwd() |
306 cwd = os.getcwd() |
306 os.chdir(os.path.join(tmpDir, project)) |
307 os.chdir(os.path.join(tmpDir, project)) |
307 opts = self.options['global'] |
308 opts = self.options['global'] |
308 recurse = "--non-recursive" not in opts |
309 recurse = "--non-recursive" not in opts |
309 url = self.__svnURL(vcsDir) |
310 url = self.__svnURL(vcsDir) |
314 "import{0} --message {1} .".format( |
315 "import{0} --message {1} .".format( |
315 (not recurse) and " --non-recursive" or "", msg), |
316 (not recurse) and " --non-recursive" or "", msg), |
316 client) |
317 client) |
317 QApplication.processEvents() |
318 QApplication.processEvents() |
318 try: |
319 try: |
319 rev = client.import_(".", url, msg, recurse, ignore=True) |
320 with E5MutexLocker(self.vcsExecutionMutex): |
|
321 rev = client.import_(".", url, msg, recurse, ignore=True) |
320 status = True |
322 status = True |
321 except pysvn.ClientError as e: |
323 except pysvn.ClientError as e: |
322 status = False |
324 status = False |
323 rev = None |
325 rev = None |
324 if not noDialog: |
326 if not noDialog: |
325 dlg.showError(e.args[0]) |
327 dlg.showError(e.args[0]) |
326 locker.unlock() |
|
327 if not noDialog: |
328 if not noDialog: |
328 rev and dlg.showMessage(self.tr("Imported revision {0}.\n") |
329 rev and dlg.showMessage(self.tr("Imported revision {0}.\n") |
329 .format(rev.number)) |
330 .format(rev.number)) |
330 dlg.finish() |
331 dlg.finish() |
331 dlg.exec() |
332 dlg.exec() |
389 "checkout{0} {1} {2}".format( |
390 "checkout{0} {1} {2}".format( |
390 (not recurse) and " --non-recursive" or "", |
391 (not recurse) and " --non-recursive" or "", |
391 url, projectDir), |
392 url, projectDir), |
392 client) |
393 client) |
393 QApplication.processEvents() |
394 QApplication.processEvents() |
394 locker = QMutexLocker(self.vcsExecutionMutex) |
|
395 try: |
395 try: |
396 client.checkout(url, projectDir, recurse) |
396 with E5MutexLocker(self.vcsExecutionMutex): |
|
397 client.checkout(url, projectDir, recurse) |
397 status = True |
398 status = True |
398 except pysvn.ClientError as e: |
399 except pysvn.ClientError as e: |
399 status = False |
400 status = False |
400 if not noDialog: |
401 if not noDialog: |
401 dlg.showError(e.args[0]) |
402 dlg.showError(e.args[0]) |
402 locker.unlock() |
|
403 if not noDialog: |
403 if not noDialog: |
404 dlg.finish() |
404 dlg.finish() |
405 dlg.exec() |
405 dlg.exec() |
406 return status |
406 return status |
407 |
407 |
455 "export --force{0} {1} {2}".format( |
455 "export --force{0} {1} {2}".format( |
456 (not recurse) and " --non-recursive" or "", |
456 (not recurse) and " --non-recursive" or "", |
457 url, projectDir), |
457 url, projectDir), |
458 client) |
458 client) |
459 QApplication.processEvents() |
459 QApplication.processEvents() |
460 locker = QMutexLocker(self.vcsExecutionMutex) |
|
461 try: |
460 try: |
462 client.export(url, projectDir, force=True, recurse=recurse) |
461 with E5MutexLocker(self.vcsExecutionMutex): |
|
462 client.export(url, projectDir, force=True, recurse=recurse) |
463 status = True |
463 status = True |
464 except pysvn.ClientError as e: |
464 except pysvn.ClientError as e: |
465 status = False |
465 status = False |
466 dlg.showError(e.args[0]) |
466 dlg.showError(e.args[0]) |
467 locker.unlock() |
|
468 dlg.finish() |
467 dlg.finish() |
469 dlg.exec() |
468 dlg.exec() |
470 return status |
469 return status |
471 |
470 |
472 def vcsCommit(self, name, message, noDialog=False): |
471 def vcsCommit(self, name, message, noDialog=False): |
565 self.svnGetReposName(dname).startswith('http') or |
564 self.svnGetReposName(dname).startswith('http') or |
566 self.svnGetReposName(dname).startswith('svn') |
565 self.svnGetReposName(dname).startswith('svn') |
567 ): |
566 ): |
568 noDialog = False |
567 noDialog = False |
569 |
568 |
570 locker = QMutexLocker(self.vcsExecutionMutex) |
|
571 cwd = os.getcwd() |
569 cwd = os.getcwd() |
572 os.chdir(dname) |
570 os.chdir(dname) |
573 opts = self.options['global'] + self.options['commit'] |
571 opts = self.options['global'] + self.options['commit'] |
574 recurse = "--non-recursive" not in opts |
572 recurse = "--non-recursive" not in opts |
575 keeplocks = "--keep-locks" in opts |
573 keeplocks = "--keep-locks" in opts |
585 " --changelist ".join([""] + changelists) or "", |
583 " --changelist ".join([""] + changelists) or "", |
586 msg, " ".join(fnames)), |
584 msg, " ".join(fnames)), |
587 client) |
585 client) |
588 QApplication.processEvents() |
586 QApplication.processEvents() |
589 try: |
587 try: |
590 if changelists: |
588 with E5MutexLocker(self.vcsExecutionMutex): |
591 rev = client.checkin(fnames, msg, |
589 if changelists: |
592 recurse=recurse, keep_locks=keeplocks, |
590 rev = client.checkin(fnames, msg, |
593 keep_changelist=keepChangelists, |
591 recurse=recurse, keep_locks=keeplocks, |
594 changelists=changelists) |
592 keep_changelist=keepChangelists, |
595 else: |
593 changelists=changelists) |
596 rev = client.checkin(fnames, msg, |
594 else: |
597 recurse=recurse, keep_locks=keeplocks) |
595 rev = client.checkin(fnames, msg, |
|
596 recurse=recurse, keep_locks=keeplocks) |
598 except pysvn.ClientError as e: |
597 except pysvn.ClientError as e: |
599 rev = None |
598 rev = None |
600 if not noDialog: |
599 if not noDialog: |
601 dlg.showError(e.args[0]) |
600 dlg.showError(e.args[0]) |
602 locker.unlock() |
|
603 if not noDialog: |
601 if not noDialog: |
604 rev and dlg.showMessage(self.tr("Committed revision {0}.") |
602 rev and dlg.showMessage(self.tr("Committed revision {0}.") |
605 .format(rev.number)) |
603 .format(rev.number)) |
606 dlg.finish() |
604 dlg.finish() |
607 dlg.exec() |
605 dlg.exec() |
624 dname, fnames = self.splitPathList(name) |
622 dname, fnames = self.splitPathList(name) |
625 else: |
623 else: |
626 dname, fname = self.splitPath(name) |
624 dname, fname = self.splitPath(name) |
627 fnames = [fname] |
625 fnames = [fname] |
628 |
626 |
629 locker = QMutexLocker(self.vcsExecutionMutex) |
|
630 cwd = os.getcwd() |
627 cwd = os.getcwd() |
631 os.chdir(dname) |
628 os.chdir(dname) |
632 opts = self.options['global'] + self.options['update'] |
629 opts = self.options['global'] + self.options['update'] |
633 recurse = "--non-recursive" not in opts |
630 recurse = "--non-recursive" not in opts |
634 client = self.getClient() |
631 client = self.getClient() |
639 (not recurse) and " --non-recursive" or "", |
636 (not recurse) and " --non-recursive" or "", |
640 " ".join(fnames)), |
637 " ".join(fnames)), |
641 client) |
638 client) |
642 QApplication.processEvents() |
639 QApplication.processEvents() |
643 try: |
640 try: |
644 client.update(fnames, recurse) |
641 with E5MutexLocker(self.vcsExecutionMutex): |
|
642 client.update(fnames, recurse) |
645 except pysvn.ClientError as e: |
643 except pysvn.ClientError as e: |
646 dlg.showError(e.args[0]) |
644 dlg.showError(e.args[0]) |
647 locker.unlock() |
|
648 if not noDialog: |
645 if not noDialog: |
649 dlg.finish() |
646 dlg.finish() |
650 dlg.exec() |
647 dlg.exec() |
651 res = dlg.hasAddOrDelete() |
648 res = dlg.hasAddOrDelete() |
652 else: |
649 else: |
752 noignore and " --no-ignore" or "", |
748 noignore and " --no-ignore" or "", |
753 " ".join(names)), |
749 " ".join(names)), |
754 client) |
750 client) |
755 QApplication.processEvents() |
751 QApplication.processEvents() |
756 try: |
752 try: |
757 client.add(names, recurse=recurse, force=force, |
753 with E5MutexLocker(self.vcsExecutionMutex): |
758 ignore=not noignore) |
754 client.add(names, recurse=recurse, force=force, |
|
755 ignore=not noignore) |
759 except pysvn.ClientError as e: |
756 except pysvn.ClientError as e: |
760 if not noDialog: |
757 if not noDialog: |
761 dlg.showError(e.args[0]) |
758 dlg.showError(e.args[0]) |
762 locker.unlock() |
|
763 if not noDialog: |
759 if not noDialog: |
764 dlg.finish() |
760 dlg.finish() |
765 dlg.exec() |
761 dlg.exec() |
766 os.chdir(cwd) |
762 os.chdir(cwd) |
767 |
763 |
861 ignore and " --ignore" or "", |
856 ignore and " --ignore" or "", |
862 " ".join(names)), |
857 " ".join(names)), |
863 client) |
858 client) |
864 QApplication.processEvents() |
859 QApplication.processEvents() |
865 try: |
860 try: |
866 client.add(names, recurse=recurse, force=force, ignore=ignore) |
861 with E5MutexLocker(self.vcsExecutionMutex): |
|
862 client.add(names, recurse=recurse, force=force, ignore=ignore) |
867 except pysvn.ClientError as e: |
863 except pysvn.ClientError as e: |
868 dlg.showError(e.args[0]) |
864 dlg.showError(e.args[0]) |
869 locker.unlock() |
|
870 dlg.finish() |
865 dlg.finish() |
871 dlg.exec() |
866 dlg.exec() |
872 os.chdir(cwd) |
867 os.chdir(cwd) |
873 |
868 |
874 def vcsRemove(self, name, project=False, noDialog=False): |
869 def vcsRemove(self, name, project=False, noDialog=False): |
897 "remove{0} {1}".format( |
892 "remove{0} {1}".format( |
898 force and " --force" or "", |
893 force and " --force" or "", |
899 " ".join(name)), |
894 " ".join(name)), |
900 client) |
895 client) |
901 QApplication.processEvents() |
896 QApplication.processEvents() |
902 locker = QMutexLocker(self.vcsExecutionMutex) |
|
903 try: |
897 try: |
904 client.remove(name, force=force) |
898 with E5MutexLocker(self.vcsExecutionMutex): |
|
899 client.remove(name, force=force) |
905 res = True |
900 res = True |
906 except pysvn.ClientError as e: |
901 except pysvn.ClientError as e: |
907 res = False |
902 res = False |
908 if not noDialog: |
903 if not noDialog: |
909 dlg.showError(e.args[0]) |
904 dlg.showError(e.args[0]) |
910 locker.unlock() |
|
911 if not noDialog: |
905 if not noDialog: |
912 dlg.finish() |
906 dlg.finish() |
913 dlg.exec() |
907 dlg.exec() |
914 |
908 |
915 return res |
909 return res |
962 force and " --force" or "", |
956 force and " --force" or "", |
963 log and (" --message {0}".format(log)) or "", |
957 log and (" --message {0}".format(log)) or "", |
964 name, target), |
958 name, target), |
965 client, log=log) |
959 client, log=log) |
966 QApplication.processEvents() |
960 QApplication.processEvents() |
967 locker = QMutexLocker(self.vcsExecutionMutex) |
|
968 try: |
961 try: |
969 client.move(name, target, force=force) |
962 with E5MutexLocker(self.vcsExecutionMutex): |
|
963 client.move(name, target, force=force) |
970 res = True |
964 res = True |
971 except pysvn.ClientError as e: |
965 except pysvn.ClientError as e: |
972 res = False |
966 res = False |
973 if not noDialog: |
967 if not noDialog: |
974 dlg.showError(e.args[0]) |
968 dlg.showError(e.args[0]) |
975 locker.unlock() |
|
976 if not noDialog: |
969 if not noDialog: |
977 dlg.finish() |
970 dlg.finish() |
978 dlg.exec() |
971 dlg.exec() |
979 if res and not rx_prot.exactMatch(target): |
972 if res and not rx_prot.exactMatch(target): |
980 if target.startswith(project.getProjectPath()): |
973 if target.startswith(project.getProjectPath()): |
1102 self.tr('Tagging {0} in the Subversion repository') |
1095 self.tr('Tagging {0} in the Subversion repository') |
1103 .format(name), |
1096 .format(name), |
1104 "copy --message {0} {1} {2}".format(log, reposURL, url), |
1097 "copy --message {0} {1} {2}".format(log, reposURL, url), |
1105 client, log=log) |
1098 client, log=log) |
1106 QApplication.processEvents() |
1099 QApplication.processEvents() |
1107 locker = QMutexLocker(self.vcsExecutionMutex) |
|
1108 try: |
1100 try: |
1109 rev = client.copy(reposURL, url) |
1101 with E5MutexLocker(self.vcsExecutionMutex): |
|
1102 rev = client.copy(reposURL, url) |
1110 except pysvn.ClientError as e: |
1103 except pysvn.ClientError as e: |
1111 dlg.showError(e.args[0]) |
1104 dlg.showError(e.args[0]) |
1112 locker.unlock() |
|
1113 else: |
1105 else: |
1114 log = 'Deleted tag <{0}>'.format(self.tagName) |
1106 log = 'Deleted tag <{0}>'.format(self.tagName) |
1115 dlg = SvnDialog( |
1107 dlg = SvnDialog( |
1116 self.tr('Tagging {0} in the Subversion repository') |
1108 self.tr('Tagging {0} in the Subversion repository') |
1117 .format(name), |
1109 .format(name), |
1118 "remove --message {0} {1}".format(log, url), |
1110 "remove --message {0} {1}".format(log, url), |
1119 client, log=log) |
1111 client, log=log) |
1120 QApplication.processEvents() |
1112 QApplication.processEvents() |
1121 locker = QMutexLocker(self.vcsExecutionMutex) |
|
1122 try: |
1113 try: |
1123 rev = client.remove(url) |
1114 with E5MutexLocker(self.vcsExecutionMutex): |
|
1115 rev = client.remove(url) |
1124 except pysvn.ClientError as e: |
1116 except pysvn.ClientError as e: |
1125 dlg.showError(e.args[0]) |
1117 dlg.showError(e.args[0]) |
1126 locker.unlock() |
|
1127 rev and dlg.showMessage( |
1118 rev and dlg.showMessage( |
1128 self.tr("Revision {0}.\n").format(rev.number)) |
1119 self.tr("Revision {0}.\n").format(rev.number)) |
1129 dlg.finish() |
1120 dlg.finish() |
1130 dlg.exec() |
1121 dlg.exec() |
1131 |
1122 |
1168 "revert {0} {1}".format( |
1159 "revert {0} {1}".format( |
1169 (not recurse) and " --non-recursive" or "", |
1160 (not recurse) and " --non-recursive" or "", |
1170 " ".join(name)), |
1161 " ".join(name)), |
1171 client) |
1162 client) |
1172 QApplication.processEvents() |
1163 QApplication.processEvents() |
1173 locker = QMutexLocker(self.vcsExecutionMutex) |
|
1174 try: |
1164 try: |
1175 client.revert(name, recurse) |
1165 with E5MutexLocker(self.vcsExecutionMutex): |
|
1166 client.revert(name, recurse) |
1176 except pysvn.ClientError as e: |
1167 except pysvn.ClientError as e: |
1177 dlg.showError(e.args[0]) |
1168 dlg.showError(e.args[0]) |
1178 locker.unlock() |
|
1179 dlg.finish() |
1169 dlg.finish() |
1180 dlg.exec() |
1170 dlg.exec() |
1181 self.checkVCSStatus() |
1171 self.checkVCSStatus() |
1182 |
1172 |
1183 def vcsSwitch(self, name): |
1173 def vcsSwitch(self, name): |
1244 client = self.getClient() |
1234 client = self.getClient() |
1245 dlg = SvnDialog(self.tr('Switching to {0}').format(tn), |
1235 dlg = SvnDialog(self.tr('Switching to {0}').format(tn), |
1246 "switch {0} {1}".format(url, name), |
1236 "switch {0} {1}".format(url, name), |
1247 client) |
1237 client) |
1248 QApplication.processEvents() |
1238 QApplication.processEvents() |
1249 locker = QMutexLocker(self.vcsExecutionMutex) |
|
1250 try: |
1239 try: |
1251 rev = client.switch(name, url) |
1240 with E5MutexLocker(self.vcsExecutionMutex): |
|
1241 rev = client.switch(name, url) |
1252 dlg.showMessage(self.tr("Revision {0}.\n").format(rev.number)) |
1242 dlg.showMessage(self.tr("Revision {0}.\n").format(rev.number)) |
1253 except pysvn.ClientError as e: |
1243 except pysvn.ClientError as e: |
1254 dlg.showError(e.args[0]) |
1244 dlg.showError(e.args[0]) |
1255 locker.unlock() |
|
1256 dlg.finish() |
1245 dlg.finish() |
1257 dlg.exec() |
1246 dlg.exec() |
1258 res = dlg.hasAddOrDelete() |
1247 res = dlg.hasAddOrDelete() |
1259 self.checkVCSStatus() |
1248 self.checkVCSStatus() |
1260 return res |
1249 return res |
1284 self.mergeList[1].remove(urlrev2) |
1273 self.mergeList[1].remove(urlrev2) |
1285 self.mergeList[1].insert(0, urlrev2) |
1274 self.mergeList[1].insert(0, urlrev2) |
1286 |
1275 |
1287 rx_rev = QRegExp('\\d+|HEAD|head') |
1276 rx_rev = QRegExp('\\d+|HEAD|head') |
1288 |
1277 |
1289 locker = QMutexLocker(self.vcsExecutionMutex) |
|
1290 cwd = os.getcwd() |
1278 cwd = os.getcwd() |
1291 os.chdir(dname) |
1279 os.chdir(dname) |
1292 recurse = "--non-recursive" not in opts |
1280 recurse = "--non-recursive" not in opts |
1293 if rx_rev.exactMatch(urlrev1): |
1281 if rx_rev.exactMatch(urlrev1): |
1294 if urlrev1 in ["HEAD", "head"]: |
1282 if urlrev1 in ["HEAD", "head"]: |
1353 "{0}{1}".format(url2, rev2 and ("@" + rev2) or ""), |
1341 "{0}{1}".format(url2, rev2 and ("@" + rev2) or ""), |
1354 fname), |
1342 fname), |
1355 client) |
1343 client) |
1356 QApplication.processEvents() |
1344 QApplication.processEvents() |
1357 try: |
1345 try: |
1358 client.merge(url1, revision1, url2, revision2, fname, |
1346 with E5MutexLocker(self.vcsExecutionMutex): |
1359 recurse=recurse, force=force) |
1347 client.merge(url1, revision1, url2, revision2, fname, |
|
1348 recurse=recurse, force=force) |
1360 except pysvn.ClientError as e: |
1349 except pysvn.ClientError as e: |
1361 dlg.showError(e.args[0]) |
1350 dlg.showError(e.args[0]) |
1362 locker.unlock() |
|
1363 dlg.finish() |
1351 dlg.finish() |
1364 dlg.exec() |
1352 dlg.exec() |
1365 os.chdir(cwd) |
1353 os.chdir(cwd) |
1366 |
1354 |
1367 def vcsRegisteredState(self, name): |
1355 def vcsRegisteredState(self, name): |
1494 client.callback_ssl_server_trust_prompt = ( |
1482 client.callback_ssl_server_trust_prompt = ( |
1495 mixin._clientSslServerTrustPromptCallback |
1483 mixin._clientSslServerTrustPromptCallback |
1496 ) |
1484 ) |
1497 |
1485 |
1498 try: |
1486 try: |
1499 locker = QMutexLocker(self.vcsExecutionMutex) |
1487 with E5MutexLocker(self.vcsExecutionMutex): |
1500 allFiles = client.status(dname, recurse=True, get_all=True, |
1488 allFiles = client.status(dname, recurse=True, get_all=True, |
1501 ignore=True, update=False) |
1489 ignore=True, update=False) |
1502 locker.unlock() |
|
1503 dirs = [x for x in names.keys() if os.path.isdir(x)] |
1490 dirs = [x for x in names.keys() if os.path.isdir(x)] |
1504 for file in allFiles: |
1491 for file in allFiles: |
1505 name = os.path.normcase(file.path) |
1492 name = os.path.normcase(file.path) |
1506 if self.__isVersioned(file): |
1493 if self.__isVersioned(file): |
1507 if name in names: |
1494 if name in names: |
1528 dirs.remove(d) |
1515 dirs.remove(d) |
1529 break |
1516 break |
1530 else: |
1517 else: |
1531 self.statusCache[name] = self.canBeAdded |
1518 self.statusCache[name] = self.canBeAdded |
1532 except pysvn.ClientError: |
1519 except pysvn.ClientError: |
1533 locker.unlock() # ignore pysvn errors |
1520 # ignore pysvn errors |
|
1521 pass |
1534 |
1522 |
1535 return names |
1523 return names |
1536 |
1524 |
1537 def __vcsAllRegisteredStates_wc(self, names, dname, shortcut=True): |
1525 def __vcsAllRegisteredStates_wc(self, names, dname, shortcut=True): |
1538 """ |
1526 """ |
1574 client.callback_ssl_server_trust_prompt = ( |
1562 client.callback_ssl_server_trust_prompt = ( |
1575 mixin._clientSslServerTrustPromptCallback |
1563 mixin._clientSslServerTrustPromptCallback |
1576 ) |
1564 ) |
1577 |
1565 |
1578 try: |
1566 try: |
1579 locker = QMutexLocker(self.vcsExecutionMutex) |
1567 with E5MutexLocker(self.vcsExecutionMutex): |
1580 allFiles = client.status(dname, recurse=True, get_all=True, |
1568 allFiles = client.status(dname, recurse=True, get_all=True, |
1581 ignore=True, update=False) |
1569 ignore=True, update=False) |
1582 locker.unlock() |
|
1583 for file in allFiles: |
1570 for file in allFiles: |
1584 name = os.path.normcase(file.path) |
1571 name = os.path.normcase(file.path) |
1585 if self.__isVersioned(file): |
1572 if self.__isVersioned(file): |
1586 if name in names: |
1573 if name in names: |
1587 names[name] = self.canBeCommitted |
1574 names[name] = self.canBeCommitted |
1588 self.statusCache[name] = self.canBeCommitted |
1575 self.statusCache[name] = self.canBeCommitted |
1589 else: |
1576 else: |
1590 self.statusCache[name] = self.canBeAdded |
1577 self.statusCache[name] = self.canBeAdded |
1591 except pysvn.ClientError: |
1578 except pysvn.ClientError: |
1592 locker.unlock() # ignore pysvn errors |
1579 # ignore pysvn errors |
|
1580 pass |
1593 |
1581 |
1594 return names |
1582 return names |
1595 |
1583 |
1596 def __isVersioned(self, status): |
1584 def __isVersioned(self, status): |
1597 """ |
1585 """ |
1650 client = self.getClient() |
1638 client = self.getClient() |
1651 dlg = SvnDialog(self.tr('Cleaning up {0}').format(name), |
1639 dlg = SvnDialog(self.tr('Cleaning up {0}').format(name), |
1652 "cleanup {0}".format(name), |
1640 "cleanup {0}".format(name), |
1653 client) |
1641 client) |
1654 QApplication.processEvents() |
1642 QApplication.processEvents() |
1655 locker = QMutexLocker(self.vcsExecutionMutex) |
|
1656 try: |
1643 try: |
1657 client.cleanup(name) |
1644 with E5MutexLocker(self.vcsExecutionMutex): |
|
1645 client.cleanup(name) |
1658 except pysvn.ClientError as e: |
1646 except pysvn.ClientError as e: |
1659 dlg.showError(e.args[0]) |
1647 dlg.showError(e.args[0]) |
1660 locker.unlock() |
|
1661 dlg.finish() |
1648 dlg.finish() |
1662 dlg.exec() |
1649 dlg.exec() |
1663 |
1650 |
1664 def vcsCommandLine(self, name): |
1651 def vcsCommandLine(self, name): |
1665 """ |
1652 """ |
1777 |
1764 |
1778 @param path local path to get the svn repository path for (string) |
1765 @param path local path to get the svn repository path for (string) |
1779 @return string with the repository path URL |
1766 @return string with the repository path URL |
1780 """ |
1767 """ |
1781 client = pysvn.Client() |
1768 client = pysvn.Client() |
1782 locker = QMutexLocker(self.vcsExecutionMutex) |
|
1783 try: |
1769 try: |
1784 entry = client.info(path) |
1770 with E5MutexLocker(self.vcsExecutionMutex): |
|
1771 entry = client.info(path) |
1785 url = entry.url |
1772 url = entry.url |
1786 except pysvn.ClientError: |
1773 except pysvn.ClientError: |
1787 url = "" |
1774 url = "" |
1788 locker.unlock() |
|
1789 return url |
1775 return url |
1790 |
1776 |
1791 def svnResolve(self, name): |
1777 def svnResolve(self, name): |
1792 """ |
1778 """ |
1793 Public method used to resolve conflicts of a file/directory. |
1779 Public method used to resolve conflicts of a file/directory. |
1798 dname, fnames = self.splitPathList(name) |
1784 dname, fnames = self.splitPathList(name) |
1799 else: |
1785 else: |
1800 dname, fname = self.splitPath(name) |
1786 dname, fname = self.splitPath(name) |
1801 fnames = [fname] |
1787 fnames = [fname] |
1802 |
1788 |
1803 locker = QMutexLocker(self.vcsExecutionMutex) |
|
1804 cwd = os.getcwd() |
1789 cwd = os.getcwd() |
1805 os.chdir(dname) |
1790 os.chdir(dname) |
1806 opts = self.options['global'] |
1791 opts = self.options['global'] |
1807 recurse = "--non-recursive" not in opts |
1792 recurse = "--non-recursive" not in opts |
1808 client = self.getClient() |
1793 client = self.getClient() |
1811 (not recurse) and " --non-recursive" or "", |
1796 (not recurse) and " --non-recursive" or "", |
1812 " ".join(fnames)), |
1797 " ".join(fnames)), |
1813 client) |
1798 client) |
1814 QApplication.processEvents() |
1799 QApplication.processEvents() |
1815 try: |
1800 try: |
1816 for name in fnames: |
1801 with E5MutexLocker(self.vcsExecutionMutex): |
1817 client.resolved(name, recurse=recurse) |
1802 for name in fnames: |
|
1803 client.resolved(name, recurse=recurse) |
1818 except pysvn.ClientError as e: |
1804 except pysvn.ClientError as e: |
1819 dlg.showError(e.args[0]) |
1805 dlg.showError(e.args[0]) |
1820 locker.unlock() |
|
1821 dlg.finish() |
1806 dlg.finish() |
1822 dlg.exec() |
1807 dlg.exec() |
1823 os.chdir(cwd) |
1808 os.chdir(cwd) |
1824 self.checkVCSStatus() |
1809 self.checkVCSStatus() |
1825 |
1810 |
1850 "copy{0} {1} {2}".format( |
1835 "copy{0} {1} {2}".format( |
1851 log and (" --message {0}".format(log)) or "", |
1836 log and (" --message {0}".format(log)) or "", |
1852 name, target), |
1837 name, target), |
1853 client, log=log) |
1838 client, log=log) |
1854 QApplication.processEvents() |
1839 QApplication.processEvents() |
1855 locker = QMutexLocker(self.vcsExecutionMutex) |
|
1856 try: |
1840 try: |
1857 client.copy(name, target) |
1841 with E5MutexLocker(self.vcsExecutionMutex): |
|
1842 client.copy(name, target) |
1858 res = True |
1843 res = True |
1859 except pysvn.ClientError as e: |
1844 except pysvn.ClientError as e: |
1860 res = False |
1845 res = False |
1861 dlg.showError(e.args[0]) |
1846 dlg.showError(e.args[0]) |
1862 locker.unlock() |
|
1863 dlg.finish() |
1847 dlg.finish() |
1864 dlg.exec() |
1848 dlg.exec() |
1865 if ( |
1849 if ( |
1866 res and |
1850 res and |
1867 not rx_prot.exactMatch(target) and |
1851 not rx_prot.exactMatch(target) and |
1911 dname, fnames = self.splitPathList(name) |
1895 dname, fnames = self.splitPathList(name) |
1912 else: |
1896 else: |
1913 dname, fname = self.splitPath(name) |
1897 dname, fname = self.splitPath(name) |
1914 fnames = [fname] |
1898 fnames = [fname] |
1915 |
1899 |
1916 locker = QMutexLocker(self.vcsExecutionMutex) |
|
1917 cwd = os.getcwd() |
1900 cwd = os.getcwd() |
1918 os.chdir(dname) |
1901 os.chdir(dname) |
1919 opts = self.options['global'] |
1902 opts = self.options['global'] |
1920 skipchecks = "--skip-checks" in opts |
1903 skipchecks = "--skip-checks" in opts |
1921 client = self.getClient() |
1904 client = self.getClient() |
1927 propName, propValue, |
1910 propName, propValue, |
1928 " ".join(fnames)), |
1911 " ".join(fnames)), |
1929 client) |
1912 client) |
1930 QApplication.processEvents() |
1913 QApplication.processEvents() |
1931 try: |
1914 try: |
1932 for name in fnames: |
1915 with E5MutexLocker(self.vcsExecutionMutex): |
1933 client.propset(propName, propValue, name, |
1916 for name in fnames: |
1934 recurse=recurse, skip_checks=skipchecks) |
1917 client.propset(propName, propValue, name, |
|
1918 recurse=recurse, skip_checks=skipchecks) |
1935 except pysvn.ClientError as e: |
1919 except pysvn.ClientError as e: |
1936 dlg.showError(e.args[0]) |
1920 dlg.showError(e.args[0]) |
1937 locker.unlock() |
|
1938 dlg.showMessage(self.tr("Property set.")) |
1921 dlg.showMessage(self.tr("Property set.")) |
1939 dlg.finish() |
1922 dlg.finish() |
1940 dlg.exec() |
1923 dlg.exec() |
1941 os.chdir(cwd) |
1924 os.chdir(cwd) |
1942 |
1925 |
1964 dname, fnames = self.splitPathList(name) |
1947 dname, fnames = self.splitPathList(name) |
1965 else: |
1948 else: |
1966 dname, fname = self.splitPath(name) |
1949 dname, fname = self.splitPath(name) |
1967 fnames = [fname] |
1950 fnames = [fname] |
1968 |
1951 |
1969 locker = QMutexLocker(self.vcsExecutionMutex) |
|
1970 cwd = os.getcwd() |
1952 cwd = os.getcwd() |
1971 os.chdir(dname) |
1953 os.chdir(dname) |
1972 opts = self.options['global'] |
1954 opts = self.options['global'] |
1973 skipchecks = "--skip-checks" in opts |
1955 skipchecks = "--skip-checks" in opts |
1974 client = self.getClient() |
1956 client = self.getClient() |
1979 skipchecks and " --skip-checks" or "", |
1961 skipchecks and " --skip-checks" or "", |
1980 propName, " ".join(fnames)), |
1962 propName, " ".join(fnames)), |
1981 client) |
1963 client) |
1982 QApplication.processEvents() |
1964 QApplication.processEvents() |
1983 try: |
1965 try: |
1984 for name in fnames: |
1966 with E5MutexLocker(self.vcsExecutionMutex): |
1985 client.propdel(propName, name, |
1967 for name in fnames: |
1986 recurse=recurse, skip_checks=skipchecks) |
1968 client.propdel(propName, name, |
|
1969 recurse=recurse, skip_checks=skipchecks) |
1987 except pysvn.ClientError as e: |
1970 except pysvn.ClientError as e: |
1988 dlg.showError(e.args[0]) |
1971 dlg.showError(e.args[0]) |
1989 locker.unlock() |
|
1990 dlg.showMessage(self.tr("Property deleted.")) |
1972 dlg.showMessage(self.tr("Property deleted.")) |
1991 dlg.finish() |
1973 dlg.finish() |
1992 dlg.exec() |
1974 dlg.exec() |
1993 os.chdir(cwd) |
1975 os.chdir(cwd) |
1994 |
1976 |
2272 dname, fnames = self.splitPathList(name) |
2254 dname, fnames = self.splitPathList(name) |
2273 else: |
2255 else: |
2274 dname, fname = self.splitPath(name) |
2256 dname, fname = self.splitPath(name) |
2275 fnames = [fname] |
2257 fnames = [fname] |
2276 |
2258 |
2277 locker = QMutexLocker(self.vcsExecutionMutex) |
|
2278 cwd = os.getcwd() |
2259 cwd = os.getcwd() |
2279 os.chdir(dname) |
2260 os.chdir(dname) |
2280 client = self.getClient() |
2261 client = self.getClient() |
2281 dlg = SvnDialog( |
2262 dlg = SvnDialog( |
2282 self.tr('Locking in the Subversion repository'), |
2263 self.tr('Locking in the Subversion repository'), |
2285 comment and (" --message {0}".format(comment)) or "", |
2266 comment and (" --message {0}".format(comment)) or "", |
2286 " ".join(fnames)), |
2267 " ".join(fnames)), |
2287 client, parent=parent) |
2268 client, parent=parent) |
2288 QApplication.processEvents() |
2269 QApplication.processEvents() |
2289 try: |
2270 try: |
2290 client.lock(fnames, comment, force=stealIt) |
2271 with E5MutexLocker(self.vcsExecutionMutex): |
|
2272 client.lock(fnames, comment, force=stealIt) |
2291 except pysvn.ClientError as e: |
2273 except pysvn.ClientError as e: |
2292 dlg.showError(e.args[0]) |
2274 dlg.showError(e.args[0]) |
2293 except AttributeError as e: |
2275 except AttributeError as e: |
2294 dlg.showError(str(e)) |
2276 dlg.showError(str(e)) |
2295 locker.unlock() |
|
2296 dlg.finish() |
2277 dlg.finish() |
2297 dlg.exec() |
2278 dlg.exec() |
2298 os.chdir(cwd) |
2279 os.chdir(cwd) |
2299 |
2280 |
2300 def svnUnlock(self, name, breakIt=False, parent=None): |
2281 def svnUnlock(self, name, breakIt=False, parent=None): |
2311 dname, fnames = self.splitPathList(name) |
2292 dname, fnames = self.splitPathList(name) |
2312 else: |
2293 else: |
2313 dname, fname = self.splitPath(name) |
2294 dname, fname = self.splitPath(name) |
2314 fnames = [fname] |
2295 fnames = [fname] |
2315 |
2296 |
2316 locker = QMutexLocker(self.vcsExecutionMutex) |
|
2317 cwd = os.getcwd() |
2297 cwd = os.getcwd() |
2318 os.chdir(dname) |
2298 os.chdir(dname) |
2319 client = self.getClient() |
2299 client = self.getClient() |
2320 dlg = SvnDialog( |
2300 dlg = SvnDialog( |
2321 self.tr('Unlocking in the Subversion repository'), |
2301 self.tr('Unlocking in the Subversion repository'), |
2322 "unlock{0} {1}".format(breakIt and " --force" or "", |
2302 "unlock{0} {1}".format(breakIt and " --force" or "", |
2323 " ".join(fnames)), |
2303 " ".join(fnames)), |
2324 client, parent=parent) |
2304 client, parent=parent) |
2325 QApplication.processEvents() |
2305 QApplication.processEvents() |
2326 try: |
2306 try: |
2327 client.unlock(fnames, force=breakIt) |
2307 with E5MutexLocker(self.vcsExecutionMutex): |
|
2308 client.unlock(fnames, force=breakIt) |
2328 except pysvn.ClientError as e: |
2309 except pysvn.ClientError as e: |
2329 dlg.showError(e.args[0]) |
2310 dlg.showError(e.args[0]) |
2330 except AttributeError as e: |
2311 except AttributeError as e: |
2331 dlg.showError(str(e)) |
2312 dlg.showError(str(e)) |
2332 locker.unlock() |
|
2333 dlg.finish() |
2313 dlg.finish() |
2334 dlg.exec() |
2314 dlg.exec() |
2335 os.chdir(cwd) |
2315 os.chdir(cwd) |
2336 |
2316 |
2337 def svnInfo(self, projectPath, name): |
2317 def svnInfo(self, projectPath, name): |
2363 msg = "relocate {0} {1} {2}".format(currUrl, newUrl, |
2343 msg = "relocate {0} {1} {2}".format(currUrl, newUrl, |
2364 projectPath) |
2344 projectPath) |
2365 client = self.getClient() |
2345 client = self.getClient() |
2366 dlg = SvnDialog(self.tr('Relocating'), msg, client) |
2346 dlg = SvnDialog(self.tr('Relocating'), msg, client) |
2367 QApplication.processEvents() |
2347 QApplication.processEvents() |
2368 locker = QMutexLocker(self.vcsExecutionMutex) |
|
2369 try: |
2348 try: |
2370 if inside: |
2349 with E5MutexLocker(self.vcsExecutionMutex): |
2371 client.switch(projectPath, newUrl) |
2350 if inside: |
2372 else: |
2351 client.switch(projectPath, newUrl) |
2373 client.relocate(currUrl, newUrl, projectPath, recurse=True) |
2352 else: |
|
2353 client.relocate(currUrl, newUrl, projectPath, |
|
2354 recurse=True) |
2374 except pysvn.ClientError as e: |
2355 except pysvn.ClientError as e: |
2375 dlg.showError(e.args[0]) |
2356 dlg.showError(e.args[0]) |
2376 locker.unlock() |
|
2377 dlg.finish() |
2357 dlg.finish() |
2378 dlg.exec() |
2358 dlg.exec() |
2379 |
2359 |
2380 def svnRepoBrowser(self, projectPath=None): |
2360 def svnRepoBrowser(self, projectPath=None): |
2381 """ |
2361 """ |
2419 dlg = SvnDialog( |
2399 dlg = SvnDialog( |
2420 self.tr('Remove from changelist'), |
2400 self.tr('Remove from changelist'), |
2421 "changelist --remove {0}".format(" ".join(names)), |
2401 "changelist --remove {0}".format(" ".join(names)), |
2422 client) |
2402 client) |
2423 QApplication.processEvents() |
2403 QApplication.processEvents() |
2424 locker = QMutexLocker(self.vcsExecutionMutex) |
|
2425 try: |
2404 try: |
2426 for name in names: |
2405 with E5MutexLocker(self.vcsExecutionMutex): |
2427 client.remove_from_changelists(name) |
2406 for name in names: |
|
2407 client.remove_from_changelists(name) |
2428 except pysvn.ClientError as e: |
2408 except pysvn.ClientError as e: |
2429 dlg.showError(e.args[0]) |
2409 dlg.showError(e.args[0]) |
2430 locker.unlock() |
|
2431 dlg.finish() |
2410 dlg.finish() |
2432 dlg.exec() |
2411 dlg.exec() |
2433 |
2412 |
2434 def svnAddToChangelist(self, names): |
2413 def svnAddToChangelist(self, names): |
2435 """ |
2414 """ |
2456 dlg = SvnDialog( |
2435 dlg = SvnDialog( |
2457 self.tr('Add to changelist'), |
2436 self.tr('Add to changelist'), |
2458 "changelist {0}".format(" ".join(names)), |
2437 "changelist {0}".format(" ".join(names)), |
2459 client) |
2438 client) |
2460 QApplication.processEvents() |
2439 QApplication.processEvents() |
2461 locker = QMutexLocker(self.vcsExecutionMutex) |
|
2462 try: |
2440 try: |
2463 for name in names: |
2441 with E5MutexLocker(self.vcsExecutionMutex): |
2464 client.add_to_changelist(name, clname, |
2442 for name in names: |
2465 depth=pysvn.depth.infinity) |
2443 client.add_to_changelist( |
|
2444 name, clname, depth=pysvn.depth.infinity) |
2466 except pysvn.ClientError as e: |
2445 except pysvn.ClientError as e: |
2467 dlg.showError(e.args[0]) |
2446 dlg.showError(e.args[0]) |
2468 locker.unlock() |
|
2469 dlg.finish() |
2447 dlg.finish() |
2470 dlg.exec() |
2448 dlg.exec() |
2471 |
2449 |
2472 def svnShowChangelists(self, path): |
2450 def svnShowChangelists(self, path): |
2473 """ |
2451 """ |
2489 """ |
2467 """ |
2490 changelists = [] |
2468 changelists = [] |
2491 client = self.getClient() |
2469 client = self.getClient() |
2492 if hasattr(client, 'get_changelist'): |
2470 if hasattr(client, 'get_changelist'): |
2493 ppath = e5App().getObject("Project").getProjectPath() |
2471 ppath = e5App().getObject("Project").getProjectPath() |
2494 locker = QMutexLocker(self.vcsExecutionMutex) |
|
2495 try: |
2472 try: |
2496 entries = client.get_changelist(ppath, |
2473 with E5MutexLocker(self.vcsExecutionMutex): |
2497 depth=pysvn.depth.infinity) |
2474 entries = client.get_changelist( |
|
2475 ppath, depth=pysvn.depth.infinity) |
2498 for entry in entries: |
2476 for entry in entries: |
2499 changelist = entry[1] |
2477 changelist = entry[1] |
2500 if changelist not in changelists: |
2478 if changelist not in changelists: |
2501 changelists.append(changelist) |
2479 changelists.append(changelist) |
2502 except pysvn.ClientError: |
2480 except pysvn.ClientError: |
2503 pass |
2481 pass |
2504 locker.unlock() |
|
2505 |
2482 |
2506 return changelists |
2483 return changelists |
2507 |
2484 |
2508 def svnUpgrade(self, path): |
2485 def svnUpgrade(self, path): |
2509 """ |
2486 """ |
2515 dlg = SvnDialog( |
2492 dlg = SvnDialog( |
2516 self.tr('Upgrade'), |
2493 self.tr('Upgrade'), |
2517 "upgrade {0}".format(path), |
2494 "upgrade {0}".format(path), |
2518 client) |
2495 client) |
2519 QApplication.processEvents() |
2496 QApplication.processEvents() |
2520 locker = QMutexLocker(self.vcsExecutionMutex) |
|
2521 try: |
2497 try: |
2522 client.upgrade(path) |
2498 with E5MutexLocker(self.vcsExecutionMutex): |
|
2499 client.upgrade(path) |
2523 except pysvn.ClientError as e: |
2500 except pysvn.ClientError as e: |
2524 dlg.showError(e.args[0]) |
2501 dlg.showError(e.args[0]) |
2525 locker.unlock() |
|
2526 dlg.finish() |
2502 dlg.finish() |
2527 dlg.exec() |
2503 dlg.exec() |
2528 |
2504 |
2529 ########################################################################### |
2505 ########################################################################### |
2530 ## Private Subversion specific methods are below. |
2506 ## Private Subversion specific methods are below. |