Mercurial > python-hglib
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 |