15 import contextlib |
15 import contextlib |
16 |
16 |
17 from PyQt6.QtCore import pyqtSignal, Qt, QDateTime, QCoreApplication |
17 from PyQt6.QtCore import pyqtSignal, Qt, QDateTime, QCoreApplication |
18 from PyQt6.QtWidgets import QLineEdit, QDialog, QInputDialog, QApplication |
18 from PyQt6.QtWidgets import QLineEdit, QDialog, QInputDialog, QApplication |
19 |
19 |
20 from E5Gui.E5Application import e5App |
20 from E5Gui.EricApplication import ericApp |
21 from E5Gui import E5MessageBox |
21 from E5Gui import EricMessageBox |
22 |
22 |
23 from EricUtilities.EricMutexLocker import EricMutexLocker |
23 from EricUtilities.EricMutexLocker import EricMutexLocker |
24 |
24 |
25 from VCS.VersionControl import VersionControl |
25 from VCS.VersionControl import VersionControl |
26 |
26 |
205 @param addAll flag indicating to add all files to the repository |
205 @param addAll flag indicating to add all files to the repository |
206 @type bool |
206 @type bool |
207 """ |
207 """ |
208 success = self.vcsImport(vcsDataDict, project.ppath, addAll=addAll)[0] |
208 success = self.vcsImport(vcsDataDict, project.ppath, addAll=addAll)[0] |
209 if not success: |
209 if not success: |
210 E5MessageBox.critical( |
210 EricMessageBox.critical( |
211 self.__ui, |
211 self.__ui, |
212 self.tr("Create project in repository"), |
212 self.tr("Create project in repository"), |
213 self.tr( |
213 self.tr( |
214 """The project could not be created in the repository.""" |
214 """The project could not be created in the repository.""" |
215 """ Maybe the given repository doesn't exist or the""" |
215 """ Maybe the given repository doesn't exist or the""" |
229 self.vcsCommit(project.ppath, vcsDataDict["message"], True) |
229 self.vcsCommit(project.ppath, vcsDataDict["message"], True) |
230 pfn = project.pfile |
230 pfn = project.pfile |
231 if not os.path.isfile(pfn): |
231 if not os.path.isfile(pfn): |
232 pfn += "z" |
232 pfn += "z" |
233 if not os.path.isfile(pfn): |
233 if not os.path.isfile(pfn): |
234 E5MessageBox.critical( |
234 EricMessageBox.critical( |
235 self.__ui, |
235 self.__ui, |
236 self.tr("New project"), |
236 self.tr("New project"), |
237 self.tr( |
237 self.tr( |
238 """The project could not be checked out of the""" |
238 """The project could not be checked out of the""" |
239 """ repository.<br />""" |
239 """ repository.<br />""" |
511 nameList = [name] |
511 nameList = [name] |
512 ok = True |
512 ok = True |
513 for nam in nameList: |
513 for nam in nameList: |
514 # check for commit of the project |
514 # check for commit of the project |
515 if os.path.isdir(nam): |
515 if os.path.isdir(nam): |
516 project = e5App().getObject("Project") |
516 project = ericApp().getObject("Project") |
517 if nam == project.getProjectPath(): |
517 if nam == project.getProjectPath(): |
518 ok &= project.checkAllScriptsDirty( |
518 ok &= project.checkAllScriptsDirty( |
519 reportSyntaxErrors=True) and project.checkDirty() |
519 reportSyntaxErrors=True) and project.checkDirty() |
520 continue |
520 continue |
521 elif os.path.isfile(nam): |
521 elif os.path.isfile(nam): |
522 editor = e5App().getObject("ViewManager").getOpenEditor( |
522 editor = ericApp().getObject("ViewManager").getOpenEditor( |
523 nam) |
523 nam) |
524 if editor: |
524 if editor: |
525 ok &= editor.checkDirty() |
525 ok &= editor.checkDirty() |
526 if not ok: |
526 if not ok: |
527 break |
527 break |
528 |
528 |
529 if not ok: |
529 if not ok: |
530 res = E5MessageBox.yesNo( |
530 res = EricMessageBox.yesNo( |
531 self.__ui, |
531 self.__ui, |
532 self.tr("Commit Changes"), |
532 self.tr("Commit Changes"), |
533 self.tr( |
533 self.tr( |
534 """The commit affects files, that have unsaved""" |
534 """The commit affects files, that have unsaved""" |
535 """ changes. Shall the commit be continued?"""), |
535 """ changes. Shall the commit be continued?"""), |
536 icon=E5MessageBox.Warning) |
536 icon=EricMessageBox.Warning) |
537 if not res: |
537 if not res: |
538 return |
538 return |
539 |
539 |
540 if self.__commitDialog is not None: |
540 if self.__commitDialog is not None: |
541 msg = self.__commitDialog.logMessage() |
541 msg = self.__commitDialog.logMessage() |
993 @param name file/directory name to be diffed (string) |
993 @param name file/directory name to be diffed (string) |
994 """ |
994 """ |
995 names = name[:] if isinstance(name, list) else [name] |
995 names = name[:] if isinstance(name, list) else [name] |
996 for nam in names: |
996 for nam in names: |
997 if os.path.isfile(nam): |
997 if os.path.isfile(nam): |
998 editor = e5App().getObject("ViewManager").getOpenEditor(nam) |
998 editor = ericApp().getObject("ViewManager").getOpenEditor(nam) |
999 if editor and not editor.checkDirty(): |
999 if editor and not editor.checkDirty(): |
1000 return |
1000 return |
1001 else: |
1001 else: |
1002 project = e5App().getObject("Project") |
1002 project = ericApp().getObject("Project") |
1003 if nam == project.ppath and not project.saveAllScripts(): |
1003 if nam == project.ppath and not project.saveAllScripts(): |
1004 return |
1004 return |
1005 if self.diff is None: |
1005 if self.diff is None: |
1006 from .SvnDiffDialog import SvnDiffDialog |
1006 from .SvnDiffDialog import SvnDiffDialog |
1007 self.diff = SvnDiffDialog(self) |
1007 self.diff = SvnDiffDialog(self) |
1035 """ |
1035 """ |
1036 dname, fname = self.splitPath(name) |
1036 dname, fname = self.splitPath(name) |
1037 |
1037 |
1038 reposURL = self.svnGetReposName(dname) |
1038 reposURL = self.svnGetReposName(dname) |
1039 if reposURL is None: |
1039 if reposURL is None: |
1040 E5MessageBox.critical( |
1040 EricMessageBox.critical( |
1041 self.__ui, |
1041 self.__ui, |
1042 self.tr("Subversion Error"), |
1042 self.tr("Subversion Error"), |
1043 self.tr( |
1043 self.tr( |
1044 """The URL of the project repository could not be""" |
1044 """The URL of the project repository could not be""" |
1045 """ retrieved from the working copy. The tag operation""" |
1045 """ retrieved from the working copy. The tag operation""" |
1065 if self.otherData["standardLayout"]: |
1065 if self.otherData["standardLayout"]: |
1066 rx_base = re.compile('(.+)/(trunk|tags|branches).*') |
1066 rx_base = re.compile('(.+)/(trunk|tags|branches).*') |
1067 |
1067 |
1068 match = rx_base.fullmatch(reposURL) |
1068 match = rx_base.fullmatch(reposURL) |
1069 if match is None: |
1069 if match is None: |
1070 E5MessageBox.critical( |
1070 EricMessageBox.critical( |
1071 self.__ui, |
1071 self.__ui, |
1072 self.tr("Subversion Error"), |
1072 self.tr("Subversion Error"), |
1073 self.tr( |
1073 self.tr( |
1074 """The URL of the project repository has an""" |
1074 """The URL of the project repository has an""" |
1075 """ invalid format. The tag operation will""" |
1075 """ invalid format. The tag operation will""" |
1128 if not isinstance(name, list): |
1128 if not isinstance(name, list): |
1129 name = [name] |
1129 name = [name] |
1130 if os.path.isdir(name[0]): |
1130 if os.path.isdir(name[0]): |
1131 recurse = True |
1131 recurse = True |
1132 |
1132 |
1133 project = e5App().getObject("Project") |
1133 project = ericApp().getObject("Project") |
1134 names = [project.getRelativePath(nam) for nam in name] |
1134 names = [project.getRelativePath(nam) for nam in name] |
1135 if names[0]: |
1135 if names[0]: |
1136 from UI.DeleteFilesConfirmationDialog import ( |
1136 from UI.DeleteFilesConfirmationDialog import ( |
1137 DeleteFilesConfirmationDialog |
1137 DeleteFilesConfirmationDialog |
1138 ) |
1138 ) |
1143 "Do you really want to revert all changes to these files" |
1143 "Do you really want to revert all changes to these files" |
1144 " or directories?"), |
1144 " or directories?"), |
1145 name) |
1145 name) |
1146 yes = dia.exec() == QDialog.DialogCode.Accepted |
1146 yes = dia.exec() == QDialog.DialogCode.Accepted |
1147 else: |
1147 else: |
1148 yes = E5MessageBox.yesNo( |
1148 yes = EricMessageBox.yesNo( |
1149 None, |
1149 None, |
1150 self.tr("Revert changes"), |
1150 self.tr("Revert changes"), |
1151 self.tr("""Do you really want to revert all changes of""" |
1151 self.tr("""Do you really want to revert all changes of""" |
1152 """ the project?""")) |
1152 """ the project?""")) |
1153 if yes: |
1153 if yes: |
1178 """ |
1178 """ |
1179 dname, fname = self.splitPath(name) |
1179 dname, fname = self.splitPath(name) |
1180 |
1180 |
1181 reposURL = self.svnGetReposName(dname) |
1181 reposURL = self.svnGetReposName(dname) |
1182 if reposURL is None: |
1182 if reposURL is None: |
1183 E5MessageBox.critical( |
1183 EricMessageBox.critical( |
1184 self.__ui, |
1184 self.__ui, |
1185 self.tr("Subversion Error"), |
1185 self.tr("Subversion Error"), |
1186 self.tr( |
1186 self.tr( |
1187 """The URL of the project repository could not be""" |
1187 """The URL of the project repository could not be""" |
1188 """ retrieved from the working copy. The switch""" |
1188 """ retrieved from the working copy. The switch""" |
1207 |
1207 |
1208 if self.otherData["standardLayout"]: |
1208 if self.otherData["standardLayout"]: |
1209 rx_base = re.compile('(.+)/(trunk|tags|branches).*') |
1209 rx_base = re.compile('(.+)/(trunk|tags|branches).*') |
1210 match = rx_base.fullmatch(reposURL) |
1210 match = rx_base.fullmatch(reposURL) |
1211 if match is None: |
1211 if match is None: |
1212 E5MessageBox.critical( |
1212 EricMessageBox.critical( |
1213 self.__ui, |
1213 self.__ui, |
1214 self.tr("Subversion Error"), |
1214 self.tr("Subversion Error"), |
1215 self.tr( |
1215 self.tr( |
1216 """The URL of the project repository has an""" |
1216 """The URL of the project repository has an""" |
1217 """ invalid format. The switch operation will""" |
1217 """ invalid format. The switch operation will""" |
1877 from .SvnPropSetDialog import SvnPropSetDialog |
1877 from .SvnPropSetDialog import SvnPropSetDialog |
1878 dlg = SvnPropSetDialog(recursive) |
1878 dlg = SvnPropSetDialog(recursive) |
1879 if dlg.exec() == QDialog.DialogCode.Accepted: |
1879 if dlg.exec() == QDialog.DialogCode.Accepted: |
1880 propName, propValue, recurse = dlg.getData() |
1880 propName, propValue, recurse = dlg.getData() |
1881 if not propName: |
1881 if not propName: |
1882 E5MessageBox.critical( |
1882 EricMessageBox.critical( |
1883 self.__ui, |
1883 self.__ui, |
1884 self.tr("Subversion Set Property"), |
1884 self.tr("Subversion Set Property"), |
1885 self.tr( |
1885 self.tr( |
1886 """You have to supply a property name. Aborting.""")) |
1886 """You have to supply a property name. Aborting.""")) |
1887 return |
1887 return |
1929 dlg = SvnPropDelDialog(recursive) |
1929 dlg = SvnPropDelDialog(recursive) |
1930 if dlg.exec() == QDialog.DialogCode.Accepted: |
1930 if dlg.exec() == QDialog.DialogCode.Accepted: |
1931 propName, recurse = dlg.getData() |
1931 propName, recurse = dlg.getData() |
1932 |
1932 |
1933 if not propName: |
1933 if not propName: |
1934 E5MessageBox.critical( |
1934 EricMessageBox.critical( |
1935 self.__ui, |
1935 self.__ui, |
1936 self.tr("Subversion Delete Property"), |
1936 self.tr("Subversion Delete Property"), |
1937 self.tr( |
1937 self.tr( |
1938 """You have to supply a property name. Aborting.""")) |
1938 """You have to supply a property name. Aborting.""")) |
1939 return |
1939 return |
2031 @param name file/directory name to be diffed (string) |
2031 @param name file/directory name to be diffed (string) |
2032 """ |
2032 """ |
2033 names = name[:] if isinstance(name, list) else [name] |
2033 names = name[:] if isinstance(name, list) else [name] |
2034 for nam in names: |
2034 for nam in names: |
2035 if os.path.isfile(nam): |
2035 if os.path.isfile(nam): |
2036 editor = e5App().getObject("ViewManager").getOpenEditor(nam) |
2036 editor = ericApp().getObject("ViewManager").getOpenEditor(nam) |
2037 if editor and not editor.checkDirty(): |
2037 if editor and not editor.checkDirty(): |
2038 return |
2038 return |
2039 else: |
2039 else: |
2040 project = e5App().getObject("Project") |
2040 project = ericApp().getObject("Project") |
2041 if nam == project.ppath and not project.saveAllScripts(): |
2041 if nam == project.ppath and not project.saveAllScripts(): |
2042 return |
2042 return |
2043 from .SvnRevisionSelectionDialog import SvnRevisionSelectionDialog |
2043 from .SvnRevisionSelectionDialog import SvnRevisionSelectionDialog |
2044 dlg = SvnRevisionSelectionDialog() |
2044 dlg = SvnRevisionSelectionDialog() |
2045 if dlg.exec() == QDialog.DialogCode.Accepted: |
2045 if dlg.exec() == QDialog.DialogCode.Accepted: |
2067 @param name file/directory name to be diffed (string) |
2067 @param name file/directory name to be diffed (string) |
2068 """ |
2068 """ |
2069 names = name[:] if isinstance(name, list) else [name] |
2069 names = name[:] if isinstance(name, list) else [name] |
2070 for nam in names: |
2070 for nam in names: |
2071 if os.path.isfile(nam): |
2071 if os.path.isfile(nam): |
2072 editor = e5App().getObject("ViewManager").getOpenEditor(nam) |
2072 editor = ericApp().getObject("ViewManager").getOpenEditor(nam) |
2073 if editor and not editor.checkDirty(): |
2073 if editor and not editor.checkDirty(): |
2074 return |
2074 return |
2075 else: |
2075 else: |
2076 project = e5App().getObject("Project") |
2076 project = ericApp().getObject("Project") |
2077 if nam == project.ppath and not project.saveAllScripts(): |
2077 if nam == project.ppath and not project.saveAllScripts(): |
2078 return |
2078 return |
2079 |
2079 |
2080 dname = self.splitPath(names[0])[0] |
2080 dname = self.splitPath(names[0])[0] |
2081 |
2081 |
2165 else: |
2165 else: |
2166 rev1, rev2 = "", "" |
2166 rev1, rev2 = "", "" |
2167 |
2167 |
2168 output1, error = self.__svnGetFileForRevision(name, rev=rev1) |
2168 output1, error = self.__svnGetFileForRevision(name, rev=rev1) |
2169 if error: |
2169 if error: |
2170 E5MessageBox.critical( |
2170 EricMessageBox.critical( |
2171 self.__ui, |
2171 self.__ui, |
2172 self.tr("Subversion Side-by-Side Difference"), |
2172 self.tr("Subversion Side-by-Side Difference"), |
2173 error) |
2173 error) |
2174 return |
2174 return |
2175 name1 = "{0} (rev. {1})".format(name, rev1 and rev1 or ".") |
2175 name1 = "{0} (rev. {1})".format(name, rev1 and rev1 or ".") |
2176 |
2176 |
2177 if rev2: |
2177 if rev2: |
2178 output2, error = self.__svnGetFileForRevision(name, rev=rev2) |
2178 output2, error = self.__svnGetFileForRevision(name, rev=rev2) |
2179 if error: |
2179 if error: |
2180 E5MessageBox.critical( |
2180 EricMessageBox.critical( |
2181 self.__ui, |
2181 self.__ui, |
2182 self.tr("Subversion Side-by-Side Difference"), |
2182 self.tr("Subversion Side-by-Side Difference"), |
2183 error) |
2183 error) |
2184 return |
2184 return |
2185 name2 = "{0} (rev. {1})".format(name, rev2) |
2185 name2 = "{0} (rev. {1})".format(name, rev2) |
2187 try: |
2187 try: |
2188 with open(name, "r", encoding="utf-8") as f1: |
2188 with open(name, "r", encoding="utf-8") as f1: |
2189 output2 = f1.read() |
2189 output2 = f1.read() |
2190 name2 = name |
2190 name2 = name |
2191 except OSError: |
2191 except OSError: |
2192 E5MessageBox.critical( |
2192 EricMessageBox.critical( |
2193 self.__ui, |
2193 self.__ui, |
2194 self.tr("Subversion Side-by-Side Difference"), |
2194 self.tr("Subversion Side-by-Side Difference"), |
2195 self.tr( |
2195 self.tr( |
2196 """<p>The file <b>{0}</b> could not be read.</p>""") |
2196 """<p>The file <b>{0}</b> could not be read.</p>""") |
2197 .format(name)) |
2197 .format(name)) |
2451 @return list of defined change list names (list of strings) |
2451 @return list of defined change list names (list of strings) |
2452 """ |
2452 """ |
2453 changelists = [] |
2453 changelists = [] |
2454 client = self.getClient() |
2454 client = self.getClient() |
2455 if hasattr(client, 'get_changelist'): |
2455 if hasattr(client, 'get_changelist'): |
2456 ppath = e5App().getObject("Project").getProjectPath() |
2456 ppath = ericApp().getObject("Project").getProjectPath() |
2457 with contextlib.suppress(pysvn.ClientError): |
2457 with contextlib.suppress(pysvn.ClientError): |
2458 with EricMutexLocker(self.vcsExecutionMutex): |
2458 with EricMutexLocker(self.vcsExecutionMutex): |
2459 entries = client.get_changelist( |
2459 entries = client.get_changelist( |
2460 ppath, depth=pysvn.depth.infinity) |
2460 ppath, depth=pysvn.depth.infinity) |
2461 for entry in entries: |
2461 for entry in entries: |