コード例 #1
0
ファイル: checkteamtags.py プロジェクト: tt20050510/chromium
def validate_mappings(options, args):
    """Ensure team/component mapping remains consistent after patch.

  The main purpose of this check is to notify the user if any edited (or added)
  team tag makes a component map to multiple teams.

  Args:
    options: Command line options from optparse
    args: List of paths to affected OWNERS files
  Returns:
    A string containing the details of any multi-team per component.
  """
    mappings_file = json.load(urllib2.urlopen(options.current_mapping_url))
    new_dir_to_component = mappings_file.get('dir-to-component', {})
    new_dir_to_team = mappings_file.get('dir-to-team', {})

    affected = {}
    deleted = []
    affected_components = set()

    # Parse affected OWNERS files
    for f in args:
        rel, full = rel_and_full_paths(options.root, f)
        if os.path.exists(full):
            affected[os.path.dirname(rel)] = parse(full)
        else:
            deleted.append(os.path.dirname(rel))

    # Update component mapping with current changes.
    for rel_path, tags in affected.iteritems():
        component = tags.get('component')
        team = tags.get('team')
        os_tag = tags.get('os')
        if component:
            if os_tag:
                component = '%s(%s)' % (component, os_tag)
            new_dir_to_component[rel_path] = component
            affected_components.add(component)
        elif rel_path in new_dir_to_component:
            del new_dir_to_component[rel_path]
        if team:
            new_dir_to_team[rel_path] = team
        elif rel_path in new_dir_to_team:
            del new_dir_to_team[rel_path]
    for deleted_dir in deleted:
        if deleted_dir in new_dir_to_component:
            del new_dir_to_component[deleted_dir]
        if deleted_dir in new_dir_to_team:
            del new_dir_to_team[deleted_dir]

    # For the components affected by this patch, compute the directories that map
    # to it.
    affected_component_to_dirs = {}
    for d, component in new_dir_to_component.iteritems():
        if component in affected_components:
            affected_component_to_dirs.setdefault(component, [])
            affected_component_to_dirs[component].append(d)

    # Convert component->[dirs], dir->team to component->[teams].
    affected_component_to_teams = {
        component:
        list(set([new_dir_to_team[d] for d in dirs if d in new_dir_to_team]))
        for component, dirs in affected_component_to_dirs.iteritems()
    }

    # Perform cardinality check.
    warnings = ''
    for component, teams in affected_component_to_teams.iteritems():
        if len(teams) > 1:
            warnings += '\nComponent %s will map to %s' % (component,
                                                           ', '.join(teams))
    if warnings:
        warnings = (
            'Are you sure these are correct? After landing this patch:%s' %
            warnings)

    return warnings
コード例 #2
0
def validate_mappings(options, args):
    """Ensure team/component mapping remains consistent after patch.

  The main purpose of this check is to prevent new and edited OWNERS files
  introduce multiple teams for the same component.

  Args:
    options: Command line options from optparse
    args: List of paths to affected OWNERS files
  """
    mappings_file = json.load(urllib2.urlopen(options.current_mapping_url))

    # Convert dir -> component, component -> team to dir -> (team, component)
    current_mappings = {}
    for dir_name in mappings_file['dir-to-component'].keys():
        component = mappings_file['dir-to-component'].get(dir_name)
        if component:
            team = mappings_file['component-to-team'].get(component)
        else:
            team = None
        current_mappings[dir_name] = (team, component)

    # Extract dir -> (team, component) for affected files
    affected = {}
    deleted = []
    for f in args:
        rel, full = rel_and_full_paths(options.root, f)
        if os.path.exists(full):
            affected[os.path.dirname(rel)] = parse(full)
        else:
            deleted.append(os.path.dirname(rel))
    for d in deleted:
        current_mappings.pop(d, None)
    current_mappings.update(affected)

    #Ensure internal consistency of modified mappings.
    new_dir_to_component = {}
    new_component_to_team = {}
    team_to_dir = defaultdict(list)
    errors = {}
    for dir_name, tags in current_mappings.iteritems():
        team, component = tags
        if component:
            new_dir_to_component[dir_name] = component
        if team:
            team_to_dir[team].append(dir_name)
        if component and team:
            if new_component_to_team.setdefault(component, team) != team:
                if component not in errors:
                    errors[component] = set(
                        [new_component_to_team[component], team])
                else:
                    errors[component].add(team)

    result = []
    for component, teams in errors.iteritems():
        error_message = 'The component "%s" has more than one team: ' % component
        team_details = []
        for team in teams:
            team_details.append('%(team)s is used in %(paths)s' % {
                'team': team,
                'paths': ', '.join(team_to_dir[team]),
            })
        error_message += '; '.join(team_details)
        result.append({
            'error':
            error_message,
            'full_path':
            ' '.join([
                '%s/OWNERS' % d for d, c in new_dir_to_component.iteritems()
                if c == component and d in affected.keys()
            ])
        })
    return result