/* 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 *)"")); 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<<>>%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<<>>\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<<>>\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) */