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