source: cmtpacman/HEAD/scripts/kit.py @ 60

Last change on this file since 60 was 60, checked in by garonne, 19 years ago

ajout de la classe kit.py version betat

  • Property svn:executable set to *
File size: 26.7 KB
Line 
1# -*- coding: iso-8859-1 -*-
2########################################
3# author: Garonne Vincent              #
4# mail: garonne@lal.in2p3.fr           #
5# Description: Class and methods to    #
6# build a kit                          #
7# sources.                             #
8# Date: june/29/2005                   #
9# based on the christian shell and     #
10# python script                        #
11########################################
12
13import os
14import sys
15import string
16import popen2
17import stat
18import re
19import time
20from   os     import path
21import getopt
22import tempfile
23import signal
24import tarfile
25
26from   cmt import *
27
28class Kit:
29##################################################################################################
30#--------------------------- __init__ -----------------------------------------------------------#
31##################################################################################################
32    def __init__ (self, DEBUG=False):
33   
34        # Log creation
35        self.debug = DEBUG
36        if DEBUG:
37            self.log = logging.Logger(name='kit.py', level=logging.DEBUG)
38        else:
39            self.log = logging.Logger(name='kit.py', level=logging.INFO)
40        hdlr = logging.StreamHandler()
41        fmt  = logging.Formatter("%(levelname)s:%(filename)s:%(lineno)d:%(message)s")
42        hdlr.setFormatter(fmt)
43        self.log.addHandler(hdlr)
44
45        # Default options
46        self.here               = os.getcwd()
47        self.kits_dir           = self.here +'/kits' 
48        self.cache_dir          = self.here +'/cache'
49        self.rpm                = False 
50        self.minimal            = False
51        self.pacman_only        = False
52        self.override           = False
53        self.do_source_kit      = False
54        self.patch_dir          = ''
55        self.patch_requirements = ''
56        self.platform           = '' 
57        self.platform_suffix    = ''
58        self.tempprefix         = ''
59        self.tempfile1          = ''
60        self.tempfile2          = ''
61        self.tempcopydir        = ''
62        self.tempcmtusercontext = ''
63        self.patch_requirements = ''
64        self.release            = ''
65        self.cyclefile          = ''
66        self.url                = ''
67        self.pacman_base        = ''
68
69        # CMT setup
70        self.cmt        = CMT ()
71        self.cmtversion = self.cmt.do ('version')
72        self.log.info("cmtversion=%s", self.cmtversion)
73 
74##################################################################################################
75#----------------------------- get_options ------------------------------------------------------#
76##################################################################################################
77    def get_options (self, args):
78   
79        self.racine = os.path.dirname(os.path.realpath(args[0]))
80        try:
81            opts, args = getopt.getopt (args[1:] , 'r:c:P:mOp:osu:', 
82                                        ['release='  , 'cycles='       , 'patches=', 
83                                        'minimal'    , 'pacman_only'   , 'platform=', 
84                                        'override'   , 'source'        , 'url='])
85        except getopt.GetoptError:
86            # print help information and exit:
87            self.usage()
88            sys.exit(2)
89
90        for o,a in opts:
91            if o in ('-r', '--release'):
92                self.release = a
93            if o in ('-c', '--cycles'):
94                self.cyclefile = a
95            if o in ('-P', '--patches'):
96                self.patch_dir = a
97            if o in ('-m', '--minimal'):
98                self.minimal = True
99            if o in ('-O', '--pacman_only'):
100                self.pacman_only = True
101            if o in ('-p', '--platform'):
102                self.platform = a
103            if o in ('-o', '--override'):
104                self.override = True
105            if o in ('-s', '--source'):
106                self.do_source_kit = True
107            if o in ('-u', '--url'):
108                self.url = a
109        for a in args:
110            self.pacman_base = os.path.normpath (a)
111            self.cache_dir = os.path.join (self.pacman_base, os.path.normpath ('cache'))
112            self.kits_dir  = os.path.join (self.pacman_base, os.path.normpath ('kits'))
113##################################################################################################
114#----------------------------- make_pacman_cache ------------------------------------------------#
115##################################################################################################
116    def make_pacman_cache (self):
117        # Prepare the target pacman cache
118        if not os.path.isdir (self.cache_dir):
119            self.log.info('Creating %s', self.cache_dir)
120            os.makedirs (self.cache_dir)
121        if not os.path.isdir (self.kits_dir):
122            self.log.info('Creating %s', self.kits_dir)
123            os.makedirs (self.kits_dir)
124##################################################################################################           
125#------------------------------------ make_tempory_file -----------------------------------------#
126##################################################################################################
127    def make_tempory_file (self): 
128        # associate handler
129        #signal.signal(signal.SIG_DFL,  self.cleanup); # 0
130        #signal.signal(signal.SIG_IGN,  self.cleanup); # 1
131        signal.signal(signal.SIGINT,  self.cleanup); # 2
132        signal.signal(signal.SIGTERM, self.cleanup); # 15       
133        # Prepare temporary file management
134        self.log.debug('CMT %s', str(os.getpid ()))
135        self.log.debug('temprefix=%s', self.tempprefix)
136        self.tempfile1          = os.path.join (self.tempprefix, 't')
137        self.tempfile2          = os.path.join (self.tempprefix, 'u')
138        self.tempcopydir        = os.path.join (self.tempprefix, 'c')
139        self.tempcmtusercontext = os.path.join (self.tempprefix, 'd')
140        self.cleanup ()
141        os.makedirs (self.tempprefix)
142##################################################################################################           
143#-------------------------------- prepare_cmt_context -------------------------------------------#
144##################################################################################################
145    def prepare_cmt_context (self):
146        # Prepare the CMT and package context
147        h    = self.cmt.do ('show pwd')
148        root = os.path.dirname (h)
149        self.cmtversion = self.cmt.do ('version')
150        self.version    = self.cmt.macro_value ('version')
151        if self.version == 'v*':
152            self.version = 'v1'
153
154        self.log.debug('cmtversion=%s', self.cmtversion)
155        self.log.debug('version=%s',    self.version)
156       
157        self.package = self.cmt.macro_value ('package')
158        self.__normpath(self.package)
159       
160        self.cmtpath = self.cmt.macro_value (self.package + '_cmtpath')
161        self.__normpath (self.cmtpath)
162
163        self.offset = self.cmt.macro_value (self.package + '_offset')
164        self.__normpath (self.offset)
165
166        self.log.debug('package=%s', self.package)
167        self.log.debug('cmtpath=%s', self.cmtpath)
168        self.log.debug('offset=%s',  self.offset)
169     
170        self.project = self.cmt.macro_value (self.package + '_project')
171        self.log.debug('package_project=%s',  self.project)
172       
173        self.project_id = os.path.basename (self.project)
174        self.log.debug('project_id=%s',  self.project_id)
175       
176        self.release = self.cmt.macro_value (self.package + '_project_release')
177        self.log.debug('package_project_release=%s',  self.release)
178        self.log.debug('CMTPATH=%s',  self.cmt.macro_value ('CMTPATH'))
179       
180        if self.cmtpath == '':
181            self.cmtpath = os.path.normpath (self.cmt.macro_value (self.package + '_root'))
182            self.cmtpath = os.path.dirname (self.cmtpath)
183            self.cmtpath = os.path.dirname (self.cmtpath)
184
185        self.log.info('# Working on %s %s %s in %s project %s % s',\
186                       self.package, self.version, self.offset, \
187                       self.cmtpath, self.project, self.release)
188        self.cleanup ()       
189##################################################################################################
190#----------------------- prepare_patch_structure ------------------------------------------------#
191##################################################################################################
192    def prepare_patch_structure (self):
193        # Prepare the patch structure
194        if self.patch_dir != '':
195            if os.path.isdir (os.path.join (self.patch_dir, self.project_id)):
196                self.log.info("create_kit> %s/%s", self.patch_dir, self.project_id)
197                os.makedirs (self.tempcmtusercontext)
198                os.putenv   ('CMTUSERCONTEXT', self.tempcmtusercontext)
199                self.patch_requirements = os.path.join (self.tempcmtusercontext, \
200                                                        os.path.normpath ('requirements'))
201               
202                files = list () 
203                files.append (os.path.join (self.patch_dir, self.project_id)+'/requirements')
204                files.append (os.path.join (self.patch_dir, self.project_id)+self.package + \
205                             '/requirements')
206                # concatenate files
207                outfile = open(self.patch_requirements, 'w+')
208                for file in files:   
209                   if os.path.isfile(file):   
210                       file=open(file,'r')
211                       data=file.read()
212                       file.close()
213                       outfile.write(data)
214                outfile.close()
215##################################################################################################
216#--------------------------------- prepare_externals --------------------------------------------#
217##################################################################################################
218    def prepare_externals (self):
219        # Prepare the detection of external packages
220        self.native_version = self.cmt.macro_value (self.package + '_native_version')
221        self.export_paths   = self.cmt.macro_value (self.package + '_export_paths')
222        self.is_internal = self.export_paths == None
223        if self.do_source_kit:
224            self.is_internal = True
225##################################################################################################
226#------------------------------------------ prepare_temp ----------------------------------------#
227##################################################################################################
228    def prepare_temp (self):
229        # Prepare the temporary copies
230        os.makedirs (self.tempcopydir)
231        copycmd = 'ln -s'
232       
233        if self.do_source_kit:
234            self.acquire_sources()
235       
236##################################################################################################
237#------------------------------------------------------------------------------------------------#
238##################################################################################################
239    def generate_pacman(self):
240        # Generate the pacman file
241        self.build_pacman ()
242##################################################################################################
243#--------------------------------------- build_pacman -------------------------------------------#
244##################################################################################################
245    def build_pacman (self):
246        print self.url, self.package, self.version, self.cmtpath, self.project_id, self.is_internal
247        self.source = '../kits'
248        # External packages (those with export_paths) are split into two kits:
249        # o The internal part, which follows the naming convention for internal packages
250        # o The external part, which only refers to the package version (no mention of
251        #   the project)
252        # Naming cnvention:
253        #  external packages : <package>-<version>-<platform>
254        #  internal packages : <projectid>/<package>-<platform>
255
256        if not self.is_internal:
257            # first build the pacman file for the external stuff
258            if self.native_version == None:
259                cmd        = "echo "+self.version+" | sed -e 's#'^"+self.package+"-'##'"
260                status, vv = os.getstatusoutput(cmd)
261            else:
262                vv = self.native_version
263                self.download_filename="${package}-${vv}${platform_suffix}"
264            self.download_filename = self.package + '-' + vv + self.platform_suffix
265
266            self.pacman_filename = self.download_filename + '.pacman'
267           
268            print 'build_pacman> Create pacman file for external stuff ' + self.pacman_filename
269            file = os.path.join (self.cache_dir, self.pacman_filename)
270            self.pacman_file_version = self.get_pacman_file_version (file)
271            if os.path.isfile(file):
272                os.rename(file, file + ".bak")
273            # if test ! $? = 0; then
274            #   print 'create_kit> failed to rename ' + cache_dir + '/' + pacman_filename + ' to ' + cache_dir + '/' + pacman_filename' + '.bak'
275            #sys.exit(2)
276           
277        # write pacman file
278        f = open (file, 'w+')
279       
280        content = '''
281        description ('External Package %s %s %s %s')
282
283        source = '%s'
284        download = { '*':'%s.tar.gz' }       
285        '''%(self.package, self.version, self.platform, file, self.source, self.download_filename)
286        f.write (content)
287        f.close()
288       
289    # Figure out dependencies from CMT.
290    # Only take directly used packages, not those used indirectly;
291    # let pacman handle the cascade.
292    # Filter the requirements file patch if any to get the direct use statements.
293    # The cmt show uses does NOT show the use statements obtained from the CMTUSERCONTEXT thus
294    # they have to be added manually here.
295    #     
296        cmd = '''
297        `(if test ! "%s" = ""; then grep use %s | sed -e 's/use /# use /'; fi; cmt show uses) | cat | awk -f %s/get_depends.awk`'''%(self.patch_requirements, self.patch_requirements, self.racine)
298        status, self.depsv = commands.getstatusoutput(cmd)
299       
300        if os.path.isfile(self.cyclefile):
301            self.new_depsv= self.filter_deps(self.depsv)
302            if self.new_depsv == self.depsv:
303              print "Filtered dependencies: "
304              print "depsv", self.depsv
305              print "new_depsv", self.new_depsv
306              self.depsv=self.new_depsv
307       
308        if self.project_id == "":
309            self.release_id=self.release
310            vv=os.system("`echo "+self.version+" | sed -e 's#'^"+self.package+"-'##'`")
311        else:
312            self.release_id=self.project_id
313            vv=self.project_id
314
315        # Format the depend statement according to Pacman syntax
316        if self.depsv == "":
317            self.depends=""
318        else:
319            self.project_dep=os.system("`echo "+self.project+self.platform_suffix+" | sed -e 's#/#-#'`")
320   
321            if self.project_dep== "contrib-CMT"+self.platform_suffix:
322                self.project_dep = "CMTCONFIG-"+self.cmtversion+self.platform_suffix
323   
324        self.depends="package ('"+str(self.project_dep)+"')"
325        first=True
326        for f in self.depsv:
327            p=os.system  ("`echo "+f+" | cut -d: -f1`")
328            v=os.system  ("`echo "+f+" | cut -d: -f2`")
329            pp=os.system ("`echo "+f+" | cut -d: -f3 | sed -e 's#/$##'`")
330
331        # end build_pacman       
332##################################################################################################
333#------------------------------- usage ----------------------------------------------------------#
334##################################################################################################
335    def usage (self):
336        print "Make a distribution kit for a CMT package"
337        print "Usage: create_kit.sh [ <option> ... ] <pacman-cache>"
338        print " where option can be:"
339        print "  -r|--release <release-id>  : specify the release id"
340        print "  -c|--cycles <cycles-file>  : specify the cycles file"
341        print "  -P|--patches <patch-dir>   : specify a directory for patches "
342        print "  -m|--minimal               : only store CMT files into the tar ball"
343        print "  -O|--pacman_only           : do not generate the tar ball"
344        print "  -p|--platform <platform>   : specify a platform suffix"
345        print "  -o|--override              : override the existing tar balls"
346        print "  -s|--source                : generate the source kit"
347        print "Typical/example usage:"
348        print "  cmt broadcast create_kit.sh -release 6.3.0 -cycles ${DEP}/cycles.txt /tmp "
349        # end usage
350##################################################################################################
351#--------------------------------------- __normpath ---------------------------------------------#
352##################################################################################################
353    def __normpath (self, path):
354        if path != '':
355            path = os.path.normpath (path)   
356##################################################################################################
357#-------------------------------------- __del__ -------------------------------------------------#
358##################################################################################################
359    def __del__ (self):
360        self.cleanup()     
361##################################################################################################   
362#----------------------------- cleanup ----------------------------------------------------------#
363##################################################################################################
364    def cleanup (self):
365        self.log.info('Cleanup')
366        self.cmt.removedirs (self.tempprefix)
367##################################################################################################
368#------------------------------ get_project -----------------------------------------------------#
369##################################################################################################
370    def get_project (self):
371        if self.cmtpath != '':
372            rr = os.path.basename (self.cmtpath)
373            pr = os.path.dirname (self.cmtpath)
374            pr = os.path.basename (pr)
375            return os.path.join (pr, rr)
376        else:
377            self.log.error('CMTPATH empty')
378            sys.exit(-1)
379##################################################################################################
380#------------------------------------------------------------------------------------------------#
381##################################################################################################
382    def get_libraries (self):
383        pass               
384##################################################################################################
385#---------------------------- get_pacman_file_version -------------------------------------------#
386##################################################################################################       
387    def get_pacman_file_version(self, old_file):
388        pacman_file_version=1
389        if os.path.isfile(old_file):
390            cmd = "grep description "+old_file+" | egrep '[(]v' | sed -e 's#.*(v##' -e 's#).*##'"
391            status, pacman_file_version = commands.getstatusoutput (cmd)
392           
393        if pacman_file_version == "":
394            pacman_file_version=1
395        else:
396            pacman_file_version=int(pacman_file_version) + 1
397
398        return "v"+str(pacman_file_version) 
399##################################################################################################
400#---------------------------------------- filter_deps -------------------------------------------#
401##################################################################################################
402    def filter_deps (self, deps):
403        #  filter_deps <cyclefile> <p> <p> ...
404        #  Remove from the list of <p>s all entries found in the cyclefile
405        cmd = "`cat "+self.cyclefile+" | awk '{if ($NF == \"'"+self.package+"'\") {print "+deps[0]+"}}'`"
406        status, cycles = commands.getstatusoutput (cmd)
407 
408        for f in deps: 
409            found = 0
410            cmd   = "`echo "+f+" | cut -d: -f1`"
411            status, p = commands.getstatusoutput (cmd)
412 
413        for c in cycles:
414            if c == p:
415                found=1
416        if found:
417            return f
418##################################################################################################
419#---------------------------------------- acquire_sources ---------------------------------------#
420##################################################################################################
421    def acquire_sources (self):
422
423        self.log.info("Now acquiring sources")
424        f      = open ('../CVS/Repository','r')
425        module = f.read() 
426        f.close()
427       
428        self.log.debug("version=%s"    , self.version)
429        self.log.debug("package=%s"    , self.package)
430        self.log.debug("offset=%s"     , self.offset)
431        self.log.debug("project=%s"    , self.project)
432        self.log.debug("kits_dir=%s"   , self.kits_dir)
433        self.log.debug("tempcopydir=%s", self.tempcopydir)
434       
435        self.project_id   = os.path.basename (self.project)
436        self.project_name = os.path.dirname  (self.project)
437
438        os.removedirs (self.tempcopydir)
439        os.makedirs   (self.tempcopydir+"/"+self.project+"/"+self.offset)
440
441        self.log.info("Now exporting the sources from CVS")
442        os.chdir(self.tempcopydir+"/"+self.project)
443        cmd = "cvs export -r "+self.version+" -d "+self.offset+self.package+" "+self.module
444        self.log.debug(str(os.listdir(self.tempcopydir)))
445
446        self.log.info("Now constructing the source tar ball")
447        os.makedirs (self.kits_dir+"/"+self.project_id)
448        os.chdir(self.tempcopydir)
449       
450        name = self.kits_dir+"/"+self.project_id+"/"+self.package+"-src.tar.gz" 
451        self.log.debug("tar ball name=%s" , name)
452        tarball = tarfile.open (name=name , mode='w:gz')
453        tarball.add            (name='.')
454        tarball.close          ()
455
456        if self.debug:
457            tarball = tarfile.open (name=name , mode='r:gz')
458            self.log.debug('tar ball content:%s', str(tarball.list ())
459            tarball.close ()
460##################################################################################################
461#---------------------------------- acquire_CMT_files -------------------------------------------#
462##################################################################################################           
463    def acquire_CMT_files (self):
464        #  Acquire the CMT files (requirements + make_fragments) file
465        #  Result is stored (symlinked) in ${tempcopydir}/cmt
466     
467#  echo `pwd` >${tempfile1}
468#  if test -d ../fragments; then
469#    up=`(cd ..; pwd)`
470#    echo ${up}/fragments >>${tempfile1}
471#  fi
472#
473#  if test -f version.cmt; then
474#    versiondir=""
475#  else
476#    versiondir="/${version}"
477#  fi
478#
479#  tempcmtbase=${project}/${offset}${package}${versiondir}
480#
481#  macro_value ${package}_CMT_files >>${tempfile1}
482#
483#  old_copycmd=${copycmd}
484#  copycmd="cp -r"
485#
486#  transfer_files "CMT files" ${tempfile1} ${tempcmtbase}
487#
488#  copycmd=${old_copycmd}
489#
490#  chmod -R +w ${tempcopydir}/${tempcmtbase}/cmt
491#  (cd ${tempcopydir}/${tempcmtbase}/cmt;
492#   eval "/bin/rm -f setup.* cleanup.* *make* Makefile")
493#
494#  if test ! "${patch_requirements}" = ""; then
495#    echo "create_kit> Patching requirements file with ${patch_requirements}"
496#    cat requirements ${patch_requirements} >|${tempcopydir}/${tempcmtbase}/cmt/requirements
497#  fi
498#}
499##################################################################################################
500#---------------------------------- transfer_files ----------------------------------------------#
501##################################################################################################
502    def transfer_files (self, kind, list, branch):
503        alt=
504        dir_prefix=
505
506        if os.path.isfile(list): return 
507#       
508#  cmt -quiet filter ${list} ${tempfile2}; mv ${tempfile2} ${list}
509#  sort -u ${list} >${tempfile2}; mv ${tempfile2} ${list}
510#
511#  n=`wc -w ${list} | awk '{print $1}'`
512#  if test "${n}" = 0; then
513#    /bin/rm -f ${list}
514#    return
515#  fi
516#
517#  echo "create_kit> Now acquiring ${kind}"
518#
519
520#  for f in `cat ${list} | sort -u`; do
521#
522#    alt=`echo ${f} | egrep '^[-]s='`
523#
524#    if test ! "${alt}" = ""; then
525#      alt=
526#      dir_prefix=`echo ${f} | sed -e 's#^[-]s=##'`
527#    else
528#
529#      test_absolute=`echo ${f} | egrep '^/'`
530#
531#      if test ! $? = 0; then
532#        if test ! "${dir_prefix}" = ""; then
533#          f=${dir_prefix}/${f}
534#        fi
535#      fi
536#
537#      ##echo "1) $f"
538#
539#      n=`(set -f; basename ${f})`
540#      d=`(set -f; dirname ${f})`
541#
542#      if test -d ${d}; then
543#        d=`(cd ${d}; pwd)`
544#        ff=${d}/${n}
545#
546#        #echo "2) $ff ${tempcopydir}/${branch} d=${d}"
547#
548#        mkdir -p ${tempcopydir}/${branch}
549#
550#        is_dir=0
551#        if test "`(set -f; echo ${ff}) | grep '[*]'`" = ""; then
552#          if test -d `(set -f; echo ${ff})`; then
553#            is_dir=1
554#          fi
555#        fi
556#
557#        ##------------------------------------
558#        ## We compare ${d} and ${branch}
559#        ## is ${branch} strictly included in ${d} ?
560#        ## if yes, compute the offset to be added to ${branch}
561#        ##
562#
563#        off=
564#
565#        aaa=`echo ${d} | grep -e ${branch}`
566#
567#        if test $? = 0; then
568#          # echo "There may be an offset d=${d} branch=${branch}"
569#          off=`echo "${d}" | sed -e 's#.*'"${branch}"'##' -e 's#^[/]##g'`
570#          if test ! "${off}" = ""; then
571#            off="/${off}"
572#            mkdir -p ${tempcopydir}/${branch}${off}
573#          fi
574#          ##echo "off=${off}"
575#        fi
576#
577#        ##echo "3) is_dir=$is_dir"
578#
579#        if test ${is_dir} = 1; then
580#          ##echo "  > directory ${ff}"
581#
582#          ##echo "4) copycmd=[$copycmd]"
583#
584#          ${copycmd} ${ff} ${tempcopydir}/${branch}${off}/${n}
585#        else
586#          a=`eval "ls ${ff} 2>/dev/null"`
587#
588#          ##echo "4) a=[$a]"
589#
590#          for g in `echo ${a}`; do
591#            nn=`basename ${g}`
592#            ##echo "  > file ${g} branch=${branch}${off}"
593#            if test ! -e ${tempcopydir}/${branch}${off}/${nn}; then
594#              ${copycmd} ${g} ${tempcopydir}/${branch}${off}/${nn}
595#           fi
596#          done
597#        fi
598#      else
599#        echo "create_kit> Warning: Directory ${d} not found for file ${f}"
600#      fi
601#    fi
602#  done
603#
604#  /bin/rm -f ${list}
605         
606##################################################################################################
607#----------------------------------      END       ----------------------------------------------#
608##################################################################################################
Note: See TracBrowser for help on using the repository browser.