X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=tools%2Fblends-inject;h=d62d3ba7dee23e06f5228b3fa5d6123479e58f11;hb=HEAD;hp=cec34f5d5f91f1d5242c5de3d1b0d5fe7c1d2fee;hpb=69d7482b5072e3bdf6eb613314fbf4215dd67fbd;p=neurodebian.git diff --git a/tools/blends-inject b/tools/blends-inject index cec34f5..d62d3ba 100755 --- a/tools/blends-inject +++ b/tools/blends-inject @@ -19,7 +19,7 @@ Possible TODOs: * For every package the same task file might be re-read/written (if entry changed/added) from disk. That allows to replace easily original entry for 'source' package - (listed as Ignore:) with actual first listed binary package. + (listed as Suggests:) with actual first listed binary package. This should be taken into consideration if current per-package handling gets changed @@ -33,14 +33,24 @@ Paths to the blends top directories, containing tasks directories are specified in ~/.blends-inject.cfg file, e.g.:: [debian-med] - path = /home/yoh/deb/debian-med/ + path = ~/deb/debian-med/ [debian-science] - path = /home/yoh/deb/debian-science/ - + path = ~/deb/debian-science/ Definition of the fields for task files by default are looked up -within debian/blends, or files provided in the command line. +within debian/blends, or files provided in the command line. Also for "-a" +mode of operation you should define list of globs to match your debian/blends +files:: + + [paths] + all=~/deb/gits/pkg-exppsy/neurodebian/future/blends/* + ~/deb/gits/*/debian/blends + ~/deb/gits/pkg-exppsy/*/debian/blends + # Python regular expression on which files to skip + # Default is listed below + #skip=.*[~#]$ + Format of debian/blends ----------------------- @@ -104,7 +114,7 @@ Remove: python-brian-doc """ -import re, os, sys +import re, os, sys, tempfile, glob from os.path import join, exists, expanduser, dirname, basename from ConfigParser import ConfigParser @@ -125,7 +135,7 @@ def open(f, *args): __author__ = 'Yaroslav Halchenko' __prog__ = os.path.basename(sys.argv[0]) -__version__ = '0.0.3' +__version__ = '0.0.7' __copyright__ = 'Copyright (c) 2010 Yaroslav Halchenko' __license__ = 'GPL' @@ -136,12 +146,12 @@ PKG_FIELDS = ('depends', 'recommends', 'suggests', 'ignore', 'remove') # Prefixes for "standard" blends/tasks fields. Others do not get embedded # into tasks files BLENDS_FIELDS_PREFIXES = ('depends', 'recommends', 'suggests', 'ignore', - 'why', 'homepage', 'wnpp', 'responsible', 'license', + 'why', 'homepage', 'language', 'wnpp', 'responsible', 'license', 'vcs-', 'pkg-url', 'pkg-description', 'published-', 'x-', 'registration', 'remark') # Additional fields which might come useful (e.g. for filing wnpp bugs) # but are not "standard" thus should be in the trailer -CUSTOM_FIELDS_PREFIXES = ('author', 'language', 'pkg-name', 'pkg-source', +CUSTOM_FIELDS_PREFIXES = ('author', 'pkg-name', 'pkg-source', 'version', 'remove') # Other fields should cause Error for consistency @@ -155,7 +165,7 @@ def error(msg, exit_code=1): def verbose(level, msg): if level <= verbosity: - print " "*level, msg + sys.stderr.write(" "*level + msg + '\n') def parse_debian_blends(f='debian/blends'): @@ -185,7 +195,9 @@ def parse_debian_blends(f='debian/blends'): pkg = deepcopy(prev_pkg) for k_ in PKG_FIELDS: # prune older depends pkg.pop(k_, None) - pkg['Pkg-Name'] = pkg[k] = bname + pkg['Pkg-Name'] = pkg[k] = bname.lower() + if sname is not None: + sname = sname.lower() pkg['Pkg-Source'] = sname pkgs.append(pkg) pkg.tasks = dict( (t.strip(), deb822.Deb822Dict()) for t in tasks ) @@ -195,6 +207,7 @@ def parse_debian_blends(f='debian/blends'): for k, v in items: kl = k.lower() + if kl == 'source': source = v.strip() elif kl == 'format': @@ -203,25 +216,26 @@ def parse_debian_blends(f='debian/blends'): if format_clean: format_ = format_[:-6] elif kl == 'tasks': - tasks = v.split(',') - newtasks = True # either we need to provide tune-ups + tasks = [x.strip() for x in v.split(',')] + newtasks = pkg is not None # either we need to provide tune-ups # for current package elif kl in PKG_FIELDS: # new package - if source is None: + if source is None and not format_ in ['extended']: source = v pkg = new_pkg(pkg, v, source, tasks) newtasks = False else: + if pkg is None: + # So we had just source? + if source is None: + error("No package or source is known where to add %s" % (k,), 1) + # TODO: just deduce source from DebianMaterials + pkg = new_pkg(pkg, source, source, tasks) + # Since only source is available, it should be only Suggest:-ed + pkg['Suggests'] = source.lower() + newtasks = False + if newtasks: - if pkg is None: - # So we had just source? - if source is None: - error("No package or source is known where to add %s" % (k,), 1) - # TODO: just deduce source from DebianMaterials - pkg = new_pkg(pkg, source, source, tasks) - # Since only source is available, it should be Ignore:-ed - pkg['Ignore'] = source - newtasks = False # Add customization for t in tasks: if not t in pkg.tasks: @@ -230,6 +244,7 @@ def parse_debian_blends(f='debian/blends'): else: # just store the key in the pkg itself pkg[k] = v + return pkgs @@ -239,6 +254,7 @@ def expand_pkgs(pkgs, topdir='.'): """ verbose(4, "Expanding content for %d packages" % len(pkgs)) debianm = None + # Expand packages which format is extended for pkg in pkgs: if pkg.format == 'extended': @@ -250,7 +266,9 @@ def expand_pkgs(pkgs, topdir='.'): ('Pkg-Description', lambda: debianm.get_description(pkg['Pkg-Name'])), ('Responsible', debianm.get_responsible), - ('Homepage', lambda: debianm.source.get('Homepage', None))): + ('Homepage', lambda: debianm.source.get('Homepage', None)), + ('Pkg-source', lambda: debianm.source.get('Source', None)), + ): if pkg.get(k, None): continue v = m() @@ -341,7 +359,7 @@ def inject_tasks(tasks, config): for task, pkgs in tasks.iteritems(): verbose(2, "Task %s with %d packages" % (task, len(pkgs))) blend, puretask = task.split('/') - taskfile = join(config.get(blend, 'path'), 'tasks', puretask) + taskfile = expanduser(join(config.get(blend, 'path'), 'tasks', puretask)) # Load the file stats = dict(Added=[], Modified=[]) @@ -364,11 +382,13 @@ def inject_tasks(tasks, config): entries = open(taskfile).readlines() known = False # We need to search by name and by source - # We need to search for every possible type of dependecy - regexp = re.compile('^ *(%s) *: *(%s) *$' % - ('|'.join(PKG_FIELDS), - '|'.join((pkg.name, pkg.source))), - re.I) + # We need to search for every possible type of dependency + regexp_str = '^ *(%s) *: *(%s) *$' \ + % ('|'.join(PKG_FIELDS), + '|'.join((pkg.name, pkg.source)).replace('+', '\+')) + verbose(4, "Searching for presence in %s using regexp: '%s'" + % (taskfile, regexp_str)) + regexp = re.compile(regexp_str, re.I) for istart, e in enumerate(entries): if regexp.search(e): verbose(4, "Found %s in position %i: %s" % @@ -414,9 +434,6 @@ def inject_tasks(tasks, config): entries_prior = entries[:istart] entries_post = entries[istart+icount:] elif not 'remove' == pkg.action: # or Append one - if pkg.name == 'python-brian-doc': - import pydb - pydb.debugger() msgs['Action'] = 'Added' entries_prior = entries entry = descr + entry @@ -486,7 +503,9 @@ class DebianMaterials(object): if v.get('Source', None): self._source = v else: - self._binaries[v['Package']] = v + # Since it might be hash-commented out + if 'Package' in v: + self._binaries[v['Package']] = v def get_license(self, package=None, first_only=True): """Return a license(s). Parsed out from debian/copyright if it is @@ -555,6 +574,57 @@ class DebianMaterials(object): % (pkg_name, self)) return self.binaries[pkg_name]['Description'] +def print_wnpp(pkgs, config, wnpp_type="ITP"): + """Little helper to spit out formatted entry for WNPP bugreport + + TODO: It would puke atm if any field is missing + """ + + pkg = pkgs[0] # everything is based on the 1st one + opts = dict(pkg.items()) + opts['WNPP-Type'] = wnpp_type.upper() + opts['Pkg-Description-Short'] = re.sub('\n.*', '', pkg['Pkg-Description']) + + subject = "%(WNPP-Type)s: %(Pkg-Name)s -- %(Pkg-Description-Short)s" % opts + body = """*** Please type your report below this line *** + +* Package name : %(Pkg-Name)s + Version : %(Version)s + Upstream Author : %(Author)s +* URL : %(Homepage)s +* License : %(License)s + Programming Lang: %(Language)s + Description : %(Pkg-Description)s + +""" % opts + + # Unfortunately could not figure out how to set the owner, so I will just print it out + if False: + tmpfile = tempfile.NamedTemporaryFile() + tmpfile.write(body) + tmpfile.flush() + cmd = "reportbug -b --paranoid --subject='%s' --severity=wishlist --body-file='%s' -o /tmp/o.txt wnpp" \ + % (subject, tmpfile.name) + verbose(2, "Running %s" %cmd) + os.system(cmd) + else: + print "Subject: %s\n\n%s" % (subject, body) + + +def is_template(p): + """Helper to return true if pkg definition looks like a template + and should not be processed + """ + # We might want to skip some which define a skeleton + # (no source/homepage/etc although fields are there) + for f in ['vcs-browser', 'pkg-url', 'pkg-description', + 'published-Title', 'pkg-name', 'homepage', + 'author']: + if f in p and p[f] != "": + return False + return True + + def main(): p = OptionParser( @@ -577,21 +647,53 @@ def main(): Option("-v", "--verbosity", action="store", type="int", dest="verbosity", default=1, help="Noise level.")) + # We might like to create a separate 'group' of options for commands + p.add_option( + Option("-w", action="store_true", + dest="wnpp", default=False, + help="Operate in WNPP mode: dumps cut-paste-able entry for WNPP bugreport")) + + p.add_option( + Option("--wnpp", action="store", + dest="wnpp_mode", default=None, + help="Operate in WNPP mode: dumps cut-paste-able entry for WNPP bugreport")) + + p.add_option( + Option("-a", action="store_true", + dest="all_mode", default=False, + help="Process all files listed in paths.all")) + + (options, infiles) = p.parse_args() global verbosity; verbosity = options.verbosity - if not len(infiles): - infiles = [join(options.topdir or './', 'debian/blends')] # default one + if options.wnpp and options.wnpp_mode is None: + options.wnpp_mode = 'ITP' # Load configuration - config = ConfigParser() + config = ConfigParser(defaults={'skip': '.*[~#]$'}) config.read(options.config_file) + if options.all_mode: + if len(infiles): + raise ValueError("Do not specify any files in -a mode. Use configuration file, section paths, option all") + globs = config.get('paths', 'all', None).split() + infiles = reduce(list.__add__, (glob.glob(expanduser(f)) for f in globs)) + verbose(1, "Found %d files in specified paths" % len(infiles)) + + if not len(infiles): + infiles = [join(options.topdir or './', 'debian/blends')] # default one + + skip_re = re.compile(config.get('paths', 'skip', None)) + for blends_file in infiles: verbose(1, "Processing %s" % blends_file) if not exists(blends_file): error("Cannot find a file %s. Either provide a file or specify top " "debian directory with -d." % blends_file, 1) + if skip_re.match(blends_file): + verbose(2, "W: Skipped since matches paths.skip regexp") + continue pkgs = parse_debian_blends(blends_file) if options.topdir is None: if dirname(blends_file).endswith('/debian'): @@ -600,9 +702,19 @@ def main(): topdir = '.' # and hope for the best ;) else: topdir = options.topdir - expand_pkgs(pkgs, topdir=topdir) - tasks = group_packages_into_tasks(pkgs) - inject_tasks(tasks, config) + + expand_pkgs(pkgs, topdir=topdir) + + pkgs = [p for p in pkgs if not is_template(p)] + if not len(pkgs): + verbose(2, "W: Skipping since seems to contain templates only") + continue + if options.wnpp_mode is not None: + print_wnpp(pkgs, config, options.wnpp_mode) + else: + # by default -- operate on blends/tasks files + tasks = group_packages_into_tasks(pkgs) + inject_tasks(tasks, config) if __name__ == '__main__':