Coverage for src/P4OO/Client.py: 35%

66 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-09-07 17:17 +0000

1###################################################################### 

2# Copyright (c)2011-2012,2015,2024 David L. Armstrong. 

3# Copyright (c)2012, Cisco Systems, Inc. 

4# 

5# P4OO.Client.py 

6# 

7###################################################################### 

8 

9 

10import re 

11from dataclasses import dataclass, field 

12 

13from P4OO.Exceptions import P4Warning, P4Fatal 

14from P4OO._SpecObj import _P4OOSpecObj 

15from P4OO._Set import _P4OOSet 

16from P4OO.Change import P4OOChangeSet 

17 

18@dataclass(unsafe_hash=True) 

19class P4OOClient(_P4OOSpecObj): 

20 """ 

21 Perforce Client Spec Object 

22 

23 id Required: No 

24 

25 Forcible: Yes 

26 

27 Attributes: 

28 client (str): Name of the client 

29 owner (P4OOUser): User that created the client spec 

30 description (str): Description field 

31 host (str): Name of the host where this client root exists 

32 root (str): Root directory on <host> where client exists 

33 altroots (str): Alternate directories to locate root 

34 options (str): Client options (see Command Reference for details) 

35 submitoptions (str): How `submit` should handle unchanged files 

36 lineend (str): [`local`|`unix`|`mac`|`win`|`share`] CRLF handling 

37 view (str): View spec mappings 

38 update (datetime): Time of last update to the spec 

39 access (datetime): Time of last access of the spec 

40 

41 See Also: 

42 Perforce Helix Core Command Reference: 

43 https://www.perforce.com/manuals/cmdref/Content/CmdRef/p4_client.html 

44 """ 

45 

46 # Subclasses must define SPECOBJ_TYPE 

47 _SPECOBJ_TYPE = 'client' 

48 

49 def addFiles(self, *fileSpec, **kwargs): 

50 """ Add the specified files as new """ 

51 

52 p4Output = None 

53 p4Output = self._runCommand('add', p4client=self, files=fileSpec, 

54 **kwargs) 

55 

56# TODO error checking 

57# try: 

58# p4Output = self._runCommand('add', p4client=self, files=fileSpec, 

59# **kwargs) 

60# except P4Warning as e: 

61# if re.search(r"\nWARNING: File\(s\) up-to-date\.$", str(e)): 

62# pass 

63# else: 

64# raise(e) 

65 

66 return p4Output 

67 

68 def editFiles(self, *fileSpec, **kwargs): 

69 """ Open the specified files for edit """ 

70 

71 p4Output = None 

72 p4Output = self._runCommand('edit', p4client=self, files=fileSpec, 

73 **kwargs) 

74 

75# TODO error checking 

76# try: 

77# p4Output = self._runCommand('add', p4client=self, files=fileSpec, 

78# **kwargs) 

79# except P4Warning as e: 

80# if re.search(r"\nWARNING: File\(s\) up-to-date\.$", str(e)): 

81# pass 

82# else: 

83# raise(e) 

84 

85 return p4Output 

86 

87 def getChanges(self, status=None): 

88 """ Find all changes this client "has" sync'd """ 

89 

90 # Asking a Client for its changes is implemented as querying 

91 # Changes filtered by Client 

92 changeSet = P4OOChangeSet(_p4Conn=self._getP4Connection()) 

93 return changeSet.query(client=self, status=status) 

94 

95 def getLatestChange(self): 

96 """ find the latest change this client "has" """ 

97 

98 # Asking a Client for its latest change is just querying the first 

99 # change record. Nifty. 

100 changeSet = P4OOChangeSet(_p4Conn=self._getP4Connection()) 

101 p4Changes = changeSet.query(files="#have", maxresults=1, client=self) 

102 

103 # We only expect one result, we only return one result. 

104 return p4Changes[0] 

105 

106 def getOpenedFiles(self, user=None): 

107 """ Return a P4OOFileSet of files opened in this client. """ 

108 

109 return self._runCommand('opened', user=user, client=self) 

110 

111 def submitChange(self, *fileSpec, **kwargs): 

112 """ Add the specified files as new """ 

113 

114 p4Output = None 

115 p4Output = self._runCommand('submit', p4client=self, files=fileSpec, 

116 **kwargs) 

117 

118# TODO error checking 

119# try: 

120# p4Output = self._runCommand('add', p4client=self, 

121# files=fileSpec, **kwargs) 

122# except P4Warning as e: 

123# if re.search(r"\nWARNING: File\(s\) up-to-date\.$", str(e)): 

124# pass 

125# else: 

126# raise(e) 

127 

128 return p4Output 

129 

130 def sync(self, *fileSpec, **kwargs): 

131 """ Sync the client (`p4 sync`) using the optional supplied 

132 fileSpec(s) 

133 """ 

134 

135 p4Output = None 

136 try: 

137 p4Output = self._runCommand('sync', p4client=self, 

138 files=fileSpec, **kwargs) 

139 except P4Warning as e: 

140 if re.search(r"\nWARNING: File\(s\) up-to-date\.$", str(e)): 

141 pass 

142 else: 

143 raise e 

144 

145 return p4Output 

146 

147 def reopenFiles(self): 

148 """ 

149 Reopen all opened files in this client to be owned by the current user 

150 

151 - First removes `host` attribute from client spec if specified 

152 

153 Returns: 

154 (list(str)): Output returned from `_P4OOBase._runCommand('reopen')` 

155 

156 See Also: 

157 Perforce Helix Core Command Reference: 

158 https://www.perforce.com/manuals/cmdref/Content/CmdRef/p4_reopen.html 

159 """ 

160 

161 self._delSpecAttr('host') 

162 self.saveSpec() 

163 try: 

164 return self._runCommand('reopen', files="//%s/..." 

165 % self._getSpecID(), p4client=self) 

166 except P4Warning: 

167 return True 

168 

169 def revertOpenedFiles(self): 

170 """ 

171 Revert all opened files in this client 

172 

173 - First reopens all files to be owned by the current user 

174 

175 Returns: 

176 (list(str)): Output returned from `_P4OOBase._runCommand('revert')` 

177 

178 See Also: 

179 Perforce Helix Core Command Reference: 

180 https://www.perforce.com/manuals/cmdref/Content/CmdRef/p4_revert.html 

181 """ 

182 

183 self.reopenFiles() 

184 try: 

185 return self._runCommand('revert', noclientrefresh=True, 

186 files="//%s/..." % self._getSpecID(), 

187 p4client=self) 

188 except P4Warning: 

189 return True 

190 

191 def deleteWithVengeance(self): 

192 """ 

193 Performs all operations necessary to remove a client. 

194 

195 - Remove `host` attribute 

196 - Remove all pending changelists 

197 - Remove client spec 

198 

199 Returns: 

200 (Boolean): Result from _P4OOSpecObj.deleteSpec() 

201 

202 See Also: 

203 Perforce Helix Core Knowledge Base: 

204 https://portal.perforce.com/s/article/1283 

205 """ 

206 try: 

207 return self.deleteSpec(force=True) 

208 except P4Fatal: 

209 # First, simplify things by removing any Host spec attr for 

210 # this client 

211 self._delSpecAttr('host') 

212 self.saveSpec() 

213 

214 # Next try removing pending changes, then try spec again 

215 changes = self.getChanges(status="pending") 

216 for change in changes: 

217 change.deleteWithVengeance() 

218 return self.deleteSpec(force=True) 

219 

220 

221@dataclass 

222class P4OOClientSet(_P4OOSet): 

223 """ `P4OOSet` of `P4OOClient` objects """ 

224 

225 def query(self, user: str=None, maxresults: int=None, 

226 namefilter: str=None, **kwargs): 

227 """ 

228 Executes `p4 clients` query 

229 

230 Args: 

231 user (P4OOUser | str, optional): The user that created the change 

232 maxresults (int, optional): Return only the first [max] results 

233 namefilter (str, optional): Case-sensitive filter on client name 

234 

235 Returns: 

236 (P4OOClientSet): `P4OOSet` of `P4OOClient` objects matching query 

237 parameters 

238 

239 See Also: 

240 Perforce Helix Core Command Reference: 

241 https://www.perforce.com/manuals/cmdref/Content/CmdRef/p4_clients.html 

242 """ 

243 

244 return self._query(setObjType='clients', user=user, 

245 maxresults=maxresults, namefilter=namefilter, 

246 **kwargs)