Skip to content
This repository has been archived by the owner on Oct 15, 2022. It is now read-only.

Commit

Permalink
Merge pull request #143 from duckduckgo/zaahir/duckpan-new-more-updates
Browse files Browse the repository at this point in the history
More updates to duckpan new
  • Loading branch information
moollaza committed Oct 24, 2014
2 parents cc6d1cb + 57e9fcc commit 679c743
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 101 deletions.
100 changes: 95 additions & 5 deletions lib/App/DuckPAN.pm
Expand Up @@ -22,6 +22,7 @@ use Encode;
use Path::Class;
use Perl::Version;
use File::Path;
use IO::All;

our $VERSION ||= '9.999';

Expand Down Expand Up @@ -53,7 +54,6 @@ sub _ua_string {
my ($self) = @_;
my $class = ref $self || $self;
my $version = $class->VERSION;

return "$class/$version";
}

Expand All @@ -80,6 +80,71 @@ has term => (

sub _build_term { Term::ReadLine->new('duckpan') }

has ia_types => (
is => 'ro',
lazy => 1,
builder => '_build_ia_types',
);

sub _build_ia_types {
my @ddg_bits = ('lib', 'DDG');
my $t_dir = io('t');
return [{
name => 'Goodie',
dir => dir(@ddg_bits, 'Goodie'),
supported => 1,
templates => {
code => {
in => io('template/lib/DDG/Goodie/Example.pm'),
out => io(join '/', @ddg_bits, 'Goodie')
},
test => {
in => io('template/t/Example.t'),
out => $t_dir
},
},
},
{
name => 'Spice',
dir => dir(@ddg_bits, 'Spice'),
supported => 1,
templates => {
code => {
in => io('template/lib/DDG/Spice/Example.pm'),
out => io(join '/', @ddg_bits, 'Spice')
},
test => {
in => io('template/t/Example.t'),
out => $t_dir
},
handlebars => {
in => io('template/share/spice/example/example.handlebars'),
out => io('share/spice')
},
js => {
in => io('template/share/spice/example/example.js'),
out => io('share/spice')
},
},
},
{
name => 'Fathead',
dir => dir(@ddg_bits, 'Fathead'),
supported => 0
},
{
name => 'Longtail',
dir => dir(@ddg_bits, 'Longtail'),
supported => 0
},
{
name => 'DuckPAN',
dir => dir('lib', 'App', 'DuckPAN'),
supported => -1 # Supported, with warning.
},
];
}

sub get_reply {
my ( $self, $prompt, %params ) = @_;
my $return = $self->term->get_reply( prompt => $prompt, %params );
Expand Down Expand Up @@ -144,7 +209,7 @@ has perl => (
lazy => 1,
);

sub _build_perl {
sub _build_perl {
load_class('App::DuckPAN::Perl');
App::DuckPAN::Perl->new( app => shift );
}
Expand All @@ -155,7 +220,7 @@ has ddg => (
lazy => 1,
);

sub _build_ddg {
sub _build_ddg {
load_class('App::DuckPAN::DDG');
App::DuckPAN::DDG->new( app => shift );
}
Expand Down Expand Up @@ -195,6 +260,7 @@ sub execute {

sub print_text {
shift;
return unless @_;
for (@_) {
print "\n";
my @words = split(/\s+/,$_);
Expand All @@ -213,6 +279,14 @@ sub print_text {
print "\n";
}

sub exit_with_msg {
my ($self, $exit_code, @msg) = @_;

$self->print_text('[ERROR] ' . shift @msg) if (@msg);
$self->print_text(@msg);
exit $exit_code;
}

sub camel_to_underscore {
my ($self, $name) = @_;
# Replace first capital by lowercase
Expand Down Expand Up @@ -382,6 +456,22 @@ sub checking_dukgo_user {
$response->code == 302 ? 1 : 0; # workaround, need something in dukgo
}

sub get_ia_type {
my ($self) = @_;

my $ia_type = first { -d $_->{dir} } @{$self->ia_types};

$self->exit_with_msg(-1, 'Must be run from the root of a checked-out Instant Answer repository.') unless ($ia_type);

if ($ia_type->{supported} == 0) {
$self->exit_with_msg(-1, "Sorry, DuckPAN does not support " . $ia_type->{name} . " yet!");
} elsif ($ia_type->{supported} == -1) {
$self->print_text("[WARN] You are in the " . $ia_type->{name} . " directory. I assume you know what you're doing?");
}

return $ia_type;
}

sub BUILD {
my ( $self ) = @_;
if ($^O eq 'MSWin32') {
Expand Down Expand Up @@ -436,11 +526,11 @@ B<IRC>:
We invite you to join us at B<#duckduckgo> on B<irc.freenode.net> for any queries and lively discussion.
B<Repository>:
L<https://github.com/duckduckgo/p5-app-duckpan>
B<Issue Tracker>:
L<https://github.com/duckduckgo/p5-app-duckpan/issues>
=cut
129 changes: 42 additions & 87 deletions lib/App/DuckPAN/Cmd/New.pm
Expand Up @@ -16,110 +16,65 @@ use Text::Xslate qw(mark_raw);
use IO::All;

sub run {
my ( $self, @args ) = @_;
my ($self, @args) = @_;

# Check which IA repo we're in...
my $type = "";
if (-d "./lib/DDG/Goodie") {
$type = "Goodie";
} elsif (-d "./lib/DDG/Spice") {
$type = "Spice";
} elsif (-d "./lib/DDG/Fathead") {
$type = "Fathead";
$self->app->print_text("[ERROR] Sorry, DuckPAN does not support Fatheads yet!");
exit -1;
} elsif (-d "./lib/DDG/Longtail") {
$type = "Longtail";
$self->app->print_text("[ERROR] Sorry, DuckPAN does not support Longtails yet!");
exit -1;
} else {
$self->app->print_text("[ERROR] No lib/DDG/Goodie, lib/DDG/Spice, lib/DDG/Fathead or lib/DDG/Longtail found");
exit -1;
}
my $type = $self->app->get_ia_type();

# Instant Answer name as parameter
my $entered_name = (@args) ? join(' ', @args) : $self->app->get_reply('Please enter a name for your Instant Answer');
$entered_name =~ s/\//::/g; #change "/" to "::" for easier handling
$self->app->exit_with_msg(-1, "Must supply a name for your Instant Answer.") unless $entered_name;
$entered_name =~ s/\//::/g; #change "/" to "::" for easier handling
my $name = $self->app->phrase_to_camel($entered_name);
my ($path, $lc_path) = ("", "");
my $package_name = $name;
my $separated_name = $package_name;
my ($package_name, $separated_name, $path, $lc_path) = ($name, $name, "", "");
$separated_name =~ s/::/ /g;

if ($entered_name =~ m/::/) {
my @path_parts = split(/::/, $entered_name);
$name = pop @path_parts;
$path = join("/", @path_parts);
$lc_path = join("/", map { $self->app->camel_to_underscore($_) } @path_parts);
if (scalar @path_parts > 1) {
$name = pop @path_parts;
$path = join("/", @path_parts);
$lc_path = join("/", map { $self->app->camel_to_underscore($_) } @path_parts);
} else {
$self->app->exit_with_msg(-1, "Malformed input. Please provide a properly formatted package name for your Instant Answer.");
}
}

my $lc_name = $self->app->camel_to_underscore($name);
my $lc_name = $self->app->camel_to_underscore($name);
my $filepath = ($path eq "") ? $name : "$path/$name";
my $lc_filepath = ($lc_path eq "") ? $lc_name : "$lc_path/$lc_name";
if (scalar $lc_path) {
$lc_path =~ s/\//_/g; #safe to modify, we already used this in $lc_filepath
$lc_name = $lc_path . "_" . $lc_name;
}

# %templates forms the spine data structure which is used
# as a guide to discovering content which is moved around
my %templates = (
Goodie => {
dirs => [
"./lib/DDG/Goodie/$path",
"./t/$path",
],
files => {
"./template/lib/DDG/Goodie/Example.pm" => "./lib/DDG/Goodie/$path/$name.pm",
"./template/t/Example.t" => "./t/$path/$name.t",
},
},
$self->app->exit_with_msg(-1, "No templates exist for this IA Type: " . $type->{name}) if (!defined $type->{templates});

Spice => {
share_dir => "./share/spice/$lc_path/$lc_name",
dirs => [
"./lib/DDG/Spice/$path",
"./t/$path",
"./share/spice/$lc_path",
"./share/spice/$lc_path",
],
files => {
"./template/lib/DDG/Spice/Example.pm" => "./lib/DDG/Spice/$path/$name.pm",
"./template/t/Example.t" => "./t/$path/$name.t",
"./template/share/spice/example/example.handlebars" => "./share/spice/$lc_path/$lc_name/$lc_name.handlebars",
"./template/share/spice/example/example.js" => "./share/spice/$lc_path/$lc_name/$lc_name.js"
}
},
Fathead => {
# [TODO] Implement Fathead templates
},
Longtail => {
# [TODO] Implement Fathead templates
}
my %template_info = %{$type->{templates}};
my $tx = Text::Xslate->new();
my %files = (
test => ["$filepath.t"],
code => ["$filepath.pm"],
handlebars => [$lc_filepath, "$lc_name.handlebars"],
js => [$lc_filepath, "$lc_name.js"]);
my %vars = (
ia_name => $name,
ia_package_name => $package_name,
ia_name_separated => $separated_name,
lia_name => $lc_name,
ia_path => $filepath
);

while (my ($source, $dest) = each(%{$templates{$type}{'files'}})) {
my $io = io($dest);
if ($io->exists) {
my $filename = $io->filename;
my $filepath= $io->filepath;
$self->app->print_text("[ERROR] File already exists: \"$filename\" in $filepath");
exit -1;
}
unless (-e $source) {
$self->app->print_text("[ERROR] Template does not exist: $source");
exit -1;
}

my $tx = Text::Xslate->new();
$lc_path =~ s/\//_/g;
my %vars = (
ia_name => $name,
ia_package_name => $package_name,
ia_name_separated => $separated_name,
lia_name => $lc_path."_".$lc_name,
ia_path => $path
);

my $content = $tx->render($source, \%vars);
$io->file->assert->append($content); #create file path and append to file
foreach my $template_type (sort keys %template_info) {
my ($source, $dest) = ($template_info{$template_type}{in}, $template_info{$template_type}{out});
$self->app->exit_with_msg(-1, 'Template does not exist: ' . $source) unless ($source->exists);
# Update dest based on type:
$dest = $dest->file(join '/', @{$files{$template_type}});
$self->app->exit_with_msg(-1, 'File already exists: "' . $dest->filename . '" in ' . $dest->filepath) if ($dest->exists);
my $content = $tx->render("$source", \%vars);
$dest->file->assert->append($content); #create file path and append to file
$self->app->print_text("Created file: $dest");
}
$self->app->print_text("Successfully created $type: $package_name");
$self->app->print_text("Successfully created " . $type->{name} . ": $package_name");
}

1;
13 changes: 4 additions & 9 deletions lib/App/DuckPAN/Perl.pm
Expand Up @@ -59,16 +59,15 @@ sub get_local_version {
}

sub cpanminus_install_error {
shift->app->print_text(
"[ERROR] Failure on installation of modules!",
shift->app->exit_with_msg(1,
"Failure on installation of modules!",
"There are several possible explanations and fixes for this error:",
"1. The download from CPAN was unsuccessful - Please restart this installer.",
"2. Some other error occured - Please read the `build.log` mentioned in the errors and see if you can fix the problem yourself.",
"If you are unable to solve the problem, please let us know by making a GitHub Issue in the DuckPAN Repo:",
"https://github.com/duckduckgo/p5-app-duckpan/issues",
"Make sure to attach the `build.log` file if it exists. Otherwise, copy/paste the output you see."
);
exit 1;
}

sub duckpan_install {
Expand All @@ -85,7 +84,6 @@ sub duckpan_install {
if (is_success(getstore($self->app->duckpan_packages,$tempfile))) {
my $packages = Parse::CPAN::Packages::Fast->new($tempfile);
my @to_install;
my $error = 0;
for (@modules) {
my $module = $packages->package($_);
if ($module) {
Expand Down Expand Up @@ -118,17 +116,14 @@ sub duckpan_install {
}
push @to_install, $duckpan_module_url if ($install_it && !(first { $_ eq $duckpan_module_url } @to_install));
} else {
$self->app->print_text("[ERROR] Can't find package ".$_." on ".$self->app->duckpan."\n");
$error = 1;
$self->app->exit_with_msg(1, "Can't find package ".$_." on ".$self->app->duckpan);
}
}
return 1 if $error;
return 0 unless @to_install;
unshift @to_install,'-f' if ($force_install); # cpanm will do the actual forcing.
return system("cpanm ".join(" ",@to_install));
} else {
$self->app->print_text("[ERROR] Can't reach duckpan at ".$self->app->duckpan."!\n");
return 1;
$self->app->exit_with_msg(1, "Can't reach duckpan at ".$self->app->duckpan."!");
}
}

Expand Down

0 comments on commit 679c743

Please sign in to comment.