import xml.etree.cElementTree as ElementTree
from osc import conf, core
-def flag2bool(flag):
+class _Metafile:
"""
- flag2bool(flag) -> Boolean
-
- Returns a boolean corresponding to the string 'enable', or 'disable'
- """
- if flag == 'enable':
- return True
- elif flag == 'disable':
- return False
-
-def bool2flag(b):
- """
- bool2flag(b) -> String
-
- Returns 'enable', or 'disable' according to boolean value b
- """
- if b == True:
- return 'enable'
- elif b == False:
- return 'disable'
-
-
-class metafile:
- """
- metafile(url, input, change_is_required=False, file_ext='.xml')
+ _Metafile(url, input, change_is_required=False, file_ext='.xml')
Implementation on osc.core.metafile that does not print to stdout
"""
+
def __init__(self, url, input, change_is_required=False, file_ext='.xml'):
self.url = url
self.change_is_required = change_is_required
os.unlink(self.filename)
return True
+# helper functions for class _ProjectFlags
+def _flag2bool(flag):
+ """
+ _flag2bool(flag) -> Boolean
+ Returns a boolean corresponding to the string 'enable', or 'disable'
+ """
+
+ if flag == 'enable':
+ return True
+ elif flag == 'disable':
+ return False
+
+def _bool2flag(b):
+ """
+ _bool2flag(b) -> String
+
+ Returns 'enable', or 'disable' according to boolean value b
+ """
+ if b == True:
+ return 'enable'
+ elif b == False:
+ return 'disable'
+
+class _ProjectFlags(object):
+ """
+ _ProjectFlags(bs, project)
+
+ Represents the flags in project through the BuildService object bs
+ """
+
+ def __init__(self, bs, project):
+ self.bs = bs
+ self.tree = ElementTree.fromstring(self.bs.getProjectMeta(project))
+
+ # The "default" flags, when undefined
+ self.defaultflags = {'build': True,
+ 'publish': True,
+ 'useforbuild': True,
+ 'debuginfo': False}
+
+ # Figure out what arches and repositories are defined
+ self.arches = {}
+ self.repositories = {}
+
+ # Build individual repository list
+ for repository in self.tree.findall('repository'):
+ repodict = {'arches': {}}
+ self.__init_flags_in_dict(repodict)
+ for arch in repository.findall('arch'):
+ repodict['arches'][arch.text] = {}
+ self.__init_flags_in_dict(repodict['arches'][arch.text])
+ # Add placeholder in global arches
+ self.arches[arch.text] = {}
+ self.repositories[repository.get('name')] = repodict
+
+ # Initialise flags in global arches
+ for archdict in self.arches.values():
+ self.__init_flags_in_dict(archdict)
+
+ # A special repository representing the global and global arch flags
+ self.allrepositories = {'arches': self.arches}
+ self.__init_flags_in_dict(self.allrepositories)
+
+ # Now populate the structures from the xml data
+ for flagtype in ('build', 'publish', 'useforbuild', 'debuginfo'):
+ flagnode = self.tree.find(flagtype)
+ if flagnode:
+ for node in flagnode:
+ repository = node.get('repository')
+ arch = node.get('arch')
+
+ if repository and arch:
+ self.repositories[repository]['arches'][arch][flagtype] = _flag2bool(node.tag)
+ elif repository:
+ self.repositories[repository][flagtype] = _flag2bool(node.tag)
+ elif arch:
+ self.arches[flagtype] = _flag2bool(node.tag)
+ else:
+ self.allrepositories[flagtype] = _flag2bool(node.tag)
+
+ def __init_flags_in_dict(self, d):
+ """
+ __init_flags_in_dict(d)
+
+ Initialize all build flags to None in d
+ """
+ d.update({'build': None,
+ 'publish': None,
+ 'useforbuild': None,
+ 'debuginfo': None})
+
+ def save(self):
+ """
+ save()
+
+ Save flags
+ """
+
+ for flagtype in ('build', 'publish', 'useforbuild', 'debuginfo'):
+ # Clear if set
+ flagnode = self.tree.find(flagtype)
+ if flagnode:
+ self.tree.remove(flagnode)
+
+ # Generate rule nodes
+ rulenodes = []
+
+ # globals
+ if self.allrepositories[flagtype] != None:
+ rulenodes.append(ElementTree.Element(_bool2flag(self.allrepositories[flagtype])))
+ for arch in self.arches:
+ if self.arches[arch][flagtype] != None:
+ rulenodes.append(ElementTree.Element(_bool2flag(self.arches[arch][flagtype]), arch=arch))
+
+ # repositories
+ for repository in self.repositories:
+ if self.repositories[repository][flagtype] != None:
+ rulenodes.append(ElementTree.Element(_bool2flag(self.repositories[repository][flagtype]), repository=repository))
+ for arch in self.repositories[repository]['arches']:
+ if self.repositories[repository]['arches'][arch][flagtype] != None:
+ rulenodes.append(ElementTree.Element(_bool2flag(self.repositories[repository]['arches'][arch][flagtype]), arch=arch, repository=repository))
+
+ # Add nodes to tree
+ if rulenodes:
+ from pprint import pprint
+ pprint(rulenodes)
+ flagnode = ElementTree.Element(flagtype)
+ self.tree.insert(3, flagnode)
+ for rulenode in rulenodes:
+ flagnode.append(rulenode)
+
+ print ElementTree.tostring(self.tree)
+
class BuildService():
"Interface to Build Service API"
- def __init__(self, apiurl=None, oscrc=None):
+ def __init__(self, apiurl=None, oscrc=None):
if oscrc:
try:
conf.get_config(override_conffile = oscrc)
return self.genRequestInfo(reqid, show_detail)
def isNewPackage(self, dst_project, dst_package):
- # Check whether the dst pac is a new one
+ """Check whether the dst pac is a new one
+ """
+
new_pkg = False
try:
core.meta_exists(metatype = 'pkg',
return new_pkg
def genRequestInfo(self, reqid, show_detail = True):
+ """Generate formated diff info for request,
+ mainly used by notification mails from BOSS
+ """
- def gen_request_diff():
+ def _gen_request_diff():
""" Recommanded getter: request_diff can get req diff info even if req is accepted/declined
"""
reqdiff = ''
return reqdiff
- def gen_server_diff(req):
+ def _gen_server_diff(req):
""" Reserved getter: get req diff, if and only if the recommanded getter failed
"""
reqdiff = ''
return reqdiff
+ ####################################
+ # function implementation start here
+
req = core.get_request(self.apiurl, reqid)
try:
req.reviews = []
reqinfo = u''
if show_detail:
- diff = gen_request_diff()
+ diff = _gen_request_diff()
if diff is None:
- diff = gen_server_diff(req)
+ diff = _gen_server_diff(req)
reqinfo += diff
watchlist = ElementTree.SubElement(person, 'watchlist')
ElementTree.SubElement(watchlist, 'project', name=str(project))
- f = metafile(url, ElementTree.tostring(person))
+ f = _Metafile(url, ElementTree.tostring(person))
f.sync()
def unwatchProject(self, project):
watchlist.remove(node)
break
- f = metafile(url, ElementTree.tostring(person))
+ f = _Metafile(url, ElementTree.tostring(person))
f.sync()
def getRepoState(self, project):
return status
def getProjectDiff(self, src_project, dst_project):
+ diffs = []
+
packages = self.getPackageList(src_project)
for src_package in packages:
diff = core.server_diff(self.apiurl,
dst_project, src_package, None,
src_project, src_package, None, False)
- print diff
+ diffs.append(diff)
+
+ return '\n'.join(diffs)
def getPackageList(self, prj, deleted=None):
query = {}
Returns a list of binaries for a particular target and package
"""
+
(repo, arch) = target.split('/')
return core.get_binarylist(self.apiurl, project, repo, arch, package)
Get binary 'file' for 'project' and 'target' and save it as 'path'
"""
+
(repo, arch) = target.split('/')
core.get_binary_file(self.apiurl, project, repo, arch, file, target_filename=path, package=package)
If offset is greater than 0, return only text after that offset. This allows live streaming
"""
+
(repo, arch) = target.split('/')
u = core.makeurl(self.apiurl, ['build', project, repo, arch, package, '_log?nostream=1&start=%s' % offset])
return core.http_GET(u).read()
'hostarch', and 'status'. If the worker is building, the dict will additionally contain the
keys 'project', 'package', 'target', and 'starttime'
"""
+
url = core.makeurl(self.apiurl, ['build', '_workerstatus'])
f = core.http_GET(url)
tree = ElementTree.parse(f).getroot()
Returns the number of jobs in the wait queue as a list of (arch, count)
pairs
"""
+
url = core.makeurl(self.apiurl, ['build', '_workerstatus'])
f = core.http_GET(url)
tree = ElementTree.parse(f).getroot()
getSubmitRequests() -> list of dicts
"""
+
url = core.makeurl(self.apiurl, ['search', 'request', '?match=submit'])
f = core.http_GET(url)
tree = ElementTree.parse(f).getroot()
Rebuild 'package' in 'project' for 'target'. If 'code' is specified,
all targets with that code will be rebuilt
"""
+
if target:
(repo, arch) = target.split('/')
else:
Abort build of a package or all packages in a project
"""
+
if target:
(repo, arch) = target.split('/')
else:
Get build history of package for target as a list of tuples of the form
(time, srcmd5, rev, versrel, bcnt)
"""
+
(repo, arch) = target.split('/')
u = core.makeurl(self.apiurl, ['build', project, repo, arch, package, '_history'])
f = core.http_GET(u)
Each log is a tuple of the form (rev, srcmd5, version, time, user,
comment)
"""
+
u = core.makeurl(self.apiurl, ['source', project, package, '_history'])
f = core.http_GET(u)
root = ElementTree.parse(f).getroot()
Get XML metadata for project
"""
+
return ''.join(core.show_project_meta(self.apiurl, project))
def getProjectData(self, project, tag):
Return a string list if node has text, else return the values dict list
"""
+
data = []
tree = ElementTree.fromstring(self.getProjectMeta(project))
nodes = tree.findall(tag)
Return a userid list in this project with this role
"""
+
userids = []
persons = self.getProjectData(project, 'person')
for person in persons:
Return the devel tuple of a project if it has the node, else return None
"""
+
devels = self.getProjectData(project, 'devel')
for devel in devels:
if devel.has_key('project') and devel.has_key('package'):
Return the linked project of a project if it has the node, else return None
"""
+
links = self.getProjectData(project, 'link')
for link in links:
if link.has_key('project'):
Delete the specific project
"""
+
try:
core.delete_project(self.apiurl, project)
except Exception:
Get XML metadata for package in project
"""
+
return ''.join(core.show_package_meta(self.apiurl, project, package))
def getPackageData(self, project, package, tag):
Return a string list if node has text, else return the values dict list
"""
+
data = []
tree = ElementTree.fromstring(self.getPackageMeta(project, package))
nodes = tree.findall(tag)
Return a userid list in the package with this role
"""
+
userids = []
persons = self.getPackageData(project, package, 'person')
for person in persons:
Return the devel tuple of a package if it has the node, else return None
"""
+
devels = self.getPackageData(project, package, 'devel')
for devel in devels:
if devel.has_key('project') and devel.has_key('package'):
Delete the specific package in project
"""
+
try:
core.delete_package(self.apiurl, project, package)
except Exception:
def projectFlags(self, project):
"""
- projectFlags(project) -> ProjectFlags
+ projectFlags(project) -> _ProjectFlags
- Return a ProjectFlags object for manipulating the flags of project
+ Return a _ProjectFlags object for manipulating the flags of project
"""
- return ProjectFlags(self, project)
-
-
-class ProjectFlags(object):
- """
- ProjectFlags(bs, project)
-
- Represents the flags in project through the BuildService object bs
- """
- def __init__(self, bs, project):
- self.bs = bs
- self.tree = ElementTree.fromstring(self.bs.getProjectMeta(project))
-
- # The "default" flags, when undefined
- self.defaultflags = {'build': True,
- 'publish': True,
- 'useforbuild': True,
- 'debuginfo': False}
-
- # Figure out what arches and repositories are defined
- self.arches = {}
- self.repositories = {}
-
- # Build individual repository list
- for repository in self.tree.findall('repository'):
- repodict = {'arches': {}}
- self.__init_flags_in_dict(repodict)
- for arch in repository.findall('arch'):
- repodict['arches'][arch.text] = {}
- self.__init_flags_in_dict(repodict['arches'][arch.text])
- # Add placeholder in global arches
- self.arches[arch.text] = {}
- self.repositories[repository.get('name')] = repodict
-
- # Initialise flags in global arches
- for archdict in self.arches.values():
- self.__init_flags_in_dict(archdict)
-
- # A special repository representing the global and global arch flags
- self.allrepositories = {'arches': self.arches}
- self.__init_flags_in_dict(self.allrepositories)
-
- # Now populate the structures from the xml data
- for flagtype in ('build', 'publish', 'useforbuild', 'debuginfo'):
- flagnode = self.tree.find(flagtype)
- if flagnode:
- for node in flagnode:
- repository = node.get('repository')
- arch = node.get('arch')
-
- if repository and arch:
- self.repositories[repository]['arches'][arch][flagtype] = flag2bool(node.tag)
- elif repository:
- self.repositories[repository][flagtype] = flag2bool(node.tag)
- elif arch:
- self.arches[flagtype] = flag2bool(node.tag)
- else:
- self.allrepositories[flagtype] = flag2bool(node.tag)
-
- def __init_flags_in_dict(self, d):
- """
- __init_flags_in_dict(d)
-
- Initialize all build flags to None in d
- """
- d.update({'build': None,
- 'publish': None,
- 'useforbuild': None,
- 'debuginfo': None})
-
- def save(self):
- """
- save()
-
- Save flags
- """
-
- for flagtype in ('build', 'publish', 'useforbuild', 'debuginfo'):
- # Clear if set
- flagnode = self.tree.find(flagtype)
- if flagnode:
- self.tree.remove(flagnode)
-
- # Generate rule nodes
- rulenodes = []
-
- # globals
- if self.allrepositories[flagtype] != None:
- rulenodes.append(ElementTree.Element(bool2flag(self.allrepositories[flagtype])))
- for arch in self.arches:
- if self.arches[arch][flagtype] != None:
- rulenodes.append(ElementTree.Element(bool2flag(self.arches[arch][flagtype]), arch=arch))
-
- # repositories
- for repository in self.repositories:
- if self.repositories[repository][flagtype] != None:
- rulenodes.append(ElementTree.Element(bool2flag(self.repositories[repository][flagtype]), repository=repository))
- for arch in self.repositories[repository]['arches']:
- if self.repositories[repository]['arches'][arch][flagtype] != None:
- rulenodes.append(ElementTree.Element(bool2flag(self.repositories[repository]['arches'][arch][flagtype]), arch=arch, repository=repository))
-
- # Add nodes to tree
- if rulenodes:
- from pprint import pprint
- pprint(rulenodes)
- flagnode = ElementTree.Element(flagtype)
- self.tree.insert(3, flagnode)
- for rulenode in rulenodes:
- flagnode.append(rulenode)
-
- print ElementTree.tostring(self.tree)
+ return _ProjectFlags(self, project)