def testCreateUpdateEmptyRevision(self): conduit = phlsys_conduit.Conduit( self.test_data.TEST_URI, self.test_data.PHAB.user, self.test_data.PHAB.certificate ) author = phldef_conduit.ALICE.user with phlsys_conduit.act_as_user_context(conduit, author): revision_id = phlcon_differential.create_empty_revision(conduit) revision_list = phlcon_differential.query(conduit, [revision_id]) self.assertEqual(len(revision_list), 1) with phlsys_conduit.act_as_user_context(conduit, author): phlcon_differential.update_revision_empty(conduit, revision_id)
def test_B_AcceptedPersistsWhenUpdated(self): conduit = self.phabConduit author = phldef_conduit.ALICE.user reviewer = phldef_conduit.BOB.user with phlsys_conduit.act_as_user_context(conduit, author): revision = phlcon_differential.create_empty_revision(conduit) with phlsys_conduit.act_as_user_context(conduit, reviewer): phlcon_differential.create_comment(conduit, revision, action=phlcon_differential.Action.accept) with phlsys_conduit.act_as_user_context(conduit, author): phlcon_differential.update_revision_empty(conduit, revision) self.assertEqual( phlcon_differential.get_revision_status(conduit, revision), phlcon_differential.ReviewStates.accepted )
def testCreateUpdateEmptyRevision(self): conduit = phlsys_conduit.Conduit( self.test_data.TEST_URI, self.test_data.PHAB.user, self.test_data.PHAB.certificate) author = phldef_conduit.ALICE.user with phlsys_conduit.act_as_user_context(conduit, author): revision_id = phlcon_differential.create_empty_revision(conduit) revision_list = phlcon_differential.query(conduit, [revision_id]) self.assertEqual(len(revision_list), 1) with phlsys_conduit.act_as_user_context(conduit, author): phlcon_differential.update_revision_empty(conduit, revision_id)
def test_B_AcceptedPersistsWhenUpdated(self): conduit = self.phabConduit author = phldef_conduit.ALICE.user reviewer = phldef_conduit.BOB.user with phlsys_conduit.act_as_user_context(conduit, author): revision = phlcon_differential.create_empty_revision(conduit) with phlsys_conduit.act_as_user_context(conduit, reviewer): phlcon_differential.create_comment( conduit, revision, action=phlcon_differential.Action.accept) with phlsys_conduit.act_as_user_context(conduit, author): phlcon_differential.update_revision_empty(conduit, revision) self.assertEqual( phlcon_differential.get_revision_status(conduit, revision), phlcon_differential.ReviewStates.accepted)
def update_revision(self, revisionid, raw_diff, message): """Update an existing Differential revision with a new diff. :revisionid: id of the Differential revision to update :raw_diff: raw output string from e.g. 'git diff master...' :message: string message to annotate the update event with :returns: None """ # do some sanity checks before committing to the expensive operation # of storing a diff in Differential status = self._reviewstate_cache.get_status(revisionid) if status == phlcon_differential.ReviewStates.closed: raise abdt_exception.AbdUserException( "can't update a closed revision") author_user = self._get_author_user(revisionid) with phlsys_conduit.act_as_user_context(self._conduit, author_user): diffid = phlcon_differential.create_raw_diff( self._conduit, raw_diff).id try: phlcon_differential.update_revision( self._conduit, revisionid, diffid, [], message) except phlcon_differential.UpdateClosedRevisionError: raise abdt_exception.AbdUserException( "CONDUIT: can't update a closed revision") self._log( 'conduit-updaterev', 'updated {} as {}'.format(revisionid, author_user))
def test_can_act_as_user(self): test_data = phldef_conduit conduit = phlsys_conduit.Conduit(test_data.TEST_URI, test_data.PHAB.user, test_data.PHAB.certificate) with phlsys_conduit.act_as_user_context(conduit, test_data.ALICE.user): conduit("differential.query")
def createDifferentialReview( conduit, user, parsed, gitContext, review_branch, rawDiff): clone = gitContext.clone phlgit_checkout.new_branch_force_based_on( clone, review_branch.branch, review_branch.remote_branch) with phlsys_conduit.act_as_user_context(conduit, user): print "- creating diff" diffid = phlcon_differential.create_raw_diff(conduit, rawDiff).id print "- creating revision" review = phlcon_differential.create_revision( conduit, diffid, parsed.fields) print "- created " + str(review.revisionid) workingBranch = abdt_naming.makeWorkingBranchName( abdt_naming.WB_STATUS_OK, review_branch.description, review_branch.base, review.revisionid) print "- pushing working branch: " + workingBranch phlgit_push.push_asymmetrical( clone, review_branch.branch, workingBranch, gitContext.remote) print "- commenting on " + str(review.revisionid) commenter = abdcmnt_commenter.Commenter(conduit, review.revisionid) commenter.createdReview(review_branch.branch, review_branch.base) return review.revisionid
def test_can_act_as_user(self): test_data = phldef_conduit conduit = phlsys_conduit.Conduit( test_data.TEST_URI, test_data.PHAB.user, test_data.PHAB.certificate) with phlsys_conduit.act_as_user_context(conduit, test_data.ALICE.user): conduit.call("differential.query")
def close_revision(self, revisionid): """Set an existing Differential revision to 'closed'. :revisionid: id of the Differential revision to close :returns: None """ author_user = self._get_author_user(revisionid) with phlsys_conduit.act_as_user_context(self._conduit, author_user): phlcon_differential.close(self._conduit, revisionid)
def create_empty_revision_as_user(self, username): """Return the id of a newly created empty revision as 'username'. :username: username for the author of the revision :returns: id of created revision """ with phlsys_conduit.act_as_user_context(self._conduit, username): revision = phlcon_differential.create_empty_revision(self._conduit) return revision
def test_C_CantUpdateClosedReviews(self): conduit = self.phabConduit author = phldef_conduit.ALICE.user reviewer = phldef_conduit.BOB.user with phlsys_conduit.act_as_user_context(conduit, author): revision = phlcon_differential.create_empty_revision(conduit) with phlsys_conduit.act_as_user_context(conduit, reviewer): phlcon_differential.create_comment(conduit, revision, action=phlcon_differential.Action.accept) with phlsys_conduit.act_as_user_context(conduit, author): phlcon_differential.create_comment(conduit, revision, action=phlcon_differential.Action.close) self.assertRaises( phlcon_differential.UpdateClosedRevisionError, phlcon_differential.update_revision_empty, conduit, revision, ) # expect that we can close a closed revision without errors phlcon_differential.close(conduit, revision)
def land(conduit, wb, gitContext, branch): clone = gitContext.clone print "landing " + wb.remote_branch + " onto " + wb.remote_base name, email, user = abdt_conduitgit.getPrimaryNameEmailAndUserFromBranch( clone, conduit, wb.remote_base, wb.remote_branch) d = phlcon_differential with phlsys_conduit.act_as_user_context(conduit, user): phlgit_checkout.new_branch_force_based_on( clone, wb.base, wb.remote_base) # compose the commit message message = d.get_commit_message(conduit, wb.id) try: with phlsys_fs.nostd(): squashMessage = phlgit_merge.squash( clone, wb.remote_branch, message, name + " <" + email + ">") except phlsys_subprocess.CalledProcessError as e: clone.call("reset", "--hard") # fix the working copy raise abdt_exception.LandingException( '\n' + e.stdout, branch, wb.base) print "- pushing " + wb.remote_base phlgit_push.push(clone, wb.base, gitContext.remote) print "- deleting " + wb.branch phlgit_push.delete(clone, wb.branch, gitContext.remote) print "- deleting " + branch phlgit_push.delete(clone, branch, gitContext.remote) print "- commenting on revision " + str(wb.id) commenter = abdcmnt_commenter.Commenter(conduit, wb.id) commenter.landedReview(branch, wb.base, squashMessage) authorPHID = d.query(conduit, [wb.id])[0].authorPHID authorUser = phlcon_user.query_usernames_from_phids( conduit, [authorPHID])[0] # TODO: there's a potential race condition on the author here with phlsys_conduit.act_as_user_context(conduit, authorUser): d.close(conduit, wb.id)
def processUpdatedBranch( mailer, conduit, gitContext, review_branch, working_branch): abdte = abdt_exception if working_branch is None: print "create review for " + review_branch.branch tryCreateReview( mailer, conduit, gitContext, review_branch, mail_on_fail=True) else: commenter = abdcmnt_commenter.Commenter(conduit, working_branch.id) if abdt_naming.isStatusBadPreReview(working_branch): hasChanged = not phlgit_branch.is_identical( gitContext.clone, review_branch.remote_branch, working_branch.remote_branch) print "try again to create review for " + review_branch.branch phlgit_push.delete( gitContext.clone, working_branch.branch, gitContext.remote) tryCreateReview( mailer, conduit, gitContext, review_branch, mail_on_fail=hasChanged) else: print "update review for " + review_branch.branch revision = phlcon_differential.query( conduit, [working_branch.id])[0] author_user = phlcon_user.query_usernames_from_phids( conduit, [revision.authorPHID])[0] try: updateReview( conduit, gitContext, review_branch, working_branch, author_user) except abdte.LandingException as e: print "landing exception" abdt_workingbranch.pushBadLand( gitContext, review_branch, working_branch) commenter.exception(e) with phlsys_conduit.act_as_user_context(conduit, author_user): phlcon_differential.create_comment( conduit, working_branch.id, action=phlcon_differential.Action.rethink) except abdte.AbdUserException as e: print "user exception" abdt_workingbranch.pushBadInReview( gitContext, review_branch, working_branch) commenter.exception(e)
def updateInReview(conduit, wb, gitContext, review_branch, author): remoteBranch = review_branch.remote_branch clone = gitContext.clone print "updateInReview" print "- creating diff" rawDiff = phlgit_diff.raw_diff_range( clone, wb.remote_base, remoteBranch, _DIFF_CONTEXT_LINES) if not rawDiff: raise abdt_exception.AbdUserException( "no difference from " + wb.base + " to " + wb.branch) # if the diff is too big then regen with less context # used_less_context = False if len(rawDiff) >= MAX_DIFF_SIZE: # used_less_context = True rawDiff = phlgit_diff.raw_diff_range( clone, wb.remote_base, remoteBranch, _LESS_DIFF_CONTEXT_LINES) # if the diff is still too big then regen with no context # used_no_context = False if len(rawDiff) >= MAX_DIFF_SIZE: # used_no_context = True rawDiff = phlgit_diff.raw_diff_range( clone, wb.remote_base, remoteBranch) # if the diff is still too big then error if len(rawDiff) >= MAX_DIFF_SIZE: raise abdt_exception.LargeDiffException( "diff too big", len(rawDiff), MAX_DIFF_SIZE) d = phlcon_differential used_default_test_plan = False with phlsys_conduit.act_as_user_context(conduit, author): print "- updating revision " + str(wb.id) diffid = d.create_raw_diff(conduit, rawDiff).id d.update_revision( conduit, wb.id, diffid, [], "update") wb = abdt_workingbranch.pushStatus( gitContext, review_branch, wb, abdt_naming.WB_STATUS_OK) print "- commenting on revision " + str(wb.id) commenter = abdcmnt_commenter.Commenter(conduit, wb.id) commenter.updatedReview(review_branch.branch) if used_default_test_plan: commenter.usedDefaultTestPlan(wb.branch, _DEFAULT_TEST_PLAN) return wb
def commandeer_revision_as_user(self, revisionid, username): """Change the author of a revision to the specified 'username'. :revisionid: id of the Differential revision to claim :username: username for the author of the revision :returns: None """ with phlsys_conduit.act_as_user_context(self._conduit, username): phlcon_differential.create_comment( self._conduit, revisionid, action=phlcon_differential.Action.claim)
def accept_revision_as_user(self, revisionid, username): """Set an existing Differential revision to 'accepted'. :revisionid: id of the Differential revision to accept :username: username for the reviewer of the revision :returns: None """ with phlsys_conduit.act_as_user_context(self._conduit, username): phlcon_differential.create_comment( self._conduit, revisionid, action=phlcon_differential.Action.accept)
def abandon_revision(self, revisionid): """Set an existing Differential revision to 'abandoned'. :revisionid: id of the Differential revision to close :returns: None """ author_user = self._get_author_user(revisionid) with phlsys_conduit.act_as_user_context(self._conduit, author_user): phlcon_differential.create_comment( self._conduit, revisionid, action=phlcon_differential.Action.abandon)
def set_requires_revision(self, revisionid): """Set an existing Differential revision to 'requires revision'. :revisionid: id of the Differential revision to update :returns: None """ author_user = self._get_author_user(revisionid) with phlsys_conduit.act_as_user_context(self._conduit, author_user): phlcon_differential.create_comment( self._conduit, revisionid, action=phlcon_differential.Action.rethink)
def test_C_CantUpdateClosedReviews(self): conduit = self.phabConduit author = phldef_conduit.ALICE.user reviewer = phldef_conduit.BOB.user with phlsys_conduit.act_as_user_context(conduit, author): revision = phlcon_differential.create_empty_revision(conduit) with phlsys_conduit.act_as_user_context(conduit, reviewer): phlcon_differential.create_comment( conduit, revision, action=phlcon_differential.Action.accept) with phlsys_conduit.act_as_user_context(conduit, author): phlcon_differential.create_comment( conduit, revision, action=phlcon_differential.Action.close) self.assertRaises( phlcon_differential.UpdateClosedRevisionError, phlcon_differential.update_revision_empty, conduit, revision) # expect that we can close a closed revision without errors phlcon_differential.close(conduit, revision)
def test_commandeeredUpdate(self): self._devCheckoutPushNewBranch("ph-review/commandeeredUpdate/master") self._devPushNewFile("NEWFILE") self._phabUpdateWithExpectations(total=1, bad=0) reviewid = self._getTheOnlyReviewId() with phlsys_conduit.act_as_user_context( self.conduit, phldef_conduit.ALICE.user) as conduit: phlcon_differential.create_comment( conduit, reviewid, action=phlcon_differential.Action.claim) self._devPushNewFile("NEWFILE2") self._phabUpdateWithExpectations(total=1, bad=0)
def create_revision_as_user(self, raw_diff, fields, username): """Return the id of a newly created revision based on specified args. See phlcon_differential.MessageFields for some examples of valid input for specified 'fields'. :raw_diff: raw output string from e.g. 'git diff master...' :fields: dict of string attributes, required: 'title' and 'testPlan' :username: username for the author of the revision :returns: id of created revision """ with phlsys_conduit.act_as_user_context(self._conduit, username): diffid = phlcon_differential.create_raw_diff( self._conduit, raw_diff).id review = phlcon_differential.create_revision( self._conduit, diffid, fields) return review.revisionid
def _actOnTheOnlyReview(self, user, action): # accept the review reviewid = self._getTheOnlyReviewId() with phlsys_conduit.act_as_user_context(self.conduit, user): phlcon_differential.create_comment( self.conduit, reviewid, action=action)
def test_A_Breathing(self): # [ A] can describe a conduit with non-empty string self.assertIsInstance(self.conduit.describe(), basestring) self.assertGreater(len(self.conduit.describe()), 0) # generally exercise all of the conduit methods alice = self.test_data.ALICE.user bob = self.test_data.BOB.user revision = self.conduit.create_empty_revision_as_user(bob) self.conduit.create_comment(revision, 'test comment') self.conduit.create_comment( revision, 'silent test comment', silent=True) self.conduit.get_commit_message(revision) self.assertFalse(self.conduit.is_review_accepted(revision)) self.assertFalse(self.conduit.is_review_abandoned(revision)) self.assertTrue(self.conduit.is_review_recently_updated(revision)) self.conduit.set_requires_revision(revision) self.assertFalse(self.conduit.is_review_accepted(revision)) self.assertFalse(self.conduit.is_review_abandoned(revision)) self.assertTrue(self.conduit.is_review_recently_updated(revision)) self.conduit.accept_revision_as_user(revision, alice) self._invalidate_cache() self.assertTrue(self.conduit.is_review_accepted(revision)) self.assertFalse(self.conduit.is_review_abandoned(revision)) self.assertTrue(self.conduit.is_review_recently_updated(revision)) self.conduit.set_requires_revision(revision) self._invalidate_cache() self.assertFalse(self.conduit.is_review_accepted(revision)) self.assertFalse(self.conduit.is_review_abandoned(revision)) self.assertTrue(self.conduit.is_review_recently_updated(revision)) self.conduit.accept_revision_as_user(revision, alice) # check that the review is still accepted after an update self._invalidate_cache() self.assertTrue(self.conduit.is_review_accepted(revision)) self.assertFalse(self.conduit.is_review_abandoned(revision)) self.assertTrue(self.conduit.is_review_recently_updated(revision)) self.conduit.update_revision(revision, self.empty_diff, 'update') self._invalidate_cache() self.assertTrue(self.conduit.is_review_accepted(revision)) self.assertFalse(self.conduit.is_review_abandoned(revision)) self.assertTrue(self.conduit.is_review_recently_updated(revision)) self.conduit.abandon_revision(revision) self.conduit.get_commit_message(revision) self._invalidate_cache() self.assertFalse(self.conduit.is_review_accepted(revision)) self.assertTrue(self.conduit.is_review_abandoned(revision)) self.assertTrue(self.conduit.is_review_recently_updated(revision)) # un-abandon with phlsys_conduit.act_as_user_context(self.sys_conduit, bob): phlcon_differential.create_comment( self.sys_conduit, revision, action=phlcon_differential.Action.reclaim) self._invalidate_cache() self.assertFalse(self.conduit.is_review_accepted(revision)) self.assertFalse(self.conduit.is_review_abandoned(revision)) self.assertTrue(self.conduit.is_review_recently_updated(revision)) self.conduit.commandeer_revision_as_user(revision, alice) self.conduit.commandeer_revision_as_user(revision, bob) # close non-accepted revision # self.conduit.set_requires_revision(revision) # self.assertFalse(self.conduit.is_review_accepted(revision)) # self.conduit.close_revision(revision) # self.assertFalse(self.conduit.is_review_accepted(revision)) # close revision self.conduit.accept_revision_as_user(revision, alice) self._invalidate_cache() self.assertTrue(self.conduit.is_review_accepted(revision)) self.assertFalse(self.conduit.is_review_abandoned(revision)) self.assertTrue(self.conduit.is_review_recently_updated(revision)) self.conduit.close_revision(revision) self.conduit.get_commit_message(revision) # commandeer closed revision # self.conduit.commandeer_revision_as_user(revision, alice) # update closed revision self._invalidate_cache() self.assertRaises( abdt_exception.AbdUserException, self.conduit.update_revision, revision, self.empty_diff, 'update') # comment on closed revision self.conduit.create_comment(revision, 'test comment')