Second step towards multiarch myplc https://svn.planet-lab.org/ticket/214
[build.git] / module-tag.py
index 26dfb0e..213f2ba 100755 (executable)
@@ -75,7 +75,7 @@ class Command:
         result=file(tmp).read()
         os.unlink(tmp)
         if self.options.debug:
-            print '+',self.command,'Done',
+            print 'Done',
         return result
 
 class Svnpath:
@@ -98,19 +98,31 @@ class Svnpath:
 
 class Module:
 
+    svn_magic_line="--This line, and those below, will be ignored--"
+    
+    redirectors=[ # ('module_name_varname','name'),
+                  ('module_version_varname','version'),
+                  ('module_taglevel_varname','taglevel'), ]
+
     # where to store user's config
     config_storage="CONFIG"
     # 
-    configKeys=[ ('svnpath',"Enter your toplevel svnpath (e.g. svn+ssh://thierry@svn.planet-lab.org/svn/)"),
-                 ('username',"Enter your firstname and lastname for changelogs"),
-                 ("email","Enter your email address for changelogs") ]
     config={}
 
-    svn_magic_line="--This line, and those below, will be ignored--"
-    
-    redirectors=[ ('module_name_varname','name'),
-                  ('module_version_varname','version'),
-                  ('module_taglevel_varname','taglevel'), ]
+    import commands
+    configKeys=[ ('svnpath',"Enter your toplevel svnpath",
+                  "svn+ssh://%s@svn.planet-lab.org/svn/"%commands.getoutput("id -un")),
+                 ("build", "Enter the name of your build module","build"),
+                 ('username',"Enter your firstname and lastname for changelogs",""),
+                 ("email","Enter your email address for changelogs",""),
+                 ]
+
+    @staticmethod
+    def prompt_config ():
+        for (key,message,default) in Module.configKeys:
+            Module.config[key]=""
+            while not Module.config[key]:
+                Module.config[key]=raw_input("%s [%s] : "%(message,default)).strip() or default
 
     def __init__ (self,name,options):
         self.name=name
@@ -138,15 +150,29 @@ class Module:
         if options.verbose:
             print 'Checking for',topdir
         storage="%s/%s"%(topdir,Module.config_storage)
+        # sanity check. Either the topdir exists AND we have a config/storage
+        # or topdir does not exist and we create it
+        # to avoid people use their own daily svn repo
+        if os.path.isdir(topdir) and not os.path.isfile(storage):
+            print """The directory %s exists and has no CONFIG file
+If this is your regular working directory, please provide another one as the
+module-* commands need a fresh working dir. Make sure that you do not use 
+that for other purposes than tagging"""%topdir
+            sys.exit(1)
         if not os.path.isdir (topdir):
-            # prompt for login or whatever svnpath
             print "Cannot find",topdir,"let's create it"
-            for (key,message) in Module.configKeys:
-                Module.config[key]=raw_input(message+" : ").strip()
+            Module.prompt_config()
+            print "Checking ...",
             Command("svn co -N %s %s"%(Module.config['svnpath'],topdir),options).run_fatal()
+            Command("svn co -N %s/%s %s/%s"%(Module.config['svnpath'],
+                                             Module.config['build'],
+                                             topdir,
+                                             Module.config['build']),options).run_fatal()
+            print "OK"
+            
             # store config
             f=file(storage,"w")
-            for (key,message) in Module.configKeys:
+            for (key,message,default) in Module.configKeys:
                 f.write("%s=%s\n"%(key,Module.config[key]))
             f.close()
             if options.debug:
@@ -159,10 +185,10 @@ class Module:
                 (key,value)=re.compile("^(.+)=(.+)$").match(line).groups()
                 Module.config[key]=value                
             f.close()
-            if options.debug:
-                print 'Using config'
-                for (key,message) in Module.configKeys:
-                    print key,'=',Module.config[key]
+        if options.verbose:
+            print '******** Using config'
+            for (key,message,default) in Module.configKeys:
+                print '\t',key,'=',Module.config[key]
 
     def init_moddir (self):
         if self.options.verbose:
@@ -190,9 +216,9 @@ class Module:
             return
         if self.options.verbose:
             print 'Updating',self.trunkdir
-        self.run_fatal("svn update %s"%self.trunkdir)
+        self.run_fatal("svn update -N %s"%self.trunkdir)
 
-    def guess_specname (self):
+    def main_specname (self):
         attempt="%s/%s.spec"%(self.trunkdir,self.name)
         if os.path.isfile (attempt):
             return attempt
@@ -203,6 +229,9 @@ class Module:
                 print 'Cannot guess specfile for module %s'%self.name
                 sys.exit(1)
 
+    def all_specnames (self):
+        return glob("%s/*.spec"%self.trunkdir)
+
     def parse_spec (self, specfile, varnames):
         if self.options.debug:
             print 'parse_spec',specfile,
@@ -224,7 +253,7 @@ class Module:
     # stores in self.module_name_varname the rpm variable to be used for the module's name
     # and the list of these names in self.varnames
     def spec_dict (self):
-        specfile=self.guess_specname()
+        specfile=self.main_specname()
         redirector_keys = [ varname for (varname,default) in Module.redirectors]
         redirect_dict = self.parse_spec(specfile,redirector_keys)
         if self.options.debug:
@@ -244,23 +273,23 @@ class Module:
         return result
 
     def patch_spec_var (self, patch_dict):
-        specfile=self.guess_specname()
-        newspecfile=specfile+".new"
-        if self.options.verbose:
-            print 'Patching',specfile,'for',patch_dict.keys()
-        spec=open (specfile)
-        new=open(newspecfile,"w")
-
-        for line in spec.readlines():
-            if self.varmatcher.match(line):
-                (var,value)=self.varmatcher.match(line).groups()
-                if var in patch_dict.keys():
-                    new.write('%%define %s %s\n'%(var,patch_dict[var]))
-                    continue
-            new.write(line)
-        spec.close()
-        new.close()
-        os.rename(newspecfile,specfile)
+        for specfile in self.all_specnames():
+            newspecfile=specfile+".new"
+            if self.options.verbose:
+                print 'Patching',specfile,'for',patch_dict.keys()
+            spec=open (specfile)
+            new=open(newspecfile,"w")
+
+            for line in spec.readlines():
+                if self.varmatcher.match(line):
+                    (var,value)=self.varmatcher.match(line).groups()
+                    if var in patch_dict.keys():
+                        new.write('%%define %s %s\n'%(var,patch_dict[var]))
+                        continue
+                new.write(line)
+            spec.close()
+            new.close()
+            os.rename(newspecfile,specfile)
 
     def unignored_lines (self, logfile):
         result=[]
@@ -273,27 +302,27 @@ class Module:
         return result
 
     def insert_changelog (self, logfile, oldtag, newtag):
-        specfile=self.guess_specname()
-        newspecfile=specfile+".new"
-        if self.options.verbose:
-            print 'Inserting changelog from %s into %s'%(logfile,specfile)
-        spec=open (specfile)
-        new=open(newspecfile,"w")
-        for line in spec.readlines():
-            new.write(line)
-            if re.compile('%changelog').match(line):
-                dateformat="* %a %b %d %Y"
-                datepart=time.strftime(dateformat)
-                logpart="%s <%s> - %s %s"%(Module.config['username'],
-                                             Module.config['email'],
-                                             oldtag,newtag)
-                new.write(datepart+" "+logpart+"\n")
-                for logline in self.unignored_lines(logfile):
-                    new.write("- " + logline)
-                new.write("\n")
-        spec.close()
-        new.close()
-        os.rename(newspecfile,specfile)
+        for specfile in self.all_specnames():
+            newspecfile=specfile+".new"
+            if self.options.verbose:
+                print 'Inserting changelog from %s into %s'%(logfile,specfile)
+            spec=open (specfile)
+            new=open(newspecfile,"w")
+            for line in spec.readlines():
+                new.write(line)
+                if re.compile('%changelog').match(line):
+                    dateformat="* %a %b %d %Y"
+                    datepart=time.strftime(dateformat)
+                    logpart="%s <%s> - %s %s"%(Module.config['username'],
+                                                 Module.config['email'],
+                                                 oldtag,newtag)
+                    new.write(datepart+" "+logpart+"\n")
+                    for logline in self.unignored_lines(logfile):
+                        new.write("- " + logline)
+                    new.write("\n")
+            spec.close()
+            new.close()
+            os.rename(newspecfile,specfile)
             
     def show_dict (self, spec_dict):
         if self.options.verbose:
@@ -303,7 +332,8 @@ class Module:
     def trunk_url (self):
         return "%s/%s/trunk"%(Module.config['svnpath'],self.name)
     def tag_name (self, spec_dict):
-        return "%s-%s-%s"%(spec_dict[self.module_name_varname],
+        return "%s-%s-%s"%(#spec_dict[self.module_name_varname],
+                           self.name,
                            spec_dict[self.module_version_varname],
                            spec_dict[self.module_taglevel_varname])
     def tag_url (self, spec_dict):
@@ -316,12 +346,11 @@ class Module:
         self.revert_trunkdir()
         self.update_trunkdir()
         print '==============================',self.name
-        #for (key,message) in Module.configKeys:
-        #    print key,':',Module.config[key]
         spec_dict = self.spec_dict()
         print 'trunk url',self.trunk_url()
         print 'latest tag url',self.tag_url(spec_dict)
-        print 'specfile:',self.guess_specname()
+        print 'main specfile:',self.main_specname()
+        print 'specfiles:',self.all_specnames()
         for varname in self.varnames:
             if not spec_dict.has_key(varname):
                 print 'Could not find %%define for %s'%varname
@@ -446,11 +475,11 @@ The module-init function has the following limitations
         # so we can provide useful information, such as version numbers and diff
         # in the same file
         changelog="/tmp/%s-%d.txt"%(self.name,os.getpid())
-        file(changelog,"w").write("""Tagging module %s  -- from %s to %s
+        file(changelog,"w").write("""Tagging module %s - %s
 
 %s
 Please write a changelog for this new tag in the section above
-"""%(self.name,old_tag_name,new_tag_name,Module.svn_magic_line))
+"""%(self.name,new_tag_name,Module.svn_magic_line))
 
         if not self.options.verbose or prompt('Want to see diffs while writing changelog',True):
             file(changelog,"a").write('DIFF=========\n' + diff_output)
@@ -465,7 +494,11 @@ Please write a changelog for this new tag in the section above
             self.insert_changelog (changelog,old_tag_name,new_tag_name)
 
         ## update build
-        build = Module(self.options.build,self.options)
+        try:
+            buildname=Module.config['build']
+        except:
+            buildname="build"
+        build = Module(buildname,self.options)
         build.init_moddir()
         build.init_trunkdir()
         build.revert_trunkdir()
@@ -490,8 +523,9 @@ Please write a changelog for this new tag in the section above
 usage="""Usage: %prog options module1 [ .. modulen ]
 Purpose:
   manage subversion tags and specfile
-  requires the specfile to define name, version and taglevel
-  OR alternatively redirection variables like module_version_varname
+  requires the specfile to define version and taglevel
+  OR alternatively 
+  redirection variables module_version_varname / module_taglevel_varname
 """
 functions={ 
     'diff' : "show difference between trunk and latest tag",
@@ -543,9 +577,8 @@ def main():
                           help="just list modules that exhibit differences")
     parser.add_option("-w","--workdir", action="store", dest="workdir", 
                       default="%s/%s"%(os.getenv("HOME"),"modules"),
-                      help="name for workdir - defaults to ~/modules")
-    parser.add_option("-B","--build", action="store", dest="build", default="build",
-                      help="set module name for build, defaults to build")
+                      help="""name for dedicated working dir - defaults to ~/modules
+** THIS MUST NOT ** be your usual working directory""")
     parser.add_option("-v","--verbose", action="store_true", dest="verbose", default=False, 
                       help="run in verbose mode")
     parser.add_option("-d","--debug", action="store_true", dest="debug", default=False,