3 # This is a replacement for the formerly bash-written function pl_parsePkgs ()
5 # Usage: $0 [-a arch] default_arch keyword fcdistro pldistro pkgs-file[..s]
6 # default_arch is $pl_DISTRO_ARCH, but can be overridden
9 #################### original language was (in this example, keyword=package)
10 ## to add to all distros
12 ## to add in one distro
14 ## to remove in one distro
16 #################### replacement language
21 ## add in fedora distros starting with f10
22 # +package>=f10: p1 p2
25 ## ditto but remove instead
26 # -package=centos5: p1 p2
27 # -package<=centos5: p1 p2
30 from sys import stderr
31 from optparse import OptionParser
35 known_arch = ['i386', 'i686', 'x86_64']
36 default_fcdistro='f14'
37 known_fcdistros = [ 'centos5','centos6',
38 'f8', 'f10','f12', 'f14', 'f16', 'f18','f20','f21',
41 'squeeze','wheezy','jessie',
43 'oneiric', 'precise', 'quantal', 'raring', 'saucy', 'trusty', 'utopic' ]
44 default_pldistro='onelab'
47 'group', 'groupname', 'groupdesc',
48 'package', 'pip', 'gem',
49 'nodeyumexclude', 'plcyumexclude', 'yumexclude',
50 'precious', 'junk', 'mirror',
54 m_fcdistro_cutter = re.compile('([a-z]+)([0-9]+)')
59 def __init__ (self,arch,fcdistro,pldistro,keyword,inputs,options):
61 self.fcdistro=fcdistro
62 self.pldistro=pldistro
65 # for verbose, new_line, and the like
68 for known in known_fcdistros:
71 (distro,version)=m_fcdistro_cutter.match(fcdistro).groups()
72 # debian-like names can't use numbering
79 self.version=int(version)
81 print >> stderr, 'unrecognized fcdistro', fcdistro
84 # qualifier is either '>=','<=', or '='
85 def match (self, qualifier, version):
87 return self.version == version
88 elif qualifier == '>=':
89 return self.version >= version
90 elif qualifier == '<=':
91 return self.version <= version
93 raise Exception, 'Internal error - unexpected qualifier %r' % qualifier
95 m_comment=re.compile('\A\s*#')
96 m_blank=re.compile('\A\s*\Z')
98 m_ident=re.compile('\A'+re_ident+'\Z')
100 re_qualified += '(?P<plus_minus>[+-]?)'
101 re_qualified += '\s*'
102 re_qualified += '(?P<keyword>%s)'%re_ident
103 re_qualified += '\s*'
104 re_qualified += '(?P<qualifier>>=|<=|=)'
105 re_qualified += '\s*'
106 re_qualified += '(?P<fcdistro>%s[0-9]+)'%re_ident
107 re_qualified += '\s*'
108 m_qualified = re.compile('\A%s\Z'%re_qualified)
110 re_old = '[a-z]+[+-][a-z]+[0-9]+'
111 m_old = re.compile ('\A%s\Z'%re_old)
113 # returns a tuple (included,excluded)
114 def parse (self,filename):
120 for line in file(filename).readlines():
123 if self.m_comment.match(line) or self.m_blank.match(line):
126 [lefts,rights] = line.split(':',1)
127 for left in lefts.split():
128 ########## single ident
129 if self.m_ident.match(left):
130 if left not in known_keywords:
131 raise Exception,"Unknown keyword %r"%left
132 elif left == self.keyword:
133 included += rights.split()
135 m=self.m_qualified.match(left)
137 (plus_minus,kw,qual,fcdistro) = m.groups()
138 if kw not in known_keywords:
139 raise Exception,"Unknown keyword in %r"%left
140 if fcdistro not in known_fcdistros:
141 raise Exception, 'Unknown fcdistro %r'%fcdistro
142 # skip if another keyword
143 if kw != self.keyword: continue
144 # does this fcdistro match ?
145 (distro,version)=m_fcdistro_cutter.match(fcdistro).groups()
146 version = int (version)
147 # skip if another distro family
148 if distro != self.distro: continue
149 # skip if the qualifier does not fit
150 if not self.match (qual, version):
151 if self.options.verbose: print >> stderr,'%s:%d:qualifer %s does not apply'%(filename,lineno,left)
153 # we're in, let's add (default) or remove (if plus_minus is minus)
154 if plus_minus == '-':
155 if self.options.verbose: print >> stderr,'%s:%d: from %s, excluding %r'%(filename,lineno,left,rights)
156 excluded += rights.split()
158 if self.options.verbose: print >> stderr,'%s:%d: from %s, including %r'%(filename,lineno,left,rights)
159 included += rights.split()
160 elif self.m_old.match(left):
161 raise Exception,'Old-fashioned syntax not supported anymore %r'%left
163 raise Exception,'error in left expression %r'%left
167 print >> stderr, "%s:%d:syntax error: %r"%(filename,lineno,e)
170 print >> stderr, 'Could not parse file',filename,e
171 return (ok,included,excluded)
177 for input in self.inputs:
178 (o,i,e) = self.parse (input)
182 # avoid set operations that would not preserve order
183 results = [ x for x in included if x not in excluded ]
185 results = [ x.replace('@arch@',self.arch).\
186 replace('@fcdistro@',self.fcdistro).\
187 replace('@pldistro@',self.pldistro) for x in results]
188 if self.options.sort_results:
190 # default is space-separated
191 if not self.options.new_line:
192 print " ".join(results)
193 # but for tests results are printed each on a line
195 for result in results : print result
199 usage="Usage: %prog [options] keyword input[...]"
200 parser=OptionParser (usage=usage)
201 parser.add_option ('-a','--arch',dest='arch',action='store',default=default_arch,
202 help='target arch, e.g. i386 or x86_64, default=%s'%default_arch)
203 parser.add_option ('-f','--fcdistro',dest='fcdistro',action='store', default=default_fcdistro,
204 help='fcdistro, e.g. f12 or centos5')
205 parser.add_option ('-d','--pldistro',dest='pldistro',action='store', default=default_pldistro,
206 help='pldistro, e.g. onelab or planetlab')
207 parser.add_option ('-v', '--verbose',dest='verbose',action='store_true',default=False,
208 help='verbose when using qualifiers')
209 parser.add_option ('-n', '--new-line',dest='new_line',action='store_true',default=False,
210 help='print outputs separated with newlines rather than with a space')
211 parser.add_option ('-u', '--no-sort',dest='sort_results',default=True,action='store_false',
212 help='keep results in the same order as in the inputs')
213 (options,args) = parser.parse_args()
216 parser.print_help(file=stderr)
220 if not options.arch in known_arch:
221 print >> stderr, 'Unsupported arch',options.arch
222 parser.print_help(file=stderr)
224 if options.arch == 'i686': options.arch='i386'
225 if not options.fcdistro in known_fcdistros:
226 print >> stderr, 'Unsupported fcdistro',options.fcdistro
227 parser.print_help(file=stderr)
230 pkgs = PkgsParser (options.arch,options.fcdistro,options.pldistro,keyword,inputs,options)
237 if __name__ == '__main__':