aboutsummaryrefslogtreecommitdiff
path: root/delivery_merge/merge.py
blob: 457c4339a790abdbbd9812b9c190521afab68b34 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import os
import re
import yaml
from .conda import conda, conda_env_load
from .utils import git, pushd
from glob import glob
from subprocess import run


DMFILE_RE = re.compile(r'^(?P<name>.*)[=<>~\!](?P<version>.*).*$')


def comment_find(s, delims=[';', '#']):
    """ Return index of first match
    """
    for delim in delims:
        pos = s.find(delim)
        if pos != -1:
            break

    return pos


def dmfile(filename):
    result = []
    with open(filename, 'r') as fp:
        for line in fp:
            line = line.strip()
            comment_pos = comment_find(line)

            if comment_pos >= 0:
                line = line[:comment_pos]

            if not line:
                continue

            result.append(line)
    return result


def env_combine(filename, conda_env, conda_channels=[]):
    packages = []
    channels_result = '--override-channels '

    for line in dmfile(filename):
        packages.append(f"'{line}'")

    for channel in conda_channels:
        channels_result += f'-c {channel} '

    packages_result = ' '.join([x for x in packages])
    proc = conda('install', '-q', '-y', '-n',
                 conda_env, channels_result, packages_result)
    if proc.stderr:
        print(proc.stderr.decode())


def testable_packages(filename, prefix):
    """ Scan a mini/anaconda prefix for unpacked packages matching versions
    requested by dmfile.
    """
    pkgdir = os.path.join(prefix, 'pkgs')
    paths = []

    for line in dmfile(filename):
        match = DMFILE_RE.match(line)
        if match:
            pkg = match.groupdict()

            # Reconstruct ${package}-${version} format from
            # ${package}${specifier}${version}
            pattern = f"{pkg['name']}-{pkg['version']}*"

            # Record path to extracted package
            path = ''.join([x for x in glob(os.path.join(pkgdir, pattern))
                            if os.path.isdir(x)])
            paths.append(path)

    for root in paths:
        info_d = os.path.join(root, 'info')
        recipe_d = os.path.join(info_d, 'recipe')
        git_log = os.path.join(info_d, 'git')

        if not os.path.exists(git_log):
            continue

        with open(os.path.join(recipe_d, 'meta.yaml')) as yaml_data:
            source = yaml.load(yaml_data.read())['source']

        if not isinstance(source, dict):
            continue

        repository = source['git_url']
        head = open(git_log).readlines()[1].split()[1]
        yield dict(repo=repository, commit=head)


def integration_test(pkg_data, conda_env, results_root='.'):
    results_root = os.path.abspath(os.path.join(results_root, 'results'))
    src_root = os.path.abspath('src')

    if not os.path.exists(src_root):
        os.mkdir(src_root, 0o755)

    with pushd(src_root) as _:
        repo_root = os.path.basename(pkg_data['repo']).replace('.git', '')
        if not os.path.exists(repo_root):
            git(f"clone --recursive {pkg_data['repo']} {repo_root}")

        with pushd(repo_root) as _:
            git(f"checkout {pkg_data['commit']}")

            with conda_env_load(conda_env):
                results = os.path.abspath(os.path.join(results_root,
                                                       repo_root,
                                                       'result.xml'))
                run("pip install -e .[test]".split()).check_returncode()
                run(f"pytest -v --junitxml={results}".split(), check=True)