App-Fetchware

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

t/App-Fetchware-config-file.t
t/App-Fetchware-download.t
t/App-Fetchware-end.t
t/App-Fetchware-install.t
t/App-Fetchware-lookup.t
t/App-Fetchware-new
t/App-Fetchware-new-fetchwarefile_name
t/App-Fetchware-new-get_filter_option
t/App-Fetchware-new-get_mirrors
t/App-Fetchware-new-get_verification
t/App-Fetchware-new-prompt_for_other_options
t/App-Fetchware-new.t
t/App-Fetchware-new_install.t
t/App-Fetchware-start.t
t/App-Fetchware-unarchive.t
t/App-Fetchware-uninstall.t
t/App-Fetchware-upgrade.t
t/App-Fetchware-verify.t
t/App-FetchwareX-HTMLPageSync-new
t/App-FetchwareX-HTMLPageSync-new-ask_about_keep_destination_directory
t/App-FetchwareX-HTMLPageSync-new-get_destination_directory

bin/fetchware  view on Meta::CPAN




###BUGALERT### Move cmd_new() before install()?????
###BUGALERT### Print out fetchware's assumptions it makes about what FTP & hTTP
#lookup_url's look like, versionstring's assumptions, timestamp's assumptions,
#verify's assumptions, and so on. If not here in new() at least do it in the
#POD documentation.
###BUGALERT### Support ~/.Fetchwarefile, or whatever File::HomeDir wants it to
#be. Test if ~/.Fetchwarefile exists, if it does do nothing, but if it does not
#exist then prompt the user to fill one out!!!

############BUGALERT########################BUGALERT##################
############BUGALERT########################BUGALERT##################
###BUGALERT### Modify analyze_lookup_listing() to print the directory listing
#for the user to peruse, and have the user choose what program they want to
#install from the listing. Then use that as the basis for the filter option.
#httpd-2.4.1.tar.bz2 would simply be m/(\w+?)[.-_\d]+?/ And $1 is the filter
#option. If the match fails to the existing manual crap.
############BUGALERT########################BUGALERT##################
############BUGALERT########################BUGALERT##################

bin/fetchware  view on Meta::CPAN

    # API subroutines, because *no* API subroutines are available until
    # parse_fetchwarefile() is called in cmd_install(), and I can't call
    # parse_fetchwarefile() before the user has answered the questons to
    # actually create a Fetchwarefile.
    my $fetchware_extension = $term->get_reply(
        print_me => <<EOP,
Unless you're using a Fetchware extension, press enter to continue along in the
creation of your new Fetchwarefile. If you are using a Fetchware extension,
please enter its name without the 'App::FetchwareX::' prefix.
EOP
        prompt => q{Unless you're using a Fetchware extension press enter to use default?},
        default => 'App::Fetchware',
    );

    ###Security Note### Whatever string the user supplies will be given
    #to Module::Load's load() subroutine, and then forwarded on to
    #Perl's require() function, which parses and executes it as far as
    #loading it goes, and then whatever new() and new_install()
    #subroutines will be imported in the current package, and later one
    #executed below new() with dropped privs, and new_install() as root
    #if fun as root. You may consider this a security hole as it is

bin/fetchware  view on Meta::CPAN


    die <<EOD if @fetchware_package_filenames == 0;
fetchware: Fetchware failed to determine the fetchware package that is
associated with the argument that you provided to fetchware
[$fetchware_package]. In this case, fetchware only allows arguments for
fetchware packages that have already been installed. Please run fetchware list
to obtain a list of installed packages to choose from.
EOD

    ###BUGALERT### Use Term::UI, and output a numbered list for the user to
    #choose from using a prompt, and then rerun upgrade with that argument.
    if (@fetchware_package_filenames > 1) {
        # Print beginning of message to STDERR.
        warn <<EOW;
fetchware: Too many installed packages match the argument you provided to the
upgrade command. Your argument was [$fetchware_package], and the multiple
results it returned were:
EOW

        # Print modified array values to STDERR.
        for (@fetchware_package_filenames) {

lib/App/Fetchware.pm  view on Meta::CPAN

    OVERRIDE_NEW => [qw(
        extension_name
        fetchwarefile_name
        opening_message
        get_lookup_url
        download_lookup_url
        get_mirrors
        get_verification
        get_filter_option
        append_to_fetchwarefile
        prompt_for_other_options
        append_options_to_fetchwarefile
        edit_manually
    )],
    OVERRIDE_NEW_INSTALL => [qw(
        ask_to_install_now_to_test_fetchwarefile
    )],
    OVERRIDE_CHECK_SYNTAX => [qw(
        check_config_options
    )],
    OVERRIDE_LOOKUP => [qw(

lib/App/Fetchware.pm  view on Meta::CPAN

        %$mirrors_hashref,
        %$verify_hashref,
        %$filter_hashref
    );

    ###BUGALERT### Ask to parrallelize make with make_options???
    ###BUGALERT### Verify prefix is writable by current user, who will
    #presumably be the user who will install the package now and later.
    ###BUGALERT### Ask user for a prefix if their running nonroot???
    vmsg 'Prompting for other options that may be needed.';
    my $other_options_hashref = prompt_for_other_options($term,
        temp_dir => {
            prompt => <<EOP,
What temp_dir configuration option would you like? 
EOP
            print_me => <<EOP
temp_dir is the directory where fetchware creates a temporary directory that
stores all of the temporary files it creates while it is building your software.
The default directory is /tmp on Unix systems and C:\\temp on Windows systems.
EOP
        },
        user => {
            prompt => <<EOP,
What user configuration option would you like? 
EOP
            print_me => <<EOP
user specifies what user fetchware will drop priveleges to on Unix systems
capable of doing so. This allows fetchware to download files from the internet
with user priveleges, and not do anything as the administrative root user until
after the downloaded software package has been verified as exactly the same as
the author of the package intended it to be. If you use this option, the only
thing that is run as root is 'make install' or whatever this package's
install_commands configuratio option is.
EOP
        },
        prefix => {
            prompt => <<EOP,
What prefix configuration option would you like? 
EOP
            print_me => <<EOP
prefix specifies the base path that will be used to install this software. The
default is /usr/local, which is acceptable for most unix users. Please note that
this difective only works for software packages that use GNU AutoTools, software
that uses ./configure --prefix=<your prefix will go here> to change the prefix.
EOP
        },
        configure_options => {
            prompt => <<EOP,
What configure_options configuration option would you like? 
EOP
            print_me => <<EOP
configure_options specifies what options fetchware should add when it configures
this software package for you. A list of possible options can be obtained by
running unarchiving the software package that corresponds to this Fetchwarefile,
and running the command './configure --help'. These options vary from software
package to software package. Please note that this option only works for GNU
AutoTools based software distributions, ones that use ./configure to configure
the software.
EOP
        },
        make_options => {
            prompt => <<EOP,
What make_options configuration option would you like? 
EOP
            print_me => <<EOP
make_options specifies what options fetchware will pass to make when make is run
to compile, perhaps test, and install your software package. They are simpley
added after make is called. An example is '-j 4', which will cause make to
execute 4 jobs simultaneously. A reasonable rule of thumb is to set make's -j
argument to two times as many cpu cores your computer has as compiling programs
is sometimes IO bound instead of CPU bound, so you can get away with running
more jobs then you have cores.
EOP
        },
###BUGALERT### Create a config sub called build_system that takes args like
#AutoTools, cmake, MakeMaker, Module::Build, and so on that will use the default
#build commands of whatever system this option specifies.
        build_commands => {
            prompt => <<EOP,
What build_commands configuration option would you like? 
EOP
            print_me => <<EOP
build_commands specifies what commands fetchware will run to compile your
software package. Fetchware's default is simply 'make', which is good for most
programs. If you're software package uses something other than fetchware's
default of GNU AutoTools, then you may need to change this configuration option
to specify what you would like instead. Specify multiple build commands in
single quotes with a comma between them:
'./configure', 'make'
EOP
        },
        install_commands => {
            prompt => <<EOP,
What install_commands configuration option would you like? 
EOP
            print_me => <<EOP
install_commands specifies what commands fetchware will run to install your
software package. Fetchware's default is simply 'make install', which is good
for most programs. If you're software package uses something other than
fetchware's default of GNU AutoTools, then you may need to change this
configuration option to specify what you would like instead. Specify multiple
build commands in single quotes with a comma between them:
'make test', 'make install'
EOP
        },
        uninstall_commands => {
            prompt => <<EOP,
What uninstall_commands configuration option would you like?
EOP
            print_me => <<EOP,
uninstall_commands specifes what commands fetchware will run to uninstall your
software pacakge. The default is 'make uninstall,' which works for some GNU
AutoTools packages, but not all. If your software package does not have a 'make
uninstall' make target, but it has some other command that can uninstall it,
then please specify it using uninstall_commands so fetchware can uninstall it. 
EOP

        },
        lookup_method => {
            prompt => <<EOP,
What lookup_method configuration option would you like? 
EOP
            print_me => <<EOP
lookup_method specifies what how fetchware determines if a new version of your
software package is available. The available algorithms are 'timstamp' and
'versionstring'. 'timestamp' uses the timestamp listed in the FTP or HTTP
listing, and uses the software package that is the newest by filesystem
timestamp. The 'versionstring' algorithm uses the filename of the files in the
FTP or HTTP listing. It parses out the version information, sorts it highest to
lowest, and then picks the highest version of your software package. The default
is try 'timestamp' and if that doesn't work, then try 'versionstring'.
EOP
        },
        gpg_keys_url => {
            prompt => <<EOP,
What gpg_keys_url configuration option would you like? 
EOP
            print_me => <<EOP
gpg_keys_url specifies a url similar to lookup_url in that it should specify a
directory instead a specific file. It is used to download KEYS files, which
contain your program author's gpg keys to import into gpg.
EOP
        },
        gpg_sig_url => {
            prompt => <<EOP,
What gpg_sig_url configuration option would you like? 
EOP
            print_me => <<EOP
gpg_sig_url specifies a url similar to lookup_url in that it should specify a
directory instead a specific file. It is used to download gpg signatures to
verify your software package.
EOP
        },
        sha1_url => {
            prompt => <<EOP,
What sha1_url configuration option would you like? 
EOP
            print_me => <<EOP
sha1_url specifies a url similar to lookup_url in that it should specify a
directory instead of a specific file. It is separate from lookup_url, because
you should download software from mirrors, but checksums from the original
vendor's server, because checksums are easily replaced on a mirror by a hacker
if the mirror gets hacked.
EOP
        },
        md5_url => {
            prompt => <<EOP,
What md5_url configuration option would you like? 
EOP
            print_me => <<EOP,
md5_url specifies a url similar to lookup_url in that it should specify a
directory instead of a specific file. It is separate from lookup_url, because
you should download software from mirrors, but checksums from the original
vendor's server, because checksums are easily replaced on a mirror by a hacker
if  the mirror gets hacked.
EOP
        },
        verify_method => {
            prompt => <<EOP,
What verify_method configuration option would you like? 
EOP
            print_me => <<EOP,
verify_method specifies what method of verification fetchware should use to
ensure the software you have downloaded has not been tampered with. The default
is to try gpg verification, then sha1, and then finally md5, and if they all
fail an error message is printed and fetchware exits, because if your software
package cannot be verified, then it should not be installed. This configuration
option allows you to remove the warnings by specifying a specific way of
verifying your software has not been tampered with. To disable verification set
the 'verify_failure_ok' configuration option to true.
EOP
        },
###BUGALERT### replace no_install config su with a command line option that
#would be the opposite of --force???
# Nah! Leave it! Just create a command line option for it too!
        no_install => {
            prompt => <<EOP,
Would you like to enable the no_install configuration option? 
EOP
            ###BUGALERT### no_install is not currently implemented properly!!!
            print_me => <<EOP
no_install is a true or false option, whoose acceptable values include 1
or 0, true or falue, On or Off. It's default value is false, but if you enable
it, then fetchware will not install your software package, and instead it will
simply download, verify, and build it. And then it will print out the full path
of the directory it built your software package in.
EOP
            ###BUGALERT### Add support for a check regex, so that I can ensure
            #that what the user enters will be either true or false!!!
        },
        verify_failure_ok => {
            prompt => <<EOP,
Would you like to enable the verify_failure_ok configuration option? 
EOP
            print_me => <<EOP
verify_failure_ok is a true or false option, whoose acceptable values include 1
or 0, true or falue, On or Off. It's default value is false, but if you enable
it, then fetchware will not print an error message and exit if verification
fails for your software package. Please note that you should never use this
option, because it makes it possible for fetchware to install source code that
may have been tampered with.
EOP
        },
        users_keyring => {
            prompt => <<EOP,
Would you like to enable users_keyring configuration option? 
EOP
            print_me => <<EOP
users_keyring when enabled causes fetchware to use the user who calls
fetchware's gpg keyring instead of fetchware's own gpg keyring. Useful for
source code distributions that do not provide an easily accessible KEYS file.
Just remember to import the author's keys into your gpg keyring with gpg
--import.
EOP
        },

lib/App/Fetchware.pm  view on Meta::CPAN

provide one below
EOM
    die <<EOD if not defined $fetchwarefile_name;
App-Fetchware: in your call to fetchwarefile_name() you failed to call it with a
defined \$fetchwarefile_name option. The \$fetchwarefile_name option you
specified is [$fetchwarefile_name]. Please specify this option, and try again.
EOD

    if (not defined $fetchwarefile_name_value) {
        $fetchwarefile_name_value = $term->get_reply(
            prompt => q{What would you like to name this specific Fetchwarefile? },
            print_me => $what_a_fetchwarefile_name_is,
            # This option requires a name, so just pressing return, which would
            # yield undef is not acceptable. We need an actual value, so check
            # the value to ensure that it is defined.
            allow => sub { defined shift @_ ? return 1 : return 0 }
        );
    }

    return $fetchwarefile_name, $fetchwarefile_name_value;
}



sub get_lookup_url {
    my $term = shift;


    # prompt for lookup_url.
    my $lookup_url = $term->get_reply(
        print_me => <<EOP,
Fetchware's heart and soul is its lookup_url. This is the configuration option
that tells fetchware where to check what the latest version of your program is.
This version number is then parsed out of the HTTP/FTP/local directory listing,
and compared against the latest installed version to determine when a new
version of your program has been released.

How to determine your application's lookup_url:
    1. Go to your application's Web site.
    2. Determine the download link for the latest version and copy it with
       CTRL-C or right-click it and select "copy".
    3. Paste the download link into your browser's URL Location Bar.
    4. Delete the filename from the location by starting at the end and deleting
       everything to the left until you reach a slash '/'.
       * ftp://a.url/downloads/program.tar.gz -> ftp://a.url/downloads/
    5. Press enter to access the directory listing on your Application's mirror
       site.
    6. If the directory listing in either FTP or HTTP format is displayed in
       your browser, then Fetchware's default, built-in lookup fuctionality will
       probably work properly. Copy and paste this URL into the prompt below, and
       Fetchware will download and analyze your lookup_url to see if it will work
       properly. If you do not end up with a browser directory listing, then
       please see Fetchware's documentation using perldoc App::Fetchware.
EOP
        prompt => q{What is your application's lookup_url? },
        allow => qr!(ftp|http|file)://!);

    return $lookup_url;
}



sub download_lookup_url {
    my $term = shift;
    my $lookup_url = shift;

lib/App/Fetchware.pm  view on Meta::CPAN

        print_me => <<EOP,
Fetchware requires you to please provide a mirror. This mirror is required,
because most software authors prefer users download their software packages from
a mirror instead of from the authors main download site, which your lookup_url
should point to.

The mirror should be a URL in standard browser format such as [ftp://a.mirror/].
FTP, HTTP, and local file:// mirrors are supported. All other formats are not
supported.
EOP
        prompt => 'Please enter the URL of your mirror: ',
        allow => qr!^(ftp|http|file)://!,
    );

    # Append mirror to $fetchwarefile.
    push @mirrors, $mirror;

    if (
        $term->ask_yn(
        print_me => <<EOP,
In addition to the one required mirror that you must define in order for
fetchware to function properly, you may specify additonal mirros that fetchware
will use if the mirror you've already specified is unreachable or download
attempts using that mirror fail.
EOP
        prompt => 'Would you like to add any additional mirrors? ',
        default => 'n',
        )
    ) {
        # Prompt for first mirror outside loop, because if you just hit enter or
        # type done, then the above text will be appended to your fetchwarefile,
        # but you'll be able to skip actually adding a mirror.
        my $first_mirror = $term->get_reply(
                prompt => 'Type in URL of mirror or done to continue: ',
                allow => qr!^(ftp|http|file)://!,
            );
            # Append $first_mirror to $fetchwarefile.
            push @mirrors, $first_mirror;

        while (1) {
            my $mirror_or_done = $term->get_reply(
                prompt => 'Type in URL of mirror or done to continue: ',
                default => 'done',
                allow => qr!(^(ftp|http|file)://)|done!,
            );
            if ($mirror_or_done eq 'done') {
                last;
            } else {
                # Append $mirror_or_done to $fetchwarefile.
                push @mirrors, $mirror_or_done;
            }
        }

lib/App/Fetchware.pm  view on Meta::CPAN

            $options{gpg_keys_url} = $lookup_url;
            $verify_configed_flag++;
        } else {
            msg <<EOM;
KEYS file *not* found!
EOM
            # Since autoconfiguration of KEYS failed, try asking the user if
            # they would like to import the author's key themselves into their
            # own keyring and have fetchware use that.
            if (
                $term->ask_yn(prompt =>
q{Would you like to import the author's key yourself after fetchware completes? },
                    default => 'n',
                    print_me => <<EOP,
Automatic KEYS file discovery failed. Fetchware needs the author's keys to
download and import into its own keyring, or you may specify the option
user_keyring, which if true will cause fetchware to use the user who runs
fetchware's keyring instead of fetchware's own keyring. But you, the user, needs
to import the author's keys into your own gpg keyring. You can do this now in a
separate shell, or after you finish configuring this Fetchwarefile. Just run the
command [gpg --import <name of file>].

lib/App/Fetchware.pm  view on Meta::CPAN

EOM
            $options{verify_method} = 'md5';
        } else {
            # Print a huge long nasty warning even include links to news stories
            # of mirrors actually getting hacked and serving malware, which
            # would be detected and prevented with proper verification enabled.

            # Ask user if they would like to continue installing fetchware even if
            # verification fails, and then enable the verify_failure_ok option.
            if (
                $term->ask_yn(prompt => <<EOP,
Would you like fetchware to ignore the fact that it is unable to verify the
authenticity of any downloads it makes? Are you ok with possibly downloading
viruses, worms, rootkits, or any other malware, and installing it possibly even
as root? 
EOP
                    default => 'n',
                    print_me => <<EOP,
Automatic verification of your fetchware package has failed! Fetchware is
capable of ignoring the error, and installing software packages anyway using its
verify_failure_ok configuration option. However, installing software packages

lib/App/Fetchware.pm  view on Meta::CPAN


    my $filter;
    if (grep {$_->[0] =~ /^(CURRENT|LATEST)[_-]IS[_-].+/} @$filename_listing) {
        # There is only one version in the lookup_url directory listing, so
        # I do not need a filter option.
        msg <<EOS;
* The lookup_url you gave fetchware includes a CURRENT_IS or a LATEST_IS file
that tells fetchware and regular users what the latest version is. Because of
this we can be reasonable sure that a filter option is not needed, so I'll skip
asking for one. You can provide one later if you need to provide one, when
fetchware prompts you for any custom options you may want to use.
EOS
    } else {
        # There is a CURRENT_IS_<ver_num> or LATEST_IS_<ver_num> file that tells
        # you what the latest version is.
###BUGALERT### Why is this line in both sections of the if statement??? Inside
#this else block means that a CURRENT_IS or LATEST-IS was *not* found??? Fix
#this!!!!!!
        msg <<EOS;
* The directory listing of your lookup_url has a CURRENT_IS_<ver_num> or
LATEST_IS_<ver_num> file that specifies the latest version, which means that

lib/App/Fetchware.pm  view on Meta::CPAN

stable branch instead of the higher version numbered 2.4 or 2.0 legacy releases.
Note the use of the dash, which is used in the filename to separate the 'httpd'
name part from the '2.2' version part.

Note: fetchware accepts any valid perl regular expresion as an acceptable
filter option, but that should only be needed for advanced users. See perldoc
fetchware.
EOA
        # Prompt for the needed filter option.
        $filter = $term->get_reply(
            prompt => <<EOP,
[Just press enter or return to skip adding a filter option]
What does fetchware need your filter option to be? 
EOP
            print_me => $what_a_filter_is,
        );
        ###BUGALERT### Consider Adding a loop around checking the filter option
        #that runs determine_lookup_url() using the provided filter option, and
        #then asking the user if that is indeed the correct filter option, and
        #if not ask again and try it again unit it succeeds or user presses
        #ctrl-c|z.
    }

    return {filter => $filter};
}



sub prompt_for_other_options {
    my $term = shift;

    my %option_description = @_;

    my %answered_option;

    if (
        $term->ask_yn(prompt =>
        q{Would you like to add extra configuration options to your fetchwarefile?},
        default => 'n',
        print_me => <<EOP,
Fetchware has many different configuration options that allow you to control its
behavior, and even change its behavior if needed to customize fetchware for any
possible source code distribution.

If you think you need to add configuration options please check out perldoc
fetchware for more details on fetchware and its Fetchwarefile configuration
options.

lib/App/Fetchware.pm  view on Meta::CPAN

package for a new program for the first time, you should skip messing with
fetchware's more flexible options, and just give the defaults a chance.
EOP
        )
    ) {
        my @options = keys %option_description;
        my @config_file_options_to_provide = $term->get_reply(
            print_me => <<EOP,
Below is a listing of Fetchware's available configuration options.
EOP
            prompt => <<EOP,
Please answer with a space seperated list of the number before the configuration
file options that you would like to add to your configuration file? 
EOP
            choices => \@options,
            multi => 1,
        );


        for my $config_file_option (@config_file_options_to_provide) {
            $answered_option{$config_file_option} = $term->get_reply(
                print_me => $option_description{$config_file_option}->{print_me},
                prompt => $option_description{$config_file_option}->{prompt},
            );
        }
    }
    return \%answered_option;
}



sub edit_manually {
    my ($term, $fetchwarefile) = @_;

lib/App/Fetchware.pm  view on Meta::CPAN

Fetchware has now asked you all of the needed questions to determine what it
thinks your new program's Fetchwarefile should look like. But it's not perfect,
and perhaps you would like to tweak it manually. If you would like to edit it
manually in your favorite editor, answer 'yes', and if you want to skip this just
answer 'no', or just press <Enter>.

If you would like to cancel any edits you have made, and use the automagically
generated Fetchwarefile, just delete the entire contents of the file, and save
an empty file.
EOP
            prompt => q{Would you like to edit your automagically generated Fetchwarefile manually? },
        default => 'n',
        )
    ) {
        my ($fh, $fetchwarefile_filename) =
            tempfile('Fetchwarefile-XXXXXXXXX', TMPDIR => 1);
        print $fh $fetchwarefile->generate();

        close $fh;

        # Ask what editor to use if EDITOR environment variable is not set.
        my $editor = $ENV{EDITOR} || do {
            $term->get_reply(prompt => <<EOP,
What text editor would you like to use? 
EOP
                print_me => <<EOP
The Environment variable EDITOR is not set. This is used by fetchware and other
programs to determine what program fetchware should use to edit your
Fetchwarefile. Please enter what text editor you would like to use. Examples
include: vim, emacs, nano, pico, or notepad.exe (on Windows).
EOP
            );
        };

lib/App/Fetchware.pm  view on Meta::CPAN


    # If the user wants to install their new Fetchwarefile.
    if (
        $term->ask_yn(
        print_me => <<EOP,
It is recommended that fetchware go ahead and install the package based on the
Fetchwarefile that fetchware has created for you. If you don't want to install
it now, then enter 'no', but if you want to test your Fetchwarefile now, and
install it, then please enter 'yes' or just press <Enter>.
EOP
        prompt => q{Would you like to install the package you just created a Fetchwarefile for? },
        default => 'y',
        )
    ) {

        # Create a temp Fetchwarefile to store the autogenerated configuration.
        my ($fh, $fetchwarefile_filename)
            =
            tempfile("fetchware-$$-XXXXXXXXXXXXXX", TMPDIR => 1, UNLINK => 1);
        print $fh $$fetchwarefile;
        # Close the temp file to ensure everything that was written to it gets

lib/App/Fetchware.pm  view on Meta::CPAN

        msg 'Installed Fetchware package to fetchware database.';
        return $fetchware_package_path;
    # Else the user just wants to save the Fetchwarefile somewhere.
    } else {
        my $fetchwarefile_filename = $program_name . '.Fetchwarefile';

        # Get a name for the Fetchwarefile that does not already exist.
        if (-e $fetchwarefile_filename) {
            while (1) {
                $fetchwarefile_filename = $term->get_reply(
                    prompt => <<EOP,
What would you like your new Fetchwarefile's filename to be?
EOP
                    print_me => <<EOP
Fetchware by default uses the program name you specified at the beginning of
running fetchware new plus a '.Fetchwarefile' extension to name your
Fetchwarefile. But his file already exists, so you'll have to pick a new
filename that does not currently exist.
EOP
                );
                last unless -e $fetchwarefile_filename;

lib/App/Fetchware.pm  view on Meta::CPAN

App::Fetchware extensions to also use some or most of these component
subroutines when they override a App::Fetchware API subroutine.

=over

=item L<new()'s OVERRIDE_NEW export tag.|new() API REFERENCE>

The export tag exports all of the helper subroutines new() uses to implement its
functionality. Some like get_lookup_url(), get_verification(), and
get_filter_option() are quite specific to App::Fetchware, but extension_name,
fetchwarefile_name(), opening_message(), prompt_for_other_options(), and
edit_manually() are nice and generic, and should be appropriate for any
Fetchware extension.

=item L<new_install()'s OVERRIDE_NEW_INSTALL export tag.|new_install() API REFERENCE>

new_install() only exports ask_to_install_now_to_test_fetchwarefile(), and most
Fetchware extensions should probably just "inherit" new_install(), because
new_install()'s only real purpose was making
ask_to_install_now_to_test_fetchwarefile() work when fetchware drops privs.

lib/App/Fetchware.pm  view on Meta::CPAN

that you want to install. The C<filter> option is needed, because some mirrors
will have multiple software packages in the same directory or multitple
different versions of one piece of software in the same directory. An example
would be Apache, which has Apache versions 2.0, 2.2, and 2.4 all in the same
directory. The C<filter> option is how you differentiate between them.

If a filter was provided by the user than it is returned as a hashref with
C<filter> as the key for use with append_options_to_fetchwarefile(), or for
further analysis by extension authors.

=head3 prompt_for_other_options()

    prompt_for_other_options($term,
        temp_dir => {
            prompt => <<EOP,
    What temp_dir configuration option would you like? 
    EOP
            print_me => <<EOP
    temp_dir is the directory where fetchware creates a temporary directory that
    stores all of the temporary files it creates while it is building your software.
    The default directory is /tmp on Unix systems and C:\\temp on Windows systems.
    EOP
        },
            ...
    );

Accepts a Term::Readline/Term::UI object as an argument to use to ask the user
questions, and a gigantic hash of hashes in list form. The hash of hashes,
%option_description, argument incluedes the C<prompt> and C<print_me> options
that are then passed through to Term::UI to ask the user what argument they want
for each specified option in the %option_description hash.

The user's answers are tallied up an returned as a hash reference.

=head3 edit_manually()

    $fetchwarefile = edit_manually($term, $fetchwarefile);

edit_manually() asks the user if they would like to edit the specified

lib/App/FetchwareX/HTMLPageSync.pm  view on Meta::CPAN

    vmsg <<EOM;
Appended destination_directory [$destination_directory] configuration option to
your Fetchwarefile";
EOM

    # Asks and sets the keep_destination_directory configuratio option if the
    # user wants to set it.
    ask_about_keep_destination_directory($term, $fetchwarefile);

    vmsg 'Prompting for other options that may be needed.';
    my $other_options_hashref = prompt_for_other_options($term,
        user_agent => {
            prompt => <<EOP,
What user_agent configuration option would you like? 
EOP
            print_me => <<EOP
user_agent, if specified, will be passed to HTML::Tiny, the Perl HTTP library
Fetchware uses, where the library will lie to the Web server you are Web
scraping from to hopefully prevent the Web sever from banning you, or updating
the page you want to scrap to use too much Javascript, which would prevent the
simple parser HTMLPageSync uses from working on the specified html_page_url.
EOP
        },
        html_treebuilder_callback => {
            prompt => <<EOP,
What html_treebuilder_callback configuration option would you like? 
EOP
            print_me => <<EOP,
html_treebuilder_callback allows you to specify a perl CODEREF that HTMLPageSync
will execute instead of its default callback that just looks for images.

It receives one parameter, which is an HTML::Element at the first C<a>,
anchor/link tag.

It must [return 'True';] to indicate that that link should be included in the

lib/App/FetchwareX/HTMLPageSync.pm  view on Meta::CPAN

link should not be included in the list of download links.

Because Term::UI's imput is limited to just one line, please just press enter,
and a dummy value will go into your Fetchwarefile, where you can then replace
that dummy value with a proper Perl callback next, when Fetchware gives you the
option to edit your Fetchwarefile manually.
EOP
            default => 'sub { my $h = shift; die "Dummy placeholder fill me in."; }',
        },
        download_links_callback => {
            prompt => <<EOP,
What download_links_callback configuration option would you like? 
EOP
            print_me => <<EOP,
download_links_callback specifies an optional callback that will allow you to do
post processing of the list of downloaded urls. This is needed, because the
results of the html_treebuilder_callback are still HTML::Element objects that
need to be converted to just string download urls. That is what the default
C<download_links_callback> does.

It receives a list of all of the download HTML::Elements that

lib/App/FetchwareX/HTMLPageSync.pm  view on Meta::CPAN

    # makes then available to new_install(), back in the parent, as arguments.
    return $page_name, $fetchwarefile;
}



sub get_html_page_url {
    my $term = shift;


    # prompt for lookup_url.
    my $html_page_url = $term->get_reply(
        print_me => <<EOP,
Fetchware's heart and soul is its html_page_url. This is the configuration option
that tells fetchware where to check if any new links have been added to the
specified Web page that match your criteria for download.

How to determine your application's html_page_url:
    1. Simply specify the URL that of the Web page that has the images that you
    would like to have Fetchware download for you.
EOP
        prompt => q{What is your Web page's html_page_url? },
        allow => qr!(ftp|http|file)://!);

    return $html_page_url;
}



sub get_destination_directory {
    my $term = shift;

    # prompt for lookup_url.
    my $destination_directory = $term->get_reply(
        print_me => <<EOP,
destination_directory is the directory on your computer where you want the files
that you configure HTMLPageSync to parse to be copied to.
EOP
        prompt => q{What is your destination_directory? });

    return $destination_directory;
}



sub ask_about_keep_destination_directory {
    my ($term, $fetchwarefile) = @_;

    if (
        $term->ask_yn(
        print_me => <<EOP,
By default, HTMLPageSync deletes your destination_directory when you uninstall
that destination_directory's assocated Fetchware package or Fetchwarefile. This
is done, because your deleting the Fetchware package, so it makes sense to
delete that package's associated data.

If you wish to keep your destination_directory after you uninstall this
HTMLPageSync Fetchware package, then answer N below.
EOP
        prompt => 'Is deleting your destination_directory on uninstall OK? ',
        default => 'y',
        )
    ) {
        vmsg <<EOM;
User wants [keep_destination_directory 'True';] added to their Fetchwarefile.
EOM

        $fetchwarefile->config_options(keep_destination_directory => 'True');
        vmsg <<EOM;
Appended [keep_destination_directory 'True';] to user's Fetchwarefile.

t/App-Fetchware-new  view on Meta::CPAN

ok (-e $fetchwarefile_path_or_package_path,
    'checked cmd_new() Fetchwarefile creation success.');

ok (unlink $fetchwarefile_path_or_package_path,
    'checked cmd_new() delete test Fetchwarefile.');


# Spit out # of tests run.
done_testing();

# Print a bogus "prompt" to keep Expect from freaking out, because it presumes
# the prompt works like it does in a shell, but fetchware new is not a shell.
print "Bogus shell: \n";

# Because we're in a child process not the same one that is running the main
# test suite, if any tests fail this failure will not be reported back to our
# caller. So, we use Test::Builder to check if our tests have passed, and if
# they have we do nothing and return succes, but if not we throw an exception.
my $test = Test::Builder->new();
unless ($test->is_passing()) {
    diag explain \[$test->details()];
    die <<EOD;

t/App-Fetchware-new-fetchwarefile_name  view on Meta::CPAN

my ($fetchwarefile_name, $fetchwarefile_value) =
    fetchwarefile_name($term, program => undef);

is($fetchwarefile_name, 'program', 'checked fetchwarefile_name() program.');
is($fetchwarefile_value, 'test', 'checked fetchwarefile_name() value.');


# Spit out # of tests run.
done_testing();

# Print a bogus "prompt" to keep Expect from freaking out, because it presumes
# the prompt works like it does in a shell, but fetchware new is not a shell.
print "Bogus shell: \n";

# Because we're in a child process not the same one that is running the main
# test suite, if any tests fail this failure will not be reported back to our
# caller. So, we use Test::Builder to check if our tests have passed, and if
# they have we do nothing and return succes, but if not we throw an exception.
my $test = Test::Builder->new();
unless ($test->is_passing()) {
    diag explain \[$test->details()];
    die <<EOD;

t/App-Fetchware-new-get_filter_option  view on Meta::CPAN


ok(exists $filter_hashref->{filter},
    'checked get_filter_option() key success.');

is($filter_hashref->{filter}, 'httpd-2.2',
    'checked get_filter_option() value success.');

# Spit out # of tests run.
done_testing();

# Print a bogus "prompt" to keep Expect from freaking out, because it presumes
# the prompt works like it does in a shell, but fetchware new is not a shell.
print "Bogus shell: \n";

# Because we're in a child process not the same one that is running the main
# test suite, if any tests fail this failure will not be reported back to our
# caller. So, we use Test::Builder to check if our tests have passed, and if
# they have we do nothing and return succes, but if not we throw an exception.
my $test = Test::Builder->new();
unless ($test->is_passing()) {
    diag explain \[$test->details()];
    die <<EOD;

t/App-Fetchware-new-get_mirrors  view on Meta::CPAN

            "checked get_mirrors($mirror) success.");
    }
} else {
    like($mirrors_hashref->{mirror}, qr!(ftp|http|file)://!ms,
        'checked get_mirrors($mirror) success.');
}

# Spit out # of tests run.
done_testing();

# Print a bogus "prompt" to keep Expect from freaking out, because it presumes
# the prompt works like it does in a shell, but fetchware new is not a shell.
print "Bogus shell: \n";

# Because we're in a child process not the same one that is running the main
# test suite, if any tests fail this failure will not be reported back to our
# caller. So, we use Test::Builder to check if our tests have passed, and if
# they have we do nothing and return succes, but if not we throw an exception.
my $test = Test::Builder->new();
unless ($test->is_passing()) {
    diag explain \[$test->details()];
    die <<EOD;

t/App-Fetchware-new-get_verification  view on Meta::CPAN

    'checked get_verification() keyring value.');

ok(exists $verification_hashref->{verify_method},
    'checked get_verification method sucess.');
like($verification_hashref->{verify_method}, qr/gpg/i,
    'checked get_verification() verify_method value.');

# Spit out # of tests run.
done_testing();

# Print a bogus "prompt" to keep Expect from freaking out, because it presumes
# the prompt works like it does in a shell, but fetchware new is not a shell.
print "Bogus shell: \n";

# Because we're in a child process not the same one that is running the main
# test suite, if any tests fail this failure will not be reported back to our
# caller. So, we use Test::Builder to check if our tests have passed, and if
# they have we do nothing and return succes, but if not we throw an exception.
my $test = Test::Builder->new();
unless ($test->is_passing()) {
    diag explain \[$test->details()];
    die <<EOD;

t/App-Fetchware-new-prompt_for_other_options  view on Meta::CPAN

#!/usr/bin/env perl
use warnings;
use strict;

# Tests cmd_new()'s prompt_for_other_options() subroutine that uses Term::UI to
# ask the user questions. This "test script" is called by
# t/bin-fetchware-new.t's using Test::Expect, if its optionally installed.
# And Test::Expect answer's the questsions that this script asks thereby testing
# add_mirrors() Q&A interface.


use Test::More;
use Test::Builder;
use Term::ReadLine;

use App::Fetchware 'prompt_for_other_options';

my $term = Term::ReadLine->new('testing fetchware new');

my $other_options_hashref = prompt_for_other_options($term,
        temp_dir => {
            prompt => <<EOP,
What temp_dir configuration option would you like? 
EOP
            print_me => <<EOP
temp_dir is the directory where fetchware creates a temporary directory that
stores all of the temporary files it creates while it is building your software.
The default directory is /tmp on Unix systems and C:\\temp on Windows systems.
EOP
        },
        user => {
            prompt => <<EOP,
What user configuration option would you like? 
EOP
            print_me => <<EOP
user specifies what user fetchware will drop priveleges to on Unix systems
capable of doing so. This allows fetchware to download files from the internet
with user priveleges, and not do anything as the administrative root user until
after the downloaded software package has been verified as exactly the same as
the author of the package intended it to be. If you use this option, the only
thing that is run as root is 'make install' or whatever this package's
install_commands configuratio option is.
EOP
        },
    );

###BUGALERT### Add tests for testing specific options.
if ($other_options_hashref) {
    ok($other_options_hashref,
        'checked prompt_for_other_options() answered Y success.');
    for my $option (keys %$other_options_hashref) {
        is($other_options_hashref->{$option}, '/var/tmp',
            'checked prompt_for_other_options() temp_dir success.')
            if $option eq 'temp_dir';
        is($other_options_hashref->{$option}, 'dly',
            'checked prompt_for_other_options() user success.')
            if $option eq 'user';
    }
} else {
    ok( ! $other_options_hashref,
        'checked prompt_for_other_options() answered N success.');
}

# Spit out # of tests run.
done_testing();

# Print a bogus "prompt" to keep Expect from freaking out, because it presumes
# the prompt works like it does in a shell, but fetchware new is not a shell.
print "Bogus shell: \n";

# Because we're in a child process not the same one that is running the main
# test suite, if any tests fail this failure will not be reported back to our
# caller. So, we use Test::Builder to check if our tests have passed, and if
# they have we do nothing and return succes, but if not we throw an exception.
my $test = Test::Builder->new();
unless ($test->is_passing()) {
    diag explain \[$test->details()];
    die <<EOD;

t/App-Fetchware-new.t  view on Meta::CPAN

    my $term = Term::ReadLine->new('fetchware');

    my ($got_name, $got_value) = fetchwarefile_name($term, program => 'Test Fetchwarefile');
    is($got_name, 'program',
        'checked fetchwarefile_name() name success.');
    is($got_value, 'Test Fetchwarefile',
        'checked fetchwarefile_name() value success.');
};


subtest 'test fetchwarefile_name() prompt' => sub {
    skip_all_unless_release_testing();

    plan(skip_all => 'Optional Test::Expect testing module not installed.')
        unless eval {require Test::Expect; Test::Expect->import(); 1;};

    # Disable Term::UI's AUTOREPLY for this subtest, because unless I use
    # something crazy like Test::Expect, this will have to be tested "manually."
    local $Term::UI::AUTOREPLY = 0;
    # Fix the "out of orderness" thanks to Test::Builder messing with
    # STD{OUT,ERR}.
    local $| = 1;

    # Have Expect tell me what it's doing for easier debugging.
    #$Expect::Exp_Internal = 1;

    expect_run(
        command => 't/App-Fetchware-new-fetchwarefile_name',
        prompt => [-re => qr/: |\? /],
        quit => "\cC"
    );

    # First test that the command produced the correct outout.
    expect_like(qr/Fetchware uses the program configuration option to name this/,
        'checked fetchwarefile_name() received correct config options prompt');

    # Send correct input
    expect_send('test',
        'check fetchwarefile_name() sent program name.');

    expect_quit();
};


subtest 'test get_lookup_url() success' => sub {

t/App-Fetchware-new.t  view on Meta::CPAN

http:// or ftp:// part). The only supported download types, schemes, are FTP and
HTTP. See perldoc App::Fetchware.
]
Please see perldoc App::Fetchware for troubleshooting tips and rerun
fetchware new.
EOE

};


subtest 'test prompt_for_other_options() success' => sub {
    skip_all_unless_release_testing();

    plan(skip_all => 'Optional Test::Expect testing module not installed.')
        unless eval {require Test::Expect; Test::Expect->import(); 1;};

    # Disable Term::UI's AUTOREPLY for this subtest, because unless I use
    # something crazy like Test::Expect, this will have to be tested "manually."
    local $Term::UI::AUTOREPLY = 0;
    # Fix the "out of orderness" thanks to Test::Builder messing with
    # STD{OUT,ERR}.
    local $| = 1;

    # Have Expect tell me what it's doing for easier debugging.
    #$Expect::Exp_Internal = 1;

    expect_run(
        command => 't/App-Fetchware-new-prompt_for_other_options',
        prompt => [-re => qr/: |\? /],
        quit => "\cC"
    );

    # First test that the command produced the correct outout.
    expect_like(qr/Fetchware has many different configuration options that allow you to control its/,
        'checked prompt_for_other_options() received correct config options prompt');

    # Have Expect print an example URL.
    expect_send('y',
        'check prompt_for_other_options() sent Y.');

    # Check if upon receiving the URL the command prints out the next correct
    # prompt.
    # The including [y/N] below is a stupid workaround for some stupid bug in
    # Expect or in my code that I can't figure out. Fix this if you can.
    #expect_like(qr/Below is a listing of Fetchware's available configuration options./,
    expect_like(qr!\[y/N\]|Below is a listing of Fetchware's available configuration options.!,
        'checked prompt_for_other_options() received configuration options prompt.');

    # Note I have no clue what numbers will line up with what configuration
    # options, because the configuraiton options come from a hash, and hash's
    # order changes each time the program is compiled. I could parse the actual
    # output with a regex or something, but as of now I'm not.
    expect_send('1 5 9',
        'checked prompt_for_other_options() specify some configuration options.');

    # The weird regex is just so it can match any possible configuration option,
    # because due to hashes being unordered I don't know which options are which
    # numbers without complicated parsing that I'm not doing.
    expect_like(qr/[\w .,?!]+/,
        'checked prompt_for_other_options() received a specifc config option.');
    expect_send('Some test value who cares',
        'checked prompt_for_other_options() specify a specific config option.');

    expect_like(qr/[\w .,?!]+/,
        'checked prompt_for_other_options() received a specifc config option.');
    expect_send('Some test value who cares',
        'checked prompt_for_other_options() specify a specific config option.');

    expect_like(qr/[\w .,?!]+/,
        'checked prompt_for_other_options() received a specifc config option.');
    expect_send('Some test value who cares',
        'checked prompt_for_other_options() specify a specific config option.');

    expect_quit();
    
};


subtest 'test get_mirrors() success' => sub {
    skip_all_unless_release_testing();

    plan(skip_all => 'Optional Test::Expect testing module not installed.')

t/App-Fetchware-new.t  view on Meta::CPAN

    local $Term::UI::AUTOREPLY = 0;
    # Fix the "out of orderness" thanks to Test::Builder messing with
    # STD{OUT,ERR}.
    local $| = 1;

    # Have Expect tell me what it's doing for easier debugging.
    #$Expect::Exp_Internal = 1;

    expect_run(
        command => 't/App-Fetchware-new-get_mirrors',
        prompt => [-re => qr/: |\? /],
        quit => "\cC"
    );

    # First test that the command produced the correct outout.
    expect_like(qr/Fetchware requires you to please provide a mirror. This mirror is required,/,
        'checked add_mirror() received correct mirror prompt');

    # Have Expect print an example URL.
    expect_send('http://who.cares/whatever/',
        'check add_mirror() sent mirror URL.');

    # Check if upon receiving the URL the command prints out the next correct
    # prompt.
    expect_like(qr/Would you like to add any additional mirrors?/,
        'checked get_mirrors() received more mirrors prompt.');

    expect_send('N', 'checked get_mirrors() say No to more mirrors.');

    expect_quit();

    # Test answering Yes for more mirrors.

    expect_run(
        command => 't/App-Fetchware-new-get_mirrors',
        prompt => [-re => qr/: |\? /],
        quit => "\cC"
    );

    # First test that the command produced the correct outout.
    expect_like(qr/Fetchware requires you to please provide a mirror. This mirror is required,/,
        'checked add_mirror() received correct mirror prompt');

    # Have Expect print an example URL.
    expect_send('http://who.cares/whatever/',
        'check add_mirror() sent mirror URL.');

    # Check if upon receiving the URL the command prints out the next correct
    # prompt.
    expect_like(qr/Would you like to add any additional mirrors?/,
        'checked get_mirrors() received more mirrors prompt.');

    expect_send('Y', 'checked get_mirrors() say No to more mirrors.');

    expect_like(qr!\[y/N\]|Type in URL of mirror or done to continue!,
        'checked get_mirrors() received prompt to enter a mirror.');

    expect_send('ftp://afakemirror.blah/huh?',
        'checked get_mirrors() sent another mirror URL.');

    expect_like(qr/Type in URL of mirror or done to continue/,
        'checked get_mirrors() received prompt to enter a mirror.');

    expect_send('ftp://anotherfake.mirror/kasdjlfkjd',
        'checked get_mirrors() sent another mirror URL.');

    expect_like(qr/Type in URL of mirror or done to continue/,
        'checked get_mirrors() received prompt to enter a mirror.');

    expect_send('done',
        'checked get_mirrors() sent done.');

    expect_quit();
};


subtest 'test get_verification() success' => sub {
    skip_all_unless_release_testing();

t/App-Fetchware-new.t  view on Meta::CPAN

    local $Term::UI::AUTOREPLY = 0;
    # Fix the "out of orderness" thanks to Test::Builder messing with
    # STD{OUT,ERR}.
    local $| = 1;

    # Have Expect tell me what it's doing for easier debugging.
    #$Expect::Exp_Internal = 1;

    expect_run(
        command => 't/App-Fetchware-new-get_verification',
        prompt => [-re => qr/: |\? /],
        quit => "\cC"
    );

    # First test that the command produced the correct outout.
    expect_like(qr/Automatic KEYS file discovery failed. Fetchware needs the/,
        'checked get_verification() received correct mirror prompt');

    # Have Expect print an example URL.
    expect_send('Y',
        'check get_verification() sent manual KEYS file Y.');

    expect_like(qr<\[y/N\]|Automatic verification of your fetchware package has failed!>,
        'check get_verification() received no verify prompt.');

    expect_send('Y',
        'checked get_verification() sent no verify Y.');


    expect_quit();

    ###BUGALERT### Add tests for get_verification()'s other branches.
};

t/App-Fetchware-new.t  view on Meta::CPAN

    local $Term::UI::AUTOREPLY = 0;
    # Fix the "out of orderness" thanks to Test::Builder messing with
    # STD{OUT,ERR}.
    local $| = 1;

    # Have Expect tell me what it's doing for easier debugging.
    #$Expect::Exp_Internal = 1;

    expect_run(
        command => 't/App-Fetchware-new-get_filter_option',
        prompt => [-re => qr/: |\? /],
        quit => "\cC" # CTRL-C
    );

    expect_like(qr/Analyzing the lookup_url you provided to determine if fetchware/,
        'checked get_filter_option() received correct filter prompt');

    expect_send('httpd-2.2',
        'check get_filter_option() provided filter.');

    expect_quit();
};


subtest 'test edit_manually() success' => sub {
    # Create test Term::UI object.

t/App-Fetchware-new.t  view on Meta::CPAN

##TODO####BROKEN##    local $Term::UI::AUTOREPLY = 0;
##TODO####BROKEN##    # Fix the "out of orderness" thanks to Test::Builder messing with
##TODO####BROKEN##    # STD{OUT,ERR}.
##TODO####BROKEN###    local $| = 1;
##TODO####BROKEN##
##TODO####BROKEN##    # Have Expect tell me what it's doing for easier debugging.
##TODO####BROKEN##    $Expect::Exp_Internal = 1;
##TODO####BROKEN##
##TODO####BROKEN##    expect_run(
##TODO####BROKEN##        command => 't/bin-fetchware-new-cmd_new',
##TODO####BROKEN###        prompt => [-re => qr/((?<!\?  \[y\/N\]): |\? )/ms],
##TODO####BROKEN##        #prompt => [-re => qr/(\?|:) \[y\/N\] |\? |: /ims],
##TODO####BROKEN###        prompt => [-re => qr/((?:\?|:) \[y\/N\]: )|\? |: /i],
##TODO####BROKEN##        prompt => [-re => qr/ \[y\/N\]: |\? |: /i],
##TODO####BROKEN###        prompt => [-re => qr/\? \n/ims],
##TODO####BROKEN##        quit => "\cC"
##TODO####BROKEN##    );
##TODO####BROKEN##
##TODO####BROKEN##    # Have Expect restart its timeout anytime output is received. Should keep
##TODO####BROKEN##    # expect from timeingout while it's waiting for Apache to compile.
##TODO####BROKEN##    #my $exp = expect_handle();
##TODO####BROKEN##    #$exp->restart_timeout_upon_receive(1);
##TODO####BROKEN##
##TODO####BROKEN##    # First test that the command produced the correct outout.
##TODO####BROKEN##    expect_like(qr/Fetchware's new command is reasonably sophisticated, and is smart enough to/ms,
##TODO####BROKEN##        'checked cmd_new() received correct name prompt');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send('Apache',
##TODO####BROKEN##        'check cmd_new() sent Apache as my name.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_like(qr/Fetchware's heart and soul is its lookup_url. This is the configuration option/ms,
##TODO####BROKEN##        'checked cmd_new() received lookup_url prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send("$ENV{FETCHWARE_HTTP_LOOKUP_URL}",
##TODO####BROKEN##        'checked cmd_new() say lookup_url.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_like(qr/Fetchware requires you to please provide a mirror. This mirror is required,/ms,
##TODO####BROKEN##        'checked cmd_new() received mirror prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send("$ENV{FETCHWARE_HTTP_MIRROR_URL}",
##TODO####BROKEN##        'checked cmd_new() say mirror.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_like(qr/In addition to the one required mirror that you must define in order for/ms,
##TODO####BROKEN##        'checked cmd_new() received more mirrors prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send('N',
##TODO####BROKEN##        'checked cmd_new() say N for more mirrors.');
##TODO####BROKEN##
##TODO####BROKEN##    #expect_like(qr!\[y/N\]|gpg digital signatures found. Using gpg verification.!ms,
##TODO####BROKEN##    expect_like(qr!.*|gpg digital signatures found. Using gpg verification.!ms,
##TODO####BROKEN##        'checked cmd_new() received filter prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send('httpd-2.2',
##TODO####BROKEN##        'checked cmd_new() say httpd-2.2 for filter option.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_like(qr/Fetchware has many different configuration options that allow you to control its/ms,
##TODO####BROKEN##        'checked cmd_new() received extra config prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send('N',
##TODO####BROKEN##        'checked cmd_new() say N for more config options prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_like(qr/Fetchware has now asked you all of the needed questions to determine what it/ms,
##TODO####BROKEN##        'checked cmd_new() received edit config prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send('N',
##TODO####BROKEN##        'checked cmd_new() say N for edit config prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_like(qr/It is recommended that fetchware go ahead and install the program based on the/ms,
##TODO####BROKEN##        'checked cmd_new() received install program prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    # Say no to avoid actually installing Apache yet again.
##TODO####BROKEN##    expect_send('N',
##TODO####BROKEN##        'checked cmd_new() say N for install program prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_quit();
##TODO####BROKEN##};

} # #End of gigantic skip block.

# Remove this or comment it out, and specify the number of tests, because doing
# so is more robust than using this, but this is better than no_plan.
#done_testing();

t/App-FetchwareX-HTMLPageSync-new  view on Meta::CPAN

    'checked $fetchwarefile for html_page_url.');
like($fetchwarefile, qr{destination_directory '/tmp';},
    'checked $fetchwarefile for destination_directory.');
like($fetchwarefile, qr/keep_destination_directory 'True';/,
    'checked $fetchwarefile for keep_destination_directory.');


# Spit out # of tests run.
done_testing();

# Print a bogus "prompt" to keep Expect from freaking out, because it presumes
# the prompt works like it does in a shell, but fetchware new is not a shell.
print "Bogus shell: \n";

# Because we're in a child process not the same one that is running the main
# test suite, if any tests fail this failure will not be reported back to our
# caller. So, we use Test::Builder to check if our tests have passed, and if
# they have we do nothing and return succes, but if not we throw an exception.
my $test = Test::Builder->new();
unless ($test->is_passing()) {
    diag explain \[$test->details()];
    die <<EOD;

t/App-FetchwareX-HTMLPageSync-new-ask_about_keep_destination_directory  view on Meta::CPAN

# Only test it if it exists, because if the caller supplies a 'n' as the answer,
# then it is not added, so I must account for both possibilities.
if (defined $keep_destination_directory) {
    is($keep_destination_directory, 'True',
        'checked ask_about_keep_destination_directory() added config option.');
}

# Spit out # of tests run.
done_testing();

# Print a bogus "prompt" to keep Expect from freaking out, because it presumes
# the prompt works like it does in a shell, but fetchware new is not a shell.
print "Bogus shell: \n";

# Because we're in a child process not the same one that is running the main
# test suite, if any tests fail this failure will not be reported back to our
# caller. So, we use Test::Builder to check if our tests have passed, and if
# they have we do nothing and return succes, but if not we throw an exception.
my $test = Test::Builder->new();
unless ($test->is_passing()) {
    diag explain \[$test->details()];
    die <<EOD;

t/App-FetchwareX-HTMLPageSync-new-get_destination_directory  view on Meta::CPAN

my $term = Term::ReadLine->new('testing HTMLPageSync new');

my $destination_directory = get_destination_directory($term);

is($destination_directory, '/tmp/somedir/that/doesntexist/somewhereelse',
    'checked get_destination_directory() received correct input');

# Spit out # of tests run.
done_testing();

# Print a bogus "prompt" to keep Expect from freaking out, because it presumes
# the prompt works like it does in a shell, but fetchware new is not a shell.
print "Bogus shell: \n";

# Because we're in a child process not the same one that is running the main
# test suite, if any tests fail this failure will not be reported back to our
# caller. So, we use Test::Builder to check if our tests have passed, and if
# they have we do nothing and return succes, but if not we throw an exception.
my $test = Test::Builder->new();
unless ($test->is_passing()) {
    diag explain \[$test->details()];
    die <<EOD;

t/App-FetchwareX-HTMLPageSync-new-get_html_page_url  view on Meta::CPAN

my $term = Term::ReadLine->new('testing HTMLPageSync new');

my $page_name = get_html_page_url($term);

is($page_name, 'http://fake.url/Test-HTMLPageSync.html',
    'checked get_html_page_url() received correct input');

# Spit out # of tests run.
done_testing();

# Print a bogus "prompt" to keep Expect from freaking out, because it presumes
# the prompt works like it does in a shell, but fetchware new is not a shell.
print "Bogus shell: \n";

# Because we're in a child process not the same one that is running the main
# test suite, if any tests fail this failure will not be reported back to our
# caller. So, we use Test::Builder to check if our tests have passed, and if
# they have we do nothing and return succes, but if not we throw an exception.
my $test = Test::Builder->new();
unless ($test->is_passing()) {
    diag explain \[$test->details()];
    die <<EOD;

t/App-FetchwareX-HTMLPageSync.t  view on Meta::CPAN

    skip_all_unless_release_testing();

    plan(skip_all => 'Optional Test::Expect testing module not installed.')
        unless eval {require Test::Expect; Test::Expect->import(); 1;};

    # Have Expect tell me what it's doing for easier debugging.
    #$Expect::Exp_Internal = 1;

    expect_run(
        command => 't/App-FetchwareX-HTMLPageSync-new-get_html_page_url',
        prompt => [-re => qr/: |\? /],
        quit => "\cC"
    );

    # First test that the command produced the correct outout.
    expect_like(qr/Fetchware's heart and soul is its html_page_url. This is the configuration option/,
        'checked get_html_page_url() received correct prompt');

    # Have Expect print an example URL.
    expect_send('http://fake.url/Test-HTMLPageSync.html',
        'check get_html_page_url() sent answer.');

    expect_quit();
};


subtest 'test HTMLPageSync new() helper get_destination_directory' => sub {
    skip_all_unless_release_testing();

    plan(skip_all => 'Optional Test::Expect testing module not installed.')
        unless eval {require Test::Expect; Test::Expect->import(); 1;};

    # Have Expect tell me what it's doing for easier debugging.
    #$Expect::Exp_Internal = 1;

    expect_run(
        command => 't/App-FetchwareX-HTMLPageSync-new-get_destination_directory',
        prompt => [-re => qr/: |\? /],
        quit => "\cC"
    );

    # First test that the command produced the correct outout.
    expect_like(qr/destination_directory is the directory on your computer where you want the files/,
        'checked get_destination_directory() received correct prompt');

    # Have Expect print an example URL.
    expect_send('/tmp/somedir/that/doesntexist/somewhereelse',
        'check get_destination_directory() sent answer.');

    expect_quit();
};


subtest 'test HTMLPageSync new() helper ask_about_keep_destination_directory' => sub {

t/App-FetchwareX-HTMLPageSync.t  view on Meta::CPAN


    plan(skip_all => 'Optional Test::Expect testing module not installed.')
        unless eval {require Test::Expect; Test::Expect->import(); 1;};

    # Have Expect tell me what it's doing for easier debugging.
    #$Expect::Exp_Internal = 1;

    # Test saying n.
    expect_run(
        command => 't/App-FetchwareX-HTMLPageSync-new-ask_about_keep_destination_directory',
        prompt => [-re => qr/: |\? /],
        quit => "\cC"
    );

    # First test that the command produced the correct outout.
    expect_like(qr/By default, HTMLPageSync deletes your destination_directory when you uninstall/,
        'checked get_destination_directory() received correct prompt');

    # Have Expect print an example URL.
    expect_send('n',
        'check get_destination_directory() sent answer.');

    expect_quit();

    # Test saying y.

    expect_run(
        command => 't/App-FetchwareX-HTMLPageSync-new-ask_about_keep_destination_directory',
        prompt => [-re => qr/: |\? /],
        quit => "\cC"
    );

    # First test that the command produced the correct outout.
    expect_like(qr/By default, HTMLPageSync deletes your destination_directory when you uninstall/,
        'checked get_destination_directory() received correct prompt');

    # Have Expect print an example URL.
    expect_send('y',
        'check get_destination_directory() sent answer.');

    expect_quit();
};



t/App-FetchwareX-HTMLPageSync.t  view on Meta::CPAN

##BROKEN####TEST##
##BROKEN####TEST##    plan(skip_all => 'Optional Test::Expect testing module not installed.')
##BROKEN####TEST##        unless eval {require Test::Expect; Test::Expect->import(); 1;};
##BROKEN####TEST##
##BROKEN####TEST##    # Have Expect tell me what it's doing for easier debugging.
##BROKEN####TEST##    $Expect::Exp_Internal = 1;
##BROKEN####TEST##
##BROKEN####TEST##    # Test saying n.
##BROKEN####TEST##    expect_run(
##BROKEN####TEST##        command => 't/App-FetchwareX-HTMLPageSync-new',
##BROKEN####TEST##        prompt => [-re => qr/: |\? /],
##BROKEN####TEST##        quit => "\cC"
##BROKEN####TEST##    );
##BROKEN####TEST##
##BROKEN####TEST##    # First test that the command produced the correct outout.
##BROKEN####TEST##    expect_like(qr/HTMLPageSync's new command is not as sophistocated as Fetchware's. Unless you/,
##BROKEN####TEST##        'checked new() received correct prompt');
##BROKEN####TEST##    # Have Expect print an example URL.
##BROKEN####TEST##    expect_send('test',
##BROKEN####TEST##        'check new() sent answer.');
##BROKEN####TEST##
##BROKEN####TEST##    # First test that the command produced the correct outout.
##BROKEN####TEST##    expect_like(qr/Fetchware's heart and soul is its html_page_url. This is the configuration option/,
##BROKEN####TEST##        'checked new() received correct prompt');
##BROKEN####TEST##    # Have Expect print an example URL.
##BROKEN####TEST##    expect_send('http://test.test/test',
##BROKEN####TEST##        'check new() sent answer.');
##BROKEN####TEST##
##BROKEN####TEST##    # First test that the command produced the correct outout.
##BROKEN####TEST##    expect_like(qr/destination_directory is the directory on your computer where you want the files/,
##BROKEN####TEST##        'checked new() received correct prompt');
##BROKEN####TEST##    # Have Expect print an example URL.
##BROKEN####TEST##    expect_send('/tmp',
##BROKEN####TEST##        'check new() sent answer.');
##BROKEN####TEST##
##BROKEN####TEST##    # First test that the command produced the correct outout.
##BROKEN####TEST##    expect_like(qr/By default, HTMLPageSync deletes your destination_directory when you uninstall/,
##BROKEN####TEST##        'checked new() received correct prompt');
##BROKEN####TEST##    # Have Expect print an example URL.
##BROKEN####TEST##    expect_send('Y',
##BROKEN####TEST##        'check new() sent answer.');
##BROKEN####TEST##
##BROKEN####TEST##    # First test that the command produced the correct outout.
##BROKEN####TEST##    expect_like(qr/Fetchware has many different configuration options that allow you to control its/,
##BROKEN####TEST##        'checked new() received correct prompt');
##BROKEN####TEST##    # Have Expect print an example URL.
##BROKEN####TEST##    expect_send('N',
##BROKEN####TEST##        'check new() sent answer.');
##BROKEN####TEST##
##BROKEN####TEST##    # First test that the command produced the correct outout.
##BROKEN####TEST##    expect_like(qr/Fetchware has now asked you all of the needed questions to determine what it/,
##BROKEN####TEST##        'checked new() received correct prompt');
##BROKEN####TEST##    # Have Expect print an example URL.
##BROKEN####TEST##    expect_send('N',
##BROKEN####TEST##        'check new() sent answer.');
##BROKEN####TEST##
##BROKEN####TEST##    expect_quit();
##BROKEN####TEST##};


subtest 'test new_install() success' => sub {
    skip_all_unless_release_testing();

t/bin-fetchware-new.t  view on Meta::CPAN

##TODO####BROKEN##    local $Term::UI::AUTOREPLY = 0;
##TODO####BROKEN##    # Fix the "out of orderness" thanks to Test::Builder messing with
##TODO####BROKEN##    # STD{OUT,ERR}.
##TODO####BROKEN###    local $| = 1;
##TODO####BROKEN##
##TODO####BROKEN##    # Have Expect tell me what it's doing for easier debugging.
##TODO####BROKEN##    $Expect::Exp_Internal = 1;
##TODO####BROKEN##
##TODO####BROKEN##    expect_run(
##TODO####BROKEN##        command => 't/bin-fetchware-new-cmd_new',
##TODO####BROKEN###        prompt => [-re => qr/((?<!\?  \[y\/N\]): |\? )/ms],
##TODO####BROKEN##        #prompt => [-re => qr/(\?|:) \[y\/N\] |\? |: /ims],
##TODO####BROKEN###        prompt => [-re => qr/((?:\?|:) \[y\/N\]: )|\? |: /i],
##TODO####BROKEN##        prompt => [-re => qr/ \[y\/N\]: |\? |: /i],
##TODO####BROKEN###        prompt => [-re => qr/\? \n/ims],
##TODO####BROKEN##        quit => "\cC"
##TODO####BROKEN##    );
##TODO####BROKEN##
##TODO####BROKEN##    # Have Expect restart its timeout anytime output is received. Should keep
##TODO####BROKEN##    # expect from timeingout while it's waiting for Apache to compile.
##TODO####BROKEN##    #my $exp = expect_handle();
##TODO####BROKEN##    #$exp->restart_timeout_upon_receive(1);
##TODO####BROKEN##
##TODO####BROKEN##    # First test that the command produced the correct outout.
##TODO####BROKEN##    expect_like(qr/Fetchware's new command is reasonably sophisticated, and is smart enough to/ms,
##TODO####BROKEN##        'checked cmd_new() received correct name prompt');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send('Apache',
##TODO####BROKEN##        'check cmd_new() sent Apache as my name.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_like(qr/Fetchware's heart and soul is its lookup_url. This is the configuration option/ms,
##TODO####BROKEN##        'checked cmd_new() received lookup_url prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send("$ENV{FETCHWARE_HTTP_LOOKUP_URL}",
##TODO####BROKEN##        'checked cmd_new() say lookup_url.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_like(qr/Fetchware requires you to please provide a mirror. This mirror is required,/ms,
##TODO####BROKEN##        'checked cmd_new() received mirror prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send("$ENV{FETCHWARE_HTTP_MIRROR_URL}",
##TODO####BROKEN##        'checked cmd_new() say mirror.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_like(qr/In addition to the one required mirror that you must define in order for/ms,
##TODO####BROKEN##        'checked cmd_new() received more mirrors prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send('N',
##TODO####BROKEN##        'checked cmd_new() say N for more mirrors.');
##TODO####BROKEN##
##TODO####BROKEN##    #expect_like(qr!\[y/N\]|gpg digital signatures found. Using gpg verification.!ms,
##TODO####BROKEN##    expect_like(qr!.*|gpg digital signatures found. Using gpg verification.!ms,
##TODO####BROKEN##        'checked cmd_new() received filter prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send('httpd-2.2',
##TODO####BROKEN##        'checked cmd_new() say httpd-2.2 for filter option.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_like(qr/Fetchware has many different configuration options that allow you to control its/ms,
##TODO####BROKEN##        'checked cmd_new() received extra config prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send('N',
##TODO####BROKEN##        'checked cmd_new() say N for more config options prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_like(qr/Fetchware has now asked you all of the needed questions to determine what it/ms,
##TODO####BROKEN##        'checked cmd_new() received edit config prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_send('N',
##TODO####BROKEN##        'checked cmd_new() say N for edit config prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_like(qr/It is recommended that fetchware go ahead and install the program based on the/ms,
##TODO####BROKEN##        'checked cmd_new() received install program prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    # Say no to avoid actually installing Apache yet again.
##TODO####BROKEN##    expect_send('N',
##TODO####BROKEN##        'checked cmd_new() say N for install program prompt.');
##TODO####BROKEN##
##TODO####BROKEN##    expect_quit();
##TODO####BROKEN##};
##TODO##
##TODO##} # #End of gigantic skip block.

# Remove this or comment it out, and specify the number of tests, because doing
# so is more robust than using this, but this is better than no_plan.
#done_testing();



( run in 1.389 second using v1.01-cache-2.11-cpan-6aa56a78535 )