diff options
-rw-r--r-- | __init__.py | 0 | ||||
-rwxr-xr-x | devshell.py | 438 | ||||
-rw-r--r-- | modules/__init__.py | 0 | ||||
-rw-r--r-- | modules/audit.py | 9 | ||||
-rw-r--r-- | modules/bugs.py | 24 | ||||
-rw-r--r-- | modules/mail.py | 116 | ||||
-rw-r--r-- | modules/pkg.py | 132 | ||||
-rwxr-xr-x | ports.py | 20 | ||||
-rw-r--r-- | rebuild-scripts/CVS/Entries | 12 | ||||
-rw-r--r-- | rebuild-scripts/CVS/Repository | 1 | ||||
-rw-r--r-- | rebuild-scripts/CVS/Root | 1 | ||||
-rwxr-xr-x | rebuild-scripts/add_owner | 28 | ||||
-rwxr-xr-x | rebuild-scripts/buildcheck | 58 | ||||
-rw-r--r-- | rebuild-scripts/buildcheck-extras-development.repo | 12 | ||||
-rwxr-xr-x | rebuild-scripts/bumpspecfile.py | 116 | ||||
-rwxr-xr-x | rebuild-scripts/check_rebuild | 17 | ||||
-rwxr-xr-x | rebuild-scripts/check_rebuild2 | 20 | ||||
-rwxr-xr-x | rebuild-scripts/check_release | 12 | ||||
-rwxr-xr-x | rebuild-scripts/gen_nr_2 | 26 | ||||
-rwxr-xr-x | rebuild-scripts/gen_rebuild_lst | 26 | ||||
-rwxr-xr-x | rebuild-scripts/rm_noarch | 21 | ||||
-rw-r--r-- | rebuild-scripts/semi_auto_rebuild.txt | 67 |
22 files changed, 828 insertions, 328 deletions
diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/__init__.py diff --git a/devshell.py b/devshell.py index 119692b..0518cc7 100755 --- a/devshell.py +++ b/devshell.py @@ -1,5 +1,4 @@ #!/usr/bin/python -tt -# $Id: $ # Fedora Developer Shell # # This program is free software; you can redistribute it and/or modify @@ -51,11 +50,6 @@ __description__ = 'A shell for hacking on the Fedora project' FEDORA_DIR = join(expanduser('~'), 'code', 'fedora') DEVSHELL_DIR = join(expanduser('~'), '.devshell') -repos = { - 'fedora_cvs' : ':ext:cvs.fedora.redhat.com:/cvs/pkgs', - 'bodhi_hg' : 'http://hg.fedoraproject.org/hg/hosted/bodhi', -} - stack = [] prompt = ['\033[34;1mfedora\033[0m'] modules = {} @@ -63,275 +57,23 @@ header = lambda x: "%s %s %s" % ('=' * 2, x, '=' * (76 - len(x))) log = logging.getLogger(__name__) class Module: - """ The parent class of all modules """ - def __init__(self): - # setup stack and prompt - pass - -class Mail(Module): - - url = 'https://www.redhat.com/archives/%s/%s' - - def search(self, mailinglist, text): - """ <list> <text>. Search specific mailing list for given text """ - now = datetime.now() - while True: - fetch = True - filename = now.strftime("%Y-%B") + '.txt.gz' - try: - f = urllib2.urlopen(self.url % (mailinglist, filename)) - except urllib2.HTTPError: - break - local = join(DEVSHELL_DIR, mailinglist, filename) - - # Don't fetch the mbox if we already have a good local copy - if exists(local): - info = os.stat(local) - if info[stat.ST_SIZE] == int(f.headers.get('Content-Length')): - fetch = False - log.debug("Using local mbox: %s" % local) - if fetch: - if not exists(dirname(local)): - os.makedirs(dirname(local)) - mbox = file(local, 'w') - log.debug("Downloading %s" % local) - mbox.write(f.read()) - mbox.close() - f.close() - - self.__search_mbox(local, text) - - # Go back in time - now = now - timedelta(days=31) - - def __search_mbox(self, mboxfile, text): - """ - Search a compressed mbox for any specified keywords - """ - num = 0 - statinfo = os.stat(mboxfile) - gzmbox = gzip.open(mboxfile) - mbox = UnixMailbox(gzmbox, email.message_from_file) - while True: - msg = mbox.next() - if not msg: break - num += 1 - fields = [msg['From'], msg['Subject']] + self.__body(msg) - for field in fields: - if re.search(text, field, re.IGNORECASE): - id = "%s.%s" % (statinfo[stat.ST_INO], num) - print "[%s] %s %s" % (id, msg['From'], msg['Subject']) - break - gzmbox.close() - - def __body(self, msg): - """ - Recursively gather multipart message bodies - """ - body = [] - if msg.is_multipart(): - for payload in msg.get_payload(): - for part in payload.walk(): - body += self.__body(part) - else: - body = [msg.get_payload()] - return body - - def show(self, id): - """ Show a message with a given ID """ - inode, msgnum = map(int, id.split('.')) - olddir = os.getcwd() - os.chdir(DEVSHELL_DIR) - mboxfile = None - for dir in filter(isdir, os.listdir('.')): - for file in os.listdir(dir): - statinfo = os.stat(join(dir, file)) - if statinfo[stat.ST_INO] == inode: - mboxfile = join(dir, file) - break - if mboxfile: break - if mboxfile: - gzmbox = gzip.open(mboxfile) - mbox = UnixMailbox(gzmbox, email.message_from_file) - num = 0 - while num != msgnum: - msg = mbox.next() - num += 1 - self.__print_msg(msg) - else: - log.error("Cannot find message %s" % id) - os.chdir(olddir) - - def __print_msg(self, msg): - log.info("From: %s" % msg['From']) - log.info("To: %s" % msg['To']) - log.info("Subject: %s" % msg['Subject']) - log.info('\n'.join(self.__body(msg))) - - -class SCM: - """ - Our generic SCM wrapper. Based on the name_scm of the repos dictionary key, - we should be able to get our hands on any up-to-date code, and easily drop - into any file, make modifications, and commit upstream. - """ - def __init__(self, name, url): - self.url = url - self.name = name - self.type = name.split('_')[-1] - if self.type not in ('cvs', 'git', 'bzr', 'hg'): - log.error("Unknown SCM '%s' for repo %s" % (self.type, name)) - return - - def co(self, module, branch=''): - self.module = module - self.branch = branch - if os.path.isdir(os.path.join(FEDORA_DIR, module)): - # from here, we have no idea what scm we're dealing with - log.debug("%s module already checked out!" % module) - return os.path.join(FEDORA_DIR, module, branch) - path = os.getcwd() - os.chdir(FEDORA_DIR) - cmd = "%s checkout %s" % (self.type, module) - status, output = commands.getstatusoutput(cmd) - log.debug("Ran `%s`\nstatus = %s\noutput= %s" % (cmd, status, output)) - os.chdir(path) - return status == 0 - - def patches(self): - path = os.getcwd() - os.chdir(os.path.join(FEDORA_DIR, self.module, self.branch)) - i = 0 - for patch in glob('*.patch'): - log.info(" [ %d ] %s" % (i, patch)) - i += 1 - os.chdir(path) - - def log(self, file=None): - path = os.getcwd() - os.chdir(os.path.join(FEDORA_DIR, self.module, self.branch)) - if not file: - os.system("%s log | less" % self.type) - else: - os.system("%s log %s | less" % (self.type, file)) - os.chdir(path) - - def update(self): - path = os.getcwd() - os.chdir(FEDORA_DIR) - cmd = "%s update" % self.type - status, output = commands.getstatusoutput(cmd) - os.chdir(path) - return status == 0 - -class Pkg(Module): - - def __init__(self, name, branch='devel', scm=None): - """ - Open a given project - """ - log.debug("Pkg(%s, %s, %s)" % (name, branch, scm)) - global stack, prompt - self.name = name - self.branch = branch - self.scm = scm - stack += [self] - prompt += [name, branch] - self.__find_scm() - - def __find_scm(self): - global repos - if self.scm: - if repos.has_key(self.scm): - self.scm = SCM(scm, repos[scm]) - else: - log.debug("TODO: use specified SCM") - else: - # Try and find our corresponding SCM.. trial-and-error style. - for scm in [SCM(repo, url) for repo, url in repos.items()]: - log.debug("checking with SCM %s" % scm) - if scm.co(self.name, self.branch): - self.scm = scm - log.debug("Found relevant scm: %s" % scm) - break - if not self.scm: - log.error("Cannot find corresponding SCM for %s" % self.name) - - def spec(self): - """ - View the RPM spec file for this project - """ - editor = os.getenv('EDITOR', 'vim') - os.system("%s %s/%s.spec" % (editor, os.path.join(FEDORA_DIR, self.name, - self.branch), self.name)) - - def patches(self): - """ - List all patches applied against this package - """ - self.scm.patches() - - def log(self, item=None): - """ - Show the log - """ - self.scm.log(item) - - def patch(self, num): - self.scm.patch(num) - - def diff(self): - raise NotImplementedError - - def prep(self): - raise NotImplementedError - - def build(self): - raise NotImplementedError - - def srpm(self): - raise NotImplementedError - - def qa(self): - raise NotImplementedError - - def bugs(self): - raise NotImplementedError - -class Bugs(Module): - """ - Interface for doing useful things with Bugs. - TODO: add support for arbitrary bug trackers! - python-bugzilla integration! - """ - def view(self, data): - """ - View a given bug number, or show all bugs for a given component - Example: bugs view #1234, bugs view nethack - """ - if data[0] == '#': - os.system('firefox "https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=%s"' % data[1:]) - else: - os.system('firefox "https://bugzilla.redhat.com/bugzilla/buglist.cgi?product=Fedora+Core&component=%s&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=MODIFIED&short_desc_type=allwordssubstr&short_desc=&long_desc_type=allwordssubstr&long_desc="' % data) - - def search(self, text): - """ - Search bugzilla for a given keyword - """ - os.system('firefox "https://bugzilla.redhat.com/buglist.cgi?query_format=specific&order=bugs.bug_id&bug_status=__open__&product=&content=%s"' % text) + """ Our parent class for all command modules """ + pass def load_modules(): global modules from inspect import isclass log.debug("Loading modules") - for key in globals().keys(): - module = globals()[key] - if isclass(module): - if issubclass(module, Module) and key != 'Module': - # Cache reference to class, *not* an instance. We'll instantiate - # modules on the fly when we need them - log.debug(" * %s" % key) - modules[key.lower()] = module + for f in os.listdir(os.path.abspath('modules')): + module_name, ext = os.path.splitext(f) + if ext == '.py': + exec "from modules import %s as module" % module_name + for item in dir(module): + obj = getattr(module, item) + if item[0] != '_' and isclass(obj): + modules[item.lower()] = obj + log.info(" * %s" % item) + del module def print_docstrings(module=None): """ @@ -359,86 +101,127 @@ def shell(): except (EOFError, KeyboardInterrupt): print break - if not data: continue if data in ('quit', 'exit'): break keyword = data.split()[0] - data = data.split()[1:] - + args = data.split()[1:] + # Show the docstrings to all methods for all loaded modules if keyword == 'help': print_docstrings() - + # Go up a module in our stack - elif keyword == 'up': + elif keyword in ('up', 'cd..', 'cd ..'): stack = stack[:-1] prompt = prompt[:-1] - + # Show the docstrings for all methods in our current module - elif keyword in ('ls', 'help'): + elif keyword in ('ls', 'help', '?'): if len(stack): print_docstrings(stack[-1]) else: print_docstrings() - + # Flush our module stack elif keyword == 'cd': stack = [] prompt = ['\033[34;1mfedora\033[0m'] - + # iPython. Never leave home without it. elif keyword in ('py', 'python'): os.system("ipython -noconfirm_exit") - - # Do some intelligent handling of unknown input. - # For the given input 'foo bar', we first check if we have the - # module 'foo' loaded, then we push it on the top of our module - # stack and check if it has the 'bar' attribute. If so, we call - # it with any remaining arguments else: - args = [] - top = None - - # See if our keyword is a global module - if keyword in modules.keys(): - log.debug("%s is a module!" % keyword) - #top = modules[keyword] - if len(data) and not hasattr(modules[keyword], data[0]): - log.debug("Loading %s.__init__(%s)" % (keyword, data)) - top = modules[keyword](*data) - #stack += [top] - #prompt += [keyword] + data - continue - else: - log.debug("Loading %s" % keyword) - try: - top = modules[keyword]() - stack += [top] - prompt += [keyword] - except TypeError, e: - log.error("%s.%s" % (keyword, e)) - continue - - # Try the top module on our stack if len(stack): - if hasattr(stack[-1], keyword): - log.debug("Current module has %s" % keyword) - top = getattr(stack[-1], keyword) - - # Iterate over the rest of our arguments, either going deeper - # into the top module, or appending tokens to our args list. - for value in data: - if hasattr(top, value): - log.debug("next property %s found in %s" % (value, top)) - top = getattr(top, value) - elif top: - log.debug("adding argument: %s" % value) - args.append(value) - if top: - log.debug("calling %s with %s" % (top, args)) - top(*args) + top = stack[-1] + else: + top = None + output, top, params = do_command(data.split(), top) + stack += [top] + prompt += [top.__class__.__name__] + params + +class ModuleError(Exception): + def __init__(self, reason, error): + self.reason = reason + self.error = error + +def load_module(name, data=[]): +# stack = [] +# prompt = [] + top = None + try: + log.debug("Loading %s.__init__(%s)" % (name, data)) + top = modules[name](*data) +# stack += [top] +# prompt += [name] + data + except TypeError, e: + log.debug('got type error') + log.error("%s: %s" % (name, e)) + raise ModuleError('probably bad call to __init__' , e) + return top + + +def do_command(data, top=None): + + # Do some intelligent handling of unknown input. + # For the given input 'foo bar', we first check if we have the + # module 'foo' loaded, then we push it on the top of our module + # stack and check if it has the 'bar' attribute. If so, we call + # it with any remaining arguments + from collections import deque + data = deque(data) + log.debug(data) + params = [] + + module = None + while len(data): + if not top: + log.debug('not top') + mod = data.popleft() + try: + module = modules[mod] + except KeyError, e: + log.error('%s is not a known module' % e.message) + return None, None, None + log.debug('mod is %s' % mod) + params = [] + while len(data): + log.debug('params so far %s' % params) + log.debug('inner loop %s' % data) + param = data.popleft() + if hasattr(module, param): + data.appendleft(param) + break + params += [param] + try: + top = module = load_module(mod, params) + mod_params = params + loaded_module = True + except ModuleError, e: + log.debug(e.reason) + break + else: + log.debug('is top') + params = [] + log.debug('params so far %s' % params) + param = data.popleft() + if hasattr(top, param): + log.debug("next property %s found in %s" % (param, top)) + top = getattr(top, param) + else: + log.debug("adding argument: %s" % param) + params += [param] + output = None + if len(params): + output = top(*params) + + if module: + return output, module, mod_params + else: + return output, None, None + def main(): + global log from optparse import OptionParser parser = OptionParser(usage="%prog [options]", version="%s %s" % ('%prog', __version__), @@ -466,7 +249,6 @@ def main(): load_modules() shell() - - + if __name__ == '__main__': - main() + main()
\ No newline at end of file diff --git a/modules/__init__.py b/modules/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/modules/__init__.py diff --git a/modules/audit.py b/modules/audit.py new file mode 100644 index 0000000..5e89f53 --- /dev/null +++ b/modules/audit.py @@ -0,0 +1,9 @@ + + +class Audit: + """ Perform various code audits on a specified Pkg """ + + tools = ['flawfinder', 'rats'] + + def __init__(self, pkg): + """ @param pkg: a Pkg instance """ diff --git a/modules/bugs.py b/modules/bugs.py new file mode 100644 index 0000000..359a06e --- /dev/null +++ b/modules/bugs.py @@ -0,0 +1,24 @@ +import os + +class Bugs: + """ + Interface for doing useful things with Bugs. + TODO: add support for arbitrary bug trackers! + python-bugzilla integration! + """ + def view(self, data): + """ + View a given bug number, or show all bugs for a given component + Example: bugs view #1234, bugs view nethack + """ + if data[0] == '#': + os.system('firefox "https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=%s"' % data[1:]) + else: + os.system('firefox "https://bugzilla.redhat.com/bugzilla/buglist.cgi?product=Fedora+Core&component=%s&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=MODIFIED&short_desc_type=allwordssubstr&short_desc=&long_desc_type=allwordssubstr&long_desc="' % data) + + def search(self, text): + """ + Search bugzilla for a given keyword + """ + os.system('firefox "https://bugzilla.redhat.com/buglist.cgi?query_format=specific&order=bugs.bug_id&bug_status=__open__&product=&content=%s"' % text) + diff --git a/modules/mail.py b/modules/mail.py new file mode 100644 index 0000000..790845d --- /dev/null +++ b/modules/mail.py @@ -0,0 +1,116 @@ +import re +import os +import gzip +import stat +import email +import urllib2 +import logging + +from os.path import join, exists, dirname, isdir +from mailbox import UnixMailbox +from datetime import datetime, timedelta + +from devshell import DEVSHELL_DIR + +log = logging.getLogger(__name__) + +class Mail: + """ A module for searching/viewing mailing lists """ + + url = 'https://www.redhat.com/archives/%s/%s' + + def search(self, mailinglist, text): + """ <list> <text>. Search specific mailing list for given text """ + now = datetime.now() + while True: + fetch = True + filename = now.strftime("%Y-%B") + '.txt.gz' + try: + f = urllib2.urlopen(self.url % (mailinglist, filename)) + except urllib2.HTTPError: + break + local = join(DEVSHELL_DIR, mailinglist, filename) + + # Don't fetch the mbox if we already have a good local copy + if exists(local): + info = os.stat(local) + if info[stat.ST_SIZE] == int(f.headers.get('Content-Length')): + fetch = False + log.debug("Using local mbox: %s" % local) + if fetch: + if not exists(dirname(local)): + os.makedirs(dirname(local)) + mbox = file(local, 'w') + log.debug("Downloading %s" % local) + mbox.write(f.read()) + mbox.close() + f.close() + + self.__search_mbox(local, text) + + # Go back in time + now = now - timedelta(days=31) + + def __search_mbox(self, mboxfile, text): + """ + Search a compressed mbox for any specified keywords + """ + num = 0 + statinfo = os.stat(mboxfile) + gzmbox = gzip.open(mboxfile) + mbox = UnixMailbox(gzmbox, email.message_from_file) + while True: + msg = mbox.next() + if not msg: break + num += 1 + fields = [msg['From'], msg['Subject']] + self.__body(msg) + for field in fields: + if re.search(text, field, re.IGNORECASE): + id = "%s.%s" % (statinfo[stat.ST_INO], num) + print "[%s] %s %s" % (id, msg['From'], msg['Subject']) + break + gzmbox.close() + + def __body(self, msg): + """ + Recursively gather multipart message bodies + """ + body = [] + if msg.is_multipart(): + for payload in msg.get_payload(): + for part in payload.walk(): + body += self.__body(part) + else: + body = [msg.get_payload()] + return body + + def show(self, id): + """ Show a message with a given ID """ + inode, msgnum = map(int, id.split('.')) + olddir = os.getcwd() + os.chdir(DEVSHELL_DIR) + mboxfile = None + for dir in filter(isdir, os.listdir('.')): + for file in os.listdir(dir): + statinfo = os.stat(join(dir, file)) + if statinfo[stat.ST_INO] == inode: + mboxfile = join(dir, file) + break + if mboxfile: break + if mboxfile: + gzmbox = gzip.open(mboxfile) + mbox = UnixMailbox(gzmbox, email.message_from_file) + num = 0 + while num != msgnum: + msg = mbox.next() + num += 1 + self.__print_msg(msg) + else: + log.error("Cannot find message %s" % id) + os.chdir(olddir) + + def __print_msg(self, msg): + log.info("From: %s" % msg['From']) + log.info("To: %s" % msg['To']) + log.info("Subject: %s" % msg['Subject']) + log.info('\n'.join(self.__body(msg))) diff --git a/modules/pkg.py b/modules/pkg.py new file mode 100644 index 0000000..a748b92 --- /dev/null +++ b/modules/pkg.py @@ -0,0 +1,132 @@ +import os +import commands + +from os.path import isdir, join +from devshell import FEDORA_DIR + + +# Hack-filled at the moment. + +UPDATE, CLONE, COMMIT, LOG, DIFF = range(5) +scm_cmds = { + 'git' : ('update', 'clone', 'log', 'diff'), + 'hg' : ('update', 'clone', 'log', 'diff'), + 'cvs' : ('update', 'checkout', 'log', 'diff'), +} +scms = { + 'cvs.fedoraproject.org' : 'cvs -d :ext:cvs.fedoraproject.org:/cvs/pkgs %(command)s %(module)s', + 'git.fedorahosted.org' : 'git %(command)s ssh+git://git.fedorahosted.org/git/%(module)s', + 'hg.fedorahosted.org' : 'hg %(command)s ssh://hg.fedorahosted.org//hg/%(module)s', +} + + +class CannotFindPackage(Exception): + pass + +#FIXME: use this? +class SCM: + cmds = dict(update='update', clone='clone', log='log', diff='diff') + +class Package(object): + + def __init__(self, name, branch='devel'): + self.name = name + self.branch = branch + self.scm = None + self.__path = None + self.__checkout() + + def __set_path(self, p): + """ Set our path and make it our current working directory """ + if isdir(join(p, self.branch)): + p = join(p, self.branch) + print p + self.__path = p + os.chdir(p) + + def __get_path(self): + return self.__path + + path = property(__get_path, __set_path) + + def __checkout(self): + """ Find where this package lives """ + + # Look in FEDORA_DIR/<scm>/<pkg> + for scm in scms.keys(): + scmdir = join(FEDORA_DIR, scm, self.name) + if isdir(scmdir): + self.scm = scm + self.path = scmdir + return + + # Find this module in our scms + for scm in scms.keys(): + scmdir = join(FEDORA_DIR, scm) + if not isdir(scmdir): + print "Creating %s" % scmdir + os.mkdir(scmdir) + os.chdir(scmdir) + cmd = scms[scm] % { + 'command' : scm_cmds[scm.split('.')[0]][CLONE], + 'module' : self.name + } + print "Running %s" % cmd + status, output = commands.getstatusoutput(cmd) + if status == 0: + self.scm = scm + self.path = join(scmdir, self.name) + return + + raise CannotFindPackage + + def spec(self): + """ View the RPM spec file for this project """ + editor = os.getenv('EDITOR', 'vi') + os.system("%s %s.spec" % (editor, self.name)) + + def sh(self): + """ Drop into a shell """ + os.system("bash") + + def update(self): + self.scm.update() + cmd = scms[self.scm] % { + 'command' : scm_cmds[self.scm.split('.')[0]][UPDATE], + 'module' : '' + } + print "Executing `%s`" % cmd + status, output = commands.getstatusoutput(cmd) + print output + + def log(self, item=''): + """ Show the history of this package """ + cmd = scms[self.scm] % { + 'command' : scm_cmds[self.scm.split('.')[0]][LOG], + 'module' : item + } + print "Executing `%s | less`" % cmd + os.system("%s | less" % cmd) + + def diff(self, item=''): + cmd = scms[self.scm] % { + 'command' : scm_cmds[self.scm.split('.')[0]][DIFF], + 'module' : item + } + print "Executing `%s | colordiff | less -R`" % cmd + os.system("%s | colordiff | less -R" % cmd) + + def build(self): + raise NotImplementedError + + def srpm(self): + raise NotImplementedError + + def qa(self): + raise NotImplementedError + + def audit(self): + raise NotImplementedError + + def bugs(self): + raise NotImplementedError diff --git a/ports.py b/ports.py new file mode 100755 index 0000000..d4d5005 --- /dev/null +++ b/ports.py @@ -0,0 +1,20 @@ +#!/usr/bin/python -tt +# Fedora Developer Shell +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Authors: Yaakov M. Nemoy <ynemoy@redhat.com> +# + + diff --git a/rebuild-scripts/CVS/Entries b/rebuild-scripts/CVS/Entries new file mode 100644 index 0000000..d2d53df --- /dev/null +++ b/rebuild-scripts/CVS/Entries @@ -0,0 +1,12 @@ +/add_owner/1.1.1.1/Fri Oct 6 22:22:02 2006// +/buildcheck/1.1.1.1/Fri Oct 6 22:22:02 2006// +/buildcheck-extras-development.repo/1.1.1.1/Fri Oct 6 22:22:02 2006// +/bumpspecfile.py/1.1.1.1/Fri Oct 6 22:22:02 2006// +/check_rebuild/1.1.1.1/Fri Oct 6 22:22:02 2006// +/check_rebuild2/1.1.1.1/Fri Oct 6 22:22:02 2006// +/check_release/1.1.1.1/Fri Oct 6 22:22:02 2006// +/gen_nr_2/1.1.1.1/Fri Oct 6 22:22:02 2006// +/gen_rebuild_lst/1.1.1.1/Fri Oct 6 22:22:02 2006// +/rm_noarch/1.1.1.1/Fri Oct 6 22:22:02 2006// +/semi_auto_rebuild.txt/1.1.1.1/Fri Oct 6 22:22:02 2006// +D diff --git a/rebuild-scripts/CVS/Repository b/rebuild-scripts/CVS/Repository new file mode 100644 index 0000000..2014fa1 --- /dev/null +++ b/rebuild-scripts/CVS/Repository @@ -0,0 +1 @@ +rebuild-scripts diff --git a/rebuild-scripts/CVS/Root b/rebuild-scripts/CVS/Root new file mode 100644 index 0000000..7c4b192 --- /dev/null +++ b/rebuild-scripts/CVS/Root @@ -0,0 +1 @@ +:ext:cvs.fedora.redhat.com:/cvs/fedora diff --git a/rebuild-scripts/add_owner b/rebuild-scripts/add_owner new file mode 100755 index 0000000..e419d42 --- /dev/null +++ b/rebuild-scripts/add_owner @@ -0,0 +1,28 @@ +#!/usr/bin/env perl +# $Id: add_owner,v 1.1.1.1 2006/10/06 22:22:02 c4chris Exp $ +use strict; +local *IN; +my %OWN; +open IN, "/home/chris/src/isrec/fedora/owners/owners.list" + or die "Couldn't open owners.list: $!"; +while ( <IN> ) { + next if /^#/; + s/\s+$//; + my @F = split /\|/; + next if $F[1] eq ""; + $OWN{$F[1]} = \@F; +} +close IN; +while ( <> ) { + s/\s+$//; + my @F = split; + my $name = $F[5]; + my $e = $OWN{$name}; + if (defined $e) { + push @F, $$e[3]; + } else { + push @F, "Unknown"; + } + print join(" ", @F), "\n"; +} +exit 0; diff --git a/rebuild-scripts/buildcheck b/rebuild-scripts/buildcheck new file mode 100755 index 0000000..be2bba4 --- /dev/null +++ b/rebuild-scripts/buildcheck @@ -0,0 +1,58 @@ +#!/bin/bash + +# if this one is rebuild again it will confuse the script: +PACKAGESUPTO=recode +byebye() +{ + [[ -e "${TMPDIR}" ]] && rm -f "${TMPDIR}/owners.list" "${TMPDIR}/repoquery" "${TMPDIR}/repoquery-noarch" "${TMPDIR}/result" + [[ -e "${TMPDIR}" ]] && rmdir "${TMPDIR}" + local return=${1} + shift + [[ "${1}" ]] && echo $@ + exit ${return} +} + + + +if ! TMPDIR="$(mktemp -d)" +then + byebye 1 Could not create TMPDIR +fi +echo "TMPDIR is $TMPDIR" + +if ! wget --quiet -O ${TMPDIR}/owners.list http://cvs.fedora.redhat.com/viewcvs/*checkout*/owners/owners.list?root=extras +then + byebye 2 Failed to get owners.list +fi + +if ! repoquery -a --repoid=buildcheck-extras-development-sources --repoid=buildcheck-extras-development-buildsys --qf='%{buildtime} %{name} %{version}-%{release}' *.src | sort | grep -B 9999 ${PACKAGESUPTO} | head -n -1 > ${TMPDIR}/repoquery +then + byebye 3 Repoquery failed +fi + +if ! repoquery -a --repoid=buildcheck-extras-development-x86 --repoid=buildcheck-extras-development-x64 --repoid=buildcheck-extras-development-ppc --repoid=buildcheck-extras-development-buildsys --qf='%{buildtime} %{name} %{arch} %{version}-%{release}' | sort | grep ' noarch ' | awk '{print $2}' > ${TMPDIR}/repoquery-noarch +then + byebye 3 Repoquery failed +fi + + + +while read buildtime name verrel +do + if ownerstring="$(grep \|${name}\| ${TMPDIR}/owners.list)" + then + echo "${ownerstring}" | while IFS='|' read ignoredone ignoredtwo ignoredthree emailone emailtwo emailthree emailfour alsoignored + do + echo ${emailone} ${name} ${verrel} | sed 's|@|_AT_|' >> ${TMPDIR}/result + done + else + echo No owner found for "${name}" >&2 + fi +done < ${TMPDIR}/repoquery + +sort < ${TMPDIR}/result | uniq | column -t > extras-tobuild +sort < ${TMPDIR}/result | uniq | column -t | grep -f ${TMPDIR}/repoquery-noarch > extras-tobuild-noarch +sort < ${TMPDIR}/result | uniq | column -t | grep -v -f ${TMPDIR}/repoquery-noarch > extras-tobuild-arch + + +byebye 0 diff --git a/rebuild-scripts/buildcheck-extras-development.repo b/rebuild-scripts/buildcheck-extras-development.repo new file mode 100644 index 0000000..0e6ffc6 --- /dev/null +++ b/rebuild-scripts/buildcheck-extras-development.repo @@ -0,0 +1,12 @@ +[buildcheck-extras-development-source] +name=Fedora Extras - Development - Source +baseurl=http://fedoraproject.org/extras/development/SRPMS/ +enabled=0 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-extras +gpgcheck=1 + +[buildcheck-extras-buildsys-source] +name=Fedora Extras - Development - Source +baseurl=http://buildsys.fedoraproject.org/plague-results/fedora-development-extras/ +enabled=0 +gpgcheck=1 diff --git a/rebuild-scripts/bumpspecfile.py b/rebuild-scripts/bumpspecfile.py new file mode 100755 index 0000000..9054266 --- /dev/null +++ b/rebuild-scripts/bumpspecfile.py @@ -0,0 +1,116 @@ +#!/usr/bin/python -t +# -*- mode: Python; indent-tabs-mode: nil; -*- + +import fcntl +import os, sys +import rpmUtils +import shutil +import string +import re +import time + +EXIT_ON_WARN = False + +class SpecFile: + def __init__(self,filename): + self.filename = filename + file=open(filename,"r") + self.lines=file.readlines() + file.close() + + def bumpRelease(self): + bump_patterns=[(re.compile(r"^Release:(\s*)(\d+.*)",re.I), self.increase), + (re.compile(r"^%define\s+rel\s+(\d+.*)"), self.increase2), + (re.compile(r"^%define\s+release\s+(\d+.*)"), self.increase3), + (re.compile(r"^%define\s+RELEASE\s+(\d+.*)"), self.increase4), + (re.compile(r"^Release:\s+%release_func\s+(\d+.*)"), self.increase5) + ] + skip_pattern=re.compile(r"\$Revision:") + for i in range(len(self.lines)): + if skip_pattern.search(self.lines[i]): continue + for bumpit, bumpit_func in bump_patterns: + self.lines[i]=bumpit.sub(bumpit_func,self.lines[i]) + + def addChangelogEntry(self,entry,email): + versionre=re.compile(r"^Version:\s*(\S+)") + changematch=re.compile(r"^%changelog") + date=time.strftime("%a %b %d %Y", time.localtime(time.time())) + for i in range(len(self.lines)): + versionmatch=versionre.search(self.lines[i]) + if(versionmatch): + version=versionmatch.group(1) + if(changematch.match(self.lines[i])): + newchangelogentry="%changelog\n* "+date+" "+email+" "+version+"-"+self.newrelease+"\n"+entry+"\n\n" + self.lines[i]=newchangelogentry + break + + def increaseMain(self,release): + relre = re.compile(r'(?P<pre>0\.)?(?P<rel>\d+)(?P<post>.*)',re.I) + relmatch = relre.search(release) + + pre = relmatch.group('pre') + value = int(relmatch.group('rel')) + self.newrelease = `value+1` + post = relmatch.group('post') + + old = '' + if pre != None: + old += pre + old += relmatch.group('rel')+post + + if pre == None: + if post.find('rc')>=0: + print 'CRUCIAL WARNING: Bad pre-release versioning scheme!' + print self.filename + if EXIT_ON_WARN: + sys.exit(1) + new = `value+1`+post + if True or post != '%{?dist}' and len(post): + self.debugdiff(old,new) + else: + if value == None or value > 10000: + print 'CRUCIAL WARNING: Bad pre-release versioning scheme!' + print self.filename + if EXIT_ON_WARN: + sys.exit(1) + new = '0.'+`value+1`+post + self.debugdiff(old,new) + return new + + def increase(self,match): + return 'Release:' + match.group(1) + self.increaseMain(match.group(2)) + + def increase2(self,match): + return '%define rel ' + self.increaseMain(match.group(1)) + + def increase3(self,match): + return '%define release ' + self.increaseMain(match.group(1)) + + def increase4(self,match): + return '%define RELEASE ' + self.increaseMain(match.group(1)) + + def increase5(self,match): + return 'Release: %release_func ' + self.increaseMain(match.group(1)) + + def writeFile(self,filename): + file=open(filename,"w") + file.writelines(self.lines) + file.close() + + def debugdiff(self,old,new): + print '-%s' % old + print '+%s\n' % new + +if __name__=="__main__": + if len(sys.argv) < 2: + print 'SYNTAX: %s <specfile> [specfile]...' % sys.argv[0] + sys.exit(22) + + userstring = "You <Your.Address@your.domain>" + for aspec in sys.argv[1:]: + s=SpecFile(aspec) + s.bumpRelease() + s.addChangelogEntry(" - rebuilt for unwind info generation, broken in gcc-4.1.1-21", userstring) + s.writeFile(aspec) + +sys.exit(0) diff --git a/rebuild-scripts/check_rebuild b/rebuild-scripts/check_rebuild new file mode 100755 index 0000000..863bbf3 --- /dev/null +++ b/rebuild-scripts/check_rebuild @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +# $Id: check_rebuild,v 1.1.1.1 2006/10/06 22:22:02 c4chris Exp $ +use strict; +my %B; +my $base_time = 1156678565; +while ( <> ) { + my @F = split; + my $name = $F[1]; + $name =~ s/-[^-]+-[^-]+\.src\.rpm$//; + if ($F[0] >= $base_time) { + $B{$name} = 1; + next; + } + next if defined $B{$name}; + print; +} +exit 0; diff --git a/rebuild-scripts/check_rebuild2 b/rebuild-scripts/check_rebuild2 new file mode 100755 index 0000000..c71c25a --- /dev/null +++ b/rebuild-scripts/check_rebuild2 @@ -0,0 +1,20 @@ +#!/usr/bin/env perl +# $Id: check_rebuild2,v 1.1.1.1 2006/10/06 22:22:02 c4chris Exp $ +use strict; +my %B; +my $cur = <>; +while ( $cur ) { + my @F = split /\s+/, $cur; + last if $F[1] eq "Sep" and $F[2] == 26; + $B{$F[5]} = 1; + $cur = <>; +} +while ( $cur ) { + my @F = split /\s+/, $cur; + last if $F[1] eq "Sep" and $F[2] == 17; + unless (defined $B{$F[5]}) { + print $cur; + } + $cur = <>; +} +exit 0; diff --git a/rebuild-scripts/check_release b/rebuild-scripts/check_release new file mode 100755 index 0000000..74b9999 --- /dev/null +++ b/rebuild-scripts/check_release @@ -0,0 +1,12 @@ +#!/usr/bin/env perl +# $Id: check_release,v 1.1.1.1 2006/10/06 22:22:02 c4chris Exp $ +use strict; +while ( <> ) { + s/\s+$//; + my @F = split; + my ($r) = $F[6] =~ /-([^-]+)$/; + $r =~ s/\.fc6//; + next if $r =~ /^\d+$/; + print "$_\n"; +} +exit 0; diff --git a/rebuild-scripts/gen_nr_2 b/rebuild-scripts/gen_nr_2 new file mode 100755 index 0000000..343b968 --- /dev/null +++ b/rebuild-scripts/gen_nr_2 @@ -0,0 +1,26 @@ +#!/usr/bin/env perl +# $Id: gen_nr_2,v 1.1.1.1 2006/10/06 22:22:02 c4chris Exp $ +use strict; +local *IN; +my %OWN; +open IN, "/home/chris/src/isrec/fedora/owners/owners.list" + or die "Couldn't open owners.list: $!"; +while ( <IN> ) { + next if /^#/; + s/\s+$//; + my @F = split /\|/; + next if $F[1] eq ""; + $OWN{$F[1]} = \@F; +} +close IN; +while ( <> ) { + my @F = split; + my $name = $F[0]; + my $e = $OWN{$name}; + my $o = "UNKNOWN"; + if (defined $e) { + $o = $$e[3]; + } + print "$o ", join(" ", @F), "\n"; +} +exit 0; diff --git a/rebuild-scripts/gen_rebuild_lst b/rebuild-scripts/gen_rebuild_lst new file mode 100755 index 0000000..c3fab75 --- /dev/null +++ b/rebuild-scripts/gen_rebuild_lst @@ -0,0 +1,26 @@ +#!/usr/bin/env perl +# $Id: gen_rebuild_lst,v 1.1.1.1 2006/10/06 22:22:02 c4chris Exp $ +use strict; +local *IN; +my %OWN; +open IN, "/home/chris/src/isrec/fedora/owners/owners.list" + or die "Couldn't open owners.list: $!"; +while ( <IN> ) { + next if /^#/; + s/\s+$//; + my @F = split /\|/; + next if $F[1] eq ""; + $OWN{$F[1]} = \@F; +} +close IN; +while ( <> ) { + my @F = split; + my $name = $F[1]; + my $e = $OWN{$name}; + if (defined $e) { + print "$$e[3]|$name\n"; + next; + } + print STDERR "No owner for $name\n"; +} +exit 0; diff --git a/rebuild-scripts/rm_noarch b/rebuild-scripts/rm_noarch new file mode 100755 index 0000000..317c6fe --- /dev/null +++ b/rebuild-scripts/rm_noarch @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +# $Id: rm_noarch,v 1.1.1.1 2006/10/06 22:22:02 c4chris Exp $ +use strict; +my %B; +local *IN; +open IN, "pkg_noarch.txt" or die "Couldn't open pkg_noarch.txt: $!"; +while ( <IN> ) { + chop; + my @F = split; + my $name = $F[4]; + $name =~ s/-[^-]+-[^-]+\.src\.rpm$//; + $B{$name} = 1; +} +close IN; +while ( <> ) { + my @F = split; + my $name = $F[5]; + next if defined $B{$name}; + print; +} +exit 0; diff --git a/rebuild-scripts/semi_auto_rebuild.txt b/rebuild-scripts/semi_auto_rebuild.txt new file mode 100644 index 0000000..e258cb8 --- /dev/null +++ b/rebuild-scripts/semi_auto_rebuild.txt @@ -0,0 +1,67 @@ +# Log of things done for the last semi-mass rebuild +# $Id: semi_auto_rebuild.txt,v 1.1.1.1 2006/10/06 22:22:02 c4chris Exp $ + + +# Grab list of noarch packages +repoquery -a --repoid=extras-development \ + --qf='%{buildtime} %{name} %{arch} %{version}-%{release} %{sourcerpm}' \ + | sort | grep ' noarch ' > pkg_noarch.txt + +# Grab list of source packages in the repo, with their build time +repoquery -a --repoid=buildcheck-extras-development-source \ + --qf='%{buildtime} %{name} %{version}-%{release}' \*.src \ + | sort -nr > lst.txt + +# Turn the time in a readable form +perl -ane '$F[0] = localtime($F[0]); print join(" ", @F), "\n"' \ + lst.txt > lst2.txt + +# Apply script to determine which ones need a rebuild +./check_rebuild2 lst2.txt > lst3.txt + +# Remove the noarch packages from the list +./rm_noarch lst3.txt >lst4.txt + +# Produce a list of package names to include in a mail +perl -ane 'print "$F[5]\n"' lst4.txt|sort >~/to_rebuild.txt + +# Add package owner email field in the list of packages to rebuild +./add_owner lst4.txt >lst5.txt + +# Edit list to hand-remove packages that other people said they'd handle +# themselves +vi lst5.txt + +# Mark out packages that do not have a simple numeric release field +./check_release lst5.txt > lst_noauto.txt + +# Extract the list of simple packages +diff lst5.txt lst_noauto.txt |grep '^<'|sed 's/^..//' >lst_auto.txt + +# Make sure we have the latest version of all packages in our CVS checkout +pushd /export/scratch/extras/ +cvs update +popd + +# Do the automated mass rebuild for the simple packages +for f in `awk '{print $6}' lst_auto.txt`; do + echo $f + ./bumpspecfile.py /export/scratch/extras/$f/devel/$f.spec + pushd /export/scratch/extras/$f/devel + cvs commit -m 'automated bump and rebuild' && make tag && make build + popd +done + +# Now do the rest of the packages (repeat for each package...) + for f in `head -1 lst_noauto.txt | awk '{print $6}'`; do + echo $f + ./bumpspecfile.py /export/scratch/extras/$f/devel/$f.spec + pushd /export/scratch/extras/$f/devel + cvs diff + done + vi <package>.spec + cvs diff + cvs commit -m 'automated bump and rebuild' && make tag && make build + popd + vi lst_noauto.txt # To remove the first line +# Done... |