#!/usr/bin/env python # Generate a port for a CPAN module. from garstowlib.makeport import * import garstowlib.packages from garstowlib.utils import die import sys, urllib, re, yaml, os, glob # As of 2011-02-04, search.cpan.org is returning most of its text encoded as # decimal characters... def decode(s): def expand(m): return chr(int(m.group(1))) return re.sub(r'&#(\d+);', expand, s) def make_cpan_port(package): if package.startswith("p5-"): package = package[3:] package = package.replace("::", "-") print "Fetching CPAN info for " + package + "...", sys.stdout.flush() url = "http://search.cpan.org/dist/" + package f = urllib.urlopen(url) page = f.read() f.close() # href="/CPAN/authors/id/M/MS/MSCHILLI/Log-Log4perl-1.05.tar.gz">Download< m = re.search(r'href="[^"]*/([^"/]*)/([^"/]*)">Download<', page) if m is None: die("cannot find Download link in page for ", package) (author, distfile) = m.group(1, 2) m = re.match(r'^(.*)-([a-zA-Z0-9._]+)\.(tar\.gz|tgz)$', distfile) if m is None: die("cannot parse distfile name for ", package, ": ", distfile) (n, version) = m.group(1, 2) if n != package: print "changing package name from " + package + " to " + n package = n i = page.find("

Modules

") if i == -1: die("cannot find Modules heading in ", package) d = page[i:] i = d.find(">" + package.replace("-", "::") + "<") if i != -1: d = d[i:] m = re.search(r'([^<]+) ', d) if m is None: print "cannot find description for " + package description = "Perl module " + package else: description = decode(m.group(1)) print package, author, version # href="/src/MSCHILLI/Log-Log4perl-1.05/META.yml">META.yml m = re.search(r'href="([^"]*)">META.yml<', page) deps = {} deps["perl/perl"] = True if m is not None: print "Fetching META.yml...", sys.stdout.flush() f = urllib.urlopen(urllib.basejoin(url, m.group(1))) meta = yaml.load(f.read().decode("ISO-8859-1")) f.close() print meta stowdir = garstowlib.packages.get_stow_dir() reqs = meta.get("requires") if reqs is None: reqs = {} for dep in reqs.keys(): if dep == "perl": continue fn = dep.replace("::", "/") + ".pm" installed = [] for path in ("lib/perl5/*", "lib/perl5/*/*", "lib/perl5/site_perl/*/*"): installed += glob.glob(stowdir + "/" + path + "/" + fn) if installed == []: deps["perl/p5-" + dep.replace("::", "-")] = True print "Needs new package " + dep else: op = garstowlib.packages.get_owning_package(installed[0]) pn = garstowlib.packages.get_full_package_name(op) deps[pn] = True print "Needs existing package " + pn garname = "p5-" + package lines = [ VarLine("GARNAME", garname), VarLine("GARVERSION", version, mode = "update"), VarLine("CPAN_AUTHOR", author, mode = "update"), VarLine("LIBDEPS", " ".join(deps.keys()), mode = "merge-deps"), BlankLine(), VarLine("DESCRIPTION", description.strip(), mode = "update"), BlankLine(), IncludeLine("../cpan.mk"), ] update_portfile(garname + "/Makefile", lines) if __name__ == "__main__": for package in sys.argv[1:]: make_cpan_port(package)