# 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 # 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.module import Module from base.exceptions import ExecutionException from base.util import pwd, one from base.vars import orig_src_dir, haskell_compiler from modules.dirfactory import DirFactory from modules.sourceball import SourceBall class Cabal(Module): def __init__(self, name, root='~/haskell'): self.name = name self.root = expanduser(root) with pwd(self.root): self.package = DirFactory(name) self.original = orig_src_dir self.compiler = haskell_compiler def copy_in(self, tarball): tarball = abspath(tarball) with pwd(self.root): self.package.add_sourceball(tarball) def darcs_get(self, url, tgt): self.package.checkout(tgt, url) def find_setup(self, orig=''): setup_re = compile("Setup\.l?hs") return one(listdir(getcwd()), setup_re.search) def compile_setup(self, orig=''): log.debug('code_dir is ' + self.package.code_dir) with pwd(self.package.code_dir): with file('ghc.log', 'a') as ghc_out: log.debug('ghc.log file is ' + str(ghc_out)) log.debug('source_dir is ' + self.package.source_dir(orig)) with pwd(self.package.source_dir(orig)): setup_f = self.find_setup(orig) 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', orig=''): user = True if target == 'home' else False self.compile_setup(orig) with pwd(self.package.code_dir): with file('cabal.log', 'a') as cabal_out: log.debug('source_dir is ' + self.package.source_dir(orig)) with pwd(self.package.source_dir(orig)): args = [abspath('Setup'), 'configure'] + \ (['--user', '--prefix=' + expanduser('~')] if user else []) p = Popen(args, stdout=cabal_out, stderr=cabal_out) log.info('Configuring %s, please wait...' % self.name) p.wait() def build(self, orig=''): '''This is not safe to run on an unconfigured source dir''' self.compile_setup(orig) with pwd(self.package.code_dir): with file('cabal.log', 'a') as cabal_out: with pwd(self.package.source_dir(orig)): args = [abspath('Setup'), 'build'] p = Popen(args, stdout=cabal_out, stderr=cabal_out) log.info('Building %s, please wait...' % self.name) p.wait() def install(self, orig=''): '''This is not safe to run on an unconfigured source dir''' self.compile_setup(orig) with pwd(self.package.code_dir): with file('cabal.log', 'a') as cabal_out: with pwd(self.package.source_dir(orig)): args = [abspath('Setup'), 'install'] p = Popen(args, stdout=cabal_out, stderr=cabal_out) log.info('Building %s, please wait...' % self.name) p.wait() def install_source(self, target='home', orig=''): self.configure(target, orig) self.build(orig) self.install(orig) def install_sourceball(self, tarball, target='home'): self.copy_in(tarball) self.install_source(target, '') def get_from_hackage(self, pkg, ver): sb_file = self.hackage_url(pkg, ver) self.copy_in(sb_file) def get_latest(self, pkg): ver = self.latest_version(pkg) self.get_from_hackage(pkg, ver) def install_from_hackage(self, pkg, ver, target='home'): self.get_from_hackage(pkg, ver) self.install_source(target, '') def install_latest(self, pkg, target='home'): self.get_latest(pkg) self.install_source(target, '') def source_dir(self, *args): with pwd(self.package.code_dir): return abspath(self.package.cfg['source'] + (self.orig_src_dir if original else "")) def latest_version(self, pkg): hackage_title = compile(r'HackageDB: (.*)-(.*)', DOTALL) site = 'http://hackage.haskell.org/cgi-bin/hackage-scripts/package/' + pkg u = urlopen(site) page = u.read() match = hackage_title.search(page) groups = match.groups() print groups if pkg == groups[0]: return groups[1] else: raise ExecutionException("package does not match package name, can't determine version, sorry") def hackage_url(self, pkg, ver): return 'http://hackage.haskell.org/packages/archive/' + \ pkg + '/' + ver + '/' + pkg + '-' + ver + '.tar.gz' def close(self): self.package.close()