diff --git a/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/BUILD b/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/BUILD index 6c2373e4d33..96810b731e2 100644 --- a/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/BUILD +++ b/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/BUILD @@ -25,3 +25,9 @@ python_library( name='meta_rename', sources=['meta_rename.py'] ) + + +python_library( + name='print_target', + sources=['print_target.py'] +) diff --git a/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/buildozer.py b/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/buildozer.py index 17cd9aa037f..20bc5c76df8 100644 --- a/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/buildozer.py +++ b/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/buildozer.py @@ -72,17 +72,31 @@ def _execute_buildozer_script(self, command): Buildozer.execute_binary(command, address.spec, binary=self._executable) @classmethod - def execute_binary(cls, command, spec, binary=None, version='0.6.0.dce8b3c287652cbcaf43c8dd076b3f48c92ab44c'): + def execute_binary(cls, command, spec, binary=None, version='0.6.0.dce8b3c287652cbcaf43c8dd076b3f48c92ab44c', suppress_warnings=False): binary = binary if binary else BinaryUtil.Factory.create().select_binary('scripts/buildozer', version, 'buildozer') + Buildozer._execute_buildozer_command([binary, command, spec], suppress_warnings, output=False) - Buildozer._execute_buildozer_command([binary, command, spec]) + @classmethod + def return_buildozer_output(cls, command, spec, binary=None, version='0.6.0.dce8b3c287652cbcaf43c8dd076b3f48c92ab44c', suppress_warnings=False): + binary = binary if binary else BinaryUtil.Factory.create().select_binary('scripts/buildozer', version, 'buildozer') + return Buildozer._execute_buildozer_command([binary, command, spec], suppress_warnings, output=True) @classmethod - def _execute_buildozer_command(cls, buildozer_command): - try: - subprocess.check_call(buildozer_command, cwd=get_buildroot()) - except subprocess.CalledProcessError as err: - if err.returncode == 3: - logger.warn('{} ... no changes were made'.format(buildozer_command)) - else: - raise TaskError('{} ... exited non-zero ({}).'.format(buildozer_command, err.returncode)) + def _execute_buildozer_command(cls, buildozer_command, suppress_warnings, output): + if not output: + try: + subprocess.check_call(buildozer_command, cwd=get_buildroot()) + except subprocess.CalledProcessError as err: + if err.returncode == 3: + if not suppress_warnings: + logger.warn('{} ... no changes were made'.format(buildozer_command)) + else: + raise TaskError('{} ... exited non-zero ({}).'.format(buildozer_command, err.returncode)) + else: + try: + subprocess.check_output(buildozer_command, cwd=get_buildroot(), stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as err: + if err.returncode == 3: + return err.output + else: + raise TaskError('{} ... exited non-zero ({}).'.format(buildozer_command, err.returncode)) diff --git a/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/print_target.py b/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/print_target.py new file mode 100644 index 00000000000..a0dcf411b39 --- /dev/null +++ b/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/print_target.py @@ -0,0 +1,53 @@ +# coding=utf-8 +# Copyright 2017 Pants project contributors (see CONTRIBUTORS.md). +# Licensed under the Apache License, Version 2.0 (see LICENSE). + +from __future__ import (absolute_import, division, generators, nested_scopes, print_function, + unicode_literals, with_statement) + +from pants.base.exceptions import TaskError +from pants.task.console_task import ConsoleTask + +from pants.contrib.buildrefactor.buildozer import Buildozer + + +class PrintTarget(ConsoleTask): + """Print's a specified target if found in the associated build file + + line-number: optional flag to print the starting and ending line numbers of the target + + Example: + $./pants print-target --line-number testprojects/tests/java/org/pantsbuild/testproject/dummies:passing_target + """ + + @classmethod + def register_options(cls, register): + super(PrintTarget, cls).register_options(register) + + register('--line-number', help='Prints the starting line number of the named target.', type=bool, default=False) + + def __init__(self, *args, **kwargs): + super(PrintTarget, self).__init__(*args, **kwargs) + + if len(self.context.target_roots) > 1: + raise TaskError('More than one target specified:\n{}'.format(str(self.context.target_roots))) + + self.target = self.context.target_roots[0] + self.options = self.get_options() + + def console_output(self, targets): + + spec_path = self.target.address.spec + + yield('\'{}\' found in BUILD file.\n'.format(self.target.name)) + + if self.options.line_number: + startline_output = Buildozer.return_buildozer_output(spec = spec_path, command = 'print startline', suppress_warnings=True) + startline_digit = int(filter(str.isdigit, startline_output)) + + endline_output = Buildozer.return_buildozer_output(spec = spec_path, command = 'print endline', suppress_warnings=True) + endline_digit = int(filter(str.isdigit, endline_output)) + + yield('Line numbers: {}-{}.\n'.format(startline_digit, endline_digit)) + + yield('Target definiton:\n\n{}'.format(Buildozer.return_buildozer_output(spec = spec_path, command = 'print rule', suppress_warnings=True))) diff --git a/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/register.py b/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/register.py index f267bb87d31..f51f0fc233b 100644 --- a/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/register.py +++ b/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/register.py @@ -6,11 +6,12 @@ unicode_literals, with_statement) from pants.goal.task_registrar import TaskRegistrar as task - from pants.contrib.buildrefactor.buildozer import Buildozer from pants.contrib.buildrefactor.meta_rename import MetaRename +from pants.contrib.buildrefactor.print_target import PrintTarget def register_goals(): task(name='buildozer', action=Buildozer).install('buildozer') task(name='meta-rename', action=MetaRename).install('meta-rename') + task(name='print-target', action=PrintTarget).install('print-target') diff --git a/contrib/buildrefactor/tests/python/pants_test/contrib/buildrefactor/BUILD b/contrib/buildrefactor/tests/python/pants_test/contrib/buildrefactor/BUILD index 2405dd17c8d..de6bd068c29 100644 --- a/contrib/buildrefactor/tests/python/pants_test/contrib/buildrefactor/BUILD +++ b/contrib/buildrefactor/tests/python/pants_test/contrib/buildrefactor/BUILD @@ -36,6 +36,13 @@ python_tests( ] ) +python_tests( + name='print_target_integration', + sources=['test_print_target_integration.py'], + dependencies=[ + 'tests/python/pants_test:int-test', + ] +) python_tests( name='meta_rename_integration', @@ -53,3 +60,4 @@ python_tests( 'tests/python/pants_test:int-test', ] ) + diff --git a/contrib/buildrefactor/tests/python/pants_test/contrib/buildrefactor/test_print_target_integration.py b/contrib/buildrefactor/tests/python/pants_test/contrib/buildrefactor/test_print_target_integration.py new file mode 100644 index 00000000000..8f696c827be --- /dev/null +++ b/contrib/buildrefactor/tests/python/pants_test/contrib/buildrefactor/test_print_target_integration.py @@ -0,0 +1,45 @@ +# coding=utf-8 +# Copyright 2017 Pants project contributors (see CONTRIBUTORS.md). +# Licensed under the Apache License, Version 2.0 (see LICENSE). + +from __future__ import (absolute_import, division, generators, nested_scopes, print_function, + unicode_literals, with_statement) + +from pants_test.pants_run_integration_test import PantsRunIntegrationTest + + +class PrintTargetIntegrationTest(PantsRunIntegrationTest): + """Test Peek goal functionality + + $./pants test contrib/buildrefactor/tests/python/pants_test/contrib/buildrefactor:print_target_integration + """ + + def test_print_name(self): + print_target_print_run = self.run_pants(['print-target', + 'testprojects/tests/java/org/pantsbuild/testproject/buildrefactor/x:X']) + + self.assertIn('\'X\' found in BUILD file.', print_target_print_run.stdout_data) + self.assertIn('name = "X"', print_target_print_run.stdout_data) + + def test_print_invalid_name(self): + print_target_invalid_name_run = self.run_pants(['print-target', + 'testprojects/tests/java/org/pantsbuild/testproject/buildrefactor/x:Y']) + + self.assertIn('ResolveError: "Y" was not found in namespace', print_target_invalid_name_run.stderr_data) + self.assertIn('Did you mean one of:\n :X', print_target_invalid_name_run.stderr_data) + + def test_print_line_number(self): + print_target_line_number_run = self.run_pants(['print-target', + '--line-number', + 'testprojects/tests/java/org/pantsbuild/testproject/buildrefactor/x:X']) + + self.assertIn('Line numbers: 4-6.', print_target_line_number_run.stdout_data) + self.assertIn('name = "X"', print_target_line_number_run.stdout_data) + + def test_multiple_targets(self): + print_target_multiple_targets_run = self.run_pants(['print-target', + 'testprojects/tests/java/org/pantsbuild/testproject/buildrefactor/x:X', + 'tmp:tmp']) + + self.assertIn('FAILURE: More than one target specified:', print_target_multiple_targets_run.stdout_data or + print_target_multiple_targets_run.stderr_data)