update recipes generation
[scm/bb/tizen.git] / tools / spec2yocto.py
1 #!/usr/bin/python
2 #
3 # Copyright 2013, Intel Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; version 2 of the License.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU Library General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 # native
18
19 '''
20 Created on  05 fevr. 2013
21
22 @author: ronan@fridu.net
23 '''
24
25 import os
26 import shutil
27 import errno
28
29 RECIPES_SOURCE_DIR = os.path.dirname( os.path.realpath( __file__ ) )
30 RECIPES_DIR_DEST = os.path.join( RECIPES_SOURCE_DIR, "../meta-tizen-ivi" )
31 GIT_COMMAND = "git://%s/%s;tag=%s;nobranch=1"
32
33 import sys
34 import platform
35
36 from urllib import urlopen
37 from xml.etree import ElementTree
38
39 try:
40     import cmdln
41 except:
42     print >> sys.stderr, 'Error spec2yocto require "python-cmdln" please install it.'
43     sys.exit( 1 )
44
45 import fcntl
46
47 import subprocess
48 import shlex
49
50 import re
51 import select
52
53 import tempfile
54
55 import ConfigParser
56
57 # Very useful to debug spec2yocto, print the subprocess EXEC_COMMAND line.
58 DEBUG_RUN = False
59
60 CONFIGURATION_FILE_PATH = os.path.expanduser( os.path.join( "~", ".spec2yoctorc" ) )
61
62 class Spec2yoctoConfig( object ):
63     '''
64     Parse the file "spec2yocto_configure",
65
66     '''
67     def __init__( self ):
68         self.__config_parser = ConfigParser.ConfigParser()
69         self.__config_parser.optionxform = str
70
71         if not os.path.isfile( CONFIGURATION_FILE_PATH ):
72             print >> sys.stderr, "Warning CONFIGURATION_FILE_PATH \"%s\" do not exist." % (CONFIGURATION_FILE_PATH)
73             print >> sys.stderr,"         a sample is available in directory \"proto-meta-Tizen_generic/.spec2yoctorc\""
74             sys.exit(1)
75
76         self.__config_file = open( CONFIGURATION_FILE_PATH , 'rw' )
77
78         self.__config_parser.readfp( self.__config_file )
79
80     def get_current_project( self ):
81         '''
82         return the list of the manifest_meta, manifest_meta can be a file or URL.
83         '''
84
85         return self.__get_value( "project", "current" , None )
86
87     def get_manifest_meta_list( self, projet ):
88         '''
89         return the list of the manifest_meta, manifest_meta can be a file or URL.
90         '''
91         meta_manifests_res = []
92         list_of_meta_manifest = self.__get_list( projet, "manifest", [] )
93         for meta_manifest in list_of_meta_manifest:
94             meta_manifests_res.append( meta_manifest.replace( " ", "" ) )
95
96         return meta_manifests_res
97
98     def get_manifest_uri( self, meta_manifest ):
99         '''
100         return the uri of the manifest.
101         '''
102         res = self.__get_value( meta_manifest, "uri" , None )
103         res = os.path.expanduser( res )
104         res = os.path.expandvars( res )
105         return res
106
107     def get_manifest_priority( self, meta_manifest ):
108         '''
109         return the priority of the manifest.
110         '''
111         return self.__get_value( meta_manifest, "priority" , 0 )
112
113     def get_manifest_default_git_src( self, meta_manifest ):
114         '''
115         return the default_git_src of the manifest.
116         '''
117         return self.__get_value( meta_manifest, "default_git_src" , None )
118
119     def is_valide_project( self, projet ):
120         '''
121         check if project is configurate in the conf file.
122         '''
123         return ( projet in self.__config_parser.sections() )
124
125     def get_project_arch( self, projet ):
126         '''
127         return the default arch of the project.
128         '''
129         return self.__get_value( projet, "arch", None )
130
131     def get_manifest_buildtarget(self, meta_manifest):
132         '''
133         return the default buildtarget of the project.
134         '''
135         return self.__get_value( meta_manifest, "buildtarget", None )
136
137     def get_working_dir( self, projet ):
138         '''
139         return the working dir of the project.
140         '''
141         res = self.__get_value( projet, "working_dir", "/tmp" )
142
143         res = os.path.expanduser( res )
144         res = os.path.expandvars( res )
145         return res
146
147     def get_list(self, project, list_name):
148         """
149         Returns the corresponding list.
150         """
151         res_list = self.__get_list( project, list_name, [] )
152         res = []
153         for element in res_list:
154             res.extend(self.__get_list(element, "list", []))
155         return res
156
157     def get_substitute( self , project = None ):
158
159         res = {}
160         for package in self.__config_parser.options( "substitute" ):
161             package_replace = self.__get_value( "substitute", package, None )
162             if package_replace is not None:
163                 res[package] = package_replace
164         return res
165
166     def __get_list( self, section, option, default_value ):
167         '''
168         generic fonction to get list value.
169         '''
170         if ( section in self.__config_parser.sections() ) and \
171            ( option in self.__config_parser.options( section ) ):
172             tmp_res = str( self.__config_parser.get( section, option ) )
173             return tmp_res.replace( " ", "" ).split( "," )
174         else:
175             return default_value
176
177     def __get_value( self, section, option, default_value ):
178         '''
179         generic fonction to get value.
180         '''
181         if ( section in self.__config_parser.sections() ) and \
182            ( option in self.__config_parser.options( section ) ):
183             tmp_res = self.__config_parser.get( section, option )
184             return tmp_res
185         else:
186             return default_value
187
188     def get_recipes_sources_directory( self, project ):
189         '''
190         return a list of the recipes directory needed to build the image.
191         '''
192         res = self.__get_value( project, 'recipes_dir_sources', None )
193         res = os.path.expanduser( res )
194         res = os.path.expandvars( res )
195         return res
196
197     def get_recipes_group_directory( self, project ):
198         res = self.__get_value( project, 'recipes_dir_group', None )
199         res = os.path.expanduser( res )
200         res = os.path.expandvars( res )
201         return res
202
203
204     def get_group( self , project = None ):
205         if project is None:
206             project = self.get_current_project()
207         return self.__get_list( project, 'group', [] )
208
209
210     def get_target_cpu( self , project = None ):
211         '''
212         return target cpu.
213         '''
214         if project is None:
215             project = self.get_current_project()
216         return self.__get_value( project, 'arch' , None )
217
218     def get_bb_autoreconf_blacklist( self , project = None ):
219         '''
220         return a list of package with no autoreconf.
221         '''
222         if project is None:
223             project = self.get_current_project()
224
225         blacklist_list = self.__get_list( project, "blacklist_autoreconf", [] )
226         res = []
227         for blacklist in blacklist_list:
228             res.extend( self.__get_list( blacklist, "blacklist", [] ) )
229
230         return res
231
232     def get_provided_extra( self , project = None ):
233
234         if project is None:
235             project = self.get_current_project()
236
237         provided_extra_list = self.__get_list( project, "provided-extra", [] )
238         provided_extra_dico={}
239         for provided_extra in provided_extra_list:
240             for package in self.__config_parser.options( provided_extra ):
241                 provided_list = self.__get_list( provided_extra, package, [] )
242                 provided_extra_dico[package] = provided_list
243         return provided_extra_dico
244
245
246     def get_ignore_depend( self ):
247         '''
248         return the ignore package to ignore for depends (build require).
249         '''
250         return self.__get_list( 'depends', 'ignore', [] )
251
252     def get_ignore_rdepend( self ):
253         '''
254         return the ignore package to ignore for rdepends (require).
255         '''
256         return self.__get_list( 'rdepends', 'ignore', [] )
257
258     def get_native_depend( self ):
259         '''
260         some buildRequire mean depends on native package not runtime.
261         '''
262         return self.__get_list( 'depends', 'native', [] )
263
264     def get_cross_depend( self ):
265         '''
266         some buildRequire mean depends on native package not runtime.
267         '''
268         return self.__get_list( 'depends', 'cross', [] )
269
270     def get_libtool_cross( self ):
271         '''
272         some buildRequire mean depends on libtool-cross package not runtime.
273         '''
274         return self.__get_list( 'depends', 'libtool_cross', [] )
275
276     def get_inherit_gettext( self ):
277         '''
278         some buildRequire mean inherit_gettext package not depends runtime.
279         '''
280         return self.__get_list( 'depends', 'inherit_gettext', [] )
281
282     def get_inherit(self, package):
283         '''
284         some buildRequire mean inherit_cmake package not depends runtime.
285         '''
286         return [package]
287
288     def get_group_uri( self, project ):
289
290         return self.__get_value( project, 'group_uri', None )
291
292
293 SPEC2YOCTO_CONFIG = Spec2yoctoConfig()
294
295 # Implementation taken from http://hetland.org
296 def levenshtein( a, b ):
297     """Calculates the Levenshtein distance between a and b."""
298     n, m = len( a ), len( b )
299     if n > m:
300         # Make sure n <= m, to use O(min(n,m)) space
301         a, b = b, a
302         n, m = m, n
303
304     current = range( n + 1 )
305     for i in range( 1, m + 1 ):
306         previous, current = current, [i] + [0] * n
307         for j in range( 1, n + 1 ):
308             add, delete = previous[j] + 1, current[j - 1] + 1
309             change = previous[j - 1]
310             if a[j - 1] != b[i - 1]:
311                 change = change + 1
312             current[j] = min( add, delete, change )
313
314     return current[n]
315
316 def get_packaging_files( package_path ):
317     res = []
318     for tmp_res in os.listdir( package_path ):
319         if tmp_res.endswith( ".spec" ) and os.path.isfile( package_path + "/" + tmp_res ):
320             res.append( tmp_res )
321     return res
322
323 def findBestSpecFile( package_path, package_name ):
324     """
325     Find the name of the spec file which matches best with `package_name`
326     """
327
328     package_spec_dir = package_path
329     package_spec_dir = os.path.expanduser( package_spec_dir )
330     package_spec_dir = os.path.expandvars( package_spec_dir )
331
332     specFileList = get_packaging_files( package_path )
333
334     specFile = None
335     if len( specFileList ) < 1:
336         # No spec file in list
337         specFile = None
338     elif len( specFileList ) == 1:
339         # Only one spec file
340         specFile = specFileList[0]
341     else:
342         sameStart = []
343         for spec in specFileList:
344             if str( spec[:-5] ) == str( package_name ):
345                 # This spec file has the same name as the package
346                 specFile = spec
347                 break
348             elif spec.startswith( package_name ):
349                 # This spec file has a name which looks like the package
350                 sameStart.append( spec )
351
352         if specFile is None:
353             if len( sameStart ) > 0:
354                 # Sort the list of 'same start' by the Levenshtein distance
355                 sameStart.sort( key = lambda x: levenshtein( x, package_name ) )
356                 specFile = sameStart[0]
357             else:
358                 # No spec file starts with the name of the package,
359                 # sort the whole spec file list by the Levenshtein distance
360                 specFileList.sort( key = lambda x: levenshtein( x, package_name ) )
361                 specFile = specFileList[0]
362
363     if specFile is None:
364         msg = "Found no spec file matching package name '%s'" % package_name
365         print msg
366         return -1
367
368     spec_full_path = os.path.join( package_spec_dir, specFile )
369     return  spec_full_path
370
371 def findSpecPatchFiles( patch_dir_path, package_name_list ):
372     """
373     Find the name of the patch for the spec file which matches best with `package_name`
374     """
375     patch_list = []
376
377     patch_dir_path = os.path.expanduser( patch_dir_path )
378     patch_dir_path = os.path.expandvars( patch_dir_path )
379     if package_name_list is not None:
380         for patch_name in set( package_name_list ):
381             for patch_extend in ["", "-yocto"]:
382                 patch_file = patch_name + patch_extend + ".spec.patch"
383                 patch_path = os.path.join( patch_dir_path, patch_file )
384                 if os.path.isfile( patch_path ):
385                     patch_list.append( patch_path )
386
387     return patch_list
388
389
390
391 class SubprocessCrt( object ):
392     '''
393     usefull class to control subprocess
394     '''
395     def __init__( self ):
396         '''
397         Initialize subprocess.
398         '''
399         self.output_res = ""
400         self.__idle_time = 0
401
402     def get_last_res( self ):
403         '''
404         return the last subprocess output.
405         '''
406         return self.output_res
407
408     def __read_subprocess_output( self, outputs, f_stdout, f_stderr ):
409         '''
410         read the stdout, stderr of the subprocess
411         '''
412         timed_out = True
413         select_timeout = 60
414         for file_d in select.select( [f_stdout, f_stderr], [], [], select_timeout )[0]:
415             timed_out = False
416             output = file_d.read()
417             if f_stdout == file_d:
418                 self.output_res += output
419             else:
420                 if DEBUG_RUN and ( len( output ) > 0 ):
421                     print "ERROR ****", output, len( output )
422
423             for line in output.split( "\n" ):
424                 if not line == b"" or not output.endswith( "\n" ):
425                     outputs[file_d]["EOF"] = False
426
427                 if line == b"" and not output.endswith( "\n" ):
428                     outputs[file_d]["EOF"] = True
429                 elif line != "" :
430                     res_clean = line.decode( "utf8", "replace" ).rstrip()
431                     if DEBUG_RUN:
432                         print res_clean
433
434         if timed_out:
435             self.__idle_time += select_timeout
436         else:
437             self.__idle_time = 0
438
439
440
441     def exec_subprocess( self, command ):
442         '''
443         Execute the "command" in a sub process,
444         the "command" must be a valid bash command.
445         _args and _kwargs are for compatibility.
446         '''
447
448         self.output_res = ""
449
450         # need Python 2.7.3 to do shlex.split(command)
451         splitted_command = shlex.split( str( command ) )
452         a_process = subprocess.Popen( splitted_command,
453                              stdout = subprocess.PIPE,
454                              stderr = subprocess.PIPE )
455         f_stdout = a_process.stdout
456         f_stderr = a_process.stderr
457
458         flags = fcntl.fcntl( f_stdout, fcntl.F_GETFL )
459         if not f_stdout.closed:
460             fcntl.fcntl( f_stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK )
461
462         flags = fcntl.fcntl( f_stderr, fcntl.F_GETFL )
463         if not f_stderr.closed:
464             fcntl.fcntl( f_stderr, fcntl.F_SETFL, flags | os.O_NONBLOCK )
465
466         outputs = {f_stdout: {"EOF": False},
467                    f_stderr: {"EOF": False}}
468
469
470         while ( ( not outputs[f_stdout]["EOF"] and
471                not outputs[f_stderr]["EOF"] ) or
472                ( a_process.poll() == None ) ):
473             try:
474                 self.__read_subprocess_output( outputs, f_stdout, f_stderr )
475             except select.error as error:
476                 # see http://bugs.python.org/issue9867
477                 if error.args[0] == errno.EINTR:
478                     print "Got select.error: %s" % unicode( error )
479                     continue
480                 else:
481                     raise Exception()
482
483         # maybe a_process.wait() is better ?
484         poll_res = a_process.poll()
485         if poll_res != 0:
486             return poll_res
487         return self.output_res
488
489 class RePattern:
490     '''
491     def of usefull re pattern to parse spec file.
492     '''
493     pattern_patch = r'([pP]atch[\d]*)[\s]*:[\s]*.*'
494     patternUrlSourceFile = r'Source[\d]*[\s]*:[\s]*([http,ftp].*/)(.*)'
495     patternUrlPatchFile = r'Patch[\d]*[\s]*:[\s]*([http,ftp].*/)(.*)'
496
497     patternPatch = r'[pP]atch([\d]*)[\s]*:[\s]*(.*)'
498     patternSource = r'Source([\d]*)[\s]*:[\s]*(.*)'
499
500     patternPatchCommand = r'#(patch)([\d]*)(.*)'
501
502     patternDescription = r'^Summary:\s*(.*)'
503     patternUrl = r'^Url:\s*(.*)'
504     patternGroup = r'^Group:\s*(.*)'
505     patternLicense = r'^License:\s*(.*)'
506
507     patternFiles = r'^%files\s*(.*)'
508
509     patternName = r'^Name:\s*(.*)'
510
511     patternPackage = r'^%package\s*(.*)'
512     provides_package = r'^Provides:\s*(.*)'
513
514     buildPkgconfig = r'pkgconfig\((.*)\).*'
515
516     pkgRe = r'([^ \t\n\r\f\v,]+)(?:\s+(<|>|<=|>=|=|==)\s+([^ \t\n\r\f\v,]+))?'
517
518     buildRequiresPackage = r'^BuildRequires:\s*(.*)'
519     requiresPackage = r'^Requires(?:\(\w+\))?:\s*(.*)'
520
521     paternDevel = "(.*)-devel"
522
523     pkgconfig_name = "/usr/lib/pkgconfig/([^*]*).pc"
524
525     def __init__( self ):
526         '''
527         init RePattern
528         '''
529
530 def get_macro_directory_path( current_cpu ):
531     '''
532     return all the valid macro directory.
533     '''
534     macro_paths = ""
535     for macro_dir in ["lib/*",
536                 "lib/fileattrs/*",
537                 "lib/platform/%s-linux/macros" % current_cpu,
538                 "lib/tizen/*",
539                 "etc/*",
540                 "user/.rpmmacros",
541                 "yocto/*"]:
542         macro_paths += os.path.join( "/usr/share/spec2yocto/macro", macro_dir ) + " "
543     return macro_paths
544
545 class SpecParser:
546     '''
547     spec file parser
548     '''
549     mPkgConfigDico = {}
550     msubprocess = SubprocessCrt()
551     def __init__( self, package_spec_path, package_pn = None ):
552         '''
553         init the SpecParser
554         '''
555         self.__introduction_section = "introduction_section"
556         self.__package = "%package"
557         self.__description = "%description"
558         self.__prep_flag = "%prep"
559         self.__build_flag = "%build"
560         self.__install_flag = "%install"
561         self.__clean_flag = "%clean"
562         self.__files_flag = "%files"
563         self.__check_flag = "%check"
564         #pkg_preinst, pkg_postinst, pkg_prerm, and pkg_postrm
565         self.__post_flag = "%post"
566         self.__preun_flag = "%preun"
567         self.__postun_flag = "%postun"
568         self.__pre_flag = "%pre"
569
570         self.__verifyscript_flag = "%verifyscript"
571         self.__changelog_flag = "%changelog"
572         self.__list_section = [self.__package,
573                              self.__description,
574                              self.__prep_flag,
575                              self.__build_flag,
576                              self.__install_flag,
577                              self.__clean_flag,
578                              self.__files_flag,
579                              self.__check_flag,
580                              self.__post_flag,
581                              self.__preun_flag,
582                              self.__postun_flag,
583                              self.__pre_flag,
584                              self.__verifyscript_flag,
585                              self.__changelog_flag]
586
587         self.__package_spec_path = package_spec_path
588         self.__package_pn = package_pn
589
590         self.__parsed_spec_file = None
591         self.__order_list = []
592         self.__spect_dico = {}
593         self.__patchs = []
594
595         self.__order_raw_list = []
596         self.__raw_spect_dico = {}
597
598         self.__cpu = SPEC2YOCTO_CONFIG.get_target_cpu()
599         self.__cpu_native = platform.machine()
600
601         self.__convert_spec_file()
602         self.__parse_parsed_spec_file()
603         self.__base_name = self.get_name()
604
605         self.__pkg_config = []
606
607     def __find_patch( self ):
608         '''
609         find the patchs of the spec file.
610         '''
611         self.__patchs = []
612         with open( self.__package_spec_path ) as file_d:
613             spec_file = file_d.read()
614             res_tmp = re.findall( RePattern.pattern_patch, spec_file )
615             for a_res in res_tmp:
616                 self.__patchs.append( a_res.replace( "Patch", "patch" ) )
617
618     def __is_native_build( self ):
619         '''
620         return True if the package is native.
621         '''
622         res_1 = ( self.__package_pn is not None )
623         if not res_1:
624             return res_1
625
626         res_2 = self.__package_pn.endswith( "-native" )
627
628         return  res_2
629
630     def init_rpmspec_command( self ):
631         '''
632         init rpmspec_command to parse spec file.
633         '''
634         rpmspec_command = "rpmspec "
635
636         if self.__is_native_build():
637             current_cpu = self.__cpu_native
638         else:
639             current_cpu = self.__cpu
640
641         rpmspec_command += " --macros=\"%s\" " % get_macro_directory_path( current_cpu )
642
643         rpmspec_command += " --define='buildroot ${D}' "
644         rpmspec_command += " --define='optflags \\$CFLAGS' "
645         if self.__is_native_build():
646             # Not the better way to do this
647             rpmspec_command += " --define='basearch i386' "
648             # I guess other tool must be set for native build.
649             rpmspec_command += " --define='__cc gcc' "
650             # the default value of the macro is %{nil}
651             base_prefix = os.getenv( "base_prefix" )
652             if ( base_prefix != "" ) and ( base_prefix is not None ):
653                 rpmspec_command += " --define='_buildPrefix %s' " % base_prefix
654
655             rpmspec_command += " --define='%find_lang echo no find_lang for package native'"
656
657         rpmspec_command += " --define='setup #setup' "
658         rpmspec_command += " --define='setup0 #setup0' "
659
660         package_dir = os.path.dirname( self.__package_spec_path )
661
662         rpmspec_command += " --define='SOURCES ${S}/packaging/' "
663         rpmspec_command += " --define='_sourcedir ${S}/packaging/' "
664
665         rpmspec_command += " --define='BUILD_BASENAME %{basename}' "
666         rpmspec_command += " --define='find_lang  #find_lang' "
667         rpmspec_command += " --define='lang_package #lang_package' "
668         rpmspec_command += " --define='with_wayland  1' "
669
670         # need to be change.
671         package_name = os.path.basename( self.__package_spec_path )[:-5]
672
673         if package_name in SPEC2YOCTO_CONFIG.get_bb_autoreconf_blacklist() :
674             oe_runconf2 = '''oe_runconf2'''
675             rpmspec_command += " --define='%%_configure %s'" % oe_runconf2
676
677         return rpmspec_command
678
679
680     def __convert_spec_file( self ):
681         '''
682         init convert spec to expand spec file.
683         '''
684         tmp_package_spec_path = self.__package_spec_path
685
686         # we can't use python rpm API to parse the spec file so we need to exec rpmspec\
687         # in a subprocess and parse the result.
688         rpmspec_command = self.init_rpmspec_command()
689
690         # it's import to remove all "Source" url because if rpm dan't find the source,\
691         # it try to downloads the file from the url.
692         with open( tmp_package_spec_path, 'r' ) as current_spec_file:
693             current_spec_string = current_spec_file.read()
694             res_url_source_files = re.findall( RePattern.patternUrlSourceFile, current_spec_string )
695
696         if len( res_url_source_files ) > 0:
697             for res_url in res_url_source_files:
698                 long_url = res_url[0] + res_url[1]
699                 short_url = res_url[1]
700                 current_spec_string = current_spec_string.replace( long_url, short_url )
701
702             with tempfile.NamedTemporaryFile( mode = 'w',
703                             suffix = '.tmp',
704                             prefix = os.path.basename( tmp_package_spec_path ) + ".",
705                             dir = os.path.dirname( tmp_package_spec_path ),
706                             delete = False ) as  tmp_spec_file:
707                 tmp_spec_file.write( current_spec_string )
708                 tmp_package_spec_path = tmp_spec_file.name
709
710         # same case as "Source"
711         with open( tmp_package_spec_path, 'r' ) as current_spec_file:
712             current_spec_string = current_spec_file.read()
713             res_url_patch_file = re.findall( RePattern.patternUrlPatchFile, current_spec_string )
714
715         if len( res_url_patch_file ) > 0:
716             for res_url in res_url_patch_file:
717                 long_url = res_url[0] + res_url[1]
718                 short_url = res_url[1]
719                 current_spec_string = current_spec_string.replace( long_url, short_url )
720             if ( tmp_package_spec_path != self.__package_spec_path ) \
721                and os.path.isfile( tmp_package_spec_path ) \
722                and not DEBUG_RUN:
723                 os.remove( tmp_package_spec_path )
724             with tempfile.NamedTemporaryFile( mode = 'w',
725                             suffix = '.tmp',
726                             prefix = os.path.basename( tmp_package_spec_path ) + ".",
727                             dir = os.path.dirname( tmp_package_spec_path ),
728                             delete = False ) as  tmp_spec_file:
729                 tmp_spec_file.write( current_spec_string )
730                 tmp_package_spec_path = tmp_spec_file.name
731
732         self.__find_patch()
733         for a_patch in self.__patchs:
734             if a_patch == "patch0":
735                 rpmspec_command += " --define='%patch #patch' "
736
737             rpmspec_command += " --define='%s #%s' " % ( a_patch, a_patch )
738
739         rpmspec_command += " --define='debug_package %{nil}'"
740
741         rpmspec_command += " --parse %s " % tmp_package_spec_path
742         if DEBUG_RUN:
743             print "rpmspec_command :", rpmspec_command
744
745
746         self.__parsed_spec_file = SpecParser.msubprocess.exec_subprocess( rpmspec_command )
747         if ( tmp_package_spec_path != self.__package_spec_path ) \
748                and os.path.isfile( tmp_package_spec_path ) \
749                and not DEBUG_RUN:
750             os.remove( tmp_package_spec_path )
751
752         if self.__parsed_spec_file == 1:
753             print >> sys.stderr, ""
754             print >> sys.stderr, "ERROR CMD: %s" % rpmspec_command
755             print >> sys.stderr, "parse error for spec file %s" % ( tmp_package_spec_path )
756             self.__parsed_spec_file = None
757             return 1
758
759         if DEBUG_RUN:
760             if not os.path.isdir( "/tmp/parsed_spec" ):
761                 os.makedirs( "/tmp/parsed_spec" )
762
763             if self.__package_pn is None:
764                 tmp_path = os.path.basename( self.__package_spec_path )
765                 package_parsed_spec_path = os.path.join( "/tmp/parsed_spec", tmp_path )
766             else:
767                 tmp_path = "%s.spec" % self.__package_pn
768                 package_parsed_spec_path = os.path.join( "/tmp/parsed_spec", tmp_path )
769
770             with open( package_parsed_spec_path, "w" ) as file_d:
771                 file_d.write( self.__parsed_spec_file )
772
773
774     def __test_section( self, line ):
775         '''
776         test if the line is the start of a new section.
777         '''
778         for sect in self.__list_section:
779             if line.startswith( sect ):
780                 return True
781         return False
782
783     def __parse_parsed_spec_file( self ):
784         '''
785         parse a spec file by section after rpmspec.
786         '''
787         # ordered dico is not provide yet...
788         self.__order_list = []
789         self.__spect_dico = {}
790
791         current_section = self.__introduction_section
792         self.__spect_dico[current_section] = []
793         self.__order_list.append( current_section )
794
795         if self.__parsed_spec_file is None:
796             return 1
797
798         for line in self.__parsed_spec_file.split( "\n" ):
799
800             if self.__test_section( line ) :
801                 if line in self.__spect_dico.keys():
802                     print "line %s" % line
803                     print "--------------------------------------"
804                     print "parsedSpecFile: %s" % self.__package_spec_path
805                     print "--------------------------------------"
806                     error_msg = "ERROR for the spec file \"%s\" this section \"%s\" is not unique."
807                     print  error_msg % ( self.__parsed_spec_file, line )
808                     # raise Exception()
809
810                 current_section = line
811                 self.__spect_dico[current_section] = []
812                 self.__order_list.append( current_section )
813
814             self.__spect_dico[current_section].append( line )
815
816     def parse_raw_spec_file( self ):
817         '''
818         parse a spec file by section before rpmspec.
819         '''
820         # need to be rewrite
821         # ordered dico is not provide yet...
822
823         self.__order_raw_list = []
824         self.__raw_spect_dico = {}
825
826         current_section = self.__introduction_section
827         self.__raw_spect_dico[current_section] = []
828         self.__order_raw_list.append( current_section )
829
830         with open( self.__package_spec_path, "r" ) as file_d:
831             parsed_raw_spec_file = file_d.read()
832
833         for line in parsed_raw_spec_file.split( "\n" ):
834             if self.__test_section( line ) :
835                 if line in self.__raw_spect_dico.keys():
836                     print "line %s" % line
837                     print "--------------------------------------"
838                     print "parsedSpecFile: %s" % self.__package_spec_path
839                     print "--------------------------------------"
840                     error_msg = "ERROR for the spec file \"%s\" this section \"%s\" is not unique."
841                     print  error_msg % ( self.__parsed_spec_file, line )
842                     raise Exception()
843
844                 current_section = line
845                 self.__raw_spect_dico[current_section] = []
846                 self.__order_raw_list.append( current_section )
847
848             self.__raw_spect_dico[current_section].append( line )
849
850
851     def get_prep_section( self ):
852         '''
853         return the prep section of the spec file.
854         '''
855         res_prep_section = "cd ${S}\n"
856
857         pattern_patch_dico = {}
858         pattern_source_dico = {}
859
860         for line in self.__spect_dico[self.__introduction_section][1:]:
861             for patch_id, files_name in re.findall( RePattern.patternPatch, line ):
862                 if patch_id == "":
863                     patch_id = "0"
864                 pattern_patch_dico[patch_id] = files_name
865
866             for source_id, files_name in re.findall( RePattern.patternSource, line ):
867                 if source_id == "":
868                     source_id = "0"
869                 pattern_source_dico[source_id] = files_name
870
871         for line in self.__spect_dico[self.__prep_flag][1:]:
872             if line.startswith( "#setup" ):
873                 splited_line = line.split()
874                 for i in range( len( splited_line ) ):
875                     if splited_line[i].startswith( "-a" ):
876                         if len( splited_line[i] ) > len( "-a" ):
877                             setup_id = splited_line[i].replace( "-a", "" )
878                         else:
879                             setup_id = splited_line[i + 1]
880                         res_prep_section += "#extracte source %s \n" % setup_id
881                         res_prep_section += "pushd ${S}\n"
882                         source = os.path.basename( pattern_source_dico[setup_id] )
883                         # not a good way to do this
884                         if source.endswith( "rpmlintrc" ):
885                             res_prep_section += "cp ${S}/packaging/%s .\n" % source
886                         else:
887                             file_name = os.path.basename( pattern_source_dico[setup_id] )
888                             res_prep_section += "unp ${S}/packaging/%s \n" % file_name
889                         res_prep_section += "popd \n"
890
891                     elif splited_line[i].startswith( "-b" ):
892                         if len( splited_line[i] ) > len( "-b" ):
893                             setup_id = splited_line[i].replace( "-b", "" )
894                         else:
895                             setup_id = splited_line[i + 1]
896
897                         res_prep_section += "#extracte source %s \n" % ( setup_id )
898                         res_prep_section += "pushd ${S}/../\n"
899                         source = os.path.basename( pattern_source_dico[setup_id] )
900                         if source.endswith( "rpmlintrc" ):
901                             res_prep_section += "cp ${S}/packaging/%s .\n" % source
902                         else:
903                             res_prep_section += "unp ${S}/packaging/%s \n" % source
904                         res_prep_section += "popd \n"
905
906                 res_prep_section += "chmod -Rf a+rX,u+w,g-w,o-w ${S}\n"
907
908
909             elif line.startswith( "#patch" ):
910                 res_findall = re.findall( RePattern.patternPatchCommand, line )
911                 # should be rewrite
912                 for patch_name, patch_id, EXEC_COMMAND in res_findall:
913                     if patch_id == '':
914                         patch_id = "0"
915
916                     files_name = pattern_patch_dico[patch_id]
917
918                     if "-p" not in EXEC_COMMAND:
919                         EXEC_COMMAND += " -p0"
920
921                     if files_name.endswith( ".bz2" ):
922                         bzcat_cmd = "bzcat ${S}/packaging/%s | patch -s %s --fuzz=2\n"
923                         bzcat_val = ( files_name, EXEC_COMMAND.replace( " -b", " -b --suffix" ) )
924                         res_prep_section += bzcat_cmd % bzcat_val
925                     else:
926                         cat_cmd = "cat ${S}/packaging/%s | patch -s %s --fuzz=2\n"
927                         cat_val = ( files_name, EXEC_COMMAND.replace( " -b", " -b --suffix" ) )
928                         res_prep_section += cat_cmd % cat_val
929
930             res_prep_section += line + "\n"
931         return res_prep_section
932
933     def get_build_section( self ):
934         '''
935         return the build section of the spec file.
936         '''
937         res_build_section = "cd ${S}\n"
938         if self.__build_flag not in self.__spect_dico.keys():
939             return 1
940
941         for line in self.__spect_dico[self.__build_flag][1:]:
942             res_build_section += line + "\n"
943
944         return res_build_section
945
946     def get_raw_build_section( self ):
947         '''
948         return the raw build section of the spec file.
949         '''
950         res_raw_build_section = ""
951         if self.__build_flag not in self.__spect_dico.keys():
952             return ""
953         for line in self.__raw_spect_dico[self.__build_flag][1:]:
954             res_raw_build_section += line + "\n"
955         return res_raw_build_section
956
957     def get_clean_raw( self ):
958         '''
959         clean the raw spec file to generate spec file for yocto packaging.
960         '''
961         res_clean_raw = ""
962         for sect in self.__order_raw_list:
963             if sect == self.__introduction_section:
964                 for line in self.__raw_spect_dico[sect]:
965                     if line.startswith("Version:"):
966                         res_clean_raw += "Version:        git\n"
967
968                     else:
969                         have_findall_source = len( re.findall( RePattern.patternSource , line ) ) > 0
970                         have_findall_patch = len( re.findall( RePattern.patternPatch, line ) ) > 0
971                         if not( have_findall_source or have_findall_patch ):
972                             res_clean_raw += line + "\n"
973
974
975             elif sect == self.__prep_flag:
976                 res_clean_raw += line + "%prep\n"
977                 res_clean_raw += line + "#FAKE\n"
978             elif sect == self.__build_flag:
979                 res_clean_raw += line + "%build\n"
980                 res_clean_raw += line + "#FAKE\n"
981             elif sect == self.__install_flag:
982                 res_clean_raw += line + "%install\n"
983                 res_clean_raw += line + "#FAKE\n"
984             elif sect == self.__check_flag:
985                 pass
986             elif sect == self.__clean_flag:
987                 pass
988             elif sect == self.__changelog_flag:
989                 pass
990             elif sect.startswith( "%files" ):
991                 for line in self.__raw_spect_dico[sect]:
992                     if line.startswith( '%manifest ' ):
993                         res_clean_raw += line[len('%manifest '):] + "\n"
994                     elif line.startswith( '%doc ' ):
995                         pass
996                     elif line.startswith( '%ghost ' ):
997                         pass
998                     elif line.startswith( '%exclude ' ):
999                         pass
1000                     elif line.startswith( '%license' ):
1001                         pass
1002
1003                     else:
1004                         res_clean_raw += line + "\n"
1005
1006             else:
1007                 for line in self.__raw_spect_dico[sect]:
1008                     res_clean_raw += line + "\n"
1009
1010         clean_raw_command = self.init_rpmspec_command()
1011
1012         tmp_package_spec_path = self.__package_spec_path
1013         with tempfile.NamedTemporaryFile( mode = 'w',
1014                 suffix = '.tmp',
1015                 prefix = os.path.basename( tmp_package_spec_path ) + ".",
1016                 dir = os.path.dirname( tmp_package_spec_path ),
1017                 delete = False ) as  tmp_spec_file:
1018             tmp_spec_file.write( res_clean_raw )
1019             tmp_package_spec_path = tmp_spec_file.name
1020
1021         clean_raw_command += " --define='debug_package %{nil}'"
1022         clean_raw_command += " --define='docs_package %{nil}'"
1023
1024         clean_raw_command += " --parse %s " % tmp_package_spec_path
1025         if DEBUG_RUN:
1026             print "clean_raw_command :", clean_raw_command
1027
1028         parsed_spec_file = SpecParser.msubprocess.exec_subprocess( clean_raw_command )
1029
1030         if os.path.isfile( tmp_package_spec_path ) and not DEBUG_RUN:
1031             os.remove( tmp_package_spec_path )
1032
1033         if parsed_spec_file == 1:
1034             print >> sys.stderr, "parse error for spec file %s" % ( tmp_package_spec_path )
1035             parsed_spec_file = None
1036             return 1
1037
1038         fake_dbg = '''
1039 %%package -n %s-dbg
1040 Summary: #FAKE - Debugging files
1041 Group: devel
1042
1043 %%description -n %s-dbg
1044 #FAKE
1045
1046
1047 %%files -n %s-dbg
1048 %%defattr(-,-,-,-)
1049 ''' % ( self.__base_name, self.__base_name, self.__base_name )
1050         work_dir = os.getenv( "WORKDIR" )
1051
1052         if work_dir is None:
1053             return parsed_spec_file
1054
1055         base_root = os.path.join( work_dir, "package" )
1056         for root, dirs, files in os.walk( base_root ):
1057             if root.endswith( ".debug" ):
1058                 if DEBUG_RUN:
1059                     print "find directory %s " % dirs
1060                 for a_file in files:
1061                     fake_dbg += os.path.join( root, a_file ).replace( base_root, "" ) + "\n"
1062         #Test don't add dbg files
1063         #return parsed_spec_file + fake_dbg
1064
1065         return parsed_spec_file
1066
1067     def get_install_section( self ):
1068         '''
1069         return the install section.
1070         '''
1071         res_install_section = "cd ${S}\n"
1072
1073         for line in self.__spect_dico[self.__install_flag][1:]:
1074             res_install_section += line + "\n"
1075         return res_install_section
1076
1077     def get_description( self ):
1078         '''
1079         return the description of the spec file.
1080         '''
1081         for line in self.__spect_dico[self.__introduction_section] :
1082             description = re.findall( RePattern.patternDescription, line )
1083             if len( description ) > 0:
1084                 return description[0]
1085         return ""
1086
1087     def get_homepage( self ):
1088         '''
1089         return the homepage of the spec file project.
1090         '''
1091         for line in self.__spect_dico[self.__introduction_section] :
1092             description = re.findall( RePattern.patternUrl, line )
1093             if len( description ) > 0:
1094                 return description[0]
1095         return ""
1096
1097     def get_section( self ):
1098         '''
1099         return the section of the spec file project.
1100         '''
1101         for line in self.__spect_dico[self.__introduction_section] :
1102             description = re.findall( RePattern.patternGroup, line )
1103             if len( description ) > 0:
1104                 return description[0]
1105         return "System/Base"
1106
1107     def get_license( self ):
1108         '''
1109         return the licence of the package.
1110         '''
1111         for line in self.__spect_dico[self.__introduction_section] :
1112             description = re.findall( RePattern.patternLicense, line )
1113             if len( description ) > 0:
1114                 res_license = description[0]
1115                 if ";" in res_license:
1116                     res_license = res_license.replace( ";", "" )
1117
1118                 return res_license
1119         return ""
1120
1121     def get_section_key(self, __flag):
1122         '''
1123         Return the list of "__flag" sections of the spec file.
1124         '''
1125         res_section = []
1126         for section_key in self.__spect_dico.keys():
1127             if section_key.startswith(__flag):
1128                 res_section.append(section_key)
1129
1130         return res_section
1131
1132     def get_script_section_key_pre(self):
1133         '''
1134         Return the list of pre script section of the spec file.
1135         get_section_key() can't be used in this case since it will also
1136         return the %preun and %prep results.
1137         '''
1138         res_script_section = []
1139         for section_key in self.__spect_dico.keys():
1140             if section_key.startswith("%pre") and \
1141                     not section_key.startswith("%preun") and \
1142                     not section_key.startswith("%prep"):
1143                 res_script_section.append(section_key)
1144
1145         return res_script_section
1146
1147     def get_script_section_key_post(self):
1148         '''
1149         Return the list of post script section of the spec file.
1150         get_section_key() can't be used in this case since it will also
1151         return the %postun results.
1152         '''
1153         res_script_section = []
1154         for section_key in self.__spect_dico.keys():
1155             if section_key.startswith("%post") and not section_key.startswith("%postun"):
1156                 res_script_section.append(section_key)
1157
1158         return res_script_section
1159
1160     def get_files_list_from_section( self, package_section_name ):
1161         '''
1162         return a list of file
1163         '''
1164         res_list = []
1165         config_list=[]
1166         manifest_list=[]
1167         dir_list=[]
1168         
1169         for line in self.__spect_dico[package_section_name][1:]:
1170             if not line.startswith( "%" ) and not line == "":
1171                 line = line.replace( "//", "/" )
1172                 res_list.append( line )
1173             elif line.startswith( "%attr(" ):
1174                 line = line.replace( "//", "/" )
1175                 pkg_f_clean=line.split(")")
1176                 pkg_f=pkg_f_clean[-1].strip()
1177                 res_list.append( pkg_f )
1178             elif line.startswith( "%doc " ):
1179                 line = line.replace( "//", "/" )
1180                 res_list.append( line.replace( "%doc ", "" ) )
1181             elif line.startswith( "%dir " ):
1182                 line = line.replace( "//", "/" )
1183                 
1184                 file_name = line.replace( "%dir ", "" )
1185                 dir_list.append( file_name )
1186                 
1187                 res_list.append( file_name )
1188             elif line.startswith( "%config " ):
1189                 line = line.replace( "//", "/" )
1190                 
1191                 file_name = line.replace( "%config ", "" )
1192                 config_list.append( file_name )
1193                 
1194                 res_list.append( file_name )
1195             elif line.startswith( "%manifest " ):
1196                 line = line.replace( "//", "/" )
1197                 
1198                 file_name = line.replace( "%manifest ", "" )
1199                 manifest_list.append( file_name )
1200                 
1201                 #res_list.append( file_name )
1202                 
1203             elif line.startswith( "%config(noreplace) " ):
1204                 line = line.replace( "//", "/" )
1205                 res_list.append( line.replace( "%config(noreplace) ", "" ) )
1206             elif line.startswith( "%config(" ):
1207                 line = line.replace( "//", "/" )
1208                 pkg_f_clean=line.split(")")
1209                 pkg_f=pkg_f_clean[-1].strip()
1210                 res_list.append( pkg_f )
1211             else:
1212                 pass
1213
1214         #return res_list,config_list
1215         return res_list,config_list, manifest_list, dir_list
1216
1217     def get_script_from_section(self, __flag):
1218         '''
1219         Return the pre/post script section of the spec file.
1220         '''
1221         res_script_section = ""
1222         if __flag in self.__spect_dico.keys():
1223             for line in self.__spect_dico[__flag][1:]:
1224                 res_script_section += line + "\n"
1225
1226         return res_script_section
1227
1228     def get_files_packages( self ):
1229         '''
1230         return a dictinaire with package for key and list of files fo value.
1231         '''
1232         res_dico = {}
1233
1234         for package_section_name in self.get_section_key("%file"):
1235             tmp_package_name = package_section_name
1236             # Need to get info of the first line.
1237             if "-f " in tmp_package_name:
1238                 tmp_split = tmp_package_name.split( "-f " )
1239                 tmp_package_name = tmp_split[0]
1240
1241             package = re.findall( RePattern.patternFiles, tmp_package_name )
1242             if len( package ) > 0:
1243                 if "-n " in package[0]:
1244                     package_name = package[0].replace( "-n ", "" )
1245                 else:
1246                     package_name = self.__base_name
1247                     pkg_ext = package[0].replace( " ", "" )
1248                     if len( pkg_ext ) > 0:
1249                         package_name += "-" + pkg_ext
1250             else:
1251                 package_name = self.__base_name
1252
1253             package_name = package_name.replace( " ", "" )
1254             res_list,config_list, manifest_list, dir_list = self.get_files_list_from_section( package_section_name )
1255             res_dico[ package_name ] = res_list,config_list, manifest_list, dir_list
1256
1257         #db_src=self.__base_name+"-debugsource"
1258         #if db_src not in res_dico:
1259         #    res_dico[db_src] = []
1260
1261         #dbinfo=self.__base_name+"-debug"
1262         #if dbinfo not in res_dico:
1263         #    res_dico[dbinfo] = []
1264
1265         return res_dico
1266
1267     def get_name( self ):
1268         '''
1269         return the name of the package
1270         '''
1271         for line in self.__spect_dico[self.__introduction_section]:
1272             description = re.findall( RePattern.patternName, line )
1273             if len( description ) > 0:
1274                 return description[0]
1275         return ""
1276
1277     def get_provides( self ):
1278         '''
1279         return all provide service by each package of the spec file.
1280         '''
1281         provide_res = {}
1282         provide_res[self.__base_name] = []
1283         provide_res[self.__base_name].append( [self.__base_name] )
1284
1285         for k in self.__spect_dico.keys():
1286             package = re.findall( RePattern.patternPackage, k )
1287             if len( package ) > 0:
1288                 package_name = self.__clean_package_name( package[0] )
1289                 provide_res[ package_name ] = []
1290                 provide_res[ package_name ].append( [package_name] )
1291
1292             if len( package ) > 0 or ( k == self.__introduction_section ):
1293                 for line in self.__spect_dico[k]:
1294                     provides = re.findall( RePattern.provides_package, line )
1295                     for provides_line in provides:
1296                         for tmp_clean in self.__clean_package_line( provides_line ):
1297                             if k == self.__introduction_section:
1298                                 provide_res[self.__base_name].append( tmp_clean )
1299                             else:
1300                                 provide_res[package_name].append( tmp_clean )
1301         return provide_res
1302
1303     def __clean_package_name( self, package_name ):
1304         '''
1305         return the package name from spec declaration.
1306         '''
1307         # re should be better.
1308         if "-n " in package_name:
1309             package_name = package_name.replace( "-n ", "" ).replace( " ", "" )
1310         else:
1311             package_name = self.__base_name + "-" + package_name
1312
1313         return package_name
1314
1315     def get_rdepends( self ):
1316         '''
1317         return all require service by each package of the spec file.
1318         '''
1319         rdepends_res = {}
1320
1321         for k in  self.__spect_dico.keys():
1322             package = re.findall( RePattern.patternPackage, k )
1323
1324             if len( package ) > 0:
1325                 package_name = self.__clean_package_name( package[0] )
1326             else:
1327                 package_name = self.__base_name
1328
1329             if len( package ) > 0 or ( k == self.__introduction_section ):
1330                 requires_list = self.get_requires( self.__spect_dico[k] )
1331                 rdepends_res[package_name] = requires_list
1332         return rdepends_res
1333
1334
1335     def get_depends( self ):
1336         '''
1337         return all build require service by each package of the spec file.
1338         '''
1339         depends_res = {}
1340
1341         for k in self.__spect_dico.keys():
1342             package = re.findall( RePattern.patternPackage, k )
1343             if len( package ) > 0:
1344                 package_name = self.__clean_package_name( package[0] )
1345
1346             if len( package ) > 0 or ( k == self.__introduction_section ):
1347                 build_requires_list = self.get_build_requires( self.__spect_dico[k] )
1348                 if ( k == self.__introduction_section ):
1349                     depends_res[self.__base_name] = build_requires_list
1350                 else:
1351                     depends_res[package_name] = build_requires_list
1352
1353
1354         return depends_res
1355
1356     def __clean_package_line( self, package_line ):
1357         '''
1358         return package list from package declaration in spec file.
1359         '''
1360         res_first = re.findall( RePattern.pkgRe, package_line )
1361         if len( res_first ) == 0:
1362             print "__clean_package_line faild for %s" % self.__package_spec_path
1363             raise Exception()
1364         # should be rewrite cleaner.
1365         res_final = []
1366         for init_res in res_first:
1367             init_res = list( init_res )
1368             init_res[0] = init_res[0].replace( ",", "" )
1369             res_final.append( init_res )
1370         return res_final
1371
1372     def get_build_requires( self, lines ):
1373         '''
1374         return the line of every build requires.
1375         '''
1376         package_replacement = SPEC2YOCTO_CONFIG.get_substitute()
1377         build_requires_res = []
1378         for line in lines:
1379             build_requires = re.findall( RePattern.buildRequiresPackage, line )
1380             for tmp_res in build_requires:
1381                 for tmp_clean in self.__clean_package_line( tmp_res ):
1382                     if len( tmp_clean ) >= 1:
1383                         if tmp_clean[0] in package_replacement.keys():
1384                             tmp_clean[0] = package_replacement[tmp_clean[0]]
1385                         build_requires_res.append( tmp_clean )
1386         return build_requires_res
1387
1388     def get_requires( self, lines ):
1389         '''
1390         return the line of every requires.
1391         '''
1392         package_replacement = SPEC2YOCTO_CONFIG.get_substitute()
1393
1394         requires_res = []
1395         for line in lines:
1396             build_requires = re.findall( RePattern.requiresPackage, line )
1397             for tmp_res in build_requires:
1398                 for tmp_clean in self.__clean_package_line( tmp_res ):
1399                     if len( tmp_clean ) >= 1:
1400                         if tmp_clean[0] in package_replacement.keys():
1401                             tmp_clean[0] = package_replacement[tmp_clean[0]]
1402                         requires_res.append( tmp_clean )
1403         return requires_res
1404
1405 class MetaSpec:
1406     '''
1407     meta spec file for generate yocto bb.
1408     '''
1409     mProvidesDico = {}
1410     mExtraRProvidesDico = {}
1411
1412     mCrossPackageBlacklist = []
1413     mInitialPackageBlacklist = []
1414     mNativePackageBlacklist = []
1415     mOePackageBlacklist = []
1416
1417     def __init__( self,
1418                 package_recipes_dir,
1419                 package_name,
1420                 package_spec_path,
1421                 package_git_srv_src,
1422                 package_git_srv_path,
1423                 package_git_tag ):
1424         '''
1425         init the MetaSpec class
1426         '''
1427         self.__package_recipes_dir = package_recipes_dir.replace( "_", "-" )
1428         self.__package_name = package_name.replace( "_", "-" )
1429
1430
1431         self.__package_git_srv_src = package_git_srv_src
1432         self.__package_git_srv_path = package_git_srv_path
1433
1434         self.__package_spec_path = package_spec_path
1435         self.__git_tag = package_git_tag
1436
1437         self.__spec_parser = SpecParser( self.__package_spec_path )
1438         self.__package_spec_name = self.__spec_parser.get_name()
1439
1440         self.__packages_dico = self.__spec_parser.get_files_packages()
1441         self.__provides_dico = self.__spec_parser.get_provides()
1442
1443         self.setm_provided_dico()
1444         self.__rdepends_dico = self.__spec_parser.get_rdepends()
1445
1446         self.__base_file = self.__package_name + ".inc"
1447         #self.__base_depends_file = self.__package_name + "-depends.inc"
1448         #self.__base_rdepends_file = self.__package_name + "-rdepends.inc"
1449         #self.__base_provides_file = self.__package_name + "-rprovides.inc"
1450
1451         self.__extra_conf_file = self.__package_name + "-extraconf.inc"
1452         #self.__extra_native_conf_file = self.__package_name + "-native-extraconf.inc"
1453         #self.__extra_oe_conf_file = self.__package_name + "-oe-extraconf.inc"
1454
1455         self.__git_native_file = self.__package_name + "-native_git.bb"
1456         self.__git_oe_file = self.__package_name + "_git.bb"
1457
1458         self.__createRecipes()
1459
1460     def setm_provided_dico( self ):
1461         '''
1462         add provides_list for package_name to mProvidesDico
1463         '''
1464         provides_list = []
1465         for k_provide in self.__provides_dico.keys():
1466             for p_provide in self.__provides_dico[k_provide]:
1467                 provides_list.append( p_provide[0] )
1468         for p_provide in self.__packages_dico.keys():
1469             provides_list.extend( self.__packages_dico[p_provide][0] )
1470
1471         for package in self.__packages_dico.keys():
1472             for pkg_file in self.__packages_dico[package][0]:
1473                 pkgconfig_name_res = re.findall( RePattern.pkgconfig_name, pkg_file )
1474                 for tmp_res in pkgconfig_name_res:
1475                     provides_list.append( "pkgconfig(%s)" % tmp_res )
1476
1477         if self.__package_name not in MetaSpec.mProvidesDico.keys():
1478             MetaSpec.mProvidesDico[self.__package_name] = []
1479
1480         MetaSpec.mProvidesDico[self.__package_name].extend( provides_list )
1481
1482     def set_mextra_provided_dico( self ):
1483         '''
1484         add provides_list for package_name to mExtraRProvidesDico
1485         '''
1486         provides_list = []
1487         for k_provide in self.__provides_dico.keys():
1488             for p_provide in self.__provides_dico[k_provide]:
1489                 provides_list.append( p_provide[0] )
1490         for p_provide in self.__packages_dico.keys():
1491             provides_list.extend( self.__packages_dico[p_provide][0] )
1492
1493         MetaSpec.mExtraRProvidesDico[self.__package_name] = provides_list
1494
1495     def __create_base_file( self ):
1496         '''
1497         create the base file of the bb file.
1498         '''
1499         bb_path = os.path.join( self.__package_recipes_dir, self.__base_file )
1500         with open( bb_path, "w" ) as file_d:
1501
1502             _description = self.__spec_parser.get_description()
1503             _homepage = self.__spec_parser.get_homepage()
1504             _section = self.__spec_parser.get_section()
1505             _priority = "10"
1506             _license = self.__spec_parser.get_license()
1507
1508             file_d.write( "DESCRIPTION = \"%s\"\n" % _description )
1509             if len( _homepage ) < 2:
1510                 _homepage = "http://nohomepage.org"
1511             file_d.write( "HOMEPAGE = \"%s\"\n" % _homepage )
1512             file_d.write( "SECTION = \"%s\"\n" % _section )
1513
1514             file_d.write( "LICENSE = \"%s\"\n" % _license )
1515             file_d.write( "\n" )
1516             file_d.write( "SRC_URI = \"\"\n" )
1517             file_d.write( "\n" )
1518             file_d.write( "S = \"${WORKDIR}/git\"\n" )
1519             file_d.write( "\n" )
1520
1521             file_d.write( "inherit autotools-brokensep\n" )
1522             file_d.write( "\n" )
1523             file_d.write( "BBCLASSEXTEND = \"\"\n"  )
1524
1525             self.__create_provides_file( file_d)
1526             self.__create_rdepends( file_d)
1527             self.__create_depends( file_d)
1528
1529             self.__create_patch( file_d)
1530             self.__create_configure( file_d)
1531             self. __create_compile( file_d)
1532             self.__create_install( file_d)
1533
1534             self.__create_script_file( file_d)
1535
1536             self.__create_files_packaging( file_d )
1537
1538             file_d.write( "require %s\n\n" % self.__extra_conf_file )
1539
1540     def __create_files_packaging(self,file_d):
1541             file_d.write( "PACKAGES = \"${PN}-dbg ${PN}-doc ${PN}-locale\"\n" )
1542             for package in self.__packages_dico.keys():
1543                 pkg_yocto_name=package
1544                 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1545                     pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1546
1547                 if  pkg_yocto_name not in [self.__package_name+"-dbg",
1548                                            self.__package_name+"-doc",
1549                                            self.__package_name+"-locale",
1550                                           ]:
1551                     file_d.write( "PACKAGES += \" %s \"\n" % pkg_yocto_name )
1552
1553             file_d.write( "\n" )
1554
1555             _license = self.__spec_parser.get_license()
1556
1557             for package in self.__packages_dico.keys():
1558                 pkg_yocto_name=package
1559                 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1560                     pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1561
1562                 file_d.write( "%s_files = \"\"\n" % pkg_yocto_name )
1563                 pkg_list, config_list, manifest_list, dir_list  = self.__packages_dico[package]
1564                 for pkg_f in pkg_list:
1565                     pkg_f=pkg_f.strip()
1566
1567                     if  pkg_f.startswith( _license ):
1568                         pass
1569                     else:
1570                         pkg_yocto_name = package.replace("-devel","-dev")
1571                         file_d.write( "%s_files += \"%s\"\n" % ( pkg_yocto_name, pkg_f ) )
1572                         
1573                 pkg_yocto_name_short = pkg_yocto_name.replace( self.__package_name, "${PN}" )  
1574                 
1575                 if len(config_list)>0:
1576                     file_d.write( "CONFFILES_%s = \"\"\n" % ( pkg_yocto_name_short ) )
1577                 for pkg_f in config_list:
1578                     file_d.write( "CONFFILES_%s += \"%s\"\n" % ( pkg_yocto_name_short, pkg_f ) )
1579                 
1580                 if (len(manifest_list) == 1) :
1581                     file_d.write( "MANIFESTFILES_%s = \"%s\"\n" % ( pkg_yocto_name_short, manifest_list[0] ) )
1582                 elif (len(manifest_list) > 1) :
1583                     msg="ERROR Too many manifest for \"%s\" " % self.__package_name
1584                     print >> sys.stderr, colorize( msg, "red" )
1585
1586                 if len(dir_list)>0:
1587                     file_d.write( "DIRFILES_%s = \"\"\n" % ( pkg_yocto_name_short ) )
1588                 for pkg_f in dir_list:
1589                     file_d.write( "DIRFILES_%s += \"%s\"\n" % ( pkg_yocto_name_short, pkg_f ) )
1590                     
1591                 file_d.write( "\n" )
1592
1593             for package in self.__packages_dico.keys():
1594                 p_parse = package.replace( self.__package_name, "${PN}" )
1595                 p_parse = p_parse.replace("-devel","-dev")
1596                 pkg_yocto_name = package.replace("-devel","-dev")
1597                 file_d.write( "FILES_%s = \"${%s_files}\"\n" % ( p_parse, pkg_yocto_name ) )
1598             file_d.write( "\n" )
1599
1600             for package in self.__packages_dico.keys():
1601                 pkg_yocto_name = package.replace("-devel","-dev")
1602                 file_d.write( "PKG_%s= \"%s\"\n" % (pkg_yocto_name,pkg_yocto_name) )
1603             file_d.write( "\n" )
1604
1605     def __create_patch( self ,file_d):
1606         code=self.__spec_parser.get_prep_section()
1607         code=code.replace("\n","\n ")
1608         file_d.write( "do_prep() {\n" )
1609         file_d.write( " %s\n" % code )
1610         file_d.write( "}\n" )
1611         file_d.write( "do_patch_append() {\n" )
1612         file_d.write( "    bb.build.exec_func('do_prep', d)\n" )
1613         file_d.write( "}\n" )
1614         file_d.write( "\n" )
1615
1616     def __create_configure( self ,file_d):
1617         file_d.write( "do_configure() {\n" )
1618         file_d.write( "}\n" )
1619         file_d.write( "\n" )
1620
1621     def __create_compile( self ,file_d):
1622         EXTRA_OECONF = None
1623         code=self.__spec_parser.get_build_section()
1624         code=code.replace("\n","\n ")
1625         
1626         file_d.write( "do_compile() {\n" )
1627         if  code.count("autotools_do_configure") == 1 :
1628               code_line=code.replace("\\\n"," ").split("\n")
1629               for line in code_line:
1630                   if "autotools_do_configure" in line:
1631                       post= line.split("autotools_do_configure")[0]
1632                       EXTRA_OECONF = line.split("autotools_do_configure")[1] 
1633                       file_d.write( "%sautotools_do_configure\n" % post)
1634                   else:
1635                       file_d.write( " %s\n" % line )
1636               
1637               
1638         elif  code.count("autotools_do_configure") > 1 :
1639             msg="ERROR more than 1 autotools_do_configure for \"%s\"" % self.__package_name
1640             print >> sys.stderr, colorize( msg, "red" )
1641         
1642         else:
1643             file_d.write( " %s\n" % code )
1644             
1645         file_d.write( "}\n" )
1646         if EXTRA_OECONF is not None:
1647             while EXTRA_OECONF.count("  "):
1648                 EXTRA_OECONF=EXTRA_OECONF.replace("  "," ")
1649             file_d.write( "EXTRA_OECONF += \"%s\"\n" % EXTRA_OECONF )
1650             
1651         file_d.write( "\n" )
1652
1653     def __create_install( self ,file_d):
1654         code=self.__spec_parser.get_install_section()
1655         code=code.replace("\n","\n ")
1656         code=code.replace("\n EOF","\nEOF")
1657         file_d.write( "do_install() {\n" )
1658         file_d.write( " export RPM_BUILD_ROOT=${D}\n" )
1659         file_d.write( " %s\n" % code )
1660         file_d.write( "}\n" )
1661         file_d.write( "\n" )
1662
1663     def __create_script_file_section_code( self, spec_section):
1664         '''
1665         Returns the command executed in one of the %pre, %post, %preun
1666         or %postun section of a spec file.
1667         '''
1668         code = self.__spec_parser.get_script_from_section(spec_section)
1669         command_list = code.split("\n")
1670         formated_code = ""
1671         for line in command_list:
1672
1673             if line != "":
1674                 formated_code += "    " + line + "\n"
1675
1676         return formated_code
1677
1678     def __create_script_file_write( self, file_d, code, recipe_section, package_name):
1679         '''
1680         Writes the pre/post (un)install sections of the recipe.
1681         '''
1682         code=code.replace("/sbin/ldconfig","[ \"x$D\" == \"x\" ] && ldconfig")
1683         code=code.replace("${prefix}","$D${prefix}")
1684
1685
1686         file_d.write("%s%s() {\n" % (recipe_section, package_name))
1687         file_d.write("    #!/bin/sh -e\n\n")
1688         file_d.write("%s\n" % code)
1689         file_d.write("}\n")
1690         file_d.write("\n")
1691
1692     def __create_script_file_session(self, file_d, flag, script_name, script_sections):
1693         '''
1694         Add script for the given flag.
1695         '''
1696         for section in script_sections:
1697             code = ""
1698             # If %section is a one line script such as: "%post -p /sbin/ldconfig"
1699             if " -p " in section:
1700                 # Remove the package name if present to only keep the command
1701                 section_split = section.split(" -p ")[1].split(" -n ")
1702                 code = "    " + section_split[0].strip()
1703             else:
1704                 code = self.__create_script_file_section_code(section)
1705             if code != "":
1706                 # Set the package name
1707                 package_name = "${PN}"
1708                 # If the package name is not the project name
1709                 if " -n " in section:
1710                     # Remove the command if any to only keep the package name
1711                     section_split = section.split(" -n ")[1].split(" -p ")
1712                     package_name = section_split[0].strip()
1713                 self.__create_script_file_write(file_d, code, script_name, package_name)
1714
1715     def __create_script_file(self, file_d):
1716         '''
1717         Add the pre/post install/uninstall sections of a spec file to
1718         the recipe.
1719         '''
1720         script_sections = self.__spec_parser.get_script_section_key_pre()
1721         self.__create_script_file_session(file_d, "%pre", "pkg_preinst_", script_sections)
1722
1723         script_sections = self.__spec_parser.get_script_section_key_post()
1724         self.__create_script_file_session(file_d, "%post", "pkg_postinst_", script_sections)
1725
1726         script_sections = self.__spec_parser.get_section_key("%preun")
1727         self.__create_script_file_session(file_d, "%preun", "pkg_prerm_", script_sections)
1728
1729         script_sections = self.__spec_parser.get_section_key("%postun")
1730         self.__create_script_file_session(file_d, "%postun", "pkg_postrm_", script_sections)
1731
1732     def __create_provides_file( self ,file_d):
1733         '''
1734         generate provide file.
1735         '''
1736         file_d.write( "PROVIDES = \"\"\n" )
1737         file_d.write( "\n" )
1738
1739         for k_provide in self.__provides_dico.keys():
1740             pkg_yocto_name=k_provide
1741             for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1742                 pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1743
1744             if len( self.__provides_dico[k_provide] ) > 0:
1745                 file_d.write( "#PROVIDES by %s\n" % pkg_yocto_name.replace(" ","") )
1746                 if pkg_yocto_name != self.__package_name:
1747                    file_d.write( "PROVIDES += \"%s\"\n" % ( pkg_yocto_name ) )
1748
1749
1750
1751             for p_provide in self.__provides_dico[k_provide]:
1752                 pkg = p_provide[0]
1753                 pkg_yocto=pkg
1754                 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto ):
1755                      pkg_yocto=pkg_yocto.replace("-devel","-dev")
1756
1757                 if not len( p_provide ) == 1:
1758                     provide_text = "# the PROVIDES rules is ignore \"%s %s %s\"\n"
1759                     file_d.write( provide_text % ( pkg_yocto, p_provide[1], p_provide[2] ) )
1760
1761                 if ( pkg == "mktemp" and self.__package_name == "tizen-coreutils" ):
1762                     continue
1763
1764
1765                 if pkg_yocto_name != pkg_yocto:
1766                    file_d.write( "PROVIDES += \"%s\"\n" % ( pkg_yocto ) )
1767                    file_d.write( "RPROVIDES_%s += \"%s\"\n" % ( pkg_yocto_name, pkg_yocto ) )
1768
1769                 #for res_pkg_devel in re.findall( RePattern.paternDevel, pkg ):
1770                 #    rprovide_text = "RPROVIDES_%s += \"%s\"\n"
1771                 #    file_d.write( rprovide_text % ( k_provide, res_pkg_devel + "-dev" ) )
1772
1773             if len( self.__provides_dico[k_provide] ) > 0:
1774                 file_d.write( "\n\n" )
1775
1776     def __create_git_native_file( self ):
1777         '''
1778         create bb native file.
1779         '''
1780         bb_native_path = os.path.join( self.__package_recipes_dir, self.__git_native_file )
1781         with open( bb_native_path, "w" ) as file_d:
1782             file_d.write( "require %s\n" % self.__base_file )
1783             file_d.write( "\n" )
1784             file_d.write( "PRIORITY = \"9\"\n" )
1785             file_d.write( "\n" )
1786             file_d.write( "inherit native\n" )
1787             file_d.write( "\n" )
1788             file_d.write( "S = \"${WORKDIR}/git\"\n" )
1789             file_d.write( "\n" )
1790
1791             md5_value = "801f80980d171dd6425610833a22dbe6"
1792             file_value = "${COMMON_LICENSE_DIR}/GPL-2.0"
1793             file_chksum_text = "LIC_FILES_CHKSUM ??= \"file://%s;md5=%s\"\n"
1794             # should be generat
1795             file_d.write( file_chksum_text % ( file_value, md5_value ) )
1796             file_d.write( "\n" )
1797             command_source = "SRC_URI += \"%s\"\n" % GIT_COMMAND
1798             file_d.write( command_source % ( self.__package_git_srv_src ,
1799                                              self.__package_git_srv_path ,
1800                                              self.__git_tag ) )
1801             #file_d.write( "require %s\n" % self.__extra_native_conf_file )
1802             file_d.write( "\n" )
1803
1804     def __create_git_oe_file( self ):
1805         '''
1806         generate  bb file.
1807         '''
1808         bb_path = os.path.join( self.__package_recipes_dir, self.__git_oe_file )
1809         with open( bb_path, "w" ) as file_d:
1810             file_d.write( "require %s\n" % self.__base_file )
1811             file_d.write( "\n" )
1812             file_d.write( "PRIORITY = \"10\"\n" )
1813             file_d.write( "\n" )
1814             md5_value = "801f80980d171dd6425610833a22dbe6"
1815             file_value = "${COMMON_LICENSE_DIR}/GPL-2.0"
1816             file_chksum_text = "LIC_FILES_CHKSUM ??= \"file://%s;md5=%s\"\n"
1817             # should be generat
1818             file_d.write( file_chksum_text % ( file_value, md5_value ) )
1819             file_d.write( "\n" )
1820             command_source = "SRC_URI += \"" + GIT_COMMAND + "\"\n"
1821             file_d.write( command_source % ( self.__package_git_srv_src ,
1822                                              self.__package_git_srv_path ,
1823                                              self.__git_tag ) )
1824             #file_d.write( "require %s\n" % self.__extra_oe_conf_file )
1825             file_d.write( "\n" )
1826             if  self.__package_name not in MetaSpec.mNativePackageBlacklist:
1827                 file_d.write( "BBCLASSEXTEND += \" native \"" )
1828             file_d.write( "\n\n" )
1829
1830     def __createRecipes( self ):
1831         '''
1832         generate all bb file.
1833         '''
1834         if self.__package_recipes_dir is  None:
1835             return
1836
1837         if not os.path.isdir( self.__package_recipes_dir ):
1838             os.makedirs( self.__package_recipes_dir )
1839
1840         # Just touch a file
1841         #rdepends_path = os.path.join( self.__package_recipes_dir, self.__base_rdepends_file )
1842         #open( rdepends_path, "a" ).close()
1843         #depends_path = os.path.join( self.__package_recipes_dir, self.__base_depends_file )
1844         #open( depends_path, "a" ).close()
1845         #provides_path = os.path.join( self.__package_recipes_dir, self.__base_provides_file )
1846         #open( provides_path, "a" ).close()
1847
1848         extra_conf_file_path = os.path.join( self.__package_recipes_dir, self.__extra_conf_file )
1849         open( extra_conf_file_path, "a" ).close()
1850
1851         #extranative_path = os.path.join( self.__package_recipes_dir, self.__extra_native_conf_file )
1852         #open( extranative_path, "a" ).close()
1853         #extra_oe_conf_path = os.path.join( self.__package_recipes_dir, self.__extra_oe_conf_file )
1854         #open( extra_oe_conf_path, "a" ).close()
1855
1856         self.__create_base_file()
1857
1858         if  not self.__package_name not in MetaSpec.mNativePackageBlacklist:
1859             bb_native_path = os.path.join( self.__package_recipes_dir, self.__git_native_file )
1860             if os.path.isfile( bb_native_path ):
1861                 os.unlink( bb_native_path )
1862
1863         #self.__create_provides_file()
1864
1865         if self.__package_name not in MetaSpec.mOePackageBlacklist:
1866             self.__create_git_oe_file()
1867         else:
1868             bb_oe_path = os.path.join( self.__package_recipes_dir, self.__git_oe_file )
1869             if os.path.isfile( bb_oe_path ):
1870                 os.unlink( bb_oe_path )
1871
1872     def __create_rdepends( self ,file_d):
1873         '''
1874         generate rdepends file.
1875         '''
1876         if self.__package_recipes_dir is  None:
1877             return
1878
1879         if not os.path.isdir( self.__package_recipes_dir ):
1880             os.makedirs( self.__package_recipes_dir )
1881
1882         #rdepends_path = os.path.join( self.__package_recipes_dir, self.__base_rdepends_file )
1883
1884         package_replacement = SPEC2YOCTO_CONFIG.get_substitute()
1885
1886         if file_d is not None:
1887             file_d.write( "RDEPENDS = \"\"\n" )
1888
1889             for k_provide in self.__rdepends_dico.keys():
1890                 pkg_yocto_name=k_provide
1891                 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1892                     pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1893
1894                 res_rdepends = set()
1895                 k_provide_replace = pkg_yocto_name.replace( self.__package_name, "${PN}" )
1896                 if len( self.__rdepends_dico[k_provide] ) > 0:
1897                     file_d.write( "#RDEPENDS of %s (%s)\n" % ( pkg_yocto_name, k_provide_replace ) )
1898
1899                 for provide in self.__rdepends_dico[k_provide]:
1900                     package_provide = provide[0]
1901
1902                     res = None
1903
1904                     for k_package_provide in MetaSpec.mExtraRProvidesDico.keys():
1905
1906                         if package_provide in MetaSpec.mExtraRProvidesDico[k_package_provide] \
1907                            or package_provide == k_package_provide:
1908                             res = k_package_provide
1909                             break
1910                     if res is None:
1911                         res = package_provide
1912
1913                     if res in package_replacement.keys():
1914                         res = package_replacement[res]
1915
1916                     res_rdepends.add( res )
1917
1918                 for pkg in res_rdepends:
1919                     res_pkg_devel = re.findall( RePattern.paternDevel, pkg )
1920
1921                     if len( res_pkg_devel ) > 0:
1922                         rdepends_value = "RDEPENDS_%s += \"%s\"\n"
1923                         file_d.write( rdepends_value % ( k_provide_replace, res_pkg_devel[0] + "-dev" ) )
1924                     else:
1925                         if not pkg in  SPEC2YOCTO_CONFIG.get_ignore_rdepend():
1926                             file_d.write( "RDEPENDS_%s += \"%s\"\n" % ( k_provide_replace, pkg ) )
1927
1928                 if len( self.__rdepends_dico[k_provide] ) > 0:
1929                     file_d.write( "\n" )
1930
1931             file_d.write( "\n" )
1932
1933     def __create_depends( self, file_d):
1934         '''
1935         create depends file.
1936         '''
1937         if self.__package_recipes_dir is  None:
1938             return
1939
1940         if not os.path.isdir( self.__package_recipes_dir ):
1941             os.makedirs( self.__package_recipes_dir )
1942
1943         depends_dico = self.__spec_parser.get_depends()
1944         #depends_path = os.path.join( self.__package_recipes_dir, self.__base_depends_file )
1945
1946         ignore_depend_list = SPEC2YOCTO_CONFIG.get_ignore_depend()
1947         native_depend_list = SPEC2YOCTO_CONFIG.get_native_depend()
1948         cross_depend_list = SPEC2YOCTO_CONFIG.get_cross_depend()
1949
1950
1951         if file_d is not None:
1952             file_d.write( "DEPENDS = \"\"\n" )
1953
1954             res_depends = set()
1955             for k_provide in depends_dico.keys():
1956                 if len( depends_dico[k_provide] ) > 0:
1957                     file_d.write( "#DEPENDS of %s\n" % k_provide )
1958
1959                 for p_provide in depends_dico[k_provide]:
1960                     pp_provide = p_provide[0]
1961                     res = None
1962
1963                     if pp_provide in ignore_depend_list:
1964                         continue
1965
1966                     for k in MetaSpec.mProvidesDico.keys():
1967                         if pp_provide in MetaSpec.mProvidesDico[k] or pp_provide == k:
1968                             res = k
1969                             break
1970                     for k_package_provide in MetaSpec.mExtraRProvidesDico.keys():
1971                         if pp_provide in MetaSpec.mExtraRProvidesDico[k_package_provide]:
1972                             res = k_package_provide
1973                             break
1974
1975                     if res is None:
1976                         if pp_provide not in SPEC2YOCTO_CONFIG.get_inherit_gettext() and \
1977                           pp_provide not in SPEC2YOCTO_CONFIG.get_inherit("python") and \
1978                           pp_provide not in SPEC2YOCTO_CONFIG.get_inherit("cmake") and \
1979                           pp_provide not in SPEC2YOCTO_CONFIG.get_inherit("perl") and \
1980                           pp_provide not in ignore_depend_list and \
1981                           pp_provide not in native_depend_list and \
1982                           pp_provide not in cross_depend_list:
1983
1984                             erro_msg = "No direct provider for package DEPENDS %s : \"%s\"."
1985                             print erro_msg % ( self.__package_name, pp_provide )
1986                         res = pp_provide
1987                     if res != self.__package_name :
1988                         res_depends.add( res )
1989
1990             # should be from a configue file.
1991             for res in res_depends:
1992                 pkg_yocto_name=res
1993                 for res_pkg_devel in re.findall( RePattern.paternDevel, pkg_yocto_name ):
1994                     pkg_yocto_name=pkg_yocto_name.replace("-devel","-dev")
1995
1996                 if pkg_yocto_name == "readline-dev":
1997                     pkg_yocto_name="readline"
1998
1999                 if pkg_yocto_name in SPEC2YOCTO_CONFIG.get_inherit_gettext():
2000                     file_d.write( "#Replace \"DEPENDS\" on gettext by \"inherit gettext\"\n" )
2001                     file_d.write( "inherit gettext\n" )
2002                 elif pkg_yocto_name in native_depend_list:
2003                     file_d.write( "DEPENDS_append_class-native = \" %s-native\"\n" % pkg_yocto_name )
2004                     file_d.write( "DEPENDS_append_class-target = \" %s-native\"\n" % pkg_yocto_name )
2005                 elif pkg_yocto_name in cross_depend_list:
2006                     file_d.write( "DEPENDS_append_class-native = \" %s\"\n" % pkg_yocto_name )
2007                     file_d.write( "DEPENDS_append_class-target = \" %s-cross\"\n" % pkg_yocto_name )
2008                 elif pkg_yocto_name in ignore_depend_list:
2009                     pass
2010                 elif pkg_yocto_name in SPEC2YOCTO_CONFIG.get_libtool_cross():
2011                     file_d.write( "DEPENDS += \"libtool-cross\"\n" )
2012                 elif pkg_yocto_name in SPEC2YOCTO_CONFIG.get_inherit("perl"):
2013                     file_d.write( "inherit perlnative\n"  )
2014                 elif pkg_yocto_name in SPEC2YOCTO_CONFIG.get_inherit("python"):
2015                     file_d.write( "inherit pythonnative\n"  )
2016                 else:
2017                     file_d.write( "DEPENDS += \"%s\"\n" % pkg_yocto_name )
2018
2019         file_d.write( "\n"  )
2020
2021 class HTTPAccessFailure( Exception ):
2022     '''Indicate the http access failed'''
2023
2024 def download_url( url ):
2025     r = urlopen( url )
2026     if r.code != 200:
2027         raise HTTPAccessFailure()
2028     page = r.read()
2029
2030     return page
2031
2032 def download_manifest_url( url ):
2033     r = urlopen( url )
2034     if r.code != 200:
2035         print "ERROR %s " % url
2036         raise HTTPAccessFailure()
2037     page = r.read()
2038
2039     return page
2040
2041 def download_build_xml( url ):
2042     return download_url( url + "/build.xml" )
2043
2044 def get_project_id( xml ):
2045     aElement = ElementTree.fromstring( xml )
2046
2047     for value in aElement:
2048         for project in value.getiterator():
2049             if project.tag == "id":
2050                 return project.text
2051
2052 def get_project_arch( xml ):
2053     aElement = ElementTree.fromstring( xml )
2054     arch_list = []
2055     for value in aElement:
2056         for project in value.getiterator():
2057             if project.tag == "archs":
2058                 for arch in project.getiterator():
2059                     if arch.tag == "arch":
2060                         arch_list.append( arch.text )
2061
2062     return arch_list
2063
2064 def get_project_buildtarget(xml):
2065     aElement = ElementTree.fromstring(xml)
2066     buildtarget_list = []
2067     for value in aElement:
2068         for project in value.getiterator():
2069             if project.tag == "buildtargets":
2070                 for buildtarget in project.getiterator():
2071                     if buildtarget.tag == "buildtarget":
2072                         buildtarget_list.append(buildtarget.text)
2073
2074     return buildtarget_list
2075
2076 def clean_name( raw_name ):
2077     #if "_" in raw_name:
2078     #    raw_name = raw_name.replace( "_", "-" )
2079
2080     if "/" in raw_name:
2081         return raw_name.split( "/" )[-1]
2082     else:
2083         return raw_name
2084
2085 def clean_revision( raw_name ):
2086     if "-" in raw_name:
2087         return raw_name.split( "-" )[0]
2088     else:
2089         return raw_name
2090
2091 def patch_the_spec_file( package_spec_path,
2092                          patch_path,
2093                          dest_spec_dir,
2094                          dest_spec_path ):
2095
2096     if not package_spec_path == dest_spec_path:
2097         shutil.copy2( package_spec_path, dest_spec_path )
2098
2099     if dest_spec_dir.endswith( "/packaging" ):
2100         dest_spec_dir = dest_spec_dir[:-len( "/packaging" )]
2101
2102     patch_command = "patch -s -p1 --fuzz=2 -d %s -i %s" % ( dest_spec_dir, patch_path )
2103
2104     a_sub_command = SubprocessCrt()
2105     res = a_sub_command.exec_subprocess( patch_command )
2106
2107     if res == 1:
2108             msg = "The patch \"%s\" can't be apply in directory \"%s\"."
2109             msg = msg % ( patch_path, dest_spec_dir )
2110             print >> sys.stderr, colorize( msg, "red" )
2111             print >> sys.stderr, colorize( "command: \"%s\"" % patch_command, "red" )
2112             sys.exit( 1 )
2113
2114     return dest_spec_path
2115
2116
2117 def specfile_patcher( package_spec_path, project, package_name_list , dest_spec_path ):
2118     working_dir = SPEC2YOCTO_CONFIG.get_working_dir( project )
2119     source_spec_patch_dir = os.path.join( working_dir, "specfile-patch" )
2120
2121     patch_path_list = findSpecPatchFiles( source_spec_patch_dir, package_name_list )
2122
2123     if len( patch_path_list ) > 0:
2124
2125         dest_spec_dir = os.path.dirname( dest_spec_path )
2126         if not os.path.isdir( dest_spec_dir ):
2127             os.makedirs( dest_spec_dir )
2128
2129         for patch_path in patch_path_list:
2130             package_spec_path = patch_the_spec_file( package_spec_path,
2131                                                      patch_path,
2132                                                      dest_spec_dir,
2133                                                      dest_spec_path )
2134
2135     return package_spec_path
2136
2137 class package_def:
2138
2139     def __init__( self, project, name, path, revision, priority, git_src ):
2140         self.__project = project
2141         self.name = name
2142         self.git_path = path
2143         self.git_revision = revision
2144         self.priority = priority
2145         self.git_src = git_src
2146         self.__my_meta_spec = None
2147
2148     def printMe( self ):
2149         print "%s %s %s %s" % ( self.name , self.git_path, self.git_revision, self.git_src )
2150
2151     def create_MetaSpec( self , package_recipes_dir, source_spec_dir ):
2152         source_path = os.path.join( source_spec_dir , self.name , "packaging" )
2153         package_spec_path = findBestSpecFile( source_path, self.name )
2154
2155         if package_spec_path == -1:
2156             msg = "no initial spec file for package \"%s\" in directory \"%s\"."
2157             msg = msg % ( self.name, source_path )
2158             print >> sys.stderr, colorize( msg, "red" )
2159             sys.exit( 1 )
2160
2161         working_dir = SPEC2YOCTO_CONFIG.get_working_dir( self.__project )
2162         specfile_patched_dir = os.path.join( working_dir, "specfile-patched" )
2163         dest_spec_dir = os.path.join( specfile_patched_dir , self.name )
2164         dest_spec_packaging_dir = os.path.join( dest_spec_dir , "packaging" )
2165         dest_spec_path = os.path.join( dest_spec_packaging_dir ,
2166                                        os.path.basename( package_spec_path ) )
2167
2168
2169         package_spec_path = specfile_patcher( package_spec_path,
2170                                               self.__project,
2171                                               [self.name, self.name + "-initial"],
2172                                                dest_spec_path )
2173
2174         self.__my_meta_spec = MetaSpec( os.path.join( package_recipes_dir, self.name ),
2175                                         self.name,
2176                                         package_spec_path,
2177                                         self.git_src,
2178                                         self.git_path,
2179                                         self.git_revision )
2180
2181 def make_alias_package( project, packages_dico ):
2182     alias_package = {}
2183     #TO DO need to be do in conf file.
2184     alias_package["python-libxml2"] = "libxml2"
2185     alias_package["python-magic"] = "file"
2186     alias_package["cross-arm-binutils"] = "binutils"
2187     alias_package["cross-armv7hl-gcc47-icecream-backend"] = "gcc47"
2188     alias_package["libffi47"] = "gcc47"
2189
2190     for alias in alias_package.keys():
2191         alias_to = alias_package[alias]
2192         if alias_to in packages_dico.keys() and alias not in packages_dico.keys():
2193             a_package_def = packages_dico[alias_to]
2194             packages_dico[alias] = package_def( project,
2195                                                 alias,
2196                                                 a_package_def.git_path,
2197                                                 a_package_def.git_revision,
2198                                                 a_package_def.priority,
2199                                                 a_package_def.git_src )
2200
2201     return packages_dico
2202
2203 class manifestCollection:
2204     '''
2205     class for all package in a distro.
2206     '''
2207     def __init__( self , project ):
2208         '''
2209         init all manifest
2210         '''
2211         self.__my_project = project
2212
2213         self.__recipes_list = None
2214
2215         if not SPEC2YOCTO_CONFIG.is_valide_project( self.__my_project ):
2216             msg = "\"%s\" has no configuration in file \"%s\"."
2217             msg = msg % ( self.__my_project, CONFIGURATION_FILE_PATH )
2218             print >> sys.stderr, colorize( msg, "red" )
2219             sys.exit( 1 )
2220
2221         #Just get the list of manifest uri.
2222         self.__my_manifest_meta_list = SPEC2YOCTO_CONFIG.get_manifest_meta_list( self.__my_project )
2223
2224         self.__my_manifest_file_list = {}
2225         #Load the project manifest.
2226         self.__update_meta_manifests()
2227
2228         self.__my_package_dico = {}
2229         self.__generate_package()
2230
2231         self.__my_package_dico = make_alias_package( self.__my_project, self.__my_package_dico )
2232
2233     def parse_manifest_xml( self, src ):
2234         primaryFile = open( src, "r" )
2235         primaryXML = primaryFile.read()
2236         primaryFile.close()
2237
2238         aElement = ElementTree.fromstring( primaryXML )
2239         remote = ""
2240         packages_dico = {}
2241         for value in aElement:
2242             for project in value.getiterator():
2243                 if project.tag == "project":
2244                     name =  project.attrib['name']
2245                     short_name=clean_name( name )
2246                     revision = clean_revision( project.attrib['revision'] )
2247                     packages_dico[short_name] = [name, revision]
2248                 elif project.tag == "default":
2249                       remote = project.attrib['remote']
2250                 elif project.tag == "remote":
2251                     fetch = project.attrib['fetch']
2252                     name = project.attrib['name']
2253                 else:
2254                     print "ERROR"
2255
2256         return remote, packages_dico
2257
2258     def print_list( self ):
2259         pkg_list = self.__my_package_dico.keys()
2260         pkg_list.sort()
2261         for package in pkg_list:
2262             self.__my_package_dico[package].printMe()
2263
2264     def __generate_package( self ):
2265         for meta_manifest in self.__my_manifest_file_list.keys():
2266             manifest_uri = self.__my_manifest_file_list[meta_manifest]
2267             
2268             manifest_git = SPEC2YOCTO_CONFIG.get_manifest_default_git_src( meta_manifest )
2269             manifest_priority = SPEC2YOCTO_CONFIG.get_manifest_priority( meta_manifest )
2270             remote, packages_dico = self.parse_manifest_xml( manifest_uri )
2271
2272             if manifest_git is not None:
2273                 remote = manifest_git
2274
2275             whitelist = SPEC2YOCTO_CONFIG.get_list(self.__my_project, "whitelist")
2276             if len( whitelist ) != 0:
2277                 list_packages = set(whitelist)
2278             else:
2279                 list_packages = set(packages_dico.keys())
2280
2281             blacklist = set(SPEC2YOCTO_CONFIG.get_list(self.__my_project, "blacklist"))
2282             list_packages=list_packages.difference(blacklist)
2283             for package in list_packages:
2284                 if package in packages_dico.keys():
2285                     [path, revision] = packages_dico[package]
2286                     if package in self.__my_package_dico.keys():
2287                         if manifest_priority > self.__my_package_dico[package].priority:
2288                             self.__my_package_dico[package] = package_def( self.__my_project,
2289                                                                            package,
2290                                                                            path,
2291                                                                            revision,
2292                                                                            manifest_priority,
2293                                                                            remote )
2294                         elif manifest_priority == self.__my_package_dico[package].priority:
2295                             msg = "most of one occurence of package \"%s\" ."
2296                             msg = msg % ( package )
2297                             print >> sys.stderr, colorize( msg, "red" )
2298                             sys.exit( 1 )
2299                     else:
2300                         self.__my_package_dico[package] = package_def( self.__my_project,
2301                                                                        package,
2302                                                                        path,
2303                                                                        revision,
2304                                                                        manifest_priority,
2305                                                                        remote )
2306         for package in whitelist:
2307             if package not in self.__my_package_dico.keys():
2308                 msg = "package \"%s\" is in the white list but not in the manifest."
2309                 msg = msg % ( package )
2310                 print >> sys.stderr, colorize( msg, "red" )
2311                 sys.exit( 1 )
2312
2313     def __update_meta_manifests( self ):
2314         '''
2315         find/download all manifest.xml file.
2316         '''
2317         for meta_manifest in self.__my_manifest_meta_list:
2318             meta_manifest_uri = SPEC2YOCTO_CONFIG.get_manifest_uri( meta_manifest )
2319             if meta_manifest_uri is None:
2320                 msg = "\"%s\" has no URI configuration in file \"%s\"."
2321                 msg = msg % ( meta_manifest_uri, CONFIGURATION_FILE_PATH )
2322                 print >> sys.stderr, colorize( msg, "red" )
2323                 sys.exit( 1 )
2324             if meta_manifest_uri.startswith( "http" ):
2325                 if meta_manifest_uri.endswith( ".xml" ):
2326                     meta_manifest_url_path = meta_manifest_uri
2327                     manifest_name = os.path.basename(meta_manifest_uri)
2328                 else:
2329                     xml_str = download_build_xml( meta_manifest_uri )
2330                     project_id = get_project_id( xml_str )
2331                     list_arch = get_project_arch( xml_str )
2332                     list_buildtarget = get_project_buildtarget(xml_str)
2333
2334                     arch = SPEC2YOCTO_CONFIG.get_project_arch( self.__my_project )
2335                     buildtarget = SPEC2YOCTO_CONFIG.get_manifest_buildtarget(meta_manifest)
2336
2337                     if ( arch == "i586" ) and ( "ia32" in list_arch ):
2338                         arch = "ia32"
2339                         buildtarget ="ia32-wayland"
2340
2341                     elif ( arch is None ) and ( len( list_arch ) > 0 ):
2342                         arch = list_arch[0]
2343
2344                     elif ( arch not in list_arch ):
2345                         arch = list_arch[0]
2346
2347                     manifest_name = "%s_%s.xml" % ( project_id, buildtarget )
2348                     meta_manifest_url_path = "%s/builddata/manifest/%s"
2349                     meta_manifest_url_path = meta_manifest_url_path % ( meta_manifest_uri,
2350                                                                         manifest_name )
2351
2352                 manifest_xml = download_manifest_url( meta_manifest_url_path )
2353                 working_dir = SPEC2YOCTO_CONFIG.get_working_dir( self.__my_project )
2354
2355                 meta_manifest_dir = os.path.join( working_dir, "manifest_file" )
2356                 meta_manifest_path = os.path.join( meta_manifest_dir, manifest_name )
2357
2358                 if not os.path.isdir( meta_manifest_dir ):
2359                     os.makedirs( meta_manifest_dir )
2360
2361                 with open( meta_manifest_path, "w" ) as manifest_xml_file:
2362                     manifest_xml_file.write( manifest_xml )
2363             else:
2364                 if not os.path.isfile( meta_manifest_uri ):
2365                     msg = "In the project \"%s\" the manifest \"%s\" is not a valid file."
2366                     msg = msg % ( self.__my_project, meta_manifest_uri )
2367                     print >> sys.stderr, colorize( msg, "red" )
2368                     sys.exit( 1 )
2369                 else:
2370                     meta_manifest_path = meta_manifest_uri
2371
2372             self.__my_manifest_file_list[ meta_manifest ] = meta_manifest_path
2373
2374     def createRecipes( self ):
2375         '''
2376         generate recipises.
2377         '''
2378         self.__recipes_dir_dest = SPEC2YOCTO_CONFIG.get_recipes_sources_directory( self.__my_project )
2379
2380         self.__clean_old_bb_files(self.__recipes_dir_dest)
2381
2382         if self.__recipes_dir_dest is None:
2383             msg = "In the project \"%s\" recipes_dir_sources is  not define."
2384             msg = msg % ( self.__my_project )
2385             print >> sys.stderr, colorize( msg, "red" )
2386             sys.exit( 1 )
2387         elif not os.path.isdir( self.__recipes_dir_dest ):
2388             os.makedirs( self.__recipes_dir_dest )
2389
2390         self.__meta_spec_dico = {}
2391         self.__meta_spec_boot_strap_dico = {}
2392
2393         self.__set_oe_package_blacklist()
2394         self.__set_native_package_blacklist()
2395
2396         self.__init_depends()
2397         self.__init_MetaSpec()
2398
2399
2400     def __clean_old_bb_files( self ,path):
2401         for root, dirs, files in os.walk(path):
2402             for a_file in files:
2403                 if a_file.endswith(".bb"):
2404                     os.unlink( os.path.join(path, root, a_file) )
2405
2406
2407     def __set_oe_package_blacklist( self ):
2408         '''
2409         load oe_package_blacklist
2410         '''
2411         list_package = SPEC2YOCTO_CONFIG.get_list(self.__my_project, "runtime_blacklist")
2412         MetaSpec.mOePackageBlacklist.extend( list_package )
2413
2414     def __set_native_package_blacklist( self ):
2415         '''
2416         load oe_package_blacklist
2417         '''
2418         list_package = SPEC2YOCTO_CONFIG.get_list(self.__my_project, "native_blacklist")
2419         MetaSpec.mNativePackageBlacklist.extend( list_package )
2420
2421
2422     def __init_MetaSpec( self ):
2423         pkg_list = self.__my_package_dico.keys()
2424         pkg_list.sort()
2425
2426         working_dir = SPEC2YOCTO_CONFIG.get_working_dir( self.__my_project )
2427         source_spec_dir = os.path.join( working_dir, "specfile-initial" )
2428
2429         for package in pkg_list:
2430             self.__my_package_dico[package].create_MetaSpec( self.__recipes_dir_dest,
2431                                                              source_spec_dir )
2432
2433     def __init_depends( self ):
2434         '''
2435         init depends
2436         '''
2437         self.__load_package_provided_extra()
2438
2439         pkg_list = self.__my_package_dico.keys()
2440         pkg_list.sort()
2441
2442     def __load_package_provided_extra( self ):
2443         '''
2444         load_package_provided_extra
2445         '''
2446         provided_extra_dico = SPEC2YOCTO_CONFIG.get_provided_extra( self.__my_project )
2447
2448         for k_package in provided_extra_dico.keys():
2449             raw_list=provided_extra_dico[k_package]
2450
2451             if k_package not in MetaSpec.mProvidesDico.keys():
2452                 MetaSpec.mProvidesDico[k_package] = []
2453
2454             MetaSpec.mProvidesDico[k_package].extend( raw_list )
2455
2456             if k_package not in MetaSpec.mExtraRProvidesDico.keys():
2457                 MetaSpec.mExtraRProvidesDico[k_package] = []
2458             MetaSpec.mExtraRProvidesDico[k_package].extend( raw_list )
2459
2460 TERMINAL_COLORS = {"black": "\033[30;1m",
2461                    "red": "\033[31;1m",
2462                    "green": "\033[32;1m",
2463                    "yellow": "\033[33;1m",
2464                    "blue": "\033[34;1m",
2465                    "magenta": "\033[35;1m",
2466                    "cyan": "\033[36;1m",
2467                    "white": "\033[37;1m",
2468                    "default": "\033[0m"}
2469
2470 def colorize( text, color = "green" ):
2471     """
2472     Return a colorized copy of `text`.
2473     See Utils.TERMINAL_COLORS.keys() for available colors.
2474     """
2475     return TERMINAL_COLORS.get( color, "" ) + text + TERMINAL_COLORS["default"]
2476
2477
2478 def check_group_file( project ):
2479     working_dir = SPEC2YOCTO_CONFIG.get_working_dir( project )
2480
2481     group_uri = SPEC2YOCTO_CONFIG.get_group_uri( project )
2482
2483     if group_uri.startswith( "http" ):
2484         group_file_path = os.path.join( working_dir, "group/group.xml" )
2485         group_xml = download_url( group_uri )
2486
2487         with open( group_file_path, "w" ) as group_file:
2488             group_file.write( group_xml )
2489
2490         return group_file_path
2491     else:
2492         return group_uri
2493
2494 def parse_group_xml( src ):
2495     groupFile = open( src, "r" )
2496     groupXML = groupFile.read()
2497     groupFile.close()
2498
2499     aElement = ElementTree.fromstring( groupXML )
2500     packages_dico = {}
2501
2502     for group in aElement:
2503         if group.tag == "group":
2504             group_name=None
2505             list_package=[]
2506             for element in group:
2507                 if element.tag == "name":
2508                     group_name = element.text
2509                 elif element.tag == "packagelist":
2510                     for packagereq in element:
2511                         list_package.append(packagereq.text)
2512
2513             packages_dico[group_name]=list_package
2514     return packages_dico
2515
2516 def dump_group(project,group_dico):
2517
2518     recipes_group_directory = SPEC2YOCTO_CONFIG.get_recipes_group_directory( project )
2519
2520     for group in group_dico.keys():
2521         group_str = group.replace( " ", "-" )
2522         path = os.path.join( recipes_group_directory, "packagegroup-tizen-%s.bb" % group_str )
2523
2524         with open(path,"w") as group_file:
2525             group_file.write( "SUMMARY = \"%s\"\n" % group )
2526             group_file.write( "DESCRIPTION = \"%s\"\n" % group )
2527             group_file.write( "LICENSE = \"MIT\"\n" )
2528             group_file.write( "DEPENDS = \"virtual/kernel\"\n" )
2529             group_file.write( "PR = \"r1\"\n" )
2530
2531             group_file.write( "inherit packagegroup\n" )
2532             group_file.write( "\n" )
2533             group_file.write( "PACKAGE_ARCH = \"${MACHINE_ARCH}\"\n" )
2534             group_file.write( "\n" )
2535
2536             group_file.write( "RDEPENDS_${PN} = \"\" \n\n" )
2537             for pkg in group_dico[group]:
2538                 group_file.write( "RDEPENDS_${PN} += \"%s\"\n" % pkg )
2539
2540 def generateBuildStatus( project_path ):
2541     res_native = {}
2542     res = {}
2543     if not os.path.isdir( project_path ):
2544             msg = "The path \"%s\" is not a directory."
2545             msg = msg % ( project_path )
2546             print >> sys.stderr, colorize( msg, "red" )
2547             sys.exit( 1 )
2548
2549     for package_path in os.listdir( project_path ):
2550         project_full_path = os.path.join( project_path, package_path )
2551         if  ( package_path == "build_stats" ) and os.path.isfile( project_full_path )  :
2552             pass
2553
2554         elif os.path.isdir( project_full_path ):
2555             BN, PV, PR = cleanPackageName( package_path )
2556             res_status = check_package_status( project_full_path )
2557
2558             if BN.endswith("-native"):
2559                 res_native[BN] = [PV ] + res_status
2560             else:
2561                 res[BN] = [PV ] + res_status
2562
2563         # ignorefiles
2564         elif package_path in ["."]:
2565             pass
2566
2567         else:
2568             msg = "This directory should not contain the file \"%s\"."
2569             msg = msg % ( package_path )
2570             print >> sys.stderr, colorize( msg, "red" )
2571             sys.exit( 1 )
2572
2573     return res_native, res
2574
2575 def cleanPackageName( package_path ):
2576     if  package_path.count( "-" ) < 2:
2577         msg = "unknow format for package \"%s\"."
2578         msg = msg % ( package_path )
2579         print >> sys.stderr, colorize( msg, "red" )
2580         sys.exit( 1 )
2581
2582     PR=package_path[package_path.rindex("-")+1:]
2583     package_path=package_path[:package_path.rindex("-")]
2584     PV=package_path[package_path.rindex("-")+1:]
2585     BN=package_path[:package_path.rindex("-")]
2586
2587     return BN, PV, PR
2588
2589
2590 def check_package_status( project_full_path ):
2591     tasks_order = ["do_fetch",
2592                    "do_unpack",
2593                    "do_patch",
2594                    "do_populate_lic",
2595                    "do_configure",
2596                    "do_compile",
2597                    "do_install",
2598                    "do_populate_sysroot",
2599                    "do_package",
2600                    "do_packagedata",
2601                    "do_package_write_rpm",
2602                    "do_rootfs"]
2603
2604     max_index=-1
2605     for package_task in os.listdir( project_full_path ):
2606         if package_task in tasks_order:
2607             task_index = tasks_order.index( package_task )
2608
2609             if task_index > max_index:
2610                 max_index = task_index
2611
2612     if max_index == -1:
2613         msg = "No log task in \"%s\"."
2614         msg = msg % ( project_full_path )
2615         print >> sys.stderr, colorize( msg, "red" )
2616         sys.exit( 1 )
2617
2618     last_task = tasks_order[max_index][3:]
2619
2620     task_status = ""
2621     status = "unknow"
2622     with open( os.path.join( project_full_path, tasks_order[max_index] ) ) as status_file:
2623         for line in status_file:
2624             if line.startswith( "Status: " ):
2625                 status = line[len( "Status: " ):].replace( "\n", "" ).replace( " ", "" )
2626                 break
2627     if last_task == "package_write_rpm" and status == "PASSED":
2628         status = "OK"
2629
2630     return [last_task, status]
2631
2632 def clean_Packagegroup( project,group_dico ):
2633     group_dico_tmp = {}
2634
2635     package_replacement = SPEC2YOCTO_CONFIG.get_substitute( project )
2636
2637     for group in group_dico.keys():
2638         group_dico_tmp[group] = []
2639         for package in group_dico[group]:
2640             if package in package_replacement.keys():
2641                 group_dico_tmp[group].append( package_replacement[package] )
2642             else:
2643                 group_dico_tmp[group].append( package )
2644
2645     return group_dico_tmp
2646
2647
2648 def check_debugmode( opts_debug ):
2649     global DEBUG_RUN
2650     if opts_debug == "no":
2651         DEBUG_RUN = False
2652     elif opts_debug == "yes":
2653         DEBUG_RUN = True
2654
2655
2656 class spec2yoctoCommandline( cmdln.Cmdln ):
2657     name = "spec2yocto"
2658     version = "0.1"
2659
2660     def do_manifestToList( self, subcmd, opts, project = None ):
2661         """${cmd_name}: print the list of package in projects.
2662
2663         ${cmd_usage}--
2664         ${cmd_option_list}
2665         """
2666         if project is None:
2667             project = SPEC2YOCTO_CONFIG.get_current_project()
2668
2669         pkg_co = manifestCollection( project )
2670         pkg_co.print_list()
2671
2672     def do_createRecipes( self, subcmd, opts, project = None ):
2673         """${cmd_name}: create all packages recipes.
2674
2675         ${cmd_usage}--
2676         ${cmd_option_list}
2677         """
2678         if project is None:
2679             project = SPEC2YOCTO_CONFIG.get_current_project()
2680
2681         pkg_co = manifestCollection( project )
2682         pkg_co.createRecipes()
2683
2684     @cmdln.option( "--package_pn",
2685                   action = "store",
2686                   default = None,
2687                   help = "select the package_pn." )
2688     def do_findBestSpecFile( self, subcmd, opts, package_path ):
2689         """${cmd_name}: print the speec file associate to package.
2690
2691         ${cmd_usage}--
2692         ${cmd_option_list}
2693         """
2694         res = findBestSpecFile( package_path, opts.package_pn )
2695         print res
2696
2697     @cmdln.option( "--package_pn",
2698                   action = "append",
2699                   default = None,
2700                   help = "select the package_pn." )
2701     def do_findSpecPatchFiles( self, subcmd, opts, patch_dir, ):
2702         """${cmd_name}: print patch from "specfile-patch" directory associate to package.
2703
2704         ${cmd_usage}--
2705         ${cmd_option_list}
2706         """
2707         res = findSpecPatchFiles( patch_dir, opts.package_pn )
2708         print " ".join( res )
2709
2710     @cmdln.option( "--package_pn",
2711                   action = "append",
2712                   default = None,
2713                   help = "select the package_pn." )
2714     @cmdln.option( "--project",
2715                   action = "store",
2716                   default = None,
2717                   help = "select the package_pn." )
2718     def do_specfile_patcher( self, subcmd, opts, package_spec_path ):
2719         """${cmd_name}: patch the spec file with patch from "specfile-patch" directory.
2720
2721         ${cmd_usage}--
2722         ${cmd_option_list}
2723         """
2724         if opts.project is None:
2725             project = SPEC2YOCTO_CONFIG.get_current_project()
2726         else:
2727             project = opts.project
2728
2729         res = specfile_patcher( package_spec_path, project, opts.package_pn, package_spec_path )
2730
2731
2732     def do_createPackagegroup( self, subcmd, opts, project = None ):
2733         """${cmd_name}: print the list of package in projects.
2734
2735         ${cmd_usage}--
2736         ${cmd_option_list}
2737         """
2738         if project is None:
2739             project = SPEC2YOCTO_CONFIG.get_current_project()
2740
2741
2742         res = SPEC2YOCTO_CONFIG.get_group( project )
2743         group_file_path = check_group_file( project )
2744         group_dico= parse_group_xml( group_file_path )
2745
2746         group_dico = clean_Packagegroup( project, group_dico )
2747
2748         dump_group(project,group_dico)
2749
2750     @cmdln.option( "--debug",
2751                   action = "store",
2752                   default = None,
2753                   help = "run the in debug mode.[yes/no]" )
2754     @cmdln.option( "--project",
2755                   action = "store",
2756                   default = None,
2757                   help = "select the project." )
2758     @cmdln.option( "--package_pn",
2759                   action = "store",
2760                   default = None,
2761                   help = "select the package_pn." )
2762     def do_prep( self, subcmd, opts, spec_path ):
2763         """${cmd_name}: print the bash code of the %prep section of a spec file.
2764
2765         ${cmd_usage}--
2766         ${cmd_option_list}
2767         """
2768         check_debugmode( opts.debug )
2769
2770         if opts.project is None:
2771             project = SPEC2YOCTO_CONFIG.get_current_project()
2772         else:
2773             project = opts.project
2774
2775         res = SpecParser( spec_path, package_pn = opts.package_pn ).get_prep_section()
2776         print res
2777         res = 0
2778
2779     @cmdln.option( "--debug",
2780                   action = "store",
2781                   default = None,
2782                   help = "run the in debug mode.[yes/no]" )
2783     @cmdln.option( "--project",
2784                   action = "store",
2785                   default = None,
2786                   help = "select the project." )
2787     @cmdln.option( "--package_pn",
2788                   action = "store",
2789                   default = None,
2790                   help = "select the package_pn." )
2791     def do_compile( self, subcmd, opts, spec_path ):
2792         """${cmd_name}: print the bash code of the %build section of a spec file.
2793
2794         ${cmd_usage}--
2795         ${cmd_option_list}
2796         """
2797         check_debugmode( opts.debug )
2798
2799         if opts.project is None:
2800             project = SPEC2YOCTO_CONFIG.get_current_project()
2801         else:
2802             project = opts.project
2803
2804         res = SpecParser( spec_path, package_pn = opts.package_pn ).get_build_section()
2805         if res != 1:
2806             print res
2807
2808     @cmdln.option( "--debug",
2809                   action = "store",
2810                   default = None,
2811                   help = "run the in debug mode.[yes/no]" )
2812     @cmdln.option( "--project",
2813                   action = "store",
2814                   default = None,
2815                   help = "select the project." )
2816     @cmdln.option( "--package_pn",
2817                   action = "store",
2818                   default = None,
2819                   help = "select the package_pn." )
2820     def do_install( self, subcmd, opts, spec_path ):
2821         """${cmd_name}: print the bash code of the %install section of a spec file.
2822
2823         ${cmd_usage}--
2824         ${cmd_option_list}
2825         """
2826         check_debugmode( opts.debug )
2827
2828
2829         if opts.project is None:
2830             project = SPEC2YOCTO_CONFIG.get_current_project()
2831         else:
2832             project = opts.project
2833
2834         res = SpecParser( spec_path, package_pn = opts.package_pn ).get_install_section()
2835         if res != 1:
2836             print res
2837
2838     @cmdln.option( "--debug",
2839                   action = "store",
2840                   default = None,
2841                   help = "run the in debug mode.[yes/no]" )
2842     def do_generateBuildStatus( self, subcmd, opts, project_path ):
2843         """${cmd_name}: print the status and the the build state of packages,
2844         builded in a single command.
2845         exemple:
2846             build/tmp-eglibc/buildstats/core-image-minimal-qemux86/XXXX/
2847         ${cmd_usage}--
2848         ${cmd_option_list}
2849         """
2850         check_debugmode( opts.debug )
2851
2852         res_native, res = generateBuildStatus( project_path )
2853
2854         res_native_keys = res_native.keys()
2855         res_keys = res.keys()
2856
2857         res_native_keys.sort()
2858         res_keys.sort()
2859
2860         for r in res_native_keys:
2861             print r + "\t" + "\t".join( res_native[r] )
2862         print
2863         for r in res_keys:
2864             print r + "\t" + "\t".join( res[r] )
2865
2866
2867     @cmdln.option( "--debug",
2868                   action = "store",
2869                   default = None,
2870                   help = "run the in debug mode.[yes/no]" )
2871     def do_generatePseudoSpecfile( self, subcmd, opts, spec_path ):
2872         """${cmd_name}: generate a spec file use by yocto, for packaging rpm.
2873
2874         ${cmd_usage}--
2875         ${cmd_option_list}
2876         """
2877         check_debugmode( opts.debug )
2878
2879         a_spec_parser = SpecParser( spec_path )
2880         a_spec_parser.parse_raw_spec_file()
2881         res = a_spec_parser.get_clean_raw()
2882         if res != 1:
2883             print res
2884
2885     @cmdln.option( "--debug",
2886                   action = "store",
2887                   default = None,
2888                   help = "run the in debug mode.[yes/no]" )
2889     @cmdln.option( "--project",
2890                   action = "store",
2891                   default = None,
2892                   help = "select the project." )
2893     def do_working_dir( self, subcmd, opts ):
2894         """${cmd_name}: return the proto directory.
2895
2896         ${cmd_usage}--
2897         ${cmd_option_list}
2898         """
2899         check_debugmode( opts.debug )
2900
2901         if opts.project is None:
2902             project = SPEC2YOCTO_CONFIG.get_current_project()
2903         else:
2904             project = opts.project
2905
2906         working_dir = SPEC2YOCTO_CONFIG.get_working_dir( project )
2907         if working_dir != 1:
2908             print working_dir
2909
2910 def main():
2911     commandline = spec2yoctoCommandline()
2912
2913     try:
2914         res = commandline.main()
2915     except ValueError as ve:
2916         print
2917         print >> sys.stderr, colorize( str( ve ), "red" )
2918         res = 1
2919     except EnvironmentError as ioe:
2920 #        commandline.do_help([sys.argv[0]])
2921         print
2922         print >> sys.stderr, colorize( str( ioe ), "red" )
2923         if hasattr( ioe, "spec2yocto_config_error" ):
2924             msg = "See '--config' option"
2925             print >> sys.stderr, colorize( msg, "red" )
2926         res = 1
2927 #     except Exception as e_all :
2928 #         print
2929 #         print >> sys.stderr, colorize( str( e_all ), "red" )
2930 #         res = 1
2931     sys.exit( res )
2932
2933 if __name__ == '__main__':
2934     main()