comparison hglib/client.py @ 5:3182303f388d

client: rawcommand, more convenient helper to run commands instead of outputruncommand
author Idan Kamara <idankk86@gmail.com>
date Tue, 09 Aug 2011 00:39:27 +0300
parents a3a9cf58801f
children 96f8c5095e2e
comparison
equal deleted inserted replaced
4:a3a9cf58801f 5:3182303f388d
106 % channel) 106 % channel)
107 # optional channel 107 # optional channel
108 else: 108 else:
109 pass 109 pass
110 110
111 def outputruncommand(self, args, inchannels = {}, raiseonerror=True): 111 def rawcommand(self, args, eh=None, prompt=None, input=None):
112 ''' run the command specified by args, returning (ret, output, error) ''' 112 """
113 args is the cmdline (usually built using util.cmdbuilder)
114
115 eh is an error handler that is passed the return code, stdout and stderr
116 If no eh is given, we raise a CommandError if ret != 0
117
118 prompt is used to reply to prompts by the server
119 It receives the max number of bytes to return and the contents of stdout
120 received so far
121
122 input is used to reply to bulk data requests by the server
123 It receives the max number of bytes to return
124 """
125
113 out, err = cStringIO.StringIO(), cStringIO.StringIO() 126 out, err = cStringIO.StringIO(), cStringIO.StringIO()
114 outchannels = {'o' : out.write, 'e' : err.write} 127 outchannels = {'o' : out.write, 'e' : err.write}
128
129 inchannels = {}
130 if prompt is not None:
131 def func(size):
132 reply = prompt(size, out.getvalue())
133 return str(reply)
134 inchannels['L'] = func
135 if input is not None:
136 inchannels['I'] = input
137
115 ret = self.runcommand(args, inchannels, outchannels) 138 ret = self.runcommand(args, inchannels, outchannels)
116 if ret and raiseonerror: 139 out, err = out.getvalue(), err.getvalue()
117 raise error.CommandError(args, ret, out.getvalue(), err.getvalue()) 140
118 return ret, out.getvalue(), err.getvalue() 141 if ret:
142 if eh is None:
143 raise error.CommandError(args, ret, out, err)
144 else:
145 return eh(ret, out, err)
146 return out
119 147
120 def close(self): 148 def close(self):
121 self.server.stdin.close() 149 self.server.stdin.close()
122 self.server.wait() 150 self.server.wait()
123 ret = self.server.returncode 151 ret = self.server.returncode
138 166
139 def config(self, refresh=False): 167 def config(self, refresh=False):
140 if not self._config or refresh: 168 if not self._config or refresh:
141 self._config.clear() 169 self._config.clear()
142 170
143 ret, out, err = self.outputruncommand(['showconfig']) 171 out = self.rawcommand(['showconfig'])
144 if ret:
145 raise error.CommandError(['showconfig'], ret, out, err)
146 172
147 for entry in cStringIO.StringIO(out): 173 for entry in cStringIO.StringIO(out):
148 k, v = entry.rstrip().split('=', 1) 174 k, v = entry.rstrip().split('=', 1)
149 section, name = k.split('.', 1) 175 section, name = k.split('.', 1)
150 self._config.setdefault(section, {})[name] = v 176 self._config.setdefault(section, {})[name] = v
151 177
152 return self._config 178 return self._config
153 179
154 def status(self): 180 def status(self):
155 ret, out = self.outputruncommand(['status', '-0']) 181 out = self.rawcommand(['status', '-0'])
156 182
157 d = dict((c, []) for c in 'MARC!?I') 183 d = dict((c, []) for c in 'MARC!?I')
158 184
159 for entry in out.split('\0'): 185 for entry in out.split('\0'):
160 if entry: 186 if entry:
164 return d 190 return d
165 191
166 def log(self, revrange=None): 192 def log(self, revrange=None):
167 args = cmdbuilder('log', style=hgclient.revstyle, rev=revrange) 193 args = cmdbuilder('log', style=hgclient.revstyle, rev=revrange)
168 194
169 out = self.outputruncommand(args)[1] 195 out = self.rawcommand(args)
170 out = out.split('\0')[:-1] 196 out = out.split('\0')[:-1]
171 197
172 return self._parserevs(out) 198 return self._parserevs(out)
173 199
174 def incoming(self, revrange=None, path=None): 200 def incoming(self, revrange=None, path=None):
175 args = cmdbuilder('incoming', 201 args = cmdbuilder('incoming',
176 path, 202 path,
177 style=hgclient.revstyle, rev=revrange) 203 style=hgclient.revstyle, rev=revrange)
178 204
179 ret, out, err = self.outputruncommand(args, raiseonerror=False) 205 def eh(ret, out, err):
180 if not ret: 206 if ret != 1:
181 out = self._eatlines(out, 2).split('\0')[:-1] 207 raise error.CommandError(args, ret, out, err)
182 return self._parserevs(out) 208
183 elif ret == 1: 209 out = self.rawcommand(args, eh=eh)
210 if not out:
184 return [] 211 return []
185 else: 212
186 raise error.CommandError(args, ret, out, err) 213 out = self._eatlines(out, 2).split('\0')[:-1]
214 return self._parserevs(out)
187 215
188 def outgoing(self, revrange=None, path=None): 216 def outgoing(self, revrange=None, path=None):
189 args = cmdbuilder('outgoing', 217 args = cmdbuilder('outgoing',
190 path, style=hgclient.revstyle, rev=revrange) 218 path, style=hgclient.revstyle, rev=revrange)
191 219
192 ret, out, err = self.outputruncommand(args, raiseonerror=False) 220 def eh(ret, out, err):
193 if not ret: 221 if ret != 1:
194 out = self._eatlines(out, 2).split('\0')[:-1] 222 raise error.CommandError(args, ret, out, err)
195 return self._parserevs(out) 223
196 elif ret == 1: 224 out = self.rawcommand(args, eh=eh)
225 if not out:
197 return [] 226 return []
198 else: 227
199 raise error.CommandError(args, ret, out, err) 228 out = self._eatlines(out, 2).split('\0')[:-1]
229 return self._parserevs(out)
200 230
201 def commit(self, message, addremove=False): 231 def commit(self, message, addremove=False):
202 args = cmdbuilder('commit', m=message, A=addremove) 232 args = cmdbuilder('commit', m=message, A=addremove)
203 233
204 self.outputruncommand(args) 234 self.rawcommand(args)
205 235
206 # hope the tip hasn't changed since we committed 236 # hope the tip hasn't changed since we committed
207 return self.tip() 237 return self.tip()
208 238
209 def import_(self, patch): 239 def import_(self, patch):
214 assert hasattr(patch, 'readline') 244 assert hasattr(patch, 'readline')
215 245
216 fp = patch 246 fp = patch
217 247
218 try: 248 try:
219 inchannels = {'I' : fp.read, 'L' : fp.readline} 249 def readline(size, output):
220 self.outputruncommand(cmdbuilder('import', _=True), inchannels) 250 return fp.readline(size)
251
252 self.rawcommand(cmdbuilder('import', _=True),
253 prompt=readline, input=fp.read)
221 finally: 254 finally:
222 if fp != patch: 255 if fp != patch:
223 fp.close() 256 fp.close()
224 257
225 def root(self): 258 def root(self):
226 return self.outputruncommand(['root'])[1].rstrip() 259 return self.rawcommand(['root']).rstrip()
227 260
228 def clone(self, source='.', dest=None, branch=None, updaterev=None, 261 def clone(self, source='.', dest=None, branch=None, updaterev=None,
229 revrange=None): 262 revrange=None):
230 args = cmdbuilder('clone', source, dest, b=branch, u=updaterev, r=revrange) 263 args = cmdbuilder('clone', source, dest, b=branch, u=updaterev, r=revrange)
231 self.outputruncommand(args) 264 self.rawcommand(args)
232 265
233 def tip(self): 266 def tip(self):
234 args = cmdbuilder('tip', style=hgclient.revstyle) 267 args = cmdbuilder('tip', style=hgclient.revstyle)
235 out = self.outputruncommand(args)[1] 268 out = self.rawcommand(args)
236 out = out.split('\0') 269 out = out.split('\0')
237 270
238 return self._parserevs(out)[0] 271 return self._parserevs(out)[0]
239 272
240 def branch(self, name=None): 273 def branch(self, name=None):
241 if not name: 274 if not name:
242 return self.outputruncommand(['branch'])[1].rstrip() 275 return self.rawcommand(['branch']).rstrip()
243 276
244 def branches(self): 277 def branches(self):
245 out = self.outputruncommand(['branches'])[1] 278 out = self.rawcommand(['branches'])
246 branches = {} 279 branches = {}
247 for line in out.rstrip().split('\n'): 280 for line in out.rstrip().split('\n'):
248 branch, revnode = line.split() 281 branch, revnode = line.split()
249 branches[branch] = self.log(revrange=[revnode.split(':')[0]])[0] 282 branches[branch] = self.log(revrange=[revnode.split(':')[0]])[0]
250 283
251 return branches 284 return branches
252 285
253 def paths(self, name=None): 286 def paths(self, name=None):
254 if not name: 287 if not name:
255 out = self.outputruncommand(['paths'])[1] 288 out = self.rawcommand(['paths'])
256 if not out: 289 if not out:
257 return {} 290 return {}
258 291
259 return dict([s.split(' = ') for s in out.rstrip().split('\n')]) 292 return dict([s.split(' = ') for s in out.rstrip().split('\n')])
260 else: 293 else:
261 args = cmdbuilder('paths', name) 294 args = cmdbuilder('paths', name)
262 ret, out, err = self.outputruncommand(args, raiseonerror=False) 295 out = self.rawcommand(args)
263 if ret:
264 raise error.CommandError(args, ret, out, err)
265 return out.rstrip() 296 return out.rstrip()
266 297
267 def cat(self, files, rev=None, output=None): 298 def cat(self, files, rev=None, output=None):
268 args = cmdbuilder('cat', *files, r=rev, o=output) 299 args = cmdbuilder('cat', *files, r=rev, o=output)
269 ret, out, err = self.outputruncommand(args) 300 out = self.rawcommand(args)
270 301
271 if not output: 302 if not output:
272 return out 303 return out