From 409150339f9c33d2e7faf3c65a89166d7d4e4dc7 Mon Sep 17 00:00:00 2001 From: Jacob Richman Date: Tue, 21 Mar 2017 16:18:48 -0700 Subject: [PATCH] Add presubmit check that runs dartfmt BUG= R=johnmccutchan@google.com, whesse@google.com, zra@google.com Review-Url: https://codereview.chromium.org/2761653003 . --- PRESUBMIT.py | 100 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 93 insertions(+), 7 deletions(-) diff --git a/PRESUBMIT.py b/PRESUBMIT.py index f850b03948c..c7e956a0b2b 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py @@ -8,11 +8,97 @@ See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for more details about the presubmit API built into gcl. """ +import imp +import os +import scm +import subprocess +import tempfile + +def _CheckBuildStatus(input_api, output_api): + results = [] + status_check = input_api.canned_checks.CheckTreeIsOpen( + input_api, + output_api, + json_url='http://dart-status.appspot.com/current?format=json') + results.extend(status_check) + return results + +def _CheckDartFormat(input_api, output_api): + local_root = input_api.change.RepositoryRoot() + upstream = input_api.change._upstream + utils = imp.load_source('utils', + os.path.join(local_root, 'tools', 'utils.py')) + + prebuilt_dartfmt = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dartfmt') + + windows = utils.GuessOS() == 'win32' + if windows: + prebuilt_dartfmt += '.bat' + + if not os.path.isfile(prebuilt_dartfmt): + print('WARNING: dartfmt not found: %s' % (prebuilt_dartfmt)) + return [] + + def HasFormatErrors(filename=None, contents=None): + args = [prebuilt_dartfmt, '--set-exit-if-changed'] + if contents: + process = subprocess.Popen(args, + stdout=subprocess.PIPE, + stdin=subprocess.PIPE + ) + out, err = process.communicate(input=contents) + + # There was a bug in the return code dartfmt returns when reading from + # stdin so we have to check whether the content matches rather than using + # the return code. When the next version of the dartfmt lands in the sdk + # we can switch this line to "return process.returncode != 0" + return out != contents + else: + try: + subprocess.check_output(args + [filename, '-n']) + except subprocess.CalledProcessError: + return True + return False + + unformatted_files = [] + for git_file in input_api.AffectedTextFiles(): + filename = git_file.AbsoluteLocalPath() + if filename.endswith('.dart'): + if HasFormatErrors(filename=filename): + old_version_has_errors = False + try: + path = git_file.LocalPath() + if windows: + # Git expects a linux style path. + path = path.replace(os.sep, '/') + old_contents = scm.GIT.Capture( + ['show', upstream + ':' + path], + cwd=local_root, + strip_out=False) + if HasFormatErrors(contents=old_contents): + old_version_has_errors = True + except subprocess.CalledProcessError as e: + # TODO(jacobr): verify that the error really is that the file was + # added for this CL. + old_version_has_errors = False + + if old_version_has_errors: + print("WARNING: %s has existing and possibly new dartfmt issues" % + git_file.LocalPath()) + else: + unformatted_files.append(filename) + + if unformatted_files: + return [output_api.PresubmitError( + 'File output does not match dartfmt.\n' + 'Fix these issues with:\n' + 'dartfmt -w \\\n%s' % ' \\\n'.join(unformatted_files))] + + return [] + def CheckChangeOnCommit(input_api, output_api): - results = [] - status_check = input_api.canned_checks.CheckTreeIsOpen( - input_api, - output_api, - json_url='http://dart-status.appspot.com/current?format=json') - results.extend(status_check) - return results + return (_CheckBuildStatus(input_api, output_api) + + _CheckDartFormat(input_api, output_api)) + +def CheckChangeOnUpload(input_api, output_api): + return _CheckDartFormat(input_api, output_api)