/* local-cache.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 "hackerlab/fs/file-names.h"
#include "hackerlab/vu/safe.h"
#include "tla/libfsutils/tmp-files.h"
#include "tla/libfsutils/rmrf.h"
#include "tla/libfsutils/ensure-dir.h"
#include "tla/libarch/build-revision.h"
#include "tla/libarch/pristines.h"
#include "tla/libarch/libraries.h"
#include "tla/libarch/chatter.h"
#include "tla/libarch/my.h"
#include "tla/libarch/library-txn.h"
#include "tla/libarch/local-cache.h"




int
arch_greedy_library_wants_revision (t_uchar * archive, t_uchar * revision)
{
  int answer = 0;
  rel_table lib_path = 0;

  lib_path = arch_my_library_path (arch_library_path_add_order);

  if (lib_path)
    {
      t_uchar * default_add_lib = 0;
      
      default_add_lib = arch_library_add_choice (archive, revision, 0, 0);
      if (arch_library_is_greedy (default_add_lib))
        {
          answer = 1;
        }

      lim_free (0, default_add_lib);
    }

  rel_free_table (lib_path);

  return answer;
}


t_uchar *
arch_find_local_copy (int chatter_fd,
                      t_uchar * tree_root,
                      t_uchar * cache_dir,
                      t_uchar * archive,
                      t_uchar * revision,
                      t_uchar * hook)
{
  t_uchar * answer = 0;
  if (hook)
    {
      int error;
      
      error = arch_run_hook (hook,
                             "ARCH_ARCHIVE", archive,
                             "ARCH_REVISION", revision,
                             0);
      
      if (error)
        {
          safe_printfmt (2, "tla: error running hook `%s' (%d)\n", hook, error);
          exit (2);
        }
    }

  if (!answer)
    answer = arch_library_find (0, archive, revision, 1);

  if (!answer && tree_root)
    answer = arch_find_pristine (0, tree_root, archive, revision, arch_any_pristine, arch_tree_and_sibling_pristine_search);

  if (!answer && cache_dir)
    answer = arch_find_pristine (0, cache_dir, archive, revision, arch_any_pristine, arch_cache_dir_pristine_search);

  if (!answer)
    {
      t_uchar *greedy_choice = 0;
      greedy_choice = arch_library_greedy_add_choice(archive, revision, 0, 1);
      if (greedy_choice)
	{
	  /* something wants a pristine copy that isn't around.
	   *
	   * There is a greedy library in the path, so add the revision to it.
	   */

	  struct arch_archive * arch = 0;

	  arch_chatter (chatter_fd, "* auto-adding %s/%s to greedy revision library %s\n", archive, revision, greedy_choice);
	  arch = arch_archive_connect (archive, 0);
	  arch_library_add (chatter_fd, 1, arch, revision, greedy_choice, 0, -1, 0);
	  answer = arch_library_find (0, archive, revision, 1);
	  arch_archive_close (arch);
	}
    }

  return answer;
}


t_uchar *
arch_find_or_make_local_copy (int chatter_fd,
                              t_uchar * tree_root,
                              t_uchar * cache_dir,
                              struct arch_archive * arch,
                              t_uchar * archive,
                              t_uchar * revision)
{
  t_uchar * answer = 0;
  t_uchar * parent_dir = 0;

  invariant (!!tree_root);
  invariant (!arch || !str_cmp (archive, arch->name));

  if (!cache_dir)
    {
      parent_dir = file_name_directory_file (0, tree_root);
      cache_dir = parent_dir;
    }

  answer = arch_find_local_copy (chatter_fd, tree_root, cache_dir, archive, revision, "make-pristine");

  if (!answer)
    {
      t_uchar * tree_dir = 0;
      t_uchar * tmp_path = 0;

      tree_dir = file_name_directory_file (0, tree_root);
      if (!tree_dir)
        tree_dir = str_save (0, ".");

      tmp_path = tmp_file_name (tree_dir, ",,new-pristine");

      rmrf_file (tmp_path);
      safe_mkdir (tmp_path, 0777);

      arch_chatter (chatter_fd, "* build pristine tree for %s/%s\n", archive, revision);

      arch_build_revision (chatter_fd, tmp_path, arch, archive, revision, cache_dir);

      arch_install_pristine (tree_root, archive, revision, tmp_path);

      answer = arch_find_local_copy (chatter_fd, tree_root, cache_dir, archive, revision, 0);

      lim_free (0, tree_dir);
      lim_free (0, tmp_path);
    }

  if (parent_dir)
    lim_free (0, parent_dir);

  return answer;
}


t_uchar *
arch_find_or_make_tmp_local_copy  (int chatter_fd,
                                   t_uchar * tmp_dir,
                                   t_uchar * tree_root,
                                   t_uchar * cache_dir,
                                   struct arch_archive * arch,
                                   t_uchar * archive,
                                   t_uchar * revision)
{
  t_uchar * answer = 0;
  t_uchar * parent_dir = 0;

  if (!cache_dir)
    {
      parent_dir = file_name_directory_file (0, tree_root);
      cache_dir = parent_dir;
    }

  answer = arch_find_local_copy (chatter_fd, tree_root, cache_dir, archive, revision, "make-tmp-pristine");

  if (!answer)
    {
      t_uchar * tmp_stem = 0;
      t_uchar * tmp_path = 0;

      tmp_stem = str_alloc_cat_many (0, ",,", revision, "--", archive, str_end);
      tmp_path = tmp_file_name (tmp_dir, tmp_stem);

      rmrf_file (tmp_path);
      ensure_directory_exists (tmp_dir);
      safe_mkdir (tmp_path, 0777);

      arch_chatter (chatter_fd, "* build reference tree for %s/%s\n", archive, revision);

      arch_build_revision (chatter_fd, tmp_path, arch, archive, revision, cache_dir);

      lim_free (0, tmp_stem);
      answer = tmp_path;
    }

  if (parent_dir)
    lim_free (0, parent_dir);

  return answer;
}




/* tag: Tom Lord Fri May 23 14:42:03 2003 (local-cache.c)
 */
