Logo Search packages:      
Sourcecode: bazaar version File versions

branch.c

/* cmd-tag.c
 *
 * vim:smartindent ts=8:sts=2:sta:et:ai:shiftwidth=2
 ****************************************************************
 * Copyright (C) 2003 Tom Lord
 * Portions (C) 2004 Canonical Ltd
 *          Author Robert Collins <robert.collins@canonical.com>
 *                 Rob Weir <rob.weir@canonical.com>
 *
 * 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 "hackerlab/fs/file-names.h"
#include "hackerlab/fs/cwd.h"
#include "libfsutils/tmp-files.h"
#include "libfsutils/file-contents.h"
#include "libfsutils/rmrf.h"
#include "libarch/archive-setup.h"
#include "libarch/inv-ids.h"
#include "libarch/namespace.h"
#include "libarch/project-tree.h"
#include "libarch/patch-logs.h"
#include "libarch/archive.h"
#include "libarch/build-revision.h"
#include "libarch/proj-tree-lint.h"
#include "libarch/tag.h"
#include "libarch/pfs.h"
#include "commands/cmd.h"
#include "commands/apply-delta.h"
#include "commands/branch.h"
#include "commands/cmdutils.h"
#include "commands/version.h"



static t_uchar * usage = N_("[options] [SOURCE] BRANCH");

#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\n" \
      "and exit.")) \
  OP (opt_log, "l", "log FILE", 1, \
      N_("commit with log file FILE")) \
  OP (opt_no_cacherev, 0, "no-cacherev", 0, \
      N_("Do not cacherev tag even if different archive")) \
  OP (opt_seal, 0, "seal", 0, \
      N_("create a version-0 revision")) \
  OP (opt_fix, 0, "fix", 0, \
      N_("create a versionfix revision")) \
  OP (opt_dir, "d", "dir DIR", 1, \
      "cd to DIR first")

t_uchar arch_cmd_branch_help[] = N_("create a branch\n"
                               "Create the continuation at the next patch level of BRANCH\n"
                               "which is equivalent to SOURCE.\n"
                               "\n"
                               "If SOURCE is not specified, the current project tree revision is used, \n"
                               "and the project tree is switched to BRANCH\n");
                                /* FIXME: describe the search path for SOURCE - patch level in tree-version. etc */

enum options
{
  OPTS (OPT_ENUM)
};

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

static void
easy_cacherev (struct arch_archive * tag_arch, t_uchar * tag_archive, t_uchar * tag_revision, t_uchar * program_name, char * dir)
{
  t_uchar * tmp_dir;
  t_uchar * pristine_dir;
  
  safe_printfmt (1, "* Archive caching revision\n");
  safe_flush (1);

  tmp_dir = tmp_file_name (dir, ",,archive-cache-revision");
  pristine_dir = file_name_in_vicinity (0, tmp_dir, tag_revision);
  safe_mkdir (tmp_dir, 0777);
  safe_mkdir (pristine_dir, 0777);

  arch_build_revision (1, pristine_dir, tag_arch, tag_archive, tag_revision, dir);
    
    {
      t_uchar * errstr;
      
      if (arch_archive_put_cached (&errstr, tag_arch, tag_revision, pristine_dir))
        {
          safe_printfmt (2, "Warning: %s: was unable to cache revision %s/%s (%s)\n",
                         program_name, tag_archive, tag_revision, errstr);
        }
      else
        {
          safe_printfmt (1, "* Made cached revision of %s/%s\n", tag_archive, tag_revision);
        }
    }
  rmrf_file (tmp_dir);
  rmrf_file (tmp_dir);
  lim_free (0, pristine_dir);
  lim_free (0, tmp_dir);
}



int
arch_cmd_branch (t_uchar * program_name, int argc, char * argv[])
{
  int o;
  struct opt_parsed * option;
  t_uchar * log_file = 0;
  char * dir = ".";
  int do_cacherev = 1;
  int seal = 0;
  int fix = 0;

  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_branch_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_log:
          {
            log_file = str_save (0, option->arg_string);
            break;
          }
        
        case opt_dir:
          {
            dir = str_save (0, option->arg_string);
            break;
          }

        case opt_no_cacherev:
          {
            do_cacherev = 0;
            break;
          }

        case opt_seal:
          {
            seal = 1;
            break;
          }

        case opt_fix:
          {
            fix = 1;
            break;
          }
        }
    }

  if (argc < 2 || argc > 3)
    goto usage_error;

  {
    t_uchar * tag_spec;
    t_uchar * source_revision = 0;
    t_uchar * tag_archive = 0;
    t_uchar * tag_version = 0;
    t_uchar * log = 0;
    struct arch_archive * source_arch = 0;
    struct arch_archive * tag_arch = 0;
    rel_table tag_version_revisions = 0;
    t_uchar * last_level = 0;
    enum arch_patch_level_type last_level_type;
    enum arch_patch_level_type desired_level_type;
    t_ulong last_n;
    t_ulong desired_n;
    t_uchar * desired_level = 0;
    t_uchar * tag_revision = 0;
    t_uchar * tree_root = 0;
    t_uchar *tree_archive = NULL;
    t_uchar *tree_fqrevision = NULL;
    
    tree_root = arch_tree_root (0, dir, 0);
    if (tree_root)
      {
      tree_fqrevision = arch_project_tree_revision (argv[0], tree_root);
        tree_archive = arch_parse_package_name (arch_ret_archive, NULL, tree_fqrevision);
        source_revision = arch_parse_package_name (arch_ret_non_archive, NULL, tree_fqrevision);
      }

    if (argc == 3)
      {
        source_revision = arch_determine_revision (&source_arch,
                                                 tree_archive,
                                                 argv[1],
                                                 argv[0]);
        tag_spec = argv[2];
      }
    else
      {
        if (!tree_root)
          {
            safe_printfmt (2, "%s: not in a project tree\n  dir: %s\n",
                           argv[0], arch_abs_path (dir));
            exit (2);
          }

        source_arch = arch_archive_connect (tree_archive, 0);
        tag_spec = argv[1];
      }

    if (log_file)
      {
        log = file_contents (log_file);
        if (!arch_valid_log_file (log))
          {
            safe_printfmt (2, "%s: invalid log file (%s)\n",
                           argv[0], log_file);
            exit (1);
          }
      }

    if (!arch_valid_package_name (tag_spec, arch_maybe_archive, arch_req_version, 0))
      {
        safe_printfmt (2, "%s: invalid version name -- %s\n",
                       argv[0], tag_spec);
        exit (1);
      }

    tag_archive = arch_parse_package_name (arch_ret_archive, tree_archive, tag_spec);
    tag_version = arch_parse_package_name (arch_ret_non_archive, NULL, tag_spec);

    if (arch_is_system_package_name (tag_version))
      {
        safe_printfmt (2, "%s: user's can not tag in system versions\n  version: %s\n", argv[0], tag_version);
        exit (2);
      }
    
    if (!str_cmp (source_arch->name, tag_archive))
      tag_arch = source_arch;
    else
      tag_arch = arch_archive_connect (tag_archive, 0);

    arch_setup_archive_simple (1, tag_archive, tag_version);

    tag_version_revisions = arch_archive_revisions (tag_arch, tag_version, 0);

    if (!tag_version_revisions)
      {
        desired_level_type = arch_is_base0_level;
        desired_n = 0;
      }
    else
      {
        last_level = str_save (0, tag_version_revisions[rel_n_records (tag_version_revisions) - 1][0]);
        last_level_type = arch_analyze_patch_level (&last_n, last_level);

        switch (last_level_type)
          {
          default:
            panic ("NOT IMPLEMENTED YET");
            panic ("internal error");
            break;

          case arch_is_base0_level:
            {
              if (seal)
                {
                  desired_level_type = arch_is_version_level;
                  desired_n = 0;
                }
              else if (fix)
                {
                  safe_printfmt (2, "%s: can not --fix before --seal",
                                 argv[0]);
                  exit (2);
                }
              else
                {
                  desired_level_type = arch_is_patch_level;
                  desired_n = 1;
                }
              break;
            }

          case arch_is_patch_level:
            {
              if (seal)
                {
                  desired_level_type = arch_is_version_level;
                  desired_n = 0;
                }
              else if (fix)
                {
                  safe_printfmt (2, "%s: can not --fix before --seal",
                                 argv[0]);
                  exit (2);
                }
              else
                {
                  desired_level_type = arch_is_patch_level;
                  desired_n = last_n + 1;
                }
              break;
            }

          case arch_is_version_level:
            {
              if (seal)
                {
                  safe_printfmt (2, "%s: version already sealed", argv[0]);
                  exit (2);
                }
              else if (fix)
                {
                  desired_level_type = arch_is_versionfix_level;
                  desired_n = 1;
                }
              else
                {
                  safe_printfmt (2, "%s: cannot commit to sealed version with --fix\n",
                                 argv[0]);
                  exit (2);
                }
              break;
            }

          case arch_is_versionfix_level:
            {
              if (seal)
                {
                  safe_printfmt (2, "%s: version already sealed", argv[0]);
                  exit (2);
                }
              else if (fix)
                {
                  desired_level_type = arch_is_versionfix_level;
                  desired_n = last_n + 1;
                }
              else
                {
                  safe_printfmt (2, "%s: cannot commit to sealed version with --fix\n",
                                 argv[0]);
                  exit (2);
                }
              break;
            }
          }
      }

    desired_level = arch_form_patch_level (desired_level_type, desired_n);
    tag_revision = str_alloc_cat_many (0, tag_version, "--", desired_level, str_end);

    arch_tag (1, tag_arch, tag_revision, source_arch, source_revision, log);

    if (tree_root && argc == 2)
      {
        t_uchar * tag_fqrevision = arch_fully_qualify (tag_archive, tag_revision);
        t_uchar * tag_fqversion = arch_fully_qualify (tag_archive, tag_version);

        arch_set_tree_version (tree_root, tag_fqversion);
        
        if (arch_call_cmd (arch_cmd_apply_delta, argv[0], 
                              "-A", "unused@example.com",  /* ARGH. bug in apply-delta */
                              "-d", tree_root, tree_fqrevision, tag_fqrevision, NULL))
          {
            safe_printfmt (2, "%s: failed to update project tree to new branch %s", argv[0], tag_fqrevision);
            exit (2);
          }

        lim_free (0, tag_fqversion);
        lim_free (0, tag_fqrevision);
      }
    
    if ( do_cacherev && str_cmp(tag_archive, source_arch->official_name) != 0)
      easy_cacherev (tag_arch, tag_archive, tag_revision, argv[0], dir);

    if (log_file)
      safe_unlink (log_file);

    lim_free (0, source_revision);
    lim_free (0, tag_archive);
    lim_free (0, tag_version);
    lim_free (0, log);
    if (source_arch != tag_arch)
      arch_archive_close (source_arch);
    arch_archive_close (tag_arch);
    rel_free_table (tag_version_revisions);
    lim_free (0, last_level);
    lim_free (0, desired_level);
    lim_free (0, tag_revision);
    lim_free (0, tree_root);
    lim_free (0, tree_archive);
    lim_free (0, tree_fqrevision);
  }

  return 0;
}



/* tag: Tom Lord Tue May 27 23:03:10 2003 (tagrev.c)
 */

Generated by  Doxygen 1.6.0   Back to index