/* apply-changeset.c: * * vim:smartindent ts=8:sts=2:sta:et:ai:shiftwidth=2 **************************************************************** * Copyright (C) 2004 Aaron Bentley * * 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/bugs/exception.h" #include "hackerlab/os/errno-to-string.h" #include "hackerlab/os/sys/wait.h" #include "hackerlab/fmt/cvt.h" #include "hackerlab/fs/file-names.h" #include "hackerlab/mem/mem.h" #include "hackerlab/vu/safe.h" #include "libfsutils/copy-file.h" #include "libfsutils/ensure-dir.h" #include "libfsutils/tmp-files.h" #include "libfsutils/rmrf.h" #include "libarch/diffs.h" #include "libarch/exec.h" #include "libarch/invent.h" #include "libarch/chatter.h" #include "libarch/changelogs.h" #include "libarch/conflict-handling.h" #include "libarch/make-changeset.h" #include "libarch/apply-changeset.h" #include "libarch/inode-sig.h" #include "libarch/project-tree.h" #include "libarch/patch-logs.h" #include "libarch/proj-tree-lint.h" #include "merge-three-way.h" static void progress_dot_callback (void * vfd, char * fmt, va_list ap); static void three_way_callback (void * vfd, char * fmt, va_list ap); static assoc_table tag_index_to_full_paths (arch_project_tree_t * tree); /* returns * 0 on success * 1 on conflicts * 2 (or exit :[) on failure */ int arch_merge3(int chatter_fd, arch_project_tree_t * mine_tree, arch_project_tree_t * base_tree, arch_project_tree_t * other_tree, int escape_classes, int show_noops) { int dots_for_generation = 1; struct arch_make_changeset_report make_report = {0, }; struct arch_apply_changeset_report * apply_report; t_uchar * tmp_dir = talloc_tmp_file_name (talloc_context, mine_tree->root, ",,merge-three-way"); t_uchar * changeset = file_name_in_vicinity (0, tmp_dir, ",,changeset"); assoc_table inode_shortcut = 0; t_uchar * base_revision = arch_tree_latest_revision (base_tree->root); assoc_table older_files_table; assoc_table yours_files_table; arch_apply_changeset_report_callback apply_callback = NULL; void * apply_thunk = NULL; rmrf_file (tmp_dir); safe_mkdir (tmp_dir, 0777); if (chatter_fd != -1) { if (dots_for_generation) make_report.callback = progress_dot_callback; else make_report.callback = three_way_callback; make_report.thunk = (void *)(long)chatter_fd; apply_callback = three_way_callback; apply_thunk = (void *)(long)chatter_fd; } older_files_table = tag_index_to_full_paths (base_tree); yours_files_table = tag_index_to_full_paths (other_tree); arch_read_inode_sig_ids (0, &inode_shortcut, base_tree->root, other_tree->root, base_revision); arch_chatter (chatter_fd, "* Comparing FROM and TO"); if (dots_for_generation) arch_chatter (chatter_fd, ": "); else arch_chatter (chatter_fd, "\n"); arch_make_changeset (&make_report, base_tree, other_tree, changeset, arch_unspecified_id_tagging, arch_inventory_unrecognized, 0, inode_shortcut, 0, escape_classes); if (dots_for_generation) arch_chatter (chatter_fd, " done.\n"); arch_chatter (chatter_fd, "* Merging into tree\n"); apply_report = arch_merge_from_changeset (changeset, talloc_context, mine_tree, arch_unspecified_id_tagging, arch_inventory_unrecognized, older_files_table, yours_files_table, escape_classes, show_noops, apply_callback, apply_thunk); rmrf_file (tmp_dir); lim_free (0, base_revision); lim_free (0, changeset); talloc_free (tmp_dir); arch_free_make_changeset_report_data (&make_report); talloc_free (apply_report); return arch_tree_conflicts_exist (mine_tree); } static void progress_dot_callback (void * vfd, char * fmt, va_list ap) { int fd; fd = (int)(t_ulong)vfd; if (fd >= 0) { safe_printfmt_va_list (fd, ".", ap); safe_flush (fd); } } static void three_way_callback (void * vfd, char * fmt, va_list ap) { int fd; fd = (int)(t_ulong)vfd; if (fd >= 0) { safe_printfmt_va_list (fd, fmt, ap); safe_flush (fd); } } static assoc_table tag_index_to_full_paths (arch_project_tree_t * tree) { rel_table index = 0; assoc_table answer = 0; int x; index = arch_source_inventory (tree, 1, 0, 0); for (x = 0; x < rel_n_records (index); ++x) { t_uchar * relpath = index[x][0]; t_uchar * id = index[x][1]; t_uchar * full_path = file_name_in_vicinity (0, tree->root, relpath); assoc_set (&answer, id, full_path); lim_free (0, full_path); } rel_free_table (index); return answer; } /* tag: 961f2509-ebf8-43aa-a14d-5b0df3090ec6 */