10 import re |
10 import re |
11 import os |
11 import os |
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 import contextlib |
15 |
16 |
16 from PyQt5.QtCore import pyqtSignal, Qt, QDateTime, QCoreApplication |
17 from PyQt5.QtCore import pyqtSignal, Qt, QDateTime, QCoreApplication |
17 from PyQt5.QtWidgets import QLineEdit, QDialog, QInputDialog, QApplication |
18 from PyQt5.QtWidgets import QLineEdit, QDialog, QInputDialog, QApplication |
18 |
19 |
19 from E5Gui.E5Application import e5App |
20 from E5Gui.E5Application import e5App |
582 msg, " ".join(fnames)), |
583 msg, " ".join(fnames)), |
583 client) |
584 client) |
584 QApplication.processEvents() |
585 QApplication.processEvents() |
585 try: |
586 try: |
586 with E5MutexLocker(self.vcsExecutionMutex): |
587 with E5MutexLocker(self.vcsExecutionMutex): |
587 if changelists: |
588 rev = ( |
588 rev = client.checkin(fnames, msg, |
589 client.checkin( |
589 recurse=recurse, keep_locks=keeplocks, |
590 fnames, msg, recurse=recurse, keep_locks=keeplocks, |
590 keep_changelist=keepChangelists, |
591 keep_changelist=keepChangelists, |
591 changelists=changelists) |
592 changelists=changelists) |
592 else: |
593 if changelists else |
593 rev = client.checkin(fnames, msg, |
594 client.checkin( |
594 recurse=recurse, keep_locks=keeplocks) |
595 fnames, msg, recurse=recurse, keep_locks=keeplocks) |
|
596 ) |
595 except pysvn.ClientError as e: |
597 except pysvn.ClientError as e: |
596 rev = None |
598 rev = None |
597 if not noDialog: |
599 if not noDialog: |
598 dlg.showError(e.args[0]) |
600 dlg.showError(e.args[0]) |
599 if not noDialog: |
601 if not noDialog: |
932 if accepted: |
934 if accepted: |
933 target, force = dlg.getData() |
935 target, force = dlg.getData() |
934 if not target: |
936 if not target: |
935 return False |
937 return False |
936 |
938 |
937 if rx_prot.fullmatch(target) is None: |
939 isDir = (os.path.isdir(name) if rx_prot.fullmatch(target) is None |
938 isDir = os.path.isdir(name) |
940 else False) |
939 else: |
|
940 isDir = False |
|
941 |
941 |
942 if accepted: |
942 if accepted: |
943 client = self.getClient() |
943 client = self.getClient() |
944 if rx_prot.fullmatch(target) is not None: |
944 if rx_prot.fullmatch(target) is not None: |
945 target = self.__svnURL(target) |
945 target = self.__svnURL(target) |
990 being edited and has unsaved modification, they can be saved or the |
990 being edited and has unsaved modification, they can be saved or the |
991 operation may be aborted. |
991 operation may be aborted. |
992 |
992 |
993 @param name file/directory name to be diffed (string) |
993 @param name file/directory name to be diffed (string) |
994 """ |
994 """ |
995 if isinstance(name, list): |
995 names = name[:] if isinstance(name, list) else [name] |
996 names = name[:] |
|
997 else: |
|
998 names = [name] |
|
999 for nam in names: |
996 for nam in names: |
1000 if os.path.isfile(nam): |
997 if os.path.isfile(nam): |
1001 editor = e5App().getObject("ViewManager").getOpenEditor(nam) |
998 editor = e5App().getObject("ViewManager").getOpenEditor(nam) |
1002 if editor and not editor.checkDirty(): |
999 if editor and not editor.checkDirty(): |
1003 return |
1000 return |
1047 """The URL of the project repository could not be""" |
1044 """The URL of the project repository could not be""" |
1048 """ retrieved from the working copy. The tag operation""" |
1045 """ retrieved from the working copy. The tag operation""" |
1049 """ will be aborted""")) |
1046 """ will be aborted""")) |
1050 return |
1047 return |
1051 |
1048 |
1052 if self.otherData["standardLayout"]: |
1049 url = ( |
1053 url = None |
1050 None |
1054 else: |
1051 if self.otherData["standardLayout"] else |
1055 url = self.svnNormalizeURL(reposURL) |
1052 self.svnNormalizeURL(reposURL) |
|
1053 ) |
1056 from .SvnTagDialog import SvnTagDialog |
1054 from .SvnTagDialog import SvnTagDialog |
1057 dlg = SvnTagDialog(self.allTagsBranchesList, url, |
1055 dlg = SvnTagDialog(self.allTagsBranchesList, url, |
1058 self.otherData["standardLayout"]) |
1056 self.otherData["standardLayout"]) |
1059 if dlg.exec() == QDialog.DialogCode.Accepted: |
1057 if dlg.exec() == QDialog.DialogCode.Accepted: |
1060 tag, tagOp = dlg.getParameters() |
1058 tag, tagOp = dlg.getParameters() |
1189 """The URL of the project repository could not be""" |
1187 """The URL of the project repository could not be""" |
1190 """ retrieved from the working copy. The switch""" |
1188 """ retrieved from the working copy. The switch""" |
1191 """ operation will be aborted""")) |
1189 """ operation will be aborted""")) |
1192 return False |
1190 return False |
1193 |
1191 |
1194 if self.otherData["standardLayout"]: |
1192 url = ( |
1195 url = None |
1193 None |
1196 else: |
1194 if self.otherData["standardLayout"] else |
1197 url = self.svnNormalizeURL(reposURL) |
1195 self.svnNormalizeURL(reposURL) |
|
1196 ) |
1198 from .SvnSwitchDialog import SvnSwitchDialog |
1197 from .SvnSwitchDialog import SvnSwitchDialog |
1199 dlg = SvnSwitchDialog(self.allTagsBranchesList, url, |
1198 dlg = SvnSwitchDialog(self.allTagsBranchesList, url, |
1200 self.otherData["standardLayout"]) |
1199 self.otherData["standardLayout"]) |
1201 if dlg.exec() == QDialog.DialogCode.Accepted: |
1200 if dlg.exec() == QDialog.DialogCode.Accepted: |
1202 tag, tagType = dlg.getParameters() |
1201 tag, tagType = dlg.getParameters() |
1482 client.callback_get_login = mixin._clientLoginCallback |
1481 client.callback_get_login = mixin._clientLoginCallback |
1483 client.callback_ssl_server_trust_prompt = ( |
1482 client.callback_ssl_server_trust_prompt = ( |
1484 mixin._clientSslServerTrustPromptCallback |
1483 mixin._clientSslServerTrustPromptCallback |
1485 ) |
1484 ) |
1486 |
1485 |
1487 try: |
1486 with contextlib.suppress(pysvn.ClientError): |
1488 with E5MutexLocker(self.vcsExecutionMutex): |
1487 with E5MutexLocker(self.vcsExecutionMutex): |
1489 allFiles = client.status(dname, recurse=True, get_all=True, |
1488 allFiles = client.status(dname, recurse=True, get_all=True, |
1490 ignore=True, update=False) |
1489 ignore=True, update=False) |
1491 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)] |
1492 for file in allFiles: |
1491 for file in allFiles: |
1515 self.statusCache[d] = self.canBeCommitted |
1514 self.statusCache[d] = self.canBeCommitted |
1516 dirs.remove(d) |
1515 dirs.remove(d) |
1517 break |
1516 break |
1518 else: |
1517 else: |
1519 self.statusCache[name] = self.canBeAdded |
1518 self.statusCache[name] = self.canBeAdded |
1520 except pysvn.ClientError: |
|
1521 # ignore pysvn errors |
|
1522 pass |
|
1523 |
1519 |
1524 return names |
1520 return names |
1525 |
1521 |
1526 def __vcsAllRegisteredStates_wc(self, names, dname, shortcut=True): |
1522 def __vcsAllRegisteredStates_wc(self, names, dname, shortcut=True): |
1527 """ |
1523 """ |
1562 client.callback_get_login = mixin._clientLoginCallback |
1558 client.callback_get_login = mixin._clientLoginCallback |
1563 client.callback_ssl_server_trust_prompt = ( |
1559 client.callback_ssl_server_trust_prompt = ( |
1564 mixin._clientSslServerTrustPromptCallback |
1560 mixin._clientSslServerTrustPromptCallback |
1565 ) |
1561 ) |
1566 |
1562 |
1567 try: |
1563 with contextlib.suppress(pysvn.ClientError): |
1568 with E5MutexLocker(self.vcsExecutionMutex): |
1564 with E5MutexLocker(self.vcsExecutionMutex): |
1569 allFiles = client.status(dname, recurse=True, get_all=True, |
1565 allFiles = client.status(dname, recurse=True, get_all=True, |
1570 ignore=True, update=False) |
1566 ignore=True, update=False) |
1571 for file in allFiles: |
1567 for file in allFiles: |
1572 name = os.path.normcase(file.path) |
1568 name = os.path.normcase(file.path) |
1574 if name in names: |
1570 if name in names: |
1575 names[name] = self.canBeCommitted |
1571 names[name] = self.canBeCommitted |
1576 self.statusCache[name] = self.canBeCommitted |
1572 self.statusCache[name] = self.canBeCommitted |
1577 else: |
1573 else: |
1578 self.statusCache[name] = self.canBeAdded |
1574 self.statusCache[name] = self.canBeAdded |
1579 except pysvn.ClientError: |
|
1580 # ignore pysvn errors |
|
1581 pass |
|
1582 |
1575 |
1583 return names |
1576 return names |
1584 |
1577 |
1585 def __isVersioned(self, status): |
1578 def __isVersioned(self, status): |
1586 """ |
1579 """ |
1717 try: |
1710 try: |
1718 entry = self.getClient().info(ppath) |
1711 entry = self.getClient().info(ppath) |
1719 except pysvn.ClientError as e: |
1712 except pysvn.ClientError as e: |
1720 return e.args[0] |
1713 return e.args[0] |
1721 |
1714 |
1722 if hasattr(pysvn, 'svn_api_version'): |
1715 apiVersion = ( |
1723 apiVersion = "{0} {1}".format( |
1716 "{0} {1}".format( |
1724 ".".join([str(v) for v in pysvn.svn_api_version[:3]]), |
1717 ".".join([str(v) for v in pysvn.svn_api_version[:3]]), |
1725 pysvn.svn_api_version[3]) |
1718 pysvn.svn_api_version[3]) |
1726 else: |
1719 if hasattr(pysvn, 'svn_api_version') else |
1727 apiVersion = QCoreApplication.translate('subversion', "unknown") |
1720 QCoreApplication.translate('subversion', "unknown") |
|
1721 ) |
1728 |
1722 |
1729 hmsz = time.strftime("%H:%M:%S %Z", time.localtime(entry.commit_time)) |
1723 hmsz = time.strftime("%H:%M:%S %Z", time.localtime(entry.commit_time)) |
1730 return QCoreApplication.translate( |
1724 return QCoreApplication.translate( |
1731 'subversion', |
1725 'subversion', |
1732 """<h3>Repository information</h3>""" |
1726 """<h3>Repository information</h3>""" |
2034 |
2028 |
2035 This method gives the chance to enter the revisions to be compared. |
2029 This method gives the chance to enter the revisions to be compared. |
2036 |
2030 |
2037 @param name file/directory name to be diffed (string) |
2031 @param name file/directory name to be diffed (string) |
2038 """ |
2032 """ |
2039 if isinstance(name, list): |
2033 names = name[:] if isinstance(name, list) else [name] |
2040 names = name[:] |
|
2041 else: |
|
2042 names = [name] |
|
2043 for nam in names: |
2034 for nam in names: |
2044 if os.path.isfile(nam): |
2035 if os.path.isfile(nam): |
2045 editor = e5App().getObject("ViewManager").getOpenEditor(nam) |
2036 editor = e5App().getObject("ViewManager").getOpenEditor(nam) |
2046 if editor and not editor.checkDirty(): |
2037 if editor and not editor.checkDirty(): |
2047 return |
2038 return |
2073 |
2064 |
2074 This method gives the chance to enter the revisions to be compared. |
2065 This method gives the chance to enter the revisions to be compared. |
2075 |
2066 |
2076 @param name file/directory name to be diffed (string) |
2067 @param name file/directory name to be diffed (string) |
2077 """ |
2068 """ |
2078 if isinstance(name, list): |
2069 names = name[:] if isinstance(name, list) else [name] |
2079 names = name[:] |
|
2080 else: |
|
2081 names = [name] |
|
2082 for nam in names: |
2070 for nam in names: |
2083 if os.path.isfile(nam): |
2071 if os.path.isfile(nam): |
2084 editor = e5App().getObject("ViewManager").getOpenEditor(nam) |
2072 editor = e5App().getObject("ViewManager").getOpenEditor(nam) |
2085 if editor and not editor.checkDirty(): |
2073 if editor and not editor.checkDirty(): |
2086 return |
2074 return |
2362 """ |
2350 """ |
2363 Public method to open the repository browser. |
2351 Public method to open the repository browser. |
2364 |
2352 |
2365 @param projectPath path name of the project (string) |
2353 @param projectPath path name of the project (string) |
2366 """ |
2354 """ |
2367 if projectPath: |
2355 url = self.svnGetReposName(projectPath) if projectPath else None |
2368 url = self.svnGetReposName(projectPath) |
|
2369 else: |
|
2370 url = None |
|
2371 |
|
2372 if url is None: |
2356 if url is None: |
2373 url, ok = QInputDialog.getText( |
2357 url, ok = QInputDialog.getText( |
2374 None, |
2358 None, |
2375 self.tr("Repository Browser"), |
2359 self.tr("Repository Browser"), |
2376 self.tr("Enter the repository URL."), |
2360 self.tr("Enter the repository URL."), |
2468 """ |
2452 """ |
2469 changelists = [] |
2453 changelists = [] |
2470 client = self.getClient() |
2454 client = self.getClient() |
2471 if hasattr(client, 'get_changelist'): |
2455 if hasattr(client, 'get_changelist'): |
2472 ppath = e5App().getObject("Project").getProjectPath() |
2456 ppath = e5App().getObject("Project").getProjectPath() |
2473 try: |
2457 with contextlib.suppress(pysvn.ClientError): |
2474 with E5MutexLocker(self.vcsExecutionMutex): |
2458 with E5MutexLocker(self.vcsExecutionMutex): |
2475 entries = client.get_changelist( |
2459 entries = client.get_changelist( |
2476 ppath, depth=pysvn.depth.infinity) |
2460 ppath, depth=pysvn.depth.infinity) |
2477 for entry in entries: |
2461 for entry in entries: |
2478 changelist = entry[1] |
2462 changelist = entry[1] |
2479 if changelist not in changelists: |
2463 if changelist not in changelists: |
2480 changelists.append(changelist) |
2464 changelists.append(changelist) |
2481 except pysvn.ClientError: |
|
2482 pass |
|
2483 |
2465 |
2484 return changelists |
2466 return changelists |
2485 |
2467 |
2486 def svnUpgrade(self, path): |
2468 def svnUpgrade(self, path): |
2487 """ |
2469 """ |