Logo Search packages:      
Sourcecode: bazaar version File versions

status.c

/* status.c
 *
 ****************************************************************
 * Copyright (C) 2003 Tom Lord
 * Copyright (C) 2004 Canonical Ltd.
 *
 * See the file "COPYING" for further information about
 * the copyright and warranty status of this work.
 */


#include "config-options.h"
#include "po/gettext.h"
#include "hackerlab/cmd/main.h"
#include "libarch/chatter.h"
#include "libarch/inode-sig.h"
#include "libarch/local-cache.h"
#include "libarch/make-changeset.h"
#include "libarch/project-tree.h"
#include "libarch/proj-tree-lint.h"
#include "libfsutils/rmrf.h"
#include "commands/cmd.h"
#include "commands/diff.h"
#include "commands/status.h"
#include "commands/version.h"



static t_uchar * usage = N_("[options] [dir]");
static void lint (struct arch_tree_lint_result * lint_result,  int categories_filter, int escape_classes);
static int lint_status (struct arch_tree_lint_result * lint_result,  int categories_filter);
static int changes (arch_project_tree_t *tree, t_uchar * program_name);

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

t_uchar arch_cmd_status_help[] = N_("scan a project tree and show the tree status.\n"
                                      "\n"
                                     "Audit a source tree for various changes, the characters in the first column mean:\n"
                                     "C - conflicts\n"
                             "R - renames\n"
                             "A - adds\n"
                             "D - deletes\n"
                             "P - permissions\n"
                             "? - unexpected files\n"
                                     "By default, changes will report the status \n"
                                     "for everything within a tree. Specific changes\n"
                                     "may be ignored by passing options to the\n"
                                     "changes command\n\n"
                                     "Note: If conflicts have occurred, when you have\n"
                             "resolved them, notify baz by run baz resolved --all\n");
                                     
enum options
{
  OPTS (OPT_ENUM)
};

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



int
arch_cmd_status (t_uchar * program_name, int argc, char * argv[])
{
  int o;
  struct opt_parsed * option;
  char * dir;
  int strict = 0;
  int only_lint = 0;
  int result = 0;

  t_uint categories_filter = 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, libarch_version_string, arch_cmd_status_help, opt_help_msg, opt_long_help, opt_version);
      if (o == opt_none)
        break;
      switch (o)
        {
/* Begin Option error handling------------------------------------- */
        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;
/* Begin General options ------------------------------------- */
        case opt_strict:
          {
            strict = 1;
            break;
          }

        case opt_lint :
          {
            only_lint = 1;
          break;
          }

/* BEGIN Lint options ------------------------------------- */
        case opt_broken_symlink:
          {
            categories_filter = categories_filter | symlinks_sans_targets;
            break;
          }

        case opt_unrecognized_files:
          {
            categories_filter = categories_filter | unrecognized_files;
            break;
          }

        case opt_untagged_files:
          {
            categories_filter = categories_filter | untagged_files;
            break;
          }

        case opt_missing_files:
          {
            categories_filter = categories_filter | ids_sans_files;
            break;
          }

        case opt_duplicate_ids:
          {
            categories_filter = categories_filter | duplicate_id_groups;
            break;
          }

      case opt_unescaped:
        {
          escape_classes = 0;
          break;
        }
      case opt_diffs:
        {
          safe_printfmt(2, "This option is deprecated. Please baz diff instead\n");
          exit(2);
          break;
        }
        }
    }

  if (argc > 2)
    goto usage_error;

  {
    int status;
    int outstanding_rejects = 0;
    arch_project_tree_t tree;
    struct arch_tree_lint_result * lint_result;
    
    /* The first thing we do is determine the tree root, which
     * is used by several of the command suboptions
     */
    if (argc == 1)
      dir = ".";
    else
      dir = argv[1];

    arch_project_tree_init (&tree, dir);

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

    /* Now, we know what directory we're working with. Now, we need to
     * run our problem finding commands. Each of the following commands
     * runs a specific set of checks for us, telling the user of changes,
     * returning to us whether or not there was success or failure. If there
     * is any failure, then we'll return a pass/fail error code back to the
     * shell
     * FIXME: Would it be useful to return a an enumerated set of bools
     * back to the shell, so that things like pybaz and fai can tell what went
     * wrong?
     */

    /* perhaps the output from lint and changes should be combined for the UI ? 
     * if so, perhaps print_compact can be given a lint report as an option 
     *
     * Note: We need to lint first, so that if things bomb, the user has a
     * better understanding of why
     */

    lint_result = arch_tree_lint (tree.root);
    status = lint_status (lint_result, categories_filter);

    if (! only_lint  && ! categories_filter)
      {
      
      /* -1 is hard errors, 1 is warnings */
      if (status < 0)
        {
          lint (lint_result, categories_filter, escape_classes);
          safe_printfmt(2, "Tree is not lint clean. Unable to continue past this point\n");
          exit(1);
        }
      status |= changes (&tree, argv[0]);
      }

    lint (lint_result, categories_filter, escape_classes);

    outstanding_rejects = arch_tree_rejects_exist(tree.root);
    if ( outstanding_rejects && ! categories_filter && ! only_lint)
      {
      /* maybe this should be part of lint ? */
        safe_printfmt(1, "This tree is in a conflicted state!\n");
      status = -1;
      }


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

    lim_free (0, lint_result);
    arch_project_tree_finalise (&tree);
  }

  return result;
}




/* Supporting functions are below this point */


/* This function prints the lints from tree */
void
lint (struct arch_tree_lint_result * lint_result, int categories_filter, int escape_classes)
{
  if (categories_filter)
    {
      arch_print_filtered_tree_lint_report (1, lint_result, categories_filter,
                                                   escape_classes);
      return;
    }
  else
    {
      arch_print_tree_lint_report (1, lint_result, escape_classes);
      return;
    }
}

/* get the status for a lint result */
int 
lint_status (struct arch_tree_lint_result * lint_result,  int categories_filter)
{
  if (categories_filter)
    {
      return arch_tree_lint_report_filtered_status (lint_result, categories_filter);
    }
  else
    {
      return arch_tree_lint_report_status (lint_result);
    }
}

/* this function generates a summary of the non lint related changes */
int
changes (arch_project_tree_t *tree, t_uchar * program_name)
{
    t_uchar * output = 0;
    rel_table limits = 0;
    int result = 0;
    
    output = arch_diff_default_output_dir (tree->root, 0 );

    /****************************************************************
     * The heart of the matter.
     */
    {
      t_uchar * orig_tree = 0;
      struct arch_make_changeset_report make_report = {0, };
      struct arch_changeset_report report = {0, };
      assoc_table inode_shortcut = 0;

      arch_chatter (1, "* looking for %s/%s to compare with\n", tree->archive, tree->revision);

      /* should be less noisy - RBC 20041209 */
      orig_tree = arch_find_or_make_local_copy (1, tree->root, 0, 0, tree->archive, tree->revision);

      if (!orig_tree)
        {
          safe_printfmt (2, "%s: no local copies to compare to (%s/%s)\n  consider `add-pristine --help'\n",
                         program_name, tree->archive, tree->revision);
          exit (2);
        }

      arch_chatter (1, "* comparing to %s/%s\n", tree->archive, tree->revision);

      arch_read_inode_sig_ids (0, &inode_shortcut, tree->root, tree->archive, tree->revision);
      arch_make_changeset (&make_report, orig_tree, tree->root, output, arch_unspecified_id_tagging, arch_inventory_unrecognized, limits, inode_shortcut, 0, arch_escape_classes);
      arch_evaluate_changeset (&report, output);
      result = arch_any_changes (&report);

      if (result)
        {
        safe_printfmt (1, "\n");
        arch_changeset_report_print_compact (1, &report, arch_escape_classes);
        }

      arch_free_make_changeset_report_data (&make_report);
      arch_free_changeset_report_data (&report);
      lim_free (0, orig_tree);

      rmrf_file (output);

      free_assoc_table (inode_shortcut);
    }
    return result;
}

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

Generated by  Doxygen 1.6.0   Back to index