Ejemplo n.º 1
0
    def _check_invalid_tags(self, symbol_map):
        """Check for commits on any symbols that are to be converted as tags.

    SYMBOL_MAP is a map {AbstractSymbol : (Trunk|TypedSymbol)}
    indicating how each AbstractSymbol is to be converted.  If there
    is a commit on a symbol, then it cannot be converted as a tag.  If
    any tags with commits are found, output error messages describing
    the problems then raise a FatalException."""

        logger.quiet("Checking for forced tags with commits...")

        invalid_tags = []
        for symbol in symbol_map.itervalues():
            if isinstance(symbol, Tag):
                stats = self.get_stats(symbol)
                if stats.branch_commit_count > 0:
                    invalid_tags.append(symbol)

        if not invalid_tags:
            # No problems found:
            return

        s = []
        s.append('%s: The following branches cannot be forced to be tags '
                 'because they have commits:\n' % (error_prefix, ))
        for tag in invalid_tags:
            s.append('    %s\n' % (tag.name))
        s.append('\n')
        logger.error(''.join(s))

        raise FatalException()
Ejemplo n.º 2
0
  def _check_blocked_excludes(self, symbol_map):
    """Check for any excluded LODs that are blocked by non-excluded symbols.

    If any are found, describe the problem to logger.error() and raise
    a FatalException."""

    # A list of (lod,[blocker,...]) tuples for excludes that are
    # blocked by the specified non-excluded blockers:
    problems = []

    for lod in symbol_map.itervalues():
      if isinstance(lod, ExcludedSymbol):
        # Symbol is excluded; make sure that its blockers are also
        # excluded:
        lod_blockers = []
        for blocker in self.get_stats(lod).branch_blockers:
          if isinstance(symbol_map.get(blocker, None), IncludedSymbol):
            lod_blockers.append(blocker)
        if lod_blockers:
          problems.append((lod, lod_blockers))

    if problems:
      s = []
      for (lod, lod_blockers) in problems:
        s.append(
            '%s: %s cannot be excluded because the following symbols '
                'depend on it:\n'
            % (error_prefix, lod,)
            )
        for blocker in lod_blockers:
          s.append('    %s\n' % (blocker,))
      s.append('\n')
      logger.error(''.join(s))

      raise FatalException()
Ejemplo n.º 3
0
    def run(self, run_options, stats_keeper):
        Ctx()._projects = read_projects(
            artifact_manager.get_temp_file(config.PROJECTS))
        Ctx()._cvs_path_db = CVSPathDatabase(DB_OPEN_READ)
        self.symbol_db = SymbolDatabase()
        Ctx()._symbol_db = self.symbol_db

        logger.quiet("Checking dependency consistency...")

        fatal_errors = []
        for cvs_item in self.iter_cvs_items():
            # Check that the pred_ids and succ_ids are mutually consistent:
            for pred_id in cvs_item.get_pred_ids():
                pred = self.get_cvs_item(pred_id)
                if not cvs_item.id in pred.get_succ_ids():
                    fatal_errors.append(
                        '%s lists pred=%s, but not vice versa.' % (
                            cvs_item,
                            pred,
                        ))

            for succ_id in cvs_item.get_succ_ids():
                succ = self.get_cvs_item(succ_id)
                if not cvs_item.id in succ.get_pred_ids():
                    fatal_errors.append(
                        '%s lists succ=%s, but not vice versa.' % (
                            cvs_item,
                            succ,
                        ))

        if fatal_errors:
            raise FatalException('Dependencies inconsistent:\n'
                                 '%s\n'
                                 'Exited due to fatal error(s).' %
                                 ('\n'.join(fatal_errors), ))

        self.symbol_db.close()
        self.symbol_db = None
        Ctx()._cvs_path_db.close()
        logger.quiet("Done")
Ejemplo n.º 4
0
class SymbolStatistics:
    """Read and handle line of development statistics.

  The statistics are read from a database created by
  SymbolStatisticsCollector.  This class has methods to process the
  statistics information and help with decisions about:

  1. What tags and branches should be processed/excluded

  2. What tags should be forced to be branches and vice versa (this
     class maintains some statistics to help the user decide)

  3. Are there inconsistencies?

     - A symbol that is sometimes a branch and sometimes a tag

     - A forced branch with commit(s) on it

     - A non-excluded branch depends on an excluded branch

  The data in this class is read from a pickle file."""
    def __init__(self, filename):
        """Read the stats database from FILENAME."""

        # A map { LineOfDevelopment -> _Stats } for all lines of
        # development:
        self._stats = {}

        # A map { LineOfDevelopment.id -> _Stats } for all lines of
        # development:
        self._stats_by_id = {}

        stats_list = cPickle.load(open(filename, 'rb'))

        for stats in stats_list:
            self._stats[stats.lod] = stats
            self._stats_by_id[stats.lod.id] = stats

    def __len__(self):
        return len(self._stats)

    def __getitem__(self, lod_id):
        return self._stats_by_id[lod_id]

    def get_stats(self, lod):
        """Return the _Stats object for LineOfDevelopment instance LOD.

    Raise KeyError if no such lod exists."""

        return self._stats[lod]

    def __iter__(self):
        return self._stats.itervalues()

    def _check_blocked_excludes(self, symbol_map):
        """Check for any excluded LODs that are blocked by non-excluded symbols.

    If any are found, describe the problem to logger.error() and raise
    a FatalException."""

        # A list of (lod,[blocker,...]) tuples for excludes that are
        # blocked by the specified non-excluded blockers:
        problems = []

        for lod in symbol_map.itervalues():
            if isinstance(lod, ExcludedSymbol):
                # Symbol is excluded; make sure that its blockers are also
                # excluded:
                lod_blockers = []
                for blocker in self.get_stats(lod).branch_blockers:
                    if isinstance(symbol_map.get(blocker, None),
                                  IncludedSymbol):
                        lod_blockers.append(blocker)
                if lod_blockers:
                    problems.append((lod, lod_blockers))

        if problems:
            s = []
            for (lod, lod_blockers) in problems:
                s.append(
                    '%s: %s cannot be excluded because the following symbols '
                    'depend on it:\n' % (
                        error_prefix,
                        lod,
                    ))
                for blocker in lod_blockers:
                    s.append('    %s\n' % (blocker, ))
            s.append('\n')
            logger.error(''.join(s))

            raise FatalException()

    def _check_invalid_tags(self, symbol_map):
        """Check for commits on any symbols that are to be converted as tags.

    SYMBOL_MAP is a map {AbstractSymbol : (Trunk|TypedSymbol)}
    indicating how each AbstractSymbol is to be converted.  If there
    is a commit on a symbol, then it cannot be converted as a tag.  If
    any tags with commits are found, output error messages describing
    the problems then raise a FatalException."""

        logger.quiet("Checking for forced tags with commits...")

        invalid_tags = []
        for symbol in symbol_map.itervalues():
            if isinstance(symbol, Tag):
                stats = self.get_stats(symbol)
                if stats.branch_commit_count > 0:
                    invalid_tags.append(symbol)

        if not invalid_tags:
            # No problems found:
            return

        s = []
        s.append('%s: The following branches cannot be forced to be tags '
                 'because they have commits:\n' % (error_prefix, ))
        for tag in invalid_tags:
            s.append('    %s\n' % (tag.name))
        s.append('\n')
        logger.error(''.join(s))

        raise FatalException()

    def check_consistency(self, symbol_map):
        """Check the plan for how to convert symbols for consistency.

    SYMBOL_MAP is a map {AbstractSymbol : (Trunk|TypedSymbol)}
    indicating how each AbstractSymbol is to be converted.  If any
    problems are detected, describe the problem to logger.error() and
    raise a FatalException."""

        # We want to do all of the consistency checks even if one of them
        # fails, so that the user gets as much feedback as possible.  Set
        # this variable to True if any errors are found.
        error_found = False

        # Check that the planned preferred parents are OK for all
        # IncludedSymbols:
        for lod in symbol_map.itervalues():
            if isinstance(lod, IncludedSymbol):
                stats = self.get_stats(lod)
                try:
                    stats.check_preferred_parent_allowed(lod)
                except SymbolPlanException, e:
                    logger.error('%s\n' % (e, ))
                    error_found = True

        try:
            self._check_blocked_excludes(symbol_map)
        except FatalException:
            error_found = True

        try:
            self._check_invalid_tags(symbol_map)
        except FatalException:
            error_found = True

        if error_found:
            raise FatalException(
                'Please fix the above errors and restart CollateSymbolsPass')