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
« 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######################################################################
10import re
11from dataclasses import dataclass, field
13from P4OO.Exceptions import P4Warning, P4Fatal
14from P4OO._SpecObj import _P4OOSpecObj
15from P4OO._Set import _P4OOSet
16from P4OO.Change import P4OOChangeSet
18@dataclass(unsafe_hash=True)
19class P4OOClient(_P4OOSpecObj):
20 """
21 Perforce Client Spec Object
23 id Required: No
25 Forcible: Yes
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
41 See Also:
42 Perforce Helix Core Command Reference:
43 https://www.perforce.com/manuals/cmdref/Content/CmdRef/p4_client.html
44 """
46 # Subclasses must define SPECOBJ_TYPE
47 _SPECOBJ_TYPE = 'client'
49 def addFiles(self, *fileSpec, **kwargs):
50 """ Add the specified files as new """
52 p4Output = None
53 p4Output = self._runCommand('add', p4client=self, files=fileSpec,
54 **kwargs)
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)
66 return p4Output
68 def editFiles(self, *fileSpec, **kwargs):
69 """ Open the specified files for edit """
71 p4Output = None
72 p4Output = self._runCommand('edit', p4client=self, files=fileSpec,
73 **kwargs)
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)
85 return p4Output
87 def getChanges(self, status=None):
88 """ Find all changes this client "has" sync'd """
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)
95 def getLatestChange(self):
96 """ find the latest change this client "has" """
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)
103 # We only expect one result, we only return one result.
104 return p4Changes[0]
106 def getOpenedFiles(self, user=None):
107 """ Return a P4OOFileSet of files opened in this client. """
109 return self._runCommand('opened', user=user, client=self)
111 def submitChange(self, *fileSpec, **kwargs):
112 """ Add the specified files as new """
114 p4Output = None
115 p4Output = self._runCommand('submit', p4client=self, files=fileSpec,
116 **kwargs)
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)
128 return p4Output
130 def sync(self, *fileSpec, **kwargs):
131 """ Sync the client (`p4 sync`) using the optional supplied
132 fileSpec(s)
133 """
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
145 return p4Output
147 def reopenFiles(self):
148 """
149 Reopen all opened files in this client to be owned by the current user
151 - First removes `host` attribute from client spec if specified
153 Returns:
154 (list(str)): Output returned from `_P4OOBase._runCommand('reopen')`
156 See Also:
157 Perforce Helix Core Command Reference:
158 https://www.perforce.com/manuals/cmdref/Content/CmdRef/p4_reopen.html
159 """
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
169 def revertOpenedFiles(self):
170 """
171 Revert all opened files in this client
173 - First reopens all files to be owned by the current user
175 Returns:
176 (list(str)): Output returned from `_P4OOBase._runCommand('revert')`
178 See Also:
179 Perforce Helix Core Command Reference:
180 https://www.perforce.com/manuals/cmdref/Content/CmdRef/p4_revert.html
181 """
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
191 def deleteWithVengeance(self):
192 """
193 Performs all operations necessary to remove a client.
195 - Remove `host` attribute
196 - Remove all pending changelists
197 - Remove client spec
199 Returns:
200 (Boolean): Result from _P4OOSpecObj.deleteSpec()
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()
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)
221@dataclass
222class P4OOClientSet(_P4OOSet):
223 """ `P4OOSet` of `P4OOClient` objects """
225 def query(self, user: str=None, maxresults: int=None,
226 namefilter: str=None, **kwargs):
227 """
228 Executes `p4 clients` query
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
235 Returns:
236 (P4OOClientSet): `P4OOSet` of `P4OOClient` objects matching query
237 parameters
239 See Also:
240 Perforce Helix Core Command Reference:
241 https://www.perforce.com/manuals/cmdref/Content/CmdRef/p4_clients.html
242 """
244 return self._query(setObjType='clients', user=user,
245 maxresults=maxresults, namefilter=namefilter,
246 **kwargs)