/* local-cache.c:
*
* vim:smartindent ts=8:sts=2:sta:et:ai:shiftwidth=2
****************************************************************
* 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/bugs/exception.h"
#include "hackerlab/mem/alloc-limits.h"
#include "hackerlab/char/str.h"
#include "hackerlab/fs/file-names.h"
#include "hackerlab/vu/safe.h"
#include "libfsutils/tmp-files.h"
#include "libfsutils/rmrf.h"
#include "libfsutils/ensure-dir.h"
#include "libarch/ancestry.h"
#include "libarch/build-revision.h"
#include "libarch/pristines.h"
#include "libarch/libraries.h"
#include "libarch/chatter.h"
#include "libarch/my.h"
#include "libarch/namespace.h"
#include "libarch/library-txn.h"
#include "libarch/local-cache.h"
int
arch_greedy_library_wants_revision (arch_patch_id * 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 (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,
arch_project_tree_t * tree,
arch_project_tree_t * cache,
t_uchar const * const archive,
t_uchar const * const revision,
t_uchar const * const hook)
{
arch_project_tree_t * result_tree = arch_find_local_tree_copy (chatter_fd, tree, cache, archive, revision, hook);
t_uchar * result = result_tree ? str_save (0, result_tree->root) : NULL;
arch_project_tree_delete (result_tree);
return result;
}
arch_project_tree_t *
arch_find_local_tree_copy (int chatter_fd,
arch_project_tree_t * tree,
arch_project_tree_t * cache,
t_uchar const * const archive,
t_uchar const * const revision,
t_uchar const * const hook)
{
arch_project_tree_t * result;
arch_patch_id patch_id;
arch_patch_id_init_archive (&patch_id, archive, revision);
if (hook)
{
int error;
error = arch_run_hook (hook,
"ARCH_ARCHIVE", archive,
"ARCH_REVISION", revision,
0);
if (error)
{
safe_printfmt (2, "baz: error running hook `%s' (%d)\n", hook, error);
exit (2);
}
}
result = arch_library_find (0, &patch_id, 1);
if (!result && tree)
result = arch_find_pristine (tree, &patch_id, arch_tree_pristine_search);
if (!result && cache)
result = arch_find_pristine (cache, &patch_id, arch_cache_dir_pristine_search);
if (!result)
{
t_uchar *greedy_choice = 0;
greedy_choice = arch_library_greedy_add_choice(&patch_id, 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_readonly (archive);
if (!arch)
{
safe_printfmt (2, "could not connect to %s to add %s/%s\n", archive, archive, revision);
exit (2);
}
arch_library_add (chatter_fd, 1, arch, revision, greedy_choice, 0, -1, 0);
result = arch_library_find (0, &patch_id, 1);
arch_archive_close (arch);
}
}
if (result)
{
if (!arch_project_tree_file_exists(result, ARCH_PROJECT_TREE_ANCESTRY_FILE))
{
struct exception * e;
/* FIXME: rather than asking for all we should be more conservative
* or allow a user policy
*/
Try
patch_ancestry (talloc_context, result, &patch_id, 2);
Catch (e)
{
/* system errors */
if (e->code < 0)
Throw (e);
talloc_free (e);
}
}
if (!result->fqrevision || str_cmp (archive, result->archive) || str_cmp (revision, result->revision))
{
rmrf_file (result->root);
talloc_free (result);
return arch_find_local_tree_copy(chatter_fd,
tree,
cache,
archive,
revision,
hook);
}
}
arch_patch_id_finalise (&patch_id);
return result;
}
/**
* \brief create a reference tree we can use to get diffs on, reference inventory etc.
* \param chatter_fd optional output fd (-1 disables)
* \param tree_root required current tree root
* \param cache_dir optional directory to build the cache in
* \param arch optional already connected archive handle
* \param the name of the archive
* \param the name of the revision
* \return the path of the resulting trees root
*/
t_uchar *
arch_find_or_make_local_copy (int chatter_fd,
arch_project_tree_t * tree,
arch_project_tree_t * cache,
struct arch_archive * arch,
t_uchar * archive,
t_uchar * revision)
{
arch_project_tree_t * result_tree = arch_find_or_make_local_tree_copy (chatter_fd, tree, cache, arch, archive, revision);
t_uchar * result = result_tree ? str_save (0, result_tree->root) : NULL;
arch_project_tree_delete (result_tree);
return result;
}
/**
* \brief create a reference tree we can use to get diffs on, reference inventory etc.
* \param chatter_fd optional output fd (-1 disables)
* \param tree_root required current tree root
* \param cache_dir optional directory to build the cache in
* \param arch optional already connected archive handle
* \param the name of the archive
* \param the name of the revision
* \return the arch project tree
*/
arch_project_tree_t *
arch_find_or_make_local_tree_copy (int chatter_fd,
arch_project_tree_t * tree,
arch_project_tree_t * cache,
struct arch_archive * arch,
t_uchar * archive,
t_uchar * revision)
{
arch_project_tree_t * answer = NULL;
invariant (!!tree);
invariant (!arch || !str_cmp (archive, arch->official_name));
answer = arch_find_local_tree_copy (chatter_fd, tree, cache, 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 = talloc_tmp_file_name (talloc_context, 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 (tmp_path, arch, archive, revision, cache);
arch_install_pristine (tree, archive, revision, tmp_path);
answer = arch_find_local_tree_copy (chatter_fd, tree, cache, archive, revision, 0);
lim_free (0, tree_dir);
talloc_free (tmp_path);
}
return answer;
}
/**
* \brief create a temporary reference tree we can use to get diffs on, reference inventory etc.
* \param chatter_fd optional output fd (-1 disables)
* \param tmp_dir required dir to place the temp tree in
* \param tree_root required current tree root
* \param cache_dir optional directory to build the cache in
* \param arch optional already connected archive handle
* \param the name of the archive
* \param the name of the revision
* \return the path of the resulting trees root
*/
t_uchar *
arch_find_or_make_tmp_local_copy (int chatter_fd,
t_uchar const * const tmp_dir,
arch_project_tree_t * tree,
arch_project_tree_t * cache,
struct arch_archive * arch,
t_uchar const * const archive,
t_uchar const * const revision)
{
t_uchar * answer = 0;
invariant (!!tmp_dir);
answer = arch_find_local_copy (chatter_fd, tree, cache, 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 = talloc_tmp_file_name (talloc_context, 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 (tmp_path, arch, archive, revision, cache);
lim_free (0, tmp_stem);
answer = str_save (0, tmp_path);
talloc_free (tmp_path);
}
return answer;
}
/* tag: Tom Lord Fri May 23 14:42:03 2003 (local-cache.c)
*/
syntax highlighted by Code2HTML, v. 0.9.1