/* changeset-utils.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/os/errno.h"
#include "hackerlab/os/errno-to-string.h"
#include "hackerlab/fmt/cvt.h"
#include "hackerlab/mem/mem.h"
#include "hackerlab/mem/talloc.h"
#include "hackerlab/char/char-class.h"
#include "hackerlab/char/str.h"
#include "hackerlab/char/pika-escaping-utils.h"
#include "hackerlab/fs/file-names.h"
#include "hackerlab/vu/safe.h"
#include "po/gettext.h"
#include "libfsutils/read-line.h"
#include "libfsutils/safety.h"
#include "libarch/diffs.h"
#include "libarch/invent.h"
#include "libarch/changeset-utils.h"
/* __STDC__ prototypes for static functions */
static void changeset_inv_callback (void * closure,
invent_callback_data_t const * const data);
static void cset_free (void *data);
void
arch_changeset_inventory (struct arch_changeset_inventory * inv_out,
arch_project_tree_t *tree,
enum arch_id_tagging_method method,
enum arch_inventory_category untagged_source_category,
int escape_classes)
{
int here_fd;
struct arch_inventory_options options;
here_fd = safe_open (".", O_RDONLY, 0);
mem_set0 ((t_uchar *)&options, sizeof (options));
options.categories = arch_inventory_source;
options.want_ids = 1;
options.treat_unrecognized_source_as_source = 1;
if (method != arch_unspecified_id_tagging)
{
options.method = method;
options.untagged_source_category = untagged_source_category;
options.override_method = 1;
}
options.nested = 0;
options.include_excluded = 1;
arch_get_inventory_naming_conventions (&options, tree);
inv_out->method = options.method;
inv_out->escape_classes = escape_classes;
safe_chdir (tree->root);
arch_project_tree_changeset_inventory_traversal (tree, &options, changeset_inv_callback, inv_out);
arch_free_inventory_naming_conventions (&options);
rel_sort_table_by_field (0, inv_out->dirs, 1);
rel_sort_table_by_field (0, inv_out->files, 1);
safe_fchdir (here_fd);
safe_close (here_fd);
}
void
arch_free_changeset_inventory_data (struct arch_changeset_inventory * i)
{
rel_free_table (i->dirs); i->dirs = 0;
rel_free_table (i->files); i->files = 0;
cset_map_free (i->entries); i->entries = NULL;
}
rel_table
arch_read_changeset_index (t_uchar * path)
{
int in_fd;
rel_table answer = 0;
t_uchar * line;
long len;
in_fd = safe_open (path, O_RDONLY, 0);
while (1)
{
t_uchar * loc;
t_uchar * id;
t_uchar * start;
line = 0;
len = 0;
safe_next_line (&line, &len, in_fd);
if (!len)
break;
while (len && char_is_space (*line))
{
++line;
--len;
}
start = line;
while (len && !char_is_space (*line))
{
++line;
--len;
}
if (line == start)
{
syntax_error:
safe_printfmt (2, "illegally formed changeset index (%s)\n", path);
exit (2);
}
loc = pika_save_unescape_iso8859_1_n (0, 0, start, line - start );
while (len && char_is_space (*line))
{
++line;
--len;
}
start = line;
while (len && !char_is_space (*line))
{
++line;
--len;
}
if (line == start)
goto syntax_error;
id = pika_save_unescape_iso8859_1_n (0, 0, start, line - start );
while (len && char_is_space (*line))
{
++line;
--len;
}
if (len)
goto syntax_error;
if (!is_non_upwards_relative_path (loc))
{
safe_printfmt (2, "illegal path in changeset: %s\n", loc);
exit (2);
}
rel_add_records (&answer, rel_make_record (loc, id, 0), 0);
lim_free (0, loc);
lim_free (0, id);
}
safe_close (in_fd);
return answer;
}
rel_table
arch_read_changeset_dir_metadata (t_uchar * path)
{
int errn;
int in_fd;
rel_table answer = 0;
in_fd = vu_open (&errn, path, O_RDONLY, 0);
if (in_fd < 0)
{
if (errn == ENOENT)
return 0;
else
{
safe_printfmt (2, "arch_read_changeset_dir_metadata: unable to open file (%s)\n", path);
safe_printfmt (2, " %s\n", errno_to_string (errn));
exit (2);
}
}
while (1)
{
t_uchar * line;
long len;
t_uchar * start;
t_uchar * perms = 0;
t_uchar * loc = 0;
line = 0;
len = 0;
safe_next_line (&line, &len, in_fd);
if (!len)
break;
while (len && char_is_space (*line))
{
++line;
--len;
}
if ((len < 13) || str_cmp_prefix ("--permissions", line))
{
syntax_error:
safe_printfmt (2, "illegal dir metadata file: %s\n", path);
exit (2);
}
len -= 13;
line += 13;
while (len && char_is_space (*line))
{
++line;
--len;
}
start = line;
while (len && !char_is_space (*line))
{
++line;
--len;
}
if (start == line)
goto syntax_error;
perms = pika_save_unescape_iso8859_1_n (0, 0, start, line - start );
while (len && char_is_space (*line))
{
++line;
--len;
}
start = line;
while (len && !char_is_space (*line))
{
++line;
--len;
}
if (start == line)
goto syntax_error;
loc = pika_save_unescape_iso8859_1_n (0, 0, start, line - start );
if (!is_non_upwards_relative_path (loc))
{
safe_printfmt (2, "illegal path in changeset: %s\n", loc);
exit (2);
}
rel_add_records (&answer, rel_make_record (loc, perms, 0), 0);
lim_free (0, perms);
lim_free (0, loc);
}
safe_close (in_fd);
rel_sort_table_by_field (0, answer, 0);
return answer;
}
mode_t
arch_read_permissions_patch (t_uchar * file)
{
int errn;
t_uchar * line = 0;
t_uchar * s;
t_uchar * e;
t_ulong answer;
line = read_line_from_file (file);
s = line;
while (char_is_space (*s))
++s;
if (str_cmp_prefix ("--permissions", s))
{
syntax_error:
safe_printfmt (2, "illegal metadata patch file: %s\n", file);
exit (2);
}
s += sizeof ("--permissions") - 1;
while (char_is_space (*s))
++s;
for (e = s; char_is_odigit (*e); ++e)
;
if (e == s)
goto syntax_error;
if (cvt_octal_to_ulong (&errn, &answer, s, e - s))
goto syntax_error;
lim_free (0, line);
return (mode_t)answer;
}
void
changeset_inv_callback (void * closure, invent_callback_data_t const * const data)
{
struct arch_changeset_inventory * index;
index = (struct arch_changeset_inventory *)closure;
if (!data->id)
{
t_uchar * dir = 0;
dir = file_name_directory_file (0, data->path);
if (!arch_is_dont_care_explicit_dflt_dir (dir))
{
t_uchar * e_path = 0;
e_path = pika_save_escape_iso8859_1 (0, 0, index->escape_classes, data->path);
safe_printfmt (2, _("missing explicit id for file (try status --lint)\n file:%s\n"), e_path);
exit (2);
}
lim_free (0, dir);
return;
}
if (S_ISDIR (data->stat_buf.st_mode))
rel_add_records (&index->dirs, rel_make_record (data->path, data->id, 0), 0);
else
rel_add_records (&index->files, rel_make_record (data->path, data->id, 0), 0);
cset_map_insert (&index->entries, data->id, arch_changeset_inventory_entry_new (&data->stat_buf));
}
char *
no_dot (char *name)
{
if (name[0] == '.' && name[1] == '/')
return name + 2;
else
return name;
}
arch_changeset_inventory_entry_t *
arch_changeset_inventory_entry_new (struct stat const * const stat_buf)
{
arch_changeset_inventory_entry_t * result = talloc (NULL, arch_changeset_inventory_entry_t);
result->stat_buf = *stat_buf;
return result;
}
void
cset_free (void *data)
{
talloc_free (data);
}
void
cset_map_insert (cset_map * vtable,
t_uchar const * key,
arch_changeset_inventory_entry_t *entry)
{
pointer_map_insert ((pointer_map *)vtable, key, entry, cset_free);
}
void
cset_map_free (cset_map vtable)
{
pointer_map_free ((pointer_map)vtable, cset_free);
}
arch_changeset_inventory_entry_t *
cset_map_find (cset_map vtable, t_uchar const * key)
{
return pointer_map_find ((pointer_map) vtable, key);
}
/* tag: Tom Lord Thu May 15 13:00:33 2003 (changeset-utils.c)
*/
syntax highlighted by Code2HTML, v. 0.9.1