eric7/Plugins/VcsPlugins/vcsMercurial/HgDiffGenerator.py

branch
eric7
changeset 8312
800c432b34c8
parent 8234
fcb6b4b96274
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2015 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a class to generate the output of the hg diff command.
8 """
9
10 import os
11
12 from PyQt5.QtCore import pyqtSignal, QObject
13
14 from E5Gui.E5OverrideCursor import E5OverrideCursor
15
16
17 class HgDiffGenerator(QObject):
18 """
19 Class implementing the generation of output of the hg diff command.
20
21 @signal finished() emitted when all processes have finished
22 """
23 finished = pyqtSignal()
24
25 def __init__(self, vcs, parent=None):
26 """
27 Constructor
28
29 @param vcs reference to the vcs object
30 @param parent parent widget (QWidget)
31 """
32 super().__init__(parent)
33
34 self.vcs = vcs
35
36 self.__hgClient = self.vcs.getClient()
37
38 def stopProcess(self):
39 """
40 Public slot to stop the diff process.
41 """
42 if self.__hgClient.isExecuting():
43 self.__hgClient.cancel()
44
45 def __getVersionArg(self, version):
46 """
47 Private method to get a hg revision argument for the given revision.
48
49 @param version revision (integer or string)
50 @return version argument (string)
51 """
52 if version == "WORKING":
53 return None
54 else:
55 return str(version).strip()
56
57 def start(self, fn, versions=None, bundle=None, qdiff=False):
58 """
59 Public slot to start the hg diff command.
60
61 @param fn filename to be diffed (string)
62 @param versions list of versions to be diffed (list of up to
63 2 strings or None)
64 @param bundle name of a bundle file (string)
65 @param qdiff flag indicating qdiff command shall be used (boolean)
66 @return flag indicating a successful start of the diff command
67 (boolean)
68 """
69 if qdiff:
70 args = self.vcs.initCommand("qdiff")
71 else:
72 args = self.vcs.initCommand("diff")
73
74 if self.vcs.hasSubrepositories():
75 args.append("--subrepos")
76
77 if bundle:
78 args.append('--repository')
79 args.append(bundle)
80 elif (
81 self.vcs.bundleFile and
82 os.path.exists(self.vcs.bundleFile)
83 ):
84 args.append('--repository')
85 args.append(self.vcs.bundleFile)
86
87 if versions is not None:
88 rev1 = self.__getVersionArg(versions[0])
89 rev2 = None
90 if len(versions) == 2:
91 rev2 = self.__getVersionArg(versions[1])
92
93 if rev1 is not None or rev2 is not None:
94 if self.vcs.version >= (5, 7, 0):
95 if rev1 is not None:
96 args += ["--from", rev1]
97 if rev2 is not None:
98 args += ["--to", rev2]
99 else:
100 args.append('-r')
101 if rev1 is not None and rev2 is not None:
102 args.append('{0}:{1}'.format(rev1, rev2))
103 elif rev2 is None:
104 args.append(rev1)
105 elif rev1 is None:
106 args.append(':{0}'.format(rev2))
107
108 if fn:
109 if isinstance(fn, list):
110 self.vcs.addArguments(args, fn)
111 else:
112 args.append(fn)
113
114 self.__oldFile = ""
115 self.__oldFileLine = -1
116 self.__fileSeparators = []
117 self.__output = []
118 self.__errors = []
119
120 with E5OverrideCursor():
121 out, err = self.__hgClient.runcommand(args)
122
123 if err:
124 self.__errors = err.splitlines(True)
125
126 if out:
127 self.__output = out.splitlines(True)
128 for lineno, line in enumerate(self.__output):
129 if line.startswith(("--- ", "+++ ")):
130 self.__processFileLine(lineno, line)
131 if self.__hgClient.wasCanceled():
132 break
133
134 self.__finish()
135
136 return True
137
138 def __finish(self):
139 """
140 Private slot called when the process finished or the user pressed
141 the button.
142 """
143 self.finished.emit()
144
145 def getResult(self):
146 """
147 Public method to return the result data.
148
149 @return tuple of lists of string containing lines of the diff, the
150 list of errors and a list of tuples of filenames and the line
151 into the diff output.
152 """
153 return (self.__output, self.__errors, self.__fileSeparators)
154
155 def __extractFileName(self, line):
156 """
157 Private method to extract the file name out of a file separator line.
158
159 @param line line to be processed (string)
160 @return extracted file name (string)
161 """
162 f = line.split(None, 1)[1]
163 f = f.rsplit(None, 6)[0]
164 f = "__NULL__" if f == "/dev/null" else f.split("/", 1)[1]
165 return f
166
167 def __processFileLine(self, lineno, line):
168 """
169 Private slot to process a line giving the old/new file.
170
171 @param lineno line number of line to be processed
172 @type int
173 @param line line to be processed
174 @type str
175 """
176 if line.startswith('---'):
177 self.__oldFileLine = lineno
178 self.__oldFile = self.__extractFileName(line)
179 else:
180 newFile = self.__extractFileName(line)
181 if self.__oldFile == "__NULL__":
182 self.__fileSeparators.append(
183 (newFile, newFile, self.__oldFileLine))
184 else:
185 self.__fileSeparators.append(
186 (self.__oldFile, newFile, self.__oldFileLine))

eric ide

mercurial