def minimize_js(repo_link, commit, path, row, substitutions):
    # minimize-js <src> [dst]
    src = file_operations.get_file(row['src'], path, substitutions)
    if 'dst' in row:
        dst = file_operations.get_file(row['dst'], path, substitutions)
    else:
        dst = src
    # check access
    file_operations.check_file(src[0], path)
    # minimize
    action = row.get('type').lower()
    print(' %s %s -> %s' % (action, src[2], dst[2]))
    cmd = "uglifyjs '%s' -c -m -o '%s'" % (src[0], dst[0])
    print('  [%s]' % cmd)
    subprocess.check_call(cmd, shell=True)
def copymove(repo_link, commit, path, row, substitutions):
    # {copy|move} <src> <dst> [add-header-comment] [replace-keywords]
    src = file_operations.get_file(row['src'], path, substitutions)
    dst = file_operations.get_file(row['dst'], path, substitutions)
    # determine which file(s) should be used
    if 'match' in row:
        sources, destinations = [], []
        for name in glob.glob(os.path.join(src[0], '*')):
            src2 = file_operations.get_file(name)
            basename = src2[2]
            if re.match(row['match'], basename) is not None:
                sources.append(src2)
                file_path = os.path.join(dst[0], basename)
                destinations.append(file_operations.get_file(file_path))
    else:
        sources, destinations = [src], [dst]
    # apply the action to each file
    is_move = row.get('type').lower() == 'move'
    for src, dst in zip(sources, destinations):
        copymove_single(repo_link, commit, path, row, src, dst, is_move)
def compile_coffee(repo_link, commit, path, row, substitutions):
    # compile-coffee <src> [dst]
    src = file_operations.get_file(row['src'], path, substitutions)
    if 'dst' in row:
        dst = file_operations.get_file(row['dst'], path, substitutions)
    else:
        basename, extension = src[2:4]
        if extension != '':
            basename = basename[:-len(extension)] + 'js'
        else:
            basename += '.js'
        dst = file_operations.get_file(basename, src[1])
    # check access
    file_operations.check_file(src[0], path)
    # compile
    action = row.get('type').lower()
    print(' %s %s -> %s' % (action, src[2], dst[2]))
    cmd = "coffee -c -p '%s' > '%s'" % (src[0], dst[0])
    print('  [%s]' % cmd)
    subprocess.check_call(cmd, shell=True)
def copymove_single(repo_link, commit, path, row, src, dst, is_move):
    action = 'move' if is_move else 'copy'
    print(' %s %s -> %s' % (action, src[2], dst[2]))
    # check access
    file_operations.check_file(src[0], path)
    # put a big "do not edit" warning at the top of the file
    if row.get('add-header-comment', False) is True:
        src = add_header(repo_link, commit, src, dst[3])
    # replace template keywords with values
    templates = row.get('replace-keywords')
    if type(templates) is str:
        templates = [templates]
    if type(templates) in (tuple, list):
        full_templates = [file_operations.get_file(t, path) for t in templates]
        src = replace_keywords(src, full_templates)
    # make the copy (method depends on destination)
    if dst[0].startswith('/var/www/html/'):
        # copy to staging area
        tmp = file_operations.get_file(src[2] + '__tmp', '/common/')
        print(' [%s] -> [%s]' % (src[0], tmp[0]))
        shutil.copy(src[0], tmp[0])
        # make directory and move the file as user `webadmin`
        cmd = "sudo -u webadmin -s mkdir -p '%s'" % (dst[1])
        print('  [%s]' % cmd)
        subprocess.check_call(cmd, shell=True)
        cmd = "sudo -u webadmin -s mv -fv '%s' '%s'" % (tmp[0], dst[0])
        print('  [%s]' % cmd)
        subprocess.check_call(cmd, shell=True)
    else:
        # make directory and copy the file
        print(' [%s] -> [%s]' % (src[0], dst[0]))
        os.makedirs(dst[1], exist_ok=True)
        shutil.copy(src[0], dst[0])
    # maybe delete the source file
    if is_move:
        os.remove(src[0])
def add_header(repo_link, commit, src, dst_ext):
    # build the header based on the source language
    ext = dst_ext.lower()
    pre_block, post_block, pre_line, post_line = '', '', '', ''
    blanks = '\n\n\n'
    if ext in ('html', 'xml'):
        pre_block, post_block = '<!--\n', '-->\n' + blanks
    elif ext in ('js', 'min.js', 'css', 'c', 'cpp', 'h', 'hpp', 'java'):
        pre_block, post_block = '/*\n', '*/\n' + blanks
    elif ext in ('py', 'r', 'coffee', 'htaccess', 'sh'):
        pre_line, post_line, post_block = '# ', ' #', blanks
    elif ext in ('php'):
        # be sure to not introduce whitespace (e.g. newlines) outside php tags
        pre_block, post_block = '<?php /*\n', '*/\n' + blanks + '?>'
    else:
        # nothing modified, return the original file
        print(' warning: skipped header for file extension [%s]' % dst_ext)
        return src

    # additional header lines
    t = round(time.time())
    dt = datetime.datetime.fromtimestamp(t).isoformat(' ')
    lines = [
        '',
        'Automatically generated from sources at:',
        repo_link,
        '',
        ('Commit hash: %s' % commit),
        ('Deployed at: %s (%d)' % (dt, t)),
    ]

    # add the header to a copy of the source file
    tmp = file_operations.get_file(src[0] + '__header')
    print(' adding header [%s] -> [%s]' % (src[0], tmp[0]))
    with open(tmp[0], 'wb') as fout:
        fout.write(bytes(pre_block, 'utf-8'))
        for line in HEADER_LINES + [
                line.center(HEADER_WIDTH) for line in lines
        ]:
            fout.write(bytes(pre_line + line + post_line + '\n', 'utf-8'))
        fout.write(bytes(post_block, 'utf-8'))
        with open(src[0], 'rb') as fin:
            fout.write(fin.read())

    # return the new file
    return tmp
def replace_keywords(src, templates):
    # load list of (key, value) pairs
    pairs = []
    for t in templates:
        with open(t[0], 'r') as f:
            pairs.extend(json.loads(f.read()))

    # make a new file to hold the results
    tmp = file_operations.get_file(src[0] + '__valued')
    print(' replacing %d keywords [%s] -> [%s]' % (len(pairs), src[0], tmp[0]))
    with open(tmp[0], 'w') as fout:
        with open(src[0], 'r') as fin:
            for line in fin.readlines():
                for (k, v) in pairs:
                    line = line.replace(k, v)
                fout.write(line)

    # return the new file
    return tmp
Beispiel #7
0
def py3test(repo_link, commit, path, row, substitutions):
    # py3test [dir]

    # parse arguments
    if 'dir' in row:
        location = file_operations.get_file(row['dir'], path, substitutions)[0]
    else:
        location = os.path.join(path, 'tests')
    pattern = '^(test_.*|.*_test)\\.py$'
    terminal = False

    # find tests
    test_files = p3t.find_tests(location, pattern, terminal)

    # run tests and gather results
    results = [p3t.analyze_results(p3t.run_tests(f)) for f in test_files]

    # check for success
    # TODO: show in repo badge
    totals = {
        'good': 0,
        'bad': 0,
        'lines': 0,
        'hits': 0,
    }
    for test in results:
        totals['good'] += test['unit']['summary']['pass']
        totals['bad'] += test['unit']['summary']['fail']
        totals['bad'] += test['unit']['summary']['error']
        totals['lines'] += test['coverage']['summary']['total_lines']
        totals['hits'] += test['coverage']['summary']['hit_lines']
    if totals['bad'] > 0:
        raise Exception('%d test(s) did not pass' % totals['bad'])
    elif totals['good'] == 0:
        print('no tests found')
    else:
        print('%d test(s) passed!' % totals['good'])
        num = len(results)
        cov = 100 * totals['hits'] / totals['lines']
        print('overall coverage for %d files: %.1f%%' % (num, cov))