/* changeset-report.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/char/str.h" #include "hackerlab/fs/file-names.h" #include "hackerlab/mem/mem.h" #include "hackerlab/vu/safe.h" #include "hackerlab/arrays/ar.h" #include "hackerlab/char/pika-escaping-utils.h" #include "libfsutils/read-line.h" #include "libawk/relassoc.h" #include "libfsutils/find-utils.h" #include "libfsutils/ensure-dir.h" #include "libfsutils/copy-file.h" #include "libarch/diffs.h" #include "libarch/changeset-utils.h" #include "libarch/changeset-report.h" /* __STDC__ prototypes for static functions */ static void fix_mod_locs (assoc_table loc_of, rel_table table); static void arch_print_file_metadata_diffs (int out_fd, struct arch_changeset_report * report, int escape_classes); static void arch_print_dir_metadata_diffs (int out_fd, struct arch_changeset_report * report, int escape_classes); static void print_custom_diffs(struct arch_changeset_report * report, t_uchar * orig_dir, t_uchar * mod_dir, t_uchar ** opts); static void arch_print_file_diffs (struct arch_changeset_report * report); static void arch_print_added_file_diffs (struct arch_changeset_report * report); static void print_removed_file_diffs (struct arch_changeset_report * report, t_uchar ** opts); static void print_file_metadata (int out_fd, struct arch_changeset_report * report, int escape_classes); static void print_dir_metadata (int out_fd, struct arch_changeset_report * report, int escape_classes); static void print_diffs_new(struct arch_changeset_report * report); static void report_unique_files_and_symlinks (rel_table * files, rel_table * symlinks, rel_table index, t_uchar * archive_dir, t_uchar * archive_basename); static void find_renames (rel_table * out, rel_table common, assoc_table orig_dir_id_of, assoc_table mod_dir_id_of); int arch_any_changes (struct arch_changeset_report * report) { return (report->removed_dirs || report->added_dirs || report->removed_files || report->added_files || report->removed_symlinks || report->added_symlinks || report->renamed_files || report->renamed_dirs || report->patched_regular_files || report->patched_symlinks || report->patched_binaries || report->file_metadata_changed || report->dir_metadata_changed || report->symlink_to_file || report->file_to_symlink); } void arch_evaluate_changeset (struct arch_changeset_report * report, t_uchar * path) { t_uchar * orig_files_index_path = 0; t_uchar * orig_dirs_index_path = 0; t_uchar * mod_files_index_path = 0; t_uchar * mod_dirs_index_path = 0; rel_table removed_dirs_index = 0; rel_table added_dirs_index = 0; rel_table removed_files_and_symlinks_index = 0; rel_table added_files_and_symlinks_index = 0; rel_table common_files_index = 0; /* [0] origloc [1] modloc [2] id */ rel_table common_dirs_index = 0; /* [0] origloc [1] modloc [2] id */ assoc_table orig_dir_loc_of = 0; assoc_table orig_dir_id_of = 0; assoc_table orig_file_loc_of = 0; assoc_table orig_file_id_of = 0; assoc_table mod_dir_loc_of = 0; assoc_table mod_dir_id_of = 0; assoc_table mod_file_loc_of = 0; assoc_table mod_file_id_of = 0; orig_files_index_path = file_name_in_vicinity (0, path, "orig-files-index"); orig_dirs_index_path = file_name_in_vicinity (0, path, "orig-dirs-index"); mod_files_index_path = file_name_in_vicinity (0, path, "mod-files-index"); mod_dirs_index_path = file_name_in_vicinity (0, path, "mod-dirs-index"); report->orig_files_index = arch_read_changeset_index (orig_files_index_path); report->orig_dirs_index = arch_read_changeset_index (orig_dirs_index_path); report->mod_files_index = arch_read_changeset_index (mod_files_index_path); report->mod_dirs_index = arch_read_changeset_index (mod_dirs_index_path); /* just to be sure: */ rel_sort_table_by_field (0, report->orig_files_index, 1); rel_sort_table_by_field (0, report->orig_dirs_index, 1); rel_sort_table_by_field (0, report->mod_files_index, 1); rel_sort_table_by_field (0, report->mod_dirs_index, 1); orig_dir_id_of = rel_to_assoc (report->orig_dirs_index, 0, 1); orig_dir_loc_of = rel_to_assoc (report->orig_dirs_index, 1, 0); orig_file_id_of = rel_to_assoc (report->orig_files_index, 0, 1); orig_file_loc_of = rel_to_assoc (report->orig_files_index, 1, 0); mod_dir_id_of = rel_to_assoc (report->mod_dirs_index, 0, 1); mod_dir_loc_of = rel_to_assoc (report->mod_dirs_index, 1, 0); mod_file_id_of = rel_to_assoc (report->mod_files_index, 0, 1); mod_file_loc_of = rel_to_assoc (report->mod_files_index, 1, 0); /**************************************************************** * Removed and added directories */ { t_uchar * original_only_dir_metadata_file = 0; t_uchar * modified_only_dir_metadata_file = 0; rel_table original_only_dir_metadata = 0; rel_table modified_only_dir_metadata = 0; rel_table orig_dirs_by_name = 0; rel_table mod_dirs_by_name = 0; rel_table t; /* [0] name [1] id -- sort 0*/ rel_table t2; /* [0] name [1] id [2] name -- sort 0 -- of dirs sans perms */ original_only_dir_metadata_file = file_name_in_vicinity (0, path, "original-only-dir-metadata"); modified_only_dir_metadata_file = file_name_in_vicinity (0, path, "modified-only-dir-metadata"); original_only_dir_metadata = arch_read_changeset_dir_metadata (original_only_dir_metadata_file); modified_only_dir_metadata = arch_read_changeset_dir_metadata (modified_only_dir_metadata_file); orig_dirs_by_name = rel_copy_table (report->orig_dirs_index); rel_sort_table_by_field (0, orig_dirs_by_name, 0); mod_dirs_by_name = rel_copy_table (report->mod_dirs_index); rel_sort_table_by_field (0, mod_dirs_by_name, 0); removed_dirs_index = rel_join (1, rel_join_output (1,0, 1,1, -1), 1, 1, report->orig_dirs_index, report->mod_dirs_index); added_dirs_index = rel_join (2, rel_join_output (2,0, 2,1, -1), 1, 1, report->orig_dirs_index, report->mod_dirs_index); t = rel_copy_table (removed_dirs_index); rel_sort_table_by_field (0, t, 0); report->removed_dirs = rel_join (-1, rel_join_output (1,0, 1,1, 2,1, -1), 0, 0, t, original_only_dir_metadata); t2 = rel_join (1, rel_join_output (1,0, 1,1, 1,0, -1), 0, 0, t, original_only_dir_metadata); rel_append_x (&report->removed_dirs, t2); rel_sort_table_by_field (0, report->removed_dirs, 0); rel_free_table (t); rel_free_table (t2); invariant (rel_n_records (report->removed_dirs) == rel_n_records (removed_dirs_index)); t = rel_copy_table (added_dirs_index); rel_sort_table_by_field (0, t, 0); report->added_dirs = rel_join (-1, rel_join_output (1,0, 1,1, 2,1, -1), 0, 0, t, modified_only_dir_metadata); t2 = rel_join (1, rel_join_output (1,0, 1,1, 1,0, -1), 0, 0, t, modified_only_dir_metadata); rel_append_x (&report->added_dirs, t2); rel_sort_table_by_field (0, report->added_dirs, 0); rel_free_table (t); rel_free_table (t2); invariant (rel_n_records (report->added_dirs) == rel_n_records (added_dirs_index)); lim_free (0, original_only_dir_metadata_file); lim_free (0, modified_only_dir_metadata_file); rel_free_table (original_only_dir_metadata); rel_free_table (modified_only_dir_metadata); rel_free_table (orig_dirs_by_name); rel_free_table (mod_dirs_by_name); } /**************************************************************** * Removed and added filenames and symlinks */ removed_files_and_symlinks_index = rel_join (1, rel_join_output (1,0, 1,1, -1), 1, 1, report->orig_files_index, report->mod_files_index); added_files_and_symlinks_index = rel_join (2, rel_join_output (2,0, 2,1, -1), 1, 1, report->orig_files_index, report->mod_files_index); report_unique_files_and_symlinks (&report->removed_files, &report->removed_symlinks, removed_files_and_symlinks_index, path, "removed-files-archive"); report_unique_files_and_symlinks (&report->added_files, &report->added_symlinks, added_files_and_symlinks_index, path, "new-files-archive"); /**************************************************************** * renamed files and dirs */ common_dirs_index = rel_join (-1, rel_join_output (1,0, 2,0, 1,1, -1), 1, 1, report->orig_dirs_index, report->mod_dirs_index); common_files_index = rel_join (-1, rel_join_output (1,0, 2,0, 1,1, -1), 1, 1, report->orig_files_index, report->mod_files_index); find_renames (&report->renamed_dirs, common_dirs_index, orig_dir_id_of, mod_dir_id_of); find_renames (&report->renamed_files, common_files_index, orig_dir_id_of, mod_dir_id_of); /**************************************************************** * Identify patches */ { int lim; int x; int here_fd; t_uchar * patches_root; rel_table patches_files = 0; assoc_table saw_patches_file = 0; patches_root = file_name_in_vicinity (0, path, "patches"); here_fd = safe_open (".", O_RDONLY, 0); safe_chdir (patches_root); find_files (&patches_files, "."); safe_fchdir (here_fd); safe_close (here_fd); saw_patches_file = rel_to_assoc (patches_files, 0, 0); lim = rel_n_records (patches_files); for (x = 0; x < lim; ++x) { t_uchar * patch_file = 0; t_uchar * patch_file_tail = 0; t_uchar * patch_file_suffix = 0; t_uchar * patch_file_loc = 0; rel_table * dest = 0; t_uchar * complement_patch = 0; t_uchar * patch_file_path = 0; t_uchar * id = 0; /* not allocated */ patch_file = patches_files[x][0]; patch_file_suffix = str_chr_rindex (patch_file, '.'); patch_file_tail = file_name_tail (0, patch_file); /* Compute the loc and the appropriate table for this * this patch. (patch_file_loc and dest) */ if (!str_cmp (patch_file_tail, "=dir-meta-orig")) { patch_file_loc = file_name_directory_file (0, patch_file); dest = &report->dir_metadata_changed; id = assoc_ref (mod_dir_id_of, patch_file_loc); } else if (!str_cmp (patch_file_suffix, ".link-orig")) { patch_file_loc = str_save_n (0, patch_file, patch_file_suffix - patch_file); complement_patch = str_alloc_cat (0, patch_file_loc, ".link-mod"); if (assoc_ref (saw_patches_file, complement_patch)) dest = &report->patched_symlinks; else dest = &report->symlink_to_file; id = assoc_ref (mod_file_id_of, patch_file_loc); } else if (!str_cmp (patch_file_suffix, ".original")) { patch_file_loc = str_save_n (0, patch_file, patch_file_suffix - patch_file); complement_patch = str_alloc_cat (0, patch_file_loc, ".modified"); if (assoc_ref (saw_patches_file, complement_patch)) dest = &report->patched_binaries; else dest = &report->file_to_symlink; id = assoc_ref (mod_file_id_of, patch_file_loc); } else if (!str_cmp (patch_file_suffix, ".patch")) { patch_file_loc = str_save_n (0, patch_file, patch_file_suffix - patch_file); dest = &report->patched_regular_files; id = assoc_ref (mod_file_id_of, patch_file_loc); } else if (!str_cmp (patch_file_suffix, ".meta-orig")) { patch_file_loc = str_save_n (0, patch_file, patch_file_suffix - patch_file); dest = &report->file_metadata_changed; id = assoc_ref (mod_file_id_of, patch_file_loc); } if (dest && patch_file_loc) { patch_file_path = file_name_in_vicinity (0, patches_root, patch_file_loc); rel_add_records (dest, rel_make_record (patch_file_loc, id, patch_file_path, 0), 0); } lim_free (0, patch_file_tail); lim_free (0, patch_file_loc); lim_free (0, complement_patch); lim_free (0, patch_file_path); } lim_free (0, patches_root); rel_free_table (patches_files); free_assoc_table (saw_patches_file); } rel_sort_table_by_field (0, report->removed_dirs, 0); rel_sort_table_by_field (0, report->added_dirs, 0); rel_sort_table_by_field (0, report->removed_files, 0); rel_sort_table_by_field (0, report->added_files, 0); rel_sort_table_by_field (0, report->removed_symlinks, 0); rel_sort_table_by_field (0, report->added_symlinks, 0); rel_sort_table_by_field (0, report->renamed_files, 0); rel_sort_table_by_field (0, report->renamed_dirs, 0); rel_sort_table_by_field (0, report->patched_regular_files, 0); rel_sort_table_by_field (0, report->patched_symlinks, 0); rel_sort_table_by_field (0, report->patched_binaries, 0); rel_sort_table_by_field (0, report->file_metadata_changed, 0); rel_sort_table_by_field (0, report->dir_metadata_changed, 0); rel_sort_table_by_field (0, report->symlink_to_file, 0); rel_sort_table_by_field (0, report->file_to_symlink, 0); lim_free (0, orig_files_index_path); lim_free (0, orig_dirs_index_path); lim_free (0, mod_files_index_path); lim_free (0, mod_dirs_index_path); rel_free_table (removed_dirs_index); rel_free_table (added_dirs_index); rel_free_table (removed_files_and_symlinks_index); rel_free_table (added_files_and_symlinks_index); free_assoc_table (orig_dir_loc_of); free_assoc_table (orig_dir_id_of); free_assoc_table (orig_file_loc_of); free_assoc_table (orig_file_id_of); free_assoc_table (mod_dir_loc_of); free_assoc_table (mod_dir_id_of); free_assoc_table (mod_file_loc_of); free_assoc_table (mod_file_id_of); rel_free_table (common_files_index); rel_free_table (common_dirs_index); } void arch_reverse_changeset (struct arch_changeset_report * report) { rel_table t; int x; assoc_table new_mod_file_loc_of = 0; assoc_table new_mod_dir_loc_of = 0; t = report->orig_files_index; report->orig_files_index = report->mod_files_index; report->mod_files_index = t; t = report->orig_dirs_index; report->orig_dirs_index = report->mod_dirs_index; report->mod_dirs_index = t; t = report->removed_dirs; report->removed_dirs = report->added_dirs; report->added_dirs = t; t = report->removed_files; report->removed_files = report->added_files; report->added_files = t; t = report->removed_symlinks; report->removed_symlinks = report->added_symlinks; report->added_symlinks = t; for (x = 0; x < rel_n_records (report->renamed_files); ++x) { rel_replace_record (report->renamed_files, x, rel_make_record (report->renamed_files[x][1], report->renamed_files[x][0], report->renamed_files[x][2], NULL)); } for (x = 0; x < rel_n_records (report->renamed_dirs); ++x) { rel_replace_record (report->renamed_dirs, x, rel_make_record (report->renamed_dirs[x][1], report->renamed_dirs[x][0], report->renamed_dirs[x][2], NULL)); } new_mod_file_loc_of = rel_to_assoc (report->mod_files_index, 1, 0); new_mod_dir_loc_of = rel_to_assoc (report->mod_dirs_index, 1, 0); fix_mod_locs (new_mod_file_loc_of, report->patched_regular_files); fix_mod_locs (new_mod_file_loc_of, report->patched_symlinks); fix_mod_locs (new_mod_file_loc_of, report->patched_binaries); fix_mod_locs (new_mod_file_loc_of, report->file_metadata_changed); fix_mod_locs (new_mod_dir_loc_of, report->dir_metadata_changed); fix_mod_locs (new_mod_file_loc_of, report->symlink_to_file); fix_mod_locs (new_mod_file_loc_of, report->file_to_symlink); } static void fix_mod_locs (assoc_table loc_of, rel_table table) { int x; for (x = 0; x < rel_n_records (table); ++x) { t_uchar * new_loc = 0; t_uchar * id; id = table[x][1]; new_loc = assoc_ref (loc_of, id); if (new_loc) new_loc = str_save (0, new_loc); rel_replace_record (table, x, rel_make_record (new_loc, table[x][1], table[x][2], NULL)); } } static void arch_print_file_metadata_diffs (int out_fd, struct arch_changeset_report * report, int escape_classes) { int x; for (x = 0; x < rel_n_records (report->file_metadata_changed); ++x) { t_uchar * orig_meta_path = 0; t_uchar * mod_meta_path = 0; t_uchar * orig_meta = 0; t_uchar * mod_meta = 0; t_uchar * file_metadata_changed = 0; file_metadata_changed = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->file_metadata_changed[x][0]); safe_printfmt (out_fd, " %s\n", file_metadata_changed); orig_meta_path = str_alloc_cat (0, report->file_metadata_changed[x][2], ".meta-orig"); mod_meta_path = str_alloc_cat (0, report->file_metadata_changed[x][2], ".meta-mod"); orig_meta = read_line_from_file (orig_meta_path); mod_meta = read_line_from_file (mod_meta_path); safe_printfmt (out_fd, " %s\n => %s\n", orig_meta, mod_meta); lim_free (0, file_metadata_changed); lim_free (0, orig_meta_path); lim_free (0, mod_meta_path); lim_free (0, orig_meta); lim_free (0, mod_meta); } } static void arch_print_dir_metadata_diffs (int out_fd, struct arch_changeset_report * report, int escape_classes) { int x; for (x = 0; x < rel_n_records (report->dir_metadata_changed); ++x) { t_uchar * orig_meta_path = 0; t_uchar * mod_meta_path = 0; t_uchar * orig_meta = 0; t_uchar * mod_meta = 0; t_uchar * dir_metadata_changed = 0; dir_metadata_changed = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->dir_metadata_changed[x][0]); safe_printfmt (out_fd, " %s\n", dir_metadata_changed); orig_meta_path = file_name_in_vicinity (0, report->dir_metadata_changed[x][2], "=dir-meta-orig"); mod_meta_path = file_name_in_vicinity (0, report->dir_metadata_changed[x][2], "=dir-meta-mod"); orig_meta = read_line_from_file (orig_meta_path); mod_meta = read_line_from_file (mod_meta_path); safe_printfmt (out_fd, " %s\n => %s\n", orig_meta, mod_meta); lim_free (0, dir_metadata_changed); lim_free (0, orig_meta_path); lim_free (0, mod_meta_path); lim_free (0, orig_meta); lim_free (0, mod_meta); } } static void arch_print_file_diffs (struct arch_changeset_report * report) { int x; for (x = 0; x < rel_n_records (report->patched_regular_files); ++x) { t_uchar * patch_file; int in_fd; patch_file = str_alloc_cat (0, report->patched_regular_files[x][2], ".patch"); in_fd = safe_open (patch_file, O_RDONLY, 0); copy_fd (in_fd, 1); safe_printfmt (1, "\n\n"); safe_close (in_fd); lim_free (0, patch_file); } } static void arch_print_added_file_diffs (struct arch_changeset_report * report) { int x; for (x = 0; x < rel_n_records (report->added_files); ++x) { arch_really_invoke_diff (1, "/dev/null", NULL, report->added_files[x][2], report->added_files[x][0], NULL); } } static void print_file_metadata (int out_fd, struct arch_changeset_report * report, int escape_classes) { if (report->file_metadata_changed) { safe_printfmt (out_fd, "* file metadata changed\n\n"); arch_print_file_metadata_diffs (out_fd, report, escape_classes); safe_printfmt (out_fd, "\n"); } } static void print_dir_metadata (int out_fd, struct arch_changeset_report * report, int escape_classes) { if (report->dir_metadata_changed) { safe_printfmt (out_fd, "* dir metadata changed\n\n"); arch_print_dir_metadata_diffs (out_fd, report, escape_classes); safe_printfmt (out_fd, "\n"); } } static void print_diffs_new(struct arch_changeset_report * report) { if (report->patched_regular_files) { safe_printfmt (1, "* modified files\n\n"); arch_print_file_diffs (report); safe_printfmt (1, "\n"); } if (report->added_files) { safe_printfmt (1, "* added files\n\n"); arch_print_added_file_diffs (report); safe_printfmt (1, "\n"); } print_removed_file_diffs(report, NULL); } /** * \brief Write custom diffs for to a file descriptor * * The changeset report is used to determine which files to diff, and the * partial file paths. The orig_dir and mod_dir are used to produce full * paths. diff is invoked to produce the output. * * \param report The report to use for output * \param orig_dir The path to a copy of the ORIG tree * \param mod_dir The path to a copy of the MOD tree */ static void print_custom_diffs (struct arch_changeset_report * report, t_uchar * orig_dir, t_uchar * mod_dir, t_uchar ** opts) { if (report->patched_regular_files) { int x; assoc_table orig_paths = rel_to_assoc (report->orig_files_index, 1, 0); safe_printfmt (1, "* modified files\n\n"); for (x = 0; x < rel_n_records (report->patched_regular_files); ++x) { t_uchar * id = report->patched_regular_files[x][1]; t_uchar * orig_part_path = assoc_ref(orig_paths, id); t_uchar * orig_path = file_name_in_vicinity(0, orig_dir, orig_part_path); t_uchar * mod_path = file_name_in_vicinity(0, mod_dir, report->patched_regular_files[x][0]); arch_really_invoke_diff (1, orig_path, orig_part_path, mod_path, report->patched_regular_files[x][0], (char **)opts); lim_free(0, mod_path); lim_free(0, orig_path); } safe_printfmt (1, "\n"); free_assoc_table (orig_paths); } if (report->added_files) { int x; safe_printfmt (1, "* added files\n\n"); for (x = 0; x < rel_n_records (report->added_files); ++x) { arch_really_invoke_diff (1, "/dev/null", NULL, report->added_files[x][2], report->added_files[x][0], (char**)opts); } safe_printfmt (1, "\n"); } print_removed_file_diffs (report, opts); } /** * \brief Print the diffs for any removed files to output. * * If no files were removed, no output is produced * \param report The changeset report to generate results for * \param opts Additional parameters to pass to diff, or NULL */ static void print_removed_file_diffs (struct arch_changeset_report * report, t_uchar ** opts) { if (report->removed_files) { int x; safe_printfmt (1, "* removed files\n\n"); for (x = 0; x < rel_n_records (report->removed_files); ++x) { arch_really_invoke_diff (1, report->removed_files[x][2], report->removed_files[x][0], "/dev/null", NULL, (char**)opts); } safe_printfmt (1, "\n"); } } /** * \brief Write a changeset report with custom diffs to a file descriptor * * \param report The report to use for output * \param orig_dir The path to a copy of the ORIG tree * \param mod_dir The path to a copy of the MOD tree * \param escape_classes The types of characters that should be escaped * \todo Consider reimplementing so that a custom changeset is generated, not * custom diffs. */ void arch_print_changeset_custom_diffs (struct arch_changeset_report * report, t_uchar * orig_dir, t_uchar * mod_dir, t_uchar ** opts, int escape_classes) { print_file_metadata (1, report, escape_classes); print_dir_metadata (1, report, escape_classes); if (opts == NULL) print_diffs_new (report); else print_custom_diffs (report, orig_dir, mod_dir, opts); } void arch_print_changeset (struct arch_changeset_report * report, int diffs, int escape_classes) { int x; int out_fd = 1; if (report->removed_dirs) { safe_printfmt (1, "* removed directories\n\n"); for (x = 0; x < rel_n_records (report->removed_dirs); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->removed_dirs[x][0]); safe_printfmt (1, " %s\n", no_dot (item)); lim_free (0, item); } safe_printfmt (1, "\n"); } if (report->added_dirs) { safe_printfmt (1, "* added directories\n\n"); for (x = 0; x < rel_n_records (report->added_dirs); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->added_dirs[x][0]); safe_printfmt (1, " %s\n", no_dot (item)); lim_free (0, item); } safe_printfmt (1, "\n"); } if (report->removed_files) { safe_printfmt (out_fd, "* removed files\n\n"); for (x = 0; x < rel_n_records (report->removed_files); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->removed_files[x][0]); safe_printfmt (out_fd, " %s\n", no_dot (item)); lim_free (0, item); } safe_printfmt (out_fd, "\n"); } if (report->removed_symlinks) { safe_printfmt (out_fd, "* removed symlinks\n\n"); for (x = 0; x < rel_n_records (report->removed_symlinks); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->removed_symlinks[x][0]); safe_printfmt (out_fd, " %s\n", no_dot (item)); lim_free (0, item); } safe_printfmt (out_fd, "\n"); } if (report->added_symlinks) { safe_printfmt (out_fd, "* added symlinks\n\n"); for (x = 0; x < rel_n_records (report->added_symlinks); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->added_symlinks[x][0]); safe_printfmt (out_fd, " %s\n", no_dot (item)); lim_free (0, item); } safe_printfmt (out_fd, "\n"); } if (report->renamed_files) { safe_printfmt (out_fd, "* renamed files and symlinks\n\n"); for (x = 0; x < rel_n_records (report->renamed_files); ++x) { t_uchar * item1; t_uchar * item2; item1 = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->renamed_files[x][0]); item2 = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->renamed_files[x][1]); safe_printfmt (out_fd, " %s\n => %s\n\n", no_dot (item1), no_dot (item2)); lim_free (0, item2); lim_free (0, item1); } } if (report->renamed_dirs) { safe_printfmt (out_fd, "* renamed directories\n\n"); for (x = 0; x < rel_n_records (report->renamed_dirs); ++x) { t_uchar * item1; t_uchar * item2; item1 = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->renamed_dirs[x][0]); item2 = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->renamed_dirs[x][1]); safe_printfmt (out_fd, " %s\n => %s\n\n", no_dot (item1), no_dot (item2)); lim_free (0, item2); lim_free (0, item1); } } if (report->file_to_symlink) { safe_printfmt (out_fd, "* files replaced by symlinks \n\n"); for (x = 0; x < rel_n_records (report->file_to_symlink); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->file_to_symlink[x][0]); safe_printfmt (out_fd, " %s\n", no_dot (item)); lim_free (0, item); } safe_printfmt (out_fd, "\n"); } if (report->symlink_to_file) { safe_printfmt (out_fd, "* symlinks replaced by files\n\n"); for (x = 0; x < rel_n_records (report->symlink_to_file); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->symlink_to_file[x][0]); safe_printfmt (out_fd, " %s\n", no_dot (item)); lim_free (0, item); } safe_printfmt (out_fd, "\n"); } if (report->file_metadata_changed) { safe_printfmt (out_fd, "* file metadata changed\n\n"); if (diffs) { arch_print_file_metadata_diffs (out_fd, report, escape_classes); } else { for (x = 0; x < rel_n_records (report->file_metadata_changed); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->file_metadata_changed[x][0]); safe_printfmt (out_fd, " %s\n", no_dot (item)); lim_free (0, item); } } safe_printfmt (out_fd, "\n"); } if (report->dir_metadata_changed) { safe_printfmt (out_fd, "* dir metadata changed\n\n"); if (diffs) { arch_print_dir_metadata_diffs (out_fd, report, escape_classes); } else { for (x = 0; x < rel_n_records (report->dir_metadata_changed); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->dir_metadata_changed[x][0]); safe_printfmt (out_fd, " %s\n", no_dot (item)); lim_free (0, item); } } safe_printfmt (out_fd, "\n"); } if (report->patched_symlinks) { safe_printfmt (out_fd, "* retargeted symlinks\n\n"); for (x = 0; x < rel_n_records (report->patched_symlinks); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->patched_symlinks[x][0]); safe_printfmt (out_fd, " %s\n", no_dot (item)); lim_free (0, item); } safe_printfmt (out_fd, "\n"); } if (report->patched_binaries) { safe_printfmt (out_fd, "* modified binary files\n\n"); for (x = 0; x < rel_n_records (report->patched_binaries); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->patched_binaries[x][0]); safe_printfmt (out_fd, " %s\n", no_dot (item)); lim_free (0, item); } safe_printfmt (out_fd, "\n"); } if (report->added_files) { safe_printfmt (out_fd, "* added files\n\n"); for (x = 0; x < rel_n_records (report->added_files); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->added_files[x][0]); safe_printfmt (out_fd, " %s\n", no_dot (item)); if (diffs) { arch_print_added_file_diffs (report); } lim_free (0, item); } safe_printfmt (out_fd, "\n"); } if (report->patched_regular_files) { safe_printfmt (out_fd, "* modified files\n\n"); if (diffs) { arch_print_file_diffs (report); } else { for (x = 0; x < rel_n_records (report->patched_regular_files); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->patched_regular_files[x][0]); safe_printfmt (out_fd, " %s\n", no_dot (item)); lim_free (0, item); } } safe_printfmt (out_fd, "\n"); } } /* * Print a changeset report in a compact format. * column 1 is : A|D|R|S|F - add/delete/rename/file->symlink and symlink->file * column 2 is : M - modified files | symlinks */ void arch_changeset_report_print_compact (int out_fd, struct arch_changeset_report * report, int escape_classes) { int x; if (report->removed_dirs) { for (x = 0; x < rel_n_records (report->removed_dirs); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->removed_dirs[x][0]); safe_printfmt (out_fd, "D %s\n", no_dot (item)); lim_free (0, item); } } if (report->added_dirs) { for (x = 0; x < rel_n_records (report->added_dirs); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->added_dirs[x][0]); safe_printfmt (out_fd, "A %s\n", no_dot (item)); lim_free (0, item); } } if (report->removed_files) { for (x = 0; x < rel_n_records (report->removed_files); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->removed_files[x][0]); safe_printfmt (out_fd, "D %s\n", no_dot (item)); lim_free (0, item); } } if (report->added_files) { for (x = 0; x < rel_n_records (report->added_files); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->added_files[x][0]); safe_printfmt (out_fd, "A %s\n", no_dot (item)); lim_free (0, item); } } if (report->removed_symlinks) { for (x = 0; x < rel_n_records (report->removed_symlinks); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->removed_symlinks[x][0]); safe_printfmt (out_fd, "D %s\n", no_dot (item)); lim_free (0, item); } } if (report->added_symlinks) { for (x = 0; x < rel_n_records (report->added_symlinks); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->added_symlinks[x][0]); safe_printfmt (out_fd, "A %s\n", no_dot (item)); lim_free (0, item); } } if (report->renamed_files) { for (x = 0; x < rel_n_records (report->renamed_files); ++x) { t_uchar * item1; t_uchar * item2; item1 = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->renamed_files[x][0]); item2 = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->renamed_files[x][1]); safe_printfmt (out_fd, "R %s => %s\n", no_dot (item1), no_dot (item2)); lim_free (0, item2); lim_free (0, item1); } } if (report->renamed_dirs) { for (x = 0; x < rel_n_records (report->renamed_dirs); ++x) { t_uchar * item1; t_uchar * item2; item1 = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->renamed_dirs[x][0]); item2 = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->renamed_dirs[x][1]); safe_printfmt (out_fd, "R %s => %s\n", no_dot (item1), no_dot (item2)); lim_free (0, item2); lim_free (0, item1); } } if (report->file_to_symlink) { for (x = 0; x < rel_n_records (report->file_to_symlink); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->file_to_symlink[x][0]); safe_printfmt (out_fd, "S %s\n", no_dot (item)); lim_free (0, item); } } if (report->symlink_to_file) { for (x = 0; x < rel_n_records (report->symlink_to_file); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->symlink_to_file[x][0]); safe_printfmt (out_fd, "F %s\n", no_dot (item)); lim_free (0, item); } } if (report->file_metadata_changed) { for (x = 0; x < rel_n_records (report->file_metadata_changed); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->file_metadata_changed[x][0]); safe_printfmt (out_fd, " P %s\n", no_dot (item)); lim_free (0, item); } } if (report->dir_metadata_changed) { for (x = 0; x < rel_n_records (report->dir_metadata_changed); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->dir_metadata_changed[x][0]); safe_printfmt (out_fd, " P %s\n", no_dot (item)); lim_free (0, item); } } if (report->patched_symlinks) { for (x = 0; x < rel_n_records (report->patched_symlinks); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->patched_symlinks[x][0]); safe_printfmt (out_fd, " M %s\n", no_dot (item)); lim_free (0, item); } } if (report->patched_binaries) { for (x = 0; x < rel_n_records (report->patched_binaries); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->patched_binaries[x][0]); safe_printfmt (out_fd, " M %s\n", no_dot (item)); lim_free (0, item); } } if (report->patched_regular_files) { for (x = 0; x < rel_n_records (report->patched_regular_files); ++x) { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, escape_classes, report->patched_regular_files[x][0]); safe_printfmt (out_fd, " M %s\n", no_dot (item)); lim_free (0, item); } } } void arch_free_changeset_report_data (struct arch_changeset_report * r) { rel_free_table (r->orig_files_index); r->orig_files_index = 0; rel_free_table (r->orig_dirs_index); r->orig_dirs_index = 0; rel_free_table (r->mod_files_index); r->mod_files_index = 0; rel_free_table (r->mod_dirs_index); r->mod_dirs_index = 0; rel_free_table (r->removed_dirs); r->removed_dirs = 0; rel_free_table (r->added_dirs); r->added_dirs = 0; rel_free_table (r->removed_files); r->removed_files = 0; rel_free_table (r->added_files); r->added_files = 0; rel_free_table (r->removed_symlinks); r->removed_symlinks = 0; rel_free_table (r->added_symlinks); r->added_symlinks = 0; rel_free_table (r->renamed_files); r->renamed_files = 0; rel_free_table (r->renamed_dirs); r->renamed_dirs = 0; rel_free_table (r->patched_regular_files); r->patched_regular_files = 0; rel_free_table (r->patched_symlinks); r->patched_symlinks = 0; rel_free_table (r->patched_binaries); r->patched_binaries = 0; rel_free_table (r->file_metadata_changed); r->file_metadata_changed = 0; rel_free_table (r->dir_metadata_changed); r->dir_metadata_changed = 0; rel_free_table (r->symlink_to_file); r->symlink_to_file = 0; rel_free_table (r->file_to_symlink); r->file_to_symlink = 0; } static void report_unique_files_and_symlinks (rel_table * files, rel_table * symlinks, rel_table index, t_uchar * archive_dir, t_uchar * archive_basename) { t_uchar * archive = 0; int lim; int x; archive = file_name_in_vicinity (0, archive_dir, archive_basename); lim = rel_n_records (index); for (x = 0; x < lim; ++x) { t_uchar * archive_path; struct stat stat_buf; archive_path = file_name_in_vicinity (0, archive, index[x][0]); safe_lstat (archive_path, &stat_buf); if (S_ISLNK (stat_buf.st_mode)) { rel_add_records (symlinks, rel_make_record (index[x][0], index[x][1], archive_path, 0), 0); } else { rel_add_records (files, rel_make_record (index[x][0], index[x][1], archive_path, 0), 0); } lim_free (0, archive_path); } rel_sort_table_by_field (0, *files, 0); rel_sort_table_by_field (0, *symlinks, 0); lim_free (0, archive); } static void find_renames (rel_table * out, rel_table common, assoc_table orig_dir_id_of, assoc_table mod_dir_id_of) { int lim; int x; lim = rel_n_records (common); for (x = 0; x < lim; ++x) { t_uchar * orig_loc = 0; t_uchar * mod_loc = 0; t_uchar * id = 0; t_uchar * orig_basename = 0; t_uchar * mod_basename = 0; t_uchar * orig_dir = 0; t_uchar * mod_dir = 0; t_uchar * orig_dir_id = 0; t_uchar * mod_dir_id = 0; orig_loc = common[x][0]; mod_loc = common[x][1]; id = common[x][2]; orig_basename = file_name_tail (0, orig_loc); mod_basename = file_name_tail (0, mod_loc); orig_dir = file_name_directory_file (0, orig_loc); mod_dir = file_name_directory_file (0, mod_loc); orig_dir_id = assoc_ref (orig_dir_id_of, orig_dir); mod_dir_id = assoc_ref (mod_dir_id_of, mod_dir); /* The conditional subexpression here attempts to identify renames * even when the the changeset is missing locs and ids for * one or both of the containing dirs of the object under consideration. * */ if (str_cmp (orig_basename, mod_basename) || ((orig_dir_id && mod_dir_id) ? str_cmp (orig_dir_id, mod_dir_id) : str_cmp (orig_dir, mod_dir))) { rel_add_records (out, rel_make_record (orig_loc, mod_loc, id, 0), 0); } lim_free (0, orig_basename); lim_free (0, mod_basename); lim_free (0, orig_dir); lim_free (0, mod_dir); } } void arch_changeset_report_init (struct arch_changeset_report * changeset) { mem_set0 ((t_uchar *)changeset, sizeof (*changeset)); } /* tag: Tom Lord Thu May 15 13:07:24 2003 (changeset-report.c) */