# # add_file "tests/t_bad_packets.at" # # add_file "tests/t_inodeprints_hook.at" # # patch "ChangeLog" # from [ad815709db8896a9323a4ffd2f1ee711529bf5b0] # to [fa1d4b7e493828ddd605f870b1a85588d644a1ea] # # patch "app_state.cc" # from [715d0beb6780ce3ea77b0934ceb4f5a4fbc0293b] # to [a7ed8e649668aca70e915e9071469219ecf9db75] # # patch "commands.cc" # from [588e56b9de4a9ff6e0146177ed642787db7b64a2] # to [6536a5fec8f4c742203ff8b03081b958c2b44be3] # # patch "lua.cc" # from [ee8e38e41928d17b8903309f71265e859443c43e] # to [324daba07afed4fccaa12d4c7bab4f02d744e705] # # patch "lua.hh" # from [9e6604ebd9285f905820bd95e92fb68c402807ce] # to [5e22c1d5555fc59e29b639fdec14696f3804feca] # # patch "monotone.texi" # from [66422aaa133c5bdab836f44a592cee17421004aa] # to [7eeb1754841491852c6101dddadee3d1435a85d6] # # patch "std_hooks.lua" # from [245cf5ff0a0858e6436cc1d44bbba982f0afbc6f] # to [d9f8c4acffb845da040ee403b42bf4d1dad79d5b] # # patch "tests/t_bad_packets.at" # from [] # to [2f4b3f6509ae0d401eff37a7d6a6fae327779a21] # # patch "tests/t_inodeprints_hook.at" # from [] # to [7a63f3be8cd9f0f003ffe3b0372e9c4d33fcc034] # # patch "testsuite.at" # from [9caba90d174e7b550907e836847f65dca5ee502e] # to [4e74e752f40c74925d7279cf87626cfbc66cb726] # # patch "work.cc" # from [1b1687d4db3d2daf7748b642d52c5fa844c251a9] # to [168c7482e944a7fc1c8b70b72615f8312a3a31bd] # # patch "work.hh" # from [1e96bd36f787031f743d29cc033bfd1cc1a9c8e2] # to [41939ab23e00e777cc07da3df1b31a74082c0ae8] # --- ChangeLog +++ ChangeLog @@ -1,5 +1,23 @@ 2005-04-20 Nathaniel Smith + * commands.cc (mdelta, mdata, fdelta, fdata, rdata): Check for + existence of command line arguments. + + * lua.{cc,hh} (hook_use_inodeprints): New hook. + * std_hooks.lua (use_inodeprints): Default definition. + * monotone.texi (Inodeprints): New section. + (Reserved Files): Document MT/inodeprints. + (Hook Reference): Document use_inodeprints. + * work.{cc,hh} (enable_inodeprints): New function. + * app_state.cc (create_working_copy): Maybe call + enable_inodeprints. + + * tests/t_inodeprints_hook.at: New test. + * tests/t_bad_packets.at: New test. + * testsuite.at: Add them. + +2005-04-20 Nathaniel Smith + * AUTHORS: Actually add Joel Reed (oops). 2005-04-20 Nathaniel Smith --- app_state.cc +++ app_state.cc @@ -139,6 +139,9 @@ blank_user_log(); + if (lua.hook_use_inodeprints()) + enable_inodeprints(); + load_rcfiles(); } --- commands.cc +++ commands.cc @@ -2126,7 +2126,9 @@ complete(app, idx(args, 0)(), m_old_id); complete(app, idx(args, 1)(), m_new_id); + N(app.db.manifest_version_exists(m_old_id), F("no such manifest %s") % m_old_id); app.db.get_manifest(m_old_id, m_old); + N(app.db.manifest_version_exists(m_new_id), F("no such manifest %s") % m_new_id); app.db.get_manifest(m_new_id, m_new); delta del; @@ -2148,7 +2150,9 @@ complete(app, idx(args, 0)(), f_old_id); complete(app, idx(args, 1)(), f_new_id); + N(app.db.file_version_exists(f_old_id), F("no such file %s") % f_old_id); app.db.get_file_version(f_old_id, f_old_data); + N(app.db.file_version_exists(f_new_id), F("no such file %s") % f_new_id); app.db.get_file_version(f_new_id, f_new_data); delta del; diff(f_old_data.inner(), f_new_data.inner(), del); @@ -2167,6 +2171,7 @@ complete(app, idx(args, 0)(), r_id); + N(app.db.revision_exists(r_id), F("no such revision %s") % r_id); app.db.get_revision(r_id, r_data); pw.consume_revision_data(r_id, r_data); } @@ -2183,6 +2188,7 @@ complete(app, idx(args, 0)(), m_id); + N(app.db.manifest_version_exists(m_id), F("no such manifest %s") % m_id); app.db.get_manifest_version(m_id, m_data); pw.consume_manifest_data(m_id, m_data); } @@ -2200,6 +2206,7 @@ complete(app, idx(args, 0)(), f_id); + N(app.db.file_version_exists(f_id), F("no such file %s") % f_id); app.db.get_file_version(f_id, f_data); pw.consume_file_data(f_id, f_data); } --- lua.cc +++ lua.cc @@ -883,6 +883,20 @@ } +bool +lua_hooks::hook_use_inodeprints() +{ + bool use = false, exec_ok = false; + + exec_ok = Lua(st) + .push_str("use_inodeprints") + .get_fn() + .call(0, 1) + .extract_bool(use) + .ok(); + return use && exec_ok; +} + bool lua_hooks::hook_get_netsync_read_permitted(std::string const & collection, rsa_keypair_id const & identity) --- lua.hh +++ lua.hh @@ -94,6 +94,9 @@ file_path const & b, file_path & res); + // working copy hooks + bool hook_use_inodeprints(); + // attribute hooks bool hook_init_attributes(file_path const & filename, std::map & attrs); --- monotone.texi +++ monotone.texi @@ -2220,6 +2220,7 @@ * Selectors:: Selecting revisions by certificate. * Restrictions:: Limit working copy changes to specified files. * Scripting:: Running monotone from other programs. +* Inodeprints:: Trading off safety for speed in your working copy. * Quality Assurance:: Integrating testing and review with development. * Vars:: Simple per-database configuration information. * Reserved Files:: File names with special meanings. @@ -2445,6 +2446,43 @@ For details of this interface, see @ref{Automation}. @page address@hidden Inodeprints address@hidden Inodeprints + +Fairly often, in order to accomplish its job, monotone has to look at +your working copy and figure out what has been changed in it since your +last commit. Commands that do this include @command{status}, address@hidden, @command{update}, @command{commit}, and others. There +are two different techniques it can use to do this. The default, which +is sufficient for most projects, is to simply read every file in the +working copy, compute their @sc{sha1} hash, and compare them to the +hashes monotone has stored. This is very safe and reliable, and turns +out to be fast enough for most projects. However, on very large +projects, ones whose source trees are many megabytes in size, it can +become unacceptably slow. + +The other technique, known as @emph{inodeprints}, is designed for this +situation. When running in inodeprints mode, monotone does not read the +whole working copy; rather, it keeps a cache of interesting information +about each file (its size, its last modification time, and so on), and +skips reading any file for which these values have not changed. This is +inherently somewhat less safe, and, as mentioned above, unnecessary for +most projects, so it is disabled by default. + +If you do determine that it is necessary to use inodeprints with your +project, it is simple to enable them. A working copy is in inodeprints +mode if a file @file{MT/inodeprints} exist. You can simply create an +empty file with this name, and the next time you commit or update, +monotone will automatically populate it with cache information. You can +at any point delete this file or truncate it; monotone uses it only as a +cache and will operate correctly if it is removed. + +Normally, instead of enabling this up on a per-working-copy basis, you +will want to simply define the @code{use_inodeprints} hook to return address@hidden; this will automatically enable inodeprints mode in any new +working copies you create. See @ref{Hook Reference} for details. + address@hidden @node Quality Assurance @section Quality Assurance @@ -2628,6 +2666,9 @@ commit. The user may add content to this file while they work. Upon a successful commit monotone will empty the file making it ready for the next edit/commit cycle. address@hidden MT/inodeprints +If this file exists, monotone considers the directory to be in address@hidden mode, and uses this file to cache the inodeprints. @item MT/debug If monotone detects a bug in itself or crashes, then before exiting it dumps a log of its recent activity to this file, to aid in debugging. @@ -4661,6 +4702,22 @@ @end smallexample address@hidden use_inodeprints () + +Returns @code{true} if you want monotone to automatically enable address@hidden support in all working copies. Only affects working +copies created after you modify the hook. + +The default definition of this hook is: address@hidden address@hidden +function use_inodeprints() + return false +end address@hidden group address@hidden smallexample + + @item get_netsync_read_permitted (@var{collection}, @var{identity}) Returns @code{true} if a peer authenticated as key @var{identity} --- std_hooks.lua +++ std_hooks.lua @@ -433,3 +433,7 @@ return nil end + +function use_inodeprints() + return false +end --- tests/t_bad_packets.at +++ tests/t_bad_packets.at @@ -0,0 +1,15 @@ +AT_SETUP([bad packet args]) +MONOTONE_SETUP + +AT_CHECK(MONOTONE mdelta 73070030f7b0d0f3d4ee02545d45ca4bbe5e189f 6c704fbd4ef58f2447fd1a3e76911b2ebe97dc77, [1], [ignore], [ignore]) +AT_CHECK(MONOTONE mdata 73070030f7b0d0f3d4ee02545d45ca4bbe5e189f, [1], [ignore], [ignore]) +AT_CHECK(MONOTONE fdelta 73070030f7b0d0f3d4ee02545d45ca4bbe5e189f 6c704fbd4ef58f2447fd1a3e76911b2ebe97dc77, [1], [ignore], [ignore]) +AT_CHECK(MONOTONE fdata 73070030f7b0d0f3d4ee02545d45ca4bbe5e189f, [1], [ignore], [ignore]) +AT_CHECK(MONOTONE rdata 73070030f7b0d0f3d4ee02545d45ca4bbe5e189f, [1], [ignore], [ignore]) +AT_CHECK(MONOTONE pubkey address@hidden, [1], [ignore], [ignore]) +AT_CHECK(MONOTONE privkey address@hidden, [1], [ignore], [ignore]) + +# This one should succeed, but print nothing. +AT_CHECK(MONOTONE certs 73070030f7b0d0f3d4ee02545d45ca4bbe5e189f, [], [], [ignore]) + +AT_CLEANUP --- tests/t_inodeprints_hook.at +++ tests/t_inodeprints_hook.at @@ -0,0 +1,38 @@ +AT_SETUP([use_inodeprints hook]) +MONOTONE_SETUP + +AT_DATA(on.lua, [ +function use_inodeprints() + return true +end +]) + +AT_DATA(off.lua, [ +function use_inodeprints() + return false +end +]) + +AT_CHECK(test ! -e MT/inodeprints) +ADD_FILE(testfile, [blah blah +]) +COMMIT(testbranch) +REV=`BASE_REVISION` + +AT_CHECK(MONOTONE setup setup_default, [], [ignore], [ignore]) +AT_CHECK(test ! -e setup_default/MT/inodeprints) +AT_CHECK(MONOTONE checkout $REV co_default, [], [ignore], [ignore]) +AT_CHECK(test ! -e co_default/MT/inodeprints) + +AT_CHECK(MONOTONE --rcfile=off.lua setup setup_off, [], [ignore], [ignore]) +AT_CHECK(test ! -e setup_off/MT/inodeprints) +AT_CHECK(MONOTONE --rcfile=off.lua checkout $REV co_off, [], [ignore], [ignore]) +AT_CHECK(test ! -e co_off/MT/inodeprints) + +AT_CHECK(MONOTONE --rcfile=on.lua setup setup_on, [], [ignore], [ignore]) +AT_CHECK(test -e setup_on/MT/inodeprints) +AT_CHECK(MONOTONE --rcfile=on.lua checkout $REV co_on, [], [ignore], [ignore]) +AT_CHECK(test -e co_on/MT/inodeprints) +AT_CHECK(test -s co_on/MT/inodeprints) + +AT_CLEANUP --- testsuite.at +++ testsuite.at @@ -572,3 +572,5 @@ m4_include(tests/t_log_depth_single.at) m4_include(tests/t_attr_init.at) m4_include(tests/t_add_executable.at) +m4_include(tests/t_inodeprints_hook.at) +m4_include(tests/t_bad_packets.at) --- work.cc +++ work.cc @@ -378,6 +378,15 @@ write_data(ip_path, dat); } +void +enable_inodeprints() +{ + local_path ip_path; + get_inodeprints_path(ip_path); + data dat; + write_data(ip_path, dat); +} + // attribute map file string const attr_file_name(".mt-attrs"); --- work.hh +++ work.hh @@ -114,6 +114,8 @@ void write_inodeprints(data const & dat); +void enable_inodeprints(); + // the "attribute map" is part of a working copy. it is *not* stored in MT, // because its contents are considered part of the "content" of a tree of // files. it is therefore stored in .mt-attrs, in the root of your