diff options
author | Auke Booij (tulcod) <auke@tulcod.com> | 2010-06-26 00:38:21 +0200 |
---|---|---|
committer | Auke Booij (tulcod) <auke@tulcod.com> | 2010-06-26 00:38:21 +0200 |
commit | c8d93826d032d7e55d10e4b82d5a2b8bba211320 (patch) | |
tree | 5f459e5bf26e1acad406d410211a8ccb536fafd3 /g_cran | |
parent | What a shameful commit, putting my home directory out there just like that. (diff) | |
download | g-cran-c8d93826d032d7e55d10e4b82d5a2b8bba211320.tar.gz g-cran-c8d93826d032d7e55d10e4b82d5a2b8bba211320.tar.bz2 g-cran-c8d93826d032d7e55d10e4b82d5a2b8bba211320.zip |
Prepare for packaging with distutils
Diffstat (limited to 'g_cran')
-rw-r--r-- | g_cran/__init__.py | 0 | ||||
-rw-r--r-- | g_cran/cran_read.py | 89 | ||||
-rw-r--r-- | g_cran/ebuild.py | 25 | ||||
-rw-r--r-- | g_cran/filetricks.py | 15 | ||||
-rw-r--r-- | g_cran/g_cran.py | 86 | ||||
-rw-r--r-- | g_cran/phases.py | 48 | ||||
-rw-r--r-- | g_cran/settings.py | 5 |
7 files changed, 268 insertions, 0 deletions
diff --git a/g_cran/__init__.py b/g_cran/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/g_cran/__init__.py diff --git a/g_cran/cran_read.py b/g_cran/cran_read.py new file mode 100644 index 0000000..30afc8a --- /dev/null +++ b/g_cran/cran_read.py @@ -0,0 +1,89 @@ +import re, os +from ebuild import * +from filetricks import * +from settings import * + +def pmsify_package_version(version_str): + return version_str.replace('-','.') #some CRAN-style versions have the form 0.1-1, which we transform into 0.1.1 + +def pmsify_package_list(package_list): + #note: the following returns a list of tuples + matches=re.findall(r'\s*(([^,]+\([^()]+?\))|([^,]+))\s*',package_list) #split into packages + versions + packages=[] + for package_part in matches: #process each package match + if len(package_part[1])>len(package_part[2]): #versioned package identifier + parse=re.match(r'([^,]+)\(([^()]+?)\)',package_part[1]) + pkg_name=parse.group(1).strip() + versions=parse.group(2) + #fixme version specifiers + if pkg_name=='R': + category='dev-lang' + else: + category='dev-R' + packages.append(category+'/'+pkg_name) + else: + pkg_name=package_part[2].strip() + if pkg_name=='R': + category='dev-lang' + else: + category='dev-R' #assume it's a CRAN package + packages.append(category+'/'+pkg_name) + return packages + +#Parse package options into values we can work with in accordance with PMS +def pmsify_package_data(data,remote_repository): + pms_pkg=Ebuild() + pms_pkg.cran_data=data + e_vars=pms_pkg.ebuild_vars + #fix settings: + if 'package' not in data: + e_vars['pn']='test' + else: + e_vars['pn']=data['package'] + if not re.match('[a-zA-Z0-9+_].*',e_vars['pn']): #package name may not be valid according to PMS + e_vars['pn']='_'+e_vars.pn + if re.match('.*-[0-9]+',e_vars['pn']): + e_vars['pn']=e_vars.pn+'_' + if 'version' not in data: #set a version even if we have none + e_vars['pv']='0' + else: + e_vars['pv']=pmsify_package_version(data['version']) + if 'depends' in data: + deps=pmsify_package_list(data['depends']) + else: #some packages don't set dependencies, so force dependency on R + deps=['dev-lang/R',] + e_vars['depend']=deps + e_vars['pdepend']=deps + e_vars['rdepend']=deps + + e_vars['iuse']="doc" + e_vars['keywords']="~x86 ~amd64" + if 'description' in data: + e_vars['description']=data['description'].strip().replace('\n',' ') + else: + e_vars['description']=e_vars['pn'] + if 'license' in data: #fixme parse license data + e_vars['license']=data['license'].strip() + + e_vars['src_uri']=remote_repository+'/src/contrib/'+data['package']+'_'+data['version']+'.tar.gz' + return pms_pkg + +def read_packages(package_filename,local_repository): + packages_file=open(package_filename,"r") + file_parts=EmptyLinesFile(packages_file) #this is where we split the PACKAGES file into several file parts + packages=[] + import rfc822 + repository_file=open(os.path.join(local_repository,REPO_MYDIR,'remote_uri'),'r') + remote_uri=repository_file.read().strip() + while not file_parts.eof: + cran_package=dict(rfc822.Message(file_parts).items()) #read part of PACKAGES file + pms_package=pmsify_package_data(cran_package,remote_uri) #fix values + packages.append(pms_package) #store in dict + return packages + +def find_package(repo_location,package_name): + packages=read_packages(os.path.join(repo_location,REPO_MYDIR,'PACKAGES'),repo_location) + for package in packages: + if package.ebuild_vars['pn']==package_name: + return package + raise ValueError("Package not found") diff --git a/g_cran/ebuild.py b/g_cran/ebuild.py new file mode 100644 index 0000000..14d6af8 --- /dev/null +++ b/g_cran/ebuild.py @@ -0,0 +1,25 @@ +#!/usr/bin/python +#Class for PMS-style packages +class Ebuild(): + def __init__(self): + #todo add needed variables as __init__ arguments + self.ebuild_vars={ + 'pn':'', + 'pv':'', + 'description':'', + 'homepage':'', + 'iuse':'', + 'keywords':'', + 'license':'', + 'slot':'0', + 'src_uri':'', + 'eapi':'3', + 'depend':[], + 'pdepend':[], + 'rdepend':[], + 'provide':[], + 'restrict':[], + 'properties':'', + } + self.cran_data={} + diff --git a/g_cran/filetricks.py b/g_cran/filetricks.py new file mode 100644 index 0000000..e42e059 --- /dev/null +++ b/g_cran/filetricks.py @@ -0,0 +1,15 @@ +#!/usr/bin/python +class EmptyLinesFile: + def __init__(self,myfile): + self.file=myfile + self.eof=False + self.lines=self.generate_lines() + def generate_lines(self,size=-1): + for line in self.file: + yield line + self.eof=True + def readline(self): + try: + return self.lines.next() + except StopIteration: + return '' diff --git a/g_cran/g_cran.py b/g_cran/g_cran.py new file mode 100644 index 0000000..0b84813 --- /dev/null +++ b/g_cran/g_cran.py @@ -0,0 +1,86 @@ +#!/usr/bin/python +import getopt, sys, os, string, urllib, re +from ebuild import * +import phases +from cran_read import * +from settings import * + +__doc__="Usage: "+sys.argv[0]+" <local repository directory> <action> [<action arguments>...]" + +def action_sync(repo_location,remote_uri): + if not os.path.isdir(os.path.join(repo_location, REPO_MYDIR)): + if os.path.isdir(repo_location): + os.mkdir(os.path.join(repo_location,REPO_MYDIR)) + packages_filename=os.path.join(repo_location, REPO_MYDIR, 'PACKAGES') + urllib.urlretrieve(remote_uri+'/src/contrib/PACKAGES',packages_filename) + repo_file=open(os.path.join(repo_location,REPO_MYDIR,'remote_uri'),'w') + repo_file.write(remote_uri) + +def list_categories(repo_location): + print "dev-R" + +def list_packages(repo_location): + packages=read_packages(os.path.join(repo_location,REPO_MYDIR,'PACKAGES'),repo_location) + for package in packages: + print 'dev-R/'+package.ebuild_vars['pn'],package.ebuild_vars['pv'] + +def action_package(repo_location,package_name): + defined_phases=[] + package=find_package(repo_location,package_name[package_name.find('/')+1:]) + #output data + for key,value in package.ebuild_vars.iteritems(): + if key=='pn' or key=='pv': #readonly vars, we cannot set these in ebuilds + continue + if isinstance(value,str): #if string + print key.upper()+'='+value.replace('\n','') + elif isinstance(value,list): #list, concat items + print key.upper()+'='+' '.join(value).replace('\n','') + for pms_func in pms_phases: + if hasattr(phases,pms_func): + defined_phases.append(pms_func) + print 'GCOMMON_PHASES='+' '.join(defined_phases) + +def usage(): + print __doc__ + +def main(): + arguments=sys.argv[1:] + #print options, arguments + if len(arguments)<2: #we need at least a local repository location and an action + usage() + sys.exit(0) + action=arguments[1] + repo_location=os.path.abspath(arguments[0]) + if action=='sync': + if len(arguments)<3: + print "The 'sync' action takes the following parameters:" + print " * remote_repository_uri" + sys.exit(1) + remote_repo=arguments[2] + action_sync(repo_location,remote_repo) + elif action=='list-categories': + list_categories(repo_location) + elif action=='list-packages': + list_packages(repo_location) + elif action=='package': + if len(arguments)<3: + print "The 'package' action takes the following parameters:" + print " * category/package_name" + print " * [version]" + sys.exit(1) + package_name=arguments[2] + action_package(repo_location,package_name) + elif action=='usage': + usage() + elif action in pms_phases and hasattr(phases,action): + getattr(phases,action)(os.environ,repo_location) + elif action in actions_wanted: + raise NotImplementedError + else: + usage() + sys.exit(0) + +if __name__ == "__main__": + main() + + diff --git a/g_cran/phases.py b/g_cran/phases.py new file mode 100644 index 0000000..6915979 --- /dev/null +++ b/g_cran/phases.py @@ -0,0 +1,48 @@ +import os +import cran_read + +R_PLATFORM="ignoreplatform" + +def verbose_system(command): + print command + return os.system(command) + +#This function actually creates a binary package (a tarball) from the source package +#this way, we cleanly split up R package installing into a compile and install phase +def src_compile(env,local_repository): + #verbose_system("R CMD INSTALL --build ") + package=cran_read.find_package(local_repository,env['PN']) + os.putenv('R_PLATFORM',R_PLATFORM) #force predictable package name + os.chdir(env['WORKDIR']) + returnval=verbose_system("R CMD build --binary "+env['WORKDIR']+'/'+package.cran_data['package']) + if returnval: + raise RuntimeError("R build failed") + +def src_install(env,local_repository): + package=cran_read.find_package(local_repository,env['PN']) + os.putenv('R_PLATFORM',R_PLATFORM) + tarname=env['WORKDIR']+'/'+package.cran_data['package']+'_'+package.cran_data['version']+'_R_'+R_PLATFORM+'.tar.gz' #assume always gzip + r_home=os.getenv('R_HOME') + if len(r_home)==0: #R home isn't set, try to read /etc/env.d/99R + envfile=open('/etc/env.d/99R','r') + for line in envfile: + if line[:len('R_HOME')]=='R_HOME': + r_home=line[line.find('=')+1:].strip() + break + else: + raise RuntimeError("Could not deduce R_HOME") + r_library=env['D']+r_home+"/library" + if not os.path.exists(r_library): + os.makedirs(r_library) + #install the binary package without documentation (excluding documentation doesn't seem to work) + returnval=verbose_system("R CMD INSTALL --debug --no-docs --no-html "+tarname+" -l "+r_library) + if returnval: + raise RuntimeError("R install failed") + #todo install HTML help + doc_dir=env['D']+'/usr/share/doc/'+env['PVR'] + + if 'doc' in package.ebuild_vars['iuse'] and 'doc' in env['USE']: + pass + #not implemented + + diff --git a/g_cran/settings.py b/g_cran/settings.py new file mode 100644 index 0000000..1da3a16 --- /dev/null +++ b/g_cran/settings.py @@ -0,0 +1,5 @@ + +pms_phases=['pkg_pretend','pkg_setup','src_unpack','src_prepare','src_configure','src_compile', + 'src_test','src_install','pkg_preinst','pkg_postinst','pkg_prerm','pkg_postrm','pkg_config','pkg_info','pkg_nofetch'] +actions_wanted=['usage','sync','list-categories','list-packages','package']+pms_phases +REPO_MYDIR=".g-cran" |