summaryrefslogtreecommitdiffstats
path: root/modules/cabal.py
blob: 3c75e19e411a777c7ed5e999b6dde001152c893f (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
# Fedora Developer Shell
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Authors: Yaakov M. Nemoy <ynemoy@redhat.com>
#
from __future__ import with_statement

from os import listdir, getcwd
from os.path import expanduser, expandvars, abspath

from re import compile, DOTALL

from subprocess import Popen

from urllib import urlopen, urlretrieve

from base.base import log
from base.exceptions import ExecutionException
from base.factories import DirFactory
from base.util import pwd, one, log_file
from base.vars import orig_src_dir, haskell_compiler

from modules.buildsystem import BuildSystem
from modules.sourceball import SourceBall

class Cabal(BuildSystem):
    '''A wrapper around common cabal operations

    This provides a useful api for other modules around the cabal build system
    '''
    def __init__(self, name):
        '''creates a new cabal module

        this api is deprecated, because it should be more autodetecting

        name is a Package (Directory) that uses cabal for its build system
        '''
        super(Cabal, self).__init__(name)
        self.compiler = haskell_compiler

    def find_setup(self):
        '''returns the name of the Setup.?hs script for cabal.
        '''
        setup_re = compile("Setup\.l?hs")
        with self.pkg_src.src_dir():
            return one(listdir(getcwd()), setup_re.search)

    def compile_setup(self, *args):
        '''compiles the setup script for faster execution
        '''
        with self.pkg_src.src(*args):
            with pwd(self.pkg_src.pkg_src_dir):
                with log_file('ghc.log') as ghc_out:
                    with self.pkg_src.src_dir():
                        setup_f = self.find_setup()
                        p = Popen([self.compiler, '--make', setup_f],
                                  stdout = ghc_out, stderr = ghc_out)
                        log.info('Building %s, please wait...' % setup_f)
                        p.communicate()

    def configure(self, target='home', *args):
        '''runs the configure stage of cabal
        
        target is either 'home' or 'root' and will configure the package to
        install either to the user's home directory, or to the system
        wide haskell.

        Some help is needed making this more flexible
        '''
        user = True if target == 'home' else False
        with self.pkg_src.src(*args):
            self.compile_setup()
            with pwd(self.pkg_src.pkg_src_dir):
                with log_file('cabal.log') as cabal_out:
                    with self.pkg_src.src_dir():
                        cmd = [abspath('Setup'), 'configure'] \
                            + (['--user', '--prefix=' + expanduser('~')] if user else [])
                        p = Popen(cmd, stdout=cabal_out, stderr=cabal_out)
                        log.info('Configuring %s, please wait...' % self.name)
                        p.communicate()

    def build(self, *args):
        '''runs the build stage of cabal

        This is not safe to run on an unconfigured source dir, because
        this module does not track the state of cabal systems. The user
        must do this on their own.
        '''
        with self.pkg_src.src(*args):
            self.compile_setup()
            with pwd(self.pkg_src.pkg_src_dir):
                with log_file('cabal.log') as cabal_out:
                    with self.pkg_src.src_dir():
                        cmd = [abspath('Setup'), 'build']
                        p = Popen(cmd, stdout=cabal_out, stderr=cabal_out)
                        log.info('Building %s, please wait...' % self.name)
                        p.communicate()

    def install(self, *args):
        '''runs the install stage of cabal

        This is not safe to run on an unconfigured source dir, because
        this module does not track the state of cabal systems. The user
        must do this on their own.
        '''
        with self.pkg_src.src(*args):
            self.compile_setup()
            with pwd(self.pkg_src.pkg_src_dir):
                with log_file('cabal.log') as cabal_out:
                    with pwd(self.pkg_src.src_dir()):
                        cmd = [abspath('Setup'), 'install']
                        p = Popen(cmd, stdout=cabal_out, stderr=cabal_out)
                        log.info('Building %s, please wait...' % self.name)
                        p.communicate()
    
    def install_source(self, target='home', *args):
        '''perform configure, build, and install steps in one
        '''
        with self.pkg_src.src(*args):
            self.configure(target, orig)
            self.build(orig)
            self.install(orig)

    def gen_spec(self):
        cabal_file = self.pkg_src.hackage_name + '.cabal'
        with pwd(self.pkg_src.pkg_src_dir):
            with log_file('cabal2spec.log') as c2s_log:
                with pwd(self.pkg_src.dir):
                    cmd = ['cabal2spec', cabal_file]
                    p = Popen(cmd, stdout=c2s_log, stderr=c2s_log)
                    log.info('Generating spec file for %s' % cabal_file)
                    p.communicate()

    def close(self):
        self.pkg_src.close()

__all__ = ['Cabal']