eric6/Plugins/VcsPlugins/vcsMercurial/hg.py

branch
maintenance
changeset 8273
698ae46f40a4
parent 8176
31965986ecd1
parent 8259
2bbec88047dd
child 8400
b3eefd7e58d1
equal deleted inserted replaced
8190:fb0ef164f536 8273:698ae46f40a4
7 Module implementing the version control systems interface to Mercurial. 7 Module implementing the version control systems interface to Mercurial.
8 """ 8 """
9 9
10 import os 10 import os
11 import shutil 11 import shutil
12 import contextlib
12 13
13 from PyQt5.QtCore import ( 14 from PyQt5.QtCore import (
14 pyqtSignal, QFileInfo, QFileSystemWatcher, QCoreApplication 15 pyqtSignal, QFileInfo, QFileSystemWatcher, QCoreApplication
15 ) 16 )
16 from PyQt5.QtWidgets import QApplication, QDialog, QInputDialog 17 from PyQt5.QtWidgets import QApplication, QDialog, QInputDialog
745 being edited and has unsaved modification, they can be saved or the 746 being edited and has unsaved modification, they can be saved or the
746 operation may be aborted. 747 operation may be aborted.
747 748
748 @param name file/directory name to be diffed (string) 749 @param name file/directory name to be diffed (string)
749 """ 750 """
750 if isinstance(name, list): 751 names = name[:] if isinstance(name, list) else [name]
751 names = name[:]
752 else:
753 names = [name]
754 for nam in names: 752 for nam in names:
755 if os.path.isfile(nam): 753 if os.path.isfile(nam):
756 editor = e5App().getObject("ViewManager").getOpenEditor(nam) 754 editor = e5App().getObject("ViewManager").getOpenEditor(nam)
757 if editor and not editor.checkDirty(): 755 if editor and not editor.checkDirty():
758 return 756 return
824 msgPart = "local " 822 msgPart = "local "
825 else: 823 else:
826 msgPart = "global " 824 msgPart = "global "
827 if tagOp in [HgTagDialog.DeleteGlobalTag, HgTagDialog.DeleteLocalTag]: 825 if tagOp in [HgTagDialog.DeleteGlobalTag, HgTagDialog.DeleteLocalTag]:
828 args.append('--remove') 826 args.append('--remove')
829 if tagOp in [HgTagDialog.CreateGlobalTag, HgTagDialog.CreateLocalTag]: 827 if (
830 if revision: 828 tagOp in [
831 args.append("--rev") 829 HgTagDialog.CreateGlobalTag, HgTagDialog.CreateLocalTag] and
832 args.append(revision) 830 revision
831 ):
832 args.append("--rev")
833 args.append(revision)
833 if force: 834 if force:
834 args.append("--force") 835 args.append("--force")
835 args.append('--message') 836 args.append('--message')
836 if tagOp in [HgTagDialog.CreateGlobalTag, HgTagDialog.CreateLocalTag]: 837 if tagOp in [HgTagDialog.CreateGlobalTag, HgTagDialog.CreateLocalTag]:
837 tag = tag.strip().replace(" ", "_") 838 tag = tag.strip().replace(" ", "_")
1076 for line in output.splitlines(): 1077 for line in output.splitlines():
1077 if line and line[0] in "MARC!?I": 1078 if line and line[0] in "MARC!?I":
1078 flag, path = line.split(" ", 1) 1079 flag, path = line.split(" ", 1)
1079 name = os.path.normcase(os.path.join(repoPath, path)) 1080 name = os.path.normcase(os.path.join(repoPath, path))
1080 dirName = os.path.dirname(name) 1081 dirName = os.path.dirname(name)
1081 if name.startswith(dname): 1082 if name.startswith(dname) and flag not in "?I":
1082 if flag not in "?I": 1083 if name in names:
1083 if name in names: 1084 names[name] = self.canBeCommitted
1084 names[name] = self.canBeCommitted 1085 if dirName in names:
1085 if dirName in names: 1086 names[dirName] = self.canBeCommitted
1086 names[dirName] = self.canBeCommitted 1087 if dirs:
1087 if dirs: 1088 for d in dirs:
1088 for d in dirs: 1089 if name.startswith(d):
1089 if name.startswith(d): 1090 names[d] = self.canBeCommitted
1090 names[d] = self.canBeCommitted 1091 dirs.remove(d)
1091 dirs.remove(d) 1092 break
1092 break
1093 if flag not in "?I": 1093 if flag not in "?I":
1094 self.statusCache[name] = self.canBeCommitted 1094 self.statusCache[name] = self.canBeCommitted
1095 self.statusCache[dirName] = self.canBeCommitted 1095 self.statusCache[dirName] = self.canBeCommitted
1096 else: 1096 else:
1097 self.statusCache[name] = self.canBeAdded 1097 self.statusCache[name] = self.canBeAdded
1139 entries = [] 1139 entries = []
1140 for pat in patterns: 1140 for pat in patterns:
1141 entries.extend(Utilities.direntries(name, True, pat)) 1141 entries.extend(Utilities.direntries(name, True, pat))
1142 1142
1143 for entry in entries: 1143 for entry in entries:
1144 try: 1144 with contextlib.suppress(OSError):
1145 os.remove(entry) 1145 os.remove(entry)
1146 except OSError:
1147 pass
1148 1146
1149 def vcsCommandLine(self, name): 1147 def vcsCommandLine(self, name):
1150 """ 1148 """
1151 Public method used to execute arbitrary mercurial commands. 1149 Public method used to execute arbitrary mercurial commands.
1152 1150
1212 1210
1213 output, error = self.__client.runcommand(args) 1211 output, error = self.__client.runcommand(args)
1214 1212
1215 infoBlock = [] 1213 infoBlock = []
1216 if output: 1214 if output:
1217 index = 0 1215 for index, line in enumerate(output.splitlines(), start=1):
1218 for line in output.splitlines():
1219 index += 1
1220 (changeset, tags, author, date, branches, 1216 (changeset, tags, author, date, branches,
1221 bookmarks) = line.split("@@@") 1217 bookmarks) = line.split("@@@")
1222 cdate, ctime = date.split()[:2] 1218 cdate, ctime = date.split()[:2]
1223 info = [] 1219 info = []
1224 info.append(QCoreApplication.translate( 1220 info.append(QCoreApplication.translate(
1246 """<tr><td><b>Last author</b></td><td>{0}</td></tr>\n""" 1242 """<tr><td><b>Last author</b></td><td>{0}</td></tr>\n"""
1247 """<tr><td><b>Committed date</b></td><td>{1}</td></tr>\n""" 1243 """<tr><td><b>Committed date</b></td><td>{1}</td></tr>\n"""
1248 """<tr><td><b>Committed time</b></td><td>{2}</td></tr>""") 1244 """<tr><td><b>Committed time</b></td><td>{2}</td></tr>""")
1249 .format(author, cdate, ctime)) 1245 .format(author, cdate, ctime))
1250 infoBlock.append("\n".join(info)) 1246 infoBlock.append("\n".join(info))
1251 if infoBlock: 1247 infoStr = (
1252 infoStr = """<tr></tr>{0}""".format("<tr></tr>".join(infoBlock)) 1248 """<tr></tr>{0}""".format("<tr></tr>".join(infoBlock))
1253 else: 1249 if infoBlock else
1254 infoStr = "" 1250 ""
1251 )
1255 1252
1256 url = "" 1253 url = ""
1257 args = self.initCommand("showconfig") 1254 args = self.initCommand("showconfig")
1258 args.append('paths.default') 1255 args.append('paths.default')
1259 1256
1260 output, error = self.__client.runcommand(args) 1257 output, error = self.__client.runcommand(args)
1261 1258 url = output.splitlines()[0].strip() if output else ""
1262 if output:
1263 url = output.splitlines()[0].strip()
1264 else:
1265 url = ""
1266 1259
1267 return QCoreApplication.translate( 1260 return QCoreApplication.translate(
1268 'mercurial', 1261 'mercurial',
1269 """<h3>Repository information</h3>\n""" 1262 """<h3>Repository information</h3>\n"""
1270 """<p><table>\n""" 1263 """<p><table>\n"""
1455 1448
1456 This method gives the chance to enter the revisions to be compared. 1449 This method gives the chance to enter the revisions to be compared.
1457 1450
1458 @param name file/directory name to be diffed (string) 1451 @param name file/directory name to be diffed (string)
1459 """ 1452 """
1460 if isinstance(name, list): 1453 names = name[:] if isinstance(name, list) else [name]
1461 names = name[:]
1462 else:
1463 names = [name]
1464 for nam in names: 1454 for nam in names:
1465 if os.path.isfile(nam): 1455 if os.path.isfile(nam):
1466 editor = e5App().getObject("ViewManager").getOpenEditor(nam) 1456 editor = e5App().getObject("ViewManager").getOpenEditor(nam)
1467 if editor and not editor.checkDirty(): 1457 if editor and not editor.checkDirty():
1468 return 1458 return
1705 '{date|isodate}@@@{branches}@@@{parents}@@@{bookmarks}\n') 1695 '{date|isodate}@@@{branches}@@@{parents}@@@{bookmarks}\n')
1706 1696
1707 output, error = self.__client.runcommand(args) 1697 output, error = self.__client.runcommand(args)
1708 1698
1709 if output: 1699 if output:
1710 index = 0 1700 for index, line in enumerate(output.splitlines(), start=1):
1711 for line in output.splitlines():
1712 index += 1
1713 (changeset, tags, author, date, branches, parents, 1701 (changeset, tags, author, date, branches, parents,
1714 bookmarks) = line.split("@@@") 1702 bookmarks) = line.split("@@@")
1715 cdate, ctime = date.split()[:2] 1703 cdate, ctime = date.split()[:2]
1716 info.append("""<p><table>""") 1704 info.append("""<p><table>""")
1717 if mode == "heads": 1705 if mode == "heads":
1791 if isinstance(name, list): 1779 if isinstance(name, list):
1792 self.addArguments(args, name) 1780 self.addArguments(args, name)
1793 else: 1781 else:
1794 args.append(name) 1782 args.append(name)
1795 1783
1796 if unresolve: 1784 title = (
1797 title = self.tr("Marking as 'unresolved'") 1785 self.tr("Marking as 'unresolved'")
1798 else: 1786 if unresolve else
1799 title = self.tr("Marking as 'resolved'") 1787 self.tr("Marking as 'resolved'")
1788 )
1800 dia = HgDialog(title, self) 1789 dia = HgDialog(title, self)
1801 res = dia.startProcess(args) 1790 res = dia.startProcess(args)
1802 if res: 1791 if res:
1803 dia.exec() 1792 dia.exec()
1804 self.checkVCSStatus() 1793 self.checkVCSStatus()
1913 defaultUrl, defaultPushUrl = dlg.getData() 1902 defaultUrl, defaultPushUrl = dlg.getData()
1914 if withLargefiles: 1903 if withLargefiles:
1915 lfMinSize, lfPattern = dlg.getLargefilesData() 1904 lfMinSize, lfPattern = dlg.getLargefilesData()
1916 else: 1905 else:
1917 createContents = False 1906 createContents = False
1918 try: 1907 with contextlib.suppress(OSError):
1919 with open(cfgFile, "w") as cfg: 1908 with open(cfgFile, "w") as cfg:
1920 if createContents: 1909 if createContents:
1921 # write the data entered 1910 # write the data entered
1922 cfg.write("[paths]\n") 1911 cfg.write("[paths]\n")
1923 if defaultUrl: 1912 if defaultUrl:
1936 cfg.write("patterns =\n") 1925 cfg.write("patterns =\n")
1937 cfg.write(" {0}\n".format( 1926 cfg.write(" {0}\n".format(
1938 "\n ".join(lfPattern))) 1927 "\n ".join(lfPattern)))
1939 self.__monitorRepoIniFile(repoName) 1928 self.__monitorRepoIniFile(repoName)
1940 self.__iniFileChanged(cfgFile) 1929 self.__iniFileChanged(cfgFile)
1941 except OSError:
1942 pass
1943 self.repoEditor = MiniEditor(cfgFile, "Properties") 1930 self.repoEditor = MiniEditor(cfgFile, "Properties")
1944 self.repoEditor.show() 1931 self.repoEditor.show()
1945 1932
1946 def hgVerify(self): 1933 def hgVerify(self):
1947 """ 1934 """
2031 "glob:__pycache__", 2018 "glob:__pycache__",
2032 "glob:**.DS_Store", 2019 "glob:**.DS_Store",
2033 ] 2020 ]
2034 2021
2035 ignoreName = os.path.join(name, Hg.IgnoreFileName) 2022 ignoreName = os.path.join(name, Hg.IgnoreFileName)
2036 if os.path.exists(ignoreName): 2023 res = (
2037 res = E5MessageBox.yesNo( 2024 E5MessageBox.yesNo(
2038 self.__ui, 2025 self.__ui,
2039 self.tr("Create .hgignore file"), 2026 self.tr("Create .hgignore file"),
2040 self.tr("""<p>The file <b>{0}</b> exists already.""" 2027 self.tr("""<p>The file <b>{0}</b> exists already."""
2041 """ Overwrite it?</p>""").format(ignoreName), 2028 """ Overwrite it?</p>""").format(ignoreName),
2042 icon=E5MessageBox.Warning) 2029 icon=E5MessageBox.Warning)
2043 else: 2030 if os.path.exists(ignoreName) else
2044 res = True 2031 True
2032 )
2045 if res: 2033 if res:
2046 try: 2034 try:
2047 # create a .hgignore file 2035 # create a .hgignore file
2048 with open(ignoreName, "w") as ignore: 2036 with open(ignoreName, "w") as ignore:
2049 ignore.write("\n".join(ignorePatterns)) 2037 ignore.write("\n".join(ignorePatterns))
2422 data = dlg.getData() 2410 data = dlg.getData()
2423 2411
2424 if data: 2412 if data:
2425 revs, phase, force = data 2413 revs, phase, force = data
2426 2414
2415 if phase not in ("p", "d", "s"):
2416 raise ValueError("Invalid phase given.")
2417
2427 args = self.initCommand("phase") 2418 args = self.initCommand("phase")
2428 if phase == "p": 2419 if phase == "p":
2429 args.append("--public") 2420 args.append("--public")
2430 elif phase == "d": 2421 elif phase == "d":
2431 args.append("--draft") 2422 args.append("--draft")
2432 elif phase == "s": 2423 else:
2433 args.append("--secret") 2424 args.append("--secret")
2434 else: 2425
2435 raise ValueError("Invalid phase given.")
2436 if force: 2426 if force:
2437 args.append("--force") 2427 args.append("--force")
2438 for rev in revs: 2428 for rev in revs:
2439 args.append(rev) 2429 args.append(rev)
2440 2430
3171 @param incoming flag indicating to get incoming bookmarks (boolean) 3161 @param incoming flag indicating to get incoming bookmarks (boolean)
3172 @return list of bookmarks (list of string) 3162 @return list of bookmarks (list of string)
3173 """ 3163 """
3174 bookmarksList = [] 3164 bookmarksList = []
3175 3165
3176 if incoming: 3166 args = (
3177 args = self.initCommand("incoming") 3167 self.initCommand("incoming")
3178 else: 3168 if incoming else
3179 args = self.initCommand("outgoing") 3169 self.initCommand("outgoing")
3170 )
3180 args.append('--bookmarks') 3171 args.append('--bookmarks')
3181 3172
3182 client = self.getClient() 3173 client = self.getClient()
3183 output = client.runcommand(args)[0] 3174 output = client.runcommand(args)[0]
3184 3175

eric ide

mercurial