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

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

correct some error message

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