def get(revision_id, diff_id=None): """Gets revision from Phabricator. Args: revision_id: (string) ID of the revision in 'D{number}' format diff_id: (integer) Id of the diff to return with the revision. By default the active diff will be returned. """ revision_id = revision_id_to_int(revision_id) phab = g.phabricator revision = phab.call_conduit('differential.revision.search', constraints={'ids': [revision_id]}, attachments={ 'reviewers': True, 'reviewers-extra': True, }) revision = phab.single(revision, 'data', none_when_empty=True) if revision is None: return problem( 404, 'Revision not found', 'The requested revision does not exist', type='https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404' ) latest_diff = phab.single( phab.call_conduit( 'differential.diff.search', constraints={ 'phids': [phab.expect(revision, 'fields', 'diffPHID')] }, attachments={'commits': True}, ), 'data') latest_diff_id = phab.expect(latest_diff, 'id') if diff_id is not None and diff_id != latest_diff_id: diff = phab.single(phab.call_conduit( 'differential.diff.search', constraints={'ids': [diff_id]}, attachments={'commits': True}, ), 'data', none_when_empty=True) else: diff = latest_diff if diff is None: return problem( 404, 'Diff not found', 'The requested diff does not exist', type='https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404' ) revision_phid = phab.expect(revision, 'phid') if phab.expect(diff, 'fields', 'revisionPHID') != revision_phid: return problem( 400, 'Diff not related to the revision', 'The requested diff is not related to the requested revision.', type='https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400' ) author_phid = phab.expect(revision, 'fields', 'authorPHID') reviewers = get_collated_reviewers(revision) # Immediately execute the lazy functions. users = lazy_user_search(phab, list(reviewers.keys()) + [author_phid])() projects = lazy_project_search(phab, list(reviewers.keys()))() accepted_reviewers = [ reviewer_identity(phid, users, projects).identifier for phid, r in reviewers.items() if r['status'] is ReviewerStatus.ACCEPTED ] title = phab.expect(revision, 'fields', 'title') summary = phab.expect(revision, 'fields', 'summary') bug_id = get_bugzilla_bug(revision) human_revision_id = 'D{}'.format(revision_id) revision_url = urllib.parse.urljoin(current_app.config['PHABRICATOR_URL'], human_revision_id) commit_message_title, commit_message = format_commit_message( title, bug_id, accepted_reviewers, summary, revision_url) reviewers_response = serialize_reviewers(reviewers, users, projects, phab.expect(diff, 'phid')) author_response = serialize_author(author_phid, users) diff_response = serialize_diff(diff) return { 'id': human_revision_id, 'phid': phab.expect(revision, 'phid'), 'bug_id': bug_id, 'title': title, 'url': revision_url, 'date_created': PhabricatorClient.to_datetime( phab.expect(revision, 'fields', 'dateCreated') ).isoformat(), 'date_modified': PhabricatorClient.to_datetime( phab.expect(revision, 'fields', 'dateModified') ).isoformat(), 'summary': summary, 'commit_message_title': commit_message_title, 'commit_message': commit_message, 'diff': diff_response, 'latest_diff_id': latest_diff_id, 'author': author_response, 'reviewers': reviewers_response, }, 200 # yapf: disable
def get(revision_id): """Get the stack a revision is part of. Args: revision_id: (string) ID of the revision in 'D{number}' format """ revision_id = revision_id_to_int(revision_id) phab = g.phabricator revision = phab.call_conduit( 'differential.revision.search', constraints={'ids': [revision_id]}, ) revision = phab.single(revision, 'data', none_when_empty=True) if revision is None: return problem( 404, 'Revision not found', 'The requested revision does not exist', type='https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404' ) # TODO: This assumes that all revisions and related objects in the stack # have uniform view permissions for the requesting user. Some revisions # being restricted could cause this to fail. nodes, edges = build_stack_graph(phab, phab.expect(revision, 'phid')) stack_data = request_extended_revision_data(phab, [phid for phid in nodes]) supported_repos = get_repos_for_env(current_app.config.get('ENVIRONMENT')) landable_repos = get_landable_repos_for_revision_data( stack_data, supported_repos ) landable, blocked = calculate_landable_subgraphs( stack_data, edges, landable_repos, other_checks=DEFAULT_OTHER_BLOCKER_CHECKS ) involved_phids = set() for revision in stack_data.revisions.values(): involved_phids.update(gather_involved_phids(revision)) involved_phids = list(involved_phids) users = lazy_user_search(phab, involved_phids)() projects = lazy_project_search(phab, involved_phids)() revisions_response = [] for phid, revision in stack_data.revisions.items(): revision_phid = PhabricatorClient.expect(revision, 'phid') fields = PhabricatorClient.expect(revision, 'fields') diff_phid = PhabricatorClient.expect(fields, 'diffPHID') diff = stack_data.diffs[diff_phid] human_revision_id = 'D{}'.format( PhabricatorClient.expect(revision, 'id') ) revision_url = urllib.parse.urljoin( current_app.config['PHABRICATOR_URL'], human_revision_id ) title = PhabricatorClient.expect(fields, 'title') summary = PhabricatorClient.expect(fields, 'summary') bug_id = get_bugzilla_bug(revision) reviewers = get_collated_reviewers(revision) accepted_reviewers = [ reviewer_identity(phid, users, projects).identifier for phid, r in reviewers.items() if r['status'] is ReviewerStatus.ACCEPTED ] commit_message_title, commit_message = format_commit_message( title, bug_id, accepted_reviewers, summary, revision_url ) author_response = serialize_author( phab.expect(fields, 'authorPHID'), users ) revisions_response.append({ 'id': human_revision_id, 'phid': revision_phid, 'status': serialize_status(revision), 'blocked_reason': blocked.get(revision_phid, ''), 'bug_id': bug_id, 'title': title, 'url': revision_url, 'date_created': PhabricatorClient.to_datetime( PhabricatorClient.expect(revision, 'fields', 'dateCreated') ).isoformat(), 'date_modified': PhabricatorClient.to_datetime( PhabricatorClient.expect(revision, 'fields', 'dateModified') ).isoformat(), 'summary': summary, 'commit_message_title': commit_message_title, 'commit_message': commit_message, 'diff': serialize_diff(diff), 'author': author_response, 'reviewers': serialize_reviewers( reviewers, users, projects, diff_phid ), }) # yapf: disable return { 'revisions': revisions_response, 'edges': [e for e in edges], 'landable_paths': landable, }
def get(revision_id): """Get the stack a revision is part of. Args: revision_id: (string) ID of the revision in 'D{number}' format """ revision_id = revision_id_to_int(revision_id) phab = g.phabricator revision = phab.call_conduit("differential.revision.search", constraints={"ids": [revision_id]}) revision = phab.single(revision, "data", none_when_empty=True) if revision is None: return problem( 404, "Revision not found", "The requested revision does not exist", type="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404", ) # TODO: This assumes that all revisions and related objects in the stack # have uniform view permissions for the requesting user. Some revisions # being restricted could cause this to fail. nodes, edges = build_stack_graph(phab, phab.expect(revision, "phid")) stack_data = request_extended_revision_data(phab, [phid for phid in nodes]) supported_repos = get_repos_for_env(current_app.config.get("ENVIRONMENT")) landable_repos = get_landable_repos_for_revision_data( stack_data, supported_repos) other_checks = get_blocker_checks( repositories=supported_repos, relman_group_phid=get_relman_group_phid(phab)) landable, blocked = calculate_landable_subgraphs(stack_data, edges, landable_repos, other_checks=other_checks) uplift_repos = [ name for name, repo in supported_repos.items() if repo.approval_required ] involved_phids = set() for revision in stack_data.revisions.values(): involved_phids.update(gather_involved_phids(revision)) involved_phids = list(involved_phids) users = user_search(phab, involved_phids) projects = project_search(phab, involved_phids) secure_project_phid = get_secure_project_phid(phab) sec_approval_project_phid = get_sec_approval_project_phid(phab) revisions_response = [] for _phid, revision in stack_data.revisions.items(): revision_phid = PhabricatorClient.expect(revision, "phid") fields = PhabricatorClient.expect(revision, "fields") diff_phid = PhabricatorClient.expect(fields, "diffPHID") diff = stack_data.diffs[diff_phid] human_revision_id = "D{}".format( PhabricatorClient.expect(revision, "id")) revision_url = urllib.parse.urljoin( current_app.config["PHABRICATOR_URL"], human_revision_id) secure = revision_is_secure(revision, secure_project_phid) commit_description = find_title_and_summary_for_display( phab, revision, secure) bug_id = get_bugzilla_bug(revision) reviewers = get_collated_reviewers(revision) accepted_reviewers = reviewers_for_commit_message( reviewers, users, projects, sec_approval_project_phid) commit_message_title, commit_message = format_commit_message( commit_description.title, bug_id, accepted_reviewers, commit_description.summary, revision_url, ) author_response = serialize_author(phab.expect(fields, "authorPHID"), users) revisions_response.append({ "id": human_revision_id, "phid": revision_phid, "status": serialize_status(revision), "blocked_reason": blocked.get(revision_phid, ""), "bug_id": bug_id, "title": commit_description.title, "url": revision_url, "date_created": PhabricatorClient.to_datetime( PhabricatorClient.expect(revision, "fields", "dateCreated")).isoformat(), "date_modified": PhabricatorClient.to_datetime( PhabricatorClient.expect(revision, "fields", "dateModified")).isoformat(), "summary": commit_description.summary, "commit_message_title": commit_message_title, "commit_message": commit_message, "repo_phid": PhabricatorClient.expect(fields, "repositoryPHID"), "diff": serialize_diff(diff), "author": author_response, "reviewers": serialize_reviewers(reviewers, users, projects, diff_phid), "is_secure": secure, "is_using_secure_commit_message": commit_description.sanitized, }) repositories = [] for phid in stack_data.repositories.keys(): short_name = PhabricatorClient.expect(stack_data.repositories[phid], "fields", "shortName") repo = supported_repos.get(short_name) if repo is None: landing_supported, approval_required = False, None else: landing_supported, approval_required = True, repo.approval_required url = ("{phabricator_url}/source/{short_name}".format( phabricator_url=current_app.config["PHABRICATOR_URL"], short_name=short_name, ) if not landing_supported else supported_repos[short_name].url) repositories.append({ "phid": phid, "short_name": short_name, "url": url, "landing_supported": landing_supported, "approval_required": approval_required, }) return { "repositories": repositories, "revisions": revisions_response, "edges": [e for e in edges], "landable_paths": landable, "uplift_repositories": uplift_repos, }
def get(revision_id): """Get the stack a revision is part of. Args: revision_id: (string) ID of the revision in 'D{number}' format """ revision_id = revision_id_to_int(revision_id) phab = g.phabricator revision = phab.call_conduit("differential.revision.search", constraints={"ids": [revision_id]}) revision = phab.single(revision, "data", none_when_empty=True) if revision is None: return not_found_problem try: nodes, edges = build_stack_graph(phab, phab.expect(revision, "phid")) except PhabricatorAPIException: # If a revision within the stack causes an API exception, treat the whole stack # as not found. return not_found_problem stack_data = request_extended_revision_data(phab, [phid for phid in nodes]) supported_repos = get_repos_for_env(current_app.config.get("ENVIRONMENT")) landable_repos = get_landable_repos_for_revision_data( stack_data, supported_repos) other_checks = get_blocker_checks( repositories=supported_repos, relman_group_phid=get_relman_group_phid(phab)) landable, blocked = calculate_landable_subgraphs(stack_data, edges, landable_repos, other_checks=other_checks) uplift_repos = [ name for name, repo in supported_repos.items() if repo.approval_required ] involved_phids = set() for revision in stack_data.revisions.values(): involved_phids.update(gather_involved_phids(revision)) involved_phids = list(involved_phids) users = user_search(phab, involved_phids) projects = project_search(phab, involved_phids) secure_project_phid = get_secure_project_phid(phab) sec_approval_project_phid = get_sec_approval_project_phid(phab) revisions_response = [] for _phid, revision in stack_data.revisions.items(): revision_phid = PhabricatorClient.expect(revision, "phid") fields = PhabricatorClient.expect(revision, "fields") diff_phid = PhabricatorClient.expect(fields, "diffPHID") diff = stack_data.diffs[diff_phid] human_revision_id = "D{}".format( PhabricatorClient.expect(revision, "id")) revision_url = urllib.parse.urljoin( current_app.config["PHABRICATOR_URL"], human_revision_id) secure = revision_is_secure(revision, secure_project_phid) commit_description = find_title_and_summary_for_display( phab, revision, secure) bug_id = get_bugzilla_bug(revision) reviewers = get_collated_reviewers(revision) accepted_reviewers = reviewers_for_commit_message( reviewers, users, projects, sec_approval_project_phid) commit_message_title, commit_message = format_commit_message( commit_description.title, bug_id, accepted_reviewers, commit_description.summary, revision_url, ) author_response = serialize_author(phab.expect(fields, "authorPHID"), users) revisions_response.append({ "id": human_revision_id, "phid": revision_phid, "status": serialize_status(revision), "blocked_reason": blocked.get(revision_phid, ""), "bug_id": bug_id, "title": commit_description.title, "url": revision_url, "date_created": PhabricatorClient.to_datetime( PhabricatorClient.expect(revision, "fields", "dateCreated")).isoformat(), "date_modified": PhabricatorClient.to_datetime( PhabricatorClient.expect(revision, "fields", "dateModified")).isoformat(), "summary": commit_description.summary, "commit_message_title": commit_message_title, "commit_message": commit_message, "repo_phid": PhabricatorClient.expect(fields, "repositoryPHID"), "diff": serialize_diff(diff), "author": author_response, "reviewers": serialize_reviewers(reviewers, users, projects, diff_phid), "is_secure": secure, "is_using_secure_commit_message": commit_description.sanitized, }) repositories = [] for phid in stack_data.repositories.keys(): short_name = PhabricatorClient.expect(stack_data.repositories[phid], "fields", "shortName") repo = supported_repos.get(short_name) landing_supported = repo is not None url = (repo.url if landing_supported else f"{current_app.config['PHABRICATOR_URL']}/source/{short_name}") repositories.append({ "approval_required": landing_supported and repo.approval_required, "commit_flags": repo.commit_flags if repo else [], "landing_supported": landing_supported, "phid": phid, "short_name": short_name, "url": url, }) return { "repositories": repositories, "revisions": revisions_response, "edges": [e for e in edges], "landable_paths": landable, "uplift_repositories": uplift_repos, }