/* merge-points.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/mem/alloc-limits.h"
#include "hackerlab/char/str.h"
#include "file-utils/libfsutils/file-contents.h"
#include "file-utils/libarch/patch-logs.h"
#include "file-utils/libarch/namespace.h"
#include "file-utils/libarch/merge-points.h"


/* __STDC__ prototypes for static functions */
static void arch_add_merge_points (rel_table * out, t_uchar * level, t_uchar * log, t_uchar * prefix);
static t_uchar * arch_merge_points_prefix (t_uchar * from_archive, t_uchar * from_spec);



rel_table
arch_tree_merge_points (t_uchar * tree_root,
                        t_uchar * into_archive, t_uchar * into_spec,
                        t_uchar * from_archive, t_uchar * from_spec)
{
  rel_table answer = 0;
  rel_table source_logs = 0;
  int x;
  t_uchar * prefix = 0;

  if (arch_valid_package_name (into_spec, arch_no_archive, arch_req_patch_level, 0))
    {
      t_uchar * path = 0;
      t_uchar * level = 0;

      path = arch_log_file (tree_root, into_archive, into_spec);
      level = arch_parse_package_name (arch_ret_patch_level, 0, into_spec);

      rel_add_records (&source_logs, rel_make_record (into_spec, path, 0), 0);

      lim_free (0, path);
      lim_free (0, level);
    }
  else if (arch_valid_package_name (into_spec, arch_no_archive, arch_req_version, 0))
    {
      arch_log_ls (tree_root, into_archive, into_spec, 0);
    }
  else
    panic ("invalid into_spec argument to arch_tree_merge_points");

  prefix = arch_merge_points_prefix (from_archive, from_spec);

  for (x = 0; x < rel_n_records (source_logs); ++x)
    {
      t_uchar * log_text = 0;

      log_text = file_contents (source_logs[x][1]);

      arch_add_merge_points (&answer, source_logs[x][0], log_text, prefix);

      lim_free (0, log_text);
    }


  rel_free_table (source_logs);
  lim_free (0, prefix);

  return answer;
}


rel_table
arch_archive_merge_points (struct arch_archive * into_arch, t_uchar * into_spec,
                           t_uchar * from_archive, t_uchar * from_spec)
{
  rel_table answer = 0;
  rel_table source_revisions = 0;
  int x;
  t_uchar * prefix = 0;

  if (arch_valid_package_name (into_spec, arch_no_archive, arch_req_patch_level, 0))
    {
      rel_add_records (&source_revisions, rel_make_record (into_spec, 0), 0);
    }
  else if (arch_valid_package_name (into_spec, arch_no_archive, arch_req_version, 0))
    {
      source_revisions = arch_archive_revisions (into_arch, into_spec, 2);
    }
  else
    panic ("invalid into_spec argument to arch_archive_merge_points");
  

  prefix = arch_merge_points_prefix (from_archive, from_spec);

  for (x = 0; x < rel_n_records (source_revisions); ++x)
    {
      t_uchar * log_text = 0;
      t_uchar * level = 0;

      log_text = arch_archive_log (into_arch, source_revisions[x][0]);
      level = arch_parse_package_name (arch_ret_patch_level, 0, source_revisions[x][0]);

      arch_add_merge_points (&answer, level, log_text, prefix);

      lim_free (0, log_text);
      lim_free (0, level);
    }


  rel_free_table (source_revisions);
  lim_free (0, prefix);

  return answer;
}




static void
arch_add_merge_points (rel_table * out, t_uchar * level, t_uchar * log, t_uchar * prefix)
{
  assoc_table headers = 0;
  t_uchar * new_patches_header;
  rel_table new_patches = 0;
  int x;

  arch_parse_log (0, &headers, 0, log);
  new_patches_header = assoc_ref (headers, "new-patches");

  new_patches = rel_ws_split (new_patches_header);
  arch_sort_table_by_name_field (0, new_patches, 0);
  rel_uniq_by_field (&new_patches, 0);

  for (x = 0; x < rel_n_records (new_patches); ++x)
    {
      if (!str_cmp_prefix (prefix, new_patches[x][0]))
        rel_add_records (out, rel_make_record (level, new_patches[x][0], 0), 0);
    }

  free_assoc_table (headers);
  rel_free_table (new_patches);
}

static t_uchar *
arch_merge_points_prefix (t_uchar * from_archive, t_uchar * from_spec)
{
  if (!from_archive)
    return 0;
  else if (arch_valid_package_name (from_spec, arch_no_archive, arch_req_patch_level, 0))
    return arch_fully_qualify (from_archive, from_spec);
  else
    return str_alloc_cat_many (0, from_archive, "/", from_spec, "--", str_end);
}




/* tag: Tom Lord Tue May 27 18:04:17 2003 (merge-points.c)
 */
