This patch implements the following: * automatic cachrev every 50 commits * smarter get algorithm. Now it weights between several possible ways to get a revision and use the one that take the minimum effort Caveats: * the number 50 is hard coded; it really should be a value that the user can customize. * when there is a greedy and non-sparse revlib and it doesn't contain anything, tla still go all the way back. (maybe we should limit the number of recursions in non-sparse revlib) The patch overhauls the build-revision.c and changes half of the library-txn.c. Still need more testing.
Derek * looking for [EMAIL PROTECTED]/tla--derek-no-pristines--1.3--base-0 to compare with * comparing to [EMAIL PROTECTED]/tla--derek-no-pristines--1.3--base-0 M libarch/library-txn.c M libarch/cmd-get.c M libarch/cmd-commit.c M libarch/build-revision.h M libarch/arch.h M libarch/build-revision.c * modified files --- orig/libarch/arch.h +++ mod/libarch/arch.h @@ -14,6 +14,7 @@ #include "hackerlab/char/char-class.h" +#define arch_default_cachrev_penalty 50 static const int arch_escape_classes = char_class_control | char_class_space | char_class_non_ascii; --- orig/libarch/build-revision.c +++ mod/libarch/build-revision.c @@ -18,9 +18,11 @@ #include "tla/libfsutils/dir-listing.h" #include "tla/libfsutils/tmp-files.h" #include "tla/libfsutils/rmrf.h" +#include "tla/libfsutils/same.h" #include "tla/libarch/namespace.h" #include "tla/libarch/libraries.h" #include "tla/libarch/archive.h" +#include "tla/libarch/arch.h" #include "tla/libarch/apply-changeset.h" #include "tla/libarch/project-tree.h" #include "tla/libarch/pristines.h" @@ -30,78 +32,165 @@ #include "tla/libarch/build-revision.h" +/* build the rev from a lib. return 1 if built 0 otherwise */ +static int +build_from_lib (const t_uchar * dest_dir, + const t_uchar * archive, + const t_uchar * revision, + int hardlinks) +{ + t_uchar * library_rev_dir = arch_library_find (rel_table_nil, archive, revision, 1); + rel_table index_by_name = rel_table_nil; + int full_meta; + if (library_rev_dir) + { + full_meta = arch_tree_has_meta_flag (library_rev_dir); + index_by_name = arch_library_index (archive, revision); + rel_sort_table_by_field (0, index_by_name, 0); + if (hardlinks && on_same_device (library_rev_dir, dest_dir)) // try hardlink + { + rmrf_file (dest_dir); // otherwise will fail + build_partial_link_tree (library_rev_dir, dest_dir, index_by_name, full_meta); + } + else + copy_file_list (dest_dir, library_rev_dir, index_by_name, full_meta); + rel_free_table (index_by_name); + lim_free (0, library_rev_dir); + return 1; + } + return 0; +} + +/* build the rev from a pristine cache. return 1 if built 0 otherwise */ +static int +build_from_cache (const t_uchar * dest_dir, + const t_uchar * archive, + const t_uchar * revision, + const t_uchar * cache_dir) +{ + t_uchar * pristine_copy = 0; + + if (cache_dir) + { + pristine_copy = arch_find_pristine (0, cache_dir, archive, revision, arch_any_pristine, + arch_cache_dir_pristine_search); + if (pristine_copy) + { + rel_table file_list = rel_table_nil; + int full_meta = arch_tree_has_meta_flag (pristine_copy); + + file_list = arch_source_inventory (pristine_copy, 1, 0, 0); + copy_file_list (dest_dir, pristine_copy, file_list, full_meta); + rel_free_table (file_list); + lim_free (0, pristine_copy); + return 1; + } + } + return 0; +} + +static void +build_from_dir (const t_uchar * dest_dir, + const t_uchar * src_dir) +{ + rel_table files = rel_table_nil; + int x; + + files = directory_files (src_dir); + + for (x = 0; x < rel_n_records (files); ++x) + { + if (str_cmp (".", rel_peek_str (files, x, 0)) && str_cmp ("..", rel_peek_str (files, x, 0))) + { + t_uchar * frm = 0; + t_uchar * to = 0; + + frm = file_name_in_vicinity (0, src_dir, rel_peek_str (files, x, 0)); + to = file_name_in_vicinity (0, dest_dir, rel_peek_str (files, x, 0)); + + safe_rename (frm, to); + + lim_free (0, frm); + lim_free (0, to); + } + } + rel_free_table (files); +} + +static void +patch_to_current_revision (const t_uchar * dest_dir, + struct arch_archive * arch, + const t_uchar * revision, + int escape_classes) +{ + t_uchar * tmppatch = 0; + struct arch_apply_changeset_report r; + + tmppatch = tmp_file_name (dest_dir, ",,next-patch"); + arch_get_patch (arch, revision, tmppatch); + + mem_set0 ((t_uchar *)&r, sizeof (r)); + + arch_apply_changeset (&r, tmppatch, dest_dir, arch_unspecified_id_tagging, + arch_inventory_unrecognized, 0, 0, 0, 0, 0, escape_classes); + + if (arch_conflicts_occured (&r)) + panic ("conflict applying patch in arch_build_revision"); + + arch_free_apply_changeset_report_data (&r); + + rmrf_file (tmppatch); + lim_free (0, tmppatch); +} -/* return non-0 if it came from a library. +/* build the revision if can be done with effort less than limit - starting_effort + * the effort is defined as: + * - building with local (library copy) tree takes 0; + * - building with a patch takes +1; + * - building with a cacherev or import takes arch_build_arch_default_cachrev_penalty + * return 1 if built from library, 2 if built but not from a library, 0 if not built */ int -arch_build_revision (int chatter_fd, - const t_uchar * dest_dir, - struct arch_archive * arch, - const t_uchar * archive, - const t_uchar * revision, - const t_uchar * cache_dir) +arch_build_revision_rec (int chatter_fd, + const t_uchar * dest_dir, + struct arch_archive * arch, + const t_uchar * archive, + const t_uchar * revision, + const t_uchar * cache_dir, + int hardlinks, + int escape_classes, + int limit, + int starting_effort) { - struct arch_archive * my_arch = 0; - t_uchar * library_rev_dir = 0; - int is_built = 0; - int from_library = 0; - - library_rev_dir = arch_library_find (rel_table_nil, archive, revision, 1); + int answer = 0; /**************************************************************** * Take it from a revision library, if we can. */ - if (!is_built && library_rev_dir) + if (build_from_lib(dest_dir, archive, revision, hardlinks)) { - rel_table index_by_name = rel_table_nil; - const int full_meta = arch_tree_has_meta_flag (library_rev_dir); - arch_chatter (chatter_fd, "* from revision library: %s/%s\n", archive, revision); - - index_by_name = arch_library_index (archive, revision); - rel_sort_table_by_field (0, index_by_name, 0); - copy_file_list (dest_dir, library_rev_dir, index_by_name, full_meta); - - rel_free_table (index_by_name); - - is_built = 1; - from_library = 1; + answer = 1; } /**************************************************************** * Next, try the pristine cache. */ - if (!is_built && cache_dir) + else if (build_from_cache(dest_dir, archive, revision, cache_dir)) { - t_uchar * pristine_copy = 0; - - pristine_copy = arch_find_pristine (0, cache_dir, archive, revision, arch_any_pristine, arch_cache_dir_pristine_search); - - if (pristine_copy) - { - rel_table file_list = rel_table_nil; - const int full_meta = arch_tree_has_meta_flag (pristine_copy); - - arch_chatter (chatter_fd, "* from pristine cache: %s/%s\n", archive, revision); - - file_list = arch_source_inventory (pristine_copy, 1, 0, 0); - copy_file_list (dest_dir, pristine_copy, file_list, full_meta); - is_built = 1; - - rel_free_table (file_list); - } - - lim_free (0, pristine_copy); + arch_chatter (chatter_fd, "* from pristine cache: %s/%s\n", archive, revision); + answer = 2; } /**************************************************************** * Ok, have to hit up the archive. */ - if (!is_built) + else { enum arch_revision_type type; int is_cached; + struct arch_archive * my_arch = 0; if (!arch) { @@ -112,166 +201,133 @@ arch_revision_type (&type, &is_cached, arch, revision); /******************************** - * Archive Cached Revision? - */ - if (is_cached) - { - t_uchar * tmpdir = 0; - rel_table files = rel_table_nil; - int x; - - arch_chatter (chatter_fd, "* from archive cached: %s/%s\n", archive, revision); - - tmpdir = tmp_file_name (dest_dir, ",,cached-revision"); - arch_get_cached_revision (arch, revision, tmpdir); - files = directory_files (tmpdir); - - for (x = 0; x < rel_n_records (files); ++x) - { - if (str_cmp (".", rel_peek_str (files, x, 0)) && str_cmp ("..", rel_peek_str (files, x, 0))) - { - t_uchar * frm = 0; - t_uchar * to = 0; - - frm = file_name_in_vicinity (0, tmpdir, rel_peek_str (files, x, 0)); - to = file_name_in_vicinity (0, dest_dir, rel_peek_str (files, x, 0)); - - safe_rename (frm, to); - - lim_free (0, frm); - lim_free (0, to); - } - } - - safe_rmdir (tmpdir); - - lim_free (0, tmpdir); - rel_free_table (files); - } - - /******************************** * Import Revision? */ - else if (type == arch_import_revision) + if (type == arch_import_revision) { - t_uchar * tmpdir = 0; - rel_table files = rel_table_nil; - int x; - - arch_chatter (chatter_fd, "* from import revision: %s/%s\n", archive, revision); - - tmpdir = tmp_file_name (dest_dir, ",,import-revision"); - arch_get_import_revision (arch, revision, tmpdir); - files = directory_files (tmpdir); - - for (x = 0; x < rel_n_records (files); ++x) + int new_limit = starting_effort + arch_default_cachrev_penalty; + if ((limit==-1) || (new_limit < limit)) // build here { - if (str_cmp (".", rel_peek_str (files, x, 0)) && str_cmp ("..", rel_peek_str (files, x, 0))) - { - t_uchar * frm = 0; - t_uchar * to = 0; - - frm = file_name_in_vicinity (0, tmpdir, rel_peek_str (files, x, 0)); - to = file_name_in_vicinity (0, dest_dir, rel_peek_str (files, x, 0)); - - safe_rename (frm, to); - - lim_free (0, frm); - lim_free (0, to); - } + t_uchar * tmpdir = 0; + arch_chatter (chatter_fd, "* from import revision: %s/%s\n", archive, revision); + tmpdir = tmp_file_name (dest_dir, ",,import-revision"); + arch_get_import_revision (arch, revision, tmpdir); + build_from_dir(dest_dir, tmpdir); + safe_rmdir (tmpdir); + lim_free (0, tmpdir); + answer = 2; } - - safe_rmdir (tmpdir); - - lim_free (0, tmpdir); - rel_free_table (files); } else { + int new_limit = limit; /******************************** - * Recurse and Build by Patching + * Archive Cached Revision? */ - - t_uchar * prev_revision = 0; - t_uchar * prev_archive = 0; - struct arch_archive * prev_arch; - - if (type == arch_simple_revision) + if (is_cached) { - prev_revision = arch_previous_revision (arch, revision); - invariant (!!prev_revision); - prev_archive = str_save (0, archive); - prev_arch = arch; + new_limit = starting_effort + arch_default_cachrev_penalty; + if ((limit!=-1) && (new_limit >= limit)) // too much effort to build here + new_limit = limit; } - else + if (new_limit==-1 || new_limit > starting_effort+1) // ok to search more { - t_uchar * fq_prev_revision = 0; - - fq_prev_revision = arch_get_continuation (arch, revision); - - if (!arch_valid_package_name (fq_prev_revision, arch_req_archive, arch_req_patch_level, 0)) - { - safe_printfmt (2, "arch_build_revision: archive contains bogus CONTINUATION file\n archive: %s\n revision: %s\n", - archive, revision); - exit (2); - } - - prev_archive = arch_parse_package_name (arch_ret_archive, 0, fq_prev_revision); - prev_revision = arch_parse_package_name (arch_ret_non_archive, 0, fq_prev_revision); - - if (!str_cmp (archive, prev_revision)) + /******************************** + * find previous revision + */ + t_uchar * prev_revision = 0; + t_uchar * prev_archive = 0; + struct arch_archive * prev_arch; + + if (type == arch_simple_revision) { + prev_revision = arch_previous_revision (arch, revision); + invariant (!!prev_revision); + prev_archive = str_save (0, archive); prev_arch = arch; } else { - prev_arch = arch_archive_connect (prev_archive, 0); + t_uchar * fq_prev_revision = 0; + + fq_prev_revision = arch_get_continuation (arch, revision); + if (!arch_valid_package_name (fq_prev_revision, arch_req_archive, + arch_req_patch_level, 0)) + { + safe_printfmt (2, "arch_build_revision: archive contains bogus CONTINUATION file\n archive: %s\n revision: %s\n", + archive, revision); + exit (2); + } + + prev_archive = arch_parse_package_name (arch_ret_archive, 0, fq_prev_revision); + prev_revision = arch_parse_package_name (arch_ret_non_archive, 0, fq_prev_revision); + lim_free (0, fq_prev_revision); + if (!str_cmp (archive, prev_archive)) + prev_arch = arch; + else if (new_limit == -1) // no solution yet + prev_arch = arch_archive_connect (prev_archive, 0); + else // we do not cross archive boundary unless neccessary + prev_arch = 0; } + if (prev_arch) + answer = arch_build_revision_rec (chatter_fd, dest_dir, prev_arch, prev_archive, + prev_revision, cache_dir, hardlinks, escape_classes, + new_limit, starting_effort+1); + + lim_free (0, prev_archive); + lim_free (0, prev_revision); + if (arch != prev_arch) + arch_archive_close (prev_arch); - lim_free (0, fq_prev_revision); + if (answer!=0) + { + arch_chatter (chatter_fd, "* patching for the revision: %s/%s\n", archive, revision); + patch_to_current_revision(dest_dir, arch, revision, escape_classes); + answer = 2; + } + } + if (answer==0 && is_cached && new_limit!=limit) // build here + { + t_uchar * tmpdir = 0; + arch_chatter (chatter_fd, "* from archive cached: %s/%s\n", archive, revision); + tmpdir = tmp_file_name (dest_dir, ",,cached-revision"); + arch_get_cached_revision (arch, revision, tmpdir); + build_from_dir(dest_dir, tmpdir); + safe_rmdir (tmpdir); + lim_free (0, tmpdir); + answer = 2; } - - - arch_build_revision (chatter_fd, dest_dir, prev_arch, prev_archive, prev_revision, cache_dir); - - arch_chatter (chatter_fd, "* patching for revision: %s/%s\n", archive, revision); - - { - t_uchar * tmppatch = 0; - struct arch_apply_changeset_report r; - - tmppatch = tmp_file_name (dest_dir, ",,next-patch"); - arch_get_patch (arch, revision, tmppatch); - - mem_set0 ((t_uchar *)&r, sizeof (r)); - - arch_apply_changeset (&r, tmppatch, dest_dir, arch_unspecified_id_tagging, arch_inventory_unrecognized, 0, 0, 0, 0, 0, 0); - - if (arch_conflicts_occured (&r)) - panic ("conflict applying patch in arch_build_revision"); - - arch_free_apply_changeset_report_data (&r); - - rmrf_file (tmppatch); - lim_free (0, tmppatch); - } - - if (arch != prev_arch) - arch_archive_close (prev_arch); - - lim_free (0, prev_archive); - lim_free (0, prev_revision); } + arch_archive_close (my_arch); } - arch_snap_inode_sig (dest_dir, archive, revision); + if (answer!=0) // built + arch_snap_inode_sig (dest_dir, archive, revision); - lim_free (0, library_rev_dir); - arch_archive_close (my_arch); - return from_library; + return answer; } - +/* return non-0 if it came from a library. + */ +int +arch_build_revision (int chatter_fd, + const t_uchar * dest_dir, + struct arch_archive * arch, + const t_uchar * archive, + const t_uchar * revision, + const t_uchar * cache_dir) +{ + int answer = arch_build_revision_rec(chatter_fd, dest_dir, arch, archive, + revision, cache_dir, 0, 0, + -1, 0); + if (answer==0) + { + safe_printfmt (2, "arch_build_revision: fail to build: archive: %s\n revision: %s\n", + archive, revision); + exit (2); + } + return answer==2 ? 0 : 1; +} --- orig/libarch/build-revision.h +++ mod/libarch/build-revision.h @@ -13,9 +13,19 @@ #include "tla/libarch/archive.h" - /* automatically generated __STDC__ prototypes */ +extern int arch_build_revision_rec (int chatter_fd, + const t_uchar * dest_dir, + struct arch_archive * arch, + const t_uchar * archive, + const t_uchar * revision, + const t_uchar * cache_dir, + int hardlinks, + int escape_classes, + int limit, + int starting_effort); + extern int arch_build_revision (int chatter_fd, const t_uchar * dest_dir, struct arch_archive * arch, --- orig/libarch/cmd-commit.c +++ mod/libarch/cmd-commit.c @@ -20,6 +20,7 @@ #include "tla/libarch/cmd.h" #include "tla/libarch/editor.h" #include "tla/libarch/cmd-commit.h" +#include "tla/libarch/archive-cache.h" /* __STDC__ prototypes for static functions */ @@ -61,6 +62,8 @@ "log with TEXT plus log-for-merge output") \ OP (opt_strict, 0, "strict", 0, \ "strict tree-lint") \ + OP (opt_no_cacherev, 0, "no-cacherev", 0, \ + "Disable automatic cacherev") \ OP (opt_seal, 0, "seal", 0, \ "create a version-0 revision") \ OP (opt_fix, 0, "fix", 0, \ @@ -111,6 +114,8 @@ int strict = 0; int seal = 0; int fix = 0; + int no_cacherev = 0; + int cacherev = 0; int out_of_date_ok = 0; t_uchar * file_list_file = 0; int opt_end_with_double_dash = 0; @@ -187,6 +192,12 @@ break; } + case opt_no_cacherev: + { + no_cacherev = 1; + break; + } + case opt_strict: { strict = 1; @@ -434,6 +445,8 @@ { desired_level_type = arch_is_patch_level; desired_n = last_n + 1; + if (!no_cacherev) + cacherev = ((desired_n % arch_default_cachrev_penalty) == 0) ? 1 : 0; } break; } @@ -505,6 +518,15 @@ arch_commit (1, arch, revision, tree_root, log, file_list, escape_classes); + if ( cacherev) + { + safe_printfmt (1, "* Archive caching revision\n"); + safe_flush (1); + + arch_archive_cache (1, arch, archive, revision, tree_root); + safe_printfmt (1, "* Made cached revision of %s/%s \n", archive, revision); + } + safe_printfmt (1, "* committed %s/%s\n", archive, revision); if (log_file) --- orig/libarch/cmd-get.c +++ mod/libarch/cmd-get.c @@ -159,13 +159,11 @@ case opt_hardlinks: { hardlinks = 1; - no_pristine = 1; break; } case opt_library: { - no_pristine = 1; library = 1; break; } @@ -223,6 +221,7 @@ t_uchar * tmp_dir = 0; t_uchar *opt_same_dev_path = 0; struct arch_archive * arch = 0; + int answer; here_fd = safe_open (".", O_RDONLY, 0); @@ -343,7 +342,7 @@ tmp_dir = tmp_file_name (output_dir_dir, tmp_tail); rmrf_file (tmp_dir); - + if (!library && permit_greed) { /* Prefer a library entry over making a pristine tree, if there's @@ -368,39 +367,29 @@ arch_library_add (1, 1, arch, revision, selected_library, opt_same_dev_path, sparse, escape_classes); } - + /* make hardlinks or build-revision */ if (hardlinks) { - t_uchar * revision_dir = 0; - rel_table index = rel_table_nil; - int full_meta; - - index = arch_library_index (archive, revision); - rel_sort_table_by_field (0, index, 0); - safe_printfmt (1, "* hard linking to library\n"); safe_flush (1); - - revision_dir = arch_library_find (rel_table_nil, archive, revision, 1); - invariant (0 != revision_dir); - full_meta = arch_tree_has_meta_flag (revision_dir); - - build_partial_link_tree (arch_library_find (rel_table_nil, archive, revision, 1), tmp_dir, index, full_meta); - arch_snap_inode_sig (tmp_dir, archive, revision); - - lim_free (0, revision_dir); } - else + + safe_mkdir (tmp_dir, 0777); + answer = arch_build_revision_rec ((silent ? -1 : 1), tmp_dir, + arch, archive, revision, cache_dir, + hardlinks, 0, -1, 0); + if (answer==0) { - safe_mkdir (tmp_dir, 0777); - no_pristine = arch_build_revision ((silent ? -1 : 1), tmp_dir, arch, archive, revision, cache_dir); + safe_printfmt (2, "%s: fail to get: archive: %s\n revision: %s\n", + argv[0], archive, revision); + exit (2); } arch_archive_close (arch); - if (!no_pristine) + if (!no_pristine && answer==2) // not from a library and no_pristine==0 { if (!silent) { --- orig/libarch/library-txn.c +++ mod/libarch/library-txn.c @@ -375,189 +375,36 @@ ensure_directory_exists (dest_dir_dir); tmp_dir = tmp_file_name (dest_dir_dir, ",,new-revision"); - if (library_ancestor) + /* There is an ancestor, it's in the same archive, it's not + * in the library, and we're not building a --sparse library. + * So, recursively add the ancestor to the library and then + * build it + */ + if (!library_ancestor && fq_ancestor_rev && + !str_cmp (ancestor_archive, arch->name) && !sparse) { - const int full_meta = arch_tree_has_meta_flag (library_ancestor); - - /* If the immediate ancestor exists in the same library, - * then fill our tmp dir with a link-tree to that ancestor. - * It will be patched for our target revision later. - */ - - arch_chatter (chatter_fd, "* found immediate ancestor revision in library (%s/%s)\n", ancestor_archive, ancestor_revision); - build_link_tree (library_ancestor, tmp_dir, full_meta); + arch_chatter (chatter_fd, "* recursively adding %s/%s to library\n", ancestor_archive, ancestor_revision); + arch_library_add (chatter_fd, no_patch_noise, arch, ancestor_revision, opt_library, opt_same_dev_path, 0, escape_classes); } - else if (!fq_ancestor_rev || str_cmp (ancestor_archive, arch->name)) - { - /* If there is no immediate ancestor (we're trying to build - * an import revision) or if the ancestor is in some other archive, - * fill the tmp-dir with the target revision just by building - * it from scratch. - * - * There's no need to further patch the tmp-dir after that. - */ - - safe_mkdir (tmp_dir, 0777); - arch_build_revision (chatter_fd, tmp_dir, arch, arch->name, revision, 0); - - patch_set_dir = file_name_in_vicinity (0, tmp_dir, ",,patch-set"); - rmrf_file (patch_set_dir); - - if (fq_ancestor_rev) - { - arch_get_patch (arch, revision, patch_set_dir); - } - else - { - safe_mkdir (patch_set_dir, 0777); - } - goto no_need_to_patch; - } - else if (!sparse) + /* Build the current version with hardlink if possible */ + safe_mkdir (tmp_dir, 0777); + arch_build_revision_rec (chatter_fd, tmp_dir, + arch, arch->name, revision, 0, + 1, escape_classes, -1, 0); + + patch_set_dir = file_name_in_vicinity (0, tmp_dir, ",,patch-set"); + rmrf_file (patch_set_dir); + + if (fq_ancestor_rev) { - const int full_meta = arch_tree_has_meta_flag (library_ancestor); - - /* There is an ancestor, it's in the same archive, it's not - * in the library, and we're not building a --sparse library. - * So, recursively add the ancestor to the library and then - * build a link-tree into tmp-dir. We'll patch tmp-dir to the - * target revision later. - */ - arch_chatter (chatter_fd, "* recursively adding %s/%s to library\n", ancestor_archive, ancestor_revision); - arch_library_add (chatter_fd, no_patch_noise, arch, ancestor_revision, opt_library, opt_same_dev_path, 0, escape_classes); - library_ancestor = arch_library_find (rel_table_nil, ancestor_archive, ancestor_revision, 1); - build_link_tree (library_ancestor, tmp_dir, full_meta); + arch_get_patch (arch, revision, patch_set_dir); } else { - /* There is an ancestor, it's in the same archive, it's - * not in the library, but we're building a --sparse library. - * - * If some _earlier_ ancestor is at hand, link to that and then - * patch. Otherwise, build the target revision from scratch. - * - * Either way, at the end, tmp-dir will have the target revision - * and there's no need to further patch it. - */ - t_uchar * anc_arch = str_save (0, ancestor_archive); - t_uchar * anc_rev = str_save (0, ancestor_revision); - t_uchar * anc_lib = 0; - int replay_status = 1; - /* list of patches to apply to revision in library to achieve new revision - */ - rel_table revisions = rel_table_nil; - - /* this is the first patch missing - */ - rel_add_records (&revisions, rel_singleton_record_taking (rel_make_field_str (revision)), rel_record_null); - - arch_chatter (chatter_fd, "* searching ancestor revision in library in archive %s\n", ancestor_archive); - - /* search backwards in the library for a revision to link to - */ - while (anc_rev && !anc_lib) - { - t_uchar * fq_anc_rev = 0; - t_uchar * prev_rev = 0; - - /* add revision to list - */ - - rel_add_records (&revisions, rel_singleton_record_taking (rel_make_field_str (anc_rev)), rel_record_null); - - /* look in the library for the immediate ancestor - */ - fq_anc_rev = arch_ancestor_revision (arch, anc_rev); - - if (fq_anc_rev) - { - lim_free (0, anc_arch); - lim_free (0, anc_rev); - - anc_arch = arch_parse_package_name (arch_ret_archive, 0, fq_anc_rev); - anc_rev = arch_parse_package_name (arch_ret_non_archive, 0, fq_anc_rev); - anc_lib = arch_library_find (rel_table_nil, anc_arch, anc_rev, 1); - } - - if (!fq_anc_rev || str_cmp (anc_arch, arch->name)) - { - /* no ancestor in the same archive - */ - arch_chatter (chatter_fd, "* no ancestor in library for revision %s/%s in the same archive\n", anc_arch, revision); - lim_free (0, fq_anc_rev); - lim_free (0, prev_rev); - break; - } - - lim_free (0, fq_anc_rev); - lim_free (0, prev_rev); - } - - /* let's patch the found revision in the library up to the needed revision - */ - if (anc_lib) - { - const int full_meta = arch_tree_has_meta_flag (anc_lib); - arch_chatter (chatter_fd, "* found ancestor revision in library (%s/%s)\n", anc_arch, anc_rev); - arch_chatter (chatter_fd, "* patching for this revision (%s/%s)\n", ancestor_archive, revision); - build_link_tree (anc_lib, tmp_dir, full_meta); - rel_reverse_table (revisions); - replay_status = arch_replay_list (chatter_fd, 1, tmp_dir, arch, revisions, 0, 0, escape_classes); - invariant (!replay_status); - lim_free (0, anc_lib); - } - else - { - /* otherwise (1st revision in library) build the revision from scratch - */ - safe_mkdir (tmp_dir, 0777); - arch_build_revision (chatter_fd, tmp_dir, arch, arch->name, revision, 0); - } - - /* keep last patchset inside revision - */ - patch_set_dir = file_name_in_vicinity (0, tmp_dir, ",,patch-set"); - rmrf_file (patch_set_dir); - arch_get_patch (arch, revision, patch_set_dir); - - lim_free (0, anc_arch); - lim_free (0, anc_rev); - rel_free_table (revisions); - goto no_need_to_patch; + safe_mkdir (patch_set_dir, 0777); } - - /* This is reached only if we have one-last patch to make to - * tmp-dir to achieve the target revision. - * - * If tmp-dir already has the target, then we `goto no_need_to_patch', - * below. - */ - - patch_set_dir = file_name_in_vicinity (0, tmp_dir, ",,patch-set"); - rmrf_file (patch_set_dir); - arch_get_patch (arch, revision, patch_set_dir); - - { - struct arch_apply_changeset_report report = {0,}; - - arch_chatter (chatter_fd, "* patching for this revision (%s/%s)\n", arch->name, revision); - - if ((chatter_fd >= 0) && !no_patch_noise) - { - report.callback = library_txn_callback; - report.thunk = (void *)(long)chatter_fd; - } - - arch_apply_changeset (&report, patch_set_dir, tmp_dir, arch_unspecified_id_tagging, arch_inventory_unrecognized, 0, 0, 0, 0, 0, escape_classes); - invariant (!arch_conflicts_occured (&report)); - - arch_free_apply_changeset_report_data (&report); - } - - no_need_to_patch: - /* Finish up adding ancillary files to the tmp-dir and then * install it in the library. */ _______________________________________________ Gnu-arch-users mailing list Gnu-arch-users@gnu.org http://lists.gnu.org/mailman/listinfo/gnu-arch-users GNU arch home page: http://savannah.gnu.org/projects/gnu-arch/