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

#include "hackerlab/bugs/panic.h"
#include "hackerlab/char/str.h"
#include "hackerlab/fs/file-names.h"
#include "hackerlab/vu/safe.h"
#include "file-utils/libfsutils/rmrf.h"
#include "file-utils/libfsutils/link-tree.h"
#include "file-utils/libfsutils/ensure-dir.h"
#include "file-utils/libfsutils/tmp-files.h"
#include "file-utils/libarch/namespace.h"
#include "file-utils/libarch/build-revision.h"
#include "file-utils/libarch/invent.h"
#include "file-utils/libarch/libraries.h"
#include "file-utils/libarch/project-tree.h"
#include "file-utils/libarch/apply-changeset.h"
#include "file-utils/libarch/library-txn.h"


/* __STDC__ prototypes for static functions */
static void library_txn_callback (void * vfp, char * fmt, va_list ap);



void
arch_library_add (int chatter_fd, struct arch_archive * arch, t_uchar * revision)
 {
  t_uchar * dest_directory = 0;
  t_uchar * fq_ancestor_rev = 0;
  t_uchar * ancestor_archive = 0;
  t_uchar * ancestor_revision = 0;
  t_uchar * library_ancestor = 0;
  t_uchar * dest_dir_dir = 0;
  t_uchar * tmp_dir = 0;
  t_uchar * patch_set_dir = 0;

  dest_directory = arch_library_revision_dir (arch->name, revision);
  if (!safe_access (dest_directory, F_OK))
    {
      lim_free (0, dest_directory);
      return;
    }
  
  fq_ancestor_rev = arch_ancestor_revision (arch, revision);

  if (fq_ancestor_rev)
    {
      ancestor_archive = arch_parse_package_name (arch_ret_archive, 0, fq_ancestor_rev);
      ancestor_revision = arch_parse_package_name (arch_ret_non_archive, 0, fq_ancestor_rev);
      library_ancestor = arch_library_find (ancestor_archive, ancestor_revision);
    }

  dest_dir_dir = file_name_directory_file (0, dest_directory);
  ensure_directory_exists (dest_dir_dir);
  tmp_dir = tmp_file_name (dest_dir_dir, ",,new-revision");

  if (library_ancestor)
    {
      if (chatter_fd)
        {
          safe_printfmt (chatter_fd, "* found immediate ancestor revision in library (%s/%s)\n", ancestor_archive, ancestor_revision);
        }
      build_link_tree (library_ancestor, tmp_dir);
    }
  else
    {
      struct arch_archive * ancestor_arch = 0;

      if (chatter_fd)
        {
          safe_printfmt (chatter_fd, "* building immediate ancestor revision (%s/%s)\n", ancestor_archive, ancestor_revision);
        }

      if (!str_cmp (ancestor_archive, arch->name))
        {
          ancestor_arch = arch;
        }
      else
        {
          ancestor_arch = arch_archive_connect (ancestor_archive);
        }

      safe_mkdir (tmp_dir, 0777);
      arch_build_revision (chatter_fd, tmp_dir, ancestor_arch, ancestor_archive, ancestor_revision, 0);

      if (ancestor_arch != arch)
        arch_archive_close (ancestor_arch);
    }

  patch_set_dir = file_name_in_vicinity (0, tmp_dir, ",,patch-set");
  rmrf_file (patch_set_dir);
  arch_get_patch (arch, revision, patch_set_dir);

  {
    struct arch_apply_changeset_report report = {0,};

    if (chatter_fd)
      {
        safe_printfmt (chatter_fd, "* patching for this revision (%s/%s)\n", arch->name, revision);
        report.callback = library_txn_callback;
        report.thunk = (void *)chatter_fd;
      }

    arch_apply_changeset (&report, patch_set_dir, tmp_dir, arch_unspecified_tagging, 0);
    invariant (!arch_conflicts_occured (&report));

    arch_free_apply_changeset_report_data (&report);
  }

  {
    t_uchar * version = 0;
    rel_table index = 0;
    t_uchar * index_by_name_path = 0;
    t_uchar * index_path = 0;
    int index_by_name_fd = -1;
    int index_fd = -1;

    version = arch_parse_package_name (arch_ret_package_version, 0, revision);
    arch_set_tree_version (tmp_dir, arch->name, version);

    index = arch_source_inventory (tmp_dir, 1, 0);
    index_by_name_path = file_name_in_vicinity (0, tmp_dir, ",,index-by-name");
    index_path = file_name_in_vicinity (0, tmp_dir, ",,index");

    rmrf_file (index_by_name_path);
    rmrf_file (index_path);

    index_by_name_fd = safe_open (index_by_name_path, O_WRONLY | O_CREAT | O_EXCL, 0444);
    rel_print_table (index_by_name_fd, index);
    safe_close (index_by_name_fd);

    rel_sort_table_by_field (0, index, 1);
    index_fd = safe_open (index_path, O_WRONLY | O_CREAT | O_EXCL, 0444);
    rel_print_table (index_fd, index);
    safe_close (index_fd);

    lim_free (0, version);
    rel_free_table (index);
    lim_free (0, index_by_name_path);
    lim_free (0, index_path);
  }

  safe_rename (tmp_dir, dest_directory);

  lim_free (0, fq_ancestor_rev);
  lim_free (0, ancestor_archive);
  lim_free (0, ancestor_revision);
  lim_free (0, library_ancestor);
  lim_free (0, dest_directory);
  lim_free (0, dest_dir_dir);
  lim_free (0, tmp_dir);
  lim_free (0, patch_set_dir);
}


static void
library_txn_callback (void * vfp, char * fmt, va_list ap)
{
  safe_printfmt_va_list ((int)(t_ulong)vfp, fmt, ap);
  safe_flush (1);
}




/* tag: Tom Lord Fri May 30 13:50:27 2003 (library-txn.c)
 */
