Esempio n. 1
0
 def _candidate_owners(self, file):
   build_file = BuildFile(get_buildroot(), relpath=os.path.dirname(file), must_exist=False)
   if build_file.exists():
     yield build_file
   for sibling in build_file.siblings():
     yield sibling
   for ancestor in build_file.ancestors():
     yield ancestor
Esempio n. 2
0
 def _candidate_owners(self, path):
   build_file = BuildFile(get_buildroot(), relpath=os.path.dirname(path), must_exist=False)
   if build_file.exists():
     yield build_file
   for sibling in build_file.siblings():
     yield sibling
   for ancestor in build_file.ancestors():
     yield ancestor
Esempio n. 3
0
    def console_output(self, _):
        buildfiles = OrderedSet()
        if self._dependees_type:
            base_paths = OrderedSet()
            for dependees_type in self._dependees_type:
                try:
                    # Try to do a fully qualified import 1st for filtering on custom types.
                    from_list, module, type_name = dependees_type.rsplit(
                        '.', 2)
                    __import__('%s.%s' % (from_list, module),
                               fromlist=[from_list])
                except (ImportError, ValueError):
                    # Fall back on pants provided target types.
                    if hasattr(twitter.pants.base.build_file_context,
                               dependees_type):
                        type_name = getattr(
                            twitter.pants.base.build_file_context,
                            dependees_type)
                    else:
                        raise TaskError('Invalid type name: %s' %
                                        dependees_type)
                # Find the SourceRoot for the given input type
                base_paths.update(SourceRoot.roots(type_name))
            if not base_paths:
                raise TaskError(
                    'No SourceRoot set for any target type in %s.' %
                    self._dependees_type +
                    '\nPlease define a source root in BUILD file as:' +
                    '\n\tsource_root(\'<src-folder>\', %s)' %
                    ', '.join(self._dependees_type))
            for base_path in base_paths:
                buildfiles.update(
                    BuildFile.scan_buildfiles(get_buildroot(), base_path))
        else:
            buildfiles = BuildFile.scan_buildfiles(get_buildroot())

        dependees_by_target = defaultdict(set)
        for buildfile in buildfiles:
            for address in Target.get_all_addresses(buildfile):
                for target in Target.get(address).resolve():
                    # TODO(John Sirois): tighten up the notion of targets written down in a BUILD by a
                    # user vs. targets created by pants at runtime.
                    target = self.get_concrete_target(target)
                    if hasattr(target, 'dependencies'):
                        for dependencies in target.dependencies:
                            for dependency in dependencies.resolve():
                                dependency = self.get_concrete_target(
                                    dependency)
                                dependees_by_target[dependency].add(target)

        roots = set(self.context.target_roots)
        if self._closed:
            for root in roots:
                yield str(root.address)

        for dependant in self.get_dependants(dependees_by_target, roots):
            yield str(dependant.address)
Esempio n. 4
0
 def _parse_addresses(self, spec):
   if spec.endswith('::'):
     dir = self._get_dir(spec[:-len('::')])
     for buildfile in BuildFile.scan_buildfiles(self._root_dir, os.path.join(self._root_dir, dir)):
       for address in Target.get_all_addresses(buildfile):
         yield address
   elif spec.endswith(':'):
     dir = self._get_dir(spec[:-len(':')])
     for address in Target.get_all_addresses(BuildFile(self._root_dir, dir)):
       yield address
   else:
     yield Address.parse(self._root_dir, spec)
Esempio n. 5
0
def create_buildfile(root_dir, relpath, name='BUILD', content=''):
    path = os.path.join(root_dir, relpath)
    safe_mkdir(path)
    buildfile = os.path.join(path, name)
    with open(buildfile, 'a') as f:
        f.write(content)
    return BuildFile(root_dir, relpath)
Esempio n. 6
0
    def parse(cls, root_dir, pathish, is_relative=True):
        """Parses pathish into an Address.  A pathish can be one of:
    1.) the (relative) path of a BUILD file
    2.) the (relative) path of a directory containing a BUILD file child
    3.) either of 1 or 2 with a ':[module name]' suffix
    4.) a bare ':[module name]' indicating the BUILD file to use is the one in the current directory

    If the pathish does not have a module suffix the targeted module name is taken to be the same
    name as the BUILD file's containing directory.  In this way the containing directory name
    becomes the 'default' module target for pants.

    If there is no BUILD file at the path pointed to, or if there is but the specified module target
    is not defined in the BUILD file, an IOError is raised."""

        parts = pathish.split(':') if not pathish.startswith(':') else [
            '.', pathish[1:]
        ]
        path, is_meta = Address._parse_meta(parts[0])
        if is_relative:
            path = os.path.relpath(os.path.abspath(path), root_dir)
        buildfile = BuildFile(root_dir, path)

        if len(parts) == 1:
            parent_name = os.path.basename(os.path.dirname(buildfile.relpath))
            return Address(buildfile, parent_name, is_meta)
        else:
            target_name, is_meta = Address._parse_meta(':'.join(parts[1:]))
            return Address(buildfile, target_name, is_meta)
Esempio n. 7
0
    def parse(cls, root_dir, spec, is_relative=True):
        """Parses the given spec into an Address.

    An address spec can be one of:
    1.) the (relative) path of a BUILD file
    2.) the (relative) path of a directory containing a BUILD file child
    3.) either of 1 or 2 with a ':[module name]' suffix
    4.) a bare ':[module name]' indicating the BUILD file to use is the one in the current directory

    If the spec does not have a target name suffix the target name is taken to be the same name
    as the BUILD file's parent directory.  In this way the containing directory name
    becomes the 'default' target name for a BUILD file.

    If there is no BUILD file at the path pointed to, or if there is but the specified target name
    is not defined in the BUILD file, an IOError is raised.
    """

        if spec.startswith(':'):
            spec = '.' + spec
        parts = spec.split(':', 1)
        path = parts[0]
        if is_relative:
            path = os.path.relpath(os.path.abspath(path), root_dir)
        buildfile = BuildFile(root_dir, path)

        name = os.path.basename(os.path.dirname(
            buildfile.relpath)) if len(parts) == 1 else parts[1]
        return Address(buildfile, name)
Esempio n. 8
0
 def _addresses(self):
   if self.context.target_roots:
     for target in self.context.target_roots:
       yield target.address
   else:
     for buildfile in BuildFile.scan_buildfiles(self._root_dir):
       for address in Target.get_all_addresses(buildfile):
         yield address
Esempio n. 9
0
  def console_output(self, _):
    buildfiles = OrderedSet()
    if self._dependees_type:
      base_paths = OrderedSet()
      for dependees_type in self._dependees_type:
        try:
          # Try to do a fully qualified import 1st for filtering on custom types.
          from_list, module, type_name = dependees_type.rsplit('.', 2)
          __import__('%s.%s' % (from_list, module), fromlist=[from_list])
        except (ImportError, ValueError):
          # Fall back on pants provided target types.
          if hasattr(twitter.pants.base.build_file_context, dependees_type):
            type_name = getattr(twitter.pants.base.build_file_context, dependees_type)
          else:
            raise TaskError('Invalid type name: %s' % dependees_type)
        # Find the SourceRoot for the given input type
        base_paths.update(SourceRoot.roots(type_name))
      if not base_paths:
        raise TaskError('No SourceRoot set for any target type in %s.' % self._dependees_type +
                        '\nPlease define a source root in BUILD file as:' +
                        '\n\tsource_root(\'<src-folder>\', %s)' % ', '.join(self._dependees_type))
      for base_path in base_paths:
        buildfiles.update(BuildFile.scan_buildfiles(get_buildroot(), base_path))
    else:
      buildfiles = BuildFile.scan_buildfiles(get_buildroot())

    dependees_by_target = defaultdict(set)
    for buildfile in buildfiles:
      for address in Target.get_all_addresses(buildfile):
        for target in Target.get(address).resolve():
          # TODO(John Sirois): tighten up the notion of targets written down in a BUILD by a
          # user vs. targets created by pants at runtime.
          target = self.get_concrete_target(target)
          if hasattr(target, 'dependencies'):
            for dependencies in target.dependencies:
              for dependency in dependencies.resolve():
                dependency = self.get_concrete_target(dependency)
                dependees_by_target[dependency].add(target)

    roots = set(self.context.target_roots)
    if self._closed:
      for root in roots:
        yield str(root.address)

    for dependant in self.get_dependants(dependees_by_target, roots):
      yield str(dependant.address)
Esempio n. 10
0
    def scan_addresses(root_dir, base_path=None):
        """Parses all targets available in BUILD files under base_path and
    returns their addresses.  If no base_path is specified, root_dir is
    assumed to be the base_path"""

        addresses = OrderedSet()
        for buildfile in BuildFile.scan_buildfiles(root_dir, base_path):
            addresses.update(Target.get_all_addresses(buildfile))
        return addresses
Esempio n. 11
0
  def scan_addresses(root_dir, base_path=None):
    """Parses all targets available in BUILD files under base_path and
    returns their addresses.  If no base_path is specified, root_dir is
    assumed to be the base_path"""

    addresses = OrderedSet()
    for buildfile in BuildFile.scan_buildfiles(root_dir, base_path):
      addresses.update(Target.get_all_addresses(buildfile))
    return addresses
Esempio n. 12
0
 def _find_targets(self):
   if len(self.context.target_roots) > 0:
     for target in self.context.target_roots:
       yield target
   else:
     for buildfile in BuildFile.scan_buildfiles(get_buildroot()):
       target_addresses = Target.get_all_addresses(buildfile)
       for target_address in target_addresses:
         yield Target.get(target_address)
Esempio n. 13
0
 def _parse_addresses(self, spec):
   if spec.endswith('::'):
     dir = self._get_dir(spec[:-len('::')])
     for buildfile in BuildFile.scan_buildfiles(self._root_dir, os.path.join(self._root_dir, dir)):
       for address in Target.get_all_addresses(buildfile):
         yield address
   elif spec.endswith(':'):
     dir = self._get_dir(spec[:-len(':')])
     for address in Target.get_all_addresses(BuildFile(self._root_dir, dir)):
       yield address
   else:
     yield Address.parse(self._root_dir, spec)
Esempio n. 14
0
    def __init__(self, context):
        ConsoleTask.__init__(self, context)

        self._print_uptodate = context.options.check_deps_print_uptodate
        self.repos = context.config.getdict('jar-publish', 'repos')
        self._artifacts_to_targets = {}
        all_addresses = (
            address for buildfile in BuildFile.scan_buildfiles(get_buildroot())
            for address in Target.get_all_addresses(buildfile))
        for address in all_addresses:
            target = Target.get(address)
            if target.is_exported:
                provided_jar, _, _ = target.get_artifact_info()
                artifact = (provided_jar.org, provided_jar.name)
                if not artifact in self._artifacts_to_targets:
                    self._artifacts_to_targets[artifact] = target
Esempio n. 15
0
  def console_output(self, _):
    dependees_by_target = defaultdict(set)
    for buildfile in BuildFile.scan_buildfiles(get_buildroot()):
      for address in Target.get_all_addresses(buildfile):
        for target in Target.get(address).resolve():
          if hasattr(target, 'dependencies'):
            for dependencies in target.dependencies:
              for dependency in dependencies.resolve():
                dependees_by_target[dependency].add(target)

    roots = set(self.context.target_roots)
    if self._closed:
      for root in roots:
        yield str(root.address)

    for dependant in self.get_dependants(dependees_by_target, roots):
      yield str(dependant.address)
Esempio n. 16
0
  def console_output(self, _):
    dependees_by_target = defaultdict(set)
    for buildfile in BuildFile.scan_buildfiles(get_buildroot()):
      for address in Target.get_all_addresses(buildfile):
        for target in Target.get(address).resolve():
          if hasattr(target, 'dependencies'):
            for dependencies in target.dependencies:
              for dependency in dependencies.resolve():
                dependees_by_target[dependency].add(target)

    roots = set(self.context.target_roots)
    if self._closed:
      for root in roots:
        yield str(root.address)

    for dependant in self.get_dependants(dependees_by_target, roots):
      yield str(dependant.address)
Esempio n. 17
0
    def setup_parser(self, parser, args):
        self.config = Config.load()
        Goal.add_global_options(parser)

        # We support attempting zero or more goals.  Multiple goals must be delimited from further
        # options and non goal args with a '--'.  The key permutations we need to support:
        # ./pants goal => goals
        # ./pants goal goals => goals
        # ./pants goal compile src/java/... => compile
        # ./pants goal compile -x src/java/... => compile
        # ./pants goal compile src/java/... -x => compile
        # ./pants goal compile run -- src/java/... => compile, run
        # ./pants goal compile run -- src/java/... -x => compile, run
        # ./pants goal compile run -- -x src/java/... => compile, run

        if not args:
            args.append('goals')

        if len(args) == 1 and args[0] in set(['-h', '--help', 'help']):

            def format_usage(usages):
                left_colwidth = 0
                for left, right in usages:
                    left_colwidth = max(left_colwidth, len(left))
                lines = []
                for left, right in usages:
                    lines.append('  %s%s%s' %
                                 (left, ' ' *
                                  (left_colwidth - len(left) + 1), right))
                return '\n'.join(lines)

            usages = [
                ("%prog goal goals ([spec]...)", Phase('goals').description),
                ("%prog goal help [goal] ([spec]...)",
                 Phase('help').description),
                ("%prog goal [goal] [spec]...",
                 "Attempt goal against one or more targets."),
                ("%prog goal [goal] ([goal]...) -- [spec]...",
                 "Attempts all the specified goals."),
            ]
            parser.set_usage("\n%s" % format_usage(usages))
            parser.epilog = (
                "Either lists all installed goals, provides extra help for a goal or else "
                "attempts to achieve the specified goal for the listed targets."
                """
                       Note that target specs accept two special forms:
                         [dir]:  to include all targets in the specified directory
                         [dir]:: to include all targets found in all BUILD files recursively under
                                 the directory""")

            parser.print_help()
            sys.exit(0)
        else:
            goals, specs = Goal.parse_args(args)
            self.requested_goals = goals

            with self.run_tracker.new_workunit(name='setup',
                                               labels=[WorkUnit.SETUP]):
                # Bootstrap goals by loading any configured bootstrap BUILD files
                with self.check_errors(
                        'The following bootstrap_buildfiles cannot be loaded:'
                ) as error:
                    with self.run_tracker.new_workunit(name='bootstrap',
                                                       labels=[WorkUnit.SETUP
                                                               ]):
                        for path in self.config.getlist('goals',
                                                        'bootstrap_buildfiles',
                                                        default=[]):
                            try:
                                buildfile = BuildFile(
                                    get_buildroot(),
                                    os.path.relpath(path, get_buildroot()))
                                ParseContext(buildfile).parse()
                            except (TypeError, ImportError, TaskError,
                                    GoalError):
                                error(path, include_traceback=True)
                            except (IOError, SyntaxError):
                                error(path)
                # Now that we've parsed the bootstrap BUILD files, and know about the SCM system.
                self.run_tracker.run_info.add_scm_info()

                # Bootstrap user goals by loading any BUILD files implied by targets.
                spec_parser = SpecParser(self.root_dir)
                with self.check_errors(
                        'The following targets could not be loaded:') as error:
                    with self.run_tracker.new_workunit(name='parse',
                                                       labels=[WorkUnit.SETUP
                                                               ]):
                        for spec in specs:
                            try:
                                for target, address in spec_parser.parse(spec):
                                    if target:
                                        self.targets.append(target)
                                        # Force early BUILD file loading if this target is an alias that expands
                                        # to others.
                                        unused = list(target.resolve())
                                    else:
                                        siblings = Target.get_all_addresses(
                                            address.buildfile)
                                        prompt = 'did you mean' if len(
                                            siblings
                                        ) == 1 else 'maybe you meant one of these'
                                        error('%s => %s?:\n    %s' %
                                              (address, prompt, '\n    '.join(
                                                  str(a) for a in siblings)))
                            except (TypeError, ImportError, TaskError,
                                    GoalError):
                                error(spec, include_traceback=True)
                            except (IOError, SyntaxError,
                                    TargetDefinitionException):
                                error(spec)

            self.phases = [Phase(goal) for goal in goals]

            rcfiles = self.config.getdefault('rcfiles', type=list, default=[])
            if rcfiles:
                rcfile = RcFile(rcfiles,
                                default_prepend=False,
                                process_default=True)

                # Break down the goals specified on the command line to the full set that will be run so we
                # can apply default flags to inner goal nodes.  Also break down goals by Task subclass and
                # register the task class hierarchy fully qualified names so we can apply defaults to
                # baseclasses.

                sections = OrderedSet()
                for phase in Engine.execution_order(self.phases):
                    for goal in phase.goals():
                        sections.add(goal.name)
                        for clazz in goal.task_type.mro():
                            if clazz == Task:
                                break
                            sections.add('%s.%s' %
                                         (clazz.__module__, clazz.__name__))

                augmented_args = rcfile.apply_defaults(sections, args)
                if augmented_args != args:
                    del args[:]
                    args.extend(augmented_args)
                    sys.stderr.write(
                        "(using pantsrc expansion: pants goal %s)\n" %
                        ' '.join(augmented_args))

            Phase.setup_parser(parser, args, self.phases)
Esempio n. 18
0
 def buildfile(cls, path):
   return BuildFile(BuildFileTest.root_dir, path)