/* cmd-tree-lint.c
 *
 ****************************************************************
 * Copyright (C) 2003 Tom Lord
 *
 * See the file "COPYING" for further information about
 * the copyright and warranty status of this work.
 */


#include "config-options.h"
#include "hackerlab/cmd/main.h"
#include "tla/libarch/project-tree.h"
#include "tla/libarch/proj-tree-lint.h"
#include "tla/libarch/cmd.h"
#include "tla/libarch/cmd-tree-lint.h"



static t_uchar * usage = "[options] [dir]";
static t_uchar * version_string = (cfg__std__package " from regexps.com\n"
                                   "\n"
                                   "Copyright 2003 Tom Lord\n"
                                   "\n"
                                   "This is free software; see the source for copying conditions.\n"
                                   "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n"
                                   "PARTICULAR PURPOSE.\n"
                                   "\n"
                                   "Report bugs to " cfg__tla_bug_mail ".\n"
                                   "\n"
                                   cfg__std__release_id_string
                                   "\n");

#define OPTS(OP) \
  OP (opt_help_msg, "h", "help", 0, \
      "Display a help message and exit.") \
  OP (opt_long_help, "H", 0, 0, \
      "Display a verbose help message and exit.") \
  OP (opt_version, "V", "version", 0, \
      "Display a release identifier string\n" \
      "and exit.") \
  OP (opt_broken_symlink, "s", "broken-symlinks", 0, \
      "Just list broken symlinks") \
  OP (opt_unrecognized_files, "u", "unrecognized-files", 0, \
      "Just list files violating naming conventions") \
  OP (opt_untagged_files, "t", "untagged-files", 0, \
      "Just list files lacking inventory ids") \
  OP (opt_missing_files, "m", "missing-files", 0, \
      "Just list inventory ids lacking corresponding files") \
  OP (opt_duplicate_ids, "d", "duplicate-ids", 0, \
      "Just list duplicated ids") \
  OP (opt_strict, 0, "strict", 0, \
      "exit with non-0 status on _any_ oddity") \
  OP (opt_unescaped, 0, "unescaped", 0, \
      "show filenames in unescaped form")

t_uchar arch_cmd_tree_lint_help[] = ("audit a source tree\n"
                                     "Audit a source tree for missing files, untagged files, duplicate ids,\n"
                                     "and files not matching recognized naming conventions.\n\n"
                                     "The default is to list files failing any of those tests.  Enabling any\n"
                                     "of the `specific' tests disables the rest, unless they're explicitly\n"
                                     "enabled on the command line. Therefore, \"tla tree-lint\" is\n"
                                     "equivalent to \"tla tree-lint -sutmd\"");

enum options
{
  OPTS (OPT_ENUM)
};

static struct opt_desc opts[] =
{
  OPTS (OPT_DESC)
    {-1, 0, 0, 0, 0}
};



int
arch_cmd_tree_lint (t_uchar * program_name, int argc, char * argv[])
{
  int o;
  struct opt_parsed * option;
  char * dir;
  int strict = 0;
  int filter_output = 0;
  t_uint categories = 0;
  int escape_classes = arch_escape_classes;

  safe_buffer_fd (1, 0, O_WRONLY, 0);

  option = 0;

  while (1)
    {
      o = opt_standard (lim_use_must_malloc, &option, opts, &argc, argv, program_name, usage, version_string, arch_cmd_tree_lint_help, opt_help_msg, opt_long_help, opt_version);
      if (o == opt_none)
        break;
      switch (o)
        {
        default:
          safe_printfmt (2, "unhandled option `%s'\n", option->opt_string);
          panic ("internal error parsing arguments");

        usage_error:
          opt_usage (2, argv[0], program_name, usage, 1);
          exit (1);

          /* bogus_arg: */
          safe_printfmt (2, "ill-formed argument for `%s' (`%s')\n", option->opt_string, option->arg_string);
          goto usage_error;

        case opt_strict:
          {
            strict = 1;
            break;
          }

        case opt_broken_symlink:
          {
            filter_output = 1;
            categories = categories | symlinks_sans_targets;
            break;
          }

        case opt_unrecognized_files:
          {
            filter_output = 1;
            categories = categories | unrecognized_files;
            break;
          }

        case opt_untagged_files:
          {
            filter_output = 1;
            categories = categories | untagged_files;
            break;
          }

        case opt_missing_files:
          {
            filter_output = 1;
            categories = categories | ids_sans_files;
            break;
          }

        case opt_duplicate_ids:
          {
            filter_output = 1;
            categories = categories | duplicate_id_groups;
            break;
          }

	case opt_unescaped:
	  {
	    escape_classes = 0;
	    break;
	  }

        }
    }

  if (argc > 2)
    goto usage_error;

  if (argc == 1)
    dir = ".";
  else
    dir = argv[1];

  {
    struct arch_tree_lint_result * result;
    int status;
    t_uchar * tree_root = 0;

    tree_root = arch_tree_root (0, dir, 0);
    if (!tree_root)
      {
        safe_printfmt (2, "%s: directory is not in a project tree.\n",
                       argv[0]);
        exit (1);
      }

    result = arch_tree_lint (tree_root);
    if (filter_output)
      status = arch_print_filtered_tree_lint_report (1, result, categories, escape_classes);
    else
      status = arch_print_tree_lint_report (1, result, escape_classes);

    if (strict)
      exit (status != 0);
    else
      exit (status < 0);

    lim_free (0, tree_root);
  }

  return 0;
}




/* tag: Tom Lord Mon May 12 12:25:44 2003 (tree-lint.c)
 */
