[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnu-arch-users] patch: automatic cacherev and smarter get
From: |
Derek Zhou |
Subject: |
[Gnu-arch-users] patch: automatic cacherev and smarter get |
Date: |
Tue, 22 Nov 2005 13:49:18 -0800 |
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 address@hidden/tla--derek-no-pristines--1.3--base-0 to compare
with
* comparing to address@hidden/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] patch: automatic cacherev and smarter get,
Derek Zhou <=
- Re: [Gnu-arch-users] patch: automatic cacherev and smarter get, Mikhael Goikhman, 2005/11/22
- Re: [Gnu-arch-users] patch: automatic cacherev and smarter get, Andrew Suffield, 2005/11/23
- Re: [Gnu-arch-users] patch: automatic cacherev and smarter get, Alfred M\. Szmidt, 2005/11/23
- Re: [Gnu-arch-users] patch: automatic cacherev and smarter get, Andrew Suffield, 2005/11/23
- Re: [Gnu-arch-users] patch: automatic cacherev and smarter get, Mikhael Goikhman, 2005/11/23
- [Gnu-arch-users] Re: patch: automatic cacherev and smarter get, Matthieu Moy, 2005/11/23
- Re: [Gnu-arch-users] patch: automatic cacherev and smarter get, Andrew Suffield, 2005/11/25
- Re: [Gnu-arch-users] patch: automatic cacherev and smarter get, Matthew Hannigan, 2005/11/25