예제 #1
0
def run_validations(commit, files, validate_only):
  '''Runs all validations against |files| in |commit|.

  A validation consists of performing regex substitution against the contents
  of each file in |files|, at the git commit |commit|.  Validation fails if the
  resulting content is not identical to the original.  The contents of the
  files will be presented as a single string, allowing for multi-line matches.
  '''
  root = git_tools.root_dir()
  validation_passed = True
  for filename in files:
    filename = str(filename, encoding='utf-8')
    contents = git_tools.file_at_commit(commit, filename)
    violations = []

    # Run all validations sequentially, so all violations can be fixed
    # together.
    for error_string, search, replace in VALIDATIONS:
      replaced = search.sub(replace, contents)
      if replaced != contents:
        violations.append(error_string)
        contents = replaced

    if violations:
      validation_passed = False
      violations_message = ', '.join('%s%s%s' % (COLORS.FAIL, violation,
        COLORS.NORMAL) for violation in violations)
      if validate_only:
        print('File %s%s%s has %s.' % (COLORS.HEADER, filename, COLORS.NORMAL,
          violations_message), file=sys.stderr)
      else:
        print('Fixing %s%s%s for %s.' % (COLORS.HEADER, filename, COLORS.NORMAL,
          violations_message), file=sys.stderr)
        with open(os.path.join(root, filename), 'wb') as f:
          f.write(replaced)
  return validation_passed
예제 #2
0
def main():
  parser = argparse.ArgumentParser(description='PHP linter')
  subparsers = parser.add_subparsers(dest='tool')

  validate_parser = subparsers.add_parser('validate',
      help='Only validates, does not make changes')
  validate_parser.add_argument('commits', metavar='commit', nargs='*',
      type=str, help='Only include files changed between commits')

  fix_parser = subparsers.add_parser('fix',
      help='Fixes all violations and leaves the results in the working tree.')
  fix_parser.add_argument('commits', metavar='commit', nargs='*',
      type=str, help='Only include files changed between commits')

  args = parser.parse_args()
  if not git_tools.validate_args(args):
    return 1

  changed_files = git_tools.changed_files(args.commits,
      whitelist=[br'^frontend.*\.php$'],
      blacklist=[br'.*third_party.*', br'.*dao/base.*',
                 br'frontend/server/libs/dao/Estructura.php',
                 br'frontend/server/libs/dao/model.inc.php'])
  if not changed_files:
    return 0

  root = git_tools.root_dir()
  phpcs_args = [which('phpcbf'), '--encoding=utf-8',
      '--standard=%s' % os.path.join(root, 'stuff/omegaup-standard.xml')]

  validate_only = args.tool == 'validate'
  validation_passed = True

  for filename in changed_files:
    filename = str(filename, encoding='utf-8')
    contents = git_tools.file_at_commit(args.commits[1], filename)
    cmd = phpcs_args + ['--stdin-path=%s' % filename]
    with subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        cwd=root) as p:
      replaced = p.communicate(contents)[0]
      if p.returncode != 0 and not replaced:
        # phpcbf returns 1 if there was no change to the file. If there was an
        # actual error, there won't be anything in stdout.
        validation_passed = False
        print('Execution of "%s" %sfailed with return code %d%s.' % (
              ' '.join(cmd), COLORS.FAIL, COLORS.NORMAL), file=sys.stderr)
    if contents != replaced:
      validation_passed = False
      if validate_only:
        print('File %s%s%s has %slint errors%s.' % (COLORS.HEADER, filename,
          COLORS.NORMAL, COLORS.FAIL, COLORS.NORMAL), file=sys.stderr)
      else:
        print('Fixing %s%s%s for %slint errors%s.' % (COLORS.HEADER, filename,
          COLORS.NORMAL, COLORS.FAIL, COLORS.NORMAL), file=sys.stderr)
        with open(os.path.join(root, filename), 'wb') as f:
          f.write(replaced)

  if not validation_passed:
    if validate_only:
      print('%sPHP validation errors.%s '
            'Please run `%s fix %s` to fix them.' % (git_tools.COLORS.FAIL,
              git_tools.COLORS.NORMAL, sys.argv[0], ' '.join(args.commits)),
              file=sys.stderr)
    else:
      print('Files written to working directory. '
          '%sPlease commit them before pushing.%s' % (COLORS.HEADER,
          COLORS.NORMAL), file=sys.stderr)
    return 1
  return 0