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