16 |
16 |
17 class GitStatusMonitorThread(VcsStatusMonitorThread): |
17 class GitStatusMonitorThread(VcsStatusMonitorThread): |
18 """ |
18 """ |
19 Class implementing the VCS status monitor thread class for Git. |
19 Class implementing the VCS status monitor thread class for Git. |
20 """ |
20 """ |
|
21 |
21 ConflictStates = ["AA", "AU", "DD", "DU", "UA", "UD", "UU"] |
22 ConflictStates = ["AA", "AU", "DD", "DU", "UA", "UD", "UU"] |
22 |
23 |
23 def __init__(self, interval, project, vcs, parent=None): |
24 def __init__(self, interval, project, vcs, parent=None): |
24 """ |
25 """ |
25 Constructor |
26 Constructor |
26 |
27 |
27 @param interval new interval in seconds (integer) |
28 @param interval new interval in seconds (integer) |
28 @param project reference to the project object (Project) |
29 @param project reference to the project object (Project) |
29 @param vcs reference to the version control object |
30 @param vcs reference to the version control object |
30 @param parent reference to the parent object (QObject) |
31 @param parent reference to the parent object (QObject) |
31 """ |
32 """ |
32 VcsStatusMonitorThread.__init__(self, interval, project, vcs, parent) |
33 VcsStatusMonitorThread.__init__(self, interval, project, vcs, parent) |
33 |
34 |
34 self.__ioEncoding = Preferences.getSystem("IOEncoding") |
35 self.__ioEncoding = Preferences.getSystem("IOEncoding") |
35 |
36 |
36 self.__client = None |
37 self.__client = None |
37 self.__useCommandLine = False |
38 self.__useCommandLine = False |
38 |
39 |
39 def _performMonitor(self): |
40 def _performMonitor(self): |
40 """ |
41 """ |
41 Protected method implementing the monitoring action. |
42 Protected method implementing the monitoring action. |
42 |
43 |
43 This method populates the statusList member variable |
44 This method populates the statusList member variable |
44 with a list of strings giving the status in the first column and the |
45 with a list of strings giving the status in the first column and the |
45 path relative to the project directory starting with the third column. |
46 path relative to the project directory starting with the third column. |
46 The allowed status flags are: |
47 The allowed status flags are: |
47 <ul> |
48 <ul> |
53 <li>"Z" path contains a conflict</li> |
54 <li>"Z" path contains a conflict</li> |
54 <li>"?" path is not tracked</li> |
55 <li>"?" path is not tracked</li> |
55 <li>"!" path is missing</li> |
56 <li>"!" path is missing</li> |
56 <li>" " path is back at normal</li> |
57 <li>" " path is back at normal</li> |
57 </ul> |
58 </ul> |
58 |
59 |
59 @return tuple of flag indicating successful operation (boolean) and |
60 @return tuple of flag indicating successful operation (boolean) and |
60 a status message in case of non successful operation (string) |
61 a status message in case of non successful operation (string) |
61 """ |
62 """ |
62 self.shouldUpdate = False |
63 self.shouldUpdate = False |
63 |
64 |
64 # step 1: get overall status |
65 # step 1: get overall status |
65 args = self.vcs.initCommand("status") |
66 args = self.vcs.initCommand("status") |
66 args.append('--porcelain') |
67 args.append("--porcelain") |
67 |
68 |
68 output = "" |
69 output = "" |
69 error = "" |
70 error = "" |
70 process = QProcess() |
71 process = QProcess() |
71 process.setWorkingDirectory(self.projectDir) |
72 process.setWorkingDirectory(self.projectDir) |
72 process.start('git', args) |
73 process.start("git", args) |
73 procStarted = process.waitForStarted(5000) |
74 procStarted = process.waitForStarted(5000) |
74 if procStarted: |
75 if procStarted: |
75 finished = process.waitForFinished(300000) |
76 finished = process.waitForFinished(300000) |
76 if finished and process.exitCode() == 0: |
77 if finished and process.exitCode() == 0: |
77 output = str(process.readAllStandardOutput(), |
78 output = str( |
78 self.__ioEncoding, 'replace') |
79 process.readAllStandardOutput(), self.__ioEncoding, "replace" |
|
80 ) |
79 else: |
81 else: |
80 process.kill() |
82 process.kill() |
81 process.waitForFinished() |
83 process.waitForFinished() |
82 error = str(process.readAllStandardError(), |
84 error = str( |
83 self.__ioEncoding, 'replace') |
85 process.readAllStandardError(), self.__ioEncoding, "replace" |
|
86 ) |
84 else: |
87 else: |
85 process.kill() |
88 process.kill() |
86 process.waitForFinished() |
89 process.waitForFinished() |
87 error = self.tr("Could not start the Git process.") |
90 error = self.tr("Could not start the Git process.") |
88 |
91 |
89 if error: |
92 if error: |
90 return False, error |
93 return False, error |
91 |
94 |
92 states = {} |
95 states = {} |
93 for line in output.splitlines(): |
96 for line in output.splitlines(): |
94 flags = line[:2] |
97 flags = line[:2] |
95 name = line[3:].split(" -> ")[-1] |
98 name = line[3:].split(" -> ")[-1] |
96 if flags in self.ConflictStates: |
99 if flags in self.ConflictStates: |
109 else: |
112 else: |
110 status = flags[1] |
113 status = flags[1] |
111 states[name] = status |
114 states[name] = status |
112 elif flags == "??": |
115 elif flags == "??": |
113 states[name] = "?" |
116 states[name] = "?" |
114 |
117 |
115 # step 2: collect the status to be reported back |
118 # step 2: collect the status to be reported back |
116 for name in states: |
119 for name in states: |
117 try: |
120 try: |
118 if self.reportedStates[name] != states[name]: |
121 if self.reportedStates[name] != states[name]: |
119 self.statusList.append( |
122 self.statusList.append("{0} {1}".format(states[name], name)) |
120 "{0} {1}".format(states[name], name)) |
|
121 except KeyError: |
123 except KeyError: |
122 self.statusList.append("{0} {1}".format(states[name], name)) |
124 self.statusList.append("{0} {1}".format(states[name], name)) |
123 for name in self.reportedStates: |
125 for name in self.reportedStates: |
124 if name not in states: |
126 if name not in states: |
125 self.statusList.append(" {0}".format(name)) |
127 self.statusList.append(" {0}".format(name)) |
126 self.reportedStates = states |
128 self.reportedStates = states |
127 |
129 |
128 return ( |
130 return (True, self.tr("Git status checked successfully")) |
129 True, |
131 |
130 self.tr("Git status checked successfully") |
|
131 ) |
|
132 |
|
133 def _getInfo(self): |
132 def _getInfo(self): |
134 """ |
133 """ |
135 Protected method implementing the real info action. |
134 Protected method implementing the real info action. |
136 |
135 |
137 This method should be overridden and create a short info message to be |
136 This method should be overridden and create a short info message to be |
138 shown in the main window status bar right next to the status indicator. |
137 shown in the main window status bar right next to the status indicator. |
139 |
138 |
140 @return short info message |
139 @return short info message |
141 @rtype str |
140 @rtype str |
142 """ |
141 """ |
143 args = self.vcs.initCommand("show") |
142 args = self.vcs.initCommand("show") |
144 args.append("--abbrev-commit") |
143 args.append("--abbrev-commit") |
145 args.append("--format=%h %D") |
144 args.append("--format=%h %D") |
146 args.append("--no-patch") |
145 args.append("--no-patch") |
147 |
146 |
148 output = "" |
147 output = "" |
149 process = QProcess() |
148 process = QProcess() |
150 process.setWorkingDirectory(self.projectDir) |
149 process.setWorkingDirectory(self.projectDir) |
151 process.start('git', args) |
150 process.start("git", args) |
152 procStarted = process.waitForStarted(5000) |
151 procStarted = process.waitForStarted(5000) |
153 if procStarted: |
152 if procStarted: |
154 finished = process.waitForFinished(30000) |
153 finished = process.waitForFinished(30000) |
155 if finished and process.exitCode() == 0: |
154 if finished and process.exitCode() == 0: |
156 output = str(process.readAllStandardOutput(), |
155 output = str( |
157 Preferences.getSystem("IOEncoding"), |
156 process.readAllStandardOutput(), |
158 'replace') |
157 Preferences.getSystem("IOEncoding"), |
159 |
158 "replace", |
|
159 ) |
|
160 |
160 if output: |
161 if output: |
161 commitId, refs = output.splitlines()[0].strip().split(None, 1) |
162 commitId, refs = output.splitlines()[0].strip().split(None, 1) |
162 ref = refs.split(",", 1)[0] |
163 ref = refs.split(",", 1)[0] |
163 if "->" in ref: |
164 if "->" in ref: |
164 branch = ref.split("->", 1)[1].strip() |
165 branch = ref.split("->", 1)[1].strip() |
165 else: |
166 else: |
166 branch = self.tr("<detached>") |
167 branch = self.tr("<detached>") |
167 |
168 |
168 return self.tr("{0} / {1}", "branch, commit").format( |
169 return self.tr("{0} / {1}", "branch, commit").format(branch, commitId) |
169 branch, commitId) |
|
170 else: |
170 else: |
171 return "" |
171 return "" |
172 |
172 |
173 def _shutdown(self): |
173 def _shutdown(self): |
174 """ |
174 """ |
175 Protected method performing shutdown actions. |
175 Protected method performing shutdown actions. |
176 """ |
176 """ |
177 if self.__client: |
177 if self.__client: |