summaryrefslogtreecommitdiff
blob: 8280d1cd27d7b5df5d98e17a9a13a54337092d73 (plain)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import commands as cmd
import subprocess as sp
import os, portage, shlex
from os.path import join as pjoin
import benchutils

class InstallException(Exception):
    def __init__(self, command, logfile):
        self.command = command
        self.logfile = logfile

def available_packages(pattern):
    """Returns a list of packages matching the given pattern.
    
    The packages are returned as (category, package, version, revision) tuple.
    No test for keywords or mask is performed. The function just returns
    every matching pattern in the portage tree and installed overlays.
    """
    return [portage.catpkgsplit(l) \
      for l in cmd.getoutput('equery -q list -po ' + pattern).split()]
    
def normalize_cpv(cpv):
    if type(cpv) == type(''):
        try:
            cpv_ = portage.catpkgsplit(cpv)
            cpv_[-1]
            cpv = cpv_
        except:
            cpv = available_packages(cpv)[-1]
    if cpv[-1] != 'r0':
        return '%s/%s-%s-%s' % cpv
    else:
        return '%s/%s-%s' % cpv[:-1]
        
    
def get_dependencies(package, env={}, split=False):
    pkg = normalize_cpv(package)
    cmd = ['emerge', '--ignore-default-opts', '='+pkg, '-poq']
    proc = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE, env=env)
    lines = proc.communicate()[0].strip().split('\n')
    if not lines[0]:
        return []
    if split:
        return [portage.catpkgsplit(shlex.split(l.strip())[-1]) for l in lines]
    else:
        return [shlex.split(l.strip())[-1] for l in lines]

def install_dependencies(package, env={}, root='/', 
                         pkgdir='usr/portage/packages', logdir=None):
    if logdir is None:
        logdir = "/var/log/benchmarks/.unordered"
    
    # Adjust environment
    denv = os.environ
    for k,v in env.items():
        denv[k] = v
    
    # Retrieve dependencies
    deps = get_dependencies(package, denv, False)
    
    for i,d in enumerate(deps):
        logfile = pjoin(logdir, 'emergedep_%i.log' % i)
        install_package(d, env, root, pkgdir, logfile)


def install_package(package, env={}, root='/', pkgdir='usr/portage/packages',
                    logfile=None):
    """Emerge a package in the given root.
    
    package is the package to be emerged. It has to be a tuple
    (category, package, version, revision).
    
    env is a dictionary of KEY:VALUE pairs describing the environment changes
    the package will be emerged with. It is useful to specifiy the compilers and
    compiler flags. It is safe to use ACCEPT_KEYWORDS=* for testing purposes.
    
    root is the directory where the packaged will be emerged. A non-root user
    can use this function, provided he has write access to that directory.
    
    pkgdir is the directory where the binary package will be placed. The user
    has to be able to write in this directory.
    
    The function has no return value and raises an exception in case of building
    or emerging failure. Note: dependencies will NOT be emerged!
    """
    
    # Adjust environment
    denv = os.environ.copy()
    for k,v in env.items():
        denv[k] = v
    denv['PKGDIR'] = pkgdir    
    #PATH
    denv['PATH'] = ':'.join([pjoin(root, i) for i in ('bin', 'usr/bin')])
    if os.environ.has_key('PATH'):
        denv['PATH'] += ':' + os.environ['PATH']
    denv['ROOTPATH'] = denv['PATH']
    #LIBRARY_PATH
    denv['LIBRARY_PATH'] = ':'.join([pjoin(root, i) for i in \
      ('usr/lib', 'usr/lib64', 'usr/lib32')])
    if os.environ.has_key('LIBRARY_PATH'):
        denv['LIBRARY_PATH'] += ':' + os.environ['LIBRARY_PATH']
    #LD_LIBRARY_PATH
    denv['LD_LIBRARY_PATH'] = ':'.join([pjoin(root, i) for i in \
      ('usr/lib', 'usr/lib64', 'usr/lib32')])
    if os.environ.has_key('LD_LIBRARY_PATH'):
        denv['LD_LIBRARY_PATH'] += ':' + os.environ['LD_LIBRARY_PATH']
    #INCLUDE_PATH
    denv['INCLUDE_PATH'] = ':'.join([pjoin(root, i) for i in ('usr/include',)])
    if os.environ.has_key('INCLUDE_PATH'):
        denv['INCLUDE_PATH'] += ':' + os.environ['INCLUDE_PATH']
    
    # Retrieve package string
    pkg = normalize_cpv(package)
    
    # Execute emerge command and log the results
    if logfile is not None:
        fout = file(logfile, 'w')
        fout.flush()
    else:
        fout = sp.PIPE
    cmd = ['emerge', '--ignore-default-opts', '-OB', '=' + pkg]
    p = sp.Popen(cmd, env=denv, stdout=fout, stderr=sp.STDOUT)
    p.wait()
    
    if p.returncode != 0:
        # In case of error, print the whole emerge command
        raise InstallException(' '.join(cmd), logfile)
    
    # Unpack package onto root
    benchutils.mkdir(pkgdir)
    benchutils.mkdir(root)
    archive = pjoin(pkgdir, pkg+'.tbz2')
    tarcmd = ['tar', 'xjvf', archive, '-C', root]
    cl = ' '.join(tarcmd)
    if logfile is not None:
        fout.write('\n\n' + 80*'#' + '\n\n')
        fout.write(cl + '\n' + 80*'-' + '\n')
    p = sp.Popen(tarcmd, stdout=fout, stderr=sp.STDOUT)
    p.wait()
    if p.returncode != 0:
        # In case of error, print the whole emerge command
        raise InstallException(cl, logfile)
    
    if logfile is not None:
        fout.close()
    
if __name__ == '__main__':
    # Just a test
    from pprint import pprint
    
    pprint(get_dependencies('sci-libs/blas-reference-3.3.1-r1'))