|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2014 - 2017 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the VCS status monitor thread class for Git. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 try: |
|
12 str = unicode |
|
13 except NameError: |
|
14 pass |
|
15 |
|
16 from PyQt5.QtCore import QProcess |
|
17 |
|
18 from VCS.StatusMonitorThread import VcsStatusMonitorThread |
|
19 |
|
20 import Preferences |
|
21 |
|
22 |
|
23 class GitStatusMonitorThread(VcsStatusMonitorThread): |
|
24 """ |
|
25 Class implementing the VCS status monitor thread class for Git. |
|
26 """ |
|
27 ConflictStates = ["AA", "AU", "DD", "DU", "UA", "UD", "UU"] |
|
28 |
|
29 def __init__(self, interval, project, vcs, parent=None): |
|
30 """ |
|
31 Constructor |
|
32 |
|
33 @param interval new interval in seconds (integer) |
|
34 @param project reference to the project object (Project) |
|
35 @param vcs reference to the version control object |
|
36 @param parent reference to the parent object (QObject) |
|
37 """ |
|
38 VcsStatusMonitorThread.__init__(self, interval, project, vcs, parent) |
|
39 |
|
40 self.__ioEncoding = Preferences.getSystem("IOEncoding") |
|
41 |
|
42 self.__client = None |
|
43 self.__useCommandLine = False |
|
44 |
|
45 def _performMonitor(self): |
|
46 """ |
|
47 Protected method implementing the monitoring action. |
|
48 |
|
49 This method populates the statusList member variable |
|
50 with a list of strings giving the status in the first column and the |
|
51 path relative to the project directory starting with the third column. |
|
52 The allowed status flags are: |
|
53 <ul> |
|
54 <li>"A" path was added but not yet comitted</li> |
|
55 <li>"M" path has local changes</li> |
|
56 <li>"O" path was removed</li> |
|
57 <li>"R" path was deleted and then re-added</li> |
|
58 <li>"U" path needs an update</li> |
|
59 <li>"Z" path contains a conflict</li> |
|
60 <li>" " path is back at normal</li> |
|
61 </ul> |
|
62 |
|
63 @return tuple of flag indicating successful operation (boolean) and |
|
64 a status message in case of non successful operation (string) |
|
65 """ |
|
66 self.shouldUpdate = False |
|
67 |
|
68 # step 1: get overall status |
|
69 args = self.vcs.initCommand("status") |
|
70 args.append('--porcelain') |
|
71 |
|
72 output = "" |
|
73 error = "" |
|
74 process = QProcess() |
|
75 process.setWorkingDirectory(self.projectDir) |
|
76 process.start('git', args) |
|
77 procStarted = process.waitForStarted(5000) |
|
78 if procStarted: |
|
79 finished = process.waitForFinished(300000) |
|
80 if finished and process.exitCode() == 0: |
|
81 output = str(process.readAllStandardOutput(), |
|
82 self.__ioEncoding, 'replace') |
|
83 else: |
|
84 process.kill() |
|
85 process.waitForFinished() |
|
86 error = str(process.readAllStandardError(), |
|
87 self.__ioEncoding, 'replace') |
|
88 else: |
|
89 process.kill() |
|
90 process.waitForFinished() |
|
91 error = self.tr("Could not start the Git process.") |
|
92 |
|
93 if error: |
|
94 return False, error |
|
95 |
|
96 states = {} |
|
97 for line in output.splitlines(): |
|
98 flags = line[:2] |
|
99 name = line[3:].split(" -> ")[-1] |
|
100 if flags in self.ConflictStates: |
|
101 states[name] = "Z" |
|
102 if flags[0] in "AMDR": |
|
103 if flags[0] == "D": |
|
104 status = "O" |
|
105 elif flags[0] == "R": |
|
106 status = "A" |
|
107 else: |
|
108 status = flags[0] |
|
109 states[name] = status |
|
110 elif flags[1] in "MD": |
|
111 if flags[1] == "D": |
|
112 status = "O" |
|
113 else: |
|
114 status = flags[1] |
|
115 states[name] = status |
|
116 |
|
117 # step 2: collect the status to be reported back |
|
118 for name in states: |
|
119 try: |
|
120 if self.reportedStates[name] != states[name]: |
|
121 self.statusList.append( |
|
122 "{0} {1}".format(states[name], name)) |
|
123 except KeyError: |
|
124 self.statusList.append("{0} {1}".format(states[name], name)) |
|
125 for name in self.reportedStates.keys(): |
|
126 if name not in states: |
|
127 self.statusList.append(" {0}".format(name)) |
|
128 self.reportedStates = states |
|
129 |
|
130 return True, \ |
|
131 self.tr("Git status checked successfully") |
|
132 |
|
133 def _shutdown(self): |
|
134 """ |
|
135 Protected method performing shutdown actions. |
|
136 """ |
|
137 if self.__client: |
|
138 self.__client.stopServer() |