From a44c74347d9b68a1f3d5a94c53f30423c43a5d28 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Fri, 15 May 2015 14:52:31 +0000 Subject: Add extension for lorrying cpan perl modules. Based on the rubygems one. --- baserockimport/exts/cpan.to_lorry | 106 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100755 baserockimport/exts/cpan.to_lorry diff --git a/baserockimport/exts/cpan.to_lorry b/baserockimport/exts/cpan.to_lorry new file mode 100755 index 0000000..bcca022 --- /dev/null +++ b/baserockimport/exts/cpan.to_lorry @@ -0,0 +1,106 @@ +#!/usr/bin/python +# +# Create a Baserock .lorry file for a given RubyGem +# +# Copyright (C) 2014 Codethink Limited +# +# 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 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., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +import requests +import requests_cache +import yaml +import json +import logging +import os +import sys +import urlparse + +from importer_base import ImportException, ImportExtension + + +class GenerateLorryException(ImportException): + pass + + +class CPANWebServiceClient(object): + def __init__(self): + # Save hammering the cpanmetadb.plackperl.org API: 'requests' API calls are + # transparently cached in an SQLite database, instead. + requests_cache.install_cache('cpan_api_cache') + + def _request(self, url): + r = requests.get(url) + if r.ok: + return yaml.load(r.text) + else: + raise GenerateLorryException( + 'Request to %s failed: %s' % (r.url, r.reason)) + + def get_cpan_info(self, cpan_name): + info = self._request( + 'http://cpanmetadb.plackperl.org/v1.0/package/%s' % cpan_name) + + # TODO: Sanity check? Check name appears in distfile string? + # TODO: Use the history/ API, rather than package/ to get version list? + return info + + +class CPANLorryGenerator(ImportExtension): + def __init__(self): + super(CPANLorryGenerator, self).__init__() + + def process_args(self, args): + if len(args) not in [1, 2]: + raise ImportException( + 'Please call me with the name of a CPAN module as an argument' + ' and optionally its version number (format: NAME [VERSION])') + + cpan_name = args[0] + # TODO: Version handling? + + lorry = self.generate_lorry_for_module(cpan_name) + self.write_lorry(sys.stdout, lorry) + + def find_tarball_uri_for_module(self, cpan_name, cpan_info): + return 'http://cpan.metacpan.org/authors/id/' + cpan_info['distfile'] + + def generate_lorry_for_module(self, cpan_name): + cpan_client = CPANWebServiceClient() + + cpan_info = cpan_client.get_cpan_info(cpan_name) + + cpan_source_url = self.find_tarball_uri_for_module(cpan_name, cpan_info) + logging.info('Got URL <%s> for %s', cpan_source_url, cpan_name) + + lorry_name = 'cpan/' + cpan_name.replace('::', '-') + + lorry = { + lorry_name: { + 'type': 'tarball', + 'url': cpan_source_url, + 'x-products-cpan': [cpan_name] + } + } + + return lorry + + def write_lorry(self, stream, lorry): + json.dump(lorry, stream, indent=4) + # Needed so the morphlib.extensions code will pick up the last line. + stream.write('\n') + + +if __name__ == '__main__': + CPANLorryGenerator().run() -- cgit v1.2.1