comparison hgext/phabricator.py @ 44774:c1c922391314 stable

phabricator: ensure that `phabsend` is given a contiguous, linear commit range Supplying a non-linear range was another orphan factory. While in theory there could be a use case for skipping over garbage commits (like adding debugging) and getting the valuable commits extracted out at the same time as posting a review, it seems far more likely that specifying a non-linear range is a user error. This is another case of issue6045, but predates both 0680b8a1992a and 601ce5392cb0. Neither the `--no-amend` case nor resubmitting a previously submitted commit would cause orphans. But for the sake of simplicity and to keep the parents tracked on Phabricator in the proper state, ban missing commits unconditionally. Differential Revision: https://phab.mercurial-scm.org/D8454
author Matt Harbison <matt_harbison@yahoo.com>
date Thu, 16 Apr 2020 19:05:25 -0400
parents 601ce5392cb0
children 11592ce6a711
comparison
equal deleted inserted replaced
44772:5e788dc7fb5d 44774:c1c922391314
1305 ctxs = [repo[rev] for rev in revs] 1305 ctxs = [repo[rev] for rev in revs]
1306 1306
1307 if any(c for c in ctxs if c.obsolete()): 1307 if any(c for c in ctxs if c.obsolete()):
1308 raise error.Abort(_(b"obsolete commits cannot be posted for review")) 1308 raise error.Abort(_(b"obsolete commits cannot be posted for review"))
1309 1309
1310 # Ensure the local commits are an unbroken range. The semantics of the
1311 # --fold option implies this, and the auto restacking of orphans requires
1312 # it. Otherwise A+C in A->B->C will cause B to be orphaned, and C' to
1313 # get A' as a parent.
1314 def _fail_nonlinear_revs(revs, skiprev, revtype):
1315 badnodes = [repo[r].node() for r in revs if r != skiprev]
1316 raise error.Abort(
1317 _(b"cannot phabsend multiple %s revisions: %s")
1318 % (revtype, scmutil.nodesummaries(repo, badnodes)),
1319 hint=_(b"the revisions must form a linear chain"),
1320 )
1321
1322 heads = repo.revs(b'heads(%ld)', revs)
1323 if len(heads) > 1:
1324 _fail_nonlinear_revs(heads, heads.max(), b"head")
1325
1326 roots = repo.revs(b'roots(%ld)', revs)
1327 if len(roots) > 1:
1328 _fail_nonlinear_revs(roots, roots.min(), b"root")
1329
1310 fold = opts.get(b'fold') 1330 fold = opts.get(b'fold')
1311 if fold: 1331 if fold:
1312 if len(revs) == 1: 1332 if len(revs) == 1:
1313 # TODO: just switch to --no-fold instead? 1333 # TODO: just switch to --no-fold instead?
1314 raise error.Abort(_(b"cannot fold a single revision")) 1334 raise error.Abort(_(b"cannot fold a single revision"))
1319 # lock the repo and ensure that the range is editable, but that would 1339 # lock the repo and ensure that the range is editable, but that would
1320 # make the code pretty convoluted. The default behavior of `arc` is to 1340 # make the code pretty convoluted. The default behavior of `arc` is to
1321 # create a new review anyway. 1341 # create a new review anyway.
1322 if not opts.get(b"amend"): 1342 if not opts.get(b"amend"):
1323 raise error.Abort(_(b"cannot fold with --no-amend")) 1343 raise error.Abort(_(b"cannot fold with --no-amend"))
1324
1325 # Ensure the local commits are an unbroken range
1326 revrange = repo.revs(b'(first(%ld)::last(%ld))', revs, revs)
1327 if any(r for r in revs if r not in revrange) or any(
1328 r for r in revrange if r not in revs
1329 ):
1330 raise error.Abort(_(b"cannot fold non-linear revisions"))
1331 1344
1332 # It might be possible to bucketize the revisions by the DREV value, and 1345 # It might be possible to bucketize the revisions by the DREV value, and
1333 # iterate over those groups when posting, and then again when amending. 1346 # iterate over those groups when posting, and then again when amending.
1334 # But for simplicity, require all selected revisions to be for the same 1347 # But for simplicity, require all selected revisions to be for the same
1335 # DREV (if present). Adding local revisions to an existing DREV is 1348 # DREV (if present). Adding local revisions to an existing DREV is