Example #1
0
 def _resolve_conflict(self, existing, proposed):
     if proposed == existing:
         return existing
     elif existing.force and proposed.force:
         raise TaskError(
             'Cannot force %s#%s to both rev %s and %s' %
             (proposed.org, proposed.name, existing.rev, proposed.rev))
     elif existing.force:
         self._log.debug(
             'Ignoring rev %s for %s#%s already forced to %s' %
             (proposed.rev, proposed.org, proposed.name, existing.rev))
         return existing
     elif proposed.force:
         self._log.debug(
             'Forcing %s#%s from %s to %s' %
             (proposed.org, proposed.name, existing.rev, proposed.rev))
         return proposed
     else:
         try:
             if Revision.lenient(proposed.rev) > Revision.lenient(
                     existing.rev):
                 self._log.debug('Upgrading %s#%s from rev %s  to %s' % (
                     proposed.org,
                     proposed.name,
                     existing.rev,
                     proposed.rev,
                 ))
                 return proposed
             else:
                 return existing
         except Revision.BadRevision as e:
             raise TaskError('Failed to parse jar revision', e)
Example #2
0
 def _resolve_conflict(existing, proposed):
   if proposed == existing:
     if proposed.force:
       return proposed
     return existing
   elif existing.force and proposed.force:
     raise TaskError('Cannot force {}#{};{} to both rev {} and {}'.format(
       proposed.org, proposed.name, proposed.classifier or '', existing.rev, proposed.rev
     ))
   elif existing.force:
     logger.debug('Ignoring rev {} for {}#{};{} already forced to {}'.format(
       proposed.rev, proposed.org, proposed.name, proposed.classifier or '', existing.rev
     ))
     return existing
   elif proposed.force:
     logger.debug('Forcing {}#{};{} from {} to {}'.format(
       proposed.org, proposed.name, proposed.classifier or '', existing.rev, proposed.rev
     ))
     return proposed
   else:
     try:
       if Revision.lenient(proposed.rev) > Revision.lenient(existing.rev):
         logger.debug('Upgrading {}#{};{} from rev {}  to {}'.format(
           proposed.org, proposed.name, proposed.classifier or '', existing.rev, proposed.rev,
         ))
         return proposed
       else:
         return existing
     except Revision.BadRevision as e:
       raise TaskError('Failed to parse jar revision', e)
Example #3
0
 def _resolve_conflict(cls, existing, proposed):
   if proposed == existing:
     if proposed.force:
       return proposed
     return existing
   elif existing.force and proposed.force:
     raise cls.IvyResolveConflictingDepsError('Cannot force {}#{};{} to both rev {} and {}'.format(
       proposed.org, proposed.name, proposed.classifier or '', existing.rev, proposed.rev
     ))
   elif existing.force:
     logger.debug('Ignoring rev {} for {}#{};{} already forced to {}'.format(
       proposed.rev, proposed.org, proposed.name, proposed.classifier or '', existing.rev
     ))
     return existing
   elif proposed.force:
     logger.debug('Forcing {}#{};{} from {} to {}'.format(
       proposed.org, proposed.name, proposed.classifier or '', existing.rev, proposed.rev
     ))
     return proposed
   else:
     if Revision.lenient(proposed.rev) > Revision.lenient(existing.rev):
       logger.debug('Upgrading {}#{};{} from rev {}  to {}'.format(
         proposed.org, proposed.name, proposed.classifier or '', existing.rev, proposed.rev,
       ))
       return proposed
     else:
       return existing
Example #4
0
 def _resolve_conflict(cls, existing, proposed):
   if existing.rev is None:
     return proposed
   if proposed.rev is None:
     return existing
   if proposed == existing:
     if proposed.force:
       return proposed
     return existing
   elif existing.force and proposed.force:
     raise cls.IvyResolveConflictingDepsError('Cannot force {}#{};{} to both rev {} and {}'.format(
       proposed.org, proposed.name, proposed.classifier or '', existing.rev, proposed.rev
     ))
   elif existing.force:
     logger.debug('Ignoring rev {} for {}#{};{} already forced to {}'.format(
       proposed.rev, proposed.org, proposed.name, proposed.classifier or '', existing.rev
     ))
     return existing
   elif proposed.force:
     logger.debug('Forcing {}#{};{} from {} to {}'.format(
       proposed.org, proposed.name, proposed.classifier or '', existing.rev, proposed.rev
     ))
     return proposed
   else:
     if Revision.lenient(proposed.rev) > Revision.lenient(existing.rev):
       logger.debug('Upgrading {}#{};{} from rev {}  to {}'.format(
         proposed.org, proposed.name, proposed.classifier or '', existing.rev, proposed.rev,
       ))
       return proposed
     else:
       return existing
Example #5
0
 def _resolve_conflict(self, existing, proposed):
   if proposed == existing:
     if proposed.force:
       return proposed
     return existing
   elif existing.force and proposed.force:
     raise TaskError('Cannot force %s#%s to both rev %s and %s' % (
       proposed.org, proposed.name, existing.rev, proposed.rev
     ))
   elif existing.force:
     self._log.debug('Ignoring rev %s for %s#%s already forced to %s' % (
       proposed.rev, proposed.org, proposed.name, existing.rev
     ))
     return existing
   elif proposed.force:
     self._log.debug('Forcing %s#%s from %s to %s' % (
       proposed.org, proposed.name, existing.rev, proposed.rev
     ))
     return proposed
   else:
     try:
       if Revision.lenient(proposed.rev) > Revision.lenient(existing.rev):
         self._log.debug('Upgrading %s#%s from rev %s  to %s' % (
           proposed.org, proposed.name, existing.rev, proposed.rev,
         ))
         return proposed
       else:
         return existing
     except Revision.BadRevision as e:
       raise TaskError('Failed to parse jar revision', e)
Example #6
0
 def _get_deprecated_tense(self,
                           deprecated_version,
                           future_tense='Will be',
                           past_tense='Was'):
     """Provides the grammatical tense for a given deprecated version vs the current version."""
     return future_tense if (Revision.semver(deprecated_version) >=
                             Revision.semver(VERSION)) else past_tense
Example #7
0
  def errorprone(self, target):
    runtime_classpaths = self.context.products.get_data('runtime_classpath')
    runtime_classpath = [jar for conf, jar in runtime_classpaths.get_for_targets(target.closure(bfs=True))]

    output_dir = os.path.join(self.workdir, target.id)
    safe_mkdir(output_dir)
    runtime_classpath.append(output_dir)

    # Try to run errorprone with the same java version as the target
    # The minimum JDK for errorprone is JDK 1.8
    min_jdk_version = max(target.platform.target_level, Revision.lenient('1.8'))
    if min_jdk_version.components[0] == 1:
      max_jdk_version = Revision(min_jdk_version.components[0], min_jdk_version.components[1], '9999')
    else:
      max_jdk_version = Revision(min_jdk_version.components[0], '9999')
    self.set_distribution(minimum_version=min_jdk_version, maximum_version=max_jdk_version, jdk=True)

    jvm_options = self.get_options().jvm_options[:]
    if self.dist.version < Revision.lenient('9'):
      # For Java 8 we need to add the errorprone javac jar to the bootclasspath to
      # avoid the "java.lang.NoSuchFieldError: ANNOTATION_PROCESSOR_MODULE_PATH" error
      # See https://github.com/google/error-prone/issues/653 for more information
      jvm_options.extend(['-Xbootclasspath/p:{}'.format(self.tool_classpath('errorprone-javac')[0])])

    args = [
      '-d', output_dir,
    ]

    # Errorprone does not recognize source or target 10 yet
    if target.platform.source_level < Revision.lenient('10'):
      args.extend(['-source', str(target.platform.source_level)])

    if target.platform.target_level < Revision.lenient('10'):
      args.extend(['-target', str(target.platform.target_level)])

    errorprone_classpath_file = os.path.join(self.workdir, '{}.classpath'.format(os.path.basename(output_dir)))
    with open(errorprone_classpath_file, 'w') as f:
      f.write('-classpath ')
      f.write(':'.join(runtime_classpath))
    args.append('@{}'.format(errorprone_classpath_file))

    for opt in self.get_options().command_line_options:
      args.extend(safe_shlex_split(opt))

    with argfile.safe_args(self.calculate_sources(target), self.get_options()) as batched_sources:
      args.extend(batched_sources)
      result = self.runjava(classpath=self.tool_classpath('errorprone'),
                            main=self._ERRORPRONE_MAIN,
                            jvm_options=jvm_options,
                            args=args,
                            workunit_name='errorprone',
                            workunit_labels=[WorkUnitLabel.LINT])

      self.context.log.debug('java {main} ... exited with result ({result})'.format(
        main=self._ERRORPRONE_MAIN, result=result))

    return result
Example #8
0
 def _validate_supports_more_than_one_source(self):
   # Support for doing the right thing with multiple files landed in
   # https://issues.apache.org/jira/browse/THRIFT-3776; first available in 0.10.0
   if self.get_options().multiple_files_per_target_override:
     return
   required_version = '0.10.0'
   if  Revision.semver(self._thrift_version) < Revision.semver(required_version):
     raise TaskError('A single .thrift source file is supported per go_thrift_library with thrift '
                     'version `{}`: upgrade to at least `{}` to support multiple files.'.format(
                     self._thrift_version, required_version))
Example #9
0
 def _validate_supports_more_than_one_source(self):
   # Support for doing the right thing with multiple files landed in
   # https://issues.apache.org/jira/browse/THRIFT-3776; first available in 0.10.0
   if self.get_options().multiple_files_per_target_override:
     return
   required_version = '0.10.0'
   if  Revision.semver(self._thrift_version) < Revision.semver(required_version):
     raise TaskError('A single .thrift source file is supported per go_thrift_library with thrift '
                     'version `{}`: upgrade to at least `{}` to support multiple files.'.format(
                     self._thrift_version, required_version))
Example #10
0
    def _preferred_jvm_distribution_args(cls,
                                         platforms,
                                         strict=None,
                                         jdk=False):
        if not platforms:
            return {"jdk": jdk}
        if strict is False:  # treat all the platforms as non-strict
            min_version = max(p.target_level for p in platforms)
            set_max_version = False
        else:
            # treat strict platforms as strict & ensure no non-strict directive is broken
            strict_target_levels = {
                p.target_level
                for p in platforms if p.strict
            }
            lenient_target_levels = {
                p.target_level
                for p in platforms if not p.strict
            }

            if len(strict_target_levels) == 0:
                min_version = max(lenient_target_levels)
                set_max_version = strict
            elif len(strict_target_levels) > 1:
                differing = ", ".join(str(t) for t in strict_target_levels)
                raise cls.IncompatiblePlatforms(
                    f"Multiple strict platforms with differing target releases were found:"
                    f" {differing}")
            else:
                if len(lenient_target_levels) == 0:
                    min_version = next(iter(strict_target_levels))
                    set_max_version = True
                else:
                    strict_level = next(iter(strict_target_levels))
                    non_strict_max = max(t for t in lenient_target_levels)
                    if non_strict_max and non_strict_max > strict_level:
                        raise cls.IncompatiblePlatforms(
                            f"lenient platform with higher minimum version,"
                            f" {non_strict_max}, than strict requirement of"
                            f" {strict_level}")
                    min_version = strict_level
                    set_max_version = True

        if len(min_version.components
               ) <= 2:  # ensure at least three components.
            min_version = Revision(*(min_version.components + [0] *
                                     (3 - len(min_version.components))))
        max_version = None
        if set_max_version:
            max_version = Revision(*(min_version.components[0:2] + [9999]))
        return {
            "minimum_version": min_version,
            "maximum_version": max_version,
            "jdk": jdk
        }
Example #11
0
    def test_pre_release(self):
        self.assertEqual(Revision.semver("1.2.3-pre1.release.1"), Revision.semver("1.2.3-pre1.release.1"))
        self.assertComponents(Revision.semver("1.2.3-pre1.release.1"), 1, 2, 3, "pre1", "release", 1, None)

        self.assertTrue(Revision.semver("1.2.3-pre1.release.1") < Revision.semver("1.2.3-pre2.release.1"))
        self.assertTrue(Revision.semver("1.2.3-pre1.release.2") < Revision.semver("1.2.3-pre1.release.10"))

        self.assertTrue(Revision.semver("1.2.3") < Revision.semver("1.2.3-pre2.release.1"))
Example #12
0
  def test_pre_release(self):
    self.assertEqual(Revision.semver('1.2.3-pre1.release.1'),
                     Revision.semver('1.2.3-pre1.release.1'))
    self.assertComponents(Revision.semver('1.2.3-pre1.release.1'),
                          1, 2, 3, 'pre1', 'release', 1, None)

    self.assertTrue(
      Revision.semver('1.2.3-pre1.release.1') < Revision.semver('1.2.3-pre2.release.1'))
    self.assertTrue(
      Revision.semver('1.2.3-pre1.release.2') < Revision.semver('1.2.3-pre1.release.10'))

    self.assertTrue(Revision.semver('1.2.3') < Revision.semver('1.2.3-pre2.release.1'))
Example #13
0
  def test_pre_release(self):
    self.assertEqual(Revision.semver('1.2.3-pre1.release.1'),
                     Revision.semver('1.2.3-pre1.release.1'))
    self.assertComponents(Revision.semver('1.2.3-pre1.release.1'),
                          1, 2, 3, 'pre1', 'release', 1, None)

    self.assertTrue(
      Revision.semver('1.2.3-pre1.release.1') < Revision.semver('1.2.3-pre2.release.1'))
    self.assertTrue(
      Revision.semver('1.2.3-pre1.release.2') < Revision.semver('1.2.3-pre1.release.10'))

    self.assertTrue(Revision.semver('1.2.3') < Revision.semver('1.2.3-pre2.release.1'))
Example #14
0
 def console_output(self, targets):
     self._force_option_parsing()
     for scope, options in sorted(
             self.context.options.tracker.option_history_by_scope.items()):
         if not self._scope_filter(scope):
             continue
         for option, history in sorted(options.items()):
             if not self._option_filter(option):
                 continue
             if not self._rank_filter(history.latest.rank):
                 continue
             if self.get_options(
             ).only_overridden and not history.was_overridden:
                 continue
             # Skip the option if it has already passed the deprecation period.
             if history.latest.deprecation_version and PANTS_SEMVER >= Revision.semver(
                     history.latest.deprecation_version):
                 continue
             if self.get_options().skip_inherited:
                 parent_scope, parent_value = self._get_parent_scope_option(
                     scope, option)
                 if parent_scope is not None and parent_value == history.latest.value:
                     continue
             yield '{} = {}'.format(self._format_scope(scope, option),
                                    self._format_record(history.latest))
             if self.get_options().show_history:
                 for line in self._show_history(history):
                     yield line
Example #15
0
 def _parse_java_version(version):
   # Java version strings have been well defined since release 1.3.1 as defined here:
   #  http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html
   # These version strings comply with semver except that the traditional pre-release semver
   # slot (the 4th) can be delimited by an _ in the case of update releases of the jdk.
   # We accomodate that difference here.
   return Revision.semver(version.replace('_', '-'))
  def project_template(self):
    target_levels = {Revision.lenient(platform['target_level'])
                     for platform in self.blob['jvm_platforms']['platforms'].values()}
    lang_level = max(target_levels) if target_levels else Revision(1, 8)

    configured_project = TemplateData(
      root_dir=get_buildroot(),
      outdir=self.output_directory,
      git_root=Git.detect_worktree(),
      modules=self.module_templates_by_filename.values(),
      java=TemplateData(
        encoding=self.java_encoding,
        maximum_heap_size=self.java_maximum_heap_size,
        jdk='{0}.{1}'.format(*lang_level.components[:2]),
        language_level='JDK_{0}_{1}'.format(*lang_level.components[:2]),
      ),
      resource_extensions=[],
      scala=None,
      checkstyle_classpath=';'.join([]),
      debug_port=self.debug_port,
      annotation_processing=self.annotation_processing_template,
      extra_components=[],
      junit_tests=self._junit_tests_config(),
      global_junit_vm_parameters=' '.join(self.global_junit_jvm_options),
    )
    return configured_project
Example #17
0
 def preferred_jvm_distribution(self, platforms):
   """Returns a jvm Distribution with a version that should work for all the platforms."""
   if not platforms:
     return DistributionLocator.cached()
   min_version = max(platform.target_level for platform in platforms)
   max_version = Revision(*(min_version.components + [9999])) if self._strict_jvm_version else None
   return DistributionLocator.cached(minimum_version=min_version, maximum_version=max_version)
Example #18
0
 def console_output(self, targets):
   self._force_option_parsing()
   for scope, options in sorted(self.context.options.tracker.option_history_by_scope.items()):
     if not self._scope_filter(scope):
       continue
     for option, history in sorted(options.items()):
       if not self._option_filter(option):
         continue
       if not self._rank_filter(history.latest.rank):
         continue
       if self.get_options().only_overridden and not history.was_overridden:
         continue
       # Skip the option if it has already passed the deprecation period.
       if history.latest.deprecation_version and PANTS_SEMVER >= Revision.semver(
         history.latest.deprecation_version):
         continue
       if self.get_options().skip_inherited:
         parent_scope, parent_value = self._get_parent_scope_option(scope, option)
         if parent_scope is not None and parent_value == history.latest.value:
           continue
       yield '{} = {}'.format(self._format_scope(scope, option),
                              self._format_record(history.latest))
       if self.get_options().show_history:
         for line in self._show_history(history):
           yield line
Example #19
0
def git_version():
  """Get a Version() based on installed command-line git's version"""
  process = subprocess.Popen(['git', '--version'], stdout=subprocess.PIPE)
  (stdout, stderr) = process.communicate()
  assert process.returncode == 0, "Failed to determine git version."
  # stdout is like 'git version 1.9.1.598.g9119e8b\n'  We want '1.9.1.598'
  matches = re.search(r'\s(\d+(?:\.\d+)*)[\s\.]', stdout.decode('utf-8'))
  return Revision.lenient(matches.group(1))
Example #20
0
def git_version():
  """Get a Version() based on installed command-line git's version"""
  process = subprocess.Popen(['git', '--version'], stdout=subprocess.PIPE)
  (stdout, stderr) = process.communicate()
  assert process.returncode == 0, "Failed to determine git version."
  # stdout is like 'git version 1.9.1.598.g9119e8b\n'  We want '1.9.1.598'
  matches = re.search(r'\s(\d+(?:\.\d+)*)[\s\.]', stdout)
  return Revision.lenient(matches.group(1))
Example #21
0
  def test_validate_version(self):
    with pytest.raises(Distribution.Error):
      with self.distribution(executables=self.exe('java', '1.7.0_25')) as jdk:
        Distribution(bin_path=jdk, minimum_version='1.7.0_45').validate()

    with self.distribution(executables=self.exe('java', '1.7.0_25')) as jdk:
      Distribution(bin_path=jdk, minimum_version='1.7.0_25').validate()
      Distribution(bin_path=jdk, minimum_version=Revision.semver('1.6.0')).validate()
Example #22
0
  def _check_deprecated(self, dest, kwargs):
    """Checks option for deprecation and issues a warning/error if necessary."""
    deprecated_ver = kwargs.get('deprecated_version', None)
    if deprecated_ver is not None:
      msg = (
        "Option '{dest}' in {scope} is deprecated and removed in version {removal_version}. {hint}"
      ).format(dest=dest,
               scope=self._scope_str(),
               removal_version=deprecated_ver,
               hint=kwargs.get('deprecated_hint', ''))

      if Revision.semver(VERSION) >= Revision.semver(deprecated_ver):
        # Once we've hit the deprecated_version, raise an error instead of warning. This allows for
        # more actionable options hinting to continue beyond the deprecation period until removal.
        raise DeprecatedOptionError(msg)
      else:
        # Out of range stacklevel to suppress printing src line.
        warnings.warn('*** {}'.format(msg), DeprecationWarning, stacklevel=9999)
Example #23
0
 def test_preferred_jvm_distributions(self):
     with temporary_dir() as strict_jdk_home:
         with temporary_dir() as non_strict_jdk_home:
             strict_cache_key = (Revision(1, 6), Revision(1, 6,
                                                          9999), False)
             non_strict_cache_key = (Revision(1, 6), None, False)
             DistributionLocator._CACHE[strict_cache_key] = Distribution(
                 home_path=strict_jdk_home)
             DistributionLocator._CACHE[
                 non_strict_cache_key] = Distribution(
                     home_path=non_strict_jdk_home)
             self.assertEqual(
                 {
                     'strict': strict_jdk_home,
                     'non_strict': non_strict_jdk_home
                 },
                 self.execute_export_json()['preferred_jvm_distributions']
                 ['java6'])
Example #24
0
def git_version() -> Revision:
  """Get a Version() based on installed command-line git's version"""
  stdout = subprocess.run(
    ['git', '--version'], stdout=subprocess.PIPE, encoding="utf-8", check=True
  ).stdout
  # stdout is like 'git version 1.9.1.598.g9119e8b\n'  We want '1.9.1.598'
  matches = re.search(r'\s(\d+(?:\.\d+)*)[\s\.]', stdout)
  if matches is None:
    raise ValueError(f"Not able to parse git version from {stdout}.")
  return Revision.lenient(matches.group(1))
Example #25
0
    def test_pre_release(self):
        self.assertEqual(
            Revision.semver("1.2.3-pre1.release.1"), Revision.semver("1.2.3-pre1.release.1")
        )
        self.assertComponents(
            Revision.semver("1.2.3-pre1.release.1"), 1, 2, 3, "pre1", "release", 1, None
        )

        self.assertTrue(
            Revision.semver("1.2.3-pre1.release.1") < Revision.semver("1.2.3-pre2.release.1")
        )
        self.assertTrue(
            Revision.semver("1.2.3-pre1.release.2") < Revision.semver("1.2.3-pre1.release.10")
        )

        self.assertTrue(Revision.semver("1.2.3") < Revision.semver("1.2.3-pre2.release.1"))
 def test_java_version_aliases(self):
   expected = {}
   for version in (6, 7, 8):
     expected[Revision.lenient('1.{}'.format(version))] = {
       self._java('j1{}'.format(version), '1.{}'.format(version)),
       self._java('j{}'.format(version), '{}'.format(version)),
     }
   partition = self._partition(list(reduce(set.union, expected.values(), set())),
                               platforms=self._platforms('6', '7', '8', '1.6', '1.7', '1.8'))
   self.assertEqual(len(expected), len(partition))
   self.assert_partitions_equal(expected, partition)
 def test_java_version_aliases(self):
   expected = {}
   for version in (6, 7, 8):
     expected[Revision.lenient('1.{}'.format(version))] = {
       self._java('j1{}'.format(version), '1.{}'.format(version)),
       self._java('j{}'.format(version), '{}'.format(version)),
     }
   partition = self._partition(list(reduce(set.union, expected.values(), set())),
                               platforms=self._platforms('6', '7', '8', '1.6', '1.7', '1.8'))
   self.assertEqual(len(expected), len(partition))
   self.assert_partitions_equal(expected, partition)
Example #28
0
    def _check_deprecated(self, dest, kwargs):
        """Checks option for deprecation and issues a warning/error if necessary."""
        deprecated_ver = kwargs.get('deprecated_version', None)
        if deprecated_ver is not None:
            msg = (
                "Option '{dest}' in {scope} is deprecated and removed in version {removal_version}. {hint}"
            ).format(dest=dest,
                     scope=self._scope_str(),
                     removal_version=deprecated_ver,
                     hint=kwargs.get('deprecated_hint', ''))

            if Revision.semver(VERSION) >= Revision.semver(deprecated_ver):
                # Once we've hit the deprecated_version, raise an error instead of warning. This allows for
                # more actionable options hinting to continue beyond the deprecation period until removal.
                raise DeprecatedOptionError(msg)
            else:
                # Out of range stacklevel to suppress printing src line.
                warnings.warn('*** {}'.format(msg),
                              DeprecationWarning,
                              stacklevel=9999)
Example #29
0
 def _parse_java_version(name, version):
   # Java version strings have been well defined since release 1.3.1 as defined here:
   #  http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html
   # These version strings comply with semver except that the traditional pre-release semver
   # slot (the 4th) can be delimited by an _ in the case of update releases of the jdk.
   # We accommodate that difference here.
   if isinstance(version, string_types):
     version = Revision.semver(version.replace('_', '-'))
   if version and not isinstance(version, Revision):
     raise ValueError('%s must be a string or a Revision object, given: %s' % (name, version))
   return version
Example #30
0
 def _parse_java_version(name, version):
   # Java version strings have been well defined since release 1.3.1 as defined here:
   #  http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html
   # These version strings comply with semver except that the traditional pre-release semver
   # slot (the 4th) can be delimited by an _ in the case of update releases of the jdk.
   # We accomodate that difference here.
   if isinstance(version, Compatibility.string):
     version = Revision.semver(version.replace('_', '-'))
   if version and not isinstance(version, Revision):
     raise ValueError('%s must be a string or a Revision object, given: %s' % (name, version))
   return version
Example #31
0
    def test_validate_version(self):
        with pytest.raises(Distribution.Error):
            with self.distribution(executables=self.exe("java", "1.7.0_25")) as jdk:
                Distribution(bin_path=jdk, minimum_version="1.7.0_45").validate()
        with pytest.raises(Distribution.Error):
            with self.distribution(executables=self.exe("java", "1.8.0_1")) as jdk:
                Distribution(bin_path=jdk, maximum_version="1.7.9999").validate()

        with self.distribution(executables=self.exe("java", "1.7.0_25")) as jdk:
            Distribution(bin_path=jdk, minimum_version="1.7.0_25").validate()
            Distribution(bin_path=jdk, minimum_version=Revision.semver("1.6.0")).validate()
            Distribution(bin_path=jdk, minimum_version="1.7.0_25", maximum_version="1.7.999").validate()
Example #32
0
  def parse_java_version(cls, version):
    """Parses the java version (given a string or Revision object).

    Handles java version-isms, converting things like '7' -> '1.7' appropriately.

    Truncates input versions down to just the major and minor numbers (eg, 1.6), ignoring extra
    versioning information after the second number.

    :param version: the input version, given as a string or Revision object.
    :return: the parsed and cleaned version, suitable as a javac -source or -target argument.
    :rtype: Revision
    """
    conversion = {str(i): '1.{}'.format(i) for i in cls.SUPPORTED_CONVERSION_VERSIONS}
    if str(version) in conversion:
      return Revision.lenient(conversion[str(version)])

    if not hasattr(version, 'components'):
      version = Revision.lenient(version)
    if len(version.components) <= 2:
      return version
    return Revision(*version.components[:2])
Example #33
0
    def test_pre_release(self):
        assert Revision.semver("1.2.3-pre1.release.1") == Revision.semver("1.2.3-pre1.release.1")

        assert Revision.semver("1.2.3-pre1.release.1").components == [
            1,
            2,
            3,
            "pre1",
            "release",
            1,
            None,
        ]

        assert Revision.semver("1.2.3-pre1.release.1") < Revision.semver("1.2.3-pre2.release.1")

        assert Revision.semver("1.2.3-pre1.release.2") < Revision.semver("1.2.3-pre1.release.10")

        assert Revision.semver("1.2.3") < Revision.semver("1.2.3-pre2.release.1")
 def test_java_version_aliases(self):
     expected = {}
     for version in (6, 7, 8):
         expected[Revision.lenient("1.{}".format(version))] = {
             self._java("j1{}".format(version), "1.{}".format(version)),
             self._java("j{}".format(version), "{}".format(version)),
         }
     partition = self._partition(
         list(reduce(set.union, expected.values(), set())),
         platforms=self._platforms("6", "7", "8", "1.6", "1.7", "1.8"),
     )
     self.assertEqual(len(expected), len(partition))
     self.assert_partitions_equal(expected, partition)
    def execute(self):
        indexable_targets = IndexableJavaTargets.global_instance().get(
            self.context)
        targets_to_zinc_args = self.context.products.get_data('zinc_args')

        with self.invalidated(
                indexable_targets,
                invalidate_dependents=True) as invalidation_check:
            extractor_cp = self.tool_classpath('kythe-java-extractor')
            for vt in invalidation_check.invalid_vts:
                self.context.log.info('Kythe extracting from {}\n'.format(
                    vt.target.address.spec))
                javac_args = self._get_javac_args_from_zinc_args(
                    targets_to_zinc_args[vt.target])
                jvm_options = []
                if self.dist.version < Revision.lenient('9'):
                    # When run on JDK8, Kythe requires javac9 on the bootclasspath.
                    javac9_cp = self.tool_classpath('javac9')
                    jvm_options.append('-Xbootclasspath/p:{}'.format(
                        ':'.join(javac9_cp)))
                jvm_options.extend(self.get_options().jvm_options)
                jvm_options.extend([
                    '-DKYTHE_CORPUS={}'.format(vt.target.address.spec),
                    '-DKYTHE_ROOT_DIRECTORY={}'.format(vt.target.target_base),
                    '-DKYTHE_OUTPUT_DIRECTORY={}'.format(vt.results_dir)
                ])

                result = self.dist.execute_java(
                    classpath=extractor_cp,
                    main=self._KYTHE_JAVA_EXTRACTOR_MAIN,
                    jvm_options=jvm_options,
                    args=javac_args,
                    create_synthetic_jar=False,
                    workunit_factory=self.context.new_workunit,
                    workunit_name='kythe-extract')
                if result != 0:
                    raise TaskError(
                        'java {main} ... exited non-zero ({result})'.format(
                            main=self._KYTHE_JAVA_EXTRACTOR_MAIN,
                            result=result))

        for vt in invalidation_check.all_vts:
            created_files = os.listdir(vt.results_dir)
            if len(created_files) != 1:
                raise TaskError(
                    'Expected a single .kzip file in {}. Got: {}.'.format(
                        vt.results_dir,
                        ', '.join(created_files) if created_files else 'none'))
            kzip_files = self.context.products.get_data('kzip_files', dict)
            kzip_files[vt.target] = os.path.join(vt.results_dir,
                                                 created_files[0])
Example #36
0
 def _parse_java_version(name, version):
   # Java version strings have been well defined since release 1.3.1 as defined here:
   #  http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html
   # These version strings comply with semver except that the traditional pre-release semver
   # slot (the 4th) can be delimited by an _ in the case of update releases of the jdk.
   # We accommodate that difference here using lenient parsing.
   # We also accommodate specification versions, which just have major and minor
   # components; eg: `1.8`.  These are useful when specifying constraints a distribution must
   # satisfy; eg: to pick any 1.8 java distribution: '1.8' <= version <= '1.8.99'
   if isinstance(version, string_types):
     version = Revision.lenient(version)
   if version and not isinstance(version, Revision):
     raise ValueError('{} must be a string or a Revision object, given: {}'.format(name, version))
   return version
Example #37
0
  def _run_tests(self, tests_to_targets, main, extra_jvm_options=None, classpath_prepend=(),
                 classpath_append=()):
    extra_jvm_options = extra_jvm_options or []

    tests_by_properties = self._tests_by_properties(tests_to_targets,
                                                    self._infer_workdir,
                                                    lambda target: target.test_platform)

    result = 0
    for (workdir, platform), tests in tests_by_properties.items():
      for batch in self._partition(tests):
        # Batches of test classes will likely exist within the same targets: dedupe them.
        relevant_targets = set(map(tests_to_targets.get, batch))
        classpath = self._task_exports.classpath(relevant_targets,
                                                 cp=self._task_exports.tool_classpath('junit'))
        complete_classpath = OrderedSet()
        complete_classpath.update(classpath_prepend)
        complete_classpath.update(classpath)
        complete_classpath.update(classpath_append)
        if self._strict_jvm_version:
          max_version = Revision(*(platform.target_level.components + [9999]))
          distribution = Distribution.cached(minimum_version=platform.target_level,
                                             maximum_version=max_version)
        else:
          distribution = Distribution.cached(minimum_version=platform.target_level)
        with binary_util.safe_args(batch, self._task_exports.task_options) as batch_tests:
          self._context.log.debug('CWD = {}'.format(workdir))
          self._context.log.debug('platform = {}'.format(platform))
          result += abs(execute_java(
            classpath=complete_classpath,
            main=main,
            jvm_options=self._task_exports.jvm_options + extra_jvm_options,
            args=self._args + batch_tests + [u'-xmlreport'],
            workunit_factory=self._context.new_workunit,
            workunit_name='run',
            workunit_labels=[WorkUnitLabel.TEST],
            cwd=workdir,
            distribution=distribution,
          ))

          if result != 0 and self._fail_fast:
            break

    if result != 0:
      failed_targets = self._get_failed_targets(tests_to_targets)
      raise TestFailedTaskError(
        'java {0} ... exited non-zero ({1}); {2} failed targets.'
        .format(main, result, len(failed_targets)),
        failed_targets=failed_targets
      )
 def test_java_version_aliases(self):
     # NB: This feature is only supported for Java 6-8. Java 9+ must be referred to, for example,
     # as `9`, not `1.9`.
     expected = {}
     for version in (6, 7, 8):
         expected[Revision.lenient(f'1.{version}')] = {
             self._java(f'j1{version}', f'1.{version}'),
             self._java(f'j{version}', f'{version}'),
         }
     partition = self._partition(
         list(reduce(set.union, list(expected.values()), set())),
         platforms=self._platforms('6', '7', '8', '1.6', '1.7', '1.8'))
     self.assertEqual(len(expected), len(partition))
     self.assert_partitions_equal(expected, partition)
Example #39
0
  def errorprone(self, target):
    runtime_classpaths = self.context.products.get_data('runtime_classpath')
    runtime_classpath = [jar for conf, jar in runtime_classpaths.get_for_targets(target.closure(bfs=True))]

    output_dir = os.path.join(self.workdir, target.id)
    safe_mkdir(output_dir)
    runtime_classpath.append(output_dir)

    # Try to run errorprone with the same java version as the target
    # The minimum JDK for errorprone is JDK 1.8
    min_jdk_version = max(target.platform.target_level, Revision.lenient('1.8'))
    if min_jdk_version.components[0] == 1:
      max_jdk_version = Revision(min_jdk_version.components[0], min_jdk_version.components[1], '9999')
    else:
      max_jdk_version = Revision(min_jdk_version.components[0], '9999')
    self.set_distribution(minimum_version=min_jdk_version, maximum_version=max_jdk_version, jdk=True)

    jvm_options = self.get_options().jvm_options[:]
    if self.dist.version < Revision.lenient('9'):
      # For Java 8 we need to add the errorprone javac jar to the bootclasspath to
      # avoid the "java.lang.NoSuchFieldError: ANNOTATION_PROCESSOR_MODULE_PATH" error
      # See https://github.com/google/error-prone/issues/653 for more information
      jvm_options.extend(['-Xbootclasspath/p:{}'.format(self.tool_classpath('errorprone-javac')[0])])

    args = [
      '-d', output_dir,
    ]

    # Errorprone does not recognize source or target 10 yet
    if target.platform.source_level < Revision.lenient('10'):
      args.extend(['-source', str(target.platform.source_level)])

    if target.platform.target_level < Revision.lenient('10'):
      args.extend(['-target', str(target.platform.target_level)])

    errorprone_classpath_file = os.path.join(self.workdir, '{}.classpath'.format(os.path.basename(output_dir)))
    with open(errorprone_classpath_file, 'w') as f:
      f.write('-classpath ')
      f.write(':'.join(runtime_classpath))
    args.append('@{}'.format(errorprone_classpath_file))

    for opt in self.get_options().command_line_options:
      args.extend(safe_shlex_split(opt))

    with argfile.safe_args(self.calculate_sources(target), self.get_options()) as batched_sources:
      args.extend(batched_sources)
      result = self.runjava(classpath=self.tool_classpath('errorprone'),
                            main=self._ERRORPRONE_MAIN,
                            jvm_options=jvm_options,
                            args=args,
                            workunit_name='errorprone',
                            workunit_labels=[WorkUnitLabel.LINT])

      self.context.log.debug('java {main} ... exited with result ({result})'.format(
        main=self._ERRORPRONE_MAIN, result=result))

    return result
Example #40
0
  def test_validate_version(self):
    with distribution(executables=EXE('bin/java', '1.7.0_25')) as dist_root:
      with self.assertRaises(Distribution.Error):
        Distribution(bin_path=os.path.join(dist_root, 'bin'), minimum_version='1.7.0_45').validate()
    with distribution(executables=EXE('bin/java', '1.8.0_1')) as dist_root:
      with self.assertRaises(Distribution.Error):
        Distribution(bin_path=os.path.join(dist_root, 'bin'), maximum_version='1.8').validate()

    with distribution(executables=EXE('bin/java', '1.7.0_25')) as dist_root:
      Distribution(bin_path=os.path.join(dist_root, 'bin'), minimum_version='1.7.0_25').validate()
      Distribution(bin_path=os.path.join(dist_root, 'bin'),
                   minimum_version=Revision.lenient('1.6')).validate()
      Distribution(bin_path=os.path.join(dist_root, 'bin'),
                   minimum_version='1.7.0_25',
                   maximum_version='1.7.999').validate()
Example #41
0
  def test_validate_version(self):
    with distribution(executables=EXE('bin/java', '1.7.0_25')) as dist_root:
      with self.assertRaises(Distribution.Error):
        Distribution(bin_path=os.path.join(dist_root, 'bin'), minimum_version='1.7.0_45').validate()
    with distribution(executables=EXE('bin/java', '1.8.0_1')) as dist_root:
      with self.assertRaises(Distribution.Error):
        Distribution(bin_path=os.path.join(dist_root, 'bin'), maximum_version='1.8').validate()

    with distribution(executables=EXE('bin/java', '1.7.0_25')) as dist_root:
      Distribution(bin_path=os.path.join(dist_root, 'bin'), minimum_version='1.7.0_25').validate()
      Distribution(bin_path=os.path.join(dist_root, 'bin'),
                   minimum_version=Revision.lenient('1.6')).validate()
      Distribution(bin_path=os.path.join(dist_root, 'bin'),
                   minimum_version='1.7.0_25',
                   maximum_version='1.7.999').validate()
Example #42
0
 def wire_compiler_version(self):
   wire_compiler_jars = set()
   classpath_spec = self.get_options().wire_compiler
   for target in self.context.resolve(classpath_spec):
     if isinstance(target, JarLibrary):
       wire_compiler_jars.update(jar for jar in target.jar_dependencies
                                 if self.is_wire_compiler_jar(jar))
   if len(wire_compiler_jars) != 1:
     msg = ('Expected to find exactly 1 wire-compiler jar in --wire-compiler classpath rooted '
            'at {}, but found {}'
            .format(classpath_spec,
                    ', '.join(map(str, wire_compiler_jars)) if wire_compiler_jars else 0))
     raise self.WireCompilerVersionError(msg)
   wire_compiler_jar = wire_compiler_jars.pop()
   wire_compiler_version = wire_compiler_jar.rev
   return Revision.lenient(wire_compiler_version)
Example #43
0
  def preferred_jvm_distribution(cls, platforms, strict=False):
    """Returns a jvm Distribution with a version that should work for all the platforms.

    Any one of those distributions whose version is >= all requested platforms' versions
    can be returned unless strict flag is set.

    :param iterable platforms: An iterable of platform settings.
    :param bool strict: If true, only distribution whose version matches the minimum
      required version can be returned, i.e, the max target_level of all the requested
      platforms.
    :returns: Distribution one of the selected distributions.
    """
    if not platforms:
      return DistributionLocator.cached()
    min_version = max(platform.target_level for platform in platforms)
    max_version = Revision(*(min_version.components + [9999])) if strict else None
    return DistributionLocator.cached(minimum_version=min_version, maximum_version=max_version)
Example #44
0
def validate_removal_semver(removal_version):
  """Validates that removal_version is a valid semver.

  If so, returns that semver.  Raises an error otherwise.

  :param str removal_version: The pantsbuild.pants version which will remove the deprecated entity.
  :rtype: `pants.base.Revision`
  :raises DeprecationApplicationError: if the removal_version parameter is invalid.
  """
  if removal_version is None:
    raise MissingRemovalVersionError('The removal version must be provided.')
  if not isinstance(removal_version, six.string_types):
    raise BadRemovalVersionError('The removal_version must be a semver version string.')
  try:
    return Revision.semver(removal_version)
  except Revision.BadRevision as e:
    raise BadRemovalVersionError('The given removal version {} is not a valid semver: '
                                 '{}'.format(removal_version, e))
Example #45
0
def validate_removal_semver(removal_version):
  """Validates that removal_version is a valid semver.

  If so, returns that semver.  Raises an error otherwise.

  :param str removal_version: The pantsbuild.pants version which will remove the deprecated entity.
  :rtype: `pants.base.Revision`
  :raises DeprecationApplicationError: if the removal_version parameter is invalid.
  """
  if removal_version is None:
    raise MissingRemovalVersionError('The removal version must be provided.')
  if not isinstance(removal_version, six.string_types):
    raise BadRemovalVersionError('The removal_version must be a semver version string.')
  try:
    return Revision.semver(removal_version)
  except Revision.BadRevision as e:
    raise BadRemovalVersionError('The given removal version {} is not a valid semver: '
                                 '{}'.format(removal_version, e))
Example #46
0
 def wire_compiler_version(self):
     wire_compiler_jars = set()
     classpath_spec = self.get_options().wire_compiler
     for target in self.context.resolve(classpath_spec):
         if isinstance(target, JarLibrary):
             wire_compiler_jars.update(jar
                                       for jar in target.jar_dependencies
                                       if self.is_wire_compiler_jar(jar))
     if len(wire_compiler_jars) != 1:
         msg = (
             'Expected to find exactly 1 wire-compiler jar in --wire-compiler classpath rooted '
             'at {}, but found {}'.format(
                 classpath_spec, ', '.join(map(str, wire_compiler_jars))
                 if wire_compiler_jars else 0))
         raise self.WireCompilerVersionError(msg)
     wire_compiler_jar = wire_compiler_jars.pop()
     wire_compiler_version = wire_compiler_jar.rev
     return Revision.lenient(wire_compiler_version)
Example #47
0
def check_deprecated_semver(removal_version):
  """Check to see if the removal version is < the current Pants version.
   :param str removal_version: The pantsbuild.pants version which will remove the deprecated
                              function.
   :raises DeprecationApplicationError if the removal_version parameter is invalid or the version
   is not an earlier version than the current release version.
  """
  if not isinstance(removal_version, six.string_types):
    raise BadRemovalVersionError('The removal_version must be a semver version string.')

  try:
    removal_semver = Revision.semver(removal_version)
  except Revision.BadRevision as e:
    raise BadRemovalVersionError('The given removal version {} is not a valid semver: '
                                 '{}'.format(removal_version, e))

  if removal_semver <= _PANTS_SEMVER:
    raise PastRemovalVersionError('The removal version must be greater than the current pants '
                                  'version of {} - given {}'.format(VERSION, removal_version))
Example #48
0
 def test_wire_compiler_version_robust(self):
     # Here the wire compiler is both indirected, and not 1st in the classpath order.
     guava = self.make_target(
         '3rdparty:guava',
         JarLibrary,
         jars=[JarDependency('com.google.guava', 'guava', '18.0')])
     wire = self.make_target(
         '3rdparty:wire',
         JarLibrary,
         jars=[
             JarDependency('com.squareup.wire', 'wire-compiler',
                           '3.0.0').exclude('com.google.guava', 'guava')
         ])
     alias = self.make_target('a/random/long/address:spec',
                              Target,
                              dependencies=[guava, wire])
     self.set_options(wire_compiler='a/random/long/address:spec')
     task = self.create_task(self.context(target_roots=[alias]))
     self.assertEqual(Revision(3, 0, 0), task.wire_compiler_version)
Example #49
0
  def execute(self):
    indexable_targets = IndexableJavaTargets.global_instance().get(self.context)

    with self.invalidated(indexable_targets, invalidate_dependents=True) as invalidation_check:
      if invalidation_check.invalid_vts:
        indexer_cp = self.tool_classpath('kythe-java-indexer')
        jvm_options = []
        if self.dist.version < Revision.lenient('9'):
          # When run on JDK8, Kythe requires javac9 on the bootclasspath.
          javac9_cp = self.tool_classpath('javac9')
          jvm_options.append('-Xbootclasspath/p:{}'.format(':'.join(javac9_cp)))
        jvm_options.extend(self.get_options().jvm_options)

        for vt in invalidation_check.invalid_vts:
          self._index(vt, indexer_cp, jvm_options)

    for vt in invalidation_check.all_vts:
      entries = self._entries_file(vt)
      self.context.products.get_data('kythe_entries_files', dict)[vt.target] = entries
Example #50
0
    def execute(self):
        indexable_targets = IndexableJavaTargets.global_instance().get(self.context)

        with self.invalidated(indexable_targets, invalidate_dependents=True) as invalidation_check:
            if invalidation_check.invalid_vts:
                indexer_cp = self.tool_classpath("kythe-java-indexer")
                jvm_options = []
                if self.dist.version < Revision.lenient("9"):
                    # When run on JDK8, Kythe requires javac9 on the bootclasspath.
                    javac9_cp = self.tool_classpath("javac9")
                    jvm_options.append("-Xbootclasspath/p:{}".format(":".join(javac9_cp)))
                jvm_options.extend(self.get_options().jvm_options)

                for vt in invalidation_check.invalid_vts:
                    self._index(vt, indexer_cp, jvm_options)

        for vt in invalidation_check.all_vts:
            entries = self._entries_file(vt)
            self.context.products.get_data("kythe_entries_files", dict)[vt.target] = entries
Example #51
0
def check_deprecated_semver(removal_version, check_expired=True):
  """Check to see if the removal version is < the current Pants version.
   :param str removal_version: The pantsbuild.pants version which will remove the deprecated
                              function.
   :raises DeprecationApplicationError if the removal_version parameter is invalid or the version
   is not an earlier version than the current release version.
  """
  if not isinstance(removal_version, six.string_types):
    raise BadRemovalVersionError('The removal_version must be a semver version string.')

  try:
    removal_semver = Revision.semver(removal_version)
  except Revision.BadRevision as e:
    raise BadRemovalVersionError('The given removal version {} is not a valid semver: '
                                 '{}'.format(removal_version, e))

  if check_expired and removal_semver <= _PANTS_SEMVER:
    raise PastRemovalVersionError('The removal version must be greater than the current pants '
                                  'version of {} - given {}'.format(VERSION, removal_version))
Example #52
0
 def console_output(self, targets):
   self._force_option_parsing()
   if self.is_json():
     output_map = {}
   for scope, options in sorted(self.context.options.tracker.option_history_by_scope.items()):
     if not self._scope_filter(scope):
       continue
     for option, history in sorted(options.items()):
       if not self._option_filter(option):
         continue
       if not self._rank_filter(history.latest.rank):
         continue
       if self.get_options().only_overridden and not history.was_overridden:
         continue
       # Skip the option if it has already passed the deprecation period.
       if history.latest.deprecation_version and PANTS_SEMVER >= Revision.semver(
         history.latest.deprecation_version):
         continue
       if self.get_options().skip_inherited:
         parent_scope, parent_value = self._get_parent_scope_option(scope, option)
         if parent_scope is not None and parent_value == history.latest.value:
           continue
       if self.is_json():
         opt_vals = self._format_record(history.latest)
         scope_key = self._format_scope(scope, option, True)
         inner_map = dict(value=opt_vals[0], source=opt_vals[1])
         output_map[scope_key] = inner_map
       elif self.is_text():
         yield '{} = {}'.format(self._format_scope(scope, option),
                                self._format_record(history.latest))
       if self.get_options().show_history:
         history_list = []
         for line in self._show_history(history):
           if self.is_text():
             yield line
           elif self.is_json():
             history_list.append(line.strip())
         if self.is_json():
           inner_map["history"] = history_list
   if self.is_json():
     yield json.dumps(output_map, indent=2, sort_keys=True)
Example #53
0
  def execute(self):
    indexable_targets = IndexableJavaTargets.global_instance().get(self.context)
    targets_to_zinc_args = self.context.products.get_data('zinc_args')

    with self.invalidated(indexable_targets, invalidate_dependents=True) as invalidation_check:
      extractor_cp = self.tool_classpath('kythe-java-extractor')
      for vt in invalidation_check.invalid_vts:
        self.context.log.info('Kythe extracting from {}\n'.format(vt.target.address.spec))
        javac_args = self._get_javac_args_from_zinc_args(targets_to_zinc_args[vt.target])
        jvm_options = []
        if self.dist.version < Revision.lenient('9'):
          # When run on JDK8, Kythe requires javac9 on the bootclasspath.
          javac9_cp = self.tool_classpath('javac9')
          jvm_options.append('-Xbootclasspath/p:{}'.format(':'.join(javac9_cp)))
        jvm_options.extend(self.get_options().jvm_options)
        jvm_options.extend([
          '-DKYTHE_CORPUS={}'.format(vt.target.address.spec),
          '-DKYTHE_ROOT_DIRECTORY={}'.format(vt.target.target_base),
          '-DKYTHE_OUTPUT_DIRECTORY={}'.format(vt.results_dir)
        ])

        result = self.dist.execute_java(
          classpath=extractor_cp, main=self._KYTHE_JAVA_EXTRACTOR_MAIN,
          jvm_options=jvm_options, args=javac_args, create_synthetic_jar=False,
          workunit_factory=self.context.new_workunit, workunit_name='kythe-extract')
        if result != 0:
          raise TaskError('java {main} ... exited non-zero ({result})'.format(
            main=self._KYTHE_JAVA_EXTRACTOR_MAIN, result=result))

    for vt in invalidation_check.all_vts:
      created_files = os.listdir(vt.results_dir)
      if len(created_files) != 1:
        raise TaskError('Expected a single .kzip file in {}. Got: {}.'.format(
          vt.results_dir, ', '.join(created_files) if created_files else 'none'))
      kzip_files = self.context.products.get_data('kzip_files', dict)
      kzip_files[vt.target] = os.path.join(vt.results_dir, created_files[0])
  def resolve_version_conflict(self, managed_coord, direct_coord, force=False):
    """Resolves an artifact version conflict between directly specified and managed jars.

    This uses the user-defined --conflict-strategy to pick the appropriate artifact version (or to
    raise an error).

    This assumes the two conflict coordinates differ only by their version.

    :param M2Coordinate managed_coord: the artifact coordinate as defined by a
      managed_jar_dependencies object.
    :param M2Coordinate direct_coord: the artifact coordinate as defined by a jar_library target.
    :param bool force: Whether the artifact defined by the jar_library() was marked with force=True.
      This is checked only if one of the *_IF_FORCED conflict strategies is being used.
    :return: the coordinate of the artifact that should be resolved.
    :rtype: M2Coordinate
    :raises: JarDependencyManagement.DirectManagedVersionConflict if the versions are different and
      the --conflict-strategy is 'FAIL' (which is the default).
    """
    if M2Coordinate.unversioned(managed_coord) != M2Coordinate.unversioned(direct_coord):
      raise ValueError('Illegal arguments passed to resolve_version_conflict: managed_coord and '
                       'direct_coord must only differ by their version!\n'
                       '  Managed: {}\n  Direct:  {}\n'.format(
        M2Coordinate.unversioned(managed_coord),
        M2Coordinate.unversioned(direct_coord),
      ))

    if direct_coord.rev is None or direct_coord.rev == managed_coord.rev:
      return managed_coord

    strategy = self.get_options().conflict_strategy
    message = dedent("""
      An artifact directly specified by a jar_library target has a different version than what
      is specified by managed_jar_dependencies.

        Artifact: jar(org={org}, name={name}, classifier={classifier}, ext={ext})
        Direct version:  {direct}
        Managed version: {managed}
    """).format(
      org=direct_coord.org,
      name=direct_coord.name,
      classifier=direct_coord.classifier,
      ext=direct_coord.ext,
      direct=direct_coord.rev,
      managed=managed_coord.rev,
    )

    if strategy == 'FAIL':
      raise self.DirectManagedVersionConflict(
        '{}\nThis raises an error due to the current --jar-dependency-management-conflict-strategy.'
        .format(message)
      )

    is_silent = self.get_options().suppress_conflict_warnings
    log = logger.debug if is_silent else logger.warn

    if strategy == 'USE_DIRECT':
      log(message)
      log('[{}] Using direct version: {}'.format(strategy, direct_coord))
      return direct_coord

    if strategy == 'USE_DIRECT_IF_FORCED':
      log(message)
      if force:
        log('[{}] Using direct version, because force=True: {}'.format(strategy, direct_coord))
        return direct_coord
      else:
        log('[{}] Using managed version, because force=False: {}'.format(strategy, managed_coord))
        return managed_coord

    if strategy == 'USE_MANAGED':
      log(message)
      log('[{}] Using managed version: {}'.format(strategy, managed_coord))
      return managed_coord

    if strategy == 'USE_NEWER':
      newer = max([managed_coord, direct_coord],
                  key=lambda coord: Revision.lenient(coord.rev))
      log(message)
      log('[{}] Using newer version: {}'.format(strategy, newer))
      return newer

    raise TaskError('Unknown value for --conflict-strategy: {}'.format(strategy))
Example #55
0
# coding=utf-8
# Copyright 2014 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.revision import Revision


VERSION = '1.1.0-pre6'

PANTS_SEMVER = Revision.semver(VERSION)
Example #56
0
def get_deprecated_tense(removal_version, future_tense='will be', past_tense='was'):
  """Provides the grammatical tense for a given deprecated version vs the current version."""
  return future_tense if (Revision.semver(removal_version) >= PANTS_SEMVER) else past_tense
Example #57
0
# Copyright 2016 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)

import re
from contextlib import contextmanager

from pants.base.revision import Revision
from pants.scm.git import Git
from pants.util.contextutil import environment_as, temporary_dir
from pants.util.process_handler import subprocess


MIN_REQUIRED_GIT_VERSION = Revision.semver('1.7.10')


def git_version():
  """Get a Version() based on installed command-line git's version"""
  process = subprocess.Popen(['git', '--version'], stdout=subprocess.PIPE)
  (stdout, stderr) = process.communicate()
  assert process.returncode == 0, "Failed to determine git version."
  # stdout is like 'git version 1.9.1.598.g9119e8b\n'  We want '1.9.1.598'
  matches = re.search(r'\s(\d+(?:\.\d+)*)[\s\.]', stdout)
  return Revision.lenient(matches.group(1))


def get_repo_root():
  """Return the absolute path to the root directory of the Pants git repo."""
  return subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).strip()