rspec/rspec-tools/rspec_tools/modify_rule.py
Marco Antognini 26e3ebc7ec Refactor rspec-tools and other cleanups
The main changes are:
 * Split RuleCreator: move some of its content to RspecRepo and to
   RuleEditor in new modules.
 * Refactor tests accordingly.

Other less important changes:
 * Sort and remove unnecessary imports
 * Remove unimplemented functions and unnecessary classes
 * Make some functions private
 * Move pushd from utils to tests where it is only used
 * Reduce code duplication here and there
 * Remove unnecessary Mock in some tests
 * Improve coverage for add_language_to_rule
2022-02-28 12:08:21 +01:00

79 lines
3.3 KiB
Python

from contextlib import contextmanager
import json
from pathlib import Path
from typing import Optional
import click
from rspec_tools.errors import InvalidArgumentError
from rspec_tools.repo import RspecRepo, tmp_rspec_repo
from rspec_tools.utils import get_label_for_language, resolve_rule
@contextmanager
def _rule_editor(token: str, user: Optional[str]):
with tmp_rspec_repo(token, user) as repo:
yield RuleEditor(repo)
def update_rule_quickfix_status(language: str, rule: str, status: str, token: str, user: Optional[str]):
label = get_label_for_language(language)
rule_number = resolve_rule(rule)
with _rule_editor(token, user) as editor:
editor.update_quickfix_status_pull_request(token, rule_number, language, status, label, user)
class RuleEditor:
'''Modify an existing Rule in a repository following the official Github 'rspec' repository structure.'''
def __init__(self, rspec_repo: RspecRepo):
self.rspec_repo = rspec_repo
self.repo_dir = Path(self.rspec_repo.repository.working_dir)
def update_quickfix_status_branch(self, title: str, rule_number: int, language: str, status: str) -> str:
'''Update the given rule/language quick fix metadata field.'''
branch_name = f'rule/S{rule_number}-{language}-quickfix'
with self.rspec_repo.checkout_branch(self.rspec_repo.MASTER_BRANCH, branch_name):
self._update_quickfix_status(rule_number, language, status)
self.rspec_repo.commit_all_and_push(title)
return branch_name
def update_quickfix_status_pull_request(self, token: str, rule_number: int, language: str, status: str, label: str, user: Optional[str]):
title = f'Modify rule S{rule_number}: mark quick fix as "{status}"'
branch_name = self.update_quickfix_status_branch(title, rule_number, language, status)
click.echo(f'Created rule branch {branch_name}')
return self.rspec_repo.create_pull_request(
token,
branch_name,
title,
f'''See the original rule [here](https://sonarsource.github.io/rspec/#/rspec/S{rule_number}/{language}).
The rule won't be updated until this PR is merged, see [RULEAPI-655](https://jira.sonarsource.com/browse/RULEAPI-655)''',
[label],
user
)
def _get_generic_quickfix_status(self, rule_number: int):
DEFAULT = 'unknown'
generic_metadata_path = self.repo_dir / 'rules' / f'S{rule_number}' / 'metadata.json'
if not generic_metadata_path.is_file():
return DEFAULT
generic_metadata = json.loads(generic_metadata_path.read_text())
return generic_metadata.get('quickfix', DEFAULT)
def _update_quickfix_status(self, rule_number: int, language: str, status: str):
metadata_path = self.repo_dir / 'rules' / f'S{rule_number}' / language / 'metadata.json'
if not metadata_path.is_file():
raise InvalidArgumentError(f'{metadata_path} does not exist or is not a file')
metadata = json.loads(metadata_path.read_text())
generic_status = self._get_generic_quickfix_status(rule_number)
if status == metadata.get('quickfix', generic_status):
raise InvalidArgumentError(f'{metadata_path} has already the same status {status}')
metadata['quickfix'] = status
# When generating the JSON, ensure forward slashes are escaped. See RULEAPI-750.
json_string = json.dumps(metadata, indent=2).replace("/", "\\/")
metadata_path.write_text(json_string)