summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYaakov M. Nemoy <loupgaroublond@gmail.com>2009-01-18 19:37:37 -0500
committerYaakov M. Nemoy <loupgaroublond@gmail.com>2009-01-18 19:37:37 -0500
commit8bbbcbd2cdad36e27c127c888897395cefcff3d0 (patch)
tree4d26aa09f936f76c1e14f0571c68e195f2adc3ac
parentc98a858abe7d209b602aaad6e01dbbf8e66bdf21 (diff)
downloadfedora-devshell-8bbbcbd2cdad36e27c127c888897395cefcff3d0.tar.gz
fedora-devshell-8bbbcbd2cdad36e27c127c888897395cefcff3d0.tar.xz
fedora-devshell-8bbbcbd2cdad36e27c127c888897395cefcff3d0.zip
Refactors Cabal to fit the new mediator pattern design
Cabal has now been split into a builder, cabal, a fetcher, hackage, and a port aka mediator, haskellport. It's been gutted to try to match some common api between the base classes. Also, bits of Darcs have been pulled out into packagesource.
-rw-r--r--modules/buildsystem.py49
-rw-r--r--modules/cabal.py196
-rw-r--r--modules/fetcher.py33
-rw-r--r--modules/hackage.py41
-rw-r--r--modules/haskellport.py96
-rw-r--r--modules/packagesource.py3
-rw-r--r--modules/port.py21
-rw-r--r--modules/sourceball.py1
8 files changed, 294 insertions, 146 deletions
diff --git a/modules/buildsystem.py b/modules/buildsystem.py
new file mode 100644
index 0000000..2c5a3a5
--- /dev/null
+++ b/modules/buildsystem.py
@@ -0,0 +1,49 @@
+# 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 base.module import Module
+
+class BuildSystem(Module): pass
+ 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
+ '''
+ raise NotImplementedError
+
+ 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.
+ '''
+ raise NotImplementedError
+
+ 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.
+ '''
+ raise NotImplementedError
diff --git a/modules/cabal.py b/modules/cabal.py
index 842aaf7..4b118d6 100644
--- a/modules/cabal.py
+++ b/modules/cabal.py
@@ -29,18 +29,18 @@ from urllib import urlopen, urlretrieve
from base.base import log
from base.exceptions import ExecutionException
from base.dirfactory import DirFactory
-from base.module import Module
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(Module):
+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, root='~/haskell'):
+ def __init__(self, name):
'''creates a new cabal module
this api is deprecated, because it should be more autodetecting
@@ -48,52 +48,30 @@ class Cabal(Module):
name is a Package (Directory) that uses cabal for its build system
'''
self.name = name
- self.root = expanduser(root)
- with pwd(self.root):
- self.package = DirFactory(name)
- self.original = orig_src_dir
+ self.pkg_src = DirFactory(name)
self.compiler = haskell_compiler
- def copy_in(self, tarball):
- '''copies a tarball into the package
-
- tarball is a path to some tarball
- '''
- tarball = abspath(tarball)
- with pwd(self.root):
- self.package.add_sourceball(tarball)
-
- def darcs_get(self, url, tgt):
- '''creates a darcs variant of a cabal package using darcs source
-
- url is a url to some darcs repo
- tgt is the local name of the darcs repo
- '''
- self.package.checkout(tgt, url)
-
- def find_setup(self, orig=''):
+ def find_setup(self):
'''returns the name of the Setup.?hs script for cabal.
'''
setup_re = compile("Setup\.l?hs")
- with pwd(self.package.dir):
+ with self.pkg_src.src_dir():
return one(listdir(getcwd()), setup_re.search)
- def compile_setup(self, orig=''):
+ def compile_setup(self, *args):
'''compiles the setup script for faster execution
'''
- log.debug('dir is ' + self.package.dir)
- with pwd(self.package.dir):
- with log_file('ghc.log') 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=''):
+ 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
@@ -103,124 +81,52 @@ class Cabal(Module):
Some help is needed making this more flexible
'''
user = True if target == 'home' else False
- self.compile_setup(orig)
- with pwd(self.package.dir):
- with log_file('cabal.log') 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=''):
+ 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.wait()
+
+ 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.
'''
- self.compile_setup(orig)
- with pwd(self.package.dir):
- with log_file('cabal.log') 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=''):
+ 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.wait()
+
+ 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.
'''
- self.compile_setup(orig)
- with pwd(self.package.dir):
- with log_file('cabal.log') 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()
+ 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.wait()
- def install_tag(self, tag):
- '''assuming a package that supports tagging, install a specific tag
-
- tag is the name of the tag in the DVCS
- '''
- with pwd(self.package.dir):
- with self.package.tag(tag):
- self.install()
-
- def install_source(self, target='home', orig=''):
- '''perform configure, build, and install steps in one
- '''
- self.configure(target, orig)
- self.build(orig)
- self.install(orig)
-
- def install_sourceball(self, tarball, target='home'):
- '''given a tarball, copy it in and install it
- '''
- self.copy_in(tarball)
- self.install_source(target, '')
-
- def get_from_hackage(self, pkg, ver):
- '''get a specific package from hackage
-
- pkg is the name of the package desired
- ver is the version wanted
- '''
- sb_file = self.hackage_url(pkg, ver)
- self.copy_in(sb_file)
-
- def get_latest(self, pkg):
- '''get the latest version of a package from hackage
-
- pkg is the package desired
- '''
- ver = self.latest_version(pkg)
- self.get_from_hackage(pkg, ver)
-
- def install_from_hackage(self, pkg, ver, target='home'):
- '''get and install a specific package from hackage
-
- pkg is the desired package
- ver is the version wanted
- target is the location to install to, either 'home' or 'root'
- '''
- self.get_from_hackage(pkg, ver)
- self.install_source(target, '')
-
- def install_latest(self, pkg, target='home'):
- '''get and install the latest version of a package from hackage'''
- self.get_latest(pkg)
- self.install_source(target, '')
-
- def latest_version(self, pkg):
- '''download information from hackage to find out the latest version of a package
- '''
- hackage_title = compile(r'<title.*?>HackageDB: (.*)-(.*)</title.*?>', 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):
- '''returns the url for tarball for a hackage package'''
- return 'http://hackage.haskell.org/packages/archive/' + \
- pkg + '/' + ver + '/' + pkg + '-' + ver + '.tar.gz'
-
def close(self):
- self.package.close()
+ self.pkg_src.close()
__all__ = ['Cabal']
diff --git a/modules/fetcher.py b/modules/fetcher.py
new file mode 100644
index 0000000..6f52fe8
--- /dev/null
+++ b/modules/fetcher.py
@@ -0,0 +1,33 @@
+# 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 base.module import Module
+
+class Fetcher(Module): pass
+ def latest_version(self, pkg):
+ '''download information from hackage to find out the latest version of a package
+ '''
+ raise NotImplementedError
+
+ def url(self, pkg, ver):
+ '''returns the url for tarball for a hackage package'''
+ raise NotImplementedError
+
+ def latest_url(self, pkg):
+ ver = self.latest_version(pkg)
+ return self.url(pkg, ver)
diff --git a/modules/hackage.py b/modules/hackage.py
new file mode 100644
index 0000000..b08299c
--- /dev/null
+++ b/modules/hackage.py
@@ -0,0 +1,41 @@
+# 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 modules.fetcher import Fetcher
+
+class Hackage(Fetcher):
+ def latest_version(self, pkg):
+ '''download information from hackage to find out the latest version of a package
+ '''
+ hackage_title = compile(r'<title.*?>HackageDB: (.*)-(.*)</title.*?>', 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 url(self, pkg, ver):
+ '''returns the url for tarball for a hackage package'''
+ return 'http://hackage.haskell.org/packages/archive/' + \
+ pkg + '/' + ver + '/' + pkg + '-' + ver + '.tar.gz'
+
diff --git a/modules/haskellport.py b/modules/haskellport.py
new file mode 100644
index 0000000..eff0d70
--- /dev/null
+++ b/modules/haskellport.py
@@ -0,0 +1,96 @@
+# 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 modules.dirfactory import DirFactory
+from modules.port import Port
+
+class HaskellPort(Port):
+ def __init__(self, package):
+ self.pkg = DirFactory(package)
+
+ def copy_in(self, tarball):
+ '''copies a tarball into the package
+
+ tarball is a path to some tarball
+ '''
+ self.package.add_sourceball(tarball)
+
+ def darcs_get(self, url, tgt):
+ '''creates a darcs variant of a cabal package using darcs source
+
+ url is a url to some darcs repo
+ tgt is the local name of the darcs repo
+ '''
+ self.package.checkout(tgt, url)
+
+ def install_tag(self, tag):
+ '''assuming a package that supports tagging, install a specific tag
+
+ tag is the name of the tag in the DVCS
+ '''
+ with pwd(self.package.dir):
+ with self.package.tag(tag):
+ self.install()
+
+ 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 install_sourceball(self, tarball, target='home'):
+ '''given a tarball, copy it in and install it
+ '''
+ self.copy_in(tarball)
+ self.install_source(target, '')
+
+ def install_latest(self, pkg, target='home'):
+ '''get and install the latest version of a package from hackage'''
+ self.get_latest(pkg)
+ self.install_source(target, '')
+
+ def get_from_hackage(self, pkg, ver):
+ '''get a specific package from hackage
+
+ pkg is the name of the package desired
+ ver is the version wanted
+ '''
+ sb_file = self.hackage_url(pkg, ver)
+ self.copy_in(sb_file)
+
+ def get_latest(self, pkg):
+ '''get the latest version of a package from hackage
+
+ pkg is the package desired
+ '''
+ ver = self.latest_version(pkg)
+ self.get_from_hackage(pkg, ver)
+
+ def install_from_hackage(self, pkg, ver, target='home'):
+ '''get and install a specific package from hackage
+
+ pkg is the desired package
+ ver is the version wanted
+ target is the location to install to, either 'home' or 'root'
+ '''
+ self.get_from_hackage(pkg, ver)
+ self.install_source(target, '')
+
+ pass
diff --git a/modules/packagesource.py b/modules/packagesource.py
index b0b87b8..1e88311 100644
--- a/modules/packagesource.py
+++ b/modules/packagesource.py
@@ -17,6 +17,7 @@
#
from __future__ import with_statement
+from contextlib import contextmanager
from os import makedirs
from os.path import join
@@ -78,7 +79,7 @@ class PackageSource(Directory):
def src_dir(self, *args):
'''executes a code block inside a specific branch and or checkout
'''
- with src(*args):
+ with self.src(*args):
with pwd(self.source_dir):
yield
diff --git a/modules/port.py b/modules/port.py
new file mode 100644
index 0000000..c447f83
--- /dev/null
+++ b/modules/port.py
@@ -0,0 +1,21 @@
+# 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 base.modules import Module
+
+class Port(Module): pass
diff --git a/modules/sourceball.py b/modules/sourceball.py
index f164bc3..4940d4b 100644
--- a/modules/sourceball.py
+++ b/modules/sourceball.py
@@ -66,6 +66,7 @@ class SourceBall(PackageSource):
with pwd(self.pkg_src_dir):
move(join(tmp_dir, sourceball_name), sourceball_name)
self.cfg['sourceball'] = sourceball_name
+ self.set_cur_to('head')
def orig_dir(self, dir):
'''where is the original source kept