/* merge-points.c:
*
****************************************************************
* 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/mem/alloc-limits.h"
#include "hackerlab/char/str.h"
#include "hackerlab/vu/safe.h"
#include "libfsutils/file-contents.h"
#include "libarch/patch-logs.h"
#include "libarch/namespace.h"
#include "libarch/merge-points.h"
/* __STDC__ prototypes for static functions */
static void arch_add_merge_points (rel_table * out, t_uchar * level, t_uchar * log, t_uchar * prefix);
static t_uchar * arch_merge_points_prefix (t_uchar * from_archive, t_uchar * from_spec);
rel_table
arch_tree_merge_points (t_uchar * tree_root,
t_uchar * into_archive, t_uchar * into_spec,
t_uchar * from_archive, t_uchar * from_spec)
{
rel_table answer = 0;
rel_table source_logs = 0;
int x;
t_uchar * prefix = 0;
if (arch_valid_package_name (into_spec, arch_no_archive, arch_req_patch_level, 0))
{
t_uchar * path = 0;
t_uchar * level = 0;
path = arch_log_file (tree_root, into_archive, into_spec);
level = arch_parse_package_name (arch_ret_patch_level, 0, into_spec);
rel_add_records (&source_logs, rel_make_record (into_spec, path, 0), 0);
lim_free (0, path);
lim_free (0, level);
}
else if (arch_valid_package_name (into_spec, arch_no_archive, arch_req_version, 0))
{
source_logs = arch_logs (tree_root, into_archive, into_spec, 0);
}
else
panic ("invalid into_spec argument to arch_tree_merge_points");
prefix = arch_merge_points_prefix (from_archive, from_spec);
for (x = 0; x < rel_n_records (source_logs); ++x)
{
t_uchar * log_text = 0;
log_text = file_contents (source_logs[x][1]);
arch_add_merge_points (&answer, source_logs[x][0], log_text, prefix);
lim_free (0, log_text);
}
rel_free_table (source_logs);
lim_free (0, prefix);
return answer;
}
rel_table
arch_archive_merge_points (struct arch_archive * into_arch, t_uchar * into_spec,
t_uchar * from_archive, t_uchar * from_spec,
int upto)
{
rel_table answer = 0;
rel_table source_revisions = 0;
int x;
t_uchar * prefix = 0;
if (arch_valid_package_name (into_spec, arch_no_archive, arch_req_patch_level, 0))
{
if (!upto)
rel_add_records (&source_revisions, rel_make_record (into_spec, 0), 0);
else
{
t_uchar * into_version = 0;
rel_table all_source_revisions = 0;
into_version = arch_parse_package_name (arch_ret_package_version, 0, into_spec);
all_source_revisions = arch_archive_revisions (into_arch, into_version, 2);
for (x = 0; x < rel_n_records (all_source_revisions); ++x)
{
rel_add_records (&source_revisions, rel_copy_record (all_source_revisions[x]), 0);
if (!str_cmp (all_source_revisions[x][0], into_spec))
break;
}
if (x == rel_n_records (all_source_revisions))
{
safe_printfmt (2, "arch: attempt to compute merge-points of non-existent revision\n (%s\%s)\n", into_arch->official_name, into_spec);
exit (2);
}
lim_free (0, into_version);
rel_free_table (all_source_revisions);
}
}
else if (arch_valid_package_name (into_spec, arch_no_archive, arch_req_version, 0))
{
source_revisions = arch_archive_revisions (into_arch, into_spec, 2);
}
else
panic ("invalid into_spec argument to arch_archive_merge_points");
prefix = arch_merge_points_prefix (from_archive, from_spec);
for (x = 0; x < rel_n_records (source_revisions); ++x)
{
t_uchar * log_text = 0;
t_uchar * level = 0;
log_text = arch_archive_log (into_arch, source_revisions[x][0]);
level = arch_parse_package_name (arch_ret_patch_level, 0, source_revisions[x][0]);
arch_add_merge_points (&answer, level, log_text, prefix);
lim_free (0, log_text);
lim_free (0, level);
}
rel_free_table (source_revisions);
lim_free (0, prefix);
return answer;
}
rel_table
arch_new_in_version (t_uchar * tree_root, t_uchar * archive, t_uchar * version)
{
rel_table merge_points = 0;
rel_table all_logs = 0;
rel_table answer = 0;
merge_points = arch_tree_merge_points (tree_root, archive, version, 0, 0);
all_logs = arch_all_logs (tree_root);
rel_sort_table_by_field (0, merge_points, 1);
rel_sort_table_by_field (0, all_logs, 0);
answer = rel_join (2, rel_join_output (2,0, -1), 1, 0, merge_points, all_logs);
arch_sort_table_by_name_field (0, answer, 0);
rel_free_table (merge_points);
rel_free_table (all_logs);
return answer;
}
/* find all tree logs that are in tree and not in reference_tree
* TODO tests !
*/
rel_table
arch_new_in_tree (arch_project_tree_t *tree, t_uchar *reference_tree_root)
{
rel_table all_logs = 0;
rel_table reference_logs = 0;
rel_table answer = 0;
all_logs = arch_all_logs (tree->root);
reference_logs = arch_all_logs (reference_tree_root);
rel_sort_table_by_field (0, all_logs, 0);
rel_sort_table_by_field (0, reference_logs, 0);
answer = rel_join (2, rel_join_output (2,0, -1), 0, 0, reference_logs, all_logs);
arch_sort_table_by_name_field (0, answer, 0);
rel_free_table (reference_logs);
rel_free_table (all_logs);
return answer;
}
static void
arch_add_merge_points (rel_table * out, t_uchar * level, t_uchar * log, t_uchar * prefix)
{
assoc_table headers = 0;
t_uchar * new_patches_header;
rel_table new_patches = 0;
int x;
arch_parse_log (0, &headers, 0, log);
new_patches_header = assoc_ref (headers, "new-patches");
new_patches = rel_ws_split (new_patches_header);
arch_sort_table_by_name_field (0, new_patches, 0);
rel_uniq_by_field (&new_patches, 0);
for (x = 0; x < rel_n_records (new_patches); ++x)
{
if (!str_cmp_prefix (prefix, new_patches[x][0]))
rel_add_records (out, rel_make_record (level, new_patches[x][0], 0), 0);
}
free_assoc_table (headers);
rel_free_table (new_patches);
}
static t_uchar *
arch_merge_points_prefix (t_uchar * from_archive, t_uchar * from_spec)
{
if (!from_archive)
return 0;
else if (arch_valid_package_name (from_spec, arch_no_archive, arch_req_patch_level, 0))
return arch_fully_qualify (from_archive, from_spec);
else
return str_alloc_cat_many (0, from_archive, "/", from_spec, "--", str_end);
}
/* tag: Tom Lord Tue May 27 18:04:17 2003 (merge-points.c)
*/
syntax highlighted by Code2HTML, v. 0.9.1