diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000..9a883d851 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,38 @@ +--- +# Use the latest 2.1 version of CircleCI pipeline process engine. See: +# https://circleci.com/docs/2.0/configuration-reference +version: 2.1 +orbs: + codecov: codecov/codecov@4.1.0 +# Orchestrate or schedule a set of jobs +workflows: + docker-compose: + jobs: + - build-and-test +jobs: + build-and-test: + machine: true + resource_class: large + steps: + - run: + name: docker compose version + command: docker compose version + - checkout + - run: + name: create coverage directory + command: | + mkdir cover_db + chmod o+w cover_db + - run: + name: docker compose build + command: | + docker compose --profile test build api-test + - run: + name: run tests with coverage + command: | + docker compose --profile test run --env HARNESS_PERL_SWITCHES=-MDevel::Cover -v ./cover_db:/app/cover_db/ api-test bash -c 'prove -lr -j4 t && cover -report codecovbash' + # We are relying on environment variables from the host to be available when + # we publish the report, so we publish from the host rather than trying + # to propagate env variables to the container. + - codecov/upload: + file: cover_db/codecov.json diff --git a/.dockerignore b/.dockerignore new file mode 120000 index 000000000..3e4e48b0b --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +.gitignore \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index 112ded780..7ff72b0cc 100644 --- a/.editorconfig +++ b/.editorconfig @@ -17,5 +17,6 @@ charset = utf-8 #trim_trailing_whitespace = true insert_final_newline = true -[.travis.yml] +# yaml indents are weird +[*.{yml,yaml}] indent_size = 2 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..0a9225563 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,143 @@ +# How to contribute + +We are always after more contributors and suggestions. + +### How can I help? + +The following issues are tagged as [Volunteer needed](https://github.com/CPAN-API/cpan-api/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3A%22Volunteer+needed%22+no%3Aassignee+) + +## Suggestions or issues with MetaCPAN... + +#### Does it relate to our API (backend)... ? + + 1. Please check the [previously reported API issues](https://github.com/CPAN-API/cpan-api/issues) + 2. Please check the [Wishlist](https://github.com/CPAN-API/cpan-api/wiki/Wishlist). If you can't find it already there: + * If it's a wishlist idea, please edit the [wiki](https://github.com/CPAN-API/cpan-api/wiki/Wishlist) (add a 'wishlist_MYIDEA' page if you need more space!) + * If it's an actual bug [create a new issue](https://github.com/CPAN-API/cpan-api/issues/new) + +#### If you are not sure, or it is related to https://metacpan.org/ front end: + + 1. Please check the [previously reported Web issues](https://github.com/CPAN-API/metacpan-web/issues) + 2. Please check the [Wishlist](https://github.com/CPAN-API/cpan-api/wiki/Wishlist). If you can't find it already there: + * If it's a wishlist idea, please edit the [wiki](https://github.com/CPAN-API/cpan-api/wiki/Wishlist) (add a 'wishlist_MYIDEA' page if you need more space!) + * If it's an actual bug [create a new issue](https://github.com/CPAN-API/metacpan-web/issues/new) + +## Contributing code + +Come talk to us on IRC (see below), or send a pull request and we'll respond +there. If you implement a new feature, please add a note about it to the +News.md file at the top level of metacpan-web so that it will appear in our +news feed. + +If you aren't using the VM, remember to enable the pre-commit hook before you start working. + + sh git/setup.sh + +These links will get you going quickly: + + * [Using our developer VM](https://github.com/CPAN-API/metacpan-developer) to get you going in minutes (depending on bandwidth) + * [Front end bug list](https://github.com/CPAN-API/metacpan-web/issues) + * [API (back end) bug list](https://github.com/CPAN-API/cpan-api/issues) + * [Wishlist](https://github.com/CPAN-API/cpan-api/wiki/Wishlist) - things that probably need doing + +# Git workflow + +We try to keep a clean git history, so if it all possible, please rebase to get +the latest changes from master _before_ submitting a pull request. You'll only +need to do the first command (git remote add) once in your local checkout. + + git remote add upstream https://github.com/CPAN-API/metacpan-web.git + git pull --rebase upstream master + +If you are comfortable rebasing, it is also helpful to squash or delete commits +which are no longer relevant to your branch before submitting your work. + + git rebase -i master + +If you are not comfortable with rebasing, but want to use it, check out the steps +from [here](https://help.github.com/articles/using-git-rebase/). + +# Coding conventions + +Please try to follow the conventions already been used in the code base. This +will generally be the right thing to do. Our standards are improving, so even +if you do follow what you see, we may ask you to make some changes, but that is +a good thing. We are trying to keep things tidy. + +If you are using the [developer VM](https://github.com/CPAN-API/metacpan-developer) you can run: + +```sh +/home/vagrant/carton/metacpan-web/bin/tidyall +``` + +## Perl Best Practices + +In general, the concepts discussed in "Perl Best Practices" are a good starting +point. Use autodie where possible and MetaCPAN::Web::Types when creating new +Moose attributes. Many of the other standards will be enforced by Perl::Critic. + +## Clear > Concise + +Take pains to use variable names which are easy to understand and to write +readable code. We value readable code over concise code. Use singular nouns +for class names. Use verbs for method names. + +## Try::Tiny > eval { ... } + +You will see many eval statements in the code. We would like to standardize on +Try::Tiny, so feel free to swap out any eval with a Try::Tiny and use Try::Tiny +in all new code. + +## Prefer single quotes + +Always use single quotes in cases where there is no variable interpolation. If +there is a single quote in the quoted item, use curly quotes. + +q{Isn't this a lovely day}; + +## Include a test (or more!) + +Any time when a pull request includes a test, it makes it easier for us to +review and accept, so please do test your changes whenever possible. If your +pull request includes visual changes, please include a before and after screen +shot, so that we can better understand the problem you're trying to solve. + +## Dependencies + +Introducing new dependencies is fine, if they solve a specific problem which +current dependencies cannot address. If we prefer a different module to be used, +we'll let you know. + +## It's OK to be controversial + +If a pull request contains any controversial changes, we'll likely wait for some +feedback from several developers before a merge. If you think your changes may +be controversial, feel free to discuss them in a Github issue before starting to +write any code. + +## Travis is your friend + +We use Travis to test all code changes. After submitting your pull request, +remember to check back to see whether Travis has come back with any test +failures. We do get some false negatives. If your pull request failed for +reasons unrelated to your changes, we may still be able to merge your work. + +# Additional Resources + + * [\#metacpan](http://widget01.mibbit.com/?autoConnect=true&server=irc.perl.org&channel=%23metacpan&nick=) IRC channel on irc.perl.org + +# Current Policies + +### What is indexed? + + * Perl distributions which contain Perl packages. + +### When are issues closed? + +We want to keep the issue list manageable, so we can focus on what actually +needs fixing. If you feel an issue needs opening again, please add a comment +explaining why it needs re-opening and we'll look at it again. + + * Issues will be closed and moved to [Wishlist](https://github.com/CPAN-API/cpan-api/wiki/Wishlist) if they are not actual bugs + * Issues we think we have addressed will be closed + * Issues we are not going to take any further action on without more information will be closed diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..326ba5a61 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,18 @@ +# Important, please read: + +MetaCPAN's core developers need to focus on fixing bugs and improving the +existing core system. + +For this reason, if you have a feature which you would like to see added (there +are loads we would love to have), please only open an issue _IF_ you are +prepared to do the work to implement it. To be clear, we'd love to have a +bunch of really cool, new, features, but it's more important for us to focus on +keeping MetaCPAN humming along. + +If you're not motivated or otherwise able to send a pull request for your cool, +new feature, please add it to our wishlist: +https://github.com/CPAN-API/cpan-api/wiki/Wishlist and someone may get to it +one day. Maybe that person will be you! + +For more details on issues and contributing please see CONTRIBUTING.md (linked +above). diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..675a53345 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +--- +version: 2 +updates: + - package-ecosystem: 'github-actions' + directory: '/' + schedule: + # Check for updates to GitHub Actions every week + interval: 'weekly' diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml new file mode 100644 index 000000000..a9b56fc7e --- /dev/null +++ b/.github/workflows/automerge.yml @@ -0,0 +1,22 @@ +name: Enable Auto-Merge For bots +on: + pull_request_target: + types: [opened] + +jobs: + enable-auto-merge: + runs-on: ubuntu-latest + if: > + github.event.pull_request.user.login == 'metacpan-automation[bot]' + || github.event.pull_request.user.login == 'dependabot[bot]' + steps: + - name: Generate Auth Token + uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + - uses: peter-evans/enable-pull-request-automerge@v3 + with: + token: ${{ steps.app-token.outputs.token }} + pull-request-number: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/build-container.yml b/.github/workflows/build-container.yml new file mode 100644 index 000000000..00d325bee --- /dev/null +++ b/.github/workflows/build-container.yml @@ -0,0 +1,44 @@ +name: Build container +on: + push: + branches: + - master + - staging + - prod + pull_request: + types: [opened, synchronize, labeled] + branches: + - master + workflow_dispatch: +jobs: + docker-build: + if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'build-container') + runs-on: ubuntu-22.04 + name: Docker Build and Push + steps: + - name: Generate Auth Token + uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: metacpan + - uses: actions/checkout@v5 + with: + token: ${{ steps.app-token.outputs.token }} + - uses: metacpan/metacpan-actions/docker-build-push@master + id: build-push + with: + docker_hub_username: ${{ secrets.DOCKER_HUB_USER }} + docker_hub_password: ${{ secrets.DOCKER_HUB_TOKEN }} + ghcr_username: ${{ github.repository_owner }} + ghcr_password: ${{ secrets.GITHUB_TOKEN }} + - name: Update deployed image + if: ${{ fromJSON(steps.build-push.outputs.tag-fq).latest }} + uses: metacpan/metacpan-actions/update-deployed-tag@master + with: + token: ${{ steps.app-token.outputs.token }} + app: api + environment: prod + base-tag: ${{ fromJSON(steps.build-push.outputs.tag-fq).latest }} + tag: ${{ fromJSON(steps.build-push.outputs.tag-fq).sha }} diff --git a/.github/workflows/code-formatting.yml b/.github/workflows/code-formatting.yml new file mode 100644 index 000000000..b833d372c --- /dev/null +++ b/.github/workflows/code-formatting.yml @@ -0,0 +1,49 @@ +--- +name: Code Formatting +on: + push: + branches: + - 'master' + merge_group: + pull_request: + branches: + - '*' + workflow_dispatch: + +jobs: + code-formatting: + runs-on: ubuntu-24.04 + name: Code Formatting + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + - name: Fetch base ref + if: ${{ github.event.pull_request }} + run: git fetch origin ${{ github.base_ref }}:upstream + - name: Install Carton + uses: perl-actions/install-with-cpm@v1 + with: + install: Carton + - name: Install CPAN deps + uses: perl-actions/install-with-cpm@v1 + with: + cpanfile: 'cpanfile' + args: > + --resolver=snapshot + --with-develop + - name: Install precious + run: ./bin/install-precious /usr/local/bin + env: + GITHUB_TOKEN: ${{ github.token }} + - run: perltidy --version + - name: Select files + id: select-files + run: | + if [[ -n "${{ github.event.pull_request.number }}" ]]; then + echo 'precious-args=--git-diff-from upstream' >> "$GITHUB_OUTPUT" + else + echo 'precious-args=--all' >> "$GITHUB_OUTPUT" + fi + - name: Lint files + run: precious lint ${{ steps.select-files.outputs.precious-args }} diff --git a/.github/workflows/update-snapshot.yml b/.github/workflows/update-snapshot.yml new file mode 100644 index 000000000..816301081 --- /dev/null +++ b/.github/workflows/update-snapshot.yml @@ -0,0 +1,35 @@ +name: Update cpanfile.snapshot +on: + schedule: + - cron: "1 15 * * 0" + workflow_dispatch: +jobs: + update-dep: + runs-on: "ubuntu-22.04" + container: + image: perl:5.22-buster + steps: + - name: Generate Auth Token + uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + - uses: haarg/setup-git-user@v1 + with: + app: ${{ steps.app-token.output.app-slug }} + - uses: actions/checkout@v5 + with: + token: ${{ steps.app-token.outputs.token }} + - name: Update cpanfile.snapshot + uses: metacpan/metacpan-actions/update-snapshot@master + - name: Create Pull Request + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ steps.app-token.outputs.token }} + commit-message: Update cpanfile.snapshot + title: Update cpanfile.snapshot + sign-commits: true + body: | + [GitHub Action Run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) + branch: update-cpanfile-snapshot diff --git a/.gitignore b/.gitignore index 871180658..cd6e79b24 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,25 @@ -# carton/local::lib -/local/ - -.DS_Store -*.sw* -*.kpf -*.komodoproject -*.sqlite* -/var -/t/var/tmp/ -/etc/metacpan_local.pl -metacpan_server_local.conf - -# generated by Makefile.PL (for instance when doing `cpanm --installdeps .`) +/MYMETA.* /Makefile /Makefile.old -/MYMETA.* -/pm_to_blib /blib - -# tidyall +/cover_db/ +/local/ +/log4perl_local.conf +/metacpan_server_local.* +/metacpan_server_testing_local.* +/perltidy.LOG +/pm_to_blib +/var +/bin/omegasort +/bin/precious +/bin/ubi +/etc/metacpan_local.pl +/t/var/darkpan/ +/t/var/log/ +/t/var/tmp/ +*.komodoproject +*.kpf +*.sqlite* +*.sw* +.DS_Store .tidyall.d -perltidy.LOG - -# coverage -cover_db/ diff --git a/.mailmap b/.mailmap new file mode 100644 index 000000000..8c9325def --- /dev/null +++ b/.mailmap @@ -0,0 +1,53 @@ +# shared between metacpan-web and metacpan-api + +Amrita Mathew +Andreas Marienborg +Andreea Pirvulescu +Andreea Pirvulescu +Andrew Fresh +Andrew Fresh +Barry Walsh +Brad Lhotsky +Chris Nehren +Christopher White +Christopher White +Christopher White +Clinton Gormley +Ed J +Gabor Szabo +Grant McLean +Grant McLean +J. Bobby Lopez +Jess Robinson +Joel Berger +Johannes Plunien +Mario Zieschang +Mark Fowler +Matthew Horsfall (alh) +Michael Peters +Michael Peters +Michiel Beijen +Mickey Nasriachi +Mickey Nasriachi +Mickey Nasriachi +Moritz Onken +Nicolas R +Olaf Alders +Olaf Alders +Olaf Alders +Randy Stauner +Renee Baecker +Shawn M Moore +Shawn Sorichetti +Sunny Patel +Sunny Patel +Talina Shrotriya +Talina Shrotriya +Talina Shrotriya Talina06 <--global> +Thomas Sibley +Tim Bunce +Vyacheslav Matyukhin +Zachary Dykstra +lnation +oiami +oiami diff --git a/.perlcriticrc b/.perlcriticrc index 4c78b9e27..578566da8 100644 --- a/.perlcriticrc +++ b/.perlcriticrc @@ -2,21 +2,31 @@ severity = 5 verbose = 11 +theme = core [-ControlStructures::ProhibitPostfixControls] -[-Documentation::RequirePodLinksIncludeText] [-Documentation::RequirePodSections] +[-InputOutput::ProhibitInteractiveTest] [-Modules::RequireVersionVar] [-RegularExpressions::RequireDotMatchAnything] [-RegularExpressions::RequireExtendedFormatting] [-RegularExpressions::RequireLineBoundaryMatching] +[-Subroutines::ProhibitExplicitReturnUndef] +[-TestingAndDebugging::ProhibitNoStrict] +[-ValuesAndExpressions::ProhibitNoisyQuotes] [-Variables::ProhibitPunctuationVars] +# doesn't understand signatures +[-Subroutines::ProhibitSubroutinePrototypes] + [CodeLayout::RequireTrailingCommas] severity = 4 [TestingAndDebugging::RequireUseStrict] -equivalent_modules = Test::Routine +equivalent_modules = MetaCPAN::Moose Mojo::Base Test::Routine + +[TestingAndDebugging::RequireUseWarnings] +equivalent_modules = MetaCPAN::Moose Mojo::Base Test::Routine [ValuesAndExpressions::ProhibitEmptyQuotes] severity = 4 diff --git a/.perltidyrc b/.perltidyrc index 961585943..ab8fed578 100644 --- a/.perltidyrc +++ b/.perltidyrc @@ -1,6 +1,17 @@ --pbp --nst - +--maximum-line-length=78 +--indent-columns=4 +--continuation-indentation=4 +--standard-error-output +--vertical-tightness=2 +--closing-token-indentation=0 +--paren-tightness=1 +--brace-tightness=1 +--square-bracket-tightness=1 +--block-brace-tightness=1 +--nospace-for-semicolon +--nooutdent-long-quotes +--want-break-before="% + - * / x != == >= <= =~ !~ < > | & = **= += *= &= <<= &&= -= /= |= >>= ||= //= .= %= ^= x=" # Break a line after opening/before closing token. --vt=0 --vtc=0 +--vertical-tightness=0 +--vertical-tightness-closing=0 +--weld-nested-containers diff --git a/.tidyallrc b/.tidyallrc deleted file mode 100644 index 614f12c3c..000000000 --- a/.tidyallrc +++ /dev/null @@ -1,6 +0,0 @@ -[PerlTidy] -select = {lib,t}/**/*.{pl,pm,t,psgi} -select = bin/daemon-control.pl -select = app.psgi -ignore = t/var/**/* -argv = --profile=$ROOT/.perltidyrc diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 11db4c03d..000000000 --- a/.travis.yml +++ /dev/null @@ -1,62 +0,0 @@ -language: perl -perl: - - "5.20" - - "5.18" - -matrix: - allow_failures: - - perl: "5.20" - -notifications: - email: - recipients: - - olaf@wundersolutions.com - on_success: always - on_failure: always - irc: "irc.perl.org#metacpan-travis" - - -env: - global: - # We use a non-standard port to avoid trashing production - # but travis will have it running on the standard port. - - METACPAN_ES_TEST_PORT=9200 - # Carton --deployment only works on the same version of perl - # that the snapshot was built from. - - DEPLOYMENT_PERL_VERSION=5.18 - - -before_install: - # We need to run a pre-1.0 instance of ES until we update everything. - - wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-0.90.13.deb - - sudo dpkg -i --force-confdef elasticsearch-0.90.13.deb - - sudo service elasticsearch restart - - - cpanm -n Devel::Cover::Report::Coveralls - - cpanm -n Carton - - sudo apt-get install libgmp-dev - - # Carton refuses to update Safe.pm to the version specified in the cpanfile and the - # version that's core in 5.16 is too old (it fails to work with Devel::Cover). - - cpanm -n Safe@2.35 - -install: - - 'carton install `test "${TRAVIS_PERL_VERSION}" = "${DEPLOYMENT_PERL_VERSION}" && echo " --deployment"`' - -before_script: - # Show status info for ES to verify that it's working, what version, etc. - - "curl http://localhost:${METACPAN_ES_TEST_PORT}/" - - "perl -i -pe 's/(servers :)9900/$1$ENV{METACPAN_ES_TEST_PORT}/' metacpan_server_testing.conf" - -script: - # Devel::Cover isn't in the cpanfile - # but if it's installed into the global dirs this should work. - # NOTE: No '-r' for prove; 't/fakecpan.t' does the recursion for us. - - HARNESS_PERL_SWITCHES=-MDevel::Cover=+ignore,local carton exec prove -lv t - -after_success: - - cover -report coveralls - - -services: - - elasticsearch diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..2948c9f24 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,101 @@ +ARG SLIM_BUILD +ARG MAYBE_BASE_BUILD=${SLIM_BUILD:+server-base-slim} +ARG BASE_BUILD=${MAYBE_BASE_BUILD:-server-base} + +################### Web Server Base +FROM metacpan/metacpan-base:main-20250531-090128 AS server-base +FROM metacpan/metacpan-base:main-20250531-090129-slim AS server-base-slim + +################### CPAN Prereqs +FROM server-base AS build-cpan-prereqs +SHELL [ "/bin/bash", "-euo", "pipefail", "-c" ] + +WORKDIR /app/ + +COPY cpanfile cpanfile.snapshot ./ +RUN \ + --mount=type=cache,target=/root/.perl-cpm,sharing=private \ +<open( + name => 'MetaCPAN::Server', + path => $root_dir, + ); + + if ($dev_mode) { + $ENV{METACPAN_SERVER_DEBUG} = 1; + if ( !$ENV{EMAIL_SENDER_TRANSPORT} ) { + $ENV{EMAIL_SENDER_TRANSPORT} = 'Maildir'; + File::Path::mkpath( $ENV{EMAIL_SENDER_TRANSPORT_dir} + = "$root_dir/var/tmp/mail" ); + } } + + my $log4perl_config + = File::Spec->rel2abs( $config->{log4perl_file} || 'log4perl.conf', + $root_dir ); + Log::Log4perl::init($log4perl_config); + + package MetaCPAN::Server::WarnHandler; ## no critic (Modules::RequireFilenameMatchesPackage) + Log::Log4perl->wrapper_register(__PACKAGE__); + my $logger = Log::Log4perl->get_logger; + $SIG{__WARN__} = sub { $logger->warn(@_) }; +} + +use MetaCPAN::Server (); + +STDERR->autoflush; + +# prevent output buffering when in Docker containers (e.g. in docker-compose) +if ( -e "/.dockerenv" and MetaCPAN::Server->log->isa('Catalyst::Log') ) { + STDOUT->autoflush; +} + +sub _add_headers { + my ( $app, $add_headers ) = @_; + sub { + Plack::Util::response_cb( + $app->(@_), + sub { + my $res = shift; + my ( $status, $headers ) = @$res; + if ( $status >= 200 && $status < 300 ) { + push @$headers, @$add_headers; + } + return $res; + } + ); + }; +} + +my $static + = Plack::App::Directory->new( + { root => path( $root_dir, 'root', 'static' ) } )->to_app; + +my $urlmap = Plack::App::URLMap->new; +$urlmap->map( + '/favicon.ico' => _add_headers( + Plack::App::File->new( + file => path( $root_dir, 'root', 'static', 'favicon.ico' ) + )->to_app, + [ + 'Cache-Control' => 'public, max-age=' . ( 60 * 60 * 24 ), + 'Surrogate-Control' => 'max-age=' . ( 60 * 60 * 24 * 365 ), + 'Surrogate-Key' => 'static', + ], + ) +); +$urlmap->map( '/static' => $static ); +if ( $ENV{PLACK_ENV} && $ENV{PLACK_ENV} eq 'development' ) { + $urlmap->map( '/v1' => MetaCPAN::Server->app ); } +$urlmap->map( '/' => MetaCPAN::Server->app ); -# The class has the Plack initialization and returns the app. -require MetaCPAN::Server; +return $urlmap->to_app; diff --git a/bin/api.pl b/bin/api.pl new file mode 100755 index 000000000..40ffdc72e --- /dev/null +++ b/bin/api.pl @@ -0,0 +1,40 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +=head2 DESCRIPTION + +This is the API web server interface. + + # On vagrant VM + ./bin/run morbo bin/api.pl + +To run the api web server, run the following on one of the servers: + + # Run the daemon on a local port (tunnel to display on your browser) + ./bin/run bin/api.pl daemon + +Start Minion worker on vagrant: + + cd /home/vagrant/metacpan-api + ./bin/run bin/api.pl minion worker + +Get status on jobs and workers. + +On production: + + sh /home/metacpan/bin/metacpan-api-carton-exec bin/api.pl minion job -s + +On vagrant: + + cd /home/vagrant/metacpan-api + ./bin/run bin/api.pl minion job -s + +=cut + +use lib 'lib'; + +# Start command line interface for application +require Mojolicious::Commands; +Mojolicious::Commands->start_app('MetaCPAN::API'); diff --git a/bin/build_test_CPAN_dir.pl b/bin/build_test_CPAN_dir.pl deleted file mode 100644 index a41ae6aab..000000000 --- a/bin/build_test_CPAN_dir.pl +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env perl - -# Script to create a /tmp/CPAN/ directory with a 02packages.details.txt.gz file -# To use as a basic for the ElasticSearch index and CPAN-API testing -# and development on the development virtual machine - -use strict; -use warnings; -use ElasticSearch; -use LWP::Simple qw(mirror is_success is_redirect); -use Path::Class; -use OrePAN2 0.07; -use OrePAN2::Injector; -use OrePAN2::Indexer; -use feature qw( say ); - -my $OUT_DIR = '/tmp/tmp_tar_files/'; -my $CPAN_DIR = '/tmp/CPAN/'; - -my $modules_to_fetch = { - 'Data::Pageset' => '1.06', - 'ElasticSearch' => '0.65', -}; - -my $injector = OrePAN2::Injector->new( directory => $CPAN_DIR, ); - -my $es = ElasticSearch->new( - no_refresh => 1, - servers => 'api.metacpan.org', - - # trace_calls => \*STDOUT, -); - -my %seen; -foreach my $module_name ( keys %{$modules_to_fetch} ) { - my $version = $modules_to_fetch->{$module_name}; - - _download_with_dependencies( $module_name, $version ); -} - -# build the 02packages.details.txt.gz file -OrePAN2::Indexer->new( directory => $CPAN_DIR )->make_index(); - -sub _download_with_dependencies { - my ( $module_name, $version ) = @_; - - my $seen_key = $module_name . $version; - return if $seen{$seen_key}; - - my ( $module, $release ) = _get_meta( $module_name, $version ); - - foreach my $dep ( @{ $release->{dependency} } ) { - - # Find latest version? - # FIXME: What to do here? - - } - - # work out where to mirror to... - my $file = $release->{download_url}; - $file =~ s{^.+/authors/}{}; - $file = file( $OUT_DIR, $file ); - $file->dir->mkpath(); - - my $status = mirror( $release->{download_url}, $file->stringify ); - if ( is_success($status) || is_redirect($status) ) { - $seen{$seen_key} = 1; - $injector->{author} = $release->{author}; - $injector->inject( $file->stringify ); - } else { - warn "Unable to mirror: " . $release->{download_url}; - } -} - -sub _get_meta { - my ( $module_name, $version ) = @_; - - my $module = $es->search( - index => 'v0', - type => 'file', - query => { match_all => {} }, - filter => { - and => [ - { term => { 'file.authorized' => 'true' } }, - { term => { 'file.module.name' => $module_name } }, - { term => { 'file.module.version' => $version } } - ] - }, - ); - - my $release_name = $module->{hits}{hits}[0]{_source}{release}; - - my $release = $es->search( - index => 'v0', - type => 'release', - query => { match_all => {} }, - filter => { term => { 'release.name' => $release_name } }, - ); - return $module->{hits}{hits}[0]{_source}, - $release->{hits}{hits}[0]{_source}; - -} - diff --git a/bin/check_json.pl b/bin/check_json.pl deleted file mode 100755 index 9eee4effa..000000000 --- a/bin/check_json.pl +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env perl -# PODNAME: check_json.pl -use 5.010; - -use Data::Dumper; -use JSON::XS; - -foreach my $file ( @ARGV ) { - say "Processing $file"; - eval { - my $hash = decode_json( - do { local ( @ARGV, $/ ) = $file; <> } - ); - print Dumper( $hash ); - }; - - if ( $@ ) { say "\terror in $file: $@" } -} \ No newline at end of file diff --git a/bin/convert_authors.pl b/bin/convert_authors.pl deleted file mode 100644 index 5f7373a21..000000000 --- a/bin/convert_authors.pl +++ /dev/null @@ -1,90 +0,0 @@ -# PODNAME: foo - -use strict; -use warnings; -use JSON; -use File::Find; - -my @files; -find( - sub { - push( @files, $File::Find::name ); - }, - 'conf/authors' ); - -foreach my $file (@files) { - next unless ( -f $file ); - next if($file =~ /1/); - next unless($file =~ /\.json$/); - my $json; - { - local $/ = undef; - local *FILE; - open FILE, "<$file"; - $json = ; - close FILE - } - warn $file; - my $data = decode_json($json); - my ($author) = keys %$data; - ($data) = values %$data; - my $raw = { donation => [], - profile => [], }; - my %profiles = ( "delicious_username" => 'delicious', - "facebook_public_profile" => 'facebook', - "github_username" => 'github', - "linkedin_public_profile" => "linkedin", - "stackoverflow_public_profile" => 'stackoverflow', - "perlmonks_username" => 'perlmonks', - "twitter_username" => 'twitter', - "slideshare_url" => 'slideshare', - "youtube_channel_url" => 'youtube', - slashdot_username => 'slashdot', - "amazon_author_profile" => 'amazon', - aim => 'aim', - icq => 'icq', - jabber => 'jabber', - msn_messenger => 'msn_messenger', - "oreilly_author_profile" => 'oreilly', - slideshare_username => 'slideshare', - stumbleupon_profile => 'stumbleupon', - xing_public_profile => 'xing', - ACT_id => 'act', - irc_nick => 'irc', - irc_nickname => 'irc' ); - - while ( my ( $k, $v ) = each %profiles ) { - next unless ( my $value = delete $data->{$k} ); - $value =~ s/^.*\///; - push( @{ $raw->{profile} }, - { name => $v, - id => $value - } ); - } - - if ( my $pp = delete $data->{paypal_address} ) { - delete $data->{accepts_donations}; - push( @{ $raw->{donation} }, - { id => $pp, - name => 'paypal' - } ); - } - - if ( $data->{blog_url} ) { - $raw->{blog} = [ - { url => delete $data->{blog_url}, - feed => delete $data->{blog_feed} } ]; - } - delete $data->{perlmongers} if ( ref $data->{perlmongers} ); - if ( $data->{perlmongers} ) { - $raw->{perlmongers} = { name => delete $data->{perlmongers}, - url => delete $data->{perlmongers_url}, }; - } - $raw->{$_} = delete $data->{$_} - for (qw(city country email region website openid)); - unlink $file; - (my $base = $file) =~ s/^(.*)\/.*?$/$1/; - open FILE, '>', "$base/author-1.0.json"; - print FILE JSON->new->pretty->encode( $raw ); - close FILE; -} diff --git a/bin/cpantesters_api_file_for_testing b/bin/cpantesters_api_file_for_testing new file mode 100755 index 000000000..f7eb90d22 --- /dev/null +++ b/bin/cpantesters_api_file_for_testing @@ -0,0 +1,59 @@ +#!/bin/bash + +cd `dirname "$0"` +cd .. + +url=http://api.cpantesters.org/v3/release +in=t/var/tmp/cpantesters-release-api.json +out=t/var/cpantesters-release-api-fake.json + +download_original () { + test -s "$in" || wget -O "$in" "$url" +} + +append_json () { + perl -MJSON::PP -e' + $file = shift; + $all = -e $file ? decode_json( + do { local $/; open $fh, "<", $file; <$fh> } + ) : []; + $add = decode_json( join "", ); + push @$all, $add; + open $fh, ">", $file; + print { $fh } encode_json( $all ) ' $out +} + +collect_dist () { + local dist="$1" version="$2" + jq '.[] | select( .dist == $dist and .version == $version )' \ + --arg dist "$dist" --arg version "$version" $in \ + | append_json +} + +fake_dist () { + echo "{ \"dist\": \"$1\", \"version\": \"$2\", \"pass\": $3, \"fail\": $4, \ + \"na\": $5, \"unknown\": $6 }" | append_json; +} + +populate_file () { + rm -f "$out" + + # Get test cases from real data. + collect_dist 'Devel-GoFaster' '0.000' + collect_dist 'P' '1.0.20' + collect_dist 'IPsonar' '0.29' + collect_dist 'weblint' '++-1.15' + collect_dist 'WWW-Tumblr' '' + + # Add records for our fake dists. + fake_dist 'Some' '1.00-TRIAL' 4 3 2 1 +} + +if [ !-x $( which jq ) ]; then + echo "ERROR: jq(1) required for this script" + exit 1 +fi + +download_original +populate_file + diff --git a/bin/cron/author.sh b/bin/cron/author.sh new file mode 100755 index 000000000..e3f279773 --- /dev/null +++ b/bin/cron/author.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# export ES_SCRIPT_INDEX=author_01 +# /home/metacpan/bin/metacpan-api-carton-exec bin/metacpan author --index author_01 + +/home/metacpan/bin/metacpan-api-carton-exec bin/metacpan author diff --git a/bin/cron/backups.sh b/bin/cron/backups.sh new file mode 100755 index 000000000..16ed9f950 --- /dev/null +++ b/bin/cron/backups.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +/home/metacpan/bin/metacpan-api-carton-exec bin/metacpan backup --index cpan_v1_01 --type favorite +/home/metacpan/bin/metacpan-api-carton-exec bin/metacpan backup --index cpan_v1_01 --type author + +/home/metacpan/bin/metacpan-api-carton-exec bin/metacpan backup --index user diff --git a/bin/get_fields.pl b/bin/get_fields.pl deleted file mode 100644 index 34c77ac58..000000000 --- a/bin/get_fields.pl +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env perl -# PODNAME: get_fields.pl -use Data::Dumper; -use JSON::XS; -use File::Find::Rule; -use File::Basename; -use Path::Class; - -my $current_dir = dirname( __FILE__ ); -my $author_dir = Path::Class::Dir->new( $current_dir, '..', 'conf' ); -my @files = File::Find::Rule->file->name( '*.json' )->in( $author_dir ); - -my %fields; - -foreach my $file ( @files ) { - warn "Processing $file"; - my $hash; - - eval { - $hash = decode_json( do { local( @ARGV, $/ ) = $file; <> } ); - } or print "\terror in $file: $@"; - - while ( my ($author, $info) = each %{$hash} ) { - my @local_fields = keys %{$info}; - @fields{@local_fields} = @local_fields; - } -} - -print $_ for sort keys %fields; diff --git a/bin/install-precious b/bin/install-precious new file mode 100755 index 000000000..0d712a470 --- /dev/null +++ b/bin/install-precious @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# This is for installing precious and other 3rd party libs needed for linting +# in CI + +set -euo pipefail + +if [ -z "${1:-}" ]; then + echo "usage: ./bin/install-precious /path/to/bin/dir" + exit 1 +fi + +TARGET=$1 +export TARGET + +TARGET=$1 +export TARGET + +curl --silent --location \ + https://raw.githubusercontent.com/houseabsolute/ubi/master/bootstrap/bootstrap-ubi.sh | + sh + +ubi --project houseabsolute/omegasort --in "$TARGET" +ubi --project houseabsolute/precious --in "$TARGET" diff --git a/bin/metacpan b/bin/metacpan index 555f9721e..e57c34fdb 100755 --- a/bin/metacpan +++ b/bin/metacpan @@ -6,7 +6,7 @@ bin/metacpan release /path/to/cpan/authors/id/ bin/metacpan release /path/to/cpan/authors/id/{A,B} - bin/metacpan release /path/to/cpan/authors/id/D/DO/DOY/Try-Tiny-0.09.tar.gz + bin/metacpan release /path/to/cpan/authors/id/D/DO/DOY/Try-Tiny-0.09.tar.gz bin/metacpan latest bin/metacpan server --cpan /path/to/cpan/ @@ -14,8 +14,10 @@ use strict; use warnings; -use FindBin; +use FindBin (); use lib "$FindBin::RealBin/../lib"; -use MetaCPAN::Script::Runner; +use MetaCPAN::Script::Runner (); MetaCPAN::Script::Runner->run; + +exit $MetaCPAN::Script::Runner::EXIT_CODE; diff --git a/bin/mirror_cpan_for_developers.pl b/bin/mirror_cpan_for_developers.pl old mode 100644 new mode 100755 index 7647e9cdc..7a8d4de10 --- a/bin/mirror_cpan_for_developers.pl +++ b/bin/mirror_cpan_for_developers.pl @@ -1,11 +1,15 @@ +#!/usr/bin/env perl +use strict; +use warnings; + # This script is only needed if you are developing metacpan, -# on the live servers we use File::Rsync::Mirror::Recent -# https://github.com/CPAN-API/Metacpan-Puppet/tree/master/modules/rrrclient +# on the live servers we use File::Rsync::Mirror::Recent +# https://github.com/metacpan/metacpan-puppet/tree/master/modules/rrrclient use CPAN::Mini; - + CPAN::Mini->update_mirror( - remote => 'http://www.cpan.org/', - local => "/home/metacpan/CPAN", - log_level => 'warn', + remote => 'http://www.cpan.org/', + local => "/home/metacpan/CPAN", + log_level => 'warn', ); diff --git a/bin/munin/monitor_minion_queue.pl b/bin/munin/monitor_minion_queue.pl new file mode 100755 index 000000000..91a83e6ff --- /dev/null +++ b/bin/munin/monitor_minion_queue.pl @@ -0,0 +1,58 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +# Munin runs this as metacpan user, but with root's env +# it's only for production so path is hard coded + +my $config_mode = 0; +$config_mode = 1 if $ARGV[0] && $ARGV[0] eq 'config'; + +if ($config_mode) { + + # Dump this (though we supported dynamic below) so it's faster + print <<'EOF'; +graph_title Minion Queue stats +graph_vlabel count +graph_category metacpan_api +graph_info What's happening in the Minion queue +workers_inactive.label Inactive workers +workers_active.label Active workers +jobs_inactive.label Inactive jobs +jobs_active.label Active jobs +jobs_failed.label Failed jobs +jobs_finished.label Finished jobs +EOF + + exit; +} + +# Get the stats +my $stats_report + = `/home/metacpan/bin/metacpan-api-carton-exec bin/queue.pl minion job -s`; + +my @lines = split( "\n", $stats_report ); + +for my $line (@lines) { + my ( $label, $num ) = split ':', $line; + + $num =~ s/\D//g; + + my $key = lc($label); # Was 'Inactive jobs' + + # Swap type and status around so idle_jobs becomes jobs_idle + $key =~ s/(\w+)\s+(\w+)/$2_$1/g; + + if ($config_mode) { + + # config + print "${key}.label $label\n"; + + } + else { + # results + print "${key}.value $num\n" if $num; + } + +} diff --git a/bin/prove b/bin/prove deleted file mode 100755 index 6d5fb7fe0..000000000 --- a/bin/prove +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -`dirname "$0"`/run prove -lv "$@" diff --git a/bin/queue.pl b/bin/queue.pl new file mode 120000 index 000000000..5474dbc6e --- /dev/null +++ b/bin/queue.pl @@ -0,0 +1 @@ +api.pl \ No newline at end of file diff --git a/bin/unlisted_prereqs.pl b/bin/unlisted_prereqs.pl deleted file mode 100644 index 5750c9fbe..000000000 --- a/bin/unlisted_prereqs.pl +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env perl -# PODNAME: check_prereqs.pl - -# TODO: this stuff should be in other modules somewhere - -use strict; -use warnings; -use Perl::PrereqScanner 1.014; -use CPAN::Meta::Requirements; -use File::Find::Rule::Perl; -use List::Util qw(sum); -use version 0.77; - -# TODO: use CPAN::Meta::Prereqs - -my @found = File::Find::Rule->not( - File::Find::Rule->name(qw( - .git - t/var/tmp - var - ))->prune->discard, -)->perl_file->in('.'); - -my $local = {}; -my $files = {}; - -foreach ( @found ){ - # FIXME: unix slashes - my $phase = - # beneath t/ or xt/ - m{^(\./)?x?t/} ? 'build' : - 'runtime'; - - push @{ $files->{ $phase } }, $_; - - if( m{^(?:\./)?(?:t/)?lib/(.+?)\.pm$} ){ - (my $pm = $1) =~ s!/!::!g; - $local->{ $pm } = $_; - } -} - -my $scanner = Perl::PrereqScanner->new( - # TODO: extra_scanners => [qw( PlackMiddleware Catalyst )], -); - -my $reqs = {}; - -foreach my $phase ( keys %$files ){ - my $pr = CPAN::Meta::Requirements->new; - foreach my $file ( @{ $files->{ $phase } } ){ - $pr->add_requirements( $scanner->scan_file( $file ) ); - } - - # ignore packages we provide locally - $pr->clear_requirement($_) - for grep { exists $local->{$_} } $pr->required_modules; - - $reqs->{ $phase } = $pr->as_string_hash; -} - -# don't duplicate runtime deps into build deps -foreach my $dep ( keys %{ $reqs->{runtime} } ){ - # TODO: check version - delete $reqs->{build}{ $dep }; -} - -sub check_prereqs { - my ($scanned, $mm) = @_; - foreach my $dep ( keys %$scanned ){ - if( exists($mm->{ $dep }) ){ - delete $scanned->{ $dep } - if version->parse($scanned->{ $dep }) <= version->parse($mm->{ $dep }); - } - } -} - -my ($PREREQ_PM, $BUILD_REQUIRES, $MIN_PERL_VERSION); - -my $mm_prereqs = qx{$^X Makefile.PL PREREQ_PRINT=1}; -eval $mm_prereqs; - -check_prereqs($reqs->{runtime}, $PREREQ_PM); -check_prereqs($reqs->{build}, $BUILD_REQUIRES); -delete $reqs->{runtime}{perl} - if version->parse($reqs->{runtime}{perl}) <= version->parse($MIN_PERL_VERSION); - -use Data::Dumper; -$Data::Dumper::Sortkeys = 1; -print Data::Dumper->Dump([$reqs], ['requires']); - -exit sum map { scalar keys %{ $reqs->{$_} } } keys %$reqs; diff --git a/bin/wait-for-open b/bin/wait-for-open new file mode 100755 index 000000000..a9729260e --- /dev/null +++ b/bin/wait-for-open @@ -0,0 +1,16 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +my $server = shift; + +my $timeout = 30; +while ( $timeout-- ) { + if ( !system "curl -s '$server' 2>/dev/null 1>&2" ) { + exit 0; + } + sleep 1; +} + +print STDERR "Timed out starting elasticsearch!\n"; +exit 1; diff --git a/bin/write_config_json b/bin/write_config_json deleted file mode 100644 index b84de54d4..000000000 --- a/bin/write_config_json +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/perl - -# PODNAME: write_config_json -# -# takes the root directory of an extracted distribution and outputs a JSON file -# suitable for CPAN::Faker to STDOUT -use strictures 1; -use JSON; -use YAML; - -use IO::All; -use Email::Address; -use File::Find; -use File::Spec; -use Path::Class; - -my ($dir) = @ARGV; - -my $meta_data; -if(-e "$dir/META.yml") { - $meta_data = YAML::LoadFile("$dir/META.yml"); -} elsif(-e "$dir/META.json") { - $meta_data = JSON::decode_json(io("$dir/META.json")->all); -} else { - die "no meta file"; -} - -my $authors = $meta_data->{author}; -my @authors = map { my ($addr) = Email::Address->parse($_); $addr->name } @$authors; - -my $files; -File::Find::find( - { - no_chdir => 1, - wanted => sub { - return unless -f; - push @$files, { - file => File::Spec->abs2rel($File::Find::name, dir($dir)), - content => io($_)->all, - } - }, - }, - $dir -); - -my $output = { - name => $meta_data->{name}, - version => $meta_data->{version}, - abstract => $meta_data->{abstract}, - X_Module_Faker => { - cpan_author => [ @authors ], - append => [ - $files - ] - }, -}; - -print JSON->new->pretty->encode($output); - -__DATA__ -{ - "name": "MetaFile-Both", - "abstract": "A dist with META.yml and META.json", - "version": 1.1, - "X_Module_Faker": { - "cpan_author": "LOCAL", - "append": [ { - "file": "lib/MetaFile/Both.pm", - "content": "package MetaFile::Both;\n\n=head1 NAME\n\nMetaFile::Both - abstract" - }, - { - "file": "META.json", - "content": "{\"meta-spec\":{\"version\":2,\"url\":\"http://search.cpan.org/perldoc?CPAN::Meta::Spec\"},\"generated_by\":\"hand\",\"version\":1.1,\"name\":\"MetaFile-Both\",\"dynamic_config\":0,\"author\":\"LOCAL\",\"license\":\"unknown\",\"abstract\":\"A dist with META.yml and META.json\",\"release_status\":\"stable\",\"x_meta_file\":\"json\"}" - }, - { - "file": "t/foo.t", - "content": "use Test::More;" - } ] - } -} - ---- -name: SignedModule -version: 1.1 -abstract: A signed dist -author: - - LOCAL -generated_by: Module::Faker version -license: unknown -meta-spec: - url: http://module-build.sourceforge.net/META-spec-v1.3.html - version: 1.3 diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 000000000..be10c0793 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,16 @@ +--- +comment: + layout: 'diff, files' + behavior: default + require_changes: true # if true: only post the comment if coverage changes + require_base: false # [true :: must have a base report to post] + require_head: true # [true :: must have a head report to post] + hide_project_coverage: false # [true :: only show coverage on the git diff] +coverage: + status: + patch: + default: + threshold: 1% + project: + default: + threshold: 1% diff --git a/cpanfile b/cpanfile index 3be90df81..dd1d4513f 100644 --- a/cpanfile +++ b/cpanfile @@ -1,177 +1,166 @@ +use strict; +use warnings; + requires 'perl', '5.010'; -requires 'Archive::Any', 0.0941; -requires 'Archive::Any::Plugin'; -requires 'Archive::Tar'; -requires 'BackPAN::Index'; -requires 'CHI'; -requires 'CPAN::DistnameInfo'; -requires 'CPAN::Meta', '2.141170'; # Avoid issues with List::Util dep under carton install. -requires 'CPAN::Meta::Requirements'; -requires 'Captcha::reCAPTCHA', '0.94'; -requires 'Catalyst', '5.90011'; -requires 'Catalyst::Action::RenderView'; -requires 'Catalyst::Authentication::User'; -requires 'Catalyst::Controller'; -requires 'Catalyst::Controller::REST', '0.94'; -requires 'Catalyst::Model'; +requires 'Archive::Any', '0.0946'; +requires 'Archive::Tar', '2.40'; +requires 'Authen::SASL', '2.16'; # for Email::Sender::Transport::SMTP +requires 'Catalyst', '5.90128'; +requires 'Catalyst::Action::RenderView', '0.16'; +requires 'Catalyst::Controller::REST', '1.21'; requires 'Catalyst::Plugin::Authentication'; -requires 'Catalyst::Plugin::ConfigLoader'; -requires 'Catalyst::Plugin::Session'; +requires 'Catalyst::Plugin::Session', '0.43'; requires 'Catalyst::Plugin::Session::State::Cookie'; requires 'Catalyst::Plugin::Session::Store'; requires 'Catalyst::Plugin::Static::Simple'; -requires 'Catalyst::Plugin::Unicode::Encoding'; -requires 'Catalyst::Utils'; -requires 'Catalyst::View'; -requires 'Catalyst::View::JSON'; -requires 'CatalystX::Component::Traits'; -requires 'CatalystX::InjectComponent'; -requires 'CatalystX::RoleApplicator'; -requires 'Config::JFDI'; +requires 'Catalyst::View::JSON', '0.37'; +requires 'CatalystX::Fastly::Role::Response', '0.06'; +requires 'CHI', '0.61'; +requires 'Config::General', '2.63'; +requires 'Config::ZOMG', '1.000000'; +requires 'Const::Fast'; +requires 'CPAN::DistnameInfo', '0.12'; +requires 'Cpanel::JSON::XS', '4.32'; +requires 'CPAN::Meta', '2.150005'; # Avoid issues with List::Util dep under carton install. +requires 'CPAN::Meta::Requirements', '2.140'; +requires 'CPAN::Meta::YAML', '0.018'; +requires 'CPAN::Repository::Perms'; requires 'Cwd'; -requires 'Data::Printer'; -requires 'DBD::SQLite', '>=1.44'; -requires 'DBI', '1.616'; -requires 'Data::DPath'; -requires 'Data::Dump'; requires 'Data::Dumper'; -requires 'DateTime'; +requires 'Data::Visitor::Callback'; +requires 'DateTime', '1.54'; requires 'DateTime::Format::ISO8601'; -requires 'Devel::ArgNames'; +requires 'DBD::SQLite', '1.66'; +requires 'DBI', '1.643'; requires 'Digest::MD5'; -requires 'Digest::SHA1'; -requires 'EV'; -requires 'ElasticSearchX::Model', '0.1.5'; -requires 'Email::Address'; +requires 'Digest::SHA'; +requires 'ElasticSearchX::Model', '2.0.1'; requires 'Email::Sender::Simple'; requires 'Email::Simple'; -requires 'Email::Valid'; -requires 'Encode'; +requires 'Email::Valid', '1.203'; +requires 'Encode', '3.17'; requires 'Encoding::FixLatin'; -requires 'Exporter'; -requires 'Facebook::Graph'; +requires 'Encoding::FixLatin::XS'; +requires 'EV'; +requires 'Exporter', '5.74'; requires 'File::Basename'; +requires 'File::Copy'; requires 'File::Find'; requires 'File::Find::Rule'; requires 'File::Find::Rule::Perl'; requires 'File::Spec'; requires 'File::Spec::Functions'; -requires 'File::Temp'; +requires 'File::pushd'; requires 'File::stat'; -requires 'Find::Lib'; +requires 'File::Temp'; requires 'FindBin'; -requires 'Graph::Centrality::Pagerank'; +requires 'Getopt::Long::Descriptive', '0.103'; requires 'Gravatar::URL'; -requires 'HTML::TokeParser::Simple'; -requires 'HTTP::Request::Common'; requires 'Hash::Merge::Simple'; -requires 'IO::All'; -requires 'IO::Interactive'; -requires 'IO::String'; -requires 'IO::Uncompress::Bunzip2'; +requires 'HTML::Entities'; +requires 'HTTP::Request::Common', '6.36'; +requires 'IO::Prompt::Tiny'; +requires 'IO::Uncompress::Bunzip2', '2.106'; requires 'IO::Zlib'; -requires 'IPC::Run3'; -requires 'JSON::XS', '3.01'; -requires 'JSON', '2.90'; -requires 'LWP::Protocol::https'; -requires 'LWP::UserAgent'; -requires 'LWP::UserAgent::Paranoid'; -requires 'List::AllUtils'; -requires 'List::MoreUtils'; -requires 'List::Util'; +requires 'IPC::Run3', '0.048'; +requires 'List::Util', '1.62'; +requires 'Log::Any::Adapter'; +requires 'Log::Any::Adapter::Log4perl'; requires 'Log::Contextual'; +requires 'Log::Dispatch'; +requires 'Log::Dispatch::Syslog'; requires 'Log::Log4perl'; requires 'Log::Log4perl::Appender::ScreenColoredLevels'; -requires 'Module::Metadata', '1.000022'; +requires 'Log::Log4perl::Catalyst'; +requires 'Log::Log4perl::Layout::JSON'; +requires 'LWP::Protocol::https'; +requires 'LWP::UserAgent', '6.66'; +requires 'MetaCPAN::Moose'; +requires 'MetaCPAN::Pod::HTML' => '0.004000'; +requires 'MetaCPAN::Role', '1.00'; +requires 'MIME::Base64', '3.15'; +requires 'Minion', '9.03'; +requires 'Minion::Backend::SQLite'; +requires 'Module::Load'; +requires 'Module::Metadata', '1.000038'; requires 'Module::Pluggable'; requires 'Module::Runtime'; -requires 'Moose', ' == 2.0802'; # Pin to older version to avoid deprecation warning on enum that we can't escape b/c we're pinned to an old version of MX-Types-ES. -requires 'Moose::Role'; -requires 'Moose::Util'; -requires 'MooseX::Aliases'; +requires 'Mojolicious::Plugin::MountPSGI', '0.14'; +requires 'Mojolicious::Plugin::OpenAPI'; +requires 'Mojolicious::Plugin::Web::Auth', '0.17'; +requires 'Mojo::Pg', '4.08'; +requires 'Moose', '2.2201'; requires 'MooseX::Attribute::Deflator', '2.1.5'; -requires 'MooseX::ChainedAccessors'; -requires 'MooseX::ClassAttribute'; -requires 'MooseX::Getopt'; +requires 'MooseX::Fastly::Role', '0.02'; +requires 'MooseX::Getopt', '0.71'; requires 'MooseX::Getopt::Dashes'; requires 'MooseX::Getopt::OptionTypeMap'; requires 'MooseX::StrictConstructor'; requires 'MooseX::Types'; -requires 'MooseX::Types::Common::String'; -requires 'MooseX::Types::ElasticSearch', ' == 0.0.2'; # Newer versions use the other ES module which we can't upgrade to yet b/c of ESX-Model. +requires 'MooseX::Types::ElasticSearch', '0.0.4'; requires 'MooseX::Types::Moose'; -requires 'MooseX::Types::Path::Class::MoreCoercions'; -requires 'MooseX::Types::Structured'; -requires 'MooseX::Types::URI'; -requires 'Mozilla::CA'; -requires 'Net::DNS::Paranoid'; -requires 'Net::OpenID::Consumer'; -requires 'Net::Twitter'; -requires 'Parse::CPAN::Packages::Fast', '0.04'; -requires 'Parse::CSV'; -requires 'Parse::PMFile', '0.29'; -requires 'Path::Class'; -requires 'Path::Class::File'; +requires 'Mozilla::CA', '20211001'; +requires 'namespace::autoclean'; +requires 'Net::Fastly', '1.12'; +requires 'Net::GitHub::V4'; +requires 'Parse::CPAN::Packages::Fast', '0.09'; +requires 'Parse::PMFile', '0.43'; +requires 'Path::Iterator::Rule', '>=1.011'; +requires 'PAUSE::Permissions', '0.17'; requires 'PerlIO::gzip'; -requires 'Pithub'; +requires 'Plack', '1.0048'; requires 'Plack::App::Directory'; -requires 'Plack::Handler::Twiggy'; -requires 'Plack::MIME'; -requires 'Plack::Middleware::Header'; requires 'Plack::Middleware::ReverseProxy'; -requires 'Plack::Middleware::Rewrite'; -requires 'Plack::Middleware::ServerStatus::Lite'; requires 'Plack::Middleware::Session'; requires 'Plack::Session::Store'; -requires 'Plack::Test'; -requires 'Plack::Util::Accessor'; -requires 'Pod::Coverage::Moose', '0.02'; -requires 'Pod::Markdown', '3.002'; -requires 'Pod::POM'; -requires 'Pod::Simple', '3.29'; -requires 'Pod::Simple::XHTML', '3.24'; -requires 'Pod::Text'; -requires 'Regexp::Common'; -requires 'Regexp::Common::time'; +requires 'Pod::Markdown', '3.300'; +requires 'Pod::Text', '4.14'; +requires 'Ref::Util'; requires 'Safe', '2.35'; # bug fixes (used by Parse::PMFile) -requires 'Starman'; -requires 'Time::Local'; +requires 'Scalar::Util', '1.62'; # Moose +requires 'Search::Elasticsearch' => '8.12'; +requires 'Search::Elasticsearch::Client::2_0' => '6.81'; requires 'Throwable::Error'; -requires 'Try::Tiny'; -requires 'URI'; -requires 'URI::Escape'; -requires 'WWW::Mechanize'; -requires 'WWW::Mechanize::Cached'; -requires 'XML::Simple'; -requires 'YAML'; -requires 'YAML::Syck'; -requires 'base'; -requires 'feature'; -requires 'namespace::autoclean'; -requires 'strict'; -requires 'strictures', 1; -requires 'utf8'; -requires 'version', '0.9901'; -requires 'warnings'; +requires 'Term::Size::Any'; # for Catalyst +requires 'Text::CSV_XS'; +requires 'Try::Tiny', '0.30'; +requires 'Type::Tiny', '2.000001'; +requires 'Types::Path::Tiny'; +requires 'Types::URI'; +requires 'Twitter::API', '1.0006'; +requires 'URI', '5.10'; +requires 'version', '0.9929'; +requires 'XML::XPath'; +requires 'YAML::XS', '0.83'; # Mojolicious::Plugin::OpenAPI YAML loading -test_requires 'App::Prove'; -test_requires 'CPAN::Faker', '0.010'; -test_requires 'Module::Faker', '0.015'; -test_requires 'Module::Faker::Dist', '0.010'; -test_requires 'Config::General'; -test_requires 'ElasticSearch::TestServer'; -test_requires 'File::Copy'; -test_requires 'HTTP::Cookies'; -test_requires 'Test::Aggregate::Nested', '0.371'; -test_requires 'Test::Code::TidyAll'; -test_requires 'Test::More', '0.99'; -test_requires 'Test::Most'; -test_requires 'Test::OpenID::Server'; -test_requires 'Test::Perl::Critic'; -test_requires 'Test::RequiresInternet'; -test_requires 'Test::Routine', '0.012'; -test_requires 'Test::Routine::Util', '0'; +# test requirements +on test => sub { + requires 'CPAN::Faker', '0.011'; + requires 'Devel::Confess'; + requires 'HTTP::Cookies', '6.10'; + requires 'MetaCPAN::Client', '2.029000'; + requires 'Module::Faker', '== 0.017'; + requires 'Module::Faker::Dist', '== 0.017'; + requires 'OrePAN2', '0.48'; + requires 'Test::Deep'; + requires 'Test::Fatal'; + requires 'Test::Harness', '3.44'; # Contains App::Prove + requires 'Test::More', '1.302190'; + requires 'Test::RequiresInternet'; + requires 'Test::Routine', '0.012'; + requires 'Test::Vars', '0.015'; +}; -author_requires 'Code::TidyAll'; -author_requires 'Plack::Middleware::Rewrite'; +# author requirements +on develop => sub { + requires 'App::perlimports'; + requires 'Perl::Critic', '0.140'; + requires 'Perl::Tidy' => '== 20240511'; + requires 'PPI', '1.274'; # Perl::Critic + requires 'PPIx::QuoteLike', '0.022'; # Perl::Critic + requires 'PPIx::Regexp', '0.085'; # Perl::Critic + requires 'String::Format', '1.18'; # Perl::Critic + requires 'Devel::Cover'; + requires 'Devel::Cover::Report::Codecovbash'; +}; diff --git a/cpanfile.forced b/cpanfile.forced new file mode 100644 index 000000000..47023795c --- /dev/null +++ b/cpanfile.forced @@ -0,0 +1,12 @@ +# transitive deps +# Not used directly, but they need to be explicitly listed to ensure they are +# in our cpanfile.snapshot at appropriate versions. Either for older perl +# versions, or unpredictable dynamic deps. These will be installed using a +# different process to ensure they are present in the snapshot, even if they +# would be satisfied by core. +requires 'CPAN::Meta', '2.141520'; +requires 'Devel::PPPort', '3.62'; # for older perls +requires 'ExtUtils::MakeMaker', '7.76'; +requires 'version', '0.9929'; # for older perls +requires 'Module::Signature', '0.90'; +requires 'Pod::Parser', '1.67'; # for newer perls diff --git a/cpanfile.snapshot b/cpanfile.snapshot index 3c0568d85..c3272cc2c 100644 --- a/cpanfile.snapshot +++ b/cpanfile.snapshot @@ -1,31 +1,12 @@ # carton snapshot format: version 1.0 DISTRIBUTIONS - Algorithm-C3-0.10 - pathname: H/HA/HAARG/Algorithm-C3-0.10.tar.gz + Algorithm-Diff-1.201 + pathname: R/RJ/RJBS/Algorithm-Diff-1.201.tar.gz provides: - Algorithm::C3 0.10 + Algorithm::Diff 1.201 + Algorithm::Diff::_impl 1.201 requirements: - Carp 0.01 ExtUtils::MakeMaker 0 - Test::More 0.47 - perl 5.006 - Algorithm-Diff-1.1902 - pathname: T/TY/TYEMQ/Algorithm-Diff-1.1902.tar.gz - provides: - Algorithm::Diff 1.1902 - Algorithm::Diff::_impl 1.1902 - Algorithm::DiffOld 1.1 - requirements: - ExtUtils::MakeMaker 0 - Any-Moose-0.21 - pathname: S/SA/SARTAK/Any-Moose-0.21.tar.gz - provides: - Any::Moose 0.21 - AnyMooseTest undef - inc::MakeMaker undef - requirements: - ExtUtils::MakeMaker 6.30 - Moose 0 Any-URI-Escape-0.01 pathname: P/PH/PHRED/Any-URI-Escape-0.01.tar.gz provides: @@ -33,126 +14,88 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 URI::Escape 0 - AnyEvent-7.07 - pathname: M/ML/MLEHMANN/AnyEvent-7.07.tar.gz - provides: - AE undef - AE::Log::COLLECT undef - AE::Log::FILTER undef - AE::Log::LOG undef - AnyEvent 7.07 - AnyEvent::Base 7.07 - AnyEvent::CondVar 7.07 - AnyEvent::CondVar::Base 7.07 - AnyEvent::DNS undef - AnyEvent::Debug undef - AnyEvent::Debug::Backtrace undef - AnyEvent::Debug::Wrap undef - AnyEvent::Debug::Wrapped undef - AnyEvent::Debug::shell undef - AnyEvent::Handle undef - AnyEvent::IO undef - AnyEvent::IO::IOAIO undef - AnyEvent::IO::Perl undef - AnyEvent::Impl::Cocoa undef - AnyEvent::Impl::EV undef - AnyEvent::Impl::Event undef - AnyEvent::Impl::EventLib undef - AnyEvent::Impl::FLTK undef - AnyEvent::Impl::Glib undef - AnyEvent::Impl::IOAsync undef - AnyEvent::Impl::Irssi undef - AnyEvent::Impl::POE undef - AnyEvent::Impl::Perl undef - AnyEvent::Impl::Qt undef - AnyEvent::Impl::Qt::Io undef - AnyEvent::Impl::Qt::Timer undef - AnyEvent::Impl::Tk undef - AnyEvent::Log undef - AnyEvent::Log::COLLECT undef - AnyEvent::Log::Ctx undef - AnyEvent::Log::FILTER undef - AnyEvent::Log::LOG undef - AnyEvent::Loop undef - AnyEvent::Socket undef - AnyEvent::Strict undef - AnyEvent::TLS undef - AnyEvent::Util undef - requirements: - ExtUtils::MakeMaker 0 - AnyEvent-HTTP-2.15 - pathname: M/ML/MLEHMANN/AnyEvent-HTTP-2.15.tar.gz - provides: - AnyEvent::HTTP 2.15 - requirements: - AnyEvent 5.33 - ExtUtils::MakeMaker 0 - common::sense 3.3 - AnyEvent-HTTP-LWP-UserAgent-0.10 - pathname: Y/YA/YAKEX/AnyEvent-HTTP-LWP-UserAgent-0.10.tar.gz - provides: - AnyEvent::HTTP::LWP::UserAgent 0.10 - requirements: - AnyEvent 5 - AnyEvent::HTTP 2.1 - ExtUtils::MakeMaker 6.30 - File::Temp 0 - HTTP::Headers::Util 0 - HTTP::Request::Common 0 - HTTP::Response 0 - LWP::UserAgent 5.815 - Test::More 0 - parent 0 - strict 0 - warnings 0 - Apache-LogFormat-Compiler-0.30 - pathname: K/KA/KAZEBURO/Apache-LogFormat-Compiler-0.30.tar.gz + Apache-LogFormat-Compiler-0.36 + pathname: K/KA/KAZEBURO/Apache-LogFormat-Compiler-0.36.tar.gz provides: - Apache::LogFormat::Compiler 0.30 + Apache::LogFormat::Compiler 0.36 requirements: - CPAN::Meta 0 - CPAN::Meta::Prereqs 0 - ExtUtils::CBuilder 0 - Module::Build 0.38 + Module::Build::Tiny 0.035 POSIX 0 POSIX::strftime::Compiler 0.30 Time::Local 0 - perl 5.008004 - App-Cache-0.37 - pathname: L/LB/LBROCARD/App-Cache-0.37.tar.gz - provides: - App::Cache 0.37 - requirements: - Class::Accessor::Chained::Fast 0 + perl 5.008001 + App-perlimports-0.000056 + pathname: O/OA/OALDERS/App-perlimports-0.000056.tar.gz + provides: + App::perlimports 0.000056 + App::perlimports::Annotations 0.000056 + App::perlimports::CLI 0.000056 + App::perlimports::Config 0.000056 + App::perlimports::Document 0.000056 + App::perlimports::ExportInspector 0.000056 + App::perlimports::Include 0.000056 + App::perlimports::Role::Logger 0.000056 + App::perlimports::Sandbox 0.000056 + requirements: + Capture::Tiny 0 + Class::Inspector 1.36 + Cpanel::JSON::XS 0 + Data::Dumper 0 + Data::UUID 0 ExtUtils::MakeMaker 0 - File::Find::Rule 0 - File::HomeDir 0 - File::stat 0 - HTTP::Cookies 0 - LWP::UserAgent 0 - Path::Class 0 - Storable 0 - Test::More 0 - Archive-Any-0.0941 - pathname: O/OA/OALDERS/Archive-Any-0.0941.tar.gz + File::Basename 0 + File::XDG 1.01 + Getopt::Long::Descriptive 0 + List::Util 0 + Log::Dispatch 2.70 + Memoize 0 + Module::Runtime 0 + Moo 0 + Moo::Role 0 + MooX::StrictConstructor 0 + PPI 1.276 + PPI::Document 0 + PPIx::Utils::Classification 0 + Path::Iterator::Rule 0 + Path::Tiny 0 + Perl::Tidy 20220613 + Pod::Usage 0 + Ref::Util 0 + Scalar::Util 0 + Sereal::Decoder 0 + Sereal::Encoder 0 + Sub::HandlesVia 0 + Symbol::Get 0.10 + TOML::Tiny 0.16 + Text::Diff 0 + Text::SimpleTable::AutoWidth 0 + Try::Tiny 0 + Types::Standard 0 + feature 0 + perl v5.18.0 + strict 0 + utf8 0 + warnings 0 + Archive-Any-0.0946 + pathname: O/OA/OALDERS/Archive-Any-0.0946.tar.gz provides: - Archive::Any 0.0941 - Archive::Any::Plugin 0.0941 - Archive::Any::Plugin::Tar 0.0941 - Archive::Any::Plugin::Zip 0.0941 - Archive::Any::Tar 0.0941 - Archive::Any::Zip 0.0941 + Archive::Any 0.0946 + Archive::Any::Plugin 0.0946 + Archive::Any::Plugin::Tar 0.0946 + Archive::Any::Plugin::Zip 0.0946 + Archive::Any::Tar 0.0946 + Archive::Any::Zip 0.0946 requirements: Archive::Tar 0 Archive::Zip 0 Cwd 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 File::MMagic 0 File::Spec::Functions 0 MIME::Types 0 - Module::Build 0.3601 Module::Find 0 base 0 + perl 5.006 strict 0 warnings 0 Archive-Any-Create-0.03 @@ -168,10 +111,10 @@ DISTRIBUTIONS ExtUtils::MakeMaker 6.30 IO::Zlib 0 UNIVERSAL::require 0 - Archive-Extract-0.72 - pathname: B/BI/BINGOS/Archive-Extract-0.72.tar.gz + Archive-Extract-0.88 + pathname: B/BI/BINGOS/Archive-Extract-0.88.tar.gz provides: - Archive::Extract 0.72 + Archive::Extract 0.88 requirements: ExtUtils::MakeMaker 0 File::Basename 0 @@ -179,27 +122,45 @@ DISTRIBUTIONS File::Spec 0.82 IPC::Cmd 0.64 Locale::Maketext::Simple 0 - Module::Load::Conditional 0.04 + Module::Load::Conditional 0.66 Params::Check 0.07 Test::More 0 if 0 - Archive-Zip-1.37 - pathname: P/PH/PHRED/Archive-Zip-1.37.tar.gz - provides: - Archive::Zip 1.37 - Archive::Zip::Archive 1.37 - Archive::Zip::BufferedFileHandle 1.37 - Archive::Zip::DirectoryMember 1.37 - Archive::Zip::FileMember 1.37 - Archive::Zip::Member 1.37 - Archive::Zip::MemberRead 1.37 - Archive::Zip::MockFileHandle 1.37 - Archive::Zip::NewFileMember 1.37 - Archive::Zip::StringMember 1.37 - Archive::Zip::Tree 1.37 - Archive::Zip::ZipFileMember 1.37 + Archive-Tar-3.04 + pathname: B/BI/BINGOS/Archive-Tar-3.04.tar.gz + provides: + Archive::Tar 3.04 + Archive::Tar::Constant 3.04 + Archive::Tar::File 3.04 + requirements: + Compress::Zlib 2.015 + ExtUtils::MakeMaker 0 + File::Spec 0.82 + IO::Compress::Base 2.015 + IO::Compress::Bzip2 2.015 + IO::Compress::Gzip 2.015 + IO::Zlib 1.01 + Test::Harness 2.26 + Test::More 0 + perl 5.00503 + Archive-Zip-1.68 + pathname: P/PH/PHRED/Archive-Zip-1.68.tar.gz + provides: + Archive::Zip 1.68 + Archive::Zip::Archive 1.68 + Archive::Zip::BufferedFileHandle 1.68 + Archive::Zip::DirectoryMember 1.68 + Archive::Zip::FileMember 1.68 + Archive::Zip::Member 1.68 + Archive::Zip::MemberRead 1.68 + Archive::Zip::MockFileHandle 1.68 + Archive::Zip::NewFileMember 1.68 + Archive::Zip::StringMember 1.68 + Archive::Zip::Tree 1.68 + Archive::Zip::ZipFileMember 1.68 requirements: Compress::Raw::Zlib 2.017 + Encode 0 ExtUtils::MakeMaker 0 File::Basename 0 File::Copy 0 @@ -210,91 +171,75 @@ DISTRIBUTIONS IO::File 0 IO::Handle 0 IO::Seekable 0 - Test::More 0.88 Time::Local 0 perl 5.006 - Array-Iterator-0.11 - pathname: S/SH/SHARYANTO/Array-Iterator-0.11.tar.gz - provides: - Array::Iterator 0.11 - Array::Iterator::BiDirectional 0.11 - Array::Iterator::Circular 0.11 - Array::Iterator::Reusable 0.11 - requirements: - ExtUtils::MakeMaker 6.30 - B-Hooks-EndOfScope-0.13 - pathname: E/ET/ETHER/B-Hooks-EndOfScope-0.13.tar.gz + Authen-SASL-2.1800 + pathname: E/EH/EHUELS/Authen-SASL-2.1800.tar.gz + provides: + Authen::SASL 2.1800 + Authen::SASL::CRAM_MD5 2.1800 + Authen::SASL::EXTERNAL 2.1800 + Authen::SASL::Perl 2.1800 + Authen::SASL::Perl::ANONYMOUS 2.1800 + Authen::SASL::Perl::CRAM_MD5 2.1800 + Authen::SASL::Perl::DIGEST_MD5 2.1800 + Authen::SASL::Perl::EXTERNAL 2.1800 + Authen::SASL::Perl::GSSAPI 2.1800 + Authen::SASL::Perl::LOGIN 2.1800 + Authen::SASL::Perl::OAUTHBEARER 2.1800 + Authen::SASL::Perl::PLAIN 2.1800 + Authen::SASL::Perl::XOAUTH2 2.1800 + requirements: + Digest::HMAC_MD5 0 + Digest::MD5 0 + ExtUtils::MakeMaker 0 + perl 5.014000 + B-Hooks-EndOfScope-0.28 + pathname: E/ET/ETHER/B-Hooks-EndOfScope-0.28.tar.gz provides: - B::Hooks::EndOfScope 0.13 - B::Hooks::EndOfScope::PP 0.13 - B::Hooks::EndOfScope::XS 0.13 + B::Hooks::EndOfScope 0.28 + B::Hooks::EndOfScope::PP 0.28 + B::Hooks::EndOfScope::XS 0.28 requirements: - ExtUtils::CBuilder 0.26 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 + Hash::Util::FieldHash 0 Module::Implementation 0.05 - Module::Runtime 0.012 + Scalar::Util 0 Sub::Exporter::Progressive 0.001006 + Text::ParseWords 0 + Tie::Hash 0 Variable::Magic 0.48 - B-Hooks-OP-Check-0.19 - pathname: Z/ZE/ZEFRAM/B-Hooks-OP-Check-0.19.tar.gz + perl 5.006001 + strict 0 + warnings 0 + B-Hooks-OP-Check-0.22 + pathname: E/ET/ETHER/B-Hooks-OP-Check-0.22.tar.gz provides: - B::Hooks::OP::Check 0.19 - B::Hooks::OP::Check::Install::Files undef + B::Hooks::OP::Check 0.22 requirements: + DynaLoader 0 ExtUtils::Depends 0.302 - ExtUtils::MakeMaker 6.42 - Test::More 0 + ExtUtils::MakeMaker 0 parent 0 perl 5.008001 - B-Keywords-1.13 - pathname: R/RU/RURBAN/B-Keywords-1.13.tar.gz + strict 0 + warnings 0 + B-Keywords-1.27 + pathname: R/RU/RURBAN/B-Keywords-1.27.tar.gz provides: - B::Keywords 1.13 + B::Keywords 1.27 requirements: B 0 ExtUtils::MakeMaker 0 - BackPAN-Index-0.42 - pathname: M/MS/MSCHWERN/BackPAN-Index-0.42.tar.gz - provides: - BackPAN::Index 0.42 - BackPAN::Index::Database undef - BackPAN::Index::Dist undef - BackPAN::Index::File undef - BackPAN::Index::IndexFile undef - BackPAN::Index::Release undef - BackPAN::Index::Role::AsHash undef - BackPAN::Index::Role::HasCache undef - BackPAN::Index::Role::Log undef - BackPAN::Index::Schema undef - BackPAN::Index::Types undef - Parse::BACKPAN::Packages 0.40 - requirements: - App::Cache 0.37 - Archive::Extract 0 - CLASS 1.00 - CPAN::DistnameInfo 0.09 - DBD::SQLite 1.25 - DBIx::Class 0.08109 - LWP::Simple 0 - Module::Build 0.340201 - Mouse 0.64 - Path::Class 0.17 - Test::Compile 0.11 - Test::More 0.90 - URI 1.54 - autodie 0 - parent 0 - perl 5.008001 - CGI-Simple-1.113 - pathname: A/AN/ANDYA/CGI-Simple-1.113.tar.gz + CGI-Simple-1.281 + pathname: M/MA/MANWAR/CGI-Simple-1.281.tar.gz provides: - CGI::Simple 1.113 - CGI::Simple::Cookie 1.113 - CGI::Simple::Standard 1.113 - CGI::Simple::Util 1.113 + CGI::Simple 1.281 + CGI::Simple::Cookie 1.281 + CGI::Simple::Standard 1.281 + CGI::Simple::Util 1.281 requirements: - IO::Scalar 0 - Test::More 0 + ExtUtils::MakeMaker 0 CGI-Struct-1.21 pathname: F/FU/FULLERMD/CGI-Struct-1.21.tar.gz provides: @@ -304,33 +249,34 @@ DISTRIBUTIONS Storable 0 Test::Deep 0 Test::More 0 - CHI-0.58 - pathname: H/HA/HAARG/CHI-0.58.tar.gz - provides: - CHI 0.58 - CHI::CacheObject 0.58 - CHI::Driver 0.58 - CHI::Driver::Base::CacheContainer 0.58 - CHI::Driver::CacheCache 0.58 - CHI::Driver::FastMmap 0.58 - CHI::Driver::File 0.58 - CHI::Driver::Memory 0.58 - CHI::Driver::Metacache 0.58 - CHI::Driver::Null 0.58 - CHI::Driver::RawMemory 0.58 - CHI::Driver::Role::HasSubcaches 0.58 - CHI::Driver::Role::IsSizeAware 0.58 - CHI::Driver::Role::IsSubcache 0.58 - CHI::Stats 0.58 + CHI-0.61 + pathname: A/AS/ASB/CHI-0.61.tar.gz + provides: + CHI 0.61 + CHI::CacheObject 0.61 + CHI::Driver 0.61 + CHI::Driver::Base::CacheContainer 0.61 + CHI::Driver::CacheCache 0.61 + CHI::Driver::FastMmap 0.61 + CHI::Driver::File 0.61 + CHI::Driver::Memory 0.61 + CHI::Driver::Metacache 0.61 + CHI::Driver::Null 0.61 + CHI::Driver::RawMemory 0.61 + CHI::Driver::Role::HasSubcaches 0.61 + CHI::Driver::Role::IsSizeAware 0.61 + CHI::Driver::Role::IsSubcache 0.61 + CHI::Stats 0.61 requirements: Carp::Assert 0.20 + Class::Load 0 Data::UUID 0 Digest::JHash 0 Digest::MD5 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 File::Spec 0.80 Hash::MoreUtils 0 - JSON 0 + JSON::MaybeXS 1.003003 List::MoreUtils 0.13 Log::Any 0.08 Moo 1.003 @@ -344,17 +290,10 @@ DISTRIBUTIONS Time::Duration::Parse 0.03 Time::HiRes 1.30 Try::Tiny 0.05 - CLASS-1.00 - pathname: M/MS/MSCHWERN/CLASS-1.00.tar.gz - provides: - CLASS 1.00 - requirements: - ExtUtils::MakeMaker 0 - Test::More 0.07 - CPAN-Checksums-2.09 - pathname: A/AN/ANDK/CPAN-Checksums-2.09.tar.gz + CPAN-Checksums-2.14 + pathname: A/AN/ANDK/CPAN-Checksums-2.14.tar.gz provides: - CPAN::Checksums 2.09 + CPAN::Checksums 2.14 requirements: Compress::Bzip2 0 Compress::Zlib 0 @@ -374,16 +313,16 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 Test::More 0 - CPAN-Faker-0.010 - pathname: R/RJ/RJBS/CPAN-Faker-0.010.tar.gz + CPAN-Faker-0.012 + pathname: R/RJ/RJBS/CPAN-Faker-0.012.tar.gz provides: - CPAN::Faker 0.010 + CPAN::Faker 0.012 requirements: CPAN::Checksums 0 Compress::Zlib 0 Cwd 0 Data::Section 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 6.78 File::Find 0 File::Next 0 File::Path 0 @@ -394,45 +333,52 @@ DISTRIBUTIONS Moose 0 Sort::Versions 0 Text::Template 0 + perl 5.014000 strict 0 warnings 0 - CPAN-Meta-2.141520 - pathname: D/DA/DAGOLDEN/CPAN-Meta-2.141520.tar.gz - provides: - CPAN::Meta 2.141520 - CPAN::Meta::Converter 2.141520 - CPAN::Meta::Feature 2.141520 - CPAN::Meta::History 2.141520 - CPAN::Meta::Prereqs 2.141520 - CPAN::Meta::Spec 2.141520 - CPAN::Meta::Validator 2.141520 + CPAN-Meta-2.150010 + pathname: D/DA/DAGOLDEN/CPAN-Meta-2.150010.tar.gz + provides: + CPAN::Meta 2.150010 + CPAN::Meta::Converter 2.150010 + CPAN::Meta::Feature 2.150010 + CPAN::Meta::History 2.150010 + CPAN::Meta::Merge 2.150010 + CPAN::Meta::Prereqs 2.150010 + CPAN::Meta::Spec 2.150010 + CPAN::Meta::Validator 2.150010 + Parse::CPAN::Meta 2.150010 requirements: CPAN::Meta::Requirements 2.121 - CPAN::Meta::YAML 0.008 + CPAN::Meta::YAML 0.011 Carp 0 + Encode 0 + Exporter 0 ExtUtils::MakeMaker 6.17 - JSON::PP 2.27200 - Parse::CPAN::Meta 1.4414 + File::Spec 0.80 + JSON::PP 2.27300 Scalar::Util 0 + perl 5.008001 strict 0 version 0.88 warnings 0 - CPAN-Meta-Check-0.008 - pathname: L/LE/LEONT/CPAN-Meta-Check-0.008.tar.gz + CPAN-Meta-Requirements-2.143 + pathname: R/RJ/RJBS/CPAN-Meta-Requirements-2.143.tar.gz provides: - CPAN::Meta::Check 0.008 + CPAN::Meta::Requirements 2.143 + CPAN::Meta::Requirements::Range 2.143 requirements: - CPAN::Meta::Prereqs 2.132830 - CPAN::Meta::Requirements 2.121 - Exporter 5.57 - ExtUtils::MakeMaker 6.30 - Module::Metadata 0 + B 0 + Carp 0 + ExtUtils::MakeMaker 6.17 + perl 5.010000 strict 0 + version 0.88 warnings 0 - CPAN-Meta-YAML-0.012 - pathname: D/DA/DAGOLDEN/CPAN-Meta-YAML-0.012.tar.gz + CPAN-Meta-YAML-0.020 + pathname: E/ET/ETHER/CPAN-Meta-YAML-0.020.tar.gz provides: - CPAN::Meta::YAML 0.012 + CPAN::Meta::YAML 0.020 requirements: B 0 Carp 0 @@ -440,50 +386,54 @@ DISTRIBUTIONS ExtUtils::MakeMaker 6.17 Fcntl 0 Scalar::Util 0 + perl 5.008001 strict 0 warnings 0 - Cache-Cache-1.06 - pathname: J/JS/JSWARTZ/Cache-Cache-1.06.tar.gz - provides: - Cache::BaseCache undef - Cache::BaseCacheTester undef - Cache::Cache 1.06 - Cache::CacheMetaData undef - Cache::CacheSizer undef - Cache::CacheTester undef - Cache::CacheUtils undef - Cache::FileBackend undef - Cache::FileCache undef - Cache::MemoryBackend undef - Cache::MemoryCache undef - Cache::NullCache undef - Cache::Object undef - Cache::SharedMemoryBackend undef - Cache::SharedMemoryCache undef - Cache::SizeAwareCache undef - Cache::SizeAwareCacheTester undef - Cache::SizeAwareFileCache undef - Cache::SizeAwareMemoryCache undef - Cache::SizeAwareSharedMemoryCache undef - requirements: - Digest::SHA1 2.02 - Error 0.15 + CPAN-Repository-0.010 + pathname: O/OA/OALDERS/CPAN-Repository-0.010.tar.gz + provides: + CPAN::Repository 0.010 + CPAN::Repository::Mailrc 0.010 + CPAN::Repository::Packages 0.010 + CPAN::Repository::Perms 0.010 + CPAN::Repository::Role::File 0.010 + requirements: + DateTime 0.72 + DateTime::Format::Epoch 0.13 + DateTime::Format::RFC3339 0 + Dist::Data 0.002 ExtUtils::MakeMaker 0 - File::Spec 0.82 - Storable 1.014 - Captcha-reCAPTCHA-0.97 - pathname: P/PH/PHRED/Captcha-reCAPTCHA-0.97.tar.gz + File::Path 2.08 + File::Spec::Functions 3.33 + IO::File 1.14 + IO::Zlib 1.10 + Moo 0.009013 + Cache-LRU-0.04 + pathname: K/KA/KAZUHO/Cache-LRU-0.04.tar.gz + provides: + Cache::LRU 0.04 + requirements: + ExtUtils::MakeMaker 6.42 + Test::More 0.88 + Test::Requires 0 + perl 5.008001 + Call-Context-0.05 + pathname: F/FE/FELIPE/Call-Context-0.05.tar.gz provides: - Captcha::reCAPTCHA 0.97 + Call::Context 0.05 + Call::Context::X 0.05 requirements: ExtUtils::MakeMaker 0 - HTML::Tiny 0.904 - LWP::UserAgent 0 - Test::More 0 - Capture-Tiny-0.24 - pathname: D/DA/DAGOLDEN/Capture-Tiny-0.24.tar.gz + Canary-Stability-2013 + pathname: M/ML/MLEHMANN/Canary-Stability-2013.tar.gz provides: - Capture::Tiny 0.24 + Canary::Stability 2013 + requirements: + ExtUtils::MakeMaker 0 + Capture-Tiny-0.50 + pathname: D/DA/DAGOLDEN/Capture-Tiny-0.50.tar.gz + provides: + Capture::Tiny 0.50 requirements: Carp 0 Exporter 0 @@ -492,113 +442,81 @@ DISTRIBUTIONS File::Temp 0 IO::Handle 0 Scalar::Util 0 + perl 5.006 strict 0 warnings 0 - Carp-Assert-0.20 - pathname: M/MS/MSCHWERN/Carp-Assert-0.20.tar.gz - provides: - Carp::Assert 0.20 - requirements: - Carp 0 - ExtUtils::MakeMaker 0 - Test::More 0.4 - Carp-Assert-More-1.14 - pathname: P/PE/PETDANCE/Carp-Assert-More-1.14.tar.gz + Carp-Assert-0.22 + pathname: Y/YV/YVES/Carp-Assert-0.22.tar.gz provides: - Carp::Assert::More 1.14 + Carp::Assert 0.22 requirements: Carp 0 - Carp::Assert 0 + Exporter 0 ExtUtils::MakeMaker 0 - Scalar::Util 0 - Test::Exception 0 - Test::More 0.18 - Carp-Clan-6.04 - pathname: S/ST/STBEY/Carp-Clan-6.04.tar.gz + perl 5.006 + strict 0 + vars 0 + warnings 0 + Carp-Clan-6.08 + pathname: E/ET/ETHER/Carp-Clan-6.08.tar.gz provides: - Carp::Clan 6.04 + Carp::Clan 6.08 requirements: ExtUtils::MakeMaker 0 - Test::Exception 0 - Carp-Clan-Share-0.013 - pathname: R/RK/RKRIMEN/Carp-Clan-Share-0.013.tar.gz - provides: - Carp::Clan::Share 0.013 - requirements: - Carp::Clan 0 - ExtUtils::MakeMaker 6.42 - Test::More 0 - Catalyst-Action-REST-1.15 - pathname: F/FR/FREW/Catalyst-Action-REST-1.15.tar.gz - provides: - Catalyst::Action::Deserialize 1.15 - Catalyst::Action::Deserialize::Callback 1.15 - Catalyst::Action::Deserialize::JSON 1.15 - Catalyst::Action::Deserialize::JSON::XS 1.15 - Catalyst::Action::Deserialize::View 1.15 - Catalyst::Action::Deserialize::XML::Simple 1.15 - Catalyst::Action::Deserialize::YAML 1.15 - Catalyst::Action::DeserializeMultiPart 1.15 - Catalyst::Action::REST 1.15 - Catalyst::Action::REST::ForBrowsers 1.15 - Catalyst::Action::Serialize 1.15 - Catalyst::Action::Serialize::Callback 1.15 - Catalyst::Action::Serialize::JSON 1.15 - Catalyst::Action::Serialize::JSON::XS 1.15 - Catalyst::Action::Serialize::JSONP 1.15 - Catalyst::Action::Serialize::View 1.15 - Catalyst::Action::Serialize::XML::Simple 1.15 - Catalyst::Action::Serialize::YAML 1.15 - Catalyst::Action::Serialize::YAML::HTML 1.15 - Catalyst::Action::SerializeBase 1.15 - Catalyst::Action::Serializer::Broken undef - Catalyst::Controller::REST 1.15 - Catalyst::Request::REST 1.15 - Catalyst::Request::REST::ForBrowsers 1.15 - Catalyst::TraitFor::Request::REST 1.15 - Catalyst::TraitFor::Request::REST::ForBrowsers 1.15 - Test::Action::Class undef - Test::Action::Class::Sub undef - Test::Catalyst::Action::REST undef - Test::Catalyst::Action::REST::Controller::Actions undef - Test::Catalyst::Action::REST::Controller::ActionsForBrowsers undef - Test::Catalyst::Action::REST::Controller::Deserialize undef - Test::Catalyst::Action::REST::Controller::DeserializeMultiPart undef - Test::Catalyst::Action::REST::Controller::Override undef - Test::Catalyst::Action::REST::Controller::REST undef - Test::Catalyst::Action::REST::Controller::Root undef - Test::Catalyst::Action::REST::Controller::Serialize undef - Test::Catalyst::Log undef - Test::Rest undef - Test::Serialize undef - Test::Serialize::Controller::JSON undef - Test::Serialize::Controller::REST undef - Test::Serialize::View::Awful undef - Test::Serialize::View::Simple undef + overload 0 + perl 5.006 + strict 0 + Catalyst-Action-REST-1.21 + pathname: J/JJ/JJNAPIORK/Catalyst-Action-REST-1.21.tar.gz + provides: + Catalyst::Action::Deserialize 1.21 + Catalyst::Action::Deserialize::Callback 1.21 + Catalyst::Action::Deserialize::JSON 1.21 + Catalyst::Action::Deserialize::JSON::XS 1.21 + Catalyst::Action::Deserialize::View 1.21 + Catalyst::Action::Deserialize::XML::Simple 1.21 + Catalyst::Action::Deserialize::YAML 1.21 + Catalyst::Action::DeserializeMultiPart 1.21 + Catalyst::Action::REST 1.21 + Catalyst::Action::REST::ForBrowsers 1.21 + Catalyst::Action::Serialize 1.21 + Catalyst::Action::Serialize::Callback 1.21 + Catalyst::Action::Serialize::JSON 1.21 + Catalyst::Action::Serialize::JSON::XS 1.21 + Catalyst::Action::Serialize::JSONP 1.21 + Catalyst::Action::Serialize::View 1.21 + Catalyst::Action::Serialize::XML::Simple 1.21 + Catalyst::Action::Serialize::YAML 1.21 + Catalyst::Action::Serialize::YAML::HTML 1.21 + Catalyst::Action::SerializeBase 1.21 + Catalyst::Controller::REST 1.21 + Catalyst::Request::REST 1.21 + Catalyst::Request::REST::ForBrowsers 1.21 + Catalyst::TraitFor::Request::REST 1.21 + Catalyst::TraitFor::Request::REST::ForBrowsers 1.21 requirements: Catalyst::Runtime 5.80030 Class::Inspector 1.13 - ExtUtils::MakeMaker 6.30 - LWP::UserAgent 2.033 + ExtUtils::MakeMaker 0 + JSON::MaybeXS 0 MRO::Compat 0.10 Module::Pluggable::Object 0 Moose 1.03 Params::Validate 0.76 URI::Find 0 namespace::autoclean 0 - Catalyst-Action-RenderView-0.16 - pathname: B/BO/BOBTFISH/Catalyst-Action-RenderView-0.16.tar.gz + Catalyst-Action-RenderView-0.17 + pathname: H/HA/HAARG/Catalyst-Action-RenderView-0.17.tar.gz provides: - Catalyst::Action::RenderView 0.16 + Catalyst::Action::RenderView 0.17 requirements: Catalyst::Runtime 5.80030 Data::Visitor 0.24 - ExtUtils::MakeMaker 6.42 - HTTP::Request::AsCGI 0 + ExtUtils::MakeMaker 0 MRO::Compat 0 - Test::More 0.88 - Catalyst-Plugin-Authentication-0.10023 - pathname: B/BO/BOBTFISH/Catalyst-Plugin-Authentication-0.10023.tar.gz + perl 5.008005 + Catalyst-Plugin-Authentication-0.10024 + pathname: J/JJ/JJNAPIORK/Catalyst-Plugin-Authentication-0.10024.tar.gz provides: Catalyst::Authentication::Credential::NoPassword undef Catalyst::Authentication::Credential::Password undef @@ -610,98 +528,85 @@ DISTRIBUTIONS Catalyst::Authentication::Store::Null undef Catalyst::Authentication::User undef Catalyst::Authentication::User::Hash undef - Catalyst::Plugin::Authentication 0.10023 + Catalyst::Plugin::Authentication 0.10024 Catalyst::Plugin::Authentication::Credential::Password undef Catalyst::Plugin::Authentication::Store::Minimal undef Catalyst::Plugin::Authentication::User undef Catalyst::Plugin::Authentication::User::Hash undef requirements: - Catalyst::Plugin::Session 0.10 Catalyst::Runtime 0 - Class::Inspector 0 - Class::MOP 0 - ExtUtils::MakeMaker 6.59 + ExtUtils::MakeMaker 0 MRO::Compat 0 Moose 0 MooseX::Emulate::Class::Accessor::Fast 0 String::RewritePrefix 0 - Test::Exception 0 - Test::More 0.88 Try::Tiny 0 namespace::autoclean 0 - perl 5.008001 - Catalyst-Plugin-ConfigLoader-0.34 - pathname: B/BO/BOBTFISH/Catalyst-Plugin-ConfigLoader-0.34.tar.gz + Catalyst-Plugin-ConfigLoader-0.35 + pathname: H/HA/HAARG/Catalyst-Plugin-ConfigLoader-0.35.tar.gz provides: - Catalyst::Plugin::ConfigLoader 0.34 + Catalyst::Plugin::ConfigLoader 0.35 requirements: Catalyst::Runtime 5.7008 Config::Any 0.20 Data::Visitor 0.24 - ExtUtils::MakeMaker 6.59 + ExtUtils::MakeMaker 0 MRO::Compat 0.09 - Path::Class 0 - Test::More 0 - perl 5.008 - Catalyst-Plugin-Session-0.39 - pathname: J/JJ/JJNAPIORK/Catalyst-Plugin-Session-0.39.tar.gz + Catalyst-Plugin-Session-0.43 + pathname: H/HA/HAARG/Catalyst-Plugin-Session-0.43.tar.gz provides: - Catalyst::Plugin::Session 0.39 - Catalyst::Plugin::Session::State undef - Catalyst::Plugin::Session::Store undef - Catalyst::Plugin::Session::Store::Dummy undef - Catalyst::Plugin::Session::Test::Store 123 + Catalyst::Plugin::Session 0.43 + Catalyst::Plugin::Session::State 0.43 + Catalyst::Plugin::Session::Store 0.43 + Catalyst::Plugin::Session::Store::Dummy 0.43 + Catalyst::Plugin::Session::Test::Store 0.43 requirements: Catalyst::Runtime 5.71001 Digest 0 - ExtUtils::MakeMaker 6.59 + ExtUtils::MakeMaker 0 File::Spec 0 File::Temp 0 + HTML::Entities 0 List::Util 0 MRO::Compat 0 Moose 0.76 MooseX::Emulate::Class::Accessor::Fast 0.00801 Object::Signature 0 - Test::Deep 0 - Test::Exception 0 Test::More 0.88 - Test::WWW::Mechanize::PSGI 0 - Tie::RefHash 1.34 namespace::clean 0.10 perl 5.008 - Catalyst-Plugin-Session-State-Cookie-0.17 - pathname: M/MS/MSTROUT/Catalyst-Plugin-Session-State-Cookie-0.17.tar.gz + Catalyst-Plugin-Session-State-Cookie-0.18 + pathname: H/HA/HAARG/Catalyst-Plugin-Session-State-Cookie-0.18.tar.gz provides: - Catalyst::Plugin::Session::State::Cookie 0.17 + Catalyst::Plugin::Session::State::Cookie 0.18 requirements: Catalyst 5.80005 Catalyst::Plugin::Session 0.27 - ExtUtils::MakeMaker 6.42 + ExtUtils::MakeMaker 0 MRO::Compat 0 Moose 0 - Test::More 0 namespace::autoclean 0 - Catalyst-Plugin-Static-Simple-0.31 - pathname: A/AB/ABRAXXA/Catalyst-Plugin-Static-Simple-0.31.tar.gz + Catalyst-Plugin-Static-Simple-0.37 + pathname: I/IL/ILMARI/Catalyst-Plugin-Static-Simple-0.37.tar.gz provides: - Catalyst::Plugin::Static::Simple 0.31 + Catalyst::Plugin::Static::Simple 0.37 requirements: Catalyst::Runtime 5.80008 - ExtUtils::MakeMaker 6.36 + ExtUtils::MakeMaker 0 MIME::Types 2.03 Moose 0 - MooseX::Types 0 - Test::More 0 namespace::autoclean 0 - Catalyst-Runtime-5.90064 - pathname: J/JJ/JJNAPIORK/Catalyst-Runtime-5.90064.tar.gz + Catalyst-Runtime-5.90132 + pathname: J/JJ/JJNAPIORK/Catalyst-Runtime-5.90132.tar.gz provides: - Catalyst 5.90064 + Catalyst 5.90132 Catalyst::Action undef Catalyst::ActionChain undef Catalyst::ActionContainer undef Catalyst::ActionRole::ConsumesContent undef Catalyst::ActionRole::HTTPMethods undef + Catalyst::ActionRole::QueryMatching undef + Catalyst::ActionRole::Scheme undef Catalyst::Base undef Catalyst::ClassData undef Catalyst::Component undef @@ -723,12 +628,15 @@ DISTRIBUTIONS Catalyst::Exception::Go undef Catalyst::Exception::Interface undef Catalyst::Log undef + Catalyst::Middleware::Stash undef Catalyst::Model undef - Catalyst::Plugin::Unicode::Encoding 2.1 + Catalyst::Plugin::Unicode::Encoding 5.90132 Catalyst::Request undef + Catalyst::Request::PartData undef Catalyst::Request::Upload undef Catalyst::Response undef - Catalyst::Runtime 5.90064 + Catalyst::Response::Writer undef + Catalyst::Runtime 5.90132 Catalyst::Script::CGI undef Catalyst::Script::Create undef Catalyst::Script::FastCGI undef @@ -737,43 +645,38 @@ DISTRIBUTIONS Catalyst::ScriptRole undef Catalyst::ScriptRunner undef Catalyst::Stats undef - Catalyst::Test 3.4 + Catalyst::Test undef Catalyst::Utils undef Catalyst::View undef requirements: CGI::Simple::Cookie 1.109 CGI::Struct 0 - Carp 0 + Carp 1.25 Class::C3::Adopt::NEXT 0.07 - Class::Data::Inheritable 0 Class::Load 0.12 Data::Dump 0 Data::OptList 0 Devel::InnerPackage 0 Encode 2.49 - ExtUtils::MakeMaker 6.59 + ExtUtils::MakeMaker 0 HTML::Entities 0 HTML::HeadParser 0 - HTTP::Body 1.06 + HTTP::Body 1.22 HTTP::Headers 1.64 HTTP::Request 5.814 - HTTP::Request::AsCGI 1.0 - HTTP::Request::Common 0 HTTP::Response 5.813 - HTTP::Status 0 Hash::MultiValue 0 - IO::Scalar 0 JSON::MaybeXS 1.000000 LWP 5.837 - List::MoreUtils 0 + List::Util 1.45 MRO::Compat 0 Module::Pluggable 4.7 - Moose 1.03 + Moose 2.1400 MooseX::Emulate::Class::Accessor::Fast 0.00903 MooseX::Getopt 0.48 MooseX::MethodAttributes::Role::AttrContainer::Inheritable 0.24 - MooseX::Role::WithOverloading 0.09 Path::Class 0.09 + PerlIO::utf8_strict 0 Plack 0.9991 Plack::Middleware::Conditional 0 Plack::Middleware::ContentLength 0 @@ -783,238 +686,155 @@ DISTRIBUTIONS Plack::Middleware::IIS6ScriptNameFix 0 Plack::Middleware::IIS7KeepAliveFix 0 Plack::Middleware::LighttpdScriptNameFix 0 - Plack::Middleware::MethodOverride 0 + Plack::Middleware::MethodOverride 0.12 Plack::Middleware::RemoveRedundantBody 0.03 Plack::Middleware::ReverseProxy 0.04 Plack::Request::Upload 0 Plack::Test::ExternalServer 0 Safe::Isa 0 Scalar::Util 0 + Socket 1.96 Stream::Buffered 0 String::RewritePrefix 0.004 Sub::Exporter 0 Task::Weaken 0 - Test::Fatal 0 - Test::More 0.88 Text::Balanced 0 Text::SimpleTable 0.03 Time::HiRes 0 Tree::Simple 1.15 - Tree::Simple::Visitor::FindByPath 0 + Tree::Simple::Visitor::FindByUID 0 Try::Tiny 0.17 - URI 1.36 - namespace::autoclean 0.09 + URI 1.65 + URI::ws 0.03 namespace::clean 0.23 perl 5.008003 - Catalyst-View-JSON-0.33 - pathname: M/MI/MIYAGAWA/Catalyst-View-JSON-0.33.tar.gz + Catalyst-View-JSON-0.37 + pathname: H/HA/HAARG/Catalyst-View-JSON-0.37.tar.gz provides: Catalyst::Helper::View::JSON undef - Catalyst::View::JSON 0.33 + Catalyst::View::JSON 0.37 requirements: - Catalyst 5.6 - ExtUtils::MakeMaker 6.42 - JSON::Any 1.15 + Catalyst 5.60 + ExtUtils::MakeMaker 0 + JSON::MaybeXS 1.003000 MRO::Compat 0 - Test::More 0 - YAML 0 - perl 5.008001 - CatalystX-Component-Traits-0.19 - pathname: R/RK/RKITOVER/CatalystX-Component-Traits-0.19.tar.gz - provides: - CatalystX::Component::Traits 0.19 - requirements: - Carp 0 - Catalyst 0 - Class::Load 0 - ExtUtils::MakeMaker 6.30 - List::MoreUtils 0 - Moose::Role 0 - MooseX::Traits::Pluggable 0 - Scalar::Util 0 - namespace::autoclean 0 - CatalystX-InjectComponent-0.025 - pathname: R/RO/ROKR/CatalystX-InjectComponent-0.025.tar.gz - provides: - CatalystX::InjectComponent 0.025 - t::Test::Apple undef - requirements: - Catalyst::Runtime 5.8 - Class::Inspector 0 - Devel::InnerPackage 0 - ExtUtils::MakeMaker 6.30 - Test::Most 0 - parent 0 - CatalystX-RoleApplicator-0.005 - pathname: H/HD/HDP/CatalystX-RoleApplicator-0.005.tar.gz + CatalystX-Fastly-Role-Response-0.07 + pathname: H/HA/HAARG/CatalystX-Fastly-Role-Response-0.07.tar.gz provides: - CatalystX::RoleApplicator 0.005 + CatalystX::Fastly::Role::Response 0.07 requirements: - Catalyst::Runtime 5.7 - Class::MOP 0.80 ExtUtils::MakeMaker 0 - Moose 0.73 - MooseX::RelatedClassRoles 0.003 - Class-Accessor-0.34 - pathname: K/KA/KASEI/Class-Accessor-0.34.tar.gz + Moose::Role 2.2200 + perl 5.008005 + Class-Accessor-0.51 + pathname: K/KA/KASEI/Class-Accessor-0.51.tar.gz provides: - Class::Accessor 0.34 - Class::Accessor::Fast 0.34 - Class::Accessor::Faster 0.34 + Class::Accessor 0.51 + Class::Accessor::Fast 0.51 + Class::Accessor::Faster 0.51 requirements: ExtUtils::MakeMaker 0 base 1.01 - Class-Accessor-Chained-0.01 - pathname: R/RC/RCLAMP/Class-Accessor-Chained-0.01.tar.gz - provides: - Class::Accessor::Chained 0.01 - Class::Accessor::Chained::Fast undef - requirements: - Class::Accessor 0 - Test::More 0 - Class-Accessor-Grouped-0.10012 - pathname: R/RI/RIBASUSHI/Class-Accessor-Grouped-0.10012.tar.gz - provides: - Class::Accessor::Grouped 0.10012 - requirements: - Carp 0 - Class::XSAccessor 1.19 - ExtUtils::CBuilder 0.27 - ExtUtils::MakeMaker 6.59 - Module::Runtime 0.012 - Scalar::Util 0 - Sub::Name 0.05 - Test::Exception 0.31 - Test::More 0.88 - perl 5.006 - Class-Accessor-Lite-0.06 - pathname: K/KA/KAZUHO/Class-Accessor-Lite-0.06.tar.gz - provides: - Class::Accessor::Lite 0.06 - requirements: - ExtUtils::MakeMaker 6.42 - Class-C3-0.27 - pathname: H/HA/HAARG/Class-C3-0.27.tar.gz + Class-C3-Adopt-NEXT-0.14 + pathname: E/ET/ETHER/Class-C3-Adopt-NEXT-0.14.tar.gz provides: - Class::C3 0.27 + Class::C3::Adopt::NEXT 0.14 requirements: - Algorithm::C3 0.07 - ExtUtils::CBuilder 0.27 - ExtUtils::MakeMaker 0 - Scalar::Util 0 - perl 5.006 - Class-C3-Adopt-NEXT-0.13 - pathname: F/FL/FLORA/Class-C3-Adopt-NEXT-0.13.tar.gz - provides: - C3NT undef - C3NT::Bar undef - C3NT::Baz undef - C3NT::Child undef - C3NT::Foo undef - C3NT::Quux undef - C3NT_nowarn undef - Class::C3::Adopt::NEXT 0.13 - requirements: - ExtUtils::MakeMaker 6.31 - FindBin 0 - List::MoreUtils 0 + List::Util 1.33 MRO::Compat 0 + Module::Build::Tiny 0.039 NEXT 0 - Test::Exception 0.27 - Test::More 0 - vars 0 + perl 5.006 + strict 0 + warnings 0 warnings::register 0 - Class-C3-Componentised-1.001000 - pathname: F/FR/FREW/Class-C3-Componentised-1.001000.tar.gz - provides: - Class::C3::Componentised 1.001000 - Class::C3::Componentised::ApplyHooks undef - requirements: - Carp 0 - Class::C3 0.20 - Class::Inspector 0 - ExtUtils::MakeMaker 6.42 - MRO::Compat 0 - Test::Exception 0 - perl 5.006002 - Class-Data-Inheritable-0.08 - pathname: T/TM/TMTM/Class-Data-Inheritable-0.08.tar.gz + Class-Data-Inheritable-0.10 + pathname: R/RS/RSHERER/Class-Data-Inheritable-0.10.tar.gz provides: - Class::Data::Inheritable 0.08 + Class::Data::Inheritable 0.10 requirements: ExtUtils::MakeMaker 0 - Class-Factory-Util-1.7 - pathname: D/DR/DROLSKY/Class-Factory-Util-1.7.tar.gz - provides: - Class::Factory::Util 1.7 - requirements: - Class-Inspector-1.28 - pathname: A/AD/ADAMK/Class-Inspector-1.28.tar.gz + Class-Inspector-1.36 + pathname: P/PL/PLICEASE/Class-Inspector-1.36.tar.gz provides: - Class::Inspector 1.28 - Class::Inspector::Functions 1.28 + Class::Inspector 1.36 + Class::Inspector::Functions 1.36 requirements: - ExtUtils::MakeMaker 6.59 + ExtUtils::MakeMaker 0 File::Spec 0.80 - Test::More 0.47 - perl 5.006 - Class-Load-0.21 - pathname: E/ET/ETHER/Class-Load-0.21.tar.gz + base 0 + perl 5.008 + Class-Load-0.25 + pathname: E/ET/ETHER/Class-Load-0.25.tar.gz provides: - Class::Load 0.21 - Class::Load::PP 0.21 + Class::Load 0.25 + Class::Load::PP 0.25 requirements: Carp 0 - Data::OptList 0 + Data::OptList 0.110 Exporter 0 - ExtUtils::MakeMaker 6.30 - Module::Build::Tiny 0.034 + ExtUtils::MakeMaker 0 Module::Implementation 0.04 Module::Runtime 0.012 Package::Stash 0.14 Scalar::Util 0 Try::Tiny 0 base 0 - perl 5.008 + perl 5.006 strict 0 warnings 0 - Class-Load-XS-0.08 - pathname: E/ET/ETHER/Class-Load-XS-0.08.tar.gz + Class-Load-XS-0.10 + pathname: E/ET/ETHER/Class-Load-XS-0.10.tar.gz provides: - Class::Load::XS 0.08 + Class::Load::XS 0.10 requirements: Class::Load 0.20 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 XSLoader 0 + perl 5.006 strict 0 warnings 0 - Class-Method-Modifiers-2.10 - pathname: E/ET/ETHER/Class-Method-Modifiers-2.10.tar.gz + Class-Method-Modifiers-2.15 + pathname: E/ET/ETHER/Class-Method-Modifiers-2.15.tar.gz provides: - Class::Method::Modifiers 2.10 + Class::Method::Modifiers 2.15 requirements: B 0 Carp 0 Exporter 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 base 0 + perl 5.006 strict 0 warnings 0 - Class-Singleton-1.4 - pathname: A/AB/ABW/Class-Singleton-1.4.tar.gz + Class-Singleton-1.6 + pathname: S/SH/SHAY/Class-Singleton-1.6.tar.gz provides: - Class::Singleton 1.4 + Class::Singleton 1.6 requirements: - ExtUtils::MakeMaker 0 - Class-Tiny-0.014 - pathname: D/DA/DAGOLDEN/Class-Tiny-0.014.tar.gz - provides: - Class::Tiny 0.014 + ExtUtils::MakeMaker 6.64 + perl 5.008001 + strict 0 + warnings 0 + Class-Tiny-1.008 + pathname: D/DA/DAGOLDEN/Class-Tiny-1.008.tar.gz + provides: + Class::Tiny 1.008 + Class::Tiny::Object 1.008 requirements: Carp 0 ExtUtils::MakeMaker 6.17 + perl 5.006 strict 0 warnings 0 + Class-Tiny-Chained-0.004 + pathname: D/DB/DBOOK/Class-Tiny-Chained-0.004.tar.gz + provides: + Class::Tiny::Chained 0.004 + requirements: + Class::Tiny 1.003 + ExtUtils::MakeMaker 0 + perl 5.006 Class-XSAccessor-1.19 pathname: S/SM/SMUELLER/Class-XSAccessor-1.19.tar.gz provides: @@ -1026,79 +846,117 @@ DISTRIBUTIONS Time::HiRes 0 XSLoader 0 perl 5.008 - Clone-0.37 - pathname: G/GA/GARU/Clone-0.37.tar.gz + Clone-0.47 + pathname: A/AT/ATOOMIC/Clone-0.47.tar.gz provides: - Clone 0.37 + Clone 0.47 requirements: ExtUtils::MakeMaker 0 - Test::More 0 - Clone-PP-1.06 - pathname: N/NE/NEILB/Clone-PP-1.06.tar.gz + Clone-Choose-0.010 + pathname: H/HE/HERMES/Clone-Choose-0.010.tar.gz provides: - Clone::PP 1.06 + Clone::Choose 0.010 requirements: - Exporter 0 ExtUtils::MakeMaker 0 - perl 5.006 - strict 0 - vars 0 - warnings 0 - Code-TidyAll-0.20 - pathname: J/JS/JSWARTZ/Code-TidyAll-0.20.tar.gz - provides: - Code::TidyAll 0.20 - Code::TidyAll::Cache 0.20 - Code::TidyAll::Config::INI::Reader 0.20 - Code::TidyAll::Git::Precommit 0.20 - Code::TidyAll::Git::Prereceive 0.20 - Code::TidyAll::Git::Util 0.20 - Code::TidyAll::Plugin 0.20 - Code::TidyAll::Plugin::CSSUnminifier 0.20 - Code::TidyAll::Plugin::JSBeautify 0.20 - Code::TidyAll::Plugin::JSHint 0.20 - Code::TidyAll::Plugin::JSLint 0.20 - Code::TidyAll::Plugin::JSON 0.20 - Code::TidyAll::Plugin::MasonTidy 0.20 - Code::TidyAll::Plugin::PHPCodeSniffer 0.20 - Code::TidyAll::Plugin::PerlCritic 0.20 - Code::TidyAll::Plugin::PerlTidy 0.20 - Code::TidyAll::Plugin::PodChecker 0.20 - Code::TidyAll::Plugin::PodSpell 0.20 - Code::TidyAll::Plugin::PodTidy 0.20 - Code::TidyAll::Plugin::SortLines 0.20 - Code::TidyAll::Result 0.20 - Code::TidyAll::SVN::Precommit 0.20 - Code::TidyAll::SVN::Util 0.20 - Code::TidyAll::Util::Zglob 0.20 - Pod::Weaver::Section::SeeAlsoCodeTidyAll 0.20 - Test::Code::TidyAll 0.20 - requirements: - Capture::Tiny 0.12 + Storable 0 + perl 5.008001 + Code-TidyAll-0.84 + pathname: D/DR/DROLSKY/Code-TidyAll-0.84.tar.gz + provides: + Code::TidyAll 0.84 + Code::TidyAll::Cache 0.84 + Code::TidyAll::CacheModel 0.84 + Code::TidyAll::CacheModel::Shared 0.84 + Code::TidyAll::Config::INI::Reader 0.84 + Code::TidyAll::Git::Precommit 0.84 + Code::TidyAll::Git::Prereceive 0.84 + Code::TidyAll::Git::Util 0.84 + Code::TidyAll::Plugin 0.84 + Code::TidyAll::Plugin::CSSUnminifier 0.84 + Code::TidyAll::Plugin::GenericTransformer 0.84 + Code::TidyAll::Plugin::GenericValidator 0.84 + Code::TidyAll::Plugin::JSBeautify 0.84 + Code::TidyAll::Plugin::JSHint 0.84 + Code::TidyAll::Plugin::JSLint 0.84 + Code::TidyAll::Plugin::JSON 0.84 + Code::TidyAll::Plugin::MasonTidy 0.84 + Code::TidyAll::Plugin::PHPCodeSniffer 0.84 + Code::TidyAll::Plugin::PerlCritic 0.84 + Code::TidyAll::Plugin::PerlTidy 0.84 + Code::TidyAll::Plugin::PerlTidySweet 0.84 + Code::TidyAll::Plugin::PodChecker 0.84 + Code::TidyAll::Plugin::PodSpell 0.84 + Code::TidyAll::Plugin::PodTidy 0.84 + Code::TidyAll::Plugin::SortLines 0.84 + Code::TidyAll::Result 0.84 + Code::TidyAll::Role::GenericExecutable 0.84 + Code::TidyAll::Role::HasIgnore 0.84 + Code::TidyAll::Role::RunsCommand 0.84 + Code::TidyAll::Role::Tempdir 0.84 + Code::TidyAll::SVN::Precommit 0.84 + Code::TidyAll::SVN::Util 0.84 + Code::TidyAll::Util::Zglob 0.84 + Code::TidyAll::Zglob 0.84 + Test::Code::TidyAll 0.84 + requirements: + Capture::Tiny 0 Config::INI::Reader 0 + Cwd 0 + Data::Dumper 0 Date::Format 0 - Digest::SHA1 0 - ExtUtils::MakeMaker 6.30 + Digest::SHA 0 + Exporter 0 + ExtUtils::MakeMaker 0 File::Basename 0 File::Find 0 - File::Path 0 - File::Temp 0 - File::Zglob 0 + File::Spec 0 + File::Which 0 + File::pushd 0 Getopt::Long 0 - Guard 0 IPC::Run3 0 - IPC::System::Simple 0.15 - List::MoreUtils 0 + IPC::System::Simple 0 + List::Compare 0 + List::SomeUtils 0 Log::Any 0 - Moo 0.0091010 + Module::Runtime 0 + Moo 2.000000 + Moo::Role 0 + Path::Tiny 0.098 Scalar::Util 0 + Scope::Guard 0 + Specio 0.40 + Specio::Declare 0 + Specio::Library::Builtins 0 + Specio::Library::Numeric 0 + Specio::Library::Path::Tiny 0.04 + Specio::Library::String 0 + Test::Builder 0 + Text::Diff 1.44 + Text::Diff::Table 0 Text::ParseWords 0 Time::Duration::Parse 0 Try::Tiny 0 - Compress-Bzip2-2.17 - pathname: R/RU/RURBAN/Compress-Bzip2-2.17.tar.gz + base 0 + constant 0 + perl 5.008008 + strict 0 + warnings 0 + Code-TidyAll-Plugin-UniqueLines-0.000003 + pathname: O/OA/OALDERS/Code-TidyAll-Plugin-UniqueLines-0.000003.tar.gz + provides: + Code::TidyAll::Plugin::UniqueLines 0.000003 + requirements: + Code::TidyAll::Plugin 0 + ExtUtils::MakeMaker 0 + List::Util 1.45 + Moo 0 + perl 5.006 + strict 0 + warnings 0 + Compress-Bzip2-2.28 + pathname: R/RU/RURBAN/Compress-Bzip2-2.28.tar.gz provides: - Compress::Bzip2 2.17 + Compress::Bzip2 2.28 requirements: Carp 0 Config 0 @@ -1108,10 +966,23 @@ DISTRIBUTIONS File::Spec 0 Getopt::Std 0 Test::More 0 - Config-Any-0.24 - pathname: B/BR/BRICAS/Config-Any-0.24.tar.gz + constant 1.04 + Compress-Raw-Bzip2-2.213 + pathname: P/PM/PMQS/Compress-Raw-Bzip2-2.213.tar.gz + provides: + Compress::Raw::Bzip2 2.213 + requirements: + ExtUtils::MakeMaker 0 + Compress-Raw-Zlib-2.213 + pathname: P/PM/PMQS/Compress-Raw-Zlib-2.213.tar.gz + provides: + Compress::Raw::Zlib 2.213 + requirements: + ExtUtils::MakeMaker 0 + Config-Any-0.33 + pathname: H/HA/HAARG/Config-Any-0.33.tar.gz provides: - Config::Any 0.24 + Config::Any 0.33 Config::Any::Base undef Config::Any::General undef Config::Any::INI undef @@ -1120,157 +991,150 @@ DISTRIBUTIONS Config::Any::XML undef Config::Any::YAML undef requirements: - ExtUtils::MakeMaker 6.59 - Module::Pluggable 3.01 - Test::More 0 - perl 5.006 - Config-General-2.56 - pathname: T/TL/TLINDEN/Config-General-2.56.tar.gz + Module::Pluggable::Object 3.6 + Config-General-2.67 + pathname: T/TL/TLINDEN/Config-General-2.67.tar.gz provides: - Config::General 2.56 + Config::General 2.67 Config::General::Extended 2.07 - Config::General::Interpolated 2.15 + Config::General::Interpolated 2.16 requirements: ExtUtils::MakeMaker 0 File::Glob 0 File::Spec::Functions 0 FileHandle 0 IO::File 0 - Config-INI-0.024 - pathname: R/RJ/RJBS/Config-INI-0.024.tar.gz + Config-INI-0.029 + pathname: R/RJ/RJBS/Config-INI-0.029.tar.gz provides: - Config::INI 0.024 - Config::INI::Reader 0.024 - Config::INI::Writer 0.024 + Config::INI 0.029 + Config::INI::Reader 0.029 + Config::INI::Writer 0.029 requirements: Carp 0 - ExtUtils::MakeMaker 6.30 - Mixin::Linewise::Readers 0.100 + ExtUtils::MakeMaker 6.78 + Mixin::Linewise::Readers 0.110 Mixin::Linewise::Writers 0 - strict 0 + perl 5.012 warnings 0 - Config-JFDI-0.065 - pathname: R/RO/ROKR/Config-JFDI-0.065.tar.gz + Config-Tiny-2.30 + pathname: R/RS/RSAVAGE/Config-Tiny-2.30.tgz + provides: + Config::Tiny 2.30 + requirements: + ExtUtils::MakeMaker 0 + File::Spec 3.30 + File::Temp 0.22 + Test::More 0.47 + perl 5.008001 + strict 0 + utf8 0 + Config-ZOMG-1.000000 + pathname: F/FR/FREW/Config-ZOMG-1.000000.tar.gz provides: - Config::JFDI 0.065 - Config::JFDI::Carp undef - Config::JFDI::Source::Loader undef - eq 0.065 - t::Test undef + Config::ZOMG 1.000000 + Config::ZOMG::Source::Loader 1.000000 requirements: - Any::Moose 0 - Carp::Clan::Share 0 Clone 0 Config::Any 0 - Config::General 0 - Data::Visitor 0.24 - ExtUtils::MakeMaker 6.31 - Getopt::Usaginator 0 + ExtUtils::MakeMaker 6.30 Hash::Merge::Simple 0 - List::MoreUtils 0 - Path::Class 0 - Sub::Install 0 - Test::Most 0 - Config-Tiny-2.20 - pathname: R/RS/RSAVAGE/Config-Tiny-2.20.tgz + List::Util 0 + Moo 0 + Const-Fast-0.014 + pathname: L/LE/LEONT/Const-Fast-0.014.tar.gz provides: - Config::Tiny 2.20 + Const::Fast 0.014 requirements: - File::Spec 3.3 - File::Temp 0.22 - Module::Build 0.34 - Test::More 0.47 - UNIVERSAL 0 - perl v5.8.1 + Carp 0 + Module::Build::Tiny 0.021 + Scalar::Util 0 + Storable 0 + Sub::Exporter::Progressive 0.001007 + perl 5.008 strict 0 - utf8 0 - Context-Preserve-0.01 - pathname: J/JR/JROCKWAY/Context-Preserve-0.01.tar.gz + warnings 0 + Cookie-Baker-0.12 + pathname: K/KA/KAZEBURO/Cookie-Baker-0.12.tar.gz provides: - Context::Preserve 0.01 + Cookie::Baker 0.12 requirements: Exporter 0 - ExtUtils::MakeMaker 0 - Test::Exception 0 - Test::More 0 - ok 0 - Cookie-Baker-0.03 - pathname: K/KA/KAZEBURO/Cookie-Baker-0.03.tar.gz + Module::Build::Tiny 0.035 + URI::Escape 0 + perl 5.008001 + Cpanel-JSON-XS-4.39 + pathname: R/RU/RURBAN/Cpanel-JSON-XS-4.39.tar.gz provides: - Cookie::Baker 0.03 + Cpanel::JSON::XS 4.39 + Cpanel::JSON::XS::Type undef requirements: - CPAN::Meta 0 - CPAN::Meta::Prereqs 0 + Carp 0 + Config 0 + Encode 1.9801 Exporter 0 - ExtUtils::CBuilder 0 - Module::Build 0.38 - URI::Escape 0 - perl 5.008005 - Cpanel-JSON-XS-3.0104 - pathname: R/RU/RURBAN/Cpanel-JSON-XS-3.0104.tar.gz + ExtUtils::MakeMaker 0 + Pod::Text 2.08 + XSLoader 0 + overload 0 + strict 0 + warnings 0 + Crypt-SysRandom-0.007 + pathname: L/LE/LEONT/Crypt-SysRandom-0.007.tar.gz provides: - Cpanel::JSON::XS 3.0104 + Crypt::SysRandom 0.007 requirements: + Carp 0 + Exporter 0 ExtUtils::MakeMaker 0 - Pod::Text 2.08 - Pod::Usage 1.33 - Crypt-DH-GMP-0.00012 - pathname: D/DM/DMAKI/Crypt-DH-GMP-0.00012.tar.gz + perl 5.006 + strict 0 + warnings 0 + Crypt-URandom-0.54 + pathname: D/DD/DDICK/Crypt-URandom-0.54.tar.gz provides: - Crypt::DH::GMP 0.00012 - Crypt::DH::GMP::Compat undef + Crypt::URandom 0.54 requirements: - Devel::CheckLib 0.4 - Devel::PPPort 3.19 - ExtUtils::MakeMaker 6.59 - ExtUtils::ParseXS 3.18 - Test::More 0 - Test::Requires 0 - XSLoader 0.02 - perl 5.0080001 - Crypt-SSLeay-0.72 - pathname: N/NA/NANIS/Crypt-SSLeay-0.72.tar.gz - provides: - Crypt::SSLeay 0.72 - Crypt::SSLeay::CTX undef - Crypt::SSLeay::Conn undef - Crypt::SSLeay::Err undef - Crypt::SSLeay::MainContext undef - Crypt::SSLeay::Version undef - Crypt::SSLeay::X509 undef - Net::SSL 2.86 - requirements: - ExtUtils::CBuilder 0.280205 + Carp 1.26 + English 0 + Exporter 0 ExtUtils::MakeMaker 0 - Getopt::Long 0 - LWP::Protocol::https 6.02 - MIME::Base64 0 - Path::Class 0.26 - Try::Tiny 0.19 + FileHandle 0 + constant 0 perl 5.006 - DBD-SQLite-1.44 - pathname: I/IS/ISHIGAKI/DBD-SQLite-1.44.tar.gz + DBD-Pg-3.18.0 + pathname: T/TU/TURNSTEP/DBD-Pg-3.18.0.tar.gz provides: - DBD::SQLite 1.44 - DBD::SQLite::VirtualTable 1.44 - DBD::SQLite::VirtualTable::Cursor 1.44 + Bundle::DBD::Pg v3.18.0 + DBD::Pg v3.18.0 + requirements: + DBI 1.614 + ExtUtils::MakeMaker 6.58 + File::Temp 0 + Test::More 0.88 + Time::HiRes 0 + version 0 + DBD-SQLite-1.76 + pathname: I/IS/ISHIGAKI/DBD-SQLite-1.76.tar.gz + provides: + DBD::SQLite 1.76 + DBD::SQLite::Constants undef + DBD::SQLite::GetInfo undef + DBD::SQLite::VirtualTable 1.76 + DBD::SQLite::VirtualTable::Cursor 1.76 DBD::SQLite::VirtualTable::FileContent undef DBD::SQLite::VirtualTable::FileContent::Cursor undef DBD::SQLite::VirtualTable::PerlData undef DBD::SQLite::VirtualTable::PerlData::Cursor undef - DBD::SQLite::_WriteOnceHash 1.44 - DBD::SQLite::db 1.44 - DBD::SQLite::dr 1.44 requirements: DBI 1.57 - ExtUtils::MakeMaker 6.48 + ExtUtils::MakeMaker 0 File::Spec 0.82 - Test::Builder 0.86 - Test::More 0.47 + Test::More 0.88 Tie::Hash 0 perl 5.006 - DBI-1.631 - pathname: T/TI/TIMB/DBI-1.631.tar.gz + DBI-1.647 + pathname: H/HM/HMBRAND/DBI-1.647.tgz provides: Bundle::DBI 12.008696 DBD::DBM 0.08 @@ -1283,15 +1147,15 @@ DISTRIBUTIONS DBD::ExampleP::db 12.014311 DBD::ExampleP::dr 12.014311 DBD::ExampleP::st 12.014311 - DBD::File 0.42 - DBD::File::DataSource::File 0.42 - DBD::File::DataSource::Stream 0.42 - DBD::File::Statement 0.42 - DBD::File::Table 0.42 - DBD::File::TableSource::FileSystem 0.42 - DBD::File::db 0.42 - DBD::File::dr 0.42 - DBD::File::st 0.42 + DBD::File 0.44 + DBD::File::DataSource::File 0.44 + DBD::File::DataSource::Stream 0.44 + DBD::File::Statement 0.44 + DBD::File::Table 0.44 + DBD::File::TableSource::FileSystem 0.44 + DBD::File::db 0.44 + DBD::File::dr 0.44 + DBD::File::st 0.44 DBD::Gofer 0.015327 DBD::Gofer::Policy::Base 0.010088 DBD::Gofer::Policy::classic 0.010088 @@ -1305,6 +1169,13 @@ DISTRIBUTIONS DBD::Gofer::db 0.015327 DBD::Gofer::dr 0.015327 DBD::Gofer::st 0.015327 + DBD::Mem 0.001 + DBD::Mem::DataSource 0.001 + DBD::Mem::Statement 0.001 + DBD::Mem::Table 0.001 + DBD::Mem::db 0.001 + DBD::Mem::dr 0.001 + DBD::Mem::st 0.001 DBD::NullP 12.014715 DBD::NullP::db 12.014715 DBD::NullP::dr 12.014715 @@ -1319,7 +1190,7 @@ DISTRIBUTIONS DBD::Sponge::dr 12.010003 DBD::Sponge::st 12.010003 DBDI 12.015129 - DBI 1.631 + DBI 1.647 DBI::Const::GetInfo::ANSI 2.008697 DBI::Const::GetInfo::ODBC 2.011374 DBI::Const::GetInfoReturn 2.008697 @@ -1336,7 +1207,6 @@ DISTRIBUTIONS DBI::DBD::SqlEngine::db 0.06 DBI::DBD::SqlEngine::dr 0.06 DBI::DBD::SqlEngine::st 0.06 - DBI::FAQ 1.014935 DBI::Gofer::Execute 0.014283 DBI::Gofer::Request 0.012537 DBI::Gofer::Response 0.011566 @@ -1360,172 +1230,27 @@ DISTRIBUTIONS DBI::SQL::Nano::Table_ 1.015544 DBI::Util::CacheMemory 0.010315 DBI::Util::_accessor 0.009479 - DBI::common 1.631 + DBI::common 1.647 requirements: ExtUtils::MakeMaker 6.48 Test::Simple 0.90 - perl 5.008 - DBIx-Class-0.082801 - pathname: R/RI/RIBASUSHI/DBIx-Class-0.082801.tar.gz - provides: - DBIx::Class 0.082801 - DBIx::Class::AccessorGroup undef - DBIx::Class::Admin undef - DBIx::Class::CDBICompat undef - DBIx::Class::Core undef - DBIx::Class::Cursor undef - DBIx::Class::DB undef - DBIx::Class::Exception undef - DBIx::Class::FilterColumn undef - DBIx::Class::InflateColumn undef - DBIx::Class::InflateColumn::DateTime undef - DBIx::Class::InflateColumn::File undef - DBIx::Class::Optional::Dependencies undef - DBIx::Class::Ordered undef - DBIx::Class::PK undef - DBIx::Class::PK::Auto undef - DBIx::Class::Relationship undef - DBIx::Class::Relationship::Base undef - DBIx::Class::ResultClass::HashRefInflator undef - DBIx::Class::ResultSet undef - DBIx::Class::ResultSetColumn undef - DBIx::Class::ResultSetManager undef - DBIx::Class::ResultSource undef - DBIx::Class::ResultSource::Table undef - DBIx::Class::ResultSource::View undef - DBIx::Class::ResultSourceHandle undef - DBIx::Class::ResultSourceProxy::Table undef - DBIx::Class::Row undef - DBIx::Class::SQLMaker undef - DBIx::Class::SQLMaker::LimitDialects undef - DBIx::Class::SQLMaker::OracleJoins undef - DBIx::Class::Schema undef - DBIx::Class::Schema::Versioned undef - DBIx::Class::Serialize::Storable undef - DBIx::Class::StartupCheck undef - DBIx::Class::Storage undef - DBIx::Class::Storage::DBI undef - DBIx::Class::Storage::DBI::ACCESS undef - DBIx::Class::Storage::DBI::ADO undef - DBIx::Class::Storage::DBI::ADO::MS_Jet undef - DBIx::Class::Storage::DBI::ADO::MS_Jet::Cursor undef - DBIx::Class::Storage::DBI::ADO::Microsoft_SQL_Server undef - DBIx::Class::Storage::DBI::ADO::Microsoft_SQL_Server::Cursor undef - DBIx::Class::Storage::DBI::AutoCast undef - DBIx::Class::Storage::DBI::Cursor undef - DBIx::Class::Storage::DBI::DB2 undef - DBIx::Class::Storage::DBI::Firebird undef - DBIx::Class::Storage::DBI::Firebird::Common undef - DBIx::Class::Storage::DBI::IdentityInsert undef - DBIx::Class::Storage::DBI::Informix undef - DBIx::Class::Storage::DBI::InterBase undef - DBIx::Class::Storage::DBI::MSSQL undef - DBIx::Class::Storage::DBI::NoBindVars undef - DBIx::Class::Storage::DBI::ODBC undef - DBIx::Class::Storage::DBI::ODBC::ACCESS undef - DBIx::Class::Storage::DBI::ODBC::DB2_400_SQL undef - DBIx::Class::Storage::DBI::ODBC::Firebird undef - DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server undef - DBIx::Class::Storage::DBI::ODBC::SQL_Anywhere undef - DBIx::Class::Storage::DBI::Oracle undef - DBIx::Class::Storage::DBI::Oracle::Generic undef - DBIx::Class::Storage::DBI::Oracle::WhereJoins undef - DBIx::Class::Storage::DBI::Pg undef - DBIx::Class::Storage::DBI::Replicated undef - DBIx::Class::Storage::DBI::Replicated::Balancer undef - DBIx::Class::Storage::DBI::Replicated::Balancer::First undef - DBIx::Class::Storage::DBI::Replicated::Balancer::Random undef - DBIx::Class::Storage::DBI::Replicated::Pool undef - DBIx::Class::Storage::DBI::Replicated::Replicant undef - DBIx::Class::Storage::DBI::Replicated::WithDSN undef - DBIx::Class::Storage::DBI::SQLAnywhere undef - DBIx::Class::Storage::DBI::SQLAnywhere::Cursor undef - DBIx::Class::Storage::DBI::SQLite undef - DBIx::Class::Storage::DBI::Sybase undef - DBIx::Class::Storage::DBI::Sybase::ASE undef - DBIx::Class::Storage::DBI::Sybase::ASE::NoBindVars undef - DBIx::Class::Storage::DBI::Sybase::FreeTDS undef - DBIx::Class::Storage::DBI::Sybase::MSSQL undef - DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server undef - DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server::NoBindVars undef - DBIx::Class::Storage::DBI::UniqueIdentifier undef - DBIx::Class::Storage::DBI::mysql undef - DBIx::Class::Storage::Statistics undef - DBIx::Class::Storage::TxnScopeGuard undef - DBIx::Class::UTF8Columns undef - SQL::Translator::Parser::DBIx::Class 1.10 - SQL::Translator::Producer::DBIx::Class::File 0.1 - requirements: - Class::Accessor::Grouped 0.10012 - Class::C3::Componentised 1.0009 - Class::Inspector 1.24 - Config::Any 0.20 - Context::Preserve 0.01 - DBD::SQLite 1.29 - DBI 1.57 - Data::Dumper::Concise 2.020 - Data::Page 2.00 - Devel::GlobalDestruction 0.09 - ExtUtils::MakeMaker 6.59 - File::Temp 0.22 - Hash::Merge 0.12 - List::Util 1.16 - MRO::Compat 0.12 - Module::Find 0.07 - Moo 1.004005 - Package::Stash 0.28 - Path::Class 0.18 - SQL::Abstract 1.80 - Scope::Guard 0.03 - Sub::Name 0.04 - Test::Deep 0.101 - Test::Exception 0.31 - Test::More 0.94 - Test::Warn 0.21 - Text::Balanced 2.00 - Try::Tiny 0.07 - namespace::clean 0.24 perl 5.008001 - Data-Compare-1.24 - pathname: D/DC/DCANTRELL/Data-Compare-1.24.tar.gz + Data-Compare-1.29 + pathname: D/DC/DCANTRELL/Data-Compare-1.29.tar.gz provides: - Data::Compare 1.24 - Data::Compare::Plugins::Scalar::Properties 1 + Data::Compare 1.29 + Data::Compare::Plugins::Scalar::Properties 1.25 requirements: - ExtUtils::MakeMaker 0 + Clone 0.43 + ExtUtils::MakeMaker 6.48 File::Find::Rule 0.1 Scalar::Util 0 - Data-DPath-0.50 - pathname: S/SC/SCHWIGON/Data-DPath-0.50.tar.gz - provides: - Data::DPath 0.50 - Data::DPath::Attrs 0.50 - Data::DPath::Context 0.50 - Data::DPath::Filters 0.50 - Data::DPath::Path 0.50 - Data::DPath::Point 0.50 - Data::DPath::Step 0.50 - requirements: - Class::XSAccessor 0 - Class::XSAccessor::Array 0 - Data::Dumper 0 - ExtUtils::MakeMaker 6.30 - Iterator::Util 0 - List::MoreUtils 0 - List::Util 0 - POSIX 0 - Safe 2.30 - Scalar::Util 0 - Sub::Exporter 0 - Text::Balanced 2.02 - aliased 0 - constant 0 - strict 0 - warnings 0 - Data-Dump-1.22 - pathname: G/GA/GAAS/Data-Dump-1.22.tar.gz + Test::More 0.88 + perl 5.006 + Data-Dump-1.25 + pathname: G/GA/GARU/Data-Dump-1.25.tar.gz provides: - Data::Dump 1.22 + Data::Dump 1.25 Data::Dump::FilterContext undef Data::Dump::Filtered undef Data::Dump::Trace 0.02 @@ -1536,168 +1261,136 @@ DISTRIBUTIONS Symbol 0 Test 0 perl 5.006 - Data-Dumper-Concise-2.022 - pathname: F/FR/FREW/Data-Dumper-Concise-2.022.tar.gz + Data-Dumper-Concise-2.023 + pathname: E/ET/ETHER/Data-Dumper-Concise-2.023.tar.gz provides: - Data::Dumper::Concise 2.022 - Data::Dumper::Concise::Sugar undef + Data::Dumper::Concise 2.023 + Data::Dumper::Concise::Sugar 2.023 Devel::Dwarn undef requirements: - ExtUtils::MakeMaker 6.59 + Data::Dumper 0 + Exporter 0 + ExtUtils::MakeMaker 0 perl 5.006 - Data-OptList-0.109 - pathname: R/RJ/RJBS/Data-OptList-0.109.tar.gz + Data-OptList-0.114 + pathname: R/RJ/RJBS/Data-OptList-0.114.tar.gz provides: - Data::OptList 0.109 + Data::OptList 0.114 requirements: - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 6.78 List::Util 0 Params::Util 0 Sub::Install 0.921 + perl 5.012 strict 0 warnings 0 - Data-Page-2.02 - pathname: L/LB/LBROCARD/Data-Page-2.02.tar.gz - provides: - Data::Page 2.02 - requirements: - Class::Accessor::Chained::Fast 0 - Test::Exception 0 - Test::More 0 - Data-Printer-0.35 - pathname: G/GA/GARU/Data-Printer-0.35.tar.gz + Data-Section-0.200008 + pathname: R/RJ/RJBS/Data-Section-0.200008.tar.gz provides: - DDP undef - Data::Printer 0.35 - Data::Printer::Filter undef - Data::Printer::Filter::DB undef - Data::Printer::Filter::DateTime undef - Data::Printer::Filter::Digest undef - requirements: - Carp 0 - Clone::PP 0 - ExtUtils::MakeMaker 0 - Fcntl 0 - File::HomeDir 0.91 - File::Spec 0 - File::Temp 0 - Package::Stash 0.3 - Scalar::Util 0 - Sort::Naturally 0 - Term::ANSIColor 3 - Test::More 0.88 - version 0.77 - Data-Section-0.200006 - pathname: R/RJ/RJBS/Data-Section-0.200006.tar.gz - provides: - Child undef - Data::Section 0.200006 - End undef - Godfather undef - Grandchild undef - Header undef - I::Child undef - I::Grandchild undef - I::Parent undef - Latin1 undef - NoData undef - NoName undef - Parent undef - Relaxed undef - Unicode_nopragma undef - Unicode_pragma undef - WindowsNewlines undef + Data::Section 0.200008 requirements: Encode 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 6.78 MRO::Compat 0.09 Sub::Exporter 0.979 + perl 5.012 strict 0 warnings 0 - Data-UUID-1.219 - pathname: R/RJ/RJBS/Data-UUID-1.219.tar.gz + Data-UUID-1.227 + pathname: G/GT/GTERMARS/Data-UUID-1.227.tar.gz provides: - Data::UUID 1.219 + Data::UUID 1.227 requirements: Digest::MD5 0 ExtUtils::MakeMaker 0 - Data-Visitor-0.30 - pathname: D/DO/DOY/Data-Visitor-0.30.tar.gz + Data-Visitor-0.32 + pathname: E/ET/ETHER/Data-Visitor-0.32.tar.gz provides: - Data::Visitor 0.30 - Data::Visitor::Callback 0.30 + Data::Visitor 0.32 + Data::Visitor::Callback 0.32 requirements: - Class::Load 0.06 - ExtUtils::MakeMaker 6.30 + Carp 0 + ExtUtils::MakeMaker 0 Moose 0.89 - Task::Weaken 0 + Scalar::Util 0 + Symbol 0 Tie::ToObject 0.01 + constant 0 namespace::clean 0.19 - DateTime-1.10 - pathname: D/DR/DROLSKY/DateTime-1.10.tar.gz - provides: - DateTime 1.10 - DateTime::Duration 1.10 - DateTime::Helpers 1.10 - DateTime::Infinite 1.10 - DateTime::Infinite::Future 1.10 - DateTime::Infinite::Past 1.10 - DateTime::LeapSecond 1.10 - inc::MyModuleBuild undef + overload 0 + perl 5.006 + strict 0 + warnings 0 + DateTime-1.66 + pathname: D/DR/DROLSKY/DateTime-1.66.tar.gz + provides: + DateTime 1.66 + DateTime::Duration 1.66 + DateTime::Helpers 1.66 + DateTime::Infinite 1.66 + DateTime::Infinite::Future 1.66 + DateTime::Infinite::Past 1.66 + DateTime::LeapSecond 1.66 + DateTime::PP 1.66 + DateTime::PPExtra 1.66 + DateTime::Types 1.66 requirements: Carp 0 - DateTime::Locale 0.41 - DateTime::TimeZone 1.09 - ExtUtils::CBuilder 0 - Module::Build 0.3601 + DateTime::Locale 1.06 + DateTime::TimeZone 2.44 + Dist::CheckConflicts 0.02 + ExtUtils::MakeMaker 0 POSIX 0 - Params::Validate 0.76 + Params::ValidationCompiler 0.26 Scalar::Util 0 + Specio 0.50 + Specio::Declare 0 + Specio::Exporter 0 + Specio::Library::Builtins 0 + Specio::Library::Numeric 0 + Specio::Library::String 0 + Specio::Subs 0 Try::Tiny 0 XSLoader 0 - base 0 - constant 0 integer 0 + namespace::autoclean 0.19 overload 0 - perl 5.008001 + parent 0 + perl 5.008004 strict 0 - vars 0 warnings 0 warnings::register 0 - DateTime-Format-Builder-0.81 - pathname: D/DR/DROLSKY/DateTime-Format-Builder-0.81.tar.gz - provides: - DateTime::Format::Builder 0.81 - DateTime::Format::Builder::Parser 0.81 - DateTime::Format::Builder::Parser::Dispatch 0.81 - DateTime::Format::Builder::Parser::Quick 0.81 - DateTime::Format::Builder::Parser::Regex 0.81 - DateTime::Format::Builder::Parser::Strptime 0.81 - DateTime::Format::Builder::Parser::generic 0.81 - DateTime::Format::Fall undef - DateTime::Format::Simple undef + DateTime-Format-Builder-0.83 + pathname: D/DR/DROLSKY/DateTime-Format-Builder-0.83.tar.gz + provides: + DateTime::Format::Builder 0.83 + DateTime::Format::Builder::Parser 0.83 + DateTime::Format::Builder::Parser::Dispatch 0.83 + DateTime::Format::Builder::Parser::Quick 0.83 + DateTime::Format::Builder::Parser::Regex 0.83 + DateTime::Format::Builder::Parser::Strptime 0.83 + DateTime::Format::Builder::Parser::generic 0.83 requirements: Carp 0 - Class::Factory::Util 1.6 DateTime 1.00 DateTime::Format::Strptime 1.04 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 Params::Validate 0.72 Scalar::Util 0 - base 0 + parent 0 strict 0 - vars 0 warnings 0 - DateTime-Format-Epoch-0.13 - pathname: C/CH/CHORNY/DateTime-Format-Epoch-0.13.tar.gz + DateTime-Format-Epoch-0.16 + pathname: C/CH/CHORNY/DateTime-Format-Epoch-0.16.tar.gz provides: - DateTime::Format::Epoch 0.13 + DateTime::Format::Epoch 0.16 DateTime::Format::Epoch::ActiveDirectory 0.13 DateTime::Format::Epoch::DotNet 0.13 DateTime::Format::Epoch::JD 0.13 DateTime::Format::Epoch::Lilian 0.13 DateTime::Format::Epoch::MJD 0.13 DateTime::Format::Epoch::MacOS 0.13 + DateTime::Format::Epoch::NTP 0.14 DateTime::Format::Epoch::RJD 0.13 DateTime::Format::Epoch::RataDie 0.13 DateTime::Format::Epoch::TAI64 0.13 @@ -1709,1055 +1402,549 @@ DISTRIBUTIONS Params::Validate 0 Test::More 0 perl 5.00503 - DateTime-Format-ISO8601-0.08 - pathname: J/JH/JHOBLITT/DateTime-Format-ISO8601-0.08.tar.gz + warnings 0 + DateTime-Format-ISO8601-0.17 + pathname: D/DR/DROLSKY/DateTime-Format-ISO8601-0.17.tar.gz provides: - DateTime::Format::ISO8601 0.08 + DateTime::Format::ISO8601 0.17 + DateTime::Format::ISO8601::Types 0.17 requirements: - DateTime 0.18 + Carp 0 + DateTime 1.45 DateTime::Format::Builder 0.77 - DateTime-Format-Strptime-1.55 - pathname: D/DR/DROLSKY/DateTime-Format-Strptime-1.55.tar.gz + ExtUtils::MakeMaker 0 + Params::ValidationCompiler 0.26 + Specio 0.18 + Specio::Declare 0 + Specio::Exporter 0 + Specio::Library::Builtins 0 + namespace::autoclean 0 + parent 0 + strict 0 + warnings 0 + DateTime-Format-RFC3339-v1.10.0 + pathname: I/IK/IKEGAMI/DateTime-Format-RFC3339-v1.10.0.tar.gz provides: - DateTime::Format::Strptime 1.55 + DateTime::Format::RFC3339 1.010000 + requirements: + DateTime 0 + ExtUtils::MakeMaker 0 + perl 5.01 + strict 0 + version 0 + warnings 0 + DateTime-Format-Strptime-1.79 + pathname: D/DR/DROLSKY/DateTime-Format-Strptime-1.79.tar.gz + provides: + DateTime::Format::Strptime 1.79 + DateTime::Format::Strptime::Types 1.79 requirements: Carp 0 DateTime 1.00 - DateTime::Locale 0.45 - DateTime::TimeZone 0.79 + DateTime::Locale 1.30 + DateTime::Locale::Base 0 + DateTime::Locale::FromData 0 + DateTime::TimeZone 2.09 Exporter 0 - ExtUtils::MakeMaker 6.30 - Params::Validate 0.64 + ExtUtils::MakeMaker 0 + Params::ValidationCompiler 0 + Specio 0.33 + Specio::Declare 0 + Specio::Exporter 0 + Specio::Library::Builtins 0 + Specio::Library::String 0 + Try::Tiny 0 + constant 0 + parent 0 strict 0 - vars 0 - DateTime-Locale-0.45 - pathname: D/DR/DROLSKY/DateTime-Locale-0.45.tar.gz - provides: - DateTime::Locale 0.45 - DateTime::Locale::Base undef - DateTime::Locale::Catalog undef - DateTime::Locale::aa undef - DateTime::Locale::aa_DJ undef - DateTime::Locale::aa_ER undef - DateTime::Locale::aa_ER_SAAHO undef - DateTime::Locale::aa_ET undef - DateTime::Locale::af undef - DateTime::Locale::af_NA undef - DateTime::Locale::af_ZA undef - DateTime::Locale::ak undef - DateTime::Locale::ak_GH undef - DateTime::Locale::am undef - DateTime::Locale::am_ET undef - DateTime::Locale::ar undef - DateTime::Locale::ar_AE undef - DateTime::Locale::ar_BH undef - DateTime::Locale::ar_DZ undef - DateTime::Locale::ar_EG undef - DateTime::Locale::ar_IQ undef - DateTime::Locale::ar_JO undef - DateTime::Locale::ar_KW undef - DateTime::Locale::ar_LB undef - DateTime::Locale::ar_LY undef - DateTime::Locale::ar_MA undef - DateTime::Locale::ar_OM undef - DateTime::Locale::ar_QA undef - DateTime::Locale::ar_SA undef - DateTime::Locale::ar_SD undef - DateTime::Locale::ar_SY undef - DateTime::Locale::ar_TN undef - DateTime::Locale::ar_YE undef - DateTime::Locale::as undef - DateTime::Locale::as_IN undef - DateTime::Locale::az undef - DateTime::Locale::az_AZ undef - DateTime::Locale::az_Cyrl undef - DateTime::Locale::az_Cyrl_AZ undef - DateTime::Locale::az_Latn undef - DateTime::Locale::az_Latn_AZ undef - DateTime::Locale::be undef - DateTime::Locale::be_BY undef - DateTime::Locale::bg undef - DateTime::Locale::bg_BG undef - DateTime::Locale::bn undef - DateTime::Locale::bn_BD undef - DateTime::Locale::bn_IN undef - DateTime::Locale::bo undef - DateTime::Locale::bo_CN undef - DateTime::Locale::bo_IN undef - DateTime::Locale::bs undef - DateTime::Locale::bs_BA undef - DateTime::Locale::byn undef - DateTime::Locale::byn_ER undef - DateTime::Locale::ca undef - DateTime::Locale::ca_ES undef - DateTime::Locale::cch undef - DateTime::Locale::cch_NG undef - DateTime::Locale::cop undef - DateTime::Locale::cs undef - DateTime::Locale::cs_CZ undef - DateTime::Locale::cy undef - DateTime::Locale::cy_GB undef - DateTime::Locale::da undef - DateTime::Locale::da_DK undef - DateTime::Locale::de undef - DateTime::Locale::de_AT undef - DateTime::Locale::de_BE undef - DateTime::Locale::de_CH undef - DateTime::Locale::de_DE undef - DateTime::Locale::de_LI undef - DateTime::Locale::de_LU undef - DateTime::Locale::dv undef - DateTime::Locale::dv_MV undef - DateTime::Locale::dz undef - DateTime::Locale::dz_BT undef - DateTime::Locale::ee undef - DateTime::Locale::ee_GH undef - DateTime::Locale::ee_TG undef - DateTime::Locale::el undef - DateTime::Locale::el_CY undef - DateTime::Locale::el_GR undef - DateTime::Locale::el_POLYTON undef - DateTime::Locale::en undef - DateTime::Locale::en_AS undef - DateTime::Locale::en_AU undef - DateTime::Locale::en_BE undef - DateTime::Locale::en_BW undef - DateTime::Locale::en_BZ undef - DateTime::Locale::en_CA undef - DateTime::Locale::en_Dsrt undef - DateTime::Locale::en_Dsrt_US undef - DateTime::Locale::en_GB undef - DateTime::Locale::en_GU undef - DateTime::Locale::en_HK undef - DateTime::Locale::en_IE undef - DateTime::Locale::en_IN undef - DateTime::Locale::en_JM undef - DateTime::Locale::en_MH undef - DateTime::Locale::en_MP undef - DateTime::Locale::en_MT undef - DateTime::Locale::en_NA undef - DateTime::Locale::en_NZ undef - DateTime::Locale::en_PH undef - DateTime::Locale::en_PK undef - DateTime::Locale::en_SG undef - DateTime::Locale::en_Shaw undef - DateTime::Locale::en_TT undef - DateTime::Locale::en_UM undef - DateTime::Locale::en_US undef - DateTime::Locale::en_US_POSIX undef - DateTime::Locale::en_VI undef - DateTime::Locale::en_ZA undef - DateTime::Locale::en_ZW undef - DateTime::Locale::eo undef - DateTime::Locale::es undef - DateTime::Locale::es_AR undef - DateTime::Locale::es_BO undef - DateTime::Locale::es_CL undef - DateTime::Locale::es_CO undef - DateTime::Locale::es_CR undef - DateTime::Locale::es_DO undef - DateTime::Locale::es_EC undef - DateTime::Locale::es_ES undef - DateTime::Locale::es_GT undef - DateTime::Locale::es_HN undef - DateTime::Locale::es_MX undef - DateTime::Locale::es_NI undef - DateTime::Locale::es_PA undef - DateTime::Locale::es_PE undef - DateTime::Locale::es_PR undef - DateTime::Locale::es_PY undef - DateTime::Locale::es_SV undef - DateTime::Locale::es_US undef - DateTime::Locale::es_UY undef - DateTime::Locale::es_VE undef - DateTime::Locale::et undef - DateTime::Locale::et_EE undef - DateTime::Locale::eu undef - DateTime::Locale::eu_ES undef - DateTime::Locale::fa undef - DateTime::Locale::fa_AF undef - DateTime::Locale::fa_IR undef - DateTime::Locale::fi undef - DateTime::Locale::fi_FI undef - DateTime::Locale::fil undef - DateTime::Locale::fil_PH undef - DateTime::Locale::fo undef - DateTime::Locale::fo_FO undef - DateTime::Locale::fr undef - DateTime::Locale::fr_BE undef - DateTime::Locale::fr_CA undef - DateTime::Locale::fr_CH undef - DateTime::Locale::fr_FR undef - DateTime::Locale::fr_LU undef - DateTime::Locale::fr_MC undef - DateTime::Locale::fr_SN undef - DateTime::Locale::fur undef - DateTime::Locale::fur_IT undef - DateTime::Locale::ga undef - DateTime::Locale::ga_IE undef - DateTime::Locale::gaa undef - DateTime::Locale::gaa_GH undef - DateTime::Locale::gez undef - DateTime::Locale::gez_ER undef - DateTime::Locale::gez_ET undef - DateTime::Locale::gl undef - DateTime::Locale::gl_ES undef - DateTime::Locale::gsw undef - DateTime::Locale::gsw_CH undef - DateTime::Locale::gu undef - DateTime::Locale::gu_IN undef - DateTime::Locale::gv undef - DateTime::Locale::gv_GB undef - DateTime::Locale::ha undef - DateTime::Locale::ha_Arab undef - DateTime::Locale::ha_Arab_NG undef - DateTime::Locale::ha_Arab_SD undef - DateTime::Locale::ha_GH undef - DateTime::Locale::ha_Latn undef - DateTime::Locale::ha_Latn_GH undef - DateTime::Locale::ha_Latn_NE undef - DateTime::Locale::ha_Latn_NG undef - DateTime::Locale::ha_NE undef - DateTime::Locale::ha_NG undef - DateTime::Locale::ha_SD undef - DateTime::Locale::haw undef - DateTime::Locale::haw_US undef - DateTime::Locale::he undef - DateTime::Locale::he_IL undef - DateTime::Locale::hi undef - DateTime::Locale::hi_IN undef - DateTime::Locale::hr undef - DateTime::Locale::hr_HR undef - DateTime::Locale::hu undef - DateTime::Locale::hu_HU undef - DateTime::Locale::hy undef - DateTime::Locale::hy_AM undef - DateTime::Locale::hy_AM_REVISED undef - DateTime::Locale::ia undef - DateTime::Locale::id undef - DateTime::Locale::id_ID undef - DateTime::Locale::ig undef - DateTime::Locale::ig_NG undef - DateTime::Locale::ii undef - DateTime::Locale::ii_CN undef - DateTime::Locale::is undef - DateTime::Locale::is_IS undef - DateTime::Locale::it undef - DateTime::Locale::it_CH undef - DateTime::Locale::it_IT undef - DateTime::Locale::iu undef - DateTime::Locale::ja undef - DateTime::Locale::ja_JP undef - DateTime::Locale::ka undef - DateTime::Locale::ka_GE undef - DateTime::Locale::kaj undef - DateTime::Locale::kaj_NG undef - DateTime::Locale::kam undef - DateTime::Locale::kam_KE undef - DateTime::Locale::kcg undef - DateTime::Locale::kcg_NG undef - DateTime::Locale::kfo undef - DateTime::Locale::kfo_CI undef - DateTime::Locale::kk undef - DateTime::Locale::kk_Cyrl undef - DateTime::Locale::kk_Cyrl_KZ undef - DateTime::Locale::kk_KZ undef - DateTime::Locale::kl undef - DateTime::Locale::kl_GL undef - DateTime::Locale::km undef - DateTime::Locale::km_KH undef - DateTime::Locale::kn undef - DateTime::Locale::kn_IN undef - DateTime::Locale::ko undef - DateTime::Locale::ko_KR undef - DateTime::Locale::kok undef - DateTime::Locale::kok_IN undef - DateTime::Locale::kpe undef - DateTime::Locale::kpe_GN undef - DateTime::Locale::kpe_LR undef - DateTime::Locale::ku undef - DateTime::Locale::ku_Arab undef - DateTime::Locale::ku_Arab_IQ undef - DateTime::Locale::ku_Arab_IR undef - DateTime::Locale::ku_Arab_SY undef - DateTime::Locale::ku_IQ undef - DateTime::Locale::ku_IR undef - DateTime::Locale::ku_Latn undef - DateTime::Locale::ku_Latn_TR undef - DateTime::Locale::ku_SY undef - DateTime::Locale::ku_TR undef - DateTime::Locale::kw undef - DateTime::Locale::kw_GB undef - DateTime::Locale::ky undef - DateTime::Locale::ky_KG undef - DateTime::Locale::ln undef - DateTime::Locale::ln_CD undef - DateTime::Locale::ln_CG undef - DateTime::Locale::lo undef - DateTime::Locale::lo_LA undef - DateTime::Locale::lt undef - DateTime::Locale::lt_LT undef - DateTime::Locale::lv undef - DateTime::Locale::lv_LV undef - DateTime::Locale::mk undef - DateTime::Locale::mk_MK undef - DateTime::Locale::ml undef - DateTime::Locale::ml_IN undef - DateTime::Locale::mn undef - DateTime::Locale::mn_CN undef - DateTime::Locale::mn_Cyrl undef - DateTime::Locale::mn_Cyrl_MN undef - DateTime::Locale::mn_MN undef - DateTime::Locale::mn_Mong undef - DateTime::Locale::mn_Mong_CN undef - DateTime::Locale::mo undef - DateTime::Locale::mr undef - DateTime::Locale::mr_IN undef - DateTime::Locale::ms undef - DateTime::Locale::ms_BN undef - DateTime::Locale::ms_MY undef - DateTime::Locale::mt undef - DateTime::Locale::mt_MT undef - DateTime::Locale::my undef - DateTime::Locale::my_MM undef - DateTime::Locale::nb undef - DateTime::Locale::nb_NO undef - DateTime::Locale::nds undef - DateTime::Locale::nds_DE undef - DateTime::Locale::ne undef - DateTime::Locale::ne_IN undef - DateTime::Locale::ne_NP undef - DateTime::Locale::nl undef - DateTime::Locale::nl_BE undef - DateTime::Locale::nl_NL undef - DateTime::Locale::nn undef - DateTime::Locale::nn_NO undef - DateTime::Locale::no undef - DateTime::Locale::nr undef - DateTime::Locale::nr_ZA undef - DateTime::Locale::nso undef - DateTime::Locale::nso_ZA undef - DateTime::Locale::ny undef - DateTime::Locale::ny_MW undef - DateTime::Locale::oc undef - DateTime::Locale::oc_FR undef - DateTime::Locale::om undef - DateTime::Locale::om_ET undef - DateTime::Locale::om_KE undef - DateTime::Locale::or undef - DateTime::Locale::or_IN undef - DateTime::Locale::pa undef - DateTime::Locale::pa_Arab undef - DateTime::Locale::pa_Arab_PK undef - DateTime::Locale::pa_Guru undef - DateTime::Locale::pa_Guru_IN undef - DateTime::Locale::pa_IN undef - DateTime::Locale::pa_PK undef - DateTime::Locale::pl undef - DateTime::Locale::pl_PL undef - DateTime::Locale::ps undef - DateTime::Locale::ps_AF undef - DateTime::Locale::pt undef - DateTime::Locale::pt_BR undef - DateTime::Locale::pt_PT undef - DateTime::Locale::ro undef - DateTime::Locale::ro_MD undef - DateTime::Locale::ro_RO undef - DateTime::Locale::root undef - DateTime::Locale::ru undef - DateTime::Locale::ru_RU undef - DateTime::Locale::ru_UA undef - DateTime::Locale::rw undef - DateTime::Locale::rw_RW undef - DateTime::Locale::sa undef - DateTime::Locale::sa_IN undef - DateTime::Locale::se undef - DateTime::Locale::se_FI undef - DateTime::Locale::se_NO undef - DateTime::Locale::sh undef - DateTime::Locale::sh_BA undef - DateTime::Locale::sh_CS undef - DateTime::Locale::sh_YU undef - DateTime::Locale::si undef - DateTime::Locale::si_LK undef - DateTime::Locale::sid undef - DateTime::Locale::sid_ET undef - DateTime::Locale::sk undef - DateTime::Locale::sk_SK undef - DateTime::Locale::sl undef - DateTime::Locale::sl_SI undef - DateTime::Locale::so undef - DateTime::Locale::so_DJ undef - DateTime::Locale::so_ET undef - DateTime::Locale::so_KE undef - DateTime::Locale::so_SO undef - DateTime::Locale::sq undef - DateTime::Locale::sq_AL undef - DateTime::Locale::sr undef - DateTime::Locale::sr_BA undef - DateTime::Locale::sr_CS undef - DateTime::Locale::sr_Cyrl undef - DateTime::Locale::sr_Cyrl_BA undef - DateTime::Locale::sr_Cyrl_CS undef - DateTime::Locale::sr_Cyrl_ME undef - DateTime::Locale::sr_Cyrl_RS undef - DateTime::Locale::sr_Cyrl_YU undef - DateTime::Locale::sr_Latn undef - DateTime::Locale::sr_Latn_BA undef - DateTime::Locale::sr_Latn_CS undef - DateTime::Locale::sr_Latn_ME undef - DateTime::Locale::sr_Latn_RS undef - DateTime::Locale::sr_Latn_YU undef - DateTime::Locale::sr_ME undef - DateTime::Locale::sr_RS undef - DateTime::Locale::sr_YU undef - DateTime::Locale::ss undef - DateTime::Locale::ss_SZ undef - DateTime::Locale::ss_ZA undef - DateTime::Locale::st undef - DateTime::Locale::st_LS undef - DateTime::Locale::st_ZA undef - DateTime::Locale::sv undef - DateTime::Locale::sv_FI undef - DateTime::Locale::sv_SE undef - DateTime::Locale::sw undef - DateTime::Locale::sw_KE undef - DateTime::Locale::sw_TZ undef - DateTime::Locale::syr undef - DateTime::Locale::syr_SY undef - DateTime::Locale::ta undef - DateTime::Locale::ta_IN undef - DateTime::Locale::te undef - DateTime::Locale::te_IN undef - DateTime::Locale::tg undef - DateTime::Locale::tg_Cyrl undef - DateTime::Locale::tg_Cyrl_TJ undef - DateTime::Locale::tg_TJ undef - DateTime::Locale::th undef - DateTime::Locale::th_TH undef - DateTime::Locale::ti undef - DateTime::Locale::ti_ER undef - DateTime::Locale::ti_ET undef - DateTime::Locale::tig undef - DateTime::Locale::tig_ER undef - DateTime::Locale::tl undef - DateTime::Locale::tn undef - DateTime::Locale::tn_ZA undef - DateTime::Locale::to undef - DateTime::Locale::to_TO undef - DateTime::Locale::tr undef - DateTime::Locale::tr_TR undef - DateTime::Locale::trv undef - DateTime::Locale::trv_TW undef - DateTime::Locale::ts undef - DateTime::Locale::ts_ZA undef - DateTime::Locale::tt undef - DateTime::Locale::tt_RU undef - DateTime::Locale::ug undef - DateTime::Locale::ug_Arab undef - DateTime::Locale::ug_Arab_CN undef - DateTime::Locale::ug_CN undef - DateTime::Locale::uk undef - DateTime::Locale::uk_UA undef - DateTime::Locale::ur undef - DateTime::Locale::ur_IN undef - DateTime::Locale::ur_PK undef - DateTime::Locale::uz undef - DateTime::Locale::uz_AF undef - DateTime::Locale::uz_Arab undef - DateTime::Locale::uz_Arab_AF undef - DateTime::Locale::uz_Cyrl undef - DateTime::Locale::uz_Cyrl_UZ undef - DateTime::Locale::uz_Latn undef - DateTime::Locale::uz_Latn_UZ undef - DateTime::Locale::uz_UZ undef - DateTime::Locale::ve undef - DateTime::Locale::ve_ZA undef - DateTime::Locale::vi undef - DateTime::Locale::vi_VN undef - DateTime::Locale::wal undef - DateTime::Locale::wal_ET undef - DateTime::Locale::wo undef - DateTime::Locale::wo_Latn undef - DateTime::Locale::wo_Latn_SN undef - DateTime::Locale::wo_SN undef - DateTime::Locale::xh undef - DateTime::Locale::xh_ZA undef - DateTime::Locale::yo undef - DateTime::Locale::yo_NG undef - DateTime::Locale::zh undef - DateTime::Locale::zh_CN undef - DateTime::Locale::zh_HK undef - DateTime::Locale::zh_Hans undef - DateTime::Locale::zh_Hans_CN undef - DateTime::Locale::zh_Hans_HK undef - DateTime::Locale::zh_Hans_MO undef - DateTime::Locale::zh_Hans_SG undef - DateTime::Locale::zh_Hant undef - DateTime::Locale::zh_Hant_HK undef - DateTime::Locale::zh_Hant_MO undef - DateTime::Locale::zh_Hant_TW undef - DateTime::Locale::zh_MO undef - DateTime::Locale::zh_SG undef - DateTime::Locale::zh_TW undef - DateTime::Locale::zu undef - DateTime::Locale::zu_ZA undef + warnings 0 + DateTime-Locale-1.45 + pathname: D/DR/DROLSKY/DateTime-Locale-1.45.tar.gz + provides: + DateTime::Locale 1.45 + DateTime::Locale::Base 1.45 + DateTime::Locale::Catalog 1.45 + DateTime::Locale::Data 1.45 + DateTime::Locale::FromData 1.45 + DateTime::Locale::Util 1.45 requirements: - List::MoreUtils 0 - Module::Build 0 - Params::Validate 0.91 - perl 5.006 - DateTime-TimeZone-1.70 - pathname: D/DR/DROLSKY/DateTime-TimeZone-1.70.tar.gz - provides: - DateTime::TimeZone 1.70 - DateTime::TimeZone::Africa::Abidjan 1.70 - DateTime::TimeZone::Africa::Accra 1.70 - DateTime::TimeZone::Africa::Addis_Ababa 1.70 - DateTime::TimeZone::Africa::Algiers 1.70 - DateTime::TimeZone::Africa::Asmara 1.70 - DateTime::TimeZone::Africa::Bamako 1.70 - DateTime::TimeZone::Africa::Bangui 1.70 - DateTime::TimeZone::Africa::Banjul 1.70 - DateTime::TimeZone::Africa::Bissau 1.70 - DateTime::TimeZone::Africa::Blantyre 1.70 - DateTime::TimeZone::Africa::Brazzaville 1.70 - DateTime::TimeZone::Africa::Bujumbura 1.70 - DateTime::TimeZone::Africa::Cairo 1.70 - DateTime::TimeZone::Africa::Casablanca 1.70 - DateTime::TimeZone::Africa::Ceuta 1.70 - DateTime::TimeZone::Africa::Conakry 1.70 - DateTime::TimeZone::Africa::Dakar 1.70 - DateTime::TimeZone::Africa::Dar_es_Salaam 1.70 - DateTime::TimeZone::Africa::Djibouti 1.70 - DateTime::TimeZone::Africa::Douala 1.70 - DateTime::TimeZone::Africa::El_Aaiun 1.70 - DateTime::TimeZone::Africa::Freetown 1.70 - DateTime::TimeZone::Africa::Gaborone 1.70 - DateTime::TimeZone::Africa::Harare 1.70 - DateTime::TimeZone::Africa::Johannesburg 1.70 - DateTime::TimeZone::Africa::Kampala 1.70 - DateTime::TimeZone::Africa::Khartoum 1.70 - DateTime::TimeZone::Africa::Kigali 1.70 - DateTime::TimeZone::Africa::Kinshasa 1.70 - DateTime::TimeZone::Africa::Lagos 1.70 - DateTime::TimeZone::Africa::Libreville 1.70 - DateTime::TimeZone::Africa::Lome 1.70 - DateTime::TimeZone::Africa::Luanda 1.70 - DateTime::TimeZone::Africa::Lubumbashi 1.70 - DateTime::TimeZone::Africa::Lusaka 1.70 - DateTime::TimeZone::Africa::Malabo 1.70 - DateTime::TimeZone::Africa::Maputo 1.70 - DateTime::TimeZone::Africa::Maseru 1.70 - DateTime::TimeZone::Africa::Mbabane 1.70 - DateTime::TimeZone::Africa::Mogadishu 1.70 - DateTime::TimeZone::Africa::Monrovia 1.70 - DateTime::TimeZone::Africa::Nairobi 1.70 - DateTime::TimeZone::Africa::Ndjamena 1.70 - DateTime::TimeZone::Africa::Niamey 1.70 - DateTime::TimeZone::Africa::Nouakchott 1.70 - DateTime::TimeZone::Africa::Ouagadougou 1.70 - DateTime::TimeZone::Africa::Porto_Novo 1.70 - DateTime::TimeZone::Africa::Sao_Tome 1.70 - DateTime::TimeZone::Africa::Tripoli 1.70 - DateTime::TimeZone::Africa::Tunis 1.70 - DateTime::TimeZone::Africa::Windhoek 1.70 - DateTime::TimeZone::America::Adak 1.70 - DateTime::TimeZone::America::Anchorage 1.70 - DateTime::TimeZone::America::Antigua 1.70 - DateTime::TimeZone::America::Araguaina 1.70 - DateTime::TimeZone::America::Argentina::Buenos_Aires 1.70 - DateTime::TimeZone::America::Argentina::Catamarca 1.70 - DateTime::TimeZone::America::Argentina::Cordoba 1.70 - DateTime::TimeZone::America::Argentina::Jujuy 1.70 - DateTime::TimeZone::America::Argentina::La_Rioja 1.70 - DateTime::TimeZone::America::Argentina::Mendoza 1.70 - DateTime::TimeZone::America::Argentina::Rio_Gallegos 1.70 - DateTime::TimeZone::America::Argentina::Salta 1.70 - DateTime::TimeZone::America::Argentina::San_Juan 1.70 - DateTime::TimeZone::America::Argentina::San_Luis 1.70 - DateTime::TimeZone::America::Argentina::Tucuman 1.70 - DateTime::TimeZone::America::Argentina::Ushuaia 1.70 - DateTime::TimeZone::America::Asuncion 1.70 - DateTime::TimeZone::America::Atikokan 1.70 - DateTime::TimeZone::America::Bahia 1.70 - DateTime::TimeZone::America::Bahia_Banderas 1.70 - DateTime::TimeZone::America::Barbados 1.70 - DateTime::TimeZone::America::Belem 1.70 - DateTime::TimeZone::America::Belize 1.70 - DateTime::TimeZone::America::Blanc_Sablon 1.70 - DateTime::TimeZone::America::Boa_Vista 1.70 - DateTime::TimeZone::America::Bogota 1.70 - DateTime::TimeZone::America::Boise 1.70 - DateTime::TimeZone::America::Cambridge_Bay 1.70 - DateTime::TimeZone::America::Campo_Grande 1.70 - DateTime::TimeZone::America::Cancun 1.70 - DateTime::TimeZone::America::Caracas 1.70 - DateTime::TimeZone::America::Cayenne 1.70 - DateTime::TimeZone::America::Cayman 1.70 - DateTime::TimeZone::America::Chicago 1.70 - DateTime::TimeZone::America::Chihuahua 1.70 - DateTime::TimeZone::America::Costa_Rica 1.70 - DateTime::TimeZone::America::Creston 1.70 - DateTime::TimeZone::America::Cuiaba 1.70 - DateTime::TimeZone::America::Curacao 1.70 - DateTime::TimeZone::America::Danmarkshavn 1.70 - DateTime::TimeZone::America::Dawson 1.70 - DateTime::TimeZone::America::Dawson_Creek 1.70 - DateTime::TimeZone::America::Denver 1.70 - DateTime::TimeZone::America::Detroit 1.70 - DateTime::TimeZone::America::Edmonton 1.70 - DateTime::TimeZone::America::Eirunepe 1.70 - DateTime::TimeZone::America::El_Salvador 1.70 - DateTime::TimeZone::America::Fortaleza 1.70 - DateTime::TimeZone::America::Glace_Bay 1.70 - DateTime::TimeZone::America::Godthab 1.70 - DateTime::TimeZone::America::Goose_Bay 1.70 - DateTime::TimeZone::America::Grand_Turk 1.70 - DateTime::TimeZone::America::Guatemala 1.70 - DateTime::TimeZone::America::Guayaquil 1.70 - DateTime::TimeZone::America::Guyana 1.70 - DateTime::TimeZone::America::Halifax 1.70 - DateTime::TimeZone::America::Havana 1.70 - DateTime::TimeZone::America::Hermosillo 1.70 - DateTime::TimeZone::America::Indiana::Indianapolis 1.70 - DateTime::TimeZone::America::Indiana::Knox 1.70 - DateTime::TimeZone::America::Indiana::Marengo 1.70 - DateTime::TimeZone::America::Indiana::Petersburg 1.70 - DateTime::TimeZone::America::Indiana::Tell_City 1.70 - DateTime::TimeZone::America::Indiana::Vevay 1.70 - DateTime::TimeZone::America::Indiana::Vincennes 1.70 - DateTime::TimeZone::America::Indiana::Winamac 1.70 - DateTime::TimeZone::America::Inuvik 1.70 - DateTime::TimeZone::America::Iqaluit 1.70 - DateTime::TimeZone::America::Jamaica 1.70 - DateTime::TimeZone::America::Juneau 1.70 - DateTime::TimeZone::America::Kentucky::Louisville 1.70 - DateTime::TimeZone::America::Kentucky::Monticello 1.70 - DateTime::TimeZone::America::La_Paz 1.70 - DateTime::TimeZone::America::Lima 1.70 - DateTime::TimeZone::America::Los_Angeles 1.70 - DateTime::TimeZone::America::Maceio 1.70 - DateTime::TimeZone::America::Managua 1.70 - DateTime::TimeZone::America::Manaus 1.70 - DateTime::TimeZone::America::Martinique 1.70 - DateTime::TimeZone::America::Matamoros 1.70 - DateTime::TimeZone::America::Mazatlan 1.70 - DateTime::TimeZone::America::Menominee 1.70 - DateTime::TimeZone::America::Merida 1.70 - DateTime::TimeZone::America::Metlakatla 1.70 - DateTime::TimeZone::America::Mexico_City 1.70 - DateTime::TimeZone::America::Miquelon 1.70 - DateTime::TimeZone::America::Moncton 1.70 - DateTime::TimeZone::America::Monterrey 1.70 - DateTime::TimeZone::America::Montevideo 1.70 - DateTime::TimeZone::America::Montreal 1.70 - DateTime::TimeZone::America::Nassau 1.70 - DateTime::TimeZone::America::New_York 1.70 - DateTime::TimeZone::America::Nipigon 1.70 - DateTime::TimeZone::America::Nome 1.70 - DateTime::TimeZone::America::Noronha 1.70 - DateTime::TimeZone::America::North_Dakota::Beulah 1.70 - DateTime::TimeZone::America::North_Dakota::Center 1.70 - DateTime::TimeZone::America::North_Dakota::New_Salem 1.70 - DateTime::TimeZone::America::Ojinaga 1.70 - DateTime::TimeZone::America::Panama 1.70 - DateTime::TimeZone::America::Pangnirtung 1.70 - DateTime::TimeZone::America::Paramaribo 1.70 - DateTime::TimeZone::America::Phoenix 1.70 - DateTime::TimeZone::America::Port_au_Prince 1.70 - DateTime::TimeZone::America::Port_of_Spain 1.70 - DateTime::TimeZone::America::Porto_Velho 1.70 - DateTime::TimeZone::America::Puerto_Rico 1.70 - DateTime::TimeZone::America::Rainy_River 1.70 - DateTime::TimeZone::America::Rankin_Inlet 1.70 - DateTime::TimeZone::America::Recife 1.70 - DateTime::TimeZone::America::Regina 1.70 - DateTime::TimeZone::America::Resolute 1.70 - DateTime::TimeZone::America::Rio_Branco 1.70 - DateTime::TimeZone::America::Santa_Isabel 1.70 - DateTime::TimeZone::America::Santarem 1.70 - DateTime::TimeZone::America::Santiago 1.70 - DateTime::TimeZone::America::Santo_Domingo 1.70 - DateTime::TimeZone::America::Sao_Paulo 1.70 - DateTime::TimeZone::America::Scoresbysund 1.70 - DateTime::TimeZone::America::Sitka 1.70 - DateTime::TimeZone::America::St_Johns 1.70 - DateTime::TimeZone::America::Swift_Current 1.70 - DateTime::TimeZone::America::Tegucigalpa 1.70 - DateTime::TimeZone::America::Thule 1.70 - DateTime::TimeZone::America::Thunder_Bay 1.70 - DateTime::TimeZone::America::Tijuana 1.70 - DateTime::TimeZone::America::Toronto 1.70 - DateTime::TimeZone::America::Vancouver 1.70 - DateTime::TimeZone::America::Whitehorse 1.70 - DateTime::TimeZone::America::Winnipeg 1.70 - DateTime::TimeZone::America::Yakutat 1.70 - DateTime::TimeZone::America::Yellowknife 1.70 - DateTime::TimeZone::Antarctica::Casey 1.70 - DateTime::TimeZone::Antarctica::Davis 1.70 - DateTime::TimeZone::Antarctica::DumontDUrville 1.70 - DateTime::TimeZone::Antarctica::Macquarie 1.70 - DateTime::TimeZone::Antarctica::Mawson 1.70 - DateTime::TimeZone::Antarctica::Palmer 1.70 - DateTime::TimeZone::Antarctica::Rothera 1.70 - DateTime::TimeZone::Antarctica::Syowa 1.70 - DateTime::TimeZone::Antarctica::Troll 1.70 - DateTime::TimeZone::Antarctica::Vostok 1.70 - DateTime::TimeZone::Asia::Aden 1.70 - DateTime::TimeZone::Asia::Almaty 1.70 - DateTime::TimeZone::Asia::Amman 1.70 - DateTime::TimeZone::Asia::Anadyr 1.70 - DateTime::TimeZone::Asia::Aqtau 1.70 - DateTime::TimeZone::Asia::Aqtobe 1.70 - DateTime::TimeZone::Asia::Ashgabat 1.70 - DateTime::TimeZone::Asia::Baghdad 1.70 - DateTime::TimeZone::Asia::Bahrain 1.70 - DateTime::TimeZone::Asia::Baku 1.70 - DateTime::TimeZone::Asia::Bangkok 1.70 - DateTime::TimeZone::Asia::Beirut 1.70 - DateTime::TimeZone::Asia::Bishkek 1.70 - DateTime::TimeZone::Asia::Brunei 1.70 - DateTime::TimeZone::Asia::Choibalsan 1.70 - DateTime::TimeZone::Asia::Chongqing 1.70 - DateTime::TimeZone::Asia::Colombo 1.70 - DateTime::TimeZone::Asia::Damascus 1.70 - DateTime::TimeZone::Asia::Dhaka 1.70 - DateTime::TimeZone::Asia::Dili 1.70 - DateTime::TimeZone::Asia::Dubai 1.70 - DateTime::TimeZone::Asia::Dushanbe 1.70 - DateTime::TimeZone::Asia::Gaza 1.70 - DateTime::TimeZone::Asia::Harbin 1.70 - DateTime::TimeZone::Asia::Hebron 1.70 - DateTime::TimeZone::Asia::Ho_Chi_Minh 1.70 - DateTime::TimeZone::Asia::Hong_Kong 1.70 - DateTime::TimeZone::Asia::Hovd 1.70 - DateTime::TimeZone::Asia::Irkutsk 1.70 - DateTime::TimeZone::Asia::Jakarta 1.70 - DateTime::TimeZone::Asia::Jayapura 1.70 - DateTime::TimeZone::Asia::Jerusalem 1.70 - DateTime::TimeZone::Asia::Kabul 1.70 - DateTime::TimeZone::Asia::Kamchatka 1.70 - DateTime::TimeZone::Asia::Karachi 1.70 - DateTime::TimeZone::Asia::Kashgar 1.70 - DateTime::TimeZone::Asia::Kathmandu 1.70 - DateTime::TimeZone::Asia::Khandyga 1.70 - DateTime::TimeZone::Asia::Kolkata 1.70 - DateTime::TimeZone::Asia::Krasnoyarsk 1.70 - DateTime::TimeZone::Asia::Kuala_Lumpur 1.70 - DateTime::TimeZone::Asia::Kuching 1.70 - DateTime::TimeZone::Asia::Kuwait 1.70 - DateTime::TimeZone::Asia::Macau 1.70 - DateTime::TimeZone::Asia::Magadan 1.70 - DateTime::TimeZone::Asia::Makassar 1.70 - DateTime::TimeZone::Asia::Manila 1.70 - DateTime::TimeZone::Asia::Muscat 1.70 - DateTime::TimeZone::Asia::Nicosia 1.70 - DateTime::TimeZone::Asia::Novokuznetsk 1.70 - DateTime::TimeZone::Asia::Novosibirsk 1.70 - DateTime::TimeZone::Asia::Omsk 1.70 - DateTime::TimeZone::Asia::Oral 1.70 - DateTime::TimeZone::Asia::Phnom_Penh 1.70 - DateTime::TimeZone::Asia::Pontianak 1.70 - DateTime::TimeZone::Asia::Pyongyang 1.70 - DateTime::TimeZone::Asia::Qatar 1.70 - DateTime::TimeZone::Asia::Qyzylorda 1.70 - DateTime::TimeZone::Asia::Rangoon 1.70 - DateTime::TimeZone::Asia::Riyadh 1.70 - DateTime::TimeZone::Asia::Sakhalin 1.70 - DateTime::TimeZone::Asia::Samarkand 1.70 - DateTime::TimeZone::Asia::Seoul 1.70 - DateTime::TimeZone::Asia::Shanghai 1.70 - DateTime::TimeZone::Asia::Singapore 1.70 - DateTime::TimeZone::Asia::Taipei 1.70 - DateTime::TimeZone::Asia::Tashkent 1.70 - DateTime::TimeZone::Asia::Tbilisi 1.70 - DateTime::TimeZone::Asia::Tehran 1.70 - DateTime::TimeZone::Asia::Thimphu 1.70 - DateTime::TimeZone::Asia::Tokyo 1.70 - DateTime::TimeZone::Asia::Ulaanbaatar 1.70 - DateTime::TimeZone::Asia::Urumqi 1.70 - DateTime::TimeZone::Asia::Ust_Nera 1.70 - DateTime::TimeZone::Asia::Vientiane 1.70 - DateTime::TimeZone::Asia::Vladivostok 1.70 - DateTime::TimeZone::Asia::Yakutsk 1.70 - DateTime::TimeZone::Asia::Yekaterinburg 1.70 - DateTime::TimeZone::Asia::Yerevan 1.70 - DateTime::TimeZone::Atlantic::Azores 1.70 - DateTime::TimeZone::Atlantic::Bermuda 1.70 - DateTime::TimeZone::Atlantic::Canary 1.70 - DateTime::TimeZone::Atlantic::Cape_Verde 1.70 - DateTime::TimeZone::Atlantic::Faroe 1.70 - DateTime::TimeZone::Atlantic::Madeira 1.70 - DateTime::TimeZone::Atlantic::Reykjavik 1.70 - DateTime::TimeZone::Atlantic::South_Georgia 1.70 - DateTime::TimeZone::Atlantic::St_Helena 1.70 - DateTime::TimeZone::Atlantic::Stanley 1.70 - DateTime::TimeZone::Australia::Adelaide 1.70 - DateTime::TimeZone::Australia::Brisbane 1.70 - DateTime::TimeZone::Australia::Broken_Hill 1.70 - DateTime::TimeZone::Australia::Currie 1.70 - DateTime::TimeZone::Australia::Darwin 1.70 - DateTime::TimeZone::Australia::Eucla 1.70 - DateTime::TimeZone::Australia::Hobart 1.70 - DateTime::TimeZone::Australia::Lindeman 1.70 - DateTime::TimeZone::Australia::Lord_Howe 1.70 - DateTime::TimeZone::Australia::Melbourne 1.70 - DateTime::TimeZone::Australia::Perth 1.70 - DateTime::TimeZone::Australia::Sydney 1.70 - DateTime::TimeZone::CET 1.70 - DateTime::TimeZone::CST6CDT 1.70 - DateTime::TimeZone::Catalog 1.70 - DateTime::TimeZone::EET 1.70 - DateTime::TimeZone::EST 1.70 - DateTime::TimeZone::EST5EDT 1.70 - DateTime::TimeZone::Europe::Amsterdam 1.70 - DateTime::TimeZone::Europe::Andorra 1.70 - DateTime::TimeZone::Europe::Athens 1.70 - DateTime::TimeZone::Europe::Belgrade 1.70 - DateTime::TimeZone::Europe::Berlin 1.70 - DateTime::TimeZone::Europe::Brussels 1.70 - DateTime::TimeZone::Europe::Bucharest 1.70 - DateTime::TimeZone::Europe::Budapest 1.70 - DateTime::TimeZone::Europe::Chisinau 1.70 - DateTime::TimeZone::Europe::Copenhagen 1.70 - DateTime::TimeZone::Europe::Dublin 1.70 - DateTime::TimeZone::Europe::Gibraltar 1.70 - DateTime::TimeZone::Europe::Helsinki 1.70 - DateTime::TimeZone::Europe::Istanbul 1.70 - DateTime::TimeZone::Europe::Kaliningrad 1.70 - DateTime::TimeZone::Europe::Kiev 1.70 - DateTime::TimeZone::Europe::Lisbon 1.70 - DateTime::TimeZone::Europe::London 1.70 - DateTime::TimeZone::Europe::Luxembourg 1.70 - DateTime::TimeZone::Europe::Madrid 1.70 - DateTime::TimeZone::Europe::Malta 1.70 - DateTime::TimeZone::Europe::Minsk 1.70 - DateTime::TimeZone::Europe::Monaco 1.70 - DateTime::TimeZone::Europe::Moscow 1.70 - DateTime::TimeZone::Europe::Oslo 1.70 - DateTime::TimeZone::Europe::Paris 1.70 - DateTime::TimeZone::Europe::Prague 1.70 - DateTime::TimeZone::Europe::Riga 1.70 - DateTime::TimeZone::Europe::Rome 1.70 - DateTime::TimeZone::Europe::Samara 1.70 - DateTime::TimeZone::Europe::Simferopol 1.70 - DateTime::TimeZone::Europe::Sofia 1.70 - DateTime::TimeZone::Europe::Stockholm 1.70 - DateTime::TimeZone::Europe::Tallinn 1.70 - DateTime::TimeZone::Europe::Tirane 1.70 - DateTime::TimeZone::Europe::Uzhgorod 1.70 - DateTime::TimeZone::Europe::Vienna 1.70 - DateTime::TimeZone::Europe::Vilnius 1.70 - DateTime::TimeZone::Europe::Volgograd 1.70 - DateTime::TimeZone::Europe::Warsaw 1.70 - DateTime::TimeZone::Europe::Zaporozhye 1.70 - DateTime::TimeZone::Europe::Zurich 1.70 - DateTime::TimeZone::Floating 1.70 - DateTime::TimeZone::HST 1.70 - DateTime::TimeZone::Indian::Antananarivo 1.70 - DateTime::TimeZone::Indian::Chagos 1.70 - DateTime::TimeZone::Indian::Christmas 1.70 - DateTime::TimeZone::Indian::Cocos 1.70 - DateTime::TimeZone::Indian::Comoro 1.70 - DateTime::TimeZone::Indian::Kerguelen 1.70 - DateTime::TimeZone::Indian::Mahe 1.70 - DateTime::TimeZone::Indian::Maldives 1.70 - DateTime::TimeZone::Indian::Mauritius 1.70 - DateTime::TimeZone::Indian::Mayotte 1.70 - DateTime::TimeZone::Indian::Reunion 1.70 - DateTime::TimeZone::Local 1.70 - DateTime::TimeZone::Local::Unix 1.70 - DateTime::TimeZone::Local::VMS 1.70 - DateTime::TimeZone::Local::Win32 1.70 - DateTime::TimeZone::MET 1.70 - DateTime::TimeZone::MST 1.70 - DateTime::TimeZone::MST7MDT 1.70 - DateTime::TimeZone::OffsetOnly 1.70 - DateTime::TimeZone::OlsonDB 1.70 - DateTime::TimeZone::OlsonDB::Change 1.70 - DateTime::TimeZone::OlsonDB::Observance 1.70 - DateTime::TimeZone::OlsonDB::Rule 1.70 - DateTime::TimeZone::OlsonDB::Zone 1.70 - DateTime::TimeZone::PST8PDT 1.70 - DateTime::TimeZone::Pacific::Apia 1.70 - DateTime::TimeZone::Pacific::Auckland 1.70 - DateTime::TimeZone::Pacific::Chatham 1.70 - DateTime::TimeZone::Pacific::Chuuk 1.70 - DateTime::TimeZone::Pacific::Easter 1.70 - DateTime::TimeZone::Pacific::Efate 1.70 - DateTime::TimeZone::Pacific::Enderbury 1.70 - DateTime::TimeZone::Pacific::Fakaofo 1.70 - DateTime::TimeZone::Pacific::Fiji 1.70 - DateTime::TimeZone::Pacific::Funafuti 1.70 - DateTime::TimeZone::Pacific::Galapagos 1.70 - DateTime::TimeZone::Pacific::Gambier 1.70 - DateTime::TimeZone::Pacific::Guadalcanal 1.70 - DateTime::TimeZone::Pacific::Guam 1.70 - DateTime::TimeZone::Pacific::Honolulu 1.70 - DateTime::TimeZone::Pacific::Kiritimati 1.70 - DateTime::TimeZone::Pacific::Kosrae 1.70 - DateTime::TimeZone::Pacific::Kwajalein 1.70 - DateTime::TimeZone::Pacific::Majuro 1.70 - DateTime::TimeZone::Pacific::Marquesas 1.70 - DateTime::TimeZone::Pacific::Midway 1.70 - DateTime::TimeZone::Pacific::Nauru 1.70 - DateTime::TimeZone::Pacific::Niue 1.70 - DateTime::TimeZone::Pacific::Norfolk 1.70 - DateTime::TimeZone::Pacific::Noumea 1.70 - DateTime::TimeZone::Pacific::Pago_Pago 1.70 - DateTime::TimeZone::Pacific::Palau 1.70 - DateTime::TimeZone::Pacific::Pitcairn 1.70 - DateTime::TimeZone::Pacific::Pohnpei 1.70 - DateTime::TimeZone::Pacific::Port_Moresby 1.70 - DateTime::TimeZone::Pacific::Rarotonga 1.70 - DateTime::TimeZone::Pacific::Saipan 1.70 - DateTime::TimeZone::Pacific::Tahiti 1.70 - DateTime::TimeZone::Pacific::Tarawa 1.70 - DateTime::TimeZone::Pacific::Tongatapu 1.70 - DateTime::TimeZone::Pacific::Wake 1.70 - DateTime::TimeZone::Pacific::Wallis 1.70 - DateTime::TimeZone::UTC 1.70 - DateTime::TimeZone::WET 1.70 + Carp 0 + Dist::CheckConflicts 0.02 + Exporter 0 + ExtUtils::MakeMaker 0 + File::ShareDir 0 + File::ShareDir::Install 0.06 + File::Spec 0 + List::Util 1.45 + Params::ValidationCompiler 0.13 + Specio::Declare 0 + Specio::Library::String 0 + Storable 0 + namespace::autoclean 0.19 + perl 5.008004 + strict 0 + warnings 0 + DateTime-TimeZone-2.65 + pathname: D/DR/DROLSKY/DateTime-TimeZone-2.65.tar.gz + provides: + DateTime::TimeZone 2.65 + DateTime::TimeZone::Africa::Abidjan 2.65 + DateTime::TimeZone::Africa::Algiers 2.65 + DateTime::TimeZone::Africa::Bissau 2.65 + DateTime::TimeZone::Africa::Cairo 2.65 + DateTime::TimeZone::Africa::Casablanca 2.65 + DateTime::TimeZone::Africa::Ceuta 2.65 + DateTime::TimeZone::Africa::El_Aaiun 2.65 + DateTime::TimeZone::Africa::Johannesburg 2.65 + DateTime::TimeZone::Africa::Juba 2.65 + DateTime::TimeZone::Africa::Khartoum 2.65 + DateTime::TimeZone::Africa::Lagos 2.65 + DateTime::TimeZone::Africa::Maputo 2.65 + DateTime::TimeZone::Africa::Monrovia 2.65 + DateTime::TimeZone::Africa::Nairobi 2.65 + DateTime::TimeZone::Africa::Ndjamena 2.65 + DateTime::TimeZone::Africa::Sao_Tome 2.65 + DateTime::TimeZone::Africa::Tripoli 2.65 + DateTime::TimeZone::Africa::Tunis 2.65 + DateTime::TimeZone::Africa::Windhoek 2.65 + DateTime::TimeZone::America::Adak 2.65 + DateTime::TimeZone::America::Anchorage 2.65 + DateTime::TimeZone::America::Araguaina 2.65 + DateTime::TimeZone::America::Argentina::Buenos_Aires 2.65 + DateTime::TimeZone::America::Argentina::Catamarca 2.65 + DateTime::TimeZone::America::Argentina::Cordoba 2.65 + DateTime::TimeZone::America::Argentina::Jujuy 2.65 + DateTime::TimeZone::America::Argentina::La_Rioja 2.65 + DateTime::TimeZone::America::Argentina::Mendoza 2.65 + DateTime::TimeZone::America::Argentina::Rio_Gallegos 2.65 + DateTime::TimeZone::America::Argentina::Salta 2.65 + DateTime::TimeZone::America::Argentina::San_Juan 2.65 + DateTime::TimeZone::America::Argentina::San_Luis 2.65 + DateTime::TimeZone::America::Argentina::Tucuman 2.65 + DateTime::TimeZone::America::Argentina::Ushuaia 2.65 + DateTime::TimeZone::America::Asuncion 2.65 + DateTime::TimeZone::America::Bahia 2.65 + DateTime::TimeZone::America::Bahia_Banderas 2.65 + DateTime::TimeZone::America::Barbados 2.65 + DateTime::TimeZone::America::Belem 2.65 + DateTime::TimeZone::America::Belize 2.65 + DateTime::TimeZone::America::Boa_Vista 2.65 + DateTime::TimeZone::America::Bogota 2.65 + DateTime::TimeZone::America::Boise 2.65 + DateTime::TimeZone::America::Cambridge_Bay 2.65 + DateTime::TimeZone::America::Campo_Grande 2.65 + DateTime::TimeZone::America::Cancun 2.65 + DateTime::TimeZone::America::Caracas 2.65 + DateTime::TimeZone::America::Cayenne 2.65 + DateTime::TimeZone::America::Chicago 2.65 + DateTime::TimeZone::America::Chihuahua 2.65 + DateTime::TimeZone::America::Ciudad_Juarez 2.65 + DateTime::TimeZone::America::Costa_Rica 2.65 + DateTime::TimeZone::America::Coyhaique 2.65 + DateTime::TimeZone::America::Cuiaba 2.65 + DateTime::TimeZone::America::Danmarkshavn 2.65 + DateTime::TimeZone::America::Dawson 2.65 + DateTime::TimeZone::America::Dawson_Creek 2.65 + DateTime::TimeZone::America::Denver 2.65 + DateTime::TimeZone::America::Detroit 2.65 + DateTime::TimeZone::America::Edmonton 2.65 + DateTime::TimeZone::America::Eirunepe 2.65 + DateTime::TimeZone::America::El_Salvador 2.65 + DateTime::TimeZone::America::Fort_Nelson 2.65 + DateTime::TimeZone::America::Fortaleza 2.65 + DateTime::TimeZone::America::Glace_Bay 2.65 + DateTime::TimeZone::America::Goose_Bay 2.65 + DateTime::TimeZone::America::Grand_Turk 2.65 + DateTime::TimeZone::America::Guatemala 2.65 + DateTime::TimeZone::America::Guayaquil 2.65 + DateTime::TimeZone::America::Guyana 2.65 + DateTime::TimeZone::America::Halifax 2.65 + DateTime::TimeZone::America::Havana 2.65 + DateTime::TimeZone::America::Hermosillo 2.65 + DateTime::TimeZone::America::Indiana::Indianapolis 2.65 + DateTime::TimeZone::America::Indiana::Knox 2.65 + DateTime::TimeZone::America::Indiana::Marengo 2.65 + DateTime::TimeZone::America::Indiana::Petersburg 2.65 + DateTime::TimeZone::America::Indiana::Tell_City 2.65 + DateTime::TimeZone::America::Indiana::Vevay 2.65 + DateTime::TimeZone::America::Indiana::Vincennes 2.65 + DateTime::TimeZone::America::Indiana::Winamac 2.65 + DateTime::TimeZone::America::Inuvik 2.65 + DateTime::TimeZone::America::Iqaluit 2.65 + DateTime::TimeZone::America::Jamaica 2.65 + DateTime::TimeZone::America::Juneau 2.65 + DateTime::TimeZone::America::Kentucky::Louisville 2.65 + DateTime::TimeZone::America::Kentucky::Monticello 2.65 + DateTime::TimeZone::America::La_Paz 2.65 + DateTime::TimeZone::America::Lima 2.65 + DateTime::TimeZone::America::Los_Angeles 2.65 + DateTime::TimeZone::America::Maceio 2.65 + DateTime::TimeZone::America::Managua 2.65 + DateTime::TimeZone::America::Manaus 2.65 + DateTime::TimeZone::America::Martinique 2.65 + DateTime::TimeZone::America::Matamoros 2.65 + DateTime::TimeZone::America::Mazatlan 2.65 + DateTime::TimeZone::America::Menominee 2.65 + DateTime::TimeZone::America::Merida 2.65 + DateTime::TimeZone::America::Metlakatla 2.65 + DateTime::TimeZone::America::Mexico_City 2.65 + DateTime::TimeZone::America::Miquelon 2.65 + DateTime::TimeZone::America::Moncton 2.65 + DateTime::TimeZone::America::Monterrey 2.65 + DateTime::TimeZone::America::Montevideo 2.65 + DateTime::TimeZone::America::New_York 2.65 + DateTime::TimeZone::America::Nome 2.65 + DateTime::TimeZone::America::Noronha 2.65 + DateTime::TimeZone::America::North_Dakota::Beulah 2.65 + DateTime::TimeZone::America::North_Dakota::Center 2.65 + DateTime::TimeZone::America::North_Dakota::New_Salem 2.65 + DateTime::TimeZone::America::Nuuk 2.65 + DateTime::TimeZone::America::Ojinaga 2.65 + DateTime::TimeZone::America::Panama 2.65 + DateTime::TimeZone::America::Paramaribo 2.65 + DateTime::TimeZone::America::Phoenix 2.65 + DateTime::TimeZone::America::Port_au_Prince 2.65 + DateTime::TimeZone::America::Porto_Velho 2.65 + DateTime::TimeZone::America::Puerto_Rico 2.65 + DateTime::TimeZone::America::Punta_Arenas 2.65 + DateTime::TimeZone::America::Rankin_Inlet 2.65 + DateTime::TimeZone::America::Recife 2.65 + DateTime::TimeZone::America::Regina 2.65 + DateTime::TimeZone::America::Resolute 2.65 + DateTime::TimeZone::America::Rio_Branco 2.65 + DateTime::TimeZone::America::Santarem 2.65 + DateTime::TimeZone::America::Santiago 2.65 + DateTime::TimeZone::America::Santo_Domingo 2.65 + DateTime::TimeZone::America::Sao_Paulo 2.65 + DateTime::TimeZone::America::Scoresbysund 2.65 + DateTime::TimeZone::America::Sitka 2.65 + DateTime::TimeZone::America::St_Johns 2.65 + DateTime::TimeZone::America::Swift_Current 2.65 + DateTime::TimeZone::America::Tegucigalpa 2.65 + DateTime::TimeZone::America::Thule 2.65 + DateTime::TimeZone::America::Tijuana 2.65 + DateTime::TimeZone::America::Toronto 2.65 + DateTime::TimeZone::America::Vancouver 2.65 + DateTime::TimeZone::America::Whitehorse 2.65 + DateTime::TimeZone::America::Winnipeg 2.65 + DateTime::TimeZone::America::Yakutat 2.65 + DateTime::TimeZone::Antarctica::Casey 2.65 + DateTime::TimeZone::Antarctica::Davis 2.65 + DateTime::TimeZone::Antarctica::Macquarie 2.65 + DateTime::TimeZone::Antarctica::Mawson 2.65 + DateTime::TimeZone::Antarctica::Palmer 2.65 + DateTime::TimeZone::Antarctica::Rothera 2.65 + DateTime::TimeZone::Antarctica::Troll 2.65 + DateTime::TimeZone::Antarctica::Vostok 2.65 + DateTime::TimeZone::Asia::Almaty 2.65 + DateTime::TimeZone::Asia::Amman 2.65 + DateTime::TimeZone::Asia::Anadyr 2.65 + DateTime::TimeZone::Asia::Aqtau 2.65 + DateTime::TimeZone::Asia::Aqtobe 2.65 + DateTime::TimeZone::Asia::Ashgabat 2.65 + DateTime::TimeZone::Asia::Atyrau 2.65 + DateTime::TimeZone::Asia::Baghdad 2.65 + DateTime::TimeZone::Asia::Baku 2.65 + DateTime::TimeZone::Asia::Bangkok 2.65 + DateTime::TimeZone::Asia::Barnaul 2.65 + DateTime::TimeZone::Asia::Beirut 2.65 + DateTime::TimeZone::Asia::Bishkek 2.65 + DateTime::TimeZone::Asia::Chita 2.65 + DateTime::TimeZone::Asia::Colombo 2.65 + DateTime::TimeZone::Asia::Damascus 2.65 + DateTime::TimeZone::Asia::Dhaka 2.65 + DateTime::TimeZone::Asia::Dili 2.65 + DateTime::TimeZone::Asia::Dubai 2.65 + DateTime::TimeZone::Asia::Dushanbe 2.65 + DateTime::TimeZone::Asia::Famagusta 2.65 + DateTime::TimeZone::Asia::Gaza 2.65 + DateTime::TimeZone::Asia::Hebron 2.65 + DateTime::TimeZone::Asia::Ho_Chi_Minh 2.65 + DateTime::TimeZone::Asia::Hong_Kong 2.65 + DateTime::TimeZone::Asia::Hovd 2.65 + DateTime::TimeZone::Asia::Irkutsk 2.65 + DateTime::TimeZone::Asia::Jakarta 2.65 + DateTime::TimeZone::Asia::Jayapura 2.65 + DateTime::TimeZone::Asia::Jerusalem 2.65 + DateTime::TimeZone::Asia::Kabul 2.65 + DateTime::TimeZone::Asia::Kamchatka 2.65 + DateTime::TimeZone::Asia::Karachi 2.65 + DateTime::TimeZone::Asia::Kathmandu 2.65 + DateTime::TimeZone::Asia::Khandyga 2.65 + DateTime::TimeZone::Asia::Kolkata 2.65 + DateTime::TimeZone::Asia::Krasnoyarsk 2.65 + DateTime::TimeZone::Asia::Kuching 2.65 + DateTime::TimeZone::Asia::Macau 2.65 + DateTime::TimeZone::Asia::Magadan 2.65 + DateTime::TimeZone::Asia::Makassar 2.65 + DateTime::TimeZone::Asia::Manila 2.65 + DateTime::TimeZone::Asia::Nicosia 2.65 + DateTime::TimeZone::Asia::Novokuznetsk 2.65 + DateTime::TimeZone::Asia::Novosibirsk 2.65 + DateTime::TimeZone::Asia::Omsk 2.65 + DateTime::TimeZone::Asia::Oral 2.65 + DateTime::TimeZone::Asia::Pontianak 2.65 + DateTime::TimeZone::Asia::Pyongyang 2.65 + DateTime::TimeZone::Asia::Qatar 2.65 + DateTime::TimeZone::Asia::Qostanay 2.65 + DateTime::TimeZone::Asia::Qyzylorda 2.65 + DateTime::TimeZone::Asia::Riyadh 2.65 + DateTime::TimeZone::Asia::Sakhalin 2.65 + DateTime::TimeZone::Asia::Samarkand 2.65 + DateTime::TimeZone::Asia::Seoul 2.65 + DateTime::TimeZone::Asia::Shanghai 2.65 + DateTime::TimeZone::Asia::Singapore 2.65 + DateTime::TimeZone::Asia::Srednekolymsk 2.65 + DateTime::TimeZone::Asia::Taipei 2.65 + DateTime::TimeZone::Asia::Tashkent 2.65 + DateTime::TimeZone::Asia::Tbilisi 2.65 + DateTime::TimeZone::Asia::Tehran 2.65 + DateTime::TimeZone::Asia::Thimphu 2.65 + DateTime::TimeZone::Asia::Tokyo 2.65 + DateTime::TimeZone::Asia::Tomsk 2.65 + DateTime::TimeZone::Asia::Ulaanbaatar 2.65 + DateTime::TimeZone::Asia::Urumqi 2.65 + DateTime::TimeZone::Asia::Ust_Nera 2.65 + DateTime::TimeZone::Asia::Vladivostok 2.65 + DateTime::TimeZone::Asia::Yakutsk 2.65 + DateTime::TimeZone::Asia::Yangon 2.65 + DateTime::TimeZone::Asia::Yekaterinburg 2.65 + DateTime::TimeZone::Asia::Yerevan 2.65 + DateTime::TimeZone::Atlantic::Azores 2.65 + DateTime::TimeZone::Atlantic::Bermuda 2.65 + DateTime::TimeZone::Atlantic::Canary 2.65 + DateTime::TimeZone::Atlantic::Cape_Verde 2.65 + DateTime::TimeZone::Atlantic::Faroe 2.65 + DateTime::TimeZone::Atlantic::Madeira 2.65 + DateTime::TimeZone::Atlantic::South_Georgia 2.65 + DateTime::TimeZone::Atlantic::Stanley 2.65 + DateTime::TimeZone::Australia::Adelaide 2.65 + DateTime::TimeZone::Australia::Brisbane 2.65 + DateTime::TimeZone::Australia::Broken_Hill 2.65 + DateTime::TimeZone::Australia::Darwin 2.65 + DateTime::TimeZone::Australia::Eucla 2.65 + DateTime::TimeZone::Australia::Hobart 2.65 + DateTime::TimeZone::Australia::Lindeman 2.65 + DateTime::TimeZone::Australia::Lord_Howe 2.65 + DateTime::TimeZone::Australia::Melbourne 2.65 + DateTime::TimeZone::Australia::Perth 2.65 + DateTime::TimeZone::Australia::Sydney 2.65 + DateTime::TimeZone::Catalog 2.65 + DateTime::TimeZone::Europe::Andorra 2.65 + DateTime::TimeZone::Europe::Astrakhan 2.65 + DateTime::TimeZone::Europe::Athens 2.65 + DateTime::TimeZone::Europe::Belgrade 2.65 + DateTime::TimeZone::Europe::Berlin 2.65 + DateTime::TimeZone::Europe::Brussels 2.65 + DateTime::TimeZone::Europe::Bucharest 2.65 + DateTime::TimeZone::Europe::Budapest 2.65 + DateTime::TimeZone::Europe::Chisinau 2.65 + DateTime::TimeZone::Europe::Dublin 2.65 + DateTime::TimeZone::Europe::Gibraltar 2.65 + DateTime::TimeZone::Europe::Helsinki 2.65 + DateTime::TimeZone::Europe::Istanbul 2.65 + DateTime::TimeZone::Europe::Kaliningrad 2.65 + DateTime::TimeZone::Europe::Kirov 2.65 + DateTime::TimeZone::Europe::Kyiv 2.65 + DateTime::TimeZone::Europe::Lisbon 2.65 + DateTime::TimeZone::Europe::London 2.65 + DateTime::TimeZone::Europe::Madrid 2.65 + DateTime::TimeZone::Europe::Malta 2.65 + DateTime::TimeZone::Europe::Minsk 2.65 + DateTime::TimeZone::Europe::Moscow 2.65 + DateTime::TimeZone::Europe::Paris 2.65 + DateTime::TimeZone::Europe::Prague 2.65 + DateTime::TimeZone::Europe::Riga 2.65 + DateTime::TimeZone::Europe::Rome 2.65 + DateTime::TimeZone::Europe::Samara 2.65 + DateTime::TimeZone::Europe::Saratov 2.65 + DateTime::TimeZone::Europe::Simferopol 2.65 + DateTime::TimeZone::Europe::Sofia 2.65 + DateTime::TimeZone::Europe::Tallinn 2.65 + DateTime::TimeZone::Europe::Tirane 2.65 + DateTime::TimeZone::Europe::Ulyanovsk 2.65 + DateTime::TimeZone::Europe::Vienna 2.65 + DateTime::TimeZone::Europe::Vilnius 2.65 + DateTime::TimeZone::Europe::Volgograd 2.65 + DateTime::TimeZone::Europe::Warsaw 2.65 + DateTime::TimeZone::Europe::Zurich 2.65 + DateTime::TimeZone::Floating 2.65 + DateTime::TimeZone::Indian::Chagos 2.65 + DateTime::TimeZone::Indian::Maldives 2.65 + DateTime::TimeZone::Indian::Mauritius 2.65 + DateTime::TimeZone::Local 2.65 + DateTime::TimeZone::Local::Android 2.65 + DateTime::TimeZone::Local::Unix 2.65 + DateTime::TimeZone::Local::VMS 2.65 + DateTime::TimeZone::OffsetOnly 2.65 + DateTime::TimeZone::OlsonDB 2.65 + DateTime::TimeZone::OlsonDB::Change 2.65 + DateTime::TimeZone::OlsonDB::Observance 2.65 + DateTime::TimeZone::OlsonDB::Rule 2.65 + DateTime::TimeZone::OlsonDB::Zone 2.65 + DateTime::TimeZone::Pacific::Apia 2.65 + DateTime::TimeZone::Pacific::Auckland 2.65 + DateTime::TimeZone::Pacific::Bougainville 2.65 + DateTime::TimeZone::Pacific::Chatham 2.65 + DateTime::TimeZone::Pacific::Easter 2.65 + DateTime::TimeZone::Pacific::Efate 2.65 + DateTime::TimeZone::Pacific::Fakaofo 2.65 + DateTime::TimeZone::Pacific::Fiji 2.65 + DateTime::TimeZone::Pacific::Galapagos 2.65 + DateTime::TimeZone::Pacific::Gambier 2.65 + DateTime::TimeZone::Pacific::Guadalcanal 2.65 + DateTime::TimeZone::Pacific::Guam 2.65 + DateTime::TimeZone::Pacific::Honolulu 2.65 + DateTime::TimeZone::Pacific::Kanton 2.65 + DateTime::TimeZone::Pacific::Kiritimati 2.65 + DateTime::TimeZone::Pacific::Kosrae 2.65 + DateTime::TimeZone::Pacific::Kwajalein 2.65 + DateTime::TimeZone::Pacific::Marquesas 2.65 + DateTime::TimeZone::Pacific::Nauru 2.65 + DateTime::TimeZone::Pacific::Niue 2.65 + DateTime::TimeZone::Pacific::Norfolk 2.65 + DateTime::TimeZone::Pacific::Noumea 2.65 + DateTime::TimeZone::Pacific::Pago_Pago 2.65 + DateTime::TimeZone::Pacific::Palau 2.65 + DateTime::TimeZone::Pacific::Pitcairn 2.65 + DateTime::TimeZone::Pacific::Port_Moresby 2.65 + DateTime::TimeZone::Pacific::Rarotonga 2.65 + DateTime::TimeZone::Pacific::Tahiti 2.65 + DateTime::TimeZone::Pacific::Tarawa 2.65 + DateTime::TimeZone::Pacific::Tongatapu 2.65 + DateTime::TimeZone::UTC 2.65 requirements: - Class::Load 0 Class::Singleton 1.03 Cwd 3 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 File::Basename 0 File::Compare 0 File::Find 0 File::Spec 0 - List::Util 0 - Params::Validate 0.72 + List::Util 1.33 + Module::Runtime 0 + Params::ValidationCompiler 0.13 + Specio::Library::Builtins 0 + Specio::Library::String 0 + Try::Tiny 0 constant 0 + namespace::autoclean 0 parent 0 + perl 5.008004 strict 0 - vars 0 warnings 0 - Devel-ArgNames-0.03 - pathname: N/NU/NUFFIN/Devel-ArgNames-0.03.tar.gz - provides: - Devel::ArgNames 0.03 - requirements: - ExtUtils::MakeMaker 0 - PadWalker 0 - Test::use::ok 0 - Devel-CheckCompiler-0.05 - pathname: S/SY/SYOHEX/Devel-CheckCompiler-0.05.tar.gz - provides: - Devel::AssertC99 undef - Devel::CheckCompiler 0.05 - requirements: - CPAN::Meta 0 - CPAN::Meta::Prereqs 0 - Exporter 0 - ExtUtils::CBuilder 0 - File::Temp 0 - Module::Build 0.38 - Test::More 0.98 - Test::Requires 0 - parent 0 - perl 5.008001 - Devel-CheckLib-1.01 - pathname: M/MA/MATTN/Devel-CheckLib-1.01.tar.gz + Devel-CheckLib-1.16 + pathname: M/MA/MATTN/Devel-CheckLib-1.16.tar.gz provides: - Devel::CheckLib 1.01 + Devel::CheckLib 1.16 requirements: Exporter 0 ExtUtils::MakeMaker 0 File::Spec 0 File::Temp 0.16 - IO::CaptureOutput 1.0801 - Test::More 0.62 - perl 5.00405 - Devel-GlobalDestruction-0.12 - pathname: H/HA/HAARG/Devel-GlobalDestruction-0.12.tar.gz + perl 5.004050 + Devel-Confess-0.009004 + pathname: H/HA/HAARG/Devel-Confess-0.009004.tar.gz provides: - Devel::GlobalDestruction 0.12 + Devel::Confess 0.009004 + Devel::Confess::Builtin 0.009004 + Devel::Confess::Source undef + Devel::Confess::_Util undef requirements: - ExtUtils::CBuilder 0.27 + Carp 0 ExtUtils::MakeMaker 0 - Sub::Exporter::Progressive 0.001011 + Scalar::Util 0 perl 5.006 - Devel-PartialDump-0.17 - pathname: E/ET/ETHER/Devel-PartialDump-0.17.tar.gz + Devel-GlobalDestruction-0.14 + pathname: H/HA/HAARG/Devel-GlobalDestruction-0.14.tar.gz provides: - Devel::PartialDump 0.17 + Devel::GlobalDestruction 0.14 requirements: - Carp 0 - Carp::Heavy 0 + ExtUtils::MakeMaker 0 + Sub::Exporter::Progressive 0.001011 + perl 5.006 + Devel-Hide-0.0015 + pathname: D/DC/DCANTRELL/Devel-Hide-0.0015.tar.gz + provides: + Devel::Hide 0.0015 + requirements: + ExtUtils::MakeMaker 0 + File::Temp 0 + perl 5.006001 + Devel-OverloadInfo-0.007 + pathname: I/IL/ILMARI/Devel-OverloadInfo-0.007.tar.gz + provides: + Devel::OverloadInfo 0.007 + requirements: + B 0 + Exporter 5.57 + ExtUtils::MakeMaker 0 + MRO::Compat 0 + Package::Stash 0.14 + Scalar::Util 0 + Sub::Util 1.40 + Text::ParseWords 0 + overload 0 + perl 5.006 + strict 0 + warnings 0 + Devel-PartialDump-0.20 + pathname: E/ET/ETHER/Devel-PartialDump-0.20.tar.gz + provides: + Devel::PartialDump 0.20 + requirements: + Carp 0 Class::Tiny 0 - ExtUtils::MakeMaker 6.30 - Module::Build::Tiny 0.030 + ExtUtils::MakeMaker 0 Scalar::Util 0 Sub::Exporter 0 - namespace::clean 0 + namespace::clean 0.19 perl 5.006001 strict 0 warnings 0 - Devel-StackTrace-1.32 - pathname: D/DR/DROLSKY/Devel-StackTrace-1.32.tar.gz + Devel-StackTrace-2.05 + pathname: D/DR/DROLSKY/Devel-StackTrace-2.05.tar.gz provides: - Devel::StackTrace 1.32 - Devel::StackTrace::Frame 1.32 + Devel::StackTrace 2.05 + Devel::StackTrace::Frame 2.05 requirements: - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 File::Spec 0 Scalar::Util 0 overload 0 + perl 5.006 strict 0 warnings 0 - Devel-StackTrace-AsHTML-0.14 - pathname: M/MI/MIYAGAWA/Devel-StackTrace-AsHTML-0.14.tar.gz + Devel-StackTrace-AsHTML-0.15 + pathname: M/MI/MIYAGAWA/Devel-StackTrace-AsHTML-0.15.tar.gz provides: - Devel::StackTrace::AsHTML 0.14 + Devel::StackTrace::AsHTML 0.15 requirements: Devel::StackTrace 0 - ExtUtils::MakeMaker 6.59 - Filter::Util::Call 0 - Test::More 0 - perl 5.008001 - Devel-Symdump-2.11 - pathname: A/AN/ANDK/Devel-Symdump-2.11.tar.gz - provides: - Devel::Symdump 2.11 - Devel::Symdump::Export undef - requirements: - Compress::Zlib 0 ExtUtils::MakeMaker 0 - Test::More 0 - perl 5.004 - Digest-HMAC-1.03 - pathname: G/GA/GAAS/Digest-HMAC-1.03.tar.gz + Digest-HMAC-1.05 + pathname: A/AR/ARODLAND/Digest-HMAC-1.05.tar.gz provides: - Digest::HMAC 1.03 - Digest::HMAC_MD5 1.01 - Digest::HMAC_SHA1 1.03 + Digest::HMAC 1.05 + Digest::HMAC_MD5 1.05 + Digest::HMAC_SHA1 1.05 requirements: Digest::MD5 2 Digest::SHA 1 ExtUtils::MakeMaker 0 - perl 5.004 - Digest-JHash-0.08 - pathname: S/SH/SHLOMIF/Digest-JHash-0.08.tar.gz + perl 5.008001 + Digest-JHash-0.10 + pathname: S/SH/SHLOMIF/Digest-JHash-0.10.tar.gz provides: - Digest::JHash 0.08 + Digest::JHash 0.10 requirements: DynaLoader 0 Exporter 0 ExtUtils::MakeMaker 0 perl 5.008 strict 0 + vars 0 warnings 0 - Digest-SHA1-2.13 - pathname: G/GA/GAAS/Digest-SHA1-2.13.tar.gz - provides: - Digest::SHA1 2.13 - requirements: - Digest::base 1.00 - ExtUtils::MakeMaker 0 - perl 5.004 Dist-CheckConflicts-0.11 pathname: D/DO/DOY/Dist-CheckConflicts-0.11.tar.gz provides: @@ -2770,243 +1957,288 @@ DISTRIBUTIONS base 0 strict 0 warnings 0 - EV-4.17 - pathname: M/ML/MLEHMANN/EV-4.17.tar.gz + Dist-Data-0.007 + pathname: G/GE/GETTY/Dist-Data-0.007.tar.gz provides: - EV 4.17 - EV::MakeMaker undef + Dist::Data 0.007 requirements: + Archive::Any 0.0932 + CPAN::Meta 2.113640 + DateTime::Format::Epoch 0.13 + Dist::Metadata 0.922 ExtUtils::MakeMaker 0 - common::sense 0 - ElasticSearch-0.68 - pathname: D/DR/DRTECH/ElasticSearch-0.68.tar.gz - provides: - ElasticSearch 0.68 - ElasticSearch::Error 0.68 - ElasticSearch::QueryParser 0.68 - ElasticSearch::ScrolledSearch 0.68 - ElasticSearch::TestServer 0.68 - ElasticSearch::Transport 0.68 - ElasticSearch::Transport::HTTP 0.68 - ElasticSearch::Transport::HTTPLite 0.68 - ElasticSearch::Transport::HTTPTiny 0.68 - ElasticSearch::Util 0.68 - requirements: - Any::URI::Escape 0 - Carp 0 - Data::Dumper 0 - ElasticSearch::SearchBuilder 0.18 - Encode 0 - Exporter 0 - ExtUtils::MakeMaker 6.30 - File::Path 0 - File::Spec::Functions 0 + File::Find::Object v0.2.3 File::Temp 0.22 - HTTP::Lite 0 - HTTP::Request 0 - HTTP::Tiny 0 - IO::Handle 0 - IO::Socket 0 - IO::Uncompress::Inflate 0 - JSON 0 - LWP::ConnCache 0 - LWP::UserAgent 0 + Module::Metadata 0 + Moo 0.009013 + Dist-Metadata-0.927 + pathname: R/RW/RWSTAUNER/Dist-Metadata-0.927.tar.gz + provides: + Dist::Metadata 0.927 + Dist::Metadata::Archive 0.927 + Dist::Metadata::Dir 0.927 + Dist::Metadata::Dist 0.927 + Dist::Metadata::Struct 0.927 + Dist::Metadata::Tar 0.927 + Dist::Metadata::Zip 0.927 + requirements: + Archive::Tar 1 + Archive::Zip 1.30 + CPAN::DistnameInfo 0.12 + CPAN::Meta 2.1 + Carp 0 + Digest 1.03 + Digest::MD5 2 + Digest::SHA 5 + ExtUtils::MakeMaker 0 + File::Basename 0 + File::Find 0 + File::Spec::Native 1.002 + File::Temp 0.19 List::Util 0 - POSIX 0 - Scalar::Util 1.07 - Task::Weaken 0 - Test::More 0.96 - URI 0 - YAML 0 - constant 0 - overload 0 + Module::Metadata 0 + Path::Class 0.24 + Try::Tiny 0.09 parent 0 + perl 5.006 strict 0 warnings 0 - ElasticSearch-SearchBuilder-0.19 - pathname: D/DR/DRTECH/ElasticSearch-SearchBuilder-0.19.tar.gz + EV-4.34 + pathname: M/ML/MLEHMANN/EV-4.34.tar.gz provides: - ElasticSearch::SearchBuilder 0.19 + EV 4.34 + EV::MakeMaker undef requirements: - Carp 0 - ExtUtils::MakeMaker 6.30 - Scalar::Util 0 - Test::More 0.96 - strict 0 - warnings 0 - ElasticSearchX-Model-0.1.7 - pathname: P/PE/PERLER/ElasticSearchX-Model-0.1.7.tar.gz - provides: - ElasticSearchX::Model 0.001007 - ElasticSearchX::Model::Bulk 0.001007 - ElasticSearchX::Model::Document 0.001007 - ElasticSearchX::Model::Document::Mapping 0.001007 - ElasticSearchX::Model::Document::Role 0.001007 - ElasticSearchX::Model::Document::Set 0.001007 - ElasticSearchX::Model::Document::Trait::Attribute 0.001007 - ElasticSearchX::Model::Document::Trait::Class 0.001007 - ElasticSearchX::Model::Document::Trait::Class::ID 0.001007 - ElasticSearchX::Model::Document::Trait::Class::Timestamp 0.001007 - ElasticSearchX::Model::Document::Trait::Class::Version 0.001007 - ElasticSearchX::Model::Document::Trait::Field::ID 0.001007 - ElasticSearchX::Model::Document::Trait::Field::TTL 0.001007 - ElasticSearchX::Model::Document::Trait::Field::Timestamp 0.001007 - ElasticSearchX::Model::Document::Trait::Field::Version 0.001007 - ElasticSearchX::Model::Document::Types 0.001007 - ElasticSearchX::Model::Index 0.001007 - ElasticSearchX::Model::Role 0.001007 - ElasticSearchX::Model::Scroll 0.001007 - ElasticSearchX::Model::Trait::Class 0.001007 - ElasticSearchX::Model::Tutorial 0.001007 - ElasticSearchX::Model::Util 0.001007 + Canary::Stability 0 + ExtUtils::MakeMaker 6.52 + common::sense 0 + ElasticSearchX-Model-2.0.1 + pathname: O/OA/OALDERS/ElasticSearchX-Model-2.0.1.tar.gz + provides: + ElasticSearchX::Model v2.0.1 + ElasticSearchX::Model::Bulk v2.0.1 + ElasticSearchX::Model::Document v2.0.1 + ElasticSearchX::Model::Document::EmbeddedRole v2.0.1 + ElasticSearchX::Model::Document::Mapping v2.0.1 + ElasticSearchX::Model::Document::Role v2.0.1 + ElasticSearchX::Model::Document::Set v2.0.1 + ElasticSearchX::Model::Document::Trait::Attribute v2.0.1 + ElasticSearchX::Model::Document::Trait::Class v2.0.1 + ElasticSearchX::Model::Document::Trait::Class::ID v2.0.1 + ElasticSearchX::Model::Document::Trait::Class::Timestamp v2.0.1 + ElasticSearchX::Model::Document::Trait::Class::Version v2.0.1 + ElasticSearchX::Model::Document::Trait::Field::ID v2.0.1 + ElasticSearchX::Model::Document::Trait::Field::TTL v2.0.1 + ElasticSearchX::Model::Document::Trait::Field::Timestamp v2.0.1 + ElasticSearchX::Model::Document::Trait::Field::Version v2.0.1 + ElasticSearchX::Model::Document::Types v2.0.1 + ElasticSearchX::Model::Index v2.0.1 + ElasticSearchX::Model::Role v2.0.1 + ElasticSearchX::Model::Scroll v2.0.1 + ElasticSearchX::Model::Trait::Class v2.0.1 + ElasticSearchX::Model::Tutorial v2.0.1 + ElasticSearchX::Model::Util v2.0.1 requirements: Carp 0 Class::Load 0 DateTime 0 DateTime::Format::Epoch::Unix 0 DateTime::Format::ISO8601 0 - Digest::SHA1 0 - ElasticSearch 0.65 - JSON 0 + Digest::SHA 0 + Eval::Closure 0 + ExtUtils::MakeMaker 0 + JSON::MaybeXS 0 List::MoreUtils 0 List::Util 0 - Module::Build 0.3601 Module::Find 0 Moose 2.02 + Moose::Exporter 0 + Moose::Role 0 + Moose::Util::TypeConstraints 0 MooseX::Attribute::Chained v1.0.1 + MooseX::Attribute::ChainedClone 0 MooseX::Attribute::Deflator v2.2.0 + MooseX::Attribute::Deflator::Moose 0 + MooseX::Attribute::LazyInflator::Meta::Role::Attribute 0 MooseX::Types 0 - MooseX::Types::ElasticSearch v0.0.2 + MooseX::Types::ElasticSearch v0.0.4 + MooseX::Types::Moose 0 MooseX::Types::Structured 0 Scalar::Util 0 + Search::Elasticsearch 2.02 Sub::Exporter 0 - Email-Abstract-3.007 - pathname: R/RJ/RJBS/Email-Abstract-3.007.tar.gz - provides: - Email::Abstract 3.007 - Email::Abstract::EmailMIME 3.007 - Email::Abstract::EmailSimple 3.007 - Email::Abstract::MIMEEntity 3.007 - Email::Abstract::MailInternet 3.007 - Email::Abstract::MailMessage 3.007 - Email::Abstract::Plugin 3.007 - Test::EmailAbstract undef + perl 5.006 + strict 0 + version 0 + warnings 0 + Email-Abstract-3.010 + pathname: R/RJ/RJBS/Email-Abstract-3.010.tar.gz + provides: + Email::Abstract 3.010 + Email::Abstract::EmailMIME 3.010 + Email::Abstract::EmailSimple 3.010 + Email::Abstract::MIMEEntity 3.010 + Email::Abstract::MailInternet 3.010 + Email::Abstract::MailMessage 3.010 + Email::Abstract::Plugin 3.010 requirements: Carp 0 Email::Simple 1.998 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 6.78 MRO::Compat 0 Module::Pluggable 1.5 Scalar::Util 0 + perl 5.006 strict 0 warnings 0 - Email-Address-1.903 - pathname: R/RJ/RJBS/Email-Address-1.903.tar.gz + Email-Address-XS-1.05 + pathname: P/PA/PALI/Email-Address-XS-1.05.tar.gz provides: - Email::Address 1.903 + Email::Address::XS 1.05 requirements: - ExtUtils::MakeMaker 6.30 + Carp 0 + Exporter 0 + ExtUtils::MakeMaker 0 + XSLoader 0 + base 0 overload 0 + perl 5.006000 strict 0 warnings 0 - Email-Date-Format-1.004 - pathname: R/RJ/RJBS/Email-Date-Format-1.004.tar.gz + Email-Date-Format-1.008 + pathname: R/RJ/RJBS/Email-Date-Format-1.008.tar.gz provides: - Email::Date::Format 1.004 + Email::Date::Format 1.008 requirements: Exporter 5.57 - ExtUtils::MakeMaker 6.30 - Time::Local 0 - strict 0 + ExtUtils::MakeMaker 6.78 + Time::Local 1.27 + perl 5.012 warnings 0 - Email-Sender-1.300011 - pathname: R/RJ/RJBS/Email-Sender-1.300011.tar.gz - provides: - Email::Sender 1.300011 - Email::Sender::Failure 1.300011 - Email::Sender::Failure::Multi 1.300011 - Email::Sender::Failure::Permanent 1.300011 - Email::Sender::Failure::Temporary 1.300011 - Email::Sender::Manual 1.300011 - Email::Sender::Manual::QuickStart 1.300011 - Email::Sender::Role::CommonSending 1.300011 - Email::Sender::Role::HasMessage 1.300011 - Email::Sender::Simple 1.300011 - Email::Sender::Success 1.300011 - Email::Sender::Success::Partial 1.300011 - Email::Sender::Transport 1.300011 - Email::Sender::Transport::DevNull 1.300011 - Email::Sender::Transport::Failable 1.300011 - Email::Sender::Transport::Maildir 1.300011 - Email::Sender::Transport::Mbox 1.300011 - Email::Sender::Transport::Print 1.300011 - Email::Sender::Transport::SMTP 1.300011 - Email::Sender::Transport::SMTP::Persistent 1.300011 - Email::Sender::Transport::Sendmail 1.300011 - Email::Sender::Transport::Test 1.300011 - Email::Sender::Transport::Wrapper 1.300011 - Email::Sender::Util 1.300011 - Test::Email::SMTPRig undef - Test::Email::Sender::Transport::FailEvery undef - Test::Email::Sender::Util undef + Email-Sender-2.601 + pathname: R/RJ/RJBS/Email-Sender-2.601.tar.gz + provides: + Email::Sender 2.601 + Email::Sender::Failure 2.601 + Email::Sender::Failure::Multi 2.601 + Email::Sender::Failure::Permanent 2.601 + Email::Sender::Failure::Temporary 2.601 + Email::Sender::Manual 2.601 + Email::Sender::Manual::QuickStart 2.601 + Email::Sender::Role::CommonSending 2.601 + Email::Sender::Role::HasMessage 2.601 + Email::Sender::Simple 2.601 + Email::Sender::Success 2.601 + Email::Sender::Success::Partial 2.601 + Email::Sender::Transport 2.601 + Email::Sender::Transport::DevNull 2.601 + Email::Sender::Transport::Failable 2.601 + Email::Sender::Transport::Maildir 2.601 + Email::Sender::Transport::Mbox 2.601 + Email::Sender::Transport::Print 2.601 + Email::Sender::Transport::SMTP 2.601 + Email::Sender::Transport::SMTP::Persistent 2.601 + Email::Sender::Transport::Sendmail 2.601 + Email::Sender::Transport::Test 2.601 + Email::Sender::Transport::Wrapper 2.601 + Email::Sender::Util 2.601 requirements: Carp 0 Email::Abstract 3.006 - Email::Address 0 + Email::Address::XS 0 Email::Simple 1.998 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 6.78 Fcntl 0 File::Basename 0 File::Path 2.06 File::Spec 0 - IO::File 0 + IO::File 1.11 IO::Handle 0 - List::MoreUtils 0 + List::Util 1.45 Module::Runtime 0 - Moo 1.000008 + Moo 2.000000 Moo::Role 0 MooX::Types::MooseLike 0.15 MooX::Types::MooseLike::Base 0 - Net::SMTP 0 + Net::SMTP 3.07 Scalar::Util 0 Sub::Exporter 0 Sub::Exporter::Util 0 Sys::Hostname 0 Throwable::Error 0.200003 Try::Tiny 0 + perl 5.012 strict 0 + utf8 0 warnings 0 - Email-Simple-2.203 - pathname: R/RJ/RJBS/Email-Simple-2.203.tar.gz + Email-Simple-2.218 + pathname: R/RJ/RJBS/Email-Simple-2.218.tar.gz provides: - Email::Simple 2.203 - Email::Simple::Creator 2.203 - Email::Simple::Header 2.203 + Email::Simple 2.218 + Email::Simple::Creator 2.218 + Email::Simple::Header 2.218 requirements: Carp 0 Email::Date::Format 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 6.78 + perl 5.012 strict 0 warnings 0 - Email-Valid-1.194 - pathname: R/RJ/RJBS/Email-Valid-1.194.tar.gz + Email-Valid-1.204 + pathname: R/RJ/RJBS/Email-Valid-1.204.tar.gz provides: - Email::Valid 1.194 + Email::Valid 1.204 requirements: ExtUtils::MakeMaker 0 Mail::Address 0 + Net::DNS 0 Scalar::Util 0 Test::More 0 perl 5.006 - Encode-Locale-1.03 - pathname: G/GA/GAAS/Encode-Locale-1.03.tar.gz + Encode-3.21 + pathname: D/DA/DANKOGAI/Encode-3.21.tar.gz + provides: + Encode 3.21 + Encode::Alias 2.25 + Encode::Byte 2.04 + Encode::CJKConstants 2.02 + Encode::CN 2.03 + Encode::CN::HZ 2.10 + Encode::Config 2.05 + Encode::EBCDIC 2.02 + Encode::Encoder 2.03 + Encode::Encoding 2.08 + Encode::GSM0338 2.10 + Encode::Guess 2.08 + Encode::JP 2.05 + Encode::JP::H2Z 2.02 + Encode::JP::JIS7 2.08 + Encode::KR 2.03 + Encode::KR::2022_KR 2.04 + Encode::MIME::Header 2.29 + Encode::MIME::Header::ISO_2022_JP 1.09 + Encode::MIME::Name 1.03 + Encode::Symbol 2.02 + Encode::TW 2.03 + Encode::UTF_EBCDIC 3.21 + Encode::Unicode 2.20 + Encode::Unicode::UTF7 2.10 + Encode::XS 3.21 + Encode::utf8 3.21 + encoding 3.00 + requirements: + Exporter 5.57 + ExtUtils::MakeMaker 0 + Storable 0 + parent 0.221 + Encode-Locale-1.05 + pathname: G/GA/GAAS/Encode-Locale-1.05.tar.gz provides: - Encode::Locale 1.03 + Encode::Locale 1.05 requirements: Encode 2 Encode::Alias 0 ExtUtils::MakeMaker 0 - Test 0 perl 5.008 Encoding-FixLatin-1.04 pathname: G/GR/GRANTM/Encoding-FixLatin-1.04.tar.gz @@ -3015,212 +2247,193 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 6.30 Test::More 0.90 - Error-0.17022 - pathname: S/SH/SHLOMIF/Error-0.17022.tar.gz + Encoding-FixLatin-XS-1.02 + pathname: G/GR/GRANTM/Encoding-FixLatin-XS-1.02.tar.gz provides: - Error 0.17022 + Encoding::FixLatin::XS 1.02 requirements: - Module::Build 0.39 - Scalar::Util 0 - perl v5.6.0 - strict 0 - warnings 0 - Eval-Closure-0.11 - pathname: D/DO/DOY/Eval-Closure-0.11.tar.gz + ExtUtils::MakeMaker 0 + perl 5.014 + Eval-Closure-0.14 + pathname: D/DO/DOY/Eval-Closure-0.14.tar.gz provides: - Eval::Closure 0.11 + Eval::Closure 0.14 requirements: Carp 0 Exporter 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 Scalar::Util 0 - Try::Tiny 0 constant 0 overload 0 strict 0 warnings 0 - Exception-Class-1.38 - pathname: D/DR/DROLSKY/Exception-Class-1.38.tar.gz + Exception-Class-1.45 + pathname: D/DR/DROLSKY/Exception-Class-1.45.tar.gz provides: - Exception::Class 1.38 - Exception::Class::Base 1.38 + Exception::Class 1.45 + Exception::Class::Base 1.45 requirements: + Carp 0 Class::Data::Inheritable 0.02 - Devel::StackTrace 1.20 - ExtUtils::MakeMaker 6.30 + Devel::StackTrace 2.00 + ExtUtils::MakeMaker 0 Scalar::Util 0 base 0 overload 0 + perl 5.008001 strict 0 warnings 0 - Exporter-Declare-0.113 - pathname: E/EX/EXODIST/Exporter-Declare-0.113.tar.gz + Exporter-5.78 + pathname: T/TO/TODDR/Exporter-5.78.tar.gz provides: - Exporter::Declare 0.113 - Exporter::Declare::Export undef - Exporter::Declare::Export::Alias undef - Exporter::Declare::Export::Generator undef - Exporter::Declare::Export::Sub undef - Exporter::Declare::Export::Variable undef - Exporter::Declare::Meta undef - Exporter::Declare::Specs undef + Exporter 5.78 + Exporter::Heavy 5.78 requirements: - Carp 0 - Fennec::Lite 0.004 - Meta::Builder 0.003 - Scalar::Util 0 - Test::Exception 0.29 - Test::Simple 0.88 - aliased 0 - perl v5.8.0 - Exporter-Lite-0.05 - pathname: N/NE/NEILB/Exporter-Lite-0.05.tar.gz + Carp 1.05 + ExtUtils::MakeMaker 0 + Exporter-Tiny-1.006002 + pathname: T/TO/TOBYINK/Exporter-Tiny-1.006002.tar.gz provides: - Exporter::Lite 0.05 + Exporter::Shiny 1.006002 + Exporter::Tiny 1.006002 requirements: - ExtUtils::MakeMaker 6.3 - perl 5.006 - strict 0 - warnings 0 - ExtUtils-Config-0.007 - pathname: L/LE/LEONT/ExtUtils-Config-0.007.tar.gz + ExtUtils::MakeMaker 6.17 + perl 5.006001 + ExtUtils-Config-0.010 + pathname: L/LE/LEONT/ExtUtils-Config-0.010.tar.gz provides: - ExtUtils::Config 0.007 + ExtUtils::Config 0.010 + ExtUtils::Config::MakeMaker 0.010 requirements: - Config 0 Data::Dumper 0 - ExtUtils::MakeMaker 6.30 - File::Find 0 - File::Temp 0 - Test::More 0.88 + ExtUtils::MakeMaker 0 + ExtUtils::MakeMaker::Config 0 + perl 5.006 strict 0 warnings 0 - ExtUtils-Depends-0.308 - pathname: X/XA/XAOC/ExtUtils-Depends-0.308.tar.gz + ExtUtils-Depends-0.8002 + pathname: E/ET/ETJ/ExtUtils-Depends-0.8002.tar.gz provides: - ExtUtils::Depends 0.308 + ExtUtils::Depends 0.8002 requirements: Data::Dumper 0 - ExtUtils::MakeMaker 0 + ExtUtils::MakeMaker 7.44 File::Spec 0 IO::File 0 perl 5.006 - ExtUtils-Helpers-0.022 - pathname: L/LE/LEONT/ExtUtils-Helpers-0.022.tar.gz + ExtUtils-Helpers-0.028 + pathname: L/LE/LEONT/ExtUtils-Helpers-0.028.tar.gz provides: - ExtUtils::Helpers 0.022 - ExtUtils::Helpers::Unix 0.022 - ExtUtils::Helpers::VMS 0.022 - ExtUtils::Helpers::Windows 0.022 + ExtUtils::Helpers 0.028 + ExtUtils::Helpers::Unix 0.028 + ExtUtils::Helpers::VMS 0.028 + ExtUtils::Helpers::Windows 0.028 requirements: Carp 0 Exporter 5.57 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 File::Basename 0 File::Copy 0 File::Spec::Functions 0 - Module::Load 0 Text::ParseWords 3.24 strict 0 warnings 0 - ExtUtils-InstallPaths-0.010 - pathname: L/LE/LEONT/ExtUtils-InstallPaths-0.010.tar.gz + ExtUtils-InstallPaths-0.014 + pathname: L/LE/LEONT/ExtUtils-InstallPaths-0.014.tar.gz provides: - ExtUtils::InstallPaths 0.010 + ExtUtils::InstallPaths 0.014 requirements: Carp 0 - ExtUtils::Config 0.002 - ExtUtils::MakeMaker 6.30 + ExtUtils::Config 0.009 + ExtUtils::MakeMaker 0 File::Spec 0 + perl 5.008 strict 0 warnings 0 - ExtUtils-MakeMaker-CPANfile-0.06 - pathname: I/IS/ISHIGAKI/ExtUtils-MakeMaker-CPANfile-0.06.tar.gz + ExtUtils-MakeMaker-7.74 + pathname: B/BI/BINGOS/ExtUtils-MakeMaker-7.74.tar.gz + provides: + ExtUtils::Command 7.74 + ExtUtils::Command::MM 7.74 + ExtUtils::Liblist 7.74 + ExtUtils::Liblist::Kid 7.74 + ExtUtils::MM 7.74 + ExtUtils::MM_AIX 7.74 + ExtUtils::MM_Any 7.74 + ExtUtils::MM_BeOS 7.74 + ExtUtils::MM_Cygwin 7.74 + ExtUtils::MM_DOS 7.74 + ExtUtils::MM_Darwin 7.74 + ExtUtils::MM_MacOS 7.74 + ExtUtils::MM_NW5 7.74 + ExtUtils::MM_OS2 7.74 + ExtUtils::MM_OS390 7.74 + ExtUtils::MM_QNX 7.74 + ExtUtils::MM_UWIN 7.74 + ExtUtils::MM_Unix 7.74 + ExtUtils::MM_VMS 7.74 + ExtUtils::MM_VOS 7.74 + ExtUtils::MM_Win32 7.74 + ExtUtils::MM_Win95 7.74 + ExtUtils::MY 7.74 + ExtUtils::MakeMaker 7.74 + ExtUtils::MakeMaker::Config 7.74 + ExtUtils::MakeMaker::Locale 7.74 + ExtUtils::MakeMaker::_version 7.74 + ExtUtils::MakeMaker::charstar 7.74 + ExtUtils::MakeMaker::version 7.74 + ExtUtils::MakeMaker::version::regex 7.74 + ExtUtils::MakeMaker::version::vpp 7.74 + ExtUtils::Mkbootstrap 7.74 + ExtUtils::Mksymlists 7.74 + ExtUtils::testlib 7.74 + MM 7.74 + MY 7.74 + requirements: + Data::Dumper 0 + Encode 0 + File::Basename 0 + File::Spec 0.8 + Pod::Man 0 + perl 5.006 + ExtUtils-MakeMaker-CPANfile-0.09 + pathname: I/IS/ISHIGAKI/ExtUtils-MakeMaker-CPANfile-0.09.tar.gz provides: - ExtUtils::MakeMaker::CPANfile 0.06 + ExtUtils::MakeMaker::CPANfile 0.09 requirements: + CPAN::Meta::Converter 2.141170 Cwd 0 ExtUtils::MakeMaker 6.17 File::Path 0 Module::CPANfile 0 Test::More 0.88 version 0.76 - ExtUtils-ParseXS-3.24 - pathname: S/SM/SMUELLER/ExtUtils-ParseXS-3.24.tar.gz - provides: - ExtUtils::ParseXS 3.24 - ExtUtils::ParseXS::Constants 3.24 - ExtUtils::ParseXS::CountLines 3.24 - ExtUtils::ParseXS::Eval 3.24 - ExtUtils::ParseXS::Utilities 3.24 - ExtUtils::Typemaps 3.24 - ExtUtils::Typemaps::Cmd 3.24 - ExtUtils::Typemaps::InputMap 3.24 - ExtUtils::Typemaps::OutputMap 3.24 - ExtUtils::Typemaps::Type 3.24 + File-Find-Object-0.3.9 + pathname: S/SH/SHLOMIF/File-Find-Object-0.3.9.tar.gz + provides: + File::Find::Object v0.3.9 + File::Find::Object::Base v0.3.9 + File::Find::Object::DeepPath v0.3.9 + File::Find::Object::PathComp v0.3.9 + File::Find::Object::Result v0.3.9 + File::Find::Object::TopPath v0.3.9 requirements: Carp 0 - Cwd 0 - DynaLoader 0 - Exporter 5.57 - ExtUtils::CBuilder 0 - ExtUtils::MakeMaker 6.46 - File::Basename 0 + Class::XSAccessor 0 + ExtUtils::MakeMaker 0 + Fcntl 0 File::Spec 0 - Symbol 0 - Test::More 0.47 - Facebook-Graph-1.0700 - pathname: R/RI/RIZEN/Facebook-Graph-1.0700.tar.gz - provides: - Facebook::Graph 1.0700 - Facebook::Graph::AccessToken 1.0700 - Facebook::Graph::AccessToken::Response 1.0700 - Facebook::Graph::Authorize 1.0700 - Facebook::Graph::BatchRequests 1.0700 - Facebook::Graph::Picture 1.0700 - Facebook::Graph::Publish 1.0700 - Facebook::Graph::Publish::Checkin 1.0700 - Facebook::Graph::Publish::Comment 1.0700 - Facebook::Graph::Publish::Event 1.0700 - Facebook::Graph::Publish::Like 1.0700 - Facebook::Graph::Publish::Link 1.0700 - Facebook::Graph::Publish::Note 1.0700 - Facebook::Graph::Publish::PageTab 1.0700 - Facebook::Graph::Publish::Photo 1.0700 - Facebook::Graph::Publish::Post 1.0700 - Facebook::Graph::Publish::RSVPAttending 1.0700 - Facebook::Graph::Publish::RSVPDeclined 1.0700 - Facebook::Graph::Publish::RSVPMaybe 1.0700 - Facebook::Graph::Query 1.0700 - Facebook::Graph::Request 1.0700 - Facebook::Graph::Response 1.0700 - Facebook::Graph::Role::Uri 1.0700 - Facebook::Graph::Session 1.0700 - requirements: - Any::Moose 0.13 - AnyEvent::HTTP::LWP::UserAgent 0.08 - AnyEvent::TLS 0 - DateTime 0.61 - DateTime::Format::Strptime 1.4000 - ExtUtils::MakeMaker 6.30 - JSON 2.16 - MIME::Base64::URLSafe 0.01 - Ouch 0.0400 - Test::More 0 - URI 1.54 - Fennec-Lite-0.004 - pathname: E/EX/EXODIST/Fennec-Lite-0.004.tar.gz - provides: - Fennec::Lite 0.004 - requirements: List::Util 0 - Test::Builder 0 - Test::More 0 - perl 5.006 - File-Find-Rule-0.33 - pathname: R/RC/RCLAMP/File-Find-Rule-0.33.tar.gz + Module::Build 0.28 + integer 0 + parent 0 + perl 5.008 + strict 0 + warnings 0 + File-Find-Rule-0.34 + pathname: R/RC/RCLAMP/File-Find-Rule-0.34.tar.gz provides: - File::Find::Rule 0.33 + File::Find::Rule 0.34 File::Find::Rule::Test::ATeam undef requirements: ExtUtils::MakeMaker 0 @@ -3229,148 +2442,128 @@ DISTRIBUTIONS Number::Compare 0 Test::More 0 Text::Glob 0.07 - File-Find-Rule-Perl-1.13 - pathname: A/AD/ADAMK/File-Find-Rule-Perl-1.13.tar.gz + File-Find-Rule-Perl-1.16 + pathname: E/ET/ETHER/File-Find-Rule-Perl-1.16.tar.gz provides: - File::Find::Rule::Perl 1.13 + File::Find::Rule::Perl 1.16 requirements: - ExtUtils::MakeMaker 6.36 + ExtUtils::MakeMaker 0 File::Find::Rule 0.20 File::Spec 0.82 Params::Util 0.38 Parse::CPAN::Meta 1.38 - Test::More 0.47 - perl 5.00503 - File-HomeDir-1.00 - pathname: A/AD/ADAMK/File-HomeDir-1.00.tar.gz - provides: - File::HomeDir 1.00 - File::HomeDir::Darwin 1.00 - File::HomeDir::Darwin::Carbon 1.00 - File::HomeDir::Darwin::Cocoa 1.00 - File::HomeDir::Driver 1.00 - File::HomeDir::FreeDesktop 1.00 - File::HomeDir::MacOS9 1.00 - File::HomeDir::TIE 1.00 - File::HomeDir::Test 1.00 - File::HomeDir::Unix 1.00 - File::HomeDir::Windows 1.00 + perl 5.006 + File-HomeDir-1.006 + pathname: R/RE/REHSACK/File-HomeDir-1.006.tar.gz + provides: + File::HomeDir 1.006 + File::HomeDir::Darwin 1.006 + File::HomeDir::Darwin::Carbon 1.006 + File::HomeDir::Darwin::Cocoa 1.006 + File::HomeDir::Driver 1.006 + File::HomeDir::FreeDesktop 1.006 + File::HomeDir::MacOS9 1.006 + File::HomeDir::Test 1.006 + File::HomeDir::Unix 1.006 + File::HomeDir::Windows 1.006 requirements: Carp 0 Cwd 3.12 - ExtUtils::MakeMaker 6.36 + ExtUtils::MakeMaker 0 + File::Basename 0 File::Path 2.01 File::Spec 3.12 File::Temp 0.19 File::Which 0.05 - Test::More 0.47 - perl 5.00503 - File-Listing-6.04 - pathname: G/GA/GAAS/File-Listing-6.04.tar.gz + POSIX 0 + perl 5.008003 + File-Listing-6.16 + pathname: P/PL/PLICEASE/File-Listing-6.16.tar.gz provides: - File::Listing 6.04 - File::Listing::apache 6.04 - File::Listing::dosftp 6.04 - File::Listing::netware 6.04 - File::Listing::unix 6.04 - File::Listing::vms 6.04 + File::Listing 6.16 + File::Listing::apache 6.16 + File::Listing::dosftp 6.16 + File::Listing::netware 6.16 + File::Listing::unix 6.16 + File::Listing::vms 6.16 requirements: + Exporter 5.57 ExtUtils::MakeMaker 0 - HTTP::Date 6 - perl 5.006002 + HTTP::Date 0 + perl 5.006 File-MMagic-1.30 pathname: K/KN/KNOK/File-MMagic-1.30.tar.gz provides: File::MMagic 1.30 requirements: ExtUtils::MakeMaker 0 - File-Next-1.12 - pathname: P/PE/PETDANCE/File-Next-1.12.tar.gz + File-Next-1.18 + pathname: P/PE/PETDANCE/File-Next-1.18.tar.gz provides: - File::Next 1.12 + File::Next 1.18 requirements: ExtUtils::MakeMaker 0 + File::Copy 0 File::Spec 0 + File::Temp 0.22 Test::More 0.88 - File-Remove-1.52 - pathname: A/AD/ADAMK/File-Remove-1.52.tar.gz - provides: - File::Remove 1.52 - requirements: - Cwd 3.29 - ExtUtils::MakeMaker 6.36 - File::Spec 3.29 - Test::More 0.42 - perl 5.00503 - File-ShareDir-1.102 - pathname: R/RE/REHSACK/File-ShareDir-1.102.tar.gz + File-ShareDir-1.118 + pathname: R/RE/REHSACK/File-ShareDir-1.118.tar.gz provides: - File::ShareDir 1.102 + File::ShareDir 1.118 requirements: Carp 0 Class::Inspector 1.12 ExtUtils::MakeMaker 0 - File::ShareDir::Install 0.03 + File::ShareDir::Install 0.13 File::Spec 0.80 perl 5.008001 warnings 0 - File-ShareDir-Install-0.08 - pathname: G/GW/GWYN/File-ShareDir-Install-0.08.tar.gz + File-ShareDir-Install-0.14 + pathname: E/ET/ETHER/File-ShareDir-Install-0.14.tar.gz provides: - File::ShareDir::Install 0.08 + File::ShareDir::Install 0.14 requirements: - ExtUtils::MakeMaker 6.11 + Carp 0 + Exporter 0 + ExtUtils::MakeMaker 0 File::Spec 0 IO::Dir 0 - File-ShareDir-ProjectDistDir-1.000001 - pathname: K/KE/KENTNL/File-ShareDir-ProjectDistDir-1.000001.tar.gz - provides: - File::ShareDir::ProjectDistDir 1.000001 - requirements: - Carp 0 - ExtUtils::MakeMaker 6.30 - File::ShareDir 0 - Path::FindDev 0 - Path::IsDev 0 - Path::Tiny 0 - Sub::Exporter 0 + perl 5.006 strict 0 - utf8 0 warnings 0 - File-Slurp-9999.19 - pathname: U/UR/URI/File-Slurp-9999.19.tar.gz + File-Spec-Native-1.004 + pathname: R/RW/RWSTAUNER/File-Spec-Native-1.004.tar.gz provides: - File::Slurp 9999.19 - FileSlurp_12 9999.13 + File::Spec::Native 1.004 requirements: - Carp 0 - Exporter 0 ExtUtils::MakeMaker 0 - Fcntl 0 - POSIX 0 - File-Which-1.09 - pathname: A/AD/ADAMK/File-Which-1.09.tar.gz + File::Spec 0 + perl 5.006 + strict 0 + warnings 0 + File-Which-1.27 + pathname: P/PL/PLICEASE/File-Which-1.27.tar.gz provides: - File::Which 1.09 + File::Which 1.27 requirements: - Exporter 0 ExtUtils::MakeMaker 0 - File::Spec 0.60 - Getopt::Std 0 - Test::More 0.80 - Test::Script 1.05 - File-Zglob-0.11 - pathname: T/TO/TOKUHIROM/File-Zglob-0.11.tar.gz + base 0 + perl 5.006 + File-XDG-1.03 + pathname: P/PL/PLICEASE/File-XDG-1.03.tar.gz provides: - File::Zglob 0.11 + File::XDG 1.03 requirements: - ExtUtils::MakeMaker 6.59 - Test::More 0.96 - perl 5.008008 - File-pushd-1.009 - pathname: D/DA/DAGOLDEN/File-pushd-1.009.tar.gz + ExtUtils::MakeMaker 0 + File::Path 2.07 + Path::Tiny 0 + Ref::Util 0 + perl 5.006 + File-pushd-1.016 + pathname: D/DA/DAGOLDEN/File-pushd-1.016.tar.gz provides: - File::pushd 1.009 + File::pushd 1.016 requirements: Carp 0 Cwd 0 @@ -3380,292 +2573,206 @@ DISTRIBUTIONS File::Spec 0 File::Temp 0 overload 0 + perl 5.006 strict 0 warnings 0 - Filesys-Notify-Simple-0.12 - pathname: M/MI/MIYAGAWA/Filesys-Notify-Simple-0.12.tar.gz + Filesys-Notify-Simple-0.14 + pathname: M/MI/MIYAGAWA/Filesys-Notify-Simple-0.14.tar.gz provides: - Filesys::Notify::Simple 0.12 + Filesys::Notify::Simple 0.14 requirements: - ExtUtils::MakeMaker 6.30 - Find-Lib-1.04 - pathname: Y/YA/YANNK/Find-Lib-1.04.tar.gz + ExtUtils::MakeMaker 0 + perl 5.008001 + Getopt-Long-2.58 + pathname: J/JV/JV/Getopt-Long-2.58.tar.gz provides: - Find::Lib 1.04 + Getopt::Long 2.58 + Getopt::Long::Parser 2.58 requirements: ExtUtils::MakeMaker 0 - File::Spec 0 - Test::More 0 - Getopt-Long-Descriptive-0.097 - pathname: R/RJ/RJBS/Getopt-Long-Descriptive-0.097.tar.gz + Pod::Usage 1.14 + Getopt-Long-Descriptive-0.116 + pathname: R/RJ/RJBS/Getopt-Long-Descriptive-0.116.tar.gz provides: - Getopt::Long::Descriptive 0.097 - Getopt::Long::Descriptive::Opts 0.097 - Getopt::Long::Descriptive::Usage 0.097 + Getopt::Long::Descriptive 0.116 + Getopt::Long::Descriptive::Opts 0.116 + Getopt::Long::Descriptive::Usage 0.116 requirements: Carp 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 6.78 File::Basename 0 - Getopt::Long 2.33 + Getopt::Long 2.55 List::Util 0 Params::Validate 0.97 Scalar::Util 0 Sub::Exporter 0.972 Sub::Exporter::Util 0 overload 0 + perl 5.012 strict 0 warnings 0 - Getopt-Usaginator-0.0012 - pathname: R/RO/ROKR/Getopt-Usaginator-0.0012.tar.gz + Gravatar-URL-1.07 + pathname: M/MS/MSCHWERN/Gravatar-URL-1.07.tar.gz provides: - Getopt::Usaginator 0.0012 - requirements: - ExtUtils::MakeMaker 6.31 - File::Spec 0 - IPC::Open3 0 - Package::Pkg 0.0014 - Test::Most 0 - Graph-0.96 - pathname: J/JH/JHI/Graph-0.96.tar.gz - provides: - Graph 0.96 - Graph::AdjacencyMap undef - Graph::AdjacencyMap::Heavy undef - Graph::AdjacencyMap::Light undef - Graph::AdjacencyMap::Vertex undef - Graph::AdjacencyMatrix undef - Graph::Attribute undef - Graph::BitMatrix undef - Graph::Directed undef - Graph::MSTHeapElem 0.01 - Graph::Matrix undef - Graph::SPTHeapElem 0.01 - Graph::TransitiveClosure undef - Graph::TransitiveClosure::Matrix undef - Graph::Traversal undef - Graph::Traversal::BFS undef - Graph::Traversal::DFS undef - Graph::Undirected undef - Graph::UnionFind undef - Heap071::Elem 0.71 - Heap071::Fibonacci 0.71 - requirements: - ExtUtils::MakeMaker 0 - List::Util 0 - Math::Complex 0 - Safe 0 - Scalar::Util 0 - Storable 2.05 - Test::More 0 - Graph-Centrality-Pagerank-1.05 - pathname: K/KU/KUBINA/Graph-Centrality-Pagerank-1.05.tar.gz - provides: - Graph::Centrality::Pagerank 1.05 - requirements: - Data::Dump 1.14 - ExtUtils::MakeMaker 0 - Graph 0.91 - Gravatar-URL-1.06 - pathname: M/MS/MSCHWERN/Gravatar-URL-1.06.tar.gz - provides: - Gravatar::URL 1.06 - Libravatar::URL 1.06 - Unicornify::URL 1.06 + Gravatar::URL 1.07 + Libravatar::URL 1.07 + Unicornify::URL 1.07 requirements: Carp 0 Digest::MD5 0 Digest::SHA 0 - Net::DNS::Resolver 0 + Net::DNS 1.01 + Test::MockRandom 1.01 Test::More 0.4 Test::Warn 0.11 URI::Escape 0 parent 0 perl v5.6.0 - Guard-1.022 - pathname: M/ML/MLEHMANN/Guard-1.022.tar.gz - provides: - Guard 1.022 - requirements: - ExtUtils::MakeMaker 0 - HTML-Form-6.03 - pathname: G/GA/GAAS/HTML-Form-6.03.tar.gz - provides: - HTML::Form 6.03 - HTML::Form::FileInput 6.03 - HTML::Form::IgnoreInput 6.03 - HTML::Form::ImageInput 6.03 - HTML::Form::Input 6.03 - HTML::Form::KeygenInput 6.03 - HTML::Form::ListInput 6.03 - HTML::Form::SubmitInput 6.03 - HTML::Form::TextInput 6.03 - requirements: - Encode 2 - ExtUtils::MakeMaker 0 - HTML::TokeParser 0 - HTTP::Request 6 - HTTP::Request::Common 6.03 - URI 1.10 - perl 5.008001 - HTML-Parser-3.71 - pathname: G/GA/GAAS/HTML-Parser-3.71.tar.gz + HTML-Parser-3.83 + pathname: O/OA/OALDERS/HTML-Parser-3.83.tar.gz provides: - HTML::Entities 3.69 - HTML::Filter 3.57 - HTML::HeadParser 3.71 - HTML::LinkExtor 3.69 - HTML::Parser 3.71 - HTML::PullParser 3.57 - HTML::TokeParser 3.69 + HTML::Entities 3.83 + HTML::Filter 3.83 + HTML::HeadParser 3.83 + HTML::LinkExtor 3.83 + HTML::Parser 3.83 + HTML::PullParser 3.83 + HTML::TokeParser 3.83 requirements: - ExtUtils::MakeMaker 0 - HTML::Tagset 3 + Carp 0 + Exporter 0 + ExtUtils::MakeMaker 6.52 + HTML::Tagset 0 + HTTP::Headers 0 + IO::File 0 + URI 0 + URI::URL 0 XSLoader 0 - perl 5.008 - HTML-Tagset-3.20 - pathname: P/PE/PETDANCE/HTML-Tagset-3.20.tar.gz - provides: - HTML::Tagset 3.20 - requirements: - ExtUtils::MakeMaker 0 - HTML-Tiny-1.05 - pathname: A/AN/ANDYA/HTML-Tiny-1.05.tar.gz - provides: - HTML::Tiny 1.05 - requirements: - ExtUtils::MakeMaker 0 - Test::More 0 - HTML-TokeParser-Simple-3.16 - pathname: O/OV/OVID/HTML-TokeParser-Simple-3.16.tar.gz - provides: - HTML::TokeParser::Simple 3.16 - HTML::TokeParser::Simple::Token 3.16 - HTML::TokeParser::Simple::Token::Comment 3.16 - HTML::TokeParser::Simple::Token::Declaration 3.15 - HTML::TokeParser::Simple::Token::ProcessInstruction 3.16 - HTML::TokeParser::Simple::Token::Tag 3.16 - HTML::TokeParser::Simple::Token::Tag::End 3.16 - HTML::TokeParser::Simple::Token::Tag::Start 3.16 - HTML::TokeParser::Simple::Token::Text 3.16 - requirements: - HTML::Parser 3.25 - HTML::TokeParser 2.24 - Sub::Override 0 - Test::More 0 - perl 5.006 - HTML-Tree-5.03 - pathname: C/CJ/CJM/HTML-Tree-5.03.tar.gz + strict 0 + HTML-Tagset-3.24 + pathname: P/PE/PETDANCE/HTML-Tagset-3.24.tar.gz provides: - HTML::AsSubs 5.03 - HTML::Element 5.03 - HTML::Element::traverse 5.03 - HTML::Parse 5.03 - HTML::Tree 5.03 - HTML::TreeBuilder 5.03 + HTML::Tagset 3.24 requirements: - Carp 0 - Encode 0 - Exporter 0 - HTML::Entities 0 - HTML::Parser 3.46 - HTML::Tagset 3.02 - Module::Build 0.2808 - Scalar::Util 0 - Test::Fatal 0 - Test::More 0 - base 0 - integer 0 - perl 5.008 - HTTP-Body-1.19 - pathname: G/GE/GETTY/HTTP-Body-1.19.tar.gz + ExtUtils::MakeMaker 6.46 + perl 5.010001 + HTTP-Body-1.23 + pathname: G/GE/GETTY/HTTP-Body-1.23.tar.gz provides: - HTTP::Body 1.19 - HTTP::Body::MultiPart 1.19 - HTTP::Body::OctetStream 1.19 - HTTP::Body::UrlEncoded 1.19 - HTTP::Body::XForms 1.19 - HTTP::Body::XFormsMultipart 1.19 - PAML undef + HTTP::Body 1.23 + HTTP::Body::MultiPart 1.23 + HTTP::Body::OctetStream 1.23 + HTTP::Body::UrlEncoded 1.23 + HTTP::Body::XForms 1.23 + HTTP::Body::XFormsMultipart 1.23 requirements: Carp 0 Digest::MD5 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 File::Temp 0.14 HTTP::Headers 0 IO::File 1.14 - HTTP-Cookies-6.01 - pathname: G/GA/GAAS/HTTP-Cookies-6.01.tar.gz + HTTP-Cookies-6.11 + pathname: O/OA/OALDERS/HTTP-Cookies-6.11.tar.gz provides: - HTTP::Cookies 6.01 - HTTP::Cookies::Microsoft 6.00 - HTTP::Cookies::Netscape 6.00 + HTTP::Cookies 6.11 + HTTP::Cookies::Microsoft 6.11 + HTTP::Cookies::Netscape 6.11 requirements: + Carp 0 ExtUtils::MakeMaker 0 HTTP::Date 6 HTTP::Headers::Util 6 - Time::Local 0 + HTTP::Request 0 + locale 0 perl 5.008001 - HTTP-Daemon-6.01 - pathname: G/GA/GAAS/HTTP-Daemon-6.01.tar.gz + strict 0 + HTTP-Date-6.06 + pathname: O/OA/OALDERS/HTTP-Date-6.06.tar.gz provides: - HTTP::Daemon 6.01 - HTTP::Daemon::ClientConn 6.01 + HTTP::Date 6.06 requirements: + Exporter 0 ExtUtils::MakeMaker 0 - HTTP::Date 6 - HTTP::Request 6 - HTTP::Response 6 - HTTP::Status 6 - IO::Socket 0 - LWP::MediaTypes 6 - Sys::Hostname 0 - perl 5.008001 - HTTP-Date-6.02 - pathname: G/GA/GAAS/HTTP-Date-6.02.tar.gz + Time::Local 1.28 + Time::Zone 0 + perl 5.006002 + strict 0 + HTTP-Entity-Parser-0.25 + pathname: K/KA/KAZEBURO/HTTP-Entity-Parser-0.25.tar.gz provides: - HTTP::Date 6.02 + HTTP::Entity::Parser 0.25 + HTTP::Entity::Parser::JSON undef + HTTP::Entity::Parser::MultiPart undef + HTTP::Entity::Parser::OctetStream undef + HTTP::Entity::Parser::UrlEncoded undef requirements: - ExtUtils::MakeMaker 0 - Time::Local 0 - perl 5.006002 - HTTP-Lite-2.43 - pathname: N/NE/NEILB/HTTP-Lite-2.43.tar.gz + Encode 0 + File::Temp 0 + HTTP::MultiPartParser 0 + Hash::MultiValue 0 + JSON::MaybeXS 1.003007 + Module::Build::Tiny 0.035 + Module::Load 0 + Stream::Buffered 0 + WWW::Form::UrlEncoded 0.23 + perl 5.008001 + HTTP-Headers-Fast-0.22 + pathname: T/TO/TOKUHIROM/HTTP-Headers-Fast-0.22.tar.gz provides: - HTTP::Lite 2.43 + HTTP::Headers::Fast 0.22 requirements: - ExtUtils::MakeMaker 6.42 - perl 5.005 - HTTP-Message-6.06 - pathname: G/GA/GAAS/HTTP-Message-6.06.tar.gz - provides: - HTTP::Config 6.00 - HTTP::Headers 6.05 - HTTP::Headers::Auth 6.00 - HTTP::Headers::ETag 6.00 - HTTP::Headers::Util 6.03 - HTTP::Message 6.06 - HTTP::Request 6.00 - HTTP::Request::Common 6.04 - HTTP::Response 6.04 - HTTP::Status 6.03 + HTTP::Date 0 + Module::Build::Tiny 0.035 + perl 5.008001 + HTTP-Message-7.00 + pathname: O/OA/OALDERS/HTTP-Message-7.00.tar.gz + provides: + HTTP::Config 7.00 + HTTP::Headers 7.00 + HTTP::Headers::Auth 7.00 + HTTP::Headers::ETag 7.00 + HTTP::Headers::Util 7.00 + HTTP::Message 7.00 + HTTP::Request 7.00 + HTTP::Request::Common 7.00 + HTTP::Response 7.00 + HTTP::Status 7.00 requirements: - Compress::Raw::Zlib 0 - Encode 2.21 + Carp 0 + Clone 0.46 + Compress::Raw::Bzip2 0 + Compress::Raw::Zlib 2.062 + Encode 3.01 Encode::Locale 1 + Exporter 5.57 ExtUtils::MakeMaker 0 + File::Spec 0 HTTP::Date 6 IO::Compress::Bzip2 2.021 IO::Compress::Deflate 0 IO::Compress::Gzip 0 IO::HTML 0 - IO::Uncompress::Bunzip2 2.021 - IO::Uncompress::Gunzip 0 IO::Uncompress::Inflate 0 IO::Uncompress::RawInflate 0 LWP::MediaTypes 6 MIME::Base64 2.1 MIME::QuotedPrint 0 URI 1.10 + parent 0 + perl 5.008001 + strict 0 + warnings 0 + HTTP-MultiPartParser-0.02 + pathname: C/CH/CHANSEN/HTTP-MultiPartParser-0.02.tar.gz + provides: + HTTP::MultiPartParser 0.02 + requirements: + Carp 0 + ExtUtils::MakeMaker 6.59 + Scalar::Util 0 + Test::Deep 0 + Test::More 0.88 perl 5.008001 HTTP-Negotiate-6.01 pathname: G/GA/GAAS/HTTP-Negotiate-6.01.tar.gz @@ -3675,426 +2782,490 @@ DISTRIBUTIONS ExtUtils::MakeMaker 0 HTTP::Headers 6 perl 5.008001 - HTTP-Parser-XS-0.16 - pathname: K/KA/KAZUHO/HTTP-Parser-XS-0.16.tar.gz + HTTP-Thin-0.006 + pathname: P/PE/PERIGRIN/HTTP-Thin-0.006.tar.gz provides: - HTTP::Parser::XS 0.16 - HTTP::Parser::XS::PP undef + HTTP::Thin 0.006 requirements: - ExtUtils::MakeMaker 6.42 - Test::More 0.96 - HTTP-Request-AsCGI-1.2 - pathname: F/FL/FLORA/HTTP-Request-AsCGI-1.2.tar.gz - provides: - HTTP::Request::AsCGI 1.2 - requirements: - Carp 0 - Class::Accessor 0 - ExtUtils::MakeMaker 0 - HTTP::Request 0 - HTTP::Response 1.53 - IO::File 0 - Test::More 0 - URI::Escape 0 - HTTP-Server-Simple-0.44 - pathname: J/JE/JESSE/HTTP-Server-Simple-0.44.tar.gz - provides: - HTTP::Server::Simple 0.44 - HTTP::Server::Simple::CGI undef - HTTP::Server::Simple::CGI::Environment undef - requirements: - CGI 0 - ExtUtils::MakeMaker 6.42 - Socket 0 - Test::More 0 - HTTP-Tiny-0.043 - pathname: D/DA/DAGOLDEN/HTTP-Tiny-0.043.tar.gz + Class::Method::Modifiers 0 + ExtUtils::MakeMaker 6.30 + HTTP::Response 0 + HTTP::Tiny 0 + Hash::MultiValue 0 + Safe::Isa 0 + parent 0 + warnings 0 + HTTP-Tiny-0.090 + pathname: H/HA/HAARG/HTTP-Tiny-0.090.tar.gz provides: - HTTP::Tiny 0.043 + HTTP::Tiny 0.090 requirements: Carp 0 ExtUtils::MakeMaker 6.17 Fcntl 0 IO::Socket 0 MIME::Base64 0 + Socket 0 Time::Local 0 bytes 0 + perl 5.006 strict 0 warnings 0 - Hash-Merge-0.200 - pathname: R/RE/REHSACK/Hash-Merge-0.200.tar.gz + Hash-Merge-0.302 + pathname: H/HE/HERMES/Hash-Merge-0.302.tar.gz provides: - Hash::Merge 0.200 + Hash::Merge 0.302 requirements: - Clone 0 - ExtUtils::MakeMaker 0 + Clone::Choose 0.008 + ExtUtils::MakeMaker 6.64 + Scalar::Util 0 perl 5.008001 - Hash-Merge-Simple-0.051 - pathname: R/RO/ROKR/Hash-Merge-Simple-0.051.tar.gz + Hash-Merge-Simple-0.052 + pathname: H/HA/HAARG/Hash-Merge-Simple-0.052.tar.gz provides: - Hash::Merge::Simple 0.051 + Hash::Merge::Simple 0.052 requirements: Clone 0 - ExtUtils::MakeMaker 6.31 + ExtUtils::MakeMaker 0 Storable 0 - Test::Most 0 - Hash-MoreUtils-0.05 - pathname: R/RE/REHSACK/Hash-MoreUtils-0.05.tar.gz + perl 5.006000 + Hash-MoreUtils-0.06 + pathname: R/RE/REHSACK/Hash-MoreUtils-0.06.tar.gz provides: - Hash::MoreUtils 0.05 + Hash::MoreUtils 0.06 requirements: - Test::More 0.90 - Hash-MultiValue-0.15 - pathname: M/MI/MIYAGAWA/Hash-MultiValue-0.15.tar.gz + ExtUtils::MakeMaker 0 + perl 5.008001 + Hash-MultiValue-0.16 + pathname: A/AR/ARISTOTLE/Hash-MultiValue-0.16.tar.gz provides: - Hash::MultiValue 0.15 + Hash::MultiValue 0.16 requirements: - ExtUtils::MakeMaker 6.30 - Hook-LexWrap-0.24 - pathname: C/CH/CHORNY/Hook-LexWrap-0.24.tar.gz - provides: - Hook::LexWrap 0.24 + ExtUtils::MakeMaker 0 + perl 5.008001 + IO-1.55 + pathname: T/TO/TODDR/IO-1.55.tar.gz + provides: + IO 1.55 + IO::Dir 1.55 + IO::File 1.55 + IO::Handle 1.55 + IO::Pipe 1.55 + IO::Pipe::End 1.55 + IO::Poll 1.55 + IO::Seekable 1.55 + IO::Select 1.55 + IO::Socket 1.55 + IO::Socket::INET 1.55 + IO::Socket::UNIX 1.55 requirements: + ExtUtils::MakeMaker 0 + File::Temp 0.15 Test::More 0 - perl 5.006 - IO-All-0.61 - pathname: F/FR/FREW/IO-All-0.61.tar.gz - provides: - IO::All 0.61 - IO::All::Base 0.61 - IO::All::DBM 0.61 - IO::All::Dir 0.61 - IO::All::File 0.61 - IO::All::Filesys 0.61 - IO::All::Link 0.61 - IO::All::MLDBM 0.61 - IO::All::Pipe 0.61 - IO::All::STDIO 0.61 - IO::All::Socket 0.61 - IO::All::String 0.61 - IO::All::Temp 0.61 - IO_All_Test undef - IO_Dumper undef - requirements: - Cwd 0 - ExtUtils::MakeMaker 6.30 + IO-Compress-2.213 + pathname: P/PM/PMQS/IO-Compress-2.213.tar.gz + provides: + Compress::Zlib 2.213 + File::GlobMapper 1.001 + IO::Compress 2.213 + IO::Compress::Adapter::Bzip2 2.213 + IO::Compress::Adapter::Deflate 2.213 + IO::Compress::Adapter::Identity 2.213 + IO::Compress::Base 2.213 + IO::Compress::Base::Common 2.213 + IO::Compress::Bzip2 2.213 + IO::Compress::Deflate 2.213 + IO::Compress::Gzip 2.213 + IO::Compress::Gzip::Constants 2.213 + IO::Compress::RawDeflate 2.213 + IO::Compress::Zip 2.213 + IO::Compress::Zip::Constants 2.213 + IO::Compress::Zlib::Constants 2.213 + IO::Compress::Zlib::Extra 2.213 + IO::Uncompress::Adapter::Bunzip2 2.213 + IO::Uncompress::Adapter::Identity 2.213 + IO::Uncompress::Adapter::Inflate 2.213 + IO::Uncompress::AnyInflate 2.213 + IO::Uncompress::AnyUncompress 2.213 + IO::Uncompress::Base 2.213 + IO::Uncompress::Bunzip2 2.213 + IO::Uncompress::Gunzip 2.213 + IO::Uncompress::Inflate 2.213 + IO::Uncompress::RawInflate 2.213 + IO::Uncompress::Unzip 2.213 + U64 2.213 + Zlib::OldDeflate 2.213 + Zlib::OldInflate 2.213 + requirements: + Compress::Raw::Bzip2 2.213 + Compress::Raw::Zlib 2.213 + Encode 0 + ExtUtils::MakeMaker 0 Scalar::Util 0 - IO-CaptureOutput-1.1103 - pathname: D/DA/DAGOLDEN/IO-CaptureOutput-1.1103.tar.gz + Time::Local 0 + IO-File-AtomicChange-0.08 + pathname: H/HI/HIROSE/IO-File-AtomicChange-0.08.tar.gz provides: - IO::CaptureOutput 1.1103 + IO::File::AtomicChange 0.08 requirements: - Carp 0 - Exporter 0 - ExtUtils::MakeMaker 6.17 - File::Basename 0 - File::Temp 0.16 - Symbol 0 - strict 0 - vars 0 - warnings 0 - IO-HTML-1.00 - pathname: C/CJ/CJM/IO-HTML-1.00.tar.gz + File::Copy 0 + File::Temp 0 + IO 1.39 + Module::Build::Tiny 0.039 + POSIX 0 + Path::Class 0 + Time::HiRes 0 + perl 5.008005 + IO-HTML-1.004 + pathname: C/CJ/CJM/IO-HTML-1.004.tar.gz provides: - IO::HTML 1.00 + IO::HTML 1.004 requirements: Carp 0 Encode 2.10 Exporter 5.57 - ExtUtils::MakeMaker 6.30 - File::Temp 0 - Scalar::Util 0 - Test::More 0.88 - IO-Interactive-0.0.6 - pathname: B/BD/BDFOY/IO-Interactive-0.0.6.tar.gz + ExtUtils::MakeMaker 0 + perl 5.008 + IO-Prompt-Tiny-0.003 + pathname: D/DA/DAGOLDEN/IO-Prompt-Tiny-0.003.tar.gz provides: - IO::Interactive 0.000006 + IO::Prompt::Tiny 0.003 requirements: - ExtUtils::MakeMaker 0 - Test::More 0 - version 0 - IO-Socket-SSL-1.992 - pathname: S/SU/SULLR/IO-Socket-SSL-1.992.tar.gz + Carp 0 + Exporter 0 + ExtUtils::MakeMaker 6.17 + perl 5.006 + strict 0 + warnings 0 + IO-Socket-IP-0.43 + pathname: P/PE/PEVANS/IO-Socket-IP-0.43.tar.gz provides: - IO::Socket::SSL 1.992 - IO::Socket::SSL::Intercept 1.93 - IO::Socket::SSL::OCSP_Cache 1.992 - IO::Socket::SSL::OCSP_Resolver 1.992 + IO::Socket::IP 0.43 + requirements: + IO::Socket 0 + Module::Build 0.4004 + Socket 1.97 + perl 5.014 + IO-Socket-SSL-2.089 + pathname: S/SU/SULLR/IO-Socket-SSL-2.089.tar.gz + provides: + IO::Socket::SSL 2.089 + IO::Socket::SSL::Intercept 2.056 + IO::Socket::SSL::OCSP_Cache 2.089 + IO::Socket::SSL::OCSP_Resolver 2.089 IO::Socket::SSL::PublicSuffix undef - IO::Socket::SSL::SSL_Context 1.992 - IO::Socket::SSL::SSL_HANDLE 1.992 - IO::Socket::SSL::Session_Cache 1.992 - IO::Socket::SSL::Utils 0.02 + IO::Socket::SSL::SSL_Context 2.089 + IO::Socket::SSL::SSL_HANDLE 2.089 + IO::Socket::SSL::Session_Cache 2.089 + IO::Socket::SSL::Trace 2.089 + IO::Socket::SSL::Utils 2.015 requirements: ExtUtils::MakeMaker 0 - Mozilla::CA 0 Net::SSLeay 1.46 Scalar::Util 0 - IO-String-1.08 - pathname: G/GA/GAAS/IO-String-1.08.tar.gz - provides: - IO::String 1.08 - requirements: - ExtUtils::MakeMaker 0 - IO-stringy-2.110 - pathname: D/DS/DSKOLL/IO-stringy-2.110.tar.gz - provides: - Common undef - ExtUtils::TBone 1.1 - IO::AtomicFile 2.110 - IO::Clever 1.01 - IO::InnerFile 2.110 - IO::Lines 2.110 - IO::Scalar 2.110 - IO::ScalarArray 2.110 - IO::Stringy 2.110 - IO::Wrap 2.110 - IO::WrapTie 2.110 - IO::WrapTie::Master 2.110 - IO::WrapTie::Slave 2.110 - requirements: - ExtUtils::MakeMaker 0 - IPC-Run3-0.048 - pathname: R/RJ/RJBS/IPC-Run3-0.048.tar.gz + IPC-Run3-0.049 + pathname: R/RJ/RJBS/IPC-Run3-0.049.tar.gz provides: - IPC::Run3 0.048 + IPC::Run3 0.049 requirements: ExtUtils::MakeMaker 0 Test::More 0.31 Time::HiRes 0 - IPC-System-Simple-1.25 - pathname: P/PJ/PJF/IPC-System-Simple-1.25.tar.gz + IPC-System-Simple-1.30 + pathname: J/JK/JKEENAN/IPC-System-Simple-1.30.tar.gz provides: - IPC::System::Simple 1.25 + IPC::System::Simple 1.30 requirements: Carp 0 Exporter 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 List::Util 0 POSIX 0 Scalar::Util 0 constant 0 + perl 5.006 re 0 strict 0 warnings 0 - Import-Into-1.002002 - pathname: E/ET/ETHER/Import-Into-1.002002.tar.gz + Import-Into-1.002005 + pathname: H/HA/HAARG/Import-Into-1.002005.tar.gz provides: - Import::Into 1.002002 + Import::Into 1.002005 requirements: ExtUtils::MakeMaker 0 + Module::Runtime 0 perl 5.006 - Iterator-0.03 - pathname: R/RO/ROODE/Iterator-0.03.tar.gz - provides: - Iterator 0.03 - requirements: - Exception::Class 1.21 - ExtUtils::MakeMaker 0 - Test::Simple 0.40 - Iterator-Util-0.02 - pathname: R/RO/ROODE/Iterator-Util-0.02.tar.gz - provides: - Iterator::Util 0.02 - requirements: - Exception::Class 1.21 - ExtUtils::MakeMaker 0 - Iterator 0.01 - Test::Simple 0.40 - JSON-2.90 - pathname: M/MA/MAKAMAKA/JSON-2.90.tar.gz + strict 0 + warnings 0 + JSON-4.10 + pathname: I/IS/ISHIGAKI/JSON-4.10.tar.gz provides: - JSON 2.90 - JSON::Backend::PP 2.90 - JSON::Boolean 2.90 + JSON 4.10 + JSON::Backend::PP 4.10 requirements: ExtUtils::MakeMaker 0 Test::More 0 - JSON-Any-1.34 - pathname: E/ET/ETHER/JSON-Any-1.34.tar.gz + JSON-MaybeXS-1.004008 + pathname: E/ET/ETHER/JSON-MaybeXS-1.004008.tar.gz provides: - JSON::Any 1.34 + JSON::MaybeXS 1.004008 requirements: Carp 0 - ExtUtils::MakeMaker 6.30 - constant 0 - strict 0 - warnings 0 - JSON-MaybeXS-1.002002 - pathname: E/ET/ETHER/JSON-MaybeXS-1.002002.tar.gz - provides: - JSON::MaybeXS 1.002002 - requirements: Cpanel::JSON::XS 2.3310 - ExtUtils::CBuilder 0.27 ExtUtils::MakeMaker 0 - File::Spec 0 - File::Temp 0 - JSON::PP 2.27202 + JSON::PP 2.27300 + Scalar::Util 0 perl 5.006 - JSON-XS-3.01 - pathname: M/ML/MLEHMANN/JSON-XS-3.01.tar.gz - provides: - JSON::XS 3.01 - requirements: - ExtUtils::MakeMaker 0 + JSON-Validator-5.15 + pathname: J/JH/JHTHORSEN/JSON-Validator-5.15.tar.gz + provides: + JSON::Validator 5.15 + JSON::Validator::Error undef + JSON::Validator::Formats undef + JSON::Validator::Joi undef + JSON::Validator::Schema undef + JSON::Validator::Schema::Draft201909 undef + JSON::Validator::Schema::Draft4 undef + JSON::Validator::Schema::Draft6 undef + JSON::Validator::Schema::Draft7 undef + JSON::Validator::Schema::OpenAPIv2 undef + JSON::Validator::Schema::OpenAPIv3 undef + JSON::Validator::Store undef + JSON::Validator::URI undef + JSON::Validator::Util undef + requirements: + ExtUtils::MakeMaker 0 + List::Util 1.45 + Mojolicious 7.28 + YAML::XS 0.67 + perl 5.016 + JSON-XS-4.03 + pathname: M/ML/MLEHMANN/JSON-XS-4.03.tar.gz + provides: + JSON::XS 4.03 + requirements: + Canary::Stability 0 + ExtUtils::MakeMaker 6.52 Types::Serialiser 0 common::sense 0 - LWP-MediaTypes-6.02 - pathname: G/GA/GAAS/LWP-MediaTypes-6.02.tar.gz + LWP-MediaTypes-6.04 + pathname: O/OA/OALDERS/LWP-MediaTypes-6.04.tar.gz provides: - LWP::MediaTypes 6.02 + LWP::MediaTypes 6.04 requirements: + Carp 0 + Exporter 0 ExtUtils::MakeMaker 0 + File::Basename 0 + Scalar::Util 0 perl 5.006002 - LWP-Protocol-https-6.04 - pathname: G/GA/GAAS/LWP-Protocol-https-6.04.tar.gz + strict 0 + LWP-Protocol-https-6.14 + pathname: O/OA/OALDERS/LWP-Protocol-https-6.14.tar.gz provides: - LWP::Protocol::https 6.04 - LWP::Protocol::https::Socket 6.04 + LWP::Protocol::https 6.14 + LWP::Protocol::https::Socket 6.14 requirements: ExtUtils::MakeMaker 0 - IO::Socket::SSL 1.54 - LWP::UserAgent 6.04 - Mozilla::CA 20110101 + IO::Socket::SSL 1.970 + LWP::Protocol::http 0 + LWP::UserAgent 6.06 Net::HTTPS 6 + base 0 perl 5.008001 - LWP-UserAgent-Paranoid-0.95 - pathname: T/TS/TSIBLEY/LWP-UserAgent-Paranoid-0.95.tar.gz + strict 0 + Lingua-EN-Inflect-1.905 + pathname: D/DC/DCONWAY/Lingua-EN-Inflect-1.905.tar.gz provides: - LWP::UserAgent::Paranoid 0.95 - LWP::UserAgent::Paranoid::Test undef + Lingua::EN::Inflect 1.905 requirements: - ExtUtils::MakeMaker 6.36 - HTTP::Server::PSGI 0 - LWP::UserAgent 0 - LWPx::ParanoidHandler 0 - Net::DNS::Paranoid 0 - Scalar::Util 0 - Test::Requires 0 - Test::TCP 0 - Time::HiRes 1.9716 - LWPx-ParanoidAgent-1.10 - pathname: S/SA/SAXJAZMAN/lwp/LWPx-ParanoidAgent-1.10.tar.gz + ExtUtils::MakeMaker 0 + Test::More 0 + List-Compare-0.55 + pathname: J/JK/JKEENAN/List-Compare-0.55.tar.gz provides: - LWPx::ParanoidAgent 1.10 - LWPx::Protocol::http_paranoid undef - LWPx::Protocol::http_paranoid::Socket undef - LWPx::Protocol::http_paranoid::SocketMethods undef - LWPx::Protocol::https_paranoid undef - LWPx::Protocol::https_paranoid::Socket undef + List::Compare 0.55 + List::Compare::Accelerated 0.55 + List::Compare::Base::_Auxiliary 0.55 + List::Compare::Base::_Engine 0.55 + List::Compare::Functional 0.55 + List::Compare::Multiple 0.55 + List::Compare::Multiple::Accelerated 0.55 requirements: ExtUtils::MakeMaker 0 - LWP::UserAgent 0 - Net::DNS 0 - Net::SSL 2.85 - Time::HiRes 0 - LWPx-ParanoidHandler-0.07 - pathname: T/TO/TOKUHIROM/LWPx-ParanoidHandler-0.07.tar.gz + List-MoreUtils-0.430 + pathname: R/RE/REHSACK/List-MoreUtils-0.430.tar.gz provides: - LWPx::ParanoidHandler 0.07 + List::MoreUtils 0.430 + List::MoreUtils::PP 0.430 requirements: - CPAN::Meta 0 - CPAN::Meta::Prereqs 0 - Exporter 0 - ExtUtils::CBuilder 0 - LWP 6 - Module::Build 0.38 - Net::DNS::Paranoid 0.07 - parent 0 - perl 5.008008 - Lexical-SealRequireHints-0.007 - pathname: Z/ZE/ZEFRAM/Lexical-SealRequireHints-0.007.tar.gz + Exporter::Tiny 0.038 + ExtUtils::MakeMaker 0 + List::MoreUtils::XS 0.430 + List-MoreUtils-XS-0.430 + pathname: R/RE/REHSACK/List-MoreUtils-XS-0.430.tar.gz provides: - Lexical::SealRequireHints 0.007 + List::MoreUtils::XS 0.430 requirements: - Module::Build 0 - Test::More 0 + Carp 0 + ExtUtils::MakeMaker 0 + File::Basename 0 + File::Copy 0 + File::Path 0 + File::Spec 0 + IPC::Cmd 0 + XSLoader 0.22 + base 0 + List-SomeUtils-0.59 + pathname: D/DR/DROLSKY/List-SomeUtils-0.59.tar.gz + provides: + List::SomeUtils 0.59 + List::SomeUtils::PP 0.59 + requirements: + Carp 0 + Exporter 0 + ExtUtils::MakeMaker 0 + List::SomeUtils::XS 0.54 + List::Util 0 + Module::Implementation 0.04 + Text::ParseWords 0 perl 5.006 strict 0 + vars 0 warnings 0 - Lingua-EN-Inflect-1.895 - pathname: D/DC/DCONWAY/Lingua-EN-Inflect-1.895.tar.gz - provides: - Lingua::EN::Inflect 1.895 - requirements: - Test::More 0 - version 0 - List-AllUtils-0.09 - pathname: D/DR/DROLSKY/List-AllUtils-0.09.tar.gz + List-SomeUtils-XS-0.58 + pathname: D/DR/DROLSKY/List-SomeUtils-XS-0.58.tar.gz provides: - List::AllUtils 0.09 + List::SomeUtils::XS 0.58 requirements: - Exporter 0 ExtUtils::MakeMaker 0 - List::MoreUtils 0.28 - List::Util 1.31 + XSLoader 0 + strict 0 + warnings 0 + Log-Any-1.717 + pathname: P/PR/PREACTION/Log-Any-1.717.tar.gz + provides: + Log::Any 1.717 + Log::Any::Adapter 1.717 + Log::Any::Adapter::Base 1.717 + Log::Any::Adapter::Capture 1.717 + Log::Any::Adapter::File 1.717 + Log::Any::Adapter::Multiplex 1.717 + Log::Any::Adapter::Null 1.717 + Log::Any::Adapter::Stderr 1.717 + Log::Any::Adapter::Stdout 1.717 + Log::Any::Adapter::Syslog 1.717 + Log::Any::Adapter::Test 1.717 + Log::Any::Adapter::Util 1.717 + Log::Any::Manager 1.717 + Log::Any::Proxy 1.717 + Log::Any::Proxy::Null 1.717 + Log::Any::Proxy::Test 1.717 + Log::Any::Proxy::WithStackTrace 1.717 + Log::Any::Test 1.717 + requirements: + ExtUtils::MakeMaker 0 + Log-Any-Adapter-Log4perl-0.09 + pathname: P/PR/PREACTION/Log-Any-Adapter-Log4perl-0.09.tar.gz + provides: + Log::Any::Adapter::Log4perl 0.09 + requirements: + ExtUtils::MakeMaker 6.17 + Log::Any::Adapter::Base 0 + Log::Any::Adapter::Util 1.03 + Log::Log4perl 1.32 base 0 + perl 5.006 strict 0 warnings 0 - List-MoreUtils-0.33 - pathname: A/AD/ADAMK/List-MoreUtils-0.33.tar.gz - provides: - List::MoreUtils 0.33 - requirements: - ExtUtils::CBuilder 0.27 - ExtUtils::MakeMaker 6.52 - Test::More 0.82 - perl 5.00503 - Log-Any-0.15 - pathname: J/JS/JSWARTZ/Log-Any-0.15.tar.gz - provides: - Log::Any 0.15 - Log::Any::Adapter::Null 0.15 - Log::Any::Adapter::Test 0.15 - Log::Any::Test 0.15 - requirements: - ExtUtils::MakeMaker 6.30 - Test::More 0 - Log-Contextual-0.006003 - pathname: F/FR/FREW/Log-Contextual-0.006003.tar.gz - provides: - BaseLogger undef - DefaultImportLogger undef - DumbLogger2 undef - Log::Contextual 0.006003 - Log::Contextual::Easy::Default 0.006003 - Log::Contextual::Easy::Package 0.006003 - Log::Contextual::Role::Router 0.006003 - Log::Contextual::Role::Router::SetLogger 0.006003 - Log::Contextual::Role::Router::WithLogger 0.006003 - Log::Contextual::Router 0.006003 - Log::Contextual::SimpleLogger 0.006003 - Log::Contextual::TeeLogger 0.006003 - Log::Contextual::WarnLogger 0.006003 - My::Module undef - My::Module2 undef - TestExporter undef - TestRouter undef + Log-Contextual-0.009001 + pathname: H/HA/HAARG/Log-Contextual-0.009001.tar.gz + provides: + Log::Contextual 0.009001 + Log::Contextual::Easy::Default 0.009001 + Log::Contextual::Easy::Package 0.009001 + Log::Contextual::Role::Router 0.009001 + Log::Contextual::Role::Router::HasLogger 0.009001 + Log::Contextual::Role::Router::SetLogger 0.009001 + Log::Contextual::Role::Router::WithLogger 0.009001 + Log::Contextual::Router 0.009001 + Log::Contextual::SimpleLogger 0.009001 + Log::Contextual::TeeLogger 0.009001 + Log::Contextual::WarnLogger 0.009001 requirements: Carp 0 Data::Dumper::Concise 0 - Exporter::Declare 0.111 - ExtUtils::MakeMaker 6.30 - Moo 1.003 + ExtUtils::MakeMaker 0 + Moo 1.003000 + Scalar::Util 0 + perl 5.008001 + Log-Dispatch-2.71 + pathname: D/DR/DROLSKY/Log-Dispatch-2.71.tar.gz + provides: + Log::Dispatch 2.71 + Log::Dispatch::ApacheLog 2.71 + Log::Dispatch::Base 2.71 + Log::Dispatch::Code 2.71 + Log::Dispatch::Email 2.71 + Log::Dispatch::Email::MIMELite 2.71 + Log::Dispatch::Email::MailSend 2.71 + Log::Dispatch::Email::MailSender 2.71 + Log::Dispatch::Email::MailSendmail 2.71 + Log::Dispatch::File 2.71 + Log::Dispatch::File::Locked 2.71 + Log::Dispatch::Handle 2.71 + Log::Dispatch::Null 2.71 + Log::Dispatch::Output 2.71 + Log::Dispatch::Screen 2.71 + Log::Dispatch::Syslog 2.71 + Log::Dispatch::Types 2.71 + Log::Dispatch::Vars 2.71 + requirements: + Carp 0 + Devel::GlobalDestruction 0 + Dist::CheckConflicts 0.02 + Encode 0 + Exporter 0 + ExtUtils::MakeMaker 0 + Fcntl 0 + IO::Handle 0 + Module::Runtime 0 + Params::ValidationCompiler 0 Scalar::Util 0 - Log-Log4perl-1.44 - pathname: M/MS/MSCHILLI/Log-Log4perl-1.44.tar.gz + Specio 0.32 + Specio::Declare 0 + Specio::Exporter 0 + Specio::Library::Builtins 0 + Specio::Library::Numeric 0 + Specio::Library::String 0 + Sys::Syslog 0.28 + Try::Tiny 0 + base 0 + namespace::autoclean 0 + parent 0 + perl 5.006 + strict 0 + warnings 0 + Log-Log4perl-1.57 + pathname: E/ET/ETJ/Log-Log4perl-1.57.tar.gz provides: L4pResurrectable 0.01 - Log::Log4perl 1.44 + Log::Log4perl 1.57 Log::Log4perl::Appender undef + Log::Log4perl::Appender::Buffer 1.53 Log::Log4perl::Appender::DBI undef Log::Log4perl::Appender::File undef + Log::Log4perl::Appender::Limit 1.53 Log::Log4perl::Appender::RRDs undef Log::Log4perl::Appender::Screen undef Log::Log4perl::Appender::ScreenColoredLevels undef Log::Log4perl::Appender::Socket undef Log::Log4perl::Appender::String undef + Log::Log4perl::Appender::Synchronized 1.53 Log::Log4perl::Appender::TestArrayBuffer undef Log::Log4perl::Appender::TestBuffer undef Log::Log4perl::Appender::TestFileCreeper undef - Log::Log4perl::Catalyst undef + Log::Log4perl::Catalyst 1.53 Log::Log4perl::Config undef Log::Log4perl::Config::BaseConfigurator undef Log::Log4perl::Config::DOMConfigurator 0.03 @@ -4131,123 +3302,331 @@ DISTRIBUTIONS Log::Log4perl::Util::TimeTracker undef requirements: ExtUtils::MakeMaker 0 - File::Path 2.0606 + File::Path 2.07 File::Spec 0.82 - Test::More 0.45 - MIME-Base64-URLSafe-0.01 - pathname: K/KA/KAZUHO/MIME-Base64-URLSafe-0.01.tar.gz + perl 5.006 + Log-Log4perl-Layout-JSON-0.61 + pathname: M/MS/MSCHOUT/Log-Log4perl-Layout-JSON-0.61.tar.gz provides: - MIME::Base64::URLSafe 0.01 + Log::Log4perl::Layout::JSON 0.61 requirements: + Carp 0 + Class::Tiny 0 ExtUtils::MakeMaker 0 - MIME::Base64 0 - MIME-Types-2.04 - pathname: M/MA/MARKOV/MIME-Types-2.04.tar.gz + JSON::MaybeXS 0 + Log::Log4perl 0 + Log::Log4perl::Layout 0 + Log::Log4perl::Layout::PatternLayout 0 + Log::Log4perl::Level 0 + Scalar::Util 0 + parent 0 + perl 5.010 + strict 0 + warnings 0 + MCE-1.901 + pathname: M/MA/MARIOROY/MCE-1.901.tar.gz + provides: + MCE 1.901 + MCE::Candy 1.901 + MCE::Channel 1.901 + MCE::Channel::Mutex 1.901 + MCE::Channel::MutexFast 1.901 + MCE::Channel::Simple 1.901 + MCE::Channel::SimpleFast 1.901 + MCE::Channel::Threads 1.901 + MCE::Channel::ThreadsFast 1.901 + MCE::Child 1.901 + MCE::Core 1.901 + MCE::Core::Input::Generator 1.901 + MCE::Core::Input::Handle 1.901 + MCE::Core::Input::Iterator 1.901 + MCE::Core::Input::Request 1.901 + MCE::Core::Input::Sequence 1.901 + MCE::Core::Manager 1.901 + MCE::Core::Validation 1.901 + MCE::Core::Worker 1.901 + MCE::Flow 1.901 + MCE::Grep 1.901 + MCE::Loop 1.901 + MCE::Map 1.901 + MCE::Mutex 1.901 + MCE::Mutex::Channel 1.901 + MCE::Mutex::Channel2 1.901 + MCE::Mutex::Flock 1.901 + MCE::Queue 1.901 + MCE::Relay 1.901 + MCE::Signal 1.901 + MCE::Step 1.901 + MCE::Stream 1.901 + MCE::Subs 1.901 + MCE::Util 1.901 + requirements: + Carp 0 + Errno 0 + ExtUtils::MakeMaker 0 + Fcntl 0 + File::Path 0 + Getopt::Long 0 + IO::Handle 0 + Scalar::Util 0 + Socket 0 + Storable 2.04 + Time::HiRes 0 + base 0 + bytes 0 + constant 0 + open 0 + perl 5.008001 + strict 0 + warnings 0 + MIME-Base32-1.303 + pathname: R/RE/REHSACK/MIME-Base32-1.303.tar.gz + provides: + MIME::Base32 1.303 + requirements: + Exporter 0 + ExtUtils::MakeMaker 0 + perl 5.008001 + utf8 0 + MIME-Charset-1.013.1 + pathname: N/NE/NEZUMI/MIME-Charset-1.013.1.tar.gz + provides: + MIME::Charset v1.13.1 + requirements: + CPAN 0 + Encode 1.98 + ExtUtils::MakeMaker 6.42 + Test::More 0 + perl 5.005 + MIME-Types-2.28 + pathname: M/MA/MARKOV/MIME-Types-2.28.tar.gz provides: - MIME::Type 2.04 - MIME::Types 2.04 + MIME::Type 2.28 + MIME::Types 2.28 + MojoX::MIME::Types 2.28 requirements: ExtUtils::MakeMaker 0 File::Basename 0 File::Spec 0 + List::Util 0 Test::More 0.47 - MRO-Compat-0.12 - pathname: B/BO/BOBTFISH/MRO-Compat-0.12.tar.gz + MRO-Compat-0.15 + pathname: H/HA/HAARG/MRO-Compat-0.15.tar.gz provides: - MRO::Compat 0.12 + MRO::Compat 0.15 requirements: - ExtUtils::MakeMaker 6.59 - Test::More 0.47 + ExtUtils::MakeMaker 0 perl 5.006 - MailTools-2.13 - pathname: M/MA/MARKOV/MailTools-2.13.tar.gz - provides: - Mail undef - Mail::Address 2.13 - Mail::Cap 2.13 - Mail::Field 2.13 - Mail::Field::AddrList 2.13 - Mail::Field::Date 2.13 - Mail::Field::Generic 2.13 - Mail::Filter 2.13 - Mail::Header 2.13 - Mail::Internet 2.13 - Mail::Mailer 2.13 - Mail::Mailer::qmail 2.13 - Mail::Mailer::rfc822 2.13 - Mail::Mailer::sendmail 2.13 - Mail::Mailer::smtp 2.13 - Mail::Mailer::smtp::pipe 2.13 - Mail::Mailer::smtps 2.13 - Mail::Mailer::smtps::pipe 2.13 - Mail::Mailer::testfile 2.13 - Mail::Mailer::testfile::pipe 2.13 - Mail::Send 2.13 - Mail::Util 2.13 + MailTools-2.22 + pathname: M/MA/MARKOV/MailTools-2.22.tar.gz + provides: + Mail::Address 2.22 + Mail::Cap 2.22 + Mail::Field 2.22 + Mail::Field::AddrList 2.22 + Mail::Field::Date 2.22 + Mail::Field::Generic 2.22 + Mail::Filter 2.22 + Mail::Header 2.22 + Mail::Internet 2.22 + Mail::Mailer 2.22 + Mail::Mailer::qmail 2.22 + Mail::Mailer::rfc822 2.22 + Mail::Mailer::sendmail 2.22 + Mail::Mailer::smtp 2.22 + Mail::Mailer::smtp::pipe 2.22 + Mail::Mailer::smtps 2.22 + Mail::Mailer::smtps::pipe 2.22 + Mail::Mailer::testfile 2.22 + Mail::Mailer::testfile::pipe 2.22 + Mail::Send 2.22 + Mail::Util 2.22 + MailTools 2.22 requirements: Date::Format 0 Date::Parse 0 ExtUtils::MakeMaker 0 IO::Handle 0 Net::Domain 1.05 - Net::SMTP 1.03 + Net::SMTP 1.28 Test::More 0 - Meta-Builder-0.003 - pathname: E/EX/EXODIST/Meta-Builder-0.003.tar.gz + Math-BigInt-2.005003 + pathname: P/PJ/PJACKLAM/Math-BigInt-2.005003.tar.gz provides: - Meta::Builder 0.003 - Meta::Builder::Base undef - Meta::Builder::Util undef + Math::BigFloat 2.005003 + Math::BigInt 2.005003 + Math::BigInt::Calc 2.005003 + Math::BigInt::Lib 2.005003 + Math::BigRat 2.005003 + requirements: + Carp 1.22 + ExtUtils::MakeMaker 6.58 + Math::Complex 1.36 + Scalar::Util 0 + perl 5.006001 + MetaCPAN-Client-2.033000 + pathname: M/MI/MICKEY/MetaCPAN-Client-2.033000.tar.gz + provides: + MetaCPAN::Client 2.033000 + MetaCPAN::Client::Author 2.033000 + MetaCPAN::Client::Cover 2.033000 + MetaCPAN::Client::Distribution 2.033000 + MetaCPAN::Client::DownloadURL 2.033000 + MetaCPAN::Client::Favorite 2.033000 + MetaCPAN::Client::File 2.033000 + MetaCPAN::Client::Mirror 2.033000 + MetaCPAN::Client::Module 2.033000 + MetaCPAN::Client::Package 2.033000 + MetaCPAN::Client::Permission 2.033000 + MetaCPAN::Client::Pod 2.033000 + MetaCPAN::Client::Rating 2.033000 + MetaCPAN::Client::Release 2.033000 + MetaCPAN::Client::Request 2.033000 + MetaCPAN::Client::ResultSet 2.033000 + MetaCPAN::Client::Role::Entity 2.033000 + MetaCPAN::Client::Role::HasUA 2.033000 + MetaCPAN::Client::Scroll 2.033000 + MetaCPAN::Client::Types 2.033000 requirements: Carp 0 - Fennec::Lite 0 - Test::Exception 0 - Test::More 0 - Mixin-Linewise-0.106 - pathname: R/RJ/RJBS/Mixin-Linewise-0.106.tar.gz + ExtUtils::MakeMaker 7.1101 + HTTP::Tiny 0.056 + IO::Socket::SSL 1.42 + JSON::MaybeXS 0 + JSON::PP 0 + Moo 0 + Moo::Role 0 + Net::SSLeay 1.49 + Ref::Util 0 + Safe::Isa 0 + Type::Tiny 0 + URI::Escape 0 + perl 5.010 + strict 0 + warnings 0 + MetaCPAN-Moose-0.000003 + pathname: O/OA/OALDERS/MetaCPAN-Moose-0.000003.tar.gz provides: - MLTests undef - Mixin::Linewise 0.106 - Mixin::Linewise::Readers 0.106 - Mixin::Linewise::Writers 0.106 + MetaCPAN::Moose 0.000003 + requirements: + ExtUtils::MakeMaker 0 + Import::Into 1.002005 + Moose 2.1605 + MooseX::StrictConstructor 0.19 + namespace::autoclean 0.28 + perl 5.006 + strict 0 + warnings 0 + MetaCPAN-Pod-HTML-0.004000 + pathname: H/HA/HAARG/MetaCPAN-Pod-HTML-0.004000.tar.gz + provides: + MetaCPAN::Pod::HTML 0.004000 + MetaCPAN::Pod::XHTML 0.004000 + Pod::Simple::Role::StripVerbatimIndent 0.004000 + Pod::Simple::Role::WithHighlightConfig 0.004000 + Pod::Simple::Role::XHTML::HTML5 0.004000 + Pod::Simple::Role::XHTML::RepairLinkEncoding 0.004000 + Pod::Simple::Role::XHTML::WithAccurateTargets 0.004000 + Pod::Simple::Role::XHTML::WithErrata 0.004000 + Pod::Simple::Role::XHTML::WithExtraTargets 0.004000 + Pod::Simple::Role::XHTML::WithHighlightConfig 0.004000 + Pod::Simple::Role::XHTML::WithLinkMappings 0.004000 + Pod::Simple::Role::XHTML::WithPostProcess 0.004000 + requirements: + ExtUtils::MakeMaker 0 + HTML::Entities 3.69 + Moo 2.003000 + Moo::Role 2.003000 + Pod::Simple::XHTML 3.45 + URL::Encode 0.03 + namespace::clean 0.27 + MetaCPAN-Role-1.00 + pathname: L/LL/LLAP/MetaCPAN-Role-1.00.tar.gz + provides: + MetaCPAN::Role 1.00 + MetaCPAN::Role::Fastly 1.00 + MetaCPAN::Role::Fastly::Catalyst 1.00 requirements: Carp 0 - ExtUtils::MakeMaker 6.30 + CatalystX::Fastly::Role::Response 0.07 + ExtUtils::MakeMaker 0 + Moose::Role 0 + MooseX::Fastly::Role 0.04 + Net::Fastly 1.05 + Minion-10.31 + pathname: S/SR/SRI/Minion-10.31.tar.gz + provides: + LinkCheck undef + LinkCheck::Controller::Links undef + LinkCheck::Task::CheckLinks undef + Minion 10.31 + Minion::Backend undef + Minion::Backend::Pg undef + Minion::Command::minion undef + Minion::Command::minion::job undef + Minion::Command::minion::worker undef + Minion::Iterator undef + Minion::Job undef + Minion::Worker undef + Mojolicious::Plugin::Minion undef + Mojolicious::Plugin::Minion::Admin undef + requirements: + ExtUtils::MakeMaker 0 + Mojolicious 9.0 + YAML::XS 0.67 + perl 5.016 + Minion-Backend-SQLite-v5.0.7 + pathname: D/DB/DBOOK/Minion-Backend-SQLite-v5.0.7.tar.gz + provides: + Minion::Backend::SQLite v5.0.7 + requirements: + List::Util 0 + Minion 10.13 + Module::Build::Tiny 0.034 + Mojo::SQLite 3.000 + Mojolicious 7.49 + Sys::Hostname 0 + Time::HiRes 0 + perl 5.010001 + Mixin-Linewise-0.111 + pathname: R/RJ/RJBS/Mixin-Linewise-0.111.tar.gz + provides: + Mixin::Linewise 0.111 + Mixin::Linewise::Readers 0.111 + Mixin::Linewise::Writers 0.111 + requirements: + Carp 0 + ExtUtils::MakeMaker 6.78 IO::File 0 PerlIO::utf8_strict 0 Sub::Exporter 0 + perl 5.012 strict 0 warnings 0 - Module-Build-0.4205 - pathname: L/LE/LEONT/Module-Build-0.4205.tar.gz - provides: - Module::Build 0.4205 - Module::Build::Base 0.4205 - Module::Build::Compat 0.4205 - Module::Build::Config 0.4205 - Module::Build::Cookbook 0.4205 - Module::Build::Dumper 0.4205 - Module::Build::ModuleInfo 0.4205 - Module::Build::Notes 0.4205 - Module::Build::PPMMaker 0.4205 - Module::Build::Platform::Default 0.4205 - Module::Build::Platform::MacOS 0.4205 - Module::Build::Platform::Unix 0.4205 - Module::Build::Platform::VMS 0.4205 - Module::Build::Platform::VOS 0.4205 - Module::Build::Platform::Windows 0.4205 - Module::Build::Platform::aix 0.4205 - Module::Build::Platform::cygwin 0.4205 - Module::Build::Platform::darwin 0.4205 - Module::Build::Platform::os2 0.4205 - Module::Build::PodParser 0.4205 - Module::Build::Version 0.87 - Module::Build::YAML 1.41 - inc::latest 0.4205 - inc::latest::private 0.4205 - requirements: - CPAN::Meta 2.110420 - CPAN::Meta::YAML 0.003 + Module-Build-0.4234 + pathname: L/LE/LEONT/Module-Build-0.4234.tar.gz + provides: + Module::Build 0.4234 + Module::Build::Base 0.4234 + Module::Build::Compat 0.4234 + Module::Build::Config 0.4234 + Module::Build::Cookbook 0.4234 + Module::Build::Dumper 0.4234 + Module::Build::Notes 0.4234 + Module::Build::PPMMaker 0.4234 + Module::Build::Platform::Default 0.4234 + Module::Build::Platform::MacOS 0.4234 + Module::Build::Platform::Unix 0.4234 + Module::Build::Platform::VMS 0.4234 + Module::Build::Platform::VOS 0.4234 + Module::Build::Platform::Windows 0.4234 + Module::Build::Platform::aix 0.4234 + Module::Build::Platform::cygwin 0.4234 + Module::Build::Platform::darwin 0.4234 + Module::Build::Platform::os2 0.4234 + Module::Build::PodParser 0.4234 + requirements: + CPAN::Meta 2.142060 Cwd 0 Data::Dumper 0 ExtUtils::CBuilder 0.27 @@ -4261,22 +3640,18 @@ DISTRIBUTIONS File::Find 0 File::Path 0 File::Spec 0.82 - File::Temp 0.15 Getopt::Long 0 Module::Metadata 1.000002 - Parse::CPAN::Meta 1.4401 Perl::OSType 1 - Pod::Man 2.17 - Test::Harness 3.16 - Test::More 0.49 + TAP::Harness 3.29 Text::Abbrev 0 Text::ParseWords 0 perl 5.006001 version 0.87 - Module-Build-Tiny-0.036 - pathname: L/LE/LEONT/Module-Build-Tiny-0.036.tar.gz + Module-Build-Tiny-0.051 + pathname: L/LE/LEONT/Module-Build-Tiny-0.051.tar.gz provides: - Module::Build::Tiny 0.036 + Module::Build::Tiny 0.051 requirements: CPAN::Meta 0 DynaLoader 0 @@ -4298,43 +3673,29 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 - Module-Build-XSUtil-0.10 - pathname: H/HI/HIDEAKIO/Module-Build-XSUtil-0.10.tar.gz - provides: - Module::Build::XSUtil 0.10 - requirements: - CPAN::Meta 0 - CPAN::Meta::Prereqs 0 - Devel::CheckCompiler 0.02 - Devel::PPPort 3.19 - Exporter 0 - ExtUtils::CBuilder 0 - File::Basename 0 - File::Path 0 - Module::Build 0.4005 - XSLoader 0.02 - parent 0 - perl 5.008005 - Module-CPANfile-1.0002 - pathname: M/MI/MIYAGAWA/Module-CPANfile-1.0002.tar.gz + Module-CPANfile-1.1004 + pathname: M/MI/MIYAGAWA/Module-CPANfile-1.1004.tar.gz provides: - Module::CPANfile 1.0002 + Module::CPANfile 1.1004 Module::CPANfile::Environment undef - Module::CPANfile::Result undef + Module::CPANfile::Prereq undef + Module::CPANfile::Prereqs undef + Module::CPANfile::Requirement undef requirements: CPAN::Meta 2.12091 CPAN::Meta::Prereqs 2.12091 - ExtUtils::MakeMaker 6.30 - Module-Faker-0.016 - pathname: R/RJ/RJBS/Module-Faker-0.016.tar.gz + ExtUtils::MakeMaker 0 + parent 0 + Module-Faker-0.017 + pathname: R/RJ/RJBS/Module-Faker-0.017.tar.gz provides: - Module::Faker 0.016 - Module::Faker::Appendix 0.016 - Module::Faker::Dist 0.016 - Module::Faker::File 0.016 - Module::Faker::Heavy 0.016 - Module::Faker::Module 0.016 - Module::Faker::Package 0.016 + Module::Faker 0.017 + Module::Faker::Appendix 0.017 + Module::Faker::Dist 0.017 + Module::Faker::File 0.017 + Module::Faker::Heavy 0.017 + Module::Faker::Module 0.017 + Module::Faker::Package 0.017 requirements: Archive::Any::Create 0 CPAN::DistnameInfo 0 @@ -4342,7 +3703,7 @@ DISTRIBUTIONS CPAN::Meta::Requirements 0 Carp 0 Encode 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 File::Next 0 File::Path 0 File::Temp 0 @@ -4354,396 +3715,896 @@ DISTRIBUTIONS Text::Template 0 strict 0 warnings 0 - Module-Find-0.12 - pathname: C/CR/CRENZ/Module-Find-0.12.tar.gz + Module-Find-0.17 + pathname: C/CR/CRENZ/Module-Find-0.17.tar.gz provides: - Module::Find 0.12 - ModuleFindTest undef - ModuleFindTest::SubMod undef - ModuleFindTest::SubMod::SubSubMod undef + Module::Find 0.17 requirements: ExtUtils::MakeMaker 0 File::Find 0 File::Spec 0 Test::More 0 - perl 5.006001 - Module-Implementation-0.07 - pathname: D/DR/DROLSKY/Module-Implementation-0.07.tar.gz + perl 5.008001 + Module-Implementation-0.09 + pathname: D/DR/DROLSKY/Module-Implementation-0.09.tar.gz provides: - Module::Implementation 0.07 - T::Impl1 undef - T::Impl2 undef - T::ImplFails1 undef - T::ImplFails2 undef + Module::Implementation 0.09 requirements: Carp 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 Module::Runtime 0.012 Try::Tiny 0 strict 0 warnings 0 - Module-Metadata-1.000024 - pathname: E/ET/ETHER/Module-Metadata-1.000024.tar.gz + Module-Load-Conditional-0.74 + pathname: B/BI/BINGOS/Module-Load-Conditional-0.74.tar.gz + provides: + Module::Load::Conditional 0.74 + requirements: + ExtUtils::MakeMaker 0 + Locale::Maketext::Simple 0 + Module::CoreList 2.22 + Module::Load 0.28 + Module::Metadata 1.000005 + Params::Check 0 + Test::More 0 + version 0.69 + Module-Metadata-1.000038 + pathname: E/ET/ETHER/Module-Metadata-1.000038.tar.gz provides: - Module::Metadata 1.000024 + Module::Metadata 1.000038 requirements: Carp 0 - ExtUtils::MakeMaker 6.30 + Encode 0 + ExtUtils::MakeMaker 0 Fcntl 0 File::Find 0 File::Spec 0 + perl 5.006 strict 0 version 0.87 warnings 0 - Module-Pluggable-5.1 - pathname: S/SI/SIMONW/Module-Pluggable-5.1.tar.gz + Module-Pluggable-6.3 + pathname: S/SI/SIMONW/Module-Pluggable-6.3.tar.gz provides: Devel::InnerPackage 0.4 - Module::Pluggable 5.1 - Module::Pluggable::Object 5.1 + Module::Pluggable 6.3 + Module::Pluggable::Object 5.2 requirements: + Exporter 5.57 + ExtUtils::MakeMaker 0 File::Basename 0 + File::Find 0 File::Spec 3.00 - Module::Build 0.38 - Test::More 0.62 + File::Spec::Functions 0 + Scalar::Util 0 if 0 - Module-Runtime-0.014 - pathname: Z/ZE/ZEFRAM/Module-Runtime-0.014.tar.gz + perl 5.006 + strict 0 + Module-Runtime-0.018 + pathname: H/HA/HAARG/Module-Runtime-0.018.tar.gz provides: - Module::Runtime 0.014 + Module::Runtime 0.018 requirements: - Module::Build 0 - Test::More 0 + ExtUtils::MakeMaker 0 + perl 5.006000 + Module-Runtime-Conflicts-0.003 + pathname: E/ET/ETHER/Module-Runtime-Conflicts-0.003.tar.gz + provides: + Module::Runtime::Conflicts 0.003 + requirements: + Dist::CheckConflicts 0 + ExtUtils::MakeMaker 0 + Module::Runtime 0 perl 5.006 strict 0 warnings 0 - Moo-1.004006 - pathname: H/HA/HAARG/Moo-1.004006.tar.gz + Mojo-Pg-4.27 + pathname: S/SR/SRI/Mojo-Pg-4.27.tar.gz + provides: + Mojo::Pg 4.27 + Mojo::Pg::Database undef + Mojo::Pg::Migrations undef + Mojo::Pg::PubSub undef + Mojo::Pg::Results undef + Mojo::Pg::Transaction undef + requirements: + DBD::Pg 3.007004 + ExtUtils::MakeMaker 0 + Mojolicious 8.50 + SQL::Abstract::Pg 1.0 + perl 5.016 + Mojo-SQLite-3.009 + pathname: D/DB/DBOOK/Mojo-SQLite-3.009.tar.gz + provides: + Mojo::SQLite 3.009 + Mojo::SQLite::Database 3.009 + Mojo::SQLite::Migrations 3.009 + Mojo::SQLite::PubSub 3.009 + Mojo::SQLite::Results 3.009 + Mojo::SQLite::Transaction 3.009 + requirements: + Carp 0 + DBD::SQLite 1.68 + DBI 1.627 + File::Spec::Functions 0 + File::Temp 0 + Module::Build::Tiny 0.034 + Mojolicious 8.03 + SQL::Abstract::Pg 1.0 + Scalar::Util 0 + URI 1.69 + URI::db 0.15 + URI::file 4.21 + perl 5.010001 + Mojolicious-9.39 + pathname: S/SR/SRI/Mojolicious-9.39.tar.gz + provides: + Mojo undef + Mojo::Asset undef + Mojo::Asset::File undef + Mojo::Asset::Memory undef + Mojo::Base undef + Mojo::BaseUtil undef + Mojo::ByteStream undef + Mojo::Cache undef + Mojo::Collection undef + Mojo::Content undef + Mojo::Content::MultiPart undef + Mojo::Content::Single undef + Mojo::Cookie undef + Mojo::Cookie::Request undef + Mojo::Cookie::Response undef + Mojo::DOM undef + Mojo::DOM::CSS undef + Mojo::DOM::HTML undef + Mojo::Date undef + Mojo::DynamicMethods undef + Mojo::EventEmitter undef + Mojo::Exception undef + Mojo::File undef + Mojo::Headers undef + Mojo::HelloWorld undef + Mojo::Home undef + Mojo::IOLoop undef + Mojo::IOLoop::Client undef + Mojo::IOLoop::Server undef + Mojo::IOLoop::Stream undef + Mojo::IOLoop::Subprocess undef + Mojo::IOLoop::TLS undef + Mojo::JSON undef + Mojo::JSON::Pointer undef + Mojo::Loader undef + Mojo::Log undef + Mojo::Message undef + Mojo::Message::Request undef + Mojo::Message::Response undef + Mojo::Parameters undef + Mojo::Path undef + Mojo::Promise undef + Mojo::Reactor undef + Mojo::Reactor::EV undef + Mojo::Reactor::Poll undef + Mojo::Server undef + Mojo::Server::CGI undef + Mojo::Server::Daemon undef + Mojo::Server::Hypnotoad undef + Mojo::Server::Morbo undef + Mojo::Server::Morbo::Backend undef + Mojo::Server::Morbo::Backend::Poll undef + Mojo::Server::PSGI undef + Mojo::Server::Prefork undef + Mojo::Template undef + Mojo::Transaction undef + Mojo::Transaction::HTTP undef + Mojo::Transaction::WebSocket undef + Mojo::URL undef + Mojo::Upload undef + Mojo::UserAgent undef + Mojo::UserAgent::CookieJar undef + Mojo::UserAgent::Proxy undef + Mojo::UserAgent::Server undef + Mojo::UserAgent::Transactor undef + Mojo::Util undef + Mojo::WebSocket undef + Mojolicious 9.39 + Mojolicious::Command undef + Mojolicious::Command::Author::cpanify undef + Mojolicious::Command::Author::generate undef + Mojolicious::Command::Author::generate::app undef + Mojolicious::Command::Author::generate::dockerfile undef + Mojolicious::Command::Author::generate::lite_app undef + Mojolicious::Command::Author::generate::makefile undef + Mojolicious::Command::Author::generate::plugin undef + Mojolicious::Command::Author::inflate undef + Mojolicious::Command::cgi undef + Mojolicious::Command::daemon undef + Mojolicious::Command::eval undef + Mojolicious::Command::get undef + Mojolicious::Command::prefork undef + Mojolicious::Command::psgi undef + Mojolicious::Command::routes undef + Mojolicious::Command::version undef + Mojolicious::Commands undef + Mojolicious::Controller undef + Mojolicious::Lite undef + Mojolicious::Plugin undef + Mojolicious::Plugin::Config undef + Mojolicious::Plugin::DefaultHelpers undef + Mojolicious::Plugin::EPLRenderer undef + Mojolicious::Plugin::EPRenderer undef + Mojolicious::Plugin::HeaderCondition undef + Mojolicious::Plugin::JSONConfig undef + Mojolicious::Plugin::Mount undef + Mojolicious::Plugin::NotYAMLConfig undef + Mojolicious::Plugin::TagHelpers undef + Mojolicious::Plugins undef + Mojolicious::Renderer undef + Mojolicious::Routes undef + Mojolicious::Routes::Match undef + Mojolicious::Routes::Pattern undef + Mojolicious::Routes::Route undef + Mojolicious::Sessions undef + Mojolicious::Static undef + Mojolicious::Types undef + Mojolicious::Validator undef + Mojolicious::Validator::Validation undef + Test::Mojo undef + ojo undef + requirements: + ExtUtils::MakeMaker 0 + IO::Socket::IP 0.37 + Sub::Util 1.41 + perl 5.016 + Mojolicious-Plugin-MountPSGI-0.15 + pathname: J/JB/JBERGER/Mojolicious-Plugin-MountPSGI-0.15.tar.gz + provides: + Mojolicious::Plugin::MountPSGI 0.15 + Mojolicious::Plugin::MountPSGI::Proxy undef + requirements: + ExtUtils::MakeMaker 0 + Mojolicious 7.70 + Plack 0 + Mojolicious-Plugin-OpenAPI-5.11 + pathname: J/JH/JHTHORSEN/Mojolicious-Plugin-OpenAPI-5.11.tar.gz + provides: + Mojolicious::Plugin::OpenAPI 5.11 + Mojolicious::Plugin::OpenAPI::Cors undef + Mojolicious::Plugin::OpenAPI::Parameters undef + Mojolicious::Plugin::OpenAPI::Security undef + Mojolicious::Plugin::OpenAPI::SpecRenderer undef + requirements: + ExtUtils::MakeMaker 0 + JSON::Validator 5.13 + Mojolicious 9.00 + perl 5.016 + Mojolicious-Plugin-Web-Auth-0.17 + pathname: H/HA/HAYAJO/Mojolicious-Plugin-Web-Auth-0.17.tar.gz + provides: + Mojolicious::Plugin::Web::Auth 0.17 + Mojolicious::Plugin::Web::Auth::Base undef + Mojolicious::Plugin::Web::Auth::OAuth undef + Mojolicious::Plugin::Web::Auth::OAuth2 undef + Mojolicious::Plugin::Web::Auth::Site::Dropbox undef + Mojolicious::Plugin::Web::Auth::Site::Facebook undef + Mojolicious::Plugin::Web::Auth::Site::Github undef + Mojolicious::Plugin::Web::Auth::Site::Google undef + Mojolicious::Plugin::Web::Auth::Site::Instagram undef + Mojolicious::Plugin::Web::Auth::Site::Twitter undef + Mojolicious::Plugin::Web::Auth::Site::Yandex undef + requirements: + IO::Socket::SSL 1.77 + Module::Build::Tiny 0.035 + Mojolicious 7.13 + Net::OAuth 0.28 + perl 5.010001 + Moo-2.005005 + pathname: H/HA/HAARG/Moo-2.005005.tar.gz provides: Method::Generate::Accessor undef Method::Generate::BuildAll undef Method::Generate::Constructor undef Method::Generate::DemolishAll undef - Method::Inliner undef - Moo 1.004006 + Moo 2.005005 Moo::HandleMoose undef Moo::HandleMoose::FakeConstructor undef Moo::HandleMoose::FakeMetaClass undef Moo::HandleMoose::_TypeMap undef Moo::Object undef - Moo::Role 1.004006 + Moo::Role 2.005005 Moo::_Utils undef - Moo::_mro undef Moo::sification undef - Sub::Defer 1.004006 - Sub::Quote 1.004006 oo undef requirements: - Class::Method::Modifiers 1.1 - Devel::GlobalDestruction 0.11 + Carp 0 + Class::Method::Modifiers 1.10 + Exporter 0 ExtUtils::MakeMaker 0 - Import::Into 1.002 - Module::Runtime 0.012 - Role::Tiny 1.003003 + Role::Tiny 2.002003 + Scalar::Util 1.00 + Sub::Defer 2.006006 + Sub::Quote 2.006006 + perl 5.006 + MooX-Aliases-0.001006 + pathname: H/HA/HAARG/MooX-Aliases-0.001006.tar.gz + provides: + MooX::Aliases 0.001006 + requirements: + Class::Method::Modifiers 1.05 + Moo 1.001 + perl 5.006 + strictures 1 + MooX-Locale-Passthrough-0.001 + pathname: R/RE/REHSACK/MooX-Locale-Passthrough-0.001.tar.gz + provides: + MooX::Locale::Passthrough 0.001 + requirements: + ExtUtils::MakeMaker 0 + Moo 1.003 + perl 5.008001 + MooX-Options-4.103 + pathname: R/RE/REHSACK/MooX-Options-4.103.tar.gz + provides: + MooX::Options 4.103 + MooX::Options::Descriptive 4.103 + MooX::Options::Descriptive::Usage 4.103 + MooX::Options::Role 4.103 + requirements: + ExtUtils::MakeMaker 0 + Getopt::Long 2.43 + Getopt::Long::Descriptive 0.099 + MRO::Compat 0 + Module::Runtime 0 + Moo 1.003 + MooX::Locale::Passthrough 0 + Path::Class 0.32 + Pod::Usage 0 + Text::LineFold 0 + perl 5.008001 + strictures 2 + MooX-StrictConstructor-0.013 + pathname: H/HA/HAARG/MooX-StrictConstructor-0.013.tar.gz + provides: + MooX::StrictConstructor 0.013 + MooX::StrictConstructor::Role::BuildAll 0.013 + MooX::StrictConstructor::Role::Constructor 0.013 + MooX::StrictConstructor::Role::Constructor::Base 0.013 + MooX::StrictConstructor::Role::Constructor::Late 0.013 + requirements: + ExtUtils::MakeMaker 0 + Moo 2.004000 + Moo::Role 0 + perl 5.008 + MooX-Traits-0.005 + pathname: T/TO/TOBYINK/MooX-Traits-0.005.tar.gz + provides: + MooX::Traits 0.005 + MooX::Traits::Util 0.005 + requirements: + Exporter::Shiny 0 + ExtUtils::MakeMaker 6.17 + Module::Runtime 0 + Role::Tiny 1.000000 Scalar::Util 0 - strictures 1.004003 - MooX-Types-MooseLike-0.25 - pathname: M/MA/MATEU/MooX-Types-MooseLike-0.25.tar.gz + perl 5.006000 + MooX-Types-MooseLike-0.29 + pathname: M/MA/MATEU/MooX-Types-MooseLike-0.29.tar.gz provides: - MooX::Types::MooseLike 0.25 - MooX::Types::MooseLike::Base 0.25 + MooX::Types::MooseLike 0.29 + MooX::Types::MooseLike::Base 0.29 requirements: ExtUtils::MakeMaker 0 - Module::Runtime 0.012 - Moo 0.09101 - Test::Fatal 0.003 - Test::More 0.96 - MooX-Types-MooseLike-Numeric-1.02 - pathname: M/MA/MATEU/MooX-Types-MooseLike-Numeric-1.02.tar.gz + Module::Runtime 0.014 + MooX-Types-MooseLike-Numeric-1.03 + pathname: M/MA/MATEU/MooX-Types-MooseLike-Numeric-1.03.tar.gz provides: - MooX::Types::MooseLike::Numeric 1.02 + MooX::Types::MooseLike::Numeric 1.03 requirements: ExtUtils::MakeMaker 0 + Moo 1.004002 MooX::Types::MooseLike 0.23 Test::Fatal 0.003 Test::More 0.96 - Moose-2.0802 - pathname: E/ET/ETHER/Moose-2.0802.tar.gz - provides: - Bar undef - Bar7::Meta::Trait undef - Bar7::Meta::Trait2 undef - BinaryTree 0.02 - Class::MOP 2.0802 - Class::MOP::Attribute 2.0802 - Class::MOP::Class 2.0802 - Class::MOP::Class::Immutable::Trait 2.0802 - Class::MOP::Deprecated 2.0802 - Class::MOP::Instance 2.0802 - Class::MOP::Method 2.0802 - Class::MOP::Method::Accessor 2.0802 - Class::MOP::Method::Constructor 2.0802 - Class::MOP::Method::Generated 2.0802 - Class::MOP::Method::Inlined 2.0802 - Class::MOP::Method::Meta 2.0802 - Class::MOP::Method::Overload 2.0802 - Class::MOP::Method::Wrapped 2.0802 - Class::MOP::MiniTrait 2.0802 - Class::MOP::Mixin 2.0802 - Class::MOP::Mixin::AttributeCore 2.0802 - Class::MOP::Mixin::HasAttributes 2.0802 - Class::MOP::Mixin::HasMethods 2.0802 - Class::MOP::Module 2.0802 - Class::MOP::Object 2.0802 - Class::MOP::Package 2.0802 - Foo undef - MMHelper undef - MY undef - Moose 2.0802 - Moose::Cookbook::Legacy::Debugging_BaseClassReplacement 2.0802 - Moose::Cookbook::Meta::Labeled_AttributeMetaclass 2.0802 - Moose::Deprecated 2.0802 - Moose::Error::Confess 2.0802 - Moose::Error::Croak 2.0802 - Moose::Error::Default 2.0802 - Moose::Exporter 2.0802 - Moose::Meta::Attribute 2.0802 - Moose::Meta::Attribute::Custom::Bar undef - Moose::Meta::Attribute::Custom::Foo undef - Moose::Meta::Attribute::Custom::Moose 2.0802 - Moose::Meta::Attribute::Custom::Trait::Bar undef - Moose::Meta::Attribute::Custom::Trait::Foo undef - Moose::Meta::Attribute::Native 2.0802 - Moose::Meta::Attribute::Native::Trait 2.0802 - Moose::Meta::Attribute::Native::Trait::Array 2.0802 - Moose::Meta::Attribute::Native::Trait::Bool 2.0802 - Moose::Meta::Attribute::Native::Trait::Code 2.0802 - Moose::Meta::Attribute::Native::Trait::Counter 2.0802 - Moose::Meta::Attribute::Native::Trait::Hash 2.0802 - Moose::Meta::Attribute::Native::Trait::Number 2.0802 - Moose::Meta::Attribute::Native::Trait::String 2.0802 - Moose::Meta::Class 2.0802 - Moose::Meta::Class::Immutable::Trait 2.0802 - Moose::Meta::Instance 2.0802 - Moose::Meta::Method 2.0802 - Moose::Meta::Method::Accessor 2.0802 - Moose::Meta::Method::Accessor::Native 2.0802 - Moose::Meta::Method::Accessor::Native::Array 2.0802 - Moose::Meta::Method::Accessor::Native::Array::Writer 2.0802 - Moose::Meta::Method::Accessor::Native::Array::accessor 2.0802 - Moose::Meta::Method::Accessor::Native::Array::clear 2.0802 - Moose::Meta::Method::Accessor::Native::Array::count 2.0802 - Moose::Meta::Method::Accessor::Native::Array::delete 2.0802 - Moose::Meta::Method::Accessor::Native::Array::elements 2.0802 - Moose::Meta::Method::Accessor::Native::Array::first 2.0802 - Moose::Meta::Method::Accessor::Native::Array::first_index 2.0802 - Moose::Meta::Method::Accessor::Native::Array::get 2.0802 - Moose::Meta::Method::Accessor::Native::Array::grep 2.0802 - Moose::Meta::Method::Accessor::Native::Array::insert 2.0802 - Moose::Meta::Method::Accessor::Native::Array::is_empty 2.0802 - Moose::Meta::Method::Accessor::Native::Array::join 2.0802 - Moose::Meta::Method::Accessor::Native::Array::map 2.0802 - Moose::Meta::Method::Accessor::Native::Array::natatime 2.0802 - Moose::Meta::Method::Accessor::Native::Array::pop 2.0802 - Moose::Meta::Method::Accessor::Native::Array::push 2.0802 - Moose::Meta::Method::Accessor::Native::Array::reduce 2.0802 - Moose::Meta::Method::Accessor::Native::Array::set 2.0802 - Moose::Meta::Method::Accessor::Native::Array::shallow_clone 2.0802 - Moose::Meta::Method::Accessor::Native::Array::shift 2.0802 - Moose::Meta::Method::Accessor::Native::Array::shuffle 2.0802 - Moose::Meta::Method::Accessor::Native::Array::sort 2.0802 - Moose::Meta::Method::Accessor::Native::Array::sort_in_place 2.0802 - Moose::Meta::Method::Accessor::Native::Array::splice 2.0802 - Moose::Meta::Method::Accessor::Native::Array::uniq 2.0802 - Moose::Meta::Method::Accessor::Native::Array::unshift 2.0802 - Moose::Meta::Method::Accessor::Native::Bool::not 2.0802 - Moose::Meta::Method::Accessor::Native::Bool::set 2.0802 - Moose::Meta::Method::Accessor::Native::Bool::toggle 2.0802 - Moose::Meta::Method::Accessor::Native::Bool::unset 2.0802 - Moose::Meta::Method::Accessor::Native::Code::execute 2.0802 - Moose::Meta::Method::Accessor::Native::Code::execute_method 2.0802 - Moose::Meta::Method::Accessor::Native::Collection 2.0802 - Moose::Meta::Method::Accessor::Native::Counter::Writer 2.0802 - Moose::Meta::Method::Accessor::Native::Counter::dec 2.0802 - Moose::Meta::Method::Accessor::Native::Counter::inc 2.0802 - Moose::Meta::Method::Accessor::Native::Counter::reset 2.0802 - Moose::Meta::Method::Accessor::Native::Counter::set 2.0802 - Moose::Meta::Method::Accessor::Native::Hash 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::Writer 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::accessor 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::clear 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::count 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::defined 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::delete 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::elements 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::exists 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::get 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::is_empty 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::keys 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::kv 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::set 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::shallow_clone 2.0802 - Moose::Meta::Method::Accessor::Native::Hash::values 2.0802 - Moose::Meta::Method::Accessor::Native::Number::abs 2.0802 - Moose::Meta::Method::Accessor::Native::Number::add 2.0802 - Moose::Meta::Method::Accessor::Native::Number::div 2.0802 - Moose::Meta::Method::Accessor::Native::Number::mod 2.0802 - Moose::Meta::Method::Accessor::Native::Number::mul 2.0802 - Moose::Meta::Method::Accessor::Native::Number::set 2.0802 - Moose::Meta::Method::Accessor::Native::Number::sub 2.0802 - Moose::Meta::Method::Accessor::Native::Reader 2.0802 - Moose::Meta::Method::Accessor::Native::String::append 2.0802 - Moose::Meta::Method::Accessor::Native::String::chomp 2.0802 - Moose::Meta::Method::Accessor::Native::String::chop 2.0802 - Moose::Meta::Method::Accessor::Native::String::clear 2.0802 - Moose::Meta::Method::Accessor::Native::String::inc 2.0802 - Moose::Meta::Method::Accessor::Native::String::length 2.0802 - Moose::Meta::Method::Accessor::Native::String::match 2.0802 - Moose::Meta::Method::Accessor::Native::String::prepend 2.0802 - Moose::Meta::Method::Accessor::Native::String::replace 2.0802 - Moose::Meta::Method::Accessor::Native::String::substr 2.0802 - Moose::Meta::Method::Accessor::Native::Writer 2.0802 - Moose::Meta::Method::Augmented 2.0802 - Moose::Meta::Method::Constructor 2.0802 - Moose::Meta::Method::Delegation 2.0802 - Moose::Meta::Method::Destructor 2.0802 - Moose::Meta::Method::Meta 2.0802 - Moose::Meta::Method::Overridden 2.0802 - Moose::Meta::Mixin::AttributeCore 2.0802 - Moose::Meta::Object::Trait 2.0802 - Moose::Meta::Role 2.0802 - Moose::Meta::Role::Application 2.0802 - Moose::Meta::Role::Application::RoleSummation 2.0802 - Moose::Meta::Role::Application::ToClass 2.0802 - Moose::Meta::Role::Application::ToInstance 2.0802 - Moose::Meta::Role::Application::ToRole 2.0802 - Moose::Meta::Role::Attribute 2.0802 - Moose::Meta::Role::Composite 2.0802 - Moose::Meta::Role::Method 2.0802 - Moose::Meta::Role::Method::Conflicting 2.0802 - Moose::Meta::Role::Method::Required 2.0802 - Moose::Meta::TypeCoercion 2.0802 - Moose::Meta::TypeCoercion::Union 2.0802 - Moose::Meta::TypeConstraint 2.0802 - Moose::Meta::TypeConstraint::Class 2.0802 - Moose::Meta::TypeConstraint::DuckType 2.0802 - Moose::Meta::TypeConstraint::Enum 2.0802 - Moose::Meta::TypeConstraint::Parameterizable 2.0802 - Moose::Meta::TypeConstraint::Parameterized 2.0802 - Moose::Meta::TypeConstraint::Registry 2.0802 - Moose::Meta::TypeConstraint::Role 2.0802 - Moose::Meta::TypeConstraint::Union 2.0802 - Moose::Object 2.0802 - Moose::Role 2.0802 - Moose::Util 2.0802 - Moose::Util::MetaRole 2.0802 - Moose::Util::TypeConstraints 2.0802 - Moose::Util::TypeConstraints::Builtins 2.0802 - My::Bar undef - My::Content undef - My::Extract undef - My::Output undef - My::Trait::Bar undef - MyExporter undef - MyInline undef - MyMetaClass undef - MyMetaClass::Attribute undef - MyMetaClass::Instance undef - MyMetaClass::Method undef - MyMetaClass::Random undef - MyMetaclassRole undef - MyMooseA undef - MyMooseB undef - MyMooseObject undef - NoInlineAccessor undef - NoInlineAttribute undef - Role::Child undef - Role::Interface undef - Role::Parent undef - SyntaxError undef - Test::Moose 2.0802 - inc::CheckDelta undef - inc::Clean undef - inc::ExtractInlineTests undef - inc::GitUpToDate undef - inc::MakeMaker undef - inc::RequireAuthorDeps undef - inc::TestRelease undef - metaclass 2.0802 - oose 2.0802 + Moose-2.2207 + pathname: E/ET/ETHER/Moose-2.2207.tar.gz + provides: + Class::MOP 2.2207 + Class::MOP::Attribute 2.2207 + Class::MOP::Class 2.2207 + Class::MOP::Class::Immutable::Trait 2.2207 + Class::MOP::Deprecated 2.2207 + Class::MOP::Instance 2.2207 + Class::MOP::Method 2.2207 + Class::MOP::Method::Accessor 2.2207 + Class::MOP::Method::Constructor 2.2207 + Class::MOP::Method::Generated 2.2207 + Class::MOP::Method::Inlined 2.2207 + Class::MOP::Method::Meta 2.2207 + Class::MOP::Method::Wrapped 2.2207 + Class::MOP::MiniTrait 2.2207 + Class::MOP::Mixin 2.2207 + Class::MOP::Mixin::AttributeCore 2.2207 + Class::MOP::Mixin::HasAttributes 2.2207 + Class::MOP::Mixin::HasMethods 2.2207 + Class::MOP::Mixin::HasOverloads 2.2207 + Class::MOP::Module 2.2207 + Class::MOP::Object 2.2207 + Class::MOP::Overload 2.2207 + Class::MOP::Package 2.2207 + Moose 2.2207 + Moose::Cookbook 2.2207 + Moose::Cookbook::Basics::BankAccount_MethodModifiersAndSubclassing 2.2207 + Moose::Cookbook::Basics::BinaryTree_AttributeFeatures 2.2207 + Moose::Cookbook::Basics::BinaryTree_BuilderAndLazyBuild 2.2207 + Moose::Cookbook::Basics::Company_Subtypes 2.2207 + Moose::Cookbook::Basics::DateTime_ExtendingNonMooseParent 2.2207 + Moose::Cookbook::Basics::Document_AugmentAndInner 2.2207 + Moose::Cookbook::Basics::Genome_OverloadingSubtypesAndCoercion 2.2207 + Moose::Cookbook::Basics::HTTP_SubtypesAndCoercion 2.2207 + Moose::Cookbook::Basics::Immutable 2.2207 + Moose::Cookbook::Basics::Person_BUILDARGSAndBUILD 2.2207 + Moose::Cookbook::Basics::Point_AttributesAndSubclassing 2.2207 + Moose::Cookbook::Extending::Debugging_BaseClassRole 2.2207 + Moose::Cookbook::Extending::ExtensionOverview 2.2207 + Moose::Cookbook::Extending::Mooseish_MooseSugar 2.2207 + Moose::Cookbook::Legacy::Debugging_BaseClassReplacement 2.2207 + Moose::Cookbook::Legacy::Labeled_AttributeMetaclass 2.2207 + Moose::Cookbook::Legacy::Table_ClassMetaclass 2.2207 + Moose::Cookbook::Meta::GlobRef_InstanceMetaclass 2.2207 + Moose::Cookbook::Meta::Labeled_AttributeTrait 2.2207 + Moose::Cookbook::Meta::PrivateOrPublic_MethodMetaclass 2.2207 + Moose::Cookbook::Meta::Table_MetaclassTrait 2.2207 + Moose::Cookbook::Meta::WhyMeta 2.2207 + Moose::Cookbook::Roles::ApplicationToInstance 2.2207 + Moose::Cookbook::Roles::Comparable_CodeReuse 2.2207 + Moose::Cookbook::Roles::Restartable_AdvancedComposition 2.2207 + Moose::Cookbook::Snack::Keywords 2.2207 + Moose::Cookbook::Snack::Types 2.2207 + Moose::Cookbook::Style 2.2207 + Moose::Deprecated 2.2207 + Moose::Exception 2.2207 + Moose::Exception::AccessorMustReadWrite 2.2207 + Moose::Exception::AddParameterizableTypeTakesParameterizableType 2.2207 + Moose::Exception::AddRoleTakesAMooseMetaRoleInstance 2.2207 + Moose::Exception::AddRoleToARoleTakesAMooseMetaRole 2.2207 + Moose::Exception::ApplyTakesABlessedInstance 2.2207 + Moose::Exception::AttachToClassNeedsAClassMOPClassInstanceOrASubclass 2.2207 + Moose::Exception::AttributeConflictInRoles 2.2207 + Moose::Exception::AttributeConflictInSummation 2.2207 + Moose::Exception::AttributeExtensionIsNotSupportedInRoles 2.2207 + Moose::Exception::AttributeIsRequired 2.2207 + Moose::Exception::AttributeMustBeAnClassMOPMixinAttributeCoreOrSubclass 2.2207 + Moose::Exception::AttributeNamesDoNotMatch 2.2207 + Moose::Exception::AttributeValueIsNotAnObject 2.2207 + Moose::Exception::AttributeValueIsNotDefined 2.2207 + Moose::Exception::AutoDeRefNeedsArrayRefOrHashRef 2.2207 + Moose::Exception::BadOptionFormat 2.2207 + Moose::Exception::BothBuilderAndDefaultAreNotAllowed 2.2207 + Moose::Exception::BuilderDoesNotExist 2.2207 + Moose::Exception::BuilderMethodNotSupportedForAttribute 2.2207 + Moose::Exception::BuilderMethodNotSupportedForInlineAttribute 2.2207 + Moose::Exception::BuilderMustBeAMethodName 2.2207 + Moose::Exception::CallingMethodOnAnImmutableInstance 2.2207 + Moose::Exception::CallingReadOnlyMethodOnAnImmutableInstance 2.2207 + Moose::Exception::CanExtendOnlyClasses 2.2207 + Moose::Exception::CanOnlyConsumeRole 2.2207 + Moose::Exception::CanOnlyWrapBlessedCode 2.2207 + Moose::Exception::CanReblessOnlyIntoASubclass 2.2207 + Moose::Exception::CanReblessOnlyIntoASuperclass 2.2207 + Moose::Exception::CannotAddAdditionalTypeCoercionsToUnion 2.2207 + Moose::Exception::CannotAddAsAnAttributeToARole 2.2207 + Moose::Exception::CannotApplyBaseClassRolesToRole 2.2207 + Moose::Exception::CannotAssignValueToReadOnlyAccessor 2.2207 + Moose::Exception::CannotAugmentIfLocalMethodPresent 2.2207 + Moose::Exception::CannotAugmentNoSuperMethod 2.2207 + Moose::Exception::CannotAutoDerefWithoutIsa 2.2207 + Moose::Exception::CannotAutoDereferenceTypeConstraint 2.2207 + Moose::Exception::CannotCalculateNativeType 2.2207 + Moose::Exception::CannotCallAnAbstractBaseMethod 2.2207 + Moose::Exception::CannotCallAnAbstractMethod 2.2207 + Moose::Exception::CannotCoerceAWeakRef 2.2207 + Moose::Exception::CannotCoerceAttributeWhichHasNoCoercion 2.2207 + Moose::Exception::CannotCreateHigherOrderTypeWithoutATypeParameter 2.2207 + Moose::Exception::CannotCreateMethodAliasLocalMethodIsPresent 2.2207 + Moose::Exception::CannotCreateMethodAliasLocalMethodIsPresentInClass 2.2207 + Moose::Exception::CannotDelegateLocalMethodIsPresent 2.2207 + Moose::Exception::CannotDelegateWithoutIsa 2.2207 + Moose::Exception::CannotFindDelegateMetaclass 2.2207 + Moose::Exception::CannotFindType 2.2207 + Moose::Exception::CannotFindTypeGivenToMatchOnType 2.2207 + Moose::Exception::CannotFixMetaclassCompatibility 2.2207 + Moose::Exception::CannotGenerateInlineConstraint 2.2207 + Moose::Exception::CannotInitializeMooseMetaRoleComposite 2.2207 + Moose::Exception::CannotInlineTypeConstraintCheck 2.2207 + Moose::Exception::CannotLocatePackageInINC 2.2207 + Moose::Exception::CannotMakeMetaclassCompatible 2.2207 + Moose::Exception::CannotOverrideALocalMethod 2.2207 + Moose::Exception::CannotOverrideBodyOfMetaMethods 2.2207 + Moose::Exception::CannotOverrideLocalMethodIsPresent 2.2207 + Moose::Exception::CannotOverrideNoSuperMethod 2.2207 + Moose::Exception::CannotRegisterUnnamedTypeConstraint 2.2207 + Moose::Exception::CannotUseLazyBuildAndDefaultSimultaneously 2.2207 + Moose::Exception::CircularReferenceInAlso 2.2207 + Moose::Exception::ClassDoesNotHaveInitMeta 2.2207 + Moose::Exception::ClassDoesTheExcludedRole 2.2207 + Moose::Exception::ClassNamesDoNotMatch 2.2207 + Moose::Exception::CloneObjectExpectsAnInstanceOfMetaclass 2.2207 + Moose::Exception::CodeBlockMustBeACodeRef 2.2207 + Moose::Exception::CoercingWithoutCoercions 2.2207 + Moose::Exception::CoercionAlreadyExists 2.2207 + Moose::Exception::CoercionNeedsTypeConstraint 2.2207 + Moose::Exception::ConflictDetectedInCheckRoleExclusions 2.2207 + Moose::Exception::ConflictDetectedInCheckRoleExclusionsInToClass 2.2207 + Moose::Exception::ConstructClassInstanceTakesPackageName 2.2207 + Moose::Exception::CouldNotCreateMethod 2.2207 + Moose::Exception::CouldNotCreateWriter 2.2207 + Moose::Exception::CouldNotEvalConstructor 2.2207 + Moose::Exception::CouldNotEvalDestructor 2.2207 + Moose::Exception::CouldNotFindTypeConstraintToCoerceFrom 2.2207 + Moose::Exception::CouldNotGenerateInlineAttributeMethod 2.2207 + Moose::Exception::CouldNotLocateTypeConstraintForUnion 2.2207 + Moose::Exception::CouldNotParseType 2.2207 + Moose::Exception::CreateMOPClassTakesArrayRefOfAttributes 2.2207 + Moose::Exception::CreateMOPClassTakesArrayRefOfSuperclasses 2.2207 + Moose::Exception::CreateMOPClassTakesHashRefOfMethods 2.2207 + Moose::Exception::CreateTakesArrayRefOfRoles 2.2207 + Moose::Exception::CreateTakesHashRefOfAttributes 2.2207 + Moose::Exception::CreateTakesHashRefOfMethods 2.2207 + Moose::Exception::DefaultToMatchOnTypeMustBeCodeRef 2.2207 + Moose::Exception::DelegationToAClassWhichIsNotLoaded 2.2207 + Moose::Exception::DelegationToARoleWhichIsNotLoaded 2.2207 + Moose::Exception::DelegationToATypeWhichIsNotAClass 2.2207 + Moose::Exception::DoesRequiresRoleName 2.2207 + Moose::Exception::EnumCalledWithAnArrayRefAndAdditionalArgs 2.2207 + Moose::Exception::EnumValuesMustBeString 2.2207 + Moose::Exception::ExtendsMissingArgs 2.2207 + Moose::Exception::HandlesMustBeAHashRef 2.2207 + Moose::Exception::IllegalInheritedOptions 2.2207 + Moose::Exception::IllegalMethodTypeToAddMethodModifier 2.2207 + Moose::Exception::IncompatibleMetaclassOfSuperclass 2.2207 + Moose::Exception::InitMetaRequiresClass 2.2207 + Moose::Exception::InitializeTakesUnBlessedPackageName 2.2207 + Moose::Exception::InstanceBlessedIntoWrongClass 2.2207 + Moose::Exception::InstanceMustBeABlessedReference 2.2207 + Moose::Exception::InvalidArgPassedToMooseUtilMetaRole 2.2207 + Moose::Exception::InvalidArgumentToMethod 2.2207 + Moose::Exception::InvalidArgumentsToTraitAliases 2.2207 + Moose::Exception::InvalidBaseTypeGivenToCreateParameterizedTypeConstraint 2.2207 + Moose::Exception::InvalidHandleValue 2.2207 + Moose::Exception::InvalidHasProvidedInARole 2.2207 + Moose::Exception::InvalidNameForType 2.2207 + Moose::Exception::InvalidOverloadOperator 2.2207 + Moose::Exception::InvalidRoleApplication 2.2207 + Moose::Exception::InvalidTypeConstraint 2.2207 + Moose::Exception::InvalidTypeGivenToCreateParameterizedTypeConstraint 2.2207 + Moose::Exception::InvalidValueForIs 2.2207 + Moose::Exception::IsaDoesNotDoTheRole 2.2207 + Moose::Exception::IsaLacksDoesMethod 2.2207 + Moose::Exception::LazyAttributeNeedsADefault 2.2207 + Moose::Exception::Legacy 2.2207 + Moose::Exception::MOPAttributeNewNeedsAttributeName 2.2207 + Moose::Exception::MatchActionMustBeACodeRef 2.2207 + Moose::Exception::MessageParameterMustBeCodeRef 2.2207 + Moose::Exception::MetaclassIsAClassNotASubclassOfGivenMetaclass 2.2207 + Moose::Exception::MetaclassIsARoleNotASubclassOfGivenMetaclass 2.2207 + Moose::Exception::MetaclassIsNotASubclassOfGivenMetaclass 2.2207 + Moose::Exception::MetaclassMustBeASubclassOfMooseMetaClass 2.2207 + Moose::Exception::MetaclassMustBeASubclassOfMooseMetaRole 2.2207 + Moose::Exception::MetaclassMustBeDerivedFromClassMOPClass 2.2207 + Moose::Exception::MetaclassNotLoaded 2.2207 + Moose::Exception::MetaclassTypeIncompatible 2.2207 + Moose::Exception::MethodExpectedAMetaclassObject 2.2207 + Moose::Exception::MethodExpectsFewerArgs 2.2207 + Moose::Exception::MethodExpectsMoreArgs 2.2207 + Moose::Exception::MethodModifierNeedsMethodName 2.2207 + Moose::Exception::MethodNameConflictInRoles 2.2207 + Moose::Exception::MethodNameNotFoundInInheritanceHierarchy 2.2207 + Moose::Exception::MethodNameNotGiven 2.2207 + Moose::Exception::MustDefineAMethodName 2.2207 + Moose::Exception::MustDefineAnAttributeName 2.2207 + Moose::Exception::MustDefineAnOverloadOperator 2.2207 + Moose::Exception::MustHaveAtLeastOneValueToEnumerate 2.2207 + Moose::Exception::MustPassAHashOfOptions 2.2207 + Moose::Exception::MustPassAMooseMetaRoleInstanceOrSubclass 2.2207 + Moose::Exception::MustPassAPackageNameOrAnExistingClassMOPPackageInstance 2.2207 + Moose::Exception::MustPassEvenNumberOfArguments 2.2207 + Moose::Exception::MustPassEvenNumberOfAttributeOptions 2.2207 + Moose::Exception::MustProvideANameForTheAttribute 2.2207 + Moose::Exception::MustSpecifyAtleastOneMethod 2.2207 + Moose::Exception::MustSpecifyAtleastOneRole 2.2207 + Moose::Exception::MustSpecifyAtleastOneRoleToApplicant 2.2207 + Moose::Exception::MustSupplyAClassMOPAttributeInstance 2.2207 + Moose::Exception::MustSupplyADelegateToMethod 2.2207 + Moose::Exception::MustSupplyAMetaclass 2.2207 + Moose::Exception::MustSupplyAMooseMetaAttributeInstance 2.2207 + Moose::Exception::MustSupplyAnAccessorTypeToConstructWith 2.2207 + Moose::Exception::MustSupplyAnAttributeToConstructWith 2.2207 + Moose::Exception::MustSupplyArrayRefAsCurriedArguments 2.2207 + Moose::Exception::MustSupplyPackageNameAndName 2.2207 + Moose::Exception::NeedsTypeConstraintUnionForTypeCoercionUnion 2.2207 + Moose::Exception::NeitherAttributeNorAttributeNameIsGiven 2.2207 + Moose::Exception::NeitherClassNorClassNameIsGiven 2.2207 + Moose::Exception::NeitherRoleNorRoleNameIsGiven 2.2207 + Moose::Exception::NeitherTypeNorTypeNameIsGiven 2.2207 + Moose::Exception::NoAttributeFoundInSuperClass 2.2207 + Moose::Exception::NoBodyToInitializeInAnAbstractBaseClass 2.2207 + Moose::Exception::NoCasesMatched 2.2207 + Moose::Exception::NoConstraintCheckForTypeConstraint 2.2207 + Moose::Exception::NoDestructorClassSpecified 2.2207 + Moose::Exception::NoImmutableTraitSpecifiedForClass 2.2207 + Moose::Exception::NoParentGivenToSubtype 2.2207 + Moose::Exception::OnlyInstancesCanBeCloned 2.2207 + Moose::Exception::OperatorIsRequired 2.2207 + Moose::Exception::OverloadConflictInSummation 2.2207 + Moose::Exception::OverloadRequiresAMetaClass 2.2207 + Moose::Exception::OverloadRequiresAMetaMethod 2.2207 + Moose::Exception::OverloadRequiresAMetaOverload 2.2207 + Moose::Exception::OverloadRequiresAMethodNameOrCoderef 2.2207 + Moose::Exception::OverloadRequiresAnOperator 2.2207 + Moose::Exception::OverloadRequiresNamesForCoderef 2.2207 + Moose::Exception::OverrideConflictInComposition 2.2207 + Moose::Exception::OverrideConflictInSummation 2.2207 + Moose::Exception::PackageDoesNotUseMooseExporter 2.2207 + Moose::Exception::PackageNameAndNameParamsNotGivenToWrap 2.2207 + Moose::Exception::PackagesAndModulesAreNotCachable 2.2207 + Moose::Exception::ParameterIsNotSubtypeOfParent 2.2207 + Moose::Exception::ReferencesAreNotAllowedAsDefault 2.2207 + Moose::Exception::RequiredAttributeLacksInitialization 2.2207 + Moose::Exception::RequiredAttributeNeedsADefault 2.2207 + Moose::Exception::RequiredMethodsImportedByClass 2.2207 + Moose::Exception::RequiredMethodsNotImplementedByClass 2.2207 + Moose::Exception::Role::Attribute 2.2207 + Moose::Exception::Role::AttributeName 2.2207 + Moose::Exception::Role::Class 2.2207 + Moose::Exception::Role::EitherAttributeOrAttributeName 2.2207 + Moose::Exception::Role::Instance 2.2207 + Moose::Exception::Role::InstanceClass 2.2207 + Moose::Exception::Role::InvalidAttributeOptions 2.2207 + Moose::Exception::Role::Method 2.2207 + Moose::Exception::Role::ParamsHash 2.2207 + Moose::Exception::Role::Role 2.2207 + Moose::Exception::Role::RoleForCreate 2.2207 + Moose::Exception::Role::RoleForCreateMOPClass 2.2207 + Moose::Exception::Role::TypeConstraint 2.2207 + Moose::Exception::RoleDoesTheExcludedRole 2.2207 + Moose::Exception::RoleExclusionConflict 2.2207 + Moose::Exception::RoleNameRequired 2.2207 + Moose::Exception::RoleNameRequiredForMooseMetaRole 2.2207 + Moose::Exception::RolesDoNotSupportAugment 2.2207 + Moose::Exception::RolesDoNotSupportExtends 2.2207 + Moose::Exception::RolesDoNotSupportInner 2.2207 + Moose::Exception::RolesDoNotSupportRegexReferencesForMethodModifiers 2.2207 + Moose::Exception::RolesInCreateTakesAnArrayRef 2.2207 + Moose::Exception::RolesListMustBeInstancesOfMooseMetaRole 2.2207 + Moose::Exception::SingleParamsToNewMustBeHashRef 2.2207 + Moose::Exception::TriggerMustBeACodeRef 2.2207 + Moose::Exception::TypeConstraintCannotBeUsedForAParameterizableType 2.2207 + Moose::Exception::TypeConstraintIsAlreadyCreated 2.2207 + Moose::Exception::TypeParameterMustBeMooseMetaType 2.2207 + Moose::Exception::UnableToCanonicalizeHandles 2.2207 + Moose::Exception::UnableToCanonicalizeNonRolePackage 2.2207 + Moose::Exception::UnableToRecognizeDelegateMetaclass 2.2207 + Moose::Exception::UndefinedHashKeysPassedToMethod 2.2207 + Moose::Exception::UnionCalledWithAnArrayRefAndAdditionalArgs 2.2207 + Moose::Exception::UnionTakesAtleastTwoTypeNames 2.2207 + Moose::Exception::ValidationFailedForInlineTypeConstraint 2.2207 + Moose::Exception::ValidationFailedForTypeConstraint 2.2207 + Moose::Exception::WrapTakesACodeRefToBless 2.2207 + Moose::Exception::WrongTypeConstraintGiven 2.2207 + Moose::Exporter 2.2207 + Moose::Intro 2.2207 + Moose::Manual 2.2207 + Moose::Manual::Attributes 2.2207 + Moose::Manual::BestPractices 2.2207 + Moose::Manual::Classes 2.2207 + Moose::Manual::Concepts 2.2207 + Moose::Manual::Construction 2.2207 + Moose::Manual::Contributing 2.2207 + Moose::Manual::Delegation 2.2207 + Moose::Manual::Delta 2.2207 + Moose::Manual::Exceptions 2.2207 + Moose::Manual::Exceptions::Manifest 2.2207 + Moose::Manual::FAQ 2.2207 + Moose::Manual::MOP 2.2207 + Moose::Manual::MethodModifiers 2.2207 + Moose::Manual::MooseX 2.2207 + Moose::Manual::Resources 2.2207 + Moose::Manual::Roles 2.2207 + Moose::Manual::Support 2.2207 + Moose::Manual::Types 2.2207 + Moose::Manual::Unsweetened 2.2207 + Moose::Meta::Attribute 2.2207 + Moose::Meta::Attribute::Native 2.2207 + Moose::Meta::Attribute::Native::Trait 2.2207 + Moose::Meta::Attribute::Native::Trait::Array 2.2207 + Moose::Meta::Attribute::Native::Trait::Bool 2.2207 + Moose::Meta::Attribute::Native::Trait::Code 2.2207 + Moose::Meta::Attribute::Native::Trait::Counter 2.2207 + Moose::Meta::Attribute::Native::Trait::Hash 2.2207 + Moose::Meta::Attribute::Native::Trait::Number 2.2207 + Moose::Meta::Attribute::Native::Trait::String 2.2207 + Moose::Meta::Class 2.2207 + Moose::Meta::Class::Immutable::Trait 2.2207 + Moose::Meta::Instance 2.2207 + Moose::Meta::Method 2.2207 + Moose::Meta::Method::Accessor 2.2207 + Moose::Meta::Method::Accessor::Native 2.2207 + Moose::Meta::Method::Accessor::Native::Array 2.2207 + Moose::Meta::Method::Accessor::Native::Array::Writer 2.2207 + Moose::Meta::Method::Accessor::Native::Array::accessor 2.2207 + Moose::Meta::Method::Accessor::Native::Array::clear 2.2207 + Moose::Meta::Method::Accessor::Native::Array::count 2.2207 + Moose::Meta::Method::Accessor::Native::Array::delete 2.2207 + Moose::Meta::Method::Accessor::Native::Array::elements 2.2207 + Moose::Meta::Method::Accessor::Native::Array::first 2.2207 + Moose::Meta::Method::Accessor::Native::Array::first_index 2.2207 + Moose::Meta::Method::Accessor::Native::Array::get 2.2207 + Moose::Meta::Method::Accessor::Native::Array::grep 2.2207 + Moose::Meta::Method::Accessor::Native::Array::insert 2.2207 + Moose::Meta::Method::Accessor::Native::Array::is_empty 2.2207 + Moose::Meta::Method::Accessor::Native::Array::join 2.2207 + Moose::Meta::Method::Accessor::Native::Array::map 2.2207 + Moose::Meta::Method::Accessor::Native::Array::natatime 2.2207 + Moose::Meta::Method::Accessor::Native::Array::pop 2.2207 + Moose::Meta::Method::Accessor::Native::Array::push 2.2207 + Moose::Meta::Method::Accessor::Native::Array::reduce 2.2207 + Moose::Meta::Method::Accessor::Native::Array::set 2.2207 + Moose::Meta::Method::Accessor::Native::Array::shallow_clone 2.2207 + Moose::Meta::Method::Accessor::Native::Array::shift 2.2207 + Moose::Meta::Method::Accessor::Native::Array::shuffle 2.2207 + Moose::Meta::Method::Accessor::Native::Array::sort 2.2207 + Moose::Meta::Method::Accessor::Native::Array::sort_in_place 2.2207 + Moose::Meta::Method::Accessor::Native::Array::splice 2.2207 + Moose::Meta::Method::Accessor::Native::Array::uniq 2.2207 + Moose::Meta::Method::Accessor::Native::Array::unshift 2.2207 + Moose::Meta::Method::Accessor::Native::Bool::not 2.2207 + Moose::Meta::Method::Accessor::Native::Bool::set 2.2207 + Moose::Meta::Method::Accessor::Native::Bool::toggle 2.2207 + Moose::Meta::Method::Accessor::Native::Bool::unset 2.2207 + Moose::Meta::Method::Accessor::Native::Code::execute 2.2207 + Moose::Meta::Method::Accessor::Native::Code::execute_method 2.2207 + Moose::Meta::Method::Accessor::Native::Collection 2.2207 + Moose::Meta::Method::Accessor::Native::Counter::Writer 2.2207 + Moose::Meta::Method::Accessor::Native::Counter::dec 2.2207 + Moose::Meta::Method::Accessor::Native::Counter::inc 2.2207 + Moose::Meta::Method::Accessor::Native::Counter::reset 2.2207 + Moose::Meta::Method::Accessor::Native::Counter::set 2.2207 + Moose::Meta::Method::Accessor::Native::Hash 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::Writer 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::accessor 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::clear 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::count 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::defined 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::delete 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::elements 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::exists 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::get 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::is_empty 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::keys 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::kv 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::set 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::shallow_clone 2.2207 + Moose::Meta::Method::Accessor::Native::Hash::values 2.2207 + Moose::Meta::Method::Accessor::Native::Number::abs 2.2207 + Moose::Meta::Method::Accessor::Native::Number::add 2.2207 + Moose::Meta::Method::Accessor::Native::Number::div 2.2207 + Moose::Meta::Method::Accessor::Native::Number::mod 2.2207 + Moose::Meta::Method::Accessor::Native::Number::mul 2.2207 + Moose::Meta::Method::Accessor::Native::Number::set 2.2207 + Moose::Meta::Method::Accessor::Native::Number::sub 2.2207 + Moose::Meta::Method::Accessor::Native::Reader 2.2207 + Moose::Meta::Method::Accessor::Native::String::append 2.2207 + Moose::Meta::Method::Accessor::Native::String::chomp 2.2207 + Moose::Meta::Method::Accessor::Native::String::chop 2.2207 + Moose::Meta::Method::Accessor::Native::String::clear 2.2207 + Moose::Meta::Method::Accessor::Native::String::inc 2.2207 + Moose::Meta::Method::Accessor::Native::String::length 2.2207 + Moose::Meta::Method::Accessor::Native::String::match 2.2207 + Moose::Meta::Method::Accessor::Native::String::prepend 2.2207 + Moose::Meta::Method::Accessor::Native::String::replace 2.2207 + Moose::Meta::Method::Accessor::Native::String::substr 2.2207 + Moose::Meta::Method::Accessor::Native::Writer 2.2207 + Moose::Meta::Method::Augmented 2.2207 + Moose::Meta::Method::Constructor 2.2207 + Moose::Meta::Method::Delegation 2.2207 + Moose::Meta::Method::Destructor 2.2207 + Moose::Meta::Method::Meta 2.2207 + Moose::Meta::Method::Overridden 2.2207 + Moose::Meta::Mixin::AttributeCore 2.2207 + Moose::Meta::Object::Trait 2.2207 + Moose::Meta::Role 2.2207 + Moose::Meta::Role::Application 2.2207 + Moose::Meta::Role::Application::RoleSummation 2.2207 + Moose::Meta::Role::Application::ToClass 2.2207 + Moose::Meta::Role::Application::ToInstance 2.2207 + Moose::Meta::Role::Application::ToRole 2.2207 + Moose::Meta::Role::Attribute 2.2207 + Moose::Meta::Role::Composite 2.2207 + Moose::Meta::Role::Method 2.2207 + Moose::Meta::Role::Method::Conflicting 2.2207 + Moose::Meta::Role::Method::Required 2.2207 + Moose::Meta::TypeCoercion 2.2207 + Moose::Meta::TypeCoercion::Union 2.2207 + Moose::Meta::TypeConstraint 2.2207 + Moose::Meta::TypeConstraint::Class 2.2207 + Moose::Meta::TypeConstraint::DuckType 2.2207 + Moose::Meta::TypeConstraint::Enum 2.2207 + Moose::Meta::TypeConstraint::Parameterizable 2.2207 + Moose::Meta::TypeConstraint::Parameterized 2.2207 + Moose::Meta::TypeConstraint::Registry 2.2207 + Moose::Meta::TypeConstraint::Role 2.2207 + Moose::Meta::TypeConstraint::Union 2.2207 + Moose::Object 2.2207 + Moose::Role 2.2207 + Moose::Spec::Role 2.2207 + Moose::Unsweetened 2.2207 + Moose::Util 2.2207 + Moose::Util::MetaRole 2.2207 + Moose::Util::TypeConstraints 2.2207 + Moose::Util::TypeConstraints::Builtins 2.2207 + Test::Moose 2.2207 + metaclass 2.2207 + oose 2.2207 requirements: Carp 1.22 Class::Load 0.09 Class::Load::XS 0.01 Data::OptList 0.107 Devel::GlobalDestruction 0 + Devel::OverloadInfo 0.005 + Devel::StackTrace 2.03 Dist::CheckConflicts 0.02 Eval::Closure 0.04 - ExtUtils::MakeMaker 6.30 - List::MoreUtils 0.28 + ExtUtils::MakeMaker 0 + List::Util 1.56 MRO::Compat 0.05 + Module::Runtime 0.014 + Module::Runtime::Conflicts 0.002 Package::DeprecationManager 0.11 Package::Stash 0.32 Package::Stash::XS 0.24 Params::Util 1.00 Scalar::Util 1.19 Sub::Exporter 0.980 - Sub::Name 0.05 - Task::Weaken 0 - Test::Fatal 0.001 - Test::More 0.88 - Test::Requires 0.05 - Try::Tiny 0.02 - MooseX-Aliases-0.11 - pathname: D/DO/DOY/MooseX-Aliases-0.11.tar.gz - provides: - MooseX::Aliases 0.11 - MooseX::Aliases::Meta::Trait::Attribute 0.11 - MooseX::Aliases::Meta::Trait::Class 0.11 - MooseX::Aliases::Meta::Trait::Method 0.11 - MooseX::Aliases::Meta::Trait::Role 0.11 - MooseX::Aliases::Meta::Trait::Role::ApplicationToClass 0.11 - MooseX::Aliases::Meta::Trait::Role::ApplicationToRole 0.11 - MooseX::Aliases::Meta::Trait::Role::Composite 0.11 - requirements: - ExtUtils::MakeMaker 6.30 - Moose 2.0000 - Moose::Exporter 0 - Moose::Role 0 - Moose::Util::TypeConstraints 0 - Scalar::Util 0 - MooseX-Attribute-Chained-1.0.1 - pathname: P/PE/PERLER/MooseX-Attribute-Chained-1.0.1.tar.gz - provides: - Moose::Meta::Attribute::Custom::Trait::Chained 1.000001 - MooseX::Attribute::Chained 1.000001 - MooseX::Attribute::ChainedClone 1.000001 - MooseX::ChainedAccessors 1.000001 - MooseX::ChainedAccessors::Accessor 1.000001 - MooseX::Traits::Attribute::Chained 1.000001 - MooseX::Traits::Attribute::ChainedClone 1.000001 - requirements: - Module::Build 0.3601 + Sub::Util 1.40 + Try::Tiny 0.17 + parent 0.223 + strict 1.03 + warnings 1.03 + MooseX-Attribute-Chained-1.0.3 + pathname: T/TO/TOMHUKINS/MooseX-Attribute-Chained-1.0.3.tar.gz + provides: + Moose::Meta::Attribute::Custom::Trait::Chained v1.0.3 + MooseX::Attribute::Chained v1.0.3 + MooseX::Attribute::Chained::Method::Accessor v1.0.3 + MooseX::Attribute::ChainedClone v1.0.3 + MooseX::Attribute::ChainedClone::Method::Accessor v1.0.3 + MooseX::ChainedAccessors v1.0.3 + MooseX::ChainedAccessors::Accessor v1.0.3 + MooseX::Traits::Attribute::Chained v1.0.3 + MooseX::Traits::Attribute::ChainedClone v1.0.3 + requirements: + Module::Build 0.28 Moose 0 Test::More 0.88 Try::Tiny 0 MooseX-Attribute-Deflator-2.2.2 pathname: P/PE/PERLER/MooseX-Attribute-Deflator-2.2.2.tar.gz provides: - MooseX::Attribute::Deflator 2.002002 - MooseX::Attribute::Deflator::Meta::Role::Attribute 2.002002 - MooseX::Attribute::Deflator::Moose 2.002002 - MooseX::Attribute::Deflator::Registry 2.002002 - MooseX::Attribute::Deflator::Structured 2.002002 - MooseX::Attribute::LazyInflator 2.002002 - MooseX::Attribute::LazyInflator::Meta::Role::ApplicationToClass 2.002002 - MooseX::Attribute::LazyInflator::Meta::Role::ApplicationToRole 2.002002 - MooseX::Attribute::LazyInflator::Meta::Role::Attribute 2.002002 - MooseX::Attribute::LazyInflator::Meta::Role::Composite 2.002002 - MooseX::Attribute::LazyInflator::Meta::Role::Method::Accessor 2.002002 - MooseX::Attribute::LazyInflator::Meta::Role::Method::Constructor 2.002002 - MooseX::Attribute::LazyInflator::Meta::Role::Role 2.002002 - MooseX::Attribute::LazyInflator::Role::Class 2.002002 + MooseX::Attribute::Deflator v2.2.2 + MooseX::Attribute::Deflator::Meta::Role::Attribute v2.2.2 + MooseX::Attribute::Deflator::Moose v2.2.2 + MooseX::Attribute::Deflator::Registry v2.2.2 + MooseX::Attribute::Deflator::Structured v2.2.2 + MooseX::Attribute::LazyInflator v2.2.2 + MooseX::Attribute::LazyInflator::Meta::Role::ApplicationToClass v2.2.2 + MooseX::Attribute::LazyInflator::Meta::Role::ApplicationToRole v2.2.2 + MooseX::Attribute::LazyInflator::Meta::Role::Attribute v2.2.2 + MooseX::Attribute::LazyInflator::Meta::Role::Composite v2.2.2 + MooseX::Attribute::LazyInflator::Meta::Role::Method::Accessor v2.2.2 + MooseX::Attribute::LazyInflator::Meta::Role::Method::Constructor v2.2.2 + MooseX::Attribute::LazyInflator::Meta::Role::Role v2.2.2 + MooseX::Attribute::LazyInflator::Role::Class v2.2.2 requirements: DateTime 0 Devel::PartialDump 0 @@ -4758,209 +4619,140 @@ DISTRIBUTIONS MooseX::Types::Structured 0 Test::More 0.88 Try::Tiny 0 - MooseX-ClassAttribute-0.27 - pathname: D/DR/DROLSKY/MooseX-ClassAttribute-0.27.tar.gz - provides: - Child undef - Delegatee undef - HasClassAttribute undef - MooseX::ClassAttribute 0.27 - MooseX::ClassAttribute::Meta::Role::Attribute 0.27 - MooseX::ClassAttribute::Trait::Application 0.27 - MooseX::ClassAttribute::Trait::Application::ToClass 0.27 - MooseX::ClassAttribute::Trait::Application::ToRole 0.27 - MooseX::ClassAttribute::Trait::Attribute 0.27 - MooseX::ClassAttribute::Trait::Class 0.27 - MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes 0.27 - MooseX::ClassAttribute::Trait::Role 0.27 - MooseX::ClassAttribute::Trait::Role::Composite 0.27 - SharedTests undef - requirements: - ExtUtils::MakeMaker 6.30 - List::MoreUtils 0 - Moose 2.00 - Moose::Exporter 0 - Moose::Meta::Role::Attribute 0 - Moose::Role 0 - Moose::Util 0 - Moose::Util::MetaRole 0 - Scalar::Util 0 - Test::Fatal 0 - Test::More 0.88 - Test::Requires 0.05 - namespace::autoclean 0.11 - namespace::clean 0.20 - strict 0 - vars 0 - warnings 0 - MooseX-Emulate-Class-Accessor-Fast-0.00903 - pathname: F/FL/FLORA/MooseX-Emulate-Class-Accessor-Fast-0.00903.tar.gz + MooseX-Emulate-Class-Accessor-Fast-0.009032 + pathname: H/HA/HAARG/MooseX-Emulate-Class-Accessor-Fast-0.009032.tar.gz provides: - MooseX::Adopt::Class::Accessor::Fast 0.00200 - MooseX::Emulate::Class::Accessor::Fast 0.00903 + MooseX::Adopt::Class::Accessor::Fast 0.009032 + MooseX::Emulate::Class::Accessor::Fast 0.009032 MooseX::Emulate::Class::Accessor::Fast::Meta::Accessor undef MooseX::Emulate::Class::Accessor::Fast::Meta::Role::Attribute undef requirements: - ExtUtils::MakeMaker 6.42 + ExtUtils::MakeMaker 0 Moose 0.84 - Test::Exception 0 - Test::More 0 namespace::clean 0 - MooseX-Getopt-0.63 - pathname: E/ET/ETHER/MooseX-Getopt-0.63.tar.gz - provides: - MooseX::Getopt 0.63 - MooseX::Getopt::Basic 0.63 - MooseX::Getopt::Dashes 0.63 - MooseX::Getopt::GLD 0.63 - MooseX::Getopt::Meta::Attribute 0.63 - MooseX::Getopt::Meta::Attribute::NoGetopt 0.63 - MooseX::Getopt::Meta::Attribute::Trait 0.63 - MooseX::Getopt::Meta::Attribute::Trait::NoGetopt 0.63 - MooseX::Getopt::OptionTypeMap 0.63 - MooseX::Getopt::ProcessedArgv 0.63 - MooseX::Getopt::Strict 0.63 + MooseX-Fastly-Role-0.04 + pathname: L/LL/LLAP/MooseX-Fastly-Role-0.04.tar.gz + provides: + MooseX::Fastly::Role 0.04 + requirements: + Carp 0 + ExtUtils::MakeMaker 0 + HTTP::Tiny 0 + Moose::Role 0 + Net::Fastly 1.08 + MooseX-Getopt-0.78 + pathname: E/ET/ETHER/MooseX-Getopt-0.78.tar.gz + provides: + MooseX::Getopt 0.78 + MooseX::Getopt::Basic 0.78 + MooseX::Getopt::Dashes 0.78 + MooseX::Getopt::GLD 0.78 + MooseX::Getopt::Meta::Attribute 0.78 + MooseX::Getopt::Meta::Attribute::NoGetopt 0.78 + MooseX::Getopt::Meta::Attribute::Trait 0.78 + MooseX::Getopt::Meta::Attribute::Trait::NoGetopt 0.78 + MooseX::Getopt::OptionTypeMap 0.78 + MooseX::Getopt::ProcessedArgv 0.78 + MooseX::Getopt::Strict 0.78 requirements: Carp 0 - ExtUtils::MakeMaker 6.30 Getopt::Long 2.37 - Getopt::Long::Descriptive 0.081 - Module::Build::Tiny 0.035 + Getopt::Long::Descriptive 0.088 + Module::Build::Tiny 0.034 Moose 0 Moose::Meta::Attribute 0 Moose::Role 0.56 Moose::Util::TypeConstraints 0 - MooseX::Role::Parameterized 0 + MooseX::Role::Parameterized 1.01 Scalar::Util 0 Try::Tiny 0 namespace::autoclean 0 perl 5.006 strict 0 warnings 0 - MooseX-MethodAttributes-0.29 - pathname: E/ET/ETHER/MooseX-MethodAttributes-0.29.tar.gz - provides: - MooseX::MethodAttributes 0.29 - MooseX::MethodAttributes::Inheritable 0.29 - MooseX::MethodAttributes::Role 0.29 - MooseX::MethodAttributes::Role::AttrContainer 0.29 - MooseX::MethodAttributes::Role::AttrContainer::Inheritable 0.29 - MooseX::MethodAttributes::Role::Meta::Class 0.29 - MooseX::MethodAttributes::Role::Meta::Map 0.29 - MooseX::MethodAttributes::Role::Meta::Method 0.29 - MooseX::MethodAttributes::Role::Meta::Method::MaybeWrapped 0.29 - MooseX::MethodAttributes::Role::Meta::Method::Wrapped 0.29 - MooseX::MethodAttributes::Role::Meta::Role 0.29 - MooseX::MethodAttributes::Role::Meta::Role::Application 0.29 - MooseX::MethodAttributes::Role::Meta::Role::Application::Summation 0.29 + MooseX-MethodAttributes-0.32 + pathname: E/ET/ETHER/MooseX-MethodAttributes-0.32.tar.gz + provides: + MooseX::MethodAttributes 0.32 + MooseX::MethodAttributes::Inheritable 0.32 + MooseX::MethodAttributes::Role 0.32 + MooseX::MethodAttributes::Role::AttrContainer 0.32 + MooseX::MethodAttributes::Role::AttrContainer::Inheritable 0.32 + MooseX::MethodAttributes::Role::Meta::Class 0.32 + MooseX::MethodAttributes::Role::Meta::Map 0.32 + MooseX::MethodAttributes::Role::Meta::Method 0.32 + MooseX::MethodAttributes::Role::Meta::Method::MaybeWrapped 0.32 + MooseX::MethodAttributes::Role::Meta::Method::Wrapped 0.32 + MooseX::MethodAttributes::Role::Meta::Role 0.32 + MooseX::MethodAttributes::Role::Meta::Role::Application 0.32 + MooseX::MethodAttributes::Role::Meta::Role::Application::Summation 0.32 requirements: Carp 0 - ExtUtils::MakeMaker 6.30 - Module::Build::Tiny 0.030 - Moose 0.98 - MooseX::Types::Moose 0.21 + ExtUtils::MakeMaker 0 + Moose 0 + Moose::Exporter 0 + Moose::Role 0 + Moose::Util 0 + Moose::Util::MetaRole 0 namespace::autoclean 0.08 perl 5.006 - MooseX-RelatedClassRoles-0.004 - pathname: H/HD/HDP/MooseX-RelatedClassRoles-0.004.tar.gz + MooseX-Role-Parameterized-1.11 + pathname: E/ET/ETHER/MooseX-Role-Parameterized-1.11.tar.gz provides: - MooseX::RelatedClassRoles 0.004 + MooseX::Role::Parameterised 1.11 + MooseX::Role::Parameterized 1.11 + MooseX::Role::Parameterized::Meta::Role::Parameterized 1.11 + MooseX::Role::Parameterized::Meta::Trait::Parameterizable 1.11 + MooseX::Role::Parameterized::Meta::Trait::Parameterized 1.11 + MooseX::Role::Parameterized::Parameters 1.11 requirements: - Class::MOP 0.80 + Carp 0 ExtUtils::MakeMaker 0 - Moose 0.73 - MooseX::Role::Parameterized 0.04 - MooseX-Role-Parameterized-1.02 - pathname: S/SA/SARTAK/MooseX-Role-Parameterized-1.02.tar.gz - provides: - MooseX::Role::Parameterized 1.02 - MooseX::Role::Parameterized::Meta::Role::Parameterizable 1.02 - MooseX::Role::Parameterized::Meta::Role::Parameterized 1.02 - MooseX::Role::Parameterized::Meta::Trait::Parameterized 1.02 - MooseX::Role::Parameterized::Parameters 1.02 - requirements: - ExtUtils::MakeMaker 6.59 + Module::Build::Tiny 0.034 Module::Runtime 0 Moose 2.0300 - Test::Fatal 0 - Test::Moose 0 - Test::More 0.96 + Moose::Exporter 0 + Moose::Meta::Role 0 + Moose::Role 0 + Moose::Util 0 + namespace::autoclean 0 + namespace::clean 0.19 perl 5.008001 - MooseX-Role-WithOverloading-0.13 - pathname: E/ET/ETHER/MooseX-Role-WithOverloading-0.13.tar.gz - provides: - MooseX::Role::WithOverloading 0.13 - MooseX::Role::WithOverloading::Meta::Role 0.13 - MooseX::Role::WithOverloading::Meta::Role::Application 0.13 - MooseX::Role::WithOverloading::Meta::Role::Application::Composite 0.13 - MooseX::Role::WithOverloading::Meta::Role::Application::Composite::ToClass 0.13 - MooseX::Role::WithOverloading::Meta::Role::Application::Composite::ToInstance 0.13 - MooseX::Role::WithOverloading::Meta::Role::Application::Composite::ToRole 0.13 - MooseX::Role::WithOverloading::Meta::Role::Application::FixOverloadedRefs 0.13 - MooseX::Role::WithOverloading::Meta::Role::Application::ToClass 0.13 - MooseX::Role::WithOverloading::Meta::Role::Application::ToInstance 0.13 - MooseX::Role::WithOverloading::Meta::Role::Application::ToRole 0.13 - MooseX::Role::WithOverloading::Meta::Role::Composite 0.13 - requirements: - ExtUtils::MakeMaker 6.30 - Moose 0.94 - Moose::Role 1.15 - Test::CheckDeps 0.002 - Test::More 0.88 - Test::NoWarnings 1.04 - aliased 0 - namespace::autoclean 0.12 - namespace::clean 0 - MooseX-StrictConstructor-0.19 - pathname: D/DR/DROLSKY/MooseX-StrictConstructor-0.19.tar.gz + strict 0 + warnings 0 + MooseX-StrictConstructor-0.21 + pathname: D/DR/DROLSKY/MooseX-StrictConstructor-0.21.tar.gz provides: - MooseX::StrictConstructor 0.19 - MooseX::StrictConstructor::Trait::Class 0.19 - MooseX::StrictConstructor::Trait::Method::Constructor 0.19 + MooseX::StrictConstructor 0.21 + MooseX::StrictConstructor::Trait::Class 0.21 + MooseX::StrictConstructor::Trait::Method::Constructor 0.21 requirements: B 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 Moose 0.94 Moose::Exporter 0 Moose::Role 0 Moose::Util::MetaRole 0 - Test::Fatal 0 - Test::Moose 0 - Test::More 0.88 namespace::autoclean 0 strict 0 warnings 0 - MooseX-Traits-Pluggable-0.12 - pathname: R/RK/RKITOVER/MooseX-Traits-Pluggable-0.12.tar.gz - provides: - MooseX::Traits::Pluggable 0.12 - requirements: - Carp 0 - Class::Load 0 - ExtUtils::MakeMaker 6.30 - List::MoreUtils 0 - Moose::Role 0 - Moose::Util 0 - Scalar::Util 0 - namespace::autoclean 0 - MooseX-Types-0.44 - pathname: E/ET/ETHER/MooseX-Types-0.44.tar.gz - provides: - MooseX::Types 0.44 - MooseX::Types::Base 0.44 - MooseX::Types::CheckedUtilExports 0.44 - MooseX::Types::Combine 0.44 - MooseX::Types::Moose 0.44 - MooseX::Types::TypeDecorator 0.44 - MooseX::Types::UndefinedType 0.44 - MooseX::Types::Util 0.44 - MooseX::Types::Wrapper 0.44 + MooseX-Types-0.51 + pathname: E/ET/ETHER/MooseX-Types-0.51.tar.gz + provides: + MooseX::Types 0.51 + MooseX::Types::Base 0.51 + MooseX::Types::CheckedUtilExports 0.51 + MooseX::Types::Combine 0.51 + MooseX::Types::Moose 0.51 + MooseX::Types::TypeDecorator 0.51 + MooseX::Types::UndefinedType 0.51 + MooseX::Types::Util 0.51 + MooseX::Types::Wrapper 0.51 requirements: Carp 0 Carp::Clan 6.00 Exporter 0 - ExtUtils::MakeMaker 6.30 - Module::Build::Tiny 0.035 + Module::Build::Tiny 0.034 Module::Runtime 0 Moose 1.06 Moose::Exporter 0 @@ -4968,87 +4760,34 @@ DISTRIBUTIONS Moose::Util::TypeConstraints 0 Scalar::Util 1.19 Sub::Exporter 0 - Sub::Name 0 + Sub::Exporter::ForMethods 0.100052 + Sub::Install 0 + Sub::Util 0 base 0 - namespace::autoclean 0.08 - namespace::clean 0 + namespace::autoclean 0.16 overload 0 + parent 0 perl 5.008 strict 0 warnings 0 - MooseX-Types-Common-0.001012 - pathname: E/ET/ETHER/MooseX-Types-Common-0.001012.tar.gz - provides: - MooseX::Types::Common 0.001012 - MooseX::Types::Common::Numeric 0.001012 - MooseX::Types::Common::String 0.001012 - requirements: - Carp 0 - ExtUtils::MakeMaker 6.30 - Module::Build::Tiny 0.030 - MooseX::Types 0 - MooseX::Types::Moose 0 - perl 5.008 - strict 0 - warnings 0 - MooseX-Types-ElasticSearch-0.0.2 - pathname: P/PE/PERLER/MooseX-Types-ElasticSearch-0.0.2.tar.gz + MooseX-Types-ElasticSearch-0.0.4 + pathname: P/PE/PERLER/MooseX-Types-ElasticSearch-0.0.4.tar.gz provides: - MooseX::Types::ElasticSearch 0.000002 + MooseX::Types::ElasticSearch v0.0.4 requirements: DateTime::Format::Epoch::Unix 0 DateTime::Format::ISO8601 0 - ElasticSearch 0 Module::Build 0.3601 MooseX::Types 0 - MooseX-Types-Path-Class-0.06 - pathname: T/TH/THEPLER/MooseX-Types-Path-Class-0.06.tar.gz - provides: - MooseX::Types::Path::Class 0.06 - requirements: - Class::MOP 0 - ExtUtils::MakeMaker 6.30 - Moose 0.39 - MooseX::Types 0.04 - Path::Class 0.16 - Test::More 0.88 - MooseX-Types-Path-Class-MoreCoercions-0.003 - pathname: D/DA/DAGOLDEN/MooseX-Types-Path-Class-MoreCoercions-0.003.tar.gz + Search::Elasticsearch 0 + MooseX-Types-Structured-0.36 + pathname: E/ET/ETHER/MooseX-Types-Structured-0.36.tar.gz provides: - MooseX::Types::Path::Class::MoreCoercions 0.003 - requirements: - ExtUtils::MakeMaker 6.30 - File::Find 0 - File::Temp 0 - File::pushd 0 - Moose 0 - MooseX::Types 0 - MooseX::Types::Path::Class 0 - MooseX::Types::Stringlike 0 - Path::Class 0 - Test::More 0.96 - strict 0 - warnings 0 - MooseX-Types-Stringlike-0.003 - pathname: D/DA/DAGOLDEN/MooseX-Types-Stringlike-0.003.tar.gz - provides: - MooseX::Types::Stringlike 0.003 - requirements: - ExtUtils::MakeMaker 6.17 - MooseX::Types 0 - MooseX::Types::Moose 0 - overload 0 - strict 0 - warnings 0 - MooseX-Types-Structured-0.30 - pathname: E/ET/ETHER/MooseX-Types-Structured-0.30.tar.gz - provides: - MooseX::Types::Structured 0.30 + MooseX::Types::Structured 0.36 requirements: Devel::PartialDump 0.13 - ExtUtils::MakeMaker 6.30 - Module::Build::Tiny 0.030 - Moose 1.08 + Module::Build::Tiny 0.034 + Moose 0 Moose::Meta::TypeCoercion 0 Moose::Meta::TypeConstraint 0 Moose::Meta::TypeConstraint::Parameterizable 0 @@ -5056,207 +4795,261 @@ DISTRIBUTIONS MooseX::Types 0.22 Scalar::Util 0 Sub::Exporter 0.982 + if 0 + namespace::clean 0.19 overload 0 perl 5.008 - MooseX-Types-URI-0.07 - pathname: E/ET/ETHER/MooseX-Types-URI-0.07.tar.gz - provides: - MooseX::Types::URI 0.07 - requirements: - ExtUtils::MakeMaker 6.30 - Module::Build::Tiny 0.036 - Moose::Util::TypeConstraints 0 - MooseX::Types 0.40 - MooseX::Types::Moose 0 - MooseX::Types::Path::Class 0 - Scalar::Util 0 - URI 0 - URI::FromHash 0 - URI::QueryParam 0 - URI::WithBase 0 - URI::data 0 - URI::file 0 - if 0 - namespace::autoclean 0 - perl 5.006 - strict 0 - warnings 0 - Mouse-2.3.0 - pathname: G/GF/GFUJI/Mouse-2.3.0.tar.gz - provides: - Mouse 2.003000 - Mouse::Exporter undef - Mouse::Meta::Attribute undef - Mouse::Meta::Class undef - Mouse::Meta::Method undef - Mouse::Meta::Method::Accessor undef - Mouse::Meta::Method::Constructor undef - Mouse::Meta::Method::Delegation undef - Mouse::Meta::Method::Destructor undef - Mouse::Meta::Module undef - Mouse::Meta::Role undef - Mouse::Meta::Role::Application undef - Mouse::Meta::Role::Composite undef - Mouse::Meta::Role::Method undef - Mouse::Meta::TypeConstraint undef - Mouse::Object undef - Mouse::PurePerl undef - Mouse::Role 2.003000 - Mouse::Spec 2.003000 - Mouse::TypeRegistry undef - Mouse::Util 2.003000 - Mouse::Util::MetaRole undef - Mouse::Util::TypeConstraints undef - Squirrel undef - Squirrel::Role undef - Test::Mouse undef - ouse undef - requirements: - CPAN::Meta 0 - CPAN::Meta::Prereqs 0 - Devel::PPPort 3.19 - ExtUtils::CBuilder 0 - ExtUtils::ParseXS 3.22 - Module::Build 0.4005 - Module::Build::XSUtil 0.10 - Scalar::Util 1.14 - XSLoader 0.02 - perl 5.008005 - Mozilla-CA-20130114 - pathname: A/AB/ABH/Mozilla-CA-20130114.tar.gz - provides: - Mozilla::CA 20130114 - requirements: - ExtUtils::MakeMaker 0 - Test 0 - perl 5.006 - Net-CIDR-Lite-0.21 - pathname: D/DO/DOUGW/Net-CIDR-Lite-0.21.tar.gz - provides: - Net::CIDR::Lite 0.21 - Net::CIDR::Lite::Span 0.21 - requirements: - ExtUtils::MakeMaker 0 - Net-DNS-0.76 - pathname: N/NL/NLNETLABS/Net-DNS-0.76.tar.gz - provides: - Net::DNS 0.76 - Net::DNS::Domain 1195 - Net::DNS::DomainName 1177 - Net::DNS::DomainName1035 1177 - Net::DNS::DomainName2535 1177 - Net::DNS::Header 1101 - Net::DNS::Mailbox 1155 - Net::DNS::Mailbox1035 1155 - Net::DNS::Mailbox2535 1155 - Net::DNS::Nameserver 1186 - Net::DNS::Packet 1204 - Net::DNS::Parameters 1194 - Net::DNS::Question 1098 - Net::DNS::RR 1203 - Net::DNS::RR::A 1188 - Net::DNS::RR::AAAA 1188 - Net::DNS::RR::AFSDB 1188 - Net::DNS::RR::APL 1188 - Net::DNS::RR::APL::Item 1188 - Net::DNS::RR::CAA 1188 - Net::DNS::RR::CERT 1188 - Net::DNS::RR::CNAME 1188 - Net::DNS::RR::DHCID 1188 - Net::DNS::RR::DNAME 1188 - Net::DNS::RR::EUI48 1188 - Net::DNS::RR::EUI64 1188 - Net::DNS::RR::GPOS 1188 - Net::DNS::RR::HINFO 1188 - Net::DNS::RR::HIP 1188 - Net::DNS::RR::IPSECKEY 1188 - Net::DNS::RR::ISDN 1188 - Net::DNS::RR::KX 1188 - Net::DNS::RR::L32 1188 - Net::DNS::RR::L64 1188 - Net::DNS::RR::LOC 1188 - Net::DNS::RR::LP 1188 - Net::DNS::RR::MB 1182 - Net::DNS::RR::MG 1182 - Net::DNS::RR::MINFO 1188 - Net::DNS::RR::MR 1182 - Net::DNS::RR::MX 1188 - Net::DNS::RR::NAPTR 1188 - Net::DNS::RR::NID 1188 - Net::DNS::RR::NS 1188 - Net::DNS::RR::NULL 1188 - Net::DNS::RR::OPT 1203 - Net::DNS::RR::PTR 1188 - Net::DNS::RR::PX 1188 - Net::DNS::RR::RP 1189 - Net::DNS::RR::RT 1188 - Net::DNS::RR::SOA 1188 - Net::DNS::RR::SPF 1188 - Net::DNS::RR::SRV 1188 - Net::DNS::RR::SSHFP 1188 - Net::DNS::RR::TKEY 1188 - Net::DNS::RR::TLSA 1188 - Net::DNS::RR::TSIG 1188 - Net::DNS::RR::TXT 1206 - Net::DNS::RR::X25 1188 - Net::DNS::Resolver 1202 - Net::DNS::Resolver::Base 1204 - Net::DNS::Resolver::MSWin32 1202 - Net::DNS::Resolver::Recurse 1185 - Net::DNS::Resolver::UNIX 1185 - Net::DNS::Resolver::cygwin 1202 - Net::DNS::Resolver::os2 1185 - Net::DNS::Text 1206 - Net::DNS::Update 1171 - Net::DNS::ZoneFile 1197 - Net::DNS::ZoneFile::Generator 1197 - Net::DNS::ZoneFile::Text 1197 - requirements: - Digest::HMAC 1.01 - Digest::MD5 2.13 + Mozilla-CA-20250202 + pathname: L/LW/LWP/Mozilla-CA-20250202.tar.gz + provides: + Mozilla::CA 20250202 + requirements: + ExtUtils::MakeMaker 0 + Net-DNS-1.50 + pathname: N/NL/NLNETLABS/Net-DNS-1.50.tar.gz + provides: + Net::DNS 1.50 + Net::DNS::Domain 2002 + Net::DNS::DomainName 2005 + Net::DNS::DomainName1035 2005 + Net::DNS::DomainName2535 2005 + Net::DNS::Header 2002 + Net::DNS::Mailbox 2002 + Net::DNS::Mailbox1035 2002 + Net::DNS::Mailbox2535 2002 + Net::DNS::Nameserver 2002 + Net::DNS::Packet 2003 + Net::DNS::Parameters 2002 + Net::DNS::Question 2002 + Net::DNS::RR 2003 + Net::DNS::RR::A 2003 + Net::DNS::RR::AAAA 2003 + Net::DNS::RR::AFSDB 2002 + Net::DNS::RR::AMTRELAY 2003 + Net::DNS::RR::APL 2003 + Net::DNS::RR::APL::Item 2003 + Net::DNS::RR::CAA 2003 + Net::DNS::RR::CDNSKEY 2003 + Net::DNS::RR::CDS 2003 + Net::DNS::RR::CERT 2002 + Net::DNS::RR::CNAME 2003 + Net::DNS::RR::CSYNC 2003 + Net::DNS::RR::DELEG 2003 + Net::DNS::RR::DHCID 2003 + Net::DNS::RR::DNAME 2003 + Net::DNS::RR::DNSKEY 2003 + Net::DNS::RR::DS 2003 + Net::DNS::RR::DSYNC 2003 + Net::DNS::RR::EUI48 2003 + Net::DNS::RR::EUI64 2003 + Net::DNS::RR::GPOS 2003 + Net::DNS::RR::HINFO 2003 + Net::DNS::RR::HIP 2003 + Net::DNS::RR::HTTPS 2002 + Net::DNS::RR::IPSECKEY 2003 + Net::DNS::RR::ISDN 2002 + Net::DNS::RR::KEY 2002 + Net::DNS::RR::KX 2003 + Net::DNS::RR::L32 2003 + Net::DNS::RR::L64 2003 + Net::DNS::RR::LOC 2003 + Net::DNS::RR::LP 2003 + Net::DNS::RR::MB 2002 + Net::DNS::RR::MG 2002 + Net::DNS::RR::MINFO 2002 + Net::DNS::RR::MR 2002 + Net::DNS::RR::MX 2002 + Net::DNS::RR::NAPTR 2003 + Net::DNS::RR::NID 2003 + Net::DNS::RR::NS 2003 + Net::DNS::RR::NSEC 2002 + Net::DNS::RR::NSEC3 2003 + Net::DNS::RR::NSEC3PARAM 2003 + Net::DNS::RR::NULL 2002 + Net::DNS::RR::OPENPGPKEY 2003 + Net::DNS::RR::OPT 2005 + Net::DNS::RR::OPT::CHAIN 2005 + Net::DNS::RR::OPT::CLIENT_SUBNET 2005 + Net::DNS::RR::OPT::COOKIE 2005 + Net::DNS::RR::OPT::DAU 2005 + Net::DNS::RR::OPT::DHU 2005 + Net::DNS::RR::OPT::EXPIRE 2005 + Net::DNS::RR::OPT::EXTENDED_ERROR 2005 + Net::DNS::RR::OPT::KEY_TAG 2005 + Net::DNS::RR::OPT::N3U 2005 + Net::DNS::RR::OPT::NSID 2005 + Net::DNS::RR::OPT::PADDING 2005 + Net::DNS::RR::OPT::REPORT_CHANNEL 2005 + Net::DNS::RR::OPT::TCP_KEEPALIVE 2005 + Net::DNS::RR::OPT::ZONEVERSION 2005 + Net::DNS::RR::PTR 2002 + Net::DNS::RR::PX 2003 + Net::DNS::RR::RESINFO 2003 + Net::DNS::RR::RP 2002 + Net::DNS::RR::RRSIG 2003 + Net::DNS::RR::RT 2003 + Net::DNS::RR::SIG 2003 + Net::DNS::RR::SMIMEA 2003 + Net::DNS::RR::SOA 2002 + Net::DNS::RR::SPF 2003 + Net::DNS::RR::SRV 2003 + Net::DNS::RR::SSHFP 2003 + Net::DNS::RR::SVCB 2003 + Net::DNS::RR::TKEY 2003 + Net::DNS::RR::TLSA 2003 + Net::DNS::RR::TSIG 2003 + Net::DNS::RR::TXT 2003 + Net::DNS::RR::URI 2003 + Net::DNS::RR::X25 2002 + Net::DNS::RR::ZONEMD 2003 + Net::DNS::Resolver 2009 + Net::DNS::Resolver::Base 2011 + Net::DNS::Resolver::MSWin32 2002 + Net::DNS::Resolver::Recurse 2002 + Net::DNS::Resolver::UNIX 2007 + Net::DNS::Resolver::android 2007 + Net::DNS::Resolver::cygwin 2002 + Net::DNS::Resolver::os2 2007 + Net::DNS::Resolver::os390 2007 + Net::DNS::Text 2002 + Net::DNS::Update 2003 + Net::DNS::ZoneFile 2002 + Net::DNS::ZoneFile::Generator 2002 + Net::DNS::ZoneFile::Text 2002 + requirements: + Carp 1.1 + Config 0 + Digest::HMAC 1.03 + Digest::MD5 2.37 Digest::SHA 5.23 + Encode 2.26 + Exporter 5.63 + ExtUtils::MakeMaker 6.48 + File::Spec 3.29 + Getopt::Long 2.43 + IO::File 1.14 + IO::Select 1.17 + IO::Socket 1.3 + IO::Socket::IP 0.38 + MIME::Base64 3.07 + PerlIO 1.05 + Scalar::Util 1.19 + Socket 1.81 + Time::Local 1.19 + base 2.13 + constant 1.17 + integer 1 + overload 1.06 + perl 5.008009 + strict 1.03 + warnings 1.0501 + Net-Fastly-1.12 + pathname: F/FA/FASTLY/Net-Fastly-1.12.tar.gz + provides: + Net::Fastly 1.12 + Net::Fastly::Backend undef + Net::Fastly::BelongsToServiceAndVersion undef + Net::Fastly::Client undef + Net::Fastly::Client::UserAgent undef + Net::Fastly::Condition undef + Net::Fastly::Customer undef + Net::Fastly::Director undef + Net::Fastly::Domain undef + Net::Fastly::Healthcheck undef + Net::Fastly::Invoice undef + Net::Fastly::Match undef + Net::Fastly::Model undef + Net::Fastly::Origin undef + Net::Fastly::Service undef + Net::Fastly::Settings undef + Net::Fastly::Stats undef + Net::Fastly::Syslog undef + Net::Fastly::UA undef + Net::Fastly::User undef + Net::Fastly::VCL undef + Net::Fastly::Version undef + requirements: + Class::Accessor::Fast 0 + File::Basename 0 + File::Spec 0 + File::Temp 0 + IO::Socket::SSL != 1.38 + JSON::XS 0 + LWP::Protocol::https 0 + LWP::UserAgent 5.813 + Module::Build::Tiny 0.034 + Test::More 0 + URI 0 + URI::Escape 0 + YAML 0 + Net-GitHub-1.05 + pathname: F/FA/FAYLAND/Net-GitHub-1.05.tar.gz + provides: + Net::GitHub 1.05 + Net::GitHub::V3 1.05 + Net::GitHub::V3::Actions 1.05 + Net::GitHub::V3::Events 1.05 + Net::GitHub::V3::Gists 1.05 + Net::GitHub::V3::GitData 1.05 + Net::GitHub::V3::Gitignore 1.05 + Net::GitHub::V3::Issues 1.05 + Net::GitHub::V3::OAuth 1.05 + Net::GitHub::V3::Orgs 0.60 + Net::GitHub::V3::PullRequests 1.05 + Net::GitHub::V3::Query 1.05 + Net::GitHub::V3::Repos 1.05 + Net::GitHub::V3::ResultSet 1.05 + Net::GitHub::V3::Search 0.68 + Net::GitHub::V3::Users 1.05 + Net::GitHub::V4 1.05 + requirements: + Cache::LRU 0 ExtUtils::MakeMaker 0 - IO::Socket 1.24 - MIME::Base64 2.11 - Test::More 0.52 - perl 5.00404 - Net-DNS-Paranoid-0.07 - pathname: T/TO/TOKUHIROM/Net-DNS-Paranoid-0.07.tar.gz - provides: - Net::DNS::Paranoid 0.07 - requirements: - Class::Accessor::Lite 0.05 - Module::Build 0.38 - Net::DNS 0.68 - Test::More 0.98 - parent 0 - perl 5.008008 - Net-HTTP-6.06 - pathname: G/GA/GAAS/Net-HTTP-6.06.tar.gz + HTTP::Request 0 + JSON::MaybeXS 0 + LWP::Protocol::https 0 + LWP::UserAgent 0 + MIME::Base64 0 + Moo 0 + Types::Standard 0 + URI 0 + URI::Escape 0 + Net-HTTP-6.23 + pathname: O/OA/OALDERS/Net-HTTP-6.23.tar.gz provides: - Net::HTTP 6.06 - Net::HTTP::Methods 6.06 - Net::HTTP::NB 6.04 - Net::HTTPS 6.04 + Net::HTTP 6.23 + Net::HTTP::Methods 6.23 + Net::HTTP::NB 6.23 + Net::HTTPS 6.23 requirements: + Carp 0 Compress::Raw::Zlib 0 ExtUtils::MakeMaker 0 - IO::Compress::Gzip 0 - IO::Select 0 IO::Socket::INET 0 + IO::Uncompress::Gunzip 0 + URI 0 + base 0 perl 5.006002 - Net-OAuth-0.28 - pathname: K/KG/KGRENNAN/Net-OAuth-0.28.tar.gz + strict 0 + warnings 0 + Net-IP-1.26 + pathname: M/MA/MANU/Net-IP-1.26.tar.gz provides: - Net::OAuth 0.28 + Net::IP 1.26 + requirements: + ExtUtils::MakeMaker 0 + Net-OAuth-0.31 + pathname: R/RR/RRWO/Net-OAuth-0.31.tar.gz + provides: + Net::OAuth 0.31 Net::OAuth::AccessToken undef Net::OAuth::AccessTokenRequest undef Net::OAuth::AccessTokenResponse undef - Net::OAuth::Client undef + Net::OAuth::Client 0.31 Net::OAuth::ConsumerRequest undef Net::OAuth::Message undef Net::OAuth::ProtectedResourceRequest undef - Net::OAuth::Request 0.28 + Net::OAuth::Request 0.31 Net::OAuth::RequestTokenRequest undef Net::OAuth::RequestTokenResponse undef Net::OAuth::Response undef @@ -5275,172 +5068,26 @@ DISTRIBUTIONS requirements: Class::Accessor 0.31 Class::Data::Inheritable 0.06 - Digest::HMAC_SHA1 1.01 + Crypt::URandom 0.37 Digest::SHA 5.47 - Digest::SHA1 2.12 Encode 2.35 + ExtUtils::MakeMaker 0 LWP::UserAgent 1 Test::More 0.66 Test::Warn 0.21 - URI::Escape 3.28 - Net-OpenID-Common-1.18 - pathname: W/WR/WROG/Net-OpenID-Common-1.18.tar.gz - provides: - Net::OpenID::Common 1.18 - Net::OpenID::Extension 1.18 - Net::OpenID::Extension::SimpleRegistration 1.18 - Net::OpenID::Extension::SimpleRegistration::Request 1.18 - Net::OpenID::Extension::SimpleRegistration::Response 1.18 - Net::OpenID::ExtensionMessage 1.18 - Net::OpenID::IndirectMessage 1.18 - Net::OpenID::URIFetch 1.18 - Net::OpenID::URIFetch::Response 1.18 - Net::OpenID::Yadis 1.18 - Net::OpenID::Yadis::Service 1.18 - OpenID::util 1.18 - requirements: - Crypt::DH::GMP 0.00011 - Encode 0 - ExtUtils::MakeMaker 6.30 - HTML::Parser 3.40 - HTTP::Headers::Util 0 - HTTP::Request 0 - HTTP::Status 0 - MIME::Base64 0 - Math::BigInt 0 - Test::More 0 - Time::Local 0 - XML::Simple 0 - Net-OpenID-Consumer-1.15 - pathname: W/WR/WROG/Net-OpenID-Consumer-1.15.tar.gz - provides: - FakeFetch undef - Net::OpenID::Association 1.15 - Net::OpenID::ClaimedIdentity 1.15 - Net::OpenID::Consumer 1.15 - Net::OpenID::VerifiedIdentity 1.15 - requirements: - Digest::SHA 0 - ExtUtils::MakeMaker 6.30 - HTTP::Request 0 - JSON 0 - LWP::UserAgent 0 - MIME::Base64 0 - Net::OpenID::Common 1.18 - Storable 0 - Test::More 0 - Time::Local 0 - URI 0 - Net-OpenID-Server-1.09 - pathname: R/RO/ROBN/Net-OpenID-Server-1.09.tar.gz - provides: - Net::OpenID::Server 1.09 - requirements: - Digest::SHA 0 - ExtUtils::MakeMaker 6.31 - MIME::Base64 0 - Net::OpenID::Common 1.11 - Test::More 0 - URI 0 - Net-SSLeay-1.63 - pathname: M/MI/MIKEM/Net-SSLeay-1.63.tar.gz + URI 5.15 + Net-SSLeay-1.94 + pathname: C/CH/CHRISN/Net-SSLeay-1.94.tar.gz provides: - Net::SSLeay 1.63 - Net::SSLeay::Handle 0.61 - requirements: - ExtUtils::MakeMaker 6.36 - MIME::Base64 0 - Test::More 0.60_01 - perl 5.005 - Net-Server-2.008 - pathname: R/RH/RHANDOM/Net-Server-2.008.tar.gz - provides: - Net::Server 2.008 - Net::Server::Daemonize 0.06 - Net::Server::Fork undef - Net::Server::HTTP undef - Net::Server::INET undef - Net::Server::INET::Handle undef - Net::Server::Log::Log::Log4perl undef - Net::Server::Log::Sys::Syslog undef - Net::Server::MultiType undef - Net::Server::Multiplex undef - Net::Server::Multiplex::MUX undef - Net::Server::PSGI undef - Net::Server::PreFork undef - Net::Server::PreForkSimple undef - Net::Server::Proto undef - Net::Server::Proto::SSL undef - Net::Server::Proto::SSLEAY undef - Net::Server::Proto::TCP undef - Net::Server::Proto::UDP undef - Net::Server::Proto::UNIX undef - Net::Server::Proto::UNIXDGRAM undef - Net::Server::SIG 0.03 - Net::Server::Single undef - Net::Server::TiedHandle 2.008 + Net::SSLeay 1.94 + Net::SSLeay::Handle 1.94 requirements: + English 0 ExtUtils::MakeMaker 0 - IO::Socket 0 - POSIX 0 - Socket 0 - Time::HiRes 0 - Net-Twitter-4.01004 - pathname: M/MM/MMIMS/Net-Twitter-4.01004.tar.gz - provides: - Net::Identica 4.01004 - Net::Twitter 4.01004 - Net::Twitter::API 4.01004 - Net::Twitter::Core 4.01004 - Net::Twitter::Error 4.01004 - Net::Twitter::Meta::Method 4.01004 - Net::Twitter::OAuth 4.01004 - Net::Twitter::Role::API::Lists 4.01004 - Net::Twitter::Role::API::REST 4.01004 - Net::Twitter::Role::API::RESTv1_1 4.01004 - Net::Twitter::Role::API::Search 4.01004 - Net::Twitter::Role::API::Search::Trends 4.01004 - Net::Twitter::Role::API::TwitterVision 4.01004 - Net::Twitter::Role::API::Upload 4.01004 - Net::Twitter::Role::AutoCursor 4.01004 - Net::Twitter::Role::InflateObjects 4.01004 - Net::Twitter::Role::Legacy 4.01004 - Net::Twitter::Role::OAuth 4.01004 - Net::Twitter::Role::RateLimit 4.01004 - Net::Twitter::Role::RetryOnError 4.01004 - Net::Twitter::Role::SimulateCursors 4.01004 - Net::Twitter::Role::WrapError 4.01004 - Net::Twitter::Search 4.01004 - requirements: - Carp::Clan 0 - Class::Load 0 - Data::Visitor::Callback 0 - DateTime 0 - DateTime::Format::Strptime 0 - Devel::StackTrace 0 - Digest::SHA 0 - Encode 0 - HTML::Entities 0 - HTTP::Request::Common 0 - JSON 0 - LWP::Protocol::https 0 - List::Util 0 - Module::Build 0.3601 - Moose 0 - Moose::Exporter 0 - Moose::Meta::Method 0 - Moose::Role 0 - MooseX::Role::Parameterized 0 - Net::HTTP >= 0, != 6.04, != 6.05 - Net::Netrc 0 - Net::OAuth 0 - Scalar::Util 0 - Time::HiRes 0 - Try::Tiny 0 - URI 0 - URI::Escape 0 - namespace::autoclean 0 - overload 0 + File::Spec::Functions 0 + MIME::Base64 0 + Text::Wrap 0 + constant 0 perl 5.008001 Number-Compare-0.03 pathname: R/RC/RCLAMP/Number-Compare-0.03.tar.gz @@ -5449,36 +5096,80 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 Test::More 0 - Object-Signature-1.07 - pathname: A/AD/ADAMK/Object-Signature-1.07.tar.gz + Object-Signature-1.08 + pathname: E/ET/ETHER/Object-Signature-1.08.tar.gz provides: - Object::Signature 1.07 - Object::Signature::File 1.07 + Object::Signature 1.08 + Object::Signature::File 1.08 requirements: Digest::MD5 2.00 - ExtUtils::MakeMaker 6.42 + ExtUtils::MakeMaker 0 Storable 2.11 - Test::More 0.47 - perl 5.005 - Ouch-0.0408 - pathname: R/RI/RIZEN/Ouch-0.0408.tar.gz - provides: - Ouch 0.0408 + base 0 + perl 5.006 + strict 0 + warnings 0 + OrePAN2-0.52 + pathname: O/OA/OALDERS/OrePAN2-0.52.tar.gz + provides: + OrePAN2 0.52 + OrePAN2::Auditor undef + OrePAN2::CLI::Indexer undef + OrePAN2::CLI::Inject undef + OrePAN2::Index undef + OrePAN2::Indexer undef + OrePAN2::Injector undef + OrePAN2::Repository undef + OrePAN2::Repository::Cache undef requirements: - Carp 0 - ExtUtils::MakeMaker 6.30 - Test::More 0 - Test::Trap 0 - overload 0 + Archive::Extract 0.72 + Archive::Tar 1.46 + CPAN::Meta 2.131560 + Digest::MD5 0 + ExtUtils::MakeMaker 7.06 + File::Path 0 + File::Spec 0 + File::Temp 0 + File::pushd 0 + File::stat 0 + Getopt::Long 2.39 + HTTP::Tiny 0 + IO::File::AtomicChange 0 + IO::Socket::SSL 1.42 + IO::Uncompress::Gunzip 0 + IO::Zlib 0 + JSON::PP 0 + LWP::UserAgent 0 + List::Compare 0 + MetaCPAN::Client 2.000000 + Module::Build::Tiny 0.035 + Moo 1.007000 + MooX::Options 0 + MooX::StrictConstructor 0 + Parse::CPAN::Meta 1.4414 + Parse::CPAN::Packages::Fast 0.09 + Parse::LocalDistribution 0.14 + Path::Tiny 0 + Pod::Usage 0 + Try::Tiny 0 + Type::Tiny 2.000000 + Types::Path::Tiny 0 + Types::Self 0 + Types::URI 0 + autodie 0 + feature 0 + namespace::clean 0 parent 0 - PAUSE-Permissions-0.11 - pathname: N/NE/NEILB/PAUSE-Permissions-0.11.tar.gz + perl 5.012000 + version 0.9912 + PAUSE-Permissions-0.17 + pathname: N/NE/NEILB/PAUSE-Permissions-0.17.tar.gz provides: - PAUSE::Permissions 0.11 - PAUSE::Permissions::Entry 0.11 - PAUSE::Permissions::EntryIterator 0.11 - PAUSE::Permissions::Module 0.11 - PAUSE::Permissions::ModuleIterator 0.11 + PAUSE::Permissions 0.17 + PAUSE::Permissions::Entry 0.17 + PAUSE::Permissions::EntryIterator 0.17 + PAUSE::Permissions::Module 0.17 + PAUSE::Permissions::ModuleIterator 0.17 requirements: Carp 0 ExtUtils::MakeMaker 0 @@ -5486,424 +5177,433 @@ DISTRIBUTIONS File::Spec::Functions 0 HTTP::Date 0 HTTP::Tiny 0 + List::Util 1.33 Moo 0 + MooX::Options 0 + Time::Duration::Parse 0 autodie 0 feature 0 perl 5.010000 strict 0 warnings 0 - POSIX-strftime-Compiler-0.31 - pathname: K/KA/KAZEBURO/POSIX-strftime-Compiler-0.31.tar.gz + POSIX-strftime-Compiler-0.46 + pathname: K/KA/KAZEBURO/POSIX-strftime-Compiler-0.46.tar.gz provides: - POSIX::strftime::Compiler 0.31 + POSIX::strftime::Compiler 0.46 requirements: - CPAN::Meta 0 - CPAN::Meta::Prereqs 0 Carp 0 Exporter 0 - ExtUtils::CBuilder 0 - Module::Build 0.38 + Module::Build::Tiny 0.035 POSIX 0 Time::Local 0 - perl 5.008004 - PPI-1.215 - pathname: A/AD/ADAMK/PPI-1.215.tar.gz - provides: - PPI 1.215 - PPI::Cache 1.215 - PPI::Document 1.215 - PPI::Document::File 1.215 - PPI::Document::Fragment 1.215 - PPI::Document::Normalized 1.215 - PPI::Dumper 1.215 - PPI::Element 1.215 - PPI::Exception 1.215 - PPI::Exception::ParserRejection 1.215 - PPI::Exception::ParserTimeout 1.215 - PPI::Find 1.215 - PPI::Lexer 1.215 - PPI::Node 1.215 - PPI::Normal 1.215 - PPI::Normal::Standard 1.215 - PPI::Statement 1.215 - PPI::Statement::Break 1.215 - PPI::Statement::Compound 1.215 - PPI::Statement::Data 1.215 - PPI::Statement::End 1.215 - PPI::Statement::Expression 1.215 - PPI::Statement::Given 1.215 - PPI::Statement::Include 1.215 - PPI::Statement::Include::Perl6 1.215 - PPI::Statement::Null 1.215 - PPI::Statement::Package 1.215 - PPI::Statement::Scheduled 1.215 - PPI::Statement::Sub 1.215 - PPI::Statement::Unknown 1.215 - PPI::Statement::UnmatchedBrace 1.215 - PPI::Statement::Variable 1.215 - PPI::Statement::When 1.215 - PPI::Structure 1.215 - PPI::Structure::Block 1.215 - PPI::Structure::Condition 1.215 - PPI::Structure::Constructor 1.215 - PPI::Structure::For 1.215 - PPI::Structure::Given 1.215 - PPI::Structure::List 1.215 - PPI::Structure::Subscript 1.215 - PPI::Structure::Unknown 1.215 - PPI::Structure::When 1.215 - PPI::Token 1.215 - PPI::Token::ArrayIndex 1.215 - PPI::Token::Attribute 1.215 - PPI::Token::BOM 1.215 - PPI::Token::Cast 1.215 - PPI::Token::Comment 1.215 - PPI::Token::DashedWord 1.215 - PPI::Token::Data 1.215 - PPI::Token::End 1.215 - PPI::Token::HereDoc 1.215 - PPI::Token::Label 1.215 - PPI::Token::Magic 1.215 - PPI::Token::Number 1.215 - PPI::Token::Number::Binary 1.215 - PPI::Token::Number::Exp 1.215 - PPI::Token::Number::Float 1.215 - PPI::Token::Number::Hex 1.215 - PPI::Token::Number::Octal 1.215 - PPI::Token::Number::Version 1.215 - PPI::Token::Operator 1.215 - PPI::Token::Pod 1.215 - PPI::Token::Prototype 1.215 - PPI::Token::Quote 1.215 - PPI::Token::Quote::Double 1.215 - PPI::Token::Quote::Interpolate 1.215 - PPI::Token::Quote::Literal 1.215 - PPI::Token::Quote::Single 1.215 - PPI::Token::QuoteLike 1.215 - PPI::Token::QuoteLike::Backtick 1.215 - PPI::Token::QuoteLike::Command 1.215 - PPI::Token::QuoteLike::Readline 1.215 - PPI::Token::QuoteLike::Regexp 1.215 - PPI::Token::QuoteLike::Words 1.215 - PPI::Token::Regexp 1.215 - PPI::Token::Regexp::Match 1.215 - PPI::Token::Regexp::Substitute 1.215 - PPI::Token::Regexp::Transliterate 1.215 - PPI::Token::Separator 1.215 - PPI::Token::Structure 1.215 - PPI::Token::Symbol 1.215 - PPI::Token::Unknown 1.215 - PPI::Token::Whitespace 1.215 - PPI::Token::Word 1.215 - PPI::Token::_QuoteEngine 1.215 - PPI::Token::_QuoteEngine::Full 1.215 - PPI::Token::_QuoteEngine::Simple 1.215 - PPI::Tokenizer 1.215 - PPI::Transform 1.215 - PPI::Transform::UpdateCopyright 1.215 - PPI::Util 1.215 - PPI::XSAccessor 1.215 - requirements: - Class::Inspector 1.22 + perl 5.008001 + PPI-1.281 + pathname: M/MI/MITHALDU/PPI-1.281.tar.gz + provides: + PPI 1.281 + PPI::Cache 1.281 + PPI::Document 1.281 + PPI::Document::File 1.281 + PPI::Document::Fragment 1.281 + PPI::Document::Normalized 1.281 + PPI::Dumper 1.281 + PPI::Element 1.281 + PPI::Exception 1.281 + PPI::Exception::ParserRejection 1.281 + PPI::Find 1.281 + PPI::Lexer 1.281 + PPI::Node 1.281 + PPI::Normal 1.281 + PPI::Normal::Standard 1.281 + PPI::Singletons 1.281 + PPI::Statement 1.281 + PPI::Statement::Break 1.281 + PPI::Statement::Compound 1.281 + PPI::Statement::Data 1.281 + PPI::Statement::End 1.281 + PPI::Statement::Expression 1.281 + PPI::Statement::Given 1.281 + PPI::Statement::Include 1.281 + PPI::Statement::Include::Perl6 1.281 + PPI::Statement::Null 1.281 + PPI::Statement::Package 1.281 + PPI::Statement::Scheduled 1.281 + PPI::Statement::Sub 1.281 + PPI::Statement::Unknown 1.281 + PPI::Statement::UnmatchedBrace 1.281 + PPI::Statement::Variable 1.281 + PPI::Statement::When 1.281 + PPI::Structure 1.281 + PPI::Structure::Block 1.281 + PPI::Structure::Condition 1.281 + PPI::Structure::Constructor 1.281 + PPI::Structure::For 1.281 + PPI::Structure::Given 1.281 + PPI::Structure::List 1.281 + PPI::Structure::Signature 1.281 + PPI::Structure::Subscript 1.281 + PPI::Structure::Unknown 1.281 + PPI::Structure::When 1.281 + PPI::Token 1.281 + PPI::Token::ArrayIndex 1.281 + PPI::Token::Attribute 1.281 + PPI::Token::BOM 1.281 + PPI::Token::Cast 1.281 + PPI::Token::Comment 1.281 + PPI::Token::DashedWord 1.281 + PPI::Token::Data 1.281 + PPI::Token::End 1.281 + PPI::Token::HereDoc 1.281 + PPI::Token::Label 1.281 + PPI::Token::Magic 1.281 + PPI::Token::Number 1.281 + PPI::Token::Number::Binary 1.281 + PPI::Token::Number::Exp 1.281 + PPI::Token::Number::Float 1.281 + PPI::Token::Number::Hex 1.281 + PPI::Token::Number::Octal 1.281 + PPI::Token::Number::Version 1.281 + PPI::Token::Operator 1.281 + PPI::Token::Pod 1.281 + PPI::Token::Prototype 1.281 + PPI::Token::Quote 1.281 + PPI::Token::Quote::Double 1.281 + PPI::Token::Quote::Interpolate 1.281 + PPI::Token::Quote::Literal 1.281 + PPI::Token::Quote::Single 1.281 + PPI::Token::QuoteLike 1.281 + PPI::Token::QuoteLike::Backtick 1.281 + PPI::Token::QuoteLike::Command 1.281 + PPI::Token::QuoteLike::Readline 1.281 + PPI::Token::QuoteLike::Regexp 1.281 + PPI::Token::QuoteLike::Words 1.281 + PPI::Token::Regexp 1.281 + PPI::Token::Regexp::Match 1.281 + PPI::Token::Regexp::Substitute 1.281 + PPI::Token::Regexp::Transliterate 1.281 + PPI::Token::Separator 1.281 + PPI::Token::Structure 1.281 + PPI::Token::Symbol 1.281 + PPI::Token::Unknown 1.281 + PPI::Token::Whitespace 1.281 + PPI::Token::Word 1.281 + PPI::Tokenizer 1.281 + PPI::Transform 1.281 + PPI::Transform::UpdateCopyright 1.281 + PPI::Util 1.281 + PPI::XSAccessor 1.281 + requirements: + Carp 0 Clone 0.30 Digest::MD5 2.35 - ExtUtils::MakeMaker 6.42 - File::Remove 1.42 + Exporter 0 + ExtUtils::MakeMaker 0 + File::Path 0 File::Spec 0.84 - IO::String 1.07 - List::MoreUtils 0.16 - List::Util 1.20 + List::Util 1.33 Params::Util 1.00 + Safe::Isa 0 + Scalar::Util 0 Storable 2.17 Task::Weaken 0 - Test::More 0.86 - Test::NoWarnings 0.084 - Test::Object 0.07 - Test::SubCalls 1.07 + YAML::PP 0 + constant 0 + if 0 + overload 0 perl 5.006 - PPIx-Regexp-0.036 - pathname: W/WY/WYANT/PPIx-Regexp-0.036.tar.gz - provides: - PPIx::Regexp 0.036 - PPIx::Regexp::Constant 0.036 - PPIx::Regexp::Dumper 0.036 - PPIx::Regexp::Element 0.036 - PPIx::Regexp::Lexer 0.036 - PPIx::Regexp::Node 0.036 - PPIx::Regexp::Node::Range 0.036 - PPIx::Regexp::Structure 0.036 - PPIx::Regexp::Structure::Assertion 0.036 - PPIx::Regexp::Structure::BranchReset 0.036 - PPIx::Regexp::Structure::Capture 0.036 - PPIx::Regexp::Structure::CharClass 0.036 - PPIx::Regexp::Structure::Code 0.036 - PPIx::Regexp::Structure::Main 0.036 - PPIx::Regexp::Structure::Modifier 0.036 - PPIx::Regexp::Structure::NamedCapture 0.036 - PPIx::Regexp::Structure::Quantifier 0.036 - PPIx::Regexp::Structure::RegexSet 0.036 - PPIx::Regexp::Structure::Regexp 0.036 - PPIx::Regexp::Structure::Replacement 0.036 - PPIx::Regexp::Structure::Subexpression 0.036 - PPIx::Regexp::Structure::Switch 0.036 - PPIx::Regexp::Structure::Unknown 0.036 - PPIx::Regexp::Support 0.036 - PPIx::Regexp::Token 0.036 - PPIx::Regexp::Token::Assertion 0.036 - PPIx::Regexp::Token::Backreference 0.036 - PPIx::Regexp::Token::Backtrack 0.036 - PPIx::Regexp::Token::CharClass 0.036 - PPIx::Regexp::Token::CharClass::POSIX 0.036 - PPIx::Regexp::Token::CharClass::POSIX::Unknown 0.036 - PPIx::Regexp::Token::CharClass::Simple 0.036 - PPIx::Regexp::Token::Code 0.036 - PPIx::Regexp::Token::Comment 0.036 - PPIx::Regexp::Token::Condition 0.036 - PPIx::Regexp::Token::Control 0.036 - PPIx::Regexp::Token::Delimiter 0.036 - PPIx::Regexp::Token::Greediness 0.036 - PPIx::Regexp::Token::GroupType 0.036 - PPIx::Regexp::Token::GroupType::Assertion 0.036 - PPIx::Regexp::Token::GroupType::BranchReset 0.036 - PPIx::Regexp::Token::GroupType::Code 0.036 - PPIx::Regexp::Token::GroupType::Modifier 0.036 - PPIx::Regexp::Token::GroupType::NamedCapture 0.036 - PPIx::Regexp::Token::GroupType::Subexpression 0.036 - PPIx::Regexp::Token::GroupType::Switch 0.036 - PPIx::Regexp::Token::Interpolation 0.036 - PPIx::Regexp::Token::Literal 0.036 - PPIx::Regexp::Token::Modifier 0.036 - PPIx::Regexp::Token::Operator 0.036 - PPIx::Regexp::Token::Quantifier 0.036 - PPIx::Regexp::Token::Recursion 0.036 - PPIx::Regexp::Token::Reference 0.036 - PPIx::Regexp::Token::Structure 0.036 - PPIx::Regexp::Token::Unknown 0.036 - PPIx::Regexp::Token::Unmatched 0.036 - PPIx::Regexp::Token::Whitespace 0.036 - PPIx::Regexp::Tokenizer 0.036 - PPIx::Regexp::Util 0.036 + strict 0 + version 0.77 + PPIx-QuoteLike-0.023 + pathname: W/WY/WYANT/PPIx-QuoteLike-0.023.tar.gz + provides: + PPIx::QuoteLike 0.023 + PPIx::QuoteLike::Constant 0.023 + PPIx::QuoteLike::Dumper 0.023 + PPIx::QuoteLike::Token 0.023 + PPIx::QuoteLike::Token::Control 0.023 + PPIx::QuoteLike::Token::Delimiter 0.023 + PPIx::QuoteLike::Token::Interpolation 0.023 + PPIx::QuoteLike::Token::String 0.023 + PPIx::QuoteLike::Token::Structure 0.023 + PPIx::QuoteLike::Token::Unknown 0.023 + PPIx::QuoteLike::Token::Whitespace 0.023 + PPIx::QuoteLike::Utils 0.023 requirements: - List::MoreUtils 0 + Carp 0 + Encode 0 + Exporter 0 List::Util 0 - PPI::Document 1.117 + PPI::Document 1.238 + PPI::Dumper 1.238 + Readonly 0 Scalar::Util 0 - Task::Weaken 0 Test::More 0.88 + base 0 + charnames 0 + constant 0 + lib 0 perl 5.006 - PPIx-Utilities-1.001000 - pathname: E/EL/ELLIOTJS/PPIx-Utilities-1.001000.tar.gz - provides: - PPIx::Utilities 1.001000 - PPIx::Utilities::Exception::Bug 1.001000 - PPIx::Utilities::Node 1.001000 - PPIx::Utilities::Statement 1.001000 + re 0 + strict 0 + warnings 0 + PPIx-Regexp-0.088 + pathname: W/WY/WYANT/PPIx-Regexp-0.088.tar.gz + provides: + PPIx::Regexp 0.088 + PPIx::Regexp::Constant 0.085_04 + PPIx::Regexp::Constant::Inf 0.088 + PPIx::Regexp::Dumper 0.088 + PPIx::Regexp::Element 0.088 + PPIx::Regexp::Lexer 0.088 + PPIx::Regexp::Node 0.088 + PPIx::Regexp::Node::Range 0.088 + PPIx::Regexp::Node::Unknown 0.088 + PPIx::Regexp::Structure 0.088 + PPIx::Regexp::Structure::Assertion 0.088 + PPIx::Regexp::Structure::Atomic_Script_Run 0.088 + PPIx::Regexp::Structure::BranchReset 0.088 + PPIx::Regexp::Structure::Capture 0.088 + PPIx::Regexp::Structure::CharClass 0.088 + PPIx::Regexp::Structure::Code 0.088 + PPIx::Regexp::Structure::Main 0.088 + PPIx::Regexp::Structure::Modifier 0.088 + PPIx::Regexp::Structure::NamedCapture 0.088 + PPIx::Regexp::Structure::Quantifier 0.088 + PPIx::Regexp::Structure::RegexSet 0.088 + PPIx::Regexp::Structure::Regexp 0.088 + PPIx::Regexp::Structure::Replacement 0.088 + PPIx::Regexp::Structure::Script_Run 0.088 + PPIx::Regexp::Structure::Subexpression 0.088 + PPIx::Regexp::Structure::Switch 0.088 + PPIx::Regexp::Structure::Unknown 0.088 + PPIx::Regexp::Support 0.088 + PPIx::Regexp::Token 0.088 + PPIx::Regexp::Token::Assertion 0.088 + PPIx::Regexp::Token::Backreference 0.088 + PPIx::Regexp::Token::Backtrack 0.088 + PPIx::Regexp::Token::CharClass 0.088 + PPIx::Regexp::Token::CharClass::POSIX 0.088 + PPIx::Regexp::Token::CharClass::POSIX::Unknown 0.088 + PPIx::Regexp::Token::CharClass::Simple 0.088 + PPIx::Regexp::Token::Code 0.088 + PPIx::Regexp::Token::Comment 0.088 + PPIx::Regexp::Token::Condition 0.088 + PPIx::Regexp::Token::Control 0.088 + PPIx::Regexp::Token::Delimiter 0.088 + PPIx::Regexp::Token::Greediness 0.088 + PPIx::Regexp::Token::GroupType 0.088 + PPIx::Regexp::Token::GroupType::Assertion 0.088 + PPIx::Regexp::Token::GroupType::Atomic_Script_Run 0.088 + PPIx::Regexp::Token::GroupType::BranchReset 0.088 + PPIx::Regexp::Token::GroupType::Code 0.088 + PPIx::Regexp::Token::GroupType::Modifier 0.088 + PPIx::Regexp::Token::GroupType::NamedCapture 0.088 + PPIx::Regexp::Token::GroupType::Script_Run 0.088 + PPIx::Regexp::Token::GroupType::Subexpression 0.088 + PPIx::Regexp::Token::GroupType::Switch 0.088 + PPIx::Regexp::Token::Interpolation 0.088 + PPIx::Regexp::Token::Literal 0.088 + PPIx::Regexp::Token::Modifier 0.088 + PPIx::Regexp::Token::NoOp 0.088 + PPIx::Regexp::Token::Operator 0.088 + PPIx::Regexp::Token::Quantifier 0.088 + PPIx::Regexp::Token::Recursion 0.088 + PPIx::Regexp::Token::Reference 0.088 + PPIx::Regexp::Token::Structure 0.088 + PPIx::Regexp::Token::Unknown 0.088 + PPIx::Regexp::Token::Unmatched 0.088 + PPIx::Regexp::Token::Whitespace 0.088 + PPIx::Regexp::Tokenizer 0.088 + PPIx::Regexp::Util 0.088 requirements: - Data::Dumper 0 - Exception::Class 0 + Carp 0 + Encode 0 Exporter 0 - PPI 1.208 - PPI::Document 1.208 - PPI::Document::Fragment 1.208 - PPI::Dumper 1.208 - Readonly 0 + List::Util 0 + PPI::Document 1.238 + PPI::Dumper 1.238 Scalar::Util 0 Task::Weaken 0 - Test::Deep 0 - Test::More 0 + Test::More 0.88 base 0 + charnames 0 + constant 0 + lib 0 + overload 0 + perl 5.006 strict 0 warnings 0 - Package-DeprecationManager-0.13 - pathname: D/DR/DROLSKY/Package-DeprecationManager-0.13.tar.gz + PPIx-Utils-0.003 + pathname: D/DB/DBOOK/PPIx-Utils-0.003.tar.gz provides: - Package::DeprecationManager 0.13 + PPIx::Utils 0.003 + PPIx::Utils::Classification 0.003 + PPIx::Utils::Language 0.003 + PPIx::Utils::Traversal 0.003 + requirements: + B::Keywords 1.09 + Exporter 0 + ExtUtils::MakeMaker 0 + PPI 1.250 + Scalar::Util 0 + perl 5.006 + Package-DeprecationManager-0.18 + pathname: D/DR/DROLSKY/Package-DeprecationManager-0.18.tar.gz + provides: + Package::DeprecationManager 0.18 requirements: Carp 0 - ExtUtils::MakeMaker 6.30 - List::MoreUtils 0 + ExtUtils::MakeMaker 0 + List::Util 1.33 + Package::Stash 0 Params::Util 0 Sub::Install 0 - Test::Fatal 0 - Test::More 0.88 - Test::Requires 0 + Sub::Util 0 strict 0 warnings 0 - Package-Pkg-0.0020 - pathname: R/RO/ROKR/Package-Pkg-0.0020.tar.gz + Package-Stash-0.40 + pathname: E/ET/ETHER/Package-Stash-0.40.tar.gz provides: - Package::Pkg 0.0020 - Package::Pkg::Lexicon undef - Package::Pkg::Loader undef - requirements: - Class::Load 0 - Clone 0 - ExtUtils::MakeMaker 6.30 - Mouse 0 - Sub::Install 0 - Test::Most 0 - Try::Tiny 0 - Package-Stash-0.36 - pathname: D/DO/DOY/Package-Stash-0.36.tar.gz - provides: - Package::Stash 0.36 - Package::Stash::PP 0.36 + Package::Stash 0.40 + Package::Stash::PP 0.40 requirements: B 0 Carp 0 - Config 0 Dist::CheckConflicts 0.02 - ExtUtils::MakeMaker 6.30 - File::Find 0 - File::Spec 0 - File::Temp 0 + ExtUtils::MakeMaker 0 Getopt::Long 0 Module::Implementation 0.06 Package::Stash::XS 0.26 Scalar::Util 0 Symbol 0 - Test::Fatal 0 - Test::More 0.88 - Test::Requires 0 Text::ParseWords 0 - base 0 constant 0 - lib 0 + perl 5.008001 strict 0 warnings 0 - Package-Stash-XS-0.28 - pathname: D/DO/DOY/Package-Stash-XS-0.28.tar.gz + Package-Stash-XS-0.30 + pathname: E/ET/ETHER/Package-Stash-XS-0.30.tar.gz provides: - CompileTime undef - Package::Stash::XS 0.28 + Package::Stash::XS 0.30 requirements: - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 XSLoader 0 + perl 5.008001 strict 0 warnings 0 - PadWalker-1.98 - pathname: R/RO/ROBIN/PadWalker-1.98.tar.gz + Parallel-ForkManager-2.03 + pathname: Y/YA/YANICK/Parallel-ForkManager-2.03.tar.gz provides: - PadWalker 1.98 + Parallel::ForkManager 2.03 + Parallel::ForkManager::Child 2.03 requirements: + Carp 0 ExtUtils::MakeMaker 0 - perl 5.008001 - Parallel-Scoreboard-0.05 - pathname: K/KA/KAZUHO/Parallel-Scoreboard-0.05.tar.gz - provides: - Parallel::Scoreboard 0.05 - Parallel::Scoreboard::PSGI::App undef - Parallel::Scoreboard::PSGI::App::JSON undef - requirements: - Class::Accessor::Lite 0.05 - ExtUtils::MakeMaker 6.42 + File::Path 0 + File::Spec 0 File::Temp 0 - Filter::Util::Call 0 - HTML::Entities 0 - JSON 0 - Test::More 0 - Params-Util-1.07 - pathname: A/AD/ADAMK/Params-Util-1.07.tar.gz + Moo 1.001000 + Moo::Role 0 + POSIX 0 + Storable 0 + perl 5.006 + strict 0 + warnings 0 + Params-Util-1.102 + pathname: R/RE/REHSACK/Params-Util-1.102.tar.gz provides: - Params::Util 1.07 + Params::Util 1.102 + Params::Util::PP 1.102 requirements: - ExtUtils::CBuilder 0.27 - ExtUtils::MakeMaker 6.52 - File::Spec 0.80 + Carp 0 + ExtUtils::MakeMaker 0 + File::Basename 0 + File::Copy 0 + File::Path 0 + File::Spec 0 + IPC::Cmd 0 Scalar::Util 1.18 - Test::More 0.42 - perl 5.00503 - Params-Validate-1.10 - pathname: D/DR/DROLSKY/Params-Validate-1.10.tar.gz - provides: - Attribute::Params::Validate 1.10 - Bar undef - Baz undef - Foo undef - PVTests undef - PVTests::Callbacks undef - PVTests::Defaults undef - PVTests::Regex undef - PVTests::Standard undef - PVTests::With undef - Params::Validate 1.10 - Params::Validate::Constants 1.10 - Params::Validate::PP 1.10 - Params::Validate::XS 1.10 - Quux undef - Testing::X undef - Yadda undef - inc::MyModuleBuild undef - requirements: - Attribute::Handlers 0.79 + XSLoader 0.22 + parent 0 + Params-Validate-1.31 + pathname: D/DR/DROLSKY/Params-Validate-1.31.tar.gz + provides: + Params::Validate 1.31 + Params::Validate::Constants 1.31 + Params::Validate::PP 1.31 + Params::Validate::XS 1.31 + requirements: Carp 0 Exporter 0 ExtUtils::CBuilder 0 - Module::Build 0.3601 + Module::Build 0.4227 Module::Implementation 0 Scalar::Util 1.10 XSLoader 0 - attributes 0 perl 5.008001 strict 0 vars 0 warnings 0 - Parse-CPAN-Meta-1.4414 - pathname: D/DA/DAGOLDEN/Parse-CPAN-Meta-1.4414.tar.gz + Params-ValidationCompiler-0.31 + pathname: D/DR/DROLSKY/Params-ValidationCompiler-0.31.tar.gz provides: - Parse::CPAN::Meta 1.4414 + Params::ValidationCompiler 0.31 + Params::ValidationCompiler::Compiler 0.31 + Params::ValidationCompiler::Exceptions 0.31 requirements: - CPAN::Meta::YAML 0.011 + B 0 Carp 0 - Encode 0 + Eval::Closure 0 + Exception::Class 0 Exporter 0 - ExtUtils::MakeMaker 6.30 - File::Spec 0.80 - JSON::PP 2.27200 + ExtUtils::MakeMaker 0 + List::Util 1.29 + Scalar::Util 0 + overload 0 strict 0 - Parse-CPAN-Packages-Fast-0.07 - pathname: S/SR/SREZIC/Parse-CPAN-Packages-Fast-0.07.tar.gz + warnings 0 + Parse-CPAN-Packages-Fast-0.09 + pathname: S/SR/SREZIC/Parse-CPAN-Packages-Fast-0.09.tar.gz provides: - Parse::CPAN::Packages::Fast 0.07 - Parse::CPAN::Packages::Fast::Distribution 0.07 - Parse::CPAN::Packages::Fast::Package 0.07 + Parse::CPAN::Packages::Fast 0.09 + Parse::CPAN::Packages::Fast::Distribution 0.09 + Parse::CPAN::Packages::Fast::Package 0.09 requirements: CPAN::DistnameInfo 0 CPAN::Version 0 ExtUtils::MakeMaker 0 IO::Uncompress::Gunzip 0 - Parse-CSV-2.00 - pathname: A/AD/ADAMK/Parse-CSV-2.00.tar.gz + Parse-LocalDistribution-0.20 + pathname: I/IS/ISHIGAKI/Parse-LocalDistribution-0.20.tar.gz provides: - Parse::CSV 2.00 + Parse::LocalDistribution 0.20 requirements: - ExtUtils::MakeMaker 6.36 - File::Spec 0.80 - IO::File 1.13 - Params::Util 0.22 - Test::More 0.47 - Text::CSV_XS 0.42 - perl 5.005 - Parse-PMFile-0.29 - pathname: I/IS/ISHIGAKI/Parse-PMFile-0.29.tar.gz + ExtUtils::MakeMaker 0 + ExtUtils::MakeMaker::CPANfile 0.09 + File::Find 0 + File::Spec 0 + List::Util 0 + Parse::CPAN::Meta 0 + Parse::PMFile 0.37 + Parse-PMFile-0.47 + pathname: I/IS/ISHIGAKI/Parse-PMFile-0.47.tar.gz provides: - Parse::PMFile 0.29 + Parse::PMFile 0.47 requirements: Dumpvalue 0 - ExtUtils::MakeMaker::CPANfile 0.06 + ExtUtils::MakeMaker 0 + ExtUtils::MakeMaker::CPANfile 0.09 File::Spec 0 - File::Temp 0.19 JSON::PP 2.00 Safe 0 - Test::More 0.88 version 0.83 - Path-Class-0.33 - pathname: K/KW/KWILLIAMS/Path-Class-0.33.tar.gz + Path-Class-0.37 + pathname: K/KW/KWILLIAMS/Path-Class-0.37.tar.gz provides: - Path::Class 0.33 - Path::Class::Dir 0.33 - Path::Class::Entity 0.33 - Path::Class::File 0.33 + Path::Class 0.37 + Path::Class::Dir 0.37 + Path::Class::Entity 0.37 + Path::Class::File 0.37 requirements: Carp 0 Cwd 0 @@ -5922,290 +5622,254 @@ DISTRIBUTIONS overload 0 parent 0 strict 0 - Path-FindDev-0.5.0 - pathname: K/KE/KENTNL/Path-FindDev-0.5.0.tar.gz + Path-Iterator-Rule-1.015 + pathname: D/DA/DAGOLDEN/Path-Iterator-Rule-1.015.tar.gz provides: - Path::FindDev 0.005000 - Path::FindDev::Object 0.005000 - requirements: - Carp 0 - Class::Tiny 0.010 - ExtUtils::MakeMaker 6.30 - Path::IsDev 0 - Path::IsDev::Object 0 - Path::Tiny 0.038 - Scalar::Util 0 - Sub::Exporter 0 - strict 0 - utf8 0 - warnings 0 - Path-IsDev-1.001000 - pathname: K/KE/KENTNL/Path-IsDev-1.001000.tar.gz - provides: - Path::IsDev 1.001000 - Path::IsDev::Heuristic::Changelog 1.001000 - Path::IsDev::Heuristic::DevDirMarker 1.001000 - Path::IsDev::Heuristic::META 1.001000 - Path::IsDev::Heuristic::MYMETA 1.001000 - Path::IsDev::Heuristic::Makefile 1.001000 - Path::IsDev::Heuristic::TestDir 1.001000 - Path::IsDev::Heuristic::Tool::Dzil 1.001000 - Path::IsDev::Heuristic::Tool::MakeMaker 1.001000 - Path::IsDev::Heuristic::Tool::ModuleBuild 1.001000 - Path::IsDev::Heuristic::VCS::Git 1.001000 - Path::IsDev::HeuristicSet::Basic 1.001000 - Path::IsDev::NegativeHeuristic::HomeDir 1.001000 - Path::IsDev::NegativeHeuristic::IsDev::IgnoreFile 1.001000 - Path::IsDev::NegativeHeuristic::PerlINC 1.001000 - Path::IsDev::Object 1.001000 - Path::IsDev::Result 1.001000 - Path::IsDev::Role::Heuristic 1.001000 - Path::IsDev::Role::HeuristicSet 1.001000 - Path::IsDev::Role::HeuristicSet::Simple 1.001000 - Path::IsDev::Role::Matcher::Child::BaseName::MatchRegexp 1.001000 - Path::IsDev::Role::Matcher::Child::BaseName::MatchRegexp::File 1.001000 - Path::IsDev::Role::Matcher::Child::Exists::Any 1.001000 - Path::IsDev::Role::Matcher::Child::Exists::Any::Dir 1.001000 - Path::IsDev::Role::Matcher::Child::Exists::Any::File 1.001000 - Path::IsDev::Role::Matcher::FullPath::Is::Any 1.001000 - Path::IsDev::Role::NegativeHeuristic 1.001000 + PIR 1.015 + Path::Iterator::Rule 1.015 requirements: Carp 0 - Class::Tiny 0.010 - ExtUtils::MakeMaker 6.30 - File::HomeDir 0 - Module::Runtime 0 - Path::Tiny 0.004 - Role::Tiny 0 - Role::Tiny::With 0 + ExtUtils::MakeMaker 6.17 + File::Basename 0 + File::Spec 0 + List::Util 0 + Number::Compare 0.02 Scalar::Util 0 - Sub::Exporter 0 + Text::Glob 0 + Try::Tiny 0 + if 0 + perl 5.008001 strict 0 - utf8 0 warnings 0 - Path-Tiny-0.054 - pathname: D/DA/DAGOLDEN/Path-Tiny-0.054.tar.gz + warnings::register 0 + Path-Tiny-0.148 + pathname: D/DA/DAGOLDEN/Path-Tiny-0.148.tar.gz provides: - Path::Tiny 0.054 - flock undef + Path::Tiny 0.148 + Path::Tiny::Error 0.148 requirements: Carp 0 Cwd 0 Digest 1.03 Digest::SHA 5.45 + Encode 0 Exporter 5.57 ExtUtils::MakeMaker 6.17 Fcntl 0 + File::Compare 0 File::Copy 0 + File::Glob 0 File::Path 2.07 - File::Spec 3.40 + File::Spec 0.86 File::Temp 0.19 File::stat 0 constant 0 - if 0 overload 0 + perl 5.008001 strict 0 warnings 0 - Perl-Critic-1.121 - pathname: T/TH/THALJEF/Perl-Critic-1.121.tar.gz - provides: - Perl::Critic 1.121 - Perl::Critic::Annotation 1.121 - Perl::Critic::Command 1.121 - Perl::Critic::Config 1.121 - Perl::Critic::Document 1.121 - Perl::Critic::Exception 1.121 - Perl::Critic::Exception::AggregateConfiguration 1.121 - Perl::Critic::Exception::Configuration 1.121 - Perl::Critic::Exception::Configuration::Generic 1.121 - Perl::Critic::Exception::Configuration::NonExistentPolicy 1.121 - Perl::Critic::Exception::Configuration::Option 1.121 - Perl::Critic::Exception::Configuration::Option::Global 1.121 - Perl::Critic::Exception::Configuration::Option::Global::ExtraParameter 1.121 - Perl::Critic::Exception::Configuration::Option::Global::ParameterValue 1.121 - Perl::Critic::Exception::Configuration::Option::Policy 1.121 - Perl::Critic::Exception::Configuration::Option::Policy::ExtraParameter 1.121 - Perl::Critic::Exception::Configuration::Option::Policy::ParameterValue 1.121 - Perl::Critic::Exception::Fatal 1.121 - Perl::Critic::Exception::Fatal::Generic 1.121 - Perl::Critic::Exception::Fatal::Internal 1.121 - Perl::Critic::Exception::Fatal::PolicyDefinition 1.121 - Perl::Critic::Exception::IO 1.121 - Perl::Critic::Exception::Parse 1.121 - Perl::Critic::OptionsProcessor 1.121 - Perl::Critic::Policy 1.121 - Perl::Critic::Policy::BuiltinFunctions::ProhibitBooleanGrep 1.121 - Perl::Critic::Policy::BuiltinFunctions::ProhibitComplexMappings 1.121 - Perl::Critic::Policy::BuiltinFunctions::ProhibitLvalueSubstr 1.121 - Perl::Critic::Policy::BuiltinFunctions::ProhibitReverseSortBlock 1.121 - Perl::Critic::Policy::BuiltinFunctions::ProhibitSleepViaSelect 1.121 - Perl::Critic::Policy::BuiltinFunctions::ProhibitStringyEval 1.121 - Perl::Critic::Policy::BuiltinFunctions::ProhibitStringySplit 1.121 - Perl::Critic::Policy::BuiltinFunctions::ProhibitUniversalCan 1.121 - Perl::Critic::Policy::BuiltinFunctions::ProhibitUniversalIsa 1.121 - Perl::Critic::Policy::BuiltinFunctions::ProhibitVoidGrep 1.121 - Perl::Critic::Policy::BuiltinFunctions::ProhibitVoidMap 1.121 - Perl::Critic::Policy::BuiltinFunctions::RequireBlockGrep 1.121 - Perl::Critic::Policy::BuiltinFunctions::RequireBlockMap 1.121 - Perl::Critic::Policy::BuiltinFunctions::RequireGlobFunction 1.121 - Perl::Critic::Policy::BuiltinFunctions::RequireSimpleSortBlock 1.121 - Perl::Critic::Policy::ClassHierarchies::ProhibitAutoloading 1.121 - Perl::Critic::Policy::ClassHierarchies::ProhibitExplicitISA 1.121 - Perl::Critic::Policy::ClassHierarchies::ProhibitOneArgBless 1.121 - Perl::Critic::Policy::CodeLayout::ProhibitHardTabs 1.121 - Perl::Critic::Policy::CodeLayout::ProhibitParensWithBuiltins 1.121 - Perl::Critic::Policy::CodeLayout::ProhibitQuotedWordLists 1.121 - Perl::Critic::Policy::CodeLayout::ProhibitTrailingWhitespace 1.121 - Perl::Critic::Policy::CodeLayout::RequireConsistentNewlines 1.121 - Perl::Critic::Policy::CodeLayout::RequireTidyCode 1.121 - Perl::Critic::Policy::CodeLayout::RequireTrailingCommas 1.121 - Perl::Critic::Policy::ControlStructures::ProhibitCStyleForLoops 1.121 - Perl::Critic::Policy::ControlStructures::ProhibitCascadingIfElse 1.121 - Perl::Critic::Policy::ControlStructures::ProhibitDeepNests 1.121 - Perl::Critic::Policy::ControlStructures::ProhibitLabelsWithSpecialBlockNames 1.121 - Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions 1.121 - Perl::Critic::Policy::ControlStructures::ProhibitNegativeExpressionsInUnlessAndUntilConditions 1.121 - Perl::Critic::Policy::ControlStructures::ProhibitPostfixControls 1.121 - Perl::Critic::Policy::ControlStructures::ProhibitUnlessBlocks 1.121 - Perl::Critic::Policy::ControlStructures::ProhibitUnreachableCode 1.121 - Perl::Critic::Policy::ControlStructures::ProhibitUntilBlocks 1.121 - Perl::Critic::Policy::Documentation::PodSpelling 1.121 - Perl::Critic::Policy::Documentation::RequirePackageMatchesPodName 1.121 - Perl::Critic::Policy::Documentation::RequirePodAtEnd 1.121 - Perl::Critic::Policy::Documentation::RequirePodLinksIncludeText 1.121 - Perl::Critic::Policy::Documentation::RequirePodSections 1.121 - Perl::Critic::Policy::ErrorHandling::RequireCarping 1.121 - Perl::Critic::Policy::ErrorHandling::RequireCheckingReturnValueOfEval 1.121 - Perl::Critic::Policy::InputOutput::ProhibitBacktickOperators 1.121 - Perl::Critic::Policy::InputOutput::ProhibitBarewordFileHandles 1.121 - Perl::Critic::Policy::InputOutput::ProhibitExplicitStdin 1.121 - Perl::Critic::Policy::InputOutput::ProhibitInteractiveTest 1.121 - Perl::Critic::Policy::InputOutput::ProhibitJoinedReadline 1.121 - Perl::Critic::Policy::InputOutput::ProhibitOneArgSelect 1.121 - Perl::Critic::Policy::InputOutput::ProhibitReadlineInForLoop 1.121 - Perl::Critic::Policy::InputOutput::ProhibitTwoArgOpen 1.121 - Perl::Critic::Policy::InputOutput::RequireBracedFileHandleWithPrint 1.121 - Perl::Critic::Policy::InputOutput::RequireBriefOpen 1.121 - Perl::Critic::Policy::InputOutput::RequireCheckedClose 1.121 - Perl::Critic::Policy::InputOutput::RequireCheckedOpen 1.121 - Perl::Critic::Policy::InputOutput::RequireCheckedSyscalls 1.121 - Perl::Critic::Policy::InputOutput::RequireEncodingWithUTF8Layer 1.121 - Perl::Critic::Policy::Miscellanea::ProhibitFormats 1.121 - Perl::Critic::Policy::Miscellanea::ProhibitTies 1.121 - Perl::Critic::Policy::Miscellanea::ProhibitUnrestrictedNoCritic 1.121 - Perl::Critic::Policy::Miscellanea::ProhibitUselessNoCritic 1.121 - Perl::Critic::Policy::Modules::ProhibitAutomaticExportation 1.121 - Perl::Critic::Policy::Modules::ProhibitConditionalUseStatements 1.121 - Perl::Critic::Policy::Modules::ProhibitEvilModules 1.121 - Perl::Critic::Policy::Modules::ProhibitExcessMainComplexity 1.121 - Perl::Critic::Policy::Modules::ProhibitMultiplePackages 1.121 - Perl::Critic::Policy::Modules::RequireBarewordIncludes 1.121 - Perl::Critic::Policy::Modules::RequireEndWithOne 1.121 - Perl::Critic::Policy::Modules::RequireExplicitPackage 1.121 - Perl::Critic::Policy::Modules::RequireFilenameMatchesPackage 1.121 - Perl::Critic::Policy::Modules::RequireNoMatchVarsWithUseEnglish 1.121 - Perl::Critic::Policy::Modules::RequireVersionVar 1.121 - Perl::Critic::Policy::NamingConventions::Capitalization 1.121 - Perl::Critic::Policy::NamingConventions::ProhibitAmbiguousNames 1.121 - Perl::Critic::Policy::Objects::ProhibitIndirectSyntax 1.121 - Perl::Critic::Policy::References::ProhibitDoubleSigils 1.121 - Perl::Critic::Policy::RegularExpressions::ProhibitCaptureWithoutTest 1.121 - Perl::Critic::Policy::RegularExpressions::ProhibitComplexRegexes 1.121 - Perl::Critic::Policy::RegularExpressions::ProhibitEnumeratedClasses 1.121 - Perl::Critic::Policy::RegularExpressions::ProhibitEscapedMetacharacters 1.121 - Perl::Critic::Policy::RegularExpressions::ProhibitFixedStringMatches 1.121 - Perl::Critic::Policy::RegularExpressions::ProhibitSingleCharAlternation 1.121 - Perl::Critic::Policy::RegularExpressions::ProhibitUnusedCapture 1.121 - Perl::Critic::Policy::RegularExpressions::ProhibitUnusualDelimiters 1.121 - Perl::Critic::Policy::RegularExpressions::RequireBracesForMultiline 1.121 - Perl::Critic::Policy::RegularExpressions::RequireDotMatchAnything 1.121 - Perl::Critic::Policy::RegularExpressions::RequireExtendedFormatting 1.121 - Perl::Critic::Policy::RegularExpressions::RequireLineBoundaryMatching 1.121 - Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils 1.121 - Perl::Critic::Policy::Subroutines::ProhibitBuiltinHomonyms 1.121 - Perl::Critic::Policy::Subroutines::ProhibitExcessComplexity 1.121 - Perl::Critic::Policy::Subroutines::ProhibitExplicitReturnUndef 1.121 - Perl::Critic::Policy::Subroutines::ProhibitManyArgs 1.121 - Perl::Critic::Policy::Subroutines::ProhibitNestedSubs 1.121 - Perl::Critic::Policy::Subroutines::ProhibitReturnSort 1.121 - Perl::Critic::Policy::Subroutines::ProhibitSubroutinePrototypes 1.121 - Perl::Critic::Policy::Subroutines::ProhibitUnusedPrivateSubroutines 1.121 - Perl::Critic::Policy::Subroutines::ProtectPrivateSubs 1.121 - Perl::Critic::Policy::Subroutines::RequireArgUnpacking 1.121 - Perl::Critic::Policy::Subroutines::RequireFinalReturn 1.121 - Perl::Critic::Policy::TestingAndDebugging::ProhibitNoStrict 1.121 - Perl::Critic::Policy::TestingAndDebugging::ProhibitNoWarnings 1.121 - Perl::Critic::Policy::TestingAndDebugging::ProhibitProlongedStrictureOverride 1.121 - Perl::Critic::Policy::TestingAndDebugging::RequireTestLabels 1.121 - Perl::Critic::Policy::TestingAndDebugging::RequireUseStrict 1.121 - Perl::Critic::Policy::TestingAndDebugging::RequireUseWarnings 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitCommaSeparatedStatements 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitComplexVersion 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitConstantPragma 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitEmptyQuotes 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitEscapedCharacters 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitImplicitNewlines 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitInterpolationOfLiterals 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitLeadingZeros 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitLongChainsOfMethodCalls 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitMagicNumbers 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitMismatchedOperators 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitMixedBooleanOperators 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitNoisyQuotes 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitQuotesAsQuotelikeOperatorDelimiters 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitSpecialLiteralHeredocTerminator 1.121 - Perl::Critic::Policy::ValuesAndExpressions::ProhibitVersionStrings 1.121 - Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion 1.121 - Perl::Critic::Policy::ValuesAndExpressions::RequireInterpolationOfMetachars 1.121 - Perl::Critic::Policy::ValuesAndExpressions::RequireNumberSeparators 1.121 - Perl::Critic::Policy::ValuesAndExpressions::RequireQuotedHeredocTerminator 1.121 - Perl::Critic::Policy::ValuesAndExpressions::RequireUpperCaseHeredocTerminator 1.121 - Perl::Critic::Policy::Variables::ProhibitAugmentedAssignmentInDeclaration 1.121 - Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations 1.121 - Perl::Critic::Policy::Variables::ProhibitEvilVariables 1.121 - Perl::Critic::Policy::Variables::ProhibitLocalVars 1.121 - Perl::Critic::Policy::Variables::ProhibitMatchVars 1.121 - Perl::Critic::Policy::Variables::ProhibitPackageVars 1.121 - Perl::Critic::Policy::Variables::ProhibitPerl4PackageNames 1.121 - Perl::Critic::Policy::Variables::ProhibitPunctuationVars 1.121 - Perl::Critic::Policy::Variables::ProhibitReusedNames 1.121 - Perl::Critic::Policy::Variables::ProhibitUnusedVariables 1.121 - Perl::Critic::Policy::Variables::ProtectPrivateVars 1.121 - Perl::Critic::Policy::Variables::RequireInitializationForLocalVars 1.121 - Perl::Critic::Policy::Variables::RequireLexicalLoopIterators 1.121 - Perl::Critic::Policy::Variables::RequireLocalizedPunctuationVars 1.121 - Perl::Critic::Policy::Variables::RequireNegativeIndices 1.121 - Perl::Critic::PolicyConfig 1.121 - Perl::Critic::PolicyFactory 1.121 - Perl::Critic::PolicyListing 1.121 - Perl::Critic::PolicyParameter 1.121 - Perl::Critic::PolicyParameter::Behavior 1.121 - Perl::Critic::PolicyParameter::Behavior::Boolean 1.121 - Perl::Critic::PolicyParameter::Behavior::Enumeration 1.121 - Perl::Critic::PolicyParameter::Behavior::Integer 1.121 - Perl::Critic::PolicyParameter::Behavior::String 1.121 - Perl::Critic::PolicyParameter::Behavior::StringList 1.121 - Perl::Critic::ProfilePrototype 1.121 - Perl::Critic::Statistics 1.121 - Perl::Critic::TestUtils 1.121 - Perl::Critic::Theme 1.121 - Perl::Critic::ThemeListing 1.121 - Perl::Critic::UserProfile 1.121 - Perl::Critic::Utils 1.121 - Perl::Critic::Utils::Constants 1.121 - Perl::Critic::Utils::DataConversion 1.121 - Perl::Critic::Utils::McCabe 1.121 - Perl::Critic::Utils::POD 1.121 - Perl::Critic::Utils::POD::ParseInteriorSequence 1.121 - Perl::Critic::Utils::PPI 1.121 - Perl::Critic::Utils::Perl 1.121 - Perl::Critic::Violation 1.121 - Test::Perl::Critic::Policy 1.121 - requirements: - B::Keywords 1.05 + warnings::register 0 + Perl-Critic-1.156 + pathname: P/PE/PETDANCE/Perl-Critic-1.156.tar.gz + provides: + Perl::Critic 1.156 + Perl::Critic::Annotation 1.156 + Perl::Critic::Command 1.156 + Perl::Critic::Config 1.156 + Perl::Critic::Document 1.156 + Perl::Critic::Exception 1.156 + Perl::Critic::Exception::AggregateConfiguration 1.156 + Perl::Critic::Exception::Configuration 1.156 + Perl::Critic::Exception::Configuration::Generic 1.156 + Perl::Critic::Exception::Configuration::NonExistentPolicy 1.156 + Perl::Critic::Exception::Configuration::Option 1.156 + Perl::Critic::Exception::Configuration::Option::Global 1.156 + Perl::Critic::Exception::Configuration::Option::Global::ExtraParameter 1.156 + Perl::Critic::Exception::Configuration::Option::Global::ParameterValue 1.156 + Perl::Critic::Exception::Configuration::Option::Policy 1.156 + Perl::Critic::Exception::Configuration::Option::Policy::ExtraParameter 1.156 + Perl::Critic::Exception::Configuration::Option::Policy::ParameterValue 1.156 + Perl::Critic::Exception::Fatal 1.156 + Perl::Critic::Exception::Fatal::Generic 1.156 + Perl::Critic::Exception::Fatal::Internal 1.156 + Perl::Critic::Exception::Fatal::PolicyDefinition 1.156 + Perl::Critic::Exception::IO 1.156 + Perl::Critic::Exception::Parse 1.156 + Perl::Critic::OptionsProcessor 1.156 + Perl::Critic::Policy 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitBooleanGrep 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitComplexMappings 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitLvalueSubstr 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitReverseSortBlock 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitShiftRef 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitSleepViaSelect 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitStringyEval 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitStringySplit 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitUniversalCan 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitUniversalIsa 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitUselessTopic 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitVoidGrep 1.156 + Perl::Critic::Policy::BuiltinFunctions::ProhibitVoidMap 1.156 + Perl::Critic::Policy::BuiltinFunctions::RequireBlockGrep 1.156 + Perl::Critic::Policy::BuiltinFunctions::RequireBlockMap 1.156 + Perl::Critic::Policy::BuiltinFunctions::RequireGlobFunction 1.156 + Perl::Critic::Policy::BuiltinFunctions::RequireSimpleSortBlock 1.156 + Perl::Critic::Policy::ClassHierarchies::ProhibitAutoloading 1.156 + Perl::Critic::Policy::ClassHierarchies::ProhibitExplicitISA 1.156 + Perl::Critic::Policy::ClassHierarchies::ProhibitOneArgBless 1.156 + Perl::Critic::Policy::CodeLayout::ProhibitHardTabs 1.156 + Perl::Critic::Policy::CodeLayout::ProhibitParensWithBuiltins 1.156 + Perl::Critic::Policy::CodeLayout::ProhibitQuotedWordLists 1.156 + Perl::Critic::Policy::CodeLayout::ProhibitTrailingWhitespace 1.156 + Perl::Critic::Policy::CodeLayout::RequireConsistentNewlines 1.156 + Perl::Critic::Policy::CodeLayout::RequireTidyCode 1.156 + Perl::Critic::Policy::CodeLayout::RequireTrailingCommas 1.156 + Perl::Critic::Policy::ControlStructures::ProhibitCStyleForLoops 1.156 + Perl::Critic::Policy::ControlStructures::ProhibitCascadingIfElse 1.156 + Perl::Critic::Policy::ControlStructures::ProhibitDeepNests 1.156 + Perl::Critic::Policy::ControlStructures::ProhibitLabelsWithSpecialBlockNames 1.156 + Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions 1.156 + Perl::Critic::Policy::ControlStructures::ProhibitNegativeExpressionsInUnlessAndUntilConditions 1.156 + Perl::Critic::Policy::ControlStructures::ProhibitPostfixControls 1.156 + Perl::Critic::Policy::ControlStructures::ProhibitUnlessBlocks 1.156 + Perl::Critic::Policy::ControlStructures::ProhibitUnreachableCode 1.156 + Perl::Critic::Policy::ControlStructures::ProhibitUntilBlocks 1.156 + Perl::Critic::Policy::ControlStructures::ProhibitYadaOperator 1.156 + Perl::Critic::Policy::Documentation::PodSpelling 1.156 + Perl::Critic::Policy::Documentation::RequirePackageMatchesPodName 1.156 + Perl::Critic::Policy::Documentation::RequirePodAtEnd 1.156 + Perl::Critic::Policy::Documentation::RequirePodSections 1.156 + Perl::Critic::Policy::ErrorHandling::RequireCarping 1.156 + Perl::Critic::Policy::ErrorHandling::RequireCheckingReturnValueOfEval 1.156 + Perl::Critic::Policy::InputOutput::ProhibitBacktickOperators 1.156 + Perl::Critic::Policy::InputOutput::ProhibitBarewordDirHandles 1.156 + Perl::Critic::Policy::InputOutput::ProhibitBarewordFileHandles 1.156 + Perl::Critic::Policy::InputOutput::ProhibitExplicitStdin 1.156 + Perl::Critic::Policy::InputOutput::ProhibitInteractiveTest 1.156 + Perl::Critic::Policy::InputOutput::ProhibitJoinedReadline 1.156 + Perl::Critic::Policy::InputOutput::ProhibitOneArgSelect 1.156 + Perl::Critic::Policy::InputOutput::ProhibitReadlineInForLoop 1.156 + Perl::Critic::Policy::InputOutput::ProhibitTwoArgOpen 1.156 + Perl::Critic::Policy::InputOutput::RequireBracedFileHandleWithPrint 1.156 + Perl::Critic::Policy::InputOutput::RequireBriefOpen 1.156 + Perl::Critic::Policy::InputOutput::RequireCheckedClose 1.156 + Perl::Critic::Policy::InputOutput::RequireCheckedOpen 1.156 + Perl::Critic::Policy::InputOutput::RequireCheckedSyscalls 1.156 + Perl::Critic::Policy::InputOutput::RequireEncodingWithUTF8Layer 1.156 + Perl::Critic::Policy::Miscellanea::ProhibitFormats 1.156 + Perl::Critic::Policy::Miscellanea::ProhibitTies 1.156 + Perl::Critic::Policy::Miscellanea::ProhibitUnrestrictedNoCritic 1.156 + Perl::Critic::Policy::Miscellanea::ProhibitUselessNoCritic 1.156 + Perl::Critic::Policy::Modules::ProhibitAutomaticExportation 1.156 + Perl::Critic::Policy::Modules::ProhibitConditionalUseStatements 1.156 + Perl::Critic::Policy::Modules::ProhibitEvilModules 1.156 + Perl::Critic::Policy::Modules::ProhibitExcessMainComplexity 1.156 + Perl::Critic::Policy::Modules::ProhibitMultiplePackages 1.156 + Perl::Critic::Policy::Modules::RequireBarewordIncludes 1.156 + Perl::Critic::Policy::Modules::RequireEndWithOne 1.156 + Perl::Critic::Policy::Modules::RequireExplicitPackage 1.156 + Perl::Critic::Policy::Modules::RequireFilenameMatchesPackage 1.156 + Perl::Critic::Policy::Modules::RequireNoMatchVarsWithUseEnglish 1.156 + Perl::Critic::Policy::Modules::RequireVersionVar 1.156 + Perl::Critic::Policy::NamingConventions::Capitalization 1.156 + Perl::Critic::Policy::NamingConventions::ProhibitAmbiguousNames 1.156 + Perl::Critic::Policy::Objects::ProhibitIndirectSyntax 1.156 + Perl::Critic::Policy::References::ProhibitDoubleSigils 1.156 + Perl::Critic::Policy::RegularExpressions::ProhibitCaptureWithoutTest 1.156 + Perl::Critic::Policy::RegularExpressions::ProhibitComplexRegexes 1.156 + Perl::Critic::Policy::RegularExpressions::ProhibitEnumeratedClasses 1.156 + Perl::Critic::Policy::RegularExpressions::ProhibitEscapedMetacharacters 1.156 + Perl::Critic::Policy::RegularExpressions::ProhibitFixedStringMatches 1.156 + Perl::Critic::Policy::RegularExpressions::ProhibitSingleCharAlternation 1.156 + Perl::Critic::Policy::RegularExpressions::ProhibitUnusedCapture 1.156 + Perl::Critic::Policy::RegularExpressions::ProhibitUnusualDelimiters 1.156 + Perl::Critic::Policy::RegularExpressions::ProhibitUselessTopic 1.156 + Perl::Critic::Policy::RegularExpressions::RequireBracesForMultiline 1.156 + Perl::Critic::Policy::RegularExpressions::RequireDotMatchAnything 1.156 + Perl::Critic::Policy::RegularExpressions::RequireExtendedFormatting 1.156 + Perl::Critic::Policy::RegularExpressions::RequireLineBoundaryMatching 1.156 + Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils 1.156 + Perl::Critic::Policy::Subroutines::ProhibitBuiltinHomonyms 1.156 + Perl::Critic::Policy::Subroutines::ProhibitExcessComplexity 1.156 + Perl::Critic::Policy::Subroutines::ProhibitExplicitReturnUndef 1.156 + Perl::Critic::Policy::Subroutines::ProhibitManyArgs 1.156 + Perl::Critic::Policy::Subroutines::ProhibitNestedSubs 1.156 + Perl::Critic::Policy::Subroutines::ProhibitReturnSort 1.156 + Perl::Critic::Policy::Subroutines::ProhibitSubroutinePrototypes 1.156 + Perl::Critic::Policy::Subroutines::ProhibitUnusedPrivateSubroutines 1.156 + Perl::Critic::Policy::Subroutines::ProtectPrivateSubs 1.156 + Perl::Critic::Policy::Subroutines::RequireArgUnpacking 1.156 + Perl::Critic::Policy::Subroutines::RequireFinalReturn 1.156 + Perl::Critic::Policy::TestingAndDebugging::ProhibitNoStrict 1.156 + Perl::Critic::Policy::TestingAndDebugging::ProhibitNoWarnings 1.156 + Perl::Critic::Policy::TestingAndDebugging::ProhibitProlongedStrictureOverride 1.156 + Perl::Critic::Policy::TestingAndDebugging::RequireTestLabels 1.156 + Perl::Critic::Policy::TestingAndDebugging::RequireUseStrict 1.156 + Perl::Critic::Policy::TestingAndDebugging::RequireUseWarnings 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitCommaSeparatedStatements 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitComplexVersion 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitConstantPragma 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitEmptyQuotes 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitEscapedCharacters 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitImplicitNewlines 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitInterpolationOfLiterals 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitLeadingZeros 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitLongChainsOfMethodCalls 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitMagicNumbers 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitMismatchedOperators 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitMixedBooleanOperators 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitNoisyQuotes 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitQuotesAsQuotelikeOperatorDelimiters 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitSpecialLiteralHeredocTerminator 1.156 + Perl::Critic::Policy::ValuesAndExpressions::ProhibitVersionStrings 1.156 + Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion 1.156 + Perl::Critic::Policy::ValuesAndExpressions::RequireInterpolationOfMetachars 1.156 + Perl::Critic::Policy::ValuesAndExpressions::RequireNumberSeparators 1.156 + Perl::Critic::Policy::ValuesAndExpressions::RequireQuotedHeredocTerminator 1.156 + Perl::Critic::Policy::ValuesAndExpressions::RequireUpperCaseHeredocTerminator 1.156 + Perl::Critic::Policy::Variables::ProhibitAugmentedAssignmentInDeclaration 1.156 + Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations 1.156 + Perl::Critic::Policy::Variables::ProhibitEvilVariables 1.156 + Perl::Critic::Policy::Variables::ProhibitLocalVars 1.156 + Perl::Critic::Policy::Variables::ProhibitMatchVars 1.156 + Perl::Critic::Policy::Variables::ProhibitPackageVars 1.156 + Perl::Critic::Policy::Variables::ProhibitPerl4PackageNames 1.156 + Perl::Critic::Policy::Variables::ProhibitPunctuationVars 1.156 + Perl::Critic::Policy::Variables::ProhibitReusedNames 1.156 + Perl::Critic::Policy::Variables::ProhibitUnusedVariables 1.156 + Perl::Critic::Policy::Variables::ProtectPrivateVars 1.156 + Perl::Critic::Policy::Variables::RequireInitializationForLocalVars 1.156 + Perl::Critic::Policy::Variables::RequireLexicalLoopIterators 1.156 + Perl::Critic::Policy::Variables::RequireLocalizedPunctuationVars 1.156 + Perl::Critic::Policy::Variables::RequireNegativeIndices 1.156 + Perl::Critic::PolicyConfig 1.156 + Perl::Critic::PolicyFactory 1.156 + Perl::Critic::PolicyListing 1.156 + Perl::Critic::PolicyParameter 1.156 + Perl::Critic::PolicyParameter::Behavior 1.156 + Perl::Critic::PolicyParameter::Behavior::Boolean 1.156 + Perl::Critic::PolicyParameter::Behavior::Enumeration 1.156 + Perl::Critic::PolicyParameter::Behavior::Integer 1.156 + Perl::Critic::PolicyParameter::Behavior::String 1.156 + Perl::Critic::PolicyParameter::Behavior::StringList 1.156 + Perl::Critic::ProfilePrototype 1.156 + Perl::Critic::Statistics 1.156 + Perl::Critic::TestUtils 1.156 + Perl::Critic::Theme 1.156 + Perl::Critic::ThemeListing 1.156 + Perl::Critic::UserProfile 1.156 + Perl::Critic::Utils 1.156 + Perl::Critic::Utils::Constants 1.156 + Perl::Critic::Utils::McCabe 1.156 + Perl::Critic::Utils::POD 1.156 + Perl::Critic::Utils::PPI 1.156 + Perl::Critic::Utils::Perl 1.156 + Perl::Critic::Violation 1.156 + Test::Perl::Critic::Policy 1.156 + requirements: + B::Keywords 1.23 Carp 0 Config::Tiny 2 - Email::Address 1.889 English 0 Exception::Class 1.23 Exporter 5.63 @@ -6215,143 +5879,84 @@ DISTRIBUTIONS File::Spec 0 File::Spec::Unix 0 File::Temp 0 + File::Which 0 Getopt::Long 0 - IO::String 0 - IPC::Open2 1 - List::MoreUtils 0.19 + List::SomeUtils 0.55 List::Util 0 - Module::Build 0.34 + Module::Build 0.4204 Module::Pluggable 3.1 - PPI 1.215 - PPI::Document 1.215 - PPI::Document::File 1.215 - PPI::Node 1.215 - PPI::Token::Quote::Single 1.215 - PPI::Token::Whitespace 1.215 + PPI 1.277 + PPI::Document 1.277 + PPI::Document::File 1.277 + PPI::Node 1.277 + PPI::Token::Quote::Single 1.277 + PPI::Token::Whitespace 1.277 + PPIx::QuoteLike 0 PPIx::Regexp 0.027 - PPIx::Utilities::Node 1.001 - PPIx::Utilities::Statement 1.001 + PPIx::Regexp::Util 0.068 + PPIx::Utils::Traversal 0.003 Perl::Tidy 0 - Pod::Parser 0 Pod::PlainText 0 Pod::Select 0 Pod::Spell 1 Pod::Usage 0 - Readonly 1.03 + Readonly 2 Scalar::Util 0 - String::Format 1.13 - Task::Weaken 0 + String::Format 1.18 + Term::ANSIColor 2.02 Test::Builder 0.92 - Test::Deep 0 - Test::More 0 Text::ParseWords 3 base 0 charnames 0 lib 0 overload 0 + parent 0 + perl 5.010001 strict 0 version 0.77 warnings 0 - Perl-Tidy-20140328 - pathname: S/SH/SHANCOCK/Perl-Tidy-20140328.tar.gz - provides: - Perl::Tidy 20140328 - Perl::Tidy::DevNull 20140328 - Perl::Tidy::Diagnostics 20140328 - Perl::Tidy::HtmlWriter 20140328 - Perl::Tidy::IOScalar 20140328 - Perl::Tidy::IOScalarArray 20140328 - Perl::Tidy::LineSink 20140328 - Perl::Tidy::LineSource 20140328 - Perl::Tidy::Logger 20140328 + Perl-Tidy-20240511 + pathname: S/SH/SHANCOCK/Perl-Tidy-20240511.tar.gz + provides: + Perl::Tidy 20240511 + Perl::Tidy::Debugger 20240511 + Perl::Tidy::Diagnostics 20240511 + Perl::Tidy::FileWriter 20240511 + Perl::Tidy::Formatter 20240511 + Perl::Tidy::HtmlWriter 20240511 + Perl::Tidy::IOScalar 20240511 + Perl::Tidy::IOScalarArray 20240511 + Perl::Tidy::IndentationItem 20240511 + Perl::Tidy::Logger 20240511 + Perl::Tidy::Tokenizer 20240511 + Perl::Tidy::VerticalAligner 20240511 + Perl::Tidy::VerticalAligner::Alignment 20240511 + Perl::Tidy::VerticalAligner::Line 20240511 requirements: ExtUtils::MakeMaker 0 - PerlIO-gzip-0.18 - pathname: N/NW/NWCLARK/PerlIO-gzip-0.18.tar.gz + perl 5.008 + PerlIO-gzip-0.20 + pathname: N/NW/NWCLARK/PerlIO-gzip-0.20.tar.gz provides: - PerlIO::gzip 0.18 + PerlIO::gzip 0.20 requirements: ExtUtils::MakeMaker 0 - PerlIO-utf8_strict-0.004 - pathname: L/LE/LEONT/PerlIO-utf8_strict-0.004.tar.gz + PerlIO-utf8_strict-0.010 + pathname: L/LE/LEONT/PerlIO-utf8_strict-0.010.tar.gz provides: - PerlIO::utf8_strict 0.004 - t::Util undef + PerlIO::utf8_strict 0.010 requirements: - Carp 0 - Exporter 0 - ExtUtils::CBuilder 0 - File::Find 0 - File::Spec::Functions 0 - File::Temp 0 - IO::File 0 - Module::Build 0.3601 - Test::Exception 0 - Test::More 0.88 + ExtUtils::MakeMaker 0 XSLoader 0 perl 5.008 strict 0 - utf8 0 warnings 0 - Pithub-0.01025 - pathname: P/PL/PLU/Pithub-0.01025.tar.gz - provides: - Pithub 0.01025 - Pithub::Base 0.01025 - Pithub::Events 0.01025 - Pithub::Gists 0.01025 - Pithub::Gists::Comments 0.01025 - Pithub::GitData 0.01025 - Pithub::GitData::Blobs 0.01025 - Pithub::GitData::Commits 0.01025 - Pithub::GitData::References 0.01025 - Pithub::GitData::Tags 0.01025 - Pithub::GitData::Trees 0.01025 - Pithub::Issues 0.01025 - Pithub::Issues::Assignees 0.01025 - Pithub::Issues::Comments 0.01025 - Pithub::Issues::Events 0.01025 - Pithub::Issues::Labels 0.01025 - Pithub::Issues::Milestones 0.01025 - Pithub::Orgs 0.01025 - Pithub::Orgs::Members 0.01025 - Pithub::Orgs::Teams 0.01025 - Pithub::PullRequests 0.01025 - Pithub::PullRequests::Comments 0.01025 - Pithub::Repos 0.01025 - Pithub::Repos::Collaborators 0.01025 - Pithub::Repos::Commits 0.01025 - Pithub::Repos::Contents 0.01025 - Pithub::Repos::Downloads 0.01025 - Pithub::Repos::Forks 0.01025 - Pithub::Repos::Hooks 0.01025 - Pithub::Repos::Keys 0.01025 - Pithub::Repos::Releases 0.01025 - Pithub::Repos::Releases::Assets 0.01025 - Pithub::Repos::Starring 0.01025 - Pithub::Repos::Stats 0.01025 - Pithub::Repos::Statuses 0.01025 - Pithub::Repos::Watching 0.01025 - Pithub::Result 0.01025 - Pithub::Search 0.01025 - Pithub::Users 0.01025 - Pithub::Users::Emails 0.01025 - Pithub::Users::Followers 0.01025 - Pithub::Users::Keys 0.01025 - requirements: - Array::Iterator 0 - ExtUtils::MakeMaker 6.30 - HTTP::Message 0 - JSON 0 - LWP::Protocol::https 0 - LWP::UserAgent 0 - Moo 0 - Plack-1.0030 - pathname: M/MI/MIYAGAWA/Plack-1.0030.tar.gz + Plack-1.0051 + pathname: M/MI/MIYAGAWA/Plack-1.0051.tar.gz provides: HTTP::Message::PSGI undef HTTP::Server::PSGI undef - Plack 1.0030 + Plack 1.0051 Plack::App::CGIBin undef Plack::App::Cascade undef Plack::App::Directory undef @@ -6410,9 +6015,9 @@ DISTRIBUTIONS Plack::Middleware::XFramework undef Plack::Middleware::XSendfile undef Plack::Recursive::ForwardRequest undef - Plack::Request 1.0030 + Plack::Request 1.0051 Plack::Request::Upload undef - Plack::Response 1.0030 + Plack::Response 1.0051 Plack::Runner undef Plack::TempBuffer undef Plack::Test undef @@ -6424,27 +6029,31 @@ DISTRIBUTIONS Plack::Util::IOWithPath undef Plack::Util::Prototype undef requirements: - Apache::LogFormat::Compiler 0.12 + Apache::LogFormat::Compiler 0.33 + Cookie::Baker 0.07 Devel::StackTrace 1.23 Devel::StackTrace::AsHTML 0.11 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 File::ShareDir 1.00 - File::ShareDir::Install 0.03 + File::ShareDir::Install 0.06 Filesys::Notify::Simple 0 - HTTP::Body 1.06 + HTTP::Entity::Parser 0.25 + HTTP::Headers::Fast 0.18 HTTP::Message 5.814 HTTP::Tiny 0.034 Hash::MultiValue 0.05 Pod::Usage 1.36 Stream::Buffered 0.02 - Test::TCP 2.00 + Test::TCP 2.15 Try::Tiny 0 URI 1.59 + WWW::Form::UrlEncoded 0.23 parent 0 - Plack-Middleware-FixMissingBodyInRedirect-0.11 - pathname: S/SW/SWEETKID/Plack-Middleware-FixMissingBodyInRedirect-0.11.tar.gz + perl 5.012000 + Plack-Middleware-FixMissingBodyInRedirect-0.12 + pathname: S/SW/SWEETKID/Plack-Middleware-FixMissingBodyInRedirect-0.12.tar.gz provides: - Plack::Middleware::FixMissingBodyInRedirect 0.10 + Plack::Middleware::FixMissingBodyInRedirect 0.12 requirements: ExtUtils::MakeMaker 6.30 HTML::Entities 0 @@ -6454,43 +6063,34 @@ DISTRIBUTIONS parent 0 strict 0 warnings 0 - Plack-Middleware-Header-0.04 - pathname: C/CH/CHIBA/Plack-Middleware-Header-0.04.tar.gz + Plack-Middleware-MethodOverride-0.20 + pathname: M/MI/MIYAGAWA/Plack-Middleware-MethodOverride-0.20.tar.gz provides: - Plack::Middleware::Header 0.04 + Plack::Middleware::MethodOverride 0.20 requirements: - ExtUtils::MakeMaker 6.42 - Filter::Util::Call 0 + ExtUtils::MakeMaker 0 Plack::Middleware 0 - Test::More 0 + Plack::Request 0 + Plack::Util::Accessor 0 parent 0 perl 5.008001 - Plack-Middleware-MethodOverride-0.10 - pathname: D/DW/DWHEELER/Plack-Middleware-MethodOverride-0.10.tar.gz - provides: - Plack::Middleware::MethodOverride 0.10 - requirements: - Module::Build 0.30 - Plack 0.9929 - Test::Builder 0.70 - Test::More 0.70 - URI 0 - perl 5.008001 - Plack-Middleware-RemoveRedundantBody-0.05 - pathname: S/SW/SWEETKID/Plack-Middleware-RemoveRedundantBody-0.05.tar.gz + strict 0 + warnings 0 + Plack-Middleware-RemoveRedundantBody-0.09 + pathname: S/SW/SWEETKID/Plack-Middleware-RemoveRedundantBody-0.09.tar.gz provides: - Plack::Middleware::RemoveRedundantBody 0.04 + Plack::Middleware::RemoveRedundantBody 0.09 requirements: - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 Plack::Middleware 0 Plack::Util 0 parent 0 strict 0 warnings 0 - Plack-Middleware-ReverseProxy-0.15 - pathname: M/MI/MIYAGAWA/Plack-Middleware-ReverseProxy-0.15.tar.gz + Plack-Middleware-ReverseProxy-0.16 + pathname: M/MI/MIYAGAWA/Plack-Middleware-ReverseProxy-0.16.tar.gz provides: - Plack::Middleware::ReverseProxy 0.15 + Plack::Middleware::ReverseProxy 0.16 requirements: ExtUtils::MakeMaker 6.59 Plack 0.9988 @@ -6499,181 +6099,87 @@ DISTRIBUTIONS Test::More 0 parent 0 perl 5.008001 - Plack-Middleware-Rewrite-1.008 - pathname: A/AR/ARISTOTLE/Plack-Middleware-Rewrite-1.008.tar.gz - provides: - Plack::Middleware::Rewrite 1.008 - requirements: - ExtUtils::MakeMaker 6.30 - HTTP::Request::Common 0 - Plack 0.9942 - Plack::Builder 0 - Plack::Middleware 0 - Plack::Request 0 - Plack::Test 0 - Plack::Util 0 - Plack::Util::Accessor 0 - Test::More 0 - parent 0 - strict 0 - warnings 0 - Plack-Middleware-ServerStatus-Lite-0.33 - pathname: K/KA/KAZEBURO/Plack-Middleware-ServerStatus-Lite-0.33.tar.gz - provides: - Plack::Middleware::ServerStatus::Lite 0.33 - requirements: - CPAN::Meta 0 - CPAN::Meta::Prereqs 0 - ExtUtils::CBuilder 0 - Getopt::Long 2.38 - JSON 2.53 - Module::Build 0.38 - Net::CIDR::Lite 0 - Parallel::Scoreboard 0.03 - Plack::Middleware 0 - Pod::Usage 0 - Try::Tiny 0.09 - parent 0 - Plack-Middleware-Session-0.21 - pathname: M/MI/MIYAGAWA/Plack-Middleware-Session-0.21.tar.gz + Plack-Middleware-Session-0.34 + pathname: M/MI/MIYAGAWA/Plack-Middleware-Session-0.34.tar.gz provides: - Plack::Middleware::Session 0.21 + Plack::Middleware::Session 0.34 Plack::Middleware::Session::Cookie undef - Plack::Session 0.21 - Plack::Session::State 0.21 - Plack::Session::State::Cookie 0.21 - Plack::Session::Store 0.21 - Plack::Session::Store::Cache 0.21 - Plack::Session::Store::DBI 0.10 - Plack::Session::Store::File 0.21 - Plack::Session::Store::Null 0.21 - requirements: - Cookie::Baker 0 + Plack::Session 0.34 + Plack::Session::Cleanup 0.34 + Plack::Session::State 0.34 + Plack::Session::State::Cookie 0.34 + Plack::Session::Store 0.34 + Plack::Session::Store::Cache 0.34 + Plack::Session::Store::DBI 0.34 + Plack::Session::Store::File 0.34 + Plack::Session::Store::Null 0.34 + requirements: + Cookie::Baker 0.12 Digest::HMAC_SHA1 1.03 - Digest::SHA1 0 - Module::Build::Tiny 0.030 + Digest::SHA 0 + Module::Build::Tiny 0.034 Plack 0.9910 - Plack-Test-ExternalServer-0.01 - pathname: F/FL/FLORA/Plack-Test-ExternalServer-0.01.tar.gz + Plack-Test-ExternalServer-0.02 + pathname: E/ET/ETHER/Plack-Test-ExternalServer-0.02.tar.gz provides: - Plack::Test::ExternalServer 0.01 + Plack::Test::ExternalServer 0.02 requirements: + Carp 0 ExtUtils::MakeMaker 0 - HTTP::Request::Common 0 LWP::UserAgent 0 - Plack::Loader 0 - Plack::Test 0 - Test::More 0.89 - Test::TCP 0 URI 0 - Pod-Coverage-0.23 - pathname: R/RC/RCLAMP/Pod-Coverage-0.23.tar.gz - provides: - Pod::Coverage 0.23 - Pod::Coverage::CountParents undef - Pod::Coverage::ExportOnly undef - Pod::Coverage::Extractor 0.23 - Pod::Coverage::Overloader undef - requirements: - Devel::Symdump 2.01 - ExtUtils::MakeMaker 0 - Pod::Find 0.21 - Pod::Parser 1.13 - Test::More 0 - Pod-Coverage-Moose-0.05 - pathname: E/ET/ETHER/Pod-Coverage-Moose-0.05.tar.gz - provides: - Pod::Coverage::Moose 0.05 - requirements: - Carp 0 - Class::Load 0 - ExtUtils::MakeMaker 6.30 - Module::Build::Tiny 0.030 - Moose 0.24 - Pod::Coverage 0 - namespace::autoclean 0.08 perl 5.006 - Pod-Markdown-3.002 - pathname: R/RW/RWSTAUNER/Pod-Markdown-3.002.tar.gz + strict 0 + warnings 0 + Pod-Markdown-3.400 + pathname: R/RW/RWSTAUNER/Pod-Markdown-3.400.tar.gz provides: - Pod::Markdown 3.002 - Pod::Perldoc::ToMarkdown 3.002 + Pod::Markdown 3.400 + Pod::Perldoc::ToMarkdown 3.400 requirements: Encode 0 ExtUtils::MakeMaker 0 Getopt::Long 0 - Pod::Simple 3.26 + Pod::Simple 3.27 Pod::Simple::Methody 0 Pod::Usage 0 + URI::Escape 0 parent 0 perl 5.008 strict 0 warnings 0 - Pod-POM-0.29 - pathname: A/AN/ANDREWF/Pod-POM-0.29.tar.gz - provides: - Pod::POM 0.29 - Pod::POM::Constants 1.01 - Pod::POM::Node 1.05 - Pod::POM::Node::Begin undef - Pod::POM::Node::Code undef - Pod::POM::Node::Content undef - Pod::POM::Node::For undef - Pod::POM::Node::Head1 undef - Pod::POM::Node::Head2 undef - Pod::POM::Node::Head3 undef - Pod::POM::Node::Head4 undef - Pod::POM::Node::Item undef - Pod::POM::Node::Over undef - Pod::POM::Node::Pod undef - Pod::POM::Node::Sequence undef - Pod::POM::Node::Text undef - Pod::POM::Node::Verbatim undef - Pod::POM::Nodes 1.03 - Pod::POM::Test 1.01 - Pod::POM::View 1.04 - Pod::POM::View::HTML 1.06 - Pod::POM::View::Pod 1.03 - Pod::POM::View::Text 1.03 - requirements: - Encode 0 - ExtUtils::MakeMaker 6.59 - File::Slurp 0 - Test::More 0 - Text::Wrap 2001.0929 - parent 0 - perl 5.006 - Pod-Simple-3.29 - pathname: D/DW/DWHEELER/Pod-Simple-3.29.tar.gz - provides: - Pod::Simple 3.29 - Pod::Simple::BlackBox 3.29 - Pod::Simple::Checker 3.29 - Pod::Simple::Debug 3.29 - Pod::Simple::DumpAsText 3.29 - Pod::Simple::DumpAsXML 3.29 - Pod::Simple::HTML 3.29 - Pod::Simple::HTMLBatch 3.29 + Pod-Simple-3.45 + pathname: K/KH/KHW/Pod-Simple-3.45.tar.gz + provides: + Pod::Simple 3.45 + Pod::Simple::BlackBox 3.45 + Pod::Simple::Checker 3.45 + Pod::Simple::Debug 3.45 + Pod::Simple::DumpAsText 3.45 + Pod::Simple::DumpAsXML 3.45 + Pod::Simple::HTML 3.45 + Pod::Simple::HTMLBatch 3.45 Pod::Simple::HTMLLegacy 5.01 - Pod::Simple::LinkSection 3.29 - Pod::Simple::Methody 3.29 - Pod::Simple::Progress 3.29 - Pod::Simple::PullParser 3.29 - Pod::Simple::PullParserEndToken 3.29 - Pod::Simple::PullParserStartToken 3.29 - Pod::Simple::PullParserTextToken 3.29 - Pod::Simple::PullParserToken 3.29 - Pod::Simple::RTF 3.29 - Pod::Simple::Search 3.29 - Pod::Simple::SimpleTree 3.29 - Pod::Simple::Text 3.29 - Pod::Simple::TextContent 3.29 - Pod::Simple::TiedOutFH 3.29 - Pod::Simple::Transcode 3.29 - Pod::Simple::TranscodeDumb 3.29 - Pod::Simple::TranscodeSmart 3.29 - Pod::Simple::XHTML 3.29 - Pod::Simple::XMLOutStream 3.29 + Pod::Simple::JustPod undef + Pod::Simple::LinkSection 3.45 + Pod::Simple::Methody 3.45 + Pod::Simple::Progress 3.45 + Pod::Simple::PullParser 3.45 + Pod::Simple::PullParserEndToken 3.45 + Pod::Simple::PullParserStartToken 3.45 + Pod::Simple::PullParserTextToken 3.45 + Pod::Simple::PullParserToken 3.45 + Pod::Simple::RTF 3.45 + Pod::Simple::Search 3.45 + Pod::Simple::SimpleTree 3.45 + Pod::Simple::Text 3.45 + Pod::Simple::TextContent 3.45 + Pod::Simple::TiedOutFH 3.45 + Pod::Simple::Transcode 3.45 + Pod::Simple::TranscodeDumb 3.45 + Pod::Simple::TranscodeSmart 3.45 + Pod::Simple::XHTML 3.45 + Pod::Simple::XMLOutStream 3.45 requirements: Carp 0 Config 0 @@ -6684,631 +6190,849 @@ DISTRIBUTIONS File::Spec 0 Pod::Escapes 1.04 Symbol 0 - Test 1.25 - Test::More 0 Text::Wrap 98.112902 + if 0 integer 0 overload 0 strict 0 - Pod-Spell-1.15 - pathname: X/XE/XENO/Pod-Spell-1.15.tar.gz + Pod-Spell-1.27 + pathname: H/HA/HAARG/Pod-Spell-1.27.tar.gz provides: - Pod::Spell 1.15 - Pod::Wordlist 1.15 + Pod::Spell 1.27 + Pod::Wordlist 1.27 requirements: Carp 0 Class::Tiny 0 - ExtUtils::MakeMaker 6.30 - File::ShareDir::Install 0.03 - File::ShareDir::ProjectDistDir 1.000 + ExtUtils::MakeMaker 0 + File::ShareDir 0 + File::ShareDir::Install 0.06 Lingua::EN::Inflect 0 + POSIX 0 Pod::Escapes 0 - Pod::Parser 0 + Pod::Simple 3.27 Text::Wrap 0 - base 0 constant 0 locale 0 - strict 0 - warnings 0 - Probe-Perl-0.03 - pathname: K/KW/KWILLIAMS/Probe-Perl-0.03.tar.gz + parent 0 + perl 5.008001 + Readonly-2.05 + pathname: S/SA/SANKO/Readonly-2.05.tar.gz provides: - Probe::Perl 0.03 + Readonly 2.05 + Readonly::Array undef + Readonly::Hash undef + Readonly::Scalar undef requirements: - Config 0 - ExtUtils::MakeMaker 6.30 - File::Spec 0 - strict 0 - Readonly-1.04 - pathname: S/SA/SANKO/Readonly-1.04.tar.gz + Module::Build::Tiny 0.035 + perl 5.005 + Ref-Util-0.204 + pathname: A/AR/ARC/Ref-Util-0.204.tar.gz provides: - Readonly 1.04 - Readonly::Array 1.04 - Readonly::Hash 1.04 - Readonly::Scalar 1.04 + Ref::Util 0.204 + Ref::Util::PP 0.204 requirements: - CPAN::Meta 0 - CPAN::Meta::Prereqs 0 - ExtUtils::CBuilder 0 - Module::Build 0.38 + Exporter 5.57 + ExtUtils::MakeMaker 0 + Ref::Util::XS 0 + Text::ParseWords 0 perl 5.006 - Regexp-Common-2013031301 - pathname: A/AB/ABIGAIL/Regexp-Common-2013031301.tar.gz - provides: - Regexp::Common 2013031301 - Regexp::Common::CC 2010010201 - Regexp::Common::Entry 2013031301 - Regexp::Common::SEN 2010010201 - Regexp::Common::URI 2010010201 - Regexp::Common::URI::RFC1035 2010010201 - Regexp::Common::URI::RFC1738 2010010201 - Regexp::Common::URI::RFC1808 2010010201 - Regexp::Common::URI::RFC2384 2010010201 - Regexp::Common::URI::RFC2396 2010010201 - Regexp::Common::URI::RFC2806 2010010201 - Regexp::Common::URI::fax 2010010201 - Regexp::Common::URI::file 2010010201 - Regexp::Common::URI::ftp 2010010201 - Regexp::Common::URI::gopher 2010010201 - Regexp::Common::URI::http 2010010201 - Regexp::Common::URI::news 2010010201 - Regexp::Common::URI::pop 2010010201 - Regexp::Common::URI::prospero 2010010201 - Regexp::Common::URI::tel 2010010201 - Regexp::Common::URI::telnet 2010010201 - Regexp::Common::URI::tv 2010010201 - Regexp::Common::URI::wais 2010010201 - Regexp::Common::_support 2010010201 - Regexp::Common::balanced 2013030901 - Regexp::Common::comment 2010010201 - Regexp::Common::delimited 2010010201 - Regexp::Common::lingua 2010010201 - Regexp::Common::list 2010010201 - Regexp::Common::net 2013031301 - Regexp::Common::number 2013031101 - Regexp::Common::profanity 2010010201 - Regexp::Common::whitespace 2010010201 - Regexp::Common::zip 2010010201 - requirements: - ExtUtils::MakeMaker 0 - perl 5.00473 - strict 0 - vars 0 - Regexp-Common-time-0.05 - pathname: S/SZ/SZABGAB/Regexp-Common-time-0.05.tar.gz + Ref-Util-XS-0.117 + pathname: X/XS/XSAWYERX/Ref-Util-XS-0.117.tar.gz provides: - Regexp::Common::time 0.05 + Ref::Util::XS 0.117 requirements: - POSIX 0 - Regexp::Common 0 - Test::More 0.40 - Role-Tiny-1.003003 - pathname: H/HA/HAARG/Role-Tiny-1.003003.tar.gz + Exporter 5.57 + ExtUtils::MakeMaker 0 + XSLoader 0 + perl 5.006 + Role-Hooks-0.008 + pathname: T/TO/TOBYINK/Role-Hooks-0.008.tar.gz provides: - Role::Tiny 1.003003 - Role::Tiny::With 1.003003 + Role::Hooks 0.008 + requirements: + Class::Method::Modifiers 0 + ExtUtils::MakeMaker 6.17 + List::Util 1.45 + perl 5.008001 + Role-Tiny-2.002004 + pathname: H/HA/HAARG/Role-Tiny-2.002004.tar.gz + provides: + Role::Tiny 2.002004 + Role::Tiny::With 2.002004 requirements: Exporter 5.57 perl 5.006 - SQL-Abstract-1.80 - pathname: R/RI/RIBASUSHI/SQL-Abstract-1.80.tar.gz - provides: - DBIx::Class::Storage::Debug::PrettyPrint undef - SQL::Abstract 1.80 + SQL-Abstract-2.000001 + pathname: M/MS/MSTROUT/SQL-Abstract-2.000001.tar.gz + provides: + Chunkstrumenter undef + DBIx::Class::SQLMaker::Role::SQLA2Passthrough undef + SQL::Abstract 2.000001 + SQL::Abstract::Formatter undef + SQL::Abstract::Parts undef + SQL::Abstract::Plugin::BangOverrides undef + SQL::Abstract::Plugin::ExtraClauses undef + SQL::Abstract::Reference undef + SQL::Abstract::Role::Plugin undef SQL::Abstract::Test undef SQL::Abstract::Tree undef requirements: Exporter 5.57 - ExtUtils::MakeMaker 6.59 + ExtUtils::MakeMaker 0 Hash::Merge 0.12 List::Util 0 MRO::Compat 0.12 - Moo 1.004002 + Moo 2.000001 Scalar::Util 0 - Storable 0 + Sub::Quote 2.000001 + Test::Builder::Module 0.84 Test::Deep 0.101 - Test::Exception 0.31 - Test::More 0.88 - Test::Warn 0 + Text::Balanced 2.00 perl 5.006 - Safe-Isa-1.000004 - pathname: E/ET/ETHER/Safe-Isa-1.000004.tar.gz + SQL-Abstract-Pg-1.0 + pathname: S/SR/SRI/SQL-Abstract-Pg-1.0.tar.gz provides: - Safe::Isa 1.000004 + SQL::Abstract::Pg 1.0 + requirements: + ExtUtils::MakeMaker 0 + SQL::Abstract 2.0 + perl 5.016 + Safe-Isa-1.000010 + pathname: E/ET/ETHER/Safe-Isa-1.000010.tar.gz + provides: + Safe::Isa 1.000010 requirements: Exporter 5.57 ExtUtils::MakeMaker 0 Scalar::Util 0 - Scalar-List-Utils-1.41 - pathname: P/PE/PEVANS/Scalar-List-Utils-1.41.tar.gz + perl 5.006 + Scalar-List-Utils-1.69 + pathname: P/PE/PEVANS/Scalar-List-Utils-1.69.tar.gz provides: - List::Util 1.41 - List::Util::XS 1.41 - Scalar::Util 1.41 - Sub::Util 1.41 + List::Util 1.69 + List::Util::XS 1.69 + Scalar::List::Utils 1.69 + Scalar::Util 1.69 + Sub::Util 1.69 requirements: ExtUtils::MakeMaker 0 - Test::More 0 - Scope-Guard-0.20 - pathname: C/CH/CHOCOLATE/Scope-Guard-0.20.tar.gz + perl 5.006 + Scope-Guard-0.21 + pathname: C/CH/CHOCOLATE/Scope-Guard-0.21.tar.gz provides: - Scope::Guard 0.20 + Scope::Guard 0.21 requirements: ExtUtils::MakeMaker 0 Test::More 0 perl 5.006001 - Sort-Naturally-1.03 - pathname: B/BI/BINGOS/Sort-Naturally-1.03.tar.gz + Search-Elasticsearch-8.12 + pathname: E/EZ/EZIMUEL/Search-Elasticsearch-8.12.tar.gz + provides: + Search::Elasticsearch 8.12 + Search::Elasticsearch::Client::8_0 8.12 + Search::Elasticsearch::Client::8_0::Bulk 8.12 + Search::Elasticsearch::Client::8_0::Direct 8.12 + Search::Elasticsearch::Client::8_0::Direct::Autoscaling 8.12 + Search::Elasticsearch::Client::8_0::Direct::CCR 8.12 + Search::Elasticsearch::Client::8_0::Direct::Cat 8.12 + Search::Elasticsearch::Client::8_0::Direct::Cluster 8.12 + Search::Elasticsearch::Client::8_0::Direct::Connector 8.12 + Search::Elasticsearch::Client::8_0::Direct::ConnectorSyncJob 8.12 + Search::Elasticsearch::Client::8_0::Direct::DanglingIndices 8.12 + Search::Elasticsearch::Client::8_0::Direct::Enrich 8.12 + Search::Elasticsearch::Client::8_0::Direct::Eql 8.12 + Search::Elasticsearch::Client::8_0::Direct::Esql 8.12 + Search::Elasticsearch::Client::8_0::Direct::Features 8.12 + Search::Elasticsearch::Client::8_0::Direct::Fleet 8.12 + Search::Elasticsearch::Client::8_0::Direct::Graph 8.12 + Search::Elasticsearch::Client::8_0::Direct::ILM 8.12 + Search::Elasticsearch::Client::8_0::Direct::Indices 8.12 + Search::Elasticsearch::Client::8_0::Direct::Inference 8.12 + Search::Elasticsearch::Client::8_0::Direct::Ingest 8.12 + Search::Elasticsearch::Client::8_0::Direct::License 8.12 + Search::Elasticsearch::Client::8_0::Direct::Logstash 8.12 + Search::Elasticsearch::Client::8_0::Direct::ML 8.12 + Search::Elasticsearch::Client::8_0::Direct::Migration 8.12 + Search::Elasticsearch::Client::8_0::Direct::Monitoring 8.12 + Search::Elasticsearch::Client::8_0::Direct::Nodes 8.12 + Search::Elasticsearch::Client::8_0::Direct::Profiling 8.12 + Search::Elasticsearch::Client::8_0::Direct::QueryRuleset 8.12 + Search::Elasticsearch::Client::8_0::Direct::Rollup 8.12 + Search::Elasticsearch::Client::8_0::Direct::SQL 8.12 + Search::Elasticsearch::Client::8_0::Direct::SSL 8.12 + Search::Elasticsearch::Client::8_0::Direct::SearchApplication 8.12 + Search::Elasticsearch::Client::8_0::Direct::SearchableSnapshots 8.12 + Search::Elasticsearch::Client::8_0::Direct::Security 8.12 + Search::Elasticsearch::Client::8_0::Direct::Shutdown 8.12 + Search::Elasticsearch::Client::8_0::Direct::Simulate 8.12 + Search::Elasticsearch::Client::8_0::Direct::Slm 8.12 + Search::Elasticsearch::Client::8_0::Direct::Snapshot 8.12 + Search::Elasticsearch::Client::8_0::Direct::Synonyms 8.12 + Search::Elasticsearch::Client::8_0::Direct::Tasks 8.12 + Search::Elasticsearch::Client::8_0::Direct::TextStructure 8.12 + Search::Elasticsearch::Client::8_0::Direct::Transform 8.12 + Search::Elasticsearch::Client::8_0::Direct::Watcher 8.12 + Search::Elasticsearch::Client::8_0::Direct::XPack 8.12 + Search::Elasticsearch::Client::8_0::Role::API 8.12 + Search::Elasticsearch::Client::8_0::Role::Bulk 8.12 + Search::Elasticsearch::Client::8_0::Role::Scroll 8.12 + Search::Elasticsearch::Client::8_0::Scroll 8.12 + Search::Elasticsearch::Client::8_0::TestServer 8.12 + Search::Elasticsearch::Cxn::Factory 8.12 + Search::Elasticsearch::Cxn::HTTPTiny 8.12 + Search::Elasticsearch::Cxn::LWP 8.12 + Search::Elasticsearch::CxnPool::Sniff 8.12 + Search::Elasticsearch::CxnPool::Static 8.12 + Search::Elasticsearch::CxnPool::Static::NoPing 8.12 + Search::Elasticsearch::Error 8.12 + Search::Elasticsearch::Logger::LogAny 8.12 + Search::Elasticsearch::Role::API 8.12 + Search::Elasticsearch::Role::Client 8.12 + Search::Elasticsearch::Role::Client::Direct 8.12 + Search::Elasticsearch::Role::Cxn 8.12 + Search::Elasticsearch::Role::CxnPool 8.12 + Search::Elasticsearch::Role::CxnPool::Sniff 8.12 + Search::Elasticsearch::Role::CxnPool::Static 8.12 + Search::Elasticsearch::Role::CxnPool::Static::NoPing 8.12 + Search::Elasticsearch::Role::Is_Sync 8.12 + Search::Elasticsearch::Role::Logger 8.12 + Search::Elasticsearch::Role::Serializer 8.12 + Search::Elasticsearch::Role::Serializer::JSON 8.12 + Search::Elasticsearch::Role::Transport 8.12 + Search::Elasticsearch::Serializer::JSON 8.12 + Search::Elasticsearch::Serializer::JSON::Cpanel 8.12 + Search::Elasticsearch::Serializer::JSON::PP 8.12 + Search::Elasticsearch::Serializer::JSON::XS 8.12 + Search::Elasticsearch::TestServer 8.12 + Search::Elasticsearch::Transport 8.12 + Search::Elasticsearch::Util 8.12 + requirements: + Any::URI::Escape 0 + Data::Dumper 0 + Devel::GlobalDestruction 0 + Encode 0 + ExtUtils::MakeMaker 0 + File::Temp 0 + HTTP::Headers 0 + HTTP::Request 0 + HTTP::Tiny 0.076 + IO::Compress::Deflate 0 + IO::Compress::Gzip 0 + IO::Select 0 + IO::Socket 0 + IO::Uncompress::Gunzip 0 + IO::Uncompress::Inflate 0 + JSON::MaybeXS 1.002002 + JSON::PP 0 + LWP::UserAgent 0 + List::Util 0 + Log::Any 1.02 + Log::Any::Adapter 0 + MIME::Base64 0 + Module::Runtime 0 + Moo 2.001000 + Moo::Role 0 + Net::IP 0 + POSIX 0 + Package::Stash 0.34 + Scalar::Util 0 + Sub::Exporter 0 + Time::HiRes 0 + Try::Tiny 0 + URI 0 + namespace::clean 0 + overload 0 + strict 0 + warnings 0 + Search-Elasticsearch-Client-2_0-6.81 + pathname: E/EZ/EZIMUEL/Search-Elasticsearch-Client-2_0-6.81.tar.gz + provides: + Search::Elasticsearch::Client::2_0 6.81 + Search::Elasticsearch::Client::2_0::Bulk 6.81 + Search::Elasticsearch::Client::2_0::Direct 6.81 + Search::Elasticsearch::Client::2_0::Direct::Cat 6.81 + Search::Elasticsearch::Client::2_0::Direct::Cluster 6.81 + Search::Elasticsearch::Client::2_0::Direct::Indices 6.81 + Search::Elasticsearch::Client::2_0::Direct::Nodes 6.81 + Search::Elasticsearch::Client::2_0::Direct::Snapshot 6.81 + Search::Elasticsearch::Client::2_0::Direct::Tasks 6.81 + Search::Elasticsearch::Client::2_0::Role::API 6.81 + Search::Elasticsearch::Client::2_0::Role::Bulk 6.81 + Search::Elasticsearch::Client::2_0::Role::Scroll 6.81 + Search::Elasticsearch::Client::2_0::Scroll 6.81 + Search::Elasticsearch::Client::2_0::TestServer 6.81 + requirements: + Devel::GlobalDestruction 0 + ExtUtils::MakeMaker 0 + Moo 0 + Moo::Role 0 + Search::Elasticsearch 6.00 + Search::Elasticsearch::Role::API 0 + Search::Elasticsearch::Role::Client::Direct 0 + Search::Elasticsearch::Role::Is_Sync 0 + Search::Elasticsearch::Util 0 + Try::Tiny 0 + namespace::clean 0 + strict 0 + warnings 0 + Sereal-Decoder-5.004 + pathname: Y/YV/YVES/Sereal-Decoder-5.004.tar.gz + provides: + Sereal::Decoder 5.004 + Sereal::Decoder::Constants 5.004 + Sereal::Performance undef + requirements: + Data::Dumper 0 + Devel::CheckLib 1.16 + ExtUtils::MakeMaker 7.0 + ExtUtils::ParseXS 2.21 + File::Find 0 + File::Path 0 + File::Spec 0 + Scalar::Util 0 + Test::Deep 0 + Test::Differences 0 + Test::LongString 0 + Test::More 0.88 + Test::Warn 0 + XSLoader 0 + perl 5.008 + Sereal-Encoder-5.004 + pathname: Y/YV/YVES/Sereal-Encoder-5.004.tar.gz provides: - Sort::Naturally 1.03 + Sereal::Encoder 5.004 + Sereal::Encoder::Constants 5.004 requirements: + Data::Dumper 0 + Devel::CheckLib 1.16 + ExtUtils::MakeMaker 7.0 + ExtUtils::ParseXS 2.21 + File::Find 0 + File::Path 0 + File::Spec 0 + Hash::Util 0 + Scalar::Util 0 + Sereal::Decoder 5.004 + Test::Deep 0 + Test::Differences 0 + Test::LongString 0 + Test::More 0.88 + Test::Warn 0 + XSLoader 0 + perl 5.008 + Sort-Versions-1.62 + pathname: N/NE/NEILB/Sort-Versions-1.62.tar.gz + provides: + Sort::Versions 1.62 + requirements: + Exporter 0 + ExtUtils::MakeMaker 0 + perl 5.006 + strict 0 + warnings 0 + Specio-0.50 + pathname: D/DR/DROLSKY/Specio-0.50.tar.gz + provides: + Specio 0.50 + Specio::Coercion 0.50 + Specio::Constraint::AnyCan 0.50 + Specio::Constraint::AnyDoes 0.50 + Specio::Constraint::AnyIsa 0.50 + Specio::Constraint::Enum 0.50 + Specio::Constraint::Intersection 0.50 + Specio::Constraint::ObjectCan 0.50 + Specio::Constraint::ObjectDoes 0.50 + Specio::Constraint::ObjectIsa 0.50 + Specio::Constraint::Parameterizable 0.50 + Specio::Constraint::Parameterized 0.50 + Specio::Constraint::Role::CanType 0.50 + Specio::Constraint::Role::DoesType 0.50 + Specio::Constraint::Role::Interface 0.50 + Specio::Constraint::Role::IsaType 0.50 + Specio::Constraint::Simple 0.50 + Specio::Constraint::Structurable 0.50 + Specio::Constraint::Structured 0.50 + Specio::Constraint::Union 0.50 + Specio::Declare 0.50 + Specio::DeclaredAt 0.50 + Specio::Exception 0.50 + Specio::Exporter 0.50 + Specio::Helpers 0.50 + Specio::Library::Builtins 0.50 + Specio::Library::Numeric 0.50 + Specio::Library::Perl 0.50 + Specio::Library::String 0.50 + Specio::Library::Structured 0.50 + Specio::Library::Structured::Dict 0.50 + Specio::Library::Structured::Map 0.50 + Specio::Library::Structured::Tuple 0.50 + Specio::OO 0.50 + Specio::PartialDump 0.50 + Specio::Registry 0.50 + Specio::Role::Inlinable 0.50 + Specio::Subs 0.50 + Specio::TypeChecks 0.50 + Test::Specio 0.50 + requirements: + B 0 + Carp 0 + Clone 0 + Devel::StackTrace 0 + Eval::Closure 0 + Exporter 0 ExtUtils::MakeMaker 0 - perl 5 - Sort-Versions-1.5 - pathname: E/ED/EDAVIS/Sort-Versions-1.5.tar.gz + IO::File 0 + List::Util 1.33 + MRO::Compat 0 + Module::Runtime 0 + Role::Tiny 1.003003 + Role::Tiny::With 0 + Scalar::Util 0 + Sub::Quote 0 + Test::Fatal 0 + Test::More 0.96 + Try::Tiny 0 + XString 0 + overload 0 + parent 0 + perl 5.008 + re 0 + strict 0 + version 0.83 + warnings 0 + Specio-Library-Path-Tiny-0.05 + pathname: D/DR/DROLSKY/Specio-Library-Path-Tiny-0.05.tar.gz provides: - Sort::Versions 1.5 + Specio::Library::Path::Tiny 0.05 requirements: ExtUtils::MakeMaker 0 - Starman-0.4009 - pathname: M/MI/MIYAGAWA/Starman-0.4009.tar.gz - provides: - HTTP::Server::PSGI::Net::Server::PreFork undef - Plack::Handler::Starman undef - Starman 0.4009 - Starman::Server undef - requirements: - Data::Dump 0 - HTTP::Date 0 - HTTP::Parser::XS 0 - HTTP::Status 0 - Module::Build::Tiny 0.035 - Net::Server 2.007 - Plack 0.9971 - Test::TCP 2.00 + Path::Tiny 0.087 + Scalar::Util 0 + Specio 0.29 + Specio::Declare 0 + Specio::Exporter 0 + Specio::Library::Builtins 0 + Specio::PartialDump 0 + overload 0 parent 0 - perl 5.008001 - Stream-Buffered-0.02 - pathname: D/DO/DOY/Stream-Buffered-0.02.tar.gz + strict 0 + warnings 0 + Stream-Buffered-0.03 + pathname: D/DO/DOY/Stream-Buffered-0.03.tar.gz provides: - Stream::Buffered 0.02 + Stream::Buffered 0.03 Stream::Buffered::Auto undef Stream::Buffered::File undef Stream::Buffered::PerlIO undef requirements: - ExtUtils::MakeMaker 6.36 - String-Format-1.17 - pathname: D/DA/DARREN/String-Format-1.17.tar.gz + ExtUtils::MakeMaker 6.30 + IO::File 1.14 + String-Format-1.18 + pathname: S/SR/SREZIC/String-Format-1.18.tar.gz provides: - String::Format 1.17 + String::Format 1.18 requirements: ExtUtils::MakeMaker 0 Test::More 0 - String-RewritePrefix-0.007 - pathname: R/RJ/RJBS/String-RewritePrefix-0.007.tar.gz + String-RewritePrefix-0.009 + pathname: R/RJ/RJBS/String-RewritePrefix-0.009.tar.gz provides: - String::RewritePrefix 0.007 + String::RewritePrefix 0.009 requirements: Carp 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 6.78 Sub::Exporter 0.972 + perl 5.012 strict 0 warnings 0 - Sub-Exporter-0.987 - pathname: R/RJ/RJBS/Sub-Exporter-0.987.tar.gz + Sub-Exporter-0.991 + pathname: R/RJ/RJBS/Sub-Exporter-0.991.tar.gz provides: - Sub::Exporter 0.987 - Sub::Exporter::Util 0.987 - Test::SubExporter::DashSetup undef - Test::SubExporter::Faux undef - Test::SubExporter::GroupGen undef - Test::SubExporter::GroupGenSubclass undef - Test::SubExporter::ObjGen undef - Test::SubExporter::ObjGen::Obj undef - Test::SubExporter::s_e undef + Sub::Exporter 0.991 + Sub::Exporter::Util 0.991 requirements: Carp 0 Data::OptList 0.100 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 6.78 Params::Util 0.14 Sub::Install 0.92 + perl 5.012 strict 0 warnings 0 - Sub-Exporter-Progressive-0.001011 - pathname: F/FR/FREW/Sub-Exporter-Progressive-0.001011.tar.gz + Sub-Exporter-ForMethods-0.100055 + pathname: R/RJ/RJBS/Sub-Exporter-ForMethods-0.100055.tar.gz provides: - Sub::Exporter::Progressive 0.001011 + Sub::Exporter::ForMethods 0.100055 requirements: - ExtUtils::MakeMaker 0 - Test::More 0.88 - Sub-Install-0.927 - pathname: R/RJ/RJBS/Sub-Install-0.927.tar.gz + ExtUtils::MakeMaker 6.78 + Scalar::Util 0 + Sub::Exporter 0.978 + Sub::Util 0 + perl 5.012 + strict 0 + warnings 0 + Sub-Exporter-Progressive-0.001013 + pathname: F/FR/FREW/Sub-Exporter-Progressive-0.001013.tar.gz + provides: + Sub::Exporter::Progressive 0.001013 + requirements: + ExtUtils::MakeMaker 0 + Sub-HandlesVia-0.050002 + pathname: T/TO/TOBYINK/Sub-HandlesVia-0.050002.tar.gz + provides: + Sub::HandlesVia 0.050002 + Sub::HandlesVia::CodeGenerator 0.050002 + Sub::HandlesVia::Declare 0.050002 + Sub::HandlesVia::Handler 0.050002 + Sub::HandlesVia::Handler::CodeRef 0.050002 + Sub::HandlesVia::Handler::Traditional 0.050002 + Sub::HandlesVia::HandlerLibrary 0.050002 + Sub::HandlesVia::HandlerLibrary::Array 0.050002 + Sub::HandlesVia::HandlerLibrary::Blessed 0.050002 + Sub::HandlesVia::HandlerLibrary::Bool 0.050002 + Sub::HandlesVia::HandlerLibrary::Code 0.050002 + Sub::HandlesVia::HandlerLibrary::Counter 0.050002 + Sub::HandlesVia::HandlerLibrary::Enum 0.050002 + Sub::HandlesVia::HandlerLibrary::Hash 0.050002 + Sub::HandlesVia::HandlerLibrary::Number 0.050002 + Sub::HandlesVia::HandlerLibrary::Scalar 0.050002 + Sub::HandlesVia::HandlerLibrary::String 0.050002 + Sub::HandlesVia::Mite undef + Sub::HandlesVia::Toolkit 0.050002 + Sub::HandlesVia::Toolkit::Mite 0.050002 + Sub::HandlesVia::Toolkit::Moo 0.050002 + Sub::HandlesVia::Toolkit::Moose 0.050002 + Sub::HandlesVia::Toolkit::Moose::PackageTrait 0.050002 + Sub::HandlesVia::Toolkit::Moose::RoleTrait 0.050002 + Sub::HandlesVia::Toolkit::Mouse 0.050002 + Sub::HandlesVia::Toolkit::Mouse::PackageTrait 0.050002 + Sub::HandlesVia::Toolkit::Mouse::RoleTrait 0.050002 + Sub::HandlesVia::Toolkit::ObjectPad 0.050002 + Sub::HandlesVia::Toolkit::Plain 0.050002 + requirements: + Class::Method::Modifiers 0 + Exporter::Shiny 0 + ExtUtils::MakeMaker 6.17 + List::Util 1.54 + Role::Hooks 0.008 + Role::Tiny 0 + Type::Tiny 1.004 + perl 5.008001 + Sub-Install-0.929 + pathname: R/RJ/RJBS/Sub-Install-0.929.tar.gz provides: - Sub::Install 0.927 + Sub::Install 0.929 requirements: B 0 Carp 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 6.78 Scalar::Util 0 + perl 5.008000 strict 0 warnings 0 - Sub-Name-0.05 - pathname: F/FL/FLORA/Sub-Name-0.05.tar.gz + Sub-Quote-2.006008 + pathname: H/HA/HAARG/Sub-Quote-2.006008.tar.gz provides: - Sub::Name 0.05 + Sub::Defer 2.006008 + Sub::Quote 2.006008 requirements: ExtUtils::MakeMaker 0 - Sub-Override-0.09 - pathname: O/OV/OVID/Sub-Override-0.09.tar.gz + Scalar::Util 0 + perl 5.006 + Sub-Uplevel-0.2800 + pathname: D/DA/DAGOLDEN/Sub-Uplevel-0.2800.tar.gz + provides: + Sub::Uplevel 0.2800 + requirements: + Carp 0 + ExtUtils::MakeMaker 6.17 + constant 0 + perl 5.006 + strict 0 + warnings 0 + Symbol-Get-0.12 + pathname: F/FE/FELIPE/Symbol-Get-0.12.tar.gz provides: - Sub::Override 0.09 + Symbol::Get 0.12 requirements: + Call::Context 0 ExtUtils::MakeMaker 0 - Test::Fatal 0.010 - Test::More 0.47 - Sub-Uplevel-0.24 - pathname: D/DA/DAGOLDEN/Sub-Uplevel-0.24.tar.gz + TOML-Tiny-0.20 + pathname: O/OA/OALDERS/TOML-Tiny-0.20.tar.gz provides: - Sub::Uplevel 0.24 + TOML::Tiny 0.20 + TOML::Tiny::Grammar 0.20 + TOML::Tiny::Parser 0.20 + TOML::Tiny::Tokenizer 0.20 + TOML::Tiny::Util 0.20 + TOML::Tiny::Writer 0.20 requirements: Carp 0 + Data::Dumper 0 + Encode 0 Exporter 0 - ExtUtils::MakeMaker 6.30 - File::Find 0 - File::Temp 0 - Test::More 0 - constant 0 - strict 0 - warnings 0 - Task-Weaken-1.04 - pathname: A/AD/ADAMK/Task-Weaken-1.04.tar.gz + ExtUtils::MakeMaker 0 + Math::BigInt 1.999718 + perl 5.018 + Task-Weaken-1.06 + pathname: E/ET/ETHER/Task-Weaken-1.06.tar.gz provides: - Task::Weaken 1.04 + Task::Weaken 1.06 requirements: - ExtUtils::MakeMaker 6.42 - File::Spec 0.80 + Config 0 + ExtUtils::MakeMaker 0 + File::Spec 0 Scalar::Util 1.14 - Test::More 0.42 - perl 5.005 - Test-Aggregate-0.371 - pathname: R/RW/RWSTAUNER/Test-Aggregate-0.371.tar.gz - provides: - Test::Aggregate 0.371 - Test::Aggregate::Base 0.371 - Test::Aggregate::Builder 0.371 - Test::Aggregate::Nested 0.371 - requirements: - FindBin 1.47 - Test::Harness 3.09 - Test::Most 0.21 - Test::NoWarnings 0 - Test::Simple 0.94 - Test::Trap 0 - Test-CheckDeps-0.010 - pathname: L/LE/LEONT/Test-CheckDeps-0.010.tar.gz - provides: - Test::CheckDeps 0.010 - requirements: - CPAN::Meta 2.120920 - CPAN::Meta::Check 0.007 - Exporter 5.57 - ExtUtils::MakeMaker 6.30 - List::Util 0 - Test::Builder 0 + perl 5.006 strict 0 - warnings 0 - Test-Compile-v1.2.0 - pathname: E/EG/EGILES/Test-Compile-v1.2.0.tar.gz + Term-Size-Any-0.002 + pathname: F/FE/FERREIRA/Term-Size-Any-0.002.tar.gz provides: - Test::Compile 1.002000 - Test::Compile::Internal 1.002000 - requirements: - Module::Build 0.38 - UNIVERSAL::require 0 - perl v5.6.2 - version 0 - Test-Deep-0.112 - pathname: R/RJ/RJBS/Test-Deep-0.112.tar.gz - provides: - Test::Deep 0.112 - Test::Deep::All undef - Test::Deep::Any undef - Test::Deep::Array undef - Test::Deep::ArrayEach undef - Test::Deep::ArrayElementsOnly undef - Test::Deep::ArrayLength undef - Test::Deep::ArrayLengthOnly undef - Test::Deep::Blessed undef - Test::Deep::Boolean undef - Test::Deep::Cache undef - Test::Deep::Cache::Simple undef - Test::Deep::Class undef - Test::Deep::Cmp undef - Test::Deep::Code undef - Test::Deep::Hash undef - Test::Deep::HashEach undef - Test::Deep::HashElements undef - Test::Deep::HashKeys undef - Test::Deep::HashKeysOnly undef - Test::Deep::Ignore undef - Test::Deep::Isa undef - Test::Deep::ListMethods undef - Test::Deep::MM undef - Test::Deep::Methods undef - Test::Deep::NoTest undef - Test::Deep::Number undef - Test::Deep::Obj undef - Test::Deep::Ref undef - Test::Deep::RefType undef - Test::Deep::Regexp undef - Test::Deep::RegexpMatches undef - Test::Deep::RegexpRef undef - Test::Deep::RegexpRefOnly undef - Test::Deep::RegexpVersion undef - Test::Deep::ScalarRef undef - Test::Deep::ScalarRefOnly undef - Test::Deep::Set undef - Test::Deep::Shallow undef - Test::Deep::Stack undef - Test::Deep::String undef - Test::Deep::SubHash undef - Test::Deep::SubHashElements undef - Test::Deep::SubHashKeys undef - Test::Deep::SubHashKeysOnly undef - Test::Deep::SuperHash undef - Test::Deep::SuperHashElements undef - Test::Deep::SuperHashKeys undef - Test::Deep::SuperHashKeysOnly undef + Term::Size::Any 0.002 requirements: + Devel::Hide 0 ExtUtils::MakeMaker 0 - List::Util 1.09 - Scalar::Util 1.09 + Module::Load::Conditional 0 + Term::Size::Perl 0 Test::More 0 - Test::NoWarnings 0.02 - Test::Tester 0.04 - Test-Differences-0.61 - pathname: O/OV/OVID/Test-Differences-0.61.tar.gz + Term-Size-Perl-0.031 + pathname: F/FE/FERREIRA/Term-Size-Perl-0.031.tar.gz provides: - Test::Differences 0.61 + Term::Size::Perl 0.031 requirements: - Data::Dumper 2.126 - Test::More 0 - Text::Diff 0.35 - Test-Exception-0.32 - pathname: A/AD/ADIE/Test-Exception-0.32.tar.gz + Exporter 0 + ExtUtils::CBuilder 0 + ExtUtils::MakeMaker 0 + Term-Table-0.024 + pathname: E/EX/EXODIST/Term-Table-0.024.tar.gz provides: - Test::Exception 0.32 + Term::Table 0.024 + Term::Table::Cell 0.024 + Term::Table::CellStack 0.024 + Term::Table::HashBase 0.024 + Term::Table::LineBreak 0.024 + Term::Table::Spacer 0.024 + Term::Table::Util 0.024 requirements: - Sub::Uplevel 0.18 - Test::Builder 0.7 - Test::Builder::Tester 1.07 - Test::Harness 2.03 - Test::More 0.7 - Test::Simple 0.7 - Test-Fatal-0.013 - pathname: R/RJ/RJBS/Test-Fatal-0.013.tar.gz + Carp 0 + ExtUtils::MakeMaker 0 + List::Util 0 + Scalar::Util 0 + perl 5.008001 + Test-Abortable-0.003 + pathname: R/RJ/RJBS/Test-Abortable-0.003.tar.gz provides: - Test::Fatal 0.013 + Test::Abortable 0.003 requirements: - Carp 0 - Exporter 5.57 - ExtUtils::MakeMaker 6.30 - Test::Builder 0 - Try::Tiny 0.07 + ExtUtils::MakeMaker 6.78 + Sub::Exporter 0 + Test2::API 1.302075 + perl 5.012 strict 0 warnings 0 - Test-HTTP-Server-Simple-0.11 - pathname: A/AL/ALEXMV/Test-HTTP-Server-Simple-0.11.tar.gz - provides: - Test::HTTP::Server::Simple 0.11 - requirements: - ExtUtils::MakeMaker 0 - HTTP::Server::Simple 0 - NEXT 0 + Test-Deep-1.205 + pathname: R/RJ/RJBS/Test-Deep-1.205.tar.gz + provides: + Test::Deep 1.205 + Test::Deep::All 1.205 + Test::Deep::Any 1.205 + Test::Deep::Array 1.205 + Test::Deep::ArrayEach 1.205 + Test::Deep::ArrayElementsOnly 1.205 + Test::Deep::ArrayLength 1.205 + Test::Deep::ArrayLengthOnly 1.205 + Test::Deep::Blessed 1.205 + Test::Deep::Boolean 1.205 + Test::Deep::Cache 1.205 + Test::Deep::Cache::Simple 1.205 + Test::Deep::Class 1.205 + Test::Deep::Cmp 1.205 + Test::Deep::Code 1.205 + Test::Deep::Hash 1.205 + Test::Deep::HashEach 1.205 + Test::Deep::HashElements 1.205 + Test::Deep::HashKeys 1.205 + Test::Deep::HashKeysOnly 1.205 + Test::Deep::Ignore 1.205 + Test::Deep::Isa 1.205 + Test::Deep::ListMethods 1.205 + Test::Deep::MM 1.205 + Test::Deep::Methods 1.205 + Test::Deep::NoTest 1.205 + Test::Deep::None 1.205 + Test::Deep::Number 1.205 + Test::Deep::Obj 1.205 + Test::Deep::Ref 1.205 + Test::Deep::RefType 1.205 + Test::Deep::Regexp 1.205 + Test::Deep::RegexpMatches 1.205 + Test::Deep::RegexpOnly 1.205 + Test::Deep::RegexpRef 1.205 + Test::Deep::RegexpRefOnly 1.205 + Test::Deep::RegexpVersion 1.205 + Test::Deep::ScalarRef 1.205 + Test::Deep::ScalarRefOnly 1.205 + Test::Deep::Set 1.205 + Test::Deep::Shallow 1.205 + Test::Deep::Stack 1.205 + Test::Deep::String 1.205 + Test::Deep::SubHash 1.205 + Test::Deep::SubHashElements 1.205 + Test::Deep::SubHashKeys 1.205 + Test::Deep::SubHashKeysOnly 1.205 + Test::Deep::SuperHash 1.205 + Test::Deep::SuperHashElements 1.205 + Test::Deep::SuperHashKeys 1.205 + Test::Deep::SuperHashKeysOnly 1.205 + requirements: + ExtUtils::MakeMaker 6.78 + List::Util 1.09 + Scalar::Util 1.09 Test::Builder 0 - Test::Builder::Tester 1.04 - Test::More 0 - Test-Harness-3.30 - pathname: L/LE/LEONT/Test-Harness-3.30.tar.gz - provides: - App::Prove 3.30 - App::Prove::State 3.30 - App::Prove::State::Result 3.30 - App::Prove::State::Result::Test 3.30 - TAP::Base 3.30 - TAP::Formatter::Base 3.30 - TAP::Formatter::Color 3.30 - TAP::Formatter::Console 3.30 - TAP::Formatter::Console::ParallelSession 3.30 - TAP::Formatter::Console::Session 3.30 - TAP::Formatter::File 3.30 - TAP::Formatter::File::Session 3.30 - TAP::Formatter::Session 3.30 - TAP::Harness 3.30 - TAP::Harness::Env 3.30 - TAP::Object 3.30 - TAP::Parser 3.30 - TAP::Parser::Aggregator 3.30 - TAP::Parser::Grammar 3.30 - TAP::Parser::Iterator 3.30 - TAP::Parser::Iterator::Array 3.30 - TAP::Parser::Iterator::Process 3.30 - TAP::Parser::Iterator::Stream 3.30 - TAP::Parser::IteratorFactory 3.30 - TAP::Parser::Multiplexer 3.30 - TAP::Parser::Result 3.30 - TAP::Parser::Result::Bailout 3.30 - TAP::Parser::Result::Comment 3.30 - TAP::Parser::Result::Plan 3.30 - TAP::Parser::Result::Pragma 3.30 - TAP::Parser::Result::Test 3.30 - TAP::Parser::Result::Unknown 3.30 - TAP::Parser::Result::Version 3.30 - TAP::Parser::Result::YAML 3.30 - TAP::Parser::ResultFactory 3.30 - TAP::Parser::Scheduler 3.30 - TAP::Parser::Scheduler::Job 3.30 - TAP::Parser::Scheduler::Spinner 3.30 - TAP::Parser::Source 3.30 - TAP::Parser::SourceHandler 3.30 - TAP::Parser::SourceHandler::Executable 3.30 - TAP::Parser::SourceHandler::File 3.30 - TAP::Parser::SourceHandler::Handle 3.30 - TAP::Parser::SourceHandler::Perl 3.30 - TAP::Parser::SourceHandler::RawTAP 3.30 - TAP::Parser::YAMLish::Reader 3.30 - TAP::Parser::YAMLish::Writer 3.30 - Test::Harness 3.30 - requirements: - ExtUtils::MakeMaker 0 - Test-LongString-0.15 - pathname: R/RG/RGARCIA/Test-LongString-0.15.tar.gz - provides: - Test::LongString 0.15 - requirements: - ExtUtils::MakeMaker 0 - Test::Builder 0.12 - Test::Builder::Tester 1.04 - Test-Most-0.33 - pathname: O/OV/OVID/Test-Most-0.33.tar.gz + Test::More 0.96 + perl 5.012 + Test-Differences-0.71 + pathname: D/DC/DCANTRELL/Test-Differences-0.71.tar.gz provides: - Test::Most 0.33 - Test::Most::Exception 0.33 + Test::Differences 0.71 requirements: - Exception::Class 1.14 + Capture::Tiny 0.24 + Data::Dumper 2.126 ExtUtils::MakeMaker 0 - Test::Deep 0.106 - Test::Differences 0.61 - Test::Exception 0.31 - Test::Harness 3.21 Test::More 0.88 - Test::Warn 0.23 - Test-NoWarnings-1.04 - pathname: A/AD/ADAMK/Test-NoWarnings-1.04.tar.gz - provides: - Test::NoWarnings 1.04 - Test::NoWarnings::Warning 1.04 - requirements: - ExtUtils::MakeMaker 0 - Test::Builder 0.86 - Test::More 0.47 - Test::Tester 0.107 - perl 5.006 - Test-Object-0.07 - pathname: A/AD/ADAMK/Test-Object-0.07.tar.gz + Text::Diff 1.43 + Test-Fatal-0.017 + pathname: R/RJ/RJBS/Test-Fatal-0.017.tar.gz provides: - Test::Object 0.07 - Test::Object::Test 0.07 + Test::Fatal 0.017 requirements: Carp 0 - Exporter 0 - ExtUtils::MakeMaker 0 - File::Spec 0.80 - Scalar::Util 1.16 - Test::Builder 0.33 - Test::Builder::Tester 1.02 - Test::More 0.42 - overload 0 - Test-OpenID-Consumer-0.01 - pathname: J/JE/JESSE/Test-OpenID-Consumer-0.01.tar.gz - provides: - Test::OpenID::Consumer 0.01 + Exporter 5.57 + ExtUtils::MakeMaker 6.78 + Test::Builder 0 + Try::Tiny 0.07 + strict 0 + warnings 0 + Test-Harness-3.50 + pathname: L/LE/LEONT/Test-Harness-3.50.tar.gz + provides: + App::Prove 3.50 + App::Prove::State 3.50 + App::Prove::State::Result 3.50 + App::Prove::State::Result::Test 3.50 + Harness::Hook undef + TAP::Base 3.50 + TAP::Formatter::Base 3.50 + TAP::Formatter::Color 3.50 + TAP::Formatter::Console 3.50 + TAP::Formatter::Console::ParallelSession 3.50 + TAP::Formatter::Console::Session 3.50 + TAP::Formatter::File 3.50 + TAP::Formatter::File::Session 3.50 + TAP::Formatter::Session 3.50 + TAP::Harness 3.50 + TAP::Harness::Env 3.50 + TAP::Object 3.50 + TAP::Parser 3.50 + TAP::Parser::Aggregator 3.50 + TAP::Parser::Grammar 3.50 + TAP::Parser::Iterator 3.50 + TAP::Parser::Iterator::Array 3.50 + TAP::Parser::Iterator::Process 3.50 + TAP::Parser::Iterator::Stream 3.50 + TAP::Parser::IteratorFactory 3.50 + TAP::Parser::Multiplexer 3.50 + TAP::Parser::Result 3.50 + TAP::Parser::Result::Bailout 3.50 + TAP::Parser::Result::Comment 3.50 + TAP::Parser::Result::Plan 3.50 + TAP::Parser::Result::Pragma 3.50 + TAP::Parser::Result::Test 3.50 + TAP::Parser::Result::Unknown 3.50 + TAP::Parser::Result::Version 3.50 + TAP::Parser::Result::YAML 3.50 + TAP::Parser::ResultFactory 3.50 + TAP::Parser::Scheduler 3.50 + TAP::Parser::Scheduler::Job 3.50 + TAP::Parser::Scheduler::Spinner 3.50 + TAP::Parser::Source 3.50 + TAP::Parser::SourceHandler 3.50 + TAP::Parser::SourceHandler::Executable 3.50 + TAP::Parser::SourceHandler::File 3.50 + TAP::Parser::SourceHandler::Handle 3.50 + TAP::Parser::SourceHandler::Perl 3.50 + TAP::Parser::SourceHandler::RawTAP 3.50 + TAP::Parser::YAMLish::Reader 3.50 + TAP::Parser::YAMLish::Writer 3.50 + Test::Harness 3.50 + requirements: + ExtUtils::MakeMaker 0 + Test-LongString-0.17 + pathname: R/RG/RGARCIA/Test-LongString-0.17.tar.gz + provides: + Test::LongString 0.17 requirements: - Cache::FileCache 0 ExtUtils::MakeMaker 0 - HTTP::Server::Simple 0 - LWPx::ParanoidAgent 0 - Net::OpenID::Consumer 0 - Test::Builder 0 - Test::HTTP::Server::Simple 0 - Test-OpenID-Server-0.02 - pathname: J/JE/JESSE/Test-OpenID-Server-0.02.tar.gz + Test::Builder 0.12 + Test::Builder::Tester 1.04 + Test-MockRandom-1.01 + pathname: D/DA/DAGOLDEN/Test-MockRandom-1.01.tar.gz provides: - Test::OpenID::Server 0.02 + Test::MockRandom 1.01 requirements: - ExtUtils::MakeMaker 0 - HTTP::Server::Simple 0 - Net::OpenID::Server 0 - Test::HTTP::Server::Simple 0 - Test::OpenID::Consumer 0 - Test::WWW::Mechanize 0 - Test-Perl-Critic-1.02 - pathname: T/TH/THALJEF/Test-Perl-Critic-1.02.tar.gz + Carp 0 + ExtUtils::MakeMaker 6.17 + strict 0 + warnings 0 + Test-Perl-Critic-1.04 + pathname: P/PE/PETDANCE/Test-Perl-Critic-1.04.tar.gz provides: - Test::Perl::Critic 1.02 + Test::Perl::Critic 1.04 requirements: Carp 0 English 0 + MCE 1.827 + Module::Build 0.4 Perl::Critic 1.105 Perl::Critic::Utils 1.105 Perl::Critic::Violation 1.105 - Test::Builder 0 + Test::Builder 0.88 Test::More 0 strict 0 warnings 0 - Test-Pod-1.48 - pathname: D/DW/DWHEELER/Test-Pod-1.48.tar.gz - provides: - Test::Pod 1.48 - requirements: - File::Find 0 - File::Spec 0 - Module::Build 0.30 - Pod::Simple 3.05 - Test::Builder::Tester 1.02 - Test::More 0.62 - Test-Pod-Coverage-1.08 - pathname: P/PE/PETDANCE/Test-Pod-Coverage-1.08.tar.gz - provides: - Nopod undef - Nosymbols undef - PC_Inherited undef - PC_Inherits undef - Privates undef - Simple undef - Test::Pod::Coverage 1.08 - requirements: - ExtUtils::MakeMaker 0 - Pod::Coverage 0 - Test::Builder::Tester 0 - Test::More 0 - Test-Requires-0.07 - pathname: T/TO/TOKUHIROM/Test-Requires-0.07.tar.gz + Test-Requires-0.11 + pathname: T/TO/TOKUHIROM/Test-Requires-0.11.tar.gz provides: - Test::Requires 0.07 + Test::Requires 0.11 requirements: - CPAN::Meta 0 - CPAN::Meta::Prereqs 0 - ExtUtils::MakeMaker 6.59 - Module::Build 0.38 + ExtUtils::MakeMaker 6.64 Test::Builder::Module 0 - Test::More 0.61 - perl 5.008_001 - Test-RequiresInternet-0.04 - pathname: M/MA/MALLEN/Test-RequiresInternet-0.04.tar.gz + Test::More 0.47 + perl 5.006 + Test-RequiresInternet-0.05 + pathname: M/MA/MALLEN/Test-RequiresInternet-0.05.tar.gz provides: - Test::RequiresInternet 0.04 + Test::RequiresInternet 0.05 requirements: ExtUtils::MakeMaker 0 Socket 0 strict 0 warnings 0 - Test-Routine-0.018 - pathname: R/RJ/RJBS/Test-Routine-0.018.tar.gz - provides: - Test::Routine 0.018 - Test::Routine::Common 0.018 - Test::Routine::Compositor 0.018 - Test::Routine::Manual::Demo 0.018 - Test::Routine::Runner 0.018 - Test::Routine::Test 0.018 - Test::Routine::Test::Role 0.018 - Test::Routine::Util 0.018 - t::lib::NoGood undef + Test-Routine-0.031 + pathname: R/RJ/RJBS/Test-Routine-0.031.tar.gz + provides: + Test::Routine 0.031 + Test::Routine::Common 0.031 + Test::Routine::Compositor 0.031 + Test::Routine::Manual::Demo 0.031 + Test::Routine::Runner 0.031 + Test::Routine::Test 0.031 + Test::Routine::Test::Role 0.031 + Test::Routine::Util 0.031 requirements: Carp 0 Class::Load 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 6.78 Moose 0 Moose::Exporter 0 Moose::Meta::Class 0 @@ -7320,231 +7044,356 @@ DISTRIBUTIONS Scalar::Util 0 Sub::Exporter 0 Sub::Exporter::Util 0 + Test2::API 1.302045 + Test::Abortable 0.002 Test::More 0.96 Try::Tiny 0 namespace::autoclean 0 namespace::clean 0 + perl 5.012000 strict 0 warnings 0 - Test-Script-1.07 - pathname: A/AD/ADAMK/Test-Script-1.07.tar.gz - provides: - Test::Script 1.07 - requirements: - ExtUtils::MakeMaker 6.42 - File::Spec 0.80 - IPC::Run3 0.034 - Probe::Perl 0.01 - Test::Builder 0.32 - Test::Builder::Tester 1.02 - Test::More 0.62 - blib 0 - Test-SharedFork-0.24 - pathname: T/TO/TOKUHIROM/Test-SharedFork-0.24.tar.gz + Test-SharedFork-0.35 + pathname: E/EX/EXODIST/Test-SharedFork-0.35.tar.gz provides: - Test::SharedFork 0.24 + Test::SharedFork 0.35 Test::SharedFork::Array undef Test::SharedFork::Scalar undef Test::SharedFork::Store undef requirements: - CPAN::Meta 0 - CPAN::Meta::Prereqs 0 - ExtUtils::CBuilder 0 + ExtUtils::MakeMaker 6.64 File::Temp 0 - Module::Build 0.38 Test::Builder 0.32 Test::Builder::Module 0 Test::More 0.88 perl 5.008_001 - Test-Simple-1.001003 - pathname: E/EX/EXODIST/Test-Simple-1.001003.tar.gz - provides: - Test::Builder 1.001003 - Test::Builder::IO::Scalar 2.110 - Test::Builder::Module 1.001003 - Test::More 1.001003 - Test::Simple 1.001003 + Test-Simple-1.302210 + pathname: E/EX/EXODIST/Test-Simple-1.302210.tar.gz + provides: + Test2 1.302210 + Test2::API 1.302210 + Test2::API::Breakage 1.302210 + Test2::API::Context 1.302210 + Test2::API::Instance 1.302210 + Test2::API::InterceptResult 1.302210 + Test2::API::InterceptResult::Event 1.302210 + Test2::API::InterceptResult::Facet 1.302210 + Test2::API::InterceptResult::Hub 1.302210 + Test2::API::InterceptResult::Squasher 1.302210 + Test2::API::Stack 1.302210 + Test2::AsyncSubtest 1.302210 + Test2::AsyncSubtest::Event::Attach 1.302210 + Test2::AsyncSubtest::Event::Detach 1.302210 + Test2::AsyncSubtest::Formatter 1.302210 + Test2::AsyncSubtest::Hub 1.302210 + Test2::Bundle 1.302210 + Test2::Bundle::Extended 1.302210 + Test2::Bundle::More 1.302210 + Test2::Bundle::Simple 1.302210 + Test2::Compare 1.302210 + Test2::Compare::Array 1.302210 + Test2::Compare::Bag 1.302210 + Test2::Compare::Base 1.302210 + Test2::Compare::Bool 1.302210 + Test2::Compare::Custom 1.302210 + Test2::Compare::DeepRef 1.302210 + Test2::Compare::Delta 1.302210 + Test2::Compare::Event 1.302210 + Test2::Compare::EventMeta 1.302210 + Test2::Compare::Float 1.302210 + Test2::Compare::Hash 1.302210 + Test2::Compare::Isa 1.302210 + Test2::Compare::Meta 1.302210 + Test2::Compare::Negatable 1.302210 + Test2::Compare::Number 1.302210 + Test2::Compare::Object 1.302210 + Test2::Compare::OrderedSubset 1.302210 + Test2::Compare::Pattern 1.302210 + Test2::Compare::Ref 1.302210 + Test2::Compare::Regex 1.302210 + Test2::Compare::Scalar 1.302210 + Test2::Compare::Set 1.302210 + Test2::Compare::String 1.302210 + Test2::Compare::Undef 1.302210 + Test2::Compare::Wildcard 1.302210 + Test2::Env 1.302210 + Test2::Event 1.302210 + Test2::Event::Bail 1.302210 + Test2::Event::Diag 1.302210 + Test2::Event::Encoding 1.302210 + Test2::Event::Exception 1.302210 + Test2::Event::Fail 1.302210 + Test2::Event::Generic 1.302210 + Test2::Event::Note 1.302210 + Test2::Event::Ok 1.302210 + Test2::Event::Pass 1.302210 + Test2::Event::Plan 1.302210 + Test2::Event::Skip 1.302210 + Test2::Event::Subtest 1.302210 + Test2::Event::TAP::Version 1.302210 + Test2::Event::V2 1.302210 + Test2::Event::Waiting 1.302210 + Test2::EventFacet 1.302210 + Test2::EventFacet::About 1.302210 + Test2::EventFacet::Amnesty 1.302210 + Test2::EventFacet::Assert 1.302210 + Test2::EventFacet::Control 1.302210 + Test2::EventFacet::Error 1.302210 + Test2::EventFacet::Hub 1.302210 + Test2::EventFacet::Info 1.302210 + Test2::EventFacet::Info::Table 1.302210 + Test2::EventFacet::Meta 1.302210 + Test2::EventFacet::Parent 1.302210 + Test2::EventFacet::Plan 1.302210 + Test2::EventFacet::Render 1.302210 + Test2::EventFacet::Trace 1.302210 + Test2::Formatter 1.302210 + Test2::Formatter::TAP 1.302210 + Test2::Hub 1.302210 + Test2::Hub::Interceptor 1.302210 + Test2::Hub::Interceptor::Terminator 1.302210 + Test2::Hub::Subtest 1.302210 + Test2::IPC 1.302210 + Test2::IPC::Driver 1.302210 + Test2::IPC::Driver::Files 1.302210 + Test2::Manual 1.302210 + Test2::Manual::Anatomy 1.302210 + Test2::Manual::Anatomy::API 1.302210 + Test2::Manual::Anatomy::Context 1.302210 + Test2::Manual::Anatomy::EndToEnd 1.302210 + Test2::Manual::Anatomy::Event 1.302210 + Test2::Manual::Anatomy::Hubs 1.302210 + Test2::Manual::Anatomy::IPC 1.302210 + Test2::Manual::Anatomy::Utilities 1.302210 + Test2::Manual::Concurrency 1.302210 + Test2::Manual::Contributing 1.302210 + Test2::Manual::Testing 1.302210 + Test2::Manual::Testing::Introduction 1.302210 + Test2::Manual::Testing::Migrating 1.302210 + Test2::Manual::Testing::Planning 1.302210 + Test2::Manual::Testing::Todo 1.302210 + Test2::Manual::Tooling 1.302210 + Test2::Manual::Tooling::FirstTool 1.302210 + Test2::Manual::Tooling::Formatter 1.302210 + Test2::Manual::Tooling::Nesting 1.302210 + Test2::Manual::Tooling::Plugin::TestExit 1.302210 + Test2::Manual::Tooling::Plugin::TestingDone 1.302210 + Test2::Manual::Tooling::Plugin::ToolCompletes 1.302210 + Test2::Manual::Tooling::Plugin::ToolStarts 1.302210 + Test2::Manual::Tooling::Subtest 1.302210 + Test2::Manual::Tooling::TestBuilder 1.302210 + Test2::Manual::Tooling::Testing 1.302210 + Test2::Mock 1.302210 + Test2::Plugin 1.302210 + Test2::Plugin::BailOnFail 1.302210 + Test2::Plugin::DieOnFail 1.302210 + Test2::Plugin::ExitSummary 1.302210 + Test2::Plugin::SRand 1.302210 + Test2::Plugin::Times 1.302210 + Test2::Plugin::UTF8 1.302210 + Test2::Require 1.302210 + Test2::Require::AuthorTesting 1.302210 + Test2::Require::AutomatedTesting 1.302210 + Test2::Require::EnvVar 1.302210 + Test2::Require::ExtendedTesting 1.302210 + Test2::Require::Fork 1.302210 + Test2::Require::Module 1.302210 + Test2::Require::NonInteractiveTesting 1.302210 + Test2::Require::Perl 1.302210 + Test2::Require::RealFork 1.302210 + Test2::Require::ReleaseTesting 1.302210 + Test2::Require::Threads 1.302210 + Test2::Suite 1.302210 + Test2::Todo 1.302210 + Test2::Tools 1.302210 + Test2::Tools::AsyncSubtest 1.302210 + Test2::Tools::Basic 1.302210 + Test2::Tools::Class 1.302210 + Test2::Tools::ClassicCompare 1.302210 + Test2::Tools::Compare 1.302210 + Test2::Tools::Defer 1.302210 + Test2::Tools::Encoding 1.302210 + Test2::Tools::Event 1.302210 + Test2::Tools::Exception 1.302210 + Test2::Tools::Exports 1.302210 + Test2::Tools::GenTemp 1.302210 + Test2::Tools::Grab 1.302210 + Test2::Tools::Mock 1.302210 + Test2::Tools::Ref 1.302210 + Test2::Tools::Refcount 1.302210 + Test2::Tools::Spec 1.302210 + Test2::Tools::Subtest 1.302210 + Test2::Tools::Target 1.302210 + Test2::Tools::Tester 1.302210 + Test2::Tools::Tiny 1.302210 + Test2::Tools::Warnings 1.302210 + Test2::Util 1.302210 + Test2::Util::ExternalMeta 1.302210 + Test2::Util::Facets2Legacy 1.302210 + Test2::Util::Grabber 1.302210 + Test2::Util::Guard 1.302210 + Test2::Util::HashBase 1.302210 + Test2::Util::Importer 1.302210 + Test2::Util::Ref 1.302210 + Test2::Util::Sig 1.302210 + Test2::Util::Stash 1.302210 + Test2::Util::Sub 1.302210 + Test2::Util::Table 1.302210 + Test2::Util::Table::Cell 1.302210 + Test2::Util::Table::LineBreak 1.302210 + Test2::Util::Term 1.302210 + Test2::Util::Times 1.302210 + Test2::Util::Trace 1.302210 + Test2::V0 1.302210 + Test2::Workflow 1.302210 + Test2::Workflow::BlockBase 1.302210 + Test2::Workflow::Build 1.302210 + Test2::Workflow::Runner 1.302210 + Test2::Workflow::Task 1.302210 + Test2::Workflow::Task::Action 1.302210 + Test2::Workflow::Task::Group 1.302210 + Test::Builder 1.302210 + Test::Builder::Formatter 1.302210 + Test::Builder::Module 1.302210 + Test::Builder::Tester 1.302210 + Test::Builder::Tester::Color 1.302210 + Test::Builder::Tester::Tie 1.302210 + Test::Builder::TodoDiag 1.302210 + Test::More 1.302210 + Test::Simple 1.302210 + Test::Tester 1.302210 + Test::Tester::Capture 1.302210 + Test::Tester::CaptureRunner 1.302210 + Test::Tester::Delegate 1.302210 + Test::use::ok 1.302210 + ok 1.302210 requirements: + B 0 + Data::Dumper 0 + Exporter 0 ExtUtils::MakeMaker 0 + File::Spec 0 + File::Temp 0 Scalar::Util 1.13 - Test::Harness 2.03 - perl 5.006 - Test-SubCalls-1.09 - pathname: A/AD/ADAMK/Test-SubCalls-1.09.tar.gz - provides: - Test::SubCalls 1.09 - requirements: - ExtUtils::MakeMaker 6.42 - File::Spec 0.80 - Hook::LexWrap 0.20 - Test::Builder::Tester 1.02 - Test::More 0.42 - Test-TCP-2.02 - pathname: T/TO/TOKUHIROM/Test-TCP-2.02.tar.gz + Storable 0 + Term::Table 0.013 + Time::HiRes 0 + overload 0 + perl 5.006002 + utf8 0 + Test-TCP-2.22 + pathname: M/MI/MIYAGAWA/Test-TCP-2.22.tar.gz provides: Net::EmptyPort undef - Test::TCP 2.02 + Test::TCP 2.22 Test::TCP::CheckPort undef requirements: - CPAN::Meta 0 - CPAN::Meta::Prereqs 0 - ExtUtils::CBuilder 0 + ExtUtils::MakeMaker 6.64 IO::Socket::INET 0 - Module::Build 0.38 + IO::Socket::IP 0 Test::More 0 - Test::SharedFork 0.19 + Test::SharedFork 0.29 Time::HiRes 0 perl 5.008001 - Test-Tester-0.109 - pathname: F/FD/FDALY/Test-Tester-0.109.tar.gz - provides: - Test::Tester 0.109 - Test::Tester::Capture undef - Test::Tester::CaptureRunner undef - Test::Tester::Delegate undef - requirements: - ExtUtils::MakeMaker 0 - Test::Builder 0 - Test-Trap-v0.2.4 - pathname: E/EB/EBHANSSEN/Test-Trap-v0.2.4.tar.gz - provides: - Test::Trap 0.002004 - Test::Trap::Builder 0.002004 - Test::Trap::Builder::PerlIO 0.002004 - Test::Trap::Builder::SystemSafe 0.002004 - Test::Trap::Builder::TempFile 0.002004 - requirements: - Carp 0 - Data::Dump 0 - Exporter 0 - File::Temp 0 - IO::Handle 0 - Test::Builder 0 - Test::More 0 - Test::Tester 0.107 - base 0 - constant 0 - lib 0 - perl v5.6.2 - strict 0 - version 0 - warnings 0 - Test-Version-1.002004 - pathname: X/XE/XENO/Test-Version-1.002004.tar.gz + Test-Vars-0.017 + pathname: J/JK/JKEENAN/Test-Vars-0.017.tar.gz provides: - Test::Version 1.002004 + Test::Vars 0.017 requirements: - Carp 0 - Exporter 0 - ExtUtils::MakeMaker 6.30 - File::Find::Rule::Perl 0 - Module::Metadata 0 - Test::Builder 0 - Test::More 0.88 + B 0 + ExtUtils::MakeMaker 6.17 + ExtUtils::Manifest 0 + IO::Pipe 0 + List::Util 1.33 + Storable 0 + Symbol 0 parent 0 - strict 0 - version 0.86 - warnings 0 - Test-WWW-Mechanize-1.44 - pathname: P/PE/PETDANCE/Test-WWW-Mechanize-1.44.tar.gz - provides: - Test::WWW::Mechanize 1.44 - requirements: - Carp::Assert::More 0 - ExtUtils::MakeMaker 0 - HTML::TreeBuilder 0 - HTTP::Server::Simple 0.42 - HTTP::Server::Simple::CGI 0 - LWP 6.02 - Test::Builder::Tester 1.09 - Test::LongString 0.15 - Test::More 0.96 - URI::file 0 - WWW::Mechanize 1.68 - perl 5.008 - Test-WWW-Mechanize-PSGI-0.35 - pathname: L/LB/LBROCARD/Test-WWW-Mechanize-PSGI-0.35.tar.gz - provides: - Test::WWW::Mechanize::PSGI 0.35 - requirements: - ExtUtils::MakeMaker 0 - HTTP::Message::PSGI 0 - Test::More 0 - Test::WWW::Mechanize 0 - Try::Tiny 0 - Test-Warn-0.30 - pathname: C/CH/CHORNY/Test-Warn-0.30.tar.gz + perl 5.010000 + Test-Warn-0.37 + pathname: B/BI/BIGJ/Test-Warn-0.37.tar.gz provides: - Test::Warn 0.30 - Test::Warn::Categorization 0.30 + Test::Warn 0.37 requirements: Carp 1.22 ExtUtils::MakeMaker 0 - File::Spec 0 Sub::Uplevel 0.12 Test::Builder 0.13 Test::Builder::Tester 1.02 - Test::More 0 perl 5.006 - Test-use-ok-0.11 - pathname: A/AU/AUDREYT/Test-use-ok-0.11.tar.gz - provides: - Test::use::ok 0.11 - ok 0.11 - requirements: - ExtUtils::MakeMaker 6.36 - perl 5.005 - Text-CSV_XS-1.08 - pathname: H/HM/HMBRAND/Text-CSV_XS-1.08.tgz + Text-CSV_XS-1.60 + pathname: H/HM/HMBRAND/Text-CSV_XS-1.60.tgz provides: - Text::CSV_XS 1.08 + Text::CSV_XS 1.60 requirements: Config 0 - DynaLoader 0 ExtUtils::MakeMaker 0 IO::Handle 0 Test::More 0 - Text-Diff-1.41 - pathname: O/OV/OVID/Text-Diff-1.41.tar.gz + XSLoader 0 + Text-Diff-1.45 + pathname: N/NE/NEILB/Text-Diff-1.45.tar.gz provides: - Text::Diff 1.41 - Text::Diff::Base 1.41 - Text::Diff::Config 1.41 - Text::Diff::Table 1.41 + Text::Diff 1.45 + Text::Diff::Base 1.45 + Text::Diff::Config 1.44 + Text::Diff::Table 1.44 requirements: Algorithm::Diff 1.19 Exporter 0 ExtUtils::MakeMaker 0 - Text-Glob-0.09 - pathname: R/RC/RCLAMP/Text-Glob-0.09.tar.gz + perl 5.006 + Text-Glob-0.11 + pathname: R/RC/RCLAMP/Text-Glob-0.11.tar.gz + provides: + Text::Glob 0.11 + requirements: + Exporter 0 + ExtUtils::MakeMaker 0 + constant 0 + perl 5.00503 + Text-SimpleTable-2.07 + pathname: M/MR/MRAMBERG/Text-SimpleTable-2.07.tar.gz provides: - Text::Glob 0.09 + Text::SimpleTable 2.07 requirements: + ExtUtils::MakeMaker 0 Test::More 0 - Text-SimpleTable-2.03 - pathname: M/MR/MRAMBERG/Text-SimpleTable-2.03.tar.gz + perl 5.008001 + Text-SimpleTable-AutoWidth-0.09 + pathname: C/CU/CUB/Text-SimpleTable-AutoWidth-0.09.tar.gz provides: - Text::SimpleTable 2.03 + Text::SimpleTable::AutoWidth 0.09 requirements: ExtUtils::MakeMaker 0 - Test::More 0 - Text-Template-1.46 - pathname: M/MJ/MJD/Text-Template-1.46.tar.gz + List::Util 0 + Moo 0 + Text::SimpleTable 0 + strict 0 + warnings 0 + Text-Template-1.61 + pathname: M/MS/MSCHOUT/Text-Template-1.61.tar.gz provides: - Text::Template 1.46 - Text::Template::Preprocess 1.46 + Text::Template 1.61 + Text::Template::Preprocess 1.61 requirements: + Carp 0 + Encode 0 + Exporter 0 ExtUtils::MakeMaker 0 - Throwable-0.200011 - pathname: R/RJ/RJBS/Throwable-0.200011.tar.gz + base 0 + perl 5.008 + strict 0 + warnings 0 + Throwable-1.001 + pathname: R/RJ/RJBS/Throwable-1.001.tar.gz provides: - StackTrace::Auto 0.200011 - Throwable 0.200011 - Throwable::Error 0.200011 + StackTrace::Auto 1.001 + Throwable 1.001 + Throwable::Error 1.001 requirements: Carp 0 - Devel::StackTrace 1.21 - ExtUtils::MakeMaker 6.30 + Devel::StackTrace 1.32 + ExtUtils::MakeMaker 6.78 Module::Runtime 0.002 Moo 1.000001 Moo::Role 0 @@ -7561,26 +7410,41 @@ DISTRIBUTIONS Test::More 0 Test::use::ok 0 Tie::RefHash 0 - Time-Duration-1.1 - pathname: A/AV/AVIF/Time-Duration-1.1.tar.gz + Time-Duration-1.21 + pathname: N/NE/NEILB/Time-Duration-1.21.tar.gz + provides: + Time::Duration 1.21 + requirements: + Exporter 0 + ExtUtils::MakeMaker 0 + constant 0 + perl 5.006 + strict 0 + warnings 0 + Time-Duration-Parse-0.16 + pathname: N/NE/NEILB/Time-Duration-Parse-0.16.tar.gz provides: - Time::Duration 1.1 + Time::Duration::Parse 0.16 requirements: + Carp 0 + Exporter 5.57 ExtUtils::MakeMaker 0 - Test::Pod 0 - Test::Pod::Coverage 0 - Time-Duration-Parse-0.11 - pathname: N/NE/NEILB/Time-Duration-Parse-0.11.tar.gz + perl 5.006 + strict 0 + warnings 0 + Time-Local-1.35 + pathname: D/DR/DROLSKY/Time-Local-1.35.tar.gz provides: - Time::Duration::Parse 0.11 + Time::Local 1.35 requirements: Carp 0 - Exporter::Lite 0 - ExtUtils::MakeMaker 6.30 + Exporter 0 + ExtUtils::MakeMaker 0 + constant 0 + parent 0 strict 0 - warnings 0 - TimeDate-2.30 - pathname: G/GB/GBARR/TimeDate-2.30.tar.gz + TimeDate-2.33 + pathname: A/AT/ATOOMIC/TimeDate-2.33.tar.gz provides: Date::Format 2.24 Date::Format::Generic 2.24 @@ -7605,6 +7469,7 @@ DISTRIBUTIONS Date::Language::Icelandic 1.01 Date::Language::Italian 1.01 Date::Language::Norwegian 1.01 + Date::Language::Occitan 1.04 Date::Language::Oromo 0.99 Date::Language::Romanian 1.01 Date::Language::Russian 1.01 @@ -7618,247 +7483,489 @@ DISTRIBUTIONS Date::Language::TigrinyaEritrean 1.00 Date::Language::TigrinyaEthiopian 1.00 Date::Language::Turkish 1.0 - Date::Parse 2.30 + Date::Parse 2.33 Time::Zone 2.24 + TimeDate 1.21 requirements: ExtUtils::MakeMaker 0 - Tree-Simple-1.23 - pathname: R/RS/RSAVAGE/Tree-Simple-1.23.tgz + Tree-Simple-1.34 + pathname: R/RS/RSAVAGE/Tree-Simple-1.34.tgz provides: - Tree::Simple 1.23 - Tree::Simple::Visitor 1.23 + Tree::Simple 1.34 + Tree::Simple::Visitor 1.34 requirements: - Module::Build 0.4 + ExtUtils::MakeMaker 0 Scalar::Util 1.18 - Test::Exception 0.15 - Test::More 0.47 - Test::Version 1.002003 constant 0 strict 0 warnings 0 - Tree-Simple-VisitorFactory-0.12 - pathname: R/RS/RSAVAGE/Tree-Simple-VisitorFactory-0.12.tgz - provides: - Tree::Simple::Visitor::BreadthFirstTraversal 0.12 - Tree::Simple::Visitor::CreateDirectoryTree 0.12 - Tree::Simple::Visitor::FindByNodeValue 0.12 - Tree::Simple::Visitor::FindByPath 0.12 - Tree::Simple::Visitor::FindByUID 0.12 - Tree::Simple::Visitor::FromNestedArray 0.12 - Tree::Simple::Visitor::FromNestedHash 0.12 - Tree::Simple::Visitor::GetAllDescendents 0.12 - Tree::Simple::Visitor::LoadClassHierarchy 0.12 - Tree::Simple::Visitor::LoadDirectoryTree 0.12 - Tree::Simple::Visitor::PathToRoot 0.12 - Tree::Simple::Visitor::PostOrderTraversal 0.12 - Tree::Simple::Visitor::PreOrderTraversal 0.12 - Tree::Simple::Visitor::Sort 0.12 - Tree::Simple::Visitor::ToNestedArray 0.12 - Tree::Simple::Visitor::ToNestedHash 0.12 - Tree::Simple::Visitor::VariableDepthClone 0.12 - Tree::Simple::VisitorFactory 0.12 + Tree-Simple-VisitorFactory-0.16 + pathname: R/RS/RSAVAGE/Tree-Simple-VisitorFactory-0.16.tgz + provides: + Tree::Simple::Visitor::BreadthFirstTraversal 0.16 + Tree::Simple::Visitor::CreateDirectoryTree 0.16 + Tree::Simple::Visitor::FindByNodeValue 0.16 + Tree::Simple::Visitor::FindByPath 0.16 + Tree::Simple::Visitor::FindByUID 0.16 + Tree::Simple::Visitor::FromNestedArray 0.16 + Tree::Simple::Visitor::FromNestedHash 0.16 + Tree::Simple::Visitor::GetAllDescendents 0.16 + Tree::Simple::Visitor::LoadClassHierarchy 0.16 + Tree::Simple::Visitor::LoadDirectoryTree 0.16 + Tree::Simple::Visitor::PathToRoot 0.16 + Tree::Simple::Visitor::PostOrderTraversal 0.16 + Tree::Simple::Visitor::PreOrderTraversal 0.16 + Tree::Simple::Visitor::Sort 0.16 + Tree::Simple::Visitor::ToNestedArray 0.16 + Tree::Simple::Visitor::ToNestedHash 0.16 + Tree::Simple::Visitor::VariableDepthClone 0.16 + Tree::Simple::VisitorFactory 0.16 requirements: + ExtUtils::MakeMaker 0 File::Spec 0.6 - Module::Build 0.38 Scalar::Util 1.1 - Test::Exception 0.15 - Test::More 0.47 Tree::Simple 1.12 Tree::Simple::Visitor 1.22 - base 2.16 + base 0 strict 0 warnings 0 - Try-Tiny-0.22 - pathname: D/DO/DOY/Try-Tiny-0.22.tar.gz + Try-Tiny-0.32 + pathname: E/ET/ETHER/Try-Tiny-0.32.tar.gz provides: - Try::Tiny 0.22 + Try::Tiny 0.32 requirements: Carp 0 Exporter 5.57 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 constant 0 + perl 5.006 strict 0 warnings 0 - Twiggy-0.1024 - pathname: M/MI/MIYAGAWA/Twiggy-0.1024.tar.gz - provides: - AnyEvent::Server::PSGI undef - Plack::Handler::Twiggy undef - Twiggy 0.1024 - Twiggy::Server undef - Twiggy::Server::SS undef - Twiggy::Writer undef + Twitter-API-1.0006 + pathname: M/MM/MMIMS/Twitter-API-1.0006.tar.gz + provides: + Twitter::API 1.0006 + Twitter::API::Context 1.0006 + Twitter::API::Error 1.0006 + Twitter::API::Role::RequestArgs 1.0006 + Twitter::API::Trait::ApiMethods 1.0006 + Twitter::API::Trait::AppAuth 1.0006 + Twitter::API::Trait::DecodeHtmlEntities 1.0006 + Twitter::API::Trait::Enchilada 1.0006 + Twitter::API::Trait::Migration 1.0006 + Twitter::API::Trait::NormalizeBooleans 1.0006 + Twitter::API::Trait::RateLimiting 1.0006 + Twitter::API::Trait::RetryOnError 1.0006 + Twitter::API::Util 1.0006 requirements: - AnyEvent 0 - ExtUtils::MakeMaker 6.30 - HTTP::Status 0 - Plack 0.99 + Carp 0 + Digest::SHA 0 + Encode 0 + HTML::Entities 0 + HTTP::Request::Common 0 + HTTP::Thin 0 + IO::Socket::SSL 0 + JSON::MaybeXS 0 + Module::Build::Tiny 0.034 + Module::Runtime 0 + Moo 0 + Moo::Role 0 + MooX::Aliases 0 + MooX::Traits 0 + Ref::Util 0 + Scalar::Util 0 + StackTrace::Auto 0 + Sub::Exporter::Progressive 0 + Throwable 0 + Time::HiRes 0 + Time::Local 0 Try::Tiny 0 - Types-Serialiser-1.0 - pathname: M/ML/MLEHMANN/Types-Serialiser-1.0.tar.gz + URI 0 + URL::Encode 0 + WWW::OAuth 0.006 + namespace::clean 0 + perl v5.14.1 + Type-Tiny-2.008001 + pathname: T/TO/TOBYINK/Type-Tiny-2.008001.tar.gz + provides: + Devel::TypeTiny::Perl58Compat 2.008001 + Error::TypeTiny 2.008001 + Error::TypeTiny::Assertion 2.008001 + Error::TypeTiny::Compilation 2.008001 + Error::TypeTiny::WrongNumberOfParameters 2.008001 + Eval::TypeTiny 2.008001 + Eval::TypeTiny::CodeAccumulator 2.008001 + Reply::Plugin::TypeTiny 2.008001 + Test::TypeTiny 2.008001 + Type::Coercion 2.008001 + Type::Coercion::FromMoose 2.008001 + Type::Coercion::Union 2.008001 + Type::Library 2.008001 + Type::Params 2.008001 + Type::Params::Alternatives 2.008001 + Type::Params::Parameter 2.008001 + Type::Params::Signature 2.008001 + Type::Parser 2.008001 + Type::Parser::AstBuilder 2.008001 + Type::Parser::Token 2.008001 + Type::Parser::TokenStream 2.008001 + Type::Registry 2.008001 + Type::Tie 2.008001 + Type::Tie::ARRAY 2.008001 + Type::Tie::BASE 2.008001 + Type::Tie::HASH 2.008001 + Type::Tie::SCALAR 2.008001 + Type::Tiny 2.008001 + Type::Tiny::Bitfield 2.008001 + Type::Tiny::Class 2.008001 + Type::Tiny::ConstrainedObject 2.008001 + Type::Tiny::Duck 2.008001 + Type::Tiny::Enum 2.008001 + Type::Tiny::Intersection 2.008001 + Type::Tiny::Role 2.008001 + Type::Tiny::Union 2.008001 + Type::Utils 2.008001 + Types::Common 2.008001 + Types::Common::Numeric 2.008001 + Types::Common::String 2.008001 + Types::Standard 2.008001 + Types::Standard::ArrayRef 2.008001 + Types::Standard::CycleTuple 2.008001 + Types::Standard::Dict 2.008001 + Types::Standard::HashRef 2.008001 + Types::Standard::Map 2.008001 + Types::Standard::ScalarRef 2.008001 + Types::Standard::StrMatch 2.008001 + Types::Standard::Tied 2.008001 + Types::Standard::Tuple 2.008001 + Types::TypeTiny 2.008001 + requirements: + Exporter::Tiny 1.006000 + ExtUtils::MakeMaker 6.17 + perl 5.008001 + Types-Path-Tiny-0.006 + pathname: D/DA/DAGOLDEN/Types-Path-Tiny-0.006.tar.gz + provides: + Types::Path::Tiny 0.006 + requirements: + ExtUtils::MakeMaker 6.17 + Path::Tiny 0 + Type::Library 0.008 + Type::Utils 0 + Types::Standard 0 + Types::TypeTiny 0.004 + perl 5.008001 + strict 0 + warnings 0 + Types-Self-0.002 + pathname: T/TO/TOBYINK/Types-Self-0.002.tar.gz + provides: + Types::Self 0.002 + requirements: + ExtUtils::MakeMaker 6.17 + Role::Hooks 0 + Types::Standard 1.012 + perl 5.008001 + Types-Serialiser-1.01 + pathname: M/ML/MLEHMANN/Types-Serialiser-1.01.tar.gz provides: - JSON::PP::Boolean 1.0 - Types::Serialiser 1.0 - Types::Serialiser::BooleanBase 1.0 - Types::Serialiser::Error 1.0 + JSON::PP::Boolean 1.01 + Types::Serialiser 1.01 + Types::Serialiser::BooleanBase 1.01 + Types::Serialiser::Error 1.01 requirements: ExtUtils::MakeMaker 0 common::sense 0 - UNIVERSAL-require-0.17 - pathname: N/NE/NEILB/UNIVERSAL-require-0.17.tar.gz + Types-URI-0.007 + pathname: T/TO/TOBYINK/Types-URI-0.007.tar.gz + provides: + Types::URI 0.007 + requirements: + ExtUtils::MakeMaker 6.17 + Type::Library 1.000000 + Types::Path::Tiny 0 + Types::Standard 0 + Types::UUID 0 + URI 0 + URI::FromHash 0 + perl 5.008 + Types-UUID-0.004 + pathname: T/TO/TOBYINK/Types-UUID-0.004.tar.gz + provides: + Types::UUID 0.004 + requirements: + ExtUtils::MakeMaker 6.17 + Type::Tiny 1.000000 + UUID::Tiny 1.02 + perl 5.008 + UNIVERSAL-require-0.19 + pathname: N/NE/NEILB/UNIVERSAL-require-0.19.tar.gz provides: - UNIVERSAL 0.17 - UNIVERSAL::require 0.17 + UNIVERSAL::require 0.19 requirements: Carp 0 ExtUtils::MakeMaker 0 Test::More 0.47 perl 5.006 - URI-1.60 - pathname: G/GA/GAAS/URI-1.60.tar.gz - provides: - URI 1.60 - URI::Escape 3.31 - URI::Heuristic 4.20 - URI::IRI undef - URI::QueryParam undef - URI::Split undef - URI::URL 5.04 - URI::WithBase 2.20 - URI::_foreign undef - URI::_generic undef - URI::_idna undef - URI::_ldap 1.12 - URI::_login undef - URI::_punycode 0.04 - URI::_query undef - URI::_segment undef - URI::_server undef - URI::_userpass undef - URI::data undef - URI::file 4.21 - URI::file::Base undef - URI::file::FAT undef - URI::file::Mac undef - URI::file::OS2 undef - URI::file::QNX undef - URI::file::Unix undef - URI::file::Win32 undef - URI::ftp undef - URI::gopher undef - URI::http undef - URI::https undef - URI::ldap 1.12 - URI::ldapi undef - URI::ldaps undef - URI::mailto undef - URI::mms undef - URI::news undef - URI::nntp undef - URI::pop undef - URI::rlogin undef - URI::rsync undef - URI::rtsp undef - URI::rtspu undef - URI::sip 0.11 - URI::sips undef - URI::snews undef - URI::ssh undef - URI::telnet undef - URI::tn3270 undef - URI::urn undef - URI::urn::isbn undef - URI::urn::oid undef + strict 0 + warnings 0 + URI-5.31 + pathname: O/OA/OALDERS/URI-5.31.tar.gz + provides: + URI 5.31 + URI::Escape 5.31 + URI::Heuristic 5.31 + URI::IRI 5.31 + URI::QueryParam 5.31 + URI::Split 5.31 + URI::URL 5.31 + URI::WithBase 5.31 + URI::data 5.31 + URI::file 5.31 + URI::file::Base 5.31 + URI::file::FAT 5.31 + URI::file::Mac 5.31 + URI::file::OS2 5.31 + URI::file::QNX 5.31 + URI::file::Unix 5.31 + URI::file::Win32 5.31 + URI::ftp 5.31 + URI::ftpes 5.31 + URI::ftps 5.31 + URI::geo 5.31 + URI::gopher 5.31 + URI::http 5.31 + URI::https 5.31 + URI::icap 5.31 + URI::icaps 5.31 + URI::irc 5.31 + URI::ircs 5.31 + URI::ldap 5.31 + URI::ldapi 5.31 + URI::ldaps 5.31 + URI::mailto 5.31 + URI::mms 5.31 + URI::news 5.31 + URI::nntp 5.31 + URI::nntps 5.31 + URI::otpauth 5.31 + URI::pop 5.31 + URI::rlogin 5.31 + URI::rsync 5.31 + URI::rtsp 5.31 + URI::rtspu 5.31 + URI::scp 5.31 + URI::sftp 5.31 + URI::sip 5.31 + URI::sips 5.31 + URI::snews 5.31 + URI::ssh 5.31 + URI::telnet 5.31 + URI::tn3270 5.31 + URI::urn 5.31 + URI::urn::isbn 5.31 + URI::urn::oid 5.31 requirements: + Carp 0 + Cwd 0 + Data::Dumper 0 + Encode 0 + Exporter 5.57 ExtUtils::MakeMaker 0 + MIME::Base32 0 MIME::Base64 2 - Test 0 - Test::More 0 + Net::Domain 0 + Scalar::Util 0 + constant 0 + integer 0 + overload 0 + parent 0 perl 5.008001 - URI-Find-20111103 - pathname: M/MS/MSCHWERN/URI-Find-20111103.tar.gz + strict 0 + utf8 0 + warnings 0 + URI-Find-20160806 + pathname: M/MS/MSCHWERN/URI-Find-20160806.tar.gz provides: - URI::Find 20111103 - URI::Find::Schemeless 20111103 + URI::Find 20160806 + URI::Find::Schemeless 20160806 requirements: Module::Build 0.30 Test::More 0.88 - URI 1.00 - URI::URL 5.00 - perl v5.6.0 - URI-FromHash-0.04 - pathname: D/DR/DROLSKY/URI-FromHash-0.04.tar.gz + URI 1.60 + perl v5.8.8 + URI-FromHash-0.05 + pathname: D/DR/DROLSKY/URI-FromHash-0.05.tar.gz provides: - URI::FromHash 0.04 + URI::FromHash 0.05 requirements: Carp 0 Exporter 0 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 Params::Validate 0 - URI 0 - URI::QueryParam 0 + URI 1.68 strict 0 warnings 0 - Variable-Magic-0.53 - pathname: V/VP/VPIT/Variable-Magic-0.53.tar.gz + URI-Nested-0.10 + pathname: D/DW/DWHEELER/URI-Nested-0.10.tar.gz + provides: + URI::Nested 0.10 + requirements: + Module::Build 0.30 + Test::More 0.88 + URI 1.40 + perl 5.008001 + URI-db-0.23 + pathname: D/DW/DWHEELER/URI-db-0.23.tar.gz + provides: + URI::cassandra 0.23 + URI::clickhouse 0.20 + URI::cockroach 0.23 + URI::cockroachdb 0.23 + URI::couch 0.23 + URI::couchdb 0.23 + URI::cubrid 0.23 + URI::db 0.23 + URI::db2 0.23 + URI::derby 0.23 + URI::exasol 0.23 + URI::firebird 0.23 + URI::hive 0.23 + URI::impala 0.23 + URI::informix 0.23 + URI::ingres 0.23 + URI::interbase 0.23 + URI::ldapdb 0.23 + URI::maria 0.23 + URI::mariadb 0.23 + URI::max 0.23 + URI::maxdb 0.23 + URI::monet 0.23 + URI::monetdb 0.23 + URI::mongo 0.23 + URI::mongodb 0.23 + URI::mssql 0.23 + URI::mysql 0.23 + URI::oracle 0.23 + URI::pg 0.23 + URI::pgsql 0.23 + URI::pgxc 0.23 + URI::postgres 0.23 + URI::postgresql 0.23 + URI::postgresxc 0.23 + URI::redshift 0.23 + URI::snowflake 0.23 + URI::sqlite 0.23 + URI::sqlite3 0.23 + URI::sqlserver 0.23 + URI::sybase 0.23 + URI::teradata 0.23 + URI::unify 0.23 + URI::vertica 0.23 + URI::yugabyte 0.23 + URI::yugabytedb 0.23 + requirements: + Module::Build 0.30 + Test::More 0.88 + URI 1.40 + URI::Nested 0.10 + perl 5.008001 + URI-ws-0.03 + pathname: P/PL/PLICEASE/URI-ws-0.03.tar.gz + provides: + URI::ws 0.03 + URI::wss 0.03 + requirements: + ExtUtils::MakeMaker 6.30 + URI 0 + URL-Encode-0.03 + pathname: C/CH/CHANSEN/URL-Encode-0.03.tar.gz provides: - Variable::Magic 0.53 + URL::Encode 0.03 + URL::Encode::PP 0.03 requirements: Carp 0 - Config 0 Exporter 0 + ExtUtils::MakeMaker 6.59 + Test::More 0.88 + XSLoader 0 + perl 5.008001 + UUID-Tiny-1.04 + pathname: C/CA/CAUGUSTIN/UUID-Tiny-1.04.tar.gz + provides: + UUID::Tiny 1.04 + requirements: + Carp 0 + Digest::MD5 0 ExtUtils::MakeMaker 0 + IO::File 0 + MIME::Base64 0 + POSIX 0 Test::More 0 - XSLoader 0 - base 0 + Time::HiRes 0 + Unicode-LineBreak-2019.001 + pathname: N/NE/NEZUMI/Unicode-LineBreak-2019.001.tar.gz + provides: + Text::LineFold 2018.012 + Unicode::GCString 2013.10 + Unicode::LineBreak 2019.001 + requirements: + Encode 1.98 + ExtUtils::MakeMaker 6.26 + MIME::Charset v1.6.2 + Test::More 0.45 perl 5.008 - WWW-Mechanize-1.73 - pathname: E/ET/ETHER/WWW-Mechanize-1.73.tar.gz + Variable-Magic-0.64 + pathname: V/VP/VPIT/Variable-Magic-0.64.tar.gz provides: - WWW::Mechanize 1.73 - WWW::Mechanize::Image undef - WWW::Mechanize::Link undef + Variable::Magic 0.64 requirements: Carp 0 + Config 0 + Exporter 0 ExtUtils::MakeMaker 0 - File::Temp 0 - FindBin 0 - Getopt::Long 0 - HTML::Form 6 - HTML::HeadParser 0 - HTML::Parser 3.33 - HTML::TokeParser 2.28 - HTML::TreeBuilder 0 - HTTP::Daemon 0 - HTTP::Request 1.3 - HTTP::Server::Simple 0.35 - HTTP::Server::Simple::CGI 0 - HTTP::Status 0 - LWP 5.829 - LWP::UserAgent 5.829 - Pod::Usage 0 - Test::More 0.34 - Test::Warn 0.11 - URI 1.36 - URI::URL 0 - URI::file 0 + IO::Handle 0 + IO::Select 0 + IPC::Open3 0 + POSIX 0 + Socket 0 + Test::More 0 + XSLoader 0 + base 0 + lib 0 perl 5.008 - WWW-Mechanize-Cached-1.43 - pathname: O/OA/OALDERS/WWW-Mechanize-Cached-1.43.tar.gz + WWW-Form-UrlEncoded-0.26 + pathname: K/KA/KAZEBURO/WWW-Form-UrlEncoded-0.26.tar.gz + provides: + WWW::Form::UrlEncoded 0.26 + WWW::Form::UrlEncoded::PP undef + requirements: + Exporter 0 + Module::Build 0.4005 + perl 5.008001 + WWW-OAuth-1.003 + pathname: D/DB/DBOOK/WWW-OAuth-1.003.tar.gz provides: - TestCache undef - WWW::Mechanize::Cached 1.43 + WWW::OAuth 1.003 + WWW::OAuth::Request 1.003 + WWW::OAuth::Request::Basic 1.003 + WWW::OAuth::Request::HTTP_Request 1.003 + WWW::OAuth::Request::Mojo 1.003 + WWW::OAuth::Util 1.003 requirements: - Cache::FileCache 0 Carp 0 - Data::Dump 0 - ExtUtils::MakeMaker 6.30 - Module::Build 0.3601 - Moose 0 - Storable 2.21 - WWW::Mechanize 0 - strict 0 - warnings 0 + Class::Tiny::Chained 0 + Crypt::SysRandom 0 + Digest::SHA 0 + ExtUtils::MakeMaker 0 + List::Util 1.33 + Module::Runtime 0 + Role::Tiny 2.000000 + Scalar::Util 0 + URI 1.28 + URI::Escape 3.26 + WWW::Form::UrlEncoded 0.23 + perl 5.008001 WWW-RobotRules-6.02 pathname: G/GA/GAAS/WWW-RobotRules-6.02.tar.gz provides: @@ -7871,18 +7978,11 @@ DISTRIBUTIONS Fcntl 0 URI 1.10 perl 5.008001 - XML-NamespaceSupport-1.11 - pathname: P/PE/PERIGRIN/XML-NamespaceSupport-1.11.tar.gz - provides: - XML::NamespaceSupport 1.11 - requirements: - ExtUtils::MakeMaker 6.42 - Test::More 0.47 - XML-Parser-2.41 - pathname: T/TO/TODDR/XML-Parser-2.41.tar.gz + XML-Parser-2.47 + pathname: T/TO/TODDR/XML-Parser-2.47.tar.gz provides: - XML::Parser 2.41 - XML::Parser::Expat 2.41 + XML::Parser 2.47 + XML::Parser::Expat 2.47 XML::Parser::Style::Debug undef XML::Parser::Style::Objects undef XML::Parser::Style::Stream undef @@ -7890,231 +7990,364 @@ DISTRIBUTIONS XML::Parser::Style::Tree undef requirements: ExtUtils::MakeMaker 0 - LWP 0 + LWP::UserAgent 0 perl 5.00405 - XML-SAX-0.99 - pathname: G/GR/GRANTM/XML-SAX-0.99.tar.gz - provides: - XML::SAX 0.99 - XML::SAX::DocumentLocator undef - XML::SAX::ParserFactory 1.01 - XML::SAX::PurePerl 0.99 - XML::SAX::PurePerl::DebugHandler undef - XML::SAX::PurePerl::Exception undef - XML::SAX::PurePerl::Productions undef - XML::SAX::PurePerl::Reader undef - XML::SAX::PurePerl::Reader::Stream undef - XML::SAX::PurePerl::Reader::String undef - XML::SAX::PurePerl::Reader::URI undef - requirements: - ExtUtils::MakeMaker 0 - File::Temp 0 - XML::NamespaceSupport 0.03 - XML::SAX::Base 1.05 - XML-SAX-Base-1.08 - pathname: G/GR/GRANTM/XML-SAX-Base-1.08.tar.gz - provides: - XML::SAX::Base 1.08 - XML::SAX::Base::NoHandler 1.08 - XML::SAX::Exception 1.08 - requirements: - ExtUtils::MakeMaker 6.31 - Test::More 0.88 - XML-SAX-Expat-0.51 - pathname: B/BJ/BJOERN/XML-SAX-Expat-0.51.tar.gz + XML-XPath-1.48 + pathname: M/MA/MANWAR/XML-XPath-1.48.tar.gz + provides: + XML::XPath 1.48 + XML::XPath::Boolean 1.48 + XML::XPath::Builder 1.48 + XML::XPath::Expr 1.48 + XML::XPath::Function 1.48 + XML::XPath::Literal 1.48 + XML::XPath::LocationPath 1.48 + XML::XPath::Node 1.48 + XML::XPath::Node::Attribute 1.48 + XML::XPath::Node::AttributeImpl 1.48 + XML::XPath::Node::Comment 1.48 + XML::XPath::Node::Element 1.48 + XML::XPath::Node::Namespace 1.48 + XML::XPath::Node::PI 1.48 + XML::XPath::Node::Text 1.48 + XML::XPath::NodeSet 1.48 + XML::XPath::Number 1.48 + XML::XPath::Parser 1.48 + XML::XPath::PerlSAX 1.48 + XML::XPath::Root 1.48 + XML::XPath::Step 1.48 + XML::XPath::Variable 1.48 + XML::XPath::XMLParser 1.48 + requirements: + ExtUtils::MakeMaker 0 + Path::Tiny 0.076 + Scalar::Util 1.45 + Test::More 0 + XML::Parser 2.23 + perl 5.010001 + XSLoader-0.24 + pathname: S/SA/SAPER/XSLoader-0.24.tar.gz provides: - XML::SAX::Expat 0.51 + XSLoader 0.24 requirements: ExtUtils::MakeMaker 0 - XML::NamespaceSupport 0.03 - XML::Parser 2.27 - XML::SAX 0.03 - XML::SAX::Base 1.00 - XML-Simple-2.20 - pathname: G/GR/GRANTM/XML-Simple-2.20.tar.gz + Test::More 0.47 + XString-0.005 + pathname: A/AT/ATOOMIC/XString-0.005.tar.gz provides: - TagsToUpper undef - XML::Simple 2.20 + XString 0.005 requirements: - ExtUtils::MakeMaker 6.31 - Test::More 0.88 - XML::NamespaceSupport 1.04 - XML::SAX 0.15 - XML::SAX::Expat 0 - YAML-0.92 - pathname: I/IN/INGY/YAML-0.92.tar.gz - provides: - Test::YAML 0.92 - Test::YAML::Filter 0.92 - YAML 0.92 - YAML::Any 0.92 - YAML::Dumper 0.92 - YAML::Dumper::Base 0.92 - YAML::Error 0.92 - YAML::Loader 0.92 - YAML::Loader::Base 0.92 - YAML::Marshall 0.92 - YAML::Mo 0.92 - YAML::Node 0.92 - YAML::Tag 0.92 - YAML::Type::blessed 0.92 - YAML::Type::code 0.92 - YAML::Type::glob 0.92 - YAML::Type::ref 0.92 - YAML::Type::regexp 0.92 - YAML::Type::undef 0.92 - YAML::Types 0.92 - YAML::Warning 0.92 - yaml_mapping 0.92 - yaml_scalar 0.92 - yaml_sequence 0.92 + ExtUtils::MakeMaker 0 + perl 5.008 + YAML-1.31 + pathname: I/IN/INGY/YAML-1.31.tar.gz + provides: + YAML 1.31 + YAML::Any 1.31 + YAML::Dumper undef + YAML::Dumper::Base undef + YAML::Error undef + YAML::Loader undef + YAML::Loader::Base undef + YAML::Marshall undef + YAML::Mo undef + YAML::Node undef + YAML::Tag undef + YAML::Type::blessed undef + YAML::Type::code undef + YAML::Type::glob undef + YAML::Type::ref undef + YAML::Type::regexp undef + YAML::Type::undef undef + YAML::Types undef + YAML::Warning undef + yaml_mapping undef + yaml_scalar undef + yaml_sequence undef requirements: - ExtUtils::MakeMaker 6.30 - YAML-Syck-1.27 - pathname: T/TO/TODDR/YAML-Syck-1.27.tar.gz + ExtUtils::MakeMaker 0 + perl 5.008001 + YAML-LibYAML-v0.903.0 + pathname: T/TI/TINITA/YAML-LibYAML-v0.903.0.tar.gz provides: - JSON::Syck 1.27 - YAML::Dumper::Syck undef - YAML::Loader::Syck undef - YAML::Syck 1.27 + YAML::LibYAML v0.903.0 + YAML::XS v0.903.0 requirements: - ExtUtils::MakeMaker 6.59 - perl 5.006 - aliased-0.31 - pathname: O/OV/OVID/aliased-0.31.tar.gz - provides: - aliased 0.31 + B::Deparse 0 + Exporter 0 + ExtUtils::MakeMaker 0 + Scalar::Util 0 + base 0 + constant 0 + perl 5.008001 + strict 0 + warnings 0 + YAML-PP-v0.39.0 + pathname: T/TI/TINITA/YAML-PP-v0.39.0.tar.gz + provides: + YAML::PP v0.39.0 + YAML::PP::Common v0.39.0 + YAML::PP::Constructor v0.39.0 + YAML::PP::Dumper v0.39.0 + YAML::PP::Emitter v0.39.0 + YAML::PP::Exception v0.39.0 + YAML::PP::Grammar v0.39.0 + YAML::PP::Highlight v0.39.0 + YAML::PP::Lexer v0.39.0 + YAML::PP::Loader v0.39.0 + YAML::PP::Parser v0.39.0 + YAML::PP::Perl v0.39.0 + YAML::PP::Preserve::Array v0.39.0 + YAML::PP::Preserve::Hash v0.39.0 + YAML::PP::Preserve::Scalar v0.39.0 + YAML::PP::Reader v0.39.0 + YAML::PP::Reader::File v0.39.0 + YAML::PP::Render v0.39.0 + YAML::PP::Representer v0.39.0 + YAML::PP::Schema v0.39.0 + YAML::PP::Schema::Binary v0.39.0 + YAML::PP::Schema::Catchall v0.39.0 + YAML::PP::Schema::Core v0.39.0 + YAML::PP::Schema::Failsafe v0.39.0 + YAML::PP::Schema::Include v0.39.0 + YAML::PP::Schema::JSON v0.39.0 + YAML::PP::Schema::Merge v0.39.0 + YAML::PP::Schema::Perl v0.39.0 + YAML::PP::Schema::Tie::IxHash v0.39.0 + YAML::PP::Schema::YAML1_1 v0.39.0 + YAML::PP::Type::MergeKey v0.39.0 + YAML::PP::Writer v0.39.0 + YAML::PP::Writer::File v0.39.0 requirements: - Test::More 0 - bareword-filehandles-0.003 - pathname: I/IL/ILMARI/bareword-filehandles-0.003.tar.gz + B 0 + B::Deparse 0 + Carp 0 + Data::Dumper 0 + Encode 0 + Exporter 0 + ExtUtils::MakeMaker 0 + File::Basename 0 + Getopt::Long 0 + MIME::Base64 0 + Module::Load 0 + Scalar::Util 1.07 + Tie::Array 0 + Tie::Hash 0 + base 0 + constant 0 + overload 0 + perl 5.008000 + strict 0 + warnings 0 + bareword-filehandles-0.007 + pathname: I/IL/ILMARI/bareword-filehandles-0.007.tar.gz provides: - bareword::filehandles 0.003 - inc::BarewordFilehandlesMakeMaker undef + bareword::filehandles 0.007 requirements: B::Hooks::OP::Check 0 ExtUtils::Depends 0 - ExtUtils::MakeMaker 6.31 - Lexical::SealRequireHints 0 + ExtUtils::MakeMaker 0 Test::More 0.88 XSLoader 0 - common-sense-3.73 - pathname: M/ML/MLEHMANN/common-sense-3.73.tar.gz + if 0 + perl 5.008001 + strict 0 + warnings 0 + common-sense-3.75 + pathname: M/ML/MLEHMANN/common-sense-3.75.tar.gz provides: - common::sense 3.73 + common::sense 3.75 requirements: ExtUtils::MakeMaker 0 - indirect-0.31 - pathname: V/VP/VPIT/indirect-0.31.tar.gz + indirect-0.39 + pathname: V/VP/VPIT/indirect-0.39.tar.gz provides: - indirect 0.31 + indirect 0.39 requirements: Carp 0 Config 0 ExtUtils::MakeMaker 0 + File::Spec 0 + IO::Handle 0 + IO::Select 0 + IPC::Open3 0 + POSIX 0 + Socket 0 Test::More 0 XSLoader 0 + lib 0 perl 5.008001 - libwww-perl-6.06 - pathname: M/MS/MSCHILLI/libwww-perl-6.06.tar.gz - provides: - LWP 6.06 - LWP::Authen::Basic undef - LWP::Authen::Digest undef - LWP::Authen::Ntlm 6.00 - LWP::ConnCache 6.02 - LWP::Debug undef - LWP::DebugFile undef - LWP::MemberMixin undef - LWP::Protocol 6.06 - LWP::Protocol::GHTTP undef - LWP::Protocol::MyFTP undef - LWP::Protocol::cpan undef - LWP::Protocol::data undef - LWP::Protocol::file undef - LWP::Protocol::ftp undef - LWP::Protocol::gopher undef - LWP::Protocol::http undef - LWP::Protocol::http::Socket undef - LWP::Protocol::http::SocketMethods undef - LWP::Protocol::loopback undef - LWP::Protocol::mailto undef - LWP::Protocol::nntp undef - LWP::Protocol::nogo undef - LWP::RobotUA 6.06 - LWP::Simple 6.00 - LWP::UserAgent 6.06 + libnet-3.15 + pathname: S/SH/SHAY/libnet-3.15.tar.gz + provides: + Net undef + Net::Cmd 3.15 + Net::Config 3.15 + Net::Domain 3.15 + Net::FTP 3.15 + Net::FTP::A 3.15 + Net::FTP::E 3.15 + Net::FTP::I 3.15 + Net::FTP::L 3.15 + Net::FTP::dataconn 3.15 + Net::NNTP 3.15 + Net::NNTP::_SSL 3.15 + Net::Netrc 3.15 + Net::POP3 3.15 + Net::POP3::_SSL 3.15 + Net::SMTP 3.15 + Net::SMTP::_SSL 3.15 + Net::Time 3.15 + requirements: + Carp 0 + Errno 0 + Exporter 0 + ExtUtils::MakeMaker 6.64 + Fcntl 0 + File::Basename 0 + FileHandle 0 + Getopt::Std 0 + IO::File 0 + IO::Select 0 + IO::Socket 1.05 + POSIX 0 + Socket 2.016 + Symbol 0 + Time::Local 0 + constant 0 + perl 5.008001 + strict 0 + utf8 0 + vars 0 + warnings 0 + libwww-perl-6.78 + pathname: O/OA/OALDERS/libwww-perl-6.78.tar.gz + provides: + LWP 6.78 + LWP::Authen::Basic 6.78 + LWP::Authen::Digest 6.78 + LWP::Authen::Ntlm 6.78 + LWP::ConnCache 6.78 + LWP::Debug 6.78 + LWP::Debug::TraceHTTP 6.78 + LWP::DebugFile 6.78 + LWP::MemberMixin 6.78 + LWP::Protocol 6.78 + LWP::Protocol::cpan 6.78 + LWP::Protocol::data 6.78 + LWP::Protocol::file 6.78 + LWP::Protocol::ftp 6.78 + LWP::Protocol::gopher 6.78 + LWP::Protocol::http 6.78 + LWP::Protocol::loopback 6.78 + LWP::Protocol::mailto 6.78 + LWP::Protocol::nntp 6.78 + LWP::Protocol::nogo 6.78 + LWP::RobotUA 6.78 + LWP::Simple 6.78 + LWP::UserAgent 6.78 requirements: - Data::Dump 0 Digest::MD5 0 Encode 2.12 Encode::Locale 0 ExtUtils::MakeMaker 0 + File::Copy 0 File::Listing 6 + File::Temp 0 + Getopt::Long 0 HTML::Entities 0 - HTML::HeadParser 0 + HTML::HeadParser 3.71 HTTP::Cookies 6 - HTTP::Daemon 6 HTTP::Date 6 HTTP::Negotiate 6 - HTTP::Request 6 - HTTP::Request::Common 6 - HTTP::Response 6 - HTTP::Status 6 + HTTP::Request 6.18 + HTTP::Request::Common 6.18 + HTTP::Response 6.18 + HTTP::Status 6.18 IO::Select 0 IO::Socket 0 LWP::MediaTypes 6 MIME::Base64 2.1 + Module::Load 0 Net::FTP 2.58 - Net::HTTP 6.04 + Net::HTTP 6.18 + Scalar::Util 0 + Try::Tiny 0 URI 1.10 URI::Escape 0 WWW::RobotRules 6 + parent 0.217 perl 5.008001 - multidimensional-0.011 - pathname: I/IL/ILMARI/multidimensional-0.011.tar.gz + strict 0 + warnings 0 + multidimensional-0.014 + pathname: I/IL/ILMARI/multidimensional-0.014.tar.gz provides: - MyTest undef - inc::MultidimensionalMakeMaker undef - multidimensional 0.011 + multidimensional 0.014 requirements: B::Hooks::OP::Check 0.19 CPAN::Meta 2.112580 ExtUtils::Depends 0 - ExtUtils::MakeMaker 6.30 - Lexical::SealRequireHints 0.005 + ExtUtils::MakeMaker 0 Test::More 0.88 XSLoader 0 + if 0 + perl 5.008001 strict 0 warnings 0 - namespace-autoclean-0.15 - pathname: E/ET/ETHER/namespace-autoclean-0.15.tar.gz + namespace-autoclean-0.31 + pathname: E/ET/ETHER/namespace-autoclean-0.31.tar.gz provides: - namespace::autoclean 0.15 + namespace::autoclean 0.31 requirements: + B 0 B::Hooks::EndOfScope 0.12 - Class::MOP 0.80 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 List::Util 0 - Module::Build::Tiny 0.030 namespace::clean 0.20 perl 5.006 strict 0 warnings 0 - namespace-clean-0.25 - pathname: R/RI/RIBASUSHI/namespace-clean-0.25.tar.gz + namespace-clean-0.27 + pathname: R/RI/RIBASUSHI/namespace-clean-0.27.tar.gz provides: - namespace::clean 0.25 + namespace::clean 0.27 requirements: B::Hooks::EndOfScope 0.12 - ExtUtils::CBuilder 0.27 + ExtUtils::MakeMaker 0 Package::Stash 0.23 - Test::More 0.88 - strictures-1.005004 - pathname: H/HA/HAARG/strictures-1.005004.tar.gz + perl 5.008001 + podlators-v6.0.2 + pathname: R/RR/RRA/podlators-v6.0.2.tar.gz + provides: + Pod undef + Pod::Man v6.0.2 + Pod::ParseLink v6.0.2 + Pod::Text v6.0.2 + Pod::Text::Color v6.0.2 + Pod::Text::Overstrike v6.0.2 + Pod::Text::Termcap v6.0.2 + requirements: + ExtUtils::MakeMaker 0 + Pod::Simple 3.26 + perl 5.012 + strictures-2.000006 + pathname: H/HA/HAARG/strictures-2.000006.tar.gz provides: - strictures 1.005004 + strictures 2.000006 + strictures::extra undef requirements: bareword::filehandles 0 indirect 0 multidimensional 0 + perl 5.006 + version-0.9933 + pathname: L/LE/LEONT/version-0.9933.tar.gz + provides: + version 0.9933 + version::regex 0.9933 + version::vpp 0.9933 + version::vxs 0.9933 + requirements: + ExtUtils::MakeMaker 0 + perl 5.006002 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..99066703d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,64 @@ +services: + api-server: + build: + context: . + target: develop + volumes: + - './:/app/' + - '/app/local' + ports: + - '8001:8000' + environment: + # default is 120, shorten to work with compose label + COLUMNS: 96 + develop: + watch: + - path: ./cpanfile + action: rebuild + + api-test: + profiles: + - test + depends_on: + elasticsearch-test: + condition: service_healthy + build: + context: . + target: test + environment: + NET_ASYNC_HTTP_MAXCONNS: 1 + COLUMNS: 80 + ES: http://elasticsearch-test:9200 + HARNESS_ACTIVE: 1 + # Instantiate Catalyst models using metacpan_server_testing.conf + METACPAN_SERVER_CONFIG_LOCAL_SUFFIX: testing + MINICPAN: /CPAN + DEVEL_COVER_OPTIONS: +ignore,^t/|^test-data/|^etc/|^local/ + networks: + - elasticsearch + volumes: + - type: volume + source: elasticsearch-test + target: /usr/share/elasticsearch/data + + elasticsearch-test: + profiles: + - test + platform: linux/amd64 + image: elasticsearch:2.4 + environment: + - discovery.type=single-node + healthcheck: + timeout: 5s + start_period: 60s + test: ["CMD", "curl", "--fail", "http://localhost:9200/_cluster/health?wait_for_status=yellow&timeout=5s"] + ports: + - "9200" + networks: + - elasticsearch + +networks: + elasticsearch: + +volumes: + elasticsearch-test: diff --git a/docs/API-docs.md b/docs/API-docs.md index dc77cf795..10137aa6d 100644 --- a/docs/API-docs.md +++ b/docs/API-docs.md @@ -1,91 +1,59 @@ -# API Docs: v0 +# API Docs: v1 -For an introduction to the MetaCPAN API which requires no previous knowledge of MetaCPAN or ElasticSearch, see [the slides for "Abusing MetaCPAN for Fun and Profit"](http://www.slideshare.net/oalders/abusing-metacpan2013) or [watch the actual talk](http://www.youtube.com/watch?v=J8ymBuFlHQg). +For an introduction to the MetaCPAN API (Application Program Interface) which requires no previous knowledge of MetaCPAN or ElasticSearch, see [the slides for "Abusing MetaCPAN for Fun and Profit"](https://www.slideshare.net/oalders/abusing-metacpan2013) or [watch the actual talk](https://www.youtube.com/watch?v=J8ymBuFlHQg). This API lets you programmatically access MetaCPAN from your own applications. -There is also [a repository of examples](https://github.com/CPAN-API/metacpan-examples) you can play with to get up and running in a hurry. Rather than editing this wiki page, please send pull requests for the metacpan-examples repository. If you'd rather edit the wiki, please do, but sending the code pull requests is probably the most helpful way to approach this. +There is also [a repository of examples](https://github.com/metacpan/metacpan-examples) you can play with to get up and running in a hurry. Rather than editing this wiki page, please send pull requests for the metacpan-examples repository. If you'd rather edit the wiki, please do, but sending the code pull requests is probably the most helpful way to approach this. _All of these URLs can be tested using the [MetaCPAN Explorer](https://explorer.metacpan.org)_ -To learn more about the ElasticSearch query DSL check out Clinton Gormley's [Terms of Endearment - ES Query DSL Explained] (http://www.slideshare.net/clintongormley/terms-of-endearment-the-elasticsearch-query-dsl-explained) slides. +To learn more about the ElasticSearch query DSL (Domain-Specific Language) check out Clinton Gormley's [Terms of Endearment - ES Query DSL Explained](https://www.slideshare.net/clintongormley/terms-of-endearment-the-elasticsearch-query-dsl-explained) slides. -The query syntax is explained on ElasticSearch's [reference page](http://www.elasticsearch.org/guide/reference/query-dsl/). You can also check out this getting started tutorial about Elasticsearch [reference page](http://joelabrahamsson.com/elasticsearch-101/). +The query syntax is explained on ElasticSearch's [reference page](https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl.html). You can also check out this getting started tutorial about Elasticsearch [reference page](http://joelabrahamsson.com/elasticsearch-101/). ## Being polite -Currently, the only rules around using the API are to "be polite". We have enforced an upper limit of a size of 5000 on search requests. If you need to fetch more than 5000 items, you should look at using the scrolling API. Search this page for "scroll" to get an example using [Search::Elasticsearch](https://metacpan.org/pod/Search::Elasticsearch) or see the [Elasticsearch scroll docs](http://www.elasticsearch.org/guide/reference/api/search/scroll.html) if you are connecting in some other way. +Currently, the only rules around using the API are to "be polite". We have enforced an upper limit of a size of 5,000 on search requests. If you need to fetch more than 5,000 items, you should look at using the scrolling API. Search this page for "scroll" to get an example using [Search::Elasticsearch](https://metacpan.org/pod/Search::Elasticsearch) or see the [Elasticsearch scroll docs](https://www.elastic.co/guide/en/elasticsearch/reference/2.4/search-request-scroll.html) if you are connecting in some other way. -You can certainly scroll if you are fetching less than 5000 items. You might want to do this if you are expecting a large data set, but will still need to run many requests to get all of the required data. +You can certainly scroll if you are fetching less than 5,000 items. You might want to do this if you are expecting a large data set, but will still need to run many requests to get all of the required data. -Be aware that when you scroll, your docs will come back unsorted, as noted in the [ElasticSearch scan documentation](http://www.elasticsearch.org/guide/reference/api/search/search-type.html). +Be aware that when you scroll, your docs will come back unsorted, as noted in the [ElasticSearch scan documentation](https://www.elastic.co/guide/en/elasticsearch/reference/2.4/search-request-search-type.html#scan). ## Identifying Yourself -Part of being polite is letting us know who you are and how to reach you. This is not mandatory, but please do consider adding your app to the [API-Consumers](https://github.com/CPAN-API/cpan-api/wiki/API-Consumers) page. +Part of being polite is letting us know who you are and how to reach you. This is not mandatory, but please do consider adding your app to the [API-Consumers](https://github.com/metacpan/metacpan-api/wiki/fastapi-Consumers) page. ## Available fields Available fields can be found by accessing the corresponding `_mapping` endpoint. -* [/author/_mapping](http://api.metacpan.org/v0/author/_mapping) - [explore](https://explorer.metacpan.org/?url=/author/_mapping) -* [/distribution/_mapping](http://api.metacpan.org/v0/distribution/_mapping) - [explore](https://explorer.metacpan.org/?url=/distribution/_mapping) -* [/favorite/_mapping](http://api.metacpan.org/v0/favorite/_mapping) - [explore](https://explorer.metacpan.org/?url=/favorite/_mapping) -* [/file/_mapping](http://api.metacpan.org/v0/file/_mapping) - [explore](https://explorer.metacpan.org/?url=/file/_mapping) -* [/module/_mapping](http://api.metacpan.org/v0/module/_mapping) - [explore](https://explorer.metacpan.org/?url=/module/_mapping) -* [/rating/_mapping](http://api.metacpan.org/v0/rating/_mapping) - [explore](https://explorer.metacpan.org/?url=/rating/_mapping) -* [/release/_mapping](http://api.metacpan.org/v0/release/_mapping) - [explore](https://explorer.metacpan.org/?url=/release/_mapping) +* [`/author/_mapping`](https://fastapi.metacpan.org/v1/author/_mapping) - [explore](https://explorer.metacpan.org/?url=/author/_mapping) +* [`/distribution/_mapping`](https://fastapi.metacpan.org/v1/distribution/_mapping) - [explore](https://explorer.metacpan.org/?url=/distribution/_mapping) +* [`/favorite/_mapping`](https://fastapi.metacpan.org/v1/favorite/_mapping) - [explore](https://explorer.metacpan.org/?url=/favorite/_mapping) +* [`/file/_mapping`](https://fastapi.metacpan.org/v1/file/_mapping) - [explore](https://explorer.metacpan.org/?url=/file/_mapping) +* [`/module/_mapping`](https://fastapi.metacpan.org/v1/module/_mapping) - [explore](https://explorer.metacpan.org/?url=/module/_mapping) +* [`/release/_mapping`](https://fastapi.metacpan.org/v1/release/_mapping) - [explore](https://explorer.metacpan.org/?url=/release/_mapping) ## Field documentation -Fields are documented in the API codebase: https://github.com/CPAN-API/cpan-api/tree/master/lib/MetaCPAN/Document Check the Pod for discussion of what the various fields represent. Be sure to have a look at https://github.com/CPAN-API/cpan-api/blob/master/lib/MetaCPAN/Document/File.pm in particular as results for /module are really a thin wrapper around the `file` type. +Fields are documented in the API codebase: https://github.com/metacpan/metacpan-api/tree/master/lib/MetaCPAN/Document Check the Pod for discussion of what the various fields represent. Be sure to have a look at https://github.com/metacpan/metacpan-api/blob/master/lib/MetaCPAN/Document/File.pm in particular as results for /module are really a thin wrapper around the `file` type. ## Search without constraints Performing a search without any constraints is an easy way to get sample data -* [/author/_search](http://api.metacpan.org/v0/author/_search) -* [/distribution/_search](http://api.metacpan.org/v0/distribution/_search) -* [/favorite/_search](http://api.metacpan.org/v0/favorite/_search) -* [/file/_search](http://api.metacpan.org/v0/file/_search) -* [/rating/_search](http://api.metacpan.org/v0/rating/_search) -* [/release/_search](http://api.metacpan.org/v0/release/_search) - -## Joins - -ElasticSearch itself doesn't support joining data across multiple types. The API server can, however, handle a `join` query parameter if the underlying type was set up accordingly. Browse https://github.com/CPAN-API/cpan-api/blob/master/lib/MetaCPAN/Server/Controller/ to see all join conditions. Here are some examples. - -Joins on documents: - -* [/author/PERLER?join=favorite](http://api.metacpan.org/v0/author/PERLER?join=favorite) -* [/author/PERLER?join=favorite&join=release](http://api.metacpan.org/v0/author/PERLER?join=favorite&join=release) -* [/release/Moose?join=author](http://api.metacpan.org/v0/release/Moose?join=author) -* [/module/Moose?join=release](http://api.metacpan.org/v0/module/Moose?join=release) - -Joins on search results is work in progress. - -Restricting the joined results can be done by using the [boolean "should"](http://www.elasticsearch.org/guide/reference/query-dsl/bool-query.html) occurrence type: - -```sh -curl -XPOST http://api.metacpan.org/v0/author/PERLER?join=release -d ' -{ - "query": { - "bool": { - "should": [{ - "term": { - "release.status": "latest" - } - }] - } - } -}' -``` +* [`/author/_search`](https://fastapi.metacpan.org/v1/author/_search) +* [`/distribution/_search`](https://fastapi.metacpan.org/v1/distribution/_search) +* [`/favorite/_search`](https://fastapi.metacpan.org/v1/favorite/_search) +* [`/file/_search`](https://fastapi.metacpan.org/v1/file/_search) +* [`/release/_search`](https://fastapi.metacpan.org/v1/release/_search) ## JSONP Simply add a `callback` query parameter with the name of your callback, and you'll get a JSONP response. -* [/favorite?q=distribution:Moose&callback=cb](http://api.metacpan.org/favorite?q=distribution:Moose&callback=cb) +* [/favorite?q=distribution:Moose&callback=cb](https://fastapi.metacpan.org/favorite?q=distribution:Moose&callback=cb) ## GET convenience URLs @@ -93,27 +61,41 @@ You should be able to run most POST queries, but very few GET urls are currently ### `/distribution/{distribution}` -The `/distribution` endpoint accepts the name of a `distribution` (e.g. [/distribution/Moose](http://api.metacpan.org/v0/distribution/Moose)), which returns information about the distribution which is not specific to a version (like RT bug counts). +The `/distribution` endpoint accepts the name of a `distribution` (e.g. [/distribution/Moose](https://fastapi.metacpan.org/v1/distribution/Moose)), which returns information about the distribution which is not specific to a version (like RT bug counts). + +### `/download_url/{module}` + +The `/download_url` endpoint exists specifically for the `cpanm` client. It takes a module name with an optional version (or range of versions) and an optional `dev` flag (for development releases) and returns a `download_url` as well as some other helpful info. + +Obviously anyone can use this endpoint, but we'll only consider changes to this endpoint after considering how `cpanm` might be affected. + +* [`https://fastapi.metacpan.org/v1/download_url/HTTP::Tiny`](https://fastapi.metacpan.org/v1/download_url/HTTP::Tiny) +* [`https://fastapi.metacpan.org/v1/download_url/Moose?version===0.01`](https://fastapi.metacpan.org/v1/download_url/Moose?version===0.01) +* [`https://fastapi.metacpan.org/v1/download_url/Moose?version=!=0.01`](https://fastapi.metacpan.org/v1/download_url/Moose?version=!=0.01) +* [`https://fastapi.metacpan.org/v1/download_url/Moose?version=<=0.02`](https://fastapi.metacpan.org/v1/download_url/Moose?version=<=0.02) +* [`https://fastapi.metacpan.org/v1/download_url/Try::Tiny?version=>0.21,<0.27,!=0.24`](https://fastapi.metacpan.org/v1/download_url/Try::Tiny?version=>0.21,<0.27,!=0.24) +* [`https://fastapi.metacpan.org/v1/download_url/Try::Tiny?version=>0.21,<0.27&dev=1`](https://fastapi.metacpan.org/v1/download_url/Try::Tiny?version=>0.21,<0.27&dev=1) +* [`https://fastapi.metacpan.org/v1/download_url/Try::Tiny?version=>0.21,<0.27,!=0.26&dev=1`](https://fastapi.metacpan.org/v1/download_url/Try::Tiny?version=>0.21,<0.27,!=0.26&dev=1) ### `/release/{distribution}` ### `/release/{author}/{release}` -The `/release` endpoint accepts either the name of a `distribution` (e.g. [/release/Moose](http://api.metacpan.org/v0/release/Moose)), which returns the most recent release of the distribution. Or provide the full path which consists of its `author` and the name of the `release` (e.g. [/release/DOY/Moose-2.0001](http://api.metacpan.org/v0/release/DOY/Moose-2.0001)). +The `/release` endpoint accepts either the name of a `distribution` (e.g. [`/release/Moose`](https://fastapi.metacpan.org/v1/release/Moose)), which returns the most recent release of the distribution. Or provide the full path which consists of its `author` and the name of the `release` (e.g. [`/release/DOY/Moose-2.0001`](https://fastapi.metacpan.org/v1/release/DOY/Moose-2.0001)). ### `/author/{author}` -`author` refers to the pauseid of the author. It must be uppercased (e.g. [/author/DOY](http://api.metacpan.org/v0/author/DOY)). +`author` refers to the pauseid of the author. It must be uppercased (e.g. [`/author/DOY`](https://fastapi.metacpan.org/v1/author/DOY)). ### `/module/{module}` -Returns the corresponding `file` of the latest version of the `module`. Considering that Moose-2.0001 is the latest release, the result of [/module/Moose](http://api.metacpan.org/v0/module/Moose) is the same as [/file/DOY/Moose-2.0001/lib/Moose.pm](http://api.metacpan.org/v0/file/DOY/Moose-2.0001/lib/Moose.pm). +Returns the corresponding `file` of the latest version of the `module`. Considering that Moose-2.0001 is the latest release, the result of [`/module/Moose`](https://fastapi.metacpan.org/v1/module/Moose) is the same as [`/file/DOY/Moose-2.0001/lib/Moose.pm`](https://fastapi.metacpan.org/v1/file/DOY/Moose-2.0001/lib/Moose.pm). ### `/pod/{module}` ### `/pod/{author}/{release}/{path}` -Returns the POD of the given module. You can change the output format by either passing a `content-type` query parameter (e.g. [/pod/Moose?content-type=text/plain](http://api.metacpan.org/v0/pod/Moose?content-type=text/plain) or by adding an `Accept` header to the HTTP request. Valid content types are: +Returns the POD of the given module. You can change the output format by either passing a `content-type` query parameter (e.g. [`/pod/Moose?content-type=text/plain`](https://fastapi.metacpan.org/v1/pod/Moose?content-type=text/plain) or by adding an `Accept` header to the HTTP request. Valid content types are: * text/html (default) * text/plain @@ -129,87 +111,57 @@ Returns the full source of the latest, authorized version of the given Names of latest releases by OALDERS: -http://api.metacpan.org/v0/release/_search?q=author:OALDERS%20AND%20status:latest&fields=name,status&size=100 +[`https://fastapi.metacpan.org/v1/release/_search?q=author:OALDERS%20AND%20status:latest&fields=name,status&size=100`](https://fastapi.metacpan.org/v1/release/_search?q=author:OALDERS%20AND%20status:latest&fields=name,status&size=100) -All CPAN Authors: +5,000 CPAN Authors: -[http://api.metacpan.org/v0/author/_search?pretty=true&q=*&size=100000](http://api.metacpan.org/author/_search?pretty=true&q=*) +[`https://fastapi.metacpan.org/v1/author/_search?q=*&size=5000`](https://fastapi.metacpan.org/author/_search?q=*) All CPAN Authors Who Have Provided Twitter IDs: -http://api.metacpan.org/v0/author/_search?pretty=true&q=author.profile.name:twitter +https://fastapi.metacpan.org/v1/author/_search?q=profile.name:twitter All CPAN Authors Who Have Updated MetaCPAN Profiles: -http://api.metacpan.org/v0/author/_search?q=updated:*&sort=updated:desc +https://fastapi.metacpan.org/v1/author/_search?q=updated:*&sort=updated:desc First 100 distributions which SZABGAB has given a ++: - http://api.metacpan.org/v0/favorite/_search?q=user:sWuxlxYeQBKoCQe1f-FQ_Q&size=100&fields=distribution +https://fastapi.metacpan.org/v1/favorite/_search?q=user:sWuxlxYeQBKoCQe1f-FQ_Q&size=100&fields=distribution The 100 most recent releases ( similar to https://metacpan.org/recent ) - http://api.metacpan.org/v0/release/_search?q=status:latest&fields=name,status,date&sort=date:desc&size=100 +https://fastapi.metacpan.org/v1/release/_search?q=status:latest&fields=name,status,date&sort=date:desc&size=100 Number of ++'es that DOY's dists have received: -http://api.metacpan.org/v0/favorite/_search?q=author:DOY&size=0 +https://fastapi.metacpan.org/v1/favorite/_search?q=author:DOY&size=0 List of users who have ++'ed DOY's dists and the dists they have ++'ed: -http://api.metacpan.org/v0/favorite/_search?q=author:DOY&fields=user,distribution +https://fastapi.metacpan.org/v1/favorite/_search?q=author:DOY&fields=user,distribution Last 50 dists to get a ++: -http://api.metacpan.org/v0/favorite/_search?size=50&fields=author,user,release,date&sort=date:desc +https://fastapi.metacpan.org/v1/favorite/_search?size=50&fields=author,user,release,date&sort=date:desc The Changes file of the Test-Simple distribution: -http://api.metacpan.org/v0/changes/Test-Simple +https://fastapi.metacpan.org/v1/changes/Test-Simple ## Querying the API with MetaCPAN::Client -Perhaps the easiest way to get started using MetaCPAN is with [MetaCPAN::Client](https://metacpan.org/pod/MetaCPAN::Client). +Perhaps the easiest way to get started using MetaCPAN is with [MetaCPAN::Client](https://metacpan.org/pod/MetaCPAN::Client). -```perl -use MetaCPAN::Client (); -my $mcpan = MetaCPAN::Client->new(); -my $author = $mcpan->author('XSAWYERX'); -my $dist = $mcpan->release('MetaCPAN-API'); -``` +You can get started with [this example script to fetch author data](https://github.com/metacpan/metacpan-examples/blob/master/scripts/author/1-fetch-single-author.pl). ## Querying the API with Search::Elasticsearch -The API server at api.metacpan.org is a wrapper around an [Elasticsearch](http://elasticsearch.org) instance. It adds support for the convenient GET URLs, handles authentication and does some access control. Therefore you can use the powerful API of [Search::Elasticsearch](https://metacpan.org/pod/Search::Elasticsearch) to query MetaCPAN. +The API server at fastapi.metacpan.org is a wrapper around an [Elasticsearch](https://elasticsearch.org) instance. It adds support for the convenient GET URLs, handles authentication and does some access control. Therefore you can use the powerful API of [Search::Elasticsearch](https://metacpan.org/pod/Search::Elasticsearch) to query MetaCPAN. **NOTE**: The `cxn_pool => 'Static::NoPing'` is important because of the HTTP proxy we have in front of Elasticsearch. -```perl -use Search::Elasticsearch; - -my $es = Search::Elasticsearch->new( - cxn_pool => 'Static::NoPing', - nodes => 'api.metacpan.org' -); - -my $scroller = $es->scroll_helper( - search_type => 'scan', - scroll => '5m', - index => 'v0', - type => 'release', - size => 100, - body => { - query => { - match_all => {} - } - } -); - -while ( my $result = $scroller->next ) { - print $result->{_source}->{author}, '/', - $result->{_source}->{name}, $/; -} -``` +You can get started with [this example script to fetch author data](https://github.com/metacpan/metacpan-examples/blob/master/scripts/author/1-fetch-single-author-es.pl). ## POST Searches @@ -221,251 +173,193 @@ This query returns a list of all releases which list MooseX::NonMoose as a dependency. ```sh -curl -XPOST api.metacpan.org/v0/release/_search -d '{ - "query": { - "match_all": {} - }, - "size": 5000, - "fields": [ "distribution" ], - "filter": { - "and": [ - { "term": { "release.dependency.module": "MooseX::NonMoose" } }, - { "term": {"release.maturity": "released"} }, - { "term": {"release.status": "latest"} } - ] - } +curl -XPOST https://fastapi.metacpan.org/v1/release/_search -d '{ + "size" : 5000, + "fields" : [ "distribution" ], + "query" : { + "bool" : { + "must" : [ + { "term" : { "dependency.module" : "MooseX::NonMoose" } }, + { "term" : { "maturity" : "released" } }, + { "term" : { "status" : "latest" } } + ] + } + } }' ``` -_Note it is also possible to use these queries in GET requests (useful for cross-domain JSONP requests) by appropriately encoding the JSON query into the `source` parameter of the URL. For example the query above [would become](http://api.metacpan.org/v0/release/_search?source=%7B%22query%22%3A%7B%22match_all%22%3A%7B%7D%7D%2C%22size%22%3A5000%2C%22fields%22%3A%5B%22distribution%22%5D%2C%22filter%22%3A%7B%22and%22%3A%5B%7B%22term%22%3A%7B%22release.dependency.module%22%3A%22MooseX%3A%3ANonMoose%22%7D%7D%2C%7B%22term%22%3A%7B%22release.maturity%22%3A%22released%22%7D%7D%2C%7B%22term%22%3A%7B%22release.status%22%3A%22latest%22%7D%7D%5D%7D%7D):_ +_Note it is also possible to use these queries in GET requests (useful for cross-domain JSONP requests) by appropriately encoding the JSON query into the `source` parameter of the URL. For example the query above [would become](https://fastapi.metacpan.org/v1/release/_search?source=%7B%0A%20%20%20%20%22size%22%20%3A%205000%2C%0A%20%20%20%20%22fields%22%20%3A%20%5B%20%22distribution%22%20%5D%2C%0A%20%20%20%20%22query%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%22bool%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22must%22%20%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%22term%22%20%3A%20%7B%20%22dependency.module%22%20%3A%20%22MooseX%3A%3ANonMoose%22%20%7D%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%22term%22%20%3A%20%7B%20%22maturity%22%20%3A%20%22released%22%20%7D%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%22term%22%20%3A%20%7B%20%22status%22%20%3A%20%22latest%22%20%7D%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D):_ ``` -curl 'api.metacpan.org/v0/release/_search?source=%7B%22query%22%3A%7B%22match_all%22%3A%7B%7D%7D%2C%22size%22%3A5000%2C%22fields%22%3A%5B%22distribution%22%5D%2C%22filter%22%3A%7B%22and%22%3A%5B%7B%22term%22%3A%7B%22release.dependency.module%22%3A%22MooseX%3A%3ANonMoose%22%7D%7D%2C%7B%22term%22%3A%7B%22release.maturity%22%3A%22released%22%7D%7D%2C%7B%22term%22%3A%7B%22release.status%22%3A%22latest%22%7D%7D%5D%7D%7D' +curl 'https://fastapi.metacpan.org/v1/release/_search?source=%7B%0A%20%20%20%20%22size%22%20%3A%205000%2C%0A%20%20%20%20%22fields%22%20%3A%20%5B%20%22distribution%22%20%5D%2C%0A%20%20%20%20%22query%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%22bool%22%20%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22must%22%20%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%22term%22%20%3A%20%7B%20%22dependency.module%22%20%3A%20%22MooseX%3A%3ANonMoose%22%20%7D%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%22term%22%20%3A%20%7B%20%22maturity%22%20%3A%20%22released%22%20%7D%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%22term%22%20%3A%20%7B%20%22status%22%20%3A%20%22latest%22%20%7D%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D' ``` -### The size of the CPAN unpacked +### [The size of the CPAN unpacked](https://github.com/metacpan/metacpan-examples/blob/master/scripts/file/5-size-of-cpan.pl) -```sh -curl -XPOST api.metacpan.org/v0/file/_search -d '{ - "query": { "match_all": {} }, - "facets": { - "size": { - "statistical": { - "field": "stat.size" - } } }, - "size":0 -}' -``` ### Get license types of all releases in an arbitrary time span: ```sh -curl -XPOST api.metacpan.org/v0/release/_search?size=100 -d '{ - "query": { - "match_all": {}, - "range" : { - "release.date" : { - "from" : "2010-06-05T00:00:00", - "to" : "2011-06-05T00:00:00" +curl -XPOST https://fastapi.metacpan.org/v1/release/_search?size=100 -d '{ + "query" : { + "range" : { + "date" : { + "gte" : "2010-06-05T00:00:00", + "lte" : "2011-06-05T00:00:00" + } } - } - }, - "fields": ["release.license", "release.name", "release.distribution", "release.date", "release.version_numified"] + }, + "fields": [ "license", "name", "distribution", "date", "version_numified" ] }' ``` ### Aggregate by license: ```sh -curl -XPOST api.metacpan.org/v0/release/_search -d '{ - "query": { - "match_all": {} +curl -XPOST https://fastapi.metacpan.org/v1/release/_search -d '{ + "query" : { + "match_all" : {} }, - "facets": { - "license": { - "terms": { - "field": "release.license" + "aggs" : { + "license" : { + "terms" : { + "field" : "license" } } }, - "size": 0 + "size" : 0 }' ``` ### Most used file names in the root directory of releases: ```sh -curl -XPOST api.metacpan.org/v0/file/_search -d '{ - "query": { "filtered":{"query":{"match_all":{}},"filter":{"term":{"level":0}}} - }, - "facets": { - "license": { - "terms": { - "size":100, - "field":"file.name" - } } }, - "size":0 +curl -XPOST https://fastapi.metacpan.org/v1/file/_search -d '{ + "query" : { + "term" : { "level" : 0 } + }, + "aggs" : { + "license" : { + "terms" : { + "size" : 100, + "field" : "name" + } + } + }, + "size" : 0 }' ``` ### Find all releases that contain a particular version of a module: ```sh -curl -XPOST api.metacpan.org/v0/file/_search -d '{ - "query": { "filtered":{ - "query":{"match_all":{}}, - "filter":{"and":[ - {"term":{"file.module.name":"DBI::Profile"}}, - {"term":{"file.module.version":"2.014123"}} - ]} - }}, - "fields":["release"] +curl -XPOST https://fastapi.metacpan.org/v1/file/_search -d '{ + "query" : { + "bool" : { + "must" : [ + { "term" : { "module.name" : "DBI::Profile" } }, + { "term" : { "module.version" : "2.014123" } } + ] + } + }, + "fields" : [ "release" ] }' ``` -[example](https://explorer.metacpan.org/?url=%2Ffile&content=%7B%22query%22%3A%7B%22filtered%22%3A%7B%22query%22%3A%7B%22match_all%22%3A%7B%7D%7D%2C%22filter%22%3A%7B%22and%22%3A%5B%7B%22term%22%3A%7B%22file.module.name%22%3A%22DBI%3A%3AProfile%22%7D%7D%2C%7B%22term%22%3A%7B%22file.module.version%22%3A%222.014123%22%7D%7D%5D%7D%7D%7D%2C%22fields%22%3A%5B%22release%22%5D%7D) -### Find all authors with github-meets-cpan in their profiles -Because of the dashes in this profile name, we need to use a term. +### [Find all authors with Twitter in their profiles](https://github.com/metacpan/metacpan-examples/blob/master/scripts/author/1c-scroll-all-authors-with-twitter-es.pl) -```sh -curl -XPOST api.metacpan.org/v0/author/_search -d '{ - "query": { - "match_all": {} - }, - "filter": { - "term": { - "author.profile.name": "github-meets-cpan" - } - } -}' -``` - -### Get a leaderboard of ++'ed distributions +### [Get a leaderboard of ++'ed distributions](https://github.com/metacpan/metacpan-examples/blob/master/scripts/favorite/3-leaderboard-es.pl) -```sh -curl -XPOST api.metacpan.org/v0/favorite/_search -d '{ - "query": { "match_all": {} - }, - "facets": { - "leaderboard": { - "terms": { - "field":"distribution", - "size" : 100 - } } }, - "size":0 -}' -``` +### [Get a leaderboard of Authors with Most Uploads](https://github.com/metacpan/metacpan-examples/blob/master/scripts/release/2-author-upload-leaderboard-es.pl) -### Get a leaderboard of Authors with Most Uploads -```sh -curl -XPOST api.metacpan.org/v0/release/_search -d '{ - "query": { - "match_all": {} - }, - "facets": { - "author": { - "terms": { - "field": "author", - "size": 100 - } - } - }, - "size": 0 -}' -``` +### [Search for a release by name](https://github.com/metacpan/metacpan-examples/blob/master/scripts/release/1-pkg2url-es.pl) -### Search for a release by name -```sh -curl -XPOST api.metacpan.org/v0/release/_search -d '{ - "query" : { "match_all" : { } }, - "filter" : { "term" : { "release.name" : "YAML-Syck-1.07_01" } } -}' - -``` ### Get the latest version numbers of your favorite modules Note that "size" should be the number of distributions you are looking for. ```sh -lynx --dump --post_data http://api.metacpan.org/v0/release/_search <set_indexed` **must** be called as early as possible, + otherwise things which inspect file.indexed or module.indexed will get + default values for those fields not _real_ values. + +* Similarly, `Document::File->set_authorized` should be called as soon after + `set_indexed` as possible. + + + +## Use cases to support + +Installing a package, various ways: + + cpanm Moose + cpanm Moose@2.1806 + cpanm Moose~'>2, <3' + cpanm --dev Moose + cpanm --dev Moose~'>2, <3' # maybe not? + +May need to inspect: + + release.authorized + release.status + file.indexed + file.authorized + file.status + module.indexed + module.authorized diff --git a/docs/logging.md b/docs/logging.md new file mode 100644 index 000000000..da725fbf5 --- /dev/null +++ b/docs/logging.md @@ -0,0 +1,16 @@ +# Logging + +Logging is done via Log::Contextual. There are three logger configs. These +can be found in the etc folder in this repository. + +## etc/metacpan.pl + +This is the default logger config + +## etc/metacpan_interactive.pl + +This logger config is used when scripts are run at the command line + +## etc/metacpan_testing.pl + +This logger config is used by the test suite. diff --git a/docs/testing.md b/docs/testing.md new file mode 100644 index 000000000..5c6c2ce42 --- /dev/null +++ b/docs/testing.md @@ -0,0 +1,25 @@ +# Testing + +## Releases + +When debugging the release indexing, try setting the bulk_size param to a low number, in order to make debugging easier. + + my $server = MetaCPAN::TestServer->new( ... ); + $server->index_releases( bulk_size => 1 ); + +You can enable Elasticsearch tracing when running tests at the command line: + + ES_TRACE=1 ./bin/prove t/darkpan.t + +You'll then find extensive logging information in `es.log`, at the top level of your Git checkout. + +## Indexing a Single Release + +If you want to speed up your debugging, you can index a solitary release using +the `MC_RELEASE` environment variable. + + MC_RELEASE=var/t/tmp/fakecpan/authors/id/L/LO/LOCAL/P-1.0.20.tar.gz ./bin/prove t/00_setup.t + +Or combine this with a test specific to the release. + + MC_RELEASE=var/t/tmp/fakecpan/authors/id/L/LO/LOCAL/P-1.0.20.tar.gz ./bin/prove t/00_setup.t t/release/p-1.0.20.t diff --git a/elasticsearch/cpanratings.pl b/elasticsearch/cpanratings.pl deleted file mode 100644 index 03683bc67..000000000 --- a/elasticsearch/cpanratings.pl +++ /dev/null @@ -1,276 +0,0 @@ -#!/usr/bin/perl -#=============================================================================== -# -# FILE: cpanratings.pl -# -# USAGE: ./cpanratings.pl -# -# DESCRIPTION: Screen-scrapper for cpanratings.perl.org's ratings and reviews -# -# OPTIONS: --- -# REQUIREMENTS: --- -# BUGS: --- -# NOTES: usage - perl cpanratings.pl Data::Dumper -# AUTHOR: J. Bobby Lopez (blopez), blopez@vmware.com, bobby.lopez@gmail.com -# COMPANY: CPAN-API Project -# VERSION: 1.0 -# CREATED: 11/11/10 05:01:10 PM -# REVISION: --- -#=============================================================================== - -#_______________________________________________________________[[ MODULES ]]_ - -#______________________________________[ Core or CPAN Modules ]_______________ - -use strict; -use warnings; -use Find::Lib '../lib'; -use Data::Dumper; -use Data::Dump; - -use List::Util qw(sum); -use WWW::Mechanize::Cached; -use HTML::TokeParser::Simple; -use JSON::XS; -use Parse::CSV; -use Path::Class::File; -use feature 'say'; - -#______________________________________[ Custom Modules ]_____________________ - -#use MetaCPAN; - -#__________________________________________________________________[[ SETUP ]]_ - -# Incoming arg = module name (e.g., Data::Dumper) -# would pull info from http://cpanratings.perl.org/dist/Data-Dumper - -my $dbg = 1; -my $cacher = WWW::Mechanize::Cached->new; -#my $es = MetaCPAN->new->es; - -prep_for_web(); - -#___________________________________________________________________[[ MAIN ]]_ - - - -my @to_insert = dump_all_ratings(); -#print Dumper( @to_insert ); - - -#dump_full_html(); # For testing - cleans up the HTML a bit before output -#print Dumper(\%ENV); - -#DONE - -#____________________________________________________________[[ SUBROUTINES ]]_ - -sub get_module_ratings -{ - my ($module) = @_; - $module =~ s/\:\:/-/g; - - my %json_hash; - my $base_url = "http://cpanratings.perl.org/dist/"; - my $url = $base_url . $module; - my $response = $cacher->get( $url ); - my $content = $response->content; - - if ( $content =~ "$module reviews" ) - { - %json_hash = populate_json_hash($content); - #my $json = dump_json(\%json_hash); - return %json_hash; - } - else - { - #print STDERR "404 Error with $module\n"; - return (); - } - -} - -sub dump_all_ratings -{ - my $csv_file = '/tmp/all_ratings.csv'; - my $file = Path::Class::File->new($csv_file); - my $fh = $file->openw(); - $cacher->get('http://cpanratings.perl.org/csv/all_ratings.csv'); - - print $fh $cacher->content; - - my $parser = Parse::CSV->new( - file => $csv_file, - fields => 'auto', - ); - - my @to_insert = (); - - my $limit = 99999; - my $i = 0; - while ( my $rating = $parser->fetch ) { - - my $dist_name = $rating->{distribution}; - chomp($dist_name); - if ( !defined( $dist_name ) ) { next; } - - $dbg && say "Trying |$dist_name| ...."; - my %fullratings = get_module_ratings($dist_name); - next if keys %fullratings != 2 - and ( $dbg && say "Skipping |$dist_name|..." ); - - $dbg && say "$dist_name: Avg Rating - " . $fullratings{avg_rating} ; - my $data = { - dist => $rating->{distribution}, - rating => $fullratings{avg_rating}, - reviews => $fullratings{reviews}, - }; - - my %es_insert = ( - index => { - index => 'cpan', - type => 'cpanratings', - id => $rating->{distribution}, - data => $data - } - ); - - push @to_insert, \%es_insert; - - last if $i >= $limit; - $i++; - } - - #my $result = $es->bulk( \@to_insert ); - - unlink $csv_file; - return @to_insert; -} - -sub populate_es -{ - my $csv_file = '/tmp/all_ratings.csv'; - my $file = Path::Class::File->new($csv_file); - my $fh = $file->openw(); - $cacher->get('http://cpanratings.perl.org/csv/all_ratings.csv'); - - print $fh $cacher->content; - - my $parser = Parse::CSV->new( - file => $csv_file, - fields => 'auto', - ); - - my @to_insert = (); - - while ( my $rating = $parser->fetch ) { - - my $dist_name = $rating->{distribution}; - - my $data = { - dist => $rating->{distribution}, - rating => $rating->{rating}, - review_count => $rating->{review_count}, - }; - - my %es_insert = ( - index => { - index => 'cpan', - type => 'cpanratings', - id => $rating->{distribution}, - data => $data - } - ); - - push @to_insert, \%es_insert; - - } - - #my $result = $es->bulk( \@to_insert ); - - unlink $csv_file; -} - -sub mean { - return sum(@_)/@_; -} - -#sub dump_full_html -#{ -# my $response = $cacher->get( $url ); -# my $content = $response->content; -# my $p = HTML::TokeParser::Simple->new(\$content); -# print "---- whole document ----\n"; -# while ( my $token = $p->get_token ) -# { -# print $token->as_is; -# } -# print "\n\n"; -#} - -sub dump_json -{ - my $hash_data = shift; - my $coder = JSON::XS->new->ascii->pretty->allow_nonref; - my $json = $coder->utf8->encode ($hash_data); - #binmode(STDOUT, ":utf8"); - return $json; -} - -sub prep_for_web -{ - if ( defined($ENV{'GATEWAY_INTERFACE'}) ) - { - print "Content-type: text/html\n\n"; - } -} - - -sub populate_json_hash -{ - my ($content) = @_; - my %json_hash; - my @avg_rating; - my $p = HTML::TokeParser::Simple->new(\$content); - my $i = 0; - while (my $token = $p->get_tag("h3")) - { - $token = $p->get_tag("a"); # start tag - $token = $p->get_token; # Module name inside - $token = $p->get_token; # end tag - $token = $p->get_token; # module version - my $module_version = $token->[1]; - $module_version =~ s/\n//g; - $module_version =~ s/.*\((.*)\).*/$1/; - - $token = $p->get_tag("img"); - my $rating = $token->[1]{'alt'} || "-"; - push @avg_rating, length($rating); - - $token = $p->get_tag("blockquote"); - my $review = $p->get_trimmed_text("/blockquote"); - - $token = $p->get_tag("a"); - my $reviewer = $p->get_trimmed_text("/a"); - my $date = $p->get_trimmed_text("br"); - chomp($date); - $date =~ s/(\d+-\d+-\d+)[[:space:]]+(\d+:\d+:\d+)/$1T$2/g; - $date =~ s/(?:^-|[[:space:]]+)//g; - - $json_hash{'reviews'}{$i}{'rating'} = length($rating); - $json_hash{'reviews'}{$i}{'review'} = $review; - $json_hash{'reviews'}{$i}{'reviewer'} = $reviewer; - $json_hash{'reviews'}{$i}{'review_date'} = $date; - $json_hash{'reviews'}{$i}{'module_version'} = $module_version; - - $i++; - } - - - if ( defined($json_hash{'reviews'}) ) - { - $json_hash{'avg_rating'} = sprintf( "%.2f", mean(@avg_rating) ); - } - return %json_hash; -} diff --git a/elasticsearch/index_perlmongers.pl b/elasticsearch/index_perlmongers.pl deleted file mode 100755 index ea7e06968..000000000 --- a/elasticsearch/index_perlmongers.pl +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env perl - -=head1 SYNOPSIS - -Loads PerlMonger groups into db. - - perl index_perlmongers.pl - -=cut - -use feature 'say'; -use Data::Dump qw( dump ); -use Find::Lib '../lib'; -use MetaCPAN::Script::PerlMongers; - -my $author = MetaCPAN::Script::PerlMongers->new; -my $result = $author->index_perlmongers; -say dump( $result ); - -$author->es->refresh_index( index => 'cpan' ); diff --git a/es/account/mapping.json b/es/account/mapping.json new file mode 100644 index 000000000..1d89039a6 --- /dev/null +++ b/es/account/mapping.json @@ -0,0 +1,33 @@ +{ + "dynamic": false, + "properties": { + "access_token": { + "dynamic": true, + "properties": { + "client": { + "type": "keyword" + }, + "token": { + "type": "keyword" + } + } + }, + "code": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "identity": { + "dynamic": false, + "properties": { + "key": { + "type": "keyword" + }, + "name": { + "type": "keyword" + } + } + } + } +} diff --git a/es/account/settings.json b/es/account/settings.json new file mode 100644 index 000000000..bbb95c38b --- /dev/null +++ b/es/account/settings.json @@ -0,0 +1,5 @@ +{ + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/author/mapping.json b/es/author/mapping.json new file mode 100644 index 000000000..d643dfe50 --- /dev/null +++ b/es/author/mapping.json @@ -0,0 +1,115 @@ +{ + "dynamic": false, + "properties": { + "asciiname": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "blog": { + "dynamic": true, + "properties": { + "feed": { + "type": "keyword" + }, + "url": { + "type": "keyword" + } + } + }, + "city": { + "type": "keyword" + }, + "country": { + "type": "keyword" + }, + "donation": { + "dynamic": true, + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + } + } + }, + "email": { + "type": "keyword" + }, + "gravatar_url": { + "type": "keyword" + }, + "is_pause_custodial_account": { + "type": "boolean" + }, + "location": { + "type": "geo_point" + }, + "name": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "pauseid": { + "type": "keyword" + }, + "perlmongers": { + "dynamic": true, + "properties": { + "name": { + "type": "keyword" + }, + "url": { + "type": "keyword" + } + } + }, + "profile": { + "dynamic": false, + "include_in_root": true, + "properties": { + "id": { + "fields": { + "analyzed": { + "analyzer": "simple", + "fielddata": false, + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "name": { + "type": "keyword" + } + }, + "type": "nested" + }, + "region": { + "type": "keyword" + }, + "updated": { + "format": "strict_date_optional_time||epoch_millis", + "type": "date" + }, + "user": { + "type": "keyword" + }, + "website": { + "type": "keyword" + } + } +} diff --git a/es/author/settings.json b/es/author/settings.json new file mode 100644 index 000000000..bbb95c38b --- /dev/null +++ b/es/author/settings.json @@ -0,0 +1,5 @@ +{ + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/contributor/mapping.json b/es/contributor/mapping.json new file mode 100644 index 000000000..72017a284 --- /dev/null +++ b/es/contributor/mapping.json @@ -0,0 +1,23 @@ +{ + "dynamic": false, + "properties": { + "distribution": { + "type": "keyword" + }, + "email": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "pauseid": { + "type": "keyword" + }, + "release_author": { + "type": "keyword" + }, + "release_name": { + "type": "keyword" + } + } +} diff --git a/es/contributor/settings.json b/es/contributor/settings.json new file mode 100644 index 000000000..bbb95c38b --- /dev/null +++ b/es/contributor/settings.json @@ -0,0 +1,5 @@ +{ + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/cover/mapping.json b/es/cover/mapping.json new file mode 100644 index 000000000..274adddc1 --- /dev/null +++ b/es/cover/mapping.json @@ -0,0 +1,34 @@ +{ + "dynamic": false, + "properties": { + "criteria": { + "dynamic": true, + "properties": { + "branch": { + "type": "float" + }, + "condition": { + "type": "float" + }, + "statement": { + "type": "float" + }, + "subroutine": { + "type": "float" + }, + "total": { + "type": "float" + } + } + }, + "distribution": { + "type": "keyword" + }, + "release": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } +} diff --git a/es/cover/settings.json b/es/cover/settings.json new file mode 100644 index 000000000..bbb95c38b --- /dev/null +++ b/es/cover/settings.json @@ -0,0 +1,5 @@ +{ + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/cve/mapping.json b/es/cve/mapping.json new file mode 100644 index 000000000..8ec674c24 --- /dev/null +++ b/es/cve/mapping.json @@ -0,0 +1,36 @@ +{ + "dynamic": false, + "properties": { + "affected_versions": { + "type": "text" + }, + "cpansa_id": { + "type": "keyword" + }, + "cves": { + "type": "text" + }, + "description": { + "type": "text" + }, + "distribution": { + "type": "keyword" + }, + "references": { + "type": "text" + }, + "releases": { + "type": "keyword" + }, + "reported": { + "format": "strict_date_optional_time||epoch_millis", + "type": "date" + }, + "severity": { + "type": "text" + }, + "versions": { + "type": "keyword" + } + } +} diff --git a/es/cve/settings.json b/es/cve/settings.json new file mode 100644 index 000000000..bbb95c38b --- /dev/null +++ b/es/cve/settings.json @@ -0,0 +1,5 @@ +{ + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/distribution/mapping.json b/es/distribution/mapping.json new file mode 100644 index 000000000..1e652f69b --- /dev/null +++ b/es/distribution/mapping.json @@ -0,0 +1,109 @@ +{ + "dynamic": false, + "properties": { + "bugs": { + "dynamic": true, + "properties": { + "github": { + "dynamic": true, + "properties": { + "active": { + "type": "integer" + }, + "closed": { + "type": "integer" + }, + "open": { + "type": "integer" + }, + "source": { + "type": "keyword" + } + } + }, + "rt": { + "dynamic": true, + "properties": { + "active": { + "type": "integer" + }, + "closed": { + "type": "integer" + }, + "new": { + "type": "integer" + }, + "open": { + "type": "integer" + }, + "patched": { + "type": "integer" + }, + "rejected": { + "type": "integer" + }, + "resolved": { + "type": "integer" + }, + "source": { + "type": "keyword" + }, + "stalled": { + "type": "integer" + } + } + } + } + }, + "external_package": { + "dynamic": true, + "properties": { + "cygwin": { + "type": "keyword" + }, + "debian": { + "type": "keyword" + }, + "fedora": { + "type": "keyword" + } + } + }, + "name": { + "type": "keyword" + }, + "repo": { + "dynamic": true, + "properties": { + "github": { + "dynamic": true, + "properties": { + "stars": { + "type": "integer" + }, + "watchers": { + "type": "integer" + } + } + } + } + }, + "river": { + "dynamic": true, + "properties": { + "bucket": { + "type": "integer" + }, + "bus_factor": { + "type": "integer" + }, + "immediate": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + } + } +} diff --git a/es/distribution/settings.json b/es/distribution/settings.json new file mode 100644 index 000000000..bbb95c38b --- /dev/null +++ b/es/distribution/settings.json @@ -0,0 +1,5 @@ +{ + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/favorite/mapping.json b/es/favorite/mapping.json new file mode 100644 index 000000000..0aa0f6e88 --- /dev/null +++ b/es/favorite/mapping.json @@ -0,0 +1,24 @@ +{ + "dynamic": false, + "properties": { + "author": { + "type": "keyword" + }, + "date": { + "format": "strict_date_optional_time||epoch_millis", + "type": "date" + }, + "distribution": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "release": { + "type": "keyword" + }, + "user": { + "type": "keyword" + } + } +} diff --git a/es/favorite/settings.json b/es/favorite/settings.json new file mode 100644 index 000000000..bbb95c38b --- /dev/null +++ b/es/favorite/settings.json @@ -0,0 +1,5 @@ +{ + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/file/mapping.json b/es/file/mapping.json new file mode 100644 index 000000000..12dc23970 --- /dev/null +++ b/es/file/mapping.json @@ -0,0 +1,242 @@ +{ + "dynamic": false, + "properties": { + "abstract": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "author": { + "type": "keyword" + }, + "authorized": { + "type": "boolean" + }, + "binary": { + "type": "boolean" + }, + "date": { + "format": "strict_date_optional_time||epoch_millis", + "type": "date" + }, + "deprecated": { + "type": "boolean" + }, + "description": { + "type": "text" + }, + "dir": { + "type": "keyword" + }, + "directory": { + "type": "boolean" + }, + "dist_fav_count": { + "type": "integer" + }, + "distribution": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + }, + "camelcase": { + "analyzer": "camelcase", + "store": true, + "type": "text" + }, + "lowercase": { + "analyzer": "lowercase", + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "documentation": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + }, + "camelcase": { + "analyzer": "camelcase", + "store": true, + "type": "text" + }, + "edge": { + "analyzer": "edge", + "store": true, + "type": "text" + }, + "edge_camelcase": { + "analyzer": "edge_camelcase", + "store": true, + "type": "text" + }, + "lowercase": { + "analyzer": "lowercase", + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "documentation_length": { + "type": "integer" + }, + "download_url": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "indexed": { + "type": "boolean" + }, + "level": { + "type": "integer" + }, + "maturity": { + "type": "keyword" + }, + "mime": { + "type": "keyword" + }, + "module": { + "dynamic": false, + "include_in_root": true, + "properties": { + "associated_pod": { + "type": "text" + }, + "authorized": { + "type": "boolean" + }, + "indexed": { + "type": "boolean" + }, + "name": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + }, + "camelcase": { + "analyzer": "camelcase", + "store": true, + "type": "text" + }, + "lowercase": { + "analyzer": "lowercase", + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "version": { + "type": "keyword" + }, + "version_numified": { + "type": "float" + } + }, + "type": "nested" + }, + "name": { + "type": "keyword" + }, + "path": { + "type": "keyword" + }, + "pod": { + "analyzer": "standard", + "fields": { + "analyzed": { + "analyzer": "standard", + "type": "text" + } + }, + "type": "text" + }, + "pod_lines": { + "type": "keyword" + }, + "release": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + }, + "camelcase": { + "analyzer": "camelcase", + "store": true, + "type": "text" + }, + "lowercase": { + "analyzer": "lowercase", + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "sloc": { + "type": "integer" + }, + "slop": { + "type": "integer" + }, + "stat": { + "dynamic": true, + "properties": { + "gid": { + "type": "long" + }, + "mode": { + "type": "integer" + }, + "mtime": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "uid": { + "type": "long" + } + } + }, + "status": { + "type": "keyword" + }, + "suggest": { + "analyzer": "simple", + "max_input_length": 50, + "preserve_position_increments": true, + "preserve_separators": true, + "type": "completion" + }, + "version": { + "type": "keyword" + }, + "version_numified": { + "type": "float" + } + } +} diff --git a/es/file/settings.json b/es/file/settings.json new file mode 100644 index 000000000..1cdf6e2f0 --- /dev/null +++ b/es/file/settings.json @@ -0,0 +1,53 @@ +{ + "analysis": { + "analyzer": { + "camelcase": { + "filter": [ + "lowercase", + "unique" + ], + "tokenizer": "camelcase", + "type": "custom" + }, + "edge": { + "filter": [ + "lowercase", + "edge" + ], + "tokenizer": "standard", + "type": "custom" + }, + "edge_camelcase": { + "filter": [ + "lowercase", + "edge" + ], + "tokenizer": "camelcase", + "type": "custom" + }, + "fulltext": { + "type": "english" + }, + "lowercase": { + "filter": "lowercase", + "tokenizer": "keyword" + } + }, + "filter": { + "edge": { + "max_gram": "20", + "min_gram": "1", + "type": "edge_ngram" + } + }, + "tokenizer": { + "camelcase": { + "pattern": "([^\\p{L}\\d]+)|(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)|(?<=[\\p{L}&&[^\\p{Lu}]])(?=\\p{Lu})|(?<=\\p{Lu})(?=\\p{Lu}[\\p{L}&&[^\\p{Lu}]])", + "type": "pattern" + } + } + }, + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/mirror/mapping.json b/es/mirror/mapping.json new file mode 100644 index 000000000..eaebd2742 --- /dev/null +++ b/es/mirror/mapping.json @@ -0,0 +1,118 @@ +{ + "dynamic": false, + "properties": { + "A_or_CNAME": { + "type": "keyword" + }, + "aka_name": { + "type": "keyword" + }, + "ccode": { + "type": "keyword" + }, + "city": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "contact": { + "dynamic": false, + "properties": { + "contact_site": { + "type": "keyword" + }, + "contact_user": { + "type": "keyword" + } + } + }, + "continent": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "country": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "dnsrr": { + "type": "keyword" + }, + "freq": { + "type": "keyword" + }, + "ftp": { + "type": "keyword" + }, + "http": { + "type": "keyword" + }, + "inceptdate": { + "format": "strict_date_optional_time||epoch_millis", + "type": "date" + }, + "location": { + "type": "geo_point" + }, + "name": { + "type": "keyword" + }, + "note": { + "type": "keyword" + }, + "org": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "region": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "reitredate": { + "format": "strict_date_optional_time||epoch_millis", + "type": "date" + }, + "rsync": { + "type": "keyword" + }, + "src": { + "type": "keyword" + }, + "tz": { + "type": "keyword" + } + } +} diff --git a/es/mirror/settings.json b/es/mirror/settings.json new file mode 100644 index 000000000..bbb95c38b --- /dev/null +++ b/es/mirror/settings.json @@ -0,0 +1,5 @@ +{ + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/package/mapping.json b/es/package/mapping.json new file mode 100644 index 000000000..0248dfe82 --- /dev/null +++ b/es/package/mapping.json @@ -0,0 +1,23 @@ +{ + "dynamic": false, + "properties": { + "author": { + "type": "keyword" + }, + "dist_version": { + "type": "keyword" + }, + "distribution": { + "type": "keyword" + }, + "file": { + "type": "keyword" + }, + "module_name": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } +} diff --git a/es/package/settings.json b/es/package/settings.json new file mode 100644 index 000000000..bbb95c38b --- /dev/null +++ b/es/package/settings.json @@ -0,0 +1,5 @@ +{ + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/permission/mapping.json b/es/permission/mapping.json new file mode 100644 index 000000000..31c2e36b6 --- /dev/null +++ b/es/permission/mapping.json @@ -0,0 +1,14 @@ +{ + "dynamic": false, + "properties": { + "co_maintainers": { + "type": "keyword" + }, + "module_name": { + "type": "keyword" + }, + "owner": { + "type": "keyword" + } + } +} diff --git a/es/permission/settings.json b/es/permission/settings.json new file mode 100644 index 000000000..bbb95c38b --- /dev/null +++ b/es/permission/settings.json @@ -0,0 +1,5 @@ +{ + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/release/mapping.json b/es/release/mapping.json new file mode 100644 index 000000000..4ab1b1a28 --- /dev/null +++ b/es/release/mapping.json @@ -0,0 +1,211 @@ +{ + "dynamic": false, + "properties": { + "abstract": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "archive": { + "type": "keyword" + }, + "author": { + "type": "keyword" + }, + "authorized": { + "type": "boolean" + }, + "changes_file": { + "type": "keyword" + }, + "checksum_md5": { + "type": "keyword" + }, + "checksum_sha256": { + "type": "keyword" + }, + "date": { + "format": "strict_date_optional_time||epoch_millis", + "type": "date" + }, + "dependency": { + "dynamic": false, + "include_in_root": true, + "properties": { + "module": { + "type": "keyword" + }, + "phase": { + "type": "keyword" + }, + "relationship": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + }, + "type": "nested" + }, + "deprecated": { + "type": "boolean" + }, + "distribution": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + }, + "camelcase": { + "analyzer": "camelcase", + "store": true, + "type": "text" + }, + "lowercase": { + "analyzer": "lowercase", + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "download_url": { + "type": "keyword" + }, + "first": { + "type": "boolean" + }, + "id": { + "type": "keyword" + }, + "license": { + "type": "keyword" + }, + "main_module": { + "type": "keyword" + }, + "maturity": { + "type": "keyword" + }, + "name": { + "fields": { + "analyzed": { + "analyzer": "standard", + "fielddata": false, + "store": true, + "type": "text" + }, + "camelcase": { + "analyzer": "camelcase", + "store": true, + "type": "text" + }, + "lowercase": { + "analyzer": "lowercase", + "store": true, + "type": "text" + } + }, + "type": "keyword" + }, + "provides": { + "type": "keyword" + }, + "resources": { + "dynamic": true, + "include_in_root": true, + "properties": { + "bugtracker": { + "dynamic": true, + "include_in_root": true, + "properties": { + "mailto": { + "type": "keyword" + }, + "web": { + "type": "keyword" + } + }, + "type": "nested" + }, + "homepage": { + "type": "keyword" + }, + "license": { + "type": "keyword" + }, + "repository": { + "dynamic": true, + "include_in_root": true, + "properties": { + "type": { + "type": "keyword" + }, + "url": { + "type": "keyword" + }, + "web": { + "type": "keyword" + } + }, + "type": "nested" + } + }, + "type": "nested" + }, + "stat": { + "dynamic": true, + "properties": { + "gid": { + "type": "long" + }, + "mode": { + "type": "integer" + }, + "mtime": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "uid": { + "type": "long" + } + } + }, + "status": { + "type": "keyword" + }, + "tests": { + "dynamic": true, + "properties": { + "fail": { + "type": "integer" + }, + "na": { + "type": "integer" + }, + "pass": { + "type": "integer" + }, + "unknown": { + "type": "integer" + } + } + }, + "version": { + "type": "keyword" + }, + "version_numified": { + "type": "float" + } + } +} diff --git a/es/release/settings.json b/es/release/settings.json new file mode 100644 index 000000000..1cdf6e2f0 --- /dev/null +++ b/es/release/settings.json @@ -0,0 +1,53 @@ +{ + "analysis": { + "analyzer": { + "camelcase": { + "filter": [ + "lowercase", + "unique" + ], + "tokenizer": "camelcase", + "type": "custom" + }, + "edge": { + "filter": [ + "lowercase", + "edge" + ], + "tokenizer": "standard", + "type": "custom" + }, + "edge_camelcase": { + "filter": [ + "lowercase", + "edge" + ], + "tokenizer": "camelcase", + "type": "custom" + }, + "fulltext": { + "type": "english" + }, + "lowercase": { + "filter": "lowercase", + "tokenizer": "keyword" + } + }, + "filter": { + "edge": { + "max_gram": "20", + "min_gram": "1", + "type": "edge_ngram" + } + }, + "tokenizer": { + "camelcase": { + "pattern": "([^\\p{L}\\d]+)|(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)|(?<=[\\p{L}&&[^\\p{Lu}]])(?=\\p{Lu})|(?<=\\p{Lu})(?=\\p{Lu}[\\p{L}&&[^\\p{Lu}]])", + "type": "pattern" + } + } + }, + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/session/mapping.json b/es/session/mapping.json new file mode 100644 index 000000000..d4f130c22 --- /dev/null +++ b/es/session/mapping.json @@ -0,0 +1,3 @@ +{ + "dynamic": false +} diff --git a/es/session/settings.json b/es/session/settings.json new file mode 100644 index 000000000..bbb95c38b --- /dev/null +++ b/es/session/settings.json @@ -0,0 +1,5 @@ +{ + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/es/settings.json b/es/settings.json new file mode 100644 index 000000000..1cdf6e2f0 --- /dev/null +++ b/es/settings.json @@ -0,0 +1,53 @@ +{ + "analysis": { + "analyzer": { + "camelcase": { + "filter": [ + "lowercase", + "unique" + ], + "tokenizer": "camelcase", + "type": "custom" + }, + "edge": { + "filter": [ + "lowercase", + "edge" + ], + "tokenizer": "standard", + "type": "custom" + }, + "edge_camelcase": { + "filter": [ + "lowercase", + "edge" + ], + "tokenizer": "camelcase", + "type": "custom" + }, + "fulltext": { + "type": "english" + }, + "lowercase": { + "filter": "lowercase", + "tokenizer": "keyword" + } + }, + "filter": { + "edge": { + "max_gram": "20", + "min_gram": "1", + "type": "edge_ngram" + } + }, + "tokenizer": { + "camelcase": { + "pattern": "([^\\p{L}\\d]+)|(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)|(?<=[\\p{L}&&[^\\p{Lu}]])(?=\\p{Lu})|(?<=\\p{Lu})(?=\\p{Lu}[\\p{L}&&[^\\p{Lu}]])", + "type": "pattern" + } + } + }, + "number_of_replicas": 1, + "number_of_shards": 1, + "refresh_interval": "1s" +} diff --git a/etc/metacpan.pl b/etc/metacpan.pl deleted file mode 100644 index 67512ff91..000000000 --- a/etc/metacpan.pl +++ /dev/null @@ -1,23 +0,0 @@ -# do not edit this file -# create etc/metacpan_local.pl instead -use FindBin; - -{ - # ElasticSearch instance, can be either a single server - # or an arrayref of servers - es => ':9200', - # the port of the api server - port => '5000', - # log level - level => 'info', - # appender for Log4perl - # default layout is "%d %p{1} %c: %m{chomp}%n" - # can be overridden using the layout key - # defining logger in metacpan_local.pl will - # override and not append to this configuration - logger => [{ - class => 'Log::Log4perl::Appender::File', - filename => $FindBin::RealBin . '/../var/log/metacpan.log', - syswrite => 1, - }] -} \ No newline at end of file diff --git a/etc/metacpan_interactive.pl b/etc/metacpan_interactive.pl deleted file mode 100644 index 520df00b4..000000000 --- a/etc/metacpan_interactive.pl +++ /dev/null @@ -1,12 +0,0 @@ -use FindBin; -{ - level => 'info', - logger => [{ - class => 'Log::Log4perl::Appender::ScreenColoredLevels', - stdout => 0, - }, { - class => 'Log::Log4perl::Appender::File', - filename => $FindBin::RealBin . '/../var/log/metacpan.log', - syswrite => 1, - }] -} \ No newline at end of file diff --git a/etc/metacpan_testing.pl b/etc/metacpan_testing.pl deleted file mode 100644 index 8ece42a6b..000000000 --- a/etc/metacpan_testing.pl +++ /dev/null @@ -1,12 +0,0 @@ -{ - es => ':' . ($ENV{METACPAN_ES_TEST_PORT} ||= 9900), - port => '5900', - die_on_error => 1, - level => ($ENV{TEST_VERBOSE} ? 'info' : 'warn'), - cpan => 't/var/tmp/fakecpan', - source_base => 't/var/tmp/source', - logger => [{ - class => 'Log::Log4perl::Appender::Screen', - name => 'testing' - }] -} diff --git a/git/hooks/pre-commit b/git/hooks/pre-commit index 01a314dbd..9256ae257 100755 --- a/git/hooks/pre-commit +++ b/git/hooks/pre-commit @@ -1,9 +1,15 @@ -#!/usr/bin/env perl +#!/bin/bash -use strict; -use warnings; -# Hack to use carton's local::lib. -use lib 'local/lib/perl5'; +declare -i status +status=0 -use Code::TidyAll::Git::Precommit; -Code::TidyAll::Git::Precommit->check(); +PRECIOUS=$(which precious) +if [[ -z $PRECIOUS ]]; then + PRECIOUS=./bin/precious +fi + +if ! "$PRECIOUS" lint -s; then + status+=1 +fi + +exit $status diff --git a/lib/Catalyst/Action/Deserialize/MetaCPANSanitizedJSON.pm b/lib/Catalyst/Action/Deserialize/MetaCPANSanitizedJSON.pm index 7e012c458..e46d7b8e2 100644 --- a/lib/Catalyst/Action/Deserialize/MetaCPANSanitizedJSON.pm +++ b/lib/Catalyst/Action/Deserialize/MetaCPANSanitizedJSON.pm @@ -1,10 +1,10 @@ package Catalyst::Action::Deserialize::MetaCPANSanitizedJSON; use Moose; -use namespace::autoclean; -use Try::Tiny; -use JSON (); +use Cpanel::JSON::XS (); use MetaCPAN::Server::QuerySanitizer (); +use namespace::autoclean; +use Try::Tiny qw( catch try ); extends 'Catalyst::Action::Deserialize::JSON'; @@ -39,7 +39,7 @@ around execute => sub { if ( my $source = delete $params->{source} ) { # NOTE: merge $controller->{json_options} if we ever use it - my $json = JSON->new->utf8; + my $json = Cpanel::JSON::XS->new->utf8; # if it decodes if ( try { $source = $json->decode($source); } ) { diff --git a/lib/Catalyst/Authentication/Store/Proxy.pm b/lib/Catalyst/Authentication/Store/Proxy.pm index ba4484e1f..d941a60df 100644 --- a/lib/Catalyst/Authentication/Store/Proxy.pm +++ b/lib/Catalyst/Authentication/Store/Proxy.pm @@ -2,18 +2,19 @@ package Catalyst::Authentication::Store::Proxy; # ABSTRACT: Delegates authentication logic to the user object use Moose; -use Catalyst::Utils; +use Catalyst::Utils (); +use MetaCPAN::Types::TypeTiny qw( ClassName HashRef Str ); has user_class => ( is => 'ro', required => 1, - isa => 'Str', + isa => Str, lazy => 1, builder => '_build_user_class' ); -has handles => ( is => 'ro', isa => 'HashRef' ); -has config => ( is => 'ro', isa => 'HashRef' ); -has app => ( is => 'ro', isa => 'ClassName' ); +has handles => ( is => 'ro', isa => HashRef ); +has config => ( is => 'ro', isa => HashRef ); +has app => ( is => 'ro', isa => ClassName ); has realm => ( is => 'ro' ); sub BUILDARGS { @@ -50,7 +51,7 @@ sub new_object { sub from_session { my ( $self, $c, $frozenuser ) = @_; - my $user = $self->new_object( $self->config, $c ); + my $user = $self->new_object( $self->config, $c ); my $delegate = $self->handles->{from_session}; return $user->$delegate( $c, $frozenuser ); } @@ -63,7 +64,7 @@ sub for_session { sub find_user { my ( $self, $authinfo, $c ) = @_; - my $user = $self->new_object( $self->config, $c ); + my $user = $self->new_object( $self->config, $c ); my $delegate = $self->handles->{find_user}; return $user->$delegate( $authinfo, $c ); diff --git a/lib/Catalyst/Plugin/Session/Store/ElasticSearch.pm b/lib/Catalyst/Plugin/Session/Store/ElasticSearch.pm index b2469fdd5..68159b5cb 100644 --- a/lib/Catalyst/Plugin/Session/Store/ElasticSearch.pm +++ b/lib/Catalyst/Plugin/Session/Store/ElasticSearch.pm @@ -4,36 +4,26 @@ package Catalyst::Plugin::Session::Store::ElasticSearch; use Moose; extends 'Catalyst::Plugin::Session::Store'; -use List::MoreUtils qw(); -use MooseX::Types::ElasticSearch qw(:all); +use MetaCPAN::Types::TypeTiny qw( ES ); + +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Server::Config (); +use MetaCPAN::Util qw( true false ); has _session_es => ( - required => 1, - is => 'rw', - coerce => 1, - isa => ES, - default => sub { shift->_session_plugin_config->{servers} || ':9200' } -); -has _session_es_index => ( - required => 1, - is => 'rw', - default => sub { shift->_session_plugin_config->{index} || 'user' } -); -has _session_es_type => ( - required => 1, - is => 'rw', - default => sub { shift->_session_plugin_config->{type} || 'session' } + is => 'ro', + lazy => 1, + coerce => 1, + isa => ES, + default => + sub { MetaCPAN::Server::Config::config()->{elasticsearch_servers} }, ); sub get_session_data { my ( $self, $key ) = @_; if ( my ($sid) = $key =~ /^\w+:(.*)/ ) { my $data = eval { - $self->_session_es->get( - index => $self->_session_es_index, - type => $self->_session_es_type, - id => $sid, - ); + $self->_session_es->get( es_doc_path('session'), id => $sid, ); } || return undef; if ( $key =~ /^expires:/ ) { return $data->{_source}->{_expires}; @@ -49,11 +39,10 @@ sub store_session_data { if ( my ($sid) = $key =~ /^session:(.*)/ ) { $session->{_expires} = $self->session_expires; $self->_session_es->index( - index => $self->_session_es_index, - type => $self->_session_es_type, + es_doc_path('session'), id => $sid, - data => $session, - refresh => 1, + body => $session, + refresh => true, ); } } @@ -63,10 +52,9 @@ sub delete_session_data { if ( my ($sid) = $key =~ /^session:(.*)/ ) { eval { $self->_session_es->delete( - index => $self->_session_es_index, - type => $self->_session_es_type, + es_doc_path('session'), id => $sid, - refresh => 1, + refresh => true, ); }; } @@ -85,13 +73,11 @@ sub delete_expired_sessions { } Session Session::Store::ElasticSearch ); - + # defaults MyApp->config( 'Plugin::Session' => { servers => ':9200', - index => 'user', - type => 'session', } ); =head1 DESCRIPTION diff --git a/lib/ElasticSearchX/Model/Document/Role.pm b/lib/ElasticSearchX/Model/Document/Role.pm new file mode 100644 index 000000000..6d2b58be2 --- /dev/null +++ b/lib/ElasticSearchX/Model/Document/Role.pm @@ -0,0 +1,24 @@ +package ElasticSearchX::Model::Document::Role; +use strict; +use warnings; + +use MetaCPAN::Model::Hacks; + +no warnings 'redefine'; + +my $_put = \&_put; +*_put = sub { + my ($self) = @_; + my $es = $self->index->model->es; + + my %return = &$_put; + + if ( $es->api_version le '6_0' ) { + return %return; + } + + delete $return{type}; + return %return; +}; + +1; diff --git a/lib/ElasticSearchX/Model/Document/Set.pm b/lib/ElasticSearchX/Model/Document/Set.pm new file mode 100644 index 000000000..7adc669ca --- /dev/null +++ b/lib/ElasticSearchX/Model/Document/Set.pm @@ -0,0 +1,63 @@ +package ElasticSearchX::Model::Document::Set; +use strict; +use warnings; + +use MetaCPAN::Model::Hacks; + +no warnings 'redefine'; + +our %query_override; +my $_build_query = \&_build_query; +*_build_query = sub { + my $query = $_build_query->(@_); + %$query = ( %$query, %query_override ); + return $query; +}; + +our %qs_override; +my $_build_qs = \&_build_qs; +*_build_qs = sub { + my $qs = $_build_qs->(@_); + %$qs = ( %$qs, %qs_override ); + return $qs; +}; + +# ESXM normally tries to use search_type => scan, which is deprecated or +# removed in newer Elasticsearch versions. Sorting on _doc gives the same +# optimization. +my $delete = \&delete; +*delete = sub { + local %qs_override = ( search_type => 'query_then_fetch' ); + local %query_override = ( sort => '_doc' ); + return $delete->(@_); +}; + +my $get = \&get; +*get = sub { + my ( $self, $args, $qs ) = @_; + if ( $self->es->api_version eq '2_0' ) { + goto &$get; + } + my %qs = %{ $qs || {} }; + if ( my $fields = $self->fields ) { + $qs{_source} = $fields; + local $self->{fields}; + return $get->( $self, $args, \%qs ); + } + goto &$get; +}; + +# ESXM will try to inflate based on the index/type stored in the result. We +# are using aliases, and ESXM doesn't know about the actual index that the +# docs are stored in. Instead, allow it to use the configured index/type for +# this doc set. +my $inflate_result = \&inflate_result; +*inflate_result = sub { + my ( $self, $res ) = @_; + my $new_res = {%$res}; + delete $new_res->{_index}; + delete $new_res->{_type}; + $self->$inflate_result($new_res); +}; + +1; diff --git a/lib/MetaCPAN/API.pm b/lib/MetaCPAN/API.pm new file mode 100644 index 000000000..86b29ab84 --- /dev/null +++ b/lib/MetaCPAN/API.pm @@ -0,0 +1,172 @@ +package MetaCPAN::API; + +=head1 DESCRIPTION + +This is the API Minion server. + + # Display information on jobs in queue + ./bin/run bin/api.pl minion job -s + +=cut + +use Mojo::Base 'Mojolicious'; + +use File::Temp (); +use List::Util qw( any ); +use MetaCPAN::Script::Runner (); +use Try::Tiny qw( catch try ); +use MetaCPAN::Server::Config (); + +sub startup { + my $self = shift; + + unless ( $self->config->{config_override} ) { + $self->config( MetaCPAN::Server::Config::config() ); + } + + die 'need secret' unless $self->config->{secret}; + + $self->secrets( [ $self->config->{secret} ] ); + + $self->static->paths( [ $self->home->child('root') ] ); + + $self->plugin( Minion => $self->_build_db_params ); + + $self->minion->add_task( + index_release => $self->_gen_index_task_sub('release') ); + + $self->minion->add_task( + index_latest => $self->_gen_index_task_sub('latest') ); + + $self->minion->add_task( + index_favorite => $self->_gen_index_task_sub('favorite') ); + + $self->_set_up_routes; +} + +sub _gen_index_task_sub { + my ( $self, $type ) = @_; + + return sub { + my ( $job, @args ) = @_; + + my @warnings; + local $SIG{__WARN__} = sub { + push @warnings, $_[0]; + warn $_[0]; + }; + + # @args could be ( '--latest', '/path/to/release' ); + unshift @args, $type; + + # Runner expects to have been called via CLI + local @ARGV = @args; + try { + MetaCPAN::Script::Runner->run(@args); + $job->finish( @warnings ? { warnings => \@warnings } : () ); + } + catch { + warn $_; + $job->fail( { + message => $_, + @warnings ? ( warnings => \@warnings ) : (), + } ); + }; + } +} + +sub _set_up_routes { + my $self = shift; + + my $r = $self->routes; + + my $admin = $r->under( + '/admin' => sub { + my $c = shift; + my $username = $c->session('github_username'); + if ( $self->_is_admin($username) ) { + return 1; + } + + # Direct non-admins away from the app + elsif ($username) { + $c->redirect_to('https://metacpan.org/'); + return 0; + } + + # This is possibly a logged out admin + $c->redirect_to('/auth/github/authenticate'); + return 0; + } + ); + + $self->_set_up_oauth_routes; + $self->plugin( 'Minion::Admin' => { route => $admin->any('/minion') } ); +} + +sub _is_admin { + my $self = shift; + my $username = $ENV{HARNESS_ACTIVE} ? $ENV{FORCE_ADMIN_AUTH} : shift; + return 0 unless $username; + + my @admins = ( + 'haarg', 'jberger', 'mickeyn', 'oalders', + 'ranguard', 'reyjrar', 'ssoriche', + $ENV{HARNESS_ACTIVE} ? 'tester' : (), + ); + + return any { $username eq $_ } @admins; +} + +sub _build_db_params { + my $self = shift; + + my $db_params; + if ( $ENV{HARNESS_ACTIVE} ) { + my $file = File::Temp->new( UNLINK => 1, SUFFIX => '.db' ); + return { SQLite => 'sqlite:' . $file }; + } + + die "Unable to determine dsn from configuration" + unless $self->config->{minion_dsn}; + + if ( $self->config->{minion_dsn} =~ /^postgresql:/ ) { + return { Pg => $self->config->{minion_dsn} }; + } + + if ( $self->config->{minion_dsn} =~ /^sqlite:/ ) { + return { SQLite => $self->config->{minion_dsn} }; + } + + die "Unsupported Database in dsn: " . $self->config->{minion_dsn}; +} + +sub _set_up_oauth_routes { + my $self = shift; + + my $oauth = $self->config->{oauth}; + + # We could do better DRY here, but it might be more complicated than it's + # worth + + $self->plugin( + 'Web::Auth', + module => 'Github', + key => $oauth->{github}->{key}, + secret => $oauth->{github}->{secret}, + user_info => 1, + on_finished => sub { + my ( $c, $access_token, $account_info ) = @_; + my $username = $account_info->{login}; + $c->session( is_logged_in => 1 ); + $c->session( github_username => $username ); + if ( $self->_is_admin($username) ) { + $c->redirect_to('/admin'); + return; + } + $c->redirect_to( $self->config->{front_end_url} ); + }, + ); +} + +1; diff --git a/lib/MetaCPAN/API/Controller/Admin.pm b/lib/MetaCPAN/API/Controller/Admin.pm new file mode 100644 index 000000000..a7095cf89 --- /dev/null +++ b/lib/MetaCPAN/API/Controller/Admin.pm @@ -0,0 +1,15 @@ +package MetaCPAN::API::Controller::Admin; + +use Mojo::Base 'Mojolicious::Controller'; + +sub identity_search_form { } + +sub search_identities { + my $self = shift; + my $data = $self->model->user->lookup( $self->param('name'), + $self->param('key') ); + $self->stash( user_data => $data ); + $self->render('admin/search_identities'); +} + +1; diff --git a/lib/MetaCPAN/API/Model/Role/ES.pm b/lib/MetaCPAN/API/Model/Role/ES.pm new file mode 100644 index 000000000..080b0e079 --- /dev/null +++ b/lib/MetaCPAN/API/Model/Role/ES.pm @@ -0,0 +1,16 @@ +package MetaCPAN::API::Model::Role::ES; + +use Moose::Role; + +use MetaCPAN::Types::TypeTiny qw( Object ); + +has es => ( + is => 'ro', + isa => Object, + handles => { _run_query => 'search', }, + required => 1, +); + +no Moose::Role; +1; + diff --git a/lib/MetaCPAN/API/Model/User.pm b/lib/MetaCPAN/API/Model/User.pm new file mode 100644 index 000000000..5414be5c0 --- /dev/null +++ b/lib/MetaCPAN/API/Model/User.pm @@ -0,0 +1,32 @@ +package MetaCPAN::API::Model::User; + +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Moose; + +with 'MetaCPAN::API::Model::Role::ES'; + +sub lookup { + my ( $self, $name, $key ) = @_; + + my $query = { + bool => { + must => [ + { term => { 'identity.name' => $name } }, + { term => { 'identity.key' => $key } }, + ] + } + }; + + my $res = $self->_run_query( + es_doc_path('account'), + body => { query => $query }, + search_type => 'dfs_query_then_fetch', + ); + + return $res->{hits}{hits}[0]{_source}; +} + +__PACKAGE__->meta->make_immutable; + +1; + diff --git a/lib/MetaCPAN/API/Plugin/Model.pm b/lib/MetaCPAN/API/Plugin/Model.pm new file mode 100644 index 000000000..f33dd4b8e --- /dev/null +++ b/lib/MetaCPAN/API/Plugin/Model.pm @@ -0,0 +1,49 @@ +package MetaCPAN::API::Plugin::Model; + +use Mojo::Base 'Mojolicious::Plugin'; + +use Carp (); + +# Models from the catalyst app +use MetaCPAN::Query::Search (); + +# New models +use MetaCPAN::API::Model::Cover (); +use MetaCPAN::API::Model::Download (); +use MetaCPAN::API::Model::User (); + +has app => sub { Carp::croak 'app is required' }, weak => 1; + +has download => sub { + my $self = shift; + return MetaCPAN::API::Model::Download->new( es => $self->app->es ); +}; + +has search => sub { + my $self = shift; + return MetaCPAN::Query::Search->new( es => $self->app->es, ); +}; + +has user => sub { + my $self = shift; + return MetaCPAN::API::Model::User->new( es => $self->app->es ); +}; + +has cover => sub { + my $self = shift; + return MetaCPAN::API::Model::Cover->new( es => $self->app->es ); +}; + +sub register { + my ( $plugin, $app, $conf ) = @_; + $plugin->app($app); + + # cached models + $app->helper( 'model.download' => sub { $plugin->download } ); + $app->helper( 'model.search' => sub { $plugin->search } ); + $app->helper( 'model.user' => sub { $plugin->user } ); + $app->helper( 'model.cover' => sub { $plugin->cover } ); +} + +1; + diff --git a/lib/MetaCPAN/Document/Author.pm b/lib/MetaCPAN/Document/Author.pm index 8cf6351f6..48296bb18 100644 --- a/lib/MetaCPAN/Document/Author.pm +++ b/lib/MetaCPAN/Document/Author.pm @@ -1,20 +1,25 @@ package MetaCPAN::Document::Author; -use strict; -use warnings; +use MetaCPAN::Moose; -# load order important for next 3 modules -use Moose; -use ElasticSearchX::Model::Document::Types qw(:all); +# load order important for next 2 modules +use ElasticSearchX::Model::Document::Types qw( Location ); use ElasticSearchX::Model::Document; # load order not important -use Gravatar::URL (); -use MetaCPAN::Types qw(:all); -use MetaCPAN::Util; -use MooseX::Types::Common::String qw(NonEmptySimpleStr); -use MooseX::Types::Moose qw( Int Num Str ArrayRef HashRef Undef); -use MooseX::Types::Structured qw(Dict Tuple Optional); +use Gravatar::URL (); +use MetaCPAN::Types qw( ESBool Profile ); +use MetaCPAN::Types::TypeTiny qw( + ArrayRef + ArrayRefPromote + Blog + Dict + HashRef + NonEmptySimpleStr + PerlMongers + Str +); +use MetaCPAN::Util qw(true false); has name => ( is => 'ro', @@ -27,12 +32,12 @@ has asciiname => ( is => 'ro', required => 1, index => 'analyzed', - isa => NonEmptySimpleStr, - required => 0, + isa => Str, + default => q{}, ); has [qw(website email)] => - ( is => 'ro', required => 1, isa => ArrayRef, coerce => 1 ); + ( is => 'ro', required => 1, isa => ArrayRefPromote, coerce => 1 ); has pauseid => ( is => 'ro', @@ -40,18 +45,17 @@ has pauseid => ( id => 1, ); -has user => ( is => 'rw' ); - -has dir => ( - is => 'ro', - required => 1, - lazy_build => 1, +has user => ( + is => 'ro', + writer => '_set_user', + clearer => '_clear_user', ); has gravatar_url => ( - is => 'ro', - lazy_build => 1, - isa => NonEmptySimpleStr, + is => 'ro', + isa => NonEmptySimpleStr, + lazy => 1, + builder => '_build_gravatar_url', ); has profile => ( @@ -59,56 +63,51 @@ has profile => ( isa => Profile, coerce => 1, type => 'nested', - required => 0, include_in_root => 1, ); has blog => ( - is => 'ro', - isa => Blog, - coerce => 1, - required => 0, - dynamic => 1, + is => 'ro', + isa => Blog, + coerce => 1, + dynamic => 1, ); has perlmongers => ( - is => 'ro', - isa => PerlMongers, - coerce => 1, - required => 0, - dynamic => 1, + is => 'ro', + isa => PerlMongers, + coerce => 1, + dynamic => 1, ); has donation => ( - is => 'ro', - isa => ArrayRef [ Dict [ name => NonEmptySimpleStr, id => Str ] ], - required => 0, - dynamic => 1, + is => 'ro', + isa => ArrayRef [ Dict [ name => NonEmptySimpleStr, id => Str ] ], + dynamic => 1, ); -has [qw(city region country)] => - ( is => 'ro', required => 0, isa => NonEmptySimpleStr ); +has [qw(city region country)] => ( is => 'ro', isa => NonEmptySimpleStr ); -has location => ( is => 'ro', isa => Location, coerce => 1, required => 0 ); +has location => ( is => 'ro', isa => Location, coerce => 1 ); has extra => ( is => 'ro', - isa => 'HashRef', + isa => HashRef, source_only => 1, dynamic => 1, - required => 0, ); has updated => ( - is => 'ro', - isa => 'DateTime', - required => 0, + is => 'ro', + isa => Str, ); -sub _build_dir { - my $pauseid = ref $_[0] ? shift->pauseid : shift; - return MetaCPAN::Util::author_dir($pauseid); -} +has is_pause_custodial_account => ( + is => 'ro', + isa => ESBool, + coerce => 1, + default => sub {false}, +); sub _build_gravatar_url { my $self = shift; @@ -117,11 +116,11 @@ sub _build_gravatar_url { # because we want to show the author's CPAN identity. # Using another e-mail than the CPAN one removes flexibility for # the author and ultimately could be a privacy leak. - # The author can manage this identity both on his gravatar account - # (by assigning an image to his author@cpan.org) + # The author can manage this identity both on their gravatar account + # (by assigning an image to their author@cpan.org) # and now by changing this URL from metacpa.org return Gravatar::URL::gravatar_url( - email => $self->{pauseid} . '@cpan.org', + email => $self->pauseid . '@cpan.org', size => 130, https => 1, @@ -158,7 +157,6 @@ sub validate { } __PACKAGE__->meta->make_immutable; - 1; =pod diff --git a/lib/MetaCPAN/Document/Author/Profile.pm b/lib/MetaCPAN/Document/Author/Profile.pm index 3a12fff69..497828b07 100644 --- a/lib/MetaCPAN/Document/Author/Profile.pm +++ b/lib/MetaCPAN/Document/Author/Profile.pm @@ -6,18 +6,23 @@ use warnings; use Moose; use ElasticSearchX::Model::Document; +with 'ElasticSearchX::Model::Document::EmbeddedRole'; + +use MetaCPAN::Types::TypeTiny qw( Str ); use MetaCPAN::Util; has name => ( is => 'ro', - isa => 'Str', + isa => Str, required => 1, ); has id => ( is => 'ro', - isa => 'Str', + isa => Str, analyzer => ['simple'], ); __PACKAGE__->meta->make_immutable; + +1; diff --git a/lib/MetaCPAN/Document/CVE.pm b/lib/MetaCPAN/Document/CVE.pm new file mode 100644 index 000000000..155b1b57a --- /dev/null +++ b/lib/MetaCPAN/Document/CVE.pm @@ -0,0 +1,63 @@ +package MetaCPAN::Document::CVE; + +use MetaCPAN::Moose; + +use ElasticSearchX::Model::Document; +use MetaCPAN::Types::TypeTiny qw( ArrayRef Str ); + +has distribution => ( + is => 'ro', + isa => Str, + required => 1, +); + +has cpansa_id => ( + is => 'ro', + isa => Str, + required => 1, +); + +has description => ( + is => 'ro', + isa => Str, + required => 1, +); + +has severity => ( + is => 'ro', + isa => Str, + required => 1, +); + +has reported => ( + is => 'ro', + isa => Str, + required => 1, +); + +has affected_versions => ( + is => 'ro', + isa => ArrayRef, + required => 1, +); + +has cves => ( + is => 'ro', + isa => ArrayRef, + required => 1, +); + +has references => ( + is => 'ro', + isa => ArrayRef, + required => 1, +); + +has versions => ( + is => 'ro', + isa => ArrayRef, + required => 1, +); + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Document/Contributor.pm b/lib/MetaCPAN/Document/Contributor.pm new file mode 100644 index 000000000..dec572834 --- /dev/null +++ b/lib/MetaCPAN/Document/Contributor.pm @@ -0,0 +1,42 @@ +package MetaCPAN::Document::Contributor; + +use MetaCPAN::Moose; + +use ElasticSearchX::Model::Document; +use MetaCPAN::Types::TypeTiny qw( ArrayRef Str ); + +has distribution => ( + is => 'ro', + isa => Str, + required => 1, +); + +has release_author => ( + is => 'ro', + isa => Str, + required => 1, +); + +has release_name => ( + is => 'ro', + isa => Str, + required => 1, +); + +has pauseid => ( + is => 'ro', + isa => Str, +); + +has name => ( + is => 'ro', + isa => Str, +); + +has email => ( + is => 'ro', + isa => ArrayRef [Str], +); + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Document/Cover.pm b/lib/MetaCPAN/Document/Cover.pm new file mode 100644 index 000000000..1ab9a5991 --- /dev/null +++ b/lib/MetaCPAN/Document/Cover.pm @@ -0,0 +1,33 @@ +package MetaCPAN::Document::Cover; + +use MetaCPAN::Moose; + +use ElasticSearchX::Model::Document; +use MetaCPAN::Types::TypeTiny qw( HashRef Str ); + +has distribution => ( + is => 'ro', + isa => Str, + required => 1, +); + +has release => ( + is => 'ro', + isa => Str, + required => 1, +); + +has version => ( + is => 'ro', + isa => Str, + required => 1, +); + +has criteria => ( + is => 'ro', + isa => HashRef, + required => 1, +); + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Document/Dependency.pm b/lib/MetaCPAN/Document/Dependency.pm index 92ce26a3f..e54f85fd9 100644 --- a/lib/MetaCPAN/Document/Dependency.pm +++ b/lib/MetaCPAN/Document/Dependency.pm @@ -6,20 +6,11 @@ use warnings; use Moose; use ElasticSearchX::Model::Document; +with 'ElasticSearchX::Model::Document::EmbeddedRole'; + use MetaCPAN::Util; has [qw(phase relationship module version)] => ( is => 'ro', required => 1 ); -has version_numified => ( - is => 'ro', - required => 1, - isa => 'Num', - lazy_build => 1, -); - -sub _build_version_numified { - return MetaCPAN::Util::numify_version( shift->version ); -} - __PACKAGE__->meta->make_immutable; 1; diff --git a/lib/MetaCPAN/Document/Distribution.pm b/lib/MetaCPAN/Document/Distribution.pm index 19baa4e81..64c178664 100644 --- a/lib/MetaCPAN/Document/Distribution.pm +++ b/lib/MetaCPAN/Document/Distribution.pm @@ -7,8 +7,8 @@ use namespace::autoclean; use Moose; use ElasticSearchX::Model::Document; -use MetaCPAN::Types qw(BugSummary); -use MooseX::Types::Moose qw(ArrayRef); +use MetaCPAN::Types::TypeTiny qw( BugSummary RiverSummary ); +use MetaCPAN::Util qw(true false); has name => ( is => 'ro', @@ -17,39 +17,48 @@ has name => ( ); has bugs => ( - is => 'rw', + is => 'ro', isa => BugSummary, dynamic => 1, + writer => '_set_bugs', +); + +has river => ( + is => 'ro', + isa => RiverSummary, + dynamic => 1, + writer => '_set_river', + default => sub { + +{ + bucket => 0, + bus_factor => 1, + immediate => 0, + total => 0, + }; + }, ); sub releases { my $self = shift; - return $self->index->type("release") - ->filter( { term => { "release.distribution" => $self->name } } ); + return $self->index->model->doc("release") + ->query( { term => { "distribution" => $self->name } } ); } sub set_first_release { my $self = shift; - $self->unset_first_release; - my $release = $self->releases->sort( ["date"] )->first; - return unless $release; - return $release if $release->first; - $release->first(1); - $release->put; - return $release; -} -sub unset_first_release { - my $self = shift; - my $releases - = $self->releases->filter( { term => { "release.first" => \1 }, } ) - ->size(200)->scroll; - while ( my $release = $releases->next ) { - $release->first(0); - $release->update; + my @releases = $self->releases->sort( ["date"] )->all; + + my $first = shift @releases; + $first->_set_first(true); + $first->put; + + for my $rel (@releases) { + $rel->_set_first(false); + $rel->put; } - $self->index->refresh if $releases->total; - return $releases->total; + + return $first; } __PACKAGE__->meta->make_immutable; diff --git a/lib/MetaCPAN/Document/Favorite.pm b/lib/MetaCPAN/Document/Favorite.pm index 013692a56..eaf7cbcf1 100644 --- a/lib/MetaCPAN/Document/Favorite.pm +++ b/lib/MetaCPAN/Document/Favorite.pm @@ -6,8 +6,7 @@ use warnings; use Moose; use ElasticSearchX::Model::Document; -use DateTime; -use MetaCPAN::Types qw(:all); +use DateTime (); use MetaCPAN::Util; has id => ( @@ -33,15 +32,5 @@ has date => ( default => sub { DateTime->now }, ); -=head2 timestamp - -Sets the C<_timestamp> field to the value of L. - -=cut - -has timestamp => ( - is => 'ro', - timestamp => { path => 'date', store => 1 }, -); - __PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Document/File.pm b/lib/MetaCPAN/Document/File.pm index adb9b188c..c9fd79c8a 100644 --- a/lib/MetaCPAN/Document/File.pm +++ b/lib/MetaCPAN/Document/File.pm @@ -7,26 +7,45 @@ use utf8; use Moose; use ElasticSearchX::Model::Document; -use Encode; -use List::AllUtils qw( any ); -use List::MoreUtils qw(any uniq); -use MetaCPAN::Document::Module; -use MetaCPAN::Types qw(:all); -use MetaCPAN::Util; -use MooseX::Types::Moose qw(ArrayRef); -use Plack::MIME; -use Pod::Text; -use Try::Tiny; -use URI::Escape (); - -Plack::MIME->add_type( ".t" => "text/x-script.perl" ); -Plack::MIME->add_type( ".pod" => "text/x-pod" ); -Plack::MIME->add_type( ".xs" => "text/x-c" ); +use List::Util qw( any ); +use MetaCPAN::Document::Module (); +use MetaCPAN::Types qw( ESBool Module ); +use MetaCPAN::Types::TypeTiny qw( ArrayRef Int Maybe Num ScalarRef Stat Str ); +use MetaCPAN::Util qw(numify_version true false); +use Plack::MIME (); +use Pod::Text (); +use Try::Tiny qw( catch try ); + +Plack::MIME->add_type( '.t' => 'text/x-script.perl' ); +Plack::MIME->add_type( '.pod' => 'text/x-pod' ); +Plack::MIME->add_type( '.xs' => 'text/x-c' ); my @NOT_PERL_FILES = qw(SIGNATURE); +sub BUILD { + my $self = shift; + + # force building of `mime` + $self->_build_mime; +} + =head1 PROPERTIES +=head2 deprecated + +Indicates file deprecation (the abstract contains "DEPRECATED" or "DEPRECIATED", +or the x_deprecated flag is included in the corresponding "provides" entry in distribution metadata); +it is also set if the entire release is marked deprecated (see L). + +=cut + +has deprecated => ( + is => 'ro', + isa => ESBool, + default => sub {false}, + writer => '_set_deprecated', +); + =head2 abstract Abstract of the documentation (if any). This is built by parsing the @@ -34,18 +53,20 @@ C section. It also sets L if it succeeds. =cut -has abstract => ( - is => 'ro', - required => 1, - lazy_build => 1, - index => 'analyzed', +has section => ( + is => 'ro', + isa => Maybe [Str], + lazy => 1, + builder => '_build_section', + property => 0, ); -sub _build_abstract { +my $RE_SECTION = qr/^\s*(\S+)((\h+-+\h+(.+))|(\r?\n\h*\r?\n\h*(.+)))?/ms; + +sub _build_section { my $self = shift; - return undef unless ( $self->is_perl_file ); - my $text = ${ $self->content }; - my ( $documentation, $abstract ); + + my $text = ${ $self->content }; my $section = MetaCPAN::Util::extract_section( $text, 'NAME' ); # if it's a POD file without a name section, let's try to generate @@ -61,10 +82,29 @@ sub _build_abstract { $section =~ s/^=\w+.*$//mg; $section =~ s/X<.*?>//mg; - if ( $section =~ /^\s*(\S+)((\h+-+\h+(.+))|(\r?\n\h*\r?\n\h*(.+)))?/ms ) { + return $section; +} + +has abstract => ( + required => 1, + is => 'ro', + isa => Maybe [Str], + lazy => 1, + builder => '_build_abstract', + index => 'analyzed', +); + +sub _build_abstract { + my $self = shift; + return undef unless ( $self->is_perl_file ); + + my $section = $self->section; + return undef unless $section; + + my $abstract; + + if ( $section =~ $RE_SECTION ) { chomp( $abstract = $4 || $6 ) if ( $4 || $6 ); - my $name = MetaCPAN::Util::strip_pod($1); - $documentation = $name if ( $name =~ /^[\w\.:\-_']+$/ ); } if ($abstract) { $abstract =~ s/^=\w+.*$//xms; @@ -74,9 +114,6 @@ sub _build_abstract { $abstract =~ s{(\s)+}{$1}gxms; $abstract = MetaCPAN::Util::strip_pod($abstract); } - if ($documentation) { - $self->documentation( MetaCPAN::Util::strip_pod($documentation) ); - } return $abstract; } @@ -102,17 +139,30 @@ modules defined in that class (i.e. package declarations). =cut has module => ( - required => 0, - is => 'rw', + is => 'ro', isa => Module, type => 'nested', include_in_root => 1, coerce => 1, clearer => 'clear_module', + writer => '_set_module', lazy => 1, default => sub { [] }, ); +=head2 download_url + +B + +Download URL of the release + +=cut + +has download_url => ( + is => 'ro', + required => 1 +); + =head2 date B @@ -135,29 +185,34 @@ whitespaces and POD commands. =cut has description => ( - is => 'ro', - required => 1, - lazy_build => 1, - index => 'analyzed', + required => 1, + is => 'ro', + lazy => 1, + builder => '_build_description', + index => 'not_analyzed', ); sub _build_description { my $self = shift; return undef unless ( $self->is_perl_file ); - my $section = MetaCPAN::Util::extract_section( ${ $self->content }, + my $section + = MetaCPAN::Util::extract_section( ${ $self->content }, 'DESCRIPTION' ); return undef unless ($section); + my $parser = Pod::Text->new; - my $text = ""; + my $text = q{}; $parser->output_string( \$text ); try { $parser->parse_string_document("=pod\n\n$section"); } catch { - warn $_[0]; + warn $_; }; + return undef unless $text; + $text =~ s/\s+/ /g; $text =~ s/^\s+//; $text =~ s/\s+$//; @@ -196,9 +251,9 @@ File is binary or not. has binary => ( is => 'ro', - isa => 'Bool', + isa => ESBool, required => 1, - default => 0, + default => sub {false}, ); =head2 authorized @@ -209,9 +264,10 @@ See L. has authorized => ( required => 1, - is => 'rw', - isa => 'Bool', - default => 1, + is => 'ro', + isa => ESBool, + default => sub {true}, + writer => '_set_authorized', ); =head2 maturity @@ -236,8 +292,8 @@ Return true if this object represents a directory. has directory => ( is => 'ro', required => 1, - isa => 'Bool', - default => 0, + isa => ESBool, + default => sub {false}, ); =head2 documentation @@ -254,36 +310,105 @@ set to C. =cut has documentation => ( - required => 1, - is => 'rw', - lazy_build => 1, - index => 'analyzed', - predicate => 'has_documentation', - analyzer => [qw(standard camelcase lowercase)], - clearer => 'clear_documentation', + is => 'ro', + isa => Maybe [Str], + lazy => 1, + index => 'analyzed', + builder => '_build_documentation', + predicate => 'has_documentation', + analyzer => [qw(standard camelcase lowercase edge edge_camelcase)], + clearer => 'clear_documentation', + writer => '_set_documentation', ); sub _build_documentation { my $self = shift; - $self->_build_abstract; - my $documentation = $self->documentation if ( $self->has_documentation ); - return undef unless ( ${ $self->pod } ); + return undef unless ( $self->is_perl_file ); + + my $section = $self->section; + return undef unless $section; + + my $documentation; + + if ( $section =~ $RE_SECTION ) { + my $name = MetaCPAN::Util::strip_pod($1); + $documentation = $name if ( $name =~ /^[\w\.:\-_']+$/ ); + } + + $documentation = MetaCPAN::Util::strip_pod($documentation) + if $documentation; + + return undef unless length $documentation; + + # Modules to be indexed my @indexed = grep { $_->indexed } @{ $self->module || [] }; + + # This is a Pod file, return its name if ( $documentation && $self->is_pod_file ) { return $documentation; } - elsif ( $documentation && grep { $_->name eq $documentation } @indexed ) { + + # OR: found an indexed module with the same name + if ( $documentation && grep { $_->name eq $documentation } @indexed ) { return $documentation; } - elsif (@indexed) { - return $indexed[0]->name; - } - elsif ( !@{ $self->module || [] } ) { - return $documentation; + + # OR: found an indexed module with a name + if ( my ($mod) = grep { defined $_->name } @indexed ) { + return $mod->name; } - else { - return undef; + + # OR: we have a parsed documentation + return $documentation if defined $documentation; + + # OR: found ANY module with a name (better than nothing) + if ( my ($mod) = grep { defined $_->name } @{ $self->module || [] } ) { + return $mod->name; } + + return undef; +} + +has documentation_length => ( + is => 'ro', + isa => Maybe [Int], + lazy => 1, + builder => '_build_documentation_length', +); + +sub _build_documentation_length { + my ($self) = @_; + return length( $self->documentation ); +} + +=head2 suggest + +Autocomplete info for documentation. + +=cut + +has suggest => ( + is => 'ro', + + # isa => Maybe [HashRef], # remarked: breaks the suggester + lazy => 1, + builder => '_build_suggest', +); + +sub _build_suggest { + my $self = shift; + my $doc = $self->documentation; + + # return +{} unless $doc; # remarked because of 'isa' + return unless $doc; + + my $weight = 1000 - length($doc); + $weight = 0 if $weight < 0; + + return +{ + input => [$doc], + weight => $weight, + }; } =head2 indexed @@ -297,15 +422,16 @@ not. See L for a more verbose explanation. has indexed => ( required => 1, - is => 'rw', - isa => 'Bool', + is => 'ro', + isa => ESBool, lazy => 1, default => sub { my ($self) = @_; - return 0 if $self->is_in_other_files; - return 0 if !$self->metadata->should_index_file( $self->path ); - return 1; + return false if $self->is_in_other_files; + return false if !$self->metadata->should_index_file( $self->path ); + return true; }, + writer => '_set_indexed', ); =head2 level @@ -316,14 +442,15 @@ has a level of C<0>). =cut has level => ( - is => 'ro', - required => 1, - isa => 'Int', - lazy_build => 1, + required => 1, + is => 'ro', + isa => Int, + lazy => 1, + builder => '_build_level', ); sub _build_level { - my $self = shift; + my $self = shift; my @level = split( /\//, $self->path ); return @level - 1; } @@ -336,10 +463,11 @@ are removed to save space and for better snippet previews. =cut has pod => ( - is => 'ro', required => 1, - isa => 'ScalarRef', - lazy_build => 1, + is => 'ro', + isa => ScalarRef, + lazy => 1, + builder => '_build_pod', index => 'analyzed', not_analyzed => 0, store => 'no', @@ -413,19 +541,19 @@ ArrayRef of ArrayRefs of offset and length of pod blocks. Example: =cut has pod_lines => ( - is => 'ro', - required => 1, - isa => 'ArrayRef', - type => 'integer', - lazy_build => 1, - index => 'no', + is => 'ro', + isa => ArrayRef, + type => 'integer', + lazy => 1, + builder => '_build_pod_lines', + index => 'no', ); sub _build_pod_lines { my $self = shift; return [] unless ( $self->is_perl_file ); my ( $lines, $slop ) = MetaCPAN::Util::pod_lines( ${ $self->content } ); - $self->slop( $slop || 0 ); + $self->_set_slop( $slop || 0 ); return $lines; } @@ -437,10 +565,11 @@ L and returns the number of lines. =cut has sloc => ( - is => 'ro', - required => 1, - isa => 'Int', - lazy_build => 1, + required => 1, + is => 'ro', + isa => Int, + lazy => 1, + builder => '_build_sloc', ); # Metrics from Perl::Metrics2::Plugin::Core. @@ -449,7 +578,7 @@ sub _build_sloc { return 0 unless ( $self->is_perl_file ); my @content = split( "\n", ${ $self->content } ); - my $pods = 0; + my $pods = 0; # Use pod_lines data to remove pod content from string. map { @@ -472,32 +601,35 @@ Source Lines of Pod. Returns the number of pod lines using L. =cut has slop => ( - is => 'ro', - required => 1, - isa => 'Int', - is => 'rw', - lazy_build => 1, + required => 1, + is => 'ro', + isa => Int, + lazy => 1, + builder => '_build_slop', + writer => '_set_slop', ); sub _build_slop { my $self = shift; return 0 unless ( $self->is_perl_file ); $self->_build_pod_lines; + + # danger! infinite recursion if not set by `_build_pod_lines` + # we should probably find a better solution -- Mickey return $self->slop; } =head2 stat -L info of the archive file. Contains C, C, -C, C and C. +L info of the archive file. Contains C, +C and C. =cut has stat => ( - is => 'ro', - isa => Stat, - required => 0, - dynamic => 1, + is => 'ro', + isa => Stat, + dynamic => 1, ); =head2 version @@ -506,14 +638,11 @@ Contains the raw version string. =cut -has version => ( - is => 'ro', - required => 0, -); +has version => ( is => 'ro', ); =head2 version_numified -B, B +B Numeric representation of L. Contains 0 if there is no version or the version could not be parsed. @@ -521,16 +650,16 @@ version could not be parsed. =cut has version_numified => ( - is => 'ro', - isa => 'Num', - lazy_build => 1, - required => 1, + required => 1, + is => 'ro', + isa => Num, + lazy => 1, + builder => '_build_version_numified', ); sub _build_version_numified { my $self = shift; - return 0 unless ( $self->version ); - return MetaCPAN::Util::numify_version( $self->version ); + return numify_version( $self->version ); } =head2 mime @@ -540,9 +669,10 @@ MIME type of file. Derived using L (for speed). =cut has mime => ( - is => 'ro', - required => 1, - lazy_build => 1, + required => 1, + is => 'ro', + lazy => 1, + builder => '_build_mime', ); sub _build_mime { @@ -566,6 +696,22 @@ sub _build_path { return join( '/', $self->release->name, $self->name ); } +has dir => ( + is => 'ro', + isa => Str, + lazy => 1, + builder => '_build_dir', + index => 'not_analyzed' +); + +sub _build_dir { + my $self = shift; + $DB::single = 1; + my $dir = $self->path; + $dir =~ s{/[^/]+$}{}; + return $dir; +} + has [qw(release distribution)] => ( is => 'ro', required => 1, @@ -579,39 +725,15 @@ These attributes are not stored. =head2 content A scalar reference to the content of the file. -Built by calling L. =cut has content => ( - is => 'ro', - isa => 'ScalarRef', - lazy_build => 1, - property => 0, - required => 0, -); - -sub _build_content { - my $self = shift; - - # NOTE: We used to remove the __DATA__ section "for performance reasons" - # however removing lines from the content will throw off pod_lines. - return $self->content_cb->(); -} - -=head2 content_cb - -Callback that returns the content of the file as a ScalarRef. - -=cut - -has content_cb => ( is => 'ro', + isa => ScalarRef, + lazy => 1, + default => sub { \"" }, property => 0, - required => 0, - default => sub { - sub { \'' } - }, ); =head2 local_path @@ -632,10 +754,10 @@ Reference to the L object of the release. =cut has metadata => ( - is => "ro", + is => 'ro', + isa => 'CPAN::Meta', lazy => 1, - default => sub { die "meta attribute missing" }, - isa => "CPAN::Meta", + default => sub { die 'meta attribute missing' }, property => 0, ); @@ -684,7 +806,7 @@ sub add_module { my ( $self, @modules ) = @_; $_ = MetaCPAN::Document::Module->new($_) for ( grep { ref $_ eq 'HASH' } @modules ); - $self->module( [ @{ $self->module }, @modules ] ); + $self->_set_module( [ @{ $self->module }, @modules ] ); } =head2 is_in_other_files @@ -739,7 +861,7 @@ Expects a C<$meta> parameter which is an instance of L. For each package (L) in the file and based on L it is decided, whether the module should have a true L attribute. -If there are any packages with leading underscores, the module gets a false +If there are any packages with leading underscores, the module gets a false L attribute, because PAUSE doesn't allow this kind of name for packages (https://github.com/andk/pause/blob/master/lib/PAUSE/pmfile.pm#L249). @@ -760,36 +882,60 @@ does not include any modules, the L property is true. sub set_indexed { my ( $self, $meta ) = @_; - #files listed under 'other files' are not shown in a search + # modules explicitly listed in 'provides' should be indexed + foreach my $mod ( @{ $self->module } ) { + if ( exists $meta->provides->{ $mod->name } + and $self->path eq $meta->provides->{ $mod->name }{file} ) + { + $mod->_set_indexed(true); + return; + } + } + + # files listed under 'other files' are not shown in a search if ( $self->is_in_other_files() ) { foreach my $mod ( @{ $self->module } ) { - $mod->indexed(0); + $mod->_set_indexed(false); } - $self->indexed(0); + $self->_set_indexed(false); return; } + # files under no_index directories should not be indexed + foreach my $dir ( @{ $meta->no_index->{directory} } ) { + if ( $self->path eq $dir or $self->path =~ /^$dir\// ) { + $self->_set_indexed(false); + return; + } + } + foreach my $mod ( @{ $self->module } ) { - if ( $mod->name !~ /^[A-Za-z]/ ) { - $mod->indexed(0); + if ( $mod->name !~ /^[A-Za-z]/ + or !$meta->should_index_package( $mod->name ) ) + { + $mod->_set_indexed(false); next; } - $mod->indexed( - $meta->should_index_package( $mod->name ) - ? $mod->hide_from_pause( ${ $self->content }, $self->name ) - ? 0 - : 1 - : 0 - ) unless ( $mod->indexed ); + + $mod->_set_indexed(true); } - $self->indexed( - # .pm file with no package declaration but pod should be indexed - !@{ $self->module } || + if ( my $doc_name = $self->documentation ) { + + # normalize the documentation name for comparison the same way module + # names are normalized + my $normalized_doc_name = $doc_name =~ s{'}{::}gr; + $self->_set_indexed( + ( + # .pm file with no package declaration but pod should be indexed + !@{ $self->module } || # don't index if the documentation doesn't match any of its modules - !!grep { $self->documentation eq $_->name } @{ $self->module } - ) if ( $self->documentation ); + grep { $normalized_doc_name eq $_->name } + @{ $self->module } + ) ? true : false + ); + } } =head2 set_authorized @@ -819,19 +965,27 @@ as unauthorized as well. sub set_authorized { my ( $self, $perms ) = @_; - # only authorized perl distributions make it into the CPAN - return () if ( $self->distribution eq 'perl' ); - foreach my $module ( @{ $self->module } ) { - $module->authorized(0) - if ( $perms->{ $module->name } && !grep { $_ eq $self->author } - @{ $perms->{ $module->name } } ); + if ( $self->distribution eq 'perl' ) { + my $allowed = grep $_ eq $self->author, @{ $perms->{perl} }; + foreach my $module ( @{ $self->module } ) { + $module->_set_authorized( $allowed ? true : false ); + } + $self->_set_authorized( $allowed ? true : false ); + } + else { + foreach my $module ( @{ $self->module } ) { + $module->_set_authorized(false) + if ( $perms->{ $module->name } + && !grep { $_ eq $self->author } + @{ $perms->{ $module->name } } ); + } + $self->_set_authorized(false) + if ( $self->authorized + && $self->documentation + && $perms->{ $self->documentation } + && !grep { $_ eq $self->author } + @{ $perms->{ $self->documentation } } ); } - $self->authorized(0) - if ( $self->authorized - && $self->documentation - && $perms->{ $self->documentation } - && !grep { $_ eq $self->author } - @{ $perms->{ $self->documentation } } ); return grep { !$_->authorized && $_->indexed } @{ $self->module }; } @@ -843,248 +997,7 @@ Concatenate L, L and L. sub full_path { my $self = shift; - return join( "/", $self->author, $self->release, $self->path ); -} - -__PACKAGE__->meta->make_immutable; - -package MetaCPAN::Document::File::Set; -use Moose; -extends 'ElasticSearchX::Model::Document::Set'; - -my @ROGUE_DISTRIBUTIONS - = qw(kurila perl_debug perl-5.005_02+apache1.3.3+modperl pod2texi perlbench spodcxx Bundle-Everything); - -sub find { - my ( $self, $module ) = @_; - my @candidates = $self->index->type("file")->filter( - { - and => [ - { - or => [ - { term => { 'file.module.name' => $module } }, - { term => { 'file.documentation' => $module } }, - ] - }, - { term => { 'file.indexed' => \1, } }, - { term => { status => 'latest', } }, - { - not => - { filter => { term => { 'file.authorized' => \0 } } } - }, - ] - } - )->sort( - [ - { 'date' => { order => "desc" } }, - 'mime', - { 'stat.mtime' => { order => 'desc' } } - ] - )->size(100)->all; - - my ($file) = grep { - grep { $_->indexed && $_->authorized && $_->name eq $module } - @{ $_->module || [] } - } grep { !$_->documentation || $_->documentation eq $module } - @candidates; - - $file ||= shift @candidates; - return $file ? $self->get( $file->id ) : undef; -} - -sub find_pod { - my ( $self, $name ) = @_; - my $file = $self->find($name); - return $file unless ($file); - my ($module) - = grep { $_->indexed && $_->authorized && $_->name eq $name } - @{ $file->module || [] }; - if ( $module && ( my $pod = $module->associated_pod ) ) { - my ( $author, $release, @path ) = split( /\//, $pod ); - return $self->get( - { - author => $author, - release => $release, - path => join( "/", @path ), - } - ); - } - else { - return $file; - } -} - -# return files that contain modules that match the given dist -# NOTE: these still need to be filtered by authorized/indexed -# TODO: test that we are getting the correct version (latest) -sub find_provided_by { - my ( $self, $release ) = @_; - return $self->filter( - { - and => [ - { term => { 'release' => $release->{name} } }, - { term => { 'author' => $release->{author} } }, - { term => { 'file.module.authorized' => 1 } }, - { term => { 'file.module.indexed' => 1 } }, - ] - } - )->size(999)->all; -} - -# filter find_provided_by results for indexed/authorized modules -# and return a list of package names -sub find_module_names_provided_by { - my ( $self, $release ) = @_; - my $mods = $self->inflate(0)->find_provided_by($release); - return ( - map { $_->{name} } - grep { $_->{indexed} && $_->{authorized} } - map { @{ $_->{_source}->{module} } } @{ $mods->{hits}->{hits} } - ); -} - -# TODO: figure out what uses this and write tests for it -sub prefix { - my ( $self, $prefix ) = @_; - my @query = split( /\s+/, $prefix ); - my $should = [ - map { - { field => { 'documentation.analyzed' => "$_*" } }, - { field => { 'documentation.camelcase' => "$_*" } } - } grep {$_} @query - ]; - return $self->query( - { - filtered => { - query => { - custom_score => { - query => { bool => { should => $should } }, - - #metacpan_script => 'prefer_shorter_module_names_100', - script => - "_score - doc['documentation'].value.length()/100" - }, - }, - filter => { - and => [ - { - not => { - filter => { - or => [ - map { - +{ - term => { - 'file.distribution' => $_ - } - } - } @ROGUE_DISTRIBUTIONS - - ] - } - } - }, - { exists => { field => 'documentation' } }, - { term => { 'file.indexed' => \1 } }, - { term => { 'file.status' => 'latest' } }, - { - not => { - filter => - { term => { 'file.authorized' => \0 } } - } - } - ] - } - } - } - ); -} - -=head2 history - -Find the history of a given module/documentation. - -=cut - -sub history { - my ( $self, $type, $module, @path ) = @_; - my $search - = $type eq "module" ? $self->filter( - { - nested => { - path => "module", - query => { - constant_score => { - filter => { - and => [ - { term => { "module.authorized" => \1 } }, - { term => { "module.indexed" => \1 } }, - { term => { "module.name" => $module } }, - ] - } - } - } - } - } - ) - : $type eq "file" ? $self->filter( - { - and => [ - { term => { "file.path" => join( "/", @path ) } }, - { term => { "file.distribution" => $module } }, - ] - } - ) - : $self->filter( - { - and => [ - { term => { "file.documentation" => $module } }, - { term => { "file.indexed" => \1 } }, - { term => { "file.authorized" => \1 } }, - ] - } - ); - return $search->sort( [ { "file.date" => "desc" } ] ); -} - -sub _not_rogue { - my @rogue_dists = map { { term => { 'file.distribution' => $_ } } } - @ROGUE_DISTRIBUTIONS; - return { not => { filter => { or => \@rogue_dists } } }; -} - -sub autocomplete { - my ( $self, @terms ) = @_; - my $query = join( " ", @terms ); - return $self unless $query; - $query =~ s/::/ /g; - my @query = split( /\s+/, $query ); - my $should = [ - map { - { field => { 'documentation.analyzed' => "$_*" } }, - { field => { 'documentation.camelcase' => "$_*" } } - } grep {$_} @query - ]; - - # TODO: custom_score is deprecated in 0.90.4 in favor of function_score. - # As of 2013-10-27 we are still using 0.20.2 in production. - return $self->query( - { - custom_score => { - query => { bool => { should => $should } }, - script => "_score - doc['documentation'].value.length()/100", - } - } - )->filter( - { - and => [ - $self->_not_rogue, - { exists => { field => 'documentation' } }, - { term => { 'file.indexed' => \1 } }, - { term => { 'file.authorized' => \1 } }, - { term => { 'file.status' => 'latest' } }, - ] - } - )->sort( [ '_score', 'documentation' ] ); + return join( '/', $self->author, $self->release, $self->path ); } __PACKAGE__->meta->make_immutable; diff --git a/lib/MetaCPAN/Document/Mirror.pm b/lib/MetaCPAN/Document/Mirror.pm index 89d1eb8a5..7b3b04e94 100644 --- a/lib/MetaCPAN/Document/Mirror.pm +++ b/lib/MetaCPAN/Document/Mirror.pm @@ -4,10 +4,10 @@ use strict; use warnings; use Moose; -use ElasticSearchX::Model::Document::Types qw(:all); +use MooseX::Types::ElasticSearch qw( Location ); use ElasticSearchX::Model::Document; -use MetaCPAN::Util; +use MetaCPAN::Types::TypeTiny qw( Dict Str ); has name => ( is => 'ro', @@ -28,10 +28,11 @@ has location => ( isa => Location, coerce => 1, ); + has contact => ( is => 'ro', required => 1, - isa => 'ArrayRef', + isa => Dict [ contact_site => Str, contact_user => Str ], ); has [qw(inceptdate reitredate)] => ( diff --git a/lib/MetaCPAN/Document/Module.pm b/lib/MetaCPAN/Document/Module.pm index ef749252b..a3901bae1 100644 --- a/lib/MetaCPAN/Document/Module.pm +++ b/lib/MetaCPAN/Document/Module.pm @@ -6,8 +6,11 @@ use warnings; use Moose; use ElasticSearchX::Model::Document; -use MetaCPAN::Types qw(AssociatedPod); -use MetaCPAN::Util; +with 'ElasticSearchX::Model::Document::EmbeddedRole'; + +use MetaCPAN::Types qw( ESBool ); +use MetaCPAN::Types::TypeTiny qw( Maybe Num Str ); +use MetaCPAN::Util qw(true false); =head1 SYNOPSIS @@ -36,13 +39,6 @@ the C and the C property. Contains the raw version string. -=head2 version_numified - -B, B - -Numified version of L. Contains 0 if there is no version or the -version could not be parsed. - =head2 indexed B @@ -67,6 +63,7 @@ not declared in one line, the module is considered not-indexed. has name => ( is => 'ro', + isa => Str, required => 1, index => 'analyzed', analyzer => [qw(standard camelcase lowercase)], @@ -74,32 +71,35 @@ has name => ( has version => ( is => 'ro' ); -has version_numified => ( - is => 'ro', - isa => 'Num', - lazy_build => 1, - required => 1, -); - has indexed => ( - is => 'rw', + is => 'ro', required => 1, - isa => 'Bool', - default => 0, + isa => ESBool, + default => sub {true}, + writer => '_set_indexed', ); has authorized => ( - is => 'rw', + is => 'ro', required => 1, - isa => 'Bool', - default => 1, + isa => ESBool, + default => sub {true}, + writer => '_set_authorized', ); -# REINDEX: make 'ro' once a full reindex has been done has associated_pod => ( - isa => AssociatedPod, - required => 0, - is => 'rw', + required => 1, + isa => Maybe [Str], + is => 'ro', + default => sub { }, + writer => '_set_associated_pod', +); + +has version_numified => ( + is => 'ro', + isa => Num, + lazy_build => 1, + required => 1, ); sub _build_version_numified { @@ -111,30 +111,6 @@ sub _build_version_numified { my $bom = qr/(?:\x00\x00\xfe\xff|\xff\xfe\x00\x00|\xfe\xff|\xff\xfe|\xef\xbb\xbf)/; -sub hide_from_pause { - my ( $self, $content, $file_name ) = @_; - return 0 if defined($file_name) && $file_name =~ m{\.pm\.PL\z}; - my $pkg = $self->name; - -# This regexp is *almost* the same as $PKG_REGEXP in Module::Metadata. -# [b] We need to allow/ignore a possible BOM since we read in binary mode. -# Module::Metadata, for example, checks for a BOM and then sets the encoding. -# [s] We change `\s` to `\h` because we want to verify that it's on one line. -# [p] We replace $PKG_NAME_REGEXP with the specific package we're looking for. -# [v] Simplify the optional whitespace/version group ($V_NUM_REGEXP). - return $content =~ / # match a package declaration - ^ # start of line - (?:\A$bom)? # possible BOM at the start of the file [b] - [\h\{;]* # intro chars on a line [s] - package # the word 'package' - \h+ # whitespace [s] - (\Q$pkg\E) # a package name [p] - (\h+ v?[0-9._]+)? # optional version number (preceded by whitespace) [v] - \h* # optional whitesapce [s] - [;\{] # semicolon line terminator or block start - /mx ? 0 : 1; -} - =head2 set_associated_pod Expects an instance C<$file> of L as first parameter @@ -152,14 +128,12 @@ my %_pod_score = ( ); sub set_associated_pod { - - # FIXME: Why is $file passed if it isn't used? - my ( $self, $file, $associated_pod ) = @_; + my ( $self, $associated_pod ) = @_; return unless ( my $files = $associated_pod->{ $self->name } ); ( my $mod_path = $self->name ) =~ s{::}{/}g; - my ($pod) = ( + my ($file) = ( #<<< # TODO: adjust score if all files are in root? map { $_->[1] } @@ -173,12 +147,12 @@ sub set_associated_pod { $_->path =~ /^README\.pod$/i ? -10 : # If the name of the package matches the name of the file, - $_->path =~ m!(^lib/)?\b${mod_path}.(pod|pm)$! ? + $_->path =~ m!(^lib/)?\b${mod_path}.((?i)pod|pm)$! ? # Score pod over pm, and boost (most points for 'lib' dir). - ($1 ? 50 : 25) + $_pod_score{$2} : + ($1 ? 50 : 25) + $_pod_score{lc($2)} : # Sort files by extension: Foo.pod > Foo.pm > foo.pl. - $_->name =~ /\.(pod|pm|pl)/i ? $_pod_score{$1} : + $_->name =~ /\.(pod|pm|pl)/i ? $_pod_score{lc($1)} : # Otherwise score unknown (near the bottom). -1 @@ -188,8 +162,7 @@ sub set_associated_pod { @$files #>>> ); - $self->associated_pod($pod); - return $pod; + $self->_set_associated_pod( $file->full_path ); } __PACKAGE__->meta->make_immutable; diff --git a/lib/MetaCPAN/Document/Package.pm b/lib/MetaCPAN/Document/Package.pm new file mode 100644 index 000000000..e5ee7bf9f --- /dev/null +++ b/lib/MetaCPAN/Document/Package.pm @@ -0,0 +1,25 @@ +package MetaCPAN::Document::Package; + +use MetaCPAN::Moose; + +use ElasticSearchX::Model::Document; +use MetaCPAN::Types::TypeTiny qw( Str ); + +has module_name => ( + is => 'ro', + isa => Str, + required => 1, +); + +has version => ( + is => 'ro', + isa => Str, +); + +has file => ( + is => 'ro', + isa => Str, +); + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Document/Permission.pm b/lib/MetaCPAN/Document/Permission.pm new file mode 100644 index 000000000..b72524dfd --- /dev/null +++ b/lib/MetaCPAN/Document/Permission.pm @@ -0,0 +1,25 @@ +package MetaCPAN::Document::Permission; + +use MetaCPAN::Moose; + +use ElasticSearchX::Model::Document; +use MetaCPAN::Types::TypeTiny qw( ArrayRef Str ); + +has module_name => ( + is => 'ro', + isa => Str, + required => 1, +); + +has owner => ( + is => 'ro', + isa => Str, +); + +has co_maintainers => ( + is => 'ro', + isa => ArrayRef, +); + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Document/Rating.pm b/lib/MetaCPAN/Document/Rating.pm deleted file mode 100644 index f30ac22e1..000000000 --- a/lib/MetaCPAN/Document/Rating.pm +++ /dev/null @@ -1,55 +0,0 @@ -package MetaCPAN::Document::Rating; - -use strict; -use warnings; - -use Moose; -use ElasticSearchX::Model::Document::Types qw(:all); -use ElasticSearchX::Model::Document; - -use MooseX::Types::Moose qw(Int Num Bool Str ArrayRef HashRef Undef); -use MooseX::Types::Structured qw(Dict Tuple Optional); - -has details => ( - is => 'ro', - isa => Dict [ documentation => Str ], -); - -has rating => ( - required => 1, - is => 'ro', - isa => Num, - builder => '_build_rating', -); - -has [qw(distribution release author user)] => ( - required => 1, - is => 'ro', - isa => Str, -); - -has date => ( - required => 1, - is => 'ro', - isa => 'DateTime', - default => sub { DateTime->now }, -); - -has helpful => ( - required => 1, - is => 'ro', - isa => ArrayRef [ Dict [ user => Str, value => Bool ] ], - default => sub { [] }, -); - -sub _build_rating { - my $self = shift; - die "Provide details to calculate a rating"; - my %details = %{ $self->details }; - my $rating = 0; - $rating += $_ for ( values %details ); - return $rating / scalar keys %details; -} - -__PACKAGE__->meta->make_immutable; -1; diff --git a/lib/MetaCPAN/Document/Release.pm b/lib/MetaCPAN/Document/Release.pm index 86495fbf0..ad92baf61 100644 --- a/lib/MetaCPAN/Document/Release.pm +++ b/lib/MetaCPAN/Document/Release.pm @@ -1,14 +1,19 @@ package MetaCPAN::Document::Release; -use strict; -use warnings; - use Moose; -use ElasticSearchX::Model::Document; -use MetaCPAN::Document::Author; -use MetaCPAN::Types qw(:all); -use MetaCPAN::Util; +use ElasticSearchX::Model::Document; +use MetaCPAN::Types qw( Dependency ESBool ); +use MetaCPAN::Types::TypeTiny qw( + ArrayRef + HashRefCPANMeta + Num + Resources + Stat + Str + Tests +); +use MetaCPAN::Util qw( numify_version true false ); =head1 PROPERTIES @@ -90,8 +95,8 @@ See L. =head2 stat -L info of the archive file. Contains C, C, -C, C and C. +L info of the archive file. Contains C, +C and C. =head2 first @@ -103,9 +108,18 @@ This is an ArrayRef of modules that are included in this release. =cut +=head2 deprecated + +This is a boolean indicating whether the release is marked as deprecated +(the main module's ABSTRACT contains "DEPRECATED" or "DEPRECIATED", +or the x_deprecated flag is set in metadata) + +=cut + has provides => ( - isa => 'ArrayRef[Str]', - is => 'rw', + is => 'ro', + isa => ArrayRef [Str], + writer => '_set_provides', ); has id => ( @@ -113,11 +127,17 @@ has id => ( id => [qw(author name)], ); -has [qw(license version author archive)] => ( +has [qw(version author archive)] => ( is => 'ro', required => 1, ); +has license => ( + is => 'ro', + isa => ArrayRef, + required => 1, +); + has date => ( is => 'ro', required => 1, @@ -125,9 +145,14 @@ has date => ( ); has download_url => ( - is => 'ro', - required => 1, - lazy_build => 1, + is => 'ro', + lazy => 1, + builder => '_build_download_url', +); + +has [qw(checksum_md5 checksum_sha256)] => ( + is => 'ro', + isa => Str, ); has [qw(distribution name)] => ( @@ -137,10 +162,13 @@ has [qw(distribution name)] => ( ); has version_numified => ( - is => 'ro', - required => 1, - isa => 'Num', - lazy_build => 1, + required => 1, + is => 'ro', + isa => Num, + lazy => 1, + default => sub { + return numify_version( shift->version ); + }, ); has resources => ( @@ -153,14 +181,14 @@ has resources => ( ); has abstract => ( - is => 'rw', + is => 'ro', index => 'analyzed', predicate => 'has_abstract', + writer => '_set_abstract', ); has dependency => ( - required => 0, - is => 'rw', + is => 'ro', isa => Dependency, coerce => 1, type => 'nested', @@ -171,9 +199,10 @@ has dependency => ( # The indexer scripts will upgrade it to 'latest' if it's the version in # 02packages or downgrade it to 'backpan' if it gets deleted. has status => ( - is => 'rw', + is => 'ro', required => 1, default => 'cpan', + writer => '_set_status', ); has maturity => ( @@ -189,144 +218,84 @@ has stat => ( ); has tests => ( - is => 'ro', - isa => Tests, - dynamic => 1, + is => 'ro', + isa => Tests, + dynamic => 1, + documentation => 'HashRef: Summary of CPANTesters data', ); has authorized => ( - is => 'rw', + is => 'ro', required => 1, - isa => 'Bool', - default => 1, + isa => ESBool, + default => sub {true}, + writer => '_set_authorized', ); has first => ( - is => 'rw', + is => 'ro', required => 1, - isa => 'Bool', - lazy => 1, - builder => '_build_first', + isa => ESBool, + default => sub {false}, + writer => '_set_first', ); has metadata => ( coerce => 1, is => 'ro', - isa => 'HashRef', + isa => HashRefCPANMeta, dynamic => 1, source_only => 1, ); has main_module => ( - is => 'rw', - isa => 'Str', - required => 0, + is => 'ro', + isa => Str, + writer => '_set_main_module', ); has changes_file => ( - is => 'rw', - isa => 'Str', - required => 0, + is => 'ro', + isa => Str, + writer => '_set_changes_file', ); -sub _build_version_numified { - return MetaCPAN::Util::numify_version( shift->version ); -} +has deprecated => ( + is => 'ro', + isa => ESBool, + default => sub {false}, + writer => '_set_deprecated', +); sub _build_download_url { my $self = shift; return 'https://cpan.metacpan.org/authors/' - . MetaCPAN::Document::Author::_build_dir( $self->author ) . '/' + . MetaCPAN::Util::author_dir( $self->author ) . '/' . $self->archive; } -sub _build_first { - my $self = shift; - $self->index->type('release')->filter( - { - and => [ - { term => { 'release.distribution' => $self->distribution } }, +sub set_first { + my $self = shift; + my $is_first = $self->index->model->doc('release')->query( { + bool => { + must => [ + { term => { distribution => $self->distribution } }, { range => { - 'release.version_numified' => - { 'lt' => $self->version_numified } + version_numified => { lt => $self->version_numified } } }, + ], + }, - # REINDEX: after a full reindex, the above line is to replaced with: - # { term => { 'release.first' => \1 } }, - # currently, the "first" property is not computed on all releases - # since this feature has not been around when last reindexed - ] - } - )->count - ? 0 - : 1; -} - -__PACKAGE__->meta->make_immutable; - -package MetaCPAN::Document::Release::Set; - -use strict; -use warnings; - -use Moose; -extends 'ElasticSearchX::Model::Document::Set'; - -sub find_depending_on { - my ( $self, $modules ) = @_; - return $self->filter( - { - or => [ - map { { term => { 'release.dependency.module' => $_ } } } - @$modules - ] - } - ); -} - -sub find { - my ( $self, $name ) = @_; - return $self->filter( - { - and => [ - { term => { 'release.distribution' => $name } }, - { term => { status => 'latest' } } - ] - } - )->sort( [ { date => 'desc' } ] )->first; -} - -sub predecessor { - my ( $self, $name ) = @_; - return $self->filter( - { - and => [ - { term => { 'release.distribution' => $name } }, - { not => { filter => { term => { status => 'latest' } } } }, - ] - } - )->sort( [ { date => 'desc' } ] )->first; -} + # REINDEX: after a full reindex, the above line is to replaced with: + # { term => { first => 1 } }, + # currently, the "first" property is not computed on all releases + # since this feature has not been around when last reindexed + } )->count ? false : true; -sub find_github_based { - my $or = [ - -# { prefix => { "resources.homepage" => 'http://github.com/' } }, -# { prefix => { "resources.homepage" => 'https://github.com/' } }, -# { prefix => { "resources.repository.web" => 'http://github.com/' } }, -# { prefix => { "resources.repository.web" => 'https://github.com/' } }, -# { prefix => { "resources.repository.url" => 'http://github.com/' } }, -# { prefix => { "resources.repository.url" => 'https://github.com/' } }, -# { prefix => { "resources.repository.url" => 'git://github.com/' } }, - { prefix => { "resources.bugtracker.web" => 'http://github.com/' } }, - { prefix => { "resources.bugtracker.web" => 'https://github.com/' } }, - ]; - shift #->fields([qw(resources)]) - ->filter( - { and => [ { term => { status => 'latest' } }, { or => $or } ] } ); + $self->_set_first($is_first); } __PACKAGE__->meta->make_immutable; diff --git a/lib/MetaCPAN/ESConfig.pm b/lib/MetaCPAN/ESConfig.pm new file mode 100644 index 000000000..e84f1d928 --- /dev/null +++ b/lib/MetaCPAN/ESConfig.pm @@ -0,0 +1,261 @@ +use v5.20; +use warnings; +use experimental qw( signatures postderef ); + +package MetaCPAN::ESConfig; + +use Carp qw( croak ); +use Const::Fast qw( const ); +use Cpanel::JSON::XS (); +use Exporter qw( import ); +use Hash::Merge::Simple qw( merge ); +use MetaCPAN::Server::Config (); +use MetaCPAN::Types::TypeTiny qw( Defined HashRef ); +use MetaCPAN::Util qw( root_dir true false ); +use Module::Runtime qw( $module_name_rx require_module ); + +const my %config => merge( + { + documents => { + author => { + index => 'author', + type => 'author', + mapping => 'es/author/mapping.json', + settings => 'es/author/settings.json', + model => 'MetaCPAN::Document::Author', + }, + cve => { + index => 'cve', + type => 'cve', + mapping => 'es/cve/mapping.json', + settings => 'es/cve/settings.json', + model => 'MetaCPAN::Document::CVE', + }, + contributor => { + index => 'contributor', + type => 'contributor', + mapping => 'es/contributor/mapping.json', + settings => 'es/contributor/settings.json', + model => 'MetaCPAN::Document::Contributor', + }, + cover => { + index => 'cover', + type => 'cover', + mapping => 'es/cover/mapping.json', + settings => 'es/cover/settings.json', + model => 'MetaCPAN::Document::Cover', + }, + distribution => { + index => 'distribution', + type => 'distribution', + mapping => 'es/distribution/mapping.json', + settings => 'es/distribution/settings.json', + model => 'MetaCPAN::Document::Distribution', + }, + favorite => { + index => 'favorite', + type => 'favorite', + mapping => 'es/favorite/mapping.json', + settings => 'es/favorite/settings.json', + model => 'MetaCPAN::Document::Favorite', + }, + file => { + index => 'file', + type => 'file', + mapping => 'es/file/mapping.json', + settings => 'es/file/settings.json', + model => 'MetaCPAN::Document::File', + }, + mirror => { + index => 'mirror', + type => 'mirror', + mapping => 'es/mirror/mapping.json', + settings => 'es/mirror/settings.json', + model => 'MetaCPAN::Document::Mirror', + }, + package => { + index => 'package', + type => 'package', + mapping => 'es/package/mapping.json', + settings => 'es/package/settings.json', + model => 'MetaCPAN::Document::Package', + }, + permission => { + index => 'permission', + type => 'permission', + mapping => 'es/permission/mapping.json', + settings => 'es/permission/settings.json', + model => 'MetaCPAN::Document::Permission', + }, + release => { + index => 'release', + type => 'release', + mapping => 'es/release/mapping.json', + settings => 'es/release/settings.json', + model => 'MetaCPAN::Document::Release', + }, + + account => { + index => 'account', + type => 'account', + mapping => 'es/account/mapping.json', + settings => 'es/account/settings.json', + model => 'MetaCPAN::Model::User::Account', + }, + session => { + index => 'session', + type => 'session', + mapping => 'es/session/mapping.json', + settings => 'es/session/settings.json', + model => 'MetaCPAN::Model::User::Session', + }, + }, + }, + MetaCPAN::Server::Config::config()->{elasticsearch} || {}, +)->%*; + +{ + use Moo; +} + +has all_indexes => ( + is => 'lazy', + default => sub ($self) { + my %seen; + [ + sort + grep !$seen{$_}++, + map $_->{index}, + values $self->documents->%* + ]; + }, +); + +my $DefinedHash = ( HashRef [Defined] )->plus_coercions( + HashRef, + => sub ($hash) { + return { + map { + my $value = $hash->{$_}; + defined $value ? ( $_ => $value ) : (); + } keys %$hash + }; + }, +); + +has documents => ( + is => 'ro', + isa => HashRef [$DefinedHash], + coerce => 1, + required => 1, +); + +sub _load_es_data ( $location, $def_sub ) { + my $data; + + if ( ref $location ) { + $data = $location; + } + elsif ( $location + =~ /\A($module_name_rx)(?:::([0-9a-zA-Z_]+)\(\)|->($module_name_rx))?\z/ + ) + { + my ( $module, $sub, $method ) = ( $1, $2, $3 ); + require_module $module; + if ($method) { + $data = $module->$method; + } + else { + $sub ||= $def_sub; + no strict 'refs'; + my $code = \&{"${module}::${sub}"}; + die "can't find $location" + if !defined &$code; + $data = $code->(); + } + } + else { + my $abs_path = File::Spec->rel2abs( $location, root_dir() ); + open my $fh, '<', $abs_path + or die "can't open mapping file $abs_path: $!"; + $data = do { local $/; <$fh> }; + } + + return $data + if ref $data; + + return Cpanel::JSON::XS::decode_json($data); +} + +sub _walk : prototype(&$); + +sub _walk : prototype(&$) { + my ( $cb, $data ) = @_; + if ( ref $data eq 'HASH' ) { + $cb->($data); + _walk( \&$cb, $data->{$_} ) for keys %$data; + } + elsif ( ref $data eq 'ARRAY' ) { + $cb->($data); + _walk( \&$cb, $_ ) for @$data; + } +} + +sub mapping ( $self, $doc, $version ) { + my $doc_data = $self->documents->{$doc} + or croak "unknown document $doc"; + my $data = _load_es_data( $doc_data->{mapping}, 'mapping' ); + if ( $version && $version eq '2_0' ) { + _walk( + sub { + my ($d) = @_; + if ( my $type = $d->{type} ) { + if ( $type eq 'keyword' ) { + $d->{type} = 'string'; + $d->{index} = 'not_analyzed'; + $d->{ignore_above} = 2048; + } + elsif ( $type eq 'text' ) { + $d->{type} = 'string'; + if ( exists $d->{fielddata} && !$d->{fielddata} ) { + $d->{fielddata} = { format => false }; + } + } + } + + }, + $data + ); + } + return $data; +} + +sub index_settings ( $self, $doc, $version = undef ) { + my $documents = $self->documents; + my $doc_data = exists $documents->{$doc} && $documents->{$doc} + or return {}; + my $settings = exists $doc_data->{settings} && $doc_data->{settings} + or return {}; + my $data = _load_es_data( $settings, 'settings' ); + return $data; +} + +sub doc_path ( $self, $doc ) { + my $doc_data = $self->documents->{$doc} + or croak "unknown document $doc"; + return ( + ( $doc_data->{index} ? ( index => $doc_data->{index} ) : () ), + ( $doc_data->{type} ? ( type => $doc_data->{type} ) : () ), + ); +} + +our @EXPORT_OK = qw( + es_config + es_doc_path +); + +my $single = __PACKAGE__->new(%config); +sub es_config : prototype() {$single} +sub es_doc_path ($doc) { $single->doc_path($doc) } + +1; diff --git a/lib/MetaCPAN/Model.pm b/lib/MetaCPAN/Model.pm index 067619072..e98d5ac6e 100644 --- a/lib/MetaCPAN/Model.pm +++ b/lib/MetaCPAN/Model.pm @@ -1,40 +1,36 @@ package MetaCPAN::Model; -use strict; -use warnings; - # load order important use Moose; -use ElasticSearchX::Model; -analyzer lowercase => ( - tokenizer => 'keyword', - filter => 'lowercase', -); - -analyzer fulltext => ( - type => 'snowball', - language => 'English', -); - -tokenizer camelcase => ( - type => 'pattern', - pattern => - "([^\\p{L}\\d]+)|(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)|(?<=[\\p{L}&&[^\\p{Lu}]])(?=\\p{Lu})|(?<=\\p{Lu})(?=\\p{Lu}[\\p{L}&&[^\\p{Lu}]])" -); -analyzer camelcase => ( - type => 'custom', - tokenizer => 'camelcase', - filter => [ 'lowercase', 'unique' ] -); - -index cpan => ( - namespace => 'MetaCPAN::Document', - alias_for => 'cpan_v1', - shards => 5 -); - -index user => ( namespace => 'MetaCPAN::Model::User' ); +use ElasticSearchX::Model; +use MetaCPAN::ESConfig qw(es_config); +use Module::Runtime qw( require_module use_package_optimistically ); + +my %indexes; +my $docs = es_config->documents; +for my $name ( sort keys %$docs ) { + my $doc = $docs->{$name}; + my $model = $doc->{model} + or next; + require_module($model); + use_package_optimistically( $model . '::Set' ); + my $index = $doc->{index} + or die "no index for $name documents!"; + + $indexes{$index}{types}{$name} = $model->meta; +} + +for my $index ( sort keys %indexes ) { + index $index => %{ $indexes{$index} }; +} + +sub doc { + my ( $self, $doc ) = @_; + my $doc_config = es_config->documents->{$doc}; + return $self->index( $doc_config->{index} ) + ->type( $doc_config->{type} // $doc_config->{index} ); +} __PACKAGE__->meta->make_immutable; 1; diff --git a/lib/MetaCPAN/Model/Archive.pm b/lib/MetaCPAN/Model/Archive.pm index 4205665bd..3ad4eebae 100644 --- a/lib/MetaCPAN/Model/Archive.pm +++ b/lib/MetaCPAN/Model/Archive.pm @@ -3,12 +3,12 @@ package MetaCPAN::Model::Archive; use v5.10; use Moose; use MooseX::StrictConstructor; -use MetaCPAN::Types qw(AbsFile AbsDir Bool); +use MetaCPAN::Types::TypeTiny qw( AbsPath ArrayRef Bool InstanceOf Str ); -use Archive::Any; -use Carp; -use File::Temp (); -use Path::Class (); +use Archive::Any (); +use Carp qw( croak ); +use Digest::file qw( digest_file_hex ); +use Path::Tiny qw( path ); =head1 NAME @@ -38,27 +38,25 @@ The Archive will clean up its extraction directory upon destruction. I -The file to be extracted. It will be returned as a Path::Class +The file to be extracted. It will be returned as a Path::Tiny object. =cut has file => ( is => 'ro', - isa => AbsFile, + isa => AbsPath, coerce => 1, required => 1, ); has _extractor => ( is => 'ro', - isa => 'Archive::Any', - handles => [ - qw( - is_impolite - is_naughty - ) - ], + isa => InstanceOf ['Archive::Any'], + handles => [ qw( + is_impolite + is_naughty + ) ], init_arg => undef, lazy => 1, default => sub { @@ -68,35 +66,61 @@ has _extractor => ( }, ); +# MD5 digest for the archive file +has file_digest_md5 => ( + is => 'ro', + isa => Str, + lazy => 1, + default => sub { + my $self = shift; + digest_file_hex( $self->file, 'MD5' ); + }, +); + +# SHA256 digest for the archive file +has file_digest_sha256 => ( + is => 'ro', + isa => Str, + lazy => 1, + default => sub { + my $self = shift; + digest_file_hex( $self->file, 'SHA-256' ); + }, +); + # Holding the File::Temp::Dir object here is necessary to keep it -# alive until the object is destroyed. Path::Class::Dir will not hold -# onto the ojbect. +# alive until the object is destroyed. has _tempdir => ( is => 'ro', - isa => 'File::Temp::Dir', + isa => AbsPath, init_arg => undef, lazy => 1, default => sub { - return File::Temp->newdir; + + my $scratch_disk = '/mnt/scratch_disk'; + return -d $scratch_disk + ? Path::Tiny->tempdir('/mnt/scratch_disk/tempXXXXX') + : Path::Tiny->tempdir; }, ); has extract_dir => ( is => 'ro', - isa => AbsDir, + isa => AbsPath, lazy => 1, coerce => 1, default => sub { my $self = shift; - return Path::Class::Dir->new( $self->_tempdir ); + return path( $self->_tempdir ); }, ); has _has_extracted => ( - is => 'rw', + is => 'ro', isa => Bool, init_arg => undef, default => 0, + writer => '_set_has_extracted', ); =head1 METHODS @@ -112,7 +136,7 @@ A list of the files in the archive as an array ref. # A cheap way to cache the result. has files => ( is => 'ro', - isa => 'ArrayRef', + isa => ArrayRef, init_arg => undef, lazy => 1, default => sub { @@ -126,7 +150,7 @@ has files => ( my $extract_dir = $archive->extract; Extract the archive into a temp directory. The directory will be a -L. +L object. Only the first call to extract will perform the extraction. After that it will just return the extraction directory. If you want to @@ -142,7 +166,7 @@ sub extract { return $self->extract_dir if $self->_has_extracted; $self->_extractor->extract( $self->extract_dir ); - $self->_has_extracted(1); + $self->_set_has_extracted(1); return $self->extract_dir; } diff --git a/lib/MetaCPAN/Model/ESWrapper.pm b/lib/MetaCPAN/Model/ESWrapper.pm new file mode 100644 index 000000000..cd990c897 --- /dev/null +++ b/lib/MetaCPAN/Model/ESWrapper.pm @@ -0,0 +1,61 @@ +package MetaCPAN::Model::ESWrapper; +use strict; +use warnings; + +use MetaCPAN::Types::TypeTiny qw( ES ); + +sub new { + my ( $class, $es ) = @_; + if ( $es->api_version le '6_0' ) { + return $es; + } + return bless { es => ES->assert_coerce($es) }, $class; +} + +sub DESTROY { } + +sub AUTOLOAD { + my $sub = our $AUTOLOAD =~ s/.*:://r; + my $self = shift; + $self->{es}->$sub(@_); +} + +sub _args { + my $self = shift; + if ( @_ == 1 ) { + return ( $self, %{ $_[0] } ); + } + return ( $self, @_ ); +} + +sub count { + my ( $self, %args ) = &_args; + delete $args{type}; + $self->{es}->count(%args); +} + +sub get { + my ( $self, %args ) = &_args; + delete $args{type}; + $self->{es}->get(%args); +} + +sub delete { + my ( $self, %args ) = &_args; + delete $args{type}; + $self->{es}->delete(%args); +} + +sub search { + my ( $self, %args ) = &_args; + delete $args{type}; + $self->{es}->search(%args); +} + +sub scroll_helper { + my ( $self, %args ) = &_args; + delete $args{type}; + $self->{es}->scroll_helper(%args); +} + +1; diff --git a/lib/MetaCPAN/Model/Email/PAUSE.pm b/lib/MetaCPAN/Model/Email/PAUSE.pm new file mode 100644 index 000000000..b022dcf0d --- /dev/null +++ b/lib/MetaCPAN/Model/Email/PAUSE.pm @@ -0,0 +1,90 @@ +package MetaCPAN::Model::Email::PAUSE; + +use MetaCPAN::Moose; + +use Email::Sender::Simple qw( sendmail ); +use Email::Sender::Transport::SMTP (); +use Email::Simple (); +use Encode (); +use MetaCPAN::Types::TypeTiny qw( Object Uri ); +use Try::Tiny qw( catch try ); + +with('MetaCPAN::Role::HasConfig'); + +has _author => ( + is => 'ro', + isa => Object, + init_arg => 'author', + required => 1, +); + +has _url => ( + is => 'ro', + isa => Uri, + init_arg => 'url', + required => 1, +); + +sub send { + my $self = shift; + + my $email = Email::Simple->create( + header => [ + 'Content-Type' => 'text/plain; charset=utf-8', + To => $self->_author->{email}->[0], + From => 'notifications@metacpan.org', + Subject => 'Connect MetaCPAN with your PAUSE account', + 'MIME-Version' => '1.0', + ], + body => $self->_email_body, + ); + + my $config = $self->config->{smtp}; + my $transport = Email::Sender::Transport::SMTP->new( { + debug => 1, + host => $config->{host}, + port => $config->{port}, + sasl_username => $config->{username}, + sasl_password => $config->{password}, + ssl => 1, + } ); + + my $success = 0; + try { + $success = sendmail( $email, { transport => $transport } ); + } + catch { + warn 'Could not send message: ' . $_; + }; + + return $success; +} + +sub _email_body { + my $self = shift; + my $name = $self->_author->name; + my $uri = $self->_url; + + my $body = < ( is => 'ro', - isa => 'MetaCPAN::Model::Archive', + isa => InstanceOf ['MetaCPAN::Model::Archive'], lazy => 1, builder => '_build_archive', ); has dependencies => ( - is => 'ro', - isa => ArrayRef, - lazy_build => 1, + is => 'ro', + isa => ArrayRef, + lazy => 1, + builder => '_build_dependencies', ); has distinfo => ( is => 'ro', - isa => 'CPAN::DistnameInfo', + isa => InstanceOf ['CPAN::DistnameInfo'], handles => { maturity => 'maturity', author => 'cpanid', @@ -41,6 +44,7 @@ has distinfo => ( distribution => 'dist', filename => 'filename', }, + lazy => 1, default => sub { my $self = shift; return CPAN::DistnameInfo->new( $self->file ); @@ -48,28 +52,30 @@ has distinfo => ( ); has document => ( - is => 'ro', - isa => 'MetaCPAN::Document::Release', - lazy_build => 1, + is => 'ro', + isa => InstanceOf ['MetaCPAN::Document::Release'], + lazy => 1, + builder => '_build_document', ); has file => ( - is => 'rw', - isa => AbsFile, + is => 'ro', + isa => AbsPath, required => 1, coerce => 1, ); has files => ( - is => 'ro', - isa => ArrayRef, - init_arg => undef, - lazy_build => 1, + is => 'ro', + isa => ArrayRef, + init_arg => undef, + lazy => 1, + builder => '_build_files', ); has date => ( - is => 'rw', - isa => 'DateTime', + is => 'ro', + isa => InstanceOf ['DateTime'], lazy => 1, default => sub { my $self = shift; @@ -77,11 +83,11 @@ has date => ( }, ); -has index => ( is => 'rw', ); +has model => ( is => 'ro' ); has metadata => ( - is => 'rw', - isa => 'CPAN::Meta', + is => 'ro', + isa => InstanceOf ['CPAN::Meta'], lazy => 1, builder => '_build_metadata', ); @@ -102,21 +108,36 @@ has modules => ( ); has version => ( - is => 'rw', + is => 'ro', isa => Str, lazy => 1, default => sub { - my $self = shift; - return MetaCPAN::Util::fix_version( $self->distinfo->version ); + return fix_version( shift->distinfo->version ); }, ); has status => ( - is => 'rw', + is => 'ro', isa => Str, ); -has bulk => ( is => 'rw', ); +has es => ( is => 'ro' ); +has bulk => ( is => 'ro' ); + +=head2 run + +Try to fix some ordering issues, which are causing deep recursion. There's +probably a much cleaner way to do this. + +=cut + +sub run { + my $self = shift; + $self->document; + $self->document->_set_changes_file( + $self->get_changes_file( $self->files ) ); + $self->set_main_module( $self->modules, $self->document ); +} sub _build_archive { my $self = shift; @@ -165,19 +186,21 @@ sub _build_dependencies { sub _build_document { my $self = shift; - my $st = $self->file->stat; - my $stat = { map { $_ => $st->$_ } qw(mode uid gid size mtime) }; + my $st = $self->file->stat; + my $stat = { map { $_ => $st->$_ } qw(mode size mtime) }; my $meta = $self->metadata; my $dependencies = $self->dependencies; my $document = DlogS_trace {"adding release $_"} +{ - abstract => MetaCPAN::Util::strip_pod( $meta->abstract ), - archive => $self->filename, - author => $self->author, - date => $self->date . q{}, - dependency => $dependencies, - distribution => $self->distribution, + abstract => MetaCPAN::Util::strip_pod( $meta->abstract ), + archive => $self->filename, + author => $self->author, + checksum_md5 => $self->archive->file_digest_md5, + checksum_sha256 => $self->archive->file_digest_sha256, + date => $self->date . q{}, + dependency => $dependencies, + distribution => $self->distribution, # CPAN::Meta->license *must* be called in list context # (and *may* return multiple strings). @@ -198,22 +221,24 @@ sub _build_document { || $document->{abstract} eq 'null' ); $document - = $self->index->type('release')->put( $document, { refresh => 1 } ); - - # create will die if the document already exists - eval { - $self->index->type('distribution') - ->put( { name => $self->distribution }, { create => 1 } ); - }; - - $self->_set_main_module( $self->modules, $document ); - - $document->changes_file( $self->get_changes_file( $self->files ) ); + = $self->model->doc('release')->put( $document, { refresh => true } ); + + # create distribution if doesn't exist + $self->es->update( + es_doc_path('distribution'), + id => $self->distribution, + body => { + doc => { + name => $self->distribution, + }, + doc_as_upsert => true, + }, + ); return $document; } -sub _set_main_module { +sub set_main_module { my $self = shift; my ( $mod, $release ) = @_; @@ -228,7 +253,7 @@ sub _set_main_module { if ( scalar @modules == 1 ) { # there is only one module and it will become the main_module - $release->main_module( $modules[0]->module->[0]->name ); + $release->_set_main_module( $modules[0]->module->[0]->name ); return; } @@ -236,7 +261,7 @@ sub _set_main_module { # the module has the exact name as the ditribution if ( $file->module->[0]->name eq $dist2module ) { - $release->main_module( $file->module->[0]->name ); + $release->_set_main_module( $file->module->[0]->name ); return; } } @@ -248,22 +273,45 @@ sub _set_main_module { $a->level <=> $b->level || length $a->module->[0]->name <=> length $b->module->[0]->name } @modules; - $release->main_module( $sorted_modules[0]->module->[0]->name ); + $release->_set_main_module( $sorted_modules[0]->module->[0]->name ); } -sub get_changes_file { - my $self = shift; - my @files = @{ $_[0] }; - my @changes_files = qw( - Changelog - ChangeLog - CHANGELOG - Changes - CHANGES - NEWS +my @changes_files = qw( + CHANGELOG + ChangeLog + Changelog + CHANGES + Changes + NEWS +); +my @exclude_dirs = qw( + corpus + fatlib + inc + local + perl5 + share + t + xt +); + +# this should match the same set of files as MetaCPAN::Query::File->interesting_files +my ($changes_match) = map qr/^(?:$_)$/, join '|', + ( map quotemeta, @changes_files, map "$_.md", @changes_files ), + ( + "(?:(?!" + . join( '|', map "$_/", @exclude_dirs ) + . ").*/)?(?:" + . join( + '|', map quotemeta, map +( "$_.pm", "$_.pod" ), @changes_files + ) + . ')' ); +sub get_changes_file { + my $self = shift; + my @files = @{ $_[0] }; if ( $files[0]->distribution eq 'perl' ) { foreach my $file (@files) { if ( $file->name eq 'perldelta.pod' ) { @@ -271,8 +319,12 @@ sub get_changes_file { } } } + + # prioritize files in the top level but otherwise alphabetical + @files = sort { $a->level <=> $b->level || $a->path cmp $b->path } @files; + foreach my $file (@files) { - return $file->path if grep { $_ eq $file->path } @changes_files; + return $file->path if $file->path =~ $changes_match; } } @@ -281,20 +333,17 @@ sub _build_files { my @files; log_debug { 'Indexing ', scalar @{ $self->archive->files }, ' files' }; - my $file_set = $self->index->type('file'); + my $file_set = $self->model->doc('file'); my $extract_dir = $self->extract; File::Find::find( sub { - my $child - = -d $File::Find::name - ? Path::Class::Dir->new($File::Find::name) - : Path::Class::File->new($File::Find::name); + my $child = path($File::Find::name); return if $self->_is_broken_file($File::Find::name); my $relative = $child->relative($extract_dir); my $stat = do { my $s = $child->stat; - +{ map { $_ => $s->$_ } qw(mode uid gid size mtime) }; + +{ map { $_ => $s->$_ } qw(mode size mtime) }; }; return if ( $relative eq q{.} ); ( my $fpath = "$relative" ) =~ s/^.*?\///; @@ -306,22 +355,26 @@ sub _build_files { my $file = $file_set->new_document( Dlog_trace {"adding file $_"} +{ - author => $self->author, - binary => -B $child, - content_cb => sub { \( scalar $child->slurp ) }, + author => $self->author, + binary => -B $child ? true : false, + content => $child->is_dir ? \"" + : \( scalar $child->slurp ), date => $self->date, - directory => $child->is_dir, + directory => $child->is_dir ? true : false, distribution => $self->distribution, - - local_path => $child, - maturity => $self->maturity, - metadata => $self->metadata, - name => $filename, - path => $fpath, - release => $self->name, - stat => $stat, - status => $self->status, - version => $self->version, + indexed => $self->metadata->should_index_file($fpath) + ? true + : false, + local_path => $child, + maturity => $self->maturity, + metadata => $self->metadata, + name => $filename, + path => $fpath, + release => $self->name, + download_url => $self->document->download_url, + stat => $stat, + status => $self->status, + version => $self->version, } ); @@ -356,14 +409,12 @@ sub _build_metadata { my $extract_dir = $self->extract; - return $self->_load_meta_file || CPAN::Meta->new( - { - license => 'unknown', - name => $self->distribution, - no_index => { directory => [@always_no_index_dirs] }, - version => $self->version || 0, - } - ); + return $self->_load_meta_file || CPAN::Meta->new( { + license => 'unknown', + name => $self->distribution, + no_index => { directory => [@always_no_index_dirs] }, + version => $self->version || 0, + } ); } sub _load_meta_file { @@ -383,29 +434,24 @@ sub _load_meta_file { } return unless (@files); - # YAML YAML::Tiny YAML::XS don't offer better results - my @backends = qw(CPAN::Meta::YAML YAML::Syck); - my $error; - while ( my $mod = shift @backends ) { - $ENV{PERL_YAML_BACKEND} = $mod; - my $last; - for my $file (@files) { - try { - $last = CPAN::Meta->load_file($file); - } - catch { $error = $_ }; - if ($last) { - last; - } + my $last; + for my $file (@files) { + try { + $last = CPAN::Meta->load_file($file); } + catch { + log_warn {"META file ($file) could not be loaded: $_"}; + }; if ($last) { - push( @{ $last->{no_index}->{directory} }, - @always_no_index_dirs ); - return $last; + last; } } + if ($last) { + push( @{ $last->{no_index}->{directory} }, @always_no_index_dirs ); + return $last; + } - log_warn {"META file could not be loaded: $error"} unless @backends; + log_warn {'No META files could be loaded'}; } sub extract { @@ -435,22 +481,21 @@ sub _modules_from_meta { my $provides = $self->metadata->provides; my $files = $self->files; + my %files = map +( $_->path => $_ ), @$files; foreach my $module ( sort keys %$provides ) { my $data = $provides->{$module}; - my $path = $data->{file}; - - # Obey no_index and take the shortest path if multiple files match. - my ($file) = sort { length( $a->path ) <=> length( $b->path ) } - grep { $_->indexed && $_->path =~ /\Q$path\E$/ } @$files; - - next unless $file; - $file->add_module( - { - name => $module, - version => $data->{version}, - indexed => 1, - } - ); + my $path = File::Spec->canonpath( $data->{file} ); + + my $file = $files{$path} + or next; + + next unless $file->indexed; + + $file->add_module( { + name => $module, + version => $data->{version}, + indexed => true, + } ); push( @modules, $file ); } @@ -474,14 +519,12 @@ sub _modules_from_files { next if !$info; foreach my $module_name ( keys %{$info} ) { - $file->add_module( - { - name => $module_name, - defined $info->{$module_name}->{version} - ? ( version => $info->{$module_name}->{version} ) - : (), - } - ); + $file->add_module( { + name => $module_name, + defined $info->{$module_name}->{version} + ? ( version => $info->{$module_name}->{version} ) + : (), + } ); } push @modules, $file; } @@ -491,7 +534,7 @@ sub _modules_from_files { log_error {'Call to Module::Metadata timed out '}; die; }; - alarm(5); + alarm(50); my $info; { local $SIG{__WARN__} = sub { }; @@ -501,26 +544,30 @@ sub _modules_from_files { # Ignore packages that people cannot claim. # https://github.com/andk/pause/blob/master/lib/PAUSE/pmfile.pm#L236 - for my $pkg ( grep { $_ ne 'main' && $_ ne 'DB' } - $info->packages_inside ) - { + # + # Parse::PMFile and PAUSE translate apostrophes to double colons, + # but Module::Metadata does not. + my @packages + = map s{'}{::}gr, + grep { $_ ne 'main' && $_ ne 'DB' } + $info->packages_inside; + + for my $pkg (@packages) { my $version = $info->version($pkg); - $file->add_module( - { - name => $pkg, - defined $version + $file->add_module( { + name => $pkg, + defined $version # Stringify if it's a version object, otherwise fall back to stupid stringification # Changes in Module::Metadata were causing inconsistencies in the return value, # we are just trying to survive. - ? ( - version => ref $version eq 'version' - ? $version->stringify - : ( $version . q{} ) - ) - : () - } - ); + ? ( + version => ref $version eq 'version' + ? $version->stringify + : ( $version . q{} ) + ) + : () + } ); } push( @modules, $file ); alarm(0); diff --git a/lib/MetaCPAN/Model/User/Account.pm b/lib/MetaCPAN/Model/User/Account.pm index 46e9b27db..bfb37ce31 100644 --- a/lib/MetaCPAN/Model/User/Account.pm +++ b/lib/MetaCPAN/Model/User/Account.pm @@ -6,11 +6,9 @@ use warnings; use Moose; use ElasticSearchX::Model::Document; -use MetaCPAN::Model::User::Identity; -use MetaCPAN::Types qw(:all); -use MetaCPAN::Util; -use MooseX::Types::Moose qw(Str ArrayRef); -use MooseX::Types::Structured qw(Dict); +use MetaCPAN::Types qw( Identity ); +use MetaCPAN::Types::TypeTiny qw( ArrayRef Dict Str ); +use MetaCPAN::Util qw(true false); =head1 PROPERTIES @@ -21,9 +19,8 @@ ID of user account. =cut has id => ( - id => 1, - required => 0, - is => 'rw', + id => 1, + is => 'ro', ); =head2 identity @@ -50,8 +47,9 @@ The code attribute is used temporarily when authenticating using OAuth. =cut has code => ( - is => 'rw', + is => 'ro', clearer => 'clear_token', + writer => '_set_code', ); =head2 access_token @@ -65,52 +63,10 @@ has access_token => ( is => 'ro', required => 1, isa => ArrayRef [ Dict [ token => Str, client => Str ] ], - default => sub { [] }, - dynamic => 1, - traits => ['Array'], - handles => { add_access_token => 'push' }, -); - -=head2 passed_captcha - -L when the user passed the captcha. - -=cut - -has passed_captcha => ( - is => 'rw', - isa => 'DateTime', -); - -=head2 looks_human - -Certain features are disabled unless a user C. This attribute -is true if the user is connected to a PAUSE account or he L. - -=cut - -has looks_human => ( - is => 'ro', - isa => 'Bool', - required => 1, - lazy_build => 1, - clearer => 'clear_looks_human', -); - -sub _build_looks_human { - my $self = shift; - return $self->has_identity('pause') || ( $self->passed_captcha ? 1 : 0 ); -} - -=head2 timestamp - -Sets the C<_timestamp> field. - -=cut - -has timestamp => ( - is => 'ro', - timestamp => { store => 1 }, + default => sub { [] }, + dynamic => 1, + traits => ['Array'], + handles => { add_access_token => 'push' }, ); =head1 METHODS @@ -118,19 +74,21 @@ has timestamp => ( =head2 add_identity Adds an identity to L. If the identity is a PAUSE account, -the user ID is added to the corresponding L document -and L is updated. +the user ID is added to the corresponding L document. =cut after add_identity => sub { my ( $self, $identity ) = @_; if ( $identity->{name} eq 'pause' ) { - $self->clear_looks_human; - my $profile = $self->index->model->index('cpan')->type('author') - ->get( $identity->{key} ); - $profile->user( $self->id ) if ($profile); - $profile->put; + my $profile + = $self->index->model->doc('author')->get( $identity->{key} ); + + # Not every user is an author + if ($profile) { + $profile->_set_user( $self->id ); + $profile->put; + } } }; @@ -152,60 +110,22 @@ sub get_identities { return grep { $_->name eq $identity } @{ $self->identity }; } -__PACKAGE__->meta->make_immutable; - -package MetaCPAN::Model::User::Account::Set; - -use Moose; -extends 'ElasticSearchX::Model::Document::Set'; - -=head1 SET METHODS - -=head2 find - - $type->find({ name => "github", key => 123455 }); - -Find an account based on its identity. +sub remove_identity { + my ( $self, $identity ) = @_; + my $ids = $self->identity; + my ($id) = grep { $_->{name} eq $identity } @$ids; + @$ids = grep { $_->{name} ne $identity } @$ids; -=cut + if ( $identity eq 'pause' ) { + my $profile = $self->index->model->doc('author')->get( $id->{key} ); -sub find { - my ( $self, $p ) = @_; - return $self->filter( - { - and => [ - { term => { 'account.identity.name' => $p->{name} } }, - { term => { 'account.identity.key' => $p->{key} } } - ] + if ( $profile && $profile->user eq $self->id ) { + $profile->_clear_user; + $profile->put; } - )->first; -} - -=head2 find_code - - $type->find_code($code); - -Find account by C<$code>. See L. - -=cut - -sub find_code { - my ( $self, $token ) = @_; - return $self->filter( { term => { 'account.code' => $token } } )->first; -} - -=head2 find_token - - $type->find_token($access_token); - -Find account by C<$access_token>. See L. - -=cut + } -sub find_token { - my ( $self, $token ) = @_; - return $self->filter( - { term => { 'account.access_token.token' => $token } } )->first; + return $id; } __PACKAGE__->meta->make_immutable; diff --git a/lib/MetaCPAN/Model/User/Account/Set.pm b/lib/MetaCPAN/Model/User/Account/Set.pm new file mode 100644 index 000000000..6891aacf1 --- /dev/null +++ b/lib/MetaCPAN/Model/User/Account/Set.pm @@ -0,0 +1,56 @@ +package MetaCPAN::Model::User::Account::Set; + +use Moose; +extends 'ElasticSearchX::Model::Document::Set'; + +=head1 SET METHODS + +=head2 find + + $type->find({ name => "github", key => 123455 }); + +Find an account based on its identity. + +=cut + +sub find { + my ( $self, $p ) = @_; + return $self->query( { + bool => { + must => [ + { term => { 'identity.name' => $p->{name} } }, + { term => { 'identity.key' => $p->{key} } }, + ], + } + } )->first; +} + +=head2 find_code + + $type->find_code($code); + +Find account by C<$code>. See L. + +=cut + +sub find_code { + my ( $self, $token ) = @_; + return $self->query( { term => { code => $token } } )->first; +} + +=head2 find_token + + $type->find_token($access_token); + +Find account by C<$access_token>. See L. + +=cut + +sub find_token { + my ( $self, $token ) = @_; + return $self->query( { term => { 'access_token.token' => $token } } ) + ->first; +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Model/User/Identity.pm b/lib/MetaCPAN/Model/User/Identity.pm index 71ff59415..6236b31a2 100644 --- a/lib/MetaCPAN/Model/User/Identity.pm +++ b/lib/MetaCPAN/Model/User/Identity.pm @@ -5,6 +5,7 @@ use warnings; use Moose; use ElasticSearchX::Model::Document; +use MetaCPAN::Types::TypeTiny qw( HashRef ); has name => ( is => 'ro', @@ -15,7 +16,7 @@ has key => ( is => 'ro' ); has extra => ( is => 'ro', - isa => 'HashRef', + isa => HashRef, source_only => 1, dynamic => 1, ); diff --git a/lib/MetaCPAN/Model/User/Session.pm b/lib/MetaCPAN/Model/User/Session.pm index 968d2d140..377068a55 100644 --- a/lib/MetaCPAN/Model/User/Session.pm +++ b/lib/MetaCPAN/Model/User/Session.pm @@ -6,16 +6,5 @@ use warnings; use Moose; use ElasticSearchX::Model::Document; -=head2 timestamp - -Sets the C<_timestamp> field. - -=cut - -has timestamp => ( - is => 'ro', - timestamp => { store => 1 }, -); - __PACKAGE__->meta->make_immutable; 1; diff --git a/lib/MetaCPAN/Pod/Renderer.pm b/lib/MetaCPAN/Pod/Renderer.pm index 85f4b68c5..6cb0591dd 100644 --- a/lib/MetaCPAN/Pod/Renderer.pm +++ b/lib/MetaCPAN/Pod/Renderer.pm @@ -1,24 +1,30 @@ package MetaCPAN::Pod::Renderer; -use strict; -use warnings; +use MetaCPAN::Moose; -use Moose; - -use MetaCPAN::Pod::XHTML; -use MetaCPAN::Types qw( Uri ); -use Pod::Markdown; -use Pod::POM; -use Pod::POM::View::Pod; -use Pod::Text; +use MetaCPAN::Pod::HTML; +use MetaCPAN::Types::TypeTiny qw( Uri ); +use Pod::Markdown (); +use Pod::Simple::JustPod (); +use Pod::Text (); has perldoc_url_prefix => ( - is => 'rw', + is => 'ro', isa => Uri, coerce => 1, default => 'https://metacpan.org/pod/', + writer => '_set_perldoc_url_prefix', ); +has nix_X_codes => ( is => 'ro' ); + +has no_errata_section => ( + is => 'ro', + default => 1, +); + +has link_mappings => ( is => 'ro' ); + sub markdown_renderer { my $self = shift; return Pod::Markdown->new( @@ -27,7 +33,7 @@ sub markdown_renderer { sub pod_renderer { my $self = shift; - return Pod::POM->new; + return Pod::Simple::JustPod->new; } sub text_renderer { @@ -38,13 +44,14 @@ sub text_renderer { sub html_renderer { my $self = shift; - my $parser = MetaCPAN::Pod::XHTML->new; + my $parser = MetaCPAN::Pod::HTML->new; $parser->html_footer(''); $parser->html_header(''); $parser->index(1); - $parser->no_errata_section(1); + $parser->no_errata_section( $self->no_errata_section ); $parser->perldoc_url_prefix( $self->perldoc_url_prefix ); + $parser->link_mappings( $self->link_mappings ); return $parser; } @@ -74,9 +81,7 @@ sub to_pod { my $self = shift; my $source = shift; - my $renderer = $self->pod_renderer; - my $pom = $renderer->parse_text($source); - return Pod::POM::View::Pod->print($pom); + return $self->_generic_render( $self->pod_renderer, $source ); } sub _generic_render { @@ -91,5 +96,5 @@ sub _generic_render { return $output; } -__PACKAGE__->meta->make_immutable(); +__PACKAGE__->meta->make_immutable; 1; diff --git a/lib/MetaCPAN/Pod/XHTML.pm b/lib/MetaCPAN/Pod/XHTML.pm deleted file mode 100644 index aeadab8b3..000000000 --- a/lib/MetaCPAN/Pod/XHTML.pm +++ /dev/null @@ -1,136 +0,0 @@ -package MetaCPAN::Pod::XHTML; - -use strict; -use warnings; - -# Keep the coding style of Pod::Simple for consistency and performance. -# Pod::Simple::XHTML expects you to subclass and then override methods. - -use parent 'Pod::Simple::XHTML'; - -sub start_X { - $_[0]{_in_X_} = 1; -} - -sub end_X { - $_[0]{_in_X_} = 0; - $_[0]{'scratch'} - .= ''; -} - -sub handle_text { - if ( $_[0]{_in_X_} ) { - $_[0]{_last_X_} = $_[1]; - } - else { - $_[0]->SUPER::handle_text( $_[1] ); - } -} - -sub link_mappings { - my $self = shift; - if (@_) { - $self->{_link_map} = $_[0]; - } - $self->{_link_map}; -} - -sub resolve_pod_page_link { - my ( $self, $module, $section ) = @_; - my $link_map = $self->{_link_map} || {}; - if ( $module and my $link = $link_map->{$module} ) { - $module = $link; - } - $self->SUPER::resolve_pod_page_link( $module, $section ); -} - -sub start_item_text { - - # see end_item_text -} - -sub end_item_text { - - # idify =item content, reset 'scratch' - my $id = $_[0]->idify( $_[0]{'scratch'} ); - my $text = $_[0]{scratch}; - $_[0]{'scratch'} = ''; - - # construct whole element here because we need the - # contents of the =item to idify it - if ( $_[0]{'in_dd'}[ $_[0]{'dl_level'} ] ) { - $_[0]{'scratch'} = "\n"; - $_[0]{'in_dd'}[ $_[0]{'dl_level'} ] = 0; - } - - $_[0]{'scratch'} .= qq{
$text
\n
}; - $_[0]{'in_dd'}[ $_[0]{'dl_level'} ] = 1; - $_[0]->emit; -} - -# Custom handling of errata section - -sub _gen_errata { - return; # override the default errata formatting -} - -sub end_Document { - my $self = shift; - $self->_emit_custom_errata() if $self->{errata}; - $self->SUPER::end_Document(@_); -} - -sub _emit_custom_errata { - my $self = shift; - - my $tag = sub { - my $name = shift; - my $attributes = ''; - if ( ref( $_[0] ) ) { - my $attr = shift; - while ( my ( $k, $v ) = each %$attr ) { - $attributes .= qq{ $k="} . $self->encode_entities($v) . '"'; - } - } - my @body = map { /^encode_entities($_) } @_; - return join( '', "<$name$attributes>", @body, "" ); - }; - - my @errors = map { - my $line = $_; - my $error = $self->{'errata'}->{$line}; - ( - $tag->( 'dt', "Around line $line:" ), - $tag->( 'dd', map { $tag->( 'p', $_ ) } @$error ), - ); - } sort { $a <=> $b } keys %{ $self->{'errata'} }; - - my $error_count = keys %{ $self->{'errata'} }; - my $s = $error_count == 1 ? '' : 's'; - - $self->{'scratch'} = $tag->( - 'div', - { id => "pod-errors" }, - $tag->( 'p', { class => 'title' }, "$error_count POD Error$s" ), - $tag->( - 'div', - { id => "pod-error-detail" }, - $tag->( - 'p', - 'The following errors were encountered while parsing the POD:' - ), - $tag->( 'dl', @errors ), - ), - ); - $self->emit; -} - -1; - -=pod - -=head2 perldoc_url_prefix - -Set perldoc domain to C. - -=cut diff --git a/lib/MetaCPAN/Query.pm b/lib/MetaCPAN/Query.pm new file mode 100644 index 000000000..d9160f077 --- /dev/null +++ b/lib/MetaCPAN/Query.pm @@ -0,0 +1,52 @@ +package MetaCPAN::Query; +use Moose; + +use Module::Runtime qw( require_module ); +use Module::Pluggable::Object (); +use MetaCPAN::Types::TypeTiny qw( ES ); + +has es => ( + is => 'ro', + required => 1, + isa => ES, + coerce => 1, +); + +my @plugins = Module::Pluggable::Object->new( + search_path => [__PACKAGE__], + max_depth => 3, + require => 0, +)->plugins; + +for my $class (@plugins) { + require_module($class); + my $name = $class->can('name') && $class->name + or next; + + my $in = "_in_$name"; + my $gen = "_gen_$name"; + + has $in => ( + is => 'ro', + init_arg => $name, + weak_ref => 1, + ); + + has $gen => ( + is => 'ro', + init_arg => undef, + lazy => 1, + default => sub { + my $self = shift; + $class->new( + es => $self->es, + query => $self, + ); + }, + ); + + no strict 'refs'; + *$name = sub { $_[0]->$in // $_[0]->$gen }; +} + +1; diff --git a/lib/MetaCPAN/Query/Author.pm b/lib/MetaCPAN/Query/Author.pm new file mode 100644 index 000000000..f3323e913 --- /dev/null +++ b/lib/MetaCPAN/Query/Author.pm @@ -0,0 +1,132 @@ +package MetaCPAN::Query::Author; + +use MetaCPAN::Moose; + +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Util qw( MAX_RESULT_WINDOW hit_total ); +use Ref::Util qw( is_arrayref ); + +with 'MetaCPAN::Query::Role::Common'; + +sub by_ids { + my ( $self, $ids ) = @_; + + map {uc} @{$ids}; + + my $body = { + query => { ids => { values => $ids } }, + size => scalar @{$ids}, + }; + + my $authors = $self->es->search( es_doc_path('author'), body => $body, ); + + my @authors = map $_->{_source}, @{ $authors->{hits}{hits} }; + + return { + authors => \@authors, + took => $authors->{took}, + total => hit_total($authors), + }; +} + +sub by_user { + my ( $self, $users ) = @_; + $users = [$users] unless is_arrayref($users); + + my $authors = $self->es->search( + es_doc_path('author'), + body => { + query => { terms => { user => $users } }, + size => 500, + } + ); + + my @authors = map $_->{_source}, @{ $authors->{hits}{hits} }; + + return { + authors => \@authors, + took => $authors->{took}, + total => hit_total($authors), + }; +} + +sub search { + my ( $self, $query, $from ) = @_; + + $from //= 0; + my $size = 10; + + if ( $from * $size >= MAX_RESULT_WINDOW ) { + return +{ + authors => [], + took => 0, + total => 0, + }; + } + + my $body = { + query => { + bool => { + should => [ + { + match => { + 'name.analyzed' => + { query => $query, operator => 'AND' } + } + }, + { + match => { + 'asciiname.analyzed' => + { query => $query, operator => 'AND' } + } + }, + { match => { 'pauseid' => uc($query) } }, + { match => { 'profile.id' => lc($query) } }, + ], + } + }, + size => $size, + from => $from || 0, + }; + + my $ret = $self->es->search( es_doc_path('author'), body => $body, ); + + my @authors = map { +{ %{ $_->{_source} }, id => $_->{_id} } } + @{ $ret->{hits}{hits} }; + + return +{ + authors => \@authors, + took => $ret->{took}, + total => hit_total($ret), + }; +} + +sub prefix_search { + my ( $self, $query, $opts ) = @_; + my $size = $opts->{size} // 500; + my $from = $opts->{from} // 0; + + my $body = { + query => { + prefix => { + pauseid => $query, + }, + }, + size => $size, + from => $from, + }; + + my $ret = $self->es->search( es_doc_path('author'), body => $body, ); + + my @authors = map { +{ %{ $_->{_source} }, id => $_->{_id} } } + @{ $ret->{hits}{hits} }; + + return +{ + authors => \@authors, + took => $ret->{took}, + total => hit_total($ret), + }; +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Query/CVE.pm b/lib/MetaCPAN/Query/CVE.pm new file mode 100644 index 000000000..20a58d328 --- /dev/null +++ b/lib/MetaCPAN/Query/CVE.pm @@ -0,0 +1,63 @@ +package MetaCPAN::Query::CVE; + +use MetaCPAN::Moose; + +use MetaCPAN::ESConfig qw( es_doc_path ); + +with 'MetaCPAN::Query::Role::Common'; + +sub find_cves_by_cpansa { + my ( $self, $cpansa_id ) = @_; + + my $query = +{ term => { cpansa_id => $cpansa_id } }; + + my $res = $self->es->search( + es_doc_path('cve'), + body => { + query => $query, + size => 999, + } + ); + + return +{ cve => [ map { $_->{_source} } @{ $res->{hits}{hits} } ] }; +} + +sub find_cves_by_release { + my ( $self, $author, $release ) = @_; + + my $query = +{ match => { releases => "$author/$release" } }; + + my $res = $self->es->search( + es_doc_path('cve'), + body => { + query => $query, + size => 999, + } + ); + + return +{ cve => [ map { $_->{_source} } @{ $res->{hits}{hits} } ] }; +} + +sub find_cves_by_dist { + my ( $self, $dist, $version ) = @_; + + my $query = +{ + match => { + dist => $dist, + ( defined $version ? ( versions => $version ) : () ), + } + }; + + my $res = $self->es->search( + es_doc_path('cve'), + body => { + query => $query, + size => 999, + } + ); + + return +{ cve => [ map { $_->{_source} } @{ $res->{hits}{hits} } ] }; +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Query/Contributor.pm b/lib/MetaCPAN/Query/Contributor.pm new file mode 100644 index 000000000..d0b1859b9 --- /dev/null +++ b/lib/MetaCPAN/Query/Contributor.pm @@ -0,0 +1,67 @@ +package MetaCPAN::Query::Contributor; + +use MetaCPAN::Moose; + +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Util qw(hit_total); + +with 'MetaCPAN::Query::Role::Common'; + +sub find_release_contributors { + my ( $self, $author, $name ) = @_; + + my $query = +{ + bool => { + must => [ + { term => { release_author => $author } }, + { term => { release_name => $name } }, + { exists => { field => 'pauseid' } }, + ] + } + }; + + my $res = $self->es->search( + es_doc_path('contributor'), + body => { + query => $query, + size => 999, + _source => [ qw( + distribution + pauseid + release_author + release_name + ) ], + } + ); + hit_total($res) or return {}; + + return +{ + contributors => [ map { $_->{_source} } @{ $res->{hits}{hits} } ] }; +} + +sub find_author_contributions { + my ( $self, $pauseid ) = @_; + + my $query = +{ term => { pauseid => $pauseid } }; + + my $res = $self->es->search( + es_doc_path('contributor'), + body => { + query => $query, + size => 999, + _source => [ qw( + distribution + pauseid + release_author + release_name + ) ], + } + ); + hit_total($res) or return {}; + + return +{ + contributors => [ map { $_->{_source} } @{ $res->{hits}{hits} } ] }; +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Query/Cover.pm b/lib/MetaCPAN/Query/Cover.pm new file mode 100644 index 000000000..d524ea5c9 --- /dev/null +++ b/lib/MetaCPAN/Query/Cover.pm @@ -0,0 +1,31 @@ +package MetaCPAN::Query::Cover; + +use MetaCPAN::Moose; + +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Util qw(hit_total); + +with 'MetaCPAN::Query::Role::Common'; + +sub find_release_coverage { + my ( $self, $release ) = @_; + + my $query = +{ term => { release => $release } }; + + my $res = $self->es->search( + es_doc_path('cover'), + body => { + query => $query, + size => 999, + } + ); + hit_total($res) or return {}; + + return +{ + %{ $res->{hits}{hits}[0]{_source} }, + url => "http://cpancover.com/latest/$release/index.html", + }; +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Query/Distribution.pm b/lib/MetaCPAN/Query/Distribution.pm new file mode 100644 index 000000000..71140d573 --- /dev/null +++ b/lib/MetaCPAN/Query/Distribution.pm @@ -0,0 +1,72 @@ +package MetaCPAN::Query::Distribution; + +use MetaCPAN::Moose; + +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Util qw(hit_total); + +with 'MetaCPAN::Query::Role::Common'; + +sub rogue_list { + return qw( + Acme-DependOnEverything + Bundle-Everything + kurila + perl-5.005_02+apache1.3.3+modperl + perlbench + perl_debug + perl_mlb + pod2texi + spodcxx + ); +} + +sub get_river_data_by_dist { + my ( $self, $dist ) = @_; + + my $query = +{ + bool => { + must => [ { term => { name => $dist } }, ] + } + }; + + my $res = $self->es->search( + es_doc_path('distribution'), + body => { + query => $query, + size => 999, + } + ); + hit_total($res) or return {}; + + return +{ river => +{ $dist => $res->{hits}{hits}[0]{_source}{river} } }; +} + +sub get_river_data_by_dists { + my ( $self, $dist ) = @_; + + my $query = +{ + bool => { + must => [ { terms => { name => $dist } }, ] + } + }; + + my $res = $self->es->search( + es_doc_path('distribution'), + body => { + query => $query, + size => 999, + } + ); + hit_total($res) or return {}; + + return +{ + river => +{ + map { $_->{_source}{name} => $_->{_source}{river} } + @{ $res->{hits}{hits} } + }, + }; +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Query/Favorite.pm b/lib/MetaCPAN/Query/Favorite.pm new file mode 100644 index 000000000..67d521657 --- /dev/null +++ b/lib/MetaCPAN/Query/Favorite.pm @@ -0,0 +1,197 @@ +package MetaCPAN::Query::Favorite; + +use MetaCPAN::Moose; + +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Util qw( MAX_RESULT_WINDOW hit_total ); + +with 'MetaCPAN::Query::Role::Common'; + +sub agg_by_distributions { + my ( $self, $distributions, $user ) = @_; + return { + favorites => {}, + myfavorites => {}, + took => 0, + } + unless $distributions; + + my $body = { + size => 0, + query => { + terms => { distribution => $distributions } + }, + aggregations => { + favorites => { + terms => { + field => 'distribution', + size => scalar @{$distributions}, + }, + }, + $user + ? ( + myfavorites => { + filter => { term => { user => $user } }, + aggregations => { + entries => { + terms => { field => 'distribution' } + } + } + } + ) + : (), + } + }; + + my $ret = $self->es->search( es_doc_path('favorite'), body => $body, ); + + my %favorites = map { $_->{key} => $_->{doc_count} } + @{ $ret->{aggregations}{favorites}{buckets} }; + + my %myfavorites; + if ($user) { + %myfavorites = map { $_->{key} => $_->{doc_count} } + @{ $ret->{aggregations}{myfavorites}{entries}{buckets} }; + } + + return { + favorites => \%favorites, + myfavorites => \%myfavorites, + took => $ret->{took}, + }; +} + +sub by_user { + my ( $self, $user, $size ) = @_; + $size ||= 250; + + my $favs = $self->es->search( + es_doc_path('favorite'), + body => { + query => { term => { user => $user } }, + _source => [qw( author date distribution )], + sort => ['distribution'], + size => $size, + } + ); + return {} unless hit_total($favs); + my $took = $favs->{took}; + + my @favs = map { $_->{_source} } @{ $favs->{hits}{hits} }; + + # filter out backpan only distributions + + my $no_backpan = $self->es->search( + es_doc_path('release'), + body => { + query => { + bool => { + must => [ + { terms => { status => [qw( cpan latest )] } }, + { + terms => { + distribution => + [ map { $_->{distribution} } @favs ] + } + }, + ] + } + }, + _source => ['distribution'], + size => scalar(@favs), + } + ); + $took += $no_backpan->{took}; + + if ( hit_total($no_backpan) ) { + my %has_no_backpan = map { $_->{_source}{distribution} => 1 } + @{ $no_backpan->{hits}{hits} }; + + @favs = grep { exists $has_no_backpan{ $_->{distribution} } } @favs; + } + + return { favorites => \@favs, took => $took }; +} + +sub leaderboard { + my $self = shift; + + my $body = { + size => 0, + query => { match_all => {} }, + aggregations => { + leaderboard => { + terms => { + field => 'distribution', + size => 100, + }, + }, + totals => { + cardinality => { + field => 'distribution', + }, + }, + }, + }; + + my $ret = $self->es->search( es_doc_path('favorite'), body => $body, ); + + return { + leaderboard => $ret->{aggregations}{leaderboard}{buckets}, + total => $ret->{aggregations}{totals}{value}, + took => $ret->{took}, + }; +} + +sub recent { + my ( $self, $page, $size ) = @_; + $page //= 1; + $size //= 100; + + if ( $page * $size >= MAX_RESULT_WINDOW ) { + return +{ + favorites => [], + took => 0, + total => 0, + }; + } + + my $favs = $self->es->search( + es_doc_path('favorite'), + body => { + size => $size, + from => ( $page - 1 ) * $size, + query => { match_all => {} }, + sort => [ { 'date' => { order => 'desc' } } ] + } + ); + + my @favs = map { $_->{_source} } @{ $favs->{hits}{hits} }; + + return +{ + favorites => \@favs, + took => $favs->{took}, + total => hit_total($favs), + }; +} + +sub users_by_distribution { + my ( $self, $distribution ) = @_; + + my $favs = $self->es->search( + es_doc_path('favorite'), + body => { + query => { term => { distribution => $distribution } }, + _source => ['user'], + size => 1000, + } + ); + return {} unless hit_total($favs); + + my @plusser_users = map { $_->{_source}{user} } @{ $favs->{hits}{hits} }; + + return { users => \@plusser_users }; +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Query/File.pm b/lib/MetaCPAN/Query/File.pm new file mode 100644 index 000000000..15696c491 --- /dev/null +++ b/lib/MetaCPAN/Query/File.pm @@ -0,0 +1,759 @@ +package MetaCPAN::Query::File; + +use MetaCPAN::Moose; + +use List::Util qw( max ); +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Util qw( hit_total true false ); + +with 'MetaCPAN::Query::Role::Common'; + +sub dir { + my ( $self, $author, $release, @path ) = @_; + + my $body = { + query => { + bool => { + must => [ + { term => { 'level' => scalar @path } }, + { term => { 'author' => $author } }, + { term => { 'release' => $release } }, + { + prefix => { + 'path' => join( q{/}, @path, q{} ) + } + }, + ] + }, + }, + size => 999, + _source => [ + qw(name stat.mtime path stat.size directory slop documentation mime) + ], + }; + + my $data = $self->es->search( { + es_doc_path('file'), body => $body, + } ); + + my $dir = [ map { $_->{_source} } @{ $data->{hits}{hits} } ]; + + return { dir => $dir }; +} + +sub _doc_files { + my @files = @_; + my %s; + return + map +( "$_", "$_.pod", "$_.md", "$_.markdown", "$_.mdown", + "$_.mkdn", ), + grep !$s{$_}++, + map +( $_, uc $_ ), + @_; +} + +my %special_files = ( + changelog => [ + _doc_files( qw( + Changelog + ChangeLog + Changes + News + ) ), + ], + contributing => [ + _doc_files( qw( + Contributing + Hacking + Development + ) ), + ], + license => [ qw( + LICENCE + LICENSE + Copyright + COPYRIGHT + Copying + COPYING + Artistic + ARTISTIC + ) ], + install => [ + _doc_files( qw( + Install + ) ), + ], + dist => [ qw( + Build.PL + MANIFEST + META.json + META.yml + Makefile.PL + alienfile + cpanfile + prereqs.json + prereqs.yml + dist.ini + minil.toml + ) ], + security => [ + _doc_files( qw( + Security + security + ) ), + qw( + security.txt + ), + ], + other => [ + _doc_files( qw( + Authors + Credits + FAQ + README + THANKS + ToDo + Todo + ) ), + ], +); +my %perl_files = ( + changelog => [ qw( + perldelta.pod + ) ], + license => [ qw( + perlartistic.pod + perlgpl.pod + ) ], + contributing => [ qw( + perlhack.pod + ) ], +); + +my @shared_path_prefix_examples = qw( + example + examples + Example + Examples + sample + samples + demo + demos +); + +my %path_files = ( + example => [ + qw( + eg + ex + ), + @shared_path_prefix_examples, + ], +); + +my %prefix_files = ( example => [ @shared_path_prefix_examples, ], ); + +my %file_to_type; +my %type_to_regex; +my %query_parts; + +my %sort_order; + +for my $type ( keys %special_files ) { + my @files = @{ $special_files{$type} || [] }; + my @perl_files = @{ $perl_files{$type} || [] }; + + $sort_order{ $files[$_] } = $_ for 0 .. $#files; + + my @root_file = grep !/\.pod$/, @files; + my @non_root_file = grep /\.pod$/, @files; + + my @parts; + if (@root_file) { + push @parts, + { + bool => { + must => [ + { term => { level => 0 } }, + { terms => { name => \@root_file } }, + ], + ( + @perl_files + ? ( must_not => + [ { term => { distribution => 'perl' } } ] ) + : () + ), + } + }; + } + if (@non_root_file) { + push @parts, + { + bool => { + must => [ { terms => { name => \@non_root_file } } ], + ( + @perl_files + ? ( must_not => + [ { term => { distribution => 'perl' } } ] ) + : () + ), + } + }; + } + if (@perl_files) { + push @parts, + { + bool => { + must => [ + { term => { distribution => 'perl' } }, + { terms => { name => \@perl_files } }, + ], + } + }; + } + + $file_to_type{$_} = $type for @files, @perl_files; + push @{ $query_parts{$type} }, @parts; +} + +for my $type ( keys %prefix_files ) { + my @prefixes = @{ $prefix_files{$type} }; + + my @parts = map +{ prefix => { 'name' => $_ } }, @prefixes; + + push @{ $query_parts{$type} }, @parts; + + my ($regex) = map qr{(?:\A|/)(?:$_)[^/]*\z}, join '|', @prefixes; + + if ( $type_to_regex{$type} ) { + $type_to_regex{$type} = qr{$type_to_regex{$type}|$regex}; + } + else { + $type_to_regex{$type} = $regex; + } +} + +for my $type ( keys %path_files ) { + my @prefixes = @{ $path_files{$type} }; + + my @parts = map +{ prefix => { 'path' => "$_/" } }, @prefixes; + + push @{ $query_parts{$type} }, @parts; + + my ($regex) = map qr{\A(?:$_)/}, join '|', @prefixes; + + if ( $type_to_regex{$type} ) { + $type_to_regex{$type} = qr{$type_to_regex{$type}|$regex}; + } + else { + $type_to_regex{$type} = $regex; + } +} + +sub interesting_files { + my ( $self, $author, $release, $categories, $options ) = @_; + + $categories = [ sort keys %query_parts ] + if !$categories || !@$categories; + + my $return = { + files => [], + total => 0, + took => 0, + }; + + my @clauses = map @{ $query_parts{$_} // [] }, @$categories; + + return $return + unless @clauses; + + $options->{_source} //= [ qw( + author + distribution + documentation + name + path + pod_lines + release + status + ) ]; + $options->{size} //= 250; + + my $body = { + query => { + bool => { + must => [ + { term => { release => $release } }, + { term => { author => $author } }, + { term => { directory => false } }, + { bool => { should => \@clauses } }, + ], + must_not => [ + { prefix => { 'path' => 'corpus/' } }, + { prefix => { 'path' => 'fatlib/' } }, + { prefix => { 'path' => 'inc/' } }, + { prefix => { 'path' => 'local/' } }, + { prefix => { 'path' => 'perl5/' } }, + { prefix => { 'path' => 'share/' } }, + { prefix => { 'path' => 't/' } }, + { prefix => { 'path' => 'xt/' } }, + ], + }, + }, + %$options, + }; + + my $data = $self->es->search( { + es_doc_path('file'), body => $body, + } ); + + $return->{took} = $data->{took}; + $return->{total} = hit_total($data); + + return $return + unless $return->{total}; + + my $files = [ map $_->{_source}, @{ $data->{hits}{hits} } ]; + + for my $file (@$files) { + my $category = $file_to_type{ $file->{name} }; + if ( !$category ) { + for my $type ( keys %type_to_regex ) { + if ( $file->{path} =~ $type_to_regex{$type} ) { + $category = $type; + last; + } + } + } + $category ||= 'unknown'; + + $file->{category} = $category; + } + + $return->{files} = $files; + + return $return; +} + +sub files_by_category { + my ( $self, $author, $release, $categories, $options ) = @_; + my $return = $self->interesting_files( $author, $release, $categories, + $options ); + my $files = delete $return->{files}; + + $return->{categories} = { map +( $_ => [] ), @$categories }; + + for my $file (@$files) { + my $category = $file->{category}; + push @{ $return->{categories}{$category} }, $file; + } + + for my $category (@$categories) { + my $files = $return->{categories}{$category}; + @$files = map $_->[0], + sort { $a->[1] <=> $b->[1] || $a->[2] cmp $b->[2] } + map [ $_, $sort_order{ $_->{name} } || 9999, $_->{path} ], + @$files; + } + return $return; +} + +sub find_changes_files { + my ( $self, $author, $release ) = @_; + my $result = $self->files_by_category( $author, $release, ['changelog'], + { _source => true } ); + my ($file) = @{ $result->{categories}{changelog} || [] }; + return $file; +} + +sub _autocomplete { + my ( $self, $query ) = @_; + + my $search_size = 100; + + my $sugg_res = $self->es->search( + es_doc_path('file'), + body => { + suggest => { + documentation => { + text => $query, + completion => { + field => "suggest", + size => $search_size, + }, + }, + } + }, + ); + + my %docs; + for my $suggest ( @{ $sugg_res->{suggest}{documentation}[0]{options} } ) { + $docs{ $suggest->{text} } = max grep {defined} + ( $docs{ $suggest->{text} }, $suggest->{score} ); + } + + my $res = $self->es->search( + es_doc_path('file'), + body => { + query => { + bool => { + must => [ + { term => { indexed => true } }, + { term => { authorized => true } }, + { term => { status => 'latest' } }, + { terms => { documentation => [ keys %docs ] } }, + ], + must_not => [ + { + terms => { + distribution => [ + $self->query->distribution->rogue_list + ] + }, + }, + ], + } + }, + _source => [ qw( + author + date + deprecated + distribution + documentation + release + ) ], + size => $search_size, + }, + ); + + my $hits = $res->{hits}{hits}; + + my $fav_res + = $self->query->favorite->agg_by_distributions( + [ map $_->{_source}{distribution}, @$hits ] ); + + my $favs = $fav_res->{favorites}; + + my %valid = map { + my $source = $_->{_source}; + ( + $source->{documentation} => { + %$source, favorites => $favs->{ $source->{distribution} }, + } + ); + } @{ $res->{hits}{hits} }; + + # remove any exact match, it will be added later + my $exact = delete $valid{$query}; + + no warnings 'uninitialized'; + my @sorted = map { $valid{$_} } + sort { + my $a_data = $valid{$a}; + my $b_data = $valid{$b}; + $a_data->{deprecated} <=> $b_data->{deprecated} + || $b_data->{favorites} <=> $a_data->{favorites} + || $docs{$b} <=> $docs{$a} + || length($a) <=> length($b) + || $a cmp $b + } + keys %valid; + + return { + took => $sugg_res->{took} + $res->{took} + $fav_res->{took}, + suggestions => [ ( $exact ? $exact : () ), @sorted ], + }; +} + +sub autocomplete { + my ( $self, @terms ) = @_; + my $data = $self->_autocomplete( join ' ', @terms ); + + return { + took => $data->{took}, + hits => { + hits => [ + map { + my $source = $_; + +{ + fields => { + map +( $_ => $source->{$_} ), qw( + documentation + release + author + distribution + ), + }, + }; + } @{ $data->{suggestions} } + ], + }, + }; +} + +sub autocomplete_suggester { + my ( $self, @terms ) = @_; + my $data = $self->_autocomplete( join ' ', @terms ); + + return { + took => $data->{took}, + suggestions => [ + map +{ + author => $_->{author}, + date => $_->{date}, + deprecated => $_->{deprecated}, + distribution => $_->{distribution}, + name => $_->{documentation}, + release => $_->{release}, + }, + @{ $data->{suggestions} } + ], + }; +} + +sub documented_modules { + my ( $self, $author, $release ) = @_; + my $query = { + bool => { + must => [ + { term => { author => $author } }, + { term => { release => $release } }, + { exists => { field => "documentation" } }, + { + bool => { + should => [ + { + bool => { + must => [ + { + exists => + { field => 'module.name' } + }, + { + term => + { 'module.indexed' => true } + }, + ], + } + }, + { + bool => { + must => [ + { + exists => + { field => 'pod.analyzed' } + }, + { term => { indexed => true } }, + ], + } + }, + ], + } + }, + ], + }, + }; + my $res = $self->es->search( + es_doc_path('file'), + body => { + query => $query, + size => 999, + _source => [qw(name module path documentation distribution)], + }, + ); + + return { + took => $res->{took}, + files => [ map $_->{_source}, @{ $res->{hits}{hits} } ], + }; +} + +sub find_module { + my ( $self, $module, $fields ) = @_; + + my $query = { + bool => { + must => [ + { term => { indexed => true } }, + { term => { authorized => true } }, + { term => { status => 'latest' } }, + { + bool => { + should => [ + { term => { documentation => $module } }, + { + nested => { + path => "module", + query => { + bool => { + must => [ + { + term => { "module.name" => + $module } + }, + { + bool => { should => + [ + { term => + { "module.authorized" + => true + } }, + { exists => + { field => + 'module.associated_pod' + } }, + ], + } + }, + ], + }, + }, + } + }, + ] + } + }, + ], + }, + }; + + my $res = $self->es->search( + es_doc_path('file'), + search_type => 'dfs_query_then_fetch', + body => { + query => $query, + sort => [ + '_score', + { 'version_numified' => { order => 'desc' } }, + { 'date' => { order => 'desc' } }, + { 'mime' => { order => 'asc' } }, + { 'stat.mtime' => { order => 'desc' } } + ], + _source => [ + qw( documentation module.indexed module.authoried module.name ) + ], + size => 100, + }, + ); + + my @candidates = @{ $res->{hits}{hits} }; + + my ($file) = grep { + grep { $_->{indexed} && $_->{authorized} && $_->{name} eq $module } + @{ $_->{module} || [] } + } grep { !$_->{documentation} || $_->{documentation} eq $module } + @candidates; + + $file ||= shift @candidates; + return undef + if !$file; + return $self->es->get_source( + es_doc_path('file'), + id => $file->{_id}, + ( $fields ? ( _source => $fields ) : () ), + ); +} + +sub find_pod { + my ( $self, $name ) = @_; + my $file = $self->find_module($name); + return $file + unless $file; + my ($module) + = grep { $_->{indexed} && $_->{authorized} && $_->{name} eq $name } + @{ $file->{module} || [] }; + if ( $module && ( my $pod = $module->{associated_pod} ) ) { + my ( $author, $release, @path ) = split( /\//, $pod ); + my $query = { + bool => { + must => [ + { term => { author => $author } }, + { term => { release => $release } }, + { term => { path => join( '/', @path ) } }, + ], + }, + }; + my $pod_file = $self->es->search( + es_doc_path('file'), + body => { + query => $query, + }, + ); + return $pod_file->{hits}{hits}[0]->{_source}; + } + else { + return $file; + } +} + +sub history { + my ( $self, $type, $name, $path, $opts ) = @_; + + $opts ||= {}; + if ( ref $path ) { + $path = join '/', @$path; + } + + my $source = $opts->{fields}; + + my $query + = $type eq "module" + ? { + nested => { + path => 'module', + query => { + constant_score => { + filter => { + bool => { + must => [ + { term => { "module.authorized" => true } }, + { term => { "module.indexed" => true } }, + { term => { "module.name" => $name } }, + ] + } + } + } + } + } + } + : $type eq "file" ? { + bool => { + must => [ + { term => { path => $path } }, + { term => { distribution => $name } }, + ] + } + } + + # XXX: to fix: no filtering on 'release' so this query + # will produce modules matching duplications. -- Mickey + : $type eq "documentation" ? { + bool => { + must => [ + { match_phrase => { documentation => $name } }, + { term => { indexed => true } }, + { term => { authorized => true } }, + ] + } + } + : return undef; + + my $res = $self->es->search( + es_doc_path('file'), + body => { + query => $query, + size => 500, + sort => [ { date => 'desc' } ], + ( $source ? ( _source => $source ) : () ), + }, + ); + + return { + took => $res->{took}, + total => hit_total($res), + files => [ map $_->{_source}, @{ $res->{hits}{hits} } ], + }; +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Query/Mirror.pm b/lib/MetaCPAN/Query/Mirror.pm new file mode 100644 index 000000000..c16ee36e0 --- /dev/null +++ b/lib/MetaCPAN/Query/Mirror.pm @@ -0,0 +1,68 @@ +package MetaCPAN::Query::Mirror; + +use MetaCPAN::Moose; +use MetaCPAN::Util qw( hit_total ); + +use MetaCPAN::ESConfig qw( es_doc_path ); + +with 'MetaCPAN::Query::Role::Common'; + +sub search { + my ( $self, $q ) = @_; + my $query = { match_all => {} }; + + if ($q) { + my @protocols = grep /^ (?: http | ftp | rsync ) $/x, split /\s+/, $q; + + $query = { + bool => { + must => [ map +{ exists => { field => $_ } }, @protocols ] + }, + }; + } + + my @sort = ( sort => [qw( continent country )] ); + + my $location; + + if ( $q and $q =~ /loc\:([^\s]+)/ ) { + $location = [ split( /,/, $1 ) ]; + if ($location) { + @sort = ( + sort => { + _geo_distance => { + location => [ $location->[1], $location->[0] ], + order => 'asc', + unit => 'km' + } + } + ); + } + } + + my $ret = $self->es->search( + es_doc_path('mirror'), + body => { + size => 999, + query => $query, + @sort, + }, + ); + + my $data = [ + map +{ + %{ $_->{_source} }, + distance => ( $location ? $_->{sort}[0] : undef ) + }, + @{ $ret->{hits}{hits} } + ]; + + return { + mirrors => $data, + total => hit_total($ret), + took => $ret->{took} + }; +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Query/Package.pm b/lib/MetaCPAN/Query/Package.pm new file mode 100644 index 000000000..00027f683 --- /dev/null +++ b/lib/MetaCPAN/Query/Package.pm @@ -0,0 +1,35 @@ +package MetaCPAN::Query::Package; + +use MetaCPAN::Moose; + +use MetaCPAN::ESConfig qw( es_doc_path ); + +with 'MetaCPAN::Query::Role::Common'; + +sub get_modules { + my ( $self, $dist, $ver ) = @_; + + my $query = +{ + bool => { + must => [ + { term => { distribution => $dist } }, + { term => { dist_version => $ver } }, + ], + } + }; + + my $res = $self->es->search( + es_doc_path('package'), + body => { + query => $query, + size => 999, + _source => [qw< module_name >], + } + ); + + return +{ modules => + [ map { $_->{_source}{module_name} } @{ $res->{hits}{hits} } ] }; +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Query/Permission.pm b/lib/MetaCPAN/Query/Permission.pm new file mode 100644 index 000000000..311a68aab --- /dev/null +++ b/lib/MetaCPAN/Query/Permission.pm @@ -0,0 +1,62 @@ +package MetaCPAN::Query::Permission; + +use MetaCPAN::Moose; + +use MetaCPAN::ESConfig qw( es_doc_path ); +use Ref::Util qw( is_arrayref ); + +with 'MetaCPAN::Query::Role::Common'; + +sub by_author { + my ( $self, $pauseid ) = @_; + + my $body = { + query => { + bool => { + should => [ + { term => { owner => $pauseid } }, + { term => { co_maintainers => $pauseid } }, + ], + }, + }, + size => 5_000, + }; + + my $ret = $self->es->search( es_doc_path('permission'), body => $body, ); + + my $data = [ + sort { $a->{module_name} cmp $b->{module_name} } + map { $_->{_source} } @{ $ret->{hits}{hits} } + ]; + + return { permissions => $data }; +} + +sub by_modules { + my ( $self, $modules ) = @_; + $modules = [$modules] unless is_arrayref($modules); + + my @modules = map +{ term => { module_name => $_ } }, + grep defined, @{$modules}; + return { permissions => [] } + unless @modules; + + my $body = { + query => { + bool => { should => \@modules } + }, + size => 1_000, + }; + + my $ret = $self->es->search( es_doc_path('permission'), body => $body, ); + + my $data = [ + sort { $a->{module_name} cmp $b->{module_name} } + map { $_->{_source} } @{ $ret->{hits}{hits} } + ]; + + return { permissions => $data }; +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Query/Release.pm b/lib/MetaCPAN/Query/Release.pm new file mode 100644 index 000000000..b45011e25 --- /dev/null +++ b/lib/MetaCPAN/Query/Release.pm @@ -0,0 +1,1142 @@ +package MetaCPAN::Query::Release; +use v5.20; + +use MetaCPAN::Moose; + +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Util + qw( MAX_RESULT_WINDOW hit_total single_valued_arrayref_to_scalar true false ); + +with 'MetaCPAN::Query::Role::Common'; + +sub author_status { + my ( $self, $id, $file ) = @_; + return unless $id and $file; + + my $status = $file->{_source} + || single_valued_arrayref_to_scalar( $file->{fields} ); + + if ( $status and $status->{pauseid} ) { + $status->{release_count} + = $self->aggregate_status_by_author( $status->{pauseid} ); + + my ( $id_2, $id_1 ) = $id =~ /^((\w)\w)/; + $status->{links} = { + cpan_directory => + "https://www.cpan.org/authors/id/$id_1/$id_2/$id", + backpan_directory => + "https://cpan.metacpan.org/authors/id/$id_1/$id_2/$id", + cpants => "https://cpants.cpanauthors.org/author/$id", + cpantesters_reports => + "https://www.cpantesters.org/author/$id_1/$id.html", + cpantesters_matrix => + "https://matrix.cpantesters.org/?author=$id", + metacpan_explorer => + "https://explorer.metacpan.org/?url=/author/$id", + repology => "https://repology.org/maintainer/$id%40cpan", + }; + } + + return $status; +} + +sub aggregate_status_by_author { + my ( $self, $pauseid ) = @_; + my $agg = $self->es->search( { + es_doc_path('release'), + body => { + query => { + term => { author => $pauseid } + }, + aggregations => { + count => { terms => { field => 'status' } } + }, + size => 0, + } + } ); + my %ret = ( cpan => 0, latest => 0, backpan => 0 ); + if ($agg) { + $ret{ $_->{'key'} } = $_->{'doc_count'} + for @{ $agg->{'aggregations'}{'count'}{'buckets'} }; + } + $ret{'backpan-only'} = delete $ret{'backpan'}; + return \%ret; +} + +sub get_contributors { + my ( $self, $author_name, $release_name ) = @_; + + my $res = $self->es->search( + es_doc_path('contributor'), + body => { + query => { + bool => { + must => [ + { term => { release_name => $release_name } }, + { term => { release_author => $author_name } }, + ], + }, + }, + size => 999, + _source => [qw< email name pauseid >], + } + ); + + my @contribs = map $_->{_source}, @{ $res->{hits}{hits} }; + + @contribs = sort { fc $a->{name} cmp fc $b->{name} } @contribs; + + return { contributors => \@contribs }; +} + +sub get_files { + my ( $self, $release, $files ) = @_; + + my $query = +{ + query => { + bool => { + must => [ + { term => { release => $release } }, + { terms => { name => $files } } + ], + } + } + }; + + my $ret = $self->es->search( + es_doc_path('file'), + body => { + query => $query, + size => 999, + _source => [qw< name path >], + } + ); + + return {} unless @{ $ret->{hits}{hits} }; + + return { files => [ map { $_->{_source} } @{ $ret->{hits}{hits} } ] }; +} + +sub get_checksums { + my ( $self, $release ) = @_; + + my $query = { term => { name => $release } }; + + my $ret = $self->es->search( + es_doc_path('release'), + body => { + query => $query, + size => 1, + _source => [qw< checksum_md5 checksum_sha256 >], + } + ); + + return {} unless @{ $ret->{hits}{hits} }; + return $ret->{hits}{hits}[0]{_source}; +} + +sub _activity_filters { + my ( $self, $params, $start ) = @_; + my ( $author, $distribution, $module, $new_dists ) + = @{$params}{qw( author distribution module new_dists )}; + + my @filters + = ( { range => { date => { from => $start->epoch . '000' } } } ); + + push @filters, +{ term => { author => uc($author) } } + if $author; + + push @filters, +{ term => { distribution => $distribution } } + if $distribution; + + push @filters, +{ term => { 'dependency.module' => $module } } + if $module; + + if ( $new_dists and $new_dists eq 'n' ) { + push @filters, + ( + +{ term => { first => true } }, + +{ terms => { status => [qw( cpan latest )] } }, + ); + } + + return +{ bool => { must => \@filters } }; +} + +sub activity { + my ( $self, $params ) = @_; + my $res = $params->{res} // '1w'; + + my $start + = DateTime->now->truncate( to => 'month' )->subtract( months => 23 ); + + my $filters = $self->_activity_filters( $params, $start ); + + my $body = { + query => { match_all => {} }, + aggregations => { + histo => { + filter => $filters, + aggregations => { + entries => { + date_histogram => + { field => 'date', interval => $res }, + } + } + } + }, + size => 0, + }; + + my $ret = $self->es->search( es_doc_path('release'), body => $body, ); + + my $data = { map { $_->{key} => $_->{doc_count} } + @{ $ret->{aggregations}{histo}{entries}{buckets} } }; + + my $line = [ + map { + $data->{ $start->clone->add( months => $_ )->epoch . '000' } + || 0 + } ( 0 .. 23 ) + ]; + + return { activity => $line }; +} + +sub by_author_and_name { + my ( $self, $author, $release ) = @_; + + my $body = { + query => { + bool => { + must => [ + { term => { 'name' => $release } }, + { term => { author => uc($author) } } + ] + } + } + }; + + my $ret = $self->es->search( es_doc_path('release'), body => $body, ); + + my $data = $ret->{hits}{hits}[0]{_source}; + + return { + took => $ret->{took}, + release => $data, + total => hit_total($ret), + }; +} + +sub by_author_and_names { + my ( $self, $releases ) = @_; + + # $releases: ArrayRef[ Dict[ author => Str, name => Str ] ] + + my $body = { + size => ( 0 + @$releases ), + query => { + bool => { + should => [ + map { + +{ + bool => { + must => [ + { + term => { + author => uc( $_->{author} ) + } + }, + { term => { 'name' => $_->{name} } }, + ] + } + } + } @$releases + ] + } + } + }; + + my $ret = $self->es->search( es_doc_path('release'), body => $body, ); + + my @releases; + for my $hit ( @{ $ret->{hits}{hits} } ) { + my $src = $hit->{_source}; + push @releases, $src; + } + + return { + took => $ret->{took}, + total => hit_total($ret), + releases => \@releases, + }; +} + +sub by_author { + my ( $self, $pauseid, $page, $size ) = @_; + $size //= 1000; + $page //= 1; + + if ( $page * $size >= MAX_RESULT_WINDOW ) { + return { + releases => [], + took => 0, + total => 0, + }; + } + + my $body = { + query => { + bool => { + must => [ + { terms => { status => [qw< cpan latest >] } }, + ( $pauseid ? { term => { author => $pauseid } } : () ), + ], + } + }, + sort => + [ 'distribution', { 'version_numified' => { reverse => 1 } } ], + _source => [ + qw( abstract author authorized date distribution license metadata.version resources.repository status tests ) + ], + size => $size, + from => ( $page - 1 ) * $size, + }; + + my $ret = $self->es->search( es_doc_path('release'), body => $body, ); + + my $data = [ map { $_->{_source} } @{ $ret->{hits}{hits} } ]; + + return { + releases => $data, + total => hit_total($ret), + took => $ret->{took} + }; +} + +sub latest_by_distribution { + my ( $self, $distribution ) = @_; + + my $body = { + query => { + bool => { + must => [ + { + term => { + 'distribution' => $distribution + } + }, + { term => { status => 'latest' } } + ] + } + }, + sort => [ { date => 'desc' } ], + size => 1 + }; + + my $ret = $self->es->search( es_doc_path('release'), body => $body, ); + + my $data = $ret->{hits}{hits}[0]{_source}; + + return { + release => $data, + took => $ret->{took}, + total => hit_total($ret), + }; +} + +sub latest_by_author { + my ( $self, $pauseid ) = @_; + + my $body = { + query => { + bool => { + must => [ + { term => { author => uc($pauseid) } }, + { term => { status => 'latest' } } + ] + } + }, + sort => + [ 'distribution', { 'version_numified' => { reverse => 1 } } ], + _source => [ + qw(author distribution name status abstract date download_url version authorized maturity) + ], + size => 1000, + }; + + my $ret = $self->es->search( es_doc_path('release'), body => $body, ); + + my $data = [ map { $_->{_source} } @{ $ret->{hits}{hits} } ]; + + return { took => $ret->{took}, releases => $data }; +} + +sub all_by_author { + my ( $self, $author, $page, $size ) = @_; + $size //= 100; + $page //= 1; + + if ( $page * $size >= MAX_RESULT_WINDOW ) { + return { + releases => [], + took => 0, + total => 0, + }; + } + + my $body = { + query => { term => { author => uc($author) } }, + sort => [ { date => 'desc' } ], + _source => [ + qw(author distribution name status abstract date download_url version authorized maturity) + ], + size => $size, + from => ( $page - 1 ) * $size, + }; + my $ret = $self->es->search( es_doc_path('release'), body => $body, ); + + my $data = [ map { $_->{_source} } @{ $ret->{hits}{hits} } ]; + + return { + took => $ret->{took}, + releases => $data, + total => hit_total($ret), + }; +} + +sub versions { + my ( $self, $dist, $versions ) = @_; + + my $size = 1000; + + my $query; + + # 'versions' param was sent + if ( @{$versions} ) { + my $filter_versions; + + # we only want 'latest' version + if ( @{$versions} == 1 and $versions->[0] eq 'latest' ) { + $filter_versions = { term => { status => 'latest' } }; + } + else { + if ( grep $_ eq 'latest', @{$versions} ) { + + # we want a combination of 'latest' and specific versions + @{$versions} = grep $_ ne 'latest', @{$versions}; + $filter_versions = { + bool => { + should => [ + { terms => { version => $versions } }, + { term => { status => 'latest' } }, + ], + } + }; + } + else { + # we only want specific versions + $filter_versions = { terms => { version => $versions } }; + } + } + + $query = { + bool => { + must => [ + { term => { distribution => $dist } }, + $filter_versions + ] + } + }; + } + else { + $query = { term => { distribution => $dist } }; + } + + my $body = { + query => $query, + size => $size, + sort => [ { date => 'desc' } ], + _source => [ qw( + name + date + author + version + status + maturity + authorized + download_url + main_module + ) ], + }; + + my $ret = $self->es->search( es_doc_path('release'), body => $body, ); + + my $data = [ map { $_->{_source} } @{ $ret->{hits}{hits} } ]; + + return { + releases => $data, + total => hit_total($ret), + took => $ret->{took} + }; +} + +sub top_uploaders { + my ( $self, $range ) = @_; + my $range_filter = { + range => { + date => { + from => $range eq 'all' ? 0 : DateTime->now->subtract( + $range eq 'weekly' ? 'weeks' + : $range eq 'monthly' ? 'months' + : $range eq 'yearly' ? 'years' + : 'weeks' => 1 + )->truncate( to => 'day' )->iso8601 + }, + } + }; + + my $body = { + query => { match_all => {} }, + aggregations => { + author => { + aggregations => { + entries => { + terms => { field => 'author', size => 50 } + } + }, + filter => $range_filter, + }, + }, + size => 0, + }; + + my $ret = $self->es->search( es_doc_path('release'), body => $body, ); + + my $counts = { map { $_->{key} => $_->{doc_count} } + @{ $ret->{aggregations}{author}{entries}{buckets} } }; + + return { + counts => $counts, + took => $ret->{took} + }; +} + +sub requires { + my ( $self, $module, $page, $page_size, $sort ) = @_; + return $self->_get_depended_releases( [$module], $page, $page_size, + $sort ); +} + +sub reverse_dependencies { + my ( $self, $distribution, $page, $page_size, $sort ) = @_; + + # get the latest release of given distribution + my $release = $self->_get_latest_release($distribution) || return; + + # get (authorized/indexed) modules provided by the release + my $modules = $self->_get_provided_modules($release) || return; + + # return releases depended on those modules + return $self->_get_depended_releases( $modules, $page, $page_size, + $sort ); +} + +sub _get_latest_release { + my ( $self, $distribution ) = @_; + + my $release = $self->es->search( + es_doc_path('release'), + body => { + query => { + bool => { + must => [ + { term => { distribution => $distribution } }, + { term => { status => 'latest' } }, + { term => { authorized => true } }, + ] + }, + }, + _source => [qw< name author >], + }, + ); + + my ($release_info) = map { $_->{_source} } @{ $release->{hits}{hits} }; + + return $release_info->{name} && $release_info->{author} + ? +{ + name => $release_info->{name}, + author => $release_info->{author}, + } + : undef; +} + +sub _get_provided_modules { + my ( $self, $release ) = @_; + + my $provided_modules = $self->es->search( + es_doc_path('file'), + body => { + query => { + bool => { + must => [ + { term => { 'release' => $release->{name} } }, + { term => { 'author' => $release->{author} } }, + { term => { 'module.authorized' => true } }, + { term => { 'module.indexed' => true } }, + ] + } + }, + size => 999, + } + ); + + my @modules = map { $_->{name} } + grep { $_->{indexed} && $_->{authorized} } + map { @{ $_->{_source}{module} } } + @{ $provided_modules->{hits}{hits} }; + + return @modules ? \@modules : undef; +} + +sub _fix_sort_value { + my $sort = shift; + + if ( $sort && $sort =~ /^(\w+):(asc|desc)$/ ) { + return { $1 => $2 }; + } + else { + return { date => 'desc' }; + } +} + +sub _get_depended_releases { + my ( $self, $modules, $page, $page_size, $sort ) = @_; + $page //= 1; + $page_size //= 50; + + if ( $page * $page_size >= MAX_RESULT_WINDOW ) { + return +{ + data => [], + took => 0, + total => 0, + }; + } + + $sort = _fix_sort_value($sort); + + my $dependency_filter = { + nested => { + path => 'dependency', + query => { + bool => { + must => [ + { + term => + { 'dependency.relationship' => 'requires' } + }, + { + terms => { + 'dependency.phase' => [ qw( + configure + build + runtime + test + ) ] + } + }, + { terms => { 'dependency.module' => $modules } }, + ], + }, + }, + }, + }; + + my $depended = $self->es->search( + es_doc_path('release'), + body => { + query => { + bool => { + must => [ + $dependency_filter, + { term => { status => 'latest' } }, + { term => { authorized => true } }, + ], + }, + }, + size => $page_size, + from => ( $page - 1 ) * $page_size, + sort => $sort, + } + ); + + return +{ + data => [ map { $_->{_source} } @{ $depended->{hits}{hits} } ], + total => hit_total($depended), + took => $depended->{took}, + }; +} + +sub recent { + my ( $self, $type, $page, $page_size ) = @_; + $page //= 1; + $page_size //= 10000; + $type //= ''; + + if ( $page * $page_size >= MAX_RESULT_WINDOW ) { + return +{ + releases => [], + took => 0, + total => 0, + }; + } + + my $query; + if ( $type eq 'n' ) { + $query = { + bool => { + must => [ + { term => { first => true } }, + { terms => { status => [qw< cpan latest >] } }, + ] + } + }; + } + elsif ( $type eq 'a' ) { + $query = { match_all => {} }; + } + else { + $query = { terms => { status => [qw< cpan latest >] } }; + } + + my $body = { + size => $page_size, + from => ( $page - 1 ) * $page_size, + query => $query, + _source => + [qw(name author status abstract date distribution maturity)], + sort => [ { 'date' => { order => 'desc' } } ] + }; + + my $ret = $self->es->search( es_doc_path('release'), body => $body, ); + + my $data = [ map { $_->{_source} } @{ $ret->{hits}{hits} } ]; + + return { + releases => $data, + total => hit_total($ret), + took => $ret->{took} + }; +} + +sub modules { + my ( $self, $author, $release ) = @_; + + my $body = { + query => { + bool => { + must => [ + { term => { release => $release } }, + { term => { author => $author } }, + { term => { directory => false } }, + { + bool => { + should => [ + { + bool => { + must => [ + { + exists => { + field => 'module.name' + } + }, + { + term => { + 'module.indexed' => true + } + } + ] + } + }, + { + bool => { + must => [ + { + range => { + slop => { gt => 0 } + } + }, + { + exists => { + field => 'pod.analyzed' + } + }, + { + term => { 'indexed' => true } + }, + ] + } + } + ] + } + } + ] + } + }, + size => 999, + + # Sort by documentation name; if there isn't one, sort by path. + sort => [ 'documentation', 'path' ], + + _source => [ qw( + module + abstract + author + authorized + distribution + documentation + indexed + path + pod_lines + release + status + ) ], + }; + + my $ret = $self->es->search( es_doc_path('file'), body => $body, ); + + my @files = map $_->{_source}, @{ $ret->{hits}{hits} }; + + return { + files => \@files, + total => hit_total($ret), + took => $ret->{took} + }; +} + +=head2 find_download_url + +cpanm Foo +=> status: latest, maturity: released + +cpanm --dev Foo +=> status: -backpan, sort_by: version_numified,date + +cpanm Foo~1.0 +=> status: latest, maturity: released, module.version_numified: gte: 1.0 + +cpanm --dev Foo~1.0 +-> status: -backpan, module.version_numified: gte: 1.0, sort_by: version_numified,date + +cpanm Foo~<2 +=> maturity: released, module.version_numified: lt: 2, sort_by: status,version_numified,date + +cpanm --dev Foo~<2 +=> status: -backpan, module.version_numified: lt: 2, sort_by: status,version_numified,date + + $release->find_download_url(http://github.com/'module',%20'Foo',%20%7B%20version%20=%3E%20$version,%20dev%20=%3E%200|1%20%7D); + +Sorting: + + if it's stable: + prefer latest > cpan > backpan + then sort by version desc + then sort by date descending (rev chron) + + if it's dev: + sort by version desc + sort by date descending (reverse chronologically) + + +=cut + +sub find_download_url { + my ( $self, $type, $name, $args ) = @_; + $args ||= {}; + + my $dev = $args->{dev}; + my $version = $args->{version}; + my $explicit_version = $version && $version =~ /==/; + + my @filters; + + die 'type must be module or dist' + unless $type eq 'module' || $type eq 'dist'; + my $module_filter = $type eq 'module'; + + if ( !$explicit_version ) { + push @filters, + { bool => { must_not => [ { term => { status => 'backpan' } } ] } + }; + if ( !$dev ) { + push @filters, { term => { maturity => 'released' } }; + } + } + + my $prefix = $module_filter ? 'module.' : ''; + + my $version_filters + = $self->_version_filters( $version, $prefix . 'version_numified' ); + + my $entity_filter = { + bool => { + must => [ + { term => { $prefix . 'authorized' => true } }, + ( + $module_filter + ? ( + { term => { $prefix . 'indexed' => true } }, + { term => { $prefix . 'name' => $name } } + ) + : { term => { 'distribution' => $name } }, + ), + ( + exists $version_filters->{must} + ? @{ $version_filters->{must} } + : () + ) + ], + ( + exists $version_filters->{must_not} + ? ( must_not => [ @{ $version_filters->{must_not} } ] ) + : () + ) + } + }; + + # filters to be applied to the nested modules + if ($module_filter) { + push @filters, + { + nested => { + path => 'module', + query => $entity_filter, + } + }; + } + else { + push @filters, $entity_filter; + } + + my $filter + = @filters + ? { bool => { must => \@filters } } + : $filters[0]; + + my $version_sort + = $module_filter + ? { + 'module.version_numified' => { + mode => 'max', + order => 'desc', + ( + $self->es->api_version ge '6_0' + ? ( + nested => { + path => 'module', + filter => $entity_filter, + }, + ) + : ( + nested_path => 'module', + nested_filter => $entity_filter, + ) + ), + } + } + : { version_numified => { order => 'desc' } }; + + # sort by score, then version desc, then date desc + my @sort = ( '_score', $version_sort, { date => { order => 'desc' } } ); + + my $query; + + if ($dev) { + $query = $filter; + } + else { + # if not dev, then prefer latest > cpan > backpan + $query = { + function_score => { + query => $filter, + score_mode => 'first', + boost_mode => 'replace', + functions => [ + { + filter => { term => { status => 'latest' } }, + weight => 3 + }, + { + filter => { term => { status => 'cpan' } }, + weight => 2 + }, + { filter => { match_all => {} }, weight => 1 }, + ] + } + }; + } + + my $body = { + query => $query, + size => 1, + sort => \@sort, + _source => [ qw( + checksum_md5 + checksum_sha256 + date + distribution + download_url + release + status + version + name + ) ], + }; + + my $res = $self->es->search( + es_doc_path( $module_filter ? 'file' : 'release' ), + body => $body, + search_type => 'dfs_query_then_fetch', + ); + + return unless hit_total($res); + + my @checksums; + + my $hit = $res->{hits}{hits}[0]; + my $source = $hit->{_source}; + my $release = $source->{release}; + + if ($release) { + my $checksums = $self->get_checksums($release); + @checksums = ( + ( + $checksums->{checksum_md5} + ? ( checksum_md5 => $checksums->{checksum_md5} ) + : () + ), + ( + $checksums->{checksum_sha256} + ? ( checksum_sha256 => $checksums->{checksum_sha256} ) + : () + ), + ); + } + + my $source_name = delete $source->{name}; + if ( !$module_filter ) { + $source->{release} = $source_name; + } + + my $module + = $hit->{inner_hits}{module} + ? $hit->{inner_hits}{module}{hits}{hits}[0]{_source} + : {}; + + return +{ %$source, %$module, @checksums, }; +} + +sub _version_filters { + my ( $self, $version, $field ) = @_; + + return () unless $version; + + if ( $version =~ s/^==\s*// ) { + return +{ + must => [ { + term => { + $field => $self->_numify($version) + } + } ] + }; + } + elsif ( $version =~ /^[<>!]=?\s*/ ) { + my %ops = qw(< lt <= lte > gt >= gte); + my ( %filters, %range, @exclusion ); + my @requirements = split /,\s*/, $version; + for my $r (@requirements) { + if ( $r =~ s/^([<>]=?)\s*// ) { + $range{ $ops{$1} } = $self->_numify($r); + } + elsif ( $r =~ s/\!=\s*// ) { + push @exclusion, $self->_numify($r); + } + } + + if ( keys %range ) { + $filters{must} + = [ { range => { $field => \%range } } ]; + } + + if (@exclusion) { + $filters{must_not} = []; + push @{ $filters{must_not} }, + map { +{ term => { $field => $self->_numify($_) } } } + @exclusion; + } + + return \%filters; + } + elsif ( $version !~ /\s/ ) { + return +{ + must => [ { + range => { + $field => { 'gte' => $self->_numify($version) } + }, + } ] + }; + } +} + +sub _numify { + my ( $self, $ver ) = @_; + $ver =~ s/_//g; + version->new($ver)->numify; +} + +sub predecessor { + my ( $self, $name ) = @_; + + my $res = $self->es->search( + es_doc_path('release'), + body => { + query => { + bool => { + must => [ { term => { distribution => $name } }, ], + must_not => [ { term => { status => 'latest' } }, ], + }, + }, + sort => [ { date => 'desc' } ], + size => 1, + }, + ); + my ($release) = $res->{hits}{hits}[0]; + return unless $release; + return $release->{_source}; +} + +sub find { + my ( $self, $name ) = @_; + + my $res = $self->es->search( + es_doc_path('release'), + body => { + query => { + bool => { + must => [ + { term => { distribution => $name } }, + { term => { status => 'latest' } }, + ], + }, + }, + sort => [ { date => 'desc' } ], + size => 1, + }, + ); + my ($file) = $res->{hits}{hits}[0]; + return undef unless $file; + return $file->{_source}; +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Query/Role/Common.pm b/lib/MetaCPAN/Query/Role/Common.pm new file mode 100644 index 000000000..bc86b311b --- /dev/null +++ b/lib/MetaCPAN/Query/Role/Common.pm @@ -0,0 +1,46 @@ +package MetaCPAN::Query::Role::Common; +use Moose::Role; + +use MetaCPAN::Types::TypeTiny qw( ES ); + +has es => ( + is => 'ro', + required => 1, + isa => ES, + coerce => 1, +); + +sub name { + my $self = shift; + my $class = ref $self || $self; + + $class =~ /^MetaCPAN::Query::([^:]+)$/ + or return undef; + return lc $1; +} + +has _in_query => ( + is => 'ro', + init_arg => 'query', + weak_ref => 1, +); + +has _gen_query => ( + is => 'ro', + lazy => 1, + init_arg => undef, + default => sub { + my $self = shift; + my $name = $self->name; + + require MetaCPAN::Query; + MetaCPAN::Query->new( + es => $self->es, + ( $name ? ( $name => $self ) : () ), + ); + }, +); + +sub query { $_[0]->_in_query // $_[0]->_gen_query } + +1; diff --git a/lib/MetaCPAN/Query/Search.pm b/lib/MetaCPAN/Query/Search.pm new file mode 100644 index 000000000..d5cf21897 --- /dev/null +++ b/lib/MetaCPAN/Query/Search.pm @@ -0,0 +1,397 @@ +package MetaCPAN::Query::Search; + +use MetaCPAN::Moose; + +use Const::Fast qw( const ); +use Hash::Merge qw( merge ); +use List::Util qw( min uniq ); +use Log::Contextual qw( :log :dlog ); +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Util qw( MAX_RESULT_WINDOW hit_total true false ); +use MooseX::StrictConstructor; + +with 'MetaCPAN::Query::Role::Common'; + +const my $RESULTS_PER_RUN => 200; +const my @ROGUE_DISTRIBUTIONS => qw( + Acme-DependOnEverything + Bundle-Everything + kurila + perl-5.005_02+apache1.3.3+modperl + perlbench + perl_debug + perl_mlb + pod2texi + spodcxx +); + +sub search_for_first_result { + my ( $self, $search_term ) = @_; + my $es_query = $self->build_query($search_term); + my $es_results = $self->run_query( file => $es_query ); + + my $data = $es_results->{hits}{hits}[0]; + return $data->{_source}; +} + +=head2 search_web + + search_web( $search_term, $from, $page_size, $collapsed ); + +- search_term: + - can be unqualified string e.g. 'paging' + - can be author e.g: 'author:LLAP' + - can be module e.g.: 'module:Data::Pageset' + - can be distribution e.g.: 'dist:Data-Pageset' + +- from: where in result set to start, int + +- page_size: number of results per page, int + +- collapsed: whether to merge results by dist or not + +=cut + +sub search_web { + my ( $self, $search_term, $page, $page_size, $collapsed, + $max_collapsed_hits ) + = @_; + $page_size //= 20; + $page //= 1; + + if ( $page * $page_size >= MAX_RESULT_WINDOW ) { + return { + results => [], + total => 0, + tool => 0, + colapsed => $collapsed ? true : false, + }; + } + + $search_term =~ s{([+=>_search_collapsed( $search_term, $page, $page_size, + $max_collapsed_hits ) + : $self->_search_expanded( $search_term, $page, $page_size ); + + return $results; +} + +sub _search_expanded { + my ( $self, $search_term, $page, $page_size ) = @_; + + # Used for distribution and module searches, the limit is included in + # the query and ES does the right thing (because we are not collapsing + # results by distribution). + my $es_query = $self->build_query( + $search_term, + { + size => $page_size, + from => ( $page - 1 ) * $page_size, + } + ); + + my $es_results = $self->run_query( file => $es_query ); + + # Extract results from es + my $results = $self->_extract_results($es_results); + + $results = [ + map { { + hits => [$_], + distribution => $_->{distribution}, + total => 1, + } } @$results + ]; + + my $return = { + results => $results, + total => hit_total($es_results), + took => $es_results->{took}, + collapsed => false, + }; + return $return; +} + +sub _search_collapsed { + my ( $self, $search_term, $page, $page_size, $max_collapsed_hits ) = @_; + + $max_collapsed_hits ||= 5; + + my $from = ( $page - 1 ) * $page_size; + my $total_size = $page * $page_size; + + my $es_query_opts = { + size => 0, + _source => [ qw( + ) ], + }; + + my $es_query = $self->build_query( $search_term, $es_query_opts ); + my $source = delete $es_query->{_source}; + + my $script_key = $self->es->api_version ge '5_0' ? 'source' : 'inline'; + + $es_query->{aggregations} = { + by_dist => { + terms => { + size => $total_size, + field => 'distribution', + order => { + max_score => 'desc', + }, + }, + aggregations => { + top_files => { + top_hits => { + _source => $source, + size => $max_collapsed_hits, + }, + }, + max_score => { + max => { + script => { + lang => "expression", + $script_key => "_score", + }, + }, + }, + }, + }, + total_dists => { + cardinality => { + field => 'distribution', + }, + }, + }; + + my $es_results = $self->run_query( file => $es_query ); + + my $output = { + results => [], + total => $es_results->{aggregations}{total_dists}{value}, + took => $es_results->{took}, + collapsed => true, + }; + + my $last = min( $total_size - 1, + $#{ $es_results->{aggregations}{by_dist}{buckets} } ); + my @dists = @{ $es_results->{aggregations}{by_dist}{buckets} } + [ $from .. $last ]; + + @{ $output->{results} } = map { + +{ + hits => $self->_extract_results( $_->{top_files} ), + distribution => $_->{key}, + total => $_->{doc_count}, + }; + } @dists; + + return $output; +} + +sub build_query { + my ( $self, $search_term, $params ) = @_; + $params //= {}; + ( my $clean = $search_term ) =~ s/::/ /g; + + my $query = { + bool => { + filter => [ + { term => { status => 'latest' } }, + { term => { authorized => true } }, + { term => { indexed => true } }, + { + bool => { + should => [ + { + bool => { + must => [ + { + exists => + { field => 'module.name' } + }, + { + term => + { 'module.indexed' => true } + } + ], + } + }, + { exists => { field => 'documentation' } }, + ], + } + }, + ], + must_not => [ { + terms => { + distribution => [ $self->query->distribution->rogue_list ] + } + } ], + must => [ + { + bool => { + should => [ + + # exact matches result in a huge boost + { + term => { + 'documentation' => { + value => $search_term, + boost => 20, + } + } + }, + { + term => { + 'module.name' => { + value => $search_term, + boost => 20, + } + } + }, + + # take the maximum score from the module name and the abstract/pod + { + dis_max => { + queries => [ + { + query_string => { + fields => [ + qw(documentation.analyzed^2 module.name.analyzed^2 distribution.analyzed), + qw(documentation.camelcase module.name.camelcase distribution.camelcase) + ], + query => $clean, + boost => 3, + default_operator => 'AND', + allow_leading_wildcard => + false, + + } + }, + { + query_string => { + fields => [ + qw(abstract.analyzed pod.analyzed) + ], + query => $clean, + default_operator => 'AND', + allow_leading_wildcard => + false, + }, + }, + ], + } + }, + ], + } + }, + ], + }, + }; + + my $script_key = $self->es->api_version ge '5_0' ? 'source' : 'inline'; + + $query = { + function_score => { + script_score => { + + # prefer shorter module names + script => { + lang => 'expression', + $script_key => + "_score - (doc['documentation_length'].value == 0 ? 26 : doc['documentation_length'].value)/400", + }, + }, + query => { + boosting => { + negative_boost => 0.5, + positive => $query, + negative => { + bool => { + should => [ + { + term => { 'mime' => 'text/x-script.perl' } + }, + { term => { 'deprecated' => true } }, + ], + }, + }, + }, + }, + }, + }; + + my $search = merge( + $params, + { + query => $query, + _source => [ qw( + module + abstract + author + authorized + date + description + dist_fav_count + distribution + documentation + id + indexed + path + pod_lines + release + status + ) ], + } + ); + + # Ensure our requested fields are unique so that Elasticsearch doesn't + # return us the same value multiple times in an unexpected arrayref. + $search->{_source} = [ uniq @{ $search->{_source} || [] } ]; + + return $search; +} + +sub run_query { + my ( $self, $doc, $es_query ) = @_; + return $self->es->search( + es_doc_path($doc), + body => $es_query, + search_type => 'dfs_query_then_fetch', + ); +} + +sub _extract_results { + my ( $self, $es_results ) = @_; + + return [ + map { + my $res = $_; + +{ + favorites => delete $res->{_source}->{dist_fav_count}, + %{ $res->{_source} }, + score => $res->{_score}, + } + } @{ $es_results->{hits}{hits} } + ]; +} + +1; + diff --git a/lib/MetaCPAN/Role/HasConfig.pm b/lib/MetaCPAN/Role/HasConfig.pm new file mode 100644 index 000000000..ad1bae0d2 --- /dev/null +++ b/lib/MetaCPAN/Role/HasConfig.pm @@ -0,0 +1,25 @@ +package MetaCPAN::Role::HasConfig; + +use Moose::Role; + +use MetaCPAN::Server::Config (); +use MetaCPAN::Types::TypeTiny qw( HashRef ); + +# Done like this so can be required by a role +sub config { + return $_[0]->_config; +} + +has _config => ( + is => 'ro', + isa => HashRef, + lazy => 1, + builder => '_build_config', +); + +sub _build_config { + my $self = shift; + return MetaCPAN::Server::Config::config(); +} + +1; diff --git a/lib/MetaCPAN/Role/HasRogueDistributions.pm b/lib/MetaCPAN/Role/HasRogueDistributions.pm new file mode 100644 index 000000000..14a02facc --- /dev/null +++ b/lib/MetaCPAN/Role/HasRogueDistributions.pm @@ -0,0 +1,25 @@ +package MetaCPAN::Role::HasRogueDistributions; + +use Moose::Role; + +use MetaCPAN::Types::TypeTiny qw( ArrayRef ); + +has rogue_distributions => ( + is => 'ro', + isa => ArrayRef, + default => sub { + [ qw( + Bundle-Everything + kurila + perl-5.005_02+apache1.3.3+modperl + perlbench + perl_debug + perl_mlb + pod2texi + spodcxx + ) ]; + }, +); + +no Moose::Role; +1; diff --git a/lib/MetaCPAN/Role/Logger.pm b/lib/MetaCPAN/Role/Logger.pm index b3acc6365..95d80d662 100644 --- a/lib/MetaCPAN/Role/Logger.pm +++ b/lib/MetaCPAN/Role/Logger.pm @@ -2,26 +2,27 @@ package MetaCPAN::Role::Logger; use v5.10; use Moose::Role; -use MetaCPAN::Types qw(:all); + use Log::Contextual qw( set_logger ); use Log::Log4perl ':easy'; -use Path::Class (); +use MetaCPAN::Types::TypeTiny qw( Logger Str ); +use MooseX::Getopt (); ## no perlimports +use Path::Tiny qw( path ); has level => ( is => 'ro', - isa => 'Str', + isa => Str, required => 1, trigger => \&set_level, documentation => 'Log level', ); has logger => ( - is => 'ro', - required => 1, - isa => Logger, - coerce => 1, - predicate => 'has_logger', - traits => ['NoGetopt'], + is => 'ro', + required => 1, + isa => Logger, + coerce => 1, + traits => ['NoGetopt'], ); sub set_level { @@ -46,11 +47,11 @@ sub set_logger_once { return; } -# XXX NOT A MOOSE BUILDER -# XXX This doesn't belong here. +# Not actually a Moose builder, so we should probably rename it. sub _build_logger { my ($config) = @_; - my $log = Log::Log4perl->get_logger( $ARGV[0] ); + my $log = Log::Log4perl->get_logger( $ARGV[0] + || 'this_would_have_been_argv_0_but_there_is_no_such_thing' ); foreach my $c (@$config) { my $layout = Log::Log4perl::Layout::PatternLayout->new( $c->{layout} || qq{%d %p{1} %c: %m{chomp}%n} ); @@ -58,7 +59,7 @@ sub _build_logger { if ( $c->{class} =~ /Appender::File$/ && $c->{filename} ) { # Create the log file's parent directory if necessary. - Path::Class::File->new( $c->{filename} )->parent->mkpath; + path( $c->{filename} )->parent->mkpath; } my $app = Log::Log4perl::Appender->new( $c->{class}, %$c ); diff --git a/lib/MetaCPAN/Role/Script.pm b/lib/MetaCPAN/Role/Script.pm index 6a030b138..3ed00e450 100644 --- a/lib/MetaCPAN/Role/Script.pm +++ b/lib/MetaCPAN/Role/Script.pm @@ -1,27 +1,43 @@ package MetaCPAN::Role::Script; -use strict; -use warnings; - -use ElasticSearch; -use ElasticSearchX::Model::Document::Types qw(:all); -use FindBin; -use Log::Contextual qw( :log :dlog ); -use MetaCPAN::Model; -use MetaCPAN::Types qw(:all); use Moose::Role; -with 'MetaCPAN::Role::Logger'; +use Carp (); +use IO::Prompt::Tiny qw( prompt ); +use Log::Contextual qw( :log :dlog ); +use MetaCPAN::Model (); +use MetaCPAN::Types::TypeTiny qw( AbsPath Bool ES HashRef Int Path Str ); +use MetaCPAN::Util qw( root_dir ); +use Mojo::Server (); +use Term::ANSIColor qw( colored ); +use MetaCPAN::Model::ESWrapper (); + +use MooseX::Getopt::OptionTypeMap (); +for my $type ( Path, AbsPath, ES ) { + MooseX::Getopt::OptionTypeMap->add_option_type_to_map( $type, '=s' ); +} + +with( 'MetaCPAN::Role::HasConfig', 'MetaCPAN::Role::Fastly', + 'MetaCPAN::Role::Logger' ); -has 'cpan' => ( - is => 'rw', - isa => Dir, - lazy_build => 1, - coerce => 1, +has cpan => ( + is => 'ro', + isa => Path, + lazy => 1, + builder => '_build_cpan', + coerce => 1, documentation => 'Location of a local CPAN mirror, looks for $ENV{MINICPAN} and ~/CPAN', ); +has cpan_file_map => ( + is => 'ro', + isa => HashRef, + lazy => 1, + builder => '_build_cpan_file_map', + traits => ['NoGetopt'], +); + has die_on_error => ( is => 'ro', isa => Bool, @@ -29,82 +45,117 @@ has die_on_error => ( documentation => 'Die on errors instead of simply logging', ); +has exit_code => ( + isa => Int, + is => 'rw', + default => 0, + documentation => 'Exit Code to be returned on termination', +); + +has ua => ( + is => 'ro', + lazy => 1, + builder => '_build_ua', +); + +has proxy => ( + is => 'ro', + isa => Str, + default => '', +); + has es => ( - isa => ES, is => 'ro', + isa => ES, required => 1, + init_arg => 'elasticsearch_servers', coerce => 1, - documentation => 'ElasticSearch http connection string', + documentation => 'Elasticsearch http connection string', ); -has model => ( lazy_build => 1, is => 'ro', traits => ['NoGetopt'] ); - -has index => ( - reader => '_index', - is => 'ro', - isa => 'Str', - default => 'cpan', - documentation => 'Index to use, defaults to "cpan"', +has model => ( + is => 'ro', + init_arg => undef, + lazy => 1, + builder => '_build_model', + traits => ['NoGetopt'], ); has port => ( - isa => 'Int', + isa => Int, is => 'ro', - required => 1, + required => 0, + lazy => 1, + default => sub {5000}, documentation => 'Port for the proxy, defaults to 5000', ); has home => ( is => 'ro', - isa => Dir, + isa => Path, + lazy => 1, coerce => 1, - default => "$FindBin::RealBin/..", + default => sub { root_dir() }, ); -has config => ( +has _minion => ( is => 'ro', - isa => 'HashRef', + isa => 'Minion', lazy => 1, - builder => '_build_config', + handles => { _add_to_queue => 'enqueue', stats => 'stats', }, + default => sub { Mojo::Server->new->build_app('MetaCPAN::API')->minion }, ); -sub _build_config { - my $self = shift; - return Config::JFDI->new( - name => 'metacpan_server', - path => "$FindBin::RealBin/..", - )->get; -} +has queue => ( + is => 'ro', + isa => Bool, + default => 0, + documentation => 'add indexing jobs to the minion queue', +); sub handle_error { - my ( $self, $error ) = @_; + my ( $self, $error, $die_always ) = @_; + + # Die if configured (for the test suite). + $die_always = $self->die_on_error unless defined $die_always; # Always log. log_fatal {$error}; - # Die if configured (for the test suite). - die $error if $self->die_on_error; + $! = $self->exit_code if ( $self->exit_code != 0 ); + + Carp::croak $error if $die_always; } -sub index { - my $self = shift; - return $self->model->index( $self->_index ); +sub print_error { + my ( $self, $error ) = @_; + + log_error {$error}; } sub _build_model { my $self = shift; - return MetaCPAN::Model->new( es => $self->es ); + + # es provided by ElasticSearchX::Model::Role + + my $es = MetaCPAN::Model::ESWrapper->new( $self->es ); + return MetaCPAN::Model->new( es => $es ); } -sub file2mod { - my $self = shift; - my $name = shift; +sub _build_ua { + my $self = shift; + my $ua = LWP::UserAgent->new; + my $proxy = $self->proxy; + + if ($proxy) { + $proxy eq 'env' + ? $ua->env_proxy + : $ua->proxy( [qw], $proxy ); + } - $name =~ s{\Alib\/}{}; - $name =~ s{\.(pod|pm)\z}{}; - $name =~ s{\/}{::}gxms; + $ua->agent('MetaCPAN'); - return $name; + return $ua; } sub _build_cpan { @@ -121,17 +172,67 @@ sub _build_cpan { } -sub remote { - shift->es->transport->default_servers->[0]; +sub _build_cpan_file_map { + my $self = shift; + my $ls = $self->cpan->child(qw(indices find-ls.gz)); + unless ( -e $ls ) { + die "File $ls does not exist"; + } + log_info {"Reading $ls"}; + my $cpan = {}; + open my $fh, "<:gzip", $ls; + while (<$fh>) { + my $path = ( split(/\s+/) )[-1]; + next unless ( $path =~ /^authors\/id\/\w+\/\w+\/(\w+)\/(.*)$/ ); + $cpan->{$1}{$2} = 1; + } + close $fh; + return $cpan; } sub run { } before run => sub { my $self = shift; - $self->set_logger_once; +}; - Dlog_debug {"Connected to $_"} $self->remote; +sub are_you_sure { + my ( $self, $msg ) = @_; + my $iconfirmed = 0; + + if ( -t *STDOUT ) { + my $answer + = prompt colored( ['bold red'], "*** Warning ***: $msg" ) . "\n" + . 'Are you sure you want to do this (type "YES" to confirm) ? '; + if ( $answer ne 'YES' ) { + log_error {"Confirmation incorrect: '$answer'"}; + print "Operation will be interruped!\n"; + + #Set System Error: 125 - ECANCELED - Operation canceled + $self->exit_code(125); + $self->handle_error( 'Operation canceled on User Request', 1 ); + } + else { + log_info {'Operation confirmed.'}; + print "alright then...\n"; + $iconfirmed = 1; + } + } + else { + log_info {"*** Warning ***: $msg"}; + $iconfirmed = 1; + } + + return $iconfirmed; +} + +before perform_purges => sub { + my ($self) = @_; + if ( $self->has_surrogate_keys_to_purge ) { + log_info { + "CDN Purge: " . join ', ', $self->surrogate_keys_to_purge; + }; + } }; 1; @@ -140,8 +241,60 @@ __END__ =pod +=head1 NAME + +MetaCPAN::Role::Script - Base Role which is used by many command line applications + =head1 SYNOPSIS -Roles which should be available to all modules +Roles which should be available to all modules. + +=head1 OPTIONS + +This Role makes the command line application accept the following options + +=over 4 + +=item Option C<--await 15> + +This option will set the I. +After C seconds the Application will fail with an Exception and the Exit Code [112] +(C<112 - EHOSTDOWN - Host is down>) will be returned + + bin/metacpan --await 15 + +B If the I service does not become available +within C seconds it exits the Script with Exit Code C< 112 >. + +See L> + +=back + +=head1 METHODS + +This Role provides the following methods + +=over 4 + +=item C + +Requests the user to confirm the operation with "I< YES >" + +B When the operator input does not match "I< YES >" it will exit the Script +with Exit Code [125] (C<125 - ECANCELED - Operation canceled>). + +=item C + +Logs the string C with the log function as fatal error. +If C is not equel C< 0 > sets its value in C< $! >. +If the option C<--die_on_error> is enabled it throws an Exception with C. +If the parameter C is set it overrides the option C<--die_on_error>. + +=item C + +Logs the string C with the log function and displays it in red. +But it does not end the application. + +=back =cut diff --git a/lib/MetaCPAN/Script/Author.pm b/lib/MetaCPAN/Script/Author.pm index c3d8b7eff..00e59e372 100644 --- a/lib/MetaCPAN/Script/Author.pm +++ b/lib/MetaCPAN/Script/Author.pm @@ -6,15 +6,17 @@ use warnings; use Moose; with 'MooseX::Getopt', 'MetaCPAN::Role::Script'; -use DateTime::Format::ISO8601 (); -use Email::Valid (); -use Encode (); -use File::stat (); -use JSON::XS (); -use Log::Contextual qw( :log ); -use MetaCPAN::Document::Author; -use URI (); -use XML::Simple qw(XMLin); +use Cpanel::JSON::XS qw( decode_json ); +use DateTime (); +use Email::Valid (); +use Encode (); +use Log::Contextual qw( :log :dlog ); +use MetaCPAN::Document::Author (); +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Types::TypeTiny qw( Str ); +use MetaCPAN::Util qw(diff_struct true false); +use URI (); +use XML::XPath (); =head1 SYNOPSIS @@ -23,110 +25,298 @@ Loads author info into db. Requires the presence of a local CPAN/minicpan. =cut has author_fh => ( - is => 'rw', + is => 'ro', traits => ['NoGetopt'], lazy => 1, default => sub { shift->cpan . '/authors/00whois.xml' }, ); +has pauseid => ( + is => 'ro', + isa => Str, +); + sub run { my $self = shift; + $self->index_authors; - $self->index->refresh; + $self->es->indices->refresh; +} + +my @author_config_fields = qw( + name + asciiname + profile + blog + perlmongers + donation + email + website + city + region + country + location + extra +); + +my @cpan_fields = qw( + pauseid + name + email + website + asciiname + is_pause_custodial_account +); + +my @compare_fields = do { + my %seen; + sort grep !$seen{$_}++, @cpan_fields, @author_config_fields; +}; + +has whois_data => ( + is => 'ro', + traits => ['NoGetopt'], + lazy => 1, + builder => '_build_whois_data', +); + +sub _build_whois_data { + my $self = shift; + + my $whois_data = {}; + + my $xp = XML::XPath->new( filename => $self->author_fh ); + + for my $author ( $xp->find('/cpan-whois/cpanid')->get_nodelist ) { + my $data = { + map +( $_->getLocalName, $_->string_value ), + grep $_->isa('XML::XPath::Node::Element'), + $author->getChildNodes + }; + + my $pauseid = $data->{id}; + my $existing = $whois_data->{$pauseid}; + if ( !$existing + || $existing->{type} eq 'author' && $data->{type} eq 'list' ) + { + $whois_data->{$pauseid} = $data; + } + } + + return $whois_data; } sub index_authors { my $self = shift; - my $type = $self->index->type('author'); - my $authors = XMLin( $self->author_fh )->{cpanid}; - my $count = keys %$authors; - log_debug {"Counting author"}; - log_info {"Indexing $count authors"}; - - log_debug {"Getting last update dates"}; - my $dates - = $type->inflate(0)->filter( { exists => { field => 'updated' } } ) - ->size(99999)->all; - $dates = { - map { - $_->{pauseid} => - DateTime::Format::ISO8601->parse_datetime( $_->{updated} ) - } map { $_->{_source} } @{ $dates->{hits}->{hits} } - }; + my $authors = $self->whois_data; - my $bulk = $self->model->bulk( size => 20 ); - - while ( my ( $pauseid, $data ) = each %$authors ) { - my ( $name, $email, $homepage, $asciiname ) - = ( @$data{qw(fullname email homepage asciiname)} ); - $name = undef if ( ref $name ); - $email = lc($pauseid) . '@cpan.org' - unless ( $email && Email::Valid->address($email) ); - log_debug { - Encode::encode_utf8( - sprintf( "Indexing %s: %s <%s>", $pauseid, $name, $email ) ); - }; - my $conf = $self->author_config( $pauseid, $dates ) || next; - my $put = { - pauseid => $pauseid, - name => $name, - asciiname => ref $asciiname ? undef : $asciiname, - email => $email, - website => $homepage, - map { $_ => $conf->{$_} } - grep { defined $conf->{$_} } keys %$conf - }; - $put->{website} = [ $put->{website} ] - unless ( ref $put->{website} eq 'ARRAY' ); - $put->{website} = [ - - # normalize www.homepage.com to http://www.homepage.com - map { $_->scheme ? $_->as_string : 'http://' . $_->as_string } - map { URI->new($_)->canonical } - grep {$_} @{ $put->{website} } - ]; - my $author = $type->new_document($put); - $author->gravatar_url; # build gravatar_url - $bulk->put($author); + if ( $self->pauseid ) { + log_info {"Indexing 1 author"}; + $authors = { $self->pauseid => $authors->{ $self->pauseid } }; + } + else { + my $count = keys %$authors; + log_debug {"Counting author"}; + log_info {"Indexing $count authors"}; + } + + my @author_ids_to_purge; + + my $bulk = $self->es->bulk_helper( + es_doc_path('author'), + max_count => 250, + timeout => '25m', + ); + + my $scroll = $self->es->scroll_helper( + es_doc_path('author'), + size => 500, + body => { + query => { + $self->pauseid + ? ( + term => { + pauseid => $self->pauseid, + }, + ) + : ( match_all => {} ), + }, + _source => [@compare_fields], + sort => '_doc', + }, + ); + + # update authors + while ( my $doc = $scroll->next ) { + my $pauseid = $doc->{_id}; + my $whois_data = delete $authors->{$pauseid} || next; + $self->update_author( $bulk, $pauseid, $whois_data, $doc->{_source} ); } - $self->index->refresh; + + # new authors + for my $pauseid ( keys %$authors ) { + my $whois_data = delete $authors->{$pauseid} || next; + $self->update_author( $bulk, $pauseid, $whois_data ); + } + + $bulk->flush; + $self->es->indices->refresh; + + $self->perform_purges; + log_info {"done"}; } -sub author_config { - my ( $self, $pauseid, $dates ) = @_; - my $fallback = $dates->{$pauseid} ? undef : {}; - my $dir = $self->cpan->subdir( 'authors', - MetaCPAN::Util::author_dir($pauseid) ); - my @files; - opendir( my $dh, $dir ) || return $fallback; - my ($file) - = sort { $dir->file($b)->stat->mtime <=> $dir->file($a)->stat->mtime } - grep {m/author-.*?\.json/} readdir($dh); - return $fallback unless ($file); - $file = $dir->file($file); - return $fallback if !-e $file; - my $mtime = DateTime->from_epoch( epoch => $file->stat->mtime ); - - if ( $dates->{$pauseid} && $dates->{$pauseid} >= $mtime ) { - log_debug {"Skipping $pauseid (newer version in index)"}; - return undef; +sub author_data_from_cpan { + my $self = shift; + my ( $pauseid, $whois_data ) = @_; + + my $author_config = $self->author_config($pauseid) || {}; + + my $data = { + pauseid => $pauseid, + name => $whois_data->{fullname}, + email => $whois_data->{email}, + website => $whois_data->{homepage}, + asciiname => $whois_data->{asciiname}, + %$author_config, + is_pause_custodial_account => ( + ( $whois_data->{fullname} // '' ) + =~ /\(PAUSE Custodial Account\)/ ? true : false + ), + }; + + undef $data->{name} + if ref $data->{name}; + + if ( !length $data->{name} ) { + $data->{name} = $pauseid; } - my $json = $file->slurp; - my $author = eval { JSON::XS->new->utf8->relaxed->decode($json) }; - if ($@) { - log_warn {"$file is broken: $@"}; - return $fallback; + $data->{asciiname} = q{} + if !defined $data->{asciiname}; + + $data->{email} = lc($pauseid) . '@cpan.org' + unless $data->{email} && Email::Valid->address( $data->{email} ); + + $data->{website} = [ + + # normalize www.homepage.com to http://www.homepage.com + map +( $_->scheme ? '' : 'http://' ) . $_->as_string, + map URI->new($_)->canonical, + grep $_, + map +( ref eq 'ARRAY' ? @$_ : $_ ), + $data->{website} + ]; + + # Do not import lat / lon's in the wrong order, or just invalid + if ( my $loc = $data->{location} ) { + if ( ref $loc ne 'ARRAY' || @$loc != 2 ) { + delete $data->{location}; + } + else { + my $lat = $loc->[1]; + my $lon = $loc->[0]; + + if ( !defined $lat or $lat > 90 or $lat < -90 ) { + + # Invalid latitude + delete $data->{location}; + } + elsif ( !defined $lon or $lon > 180 or $lon < -180 ) { + + # Invalid longitude + delete $data->{location}; + } + } + } + + return $data; +} + +sub update_author { + my $self = shift; + my ( $bulk, $pauseid, $whois_data, $current_data ) = @_; + + my $data = $self->author_data_from_cpan( $pauseid, $whois_data ); + + log_debug { + Encode::encode_utf8( sprintf( + "Indexing %s: %s <%s>", + $pauseid, $data->{name}, $data->{email} + ) ); + }; + + # Now check the format we have is actually correct + if ( my @errors = MetaCPAN::Document::Author->validate($data) ) { + Dlog_error { + "Invalid data for $pauseid: $_" + } + \@errors; + return; + } + + if ( my $diff = diff_struct( $current_data, $data, 1 ) ) { + + # log a sampling of differences + if ( $self->has_surrogate_keys_to_purge % 10 == 9 ) { + Dlog_debug { + "Found difference in $pauseid: $_" + } + $diff; + } } else { - $author - = { map { $_ => $author->{$_} } - qw(name asciiname profile blog perlmongers donation email website city region country location extra) - }; - $author->{updated} = $mtime; - return $author; + return; } + + $data->{updated} = DateTime->now( time_zone => 'UTC' )->iso8601; + + $bulk->update( { + id => $pauseid, + doc => $data, + doc_as_upsert => true, + } ); + + $self->purge_author_key($pauseid); +} + +sub author_config { + my ( $self, $pauseid ) = @_; + + my $dir = $self->cpan->child( 'authors', + MetaCPAN::Util::author_dir($pauseid) ); + + return undef + unless $dir->is_dir; + + my $author_cpan_files = $self->cpan_file_map->{$pauseid} + or return undef; + + # Get the most recent version + my ($file) = map $_->[0], sort { $b->[1] <=> $a->[1] } + map [ $_ => $_->stat->mtime ], + grep $author_cpan_files->{ $_->basename }, + $dir->children(qr/\Aauthor-.*\.json\z/); + + return undef + unless $file; + + my $author; + eval { + $author = decode_json( $file->slurp_raw ); + 1; + } or do { + log_warn {"$file is broken: $@"}; + return undef; + }; + + return { + map { + my $value = $author->{$_}; + defined $value ? ( $_ => $value ) : () + } @author_config_fields + }; } __PACKAGE__->meta->make_immutable; diff --git a/lib/MetaCPAN/Script/Backpan.pm b/lib/MetaCPAN/Script/Backpan.pm index afdecac1a..935ed4a36 100644 --- a/lib/MetaCPAN/Script/Backpan.pm +++ b/lib/MetaCPAN/Script/Backpan.pm @@ -3,65 +3,198 @@ package MetaCPAN::Script::Backpan; use strict; use warnings; -use BackPAN::Index; use Moose; +use Log::Contextual qw( :log :dlog ); +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Types::TypeTiny qw( Bool HashRef Str ); + with 'MetaCPAN::Role::Script', 'MooseX::Getopt::Dashes'; +has distribution => ( + is => 'ro', + isa => Str, + documentation => 'work on given distribution', +); + +has undo => ( + is => 'ro', + isa => Bool, + default => 0, + documentation => 'mark releases as status=cpan', +); + +has files_only => ( + is => 'ro', + isa => Bool, + default => 0, + documentation => 'only update the "file" index', +); + +has _release_status => ( + is => 'ro', + isa => HashRef, + default => sub { +{} }, +); + +has _bulk => ( + is => 'ro', + isa => HashRef, + default => sub { +{} }, +); + sub run { my $self = shift; - my $backpan = BackPAN::Index->new( debug => 0 ); - my $releases = $backpan->releases(); - - my @search; - while ( my $release = $releases->next ) { - push @search, - { - and => [ - { term => { 'author' => $release->cpanid } }, - { term => { 'name' => $release->distvname } }, - { not => { term => { status => 'backpan' } } }, - ] - }; - if ( scalar @search >= 5000 ) { - $self->update_status(@search); - @search = (); + $self->es->trace_calls(1) if $ENV{DEBUG}; + + $self->build_release_status_map(); + + $self->update_releases() unless $self->files_only; + + $self->update_files(); + + $_->flush for values %{ $self->_bulk }; +} + +sub build_release_status_map { + my $self = shift; + + log_info {"find_releases"}; + + my $scroll = $self->es->scroll_helper( + scroll => '5m', + es_doc_path('release'), + body => { + %{ $self->_get_release_query }, + size => 500, + _source => [ 'author', 'archive', 'name' ], + }, + ); + + while ( my $release = $scroll->next ) { + my $author = $release->{_source}{author}; + my $archive = $release->{_source}{archive}; + my $name = $release->{_source}{name}; + next unless $name; # bypass some broken releases + + $self->_release_status->{$author}{$name} = [ + ( + $self->undo + or exists $self->cpan_file_map->{$author}{$archive} + ) + ? 'cpan' + : 'backpan', + $release->{_id} + ]; + } +} + +sub _get_release_query { + my $self = shift; + + unless ( $self->undo ) { + return +{ + query => { + bool => + { must_not => [ { term => { status => 'backpan' } } ] } + } + }; + } + + return +{ + query => { + bool => { + must => [ + { term => { status => 'backpan' } }, + ( + $self->distribution + ? { + term => { distribution => $self->distribution } + } + : () + ) + ] + } + } + }; +} + +sub update_releases { + my $self = shift; + + log_info {"update_releases"}; + + $self->_bulk->{release} ||= $self->es->bulk_helper( + es_doc_path('release'), + max_count => 250, + timeout => '5m', + ); + + for my $author ( keys %{ $self->_release_status } ) { + + # value = [ status, _id ] + for ( values %{ $self->_release_status->{$author} } ) { + $self->_bulk->{release}->update( { + id => $_->[1], + doc => { + status => $_->[0], + } + } ); } } - $self->update_status(@search) if @search; } -sub update_status { - my $self = shift; - my @search = @_; - - my $es = $self->es; - $es->trace_calls(1) if $ENV{DEBUG}; - - my $scroll = $es->scrolled_search( - size => 500, - scroll => '2m', - index => 'cpan_v1', - type => 'release', - fields => [ 'author', 'name' ], - query => { - filtered => { - query => { match_all => {} }, - filter => { - or => \@search, - }, +sub update_files { + my $self = shift; + + for my $author ( keys %{ $self->_release_status } ) { + my @releases = keys %{ $self->_release_status->{$author} }; + while ( my @chunk = splice @releases, 0, 1000 ) { + $self->update_files_author( $author, \@chunk ); + } + } +} + +sub update_files_author { + my $self = shift; + my $author = shift; + my $author_releases = shift; + + log_info { "update_files: " . $author }; + + my $scroll = $self->es->scroll_helper( + scroll => '5m', + es_doc_path('file'), + body => { + query => { + bool => { + must => [ + { term => { author => $author } }, + { terms => { release => $author_releases } } + ] + } }, + size => 500, + _source => ['release'], }, ); - while ( my $release = $scroll->next ) { - $es->update( - index => 'cpan_v1', - type => 'release', - id => $release->{_id}, - doc => { status => 'backpan' } - ); + $self->_bulk->{file} ||= $self->es->bulk_helper( + es_doc_path('file'), + max_count => 250, + timeout => '5m', + ); + my $bulk = $self->_bulk->{file}; + + while ( my $file = $scroll->next ) { + my $release = $file->{_source}{release}; + $bulk->update( { + id => $file->{_id}, + doc => { + status => $self->_release_status->{$author}{$release}[0] + } + } ); } } diff --git a/lib/MetaCPAN/Script/Backup.pm b/lib/MetaCPAN/Script/Backup.pm index 1f23ba614..2ced44ea0 100644 --- a/lib/MetaCPAN/Script/Backup.pm +++ b/lib/MetaCPAN/Script/Backup.pm @@ -4,25 +4,36 @@ use strict; use warnings; use feature qw( state ); -use Data::Printer; -use DateTime; -use IO::Zlib (); -use JSON::XS; -use Log::Contextual qw( :log :dlog ); -use MetaCPAN::Types qw( Bool Int Str File ); +use Cpanel::JSON::XS qw( decode_json encode_json ); +use DateTime (); +use IO::Zlib (); +use Log::Contextual qw( :log :dlog ); +use MetaCPAN::Types::TypeTiny qw( Bool CommaSepOption Int Path Str ); +use MetaCPAN::Util qw( true false ); +use MetaCPAN::ESConfig qw( es_config ); use Moose; -use Try::Tiny; +use Try::Tiny qw( catch try ); with 'MetaCPAN::Role::Script', 'MooseX::Getopt::Dashes'; has batch_size => ( - is => 'ro', - isa => Int, - default => 100, + is => 'ro', + isa => Int, + default => 100, documentation => 'Number of documents to restore in one batch, defaults to 100', ); +has index => ( + reader => '_index', + is => 'ro', + isa => CommaSepOption, + coerce => 1, + default => sub { es_config->all_indexes }, + documentation => 'ES indexes to backup, defaults to "' + . join( ', ', @{ es_config->all_indexes } ) . '"', +); + has type => ( is => 'ro', isa => Str, @@ -50,7 +61,7 @@ has dry_run => ( has restore => ( is => 'ro', - isa => File, + isa => Path, coerce => 1, documentation => 'Restore a backup', ); @@ -62,32 +73,38 @@ sub run { return $self->run_restore if $self->restore; my $es = $self->es; - $self->index->refresh; - - my $filename = join( '-', - DateTime->now->strftime('%F'), - grep {defined} $self->index->name, - $self->type ); - - my $file = $self->home->subdir(qw(var backup))->file("$filename.json.gz"); - $file->dir->mkpath unless ( -e $file->dir ); - my $fh = IO::Zlib->new( "$file", 'wb4' ); - - my $scroll = $es->scrolled_search( - index => $self->index->name, - $self->type ? ( type => $self->type ) : (), - size => $self->size, - search_type => 'scan', - fields => [qw(_parent _source)], - scroll => '1m', - ); - log_info { 'Backing up ', $scroll->total, ' documents' }; + for my $index ( @{ $self->_index } ) { + + $self->es->indices->refresh( index => $index ); + + my $filename = join( '-', + DateTime->now->strftime('%F'), + grep {defined} $index, + $self->type ); - while ( my $result = $scroll->next ) { - print $fh encode_json($result), $/; + my $file = $self->home->child( qw(var backup), "$filename.json.gz" ); + $file->parent->mkpath unless ( -e $file->parent ); + my $fh = IO::Zlib->new( "$file", 'wb4' ); + + my $scroll = $es->scroll_helper( + index => $index, + $self->type ? ( type => $self->type ) : (), + scroll => '1m', + body => { + _source => true, + size => $self->size, + sort => '_doc', + }, + ); + + log_info { 'Backing up ', $scroll->total, ' documents' }; + + while ( my $result = $scroll->next ) { + print $fh encode_json($result), $/; + } + close $fh; } - close $fh; log_info {'done'}; } @@ -95,58 +112,91 @@ sub run_restore { my $self = shift; return log_fatal { $self->restore, q{ doesn't exist} } - unless ( -e $self->restore ); + unless ( -e $self->restore ); log_info { 'Restoring from ', $self->restore }; my @bulk; my $es = $self->es; my $fh = IO::Zlib->new( $self->restore->stringify, 'rb' ); + my %bulk_store; + while ( my $line = $fh->readline ) { + state $line_count = 0; ++$line_count; - my $obj; + my $raw; - try { $obj = decode_json($line) } + try { $raw = decode_json($line) } catch { - log_warn {"cannot decode JSON: $line --- $_"}; + log_warn {"cannot decode JSON: $line --- $&"}; }; - my $parent = $obj->{fields}->{_parent}; - push( - @bulk, - { - id => $obj->{_id}, - $parent ? ( parent => $parent ) : (), - index => $obj->{_index}, - type => $obj->{_type}, - data => $obj->{_source}, - } + # Create our bulk_helper if we need, + # incase a backup has mixed _index or _type + # create a new bulk helper for each + my $bulk_key = $raw->{_index} . $raw->{_type}; + + $bulk_store{$bulk_key} ||= $es->bulk_helper( + index => $raw->{_index}, + type => $raw->{_type}, + max_count => $self->batch_size ); - if ( @bulk >= $self->batch_size ) { - log_info { 'line count: ' . $line_count }; - try { - $es->bulk_index( \@bulk ); - } - catch { - # try docs individually to find the problem doc(s) - log_warn {"failed to bulk index $_"}; - foreach my $document (@bulk) { - try { - $es->bulk_index( [$document] ); - } - catch { - log_warn { - "failed to index document: $_" . p $document; - }; - }; + # Fetch relevant bulk helper + my $bulk = $bulk_store{$bulk_key}; + + my $parent = $raw->{_parent}; + + if ( $raw->{_type} eq 'author' ) { + + # Hack for dodgy lat / lon's + if ( my $loc = $raw->{_source}->{location} ) { + + my $lat = $loc->[1]; + my $lon = $loc->[0]; + + if ( $lat > 90 or $lat < -90 ) { + + # Invalid latitude + delete $raw->{_source}->{location}; + } + elsif ( $lon > 180 or $lon < -180 ) { + + # Invalid longitude + delete $raw->{_source}->{location}; } - }; - @bulk = (); + } + } + + my $exists = $es->exists( + index => $raw->{_index}, + type => $raw->{_type}, + id => $raw->{_id}, + ); + + if ($exists) { + $bulk->update( { + id => $raw->{_id}, + doc => $raw->{_source}, + doc_as_upsert => true, + } ); + + } + else { + $bulk->create( { + id => $raw->{_id}, + $parent ? ( parent => $parent ) : (), + source => $raw->{_source}, + } ); } } - $es->bulk_index( \@bulk ); + + # Flush anything left over just incase + for my $bulk ( values %bulk_store ) { + $bulk->flush; + } + log_info {'done'}; } @@ -154,8 +204,8 @@ sub run_purge { my $self = shift; my $now = DateTime->now; - $self->home->subdir(qw(var backup))->recurse( - callback => sub { + $self->home->child(qw(var backup))->visit( + sub { my $file = shift; return if ( $file->is_dir ); @@ -169,12 +219,13 @@ sub run_purge { if ( $mtime->clone->truncate( to => 'week' ) != $mtime->clone->truncate( to => 'day' ) ) { - log_info {"Removing old backup $file"}; + log_info {"Removing old backup $file"}; return log_info {'Not (dry run)'} if ( $self->dry_run ); $file->remove; } - } + }, + { recurse => 1 } ); } diff --git a/lib/MetaCPAN/Script/CPANTesters.pm b/lib/MetaCPAN/Script/CPANTesters.pm index f78aee06d..ebf630ae8 100644 --- a/lib/MetaCPAN/Script/CPANTesters.pm +++ b/lib/MetaCPAN/Script/CPANTesters.pm @@ -1,202 +1,166 @@ package MetaCPAN::Script::CPANTesters; -use strict; -use warnings; - -use CPAN::DistnameInfo (); -use DBI (); -use File::Spec::Functions qw(catfile); -use File::Temp qw(tempdir); -use File::stat qw(stat); -use IO::Uncompress::Bunzip2 qw(bunzip2); -use List::AllUtils qw(any); -use LWP::UserAgent (); -use Log::Contextual qw( :log :dlog ); use Moose; -use Try::Tiny; -with 'MetaCPAN::Role::Script', 'MooseX::Getopt'; +use DBI (); +use ElasticSearchX::Model::Document::Types qw( ESBulk ); +use File::stat qw( stat ); +use IO::Uncompress::Bunzip2 qw( bunzip2 ); +use Log::Contextual qw( :log :dlog ); +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Types::TypeTiny qw( Bool Path Uri ); +use MetaCPAN::Util qw( true false ); -has _bulk_queue => ( +with 'MetaCPAN::Role::Script', 'MooseX::Getopt::Dashes'; + +has db => ( is => 'ro', - default => sub { [] }, + isa => Uri, + lazy => 1, + coerce => 1, + builder => '_build_db', ); -has url => ( +has force_refresh => ( is => 'ro', - default => 'http://devel.cpantesters.org/release/release.db.bz2' + isa => Bool, + default => 0, ); -has db_file => ( +# XXX move path to config +has mirror_file => ( is => 'ro', - lazy => 1, + isa => Path, default => sub { - $_[0]->home->file(qw(var tmp cpantesters.db)); + shift->home->child( 'var', ( $ENV{HARNESS_ACTIVE} ? 't' : () ), + 'tmp', 'cpantesters.db' ); }, + coerce => 1, ); -has dbh => ( - is => 'ro', - lazy => 1, - default => sub { - my $db = $_[0]->db_file; - log_info { 'Opening database file at ' . $db }; - return DBI->connect( 'dbi:SQLite:dbname=' . $db ); - }, +has skip_download => ( + is => 'ro', + isa => Bool, ); -has ua => ( +has _bulk => ( is => 'ro', + isa => ESBulk, lazy => 1, default => sub { - LWP::UserAgent->new; - } + $_[0]->es->bulk_helper( es_doc_path('release') ); + }, ); +# XXX fix hardcoded path +sub _build_db { + my $self = shift; + return $ENV{HARNESS_ACTIVE} + ? $self->home->child('t/var/cpantesters-release-fake.db.bz2') + : 'http://devel.cpantesters.org/release/release.db.bz2'; +} + sub run { my $self = shift; $self->index_reports; - $self->index->refresh; + $self->es->indices->refresh; } -sub update_database { - my ($self) = @_; - my $db = $self->db_file; +sub index_reports { + my $self = shift; + + my $es = $self->es; - log_info { 'Mirroring ' . $self->url }; - $self->ua->mirror( $self->url, "$db.bz2" ); + log_info { 'Mirroring ' . $self->db }; + my $db = $self->mirror_file; + + $self->ua->mirror( $self->db, "$db.bz2" ) unless $self->skip_download; if ( -e $db && stat($db)->mtime >= stat("$db.bz2")->mtime ) { - log_info {"DB hasn't been modified"}; - return; + log_info {'DB hasn\'t been modified'}; + return unless $self->force_refresh; } - bunzip2 "$db.bz2" => "$db", AutoClose => 1; - return 1; -} + bunzip2 "$db.bz2" => "$db", AutoClose => 1 if -e "$db.bz2"; -sub fetch_all_releases { - my ($self) = @_; - my $index = $self->index->name; - - my $scroll = $self->es->scrolled_search( - index => $index, - type => 'release', - query => { match_all => {} }, - size => 500, - search_type => 'scan', - scroll => '5m', + my $scroll = $es->scroll_helper( + es_doc_path('release'), + size => '500', + body => { + sort => '_doc', + }, ); my %releases; while ( my $release = $scroll->next ) { my $data = $release->{_source}; - $releases{ $self->_dist_key($data) } = $data; - } - - log_debug { 'Releases: ' . keys %releases }; - return \%releases; -} + # XXX temporary hack. This may be masking issues with release + # versions. (Olaf) + my $version = $data->{version}; + $version =~ s{\Av}{} if $version; -sub index_reports { - my $self = shift; + $releases{ + join( '-', grep {defined} $data->{distribution}, $version ) } + = $data; + } - $self->update_database - or return; + log_info { 'Opening database file at ' . $db }; - # Fetch all releases up front and put them in a hash for fast lookup. - my $releases = $self->fetch_all_releases; + my $dbh = DBI->connect( 'dbi:SQLite:dbname=' . $db ); + my $sth; + $sth = $dbh->prepare('SELECT * FROM release'); - my $sth = $self->dbh->prepare('SELECT * FROM release'); $sth->execute; + my @bulk; + while ( my $row_from_db = $sth->fetchrow_hashref ) { - my $count = 0; - my @result_fields = qw(fail pass na unknown); - while ( my $row = $sth->fetchrow_hashref ) { - $count++; + # The testers db seems to return q{} where we would expect a version of + # 0. - next - unless my $release - = $releases->{ join( '-', $row->{dist}, $row->{version} ) }; + my $version = $row_from_db->{version} || 0; - # Only include this doc in the bulk update if there has been a change. - next - unless any { $row->{$_} != ( $release->{tests}->{$_} || 0 ) } - @result_fields; + # weblint++ gets a name of 'weblint' and a version of '++-1.15' from + # the testers db. Special case it for now. Maybe try and get the db + # fixed. - $release->{tests} - = { map { $_ => $row->{$_} } @result_fields }; + $version =~ s{\+}{}g; + $version =~ s{\A-}{}; - $self->update_release($release); - } + my $release = join( '-', $row_from_db->{dist}, $version ); + my $release_doc = $releases{$release}; - $self->dequeue_bulk; - log_info {"Done. Checked $count releases."}; -} + # there's a cpantesters dist we haven't indexed + next unless ($release_doc); -sub update_release { - my ( $self, $release ) = @_; - my $queue = $self->_bulk_queue; - log_debug { 'Updating ' . $release->{name} }; - push @$queue, $release; - $self->dequeue_bulk if ( @$queue > 100 ); -} + my $insert_ok = 0; -sub dequeue_bulk { - my ($self) = @_; - my $queue = $self->_bulk_queue; - my @bulk; - my $index = $self->index->name; - while ( my $data = shift @$queue ) { - push( - @bulk, + my $tester_results = $release_doc->{tests}; + if ( !$tester_results ) { + $tester_results = {}; + $insert_ok = 1; + } + + # maybe use Data::Compare instead + for my $condition (qw(fail pass na unknown)) { + last if $insert_ok; + if ( ( $tester_results->{$condition} || 0 ) + != $row_from_db->{$condition} ) { - index => { - index => $index, - id => $data->{id}, - type => 'release', - data => $data - } + $insert_ok = 1; } - ); - } - - log_debug { 'Bulk updating ' . @bulk . ' releases' }; - - $self->es->bulk( \@bulk ); -} - -sub _dist_key { - my ( $self, $release ) = @_; - - # The CPAN Testers db uses CPAN::DistnameInfo rather than the META file - # so we get better matches this way. - try { - my $info = CPAN::DistnameInfo->new( $release->{download_url} ); - - my $v = $info->version; - -# The CPAN Testers release db has no records with a version of '0' -# but it has several with a version of ''. -# There are also plenty of '0.00'. -# I believe the code responsible is -# https://github.com/barbie/cpan-testers-data-generator/blob/master/lib/CPAN/Testers/Data/Generator.pm#L864: -# > $fields{$_} ||= '' for(@fields); -# Since '0' is false, but '0.0' is true. -# So use the same logic here, since this also DWIMs undef (which we want): - $v ||= ''; - - join '-', $info->dist, $v; + } + + next unless ($insert_ok); + my %tests = map { $_ => $row_from_db->{$_} } qw(fail pass na unknown); + $self->_bulk->update( { + doc => { tests => \%tests }, + doc_as_upsert => true, + id => $release_doc->{id}, + } ); } - catch { - my $error = $_[0]; - log_warn {$error}; - - join '-', - grep { defined($_) ? $_ : '' } $release->{distribution}, - $release->{version}; - }; + $self->_bulk->flush; + log_info {'done'}; } __PACKAGE__->meta->make_immutable; diff --git a/lib/MetaCPAN/Script/CPANTestersAPI.pm b/lib/MetaCPAN/Script/CPANTestersAPI.pm new file mode 100644 index 000000000..0c9e6ca50 --- /dev/null +++ b/lib/MetaCPAN/Script/CPANTestersAPI.pm @@ -0,0 +1,139 @@ +package MetaCPAN::Script::CPANTestersAPI; + +use strict; +use warnings; + +use Cpanel::JSON::XS qw( decode_json ); +use ElasticSearchX::Model::Document::Types qw( ESBulk ); +use Log::Contextual qw( :log :dlog ); +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Types::TypeTiny qw( Uri ); +use MetaCPAN::Util qw( true false ); +use Moose; + +with 'MetaCPAN::Role::Script', 'MooseX::Getopt::Dashes'; + +has url => ( + is => 'ro', + isa => Uri, + coerce => 1, + lazy => 1, + builder => '_build_url', +); + +sub _build_url { + my ($self) = @_; + $ENV{HARNESS_ACTIVE} + ? 'file:' + . $self->home->child('t/var/cpantesters-release-api-fake.json') + : 'http://api-3.cpantesters.org/v3/release'; +} + +has _bulk => ( + is => 'ro', + isa => ESBulk, + lazy => 1, + default => sub { + $_[0]->es->bulk_helper( + es_doc_path('release'), + max_count => 250, + timeout => '30m', + ); + }, +); + +sub run { + my $self = shift; + $self->index_reports; + $self->es->indices->refresh; +} + +sub index_reports { + my $self = shift; + + my $es = $self->es; + + log_info { 'Fetching ' . $self->url }; + + my $res; + eval { $res = $self->ua->get( $self->url ) }; + return unless $res and $res->code == 200; + + my $json = $res->decoded_content; + my $data = decode_json $json; + + my $scroll = $es->scroll_helper( + es_doc_path('release'), + size => '500', + body => { + sort => '_doc', + }, + ); + + # Create a cache of all releases (dist + version combos) + my %releases; + while ( my $release = $scroll->next ) { + my $data = $release->{_source}; + + # XXX temporary hack. This may be masking issues with release + # versions. (Olaf) + my $version = $data->{version}; + $version =~ s{\Av}{} if $version; + + $releases{ + join( '-', grep {defined} $data->{distribution}, $version ) } + = $data; + } + + for my $row (@$data) { + + # The testers db seems to return q{} where we would expect + # a version of 0. + my $version = $row->{version} || 0; + + # weblint++ gets a name of 'weblint' and a version of '++-1.15' + # from the testers db. Special case it for now. Maybe try and + # get the db fixed. + + $version =~ s{\+}{}g; + $version =~ s{\A-}{}; + + my $release = join( '-', $row->{dist}, $version ); + my $release_doc = $releases{$release}; + + # there's a cpantesters dist we haven't indexed + next unless $release_doc; + + # Check if we need to update this data + my $insert_ok = 0; + my $tester_results = $release_doc->{tests}; + if ( !$tester_results ) { + $tester_results = {}; + $insert_ok = 1; + } + + # maybe use Data::Compare instead + for my $condition (qw(fail pass na unknown)) { + last if $insert_ok; + if ( + ( $tester_results->{$condition} || 0 ) != $row->{$condition} ) + { + $insert_ok = 1; + } + } + + next unless $insert_ok; + + my %tests = map { $_ => $row->{$_} } qw(fail pass na unknown); + $self->_bulk->update( { + doc => { tests => \%tests }, + doc_as_upsert => true, + id => $release_doc->{id}, + } ); + } + + $self->_bulk->flush; + log_info {'done'}; +} + +1; diff --git a/lib/MetaCPAN/Script/CVE.pm b/lib/MetaCPAN/Script/CVE.pm new file mode 100644 index 000000000..2c22c58f0 --- /dev/null +++ b/lib/MetaCPAN/Script/CVE.pm @@ -0,0 +1,261 @@ +package MetaCPAN::Script::CVE; + +use Moose; +use namespace::autoclean; + +use Cpanel::JSON::XS qw( decode_json ); +use Log::Contextual qw( :log :dlog ); +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Types::TypeTiny qw( Bool Str Uri ); +use MetaCPAN::Util qw( hit_total numify_version true false ); +use Path::Tiny qw( path ); +use Ref::Util qw( is_arrayref ); + +with 'MetaCPAN::Role::Script', 'MooseX::Getopt'; + +has cve_url => ( + is => 'ro', + isa => Uri, + coerce => 1, + default => 'https://cpan-security.github.io/cpansa-feed/cpansa.json', +); + +has cve_dev_url => ( + is => 'ro', + isa => Uri, + coerce => 1, + default => 'https://cpan-security.github.io/cpansa-feed/cpansa_dev.json', +); + +has test => ( + is => 'ro', + isa => Bool, + default => 0, + documentation => 'Test mode (pulls smaller development data set)', +); + +has json_file => ( + is => 'ro', + isa => Str, + default => 0, + documentation => + 'Path to JSON file to be read instead of URL (for testing)', +); + +my %range_ops = qw(< lt <= lte > gt >= gte); + +my %valid_keys = map { $_ => 1 } qw< + affected_versions + cpansa_id + cves + description + distribution + references + releases + reported + severity + versions +>; + +sub run { + my $self = shift; + my $data = $self->retrieve_cve_data; + $self->index_cve_data($data); + return 1; +} + +sub index_cve_data { + my ( $self, $data ) = @_; + + my $bulk = $self->es->bulk_helper( es_doc_path('cve') ); + + log_info {'Updating the cve index'}; + + for my $dist ( sort keys %{$data} ) { + for my $cpansa ( @{ $data->{$dist} } ) { + if ( !$cpansa->{cpansa_id} ) { + log_warn { sprintf( "Dist '%s' missing cpansa_id", $dist ) }; + next; + } + + my @matches; + + if ( !is_arrayref( $cpansa->{affected_versions} ) ) { + log_debug { + sprintf( "Dist '%s' has non-array affected_versions %s", + $dist, $cpansa->{affected_versions} ) + }; + + # Temp - remove after fixed upstream + # (affected_versions will always be an array) + $cpansa->{affected_versions} + = [ $cpansa->{affected_versions} ]; + + # next; + } + + my @filters; + my @afv_filters; + + for my $afv ( @{ $cpansa->{affected_versions} } ) { + + # Temp - remove after fixed upstream + # (affected_versions will always be an array) + next unless $afv; + + my @rules = map {s/\(.*?\)//gr} split /,/, $afv; + + my @rule_filters; + + for my $rule (@rules) { + my ( $op, $num ) = $rule =~ /^([=<>]*)(.*)$/; + $num = numify_version($num); + + if ( !$op ) { + log_debug { + sprintf( + "Dist '%s' - affected_versions has no operator", + $dist ) + }; + + # Temp - remove after fixed upstream + # (affected_versions will always have an operator) + $op ||= '='; + } + + if ( exists $range_ops{$op} ) { + push @rule_filters, + +{ + range => { + version_numified => + { $range_ops{$op} => $num } + } + }; + } + else { + push @rule_filters, + +{ term => { version_numified => $num } }; + } + } + + # multiple rules (csv) in affected_version line -> AND + if ( @rule_filters == 1 ) { + push @afv_filters, @rule_filters; + } + elsif ( @rule_filters > 1 ) { + push @afv_filters, { bool => { must => \@rule_filters } }; + } + } + + # multiple elements in affected_version -> OR + if ( @afv_filters == 1 ) { + push @filters, @afv_filters; + } + elsif ( @afv_filters > 1 ) { + push @filters, { bool => { should => \@afv_filters } }; + } + + if (@filters) { + my $query = {}; + + my $releases = $self->es->search( + es_doc_path('release'), + body => { + query => { + bool => { + must => [ + { term => { distribution => $dist } }, + @filters, + ] + } + }, + _source => [ "version", "name", "author", ], + size => 2000, + }, + ); + + if ( hit_total($releases) ) { + ## no critic (ControlStructures::ProhibitMutatingListFunctions) + @matches = map { $_->[0] } + sort { $a->[1] <=> $b->[1] } + map { + [ + $_->{_source}, + numify_version( $_->{_source}{version} ) + ]; + } @{ $releases->{hits}{hits} }; + } + else { + log_debug { + sprintf( "Dist '%s' doesn't have matches.", $dist ) + }; + next; + } + } + + my $doc_data = { + distribution => $dist, + cpansa_id => $cpansa->{cpansa_id}, + affected_versions => $cpansa->{affected_versions}, + cves => $cpansa->{cves}, + description => $cpansa->{description}, + references => $cpansa->{references}, + reported => $cpansa->{reported}, + severity => $cpansa->{severity}, + versions => [ map { $_->{version} } @matches ], + releases => [ map {"$_->{author}/$_->{name}"} @matches ], + }; + + for my $k ( keys %{$doc_data} ) { + delete $doc_data->{$k} unless exists $valid_keys{$k}; + } + + $bulk->update( { + id => $cpansa->{cpansa_id}, + doc => $doc_data, + doc_as_upsert => true, + } ); + } + } + + $bulk->flush; +} + +sub retrieve_cve_data { + my $self = shift; + + return decode_json( path( $self->json_file )->slurp ) if $self->json_file; + + my $url = $self->test ? $self->cve_dev_url : $self->cve_url; + + log_info { 'Fetching data from ', $url }; + my $resp = $self->ua->get($url); + + $self->handle_error( $resp->status_line ) unless $resp->is_success; + + # clean up headers if .json.gz is served as gzip type + # rather than json encoded with gzip + if ( $resp->header('Content-Type') eq 'application/x-gzip' ) { + $resp->header( 'Content-Type' => 'application/json' ); + $resp->header( 'Content-Encoding' => 'gzip' ); + } + + return decode_json( $resp->decoded_content ); +} + +__PACKAGE__->meta->make_immutable; + +1; + +=pod + +=head1 SYNOPSIS + + # bin/metacpan cve [--test] [json_file] + +=head1 DESCRIPTION + +Retrieves the CPAN CVE data from its source and +updates our ES information. + +=cut diff --git a/lib/MetaCPAN/Script/Check.pm b/lib/MetaCPAN/Script/Check.pm index 548502002..81b115ca0 100644 --- a/lib/MetaCPAN/Script/Check.pm +++ b/lib/MetaCPAN/Script/Check.pm @@ -3,47 +3,50 @@ package MetaCPAN::Script::Check; use strict; use warnings; -use ElasticSearch; -use File::Spec::Functions qw(catfile); -use Log::Contextual qw( :log ); +use File::Spec::Functions qw( catfile ); +use Log::Contextual qw( :log ); use Moose; +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Types::TypeTiny qw( Bool Int Str ); +use MetaCPAN::Util qw( true false ); with 'MetaCPAN::Role::Script', 'MooseX::Getopt'; has modules => ( is => 'ro', - isa => 'Bool', + isa => Bool, default => 0, documentation => 'check CPAN packages against MetaCPAN', ); has module => ( is => 'ro', - isa => 'Str', + isa => Str, default => '', documentation => 'the name of the module you are checking', ); has max_errors => ( - is => 'ro', - isa => 'Int', - default => 0, + is => 'ro', + isa => Int, + default => 0, documentation => 'the maximum number of errors to encounter before stopping', ); has errors_only => ( is => 'ro', - isa => 'Bool', + isa => Bool, default => 0, documentation => 'just show errors', ); has error_count => ( - is => 'rw', - isa => 'Int', + is => 'ro', + isa => Int, default => 0, - traits => ['NoGetopt'] + traits => ['NoGetopt'], + writer => '_set_error_count', ); sub run { @@ -83,19 +86,27 @@ sub check_modules { # look up this module in ElasticSearch and see what we have on it my $results = $es->search( - index => $self->index->name, - type => 'file', - size => 100, # shouldn't get more than this - fields => [ - qw(name release author distribution version authorized indexed maturity date) - ], - query => { match_all => {} }, - filter => { - and => [ - { term => { 'module.name' => $pkg } }, - { term => { 'authorized' => 'true' } }, - { term => { 'maturity' => 'released' } }, - ], + es_doc_path('file'), + query => { + bool => { + must => [ + { term => { 'module.name' => $pkg } }, + { term => { 'authorized' => true } }, + { term => { 'maturity' => 'released' } }, + ], + }, + size => 100, # shouldn't get more than this + _source => [ qw( + name + release + author + distribution + version + authorized + indexed + maturity + date + ) ], }, ); my @files = @{ $results->{hits}->{hits} }; @@ -103,21 +114,22 @@ sub check_modules { # now find the first latest releases for these files foreach my $file (@files) { my $release_results = $es->search( - index => $self->index->name, - type => 'release', - size => 1, - fields => - [qw(name status authorized version id date)], - query => { match_all => {} }, - filter => { - and => [ - { - term => { - 'name' => $file->{fields}->{release} - } - }, - { term => { 'status' => 'latest' } }, - ], + es_doc_path('release'), + query => { + bool => { + must => [ + { + term => { + name => + $file->{_source}->{release} + } + }, + { term => { status => 'latest' } }, + ], + }, + size => 1, + _source => + [qw(name status authorized version id date)], }, ); @@ -132,21 +144,22 @@ sub check_modules { if ( !@releases ) { foreach my $file (@files) { my $release_results = $es->search( - index => $self->index->name, - type => 'release', - size => 1, - fields => - [qw(name status authorized version id date)], - query => { match_all => {} }, - filter => { - and => [ - { - term => { - 'name' => - $file->{fields}->{release} - } - } - ] + es_doc_path('release'), + query => { + bool => { + must => [ + { + term => { + name => $file->{_source} + ->{release} + } + }, + ], + }, + size => 1, + _source => [ + qw(name status authorized version id date) + ], }, ); @@ -158,10 +171,10 @@ sub check_modules { # if we found the releases tell them about it if (@releases) { if ( @releases == 1 - && $releases[0]->{fields}->{status} eq 'latest' ) + && $releases[0]->{_source}->{status} eq 'latest' ) { log_info { - "Found latest release $releases[0]->{fields}->{name} for $pkg"; + "Found latest release $releases[0]->{_source}->{name} for $pkg"; } unless $self->errors_only; } @@ -169,19 +182,19 @@ sub check_modules { log_error {"Could not find latest release for $pkg"}; foreach my $rel (@releases) { log_warn { - " Found release $rel->{fields}->{name}"; + " Found release $rel->{_source}->{name}"; }; log_warn { - " STATUS : $rel->{fields}->{status}"; + " STATUS : $rel->{_source}->{status}"; }; log_warn { - " AUTORIZED : $rel->{fields}->{authorized}"; + " AUTORIZED : $rel->{_source}->{authorized}"; }; log_warn { - " DATE : $rel->{fields}->{date}"; + " DATE : $rel->{_source}->{date}"; }; } - $self->error_count( $self->error_count + 1 ); + $self->_set_error_count( $self->error_count + 1 ); } } elsif (@files) { @@ -189,25 +202,25 @@ sub check_modules { "Module $pkg doesn't have any releases in ElasticSearch!"; }; foreach my $file (@files) { - log_warn {" Found file $file->{fields}->{name}"}; + log_warn {" Found file $file->{_source}->{name}"}; log_warn { - " RELEASE : $file->{fields}->{release}"; + " RELEASE : $file->{_source}->{release}"; }; log_warn { - " AUTHOR : $file->{fields}->{author}"; + " AUTHOR : $file->{_source}->{author}"; }; log_warn { - " AUTHORIZED : $file->{fields}->{authorized}"; + " AUTHORIZED : $file->{_source}->{authorized}"; }; - log_warn {" DATE : $file->{fields}->{date}"}; + log_warn {" DATE : $file->{_source}->{date}"}; } - $self->error_count( $self->error_count + 1 ); + $self->_set_error_count( $self->error_count + 1 ); } else { log_error { "Module $pkg [$dist] doesn't not appear in ElasticSearch!"; }; - $self->error_count( $self->error_count + 1 ); + $self->_set_error_count( $self->error_count + 1 ); } last if $self->module; } diff --git a/lib/MetaCPAN/Script/Checksum.pm b/lib/MetaCPAN/Script/Checksum.pm new file mode 100644 index 000000000..57d1b68af --- /dev/null +++ b/lib/MetaCPAN/Script/Checksum.pm @@ -0,0 +1,137 @@ +package MetaCPAN::Script::Checksum; + +use Moose; + +use Log::Contextual qw( :log ); +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Types::TypeTiny qw( Bool Int ); +use MetaCPAN::Util qw( true false ); + +use Digest::file qw( digest_file_hex ); + +with 'MooseX::Getopt', 'MetaCPAN::Role::Script'; + +=head1 SYNOPSIS + +Fill checksums for releases + +=cut + +has limit => ( + is => 'ro', + isa => Int, + default => 1000, +); + +has dry_run => ( + is => 'ro', + isa => Bool, + default => 1, +); + +sub run { + my $self = shift; + + my $bulk; + if ( !$self->dry_run ) { + $bulk = $self->es->bulk_helper( es_doc_path('release') ); + } + else { + log_warn {"--- DRY-RUN ---"}; + } + + log_info {"Searching for releases missing checksums"}; + + my $scroll = $self->es->scroll_helper( + es_doc_path('release'), + scroll => '10m', + body => { + query => { + bool => { + must_not => [ + { + exists => { + field => "checksum_md5" + } + }, + ], + }, + }, + _source => [qw( name download_url )], + }, + ); + + log_warn { "Found " . $scroll->total . " releases" }; + log_warn { "Limit is " . $self->limit }; + + my $count = 0; + + while ( my $p = $scroll->next ) { + if ( $self->limit >= 0 and $count++ >= $self->limit ) { + log_info {"Max number of changes reached."}; + last; + } + + log_info { "Adding checksums for " . $p->{_source}{name} }; + + if ( my $download_url = $p->{_source}{download_url} ) { + my $file + = $self->cpan . "/authors" . $download_url =~ s/^.*authors//r; + my $checksum_md5 = digest_file_hex( $file, 'MD5' ); + my $checksum_sha256 = digest_file_hex( $file, 'SHA-256' ); + + if ( $self->dry_run ) { + log_info { "--- MD5: " . $checksum_md5 } + log_info { "--- SHA256: " . $checksum_sha256 } + } + else { + $bulk->update( { + id => $p->{_id}, + doc => { + checksum_md5 => $checksum_md5, + checksum_sha256 => $checksum_sha256 + }, + doc_as_upsert => true, + } ); + } + } + else { + log_info { + $p->{_source}{name} . " is missing a download_url" + }; + } + } + + if ( !$self->dry_run ) { + $bulk->flush; + } + + log_info {'Finished adding checksums'}; +} + +__PACKAGE__->meta->make_immutable; +1; + +=pod + +=head1 SYNOPSIS + + # bin/metacpan checksum --[no-]dry_run --limit X + +=head1 DESCRIPTION + +Backfill checksums for releases + +=head2 dry_run + +Don't update - just show what would have been updated (default) + +=head2 no-dry_run + +Update records + +=head2 limit + +Max number of records to update. default=1000, for unlimited set to -1 + +=cut diff --git a/lib/MetaCPAN/Script/Contributor.pm b/lib/MetaCPAN/Script/Contributor.pm new file mode 100644 index 000000000..230216060 --- /dev/null +++ b/lib/MetaCPAN/Script/Contributor.pm @@ -0,0 +1,100 @@ +package MetaCPAN::Script::Contributor; + +use strict; +use warnings; + +use Moose; + +use Log::Contextual qw( :log ); + +use MetaCPAN::Types::TypeTiny qw( Bool HashRef Int Str ); + +with 'MetaCPAN::Role::Script', 'MooseX::Getopt', + 'MetaCPAN::Script::Role::Contributor'; + +has all => ( + is => 'ro', + isa => Bool, + default => 0, + documentation => 'update contributors for *all* releases', +); + +has distribution => ( + is => 'ro', + isa => Str, + documentation => + 'update contributors for all releases matching distribution name', +); + +has release => ( + is => 'ro', + isa => Str, + documentation => + 'update contributors for a single release (format: author/release_name)', +); + +has age => ( + is => 'ro', + isa => Int, + documentation => 'update contributors for a given number of days back', +); + +has author_release => ( + is => 'ro', + isa => HashRef, + lazy => 1, + builder => '_build_author_release', +); + +sub _build_author_release { + my $self = shift; + return unless $self->release; + my ( $author, $release ) = split m{/}, $self->release; + $author && $release + or die + "Error: invalid 'release' argument (format: PAUSEID/DISTRIBUTION-VERSION)"; + return +{ + author => $author, + release => $release, + }; +} + +sub run { + my $self = shift; + + my $query + = $self->all ? { match_all => {} } + : $self->distribution + ? { term => { distribution => $self->distribution } } + : $self->release ? { + bool => { + must => [ + { term => { author => $self->author_release->{author} } }, + { term => { name => $self->author_release->{release} } }, + ] + } + } + : $self->age + ? { range => { date => { gte => sprintf( 'now-%dd', $self->age ) } } } + : return; + + $self->update_contributors($query); +} + +__PACKAGE__->meta->make_immutable; +1; + +__END__ + +=head1 SYNOPSIS + + # bin/metacpan contributor --all + # bin/metacpan contributor --distribution Moose + # bin/metacpan contributor --release ETHER/Moose-2.1806 + +=head1 DESCRIPTION + +Update the list of contributors (CPAN authors only) of all/matching +releases in the 'contributor' type (index). + +=cut diff --git a/lib/MetaCPAN/Script/Cover.pm b/lib/MetaCPAN/Script/Cover.pm new file mode 100644 index 000000000..e14f51d0c --- /dev/null +++ b/lib/MetaCPAN/Script/Cover.pm @@ -0,0 +1,138 @@ +package MetaCPAN::Script::Cover; + +use Moose; +use namespace::autoclean; + +use Cpanel::JSON::XS qw( decode_json ); +use Log::Contextual qw( :log :dlog ); +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Types::TypeTiny qw( Bool Str Uri ); +use Path::Tiny qw( path ); +use MetaCPAN::Util qw( hit_total true false ); + +with 'MetaCPAN::Role::Script', 'MooseX::Getopt'; + +has cover_url => ( + is => 'ro', + isa => Uri, + coerce => 1, + default => 'http://cpancover.com/latest/cpancover.json', +); + +has cover_dev_url => ( + is => 'ro', + isa => Uri, + coerce => 1, + default => 'http://cpancover.com/latest/cpancover_dev.json', +); + +has test => ( + is => 'ro', + isa => Bool, + default => 0, + documentation => 'Test mode (pulls smaller development data set)', +); + +has json_file => ( + is => 'ro', + isa => Str, + default => 0, + documentation => + 'Path to JSON file to be read instead of URL (for testing)', +); + +my %valid_keys + = map { $_ => 1 } qw< branch condition statement subroutine total >; + +sub run { + my $self = shift; + my $data = $self->retrieve_cover_data; + $self->index_cover_data($data); + return 1; +} + +sub index_cover_data { + my ( $self, $data ) = @_; + + my $bulk = $self->es->bulk_helper( es_doc_path('cover') ); + + log_info {'Updating the cover index'}; + + for my $dist ( sort keys %{$data} ) { + for my $version ( keys %{ $data->{$dist} } ) { + my $release = $dist . '-' . $version; + my $rel_check = $self->es->search( + es_doc_path('release'), + size => 0, + body => { + query => { term => { name => $release } }, + }, + ); + if ( hit_total($rel_check) ) { + log_info { "Adding release info for '" . $release . "'" }; + } + else { + log_warn { "Release '" . $release . "' does not exist." }; + next; + } + + my %doc_data = %{ $data->{$dist}{$version}{coverage}{total} }; + + for my $k ( keys %doc_data ) { + delete $doc_data{$k} unless exists $valid_keys{$k}; + } + + $bulk->update( { + id => $release, + doc => { + distribution => $dist, + version => $version, + release => $release, + criteria => \%doc_data, + }, + doc_as_upsert => true, + } ); + } + } + + $bulk->flush; +} + +sub retrieve_cover_data { + my $self = shift; + + return decode_json( path( $self->json_file )->slurp ) if $self->json_file; + + my $url = $self->test ? $self->cover_dev_url : $self->cover_url; + + log_info { 'Fetching data from ', $url }; + my $resp = $self->ua->get($url); + + $self->handle_error( $resp->status_line ) unless $resp->is_success; + + # clean up headers if .json.gz is served as gzip type + # rather than json encoded with gzip + if ( $resp->header('Content-Type') eq 'application/x-gzip' ) { + $resp->header( 'Content-Type' => 'application/json' ); + $resp->header( 'Content-Encoding' => 'gzip' ); + } + + return decode_json( $resp->decoded_content ); +} + +__PACKAGE__->meta->make_immutable; + +1; + +=pod + +=head1 SYNOPSIS + + # bin/metacpan cover [--test] + +=head1 DESCRIPTION + +Retrieves the CPAN cover data from its source and +updates our ES information. + +=cut diff --git a/lib/MetaCPAN/Script/External.pm b/lib/MetaCPAN/Script/External.pm new file mode 100644 index 000000000..76d50ee59 --- /dev/null +++ b/lib/MetaCPAN/Script/External.pm @@ -0,0 +1,134 @@ +package MetaCPAN::Script::External; + +use Moose; +use namespace::autoclean; + +use Email::Sender::Simple (); +use Email::Simple (); +use Log::Contextual qw( :log ); +use MetaCPAN::ESConfig qw( es_doc_path ); + +use MetaCPAN::Types::TypeTiny qw( Str ); +use MetaCPAN::Util qw( true false ); + +with( + 'MetaCPAN::Role::Script', + 'MetaCPAN::Script::Role::External::Cygwin', + 'MetaCPAN::Script::Role::External::Debian', + 'MooseX::Getopt', +); + +has external_source => ( + is => 'ro', + isa => Str, + required => 1, +); + +has email_to => ( + is => 'ro', + isa => Str, + required => 1, +); + +sub run { + my $self = shift; + my $ret; + + $ret = $self->run_cygwin if $self->external_source eq 'cygwin'; + $ret = $self->run_debian if $self->external_source eq 'debian'; + + my $email_body = $ret->{errors_email_body}; + if ($email_body) { + my $email = Email::Simple->create( + header => [ + 'Content-Type' => 'text/plain; charset=utf-8', + To => $self->email_to, + From => 'noreply@metacpan.org', + Subject => 'Package mapping failures report for ' + . $self->external_source, + 'MIME-Version' => '1.0', + ], + body => $email_body, + ); + Email::Sender::Simple->send($email); + + log_debug { "Sending email to " . $self->email_to . ":" }; + log_debug {"Email body:"}; + log_debug {$email_body}; + } + + $self->update( $ret->{dist} ); +} + +sub update { + my ( $self, $dist ) = @_; + my $external_source = $self->external_source; + + my $scroll = $self->es->scroll_helper( + es_doc_path('distribution'), + scroll => '10m', + body => { + query => { + exists => { field => "external_package." . $external_source } + } + }, + ); + + my @to_remove; + + while ( my $s = $scroll->next ) { + my $name = $s->{_source}{name}; + next unless $name; + + if ( exists $dist->{$name} ) { + delete $dist->{$name} + if $dist->{$name} eq + $s->{_source}{external_package}{$external_source}; + } + else { + push @to_remove => $name; + } + } + + my $bulk = $self->es->bulk_helper( es_doc_path('distribution'), ); + + for my $d ( keys %{$dist} ) { + log_debug {"[$external_source] adding $d"}; + $bulk->update( { + id => $d, + doc => +{ + 'external_package' => { + $external_source => $dist->{$d} + } + }, + doc_as_upsert => true, + } ); + } + + for my $d (@to_remove) { + log_debug {"[$external_source] removing $d"}; + $bulk->update( { + id => $d, + doc => +{ + 'external_package' => { + $external_source => undef + } + } + } ); + } + + $bulk->flush; +} + +__PACKAGE__->meta->make_immutable; + +1; + +=pod + +=head1 SYNOPSIS + + # bin/metacpan external --external_source SOURCE + +=cut + diff --git a/lib/MetaCPAN/Script/Favorite.pm b/lib/MetaCPAN/Script/Favorite.pm new file mode 100644 index 000000000..958203e85 --- /dev/null +++ b/lib/MetaCPAN/Script/Favorite.pm @@ -0,0 +1,258 @@ +package MetaCPAN::Script::Favorite; + +use Moose; + +use Log::Contextual qw( :log ); + +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Types::TypeTiny qw( Bool Int Str ); +use MetaCPAN::Util qw( true false ); + +with 'MooseX::Getopt', 'MetaCPAN::Role::Script'; + +=head1 SYNOPSIS + +Updates the dist_fav_count field in 'file' by the count of ++ in 'favorite' + +=cut + +has queue => ( + is => 'ro', + isa => Bool, + default => 0, + documentation => 'Use the queue for updates', +); + +has check_missing => ( + is => 'ro', + isa => Bool, + default => 0, + documentation => + 'Report distributions that are missing from "file" or queue jobs if "--queue" specified', +); + +has age => ( + is => 'ro', + isa => Int, + documentation => + 'Update distributions that were voted on in the last X minutes', +); + +has limit => ( + is => 'ro', + isa => Int, + documentation => 'Limit number of results', +); + +has distribution => ( + is => 'ro', + isa => Str, + documentation => 'Update only a given distribution', +); + +has count => ( + is => 'ro', + isa => Int, + documentation => + 'Update this count to a given distribution (will only work with "--distribution"', +); + +sub run { + my $self = shift; + + if ( $self->count and !$self->distribution ) { + die + "Cannot set count in a distribution search mode, this flag only applies to a single distribution. please use together with --distribution DIST"; + } + + if ( $self->check_missing and $self->distribution ) { + die + "check_missing doesn't work in filtered mode - please remove other flags"; + } + + $self->index_favorites; + $self->es->indices->refresh; +} + +sub index_favorites { + my $self = shift; + + my $query = { match_all => {} }; + my $age_filter; + if ( $self->age ) { + $age_filter = { + range => { + date => { gte => sprintf( 'now-%dm', $self->age ) } + } + }; + } + + if ( $self->distribution ) { + $query = { term => { distribution => $self->distribution } }; + + } + elsif ( $self->age ) { + my $favs = $self->es->scroll_helper( + es_doc_path('favorite'), + scroll => '5m', + body => { + query => $age_filter, + _source => [qw< distribution >], + size => $self->limit || 500, + sort => '_doc', + } + ); + + my %recent_dists; + + while ( my $fav = $favs->next ) { + my $dist = $fav->{_source}{distribution}; + $recent_dists{$dist}++ if $dist; + } + + my @keys = keys %recent_dists; + if (@keys) { + $query = { terms => { distribution => \@keys } }; + } + } + + # get total fav counts for distributions + + my %dist_fav_count; + + if ( $self->count ) { + $dist_fav_count{ $self->distribution } = $self->count; + } + else { + my $favs = $self->es->scroll_helper( + es_doc_path('favorite'), + scroll => '30s', + body => { + query => $query, + _source => [qw< distribution >], + size => 500, + sort => '_doc', + }, + ); + + while ( my $fav = $favs->next ) { + my $dist = $fav->{_source}{distribution}; + $dist_fav_count{$dist}++ if $dist; + } + + log_debug {"Done counting favs for distributions"}; + } + + # Report missing distributions if requested + + if ( $self->check_missing ) { + my %missing; + my @age_filter; + if ( $self->age ) { + @age_filter = ( must => [$age_filter] ); + } + + my $files = $self->es->scroll_helper( + es_doc_path('file'), + scroll => '15m', + body => { + query => { + bool => { + must_not => [ + { range => { dist_fav_count => { gte => 1 } } } + ], + @age_filter, + } + }, + _source => [qw< distribution >], + size => 500, + sort => '_doc', + }, + ); + + while ( my $file = $files->next ) { + my $dist = $file->{_source}{distribution}; + next unless $dist; + next if exists $missing{$dist} or exists $dist_fav_count{$dist}; + + if ( $self->queue ) { + log_debug {"Queueing: $dist"}; + + my @count_flag; + if ( $self->count or $dist_fav_count{$dist} ) { + @count_flag = ( + '--count', $self->count || $dist_fav_count{$dist} + ); + } + + $self->_add_to_queue( index_favorite => + [ '--distribution', $dist, @count_flag ] => + { priority => 0, attempts => 10 } ); + } + else { + log_debug {"Found missing: $dist"}; + } + + $missing{$dist} = 1; + last if $self->limit and scalar( keys %missing ) >= $self->limit; + } + + my $total_missing = scalar( keys %missing ); + log_debug {"Total missing: $total_missing"} unless $self->queue; + + return; + } + + # Update fav counts for files per distributions + + for my $dist ( keys %dist_fav_count ) { + log_debug {"Dist $dist"}; + + if ( $self->queue ) { + $self->_add_to_queue( + index_favorite => [ + '--distribution', + $dist, + '--count', + ( $self->count ? $self->count : $dist_fav_count{$dist} ) + ] => { priority => 0, attempts => 10 } + ); + + } + else { + my $bulk = $self->es->bulk_helper( + es_doc_path('file'), + max_count => 250, + timeout => '120m', + ); + + my $files = $self->es->scroll_helper( + es_doc_path('file'), + scroll => '15s', + body => { + query => { term => { distribution => $dist } }, + _source => false, + size => 500, + sort => '_doc', + }, + ); + + while ( my $file = $files->next ) { + my $id = $file->{_id}; + my $cnt = $dist_fav_count{$dist}; + + log_debug {"Updating file id $id with fav_count $cnt"}; + + $bulk->update( { + id => $file->{_id}, + doc => { dist_fav_count => $cnt }, + } ); + } + + $bulk->flush; + } + } +} + +__PACKAGE__->meta->make_immutable; +1; diff --git a/lib/MetaCPAN/Script/First.pm b/lib/MetaCPAN/Script/First.pm index e380dfe2c..71b2c3a79 100644 --- a/lib/MetaCPAN/Script/First.pm +++ b/lib/MetaCPAN/Script/First.pm @@ -5,21 +5,21 @@ use warnings; use Log::Contextual qw( :log ); use Moose; +use MetaCPAN::Types::TypeTiny qw( Str ); with 'MetaCPAN::Role::Script', 'MooseX::Getopt'; has distribution => ( - is => 'rw', - isa => 'Str', + is => 'ro', + isa => Str, documentation => q{set the 'first' for only this distribution}, ); sub run { my $self = shift; - my $distributions = $self->index->type("distribution"); + my $distributions = $self->model->doc("distribution"); $distributions - = $distributions->filter( - { term => { name => $self->distribution } } ) + = $distributions->query( { term => { name => $self->distribution } } ) if $self->distribution; $distributions = $distributions->size(500)->scroll; @@ -30,11 +30,16 @@ sub run { $release ? log_debug { "@{[ $release->name ]} by @{[ $release->author ]} was first"; - } + } : log_warn { "no release found for distribution @{[$distribution->name]}"; }; } + + # Everything changed - reboot the world! + $self->cdn_purge_all; + + 1; } __PACKAGE__->meta->make_immutable; diff --git a/lib/MetaCPAN/Script/Latest.pm b/lib/MetaCPAN/Script/Latest.pm index b1edb2a54..e678806fd 100644 --- a/lib/MetaCPAN/Script/Latest.pm +++ b/lib/MetaCPAN/Script/Latest.pm @@ -5,45 +5,66 @@ use warnings; use Log::Contextual qw( :log ); use Moose; -use MooseX::Aliases; -use Parse::CPAN::Packages::Fast; -use Regexp::Common qw(time); -use Time::Local; +use CPAN::DistnameInfo (); +use DateTime::Format::ISO8601 (); +use MetaCPAN::ESConfig qw( es_doc_path ); +use MetaCPAN::Types::TypeTiny qw( Bool Str ); +use MetaCPAN::Util qw( true false ); +use Parse::CPAN::Packages::Fast (); with 'MetaCPAN::Role::Script', 'MooseX::Getopt'; has dry_run => ( is => 'ro', - isa => 'Bool', + isa => Bool, default => 0, ); has distribution => ( is => 'ro', - isa => 'Str', + isa => Str, ); has packages => ( - is => 'ro', - lazy_build => 1, - traits => ['NoGetopt'], + is => 'ro', + lazy => 1, + builder => '_build_packages', + traits => ['NoGetopt'], +); + +has force => ( + is => 'ro', + isa => Bool, + default => 0, ); sub _build_packages { return Parse::CPAN::Packages::Fast->new( - shift->cpan->file(qw(modules 02packages.details.txt.gz))->stringify ); + shift->cpan->child(qw(modules 02packages.details.txt.gz)) + ->stringify ); +} + +sub _queue_latest { + my $self = shift; + my $dist = shift || $self->distribution; + + log_info { "queueing " . $dist }; + $self->_add_to_queue( + index_latest => + [ ( $self->force ? '--force' : () ), '--distribution', $dist ], + { attempts => 3 } + ); } sub run { - my $self = shift; - my $modules = $self->index->type('file'); + my $self = shift; if ( $self->dry_run ) { log_info {'Dry run: updates will not be written to ES'}; } my $p = $self->packages; - $self->index->refresh; + $self->es->indices->refresh; # If a distribution name is passed get all the package names # from 02packages that match that distribution so we can limit @@ -60,161 +81,236 @@ sub run { return if ( !@filter && $self->distribution ); - my $scroll = $modules->filter( - { - and => [ - @filter - ? { - or => [ - map { { term => { 'file.module.name' => $_ } } } - @filter - ] - } - : (), - { exists => { field => 'file.module.name' } }, - { term => { 'file.module.indexed' => \1 } }, - { term => { 'file.maturity' => 'released' } }, - { not => { filter => { term => { status => 'backpan' } } } }, - { - not => { - filter => - { term => { 'file.distribution' => 'perl' } } - } - }, - ] + # if we are just queueing a single distribution + if ( $self->queue and $self->distribution ) { + $self->_queue_latest(); + return; + } + + my %upgrade; + my %downgrade; + my %queued_distributions; + + my $total = @filter; + my $found_total = 0; + + my @module_filters; + if (@filter) { + while (@filter) { + my @modules = splice @filter, 0, 500; + + push @module_filters, + [ + { term => { 'module.indexed' => true } }, + { terms => { "module.name" => \@modules } }, + ]; } - )->fields( - [ - 'file.module.name', 'file.author', - 'file.release', 'file.distribution', - 'file.date', 'file.status', - ] - )->size(10000)->raw->scroll('1h'); - - my ( %downgrade, %upgrade ); - log_debug { 'Found ' . $scroll->total . ' modules' }; - - my $i = 0; - - # For each file... - while ( my $file = $scroll->next ) { - $i++; - log_debug { "$i of " . $scroll->total } unless ( $i % 1000 ); - my $data = $file->{fields}; - my @modules - = ref $data->{'module.name'} - ? @{ $data->{'module.name'} } - : $data->{'module.name'}; + } + else { + push @module_filters, + [ + { term => { 'module.indexed' => true } }, + { exists => { field => "module.name" } }, + ]; + } + for my $filter (@module_filters) { + + # This query will be used to produce a (scrolled) list of + # 'file' type records where the module.name matches the + # distribution name and which are released & + # indexed (the 'leading' module) + my $query = { + bool => { + must => [ + { + nested => { + path => 'module', + query => { bool => { must => $filter } } + } + }, + { term => { 'maturity' => 'released' } }, + ], + must_not => [ + { term => { status => 'backpan' } }, + { term => { distribution => 'perl' } } + ] + } + }; + + log_debug { + 'Searching for ' . @$filter . ' of ' . $total . ' modules' + } + if @module_filters > 1; + + my $scroll = $self->es->scroll_helper( { + es_doc_path('file'), + size => 100, + body => { + query => $query, + _source => [ + qw(author date distribution download_url module.name release status) + ], + sort => '_doc', + }, + } ); + + $found_total += $scroll->total; + + log_debug { 'Found ' . $scroll->total . ' modules' }; + log_debug { 'Found ' . $found_total . 'total modules' } + if @$filter != $total and $filter == $module_filters[-1]; + + my $i = 0; + + # For each file... + while ( my $file = $scroll->next ) { + $i++; + log_debug { "$i of " . $scroll->total } unless ( $i % 100 ); + my $file_data = $file->{_source}; # Convert module name into Parse::CPAN::Packages::Fast::Package object. - @modules = grep {defined} map { - eval { $p->package($_) } - } @modules; + my @modules = grep {defined} + map { + eval { $p->package( $_->{name} ) } + } @{ $file_data->{module} }; + + $file_data->{date} + = DateTime::Format::ISO8601->parse_datetime( + $file_data->{date} ); - # For each of the packages in this file... - foreach my $module (@modules) { + # For each of the packages in this file... + foreach my $module (@modules) { # Get P:C:P:F:Distribution (CPAN::DistnameInfo) object for package. - my $dist = $module->distribution; - - # If 02packages has the same author/release for this package... - - # NOTE: CPAN::DistnameInfo doesn't parse some weird uploads - # (like /\.pm\.gz$/) so distvname might not be present. - # I assume cpanid always will be. - if ( defined( $dist->distvname ) - && $dist->distvname eq $data->{release} - && $dist->cpanid eq $data->{author} ) - { - my $upgrade = $upgrade{ $data->{distribution} }; - - # If multiple versions of a dist appear in 02packages - # only mark the most recent upload as latest. - next - if ( $upgrade - && $self->compare_dates( $upgrade->{date}, $data->{date} ) - ); - $upgrade{ $data->{distribution} } = $data; - } - elsif ( $data->{status} eq 'latest' ) { - $downgrade{ $data->{release} } = $data; + my $dist = $module->distribution; + + if ( $self->queue ) { + my $d = $dist->dist; + $self->_queue_latest($d) + unless exists $queued_distributions{$d}; + $queued_distributions{$d} = 1; + next; + } + + # If 02packages has the same author/release for this package... + + # NOTE: CPAN::DistnameInfo doesn't parse some weird uploads + # (like /\.pm\.gz$/) so distvname might not be present. + # I assume cpanid always will be. + if ( defined( $dist->distvname ) + && $dist->distvname eq $file_data->{release} + && $dist->cpanid eq $file_data->{author} ) + { + my $upgrade = $upgrade{ $file_data->{distribution} }; + + # If multiple versions of a dist appear in 02packages + # only mark the most recent upload as latest. + next + if $upgrade && $upgrade->{date} > $file_data->{date}; + $upgrade{ $file_data->{distribution} } = $file_data; + } + elsif ( $file_data->{status} eq 'latest' ) { + $downgrade{ $file_data->{release} } = $file_data; + } } } } - while ( my ( $dist, $data ) = each %upgrade ) { + my $bulk = $self->es->bulk_helper( es_doc_path('file') ); + + my %to_purge; + + while ( my ( $dist, $file_data ) = each %upgrade ) { # Don't reindex if already marked as latest. # This just means that it hasn't changed (query includes 'latest'). - next if ( $data->{status} eq 'latest' ); + next if ( !$self->force and $file_data->{status} eq 'latest' ); - $self->reindex( $data, 'latest' ); + $to_purge{ $file_data->{download_url} } = 1; + + $self->reindex( $bulk, $file_data, 'latest' ); } - while ( my ( $release, $data ) = each %downgrade ) { + while ( my ( $release, $file_data ) = each %downgrade ) { # Don't downgrade if this release version is also marked as latest. # This could happen if a module is moved to a new dist # but the old dist remains (with other packages). # This could also include bug fixes in our indexer, PAUSE, etc. next - if ( $upgrade{ $data->{distribution} } - && $upgrade{ $data->{distribution} }->{release} eq - $data->{release} ); + if ( !$self->force + && $upgrade{ $file_data->{distribution} } + && $upgrade{ $file_data->{distribution} }->{release} eq + $file_data->{release} ); + + $to_purge{ $file_data->{download_url} } = 1; - $self->reindex( $data, 'cpan' ); + $self->reindex( $bulk, $file_data, 'cpan' ); } - $self->index->refresh; + $bulk->flush; + $self->es->indices->refresh; + + # Call Fastly to purge + $self->purge_cpan_distnameinfos( [ + map CPAN::DistnameInfo->new($_), keys %to_purge ] ); } # Update the status for the release and all the files. sub reindex { - my ( $self, $source, $status ) = @_; - my $es = $self->es; + my ( $self, $bulk, $source, $status ) = @_; # Update the status on the release. - my $release = $self->index->type('release')->get( - { - author => $source->{author}, - name => $source->{release}, - } - ); + my $releases = $self->es->search( { + es_doc_path('release'), + body => { + query => { + bool => { + must => [ + { term => { author => $source->{author} } }, + { term => { name => $source->{release} } }, + ], + }, + }, + }, + _source => false, + } ); + my $release = $releases->{hits}{hits}[0]{_id}; - $release->status($status); log_info { $status eq 'latest' ? 'Upgrading ' : 'Downgrading ', - 'release ', $release->name || q[]; + 'release ', $source->{release}, "($release)"; }; - $release->put unless ( $self->dry_run ); + + if ( !$self->dry_run ) { + $self->es->update( { + es_doc_path('release'), + id => $release, + body => { + doc => { + status => $status, + }, + }, + } ); + } # Get all the files for the release. - my $scroll = $es->scrolled_search( - { - index => $self->index->name, - type => 'file', - scroll => '5m', - size => 1000, - search_type => 'scan', - query => { - filtered => { - query => { match_all => {} }, - filter => { - and => [ - { - term => - { 'file.release' => $source->{release} } - }, - { - term => { 'file.author' => $source->{author} } - } - ] - } - } - } - } + my $scroll = $self->es->scroll_helper( + es_doc_path('file'), + size => 100, + body => { + query => { + bool => { + must => [ + { term => { 'release' => $source->{release} } }, + { term => { 'author' => $source->{author} } }, + ], + }, + }, + _source => [ 'status', 'file' ], + sort => '_doc', + }, ); - my @bulk; while ( my $row = $scroll->next ) { my $source = $row->{_source}; log_trace { @@ -223,33 +319,10 @@ sub reindex { }; # Use bulk update to overwrite the status for X files at a time. - push( - @bulk, - { - index => { - index => $self->index->name, - type => 'file', - id => $row->{_id}, - data => { %$source, status => $status } - } - } - ) unless ( $self->dry_run ); - if ( @bulk > 100 ) { - $self->es->bulk( \@bulk ); - @bulk = (); - } + $bulk->update( { id => $row->{_id}, doc => { status => $status } } ) + unless $self->dry_run; } - $self->es->bulk( \@bulk ) if (@bulk); -} -sub compare_dates { - my ( $self, $d1, $d2 ) = @_; - for ( $d1, $d2 ) { - if ( $_ =~ /$RE{time}{iso}{-keep}/ ) { - $_ = timelocal( $7, $6, $5, $4, $3 - 1, $2 ); - } - } - return $d1 > $d2; } __PACKAGE__->meta->make_immutable; diff --git a/lib/MetaCPAN/Script/Mapping.pm b/lib/MetaCPAN/Script/Mapping.pm index c87935300..128c78b76 100644 --- a/lib/MetaCPAN/Script/Mapping.pm +++ b/lib/MetaCPAN/Script/Mapping.pm @@ -1,85 +1,764 @@ package MetaCPAN::Script::Mapping; -use strict; -use warnings; - -use Log::Contextual qw( :log ); use Moose; +use Cpanel::JSON::XS (); +use Log::Contextual qw( :log ); +use MetaCPAN::ESConfig qw( es_config ); +use MetaCPAN::Types::TypeTiny qw( Bool HashRef Int ); +use Time::HiRes qw( sleep time ); + +use constant { + EXPECTED => 1, + NOT_EXPECTED => 0, +}; + with 'MetaCPAN::Role::Script', 'MooseX::Getopt'; -has delete => ( +has arg_deploy_mapping => ( + init_arg => 'delete', is => 'ro', - isa => 'Bool', + isa => Bool, default => 0, documentation => 'delete index if it exists already', ); +has arg_delete_all => ( + init_arg => 'all', + is => 'ro', + isa => Bool, + default => 0, + documentation => + 'delete ALL existing indices (only effective in combination with "--delete")', +); + +has arg_verify_mapping => ( + init_arg => 'verify', + is => 'ro', + isa => Bool, + default => 0, + documentation => 'verify deployed index structure against definition', +); + +has arg_cluster_info => ( + init_arg => 'show_cluster_info', + is => 'ro', + isa => Bool, + default => 0, + documentation => 'show basic info about cluster and indices', +); + +has arg_await_timeout => ( + init_arg => 'await', + is => 'ro', + isa => Int, + default => 15, + documentation => + 'seconds before connection is considered failed with timeout', +); + +has cluster_info => ( + isa => HashRef, + traits => ['Hash'], + is => 'rw', + lazy => 1, + default => sub { {} }, +); + +has indices_info => ( + isa => HashRef, + traits => ['Hash'], + is => 'rw', + lazy => 1, + default => sub { {} }, +); + sub run { my $self = shift; - log_info {"Putting mapping to ElasticSearch server"}; - $self->model->deploy( delete => $self->delete ); + + # Wait for the ElasticSearch Engine to become ready + if ( $self->await ) { + if ( $self->arg_deploy_mapping ) { + if ( $self->arg_delete_all ) { + $self->check_health; + $self->delete_all; + } + unless ( $self->deploy_mapping ) { + $self->print_error("Indices Re-creation has failed!"); + $self->exit_code(1); + } + } + + if ( $self->arg_verify_mapping ) { + $self->check_health; + unless ( $self->indices_valid( $self->_build_index_config ) ) { + $self->print_error("Indices Verification has failed!"); + $self->exit_code(1); + } + } + + if ( $self->arg_cluster_info ) { + $self->check_health; + $self->show_info; + } + } + +# The run() method is expected to communicate Success to the superior execution level + return ( $self->exit_code == 0 ? 1 : 0 ); +} + +sub delete_all { + my $self = $_[0]; + my $runtime_environment = 'production'; + + $runtime_environment = $ENV{'PLACK_ENV'} + if ( defined $ENV{'PLACK_ENV'} ); + $runtime_environment = $ENV{'MOJO_MODE'} + if ( defined $ENV{'MOJO_MODE'} ); + + my $is_development + = $ENV{HARNESS_ACTIVE} + || $runtime_environment eq 'development' + || $runtime_environment eq 'testing'; + + if ($is_development) { + foreach my $name ( grep !/\A\./, keys %{ $self->indices_info } ) { + $self->_delete_index($name); + } + } + else { + #Set System Error: 1 - EPERM - Operation not permitted + $self->exit_code(1); + $self->print_error("Operation not permitted!"); + $self->handle_error( + "Operation not permitted in environment: $runtime_environment", + 1 ); + } +} + +sub _delete_index { + my ( $self, $name ) = @_; + + log_info {"Deleting index: $name"}; + my $idx = $self->es->indices; + $idx->delete( index => $name ); + + my $exists; + my $end = time + 2; + while ( time < $end ) { + $exists = $idx->exists( index => $name ) or last; + sleep 0.1; + } + if ($exists) { + log_error {"Failed to delete index: $name"}; + } + return $exists; +} + +sub show_info { + my $self = $_[0]; + my $info_rs = { + 'cluster_info' => \%{ $self->cluster_info }, + 'indices_info' => \%{ $self->indices_info }, + }; + log_info { Cpanel::JSON::XS->new->utf8->pretty->encode($info_rs) }; +} + +sub _build_index_config { + my $self = $_[0]; + my $docs = es_config->documents; + my $indices = {}; + my $api_version = $self->es->api_version; + for my $name ( sort keys %$docs ) { + my $doc = $docs->{$name}; + my $index = $doc->{index} + or die "no index defined for $name documents"; + die "$index specified for multiple documents" + if $indices->{$index}; + my $mapping = es_config->mapping( $name, $api_version ); + my $settings = es_config->index_settings( $name, $api_version ); + if ( $api_version le '6_0' ) { + my $type = $doc->{type} + or die "no type defined for $name documents"; + $mapping = { $type => $mapping }; + } + $indices->{$index} = { + settings => $settings, + mappings => $mapping, + }; + } + + return $indices; +} + +sub deploy_mapping { + my $self = shift; + + $self->are_you_sure( + 'this will delete EVERYTHING and re-create the (empty) indexes'); + + # Deserialize the Index Mapping Structure + my $rindices = $self->_build_index_config; + + my $es = $self->es; + + # recreate the indices and apply the mapping + + for my $idx ( sort keys %$rindices ) { + $self->_delete_index($idx) + if $es->indices->exists( index => $idx ); + + log_info {"Creating index: $idx"}; + + $es->indices->create( index => $idx, body => $rindices->{$idx} ); + } + + $self->check_health(1); + + # done + log_info {"Done."}; + + return $self->indices_valid($rindices); +} + +sub _compare_mapping { + my ( $self, $sname, $rdeploy, $rmodel ) = @_; + my $imatch = 0; + + if ( defined $rdeploy && defined $rmodel ) { + my $json_parser = Cpanel::JSON::XS->new->allow_nonref; + my ( $deploy_type, $deploy_value ); + my ( $model_type, $model_value ); + + $imatch = 1; + + if ( ref $rdeploy eq 'HASH' ) { + foreach my $sfield ( sort keys %$rdeploy ) { + if ( defined $rdeploy->{$sfield} + && defined $rmodel->{$sfield} ) + { + $deploy_type = ref( $rdeploy->{$sfield} ); + $model_type = ref( $rmodel->{$sfield} ); + $deploy_value = $rdeploy->{$sfield}; + $model_value = $rmodel->{$sfield}; + + if ( $deploy_type eq 'JSON::PP::Boolean' ) { + $deploy_type = ''; + $deploy_value + = $json_parser->encode( $rdeploy->{$sfield} ); + } + + if ( $model_type eq 'JSON::PP::Boolean' ) { + $model_type = ''; + $model_value + = $json_parser->encode( $rmodel->{$sfield} ); + } + + if ( $deploy_type ne '' ) { + if ( $deploy_type eq 'HASH' + || $deploy_type eq 'ARRAY' ) + { + $imatch = ( + $imatch && $self->_compare_mapping( + $sname . '.' . $sfield, $deploy_value, + $model_value + ) + ); + } + else { # No Hash nor Array + if ( ${$deploy_value} ne ${$model_value} ) { + log_error { + 'Mismatch field: ' + . $sname . '.' + . $sfield . ' (' + . ${$deploy_value} . ' <> ' + . ${$model_value} . ')' + }; + $imatch = 0; + } + } + } + else { # Scalar Value + if ( + $sfield eq 'type' + && $model_value eq 'string' + && ( $deploy_value eq 'text' + || $deploy_value eq 'keyword' ) + ) + { + # ES5 automatically converts string types to text + # or keyword. once we upgrade to ES5 and update + # our mappings, this special case can be removed. + } + elsif ($sfield eq 'index' + && $model_value eq 'no' + && $deploy_value eq 'false' ) + { + # another ES5 string automatic conversion + } + elsif ( $deploy_value ne $model_value ) { + log_error { + 'Mismatch field: ' + . $sname . '.' + . $sfield . ' (' + . $deploy_value . ' <> ' + . $model_value . ')' + }; + $imatch = 0; + } + } + } + else { + unless ( defined $rdeploy->{$sfield} ) { + log_error { + 'Missing field: ' . $sname . '.' . $sfield + }; + $imatch = 0; + + } + + unless ( defined $rmodel->{$sfield} ) { + if ( $sfield eq 'payloads' + && $rmodel->{type} + && $rmodel->{type} eq 'completion' + && !$rdeploy->{$sfield} ) + { + # ES5 doesn't allow payloads option. we've removed + # it from our mapping. but it gets a default + # value. ignore the default. + } + else { + log_error { + 'Missing definition: ' . $sname . '.' + . $sfield + }; + $imatch = 0; + } + } + } + } + } + elsif ( ref $rdeploy eq 'ARRAY' ) { + foreach my $iindex (@$rdeploy) { + if ( defined $rdeploy->[$iindex] + && defined $rmodel->[$iindex] ) + { + $deploy_type = ref( $rdeploy->[$iindex] ); + $model_type = ref( $rmodel->[$iindex] ); + $deploy_value = $rdeploy->[$iindex]; + $model_value = $rmodel->[$iindex]; + + if ( $deploy_type eq 'JSON::PP::Boolean' ) { + $deploy_type = ''; + $deploy_value + = $json_parser->encode( $rdeploy->[$iindex] ); + } + + if ( $model_type eq 'JSON::PP::Boolean' ) { + $model_type = ''; + $model_value + = $json_parser->encode( $rmodel->[$iindex] ); + } + + if ( $deploy_type eq '' ) { # Reference Value + if ( $deploy_type eq 'HASH' + || $deploy_type eq 'ARRAY' ) + { + $imatch = ( + $imatch && $self->_compare_mapping( + $sname . '[' . $iindex . ']', + $deploy_value, + $model_value + ) + ); + } + else { # No Hash nor Array + if ( ${$deploy_value} ne ${$model_value} ) { + log_error { + 'Mismatch field: ' + . $sname . '[' + . $iindex . '] (' + . ${$deploy_value} . ' <> ' + . ${$model_value} . ')' + }; + $imatch = 0; + } + } + } + else { # Scalar Value + if ( $deploy_value ne $model_value ) { + log_error { + 'Mismatch field: ' + . $sname . '[' + . $iindex . '] (' + . $deploy_value . ' <> ' + . $model_value . ')' + }; + $imatch = 0; + } + } + } + else { # Missing Field + unless ( defined $rdeploy->[$iindex] ) { + log_error { + 'Missing field: ' . $sname . '[' . $iindex . ']' + }; + $imatch = 0; + + } + unless ( defined $rmodel->[$iindex] ) { + log_error { + 'Missing definition: ' . $sname . '[' . $iindex + . ']' + }; + $imatch = 0; + } + } + } + } + } + else { # Missing Field + unless ( defined $rdeploy ) { + log_error { 'Missing field: ' . $sname }; + $imatch = 0; + } + unless ( defined $rmodel ) { + log_error { 'Missing definition: ' . $sname }; + $imatch = 0; + } + } + + if ( $self->{'logger'}->is_debug ) { + if ($imatch) { + log_debug {"field '$sname': ok"}; + } + else { + log_debug {"field '$sname': failed!"}; + } + } + + return $imatch; +} + +sub indices_valid { + my ( $self, $config_indices ) = @_; + my $valid = 0; + + if ( defined $config_indices && ref $config_indices eq 'HASH' ) { + my $deploy_indices = $self->es->indices->get_mapping; + $valid = 1; + + for my $idx ( sort keys %$config_indices ) { + my $config_mappings = $config_indices->{$idx} + && $config_indices->{$idx}->{'mappings'}; + my $deploy_mappings = $deploy_indices->{$idx} + && $deploy_indices->{$idx}->{'mappings'}; + if ( !$deploy_mappings ) { + log_error {"Missing index: $idx"}; + $valid = 0; + next; + } + + log_info { + "Verifying index: $idx" + }; + + if ( $self->_compare_mapping( + $idx, $deploy_mappings, $config_mappings + ) ) + { + log_info { + "Correct index: $idx (mapping deployed)" + }; + } + else { + log_error { + "Broken index: $idx (mapping does not match definition)" + }; + $valid = 0; + } + } + } + + if ($valid) { + log_info {"Verification indices: ok"}; + } + else { + log_info {"Verification indices: failed"}; + } + + return $valid; +} + +sub _get_indices_info { + my ( $self, $irefresh ) = @_; + + if ( $irefresh || scalar( keys %{ $self->indices_info } ) == 0 ) { + my $sinfo_rs = $self->es->cat->indices( h => [ 'index', 'health' ] ); + my $sindices_parsing = qr/^([^[:space:]]+) +([^[:space:]]+)/m; + + $self->indices_info( {} ); + + while ( $sinfo_rs =~ /$sindices_parsing/g ) { + $self->indices_info->{$1} + = { 'index_name' => $1, 'health' => $2 }; + } + } } -sub map_perlmongers { - my ( $self, $es ) = @_; - return $es->put_mapping( - index => ['cpan'], - type => 'perlmongers', - properties => { - city => { type => "string" }, - continent => { type => "string" }, - email => { properties => { type => { type => "string" } } }, - inception_date => - { format => "dateOptionalTime", type => "date" }, - latitude => { type => "object" }, - location => { - properties => { - city => { type => "string" }, - continent => { type => "string" }, - country => { type => "string" }, - latitude => { type => "string" }, - longitude => { type => "string" }, - region => { type => "object" }, - state => { type => "string" }, - }, - }, - longitude => { type => "object" }, - mailing_list => { - properties => { - email => { - properties => { - domain => { type => "string" }, - type => { type => "string" }, - user => { type => "string" }, - }, - }, - name => { type => "string" }, - }, - }, - name => { type => "string" }, - pm_id => { type => "string" }, - region => { type => "string" }, - state => { type => "object" }, - status => { type => "string" }, - tsar => { - properties => { - email => { - properties => { - domain => { type => "string" }, - type => { type => "string" }, - user => { type => "string" }, - }, - }, - name => { type => "string" }, - }, - }, - web => { type => "string" }, - }, - - ); +sub check_health { + my ( $self, $irefresh ) = @_; + my $ihealth = 0; + + $irefresh = 0 unless ( defined $irefresh ); + + $ihealth = $self->await; + if ($ihealth) { + $self->_get_indices_info($irefresh); + + foreach ( keys %{ $self->indices_info } ) { + $ihealth = 0 + if ( $self->indices_info->{$_}->{'health'} eq 'red' ); + } + } + + return $ihealth; +} + +sub await { + my $self = $_[0]; + my $iready = 0; + + if ( scalar( keys %{ $self->cluster_info } ) == 0 ) { + my $es = $self->es; + my $iseconds = 0; + + log_info {"Awaiting Elasticsearch ..."}; + + do { + eval { + $iready = $es->ping; + + if ($iready) { + log_info { + "Awaiting $iseconds / " + . $self->arg_await_timeout + . " : ready" + }; + + $self->cluster_info( \%{ $es->info } ); + } + }; + + if ($@) { + if ( $iseconds < $self->arg_await_timeout ) { + log_info { + "Awaiting $iseconds / " + . $self->arg_await_timeout + . " : unavailable - sleeping ..." + }; + + sleep(1); + + $iseconds++; + } + else { + log_error { + "Awaiting $iseconds / " + . $self->arg_await_timeout + . " : unavailable - timeout!" + }; + + #Set System Error: 112 - EHOSTDOWN - Host is down + $self->exit_code(112); + $self->handle_error( $@, 1 ); + } + } + } while ( !$iready && $iseconds <= $self->arg_await_timeout ); + } + else { + #ElasticSearch Service is available + $iready = 1; + } + + return $iready; } __PACKAGE__->meta->make_immutable; 1; + +__END__ + +=pod + +=head1 NAME + +MetaCPAN::Script::Mapping - Script to set the index and mapping the types + +=head1 SYNOPSIS + + # bin/metacpan mapping --show_cluster_info # show basic info about the cluster and indices + # bin/metacpan mapping --delete + # bin/metacpan mapping --delete --all # deletes ALL indices in the cluster + # bin/metacpan mapping --verify # compare deployed indices with project definitions + +=head1 DESCRIPTION + +This is the index mapping handling script. +Used rarely, but carries the most important task of setting +the index and mapping the types. + +=head1 OPTIONS + +This Script accepts the following options + +=over 4 + +=item Option C<--show_cluster_info> + +This option makes the Script show basic information about the I Cluster +and its indices. +This information has to be collected with the C Method. +On Script start-up it is empty. + + bin/metacpan mapping --show_cluster_info + +See L> + +=item Option C<--delete> + +This option makes the Script delete all indices configured in the project and re-create them emtpy. +It verifies the index integrity of the indices calling the methods +C and C. +If the C Method fails it will report an error. + + bin/metacpan mapping --delete + +B If the mapping deployment fails it exits the Script with B C< 1 >. + +See L> + +See L> + +See L> + +=item Option C<--all> + +This option is only effective in combination with Option C<--delete>. +It uses the information gathered by C to delete +B indices in the I Cluster. +This option is usefull to reconstruct a broken I Cluster + + bin/metacpan mapping --delete --all + +B It will throw an exceptions when not performed in an development or +testing environment. + +See L
}sg; is( scalar(@err), 2, 'two parse errors listed ' ); like( $err[0], qr/=head\b/, 'first error mentions =head' ); like( $err[1], qr/C</, 'first error mentions C< ... >' ); -}; +} done_testing; diff --git a/t/server/controller/rating.t b/t/server/controller/rating.t new file mode 100644 index 000000000..e59adb3c2 --- /dev/null +++ b/t/server/controller/rating.t @@ -0,0 +1,117 @@ +use strict; +use warnings; +use lib 't/lib'; + +use MetaCPAN::Server::Test qw( app GET POST test_psgi ); +use MetaCPAN::TestHelpers qw( decode_json_ok ); +use Test::More; + +test_psgi app, sub { + my $cb = shift; + + my $res; + + ok( $res = $cb->( GET '/rating/random-id' ), 'GET /rating/random-id' ); + + is $res->code, 404, 'not found'; + + ok( $res = $cb->( GET '/rating/_mapping' ), 'GET /rating/_mapping' ); + + is $res->code, 404, 'not found'; + + ok( $res = $cb->( GET '/rating/by_distributions?distribution=Moose' ), + 'GET /rating/by_distributions' ); + + is $res->code, 200, 'found'; + + my $ratings = decode_json_ok($res); + + is_deeply $ratings->{distributions}, {}, 'empty distributions'; + + ok( + $res = $cb->( + POST '/rating/_search', + Content => '{"query":{"term":{"distribution":"Moose"}}}' + ), + 'POST /rating/_search' + ); + + is $res->code, 200, 'found'; + + $ratings = decode_json_ok($res); + + is_deeply $ratings->{hits}{hits}, [], 'no hits'; + + ok( + $res = $cb->( + POST '/rating', + Content => '{"query":{"term":{"distribution":"Moose"}}}', + ), + 'POST /rating' + ); + + is $res->code, 200, 'found'; + + $ratings = decode_json_ok($res); + + is_deeply $ratings->{hits}{hits}, [], 'no hits'; + + ok( + $res = $cb->( + POST '/rating/_search?scroll=5m', + Content => '{"query":{"term":{"distribution":"Moose"}}}', + ), + 'POST /rating' + ); + + is $res->code, 200, 'found'; + + $ratings = decode_json_ok($res); + + is_deeply $ratings->{hits}{hits}, [], 'no hits'; + + is_deeply $ratings->{_scroll_id}, 'FAKE_SCROLL_ID', + 'gives fake scroll id'; + + ok( + $res + = $cb->( POST "/_search/scroll/$ratings->{_scroll_id}?scroll=5m", + ), + 'POST /_search/scroll/$id', + ); + + is $res->code, 200, 'found' + or diag $res->as_string; + + $ratings = decode_json_ok($res); + + is_deeply $ratings->{hits}{hits}, [], 'working with no hits'; + is $ratings->{_shards}{total}, 0, 'results are fake'; + + ok( + $res = $cb->( + POST '/rating/_search', + 'User-Agent' => 'MetaCPAN::Client/2.031001', + Content => '{"query":{"term":{"distribution":"Moose"}}}', + ), + 'POST /rating with MetaCPAN::Client test UA' + ); + + is $res->code, 200, 'found'; + + $ratings = decode_json_ok($res); + + is_deeply $ratings->{hits}{hits}, + [ + { + _source => { + distribution => 'Moose', + }, + }, + ], + 'no hits'; + +}; + +done_testing; + diff --git a/t/server/controller/release.t b/t/server/controller/release.t new file mode 100644 index 000000000..340382e46 --- /dev/null +++ b/t/server/controller/release.t @@ -0,0 +1,109 @@ +use strict; +use warnings; +use lib 't/lib'; + +use MetaCPAN::Server::Test qw( app GET test_psgi ); +use MetaCPAN::TestHelpers qw( decode_json_ok test_cache_headers ); +use Test::More; + +{ + no warnings 'redefine'; + + sub get_ok { + my ( $cb, $url, $desc, $headers ) = @_; + ok( my $res = $cb->( GET $url ), $desc || "GET $url" ); + is( $res->code, 200, 'code 200' ); + + test_cache_headers( $res, $headers ); + + return $res; + } +} + +sub get_json_ok { + return decode_json_ok( get_ok(@_) ); +} + +test_psgi app, sub { + my $cb = shift; + + # find (/release/DIST) + get_json_ok( + $cb, + '/release/Moose', + 'GET /release/dist', + { + # ??? + cache_control => 'private', + surrogate_key => + 'content_type=application/json content_type=application', + surrogate_control => undef, + } + ); + + # get (/release/AUTHOR/NAME) + get_json_ok( + $cb, + '/release/DOY/Moose-0.01', + 'GET /release/DOY/Moose-0.01', + { + # ??? + } + ); + + # versions (/release/versions/DIST) + my $versions = get_json_ok( + $cb, + '/release/versions/Moose', + 'GET /release/versions/Moose', + { + # ??? + } + ); + is( @{ $versions->{releases} }, 2, "Got 2 Moose versions (all)" ); + + # versions - specific (/release/versions/DIST?versions=VERSION) + my $versions_specific = get_json_ok( + $cb, + '/release/versions/Moose?versions=0.01', + 'GET /release/versions/Moose?versions=0.01', + { + # ??? + } + ); + is( @{ $versions_specific->{releases} }, + 1, "Got 1 Moose version (specificly requested)" ); + + # versions - latest (/release/versions/DIST?versions=latest) + my $versions_latest = get_json_ok( + $cb, + '/release/versions/Moose?versions=latest', + 'GET /release/versions/Moose?versions=latest', + { + # ??? + } + ); + is( @{ $versions_latest->{releases} }, + 1, "Got 1 Moose version (only latest requested)" ); + is( $versions_latest->{releases}[0]{status}, + 'latest', "Release status is latest" ); + + # versions - plain (/release/versions/DIST?plain=1) + ok( my $versions_plain = $cb->( GET '/release/versions/Moose?plain=1' ), + 'GET /release/versions/Moose?plain=1' ); + is( $versions_plain->code, 200, 'code 200' ); + ok( $versions_plain->content =~ /\A .+ \t .+ \n .+ \t .+ \z/xsm, + 'Content is plain text result' ); + + # latest_by_distribution (/release/latest_by_distribution/DIST) + get_json_ok( + $cb, + '/release/latest_by_distribution/Moose', + 'GET /release/latest_by_distribution/Moose', + { + # ??? + } + ); +}; + +done_testing; diff --git a/t/server/controller/root.t b/t/server/controller/root.t new file mode 100644 index 000000000..5039474a5 --- /dev/null +++ b/t/server/controller/root.t @@ -0,0 +1,19 @@ +use strict; +use warnings; +use lib 't/lib'; + +use MetaCPAN::Server::Test qw( app GET test_psgi ); +use Test::More; + +test_psgi app, sub { + my $cb = shift; + ok( my $res = $cb->( GET '/' ), "GET /" ); + is( $res->code, 302, 'got redirect' ); + is( + $res->header('Location'), + 'https://github.com/metacpan/metacpan-api/blob/master/docs/API-docs.md', + 'correct redirect target' + ); +}; + +done_testing; diff --git a/t/server/controller/scroll.t b/t/server/controller/scroll.t index 020b7304c..e9ba29ce1 100644 --- a/t/server/controller/scroll.t +++ b/t/server/controller/scroll.t @@ -1,9 +1,9 @@ use strict; use warnings; - use lib 't/lib'; -use MetaCPAN::Server::Test; -use MetaCPAN::TestHelpers; + +use MetaCPAN::Server::Test qw( app GET POST test_psgi ); +use MetaCPAN::TestHelpers qw( decode_json_ok test_cache_headers ); use Test::More; test_psgi app, sub { @@ -60,6 +60,16 @@ sub req_json { is( $res->code, $code, "HTTP $code" ) or diag Test::More::explain($res); + test_cache_headers( + $res, + { + cache_control => 'private', + surrogate_key => + 'content_type=application/json content_type=application', + surrogate_control => undef, + } + ); + my $json = decode_json_ok($res); return $json; } diff --git a/t/server/controller/search/autocomplete.t b/t/server/controller/search/autocomplete.t index 208353a4d..760cd7405 100644 --- a/t/server/controller/search/autocomplete.t +++ b/t/server/controller/search/autocomplete.t @@ -1,9 +1,9 @@ use strict; use warnings; - use lib 't/lib'; -use MetaCPAN::Server::Test; -use MetaCPAN::TestHelpers; + +use MetaCPAN::Server::Test qw( app GET test_psgi ); +use MetaCPAN::TestHelpers qw( decode_json_ok ); use Test::More; test_psgi app, sub { @@ -18,18 +18,45 @@ test_psgi app, sub { my $got = [ map { $_->{fields}{documentation} } @{ $json->{hits}{hits} } ]; - is_deeply $got, [ - qw( - Multiple::Modules - Multiple::Modules::A - Multiple::Modules::B - Multiple::Modules::RDeps - Multiple::Modules::Tester - Multiple::Modules::RDeps::A - Multiple::Modules::RDeps::Deprecated - ) - ], - 'results are sorted by module name length' + is_deeply $got, [ qw( + Multiple::Modules + Multiple::Modules::A + Multiple::Modules::B + Multiple::Modules::RDeps + Multiple::Modules::Tester + Multiple::Modules::RDeps::A + Multiple::Modules::RDeps::Deprecated + ) ], + 'results are sorted lexically by module name + length' + or diag( Test::More::explain($got) ); + } +}; + +test_psgi app, sub { + my $cb = shift; + + # test ES script using doc['blah'] value + { + ok( + my $res + = $cb->( + GET '/search/autocomplete/suggest?q=Multiple::Modu' ), + 'GET' + ); + my $json = decode_json_ok($res); + + my $got = [ map $_->{name}, @{ $json->{suggestions} } ]; + + is_deeply $got, [ qw( + Multiple::Modules + Multiple::Modules::A + Multiple::Modules::B + Multiple::Modules::RDeps + Multiple::Modules::Tester + Multiple::Modules::RDeps::A + Multiple::Modules::RDeps::Deprecated + ) ], + 'results are sorted lexically by module name + length' or diag( Test::More::explain($got) ); } }; diff --git a/t/server/controller/search/reverse_dependencies.t b/t/server/controller/search/reverse_dependencies.t deleted file mode 100644 index 5fee46f2f..000000000 --- a/t/server/controller/search/reverse_dependencies.t +++ /dev/null @@ -1,133 +0,0 @@ -use strict; -use warnings; - -use lib 't/lib'; -use MetaCPAN::Server::Test; -use MetaCPAN::TestHelpers; -use Test::More; - -my %tests = ( - '/search/reverse_dependencies/NonExistent' => [ 404, [], [] ], - '/search/reverse_dependencies/Pod-Pm' => [ 200, [], [] ], - - # just dist name - '/search/reverse_dependencies/Multiple-Modules' => [ - 200, - [qw( Multiple-Modules-RDeps-0.11 )], - [qw( Multiple-Modules-RDeps-2.03 Multiple-Modules-RDeps-A-2.03 )], - ], - - # author/name-version - '/search/reverse_dependencies/LOCAL/Multiple-Modules-1.01' => [ - 200, - [qw( Multiple-Modules-RDeps-0.11 )], - [qw( Multiple-Modules-RDeps-2.03 Multiple-Modules-RDeps-A-2.03 )], - ], - - # older author/name-version with different modules - '/search/reverse_dependencies/LOCAL/Multiple-Modules-0.1' => [ - 200, - [qw( Multiple-Modules-RDeps-0.11 )], - [ - qw( Multiple-Modules-RDeps-2.03 Multiple-Modules-RDeps-Deprecated-0.01 ) - ], - ], -); - -sub check_search_results { - my ( $name, $res, $code, $rdeps ) = @_; - ok( $res, $name ); - is( - $res->header('content-type'), - 'application/json; charset=utf-8', - 'Content-type' - ); - is( $res->code, $code, "code $code" ) - or return; - my $json = decode_json_ok($res); - return unless $code == 200; - - $json = $json->{hits}{hits} if $json->{hits}; - is scalar @$json, @$rdeps, 'got expected number of releases'; - is_deeply [ - sort map { join q[-], @{ $_->{_source} }{qw(distribution version)} } - @$json - ], - $rdeps, - 'got expected releases'; -} - -test_psgi app, sub { - my $cb = shift; - - # verify search results - while ( my ( $k, $v ) = each %tests ) { - my ( $code, $rdep_old, $rdep_latest ) = @$v; - - # all results - check_search_results( - "GET $k" => $cb->( GET $k ), - $code, [ sort( @$rdep_old, @$rdep_latest ) ] - ); - - # only releases marked as latest - check_search_results( - "POST $k" => $cb->( - POST $k, - Content => encode_json( - { - query => { match_all => {} }, - filter => - { term => { 'release.status' => 'latest' }, }, - } - ) - ), - $code, - [ sort(@$rdep_latest) ] - ); - } - - # test passing additional ES parameters - { - ok( - my $res = $cb->( - POST '/search/reverse_dependencies/Multiple-Modules', - Content => encode_json( - { query => { match_all => {} }, size => 1 } - ) - ), - 'POST' - ); - my $json = decode_json_ok($res); - is( $json->{hits}->{total}, 3, 'total is 3' ); - is( scalar @{ $json->{hits}->{hits} }, 1, 'only 1 received' ); - } - - # test appending filters - { - ok( - my $res = $cb->( - POST - '/search/reverse_dependencies/Multiple-Modules?fields=release.distribution', - Content => encode_json( - { - query => { match_all => {} }, - filter => { - term => { - 'release.distribution' => - 'Multiple-Modules-RDeps-A' - }, - }, - } - ) - ), - 'POST' - ); - my $json = decode_json_ok($res); - is( $json->{hits}->{total}, 1, 'total is 1' ); - is( $json->{hits}->{hits}->[0]->{fields}->{distribution}, - 'Multiple-Modules-RDeps-A', 'filter worked' ); - } -}; - -done_testing; diff --git a/t/server/controller/source.t b/t/server/controller/source.t index 02bbaceba..97d5f8cd1 100644 --- a/t/server/controller/source.t +++ b/t/server/controller/source.t @@ -1,39 +1,85 @@ use strict; use warnings; +use lib 't/lib'; -use MetaCPAN::Server::Test; +use Cpanel::JSON::XS (); +use MetaCPAN::Server::Test qw( app GET test_psgi ); +use MetaCPAN::TestHelpers qw( test_cache_headers ); use Test::More; my %tests = ( - '/source/DOESNEXIST' => 404, - '/source/DOY/Moose-0.01/' => 200, - '/source/DOY/Moose-0.01/MANIFEST' => 200, - '/source/DOY/Moose-0.01/MANIFEST?callback=foo' => 200, - '/source/DOY/Moose-0.01/Changes' => 200, - '/source/DOY/Moose-0.01/Changes?callback=foo' => 200, - '/source/Moose' => 200, + '/source/DOESNEXIST' => { + code => 404, + cache_control => 'private', + surrogate_key => + 'content_type=application/json content_type=application', + surrogate_control => undef + }, + '/source/DOY/Moose-0.01/' => { + code => 200, + cache_control => undef, + surrogate_key => + 'author=DOY content_type=text/html content_type=text', + surrogate_control => + 'max-age=31556952, stale-while-revalidate=86400, stale-if-error=2592000' + }, + '/source/DOY/Moose-0.01/Changes' => { + code => 200, + cache_control => undef, + surrogate_key => + 'author=DOY content_type=text/plain content_type=text', + surrogate_control => + 'max-age=31556952, stale-while-revalidate=86400, stale-if-error=2592000', + }, + '/source/DOY/Moose-0.01/Changes?callback=foo' => { + code => 200, + cache_control => undef, + surrogate_key => + 'author=DOY content_type=text/javascript content_type=text', + surrogate_control => + 'max-age=31556952, stale-while-revalidate=86400, stale-if-error=2592000', + }, + '/source/DOY/Moose-0.01/MANIFEST' => { + code => 200, + cache_control => undef, + surrogate_key => + 'author=DOY content_type=text/plain content_type=text', + surrogate_control => + 'max-age=31556952, stale-while-revalidate=86400, stale-if-error=2592000', + }, + '/source/DOY/Moose-0.01/MANIFEST?callback=foo' => { + code => 200, + cache_control => undef, + surrogate_key => + 'author=DOY content_type=text/javascript content_type=text', + surrogate_control => + 'max-age=31556952, stale-while-revalidate=86400, stale-if-error=2592000', + }, + '/source/Moose' => { + code => 200, + cache_control => 'private', + surrogate_key => + 'author=DOY content_type=text/plain content_type=text', + surrogate_control => undef + }, ); test_psgi app, sub { my $cb = shift; while ( my ( $k, $v ) = each %tests ) { - ok( my $res = $cb->( GET $k), "GET $k" ); - is( $res->code, $v, "code $v" ); + ok( my $res = $cb->( GET $k ), "GET $k" ); + is( $res->code, $v->{code}, "code " . $v->{code} ); + + test_cache_headers( $res, $v ); + if ( $k eq '/source/Moose' ) { like( $res->content, qr/package Moose/, 'Moose source' ); - is( - $res->header('content-type'), - 'text/plain; charset=UTF-8', - 'Content-type' - ); + is( $res->header('content-type'), 'text/plain', 'Content-type' ); # Used for fastly on st.aticpan.org is( $res->header('X-Content-Type'), 'text/x-script.perl-module', 'X-Content-Type' ); - is( $res->header('Surrogate-Control'), - 'max-age=86400', 'Surrogate-Control' ); - } elsif ( $k =~ /MANIFEST/ ) { @@ -46,7 +92,7 @@ test_psgi app, sub { t/00-nop.t META.json META.yml - ) + ) ); if ( $k =~ /callback=foo/ ) { ok( @@ -55,8 +101,8 @@ test_psgi app, sub { 'JSONP wrapper' ); ok( - my $jsdata - = JSON->new->allow_nonref->decode($function_args), + my $jsdata = Cpanel::JSON::XS->new->allow_nonref->decode( + $function_args), 'decode json' ); is( $jsdata, $manifest, 'JSONP-wrapped manifest' ); @@ -68,19 +114,12 @@ test_psgi app, sub { } else { is( $res->content, $manifest, 'Plain text manifest' ); - is( - $res->header('content-type'), - 'text/plain; charset=UTF-8', - 'Content-type' - ); + is( $res->header('content-type'), + 'text/plain', 'Content-type' ); } } elsif ( $k eq '/source/DOY/Moose-0.01/Changes' ) { - is( - $res->header('content-type'), - 'text/plain; charset=UTF-8', - 'Content-type' - ); + is( $res->header('content-type'), 'text/plain', 'Content-type' ); like( $res->decoded_content, qr/codename 'M\x{fc}nchen'/, @@ -108,7 +147,7 @@ test_psgi app, sub { 'JSONP-wrapped change-log' ); } - elsif ( $v eq 200 ) { + elsif ( $v->{code} eq 200 ) { like( $res->content, qr/Index of/, 'Index of' ); is( $res->header('content-type'), diff --git a/t/server/controller/url_parameters.pm b/t/server/controller/url_parameters.pm new file mode 100644 index 000000000..58639a356 --- /dev/null +++ b/t/server/controller/url_parameters.pm @@ -0,0 +1,63 @@ +use strict; +use warnings; + +use Cpanel::JSON::XS (); +use HTTP::Request::Common qw( GET ); +use MetaCPAN::Server (); +use MetaCPAN::TestHelpers qw( test_cache_headers ); +use Plack::Test (); +use Ref::Util qw( is_arrayref is_hashref ); +use Test::More; + +my $app = MetaCPAN::Server->new->to_app(); +my $test = Plack::Test->create($app); + +subtest "parem 'source'" => sub { + my $source = Cpanel::JSON::XS::encode_json { + query => { + term => { distribution => "Moose" } + }, + aggs => { + count => { + terms => { field => "distribution" } + } + }, + size => 0, + }; + + # test different types, as the parameter is generic to all + for ( [ release => 2 ], [ file => 27 ] ) { + my ( $type, $count ) = @$_; + + my $url = "/$type/_search?source=$source"; + + subtest "check with '$type' controller" => sub { + my $res = $test->request( GET $url ); + ok( $res, "GET $url" ); + is( $res->code, 200, "code 200" ); + test_cache_headers( + $res, + { + cache_control => 'private', + surrogate_key => + 'content_type=application/json content_type=application', + surrogate_control => undef, + + } + ); + is( + $res->header('content-type'), + 'application/json; charset=utf-8', + 'Content-type' + ); + my $content = Cpanel::JSON::XS::decode_json $res->content; + ok( is_hashref($content), 'content is a JSON object' ); + my $buckets = $content->{aggregations}{count}{buckets}; + ok( is_arrayref($buckets), 'we have aggregation buckets' ); + is( @{$buckets}, 1, 'one key (Moose)' ); + is( $buckets->[0]{doc_count}, $count, "record count is $count" ); + }; + } +}; + +done_testing; diff --git a/t/server/controller/user/favorite.t b/t/server/controller/user/favorite.t index 5c8226ae5..6aebeccad 100644 --- a/t/server/controller/user/favorite.t +++ b/t/server/controller/user/favorite.t @@ -1,9 +1,9 @@ use strict; use warnings; - use lib 't/lib'; -use MetaCPAN::Server::Test; -use MetaCPAN::TestHelpers; + +use MetaCPAN::Server::Test qw( app DELETE GET POST test_psgi ); +use MetaCPAN::TestHelpers qw( decode_json_ok encode_json ); use Test::More; test_psgi app, sub { @@ -13,16 +13,33 @@ test_psgi app, sub { is( $user->code, 200, 'code 200' ); $user = decode_json_ok($user); + is_deeply( + $user->{identity}, + [ { + 'key' => 'MO', + 'name' => 'pause' + } ], + 'got correct identity' + ); + + is_deeply( + $user->{access_token}, + [ { + 'client' => 'testing', + 'token' => 'testing' + } ], + 'got correct access_token' + ); + ok( my $res = $cb->( POST '/user/favorite?access_token=testing', - Content => encode_json( - { - distribution => 'Moose', - release => 'Moose-1.10', - author => 'DOY' - } - ) + Content_Type => 'application/json', + Content => encode_json( { + distribution => 'Moose', + release => 'Moose-1.10', + author => 'DOY' + } ) ), 'POST favorite' ); @@ -30,6 +47,7 @@ test_psgi app, sub { ok( my $location = $res->header('location'), 'location header set' ); ok( $res = $cb->( GET $location ), "GET $location" ); is( $res->code, 200, 'found' ); + my $json = decode_json_ok($res); is( $json->{user}, $user->{id}, 'user is ' . $user->{id} ); ok( $res = $cb->( DELETE '/user/favorite/Moose?access_token=testing' ), @@ -41,24 +59,6 @@ test_psgi app, sub { ok( $user = $cb->( GET '/user?access_token=bot' ), 'get bot' ); is( $user->code, 200, 'code 200' ); - $user = decode_json_ok($user); - ok( !$user->{looks_human}, 'user looks like a bot' ); - ok( - $res = $cb->( - POST '/user/favorite?access_token=bot', - Content => encode_json( - { - distribution => 'Moose', - release => 'Moose-1.10', - author => 'DOY' - } - ) - ), - 'POST favorite' - ); - decode_json_ok($res); - is( $res->code, 403, 'forbidden' ); - }; done_testing; diff --git a/t/server/controller/user/turing.t b/t/server/controller/user/turing.t deleted file mode 100644 index c74821ab4..000000000 --- a/t/server/controller/user/turing.t +++ /dev/null @@ -1,59 +0,0 @@ -package ## no critic (Package) - Captcha::Mock; - -use strict; -use warnings; - -sub check_answer { - return { is_valid => $_[4], error => 'error' }; -} - -sub new { - bless {}, shift; -} - -package main; - -use strict; -use warnings; - -use lib 't/lib'; -use MetaCPAN::Server::Test; -use MetaCPAN::TestHelpers; -use Test::More; - -test_psgi app, sub { - my $cb = shift; - ok( - my $res = $cb->( - POST '/user/turing?access_token=bot', - Content => encode_json( - { - challenge => 'foo', - answer => 0 - } - ) - ), - 'post challenge' - ); - is( $res->code, 400, 'bad request' ); - - ok( - $res = $cb->( - POST '/user/turing?access_token=bot', - Content => encode_json( - { - challenge => 'foo', - answer => 1, - } - ) - ), - 'post challenge' - ); - is( $res->code, 200, 'successful request' ); - my $user = decode_json_ok($res); - ok( $user->{looks_human}, 'looks human' ); - ok( $user->{passed_captcha}, 'passed captcha' ); -}; - -done_testing; diff --git a/t/server/model/file.t b/t/server/model/file.t deleted file mode 100644 index cdf9c1c3c..000000000 --- a/t/server/model/file.t +++ /dev/null @@ -1,55 +0,0 @@ -use strict; -use warnings; - -use MetaCPAN::Server (); -use Test::More; - -my $c = 'MetaCPAN::Server'; - -foreach my $test ( - [ - LOCAL => 'Multiple-Modules-0.1', - [qw( Multiple::Modules Multiple::Modules::Deprecated )], - [] - ], - [ - LOCAL => 'Multiple-Modules-1.01', - [ - qw( Multiple::Modules Multiple::Modules::A Multiple::Modules::A2 Multiple::Modules::B ) - ], - [qw( Multiple::Modules::B::Secret )] - ], - [ - LOCAL => 'Multiple-Modules-RDeps-2.03', - [qw( Multiple::Modules::RDeps )], - [] - ], - [ - LOCAL => 'Multiple-Modules-RDeps-A-2.03', - [qw( Multiple::Modules::RDeps::A )], - [] - ], - ) -{ - my ( $author, $release, $indexed, $extra ) = @$test; - my $find = { author => $author, name => $release }; - is_deeply [ - sort - map { $_->{name} } - map { @{ $_->{_source}->{module} } } @{ - $c->model('CPAN::File')->raw->find_provided_by($find) - ->{hits}{hits} - } - ], - [ sort( @$indexed, @$extra ) ], - 'got all included modules'; - - is_deeply [ - sort $c->model('CPAN::File') - ->raw->find_module_names_provided_by($find) - ], - [ sort @$indexed ], - 'got only the module names expected'; -} - -done_testing; diff --git a/t/server/not_found.t b/t/server/not_found.t index 7eebb1c58..ee2666d28 100644 --- a/t/server/not_found.t +++ b/t/server/not_found.t @@ -1,20 +1,20 @@ use strict; use warnings; - use lib 't/lib'; -use MetaCPAN::Server::Test; -use MetaCPAN::TestHelpers; + +use MetaCPAN::Server::Test qw( app GET test_psgi ); +use MetaCPAN::TestHelpers qw( decode_json_ok ); use Test::More; my @tests = ( - [ '/release/File-Changes' => 200 ], - [ '/release/No-Dist-Here' => 404 ], - [ '/changes/LOCAL/File-Changes-2.0' => 200 ], [ '/changes/LOCAL/File-Changes-2' => 404 ], + [ '/changes/LOCAL/File-Changes-2.0' => 200 ], + [ '/fakedoctype/andaction' => 404 ], [ '/file/LOCAL/File-Changes-2.0/Changes' => 200 ], [ '/file/LOCAL/File-Changes-2.0/NoChanges' => 404 ], + [ '/release/File-Changes' => 200 ], + [ '/release/No-Dist-Here' => 404 ], [ '/root.file' => 404 ], - [ '/fakedoctype/andaction' => 404 ], ); test_psgi app, sub { @@ -22,7 +22,7 @@ test_psgi app, sub { for my $test (@tests) { my ( $path, $code ) = @{$test}; - ok( my $res = $cb->( GET $path), "GET $path" ); + ok( my $res = $cb->( GET $path ), "GET $path" ); is( $res->code, $code, "code $code" ); # 404 should still be json diff --git a/t/server/sanitize_query.t b/t/server/sanitize_query.t index 3ee0130fb..d843eeb33 100644 --- a/t/server/sanitize_query.t +++ b/t/server/sanitize_query.t @@ -1,12 +1,11 @@ use strict; use warnings; - use lib 't/lib'; -use MetaCPAN::Server::Test; -use MetaCPAN::TestHelpers; -use Test::More; -use URI; +use MetaCPAN::Server::Test qw( app GET POST test_psgi ); +use MetaCPAN::TestHelpers qw( catch decode_json_ok encode_json try ); +use Test::More skip_all => 'Scripting is disabled'; +use URI (); sub uri { my $uri = URI->new(shift); @@ -48,32 +47,6 @@ test_psgi app, sub { } ); } - - local - $MetaCPAN::Server::QuerySanitizer::metacpan_scripts{test_script_field} - = q{doc['author.pauseid'].value.length() * 2}; - - test_all_methods( - { - query => { match_all => {} }, - script_fields => - { pauselen2 => { metacpan_script => 'test_script_field' }, }, - filter => { term => { pauseid => 'RWSTAUNER' } }, - }, - sub { - my ($req) = shift; - - my $res = $cb->($req); - is $res->code, 200, $req->method . ' 200 OK' - or diag explain $res; - - my $json = decode_json_ok($res); - - is_deeply $json->{hits}{hits}->[0]->{fields}, - { pauselen2 => 18 }, 'script_fields via metacpan_script' - or diag explain $json; - }, - ); }; sub test_all_methods { @@ -113,49 +86,6 @@ sub test_bad_request { }; } -my %replacements = ( - prefer_shorter_module_names_100 => - qr#\Q_score - doc['documentation'].value.length()/100\E#, - - prefer_shorter_module_names_400 => - qr#\Qif(documentation == empty)\E.+\Q.length()/400\E#s, - - score_version_numified => qr#\Qdoc['module.version_numified'].value\E#, - - status_is_latest => qr#\Qdoc['status'].value == 'latest'\E#, - - stupid_script_that_doesnt_exist => undef, -); - -while ( my ( $mscript, $re ) = each %replacements ) { - my $query = filtered_custom_score_hash( metacpan_script => $mscript ); - - my $sanitizer = MetaCPAN::Server::QuerySanitizer->new( query => $query, ); - - my $cleaned = $sanitizer->query; - like_if_defined - delete $cleaned->{query}{filtered}{query}{custom_score}{script}, - $re, "$mscript script replaced"; - - is_deeply $cleaned, filtered_custom_score_hash(), - 'metacpan_script removed'; - - # try another hash structure - $query - = { - foo => { bar => [ { metacpan_script => $mscript, other => 'val' } ] } - }; - - $cleaned - = MetaCPAN::Server::QuerySanitizer->new( query => $query )->query; - - like_if_defined - delete $cleaned->{foo}{bar}->[0]->{script}, - $re, "$mscript script replaced"; - is_deeply $cleaned, { foo => { bar => [ { other => 'val' } ] } }, - 'any hash structure accepts metacpan_script'; -} - hash_key_rejected( script => { script => 'foobar' } ); hash_key_rejected( script => { tree => { of => 'many', hashes => { script => 'foobar' } } } @@ -169,8 +99,7 @@ hash_key_rejected( { my $hash = filtered_custom_score_hash( hi => 'there' ); - is_deeply - delete $hash->{query}{filtered}{query}, + is_deeply delete $hash->{query}{filtered}{query}, { custom_score => { query => { foo => 'bar' }, hi => 'there' } }, 'remove custom_score hash'; diff --git a/t/test-vars.t b/t/test-vars.t new file mode 100644 index 000000000..1787f26c4 --- /dev/null +++ b/t/test-vars.t @@ -0,0 +1,10 @@ +use strict; +use warnings; +use lib 't/lib'; + +use Test::More; +use Test::Vars import => [qw( vars_ok )]; + +vars_ok('MetaCPAN::Server'); + +done_testing(); diff --git a/t/testrules.yml b/t/testrules.yml new file mode 100644 index 000000000..f5e59287f --- /dev/null +++ b/t/testrules.yml @@ -0,0 +1,9 @@ +--- +seq: + - seq: t/0*.t + + # ensure t/script/cover.t runs before t/server/controller/cover.t + - seq: t/script/cover.t + + - par: + - t/**.t diff --git a/t/tidyall.t b/t/tidyall.t deleted file mode 100644 index c7ad552e6..000000000 --- a/t/tidyall.t +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env perl - -use strict; -use warnings; - -use Test::Code::TidyAll; -tidyall_ok(); diff --git a/t/types.t b/t/types.t index 589f9ca06..3f8ce75a5 100644 --- a/t/types.t +++ b/t/types.t @@ -1,25 +1,24 @@ -use Test::Most; use strict; use warnings; -use MetaCPAN::Types qw(:all); + +use MetaCPAN::Types::TypeTiny qw( Resources ); +use Test::More; is_deeply( - Resources->coerce( - { - license => ['http://dev.perl.org/licenses/'], - homepage => 'http://sourceforge.net/projects/module-build', - bugtracker => { - web => 'http://github.com/dagolden/cpan-meta-spec/issues', - mailto => 'meta-bugs@example.com', - }, - repository => { - url => 'git://github.com/dagolden/cpan-meta-spec.git', - web => 'http://github.com/dagolden/cpan-meta-spec', - type => 'git', - }, - x_twitter => 'http://twitter.com/cpan_linked/', - } - ), + Resources->coerce( { + license => ['http://dev.perl.org/licenses/'], + homepage => 'http://sourceforge.net/projects/module-build', + bugtracker => { + web => 'http://github.com/dagolden/cpan-meta-spec/issues', + mailto => 'meta-bugs@example.com', + }, + repository => { + url => 'git://github.com/dagolden/cpan-meta-spec.git', + web => 'http://github.com/dagolden/cpan-meta-spec', + type => 'git', + }, + x_twitter => 'http://twitter.com/cpan_linked/', + } ), { license => ['http://dev.perl.org/licenses/'], homepage => 'http://sourceforge.net/projects/module-build', @@ -37,34 +36,28 @@ is_deeply( ); ok( - Resources->check( - Resources->coerce( - { - license => ['http://dev.perl.org/licenses/'], - homepage => 'http://sourceforge.net/projects/module-build', - bugtracker => { - web => 'http://github.com/dagolden/cpan-meta-spec/issues', - mailto => 'meta-bugs@example.com', - }, - repository => { - url => 'git://github.com/dagolden/cpan-meta-spec.git', - web => 'http://github.com/dagolden/cpan-meta-spec', - type => 'git', - }, - x_twitter => 'http://twitter.com/cpan_linked/', - } - ) - ), + Resources->check( Resources->coerce( { + license => ['http://dev.perl.org/licenses/'], + homepage => 'http://sourceforge.net/projects/module-build', + bugtracker => { + web => 'http://github.com/dagolden/cpan-meta-spec/issues', + mailto => 'meta-bugs@example.com', + }, + repository => { + url => 'git://github.com/dagolden/cpan-meta-spec.git', + web => 'http://github.com/dagolden/cpan-meta-spec', + type => 'git', + }, + x_twitter => 'http://twitter.com/cpan_linked/', + } ) ), 'check CPAN::Meta::Spec example' ); is_deeply( - Resources->coerce( - { - license => ['http://dev.perl.org/licenses/'], - homepage => 'http://sourceforge.net/projects/module-build', - } - ), + Resources->coerce( { + license => ['http://dev.perl.org/licenses/'], + homepage => 'http://sourceforge.net/projects/module-build', + } ), { homepage => 'http://sourceforge.net/projects/module-build', license => ['http://dev.perl.org/licenses/'], @@ -73,32 +66,26 @@ is_deeply( ); ok( - Resources->check( - { - license => ['http://dev.perl.org/licenses/'], - homepage => 'http://sourceforge.net/projects/module-build', - } - ), + Resources->check( { + license => ['http://dev.perl.org/licenses/'], + homepage => 'http://sourceforge.net/projects/module-build', + } ), 'check sparse resources' ); ok( - Resources->check( - { - bugtracker => { - web => - 'https://github.com/AlexBio/Dist-Zilla-Plugin-GitHub/issues' - }, - homepage => - 'http://search.cpan.org/dist/Dist-Zilla-Plugin-GitHub/', - repository => { - type => 'git', - url => - 'git://github.com/AlexBio/Dist-Zilla-Plugin-GitHub.git', - web => 'https://github.com/AlexBio/Dist-Zilla-Plugin-GitHub' - } + Resources->check( { + bugtracker => { + web => + 'https://github.com/AlexBio/Dist-Zilla-Plugin-GitHub/issues' + }, + homepage => 'http://search.cpan.org/dist/Dist-Zilla-Plugin-GitHub/', + repository => { + type => 'git', + url => 'git://github.com/AlexBio/Dist-Zilla-Plugin-GitHub.git', + web => 'https://github.com/AlexBio/Dist-Zilla-Plugin-GitHub' } - ), + } ), 'sparse' ); diff --git a/t/util.t b/t/util.t index 2c508e5ac..e53d06014 100644 --- a/t/util.t +++ b/t/util.t @@ -1,41 +1,83 @@ -use Test::Most; use strict; use warnings; -use MetaCPAN::Util; -use CPAN::Meta; - -is( MetaCPAN::Util::numify_version(1), 1.000 ); -is( MetaCPAN::Util::numify_version('010'), 10.000 ); -is( MetaCPAN::Util::numify_version('v2.1.1'), 2.001001 ); -is( MetaCPAN::Util::numify_version(undef), 0.000 ); -is( MetaCPAN::Util::numify_version('LATEST'), 0.000 ); -is( MetaCPAN::Util::numify_version('0.20_8'), 0.208 ); -is( MetaCPAN::Util::numify_version('0.20_88'), 0.2088 ); -is( MetaCPAN::Util::numify_version('0.208_8'), 0.2088 ); -is( MetaCPAN::Util::numify_version('0.20_108'), 0.20108 ); -is( MetaCPAN::Util::numify_version('v0.9_9'), 0.099 ); - -lives_ok { is( version('2a'), 2 ) }; -lives_ok { is( version('V0.01'), 'v0.01' ) }; -lives_ok { is( version('0.99_1'), '0.99_1' ) }; -lives_ok { is( version('0.99.01'), 'v0.99.01' ) }; - -is( MetaCPAN::Util::strip_pod('hello L foo'), - 'hello link foo' ); -is( MetaCPAN::Util::strip_pod('hello L foo'), - 'hello section in Module foo' ); -is( MetaCPAN::Util::strip_pod('for L'), 'for Dist::Zilla' ); -is( MetaCPAN::Util::strip_pod('without a leading C<$>.'), - 'without a leading $.' ); +use lib 't/lib'; + +use CPAN::Meta (); +use MetaCPAN::Util qw( + extract_section + generate_sid + numify_version + strip_pod +); + +use Test::Fatal qw( exception ); +use Test::More; + +ok( generate_sid(), 'generate_sid' ); + +{ + my %versions = ( + '010' => 10, + '0.20_8' => 0.208, + '0.208_8' => 0.2088, + '0.20_88' => 0.2088, + 1 => 1, + LATEST => 0, + undef => 0, + 'v0.9_9' => 0.099, + 'v2.1.1' => 2.001001, + 'v2.0.0' => 2.0, + ); + + foreach my $before ( sort keys %versions ) { + is( numify_version($before), $versions{$before}, + "$before => $versions{$before}" ); + } +} + +{ + my %versions = ( + '2a' => 2, + 'V0.01' => 'v0.01', + '0.99_1' => '0.99_1', + '0.99.01' => 'v0.99.01', + 'v1.2' => 'v1.2', + ); + foreach my $before ( sort keys %versions ) { + is exception { + is( version($before), $versions{$before}, + "$before => $versions{$before}" ) + }, undef, "$before => $versions{$before} does not die"; + } +} + +is( + strip_pod('hello L foo'), + 'hello link foo', + 'strip_pod strips http links' +); +is( + strip_pod('hello L foo'), + 'hello section in Module foo', + 'strip_pod strips internal links' +); +is( + strip_pod('for L'), + 'for Dist::Zilla', + 'strip_pod strips module links' +); +is( + strip_pod('without a leading C<$>.'), + 'without a leading $.', + 'strip_pod strips C<>' +); sub version { - CPAN::Meta->new( - { - name => 'foo', - license => 'unknown', - version => MetaCPAN::Util::fix_version(shift) - } - )->version; + CPAN::Meta->new( { + name => 'foo', + license => 'unknown', + version => MetaCPAN::Util::fix_version(shift) + } )->version; } # extract_section tests @@ -52,12 +94,12 @@ Some data about a named pipe EOF - my $section = MetaCPAN::Util::extract_section( $content, 'NAME' ); + my $section = extract_section( $content, 'NAME' ); is( $section, 'Some::Thing - Test', 'NAME matched correct head1 section' ); } -# https://github.com/CPAN-API/cpan-api/issues/167 +# https://github.com/metacpan/metacpan-api/issues/167 { my $content = < 'Binary-Data', - abstract => 'Binary after __DATA__ token', - version => '0.01', - - # Specify provides so that both modules are included - # in release 'provides' list and the release will get marked as latest. - provides => { - 'Binary::Data' => { - file => 'lib/Binary/Data.pm', - version => '0.01' - }, - 'Binary::Data::WithPod' => { - file => 'lib/Binary/Data/WithPod.pm', - version => '0.02' - } - }, - - X_Module_Faker => { - cpan_author => 'BORISNAT', - append => [ { - file => 'lib/Binary/Data.pm', - content => < 'lib/Binary/Data/WithPod.pm', - 'content' => < 'Binary-Data', + abstract => 'Binary after __DATA__ token', + version => '0.01', + + # Specify provides so that both modules are included + # in release 'provides' list and the release will get marked as latest. + provides => { + 'Binary::Data' => { + file => 'lib/Binary/Data.pm', + version => '0.01' + }, + 'Binary::Data::WithPod' => { + file => 'lib/Binary/Data/WithPod.pm', + version => '0.02' + } + }, + + X_Module_Faker => { + cpan_author => 'BORISNAT', + append => [ + { + file => 'lib/Binary/Data.pm', + content => < 'lib/Binary/Data/WithPod.pm', + 'content' => < "Encoding", +{ + "name" => "Encoding", "abstract" => "Beyond 7bit ascii", "version" => "1.0", "X_Module_Faker" => { "cpan_author" => "RWSTAUNER", "omitted_files" => [ "META.json", "META.yml" ], "append" => [ - { "file" => "lib/Encoding/CP1252.pm", + { + "file" => "lib/Encoding/CP1252.pm", "content" => "package Encoding::CP1252;\n\nsub bullet { qq<\x{95}> }\n", }, diff --git a/t/var/fakecpan/configs/encoding-1.1.pl b/test-data/fakecpan/configs/encoding-1.1.pl similarity index 74% rename from t/var/fakecpan/configs/encoding-1.1.pl rename to test-data/fakecpan/configs/encoding-1.1.pl index c92b3ebe3..aa16f0818 100644 --- a/t/var/fakecpan/configs/encoding-1.1.pl +++ b/test-data/fakecpan/configs/encoding-1.1.pl @@ -1,15 +1,18 @@ -{ "name" => "Encoding", +{ + "name" => "Encoding", "abstract" => "Beyond 7bit ascii", "version" => "1.1", "X_Module_Faker" => { "cpan_author" => "RWSTAUNER", "omitted_files" => [ "META.json", "META.yml" ], "append" => [ - { "file" => "lib/Encoding/UTF8.pm", + { + "file" => "lib/Encoding/UTF8.pm", "content" => "package Encoding::UTF8;\n\nuse utf8;\nmy \$heart = qq<\342\235\244>;\n", }, - { "file" => "lib/Encoding/CP1252.pm", + { + "file" => "lib/Encoding/CP1252.pm", "content" => "package Encoding::CP1252;\n\nsub bullet { qq<\x95-\xf7> }\n", }, diff --git a/t/var/fakecpan/configs/encoding-1.2.pl b/test-data/fakecpan/configs/encoding-1.2.pl similarity index 78% rename from t/var/fakecpan/configs/encoding-1.2.pl rename to test-data/fakecpan/configs/encoding-1.2.pl index 21bd017ed..a16f2fb97 100644 --- a/t/var/fakecpan/configs/encoding-1.2.pl +++ b/test-data/fakecpan/configs/encoding-1.2.pl @@ -1,11 +1,13 @@ -{ "name" => "Encoding", +{ + "name" => "Encoding", "abstract" => "Beyond 7bit ascii", "version" => "1.2", "X_Module_Faker" => { "cpan_author" => "RWSTAUNER", "omitted_files" => [ "META.json", "META.yml" ], "append" => [ - { "file" => "lib/Encoding/UTF8.pm", + { + "file" => "lib/Encoding/UTF8.pm", "content" => "package Encoding::UTF8;\n\nuse utf8;\nmy \$heart = qq<\342\231\245>;\n", }, diff --git a/t/var/fakecpan/configs/file-changes-1.json b/test-data/fakecpan/configs/file-changes-1.json similarity index 100% rename from t/var/fakecpan/configs/file-changes-1.json rename to test-data/fakecpan/configs/file-changes-1.json diff --git a/t/var/fakecpan/configs/file-changes-2.json b/test-data/fakecpan/configs/file-changes-2.json similarity index 100% rename from t/var/fakecpan/configs/file-changes-2.json rename to test-data/fakecpan/configs/file-changes-2.json diff --git a/t/var/fakecpan/configs/file-changes-latin1.json b/test-data/fakecpan/configs/file-changes-latin1.json similarity index 100% rename from t/var/fakecpan/configs/file-changes-latin1.json rename to test-data/fakecpan/configs/file-changes-latin1.json diff --git a/t/var/fakecpan/configs/file-changes-news.json b/test-data/fakecpan/configs/file-changes-news.json similarity index 100% rename from t/var/fakecpan/configs/file-changes-news.json rename to test-data/fakecpan/configs/file-changes-news.json diff --git a/t/var/fakecpan/configs/file-changes-utf8.json b/test-data/fakecpan/configs/file-changes-utf8.json similarity index 100% rename from t/var/fakecpan/configs/file-changes-utf8.json rename to test-data/fakecpan/configs/file-changes-utf8.json diff --git a/t/var/fakecpan/configs/file-duplicates.pl b/test-data/fakecpan/configs/file-duplicates.pl similarity index 86% rename from t/var/fakecpan/configs/file-duplicates.pl rename to test-data/fakecpan/configs/file-duplicates.pl index 72de45acb..e5c1654f1 100644 --- a/t/var/fakecpan/configs/file-duplicates.pl +++ b/test-data/fakecpan/configs/file-duplicates.pl @@ -31,8 +31,8 @@ }; my $meta = { - name => 'File-Duplicates', - author => 'BORISNAT', + name => 'File-Duplicates', + author => 'BORISNAT', abstract => 'A dist with duplicate file names in different directories', version => '1.000', @@ -48,10 +48,10 @@ 'url' => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec' }, - # Pass some packages so that Module::Faker will add them to 02packages - # and this dist will get 'status' => 'latest' - # but omit the Dupe packages since the paths are explicitly not correct - # and we don't want Module::Faker to generate the missing ones for us. + # Pass some packages so that Module::Faker will add them to 02packages + # and this dist will get 'status' => 'latest' + # but omit the Dupe packages since the paths are explicitly not correct + # and we don't want Module::Faker to generate the missing ones for us. provides => { map { ( $_ => $provides->{$_} ) } grep {/File/} keys %$provides }, @@ -62,7 +62,7 @@ cpan_author => $meta->{author}, append => [ { - file => 'META.json', + file => 'META.json', content => JSON::encode_json( { %$meta, provides => $provides } ), }, @@ -87,7 +87,7 @@ content => 'short path but no_index', }, { - file => 'lib/Dupe.pm', + file => 'lib/Dupe.pm', content => 'shortest indexed path though metadata is probably wrong', }, diff --git a/t/var/fakecpan/configs/ipsonar-0.29.yml b/test-data/fakecpan/configs/ipsonar-0.29.yml similarity index 100% rename from t/var/fakecpan/configs/ipsonar-0.29.yml rename to test-data/fakecpan/configs/ipsonar-0.29.yml diff --git a/t/var/fakecpan/configs/local-lib.json b/test-data/fakecpan/configs/local-lib.json similarity index 100% rename from t/var/fakecpan/configs/local-lib.json rename to test-data/fakecpan/configs/local-lib.json diff --git a/t/var/fakecpan/configs/meta-license-dual.json b/test-data/fakecpan/configs/meta-license-dual.json similarity index 100% rename from t/var/fakecpan/configs/meta-license-dual.json rename to test-data/fakecpan/configs/meta-license-dual.json diff --git a/t/var/fakecpan/configs/meta-license-single.json b/test-data/fakecpan/configs/meta-license-single.json similarity index 100% rename from t/var/fakecpan/configs/meta-license-single.json rename to test-data/fakecpan/configs/meta-license-single.json diff --git a/t/var/fakecpan/configs/meta-provides-1.01.json b/test-data/fakecpan/configs/meta-provides-1.01.json similarity index 100% rename from t/var/fakecpan/configs/meta-provides-1.01.json rename to test-data/fakecpan/configs/meta-provides-1.01.json diff --git a/t/var/fakecpan/configs/metafile-both.json b/test-data/fakecpan/configs/metafile-both.json similarity index 100% rename from t/var/fakecpan/configs/metafile-both.json rename to test-data/fakecpan/configs/metafile-both.json diff --git a/t/var/fakecpan/configs/metafile-json.json b/test-data/fakecpan/configs/metafile-json.json similarity index 58% rename from t/var/fakecpan/configs/metafile-json.json rename to test-data/fakecpan/configs/metafile-json.json index 610800f85..5e63c6fa3 100644 --- a/t/var/fakecpan/configs/metafile-json.json +++ b/test-data/fakecpan/configs/metafile-json.json @@ -11,7 +11,7 @@ }, { "file": "META.json", - "content": "{\"resources\":{\"bugtracker\":{\"web\":\"https://github.com/CPAN-API/cpan-api/issues/"}},\"meta-spec\":{\"version\":2,\"url\":\"http://search.cpan.org/perldoc?CPAN::Meta::Spec\"},\"generated_by\":\"hand\",\"version\":1.1,\"name\":\"MetaFile-JSON\",\"dynamic_config\":0,\"author\":\"LOCAL\",\"license\":\"unknown\",\"abstract\":\"A dist with META.yml and META.json\",\"release_status\":\"stable\",\"x_meta_file\":\"json\"}" + "content": "{\"resources\":{\"bugtracker\":{\"web\":\"https://github.com/metacpan/metacpan-api/issues/"}},\"meta-spec\":{\"version\":2,\"url\":\"http://search.cpan.org/perldoc?CPAN::Meta::Spec\"},\"generated_by\":\"hand\",\"version\":1.1,\"name\":\"MetaFile-JSON\",\"dynamic_config\":0,\"author\":\"LOCAL\",\"license\":\"unknown\",\"abstract\":\"A dist with META.yml and META.json\",\"release_status\":\"stable\",\"x_meta_file\":\"json\"}" }, { "file": "t/foo.t", diff --git a/t/var/fakecpan/configs/metafile-yaml.json b/test-data/fakecpan/configs/metafile-yaml.json similarity index 100% rename from t/var/fakecpan/configs/metafile-yaml.json rename to test-data/fakecpan/configs/metafile-yaml.json diff --git a/t/var/fakecpan/configs/moose-recent.json b/test-data/fakecpan/configs/moose-recent.json similarity index 100% rename from t/var/fakecpan/configs/moose-recent.json rename to test-data/fakecpan/configs/moose-recent.json diff --git a/t/var/fakecpan/configs/moose.json b/test-data/fakecpan/configs/moose.json similarity index 100% rename from t/var/fakecpan/configs/moose.json rename to test-data/fakecpan/configs/moose.json diff --git a/t/var/fakecpan/configs/multiple-modules-0.1.json b/test-data/fakecpan/configs/multiple-modules-0.1.json similarity index 100% rename from t/var/fakecpan/configs/multiple-modules-0.1.json rename to test-data/fakecpan/configs/multiple-modules-0.1.json diff --git a/t/var/fakecpan/configs/multiple-modules-1.01.json b/test-data/fakecpan/configs/multiple-modules-1.01.json similarity index 100% rename from t/var/fakecpan/configs/multiple-modules-1.01.json rename to test-data/fakecpan/configs/multiple-modules-1.01.json diff --git a/t/var/fakecpan/configs/multiple-modules-rdeps-0.11.json b/test-data/fakecpan/configs/multiple-modules-rdeps-0.11.json similarity index 100% rename from t/var/fakecpan/configs/multiple-modules-rdeps-0.11.json rename to test-data/fakecpan/configs/multiple-modules-rdeps-0.11.json diff --git a/t/var/fakecpan/configs/multiple-modules-rdeps-2.03.json b/test-data/fakecpan/configs/multiple-modules-rdeps-2.03.json similarity index 100% rename from t/var/fakecpan/configs/multiple-modules-rdeps-2.03.json rename to test-data/fakecpan/configs/multiple-modules-rdeps-2.03.json diff --git a/t/var/fakecpan/configs/multiple-modules-rdeps-a.json b/test-data/fakecpan/configs/multiple-modules-rdeps-a.json similarity index 100% rename from t/var/fakecpan/configs/multiple-modules-rdeps-a.json rename to test-data/fakecpan/configs/multiple-modules-rdeps-a.json diff --git a/t/var/fakecpan/configs/multiple-modules-rdeps-deprecated.json b/test-data/fakecpan/configs/multiple-modules-rdeps-deprecated.json similarity index 100% rename from t/var/fakecpan/configs/multiple-modules-rdeps-deprecated.json rename to test-data/fakecpan/configs/multiple-modules-rdeps-deprecated.json diff --git a/t/var/fakecpan/configs/multiple-modules-tester.json b/test-data/fakecpan/configs/multiple-modules-tester.json similarity index 100% rename from t/var/fakecpan/configs/multiple-modules-tester.json rename to test-data/fakecpan/configs/multiple-modules-tester.json diff --git a/t/var/fakecpan/configs/no-modules.yml b/test-data/fakecpan/configs/no-modules.yml similarity index 100% rename from t/var/fakecpan/configs/no-modules.yml rename to test-data/fakecpan/configs/no-modules.yml diff --git a/t/var/fakecpan/configs/no-packages.yml b/test-data/fakecpan/configs/no-packages.yml similarity index 100% rename from t/var/fakecpan/configs/no-packages.yml rename to test-data/fakecpan/configs/no-packages.yml diff --git a/t/var/fakecpan/configs/oops-locallib.json b/test-data/fakecpan/configs/oops-locallib.json similarity index 100% rename from t/var/fakecpan/configs/oops-locallib.json rename to test-data/fakecpan/configs/oops-locallib.json diff --git a/t/var/fakecpan/configs/p-1.0.20.yml b/test-data/fakecpan/configs/p-1.0.20.yml similarity index 76% rename from t/var/fakecpan/configs/p-1.0.20.yml rename to test-data/fakecpan/configs/p-1.0.20.yml index 1b9720ae5..ed8e94a32 100644 --- a/t/var/fakecpan/configs/p-1.0.20.yml +++ b/test-data/fakecpan/configs/p-1.0.20.yml @@ -2,7 +2,7 @@ name: P version: 'v1.0.20' X_Module_Faker: - # Live test case (https://github.com/CPAN-API/metacpan-web/issues/1046): + # Live test case (https://github.com/metacpan/metacpan-web/issues/1046): # The archive basename doesn't have the 'v' in the version # but the META file does. archive_basename: 'P-1.0.20' diff --git a/t/var/fakecpan/configs/packages-unclaimable.json b/test-data/fakecpan/configs/packages-unclaimable.json similarity index 100% rename from t/var/fakecpan/configs/packages-unclaimable.json rename to test-data/fakecpan/configs/packages-unclaimable.json diff --git a/t/var/fakecpan/configs/packages.json b/test-data/fakecpan/configs/packages.json similarity index 100% rename from t/var/fakecpan/configs/packages.json rename to test-data/fakecpan/configs/packages.json diff --git a/t/var/fakecpan/configs/perl-1.json b/test-data/fakecpan/configs/perl-1.json similarity index 100% rename from t/var/fakecpan/configs/perl-1.json rename to test-data/fakecpan/configs/perl-1.json diff --git a/t/var/fakecpan/configs/pod-examples.json b/test-data/fakecpan/configs/pod-examples.json similarity index 100% rename from t/var/fakecpan/configs/pod-examples.json rename to test-data/fakecpan/configs/pod-examples.json diff --git a/t/var/fakecpan/configs/pod-pm.json b/test-data/fakecpan/configs/pod-pm.json similarity index 100% rename from t/var/fakecpan/configs/pod-pm.json rename to test-data/fakecpan/configs/pod-pm.json diff --git a/t/var/fakecpan/configs/pod-with-data-token.json b/test-data/fakecpan/configs/pod-with-data-token.json similarity index 100% rename from t/var/fakecpan/configs/pod-with-data-token.json rename to test-data/fakecpan/configs/pod-with-data-token.json diff --git a/t/var/fakecpan/configs/pod-with-generator.json b/test-data/fakecpan/configs/pod-with-generator.json similarity index 100% rename from t/var/fakecpan/configs/pod-with-generator.json rename to test-data/fakecpan/configs/pod-with-generator.json diff --git a/t/var/fakecpan/configs/prefer-meta-json.json b/test-data/fakecpan/configs/prefer-meta-json.json similarity index 100% rename from t/var/fakecpan/configs/prefer-meta-json.json rename to test-data/fakecpan/configs/prefer-meta-json.json diff --git a/t/var/fakecpan/configs/prereqs.json b/test-data/fakecpan/configs/prereqs.json similarity index 100% rename from t/var/fakecpan/configs/prereqs.json rename to test-data/fakecpan/configs/prereqs.json diff --git a/t/var/fakecpan/configs/scripts.json b/test-data/fakecpan/configs/scripts.json similarity index 100% rename from t/var/fakecpan/configs/scripts.json rename to test-data/fakecpan/configs/scripts.json diff --git a/t/var/fakecpan/configs/some-trial.json b/test-data/fakecpan/configs/some-trial.json similarity index 100% rename from t/var/fakecpan/configs/some-trial.json rename to test-data/fakecpan/configs/some-trial.json diff --git a/t/var/fakecpan/configs/text-tabs+wrap-2013.0523.yml b/test-data/fakecpan/configs/text-tabs+wrap-2013.0523.yml similarity index 100% rename from t/var/fakecpan/configs/text-tabs+wrap-2013.0523.yml rename to test-data/fakecpan/configs/text-tabs+wrap-2013.0523.yml diff --git a/t/var/fakecpan/configs/uncommon-sense.json b/test-data/fakecpan/configs/uncommon-sense.json similarity index 100% rename from t/var/fakecpan/configs/uncommon-sense.json rename to test-data/fakecpan/configs/uncommon-sense.json diff --git a/t/var/fakecpan/configs/versions.json b/test-data/fakecpan/configs/versions.json similarity index 100% rename from t/var/fakecpan/configs/versions.json rename to test-data/fakecpan/configs/versions.json diff --git a/t/var/fakecpan/configs/weblint++-1.15.yml b/test-data/fakecpan/configs/weblint++-1.15.yml similarity index 100% rename from t/var/fakecpan/configs/weblint++-1.15.yml rename to test-data/fakecpan/configs/weblint++-1.15.yml diff --git a/t/var/fakecpan/configs/www-tumblr-0.yml b/test-data/fakecpan/configs/www-tumblr-0.yml similarity index 100% rename from t/var/fakecpan/configs/www-tumblr-0.yml rename to test-data/fakecpan/configs/www-tumblr-0.yml diff --git a/test-data/fakecpan/mirrors.json b/test-data/fakecpan/mirrors.json new file mode 100644 index 000000000..c25fef6c2 --- /dev/null +++ b/test-data/fakecpan/mirrors.json @@ -0,0 +1,7482 @@ +[ + { + "name" : "23media.de", + "org" : "23Media GmbH", + "city" : "Frankfurt", + "region" : "Hessen", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "+50.129995", + "longitude" : "+8.598073", + "tz" : "+1", + "pipesize" : 4000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "23media.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.23media.de/cpan/", + "ftp" : "ftp://mirror.23media.de/cpan/", + "rsync" : null, + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-07-06", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "acc.umu.se", + "org" : "Academic Computer Club Umeå University", + "city" : "Umeå", + "region" : "Västerbotten", + "country" : "Sweden", + "continent" : "Europe", + "latitude" : "+63.8200", + "longitude" : "+20.3000", + "tz" : "+1", + "pipesize" : 6000, + "contact" : [ + { + "contact_user" : "ftp-adm", + "contact_site" : "acc.umu.se" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.acc.umu.se/mirror/CPAN/", + "ftp" : "ftp://ftp.acc.umu.se/mirror/CPAN/", + "rsync" : "rsync://ftp.acc.umu.se/mirror/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2013-05-07", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "se", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "agh.edu.pl", + "org" : "AGH University of Science and Technology", + "city" : "Kraków", + "region" : null, + "country" : "Poland", + "continent" : "Europe", + "latitude" : "+50.065700", + "longitude" : "+19.922900", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "ftp", + "contact_site" : "agh.edu.pl" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.agh.edu.pl/CPAN/", + "ftp" : "ftp://ftp.agh.edu.pl/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2015-01-09", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "pl", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "aha.ru", + "org" : "Zenon N.S.P.", + "city" : "Moscow", + "region" : null, + "country" : "Russian Federation", + "continent" : "Europe", + "latitude" : "55.782", + "longitude" : "37.584", + "tz" : "+3", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "tech", + "contact_site" : "zenon.net" + } + ], + "src" : "rsync.nic.funet.fi", + "http" : null, + "ftp" : "ftp://ftp.aha.ru/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : null, + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ru", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "anlx.net", + "org" : "Associated Networks Limited", + "city" : "London", + "region" : "England", + "country" : "United Kingdom", + "continent" : "Europe", + "latitude" : "51.50595", + "longitude" : "-0.12689", + "tz" : "0", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "eng", + "contact_site" : "anlx.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirror.anlx.net/", + "ftp" : "ftp://ftp.mirror.anlx.net/CPAN/", + "rsync" : "rsync://rsync.mirror.anlx.net/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : "Server is load balanced over 2 machines using an Arrowpoint CS-800", + "inceptdate" : "2001-09-27", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "uk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "arnes.si", + "org" : "Academic and Research Network in Slovenia", + "city" : "Ljubljana", + "region" : null, + "country" : "Slovenia", + "continent" : "Europe", + "latitude" : "46.058", + "longitude" : "14.5049", + "tz" : "+1", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "ftpadmin", + "contact_site" : "arnes.si" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.arnes.si/software/perl/CPAN/", + "ftp" : "ftp://ftp.arnes.si/software/perl/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1998-12-05", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "si", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "artfiles.org", + "org" : "Artfiles New Media GmbH", + "city" : "Hamburg", + "region" : null, + "country" : "Germany", + "continent" : "Europe", + "latitude" : "+53.548", + "longitude" : "+10.051", + "tz" : "+1", + "pipesize" : 1, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "artfiles.org" + } + ], + "src" : "rsync://rsync.cs.uu.nl/CPAN/", + "http" : "http://artfiles.org/cpan.org/", + "ftp" : "ftp://artfiles.org/cpan.org/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-02-21", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "as24220.net", + "org" : "HostCentral", + "city" : "Melbourne", + "region" : "Victoria", + "country" : "Australia", + "continent" : "Oceania", + "latitude" : "-37.818802", + "longitude" : "144.956938", + "tz" : "+10", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "as24220.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.as24220.net/pub/cpan/", + "ftp" : "ftp://mirror.as24220.net/pub/cpan/", + "rsync" : null, + "freq" : "2h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-10-25", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "au", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "as43289.net", + "org" : "Trabia-Network", + "city" : "Chisinau", + "region" : null, + "country" : "Moldova", + "continent" : "Europe", + "latitude" : "+47.023200", + "longitude" : "+28.837413", + "tz" : "+0", + "pipesize" : 10000, + "contact" : [ + { + "contact_user" : "noc", + "contact_site" : "trabia.net" + } + ], + "src" : "rsync://cpan-rsync-master.perl.org/CPAN/", + "http" : "http://mirror.as43289.net/pub/CPAN/", + "ftp" : "ftp://mirror.as43289.net/pub/CPAN/", + "rsync" : "rsync://mirror.as43289.net/CPAN/", + "freq" : "instant", + "tier1" : "Y", + "note" : null, + "inceptdate" : "2014-01-28", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "md", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "auckland.ac.nz", + "org" : "Auckland University", + "city" : "Auckland", + "region" : null, + "country" : "New Zealand", + "continent" : "Oceania", + "latitude" : "-36.917", + "longitude" : "174.783", + "tz" : "+12", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "webmaster", + "contact_site" : "auckland.ac.nz" + } + ], + "src" : "ftp.funet.fi", + "http" : null, + "ftp" : "ftp://ftp.auckland.ac.nz/pub/perl/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1998-12-05", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "nz", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "belnet.be", + "org" : "Belnet", + "city" : "Brussels", + "region" : null, + "country" : "Belgium", + "continent" : "Europe", + "latitude" : "50.8333", + "longitude" : "4.333", + "tz" : "+1", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "ftpmaint", + "contact_site" : "belnet.be" + } + ], + "src" : "nic.funet.fi", + "http" : "http://ftp.belnet.be/ftp.cpan.org/", + "ftp" : "ftp://ftp.belnet.be/mirror/ftp.cpan.org/", + "rsync" : "rsync://ftp.belnet.be/cpan/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : null, + "retiredate" : null, + "dnsrr" : null, + "ccode" : "be", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "bibleonline.ru", + "org" : "BibleOnline Russia", + "city" : "Falkenstein", + "region" : "Sachsen", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "+50.466700", + "longitude" : "+12.366700", + "tz" : "+3", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "perl", + "contact_site" : "bibleonline.ru" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.bibleonline.ru/cpan/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2013-09-30", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "ru", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "biocourse.weizmann.ac.il", + "org" : "Weizmann Institute of Science", + "city" : "Rehovot", + "region" : null, + "country" : "Israel", + "continent" : "Asia", + "latitude" : "+31.890", + "longitude" : "+34.800", + "tz" : "+2", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "jaime.prilusky", + "contact_site" : "weizmann.ac.il" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://biocourse.weizmann.ac.il/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-25", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "il", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "bo.mirror.garr.it", + "org" : "GARR/CILEA", + "city" : "Bologna", + "region" : null, + "country" : "Italy", + "continent" : "Europe", + "latitude" : "44.483", + "longitude" : "11.333", + "tz" : "+1", + "pipesize" : 144, + "contact" : [ + { + "contact_user" : "mirror-service", + "contact_site" : "garr.it" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://bo.mirror.garr.it/mirrors/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-03-05", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "it", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "byfly.by", + "org" : "RUE Beltelecom, ByFly ISP", + "city" : "Minsk", + "region" : null, + "country" : "Belarus", + "continent" : "Europe", + "latitude" : "+53.907", + "longitude" : "+27.540", + "tz" : "+3", + "pipesize" : 2000, + "contact" : [ + { + "contact_user" : "ftp", + "contact_site" : "mgts.by" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.byfly.by/pub/CPAN/", + "ftp" : "ftp://ftp.byfly.by/pub/CPAN/", + "rsync" : "rsync://ftp.byfly.by/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-05-16", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "by", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "bytemark.co.uk", + "org" : "Bytemark Hosting", + "city" : "Manchester", + "region" : null, + "country" : "United Kingdom", + "continent" : "Europe", + "latitude" : "53.465", + "longitude" : "-2.246", + "tz" : "+0", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "support", + "contact_site" : "support.bytemark.co.uk" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.bytemark.co.uk/CPAN/", + "ftp" : "ftp://mirror.bytemark.co.uk/CPAN/", + "rsync" : "rsync://mirror.bytemark.co.uk/CPAN/", + "freq" : "4h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2009-06-14", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "uk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "carnet.hr", + "org" : "CARNet (Croatian Academic and Research Network)", + "city" : "Zagreb", + "region" : null, + "country" : "Croatia", + "continent" : "Europe", + "latitude" : "45.7924", + "longitude" : "15.9696", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "ftpadmin", + "contact_site" : "carnet.hr" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.carnet.hr/pub/CPAN/", + "ftp" : "ftp://ftp.carnet.hr/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2007-05-21", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "hr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cc.columbia.edu", + "org" : "Columbia University", + "city" : "New York", + "region" : "New York", + "country" : "United States", + "continent" : "North America", + "latitude" : "40.8", + "longitude" : "-73.95", + "tz" : "-5", + "pipesize" : 622, + "contact" : [ + { + "contact_user" : "mirror-admin", + "contact_site" : "columbia.edu" + } + ], + "src" : "mirrors.kernel.org", + "http" : "http://mirror.cc.columbia.edu/pub/software/cpan/", + "ftp" : "ftp://mirror.cc.columbia.edu/pub/software/cpan/", + "rsync" : "rsync://mirror.cc.columbia.edu/cpan/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2005-02-01", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ccs.neu.edu", + "org" : "College of Computer Science, Northeastern University", + "city" : "Boston", + "region" : "Massachusetts", + "country" : "United States", + "continent" : "North America", + "latitude" : "42.362", + "longitude" : "-71.058", + "tz" : "-5", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "ftp", + "contact_site" : "ccs.neu.edu" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.ccs.neu.edu/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1997-05-19", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cdnetworks.com", + "org" : "CDNetwork Co., Ltd.", + "city" : "Seoul", + "region" : null, + "country" : "Republic of Korea", + "continent" : "Asia", + "latitude" : "37.56", + "longitude" : "126.98", + "tz" : "+9", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "sukbum.hong", + "contact_site" : "cdnetworks.co.kr" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirror.cdnetworks.com/", + "ftp" : "ftp://cpan.mirror.cdnetworks.com/CPAN/", + "rsync" : null, + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-06-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "kr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "checkdomain.de", + "org" : "Checkdomain GmbH", + "city" : "Falkenstein", + "region" : "Sachsen", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "+50.478", + "longitude" : "+12.350", + "tz" : "1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "s.jalandt", + "contact_site" : "checkdomain.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.checkdomain.de/CPAN/", + "ftp" : "ftp://mirror.checkdomain.de/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-11-07", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "choon.net", + "org" : "choon.net", + "city" : "Singapore", + "region" : null, + "country" : "Singapore", + "continent" : "Asia", + "latitude" : "1.283", + "longitude" : "103.85", + "tz" : "+8", + "pipesize" : 10, + "contact" : [ + { + "contact_user" : "mirror.cpan.org", + "contact_site" : "choon.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirror.choon.net/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-09-08", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "sg", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ciril.fr", + "org" : "CIRIL - Centre Interuniversitaire de Ressources Informatiques de Lorraine", + "city" : "Vandoeuvre-lès-Nancy", + "region" : "Lorraine", + "country" : "France", + "continent" : "Europe", + "latitude" : "+48.658", + "longitude" : "+6.154", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "ftpmaster", + "contact_site" : "ciril.fr" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.ciril.fr/pub/cpan/", + "ftp" : "ftp://ftp.ciril.fr/pub/cpan/", + "rsync" : "rsync://ftp.ciril.fr/pub/cpan/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-09-18", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "fr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "clemson.edu", + "org" : "Clemson University", + "city" : "Clemson", + "region" : "South Carolina", + "country" : "United States", + "continent" : "North America", + "latitude" : "34.68493", + "longitude" : "-82.814777", + "tz" : "-5", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "hbj", + "contact_site" : "clemson.edu" + } + ], + "src" : "csociety-ftp.ecn.purdue.edu::CPAN", + "http" : "http://cpan.mirror.clemson.edu/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2007-05-21", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "clouditalia.com", + "org" : "Clouditalia Communications SpA", + "city" : "Arezzo", + "region" : null, + "country" : "Italy", + "continent" : "Europe", + "latitude" : "+43.455220", + "longitude" : "+11.877521", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "rpoltronieri", + "contact_site" : "clouditalia.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.eutelia.it/CPAN_Mirror/", + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-23", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "it", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cogentco.com", + "org" : "Cogent Communications", + "city" : "Herndon", + "region" : "Virginia", + "country" : "United States", + "continent" : "North America", + "latitude" : "38.9667", + "longitude" : "-77.3833", + "tz" : "-5", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror-admin", + "contact_site" : "cogentco.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.cogentco.com/pub/CPAN/", + "ftp" : "ftp://mirror.cogentco.com/pub/CPAN/", + "rsync" : "rsync://mirror.cogentco.com/CPAN/", + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2001-08-03", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "communilink.net", + "org" : "Communilink Internet Limited", + "city" : "Hong Kong", + "region" : "Hong Kong SAR", + "country" : "China", + "continent" : "Asia", + "latitude" : "22.338741", + "longitude" : "114.199499", + "tz" : "+8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "communilink.net" + } + ], + "src" : "ftp.funet.fi", + "http" : "http://cpan.communilink.net/", + "ftp" : null, + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-02-01", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "cn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "concertpass.com", + "org" : "ConcertPass", + "city" : "Newton", + "region" : "Kansas", + "country" : "United States", + "continent" : "North America", + "latitude" : "+38.045650", + "longitude" : "-97.342979", + "tz" : "-6", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "admin", + "contact_site" : "mirrors.concertpass.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.concertpass.com/cpan/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2015-01-30", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "coreix.net", + "org" : "Coreix LTD", + "city" : "Enfield", + "region" : "England", + "country" : "United Kingdom", + "continent" : "Europe", + "latitude" : "+51.653", + "longitude" : "-0.054", + "tz" : "+0", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "coreix.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.coreix.net/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "4h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-05-01", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "uk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.belfry.net", + "org" : "The Belfry(!)", + "city" : "New York", + "region" : "New York", + "country" : "United States", + "continent" : "North America", + "latitude" : "40.741891", + "longitude" : "-73.994778", + "tz" : "-5", + "pipesize" : 2, + "contact" : [ + { + "contact_user" : "jerlbaum", + "contact_site" : "cpan.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.belfry.net/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2002-03-07", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.catalyst.net.nz", + "org" : "Catalyst IT", + "city" : "Wellington", + "region" : null, + "country" : "New Zealand", + "continent" : "Oceania", + "latitude" : "-41.294704", + "longitude" : "174.773512", + "tz" : "+12", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "catalyst.net.nz" + } + ], + "src" : "mirrors.kernel.org", + "http" : "http://cpan.catalyst.net.nz/CPAN/", + "ftp" : "ftp://cpan.catalyst.net.nz/pub/CPAN/", + "rsync" : null, + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-07-30", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "nz", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.cc.uoc.gr", + "org" : "University of Crete / Computer Center", + "city" : "Heraklion", + "region" : "Crete", + "country" : "Greece", + "continent" : "Europe", + "latitude" : "35.1823", + "longitude" : "25.0454", + "tz" : "+2", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "uoc.gr" + } + ], + "src" : "rsync.nic.funet.fi::CPAN", + "http" : "http://cpan.cc.uoc.gr/mirrors/CPAN/", + "ftp" : "ftp://ftp.cc.uoc.gr/mirrors/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2007-08-01", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "gr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.cdpa.nsysu.edu.tw", + "org" : "CDPA National Sun Yat-Sen University", + "city" : "Kao-hsiung", + "region" : null, + "country" : "Taiwan", + "continent" : "Asia", + "latitude" : "22.38", + "longitude" : "120.17", + "tz" : "+8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "tjs", + "contact_site" : "cdpa.nsysu.edu.tw" + } + ], + "src" : "ftp.funet.fi", + "http" : "http://cpan.cdpa.nsysu.edu.tw/Unix/Lang/CPAN/", + "ftp" : "ftp://cpan.cdpa.nsysu.edu.tw/Unix/Lang/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2003-04-22", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "tw", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.cs.utah.edu", + "org" : "University of Utah School of Computing", + "city" : "Salt Lake City", + "region" : "Utah", + "country" : "United States", + "continent" : "North America", + "latitude" : "40.761", + "longitude" : "-111.890", + "tz" : "-7", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "cs.utah.edu" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.cs.utah.edu/", + "ftp" : "ftp://cpan.cs.utah.edu/CPAN/", + "rsync" : "rsync://cpan.cs.utah.edu/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2004-03-30", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.cse.msu.edu", + "org" : "Computer Science and Engineering, Michigan State University", + "city" : "East Lansing", + "region" : "Michigan", + "country" : "United States", + "continent" : "North America", + "latitude" : "42.72", + "longitude" : "-84.48", + "tz" : "-5", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "manager", + "contact_site" : "cse.msu.edu" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.cse.msu.edu/", + "ftp" : "ftp://cpan.cse.msu.edu/", + "rsync" : "rsync://debian.cse.msu.edu/cpan/", + "freq" : "instant", + "tier1" : "Y", + "note" : "", + "inceptdate" : "2001-04-23", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.dcc.fc.up.pt", + "org" : "Departamento de Ciéncia de Computadores, Faculdade de Ciéncias da Universidade do Porto (Computer Science Departement, Science Faculty, Oporto University)", + "city" : "Porto", + "region" : null, + "country" : "Portugal", + "continent" : "Europe", + "latitude" : "41.15", + "longitude" : "-8.62", + "tz" : "+0", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "LabCC", + "contact_site" : "labcc.dcc.fc.up.pt" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.dcc.fc.up.pt/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-01-01", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "pt", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.develooper.com", + "org" : "Develooper LLC", + "city" : "Los Angeles", + "region" : "California", + "country" : "United States", + "continent" : "North America", + "latitude" : "34.050", + "longitude" : "-118.233", + "tz" : "-8", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "ask", + "contact_site" : "develooper.com" + } + ], + "src" : "rsync://cpan-rsync-master.perl.org/CPAN/", + "http" : "http://cpan.develooper.com/", + "ftp" : null, + "rsync" : null, + "freq" : "1h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2002-06-06", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.dk", + "org" : "Telia Danmark", + "city" : "Copenhagen", + "region" : null, + "country" : "Denmark", + "continent" : "Europe", + "latitude" : "55.67621", + "longitude" : "12.56951", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "dk.telia.net" + } + ], + "src" : "rsync://cpan-rsync-master.perl.org/CPAN/", + "http" : "http://www.cpan.dk/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "Y", + "note" : null, + "inceptdate" : "2006-01-01", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "dk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.erlbaum.net", + "org" : "The Erlbaum Group", + "city" : "New York", + "region" : "New York", + "country" : "United States", + "continent" : "North America", + "latitude" : "40.7418", + "longitude" : "-73.9947", + "tz" : "-5", + "pipesize" : 2, + "contact" : [ + { + "contact_user" : "jerlbaum", + "contact_site" : "cpan.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.erlbaum.net/", + "ftp" : "ftp://cpan.erlbaum.net/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2003-05-24", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.etla.org", + "org" : "cpan.etla.org", + "city" : "London", + "region" : null, + "country" : "United Kingdom", + "continent" : "Europe", + "latitude" : "51.512078", + "longitude" : "-0.002035", + "tz" : "0", + "pipesize" : 10, + "contact" : [ + { + "contact_user" : "mstevens", + "contact_site" : "etla.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.etla.org/", + "ftp" : "ftp://cpan.etla.org/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2003-06-18", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "uk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.hexten.net", + "org" : "Hexten", + "city" : "New York", + "region" : "New York", + "country" : "United States", + "continent" : "North America", + "latitude" : "40.7", + "longitude" : "-74", + "tz" : "-5", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "andy", + "contact_site" : "hexten.net" + } + ], + "src" : "rsync.nic.funet.fi", + "http" : "http://cpan.hexten.net/", + "ftp" : "ftp://cpan.hexten.net/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : "See also backpan.hexten.net", + "inceptdate" : "2006-08-23", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.inode.at", + "org" : "UPC Austria", + "city" : "Vienna", + "region" : null, + "country" : "Austria", + "continent" : "Europe", + "latitude" : "48.1813", + "longitude" : "16.3734", + "tz" : "+2", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "inode.at" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.inode.at/", + "ftp" : "ftp://cpan.inode.at/", + "rsync" : "rsync://cpan.inode.at/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : "rsync and ftp are limited to 30 concurrent sessions", + "inceptdate" : "2003-08-21", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "at", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.inspire.net.nz", + "org" : "InspireNet ltd", + "city" : "Palmerston North", + "region" : null, + "country" : "New Zealand", + "continent" : "Oceania", + "latitude" : "-40.32", + "longitude" : "175.62", + "tz" : "+12", + "pipesize" : 155, + "contact" : [ + { + "contact_user" : "brenden", + "contact_site" : "inspire.net.nz" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.inspire.net.nz/", + "ftp" : "ftp://cpan.inspire.net.nz/cpan/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-02-12", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "nz", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.llarian.net", + "org" : "Semaphore Corporation", + "city" : "Seattle", + "region" : "Washington", + "country" : "United States", + "continent" : "North America", + "latitude" : "47.612", + "longitude" : "-122.338", + "tz" : "-8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "llarian", + "contact_site" : "llarian.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.llarian.net/", + "ftp" : "ftp://cpan.llarian.net/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2000-02-08", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.mirror.dkm.cz", + "org" : "UPC Czech Republic", + "city" : "Prague", + "region" : null, + "country" : "Czech Republic", + "continent" : "Europe", + "latitude" : "+50.08", + "longitude" : "+14.42", + "tz" : "+1", + "pipesize" : 2000, + "contact" : [ + { + "contact_user" : "tz", + "contact_site" : "upcbroadband.cz" + } + ], + "src" : "ftp.funet.fi::CPAN", + "http" : "http://cpan.mirror.dkm.cz/pub/CPAN/", + "ftp" : "ftp://cpan.mirror.dkm.cz/pub/CPAN/", + "rsync" : "rsync://cpan.mirror.dkm.cz/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-22", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "cz", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.mirror.rafal.ca", + "org" : "Rafal Rzeczkowski", + "city" : "Hamilton", + "region" : "Ontario", + "country" : "Canada", + "continent" : "North America", + "latitude" : "43.22361", + "longitude" : "-79.87541", + "tz" : "-5", + "pipesize" : 622, + "contact" : [ + { + "contact_user" : "mirror-cpan", + "contact_site" : "mail.rafal.ca" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirror.rafal.ca/", + "ftp" : "ftp://CPAN.mirror.rafal.ca/pub/CPAN/", + "rsync" : "rsync://CPAN.mirror.rafal.ca/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : "", + "inceptdate" : "2006-01-01", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "ca", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.mirrors.hoobly.com", + "org" : "Hoobly Classifieds", + "city" : "Chicago", + "region" : "Illinois", + "country" : "United States", + "continent" : "North America", + "latitude" : "41.59", + "longitude" : "-87.54", + "tz" : "-6", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "pgrigor", + "contact_site" : "hoobly.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirrors.hoobly.com/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2004-08-15", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.mirrors.ilisys.com.au", + "org" : "Ilisys Web Hosting", + "city" : "Melbourne", + "region" : "Victoria", + "country" : "Australia", + "continent" : "Oceania", + "latitude" : "-37.814", + "longitude" : "+144.963", + "tz" : "+10", + "pipesize" : 200, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "ilisys.com.au" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirrors.ilisys.com.au/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-24", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "au", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.mirrors.tds.net", + "org" : "TDS Internet Services", + "city" : "Madison", + "region" : "Wisconsin", + "country" : "United States", + "continent" : "North America", + "latitude" : "43.090091", + "longitude" : "-089.530023", + "tz" : "-6", + "pipesize" : 622, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "tds.net" + } + ], + "src" : "rsync.nic.funet.fi", + "http" : "http://cpan.mirrors.tds.net/", + "ftp" : "ftp://cpan.mirrors.tds.net/pub/CPAN/", + "rsync" : "rsync://cpan.mirrors.tds.net/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2004-01-31", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.netnitco.net", + "org" : "NetNITCO Internet Services", + "city" : "Hebron", + "region" : "Indiana", + "country" : "United States", + "continent" : "North America", + "latitude" : "41.322", + "longitude" : "-87.202", + "tz" : "-6", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "netnitco.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.netnitco.net/", + "ftp" : "ftp://cpan.netnitco.net/pub/mirrors/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : null, + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.noris.de", + "org" : "noris network AG", + "city" : "Nüremberg", + "region" : "Bayern", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "49.4541", + "longitude" : "11.0634", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "cpan", + "contact_site" : "noris.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.noris.de/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2001-07-16", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "de", + "aka_name" : "de.cpan.org", + "A_or_CNAME" : "cpan.noris.de" + }, + { + "name" : "cpan.pair.com", + "org" : "pair Networks, Inc.", + "city" : "Pittsburgh", + "region" : "Pennsylvania", + "country" : "United States", + "continent" : "North America", + "latitude" : "40.437", + "longitude" : "-80.000", + "tz" : "-5", + "pipesize" : 600, + "contact" : [ + { + "contact_user" : "CPAN", + "contact_site" : "pair.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.pair.com/", + "ftp" : "ftp://cpan.pair.com/pub/CPAN/", + "rsync" : "rsync://cpan.pair.com/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2002-01-02", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.panu.it", + "org" : "Alberto Panu", + "city" : "Milano", + "region" : null, + "country" : "Italy", + "continent" : "Europe", + "latitude" : "45.4", + "longitude" : "9.3", + "tz" : "+1", + "pipesize" : 10, + "contact" : [ + { + "contact_user" : "alberto", + "contact_site" : "panu.it" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.panu.it/", + "ftp" : "ftp://ftp.panu.it/pub/mirrors/perl/CPAN/", + "rsync" : "rsync://rsync.panu.it/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-02-12", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "it", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpan.rinet.ru", + "org" : "Cronyx Plus Ltd. (RiNet ISP)", + "city" : "Moscow", + "region" : null, + "country" : "Russian Federation", + "continent" : "Europe", + "latitude" : "55.75", + "longitude" : "37.5833", + "tz" : "+3", + "pipesize" : 10, + "contact" : [ + { + "contact_user" : "mirroradm", + "contact_site" : "rinet.ru" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.rinet.ru/", + "ftp" : "ftp://cpan.rinet.ru/pub/mirror/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2001-02-03", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ru", + "aka_name" : "ru.cpan.org", + "A_or_CNAME" : "cpan.rinet.ru" + }, + { + "name" : "cpan.stu.edu.tw", + "org" : "Computer Center, Shu-Te University", + "city" : "Kaohsiung", + "region" : null, + "country" : "Taiwan", + "continent" : "Asia", + "latitude" : "22.76", + "longitude" : "120.38", + "tz" : "+8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "ftp", + "contact_site" : "stu.edu.tw" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.stu.edu.tw/", + "ftp" : "ftp://ftp.stu.edu.tw/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : "update ftp.stu.edu.tw/cpan to cpan.stu.edu.tw", + "inceptdate" : "2006-01-01", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "tw", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cpantesters.org", + "org" : "CPAN Testers", + "city" : "London", + "region" : "England", + "country" : "United Kingdom", + "continent" : "Europe", + "latitude" : "54.000", + "longitude" : "-2.0", + "tz" : "0", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "barbie", + "contact_site" : "cpantesters.org" + } + ], + "src" : "rsync://cpan-rsync-master.perl.org/CPAN/", + "http" : "http://cpan.cpantesters.org/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "Y", + "note" : null, + "inceptdate" : "2009-03-31", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "uk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cs.uu.nl", + "org" : "Utrecht University", + "city" : "Utrecht", + "region" : null, + "country" : "Netherlands", + "continent" : "Europe", + "latitude" : "52.087253", + "longitude" : "5.165408", + "tz" : "+1", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "webmaster", + "contact_site" : "cs.uu.nl" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.cs.uu.nl/", + "ftp" : "ftp://ftp.cs.uu.nl/pub/CPAN/", + "rsync" : "rsync://rsync.cs.uu.nl/CPAN/", + "freq" : "instant", + "tier1" : "Y", + "note" : null, + "inceptdate" : "1995-10-26", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "nl", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "csclub.uwaterloo.ca", + "org" : "University of Waterloo Computer Science Club", + "city" : "Waterloo", + "region" : "Ontario", + "country" : "Canada", + "continent" : "North America", + "latitude" : "43.472", + "longitude" : "-80.544", + "tz" : "-5", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "syscom", + "contact_site" : "csclub.uwaterloo.ca" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.csclub.uwaterloo.ca/CPAN/", + "ftp" : "ftp://mirror.csclub.uwaterloo.ca/CPAN/", + "rsync" : "rsync://mirror.csclub.uwaterloo.ca/CPAN/", + "freq" : "12h", + "tier1" : "N", + "note" : "1Gbps over CA*Net4; 300Mbps otherwise", + "inceptdate" : "2007-11-06", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "ca", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cse.yzu.edu.tw", + "org" : "Department of CSE, Yuan Ze University", + "city" : "Chung-Li", + "region" : "Taoyuan County", + "country" : "Taiwan", + "continent" : "Asia", + "latitude" : "+24.969894", + "longitude" : "+121.266483", + "tz" : "+9", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "hsu", + "contact_site" : "peterdavehello.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.yzu.edu.tw/CPAN/", + "ftp" : "ftp://ftp.yzu.edu.tw/CPAN/", + "rsync" : "rsync://ftp.yzu.edu.tw/pub/CPAN/", + "freq" : "8h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-10-26", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "tw", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cu.be", + "org" : "Cu.be Solutions", + "city" : "Brussels", + "region" : null, + "country" : "Belgium", + "continent" : "Europe", + "latitude" : "+50.89", + "longitude" : "+4.46", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "cu.be" + } + ], + "src" : "rsync://cpan-rsync-master.perl.org/CPAN/", + "http" : "http://cpan.cu.be/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-23", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "be", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "cuhk.edu.hk", + "org" : "The Chinese University of Hong Kong", + "city" : "Hong Kong", + "region" : "Hong Kong SAR", + "country" : "China", + "continent" : "Asia", + "latitude" : "22.42", + "longitude" : "114.2", + "tz" : "+8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "ftp-admin", + "contact_site" : "ftp.cuhk.edu.hk" + } + ], + "src" : "ftp://mirrors.hknet.com/CPAN", + "http" : "http://ftp.cuhk.edu.hk/pub/packages/perl/CPAN/", + "ftp" : "ftp://ftp.cuhk.edu.hk/pub/packages/perl/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : null, + "retiredate" : null, + "dnsrr" : null, + "ccode" : "cn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "datapipe.net", + "org" : "DataPipe", + "city" : "Newark", + "region" : "New Jersey", + "country" : "United States", + "continent" : "North America", + "latitude" : "40.736", + "longitude" : "-74.173", + "tz" : "-5", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "ftpadmin", + "contact_site" : "mail5.datapipe.com" + } + ], + "src" : "carroll.cac.psu.edu", + "http" : "http://mirror.datapipe.net/CPAN/", + "ftp" : "ftp://mirror.datapipe.net/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2003-12-09", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "de.leaseweb.net", + "org" : "Leaseweb", + "city" : "Frankfurt", + "region" : null, + "country" : "Germany", + "continent" : "Europe", + "latitude" : "50.08027", + "longitude" : "8.62406", + "tz" : "+1", + "pipesize" : 2000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "leaseweb.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.de.leaseweb.net/CPAN/", + "ftp" : "ftp://mirror.de.leaseweb.net/CPAN/", + "rsync" : "rsync://mirror.de.leaseweb.net/CPAN/", + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-05-24", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "devlib.org", + "org" : "GeoClicks", + "city" : "Hong Kong", + "region" : "Hong Kong SAR", + "country" : "China", + "continent" : "Asia", + "latitude" : "+22.285", + "longitude" : "+114.158", + "tz" : "+8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "shri", + "contact_site" : "geoclicks.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.devlib.org/cpan/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-11-01", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "cn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "dhakacom.com", + "org" : "dhakaCom Limited", + "city" : "Dhaka", + "region" : null, + "country" : "Bangladesh", + "continent" : "Asia", + "latitude" : "+23.780475", + "longitude" : "+90.416300", + "tz" : "+6", + "pipesize" : 10000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "dhakacom.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.dhakacom.com/CPAN/", + "ftp" : "ftp://mirror.dhakacom.com/CPAN/", + "rsync" : "rsync://mirror.dhakacom.com/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2015-05-02", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "bd", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "digipower.vn", + "org" : "DIGIPOWER Co.,ltd", + "city" : "Ho Chi Minh City", + "region" : null, + "country" : "Viet Nam", + "continent" : "Asia", + "latitude" : "+10.7968", + "longitude" : "+106.6181", + "tz" : "+7", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "duchoang", + "contact_site" : "digipower.vn" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.digipower.vn/CPAN/", + "ftp" : null, + "rsync" : "rsync://mirrors.digipower.vn/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-03-19", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "vn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "digitalpacific.com.au", + "org" : "Digital Pacific", + "city" : "Sydney", + "region" : "New South Wales", + "country" : "Australia", + "continent" : "Oceania", + "latitude" : "-33.914807", + "longitude" : "+151.193308", + "tz" : "+10", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "networking", + "contact_site" : "digitalpacific.com.au" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirror.digitalpacific.com.au/", + "ftp" : null, + "rsync" : "rsync://cpan.mirror.digitalpacific.com.au/cpan/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-12-08", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "au", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "dotsrc.org", + "org" : "dotsrc.org", + "city" : "Aalborg", + "region" : null, + "country" : "Denmark", + "continent" : "Europe", + "latitude" : "57.0319", + "longitude" : "9.98627", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "staff", + "contact_site" : "dotsrc.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.dotsrc.org/cpan/", + "ftp" : "ftp://mirrors.dotsrc.org/cpan/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1996-04-01", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "dk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "downloadvn.com", + "org" : "DownloadVN.com", + "city" : "Ha Noi", + "region" : null, + "country" : "Viet Nam", + "continent" : "Asia", + "latitude" : "+20.939894", + "longitude" : "+105.820313", + "tz" : "+7", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "contact", + "contact_site" : "downloadvn.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.downloadvn.com/cpan/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-04-09", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "vn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "easyname.at", + "org" : "Easyname GmbH", + "city" : "Vienna", + "region" : "Vienna", + "country" : "Austria", + "continent" : "Europe", + "latitude" : "+48.181380", + "longitude" : "+16.366470", + "tz" : "+1", + "pipesize" : 10000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "easyname.com" + } + ], + "src" : "rsync://mirror.easyname.com/cpan/", + "http" : "http://mirror.easyname.at/cpan/", + "ftp" : "ftp://mirror.easyname.at/cpan/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2015-05-31", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "at", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "euserv.com", + "org" : "EUserv Internet - euserv.com", + "city" : "Jena", + "region" : "Thüringen", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "+50.9330", + "longitude" : "+11.5897", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirrormaster", + "contact_site" : "euserv.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirror.euserv.net/", + "ftp" : "ftp://mirror.euserv.net/cpan/", + "rsync" : "rsync://mirror.euserv.net/cpan/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-11-19", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "evowise.com", + "org" : "Evowise", + "city" : "Bucharest", + "region" : null, + "country" : "Romania", + "continent" : "Europe", + "latitude" : "+44.433306", + "longitude" : "+26.153736", + "tz" : "+2", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "hayden", + "contact_site" : "madrivo.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.evowise.com/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-05-18", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "ro", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "exascale.co.uk", + "org" : "Exascale", + "city" : "Wolverhampton", + "region" : "England", + "country" : "United Kingdom", + "continent" : "Europe", + "latitude" : "+52.584576", + "longitude" : "-2.124904", + "tz" : "0", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "noc", + "contact_site" : "exascale.co.uk" + } + ], + "src" : "rsync://rsync.mirrorservice.org/cpan.perl.org/CPAN/", + "http" : "http://mirror.sax.uk.as61049.net/CPAN/", + "ftp" : null, + "rsync" : "rsync://mirror.sax.uk.as61049.net/CPAN/", + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-04-09", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "uk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "excellmedia.net", + "org" : "Excell Media Pvt. Ltd.", + "city" : "Hyderabad", + "region" : "Telangana", + "country" : "India", + "continent" : "Asia", + "latitude" : "+17.428050", + "longitude" : "+78.433290", + "tz" : "+5.5", + "pipesize" : 2000, + "contact" : [ + { + "contact_user" : "raj", + "contact_site" : "excellmedia.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.excellmedia.net/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-02-20", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "in", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "fht-esslingen.de", + "org" : "Rechenzentrum, Hochschule Esslingen (Computing Center, University of Applied Sciences)", + "city" : "Esslingen am Neckar", + "region" : "Baden-Württemberg", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "48.45", + "longitude" : "9.16", + "tz" : "+1", + "pipesize" : 2000, + "contact" : [ + { + "contact_user" : "adrian", + "contact_site" : "hs-esslingen.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp-stud.hs-esslingen.de/pub/Mirrors/CPAN/", + "ftp" : null, + "rsync" : "rsync://ftp-stud.hs-esslingen.de/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : null, + "retiredate" : null, + "dnsrr" : null, + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "fi.muni.cz", + "org" : "Fakulta Informatiky Masarykovy Univerzity (Faculty of Informatics, Masaryk University)", + "city" : "Brno", + "region" : "Jihomoravský", + "country" : "Czech Republic", + "continent" : "Europe", + "latitude" : "49.1942", + "longitude" : "16.6085", + "tz" : "+1", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "ftp-admin", + "contact_site" : "fi.muni.cz" + } + ], + "src" : "rsync://cpan-rsync-master.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.fi.muni.cz/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1997-05-28", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "cz", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "fraunhofer.de", + "org" : "Fraunhofer-Gesellschaft e.V.", + "city" : "Sankt Augustin", + "region" : "Nordrhein-Westfalen", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "50.74951", + "longitude" : "7.20358", + "tz" : "+1", + "pipesize" : 155, + "contact" : [ + { + "contact_user" : "mirror-cpan", + "contact_site" : "bi.fraunhofer.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://mirror.fraunhofer.de/CPAN/", + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "1997-02-07", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "freenet.de", + "org" : "freenet.de AG", + "city" : "Düsseldorf", + "region" : "Nordrhein-Westfalen", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "51.2264", + "longitude" : "6.77679", + "tz" : "+1", + "pipesize" : 2500, + "contact" : [ + { + "contact_user" : "ftpmaster", + "contact_site" : "freenet.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.freenet.de/pub/ftp.cpan.org/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1999-11-12", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ftp.hosteurope.de", + "org" : "Host Europe GmbH", + "city" : "Cologne", + "region" : "Nordrhein-Westfalen", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "50.91", + "longitude" : "7.06", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror-admins", + "contact_site" : "hosteurope.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.hosteurope.de/pub/CPAN/", + "ftp" : "ftp://ftp.hosteurope.de/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2007-05-21", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "fu-berlin.de", + "org" : "Freie Universität Berlin", + "city" : "Berlin", + "region" : null, + "country" : "Germany", + "continent" : "Europe", + "latitude" : "52.45", + "longitude" : "13.29", + "tz" : "+1", + "pipesize" : 622, + "contact" : [ + { + "contact_user" : "ftp", + "contact_site" : "fu-berlin.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.fu-berlin.de/unix/languages/perl/", + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-01-01", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "funet.fi", + "org" : "Finnish University NETwork", + "city" : "Espoo", + "region" : "Etelä-Suomen Lääni", + "country" : "Finland", + "continent" : "Europe", + "latitude" : "60.2099", + "longitude" : "24.6568", + "tz" : "+2", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "cpan", + "contact_site" : "perl.org" + } + ], + "src" : "rsync://cpan-rsync-master.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.funet.fi/pub/languages/perl/CPAN/", + "rsync" : "rsync://rsync.nic.funet.fi/CPAN/", + "freq" : "1h", + "tier1" : "N", + "note" : null, + "inceptdate" : "1995-10-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "fi", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "gd.tuwien.ac.at", + "org" : "Technische Universität Wien (Vienna University of Technology)", + "city" : "Vienna", + "region" : null, + "country" : "Austria", + "continent" : "Europe", + "latitude" : "48.20234", + "longitude" : "16.36958", + "tz" : "+1", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "gd", + "contact_site" : "tuwien.ac.at" + } + ], + "src" : "ftp.funet.fi", + "http" : "http://gd.tuwien.ac.at/languages/perl/CPAN/", + "ftp" : "ftp://gd.tuwien.ac.at/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : "a.k.a. at.cpan.org", + "inceptdate" : "1996-03-01", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "at", + "aka_name" : "at.cpan.org", + "A_or_CNAME" : "ftp.tuwien.ac.at" + }, + { + "name" : "goscomb.net", + "org" : "Goscomb Technologies Limited", + "city" : "London", + "region" : null, + "country" : "United Kingdom", + "continent" : "Europe", + "latitude" : "51.49978", + "longitude" : "-0.011137", + "tz" : "0", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "goscomb.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.sov.uk.goscomb.net/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "2h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2009-05-26", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "uk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "gossamer-threads.com", + "org" : "Gossamer Threads Inc.", + "city" : "Vancouver", + "region" : "British Columbia", + "country" : "Canada", + "continent" : "North America", + "latitude" : "49.25", + "longitude" : "-123.1", + "tz" : "-8", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "gossamer-threads.com" + } + ], + "src" : "rsync://cpan-rsync-master.perl.org/CPAN/", + "http" : "http://mirrors.gossamer-threads.com/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "Y", + "note" : null, + "inceptdate" : "2001-09-21", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ca", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "gwdg.de", + "org" : "Gesellschaft für wissenschaftliche Datenverarbeitung (Society for Scientific Data Processing)", + "city" : "Göttingen", + "region" : "Niedersachsen", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "51.53098", + "longitude" : "9.93825", + "tz" : "+1", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "emoenke", + "contact_site" : "gwdg.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.gwdg.de/pub/languages/perl/CPAN/", + "ftp" : "ftp://ftp.gwdg.de/pub/languages/perl/CPAN/", + "rsync" : "rsync://ftp.gwdg.de/pub/languages/perl/CPAN/", + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "1997-12-11", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "hawo.stw.uni-erlangen.de", + "org" : "HaWo - University of Erlangen", + "city" : "Erlangen", + "region" : "Bayern", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "+49.5799", + "longitude" : "+11.0197", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "noc", + "contact_site" : "hawo-net.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.hawo.stw.uni-erlangen.de/CPAN/", + "ftp" : "ftp://ftp.hawo.stw.uni-erlangen.de/CPAN/", + "rsync" : "rsync://ftp.hawo.stw.uni-erlangen.de/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2013-04-07", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "heanet.ie", + "org" : "HEAnet", + "city" : "Dublin", + "region" : null, + "country" : "Ireland", + "continent" : "Europe", + "latitude" : "53.333", + "longitude" : "-6.250", + "tz" : "0", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "heanet.ie" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.heanet.ie/mirrors/ftp.perl.org/pub/CPAN/", + "ftp" : "ftp://ftp.heanet.ie/mirrors/ftp.perl.org/pub/CPAN/", + "rsync" : "rsync://ftp.heanet.ie/mirrors/ftp.perl.org/pub/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : "See http://ftp.heanet.ie/about and http://www.hea.net/ for details of server and connectivity.", + "inceptdate" : "2002-10-08", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ie", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "hoovism.com", + "org" : "Matthew Hoover", + "city" : "Newark", + "region" : "New Jersey", + "country" : "United States", + "continent" : "North America", + "latitude" : "+40.720000", + "longitude" : "-74.170000", + "tz" : "-5", + "pipesize" : 25, + "contact" : [ + { + "contact_user" : "ops", + "contact_site" : "hoovism.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://www.hoovism.com/CPAN/", + "ftp" : "ftp://ftp.hoovism.com/CPAN/", + "rsync" : "rsync://rsync.hoovism.com/CPAN/", + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-02-20", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "hostingromania.ro", + "org" : "Hosting Romania", + "city" : "Craiova", + "region" : "Dolj", + "country" : "Romania", + "continent" : "Europe", + "latitude" : "44.317368", + "longitude" : "23.791022", + "tz" : "+2", + "pipesize" : 4000, + "contact" : [ + { + "contact_user" : "tech", + "contact_site" : "hostingromania.ro" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.hostingromania.ro/cpan.org/", + "ftp" : null, + "rsync" : null, + "freq" : "8h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-09-08", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "ro", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "httpupdate18.cpanel.net", + "org" : "cPanel Fast Update Server #18", + "city" : "Lansing", + "region" : "Michigan", + "country" : "United States", + "continent" : "North America", + "latitude" : "+42.779", + "longitude" : "-84.587", + "tz" : "-5", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "systems", + "contact_site" : "cpanel.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://httpupdate118.cpanel.net/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-09-24", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "httpupdate27.cpanel.net", + "org" : "cPanel Fast Update Server #27", + "city" : "Dana Point", + "region" : "California", + "country" : "United States", + "continent" : "North America", + "latitude" : "+33.676", + "longitude" : "-117.868", + "tz" : "-8", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "systems", + "contact_site" : "cpanel.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://httpupdate127.cpanel.net/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-09-24", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "httpupdate40.cpanel.net", + "org" : "cPanel Fast Update Server #40", + "city" : "Charlotte", + "region" : "North Carolina", + "country" : "United States", + "continent" : "North America", + "latitude" : "+35.214", + "longitude" : "-80.943", + "tz" : "-5", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "systems", + "contact_site" : "cpanel.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://httpupdate140.cpanel.net/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-09-24", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "hust.edu.cn", + "org" : "Huazhong University of Science and Technology", + "city" : "Wuhan", + "region" : "Hubei", + "country" : "China", + "continent" : "Asia", + "latitude" : "+30.511244", + "longitude" : "+114.413810", + "tz" : "+8", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "hust.edu.cn" + } + ], + "src" : "rsync://ftp.nara.wide.ad.jp/cpan/", + "http" : "http://mirrors.hust.edu.cn/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "8h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2013-07-05", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "cn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ibiblio.org", + "org" : "ibiblio.org", + "city" : "Chapel Hill", + "region" : "North Carolina", + "country" : "United States", + "continent" : "North America", + "latitude" : "35.92", + "longitude" : "-79.03", + "tz" : "-5", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "admin", + "contact_site" : "ibiblio.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.ibiblio.org/CPAN/", + "ftp" : null, + "rsync" : "rsync://mirrors.ibiblio.org/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2003-07-02", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "indialinks.com", + "org" : "IndiaLinks Web Hosting Pvt Ltd", + "city" : "Mumbai", + "region" : "Maharashtra", + "country" : "India", + "continent" : "Asia", + "latitude" : "18.91667", + "longitude" : "72.9", + "tz" : "+5.30", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "hostmaster", + "contact_site" : "indialinks.com" + } + ], + "src" : "cpan.pair.com", + "http" : "http://perlmirror.indialinks.com/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2009-07-11", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "in", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ionfish.org", + "org" : "ionFish Group, LLC", + "city" : "Philadelphia", + "region" : "Pennsylvania", + "country" : "United States", + "continent" : "North America", + "latitude" : "+39.955000", + "longitude" : "-75.164000", + "tz" : "-5", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "zvanrijn", + "contact_site" : "ionfish.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirrors.ionfish.org/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2015-03-16", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ip-connect.vn.ua", + "org" : "IP-Connect LLC", + "city" : "Vinnytsia", + "region" : null, + "country" : "Ukraine", + "continent" : "Europe", + "latitude" : "+49.233338", + "longitude" : "+28.447228", + "tz" : "+2", + "pipesize" : 2000, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "ip-connect.vn.ua" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.ip-connect.vn.ua/", + "ftp" : "ftp://cpan.ip-connect.vn.ua/mirror/cpan/", + "rsync" : "rsync://cpan.ip-connect.vn.ua/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-04-24", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "ua", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "is.co.za", + "org" : "Internet Solutions", + "city" : "Johannesburg", + "region" : "Gauteng", + "country" : "South Africa", + "continent" : "Africa", + "latitude" : "-26.17", + "longitude" : "28.03", + "tz" : "+2", + "pipesize" : 50, + "contact" : [ + { + "contact_user" : "ftpadmin", + "contact_site" : "is.co.za" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.is.co.za/pub/cpan/", + "ftp" : "ftp://ftp.is.co.za/pub/cpan/", + "rsync" : "rsync://ftp.is.co.za/IS-Mirror/ftp.cpan.org/", + "freq" : "1d", + "tier1" : "N", + "note" : "Limit to 4 simultaneous connections.", + "inceptdate" : "1995-10-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "za", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "jaist.ac.jp", + "org" : "Japan Advanced Institute of Science and Technology", + "city" : "Tatsunokuchi", + "region" : "Nomi", + "country" : "Japan", + "continent" : "Asia", + "latitude" : "36.444467", + "longitude" : "136.592871", + "tz" : "+9", + "pipesize" : 2000, + "contact" : [ + { + "contact_user" : "ftp-admin", + "contact_site" : "jaist.ac.jp" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.jaist.ac.jp/pub/CPAN/", + "ftp" : "ftp://ftp.jaist.ac.jp/pub/CPAN/", + "rsync" : "rsync://ftp.jaist.ac.jp/pub/CPAN/", + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-05-11", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "jp", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "jmu.edu", + "org" : "James Madison University", + "city" : "Harrisonburg", + "region" : "Virginia", + "country" : "United States", + "continent" : "North America", + "latitude" : "+38.4374", + "longitude" : "-78.8748", + "tz" : "-5", + "pipesize" : 900, + "contact" : [ + { + "contact_user" : "mirrormaster", + "contact_site" : "jmu.edu" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.jmu.edu/pub/CPAN/", + "ftp" : "ftp://mirror.jmu.edu/pub/CPAN/", + "rsync" : "rsync://mirror.jmu.edu/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-06-27", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "jre655.com", + "org" : "Fukuda Project", + "city" : "Tokyo", + "region" : "Kantō", + "country" : "Japan", + "continent" : "Asia", + "latitude" : "+35.706657", + "longitude" : "+139.868427", + "tz" : "+9", + "pipesize" : 350, + "contact" : [ + { + "contact_user" : "tea_hugutaku", + "contact_site" : "yahoo.co.jp" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.jre655.com/CPAN/", + "ftp" : "ftp://mirror.jre655.com/CPAN/", + "rsync" : "rsync://mirror.jre655.com/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2013-08-05", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "jp", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "jussieu.fr", + "org" : "IPSL/CNRS", + "city" : "Paris", + "region" : "Île-de-France", + "country" : "France", + "continent" : "Europe", + "latitude" : "48.8", + "longitude" : "2.33", + "tz" : "+1", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "olivier.thauvin", + "contact_site" : "aero.jussieu.fr" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://distrib-coffee.ipsl.jussieu.fr/pub/mirrors/cpan/", + "ftp" : "ftp://distrib-coffee.ipsl.jussieu.fr/pub/mirrors/cpan/", + "rsync" : "rsync://distrib-coffee.ipsl.jussieu.fr/pub/mirrors/cpan/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2007-05-20", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "fr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "kaist.ac.kr", + "org" : "Korea Advanced Institute of Science and Technology (KAIST)", + "city" : "Daejeon", + "region" : null, + "country" : "Republic of Korea", + "continent" : "Asia", + "latitude" : "36.37", + "longitude" : "127.37", + "tz" : "+9", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "ftp", + "contact_site" : "ftp.kaist.ac.kr" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.kaist.ac.kr/pub/CPAN/", + "ftp" : "ftp://ftp.kaist.ac.kr/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2003-12-11", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "kr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "kambing.ui.ac.id", + "org" : "University of Indonesia", + "city" : "Depok", + "region" : null, + "country" : "Indonesia", + "continent" : "Asia", + "latitude" : "-6.368", + "longitude" : "+106.828", + "tz" : "+8", + "pipesize" : 400, + "contact" : [ + { + "contact_user" : "admin", + "contact_site" : "kambing.ui.ac.id" + } + ], + "src" : "rsync.nic.funet.fi", + "http" : "http://kambing.ui.ac.id/cpan/", + "ftp" : null, + "rsync" : "rsync://kambing.ui.ac.id/CPAN/", + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-24", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "id", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "kddilabs.jp", + "org" : "KDDI R&D Labs, Inc.", + "city" : "Kamifukuoka", + "region" : "Kantō", + "country" : "Japan", + "continent" : "Asia", + "latitude" : "35.8746", + "longitude" : "139.5304", + "tz" : "+9", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "ftpadmin", + "contact_site" : "kddilabs.jp" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.kddilabs.jp/CPAN/", + "rsync" : "rsync://ftp.kddilabs.jp/cpan/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : null, + "retiredate" : null, + "dnsrr" : null, + "ccode" : "jp", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "kinghost.net", + "org" : "Cyberweb Networks", + "city" : "Porto Alegre", + "region" : null, + "country" : "Brazil", + "continent" : "South America", + "latitude" : "-30.033", + "longitude" : "-51.126", + "tz" : "-3", + "pipesize" : 2, + "contact" : [ + { + "contact_user" : "juliano", + "contact_site" : "cyberweb.com.br" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.kinghost.net/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2007-10-04", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "br", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "kr.freebsd.org", + "org" : "Korea FreeBSD Users Group", + "city" : "Seoul", + "region" : null, + "country" : "Republic of Korea", + "continent" : "Asia", + "latitude" : "+37.560000", + "longitude" : "+126.980000", + "tz" : "+9", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "cjh", + "contact_site" : "kr.freebsd.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.kr.freebsd.org/pub/CPAN/", + "ftp" : "ftp://ftp.kr.freebsd.org/pub/CPAN/", + "rsync" : null, + "freq" : "instant", + "tier1" : "Y", + "note" : null, + "inceptdate" : "2003-06-04", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "kr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "kvin.lv", + "org" : "Kvant-Interkom", + "city" : "Riga", + "region" : null, + "country" : "Latvia", + "continent" : "Europe", + "latitude" : "56.9498", + "longitude" : "24.1148", + "tz" : "+2", + "pipesize" : 11, + "contact" : [ + { + "contact_user" : "arkadi", + "contact_site" : "kvin.lv" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://kvin.lv/pub/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2001-01-22", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "lv", + "aka_name" : "lv.cpan.org", + "A_or_CNAME" : "kvin.lv" + }, + { + "name" : "lagoon.nc", + "org" : "OFFRATEL LAGOON", + "city" : "Nouméa", + "region" : null, + "country" : "New Caledonia", + "continent" : "Oceania", + "latitude" : "-22.245656", + "longitude" : "+166.449162", + "tz" : "+11", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "tech", + "contact_site" : "offratel.net" + } + ], + "src" : "mirror.as24220.net::cpan", + "http" : "http://cpan.lagoon.nc/pub/CPAN/", + "ftp" : "ftp://cpan.lagoon.nc/pub/CPAN/", + "rsync" : "rsync://cpan.lagoon.nc/cpan/", + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-02-25", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "nc", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "linorg.usp.br", + "org" : "Universidade de Sao Paulo", + "city" : "Sao Paulo", + "region" : null, + "country" : "Brazil", + "continent" : "South America", + "latitude" : "-23.53", + "longitude" : "-46.62", + "tz" : "-3", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "linorg", + "contact_site" : "usp.br" + }, + { + "contact_user" : "yunakaof", + "contact_site" : "usp.br" + } + ], + "src" : "nic.funet.fi", + "http" : "http://linorg.usp.br/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "19h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2009-09-23", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "br", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "lip6.fr", + "org" : "Laboratoire d'Informatique de Paris 6 (Informatics Laboratory of Paris 6)", + "city" : "Paris", + "region" : "Île-de-France", + "country" : "France", + "continent" : "Europe", + "latitude" : "48.85424", + "longitude" : "2.34486", + "tz" : "+1", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "ftpmaint", + "contact_site" : "lip6.fr" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.lip6.fr/pub/perl/CPAN/", + "ftp" : "ftp://ftp.lip6.fr/pub/perl/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1997-08-02", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "fr", + "aka_name" : "fr.cpan.org", + "A_or_CNAME" : "ftp.lip6.fr" + }, + { + "name" : "litnet.lt", + "org" : "Lithuanian Academical and Research Network", + "city" : "Kaunas", + "region" : null, + "country" : "Lithuania", + "continent" : "Europe", + "latitude" : "54.54", + "longitude" : "23.54", + "tz" : "+2", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "ftpadmin", + "contact_site" : "litnet.lt" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.litnet.lt/pub/CPAN/", + "ftp" : "ftp://ftp.litnet.lt/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2004-01-05", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "lt", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "lnx.sk", + "org" : "lnx.sk", + "city" : "Bratislava", + "region" : null, + "country" : "Slovakia", + "continent" : "Europe", + "latitude" : "+48.148", + "longitude" : "+17.107", + "tz" : "+1", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "lnx", + "contact_site" : "lnx.sk" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.lnx.sk/", + "ftp" : null, + "rsync" : null, + "freq" : "2d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "sk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "lug.ro", + "org" : "KPNQwest/GTS Romania -- Romanian Linux Users Group", + "city" : "Bucharest", + "region" : null, + "country" : "Romania", + "continent" : "Europe", + "latitude" : "44.4333", + "longitude" : "26.1000", + "tz" : "+2", + "pipesize" : 155, + "contact" : [ + { + "contact_user" : "cpan", + "contact_site" : "lug.ro" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.lug.ro/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2003-07-11", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ro", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "m247.ro", + "org" : "M247 Europe SRL", + "city" : "Bucharest", + "region" : null, + "country" : "Romania", + "continent" : "Europe", + "latitude" : "+44.478147", + "longitude" : "+26.117641", + "tz" : "+2", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "m247.ro" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.m247.ro/CPAN/", + "ftp" : null, + "rsync" : "rsync://mirrors.m247.ro/CPAN/", + "freq" : "3h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-03-25", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ro", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "met.hu", + "org" : "Hungarian Meteorological Service", + "city" : "Budapest", + "region" : null, + "country" : "Hungary", + "continent" : "Europe", + "latitude" : "+47.511150", + "longitude" : "+19.028450", + "tz" : "+1", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "lowinger.e", + "contact_site" : "met.hu" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.met.hu/CPAN/", + "ftp" : null, + "rsync" : "rsync://mirror.met.hu/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-12-18", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "hu", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "metrocast.net", + "org" : "MetroCast Cablevision", + "city" : "Rochester", + "region" : "New Hampshire", + "country" : "United States", + "continent" : "North America", + "latitude" : "+43.327", + "longitude" : "-70.975", + "tz" : "-5", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror-admin", + "contact_site" : "metrocast.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.metrocast.net/cpan/", + "ftp" : null, + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-02-14", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mirror.0x.sg", + "org" : "Andrew Yong", + "city" : "Singapore", + "region" : null, + "country" : "Singapore", + "continent" : "Asia", + "latitude" : "+1.283000", + "longitude" : "+103.850000", + "tz" : "+8", + "pipesize" : 10000, + "contact" : [ + { + "contact_user" : "me", + "contact_site" : "ndoo.sg" + } + ], + "src" : "rsync://ftpv6.cuhk.edu.hk/pub/packages/perl/CPAN/", + "http" : "http://mirror.0x.sg/CPAN/", + "ftp" : "ftp://mirror.0x.sg/CPAN/", + "rsync" : "rsync://mirror.0x.sg/CPAN/", + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-04-12", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "sg", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mirror.ac.za", + "org" : "TENET", + "city" : "Cape Town", + "region" : null, + "country" : "South Africa", + "continent" : "Africa", + "latitude" : "-33.93", + "longitude" : "18.47", + "tz" : "+2", + "pipesize" : 155, + "contact" : [ + { + "contact_user" : "mirroradmin", + "contact_site" : "tenet.ac.za" + } + ], + "src" : "rsync://www.cpan.org/CPAN/", + "http" : "http://cpan.mirror.ac.za/", + "ftp" : "ftp://cpan.mirror.ac.za/", + "rsync" : "rsync://mirror.ac.za/CPAN/", + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2007-05-21", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "za", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mirror.ba", + "org" : "Mirror.ba", + "city" : "Sarajevo", + "region" : null, + "country" : "Bosnia and Herzegovina", + "continent" : "Europe", + "latitude" : "+43.856259", + "longitude" : "+18.413076", + "tz" : "+1", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "mirror.ba" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirror.ba/", + "ftp" : "ftp://ftp.mirror.ba/CPAN/", + "rsync" : "rsync://cpan.mirror.ba/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-03-31", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "ba", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mirror.datacenter.by", + "org" : "RUE Beltelecom, Datacenter", + "city" : "Minsk", + "region" : null, + "country" : "Belarus", + "continent" : "Europe", + "latitude" : "+53.9010", + "longitude" : "+27.5855", + "tz" : "+3", + "pipesize" : 2000, + "contact" : [ + { + "contact_user" : "ftp", + "contact_site" : "mgts.by" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.datacenter.by/pub/CPAN/", + "ftp" : "ftp://mirror.datacenter.by/pub/CPAN/", + "rsync" : "rsync://mirror.datacenter.by/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-03-27", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "by", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mirror.ibcp.fr", + "org" : "CNRS IBCP", + "city" : "Lyon", + "region" : "Rhône-Alpes", + "country" : "France", + "continent" : "Europe", + "latitude" : "+45.76", + "longitude" : "+4.84", + "tz" : "+1", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "alexis.michon", + "contact_site" : "ibcp.fr" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.ibcp.fr/pub/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-23", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "fr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mirror.internode.on.net", + "org" : "Internode", + "city" : "Adelaide", + "region" : "South Australia", + "country" : "Australia", + "continent" : "Oceania", + "latitude" : "-34.9252", + "longitude" : "138.5985", + "tz" : "+9", + "pipesize" : 34, + "contact" : [ + { + "contact_user" : "support", + "contact_site" : "internode.on.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://mirror.internode.on.net/pub/cpan/", + "rsync" : "rsync://mirror.internode.on.net/cpan/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2007-08-01", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "au", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mirror.iphh.net", + "org" : "IPHH Internet Port Hamburg GmbH", + "city" : "Hamburg", + "region" : null, + "country" : "Germany", + "continent" : "Europe", + "latitude" : "53.54841", + "longitude" : "9.995327", + "tz" : "1", + "pipesize" : 622, + "contact" : [ + { + "contact_user" : "mirror-cpan", + "contact_site" : "iphh.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirror.iphh.net/", + "ftp" : "ftp://cpan.mirror.iphh.net/pub/CPAN/", + "rsync" : "rsync://cpan.mirror.iphh.net/CPAN/", + "freq" : "1h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-07-30", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mirror.its.dal.ca", + "org" : "Dalhousie University", + "city" : "Halifax", + "region" : "Nova Scotia", + "country" : "Canada", + "continent" : "North America", + "latitude" : "+44.637", + "longitude" : "-63.591", + "tz" : "-4", + "pipesize" : 1, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "lists.dal.ca" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.its.dal.ca/cpan/", + "ftp" : "ftp://mirror.its.dal.ca/cpan/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ca", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mirror.team-cymru.org", + "org" : "Team Cymru, Inc.", + "city" : "Chicago", + "region" : "Illinois", + "country" : "United States", + "continent" : "North America", + "latitude" : "+42.00", + "longitude" : "-87.96", + "tz" : "GMT-0600", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "noc", + "contact_site" : "cymru.com" + } + ], + "src" : "cpan.pair.org::CPAN", + "http" : "http://mirror.team-cymru.org/CPAN/", + "ftp" : "ftp://mirror.team-cymru.org/CPAN/", + "rsync" : "rsync://mirror.team-cymru.org/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-22", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mirrors-usa.go-parts.com", + "org" : "Go-Parts", + "city" : "Lancing", + "region" : "Michigan", + "country" : "United States", + "continent" : "North America", + "latitude" : "+42.725700", + "longitude" : "-84.636000", + "tz" : "-8", + "pipesize" : 250, + "contact" : [ + { + "contact_user" : "dan1487", + "contact_site" : "msn.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors-usa.go-parts.com/cpan/", + "ftp" : null, + "rsync" : "rsync://mirrors-usa.go-parts.com/mirrors/cpan/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-05-01", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mirrors.sonic.net", + "org" : "Sonic.net, Inc", + "city" : "San Francisco", + "region" : "California", + "country" : "United States", + "continent" : "North America", + "latitude" : "+37.723698", + "longitude" : "-122.398056", + "tz" : "-8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "soc", + "contact_site" : "sonic.net" + } + ], + "src" : "rsync://rsync.cs.uu.nl/CPAN/", + "http" : "http://mirrors.sonic.net/cpan/", + "ftp" : "ftp://mirrors.sonic.net/cpan/", + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-10-08", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mirrorservice.org", + "org" : "UK Mirror Service", + "city" : "Canterbury", + "region" : "England", + "country" : "United Kingdom", + "continent" : "Europe", + "latitude" : "51.29870", + "longitude" : "1.07005", + "tz" : "0", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "help", + "contact_site" : "mirrorservice.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://www.mirrorservice.org/sites/cpan.perl.org/CPAN/", + "ftp" : "ftp://ftp.mirrorservice.org/sites/cpan.perl.org/CPAN/", + "rsync" : "rsync://rsync.mirrorservice.org/cpan.perl.org/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2000-03-08", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "uk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mmgdesigns.com.ar", + "org" : "MMG Designs", + "city" : "Buenos Aires", + "region" : null, + "country" : "Argentina", + "continent" : "South America", + "latitude" : "-34.600", + "longitude" : "-58.450", + "tz" : "-3", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "hostmaster", + "contact_site" : "mmgdesigns.com.ar" + } + ], + "src" : "ftp.funet.fi", + "http" : "http://cpan.mmgdesigns.com.ar/", + "ftp" : null, + "rsync" : "rsync://mirrors.mmgdesigns.com.ar/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-25", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ar", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "mpi-inf.mpg.de", + "org" : "Max-Planck Institute for Informatics", + "city" : "Saarbrücken", + "region" : "Saarland", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "49.23109", + "longitude" : "6.99801", + "tz" : "+1", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "ftpadmin", + "contact_site" : "mpi-inf.mpg.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.mpi-inf.mpg.de/pub/perl/CPAN/", + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "1997-02-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "msg.com.mx", + "org" : "Matias Software Group", + "city" : "Mexico City", + "region" : "Distrito Federál", + "country" : "Mexico", + "continent" : "North America", + "latitude" : "19.4547", + "longitude" : "-99.1433", + "tz" : "-6", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "ftpadmin", + "contact_site" : "msg.com.mx" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://www.msg.com.mx/CPAN/", + "ftp" : "ftp://ftp.msg.com.mx/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1998-10-30", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "mx", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "muzzy.it", + "org" : "Emiliano Muzzurru Renzi", + "city" : "Arezzo", + "region" : null, + "country" : "Italy", + "continent" : "Europe", + "latitude" : "+43.466243", + "longitude" : "+11.860497", + "tz" : "+1", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "muzzy.it" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.muzzy.it/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-10-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "it", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "n5tech.com", + "org" : "N5 Tech, Inc", + "city" : "Phoenix", + "region" : "Arizona", + "country" : "United States", + "continent" : "North America", + "latitude" : "+33.434000", + "longitude" : "-112.012000", + "tz" : "-7", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "noc", + "contact_site" : "n5tech.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.n5tech.com/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-04-12", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "nac.net", + "org" : "Net Access LLC", + "city" : "Cedar Knolls", + "region" : "New Jersey", + "country" : "United States", + "continent" : "North America", + "latitude" : "+40.831793", + "longitude" : "-74.448853", + "tz" : "-4", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "sstogner", + "contact_site" : "corp.nac.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirror.nac.net/", + "ftp" : null, + "rsync" : null, + "freq" : "4h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-08-06", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "NAIST", + "org" : "Nara Institute of Science and Technology", + "city" : "Takayama-cho", + "region" : null, + "country" : "Japan", + "continent" : "Asia", + "latitude" : "34.75", + "longitude" : "135.73", + "tz" : "+9", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "ftp-admin", + "contact_site" : "is.naist.jp" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.nara.wide.ad.jp/pub/CPAN/", + "ftp" : "ftp://ftp.nara.wide.ad.jp/pub/CPAN/", + "rsync" : "rsync://ftp.nara.wide.ad.jp/cpan/", + "freq" : "1d", + "tier1" : "N", + "note" : "ftp max connection 100, rsync max connection 30", + "inceptdate" : "2006-01-01", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "jp", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "namecheap.com", + "org" : "NameCheap.com", + "city" : "Phoenix", + "region" : "Arizona", + "country" : "United States", + "continent" : "North America", + "latitude" : "+33.434000", + "longitude" : "-112.012000", + "tz" : "-7", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "bvierra", + "contact_site" : "namecheap.com" + } + ], + "src" : "mirrors.kernel.org", + "http" : "http://mirrors.namecheap.com/CPAN/", + "ftp" : "ftp://mirrors.namecheap.com/CPAN/", + "rsync" : "rsync://mirrors.namecheap.com/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2015-03-08", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "nautile.nc", + "org" : "Nautile (ISP)", + "city" : "Nouméa", + "region" : null, + "country" : "New Caledonia", + "continent" : "Oceania", + "latitude" : "-22.267865", + "longitude" : "166.461952", + "tz" : "+11", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "admin", + "contact_site" : "nautile.nc" + } + ], + "src" : "mirror.internode.on.net", + "http" : "http://cpan.nautile.nc/CPAN/", + "ftp" : "ftp://cpan.nautile.nc/CPAN/", + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2009-07-12", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "nc", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "navercorp.com", + "org" : "NAVER Business Platform Corp.", + "city" : "Bundang", + "region" : null, + "country" : "Republic of Korea", + "continent" : "Asia", + "latitude" : "+37.359000", + "longitude" : "+127.105000", + "tz" : "+9", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "dl_mirror_admin", + "contact_site" : "navercorp.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.navercorp.com/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-04-12", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "kr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "nbtelecom.com.br", + "org" : "NB Telecom", + "city" : "Rio de Janeiro", + "region" : null, + "country" : "Brazil", + "continent" : "South America", + "latitude" : "-22.908496", + "longitude" : "-43.221205", + "tz" : "-3", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "noc", + "contact_site" : "nbtelecom.com.br" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.nbtelecom.com.br/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-07-12", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "br", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "nctu.edu.tw", + "org" : "National Chiao Tung University", + "city" : "HsinChu", + "region" : null, + "country" : "Taiwan", + "continent" : "Asia", + "latitude" : "24.787576", + "longitude" : "120.996778", + "tz" : "+8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "shelling", + "contact_site" : "cpan.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.nctu.edu.tw/", + "ftp" : "ftp://cpan.nctu.edu.tw/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : "", + "inceptdate" : "2002-05-06", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "tw", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "neacm.fe.up.pt", + "org" : "Faculdade de Engenharia da Universidade do Porto (Faculty of Engineering at the University of Porto)", + "city" : "Porto", + "region" : null, + "country" : "Portugal", + "continent" : "Europe", + "latitude" : "41.18", + "longitude" : "-8.60", + "tz" : "+0", + "pipesize" : 80, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "fe.up.pt" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.fe.up.pt/pub/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-01-01", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "pt", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "neolabs.kz", + "org" : "Neolabs LLP", + "city" : "Almaty", + "region" : null, + "country" : "Kazakhstan", + "continent" : "Asia", + "latitude" : "+43.306", + "longitude" : "+76.896", + "tz" : "+6", + "pipesize" : 300, + "contact" : [ + { + "contact_user" : "support", + "contact_site" : "neolabs.kz" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.neolabs.kz/CPAN/", + "ftp" : "ftp://mirror.neolabs.kz/CPAN/", + "rsync" : "rsync://mirror.neolabs.kz/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-23", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "kz", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "neowiz.com", + "org" : "NeowizGames Corp.", + "city" : "Seoul", + "region" : null, + "country" : "Republic of Korea", + "continent" : "Asia", + "latitude" : "+37.4820", + "longitude" : "+126.8800", + "tz" : "+9", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "ftpadm", + "contact_site" : "neowiz.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.neowiz.com/CPAN/", + "ftp" : "ftp://ftp.neowiz.com/CPAN/", + "rsync" : "rsync://ftp.neowiz.com/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-05-29", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "kr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "netbet.org", + "org" : "NetBet.org Free Online Gambling", + "city" : "Düsseldorf", + "region" : "Nordrhein-Westfalen", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "+51.226300", + "longitude" : "+6.776780", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "webmaster", + "contact_site" : "netbet.org" + } + ], + "src" : "rsync://cpan.inode.at/", + "http" : "http://cpan.netbet.org/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-03-01", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "netcologne.de", + "org" : "NetCologne GmbH", + "city" : "Cologne", + "region" : null, + "country" : "Germany", + "continent" : "Europe", + "latitude" : "50.94169", + "longitude" : "6.95504", + "tz" : "+1", + "pipesize" : 2000, + "contact" : [ + { + "contact_user" : "mirror-service", + "contact_site" : "netcologne.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.netcologne.de/cpan/", + "ftp" : "ftp://mirror.netcologne.de/cpan/", + "rsync" : "rsync://mirror.netcologne.de/cpan/", + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-10-25", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "neterra.net", + "org" : "Neterra LTD - Sofia Data Center", + "city" : "Sofia", + "region" : null, + "country" : "Bulgaria", + "continent" : "Europe", + "latitude" : "+42.655960", + "longitude" : "+23.369546", + "tz" : "+2", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "neterra.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.neterra.net/CPAN/", + "ftp" : "ftp://mirrors.neterra.net/CPAN/", + "rsync" : "rsync://mirrors.neterra.net/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2013-05-25", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "bg", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "netix.net", + "org" : "Netix LTD", + "city" : "Sofia", + "region" : null, + "country" : "Bulgaria", + "continent" : "Europe", + "latitude" : "+42.655960", + "longitude" : "+23.369546", + "tz" : "+2", + "pipesize" : 4000, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "netix.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.netix.net/CPAN/", + "ftp" : "ftp://mirrors.netix.net/CPAN/", + "rsync" : "rsync://mirrors.netix.net/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-02-07", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "bg", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "neusoft.edu.cn", + "org" : "Dalian Neusoft University of Information", + "city" : "Dalian", + "region" : "Liaoning", + "country" : "China", + "continent" : "Asia", + "latitude" : "+38.8903", + "longitude" : "+121.5353", + "tz" : "+8", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "sfl", + "contact_site" : "neusoft.edu.cn" + } + ], + "src" : "mirrors.kernel.org::CPAN", + "http" : "http://mirrors.neusoft.edu.cn/cpan/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-10-17", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "cn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "nic.cz", + "org" : "CZ.NIC", + "city" : "Prague", + "region" : null, + "country" : "Czech Republic", + "continent" : "Europe", + "latitude" : "+50.080764", + "longitude" : "+14.450715", + "tz" : "+1", + "pipesize" : 10000, + "contact" : [ + { + "contact_user" : "ondrej.sury", + "contact_site" : "nic.cz" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.nic.cz/CPAN/", + "ftp" : "ftp://mirrors.nic.cz/pub/CPAN/", + "rsync" : "rsync://mirrors.nic.cz/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-01-08", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "cz", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "nl.leaseweb.net", + "org" : "Leaseweb", + "city" : "Haarlem", + "region" : null, + "country" : "Netherlands", + "continent" : "Europe", + "latitude" : "52.391245", + "longitude" : "4.665534", + "tz" : "+1", + "pipesize" : 4000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "leaseweb.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.nl.leaseweb.net/CPAN/", + "ftp" : "ftp://mirror.nl.leaseweb.net/CPAN/", + "rsync" : "rsync://mirror.nl.leaseweb.net/CPAN/", + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-12-28", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "nl", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "nluug.nl", + "org" : "Dutch Unix Users Group NLUUG", + "city" : "Amsterdam", + "region" : "Noord-Holland", + "country" : "Netherlands", + "continent" : "Europe", + "latitude" : "52.354999", + "longitude" : "4.957912", + "tz" : "+1", + "pipesize" : 3000, + "contact" : [ + { + "contact_user" : "ftpmirror-beheer", + "contact_site" : "nluug.nl" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.nluug.nl/languages/perl/CPAN/", + "ftp" : "ftp://ftp.nluug.nl/pub/languages/perl/CPAN/", + "rsync" : "rsync://ftp.nluug.nl/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "1998-07-09", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "nl", + "aka_name" : null, + "A_or_CNAME" : "ftp.nluug.nl" + }, + { + "name" : "nrc.ca", + "org" : "Ottawa Internet Exchange", + "city" : "Ottawa", + "region" : "Ontario", + "country" : "Canada", + "continent" : "North America", + "latitude" : "45.419807", + "longitude" : "-75.70056", + "tz" : "-5", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "wmaton", + "contact_site" : "ottix.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.ottix.net/pub/CPAN/", + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : "", + "inceptdate" : "1996-08-05", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "ca", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ntua.gr", + "org" : "Ethnikon Metsovion Polytechnion (National Technical University of Athens)", + "city" : "Athens", + "region" : null, + "country" : "Greece", + "continent" : "Europe", + "latitude" : "37.978444", + "longitude" : "23.782062", + "tz" : "+2", + "pipesize" : "1000", + "contact" : [ + { + "contact_user" : "ftpadm", + "contact_site" : "ntua.gr" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.ntua.gr/pub/lang/perl/", + "ftp" : "ftp://ftp.ntua.gr/pub/lang/perl/", + "rsync" : "rsync://ftp.ntua.gr/CPAN/", + "freq" : "4h", + "tier1" : "N", + "note" : null, + "inceptdate" : "1998-12-05", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "gr", + "aka_name" : "gr.cpan.org", + "A_or_CNAME" : "achilles.noc.ntua.gr" + }, + { + "name" : "nyi.net", + "org" : "The New York Internet Company", + "city" : "New York", + "region" : "New York", + "country" : "United States", + "continent" : "North America", + "latitude" : "40.71", + "longitude" : "-74.01", + "tz" : "-5", + "pipesize" : 20, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "nyi.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.nyi.net/CPAN/", + "ftp" : "ftp://mirror.nyi.net/pub/CPAN/", + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2007-05-20", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "oleane.net", + "org" : "France Telecom Transpac", + "city" : "Paris", + "region" : "Île-de-France", + "country" : "France", + "continent" : "Europe", + "latitude" : "48.85424", + "longitude" : "2.34486", + "tz" : "+1", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "ftpmaint", + "contact_site" : "oleane.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.oleane.net/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2004-05-30", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "fr", + "aka_name" : "fr.cpan.org", + "A_or_CNAME" : "ftp.oleane.net" + }, + { + "name" : "optusnet.com.au", + "org" : "Optus", + "city" : "Sydney", + "region" : "New South Wales", + "country" : "Australia", + "continent" : "Oceania", + "latitude" : "-33.860", + "longitude" : "+151.211", + "tz" : "+10", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "staff.optusnet.com.au" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.optusnet.com.au/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "8h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-23", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "au", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "osl.ugr.es", + "org" : "Oficina de Software Libre de la Universidad de Granada", + "city" : "Granada", + "region" : "Andalucía", + "country" : "Spain", + "continent" : "Europe", + "latitude" : "37.18638888", + "longitude" : "-3.77749999", + "tz" : "+1", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "dirosl", + "contact_site" : "ugr.es" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://osl.ugr.es/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2009-03-31", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "es", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "oss.lzu.edu.cn", + "org" : "Lanzhou University Open Source Society", + "city" : "Lanzhou", + "region" : "Gansu", + "country" : "China", + "continent" : "Asia", + "latitude" : "+36.048064", + "longitude" : "+103.859077", + "tz" : "+8", + "pipesize" : 2000, + "contact" : [ + { + "contact_user" : "oss.lzu.edu.cn", + "contact_site" : "gmail.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.lzu.edu.cn/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-04-01", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "cn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "osuosl.org", + "org" : "Oregon State University Open Source Lab", + "city" : "Corvallis", + "region" : "Oregon", + "country" : "United States", + "continent" : "North America", + "latitude" : "44.56", + "longitude" : "-123.26", + "tz" : "-8", + "pipesize" : 622, + "contact" : [ + { + "contact_user" : "support", + "contact_site" : "osuosl.org" + } + ], + "src" : "mirrors.kernel.org", + "http" : "http://ftp.osuosl.org/pub/CPAN/", + "ftp" : "ftp://ftp.osuosl.org/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2005-02-01", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ovh.net", + "org" : "OVH", + "city" : "Roubaix", + "region" : "Nord-Pas-de-Calais", + "country" : "France", + "continent" : "Europe", + "latitude" : "50.691998", + "longitude" : "3.199946", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "ovh.net" + } + ], + "src" : "rsync.nic.funet.fi", + "http" : "http://cpan.mirrors.ovh.net/ftp.cpan.org/", + "ftp" : "ftp://cpan.mirrors.ovh.net/ftp.cpan.org/", + "rsync" : "rsync://cpan.mirrors.ovh.net/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2002-05-05", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "fr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ox.ac.uk", + "org" : "Computing Services, University of Oxford", + "city" : "Oxford", + "region" : null, + "country" : "United Kingdom", + "continent" : "Europe", + "latitude" : "51.76", + "longitude" : "-1.26", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "sysdev", + "contact_site" : "oucs.ox.ac.uk" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.ox.ac.uk/sites/www.cpan.org/", + "ftp" : "ftp://mirror.ox.ac.uk/sites/www.cpan.org/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2009-05-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "uk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "perl-hackers.net", + "org" : "Universidade do Minho", + "city" : "Braga", + "region" : null, + "country" : "Portugal", + "continent" : "Europe", + "latitude" : "+41.560998", + "longitude" : "-8.396322", + "tz" : "+0", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "ambs", + "contact_site" : "cpan.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.perl-hackers.net/", + "ftp" : null, + "rsync" : "rsync://cpan.perl-hackers.net/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-03-31", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "pt", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "perl.com", + "org" : "The O'Reilly Network's perl.com", + "city" : "Sebastopol", + "region" : "California", + "country" : "United States", + "continent" : "North America", + "latitude" : "38.4030", + "longitude" : "-122.8188", + "tz" : "-8", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "cpan", + "contact_site" : "www.perl.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://www.perl.com/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1997-04-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "perl.enstimac.fr", + "org" : "Ecole des Mines d'Albi-Carmaux", + "city" : "Albi", + "region" : "Midi-Pyrénées", + "country" : "France", + "continent" : "Europe", + "latitude" : "43.933", + "longitude" : "2.133", + "tz" : "+1", + "pipesize" : 2, + "contact" : [ + { + "contact_user" : "paul.gaborit", + "contact_site" : "enstimac.fr" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.enstimac.fr/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2003-03-11", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "fr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "perl.pt", + "org" : "Associação Portugesa de Programadores Perl", + "city" : "Lisboa", + "region" : null, + "country" : "Portugal", + "continent" : "Europe", + "latitude" : "38.78789", + "longitude" : "-9.12496", + "tz" : "0", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "cpan-mirror", + "contact_site" : "perl.pt" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.perl.pt/", + "ftp" : null, + "rsync" : "rsync://cpan.perl.pt/cpan/", + "freq" : "4h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-06-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "pt", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "pesat.net.id", + "org" : "PSN", + "city" : "Jakarta", + "region" : null, + "country" : "Indonesia", + "continent" : "Asia", + "latitude" : "-6.232469", + "longitude" : "+106.829153", + "tz" : "+7", + "pipesize" : 200, + "contact" : [ + { + "contact_user" : "budi", + "contact_site" : "pesat.net.id" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.pesat.net.id/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-06-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "id", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "petamem.com", + "org" : "PetaMem GmbH", + "city" : "Nüremberg", + "region" : null, + "country" : "Germany", + "continent" : "Europe", + "latitude" : "49.41", + "longitude" : "11.07", + "tz" : "+1", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "info", + "contact_site" : "petamem.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://mirror.petamem.com/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-01-08", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "piotrkosoft.net", + "org" : "Piotrkosoft - Data Storage Center", + "city" : "Oswiecim", + "region" : "Malopolskie", + "country" : "Poland", + "continent" : "Europe", + "latitude" : "50.0333", + "longitude" : "19.2333", + "tz" : "+1", + "pipesize" : 10, + "contact" : [ + { + "contact_user" : "admin", + "contact_site" : "piotrkosoft.net" + } + ], + "src" : "funet.fi", + "http" : "http://ftp.piotrkosoft.net/pub/mirrors/CPAN/", + "ftp" : "ftp://ftp.piotrkosoft.net/pub/mirrors/CPAN/", + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : "Access through IPv4 and IPv6.", + "inceptdate" : "2007-05-21", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "pl", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "pirbot.com", + "org" : "ComunidadHosting", + "city" : "Zurich", + "region" : null, + "country" : "Switzerland", + "continent" : "Europe", + "latitude" : "+47.368650", + "longitude" : "+8.539183", + "tz" : "+0", + "pipesize" : 10, + "contact" : [ + { + "contact_user" : "info", + "contact_site" : "comunidadhosting.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://www.pirbot.com/mirrors/cpan/", + "ftp" : null, + "rsync" : "rsync://rsync.pirbot.com/ftp/cpan/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-11-25", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "ch", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "planet-elektronik.de", + "org" : "PLANET-Elektronik GmbH", + "city" : "Chemnitz", + "region" : null, + "country" : "Germany", + "continent" : "Europe", + "latitude" : "53.5833", + "longitude" : "13.1500", + "tz" : "+2", + "pipesize" : 2, + "contact" : [ + { + "contact_user" : "cardb", + "contact_site" : "planet-elektronik.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://www.planet-elektronik.de/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : null, + "retiredate" : null, + "dnsrr" : null, + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "poliwangi.ac.id", + "org" : "State Polytechnic of Banyuwangi", + "city" : "Banyuwangi", + "region" : "East Java", + "country" : "Indonesia", + "continent" : "Asia", + "latitude" : "-8.294509", + "longitude" : "+114.307095", + "tz" : "+7", + "pipesize" : 10, + "contact" : [ + { + "contact_user" : "banksonk", + "contact_site" : "poliwangi.ac.id" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.poliwangi.ac.id/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-06-18", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "id", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "portalus.net", + "org" : "Portalus Group", + "city" : "Brooklyn", + "region" : "New York", + "country" : "United States", + "continent" : "North America", + "latitude" : "+40.6400", + "longitude" : "-73.9400", + "tz" : "-4", + "pipesize" : 15, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "portalus.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://noodle.portalus.net/CPAN/", + "ftp" : "ftp://noodle.portalus.net/CPAN/", + "rsync" : "rsync://noodle.portalus.net/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-03-30", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "pregi.net", + "org" : "Advanced Science and Technology Institute", + "city" : "Quezon City", + "region" : null, + "country" : "Philippines", + "continent" : "Asia", + "latitude" : "+14.647195", + "longitude" : "+121.071463", + "tz" : "+8", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "bert", + "contact_site" : "asti.dost.gov.ph" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.pregi.net/CPAN/", + "ftp" : "ftp://mirror.pregi.net/CPAN/", + "rsync" : null, + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-02-07", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "ph", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ps.pl", + "org" : "West Pomeranian University of Technology", + "city" : "Szczecin", + "region" : null, + "country" : "Poland", + "continent" : "Europe", + "latitude" : "53.42", + "longitude" : "14.53", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "adam", + "contact_site" : "popik.pl" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.ps.pl/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2009-09-23", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "pl", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "qnren.qa", + "org" : "Qatar National Research and Education Network", + "city" : "Doha", + "region" : null, + "country" : "Qatar", + "continent" : "Asia", + "latitude" : "+25.374700", + "longitude" : "+51.490300", + "tz" : "+3", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "qnren.qa" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.qnren.qa/CPAN/", + "ftp" : "ftp://mirror.qnren.qa/CPAN/", + "rsync" : "rsync://mirror.qnren.qa/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-02-07", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "qa", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "rbc.ru", + "org" : "RosBusinessConsulting", + "city" : "Moscow", + "region" : null, + "country" : "Russian Federation", + "continent" : "Europe", + "latitude" : "+55.6598", + "longitude" : "+37.5395", + "tz" : "+4", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "cpan-mirror-lst", + "contact_site" : "rbc.ru" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan-mirror.rbc.ru/pub/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-04-11", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ru", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "rediris.es", + "org" : "Red Académica y de Investigación Nacional Española (Spanish Academic Network for Research and Development)", + "city" : "Madrid", + "region" : null, + "country" : "Spain", + "continent" : "Europe", + "latitude" : "40.42031", + "longitude" : "-3.70562", + "tz" : "+1", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "ftp", + "contact_site" : "rediris.es" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.rediris.es/mirror/CPAN/", + "ftp" : "ftp://ftp.rediris.es/mirror/CPAN/", + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "1998-12-05", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "es", + "aka_name" : "es.cpan.org", + "A_or_CNAME" : "ftp.rediris.es" + }, + { + "name" : "riken.jp", + "org" : "RIKEN", + "city" : "Wako-shi", + "region" : "Saitama-Ken", + "country" : "Japan", + "continent" : "Asia", + "latitude" : "35.7803", + "longitude" : "139.6140", + "tz" : "+9", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "ftp-admin", + "contact_site" : "ftp.riken.jp" + } + ], + "src" : "ftp.funet.fi", + "http" : "http://ftp.riken.jp/lang/CPAN/", + "ftp" : "ftp://ftp.riken.jp/lang/CPAN/", + "rsync" : "rsync://ftp.riken.jp/cpan/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-06-25", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "jp", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "rise.ph", + "org" : "Rise", + "city" : "Cebu", + "region" : null, + "country" : "Philippines", + "continent" : "Asia", + "latitude" : "+10.324442", + "longitude" : "+123.908855", + "tz" : "+8", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "noc", + "contact_site" : "rise.ph" + } + ], + "src" : "rsync://ftp.yzu.edu.tw/pub/CPAN/", + "http" : "http://mirror.rise.ph/cpan/", + "ftp" : "ftp://mirror.rise.ph/cpan/", + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2015-07-05", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "ph", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "rit.edu", + "org" : "Rochester Institute of Technology", + "city" : "Rochester", + "region" : "New York", + "country" : "United States", + "continent" : "North America", + "latitude" : "43.154", + "longitude" : "-77.615", + "tz" : "-5", + "pipesize" : 200, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "rit.edu" + } + ], + "src" : "rsync://cpan.mirrors.tds.net/CPAN/", + "http" : "http://mirrors.rit.edu/CPAN/", + "ftp" : "ftp://mirrors.rit.edu/CPAN/", + "rsync" : "rsync://mirrors.rit.edu/cpan/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-03-11", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "rol.ru", + "org" : "GoldenTelecom, ROL", + "city" : "Moscow", + "region" : null, + "country" : "Russian Federation", + "continent" : "Europe", + "latitude" : "55.73117", + "longitude" : "37.645683", + "tz" : "+3", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "webmaster", + "contact_site" : "mirror.rol.ru" + } + ], + "src" : "ftp.funet.fi::CPAN", + "http" : "http://mirror.rol.ru/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-06-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ru", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "rs.163.com", + "org" : "Netease", + "city" : "Hangzhou", + "region" : null, + "country" : "China", + "continent" : "Asia", + "latitude" : "+30.30", + "longitude" : "+120.20", + "tz" : "+8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "service.netease.com" + } + ], + "src" : "mirrors.kernel.org", + "http" : "http://mirrors.163.com/cpan/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-21", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "cn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "rwth-aachen.de", + "org" : "RWTH Aachen University", + "city" : "Aachen", + "region" : "Nordrhein-Westfalen", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "+50.781301", + "longitude" : "+6.065633", + "tz" : "+1", + "pipesize" : 20000, + "contact" : [ + { + "contact_user" : "ftp", + "contact_site" : "halifax.rwth-aachen.de" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.halifax.rwth-aachen.de/cpan/", + "ftp" : "ftp://ftp.halifax.rwth-aachen.de/cpan/", + "rsync" : "rsync://ftp.halifax.rwth-aachen.de/cpan/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-02-01", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "saix.net", + "org" : "South African Internet eXchange (SAIX)", + "city" : "Parow", + "region" : "Western Cape", + "country" : "South Africa", + "continent" : "Africa", + "latitude" : "-33.9064", + "longitude" : "18.5631", + "tz" : "+2", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "ftp", + "contact_site" : "saix.net" + } + ], + "src" : "rsync://rsync.cs.uu.nl/CPAN/", + "http" : "http://cpan.saix.net/", + "ftp" : "ftp://ftp.saix.net/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1999-10-06", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "za", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "sbb.rs", + "org" : "Serbia BroadBand", + "city" : "Belgrade", + "region" : null, + "country" : "Serbia", + "continent" : "Europe", + "latitude" : "+44.7477", + "longitude" : "+20.3960", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "sbb.rs" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.sbb.rs/CPAN/", + "ftp" : "ftp://mirror.sbb.rs/CPAN/", + "rsync" : "rsync://mirror.sbb.rs/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-03-17", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "rs", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "sby.datautama.net.id", + "org" : "Datautama Dinamika - datautama-net-id", + "city" : "Surabaya", + "region" : "East Java", + "country" : "Indonesia", + "continent" : "Asia", + "latitude" : "-7.265", + "longitude" : "+112.743", + "tz" : "+7", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "noc", + "contact_site" : "sby.datautama.net.id" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://kartolo.sby.datautama.net.id/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-02-09", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "id", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "serversaustralia.com.au", + "org" : "Servers Australia Pty. Ltd.", + "city" : "Sydney", + "region" : "New South Wales", + "country" : "Australia", + "continent" : "Oceania", + "latitude" : "-33.902170", + "longitude" : "+151.203082", + "tz" : "+10", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "serversaustralia.com.au" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirror.serversaustralia.com.au/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2013-06-04", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "au", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "softaculous.com", + "org" : "Softaculous ltd", + "city" : "Hürth", + "region" : null, + "country" : "Germany", + "continent" : "Europe", + "latitude" : "+50.877", + "longitude" : "+6.876", + "tz" : "+1", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "brijesh", + "contact_site" : "softaculous.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.softaculous.com/cpan/", + "ftp" : null, + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-06-14", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "sohu.com", + "org" : "Sohu, Inc", + "city" : "Beijing", + "region" : null, + "country" : "China", + "continent" : "Asia", + "latitude" : "+39.912", + "longitude" : "+116.379", + "tz" : "+8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "girl111_2002", + "contact_site" : "hotmail.com" + }, + { + "contact_user" : "mirror", + "contact_site" : "sohu-inc.com" + } + ], + "src" : "ftp.tw.debian.org/pub/CPAN/", + "http" : "http://mirrors.sohu.com/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-23", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "cn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "sunsite.dcc.uchile.cl", + "org" : "Departamento de Ciencias de la Computación, Facultad de Ciencias Físicas y Matemáticas de la Universidad de Chile (Department of Computing Sciences, Faculty of Physical and Mathematical Sciences of the University of Chile)", + "city" : "Santiago", + "region" : null, + "country" : "Chile", + "continent" : "South America", + "latitude" : "-33.45", + "longitude" : "-70.666", + "tz" : "-4", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "sistemas", + "contact_site" : "dcc.uchile.cl" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.dcc.uchile.cl/", + "ftp" : "ftp://cpan.dcc.uchile.cl/pub/lang/cpan/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1998-12-05", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "cl", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "sunsite.icm.edu.pl", + "org" : "Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego Uniwersytet Warszawski (Interdisciplinary Centre for Mathematical and Computational Modeling)", + "city" : "Warsaw", + "region" : "Mazowieckie", + "country" : "Poland", + "continent" : "Europe", + "latitude" : "52.2478", + "longitude" : "21.0208", + "tz" : "+1", + "pipesize" : 34, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "icm.edu.pl" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://sunsite.icm.edu.pl/pub/CPAN/", + "ftp" : "ftp://sunsite.icm.edu.pl/pub/CPAN/", + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "1997-03-27", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "pl", + "aka_name" : "pl.cpan.org", + "A_or_CNAME" : "sunsite.icm.edu.pl" + }, + { + "name" : "switch.ch", + "org" : "SWITCHmirror", + "city" : "Zürich", + "region" : null, + "country" : "Switzerland", + "continent" : "Europe", + "latitude" : "47.37704", + "longitude" : "8.53951", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "switch.ch" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.switch.ch/ftp/mirror/CPAN/", + "ftp" : "ftp://mirror.switch.ch/mirror/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1995-10-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ch", + "aka_name" : "ch.cpan.org", + "A_or_CNAME" : "sunsite.cnlab-switch.ch" + }, + { + "name" : "syringanetworks.net", + "org" : "Syringa Networks", + "city" : "Boise", + "region" : "Idaho", + "country" : "United States", + "continent" : "North America", + "latitude" : "+43.5681", + "longitude" : "-116.2103", + "tz" : "+0", + "pipesize" : 1, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "syringanetworks.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.syringanetworks.net/CPAN/", + "ftp" : "ftp://mirrors.syringanetworks.net/CPAN/", + "rsync" : "rsync://mirrors.syringanetworks.net/CPAN/", + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-03-27", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "teentelecom.net", + "org" : "TeenTelecom", + "city" : "Bucharest", + "region" : null, + "country" : "Romania", + "continent" : "Europe", + "latitude" : "+44.482", + "longitude" : "+26.121", + "tz" : "+2", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "noc", + "contact_site" : "teentelecom.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.teentelecom.net/CPAN/", + "ftp" : "ftp://mirrors.teentelecom.net/CPAN/", + "rsync" : "rsync://mirrors.teentelecom.net/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-09-14", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "ro", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "teklinks.com", + "org" : "TekLinks", + "city" : "Birmingham", + "region" : "Alabama", + "country" : "United States", + "continent" : "North America", + "latitude" : "+33.570", + "longitude" : "-86.750", + "tz" : "-6", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "hosting", + "contact_site" : "teklinks.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.teklinks.com/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-06-30", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ticklers.org", + "org" : "Ticklers", + "city" : "London", + "region" : null, + "country" : "United Kingdom", + "continent" : "Europe", + "latitude" : "51.52", + "longitude" : "-0.08", + "tz" : "0", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "ftp-mirror", + "contact_site" : "ticklers.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.ticklers.org/pub/CPAN/", + "ftp" : "ftp://ftp.ticklers.org/pub/CPAN/", + "rsync" : "rsync://ftp.ticklers.org/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-10-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "uk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "transip.nl", + "org" : "TransIP", + "city" : "Amsterdam", + "region" : null, + "country" : "Netherlands", + "continent" : "Europe", + "latitude" : "+52.391016", + "longitude" : "+4.847513", + "tz" : "+1", + "pipesize" : 4000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "transip.nl" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.transip.net/CPAN/", + "ftp" : "ftp://mirror.transip.net/CPAN/", + "rsync" : "rsync://mirror.transip.net/CPAN/", + "freq" : "4h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-06-19", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "nl", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "triple-it.nl", + "org" : "Triple IT", + "city" : "Amsterdam", + "region" : null, + "country" : "Netherlands", + "continent" : "Europe", + "latitude" : "+52.302", + "longitude" : "+4.939", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "triple-it.nl" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirror.triple-it.nl/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-01-05", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "nl", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "tudelft.nl", + "org" : "Delft University of Technology", + "city" : "Delft", + "region" : "Zuid-Holland", + "country" : "Netherlands", + "continent" : "Europe", + "latitude" : "+52.000998", + "longitude" : "+4.369268", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "ftpadmin", + "contact_site" : "tudelft.nl" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.tudelft.nl/cpan/", + "ftp" : "ftp://ftp.tudelft.nl/pub/CPAN/", + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2013-10-07", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "nl", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "tux.rainside.sk", + "org" : "Rainside", + "city" : "Bratislava", + "region" : null, + "country" : "Slovakia", + "continent" : "Europe", + "latitude" : "+48.143", + "longitude" : "+17.109", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "tux", + "contact_site" : "rainside.sk" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://tux.rainside.sk/CPAN/", + "ftp" : "ftp://tux.rainside.sk/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-23", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "sk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "u-aizu.ac.jp", + "org" : "University of Aizu", + "city" : "Aizu-Wakamatsu", + "region" : "Fukushima", + "country" : "Japan", + "continent" : "Asia", + "latitude" : "37.4333", + "longitude" : "139.9821", + "tz" : "+9", + "pipesize" : 6, + "contact" : [ + { + "contact_user" : "ftp-admin", + "contact_site" : "u-aizu.ac.jp" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.u-aizu.ac.jp/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1996-01-01", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "jp", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "u-tx.net", + "org" : "Computing Pages", + "city" : "Nüremberg", + "region" : null, + "country" : "Germany", + "continent" : "Europe", + "latitude" : "+49.44", + "longitude" : "+11.07", + "tz" : "+1", + "pipesize" : 1, + "contact" : [ + { + "contact_user" : "francesc", + "contact_site" : "u-tx.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.u-tx.net/CPAN/", + "ftp" : "ftp://ftp.u-tx.net/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-19", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "uber.com.au", + "org" : "UberGlobal Pty Ltd", + "city" : "Sydney", + "region" : "New South Wales", + "country" : "Australia", + "continent" : "Oceania", + "latitude" : "-33.876401", + "longitude" : "151.197861", + "tz" : "+10", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "uber.com.au" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.uberglobalmirror.com/", + "ftp" : null, + "rsync" : "rsync://uberglobalmirror.com/cpan/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-06-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "au", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ubuntu-tw.org", + "org" : "Ubuntu-TW LoCo Team", + "city" : "Puli", + "region" : "Nantou", + "country" : "Taiwan", + "continent" : "Asia", + "latitude" : "+23.950800", + "longitude" : "+120.934803", + "tz" : "+8", + "pipesize" : 4000, + "contact" : [ + { + "contact_user" : "bluet", + "contact_site" : "bluet.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.ubuntu-tw.org/mirror/CPAN/", + "ftp" : "ftp://ftp.ubuntu-tw.org/mirror/CPAN/", + "rsync" : "rsync://ftp.ubuntu-tw.org/CPAN/", + "freq" : "4h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-05-17", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "tw", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ucr.ac.cr", + "org" : "Centro de Informatica, Universidad de Costa Rica (Computing Center, University of Costa Rica)", + "city" : "San Pedro", + "region" : "San José Province", + "country" : "Costa Rica", + "continent" : "North America", + "latitude" : "9.93", + "longitude" : "-84.079", + "tz" : "-6", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "software.libre", + "contact_site" : "ucr.ac.cr" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.ucr.ac.cr/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1997-07-19", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "cr", + "aka_name" : "cr.cpan.org", + "A_or_CNAME" : "ftp.ucr.ac.cr" + }, + { + "name" : "ucu.ac.ug", + "org" : "Uganda Christian University", + "city" : "Mukono", + "region" : null, + "country" : "Uganda", + "continent" : "Africa", + "latitude" : "+0.3516", + "longitude" : "+32.9194", + "tz" : "+0", + "pipesize" : 10, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "ucu.ac.ug" + } + ], + "src" : "mirror.ucu.ac.ug", + "http" : "http://mirror.ucu.ac.ug/cpan/", + "ftp" : null, + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-04-30", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ug", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ugent.be", + "org" : "Ghent University Library", + "city" : "Gent", + "region" : null, + "country" : "Belgium", + "continent" : "Europe", + "latitude" : "+51.0451", + "longitude" : "+3.7252", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "libservice", + "contact_site" : "ugent.be" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://lib.ugent.be/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-06-17", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "be", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "uib.no", + "org" : "University of Bergen", + "city" : "Bergen", + "region" : null, + "country" : "Norway", + "continent" : "Europe", + "latitude" : "+60.389", + "longitude" : "+5.330", + "tz" : "+1", + "pipesize" : 10000, + "contact" : [ + { + "contact_user" : "sundrift", + "contact_site" : "it.uib.no" + } + ], + "src" : "rsync://ftp.uninett.no/cpan/", + "http" : "http://cpan.uib.no/", + "ftp" : "ftp://cpan.uib.no/pub/CPAN/", + "rsync" : "rsync://cpan.uib.no/cpan/", + "freq" : "2h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "no", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "uk2.net", + "org" : "UK2", + "city" : "London", + "region" : null, + "country" : "United Kingdom", + "continent" : "Europe", + "latitude" : "51.5", + "longitude" : "-0.17", + "tz" : "0", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "uk2.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirrors.uk2.net/", + "ftp" : "ftp://mirrors.uk2.net/pub/CPAN/", + "rsync" : "rsync://mirrors.uk2.net/CPAN/", + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-03-11", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "uk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ukhost4u.co.uk", + "org" : "UKHost4u", + "city" : "London", + "region" : "England", + "country" : "United Kingdom", + "continent" : "Europe", + "latitude" : "+51.500683", + "longitude" : "-0.709290", + "tz" : "+0", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "paul", + "contact_site" : "ukhost4u.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.ukhost4u.com/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2015-05-31", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "uk", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ulak.net.tr", + "org" : "TUBITAK ULAKBIM", + "city" : "Ankara", + "region" : null, + "country" : "Turkey", + "continent" : "Asia", + "latitude" : "+39.916", + "longitude" : "+32.83", + "tz" : "+2", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "admins", + "contact_site" : "ulakbim.gov.tr" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.ulak.net.tr/", + "ftp" : "ftp://ftp.ulak.net.tr/pub/perl/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-01-01", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "tr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "uni-altai.ru", + "org" : "Altai State Pedagogical Academy", + "city" : "Barnaul", + "region" : null, + "country" : "Russian Federation", + "continent" : "Europe", + "latitude" : "+53.349", + "longitude" : "+83.796", + "tz" : "+7", + "pipesize" : 10, + "contact" : [ + { + "contact_user" : "wmaster", + "contact_site" : "uni-altai.ru" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.uni-altai.ru/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ru", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "unicorncloud.org", + "org" : "UnicornCloud.org", + "city" : "Falkenstein", + "region" : "Bayern", + "country" : "Germany", + "continent" : "Europe", + "latitude" : "+50.473576", + "longitude" : "+12.338727", + "tz" : "+1", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "kontakt", + "contact_site" : "unicorncloud.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.reismil.ch/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2015-07-07", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "de", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "uninett.no", + "org" : "University of Oslo / Uninett", + "city" : "Oslo", + "region" : null, + "country" : "Norway", + "continent" : "Europe", + "latitude" : "59.9104", + "longitude" : "10.7524", + "tz" : "+1", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "ftp-drift", + "contact_site" : "uio.no" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://ftp.uninett.no/pub/languages/perl/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1998-12-05", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "no", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "uoregon.edu", + "org" : "University of Oregon", + "city" : "Eugene", + "region" : "Oregon", + "country" : "United States", + "continent" : "North America", + "latitude" : "44.05", + "longitude" : "-123.0833", + "tz" : "-8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "nethelp", + "contact_site" : "ithelp.uoregon.edu" + } + ], + "src" : "mirrors.kernel.org", + "http" : "http://mirror.uoregon.edu/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2007-10-04", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "us.leaseweb.net", + "org" : "LeaseWeb", + "city" : "Manassas", + "region" : "Virginia", + "country" : "United States", + "continent" : "North America", + "latitude" : "+38.751", + "longitude" : "-77.476", + "tz" : "-5", + "pipesize" : 2000, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "leaseweb.com" + } + ], + "src" : "cpan-rsync.perl.org", + "http" : "http://mirror.us.leaseweb.net/CPAN/", + "ftp" : "ftp://mirror.us.leaseweb.net/CPAN/", + "rsync" : "rsync://mirror.us.leaseweb.net/CPAN/", + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-10-10", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "ustc.edu.cn", + "org" : "Linux User Group, University of Science and Technology", + "city" : "Hefei", + "region" : "AnHui", + "country" : "China", + "continent" : "Asia", + "latitude" : "+31.870", + "longitude" : "+117.230", + "tz" : "+8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "lug", + "contact_site" : "ustc.edu.cn" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.ustc.edu.cn/CPAN/", + "ftp" : "ftp://mirrors.ustc.edu.cn/CPAN/", + "rsync" : "rsync://mirrors.ustc.edu.cn/CPAN/", + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-04-20", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "cn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "uta.edu", + "org" : "The University of Texas at Arlington", + "city" : "Arlington", + "region" : "Texas", + "country" : "United States", + "continent" : "North America", + "latitude" : "32.74", + "longitude" : "-97.11", + "tz" : "-5", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "mirror-admin", + "contact_site" : "uta.edu" + } + ], + "src" : "cpan.pair.com::CPAN", + "http" : "http://mirror.uta.edu/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-01-01", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "uwsg.iu.edu", + "org" : "Unix Workstation Support Group, Indiana University Bloomington", + "city" : "Bloomington", + "region" : "Indiana", + "country" : "United States", + "continent" : "North America", + "latitude" : "39.166", + "longitude" : "-86.521", + "tz" : "-5", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "uwsg", + "contact_site" : "indiana.edu" + } + ], + "src" : "ftp.funet.fi", + "http" : null, + "ftp" : "ftp://ftp.uwsg.iu.edu/pub/perl/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1998-01-20", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "vianett.no", + "org" : "ViaNett AS", + "city" : "Moss", + "region" : "Østfold", + "country" : "Norway", + "continent" : "Europe", + "latitude" : "+59.4210", + "longitude" : "+10.6750", + "tz" : "+2", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "vianett.no" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.vianett.no/", + "ftp" : null, + "rsync" : "rsync://cpan.vianett.no/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-10-01", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "no", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "vinahost.vn", + "org" : "VinaHost Co.,ltd", + "city" : "Ho Chi Minh City", + "region" : null, + "country" : "Viet Nam", + "continent" : "Asia", + "latitude" : "+10.80023180", + "longitude" : "+106.66679080", + "tz" : "+7", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "mirror-admin", + "contact_site" : "vinahost.vn" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.vinahost.vn/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2013-07-31", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "vn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "vit.com.tr", + "org" : "Vital Teknoloji", + "city" : "Bursa", + "region" : null, + "country" : "Turkey", + "continent" : "Asia", + "latitude" : "+40.200", + "longitude" : "+28.930", + "tz" : "+2", + "pipesize" : 1000000, + "contact" : [ + { + "contact_user" : "admin", + "contact_site" : "vit.com.tr" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.vit.com.tr/mirror/CPAN/", + "ftp" : "ftp://mirror.vit.com.tr/CPAN/", + "rsync" : null, + "freq" : "1h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-02-19", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "tr", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "vutbr.cz", + "org" : "Brno University of Technology", + "city" : "Brno", + "region" : null, + "country" : "Czech Republic", + "continent" : "Europe", + "latitude" : "+49.201582", + "longitude" : "+16.603337", + "tz" : "+1", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "mirror-adm", + "contact_site" : "cis.vutbr.cz" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.mirror.vutbr.cz/", + "ftp" : "ftp://mirror.vutbr.cz/cpan/", + "rsync" : "rsync://cpan.mirror.vutbr.cz/cpan/", + "freq" : "instant", + "tier1" : "Y", + "note" : null, + "inceptdate" : "2014-04-02", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "cz", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "wa.co.za", + "org" : "Web Africa Networks", + "city" : "Cape Town", + "region" : null, + "country" : "South Africa", + "continent" : "Africa", + "latitude" : "-33.970", + "longitude" : "+18.464", + "tz" : "+2", + "pipesize" : 155, + "contact" : [ + { + "contact_user" : "support", + "contact_site" : "webafrica.co.za" + } + ], + "src" : "mirror.ac.za::cpan", + "http" : "http://ftp.wa.co.za/pub/CPAN/", + "ftp" : "ftp://ftp.wa.co.za/pub/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "za", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "waia.asn.au", + "org" : "WA Internet Association", + "city" : "Perth", + "region" : "Western Australia", + "country" : "Australia", + "continent" : "Oceania", + "latitude" : "-31.952", + "longitude" : "+115.859", + "tz" : "+8", + "pipesize" : 1, + "contact" : [ + { + "contact_user" : "hostmaster", + "contact_site" : "waia.asn.au" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.waia.asn.au/pub/cpan/", + "ftp" : null, + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-23", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "au", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "wanxp.id", + "org" : "WANXP", + "city" : "Pekanbaru", + "region" : "Riau", + "country" : "Indonesia", + "continent" : "Asia", + "latitude" : "+0.536288", + "longitude" : "+101.444666", + "tz" : "+7", + "pipesize" : 300, + "contact" : [ + { + "contact_user" : "support", + "contact_site" : "wanxp.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.wanxp.id/cpan/", + "ftp" : null, + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2015-12-23", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "id", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "wayne.edu", + "org" : "Wayne State University", + "city" : "Detroit", + "region" : "Michigan", + "country" : "United States", + "continent" : "North America", + "latitude" : "42.364", + "longitude" : "-83.069", + "tz" : "-5", + "pipesize" : 622, + "contact" : [ + { + "contact_user" : "adamlincoln", + "contact_site" : "wayne.edu" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.wayne.edu/CPAN/", + "ftp" : "ftp://ftp.wayne.edu/CPAN/", + "rsync" : null, + "freq" : "12h", + "tier1" : "N", + "note" : "HTTP unlimited users, FTP limited to 40 users.", + "inceptdate" : "2006-03-05", + "retiredate" : null, + "dnsrr" : "N", + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "webdesk.ru", + "org" : "WEB DESK, LLC", + "city" : "Moscow", + "region" : null, + "country" : "Russian Federation", + "continent" : "Europe", + "latitude" : "+55.798088", + "longitude" : "+37.600842", + "tz" : "+3", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "webdesk.ru", + "contact_site" : "it" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.webdesk.ru/", + "ftp" : "ftp://cpan.webdesk.ru/cpan/", + "rsync" : "rsync://cpan.webdesk.ru/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2014-10-17", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ru", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "webtastix.net", + "org" : "Webtastix Internet Services", + "city" : "Auckland", + "region" : null, + "country" : "New Zealand", + "continent" : "Oceania", + "latitude" : "-36.867", + "longitude" : "+174.767", + "tz" : "+12", + "pipesize" : 10, + "contact" : [ + { + "contact_user" : "mirrors", + "contact_site" : "webtastix.net" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.webtastix.net/CPAN/", + "ftp" : "ftp://mirror.webtastix.net/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-02-16", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "nz", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "weepee.org", + "org" : "WeePee telecom", + "city" : "Brussels", + "region" : null, + "country" : "Belgium", + "continent" : "Europe", + "latitude" : "50.51", + "longitude" : "4.24", + "tz" : "+1", + "pipesize" : 200, + "contact" : [ + { + "contact_user" : "joeri", + "contact_site" : "weepee.org" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.weepeetelecom.be/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-10-25", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "be", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "xmission.com", + "org" : "XMission Internet", + "city" : "Salt Lake City", + "region" : "Utah", + "country" : "United States", + "continent" : "North America", + "latitude" : "40.771", + "longitude" : "-111.891", + "tz" : null, + "pipesize" : null, + "contact" : [ + { + "contact_user" : "mirror", + "contact_site" : "xmission.com" + } + ], + "src" : "ftp.funet.fi", + "http" : null, + "ftp" : "ftp://mirror.xmission.com/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "1998-08-18", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "xmu.edu.cn", + "org" : "Information and Network Center, Xiamen University", + "city" : "Xiamen", + "region" : "Fujian", + "country" : "China", + "continent" : "Asia", + "latitude" : "+24.437", + "longitude" : "+118.097", + "tz" : "+8", + "pipesize" : 1000, + "contact" : [ + { + "contact_user" : "yu_yuwei", + "contact_site" : "xmu.edu.cn" + } + ], + "src" : "cpan.mirror.iphh.net::CPAN", + "http" : "http://mirrors.xmu.edu.cn/CPAN/", + "ftp" : "ftp://mirrors.xmu.edu.cn/CPAN/", + "rsync" : "rsync://mirrors.xmu.edu.cn/CPAN/", + "freq" : "1h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2011-01-24", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "cn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "xs4all.nl", + "org" : "XS4ALL", + "city" : "Amsterdam", + "region" : "Noord-Holland", + "country" : "Netherlands", + "continent" : "Europe", + "latitude" : "52.37269", + "longitude" : "4.89296", + "tz" : "+1", + "pipesize" : null, + "contact" : [ + { + "contact_user" : "unixbeheer", + "contact_site" : "xs4all.nl" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : null, + "ftp" : "ftp://download.xs4all.nl/pub/mirror/CPAN/", + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2000-10-09", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "nl", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "xservers.ro", + "org" : "xServers Romania", + "city" : "Bucharest", + "region" : null, + "country" : "Romania", + "continent" : "Europe", + "latitude" : "44.4", + "longitude" : "26.1", + "tz" : "+2", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "tehnic", + "contact_site" : "xservers.ro" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirrors.xservers.ro/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "2d", + "tier1" : "N", + "note" : "seepds up to 1 Gps within Romania", + "inceptdate" : "2008-06-26", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "ro", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "yahoo.com", + "org" : "Yahoo, Inc.", + "city" : "Sunnyvale", + "region" : "California", + "country" : "United States", + "continent" : "North America", + "latitude" : "37.3667", + "longitude" : "-122.0333", + "tz" : "-8", + "pipesize" : 44, + "contact" : [ + { + "contact_user" : "cpan", + "contact_site" : "yahoo-inc.com" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://cpan.yimg.com/", + "ftp" : null, + "rsync" : null, + "freq" : "1d", + "tier1" : "N", + "note" : null, + "inceptdate" : "2008-06-26", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "us", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "yandex.ru", + "org" : "Yandex", + "city" : "Moscow", + "region" : null, + "country" : "Russian Federation", + "continent" : "Europe", + "latitude" : "+55.7340", + "longitude" : "+37.5880", + "tz" : "+3", + "pipesize" : 1, + "contact" : [ + { + "contact_user" : "opensource", + "contact_site" : "yandex-team.ru" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.yandex.ru/mirrors/cpan/", + "ftp" : "ftp://mirror.yandex.ru/mirrors/cpan/", + "rsync" : "rsync://mirror.yandex.ru/mirrors/cpan/", + "freq" : "12h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2012-11-15", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ru", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "yazd.ac.ir", + "org" : "Yazd University", + "city" : "Yazd", + "region" : null, + "country" : "Iran", + "continent" : "Asia", + "latitude" : "+31.832831", + "longitude" : "+54.349873", + "tz" : "+0", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "fatemi", + "contact_site" : "yazd.ac.ir" + } + ], + "src" : "mirror.netcologne.de::cpan", + "http" : "http://mirror.yazd.ac.ir/cpan/", + "ftp" : null, + "rsync" : null, + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2013-12-12", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "ir", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "yz.yamagata-u.ac.jp", + "org" : "Yamagata", + "city" : "Yonezawa", + "region" : "Yamagata-ken", + "country" : "Japan", + "continent" : "Asia", + "latitude" : "37.897", + "longitude" : "140.108", + "tz" : "+9", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "www-admin", + "contact_site" : "ftp.yz.yamagata-u.ac.jp" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/", + "ftp" : "ftp://ftp.yz.yamagata-u.ac.jp/pub/lang/cpan/", + "rsync" : null, + "freq" : "6h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2006-04-17", + "retiredate" : null, + "dnsrr" : "Y", + "ccode" : "jp", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "zju.edu.cn", + "org" : "Zhejiang University", + "city" : "Zhejiang", + "region" : "Zhejiang", + "country" : "China", + "continent" : "Asia", + "latitude" : "+30.263867", + "longitude" : "+120.123450", + "tz" : "+8", + "pipesize" : 10000, + "contact" : [ + { + "contact_user" : "vxst", + "contact_site" : "vxst.org" + } + ], + "src" : "rsync://mirrors.kernel.org/CPAN/", + "http" : "http://mirrors.zju.edu.cn/CPAN/", + "ftp" : null, + "rsync" : null, + "freq" : "24h", + "tier1" : "N", + "note" : null, + "inceptdate" : "2016-02-07", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "cn", + "aka_name" : null, + "A_or_CNAME" : null + }, + { + "name" : "zol.co.zw", + "org" : "Zimbabwe Online", + "city" : "Harare", + "region" : null, + "country" : "Zimbabwe", + "continent" : "Africa", + "latitude" : "-17.831544", + "longitude" : "+31.052655", + "tz" : "+2", + "pipesize" : 100, + "contact" : [ + { + "contact_user" : "anthony", + "contact_site" : "somersettechsolutions.co.uk" + } + ], + "src" : "rsync://cpan-rsync.perl.org/CPAN/", + "http" : "http://mirror.zol.co.zw/CPAN/", + "ftp" : "ftp://mirror.zol.co.zw/CPAN/", + "rsync" : "rsync://mirror.zol.co.zw/CPAN/", + "freq" : "instant", + "tier1" : "N", + "note" : null, + "inceptdate" : "2013-12-23", + "retiredate" : null, + "dnsrr" : null, + "ccode" : "zw", + "aka_name" : null, + "A_or_CNAME" : null + } +] + diff --git a/wait-for-es.sh b/wait-for-es.sh new file mode 100755 index 000000000..47cdb4d7b --- /dev/null +++ b/wait-for-es.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# Courtesy of @fxdgear +# https://github.com/elastic/elasticsearch-py/issues/778#issuecomment-384389668 + +set -ux + + +HOST="$1" +CONTAINER=${2:-""} +PREAMBLE="" + +echo "container |$CONTAINER|" +if [[ $CONTAINER != "" ]]; then + PREAMBLE="docker-compose exec $CONTAINER" +fi + +while true; do + response=$($PREAMBLE curl --write-out '%{http_code}' --silent --fail --output /dev/null "$HOST") + if [[ "$response" -eq "200" ]]; then + break + fi + + echo "Elastic Search is unavailable - sleeping" >&2 + sleep 1 +done + +# set -e now because it was causing the curl command above to exit the script +# if the server was not available +set -e + +COUNTER=0 +MAX_LOOPS=60 +while true; do + ## Wait for ES status to turn to yellow. + ## TODO: Ideally we'd be waiting for green, but we need multiple nodes for that. + health=$($PREAMBLE curl -fsSL "$HOST/_cat/health?format=JSON" | jq '.[0].status == "yellow" or .[0].status == "green"') + if [[ $health == 'true' ]]; then + echo "Elasticsearch is up" >&2 + break + fi + echo "Elastic Search is unavailable ($health) - sleeping" >&2 + COUNTER=$((COUNTER + 1)) + if [[ $COUNTER -gt $MAX_LOOPS ]]; then + echo "Giving up after $COUNTER attempts" + exit 1 + break + fi + sleep 1 +done + +# Allow commands to be chained +shift +shift +exec "$@" diff --git a/wait-for-it.sh b/wait-for-it.sh new file mode 100755 index 000000000..33e0d0e00 --- /dev/null +++ b/wait-for-it.sh @@ -0,0 +1,202 @@ +#!/bin/bash +# +# See https://github.com/vishnubob/wait-for-it +# +# The MIT License (MIT) +# Copyright (c) 2016 Giles Hall + +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +#!/usr/bin/env bash +# Use this script to test if a given TCP host/port are available + +cmdname=$(basename $0) + +echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } + +usage() +{ + cat << USAGE >&2 +Usage: + $cmdname host:port [-s] [-t timeout] [-- command args] + -h HOST | --host=HOST Host or IP under test + -p PORT | --port=PORT TCP port under test + Alternatively, you specify the host and port as host:port + -s | --strict Only execute subcommand if the test succeeds + -q | --quiet Don't output any status messages + -t TIMEOUT | --timeout=TIMEOUT + Timeout in seconds, zero for no timeout + -- COMMAND ARGS Execute command with args after the test finishes +USAGE + exit 1 +} + +wait_for() +{ + if [[ $TIMEOUT -gt 0 ]]; then + echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT" + else + echoerr "$cmdname: waiting for $HOST:$PORT without a timeout" + fi + start_ts=$(date +%s) + while : + do + if [[ $ISBUSY -eq 1 ]]; then + nc -z $HOST $PORT + result=$? + else + (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1 + result=$? + fi + if [[ $result -eq 0 ]]; then + end_ts=$(date +%s) + echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds" + break + fi + sleep 1 + done + return $result +} + +wait_for_wrapper() +{ + # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 + if [[ $QUIET -eq 1 ]]; then + timeout $BUSYTIMEFLAG $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & + else + timeout $BUSYTIMEFLAG $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & + fi + PID=$! + trap "kill -INT -$PID" INT + wait $PID + RESULT=$? + if [[ $RESULT -ne 0 ]]; then + echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT" + fi + return $RESULT +} + +# process arguments +while [[ $# -gt 0 ]] +do + case "$1" in + *:* ) + hostport=(${1//:/ }) + HOST=${hostport[0]} + PORT=${hostport[1]} + shift 1 + ;; + --child) + CHILD=1 + shift 1 + ;; + -q | --quiet) + QUIET=1 + shift 1 + ;; + -s | --strict) + STRICT=1 + shift 1 + ;; + -h) + HOST="$2" + if [[ $HOST == "" ]]; then break; fi + shift 2 + ;; + --host=*) + HOST="${1#*=}" + shift 1 + ;; + -p) + PORT="$2" + if [[ $PORT == "" ]]; then break; fi + shift 2 + ;; + --port=*) + PORT="${1#*=}" + shift 1 + ;; + -t) + TIMEOUT="$2" + if [[ $TIMEOUT == "" ]]; then break; fi + shift 2 + ;; + --timeout=*) + TIMEOUT="${1#*=}" + shift 1 + ;; + --) + shift + CLI=("$@") + break + ;; + --help) + usage + ;; + *) + echoerr "Unknown argument: $1" + usage + ;; + esac +done + +if [[ "$HOST" == "" || "$PORT" == "" ]]; then + echoerr "Error: you need to provide a host and port to test." + usage +fi + +TIMEOUT=${TIMEOUT:-15} +STRICT=${STRICT:-0} +CHILD=${CHILD:-0} +QUIET=${QUIET:-0} + +# check to see if timeout is from busybox? +# check to see if timeout is from busybox? +TIMEOUT_PATH=$(realpath $(which timeout)) +if [[ $TIMEOUT_PATH =~ "busybox" ]]; then + ISBUSY=1 + BUSYTIMEFLAG="-t" +else + ISBUSY=0 + BUSYTIMEFLAG="" +fi + +if [[ $CHILD -gt 0 ]]; then + wait_for + RESULT=$? + exit $RESULT +else + if [[ $TIMEOUT -gt 0 ]]; then + wait_for_wrapper + RESULT=$? + else + wait_for + RESULT=$? + fi +fi + +if [[ $CLI != "" ]]; then + if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then + echoerr "$cmdname: strict mode, refusing to execute subprocess" + exit $RESULT + fi + exec "${CLI[@]}" +else + exit $RESULT +fi diff --git a/xt/README.txt b/xt/README.txt new file mode 100644 index 000000000..6dec4f427 --- /dev/null +++ b/xt/README.txt @@ -0,0 +1,7 @@ +# Tests in here are for development only + +# Setup port forwarding to our staging server +ssh -L 9200:localhost:9200 leo@bm-mc-02.metacpan.org + +# Run tests - with ES env +bin/prove_live xt/... diff --git a/xt/search_web.t b/xt/search_web.t new file mode 100644 index 000000000..33e19143d --- /dev/null +++ b/xt/search_web.t @@ -0,0 +1,42 @@ +use strict; +use warnings; +use lib 't/lib'; + +# USE `bin/prove_live` to run this +# READ the README.txt in this dir + +use MetaCPAN::Query::Search (); +use MetaCPAN::TestServer (); +use Test::More; + +# Just use this to get an es object. +my $server = MetaCPAN::TestServer->new; +my $search = MetaCPAN::Query::Search->new( es => $server->es_client ); + +my %tests = ( + 'anyevent http' => 'AnyEvent::HTTP', + 'anyevent' => 'AnyEvent', + 'AnyEvent' => 'AnyEvent', + 'dbi' => 'DBI', + 'dbix class resultset' => 'DBIx::Class::ResultSet', + 'DBIx::Class' => 'DBIx::Class', + 'Dist::Zilla' => 'Dist::Zilla', + 'HTML::Element' => 'HTML::Element', + 'HTML::TokeParser' => 'HTML::TokeParser', + 'net dns' => 'Net::DNS', + 'net::amazon::s3' => 'Net::Amazon::S3', + 'Perl::Critic' => 'Perl::Critic', +); + +for my $q ( sort keys %tests ) { + my $match = $tests{$q}; + my $returned = $search->search_web($q); + my $first_match = $returned->{results}->[0]->[0]; + + is( $first_match->{documentation}, + $match, "Search for ${q} matched ${match}" ); + + # or diag Dumper($first_match); +} + +done_testing();