summaryrefslogtreecommitdiff
blob: 4bd51d401614930865c932fd76cd64ef4933bfa0 (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
import re, os
from ebuild import *
from filetricks import *
from settings import *

#figure out the location of the portage tree, or return it if we already know it
portage_location=None
def portage_dir():
    global portage_location
    if portage_location!=None: #we already know
        return portage_location
    if os.path.exists('/etc/paludis/repositories/gentoo.conf'): #paludis stores repository data here
        conffile=open('/etc/paludis/repositories/gentoo.conf')
        for line in conffile:
            if 'location'==line[:len('location')]:
                portage_location=re.sub('\$\{.+?\}','',line[line.find('=')+1:]).strip() #remove ${ROOT} and other variables (lucky guess, lol)
    elif os.path.exists('/etc/make.conf'): #portage stores portage location here
        conffile=open('/etc/make.conf')
        for line in conffile:
            if 'PORTDIR' in line and '=' in line:
                portage_location=re.sub('\"(.*)\"','\1',line[line.find('='):]).strip()
    elif os.path.exists('/usr/portage'): #default location
        portage_location='/usr/portage'
    else:
        raise RuntimeError('Could not deduce portage location')
    return portage_location

def pmsify_license_field(license_list):
    portdir=portage_dir()
    available_licenses=os.listdir(os.path.join(portdir,'licenses'))
    #note: the following returns a list of tuples
    matches=re.findall(r'\s*([^|]+)\s*',license_list) #split into licenses + versions
    licenses=[]
    for license_part in matches: #process each license option
        if license_part[:4]=='file': #license field referse to a file
            #licenses.append(license_part) #we'll have to somehow install this file...
            continue
        parse=re.match(r'(.+)\(\W*([^()]+?)\)',license_part)
        try_license=None
        if parse: #versioned license
            license_name=parse.group(1).strip()
            version=parse.group(2).strip()
            try_license=license_name+'-'+version
        else: #perhaps we just want version 1?
            try_license=license_part+'-1'
        for license in available_licenses:
            if license==license_part or try_license==license:
                licenses.append(license)
                break
        else:
            licenses.append('as-is') #unknown
    return licenses

def pmsify_package_name(name):
    if len(name)==0:
        return 'test'
    name=re.sub('[^a-zA-Z0-9+_-]','',name) #name may only contain these characters
    if not re.match('[a-zA-Z0-9+_].*',name): #package name must start with [a-zA-Z0-9+_]
        name='_'+name
    if re.match('.*-[0-9]+',name): #package name may not end in hyphen followed by integer
        name=name+'_'
    return name

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:
    e_vars['pn']=pmsify_package_name(data['package'])
    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']=pmsify_license_field(data['license'])

    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")