/* patch-logs.c:
*
****************************************************************
* Copyright (C) 2003 Tom Lord
*
* See the file "COPYING" for further information about
* the copyright and warranty status of this work.
*/
#include "hackerlab/arrays/ar.h"
#include "hackerlab/bugs/panic.h"
#include "hackerlab/os/errno.h"
#include "hackerlab/os/errno-to-string.h"
#include "hackerlab/char/char-class.h"
#include "hackerlab/char/pika-escaping-utils.h"
#include "hackerlab/char/str.h"
#include "hackerlab/fs/file-names.h"
#include "hackerlab/vu/safe.h"
#include "libfsutils/dir-listing.h"
#include "libfsutils/string-files.h"
#include "libfsutils/file-contents.h"
#include "libfsutils/ensure-dir.h"
#include "libfsutils/rmrf.h"
#include "libfsutils/copy-file.h"
#include "libawk/trim.h"
#include "libarch/arch.h"
#include "libarch/namespace.h"
#include "libarch/merge-points.h"
#include "libarch/project-tree.h"
#include "libarch/patch-logs.h"
AR_TYPEDEF (arch_patch_log_dir_t, arch_patch_log_dir);
t_uchar *
arch_make_log_file (t_uchar * tree_root, t_uchar * archive, t_uchar * version)
{
t_uchar * log_name = 0;
t_uchar * log_path = 0;
invariant (arch_valid_archive_name (archive));
invariant (arch_valid_package_name (version, arch_no_archive, arch_req_version, 0));
/* The VI-user flame generator:
*/
log_name = str_alloc_cat_many (0, "++log.", version, "--", archive, str_end);
log_path = file_name_in_vicinity (0, tree_root, log_name);
lim_free (0, log_name);
return log_path;
}
t_uchar *
arch_make_log (t_uchar * tree_root, t_uchar * archive, t_uchar * version)
{
int errn;
t_uchar * log_path = 0;
int out_fd;
log_path = arch_make_log_file (tree_root, archive, version);
out_fd = vu_open (&errn, log_path, O_WRONLY | O_CREAT | O_EXCL, 0666);
if (out_fd >= 0)
{
safe_printfmt (out_fd, "Summary: \nKeywords: \n\n");
safe_close (out_fd);
}
else if (errn != EEXIST)
{
safe_printfmt (2, "arch_make_log: I/O error (%s) creating %s\n", errno_to_string (errn), log_path);
exit (2);
}
return log_path;
}
t_uchar *
arch_auto_log_message (t_uchar * tree_root, t_uchar * archive, t_uchar * version, t_uchar * summary, t_uchar * body)
{
t_uchar * cooked_summary = 0;
t_uchar * merge_summary = 0;
t_uchar * answer = 0;
cooked_summary = trim_surrounding_ws (str_save (0, summary));
merge_summary = arch_log_for_merge (tree_root, archive, version, 0);
answer = str_alloc_cat_many (0,
"Summary: ", summary, "\n",
"Keywords: \n",
"\n",
body, (body ? "\n" : 0),
(body ? "\n" : 0),
merge_summary,
str_end);
lim_free (0, cooked_summary);
lim_free (0, merge_summary);
return answer;
}
t_uchar *
arch_log_for_merge (t_uchar * tree_root, t_uchar * archive, t_uchar * version, int reverse)
{
rel_table new_logs = 0;
int string_fd;
new_logs = arch_new_in_version (tree_root, archive, version);
if (reverse)
arch_sort_table_by_name_field (1, new_logs, 0);
string_fd = make_output_to_string_fd ();
if (new_logs)
{
int x;
safe_printfmt (string_fd, "Patches applied:\n\n");
for (x = 0; x < rel_n_records (new_logs); ++x)
{
t_uchar * archive = 0;
t_uchar * revision = 0;
t_uchar * log_file = 0;
t_uchar * log = 0;
assoc_table headers = 0;
t_uchar * summary;
archive = arch_parse_package_name (arch_ret_archive, 0, new_logs[x][0]);
revision = arch_parse_package_name (arch_ret_non_archive, 0, new_logs[x][0]);
invariant (!!archive && !!revision);
log_file = arch_log_file (tree_root, archive, revision);
log = file_contents (log_file);
arch_parse_log (0, &headers, 0, log);
summary = assoc_ref (headers, "summary");
safe_printfmt (string_fd, " * %s\n", new_logs[x][0]);
safe_printfmt (string_fd, " %s\n\n", (summary ? summary : (t_uchar *)"<no summary provided>"));
lim_free (0, archive);
lim_free (0, revision);
lim_free (0, log_file);
lim_free (0, log);
free_assoc_table (headers);
}
}
rel_free_table (new_logs);
return string_fd_close (string_fd);
}
t_uchar *
arch_log_dir (t_uchar const * tree_root, t_uchar const * archive, t_uchar const * version)
{
t_uchar * category;
t_uchar * package;
t_uchar * package_version;
t_uchar * t;
t_uchar * log_dir;
invariant (arch_valid_archive_name (archive));
invariant (arch_valid_package_name (version, arch_no_archive, arch_req_version, 0));
category = arch_parse_package_name (arch_ret_category, 0, version);
package = arch_parse_package_name (arch_ret_package, 0, version);
package_version = arch_parse_package_name (arch_ret_package_version, 0, version);
log_dir = arch_tree_ctl_dir (tree_root);
t = file_name_in_vicinity (0, log_dir, category);
lim_free (0, log_dir);
log_dir = t;
t = file_name_in_vicinity (0, log_dir, package);
lim_free (0, log_dir);
log_dir = t;
t = file_name_in_vicinity (0, log_dir, package_version);
lim_free (0, log_dir);
log_dir = t;
t = file_name_in_vicinity (0, log_dir, archive);
lim_free (0, log_dir);
log_dir = t;
t = file_name_in_vicinity (0, log_dir, "patch-log");
lim_free (0, log_dir);
log_dir = t;
lim_free (0, category);
lim_free (0, package);
lim_free (0, package_version);
return log_dir;
}
t_uchar *
arch_log_file (t_uchar * tree_root, t_uchar * archive, t_uchar * revision)
{
t_uchar * version;
t_uchar * dir;
t_uchar * lvl;
t_uchar * file;
version = arch_parse_package_name (arch_ret_package_version, 0, revision);
dir = arch_log_dir (tree_root, archive, version);
lvl = arch_parse_package_name (arch_ret_patch_level, 0, revision);
file = file_name_in_vicinity (0, dir, lvl);
lim_free (0, version);
lim_free (0, dir);
lim_free (0, lvl);
return file;
}
t_uchar *
arch_log_contents (t_uchar * tree_root, t_uchar * archive, t_uchar * revision)
{
t_uchar * file = 0;
t_uchar * answer = 0;
if (!arch_tree_has_log (tree_root, archive, revision))
return 0;
file = arch_log_file (tree_root, archive, revision);
answer = file_contents (file);
lim_free (0, file);
return answer;
}
int
arch_tree_has_log (t_uchar * tree_root, t_uchar * archive, t_uchar * revision)
{
t_uchar * file = 0;
int answer;
file = arch_log_file (tree_root, archive, revision);
answer = !safe_access (file, F_OK);
lim_free (0, file);
return answer;
}
void
arch_add_log_version (t_uchar * tree_root, t_uchar * archive,
t_uchar * version)
{
t_uchar * log_dir;
log_dir = arch_log_dir (tree_root, archive, version);
ensure_directory_exists (log_dir);
lim_free (0, log_dir);
}
void
arch_remove_log_version (t_uchar * tree_root, t_uchar * archive,
t_uchar * version)
{
t_uchar * log_dir;
log_dir = arch_log_dir (tree_root, archive, version);
rmrf_file (log_dir);
lim_free (0, log_dir);
}
int
arch_has_patch_log (t_uchar * tree_root, t_uchar * archive, t_uchar * version)
{
t_uchar * dir = 0;
int answer = 0;
dir = arch_log_dir (tree_root, archive, version);
if (!safe_access (dir, F_OK))
answer = 1;
lim_free (0, dir);
return answer;
}
rel_table
arch_log_versions (t_uchar * tree_root,
t_uchar * only_archive,
t_uchar * only_category,
t_uchar * only_branch,
t_uchar * only_version)
{
t_uchar * logs_root;
int lim;
int x;
rel_table dir_listing;
rel_table categories;
int c_lim;
int c;
rel_table branches; /* [0] == cat--branch, [1] == path of branch's log dir */
int b_lim;
int b;
rel_table versions; /* [0] == cat--branch--vsn, [1] == path of vsn's log dir */
int v_lim;
int v;
rel_table log_versions; /* [0] == fqversion, [1] == patch-log dir for fqversion */
logs_root = arch_tree_ctl_dir (tree_root);
if (only_version)
only_version = str_save (0, only_version);
if (only_version && !only_branch)
{
only_branch = arch_parse_package_name (arch_ret_package, 0, only_version);
}
else if (only_branch)
only_branch = str_save (0, only_branch);
if (only_branch && !only_category)
{
only_category = arch_parse_package_name (arch_ret_category, 0, only_branch);
}
else if (only_category)
only_category = str_save (0, only_category);
/****************************************************************
* Get a list of all categories in the log
*/
dir_listing = directory_files (logs_root);
categories = 0;
lim = rel_n_records (dir_listing);
for (x = 0; x < lim; ++x)
{
if (only_category && str_cmp (dir_listing[x][0], only_category))
continue;
if (arch_valid_package_name (dir_listing[x][0], arch_no_archive, arch_req_category, 0))
rel_add_records (&categories, rel_copy_record (dir_listing[x]), 0);
}
rel_free_table (dir_listing);
/****************************************************************
* For each category, get a list of each branch for it in the log
*/
branches = 0;
c_lim = rel_n_records (categories);
for (c = 0; c < c_lim; ++c)
{
t_uchar * category;
t_uchar * cat_dir;
category = categories[c][0];
cat_dir = file_name_in_vicinity (0, logs_root, category);
dir_listing = directory_files (cat_dir);
lim = rel_n_records (dir_listing);
for (x = 0; x < lim; ++x)
{
t_uchar * maybe_branch;
t_uchar * branch_cat;
maybe_branch = dir_listing[x][0];
if (only_branch && str_cmp (only_branch, maybe_branch))
continue;
if (!arch_valid_package_name (maybe_branch, arch_no_archive, arch_req_package, 0))
continue;
branch_cat = arch_parse_package_name (arch_ret_category, 0, maybe_branch);
if (!str_cmp (category, branch_cat))
{
t_uchar * branch_path;
branch_path = file_name_in_vicinity (0, cat_dir, maybe_branch);
rel_add_records (&branches, rel_make_record (maybe_branch, branch_path, 0), 0);
lim_free (0, branch_path);
}
lim_free (0, branch_cat);
}
rel_free_table (dir_listing);
lim_free (0, cat_dir);
}
rel_free_table (categories);
/****************************************************************
* For each branch, get a list of each version for it in the log
*/
versions = 0;
b_lim = rel_n_records (branches);
for (b = 0; b < b_lim; ++b)
{
t_uchar * branch;
t_uchar * branch_dir;
branch = branches[b][0];
branch_dir = branches[b][1];
dir_listing = directory_files (branch_dir);
lim = rel_n_records (dir_listing);
for (x = 0; x < lim; ++x)
{
t_uchar * maybe_version;
t_uchar * version_pkg;
maybe_version = dir_listing[x][0];
if (only_version && str_cmp (only_version, maybe_version))
continue;
if (!arch_valid_package_name (maybe_version, arch_no_archive, arch_req_version, 0))
continue;
version_pkg = arch_parse_package_name (arch_ret_package, 0, maybe_version);
if (!str_cmp (branch, version_pkg))
{
t_uchar * version_path;
version_path = file_name_in_vicinity (0, branch_dir, maybe_version);
rel_add_records (&versions, rel_make_record (maybe_version, version_path, 0), 0);
lim_free (0, version_path);
}
lim_free (0, version_pkg);
}
rel_free_table (dir_listing);
}
rel_free_table (branches);
/****************************************************************
* For each version, get a list of each archive for it in the log
*/
log_versions = 0;
v_lim = rel_n_records (versions);
for (v = 0; v < v_lim; ++v)
{
t_uchar * version;
t_uchar * vsn_dir;
version = versions[v][0];
vsn_dir = versions[v][1];
dir_listing = directory_files (vsn_dir);
lim = rel_n_records (dir_listing);
for (x = 0; x < lim; ++x)
{
t_uchar * maybe_archive;
t_uchar * archive_path;
t_uchar * patch_log_path;
maybe_archive = dir_listing[x][0];
if (only_archive && str_cmp (only_archive, maybe_archive))
continue;
if (!arch_valid_archive_name (maybe_archive))
continue;
archive_path = file_name_in_vicinity (0, vsn_dir, maybe_archive);
patch_log_path = file_name_in_vicinity (0, archive_path, "patch-log");
if (!safe_access (patch_log_path, F_OK))
{
t_uchar * fqversion;
fqversion = arch_fully_qualify (maybe_archive, version);
rel_add_records (&log_versions, rel_make_record (fqversion, patch_log_path, 0), 0);
lim_free (0, fqversion);
}
lim_free (0, archive_path);
lim_free (0, patch_log_path);
}
rel_free_table (dir_listing);
}
rel_free_table (versions);
if (only_category)
lim_free (0, only_category);
if (only_branch)
lim_free (0, only_branch);
if (only_version)
lim_free (0, only_version);
lim_free (0, logs_root);
return log_versions;
}
/* populate an arch_patch_log_dirs cache */
static arch_patch_log_dir_t *
arch_patch_log_dirs_populate (arch_project_tree_t * tree, t_uchar const *fqrevision_before)
{
t_uchar *archive = arch_parse_package_name (arch_ret_archive, 0, fqrevision_before);
t_uchar *version = arch_parse_package_name (arch_ret_package_version, 0, fqrevision_before);
arch_patch_log_dir_t *aDir = ar_ref_arch_patch_log_dir (&tree->patch_logs, ar_size_arch_patch_log_dir (tree->patch_logs));
aDir->fqversion = str_alloc_cat_many (0, archive, "/", version, str_end);
aDir->logs = arch_logs (tree->root, archive, version, 0);
lim_free (0, archive);
lim_free (0, version);
return aDir;
}
static arch_patch_log_dir_t *
arch_patch_log_dirs_find (arch_project_tree_t *tree, t_uchar const * fqrevision)
{
t_uchar *archive = arch_parse_package_name (arch_ret_archive, 0, fqrevision);
t_uchar *version = arch_parse_package_name (arch_ret_package_version, 0, fqrevision);
t_uchar *fqversion = str_alloc_cat_many (0, archive, "/", version, str_end);
arch_patch_log_dir_t *result = NULL;
int position;
for (position = 0; position < ar_size_arch_patch_log_dir (tree->patch_logs); ++position)
if (!str_cmp (fqversion, ar_ref_arch_patch_log_dir (&tree->patch_logs, position)->fqversion))
{
result = ar_ref_arch_patch_log_dir (&tree->patch_logs, position);
goto done;
}
done:
lim_free (0, fqversion);
lim_free (0, archive);
lim_free (0, version);
return result;
}
/* find the highest patch before fqrevision_before in
* archive/version, according to the logs in tree_root
* memoise the log list in the tree, for efficiency
*/
t_uchar *
arch_highest_patch_level_before (arch_project_tree_t *tree, t_uchar const *fqrevision_before)
{
t_uchar *patch_level = arch_parse_package_name (arch_ret_patch_level, 0, fqrevision_before);
t_uchar * answer = 0;
int position;
arch_patch_log_dir_t *aDir = arch_patch_log_dirs_find (tree, fqrevision_before);
if (!aDir)
aDir = arch_patch_log_dirs_populate (tree, fqrevision_before);
position = rel_n_records(aDir->logs);
while (position > 1)
{
--position;
if (!str_cmp (patch_level, aDir->logs[position][0]))
/* matched fqrevision_before */
answer = str_alloc_cat_many (0, aDir->fqversion, "--", aDir->logs[position - 1][0], str_end);
}
lim_free (0, patch_level);
return answer;
}
t_uchar *
arch_highest_patch_level (t_uchar const * tree_root, t_uchar const * archive, t_uchar const * version)
{
rel_table logs = 0;
t_uchar * answer = 0;
logs = arch_logs (tree_root, archive, version, 0);
if (logs)
answer = str_save (0, logs[rel_n_records(logs) - 1][0]);
rel_free_table (logs);
return answer;
}
t_uchar *
arch_latest_logged_version (t_uchar * tree_root, t_uchar * archive, t_uchar * package)
{
rel_table log_versions = 0;
t_uchar * answer = 0;
log_versions = arch_log_versions (tree_root, archive, 0, package, 0);
arch_sort_table_by_name_field (1, log_versions, 0);
if (log_versions)
{
answer = arch_parse_package_name (arch_ret_non_archive, 0, log_versions[0][0]);
}
rel_free_table (log_versions);
return answer;
}
rel_table
arch_logs (t_uchar const * tree_root, t_uchar const * archive, t_uchar const * version, int full)
{
rel_table answer; /* [0] == lvl, [2] == path */
t_uchar * log_dir;
rel_table dir_listing = NULL;
int lim;
int x;
answer = 0;
log_dir = arch_log_dir (tree_root, archive, version);
if (safe_access (log_dir, F_OK))
goto leave;
dir_listing = directory_files (log_dir);
lim = rel_n_records (dir_listing);
for (x = 0; x < lim; ++x)
{
if (arch_valid_patch_level_name (dir_listing[x][0]))
{
t_uchar * path = 0;
path = file_name_in_vicinity (0, log_dir, dir_listing[x][0]);
if (!full)
{
rel_add_records (&answer, rel_make_record (dir_listing[x][0], path, 0), 0);
}
else
{
t_uchar * full_name = 0;
full_name = str_alloc_cat_many (0, archive, "/", version, "--", dir_listing[x][0], str_end);
rel_add_records (&answer, rel_make_record (full_name, path, 0), 0);
lim_free (0, full_name);
}
lim_free (0, path);
}
}
leave:
lim_free (0, log_dir);
rel_free_table (dir_listing);
if (full)
arch_sort_table_by_name_field (0, answer, 0);
else
arch_sort_table_by_patch_level_field (0, answer, 0);
return answer;
}
int
arch_valid_log_file (t_uchar * log)
{
size_t len;
t_uchar * pos;
len = str_length (log);
pos = log;
/* Parse the headers.
*/
while (1)
{
t_uchar * eol;
t_uchar * colon;
eol = str_chr_index (pos, '\n');
if (!eol)
eol = pos + len;
if (eol == pos)
break;
colon = str_chr_index_n (pos, eol - pos, ':');
if (!colon)
return 0;
len -= (1 + (colon - pos));
pos = colon + 1;
while (char_is_blank (*pos))
{
++pos;
--len;
}
while (*eol && char_is_blank (eol[1]))
{
eol = str_chr_index (eol + 1, '\n');
if (!eol)
eol = pos + len;
}
if (*eol)
++eol;
len -= (eol - pos);
pos = eol;
}
/* skip the blank line */
if (!*pos)
return 0;
return 1;
}
void
arch_parse_log (rel_table * headers_list, assoc_table * headers, t_uchar ** body, t_uchar * log)
{
size_t len;
t_uchar * pos;
len = str_length (log);
pos = log;
/* Parse and assemble the headers.
*/
while (1)
{
t_uchar * eol;
t_uchar * colon;
t_uchar * field_name;
t_uchar * field_value;
eol = str_chr_index (pos, '\n');
if (!eol)
eol = pos + len;
if (eol == pos)
break;
colon = str_chr_index_n (pos, eol - pos, ':');
if (!colon)
panic ("bogusly formatted log message (missing field name in headers)");
field_name = str_save_n (0, pos, colon - pos);
{
size_t x;
size_t l;
l = str_length (field_name);
for (x = 0; x < l; ++x)
field_name[x] = char_to_lower (field_name[x]);
}
len -= (1 + (colon - pos));
pos = colon + 1;
while (char_is_blank (*pos))
{
++pos;
--len;
}
while (*eol && char_is_blank (eol[1]))
{
eol = str_chr_index (eol + 1, '\n');
if (!eol)
eol = pos + len;
}
field_value = str_save_n (0, pos, eol - pos);
if (headers)
assoc_set (headers, field_name, field_value);
if (headers_list)
rel_add_records (headers_list, rel_make_record (field_name, field_value, 0), 0);
lim_free (0, field_name);
lim_free (0, field_value);
if (*eol)
++eol;
len -= (eol - pos);
pos = eol;
}
/* skip the blank line */
if (*pos)
++pos;
/* save the body */
if (body)
*body = str_save (0, pos);
}
void
arch_print_headers_summary (int out_fd, int indent_level, assoc_table headers, int summarized_headers)
{
if (arch_include_date & summarized_headers)
{
t_uchar * d;
t_uchar * separator;
if (arch_include_creator & summarized_headers)
{
separator = "";
}
else
{
separator = "\n";
}
d = assoc_ref (headers, "standard-date");
if (!d)
safe_printfmt (out_fd, "%*s<<<no date: header>>>%s", indent_level, "", separator);
else
safe_printfmt (out_fd, "%*s%s%s", indent_level, "", d, separator);
}
if (arch_include_creator & summarized_headers)
{
t_uchar * c;
int creator_indent;
if (arch_include_date & summarized_headers)
{
creator_indent = 6;
}
else
{
creator_indent = indent_level;
}
c = assoc_ref (headers, "creator");
if (!c)
safe_printfmt (out_fd, "%*s<<<no creator: header>>>\n", creator_indent, "");
else
safe_printfmt (out_fd, "%*s%s\n", creator_indent, "", c);
}
if (arch_include_summary & summarized_headers)
{
t_uchar * s;
s = assoc_ref (headers, "summary");
if (!s)
safe_printfmt (out_fd, "%*s<<<no summary: header>>>\n", indent_level, "");
else
{
rel_table s_lines = 0;
int x;
s_lines = rel_nl_split (s);
for (x = 0; x < rel_n_records (s_lines); ++x)
{
t_uchar *temp = str_save (0, s_lines[x][0]);
temp = trim_surrounding_ws (temp);
rel_replace_record (s_lines, x, rel_make_record
(temp, NULL));
lim_free (0, temp);
safe_printfmt (out_fd, "%*s%s\n", indent_level, "", s_lines[x][0]);
}
rel_free_table (s_lines);
}
}
if (summarized_headers & (arch_include_foreign_merges | arch_include_local_merges))
{
t_uchar * this_archive = 0;
t_uchar * this_revision = 0;
t_uchar * this_fqrevision = 0;
t_uchar * raw_merges = 0;
rel_table new_patches = 0;
int any = 0;
int x;
this_archive = trim_surrounding_ws (str_save (0, assoc_ref (headers, "archive")));
this_revision = trim_surrounding_ws (str_save (0, assoc_ref (headers, "revision")));
this_fqrevision = arch_fully_qualify (this_archive, this_revision);
raw_merges = trim_surrounding_ws (str_save (0, assoc_ref (headers, "new-patches")));
new_patches = rel_ws_split (raw_merges);
arch_sort_table_by_name_field (0, new_patches, 0);
for (x = 0; x < rel_n_records (new_patches); ++x)
{
if (arch_valid_package_name (new_patches[x][0], arch_req_archive, arch_req_patch_level, 0)
&& str_cmp (new_patches[x][0], this_fqrevision))
{
t_uchar * patch_archive = 0;
patch_archive = arch_parse_package_name (arch_ret_archive, 0, new_patches[x][0]);
if (str_cmp (patch_archive, this_archive)
? (summarized_headers & arch_include_foreign_merges)
: (summarized_headers & arch_include_local_merges))
{
if (!any)
{
if (arch_include_summary & summarized_headers)
safe_printfmt (out_fd, "\n");
safe_printfmt (out_fd, "%*smerges in:\n", indent_level, "");
any = 1;
}
safe_printfmt (out_fd, "%*s%s\n", indent_level + 2, "", new_patches[x][0]);
}
lim_free (0, patch_archive);
}
}
lim_free (0, this_archive);
lim_free (0, this_revision);
lim_free (0, this_fqrevision);
lim_free (0, raw_merges);
rel_free_table (new_patches);
}
}
static char *
no_dot (char *name)
{
if (name[0] == '.' && name[1] == '/')
return name + 2;
else
return name;
}
void
arch_print_log_list_header (int out_fd, t_uchar * header, rel_table list, int field)
{
int num_recs = rel_n_records (list);
int escape_classes = arch_escape_classes;
if (num_recs > 0)
{
int x;
size_t col;
int any_on_this_line;
safe_printfmt (out_fd, "%s: ", header);
col = str_length (header) + 2;
any_on_this_line = 0;
for (x = 0; x < num_recs; ++x)
{
t_uchar * escape_tmp = 0;
size_t len_this;
escape_tmp = pika_save_escape_iso8859_1 (0, 0, escape_classes, no_dot (list[x][field]));
len_this = str_length (escape_tmp);
if (!any_on_this_line)
{
safe_printfmt (out_fd, "%s", escape_tmp);
col += len_this;
any_on_this_line = 1;
}
else
{
if ((col + 1 + len_this) >= 60)
{
safe_printfmt (out_fd, "\n %s", escape_tmp);
col = 4 + len_this;
any_on_this_line = 1;
}
else
{
safe_printfmt (out_fd, " %s", escape_tmp);
col += len_this;
any_on_this_line = 1;
}
}
lim_free (0, escape_tmp);
}
safe_printfmt (out_fd, "\n");
}
}
void
arch_print_log_pairs_header (int out_fd, t_uchar * header, rel_table list, int field_a, int field_b)
{
int num_recs = rel_n_records (list);
int escape_classes = arch_escape_classes;
if (num_recs > 0)
{
int x;
int once;
safe_printfmt (out_fd, "%s: ", header);
once = 0;
for (x = 0; x < num_recs; ++x)
{
t_uchar * escape_tmp_a;
t_uchar * escape_tmp_b;
escape_tmp_a = pika_save_escape_iso8859_1 (0, 0, escape_classes, list[x][field_a]);
escape_tmp_b = pika_save_escape_iso8859_1 (0, 0, escape_classes, list[x][field_b]);
safe_printfmt (out_fd, "%s%s %s", (once ? "\n " : ""),
no_dot (escape_tmp_a), no_dot (escape_tmp_b));
once = 1;
lim_free (0, escape_tmp_b);
lim_free (0, escape_tmp_a);
}
safe_printfmt (out_fd, "\n");
}
}
void
arch_copy_to_patch_log (t_uchar * tree_root, t_uchar * archive, t_uchar * revision, t_uchar * log_file)
{
int ign;
t_uchar * version = 0;
t_uchar * lvl = 0;
t_uchar * log_dir = 0;
t_uchar * dest_path = 0;
t_uchar * dest_dir = 0;
t_uchar * tmp_path = 0;
version = arch_parse_package_name (arch_ret_package_version, 0, revision);
lvl = arch_parse_package_name (arch_ret_patch_level, 0, revision);
log_dir = arch_log_dir (tree_root, archive, version);
dest_path = file_name_in_vicinity (0, log_dir, lvl);
dest_dir = file_name_directory_file (0, dest_path);
tmp_path = file_name_in_vicinity (0, dest_dir, ",,new-log");
ensure_directory_exists (log_dir);
vu_unlink (&ign, tmp_path);
copy_file (log_file, tmp_path);
safe_rename (tmp_path, dest_path);
lim_free (0, version);
lim_free (0, lvl);
lim_free (0, log_dir);
lim_free (0, dest_path);
lim_free (0, dest_dir);
lim_free (0, tmp_path);
}
void
arch_rename_to_patch_log (t_uchar * tree_root, t_uchar * archive, t_uchar * revision, t_uchar * log_file)
{
t_uchar * version = 0;
t_uchar * lvl = 0;
t_uchar * log_dir = 0;
t_uchar * dest_path = 0;
version = arch_parse_package_name (arch_ret_package_version, 0, revision);
lvl = arch_parse_package_name (arch_ret_patch_level, 0, revision);
log_dir = arch_log_dir (tree_root, archive, version);
dest_path = file_name_in_vicinity (0, log_dir, lvl);
ensure_directory_exists (log_dir);
safe_rename (log_file, dest_path);
lim_free (0, version);
lim_free (0, lvl);
lim_free (0, log_dir);
lim_free (0, dest_path);
}
rel_table
arch_all_logs (t_uchar * tree_root)
{
rel_table log_versions = 0;
rel_table answer = 0;
int x;
log_versions = arch_log_versions (tree_root, 0, 0, 0, 0);
for (x = 0; x < rel_n_records (log_versions); ++x)
{
t_uchar * archive = 0;
t_uchar * version = 0;
rel_table in_this_log = 0;
archive = arch_parse_package_name (arch_ret_archive, 0,
log_versions[x][0]);
version = arch_parse_package_name (arch_ret_non_archive, 0,
log_versions[x][0]);
in_this_log = arch_logs (tree_root, archive, version, 1);
rel_append_x (&answer, in_this_log);
lim_free (0, archive);
lim_free (0, version);
rel_free_table (in_this_log);
}
arch_sort_table_by_name_field (0, answer, 0);
rel_free_table (log_versions);
return answer;
}
extern t_uchar *
arch_tree_latest_revision (t_uchar * base_tree_root)
{
t_uchar * fq_version = arch_tree_version (base_tree_root);
t_uchar * archive = arch_parse_package_name (arch_ret_archive, 0, fq_version);
t_uchar * version = arch_parse_package_name (arch_ret_package_version, 0, fq_version);
t_uchar * patch_level = arch_highest_patch_level (base_tree_root, archive, version);
t_uchar * revision = str_alloc_cat_many (0, version, "--", patch_level, str_end);
lim_free (0, patch_level);
lim_free (0, version);
lim_free (0, archive);
lim_free (0, fq_version);
return revision;
}
void
arch_patch_log_dirs_init (arch_patch_log_dir_t **dirs)
{
*dirs = NULL;
}
void
arch_patch_log_dirs_finalise (arch_patch_log_dir_t **dirs)
{
while (ar_size_arch_patch_log_dir (*dirs))
{
arch_patch_log_dir_t *aDir = ar_ref_arch_patch_log_dir(dirs, ar_size_arch_patch_log_dir (*dirs) - 1);
rel_free_table (aDir->logs);
lim_free (0, aDir->fqversion);
ar_pop_arch_patch_log_dir (dirs);
}
ar_free_arch_patch_log_dir (dirs);
}
/* tag: Tom Lord Mon May 12 19:20:16 2003 (patch-logs.c)
*/
syntax highlighted by Code2HTML, v. 0.9.1