aboutsummaryrefslogtreecommitdiff
blob: 98d6a8ee553532265b5b9c7aa3146e80a4d862fc (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
# vim: set sw=4 sts=4 et :
# Copyright: 2008 Gentoo Foundation
# Author(s): Nirbheek Chauhan <nirbheek.chauhan@gmail.com>
# License: GPL-2
#
# Immortal lh!
#

# XXX: This is purely yay-something-works code
# This will change radically with time

import re, subprocess, sys, os
import os.path as osp
from .. import const

class Jobuild(object):
    """A jobuild"""

    def __init__(self, jobdir, atom):
        """
        @param jobdir: Job directory (of the form tmpdir/maint/job_name)
        @type jobdir: string

        @param atom: Atom for finding the corresponding jobuild
        @type jobdir: string
        """
        self.name = atom
        self.jobdir = jobdir
        self.path = self._best_jobuild(atom)

    def __str__(self):
        return '%s jobuild object' % self.name

    def _split_atom(self, atom):
        regex = re.compile(r'^([<>]?=)?([a-zA-Z0-9_+-]+)/([a-zA-Z0-9_+-]+)(-|$)([0-9]+\.[0-9]+)?') # Fancy regex aye?
        #                       >=       bheekling       /    test-beagle   -    1.0
        #                                bheekling       /    build-brasero
        parts = regex.findall(atom)
        if not parts:
            # FIXME: Custom exceptions
            raise 'Invalid atom %s' % atom
        parts = parts[0]
        if parts[3] and not parts[4]:
            # FIXME: Custom exceptions
            raise 'Invalid atom %s' % atom
        parts = (parts[0], parts[1], parts[2], parts[4],)
        if (parts[0] and not parts[3]) or (parts[3] and not parts[0]):
            # FIXME: Custom exceptions
            raise 'Invalid atom %s' % atom
        return parts

    def _get_all_pv_sorted(self, data):
        files = os.listdir('%(jobtage)s/%(maint)s/%(pn)s' % data)
        for file in files[:]:
            if not file.endswith('.jobuild'):
                files.remove(file)
            else:
                files[files.index(file)] = '=%s/%s' % (data['maint'], osp.basename(file)[:-8],) # .jobuild is 8 characters
                #                           =maint/pn-pv
        pv = []
        for atom in files:
            pv.append(self._split_atom(atom)[3])
        pv.sort()
        return pv

    def _best_jobuild(self, atom):
        parts = self._split_atom(atom)
        data = {'op': parts[0],
                'maint': parts[1],
                'pn': parts[2],
                'pv': parts[3],
                'jobtage': '%s/jobtage' % self.jobdir}
        if data['op'] == '=':
            pass # Nothing to be done
        elif not data['op']:
            pv = self._get_all_pv_sorted(data)
            data['pv'] = pv[-1]
        elif data['op'] == '>=':
            pv = self._get_all_pv_sorted(data)
            if pv[-1] >= data['pv']:
                data['pv'] = pv[-1]
            else:
                raise 'No matching jobuild found for atom \"%s\"' % atom
        elif data['op'] == '<=':
            pv = self._get_all_pv_sorted(data)
            pv.reverse()
            for i in pv:
                if i <= data['pv']:
                    data['pv'] = i
                    break
                if i == pv[-1]: # If it's the last pv..
                    raise 'No matching jobuild found for atom \"%s\"' % atom
        return '%(jobtage)s/%(maint)s/%(pn)s/%(pn)s-%(pv)s.jobuild' % data

class Processor(object):
    """Jobuild processor"""

    def __init__(self, jobuild, chroot):
        """
        @param jobuild: Jobuild to process
        @type jobuild: L{autotua.jobuild.Jobuild}

        @param chroot: Chroot to use for processing the jobuild
        @type chroot: L{autotua.chroot.WorkChroot}
        """
        self.jobuild = jobuild
        self.chroot = chroot

    def run_phase(self, phase):
        """Run the specified phase of the jobuild"""
        args = {'phase': phase,
                'jobuild': self.jobuild.path,
                'chroot': self.chroot.dir,}
        self._msg('RUN_PHASE "%(phase)s" "%(jobuild)s" "%(chroot)s"' % args)

    def get_var(self, var):
        """
        Parse jobuild and get a variable
        (yay-something-works function)
        """
        args = {'var': var,
                'jobuild': self.jobuild.path,}
        return self._msg('GET_VAR "%(var)s" "%(jobuild)s"' % args)

    def _msg(self, msg):
        # Messages goto 3 and then to /dev/tty1
        # stderr goes to stdout
        # stdout goes to ${LOGFILE}
        process = subprocess.Popen('\"%s\"/bin/jobuild.sh %s 3>&2 2>&1 | tee -a \"%s\"' % (const.AUTOTUA_DIR, msg, const.LOGFILE), shell=True, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
        process.stdin.write('ping\n')
        response = process.stderr.readline()[:-1] # Remove trailing newline
        if not response == 'pong':
            # FIXME: Custom exceptions
            raise 'Communication error: received %s when expecting "pong"' % response
        response = process.stderr.read()[:-1] # Remove trailing newline
        return response