diff options
| author | Yaakov M. Nemoy <loupgaroublond@gmail.com> | 2008-12-29 23:11:55 -0500 |
|---|---|---|
| committer | Yaakov M. Nemoy <loupgaroublond@gmail.com> | 2008-12-29 23:11:55 -0500 |
| commit | 0cb6e545b308e79a5d4aa6c36b7366f2b0fc30fd (patch) | |
| tree | 8c30624c6191a3d7a138b8229ef829a8406b9aa0 | |
| parent | 3d02771f3e2376cd459e9a4d0edf2ff0c0f22b2c (diff) | |
| download | fedora-devshell-0cb6e545b308e79a5d4aa6c36b7366f2b0fc30fd.tar.gz fedora-devshell-0cb6e545b308e79a5d4aa6c36b7366f2b0fc30fd.tar.xz fedora-devshell-0cb6e545b308e79a5d4aa6c36b7366f2b0fc30fd.zip | |
Mass commit, i should be cleaner in the future.
| -rw-r--r-- | base/profiles.py | 110 | ||||
| -rw-r--r-- | base/rpm_utils.py | 33 | ||||
| -rw-r--r-- | modules/cabal.py | 132 | ||||
| -rw-r--r-- | modules/mock.py | 46 | ||||
| -rw-r--r-- | modules/package.py | 111 | ||||
| -rw-r--r-- | modules/profile.py | 11 |
6 files changed, 413 insertions, 30 deletions
diff --git a/base/profiles.py b/base/profiles.py new file mode 100644 index 0000000..2490b3f --- /dev/null +++ b/base/profiles.py @@ -0,0 +1,110 @@ + +from os.path import join +from subprocess import Popen, PIPE + +from vars import FEDORA_DIR + +TARGET = 0 +DIST = 1 +DISTVAR = 2 +DISTVAL = 3 + +def distdef(dist): + return dist.replace('.', '') + +def define(key, value): + return '--define "%s %s"' % (key, value) + +def join_defines(*defines): + return " ".join(defines) + +def dist_defines(dist, distvar, distval): + dist = define('dist', dist) + distvar = define(distvar, distval) + distdef = define(distdef(dist), 1) + return join_defines([dist, distvar, distdef]) + +head_branch = 'devel' + +def get_mock_cfg(distvar, distval, buildarch): + if distvar == 'fedora' and distval in [4, 5, 6]: + return '%s-%s-%s-core' % (distvar, distval, buildarch) + else: + return '%s-%s-%s' % (distvar, distval, buildarch) + +def dir_defines(some_dir): + defs = list() + defs.append(define('_sourcedir', join(some_dir, 'SOURCES'))) + defs.append(define('_specdir', join(some_dir, 'SPECS'))) + defs.append(define('_builddir', join(some_dir, 'BUILD'))) + defs.append(define('_srcrpmdir', join(some_dir, 'SRPMS'))) + defs.append(define('_rpmdir', join(some_dir, 'RPMS'))) + return join_defines(defs) + +def ver_rel(spec_file, defines): + rpm_p = Popen('rpm %s -q --qf "%%{VERSION} %%{RELEASE}\n" --specfile %s' % \ + (defines, spec_file), stdout=PIPE, shell=True) + verrels = rpm_p.communicate()[0] + verrel = verrels.split('\n')[0] + return verrel.split(' ') + +#taken from CVS for now +distro = [{'RHL-7':('rhl7','.rhl7','rhl','7'), + 'RHL-8':('rhl8','.rhl8','rhl','8'), + 'RHL-9':('rhl9','.rhl9','rhl','9'), + 'OLPC-2':('dist-olpc2','.olpc2','olpc','2'), + 'OLPC-3':('dist-olpc3','.olpc3','olpc','3'), + 'EL-4':('el4','.el4','epel','4'), + 'EL-5':('el5','.el5','epel','5'), + 'FC-1':('fc1','.fc1','fedora','1'), + 'FC-2':('fc2','.fc2','fedora','2'), + 'FC-3':('fc3','.fc3','fedora','3'), + 'FC-4':('fc4','.fc4','fedora','4'), + 'FC-5':('fc5','.fc5','fedora','5'), + 'FC-6':('fc6','.fc6','fedora','6'), + 'F-7':('dist-fc7','.fc7','fedora','7'), + 'F-8':('dist-f8','.fc8','fedora','8'), + 'F-9':('dist-f9','.fc9','fedora','9'), + 'F-10':('dist-f10','.fc10','fedora','10'), + 'F-11':('dist-f11','.fc11','fedora','11'), + 'devel':('dist-devel','.devel','fedora','10')}] + +# this class is temporary, it's only for mimickng CVS for now +# later we'll come up with a better way to do custom profiles +class Profile(object): + def __init__(self, branch): + self.branch = branch + self.distro = distro[branch] + + @property + def dist_defines(self): + d = self.distro + return dist_defines(d[DIST], d[DISTVAR], d[DISTVAL]) + + @property + def mock_cfg(self): + d = self.distro + # TODO: buildarchs need to be handled somehow + # yes i'm lame and i did this i386 only for now + return get_mock_cfg(d[DISTVAR], d[DISTVAL], 'i386') + + @property + def config_dir(self): + return '/etc/mock' + + @property + def result_dir(self): + return FEDORA_DIR + + +def main(): + print distdef('.fc9') + print ver_rel('ghc-X11.spec', '') + +if __name__ == '__main__': + main() + +__all__ = ['TARGET', 'DISTVAR', 'distdef', 'DISTVAL', 'head_branch', + 'DIST', 'join_defines', 'ver_rel', 'define', + 'dir_defines', 'get_mock_cfg', 'dist_defines', + 'Profile']
\ No newline at end of file diff --git a/base/rpm_utils.py b/base/rpm_utils.py new file mode 100644 index 0000000..bfdae46 --- /dev/null +++ b/base/rpm_utils.py @@ -0,0 +1,33 @@ +from __future__ import with_statement + +import re +import rpm + +from contextlib import contextmanager +from base import log + +class RPMSpec(object): + def __init__(self, spec_file): + self.contents = [x for x in file(spec_file)] + + def version(self): + ver_line = [x for x in self.contents if x.startswith('Version:')][0] + ver_re = re.search(r'Version: (.*)', ver_line) + return ver_re.groups()[0] + + def rel(self): + rel_line = [x for x in self.contents if x.startswith('Release:')][0] + rel_re = re.search(r'Release: (.*)', rel_line) + return rel_re.groups()[0] + +@contextmanager +def rpm_macros(**keys): + for key, value in keys.iteritems(): + log.debug('setting...') + log.debug(key + ' ' + value) + rpm.addMacro(key, value) + yield + for key, value in keys.iteritems(): + rpm.delMacro(key) + +__all__ = ['rpm_macros', 'RPMSpec']
\ No newline at end of file diff --git a/modules/cabal.py b/modules/cabal.py new file mode 100644 index 0000000..81f4b68 --- /dev/null +++ b/modules/cabal.py @@ -0,0 +1,132 @@ +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.package import Package + +class Cabal(Module): + def __init__(self, name, root='~/haskell'): + self.name = name + self.root = expanduser(root) + with pwd(self.root): + self.package = Package(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 find_setup(self, original=False): + setup_re = compile("Setup\.l?hs") + with pwd(self.source_dir(original)): + setup_f = one(listdir(getcwd()), setup_re.search) + log.debug(setup_f) + return setup_f + + def compile_setup(self, original=False): + with pwd(self.pkg.code_dir): + with file('ghc.log', 'a') as ghc_out: + with pwd(self.source_dir(original)): + setup_f = self.find_setup(original) + p = Popen([self.compiler, '--make', setup_f], + stdout = ghc_out, stderr = ghc_out) + log.info('Building %s, please wait...' % setup_f) + p.wait() + + def configure(self, target='home', original=False): + user = True if target == 'home' else False + self.compile_setup(original) + with pwd(self.pkg.code_dir): + with file('cabal.log', 'a') as cabal_out: + with pwd(self.source_dir(original)): + 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, original=False): + '''This is not safe to run on an unconfigured source dir''' + self.compile_setup(original) + with pwd(self.pkg.code_dir): + with file('cabal.log', 'a') as cabal_out: + with pwd(self.source_dir(original)): + 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, original=False): + '''This is not safe to run on an unconfigured source dir''' + self.compile_setup(original) + with pwd(self.pkg.code_dir): + with file('cabal.log', 'a') as cabal_out: + with pwd(self.source_dir(original)): + 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', original=False): + self.configure(target, original) + self.build(original) + self.install(original) + + def install_sourceball(self, tarball, target='home'): + self.copy_in(tarball) + self.install_source(target, False) + + 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, False) + + def install_latest(self, pkg, target='home'): + self.get_latest(pkg) + self.install_source(target, False) + + def source_dir(self, original=False): + 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'<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): + return 'http://hackage.haskell.org/packages/archive/' + \ + pkg + '/' + ver + '/' + pkg + '-' + ver + '.tar.gz' + + def close(self): + self.package.close() diff --git a/modules/mock.py b/modules/mock.py new file mode 100644 index 0000000..3655c37 --- /dev/null +++ b/modules/mock.py @@ -0,0 +1,46 @@ +from __future__ import with_statement + +from base.module import Module +from base.vars import FEDORA_DIR +from base.profiles import ver_rel, Profile +from modules.build import Build +from modules.package import Package + +class Mock(Module): + def __init__(self, target_dir, name, profile): + self.target_dir = target_dir + self.name = name + self.pkg = Package(name) + self.build = Build(name, target_dir) + # for now we're using the old profile form, namely a branch + # TODO: fix real profiles + self.profile = Profile(profile) + + def build_rpm(self, target_dir=None): + if not target_dir: + if self.target_dir: + target_dir = self.target_dir + else: + raise ExecutionException(None, 'no Target Dir specified') + + self.build.build_source_rpm(target_dir, self.profile) + self.build.fetch_rpms(target_dir) + + srpm_name = self.pkg.get_srpm_name(self.profile) + mock_cfg = self.profile.mock_cfg + result_dir = self.profile.result_dir + config_dir = self.profile.config_dir + with pwd(self.pkg.code_dir): + with file('mock.log', 'w') as mock_out: + with pwd(FEDORA_DIR): + p = Popen(['/usr/bin/mock', + '-r %s' % mock_cfg, + '--configdir=%s' % config_dir, + '--resultdir=%s' % result_dir, + srpm_name], + stdout=mock_out, stderr=mock_out) + log.info('quick compiling %s... please wait' % srpm_name) + p.wait() + + +__all__ = ['Mock']
\ No newline at end of file diff --git a/modules/package.py b/modules/package.py index 8072938..18e4dde 100644 --- a/modules/package.py +++ b/modules/package.py @@ -1,43 +1,75 @@ from __future__ import with_statement import tarfile -from os import makedirs, getcwd, chdir +from os import makedirs, getcwd, chdir, listdir from shutil import copyfileobj, copytree -from os.path import abspath, join, split, splitext, basename +from os.path import abspath, join, split, splitext, basename, exists from configobj import ConfigObj - +from subprocess import Popen, PIPE +from urllib import urlretrieve from base.module import Module from base.base import log from base.exceptions import ExecutionException from base.util import pwd, copy +from base.profiles import ver_rel #TODO: Find universal library for parsing URLs and PATHs alike class Package(Module): def __init__(self, name=None): if not name: - log.debug(split(getcwd())) + log.debug('no name with package') + cwd = getcwd() + log.debug(split(cwd)) + if self.is_dir_pkg(cwd): + self.load_pkg(cwd) + else: + self.make_pkg(cwd) name = split(getcwd())[1] + self.code_dir = getcwd() #detect name somehow else: + log.debug('package.init with name ' + name) + dir = abspath(name) + if not exists(dir): + makedirs(dir) + if self.is_dir_pkg(dir): + self.load_pkg(dir) + else: + self.make_pkg(dir) + + def is_dir_pkg(self, dir): + with pwd(dir): + cfg = ConfigObj('.devshell') try: - cfg = ConfigObj('.devshell') if cfg['type'] == 'package': - self.code_dir = getcwd() - except: - self.code_dir = abspath(name) - with pwd(self.code_dir): - self.pkg_cfg = ConfigObj('.devshell') - if not self.pkg_cfg['type'] == 'package': - raise ExecutionException('invalid package directory') - self.name = name - - def create(self, name): - if not self.name: - makedirs(join(getcwd(), name)) - + log.debug('is type package') + return True + else: + return False + except KeyError, e: + return False + + def load_pkg(self, dir): + log.debug('package.load_pkg') + with pwd(dir): + self.cfg = ConfigObj('.devshell') + self.name = self.cfg['name'] + self.code_dir = self.cfg['code_dir'] + + def make_pkg(self, dir): + log.debug('package.make_pkg') + with pwd(dir): + code_dir = dir + name = split(getcwd())[1] + self.cfg = ConfigObj('.devshell') + self.cfg['type'] = 'package' + self.cfg['name'] = self.name = name + self.cfg['code_dir'] = self.code_dir = code_dir + self.cfg.write() + def add_spec(self, spec_file): log.debug('spec_file is %s' % spec_file) log.debug('spec_file_name is %s' % self.name + '.spec') @@ -47,21 +79,28 @@ class Package(Module): except IOError, e: log.error(str(e)) raise ExecutionException(e, 'spec-file could not be added') - + + def orig_dir(self, dir): + return dir + '_orig' + def add_sourceball(self, sourceball_name, extract_dir=None): + log.debug('addincg sourceball with code_dir ' + self.code_dir) with pwd(self.code_dir): try: - copy(sourceball_name, split(sourceball_name)[1]) - sourceball_name = split(sourceball_name)[1] - - self.pkg_cfg['sourceball'] = sourceball_name + sourceball_name = urlretrieve(sourceball_name, + split(sourceball_name)[1])[0] + + self.cfg['sourceball'] = sourceball_name sourceball = tarfile.open(sourceball_name) if not extract_dir: extract_dir = min([(x.name, x) for x in sourceball])[0] extract_dir = basename(abspath(extract_dir)) - log.debug('extract_dir is %s' % extract_dir) - self.pkg_cfg['source'] = extract_dir - orig_extract_dir = extract_dir + '_orig' + log.debug('extract_dir is %s' % extract_dir) + log.debug('config is of ' + str(self.cfg)) + self.cfg['source'] = extract_dir + log.debug('cfg[\'source\'] is ' + self.cfg['source']) + log.debug('set source') + orig_extract_dir = self.orig_dir(extract_dir) sourceball.extractall() copytree(abspath(extract_dir), abspath(orig_extract_dir)) except OSError, e: @@ -69,8 +108,20 @@ class Package(Module): #Chances are the _orig dir already exists raise ExecutionException(e, 'something went wrong') #TODO: figure out what exceptions TarFile will throw - + def close(self): - self.pkg_cfg.write() - -__all__ = ['Package']
\ No newline at end of file + log.debug('writing self.cfg for package') + with pwd(self.code_dir): + self.cfg.write() + + @property + def spec_file(self): + return self.name + '.spec' + + def get_srpm_name(self, profile): + with pwd(self.code_dir): + ver, rel = ver_rel(self.spec_file, profile.dist_defines()) + return '%s-%s-%s.src.rpm' % (self.name, ver, rel) + + +__all__ = ['Package'] diff --git a/modules/profile.py b/modules/profile.py new file mode 100644 index 0000000..bac1553 --- /dev/null +++ b/modules/profile.py @@ -0,0 +1,11 @@ +from base.module import Module +from base.exceptions import ExecutionException + +class Profile(Module): + def __init__(self, name=None, branch=None): + if branch: + pass + elif name: + pass + else: + raise ExecutionException('need a saved profile or a branch to lookup')
\ No newline at end of file |
