| # Copyright 2021 The Pigweed Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| # use this file except in compliance with the License. You may obtain a copy of |
| # the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| """Check that lines were not removed from the token database.""" |
| |
| import re |
| |
| from PB.recipes.pigweed.tokendb_check import InputProperties |
| from recipe_engine import post_process |
| |
| DEPS = [ |
| 'fuchsia/git', |
| 'fuchsia/status_check', |
| 'pigweed/checkout', |
| 'pigweed/util', |
| 'recipe_engine/context', |
| 'recipe_engine/properties', |
| 'recipe_engine/raw_io', |
| 'recipe_engine/step', |
| ] |
| |
| PROPERTIES = InputProperties |
| |
| PYTHON_VERSION_COMPATIBILITY = "PY3" |
| |
| |
| def RunSteps(api, props): |
| if not props.tokendb_paths: |
| raise api.step.StepFailure('no tokendb_paths property') |
| |
| # TODO(mohrr) Remove nesting. Apparently the gerrit module doesn't work as |
| # a top-level step. Change the next line to 'if True:' to reproduce. |
| with api.step.nest('gerrit'): |
| res = api.util.get_change_with_comments() |
| |
| match = api.util.find_matching_comment( |
| re.compile(r'Token-Database-Removal-Reason: \w.*'), res.comments, |
| ) |
| if match: |
| return |
| |
| checkout = api.checkout(props.checkout_options) |
| with api.context(cwd=checkout.root): |
| kwargs = { |
| 'stdout': api.raw_io.output_text(), |
| 'step_test_data': lambda: api.raw_io.test_api.stream_output_text( |
| '' |
| ), |
| } |
| lines = ( |
| api.git( |
| 'git show --numstat', |
| 'show', |
| '--numstat', |
| '--pretty=format:', |
| '--', |
| *props.tokendb_paths, |
| **kwargs |
| ) |
| .stdout.strip() |
| .split('\n') |
| ) |
| |
| # Each line of output looks like this: |
| # $ADDED $REMOVED $PATH |
| for line in lines: |
| if not line: |
| continue |
| |
| _, removed, path = line.split() |
| if int(removed): |
| raise api.step.StepFailure( |
| 'Lines are not allowed to be removed from token database ' |
| "{}. If there's a good reason to remove them post a Gerrit " |
| 'comment explaining why that starts with ' |
| '"Token-Database-Removal-Reason: ".'.format(path) |
| ) |
| |
| |
| def GenTests(api): |
| def diff(path, added, removed): |
| return '{} {} {}'.format(added, removed, path) |
| |
| def test(name, paths=(), diffs=None, status='success', comment=None): |
| res = api.status_check.test(name, status=status) |
| res += api.properties(tokendb_paths=list(paths)) |
| res += api.checkout.try_test_data() |
| res += api.properties(**api.checkout.git_properties()) |
| |
| if diffs is not None: |
| commit_summary = '\n'.join(diffs) |
| res += api.step_data( |
| 'git show --numstat', |
| api.raw_io.stream_output_text(commit_summary), |
| ) |
| |
| if comment: |
| res += api.util.change_comment(comment) |
| |
| return res |
| |
| yield test('no-props', status='failure') |
| |
| yield test('no-change', paths=['token.db'], diffs=[]) |
| |
| yield test('addition', paths=['token.db'], diffs=[diff('token.db', 1, 0)]) |
| |
| yield test( |
| 'removal', |
| paths=['token.db'], |
| diffs=[diff('token.db', 0, 1)], |
| status='failure', |
| ) |
| |
| yield test( |
| 'comment', |
| paths=['token.db'], |
| comment='Token-Database-Removal-Reason: because', |
| ) |