/* upgrade.c
 *
 * vim:smartindent ts=8:sts=2:sta:et:ai:shiftwidth=2
 ****************************************************************
 * Copyright (C) 2005 Canonical Limited
 *    Authors: Robert Collins <robert.collins@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 "libfsutils/ensure-dir.h"
#include "libarch/my.h"
#include "libarch/namespace.h"
#include "libarch/archive.h"
#include "libarch/archives.h"
#include "libarch/pfs.h"
#include "commands/upgrade.h"
#include "commands/version.h"



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

#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_leave, NULL, "leave-old-config", 0, \
      N_("Leave the old config in place. this may interfere with normal operation and is not recommended.")) \
  OP (opt_move, NULL, "move-old-config", 0, \
      N_("Move the config data to ~/.arch-params/upgraded-by-baz-1.3 after it is upgraded"))

t_uchar arch_upgrade_help[] = N_("perform an upgrade of local baz settings and data.\n"
                                 "By default, nothing is done. You must supply --move-old-config (recommended)\n"
                                 "or --leave-old-config\n"
                                 "\n"
                                 "For baz 1.3 this:\n"
                                 "Scans all the archives listed in ~/.arch-params/=locations and writes\n"
                                 "consolidated configuration details to ~/.arch-params/archives.\n"
                                 "After upgrading, the previous configuration details are saved in\n"
                                 "~/.arch-params/upgraded-by-baz-1.3/\n"
                                 "\n"
                                 "If an archive cannot be connected to, its configuration details are left\n"
                                 "untouched\n");

enum options
{
  OPTS (OPT_ENUM)
};

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


static void
upgrade_locations (int leave_config)
{
  rel_table archives = NULL;
  int archive_index;
  t_uchar * my_archives_dir = arch_my_archives_dir();
  t_uchar * my_upgraded_locations = str_alloc_cat (0, arch_my_arch_params(), "/upgraded-by-baz-1.3/=locations");
  t_uchar * my_upgraded_signing = str_alloc_cat (0, arch_my_arch_params(), "/upgraded-by-baz-1.3/signing");
  arch_registered_registered_name_archives (&archives);

  rel_sort_table_by_field (0, archives, 0);
  rel_for_each (archives, archive_index)
    {
      struct arch_archive *arch;
      t_uchar *oldloc, *newloc;
      safe_printfmt (2, "Upgrading configuration for registered name: %s\n", archives[archive_index][0]);
      arch = arch_archive_connect_location (archives[archive_index][1], 1);
      if (!arch)
        {
          safe_printfmt (2, "Could not connect to registered name %s at location %s. Its configuration data is being left in the =locations format.\n", archives[archive_index][0], archives[archive_index][1]);
          continue;
        }
      arch->registered_name = str_replace (arch->registered_name, str_save (0, archives[archive_index][0]));
      arch_archive_register (arch);
      ensure_directory_exists (my_upgraded_locations);
      oldloc = arch_archive_location_file (archives[archive_index][0]);
      newloc = str_alloc_cat_many (0, my_upgraded_locations, "/", archives[archive_index][0], str_end);
      if (!leave_config)
          safe_rename (oldloc, newloc);
      lim_free (0, oldloc);
      lim_free (0, newloc);

      if (arch->signed_archive)
        {
          inifile_t inifile;
          t_uchar *filename;
          arch_archives_get_archive_ini_no_default (arch->official_name, &inifile);
          arch_archive_inifile_set_signed (&inifile, arch_archive_inifile_signed (arch, &inifile, arch_fail_error));
          filename = arch_archives_signature_signing_rule_file (archives[archive_index][0]);
          if (!safe_access (filename, F_OK))
              upgrade_signing_rule (&inifile, filename, 0);
          lim_free (0, filename);
          filename = arch_archives_signature_checking_rule_file (archives[archive_index][0]);
          if (!safe_access (filename, F_OK))
              upgrade_checking_rule (&inifile, filename);
          lim_free (0, filename);
          /* FIXME RBC 20050329 move or backup the old signing rules too */

          arch_archives_save_archive_ini_no_default (arch->official_name, &inifile);
          inifile_finalise (&inifile);
        }
      
    }

  lim_free (0, my_archives_dir);
  lim_free (0, my_upgraded_locations);
  lim_free (0, my_upgraded_signing);
}
  
int
arch_upgrade (t_uchar * program_name, int argc, char * argv[])
{
  int o;
  struct opt_parsed * option;
  int leave_config = 1;
  
  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_upgrade_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);

        usage_error:
          opt_usage (2, argv[0], program_name, usage, 1);
          exit (1);
        case opt_leave:
          leave_config = -1;
          break;
        case opt_move:
          leave_config = 0;
        }
    }

  if (argc != 1)
    goto usage_error;
  if (leave_config == 1)
    {
      safe_printfmt (2, _("You must supply either --leave-old-config or --move-old-config (recommended). See the help for more information.\n"));
      goto usage_error;
    }

  upgrade_locations (leave_config);

  return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1