/* tla-project-tree.c:
*
* vim:smartindent ts=8:sts=2:sta:et:ai:shiftwidth=2
****************************************************************
* 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/panic.h"
#include "hackerlab/bugs/exception.h"
#include "hackerlab/vu/safe.h"
#include "hackerlab/fs/cwd.h"
#include "hackerlab/fs/file-names.h"
#include "hackerlab/os/errno.h"
#include "hackerlab/char/str.h"
#include "hackerlab/vu/vu.h"
#include "hackerlab/os/errno-to-string.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/null-project-tree.h"
typedef arch_project_tree_t null_project_tree_t;
static int null_project_tree_destructor (void * data);
/* methods */
static void null_init (arch_project_tree_t * tree);
static enum arch_id_tagging_method null_id_tagging_method (arch_project_tree_t * tree, enum arch_inventory_category * cat_var, int strict);
static inventory_entry_t * null_path_id (arch_project_tree_t * tree, int * errn, t_uchar const * const path, struct stat * known_lstat);
static void null_changeset_inventory_traveral (arch_project_tree_t * tree, struct arch_inventory_options * options, inv_callback callback, void * closure);
arch_project_tree_vtable null_project_tree_vtable =
{
null_init,
null_id_tagging_method,
null_path_id,
null_changeset_inventory_traveral,
NULL,
arch_project_tree_vtable_end
};
/**
* \brief is dir the root of a null project tree?
* \return non zero on true.
*/
int
null_project_tree_dir_is_root (void * context, t_uchar const * dir, arch_project_tree_t **out)
{
if (!safe_access ((t_uchar *)dir, F_OK))
{
if (out)
{
*out = talloc (context, null_project_tree_t);
talloc_set_destructor (*out, null_project_tree_destructor);
(*out)->vtable = &null_project_tree_vtable;
}
return -1;
}
/* incompatible tree */
safe_printfmt (2, "null_project_tree_dir_is_root: inaccessible path: '%s'\n", dir);
exit (2);
}
/**
* \brief free a null project tree
*/
int
null_project_tree_destructor (void * data)
{
arch_project_tree_t * tree = talloc_get_type (data, null_project_tree_t);
if (!tree)
Throw (exception (EINVAL, "invalid tree in null_project_tree_destructor"));
arch_project_tree_finalise (tree);
return 0;
}
/**
* \brief find the id tagging method for a tree
*/
enum arch_id_tagging_method
null_id_tagging_method (arch_project_tree_t * tree, enum arch_inventory_category * cat_var, int strict)
{
if (cat_var)
{
*cat_var = arch_inventory_source;
}
return arch_names_id_tagging;
}
/**
* \brief see arch_project_tree_init
*/
void
null_init (arch_project_tree_t * tree)
{
tree->untagged_is_source = 1;
tree->tag_method = arch_names_id_tagging; /* no ids in real fs's */
}
/**
* \brief see arch_inventory_id
*/
inventory_entry_t *
null_path_id (arch_project_tree_t * tree, int * errn, t_uchar const * const path, struct stat * known_lstat)
{
t_uchar * as_file = file_name_from_directory (0, (t_uchar *)path);
t_uchar * answer_id = NULL;
t_uchar * as_file_tail = NULL;
inventory_entry_t * answer = NULL;
t_uchar * fq_path = NULL;
if (!as_file)
goto enomem;
as_file_tail = file_name_tail (0, as_file);
if (!as_file_tail)
goto enomem;
fq_path = file_name_in_vicinity (0, tree->root, as_file);
if (!fq_path)
goto enomem;
answer_id = str_alloc_cat (0, "?", as_file);
if (!answer_id)
{
enomem:
*errn = ENOMEM;
error:
lim_free (0, fq_path);
lim_free (0, as_file);
lim_free (0, as_file_tail);
lim_free (0, answer_id);
return 0;
}
/* FIXME RBC 20050331 make this cleaner and only-called once */
{
struct stat stat_buf;
struct stat *thestat;
if (known_lstat)
thestat = known_lstat;
else
{
thestat = &stat_buf;
if (vu_lstat (errn, fq_path, thestat))
{
goto error;
}
}
if (S_ISDIR (thestat->st_mode))
answer = inventory_dir_new (NULL, as_file_tail, answer_id);
else if (S_ISLNK (thestat->st_mode))
answer = inventory_link_new (NULL, as_file_tail, answer_id);
else
answer = inventory_file_new (NULL, as_file_tail, answer_id);
}
lim_free (0, fq_path);
lim_free (0, answer_id);
lim_free (0, as_file_tail);
return answer;
}
/**
* \brief see arch_project_tree_changeset_inventory_traversal
*/
void
null_changeset_inventory_traveral (arch_project_tree_t * tree, struct arch_inventory_options * options, inv_callback callback, void * closure)
{
arch_inventory_traversal (options, tree, callback, closure);
}
syntax highlighted by Code2HTML, v. 0.9.1