components add
This commit is contained in:
Executable
+324
@@ -0,0 +1,324 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import shutil
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
|
||||
from optparse import OptionParser
|
||||
|
||||
def read_file(path):
|
||||
with open(path) as f:
|
||||
return f.read().strip()
|
||||
|
||||
def write_file(path, content):
|
||||
open(path, "w").write(content)
|
||||
open(path, "a").write("\n")
|
||||
|
||||
class Components():
|
||||
COMPONENT_XML = """<PISI>
|
||||
<Name>%s</Name>
|
||||
</PISI>
|
||||
"""
|
||||
EMPTY_COMPONENT = """ <Component>
|
||||
<Name>%s</Name>
|
||||
<LocalName xml:lang="en">FIXME</LocalName>
|
||||
<Summary xml:lang="en">FIXME</Summary>
|
||||
<Description xml:lang="en">FIXME</Description>
|
||||
<Group>FIXME</Group>
|
||||
<Maintainer>
|
||||
<Name>PisiLinux Community</Name>
|
||||
<Email>admins@pisilinux.org</Email>
|
||||
</Maintainer>
|
||||
</Component>"""
|
||||
CBGN = """<PISI>
|
||||
<Components>"""
|
||||
CEND = """
|
||||
</Components>
|
||||
</PISI>"""
|
||||
LOCALNAME = ' <LocalName xml:lang="%s">%s</LocalName>\n'
|
||||
SUMMARY = ' <Summary xml:lang="%s">%s</Summary>\n'
|
||||
DESCRIPTION = ' <Description xml:lang="%s">%s</Description>\n'
|
||||
COMPONENT = """
|
||||
<Component>
|
||||
<Name>%s</Name>
|
||||
%s%s%s <Group>%s</Group>
|
||||
<Maintainer>
|
||||
<Name>%s</Name>
|
||||
<Email>%s</Email>
|
||||
</Maintainer>
|
||||
</Component>"""
|
||||
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
self.components = []
|
||||
self.components_xml = "%s/components.xml" % self.path
|
||||
self.name_ptrn = re.compile("\s*<Name>(.+?)<\/Name>\s*")
|
||||
self.lnamech_ptrn = re.compile("\s*<LocalName.*?>(.+?)<\/LocalName>\s*")
|
||||
self.lname_ptrn = re.compile("\s*<LocalName\s+xml:lang\s?=\s?[\'\"](\w\w.*?)[\'\"]\s?>(.+?)<\/LocalName>\s*")
|
||||
self.summarych_ptrn = re.compile("\s*<Summary.*?>(.+?)<\/Summary>\s*")
|
||||
self.summary_ptrn = re.compile("\s*<Summary\s+xml:lang\s?=\s?[\'\"](\w\w.*?)[\'\"]\s?>(.+?)<\/Summary>\s*")
|
||||
self.descch_ptrn = re.compile("\s*<Description.*?>(.+?)<\/Description>\s*")
|
||||
self.desc_ptrn = re.compile("\s*<Description\s+xml:lang\s?=\s?[\'\"](\w\w.*?)[\'\"]\s?>(.+?)<\/Description>\s*")
|
||||
self.group_ptrn = re.compile("\s*<Group>(.+?)<\/Group>\s*")
|
||||
self.email_ptrn = re.compile("\s*<Email>(.+?)<\/Email>\s*")
|
||||
self.cbgn_ptrn = re.compile("\s*<Component>\s*")
|
||||
self.cend_ptrn = re.compile("\s*<\/Component>\s*")
|
||||
self.mbgn_ptrn = re.compile("\s*<Maintainer>\s*")
|
||||
self.mend_ptrn = re.compile("\s*<\/Maintainer>\s*")
|
||||
self.csend_ptrn = re.compile("\s*<\/Components>\s*")
|
||||
|
||||
def read_components(self):
|
||||
csfile = read_file(self.components_xml)
|
||||
cread = False
|
||||
mread = False
|
||||
component = {}
|
||||
for line in csfile.split("\n"):
|
||||
if re.search(self.cbgn_ptrn, line):
|
||||
cread = True
|
||||
component["err"] = []
|
||||
component["unknown"] = []
|
||||
component["clname"] = []
|
||||
component["csummary"] = []
|
||||
component["cdesc"] = []
|
||||
continue
|
||||
elif re.search(self.cend_ptrn, line):
|
||||
cread = False
|
||||
self.components.append(component)
|
||||
component = {}
|
||||
continue
|
||||
if cread:
|
||||
if re.search(self.mbgn_ptrn, line):
|
||||
mread = True
|
||||
continue
|
||||
elif re.search(self.mend_ptrn, line):
|
||||
mread = False
|
||||
continue
|
||||
elif re.search(self.name_ptrn, line):
|
||||
if mread: component["mname"] = re.sub(self.name_ptrn, r"\1", line)
|
||||
else: component["cname"] = re.sub(self.name_ptrn, r"\1", line)
|
||||
elif re.search(self.lnamech_ptrn, line):
|
||||
if re.search(self.lname_ptrn, line):
|
||||
component["clname"].append(re.sub(self.lname_ptrn, r"\1:\2", line))
|
||||
else:
|
||||
component["err"].append("LocalName")
|
||||
elif re.search(self.summarych_ptrn, line):
|
||||
if re.search(self.summary_ptrn, line):
|
||||
component["csummary"].append(re.sub(self.summary_ptrn, r"\1:\2", line))
|
||||
else:
|
||||
component["err"].append("Summary")
|
||||
elif re.search(self.descch_ptrn, line):
|
||||
if re.search(self.desc_ptrn, line):
|
||||
component["cdesc"].append(re.sub(self.desc_ptrn, r"\1:\2", line))
|
||||
else:
|
||||
component["err"].append("Description")
|
||||
elif re.search(self.group_ptrn, line):
|
||||
component["cgroup"] = re.sub(self.group_ptrn, r"\1", line)
|
||||
elif re.search(self.email_ptrn, line):
|
||||
component["memail"] = re.sub(self.email_ptrn, r"\1", line)
|
||||
else: component["unknown"].append(line)
|
||||
|
||||
def sort_components(self):
|
||||
self.components = sorted(self.components, key=lambda k: k['cname'])
|
||||
|
||||
def backup_components(self):
|
||||
files = os.walk(self.path).next()[2]
|
||||
last = 0
|
||||
for f in files:
|
||||
if f.startswith("components.xml.") and int(f[-3:]) > last: last = int(f[-3:])
|
||||
last = str(last + 1)
|
||||
while len(last) < 3: last = "0" + last
|
||||
shutil.copyfile(self.components_xml, ".".join((self.components_xml, last)))
|
||||
|
||||
def write_components(self):
|
||||
self.sort_components()
|
||||
cs = ''
|
||||
for c in self.components:
|
||||
ln = ""
|
||||
for i in c["clname"]:
|
||||
ln += self.LOCALNAME % tuple(i.split(":"))
|
||||
s = ""
|
||||
for i in c["csummary"]:
|
||||
s += self.SUMMARY % tuple(i.split(":"))
|
||||
d = ""
|
||||
for i in c["cdesc"]:
|
||||
d += self.DESCRIPTION % tuple(i.split(":"))
|
||||
cs += self.COMPONENT % (c["cname"], ln, s, d, c["cgroup"], c["mname"], c["memail"])
|
||||
self.backup_components()
|
||||
open(self.components_xml, "w").write(self.CBGN)
|
||||
open(self.components_xml, "a").write(cs)
|
||||
open(self.components_xml, "a").write(self.CEND)
|
||||
open(self.components_xml, "a").write("\n")
|
||||
|
||||
def edit(self):
|
||||
l = []
|
||||
mcommands = {"q": "quit",
|
||||
"l": "list components",
|
||||
"c": "choose component",
|
||||
"h": "help"}
|
||||
ecommands = {"mn": "set maintainer name",
|
||||
"me": "set maintainer email",
|
||||
"ln": "set local name (lang:name)",
|
||||
"s": "set summary (lang:summary)",
|
||||
"d": "set description (lang:description)",
|
||||
"m": "main menu",
|
||||
"w": "write",
|
||||
"h": "help"}
|
||||
|
||||
def read_command(m):
|
||||
opts = mcommands.keys() if m == "m" else ecommands.keys()
|
||||
return (opts, raw_input(":".join(sorted(opts)) + " > ").split())
|
||||
|
||||
def list_components(param, regexp = True):
|
||||
res = []
|
||||
num = 0
|
||||
if not param: param = ".*"
|
||||
for c in self.components:
|
||||
if regexp and re.search(param, c["cname"]):
|
||||
res.append(c["cname"])
|
||||
print num, c["cname"]
|
||||
num += 1
|
||||
elif not regexp and param == c["cname"]:
|
||||
res.append(c["cname"])
|
||||
break
|
||||
return res
|
||||
|
||||
def get_component_data(name):
|
||||
#print self.components
|
||||
for c in self.components:
|
||||
if name == c["cname"]: return c
|
||||
print "Component %s not found!" % name
|
||||
return False
|
||||
|
||||
def print_help(hdict):
|
||||
for i in iter(sorted(hdict.iteritems())):
|
||||
print i[0] + "\t" + i[1]
|
||||
|
||||
def edit_loop(component):
|
||||
def update(key, val, data):
|
||||
d = val.split(":")
|
||||
if not len(d) == 2: print "Wrong param format! (ln lang:text)"
|
||||
else:
|
||||
lexists = -1
|
||||
for i in data[key]:
|
||||
if i.split(":")[0] == d[0]:
|
||||
lexists = data[key].index(i)
|
||||
break
|
||||
if lexists > -1: data[key][lexists] = val
|
||||
else: data[key].append(val)
|
||||
return data
|
||||
|
||||
data = get_component_data(component)
|
||||
while True:
|
||||
print "-" * (len(component) + 8)
|
||||
print "Editing " + component
|
||||
print "-" * (len(component) + 8)
|
||||
print "LocalName:"
|
||||
for i in data["clname"]: print " %s" %i
|
||||
print "Summary:"
|
||||
for i in data["csummary"]: print " %s" %i
|
||||
print "Description:"
|
||||
for i in data["cdesc"]: print " %s" %i
|
||||
print "Group:\n %s" % data["cgroup"]
|
||||
print "Maintainer name:\n %s" % data["mname"]
|
||||
print "Email:\n %s" % data["memail"]
|
||||
o, c = read_command("c")
|
||||
if not c[0] in o: continue
|
||||
if len(c) == 1: c.append("")
|
||||
if c[0] == "m": break
|
||||
elif c[0] == "h": print_help(ecommands)
|
||||
elif c[0] == "ln": data = update("clname", c[1], data)
|
||||
elif c[0] == "s": data = update("csummary", c[1], data)
|
||||
elif c[0] == "d": data = update("cdesc", c[1], data)
|
||||
elif c[0] == "mn": data["mname"] = c[1]
|
||||
elif c[0] == "me": data["memail"] = c[1]
|
||||
elif c[0] == "w": self.write_components()
|
||||
else: print"%s is not implemented yet" % c[0]
|
||||
|
||||
def edit_component(param, l):
|
||||
try:
|
||||
int(param)
|
||||
edit_loop(l[int(param)])
|
||||
except ValueError:
|
||||
l = list_components(param, regexp = False)
|
||||
if not len(l) == 1: print "Component %s not found" % param
|
||||
else: edit_loop(l[0])
|
||||
|
||||
while True:
|
||||
o, c = read_command("m")
|
||||
if len(c) == 1: c.append("")
|
||||
if not c[0] in o: continue
|
||||
elif c[0] == "q": break
|
||||
elif c[0] == "l": l = list_components(c[1])
|
||||
elif c[0] == "c": edit_component(c[1], l)
|
||||
elif c[0] == "h": print_help(mcommands)
|
||||
else: print"%s is not implemented yet" % c[0]
|
||||
|
||||
def check(self):
|
||||
cs = []
|
||||
for root, dirs, files in os.walk(self.path):
|
||||
c = root.split(self.path)[1][1:].split("/")
|
||||
if "files" in c or "comar" in c: continue
|
||||
c = ".".join(c)
|
||||
component_xml = "%s/component.xml" % root
|
||||
pspec_xml = "%s/pspec.xml" % root
|
||||
actions_py = "%s/actions.py" % root
|
||||
if not os.path.isfile(component_xml) and not os.path.isfile(pspec_xml):
|
||||
if os.path.isfile(actions_py): print "WARNING: %s not exists" % pspec_xml
|
||||
else:
|
||||
is_src_repo = False
|
||||
for r, d, f in os.walk(root):
|
||||
if "pspec.xml" in f:
|
||||
is_src_repo = True
|
||||
break
|
||||
if is_src_repo and c:
|
||||
print "%s not exists. creating..." % component_xml
|
||||
write_file(component_xml, self.COMPONENT_XML % c)
|
||||
if os.path.isfile(component_xml) and c: cs.append(c)
|
||||
|
||||
mcs = cs[:]
|
||||
csfile = read_file(self.components_xml)
|
||||
maintainer = False
|
||||
new_file = []
|
||||
for line in csfile.split("\n"):
|
||||
new_file.append(line)
|
||||
if re.search(self.mbgn_ptrn, line): maintainer = True
|
||||
elif re.search(self.mend_ptrn, line): maintainer = False
|
||||
elif re.search(self.csend_ptrn, line):
|
||||
for m in mcs:
|
||||
new_file.insert(-1, self.EMPTY_COMPONENT % m)
|
||||
if not re.search(self.name_ptrn, line) or maintainer: continue
|
||||
cn = re.sub(self.name_ptrn, r"\1", line)
|
||||
if cn in mcs: mcs.pop(mcs.index(cn))
|
||||
|
||||
new_file = "\n".join(new_file)
|
||||
write_file(self.components_xml, new_file)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
usage = "Usage: %prog [PATH]"
|
||||
parser = OptionParser(usage)
|
||||
parser.add_option("-c", "--check", action="store_true", dest="check", help="fix missing component.xml files and entries in components.xml")
|
||||
parser.add_option("-e", "--edit", action="store_true", dest="edit", help="edit components.xml")
|
||||
(options,args) = parser.parse_args()
|
||||
try:
|
||||
root = args[0]
|
||||
except IndexError:
|
||||
print "Using ./ as PATH"
|
||||
root = "./"
|
||||
|
||||
if root.endswith("/"): root = root[:-1]
|
||||
|
||||
cs = Components(root)
|
||||
if not os.path.isfile(cs.components_xml):
|
||||
print "%s not exists!" % cs.components_xml
|
||||
sys.exit(1)
|
||||
if not os.access(cs.components_xml, os.W_OK):
|
||||
print "Cannot write to %s" % cs.components_xml
|
||||
sys.exit(1)
|
||||
cs.read_components()
|
||||
|
||||
if options.check: cs.check()
|
||||
if options.edit:
|
||||
cs.edit()
|
||||
Reference in New Issue
Block a user