<commit_before>#
# Copyright (c) 2008 rPath, Inc.
#
# All rights reserved.
#

'''
Tools for manipulating recipes and source troves.
'''

import logging
import os
import re
import sha
import shutil
import tempfile
import time

from conary import checkin
from conary import state
from conary import versions
from conary.build import cook
from conary.build import use
from conary.deps import deps
from conary.lib import log as conary_log
from conary.lib import util
from rmake import compat

from bob import macro

log = logging.getLogger('bob.mangle')


filters = []


##
## Decorators and helpers
##

def mangle(parent, trove, recipe):
    '''
    Feed the given recipe through all available filters.
    '''
    for f in filters:
        recipe = f(parent, trove, recipe)
    return recipe


def _register(fun):
    '''Decorator: Add the function as a mangler for all mangled recipes.'''
    filters.append(fun)
    return fun


def _require_target_attribute(*target_attributes):
    '''
    Decorator: require that the given attributes be set on a target section
    for the trove being mangled.
    '''

    def decorate(fun):
        def wrapper(parent, trove, recipe):
            if trove not in parent.targets:
                return recipe
            for attribute in target_attributes:
                if not parent.targets[trove][attribute]:
                    return recipe
            return fun(parent, trove, recipe)
        return wrapper
    return decorate


##
## Manglers
##

re_version = re.compile('^(\s+)version\s*=.*?$', re.M)
@_register
@_require_target_attribute('version')
def version(parent, trove, recipe):
    '''
    Update the recipe's version to reflect any configured pattern.
    '''

    rawVersion = parent.targets[trove].version
    newVersion = macro.expand(rawVersion, parent, trove=trove)
    return re_version.sub(r'\1version = %r' % (newVersion,), recipe)


re_source = re.compile(
    r'''^(\s+)(\S+)\.addMercurialSnapshot\s*\(.*?\).*?$''', re.M | re.S)
@_register
@_require_target_attribute('hg')
def source(parent, trove, recipe):
    '''
    Modify addMercurialSnapshot calls to use the selected revision.
    '''

    repo = parent.targets[trove].hg
    if not parent.hg.has_key(repo):
        logging.warning('Trove %s references undefined Hg repository %s',
            trove, repo)

    uri, node = parent.hg[repo]
    return re_source.sub(r'\1\2.addMercurialSnapshot(%r, tag=%r)'
        % (str(uri), str(node)), recipe)


##
## Repository/commit code
##

def mangleTrove(parent, name, version, siblingClone=False, save_recipe=False):
    '''
    Check out a given source trove, mangle it, and commit it to a shadow on
    the internal repository.
    '''

    _start_time = time.time()

    oldKey = parent.buildcfg.signatureKey
    oldMap = parent.buildcfg.signatureKeyMap
    oldInteractive = parent.buildcfg.interactive

    package = name.split(':')[0]
    sourceName = package + ':source'
    newTrove = None

    work_dir = tempfile.mkdtemp(prefix='bob-mangle-%s' % package)
    upstream_dir = tempfile.mkdtemp(prefix='bob-upstream-%s' % package)
    oldWd = os.getcwd()

    try:
        # Prevent any questions from being asked during check-in
        parent.buildcfg.signatureKey = None
        parent.buildcfg.signatureKeyMap = {}
        parent.buildcfg.interactive = False

        # Find source
        log.debug('Finding trove %s=%s', sourceName, version)
        matches = parent.nc.findTrove(None, (sourceName, str(version), None))
        sourceVersion = max(x[1] for x in matches)

        # Check out upstream version and fetch recipe
        log.debug('Checking out upstream trove %s=%s',
            sourceName, sourceVersion)
        checkin.checkout(parent.nc, parent.buildcfg, upstream_dir,
            ['%s=%s' % (sourceName, sourceVersion)])
        upstream_recipe = open(os.path.join(upstream_dir,
            '%s.recipe' % package)).read()

        # Shadow or clone to rMake's internal repos
        target_label = parent.buildcfg.getTargetLabel(version)
        cs = None
        if not siblingClone:
            # Shadow
            log.debug('Shadowing %s to rMake repository', package)
            skipped, cs = parent.cc.createShadowChangeSet(str(target_label),
                [(sourceName, sourceVersion, deps.parseFlavor(''))])<commit_msg>Use target label when generating shadows, to avoid collisions.<commit_after>#
# Copyright (c) 2008 rPath, Inc.
#
# All rights reserved.
#

'''
Tools for manipulating recipes and source troves.
'''

import logging
import os
import re
import sha
import shutil
import tempfile
import time

from conary import checkin
from conary import state
from conary import versions
from conary.build import cook
from conary.build import use
from conary.deps import deps
from conary.lib import log as conary_log
from conary.lib import util
from rmake import compat

from bob import macro

log = logging.getLogger('bob.mangle')


filters = []


##
## Decorators and helpers
##

def mangle(parent, trove, recipe):
    '''
    Feed the given recipe through all available filters.
    '''
    for f in filters:
        recipe = f(parent, trove, recipe)
    return recipe


def _register(fun):
    '''Decorator: Add the function as a mangler for all mangled recipes.'''
    filters.append(fun)
    return fun


def _require_target_attribute(*target_attributes):
    '''
    Decorator: require that the given attributes be set on a target section
    for the trove being mangled.
    '''

    def decorate(fun):
        def wrapper(parent, trove, recipe):
            if trove not in parent.targets:
                return recipe
            for attribute in target_attributes:
                if not parent.targets[trove][attribute]:
                    return recipe
            return fun(parent, trove, recipe)
        return wrapper
    return decorate


##
## Manglers
##

re_version = re.compile('^(\s+)version\s*=.*?$', re.M)
@_register
@_require_target_attribute('version')
def version(parent, trove, recipe):
    '''
    Update the recipe's version to reflect any configured pattern.
    '''

    rawVersion = parent.targets[trove].version
    newVersion = macro.expand(rawVersion, parent, trove=trove)
    return re_version.sub(r'\1version = %r' % (newVersion,), recipe)


re_source = re.compile(
    r'''^(\s+)(\S+)\.addMercurialSnapshot\s*\(.*?\).*?$''', re.M | re.S)
@_register
@_require_target_attribute('hg')
def source(parent, trove, recipe):
    '''
    Modify addMercurialSnapshot calls to use the selected revision.
    '''

    repo = parent.targets[trove].hg
    if not parent.hg.has_key(repo):
        logging.warning('Trove %s references undefined Hg repository %s',
            trove, repo)

    uri, node = parent.hg[repo]
    return re_source.sub(r'\1\2.addMercurialSnapshot(%r, tag=%r)'
        % (str(uri), str(node)), recipe)


##
## Repository/commit code
##

def mangleTrove(parent, name, version, siblingClone=False, save_recipe=False):
    '''
    Check out a given source trove, mangle it, and commit it to a shadow on
    the internal repository.
    '''

    _start_time = time.time()

    oldKey = parent.buildcfg.signatureKey
    oldMap = parent.buildcfg.signatureKeyMap
    oldInteractive = parent.buildcfg.interactive

    package = name.split(':')[0]
    sourceName = package + ':source'
    newTrove = None

    work_dir = tempfile.mkdtemp(prefix='bob-mangle-%s' % package)
    upstream_dir = tempfile.mkdtemp(prefix='bob-upstream-%s' % package)
    oldWd = os.getcwd()

    try:
        # Prevent any questions from being asked during check-in
        parent.buildcfg.signatureKey = None
        parent.buildcfg.signatureKeyMap = {}
        parent.buildcfg.interactive = False

        # Find source
        log.debug('Finding trove %s=%s', sourceName, version)
        matches = parent.nc.findTrove(None, (sourceName, str(version), None))
        sourceVersion = max(x[1] for x in matches)

        # Check out upstream version and fetch recipe
        log.debug('Checking out upstream trove %s=%s',
            sourceName, sourceVersion)
        checkin.checkout(parent.nc, parent.buildcfg, upstream_dir,
            ['%s=%s' % (sourceName, sourceVersion)])
        upstream_recipe = open(os.path.join(upstream_dir,
            '%s.recipe' % package)).read()

        # Shadow or clone to rMake's internal repos
        target_label = parent.buildcfg.getTargetLabel(parent.cfg.targetLabel)
        cs = None
        if not siblingClone:
            # Shadow
            log.debug('Shadowing %s to rMake repository', package)
            skipped, cs = parent.cc.createShadowChangeSet(str(target_label),
                [(sourceName, sourceVersion, deps.parseFlavor(''))])
{'fraction_non_alphanumeric': 0.11118752865657955, 'fraction_numerical': 0.0020632737276478678, 'mean_word_length': 2.980383211678832, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1298385', 'n_tokens_mistral': 2708, 'n_tokens_neox': 2582, 'n_words': 745}