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

#include "hackerlab/os/errno.h"
#include "hackerlab/bugs/panic.h"
#include "hackerlab/char/char-class.h"
#include "hackerlab/char/str.h"
#include "hackerlab/mem/mem.h"
#include "hackerlab/fs/file-names.h"
#include "hackerlab/fs/cwd.h"
#include "hackerlab/vu/safe.h"
#include "tla/libfsutils/tmp-files.h"
#include "tla/libfsutils/read-line.h"
#include "tla/libfsutils/dir-listing.h"
#include "tla/libawk/relational.h"
#include "tla/libarch/my.h"
#include "tla/libarch/namespace.h"
#include "tla/libarch/archive-version.h"
#include "tla/libarch/archives.h"



t_uchar *
arch_archive_location_file (const t_uchar * archive_name)
{
  t_uchar * location_dir = 0;
  t_uchar * answer = 0;

  if (! arch_valid_archive_name(archive_name)) 
    {
      int ign;

      printfmt (&ign, 2, "Invalid archive name `%s'.", archive_name);
      exit (2);
    }

  location_dir = arch_my_archive_locations_dir ();
  answer = file_name_in_vicinity (0, location_dir, archive_name);

  lim_free (0, location_dir);

  return answer;
}


void
arch_set_archive_location (const t_uchar * archive_name,
                           const t_uchar * location,
                           int force_p,
                           int quietly_fail)
{
  t_uchar * file = 0;
  t_uchar * dir = 0;
  t_uchar * tmp_name = 0;

  file = arch_archive_location_file (archive_name);
  dir = file_name_directory_file (0, file);
  tmp_name = tmp_file_name (dir, ",,new-location");

  if (!force_p && !safe_access (file, F_OK))
    {
      if (! quietly_fail)
        {
          safe_printfmt (2, "archive already registered: %s\n", archive_name);
          if (quietly_fail == ARCH_REG_FAIL_NOFAIL)
            {
              return;
            }
          else
            {
              exit (2);
            }
        }
    }
  else
    {
      int ign;
      int out_fd;

      arch_ensure_my_arch_params ();
      vu_mkdir (&ign, dir, 0700);

      out_fd = safe_open (tmp_name, O_WRONLY | O_CREAT | O_EXCL, 0666);
      safe_printfmt (out_fd, "%s\n", location);
      safe_close (out_fd);

      safe_rename (tmp_name, file);
    }

  lim_free (0, file);
  lim_free (0, dir);
  lim_free (0, tmp_name);
}


t_uchar *
arch_archive_location (const t_uchar * archive_name,
                       int soft)
{
  t_uchar * file = 0;
  t_uchar * first_line = 0;
  t_uchar * start;
  t_uchar * end;
  t_uchar * answer = 0;

  file = arch_archive_location_file (archive_name);

  if (safe_access (file, F_OK))
    {
      if (soft)
        return 0;

      safe_printfmt (2, "archive not registered: %s\n", archive_name);
      safe_printfmt (2, "  (see register-archive)\n");
      exit (2);
    }

  first_line = read_line_from_file (file);

  for (start = first_line; char_is_blank (*start); ++start)
    ;
  for (end = start; *end && !char_is_space (*start); ++end)
    ;

  answer = str_save_n (0, start, end - start);

  lim_free (0, file);
  lim_free (0, first_line);

  return answer;
}


void
arch_delete_archive_location (const t_uchar * archive_name,
                              int force_p)
{
  t_uchar * file = 0;
  int errn;

  file = arch_archive_location_file (archive_name);

  if (vu_unlink (&errn, file))
    {
      if (!(force_p && (errn == ENOENT)))
        {
          safe_printfmt (2, "archive not registered: %s\n", archive_name);
          safe_printfmt (2, "  (see register-archive)\n");
          exit (2);
        }
    }

  lim_free (0, file);
}


rel_table
arch_registered_archives (void)
{
  t_uchar * dir = 0;
  rel_table files  = rel_table_nil;
  rel_table answer  = rel_table_nil;
  int x;

  dir = arch_my_archive_locations_dir ();
  files = maybe_directory_files (dir);

  for (x = 0; x < rel_n_records (files); ++x)
    {
      const t_uchar * f;

      f = rel_peek_str (files, x, 0);
      if (str_cmp (".", f) && str_cmp ("..", f) && arch_valid_archive_name (f))
        {
          t_uchar * location = 0;

          location = arch_archive_location (f, 0);
          rel_add_records (&answer, rel_make_record_2_taking (rel_get_field (files, x, 0), rel_make_field_str (location)), rel_record_null);

          lim_free (0, location);
        }
    }


  lim_free (0, dir);
  rel_free_table (files);

  return answer;
}

t_uchar *
arch_mirrored_at_name (const t_uchar * archive)
{
  t_uchar * mirror_name = 0;

  mirror_name = str_alloc_cat (0, archive, "-MIRROR");

  return mirror_name;
}

t_uchar *
arch_mirrored_from_name (const t_uchar * archive)
{
  t_uchar * source_name = 0;

  source_name = str_alloc_cat (0, archive, "-SOURCE");

  return source_name;
}

t_uchar *
arch_mirrored_at (const t_uchar * archive)
{
  t_uchar * mirror_name = 0;
  t_uchar * mirror_loc = 0;

  mirror_name = arch_mirrored_at_name (archive);
  mirror_loc = arch_archive_location (mirror_name, 1);

  if (!mirror_loc)
    {
      lim_free (0, mirror_name);
      mirror_name = 0;
    }

  lim_free (0, mirror_loc);
  return mirror_name;
}


t_uchar *
arch_mirrored_from (const t_uchar * archive)
{
  t_uchar * source_name = 0;
  t_uchar * source_loc = 0;

  source_name = arch_mirrored_from_name (archive);
  source_loc = arch_archive_location (source_name, 1);

  if (!source_loc)
    {
      lim_free (0, source_name);
      source_name = 0;
    }

  lim_free (0, source_loc);
  return source_name;
}



t_uchar *
arch_fs_archive_archive_version_path (const t_uchar * archive_path)
{
  return file_name_in_vicinity (0, archive_path, ".archive-version");
}


t_uchar *
arch_fs_archive_meta_info_path (const t_uchar * archive_path)
{
  return file_name_in_vicinity (0, archive_path, "=meta-info");
}


t_uchar *
arch_fs_archive_meta_info_item_path (const t_uchar * archive_path,
                                     const t_uchar * meta_info_name)
{
  t_uchar * meta_info_dir = 0;
  t_uchar * meta_info_path;

  meta_info_dir = arch_fs_archive_meta_info_path (archive_path);
  meta_info_path = file_name_in_vicinity (0, meta_info_dir, meta_info_name);

  lim_free (0, meta_info_dir);

  return meta_info_path;
}




/* tag: Tom Lord Sun May 18 19:17:40 2003 (archives.c)
 */
