123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- #!/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()
|