comparison contrib/phabricator.py @ 39650:d8f07b16abfc

phabricator: add support for using the vcr library to mock interactions I'll use this in an upcoming test. The decorator dancing in this is more complicated than I'd like, but it beats repeating all this code everywhere. Differential Revision: https://phab.mercurial-scm.org/D4600
author Augie Fackler <raf@durin42.com>
date Sat, 15 Sep 2018 00:20:03 -0400
parents 0dce1297dd01
children
comparison
equal deleted inserted replaced
39649:d6d094259d9c 39650:d8f07b16abfc
103 b'phabricator.action.updated': b'magenta', 103 b'phabricator.action.updated': b'magenta',
104 b'phabricator.desc': b'', 104 b'phabricator.desc': b'',
105 b'phabricator.drev': b'bold', 105 b'phabricator.drev': b'bold',
106 b'phabricator.node': b'', 106 b'phabricator.node': b'',
107 } 107 }
108
109 _VCR_FLAGS = [
110 (b'', b'test-vcr', b'',
111 _(b'Path to a vcr file. If nonexistent, will record a new vcr transcript'
112 b', otherwise will mock all http requests using the specified vcr file.'
113 b' (ADVANCED)'
114 )),
115 ]
116
117 def vcrcommand(name, flags, spec):
118 fullflags = flags + _VCR_FLAGS
119 def decorate(fn):
120 def inner(*args, **kwargs):
121 cassette = kwargs.pop(r'test_vcr', None)
122 if cassette:
123 import hgdemandimport
124 with hgdemandimport.deactivated():
125 import vcr as vcrmod
126 import vcr.stubs as stubs
127 vcr = vcrmod.VCR(
128 serializer=r'json',
129 custom_patches=[
130 (urlmod, 'httpconnection', stubs.VCRHTTPConnection),
131 (urlmod, 'httpsconnection', stubs.VCRHTTPSConnection),
132 ])
133 with vcr.use_cassette(cassette):
134 return fn(*args, **kwargs)
135 return fn(*args, **kwargs)
136 inner.__name__ = fn.__name__
137 return command(name, fullflags, spec)(inner)
138 return decorate
108 139
109 def urlencodenested(params): 140 def urlencodenested(params):
110 """like urlencode, but works with nested parameters. 141 """like urlencode, but works with nested parameters.
111 142
112 For example, if params is {'a': ['b', 'c'], 'd': {'e': 'f'}}, it will be 143 For example, if params is {'a': ['b', 'c'], 'd': {'e': 'f'}}, it will be
213 msg = (_(b'Conduit Error (%s): %s') 244 msg = (_(b'Conduit Error (%s): %s')
214 % (parsed[r'error_code'], parsed[r'error_info'])) 245 % (parsed[r'error_code'], parsed[r'error_info']))
215 raise error.Abort(msg) 246 raise error.Abort(msg)
216 return parsed[r'result'] 247 return parsed[r'result']
217 248
218 @command(b'debugcallconduit', [], _(b'METHOD')) 249 @vcrcommand(b'debugcallconduit', [], _(b'METHOD'))
219 def debugcallconduit(ui, repo, name): 250 def debugcallconduit(ui, repo, name):
220 """call Conduit API 251 """call Conduit API
221 252
222 Call parameters are read from stdin as a JSON blob. Result will be written 253 Call parameters are read from stdin as a JSON blob. Result will be written
223 to stdout as a JSON blob. 254 to stdout as a JSON blob.
450 if unresolved: 481 if unresolved:
451 raise error.Abort(_(b'unknown username: %s') 482 raise error.Abort(_(b'unknown username: %s')
452 % b' '.join(sorted(unresolved))) 483 % b' '.join(sorted(unresolved)))
453 return [entry[r'phid'] for entry in data] 484 return [entry[r'phid'] for entry in data]
454 485
455 @command(b'phabsend', 486 @vcrcommand(b'phabsend',
456 [(b'r', b'rev', [], _(b'revisions to send'), _(b'REV')), 487 [(b'r', b'rev', [], _(b'revisions to send'), _(b'REV')),
457 (b'', b'amend', True, _(b'update commit messages')), 488 (b'', b'amend', True, _(b'update commit messages')),
458 (b'', b'reviewer', [], _(b'specify reviewers')), 489 (b'', b'reviewer', [], _(b'specify reviewers')),
459 (b'', b'confirm', None, _(b'ask for confirmation before sending'))], 490 (b'', b'confirm', None, _(b'ask for confirmation before sending'))],
460 _(b'REV [OPTIONS]')) 491 _(b'REV [OPTIONS]'))
907 header += b'# %s %s\n' % (_metanamemap[k], meta[k]) 938 header += b'# %s %s\n' % (_metanamemap[k], meta[k])
908 939
909 content = b'%s%s\n%s' % (header, desc, body) 940 content = b'%s%s\n%s' % (header, desc, body)
910 write(encoding.unitolocal(content)) 941 write(encoding.unitolocal(content))
911 942
912 @command(b'phabread', 943 @vcrcommand(b'phabread',
913 [(b'', b'stack', False, _(b'read dependencies'))], 944 [(b'', b'stack', False, _(b'read dependencies'))],
914 _(b'DREVSPEC [OPTIONS]')) 945 _(b'DREVSPEC [OPTIONS]'))
915 def phabread(ui, repo, spec, **opts): 946 def phabread(ui, repo, spec, **opts):
916 """print patches from Phabricator suitable for importing 947 """print patches from Phabricator suitable for importing
917 948
934 if opts.get(b'stack'): 965 if opts.get(b'stack'):
935 spec = b':(%s)' % spec 966 spec = b':(%s)' % spec
936 drevs = querydrev(repo, spec) 967 drevs = querydrev(repo, spec)
937 readpatch(repo, drevs, ui.write) 968 readpatch(repo, drevs, ui.write)
938 969
939 @command(b'phabupdate', 970 @vcrcommand(b'phabupdate',
940 [(b'', b'accept', False, _(b'accept revisions')), 971 [(b'', b'accept', False, _(b'accept revisions')),
941 (b'', b'reject', False, _(b'reject revisions')), 972 (b'', b'reject', False, _(b'reject revisions')),
942 (b'', b'abandon', False, _(b'abandon revisions')), 973 (b'', b'abandon', False, _(b'abandon revisions')),
943 (b'', b'reclaim', False, _(b'reclaim revisions')), 974 (b'', b'reclaim', False, _(b'reclaim revisions')),
944 (b'm', b'comment', b'', _(b'comment on the last revision')), 975 (b'm', b'comment', b'', _(b'comment on the last revision')),