#!/usr/bin/perl -w

###############################################################################
# Runs krazy over the KDE source code                                         #
# Copyright 2006-2010 by Allen Winter <winter@kde.org>                        #
#                                                                             #
# This program is free software; you can redistribute it and/or modify        #
# it under the terms of the GNU General Public License as published by        #
# the Free Software Foundation; either version 2 of the License, or           #
# (at your option) any later version.                                         #
#                                                                             #
# This program is distributed in the hope that it will be useful,             #
# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                #
# GNU General Public License for more details.                                #
#                                                                             #
# You should have received a copy of the GNU General Public License along     #
# with this program; if not, write to the Free Software Foundation, Inc.,     #
# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.               #
#                                                                             #
###############################################################################

use strict;
use Getopt::Long;
use Cwd;
use FindBin qw($Bin);
use lib "$Bin/../lib";
use Krazy::Utils;

my ($Prog) = 'krazy2all';
my
 $VERSION = '2.92';    #split line so MakeMaker can find the version here

my ($help)      = '';
my ($version)   = '';
my ($list)      = '';
my ($listtypes) = '';
my ($verbose)   = '';
my ($ignorerc)  = '';
my ($configf)   = '';
my ($dryrun)    = '';
my ($brief)     = '';
my ($nobrief)   = '';
my ($quiet)     = '';
my ($priority)  = '';
my ($strict)    = '';
my ($check)     = '';
my ($checksets) = '';
my ($exclude)   = '';
my ($extra)     = '';
my ($inctypes)  = '';
my ($exctypes)  = '';
my ($export)    = '';
my ($title)     = '';
my ($cms)       = '';

exit 1
  if ( !GetOptions(
		   'help'           => \$help,
		   'version'        => \$version,
		   'list'           => \$list,
		   'list-types'     => \$listtypes,
		   'dry-run'        => \$dryrun,
		   'ignorerc'       => \$ignorerc,
                   'config=s'       => \$configf,
		   'verbose'        => \$verbose,
		   'brief'          => \$brief,
                   'no-brief'       => \$nobrief,
		   'quiet'          => \$quiet,
		   'priority=s'     => \$priority,
		   'strict=s'       => \$strict,
		   'check=s'        => \$check,
                   'check-sets=s'   => \$checksets,
		   'exclude=s'      => \$exclude,
		   'extra=s'        => \$extra,
                   'types=s'        => \$inctypes,
                   'exclude-types=s'=> \$exctypes,
		   'export=s'       => \$export,
		   'title=s'        => \$title,
		   'cms=s'          => \$cms
		  )
     );

&Help()    if ($help);
&Version() if ($version);

if ($list) {
  system("krazy2 --list");
  exit 0;
}

if ($listtypes) {
  system("krazy2 --list-types");
  exit 0;
}

if ($priority && !&validatePriorityType($priority)) {
  die "Bad priority level \"$priority\" specified... exiting\n";
}

if ($strict && !&validateStrictType($strict)) {
  die "Bad strictness level \"$strict\" specified... exiting\n";
}

if ($export && !&validateExportType($export)) {
  die "Unsupported export type \"$export\"... exiting\n";
}

# Options to pass to Krazy
my ($opts) = "";
$opts .= "--dry-run "                 if ($dryrun);
$opts .= "--ignorerc "                if ($ignorerc);
$opts .= "--config=$configf "         if ($configf);
$opts .= "--brief "                   if ($brief);
$opts .= "--no-brief "                if ($nobrief);
$opts .= "--quiet "                   if ($quiet);
$opts .= "--verbose "                 if ($verbose);
$opts .= "--check=$check "            if ($check);
$opts .= "--check-sets=$checksets "   if ($checksets);
$opts .= "--exclude=$exclude "        if ($exclude);
$opts .= "--extra=$extra "            if ($extra);
$opts .= "--types=$inctypes "         if ($inctypes);
$opts .= "--exclude-types=$exctypes " if ($exctypes);
$opts .= "--export=$export "          if ($export);
$opts .= "--title=\"$title\" "        if ($title);
$opts .= "--cms=$cms "                if ($cms);
$opts .= "--priority=$priority "      if ($priority);
$opts .= "--strict=$strict "          if ($strict);
$opts .= "--explain"                  if ($export ne "textlist" && $export ne "textedit");

my($files) = &findFiles();
my($cwd) = getcwd;
$cwd =~ s:\+:\\\+:g;  #escape '+'
$files =~ s+^$cwd+\.+gm;
$files =~ s+\\n+\'\\n\'+g;
open(P, "| krazy2 $opts -");
print P "$files\n";
close(P);

exit 0;

# Help function: print help message and exit.
sub Help {
  &Version();
  print "Run krazy2 on all the source in the current working directory\n\n";
  print "Usage: $Prog [OPTION]\n";
  print "  --help       display help message and exit\n";
  print "  --version    display version information and exit\n";
  print "  --list       list all the checker programs and exit\n";
  print "  --list-types list all the supported file types and exit\n";
  print "  --priority <low|normal|high|important|all>\n";
  print "               report only issues with the specified priorities:\n";
  print "                 low -> print low priority issues only\n";
  print "                 normal -> print normal priority issues only\n";
  print "                 high -> print high priority issues only\n";
  print "                 important -> print issues with normal or high priority\n";
  print "                 all -> print all issues (default)\n";
  print "               use priorities to help put the issues in fix-first order.\n";
  print "  --strict <normal|super|all>\n";
  print "               report only issues matching the strictness level:\n";
  print "                 normal -> print non-super strict issues only\n";
  print "                 super -> print super strict issues only\n";
  print "                 all -> print all issues (default)\n";
  print "               use strictness to help filter out issues of less importance\n";
  print "  --check <prog[,prog1,prog2,...,progN]>\n";
  print "               run the specified sanity checker program(s) only\n";
  print "  --check-sets <set[,set1,set2,...,setN]>\n";
  print "               run the checker programs belonging to the specified set(s) only\n";
  print "  --exclude <prog[,prog1,prog2,...,progN]>\n";
  print "               do NOT run the specified checker program(s)\n";
  print "  --extra <prog[,prog1,prog2,...,progN]>:\n";
  print "               add the specified \"extra\" program(s) to the checker list\n";
  print "  --types <type[,type1,type2,...,typeN]>:\n";
  print "               check the specified file type(s) only\n";
  print "  --exclude-types <type[,type1,type2,...,typeN]>:\n";
  print "               do NOT check the specified file type(s)\n";
  print "  --export <text|textlist|textedit|xml>\n";
  print "               output in one of the following formats:\n";
  print "                 text (default)\n";
  print "                 textlist -> plain old text, 1 offending file-per-line\n";
  print "                 textedit -> text formatted for IDEs, 1 issue-per-line\n";
  print "                 xml -> XML formatted\n";
  print "  --title:     give the output a project title\n";
  print "  --cms        component/module/subdir triple for XML\n";
  print "  --ignorerc:  ignore .krazy files\n";
  print "  --config <krazyrc>\n";
  print "               read settings from the specified config file\n";
  print "  --dry-run    don't execute the checks; only show what would be run\n";
  print "  --brief:     print only checks with at least 1 issue\n";
  print "  --no-brief:  print the result of all checks i.e, the opposite of brief (default)\n";
  print "  --quiet      suppress all output messages\n";
  print "  --verbose    print the offending content for each file processed\n";
  print "\n";
  exit 0 if $help;
}

# Version function: print the version number and exit.
sub Version {
  print "$Prog, version $VERSION\n";
  exit 0 if $version;
}

__END__

#==============================================================================

=head1 NAME

krazy2all - Sanity checks KDE source code.

=head1 SYNOPSIS

krazy2all [options]

=head1 DESCRIPTION

krazy2all finds all supported files within the current directory tree
and runs the krazy2 checker on all of them, producing 1 concise report
in the specified export format.

=head1 OPTIONS

=over 4

=item B<--help>

Print help message and exit.

=item B<--version>

Print version information and exit.

=item B<--list>

Print a list of all available checker programs and exit.

=item B<--list-types>

Print a list of the support file types and exit.

=item B<--ignorerc>

Ignore .krazy files.

=item B<--config> <krazyrc>

Read settings from the specified krazyrc configuration file only.
All other configuration files will be ignored, including those
found in the user's home directory or in the current working directory.

=item B<--dry-run>

With this option the checker programs aren't run; instead, the command line
for each check that would be run is printed.

=item B<--priority> <low|normal|high|important|all>

Tell each checker program to report issues with the specified priority only.
This option is useful to help put issues into "fix-first" order.

Supported priorites are:
     low -> print low priority issues only
     normal -> print normal priority issues only
     high -> print high priority issues only
     important -> print issues with normal or high priority
     all -> print all issues (default)

=item B<--strict> <normal|super|all>

Tell each checker program to report issues match the strictness level only.
Use this option to help filter out issues of less importance.

Support strictness levels are:
     normal -> print non-super strict issues only
     super -> print super strict issues only
     all -> print all issues (default)

=item B<--check> <prog[,prog1,prog2,...,progN]>

Run the specified checker program(s) only.
You may not combine this option with B<--check-sets>.

Use the B<--list> option to show the list of available checkers.

=item B<--check-sets> <set[,set1,set2,...,setN]>

Run the checker programs belonging to the specified set(s) only.
You may not combine this option with B<--check>.

Use the B<--list-sets> option to see the list of available check sets and programs.

=item B<--exclude> <prog[,prog1,prog2,...,progN]>

Do B<NOT> run the specified checker program(s).

=item B<--extra> <prog[,prog1,prog2,...,progN]>

Add the specified "extra" program(s) to the list of checkers to run.
Use the --list option to show the list of available "extra" checkers; they
will be marked with the tag [EXTRA] by the checker description line.

=item B<--types> <type[,type1,type2,...,typeN]>

Check the specified file type(s) only.

=item B<--exclude-types> <type[,type1,type2,...,typeN]>

Do NOT check the specified file type(s).

=item B<--export> <text|textlist|textedit|xml>

Output in one of the following formats:
     text (default)
     textlist -> plain old text, 1 offending file-per-line
     textedit -> text formatted for IDEs, 1 issue-per-line (file:line:issue)
     xml -> XML formatted

=item B<--title>

Give the output report a project title.

=item B<--cms>

An acronym for "component/module/subdir".  Used to write the breadcrumbs line
in the XML output.  Must be a slash-delimited triple containing the component,
module, and subdir which is being scanned.

=item B<--brief>

Only print the output for checkers that have at least 1 issue.

=item B<--no-brief>

Print the result of all checks i.e, the opposite of B<--brief>.
This is the default output setting.

=item B<--quiet>

Suppress all output messages.

=item B<--verbose>

Print the offending content for each file processed

=back

=head1 ENVIRONMENT

KRAZY_PLUGIN_PATH - this is a colon-separated list of paths which is
searched when locating plugins. By default, plugins are searched for in
the path F<$TOP/lib/krazy2/krazy-plugins:krazy-plugins>.

KRAZY_EXTRA_PATH - this is a colon-separated list of paths which is
searched when locating "extra" plugins. By default, the "extras" are searched
for in the path F<$TOP/lib/krazy2/krazy-extras:krazy-extras>.

KRAZY_SET_PATH - this is a colon-separated list of paths which is
searched when locating checker sets. By default, the sets are searched
for in the path F<$TOP/lib/krazy2/krazy-sets:krazy-sets>.

where $TOP is the top-level installation directory (eg. F</usr/local>, F</usr/local/Krazy2>)

=head1 EXIT STATUS

In normal operation, krazy2all exits with a status 0.

If a command line option was incorrectly provided, krazy2all exits with
status=1.

If krazy2all was envoked with the B<--help>, B<--version>  B<--list>
or B<--list-types> options it will exit with status=0.

=head1 COPYRIGHT

Copyright (c) 2005-2010 by Allen Winter <winter@kde.org>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

=head1 FILES

F<.krazy> (see krazyrc(3))

krazy2all looks up the current working directory tree for a F<.krazy> file
in the project subdirectory.  Only F<.krazy> files found at the project
subdirectory level are read.

For example, if the current working dir is
F</my/kde/trunk/KDE/kdepimlibs/kcal/versit>, then krazy2all will look for
F</my/kde/trunk/KDE/kdepimlibs/kcal/.krazy>, since kcal is the project
within the kdepimlibs module.

If the current working dir is not within a KDE module, or if the current
working dir is above a project subdir, then a F<.krazy> file will not be read.


=head1 SEE ALSO

krazyrc(3), krazy2(1), krazy2xml(1)

=head1 AUTHORS

Allen Winter, <winter@kde.org>

=cut
