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

#include "hackerlab/char/str.h"
#include "hackerlab/fs/file-names.h"
#include "hackerlab/vu/safe.h"
#include "tla/libfsutils/tmp-files.h"
#include "tla/libfsutils/rmrf.h"
#include "tla/libarch/apply-changeset.h"
#include "tla/libarch/namespace.h"
#include "tla/libarch/chatter.h"
#include "tla/libarch/replay.h"


/* __STDC__ prototypes for static functions */
static void replay_callback (void * vfd,
                             const char * fmt,
                             va_list ap);



int
arch_replay_exact (int chatter_fd,
                   int no_patch_noise,
                   const t_uchar * tree_root,
                   struct arch_archive * arch,
                   const t_uchar * revision,
                   int reverse,
                   int forward,
                   int escape_classes)
{
  t_uchar * patch_dir_stem = 0;
  t_uchar * patch_dir = 0;
  struct arch_apply_changeset_report report = {0, };
  int status;

  patch_dir_stem = str_alloc_cat_many (0, ",,patch.", revision, "--", arch->name, str_end);
  patch_dir = tmp_file_name (tree_root, patch_dir_stem);

  arch_get_patch (arch, revision, patch_dir);

  arch_chatter (chatter_fd, "* patching for revision %s/%s\n", arch->name, revision);
  if ((chatter_fd >= 0) && !no_patch_noise)
    {
      report.callback = replay_callback;
      report.thunk = (void *)(long)chatter_fd;
    }

  arch_apply_changeset (&report, patch_dir, tree_root, arch_unspecified_id_tagging, arch_inventory_unrecognized, reverse, forward, 0, 0, 0, escape_classes);
  status = arch_conflicts_occured (&report);
  rmrf_file (patch_dir);

  lim_free (0, patch_dir_stem);
  lim_free (0, patch_dir);
  arch_free_apply_changeset_report_data (&report);
  return status;
}


int
arch_replay_list (int chatter_fd,
                  int no_patch_noise,
                  const t_uchar * tree_root,
                  struct arch_archive * arch,
                  rel_table revisions,
                  int reverse,
                  int forward,
                  int escape_classes)
{
  int x;
  int status = 0;

  for (x = 0; x < rel_n_records (revisions); ++x)
    {
      if (arch_replay_exact (chatter_fd, no_patch_noise, tree_root, arch, rel_peek_str (revisions, x, 0), reverse, forward,escape_classes))
        {
          t_uchar * conflicts_in_file = 0;
          t_uchar * patches_remaining_file = 0;
          int out_fd;
          int y;

          conflicts_in_file = file_name_in_vicinity (0, tree_root, ",,replay.conflicts-in");
          out_fd = safe_open (conflicts_in_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
          safe_printfmt (out_fd, "%s/%s\n", arch->name, rel_peek_str (revisions, x, 0));
          safe_close (out_fd);

          patches_remaining_file = file_name_in_vicinity (0, tree_root, ",,replay.remaining");
          out_fd = safe_open (patches_remaining_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
          for (y = x + 1; y < rel_n_records (revisions); ++y)
            {
              safe_printfmt (out_fd, "%s/%s\n", arch->name, rel_peek_str (revisions, y, 0));
            }
          safe_close (out_fd);

          lim_free (0, conflicts_in_file);
          lim_free (0, patches_remaining_file);

          status = 1;
          break;
        }
    }
  return status;
}


int
arch_replay_fqlist (int chatter_fd,
                    int no_patch_noise,
                    const t_uchar * tree_root,
                    const t_uchar * default_archive,
                    rel_table revisions,
                    int reverse,
                    int forward,
                    int escape_classes)
{
  int x;
  int status = 0;
  struct arch_archive * connected_archive = 0;

  for (x = 0; !status && (x < rel_n_records (revisions)); ++x)
    {
      t_uchar * archive = 0;
      t_uchar * revision = 0;

      archive = arch_parse_package_name (arch_ret_archive, default_archive, rel_peek_str (revisions, x, 0));
      revision = arch_parse_package_name (arch_ret_non_archive, 0, rel_peek_str (revisions, x, 0));

      if (!connected_archive || str_cmp (connected_archive->name, archive))
        {
          arch_archive_close (connected_archive);
          connected_archive = arch_archive_connect (archive, 0);
        }

      if (!connected_archive
          || arch_replay_exact (chatter_fd, no_patch_noise, tree_root, connected_archive, revision,
                                reverse, forward, escape_classes))
        {
          t_uchar * conflicts_in_file = 0;
          t_uchar * patches_remaining_file = 0;
          int out_fd;
          int y;

          conflicts_in_file = file_name_in_vicinity (0, tree_root, ",,replay.conflicts-in");
          out_fd = safe_open (conflicts_in_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
          safe_printfmt (out_fd, "%s\n", rel_peek_str (revisions, x, 0));
          safe_close (out_fd);

          patches_remaining_file = file_name_in_vicinity (0, tree_root, ",,replay.remaining");
          out_fd = safe_open (patches_remaining_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
          for (y = x + 1; y < rel_n_records (revisions); ++y)
            {
              safe_printfmt (out_fd, "%s\n", rel_peek_str (revisions, y, 0));
            }
          safe_close (out_fd);

          lim_free (0, conflicts_in_file);
          lim_free (0, patches_remaining_file);

          status = 1;
        }

      lim_free (0, archive);
      lim_free (0, revision);
    }

  arch_archive_close (connected_archive);
  return status;
}




static void
replay_callback (void * vfd,
                 const char * fmt,
                 va_list ap)
{
  safe_printfmt_va_list ((int)(t_ulong)vfd, fmt, ap);
  safe_flush ((int)(t_ulong)vfd);
}



/* tag: Tom Lord Tue Jun  3 18:03:29 2003 (replay.c)
 */
