/* tla-project-tree.c:
*
* vim:smartindent ts=8:sts=2:sta:et:ai:shiftwidth=2
****************************************************************
* Copyright (C) 2003 Tom Lord
* Copyright (C) 2005 Canonical Limited
* Authors: Robert Collins <robert.collins@canonical.com>
*
* See the file "COPYING" for further information about
* the copyright and warranty status of this work.
*/
#include "hackerlab/bugs/exception.h"
#include "hackerlab/bugs/panic.h"
#include "hackerlab/os/errno.h"
#include "hackerlab/vu/safe.h"
#include "hackerlab/fs/cwd.h"
#include "hackerlab/fs/file-names.h"
#include "hackerlab/char/str.h"
#include "hackerlab/mem/mem.h"
#include "libfsutils/file-contents.h"
#include "libawk/trim.h"
#include "libarch/ancestry.h"
#include "libarch/namespace.h"
#include "libarch/patch-id.h"
#include "libarch/patch-logs.h"
#include "libarch/changelogs.h"
#include "libarch/inv-ids.h"
#include "libarch/invent.h"
#include "libarch/project-tree.h"
#include "libarch/tla-project-tree.h"
static const char arch_tree_format_str_hackerlab[] = "Hackerlab arch project directory, format version 1.";
typedef struct tla_project_tree_
{
arch_project_tree_t parent;
cached_changeset_inventory_t * inventory_cache;
} tla_project_tree_t;
/* methods */
static void tla_init (arch_project_tree_t * tree);
static enum arch_id_tagging_method tla_id_tagging_method (arch_project_tree_t * tree, enum arch_inventory_category * cat_var, int strict);
static void tla_changeset_inventory_traveral (arch_project_tree_t * tree, struct arch_inventory_options * options, inv_callback callback, void * closure);
static void tla_project_tree_mutated (arch_project_tree_t * tree);
/* will become static eventually */
extern inventory_entry_t * tla_path_id (arch_project_tree_t * tree, int * errn, t_uchar const * const path, struct stat * known_lstat);
static int tla_project_tree_destructor(void * data);
arch_project_tree_vtable tla_project_tree_vtable =
{
tla_init,
tla_id_tagging_method,
tla_path_id,
tla_changeset_inventory_traveral,
tla_project_tree_mutated,
arch_project_tree_vtable_end
};
/**
* \brief prepare a directory to be a tla tree
*/
void
tla_project_tree_init_directory (t_uchar const * const tree_root)
{
t_uchar * arch_dir = 0;
t_uchar * arch_vsn_file = 0;
t_uchar * id_tagging_method_file = 0;
t_uchar * id_tagging_method_defaults = 0;
int out_fd;
arch_dir = file_name_in_vicinity (0, tree_root, "{arch}");
arch_vsn_file = file_name_in_vicinity (0, arch_dir, ".arch-project-tree");
id_tagging_method_file = file_name_in_vicinity (0, arch_dir, "=tagging-method");
safe_mkdir (arch_dir, 0777);
out_fd = safe_open (arch_vsn_file, O_WRONLY | O_CREAT | O_EXCL, 0666);
safe_printfmt (out_fd, "%s\n", arch_tree_format_str_hackerlab);
safe_close (out_fd);
id_tagging_method_defaults = arch_default_id_tagging_method_contents (arch_unspecified_id_tagging);
out_fd = safe_open (id_tagging_method_file, O_WRONLY | O_CREAT | O_EXCL, 0666);
safe_printfmt (out_fd, "%s", id_tagging_method_defaults);
safe_close (out_fd);
lim_free (0, arch_dir);
lim_free (0, arch_vsn_file);
lim_free (0, id_tagging_method_defaults);
lim_free (0, id_tagging_method_file);
}
/**
* \brief is dir the root of a tla(hackerlab) project tree?
* \return non zero on true.
*/
int
tla_project_tree_dir_is_root (void * context, t_uchar const * dir, arch_project_tree_t **out)
{
int result = 0;
t_uchar * arch_dir = file_name_in_vicinity (0, dir, "{arch}");
t_uchar * arch_version_file = file_name_in_vicinity (0, arch_dir, ".arch-project-tree");
if (!safe_access (arch_version_file, F_OK))
{
t_uchar * content = trim_surrounding_ws(file_contents (arch_version_file));
if (!str_cmp (content, arch_tree_format_str_hackerlab))
{
result = -1;
if (out)
{
*out = (arch_project_tree_t *)talloc (context, tla_project_tree_t);
talloc_set_destructor (*out, tla_project_tree_destructor);
(*out)->vtable = &tla_project_tree_vtable;
}
}
else
/* incompatible tree */
{
safe_printfmt (2, "tla_project_tree_dir_is_root: unrecognized project tree format: '%s'\n", content);
exit (2);
}
lim_free (0, content);
}
lim_free (0, arch_dir);
lim_free (0, arch_version_file);
return result;
}
/**
* \brief find the id tagging method for a tree
*/
enum arch_id_tagging_method
tla_id_tagging_method (arch_project_tree_t * tree, enum arch_inventory_category * cat_var, int strict)
{
struct arch_inventory_options options;
mem_set0 ((t_uchar *)&options, sizeof (options));
arch_get_inventory_naming_conventions (&options, tree);
if (cat_var)
{
*cat_var = options.untagged_source_category;
}
tree->untagged_is_source = (options.untagged_source_category == arch_inventory_source);
tree->tag_method = options.method;
arch_free_inventory_naming_conventions (&options);
return tree->tag_method;
}
/**
* \brief see arch_project_tree_init
*/
void
tla_init (arch_project_tree_t * tree)
{
/* perhaps this should call id_tagging_method ? */
tree->untagged_is_source = 0;
tree->tag_method = arch_names_id_tagging; /* ancient default */
tree->id_tagging_shortcut = NULL;
tree->explicit_skips = NULL;
arch_tree_id_tagging_method (tree, NULL, 0);
((tla_project_tree_t *) tree)->inventory_cache = NULL;
}
/**
* \brief destroy the resources of a tla tree
*/
int
tla_project_tree_destructor (void * data)
{
tla_project_tree_t * tree = talloc_get_type (data, tla_project_tree_t);
arch_project_tree_t * arch_tree = (arch_project_tree_t *) tree;
if (!tree)
Throw (exception (EINVAL, "invalid tree in tla_project_tree_destructor"));
free_assoc_table (arch_tree->id_tagging_shortcut);
arch_tree->id_tagging_shortcut = NULL;
free_assoc_table (arch_tree->explicit_skips);
arch_tree->explicit_skips = NULL;
tree->inventory_cache = NULL;
arch_project_tree_finalise (arch_tree);
return 0;
}
/**
* \brief see arch_project_tree_changeset_inventory_traversal
*/
void
tla_changeset_inventory_traveral (arch_project_tree_t * tree, struct arch_inventory_options * options, inv_callback callback, void * closure)
{
cached_changeset_inventory_traveral (options, tree, callback, closure, &((tla_project_tree_t *)tree)->inventory_cache);
talloc_steal (tree, ((tla_project_tree_t *)tree)->inventory_cache);
}
/**
* \brief see arch_project_tree_mutated
*/
void
tla_project_tree_mutated (arch_project_tree_t * tree)
{
talloc_free (((tla_project_tree_t *)tree)->inventory_cache);
((tla_project_tree_t *)tree)->inventory_cache = NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1