comparison contrib/phabricator.py @ 33442:3ab0d5767b54

phabricator: finding old nodes in batch This allows us to do extra sanity checks using batch APIs to prevent updating a wrong revision, which could happen when people switch Phabricator instances and having stale tags living in the repo. Differential Revision: https://phab.mercurial-scm.org/D34
author Jun Wu <quark@fb.com>
date Mon, 10 Jul 2017 13:50:50 -0700
parents de7c6ec27d99
children e48082e0a8d5
comparison
equal deleted inserted replaced
33441:de7c6ec27d99 33442:3ab0d5767b54
137 137
138 _differentialrevisiontagre = re.compile('\AD([1-9][0-9]*)\Z') 138 _differentialrevisiontagre = re.compile('\AD([1-9][0-9]*)\Z')
139 _differentialrevisiondescre = re.compile( 139 _differentialrevisiondescre = re.compile(
140 '^Differential Revision:.*D([1-9][0-9]*)$', re.M) 140 '^Differential Revision:.*D([1-9][0-9]*)$', re.M)
141 141
142 def getmapping(ctx): 142 def getoldnodedrevmap(repo, nodelist):
143 """return (node, associated Differential Revision ID) or (None, None) 143 """find previous nodes that has been sent to Phabricator
144
145 return {node: (oldnode or None, Differential Revision ID)}
146 for node in nodelist with known previous sent versions, or associated
147 Differential Revision IDs.
144 148
145 Examines all precursors and their tags. Tags with format like "D1234" are 149 Examines all precursors and their tags. Tags with format like "D1234" are
146 considered a match and the node with that tag, and the number after "D" 150 considered a match and the node with that tag, and the number after "D"
147 (ex. 1234) will be returned. 151 (ex. 1234) will be returned.
148 152
149 If tags are not found, examine commit message. The "Differential Revision:" 153 If tags are not found, examine commit message. The "Differential Revision:"
150 line could associate this changeset to a Differential Revision. 154 line could associate this changeset to a Differential Revision.
151 """ 155 """
152 unfi = ctx.repo().unfiltered() 156 url, token = readurltoken(repo)
157 unfi = repo.unfiltered()
153 nodemap = unfi.changelog.nodemap 158 nodemap = unfi.changelog.nodemap
154 159
155 # Check tags like "D123" 160 result = {} # {node: (oldnode or None, drev)}
156 for n in obsolete.allprecursors(unfi.obsstore, [ctx.node()]): 161 for node in nodelist:
157 if n in nodemap: 162 ctx = unfi[node]
158 for tag in unfi.nodetags(n): 163 # Check tags like "D123"
159 m = _differentialrevisiontagre.match(tag) 164 for n in obsolete.allprecursors(unfi.obsstore, [node]):
160 if m: 165 if n in nodemap:
161 return n, int(m.group(1)) 166 for tag in unfi.nodetags(n):
162 167 m = _differentialrevisiontagre.match(tag)
163 # Check commit message 168 if m:
164 m = _differentialrevisiondescre.search(ctx.description()) 169 result[node] = (n, int(m.group(1)))
165 if m: 170 continue
166 return None, int(m.group(1)) 171
167 172 # Check commit message
168 return None, None 173 m = _differentialrevisiondescre.search(ctx.description())
174 if m:
175 result[node] = (None, int(m.group(1)))
176
177 return result
169 178
170 def getdiff(ctx, diffopts): 179 def getdiff(ctx, diffopts):
171 """plain-text diff without header (user, commit message, etc)""" 180 """plain-text diff without header (user, commit message, etc)"""
172 output = util.stringio() 181 output = util.stringio()
173 for chunk, _label in patch.diffui(ctx.repo(), ctx.p1().node(), ctx.node(), 182 for chunk, _label in patch.diffui(ctx.repo(), ctx.p1().node(), ctx.node(),
272 revs = scmutil.revrange(repo, revs) 281 revs = scmutil.revrange(repo, revs)
273 282
274 if not revs: 283 if not revs:
275 raise error.Abort(_('phabsend requires at least one changeset')) 284 raise error.Abort(_('phabsend requires at least one changeset'))
276 285
286 oldnodedrev = getoldnodedrevmap(repo, [repo[r].node() for r in revs])
287
277 # Send patches one by one so we know their Differential Revision IDs and 288 # Send patches one by one so we know their Differential Revision IDs and
278 # can provide dependency relationship 289 # can provide dependency relationship
279 lastrevid = None 290 lastrevid = None
280 for rev in revs: 291 for rev in revs:
281 ui.debug('sending rev %d\n' % rev) 292 ui.debug('sending rev %d\n' % rev)
282 ctx = repo[rev] 293 ctx = repo[rev]
283 294
284 # Get Differential Revision ID 295 # Get Differential Revision ID
285 oldnode, revid = getmapping(ctx) 296 oldnode, revid = oldnodedrev.get(ctx.node(), (None, None))
286 if oldnode != ctx.node(): 297 if oldnode != ctx.node():
287 # Create or update Differential Revision 298 # Create or update Differential Revision
288 revision = createdifferentialrevision(ctx, revid, lastrevid, 299 revision = createdifferentialrevision(ctx, revid, lastrevid,
289 oldnode) 300 oldnode)
290 newrevid = int(revision[r'object'][r'id']) 301 newrevid = int(revision[r'object'][r'id'])