Mercurial > hg
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']) |