/* 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) */