Package buildbot :: Package scripts :: Module base
[frames] | no frames]

Source Code for Module buildbot.scripts.base

  1  # This file is part of Buildbot.  Buildbot is free software: you can 
  2  # redistribute it and/or modify it under the terms of the GNU General Public 
  3  # License as published by the Free Software Foundation, version 2. 
  4  # 
  5  # This program is distributed in the hope that it will be useful, but WITHOUT 
  6  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  8  # details. 
  9  # 
 10  # You should have received a copy of the GNU General Public License along with 
 11  # this program; if not, write to the Free Software Foundation, Inc., 51 
 12  # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 13  # 
 14  # Copyright Buildbot Team Members 
 15   
 16  from __future__ import with_statement 
 17   
 18  import os 
 19  import copy 
 20  import stat 
 21  from twisted.python import usage, runtime 
 22   
23 -def isBuildmasterDir(dir):
24 buildbot_tac = os.path.join(dir, "buildbot.tac") 25 if not os.path.isfile(buildbot_tac): 26 print "no buildbot.tac" 27 return False 28 29 with open(buildbot_tac, "r") as f: 30 contents = f.read() 31 return "Application('buildmaster')" in contents
32
33 -class SubcommandOptions(usage.Options):
34 # subclasses should set this to a list-of-lists in order to source the 35 # .buildbot/options file. Note that this *only* works with optParameters, 36 # not optFlags. Example: 37 # buildbotOptions = [ [ 'optfile-name', 'parameter-name' ], .. ] 38 buildbotOptions = None 39 40 # set this to options that must have non-None values 41 requiredOptions = [] 42
43 - def __init__(self, *args):
44 # for options in self.buildbotOptions, optParameters, and the options 45 # file, change the default in optParameters to the value in the options 46 # file, call through to the constructor, and then change it back. 47 # Options uses reflect.accumulateClassList, so this *must* be a class 48 # attribute; however, we do not want to permanently change the class. 49 # So we patch it temporarily and restore it after. 50 cls = self.__class__ 51 if hasattr(cls, 'optParameters'): 52 old_optParameters = cls.optParameters 53 cls.optParameters = op = copy.deepcopy(cls.optParameters) 54 if self.buildbotOptions: 55 optfile = self.optionsFile = self.loadOptionsFile() 56 for optfile_name, option_name in self.buildbotOptions: 57 for i in range(len(op)): 58 if (op[i][0] == option_name 59 and optfile_name in optfile): 60 op[i] = list(op[i]) 61 op[i][2] = optfile[optfile_name] 62 usage.Options.__init__(self, *args) 63 if hasattr(cls, 'optParameters'): 64 cls.optParameters = old_optParameters
65
66 - def loadOptionsFile(self, _here=None):
67 """Find the .buildbot/options file. Crawl from the current directory 68 up towards the root, and also look in ~/.buildbot . The first directory 69 that's owned by the user and has the file we're looking for wins. 70 Windows skips the owned-by-user test. 71 72 @rtype: dict 73 @return: a dictionary of names defined in the options file. If no 74 options file was found, return an empty dict. 75 """ 76 77 here = _here or os.path.abspath(os.getcwd()) 78 79 if runtime.platformType == 'win32': 80 # never trust env-vars, use the proper API 81 from win32com.shell import shellcon, shell 82 appdata = shell.SHGetFolderPath(0, shellcon.CSIDL_APPDATA, 0, 0) 83 home = os.path.join(appdata, "buildbot") 84 else: 85 home = os.path.expanduser("~/.buildbot") 86 87 searchpath = [] 88 toomany = 20 89 while True: 90 searchpath.append(os.path.join(here, ".buildbot")) 91 next = os.path.dirname(here) 92 if next == here: 93 break # we've hit the root 94 here = next 95 toomany -= 1 # just in case 96 if toomany == 0: 97 print ("I seem to have wandered up into the infinite glories " 98 "of the heavens. Oops.") 99 break 100 101 searchpath.append(home) 102 103 localDict = {} 104 105 for d in searchpath: 106 if os.path.isdir(d): 107 if runtime.platformType != 'win32': 108 if os.stat(d)[stat.ST_UID] != os.getuid(): 109 print "skipping %s because you don't own it" % d 110 continue # security, skip other people's directories 111 optfile = os.path.join(d, "options") 112 if os.path.exists(optfile): 113 try: 114 with open(optfile, "r") as f: 115 options = f.read() 116 exec options in localDict 117 except: 118 print "error while reading %s" % optfile 119 raise 120 break 121 122 for k in localDict.keys(): 123 if k.startswith("__"): 124 del localDict[k] 125 return localDict
126
127 - def postOptions(self):
128 missing = [ k for k in self.requiredOptions if self[k] is None ] 129 if missing: 130 if len(missing) > 1: 131 msg = 'Required arguments missing: ' + ', '.join(missing) 132 else: 133 msg = 'Required argument missing: ' + missing[0] 134 raise usage.UsageError(msg)
135
136 -class BasedirMixin(object):
137 138 """SubcommandOptions Mixin to handle subcommands that take a basedir 139 argument""" 140
141 - def parseArgs(self, *args):
142 if len(args) > 0: 143 self['basedir'] = args[0] 144 else: 145 # Use the current directory if no basedir was specified. 146 self['basedir'] = os.getcwd() 147 if len(args) > 1: 148 raise usage.UsageError("I wasn't expecting so many arguments")
149
150 - def postOptions(self):
151 # get an unambiguous, epxnaed basedir, including expanding '~', which 152 # may be useful in a .buildbot/config file 153 self['basedir'] = os.path.abspath(os.path.expanduser(self['basedir']))
154