# # patch "app_state.cc" # from [7fb51954421323439c2f12876ed81b71e7eaf634] # to [55b5ec36dc4de179a4293cc1b3a4af5d548528dd] # # patch "automate.cc" # from [073d5883f4506ee0da368c9a1f9c3685f528a1e4] # to [e15a4769643c342098932ebec2a689a4b7e33d4d] # # patch "manifest.cc" # from [3b2650b112fe4a1689397e1dc504d0f4904c0e08] # to [61c9623150c902da0dc9d29cdd18175114382e6b] # # patch "manifest.hh" # from [2af22b3415d9ef59fbf687d1f2e3ae2bb6e38701] # to [7256376905b4161910893bbbdc9e83bd6ab3f9d8] # # patch "paths.cc" # from [6fe0bd93f244fba831107a018310d4963fe5f17c] # to [b2e0c5b32c2e2b37e6051a23fc50f58b79fdced2] # # patch "paths.hh" # from [b019e9708f84baea6625e9554f0d79969dd18051] # to [6ae0e9e03232b0919c62bf80814e8d10c7b15883] # # patch "restrictions.cc" # from [3663fae6770f27150282915b8adc94332dd5d870] # to [796355f19d1f74c8080da8ea37bed01a3fd9c6b0] # # patch "restrictions.hh" # from [ab5ee1c29bdfd409847f5d9f369de9a69f2795b7] # to [edac33b08225c94ec8cdee860aece9d2fb05c68f] # # patch "roster.cc" # from [5879cd218111c8aff91974a36fc726a7fd2ed78f] # to [74b027c27b8f4dfa1d19ed2e9971273cbd173054] # # patch "roster.hh" # from [bfe4af746e5615b2b419fd8a2501ce96649c4a5e] # to [356168d5db89209841dfafc57a7b47fc708a9753] # # patch "work.cc" # from [ee202edbc9284547d8ecd4bdbb9c45430de7bdf4] # to [a0ff264fdddfaa222eaa72a6bd70aa6a6801fc65] # # patch "work.hh" # from [f7b39329a294dbcf5371fcea21bfead980d371f6] # to [e69fe80720ad44a1b9079de769cbd9075db1d2ac] # ======================================================================== --- app_state.cc 7fb51954421323439c2f12876ed81b71e7eaf634 +++ app_state.cc 55b5ec36dc4de179a4293cc1b3a4af5d548528dd @@ -123,12 +123,18 @@ vector const & paths, bool respect_ignore) { + // FIXME: this was written before split_path, and only later kludged to + // work with it. Could be much tidier if written with knowledge of + // split_path. + static file_path root = file_path_internal(""); restrictions.clear(); excludes.clear(); for (vector::const_iterator i = paths.begin(); i != paths.end(); ++i) { file_path p = file_path_external(*i); + split_path sp; + p.split(sp); if (respect_ignore && lua.hook_ignore_file(p)) { @@ -136,17 +142,19 @@ continue; } - N(p == root || valid_paths.find(p) != valid_paths.end(), + N(p == root || valid_paths.find(sp) != valid_paths.end(), F("unknown path '%s'\n") % p); L(F("'%s' added to restricted path set\n") % p); - restrictions.insert(p); + restrictions.insert(sp); } for (std::set::const_iterator i = exclude_patterns.begin(); i != exclude_patterns.end(); ++i) { file_path p = file_path_external(*i); + split_path sp; + p.split(sp); if (respect_ignore && lua.hook_ignore_file(p)) { @@ -154,31 +162,40 @@ continue; } - N(p == root || valid_paths.find(p) != valid_paths.end(), + N(p == root || valid_paths.find(sp) != valid_paths.end(), F("unknown path '%s'\n") % p); L(F("'%s' added to excluded path set\n") % p); - excludes.insert(p); + excludes.insert(sp); } // if user supplied a depth but provided no paths // assume current directory if ((depth != -1) && restrictions.empty()) { - restrictions.insert(file_path_external(utf8("."))); + file_path fp = file_path_external(utf8(".")); + split_path sp; + fp.split(sp); + restrictions.insert(sp); } } bool app_state::restriction_includes(file_path const & path) { + // FIXME: this was written before split_path, and only later kludged to + // work with it. Could be much tidier if written with knowledge of + // split_path. + static file_path root = file_path_internal(""); + split_path sp_root; + root.split(sp_root); if (restrictions.empty()) { if (!excludes.empty()) { - if (excludes.find(root) != excludes.end()) + if (excludes.find(sp_root) != excludes.end()) return false; fs::path test = fs::path(path.as_external(), fs::native); @@ -187,7 +204,9 @@ L(F("checking excluded path set for '%s'\n") % test.string()); file_path p = file_path_internal(test.string()); - path_set::const_iterator i = excludes.find(p); + split_path sp; + p.split(sp); + path_set::const_iterator i = excludes.find(sp); if (i != excludes.end()) { @@ -213,8 +232,10 @@ L(F("checking restricted path set for '%s'\n") % test.string()); file_path p = file_path_internal(test.string()); - path_set::const_iterator i = restrictions.find(p); - path_set::const_iterator j = excludes.find(p); + split_path sp; + p.split(sp); + path_set::const_iterator i = restrictions.find(sp); + path_set::const_iterator j = excludes.find(sp); if (i != restrictions.end()) { @@ -238,7 +259,7 @@ // essentially cleared (all files are included). rather than be // careful about what goes in to the restricted path set we just // check for this special case here. - if (restrictions.find(root) != restrictions.end()) + if (restrictions.find(sp_root) != restrictions.end()) { return (!user_supplied_depth) || (branch_depth <= max_depth); } ======================================================================== --- automate.cc 073d5883f4506ee0da368c9a1f9c3685f528a1e4 +++ automate.cc e15a4769643c342098932ebec2a689a4b7e33d4d @@ -556,7 +556,8 @@ { for (path_set::const_iterator i = paths.begin(); i != paths.end(); i++) { - L(F("%d %d %s\n") % inventory[*i].pre_state % pre_state % *i); + file_path fp(*i); + L(F("%d %d %s\n") % inventory[*i].pre_state % pre_state % fp); I(inventory[*i].pre_state == inventory_item::KNOWN_PATH); inventory[*i].pre_state = pre_state; inventory[*i].path_type = path_type; @@ -577,7 +578,8 @@ { for (path_set::const_iterator i = paths.begin(); i != paths.end(); i++) { - L(F("%d %d %s\n") % inventory[*i].post_state % post_state % *i); + file_path fp(*i); + L(F("%d %d %s\n") % inventory[*i].post_state % post_state % fp); I(inventory[*i].post_state == inventory_item::KNOWN_PATH); inventory[*i].post_state = post_state; inventory[*i].path_type = path_type; @@ -596,7 +598,8 @@ { for (path_set::const_iterator i = paths.begin(); i != paths.end(); i++) { - L(F("%d %d %s\n") % inventory[*i].file_state % file_state % *i); + file_path fp(*i); + L(F("%d %d %s\n") % inventory[*i].file_state % file_state % fp); I(inventory[*i].file_state == inventory_item::KNOWN_FILE); inventory[*i].file_state = file_state; } @@ -615,8 +618,11 @@ for (std::map::const_iterator i = renames.begin(); i != renames.end(); i++) { - old_name.insert(i->first); - new_name.insert(i->second); + split_path sp1, sp2; + i->first.split(sp1); + i->second.split(sp2); + old_name.insert(sp1); + new_name.insert(sp2); inventory_pre_state(inventory, old_name, inventory_item::RENAMED_PATH, id, path_type); inventory_post_state(inventory, new_name, inventory_item::RENAMED_PATH, id, path_type); ======================================================================== --- manifest.cc 3b2650b112fe4a1689397e1dc504d0f4904c0e08 +++ manifest.cc 61c9623150c902da0dc9d29cdd18175114382e6b @@ -20,6 +20,7 @@ #include "transforms.hh" #include "sanity.hh" #include "inodeprint.hh" +#include "paths.hh" #include "platform.hh" #include "constants.hh" @@ -57,15 +58,6 @@ man.insert(manifest_entry(path, file_id(ident))); } -void -extract_path_set(manifest_map const & man, path_set & paths) -{ - paths.clear(); - for (manifest_map::const_iterator i = man.begin(); - i != man.end(); ++i) - paths.insert(manifest_entry_path(i)); -} - inline static bool inodeprint_unchanged(inodeprint_map const & ipm, file_path const & path) { @@ -103,6 +95,9 @@ for (manifest_map::const_iterator i = man.begin(); i != man.end(); ++i) { + split_path sp; + i->first.split(sp); + if (app.restriction_includes(i->first)) { // compute the current sha1 id for included files @@ -113,7 +108,7 @@ // hasn't either. manifest_map::const_iterator k = man.find(i->first); I(k != man.end()); - unchanged.insert(i->first); + unchanged.insert(sp); continue; } @@ -122,20 +117,20 @@ if (ident_existing_file(i->first, ident, app.lua)) { if (ident == i->second) - unchanged.insert(i->first); + unchanged.insert(sp); else - changed.insert(i->first); + changed.insert(sp); } else { - missing.insert(i->first); + missing.insert(sp); } } else { // changes to excluded files are ignored - unchanged.insert(i->first); + unchanged.insert(sp); } } } @@ -185,7 +180,8 @@ } else { - W(F("missing %s") % (*i)); + file_path fp(*i); + W(F("missing %s") % fp); missing_files++; } } ======================================================================== --- manifest.hh 2af22b3415d9ef59fbf687d1f2e3ae2bb6e38701 +++ manifest.hh 7256376905b4161910893bbbdc9e83bd6ab3f9d8 @@ -39,8 +39,6 @@ // have only one entry for each pathname. the same sha1 can occur multiple // times in a manifest. -typedef std::set path_set; - typedef std::pair manifest_entry; typedef std::map path_set; + #endif ======================================================================== --- restrictions.cc 3663fae6770f27150282915b8adc94332dd5d870 +++ restrictions.cc 796355f19d1f74c8080da8ea37bed01a3fd9c6b0 @@ -11,48 +11,28 @@ #include "restrictions.hh" #include "revision.hh" #include "transforms.hh" -/* -// FIXME_ROSTERS: disabled until rewritten to use rosters void -extract_rearranged_paths(change_set::path_rearrangement const & rearrangement, path_set & paths) +extract_rearranged_paths(cset const & cs, path_set & paths) { - paths.insert(rearrangement.deleted_files.begin(), rearrangement.deleted_files.end()); - paths.insert(rearrangement.deleted_dirs.begin(), rearrangement.deleted_dirs.end()); + paths.insert(cs.nodes_deleted.begin(), cs.nodes_deleted.end()); + paths.insert(cs.dirs_added.begin(), cs.dirs_added.end()); - for (std::map::const_iterator i = rearrangement.renamed_files.begin(); - i != rearrangement.renamed_files.end(); ++i) + for (std::map::const_iterator i = cs.files_added.begin(); + i != cs.files_added.end(); ++i) { - paths.insert(i->first); - paths.insert(i->second); + paths.insert(i->first); } - for (std::map::const_iterator i = rearrangement.renamed_dirs.begin(); - i != rearrangement.renamed_dirs.end(); ++i) + for (std::map::const_iterator i = cs.nodes_renamed.begin(); + i != cs.nodes_renamed.end(); ++i) { paths.insert(i->first); paths.insert(i->second); } - - paths.insert(rearrangement.added_files.begin(), rearrangement.added_files.end()); } -static void -extract_delta_paths(change_set::delta_map const & deltas, path_set & paths) -{ - for (change_set::delta_map::const_iterator i = deltas.begin(); i != deltas.end(); ++i) - { - paths.insert(i->first); - } -} -static void -extract_changed_paths(change_set const & cs, path_set & paths) -{ - extract_rearranged_paths(cs.rearrangement, paths); - extract_delta_paths(cs.deltas, paths); -} - void add_intermediate_paths(path_set & paths) { @@ -60,204 +40,222 @@ for (path_set::const_iterator i = paths.begin(); i != paths.end(); ++i) { - // we know that file_path's are normalized relative paths. So we can - // find intermediate paths simply by searching for /. - std::string::size_type j = std::string::npos; - while ((j = (*i).as_internal().rfind('/', j)) != std::string::npos) + split_path sp; + for (split_path::const_iterator j = i->begin(); j != i->end(); ++j) { - file_path dir = file_path_internal((*i).as_internal().substr(0, j)); - if (intermediate_paths.find(dir) != intermediate_paths.end()) break; - if (paths.find(dir) != paths.end()) break; - intermediate_paths.insert(dir); - --j; + sp.push_back(*j); + intermediate_paths.insert(sp); } } - paths.insert(intermediate_paths.begin(), intermediate_paths.end()); } +void +restrict_cset(cset const & cs, + cset & included, + cset & excluded, + app_state & app) +{ + for (std::set::const_iterator i = cs.nodes_deleted.begin(); + i != cs.nodes_deleted.end(); ++i) + { + if (app.restriction_includes(*i)) + included.nodes_deleted.insert(*i); + else + excluded.nodes_deleted.insert(*i); + } -static void -restrict_path_set(std::string const & type, - path_set const & paths, - path_set & included, - path_set & excluded, - app_state & app) -{ - for (path_set::const_iterator i = paths.begin(); i != paths.end(); ++i) + for (std::map::const_iterator i = cs.nodes_renamed.begin(); + i != cs.nodes_renamed.end(); ++i) { + if (app.restriction_includes(i->first) || + app.restriction_includes(i->second)) + included.nodes_renamed.insert(*i); + else + excluded.nodes_renamed.insert(*i); + } + + for (std::set::const_iterator i = cs.dirs_added.begin(); + i != cs.dirs_added.end(); ++i) + { if (app.restriction_includes(*i)) - { - L(F("restriction includes %s %s\n") % type % *i); - included.insert(*i); - } + included.dirs_added.insert(*i); else - { - L(F("restriction excludes %s %s\n") % type % *i); - excluded.insert(*i); - } + excluded.dirs_added.insert(*i); } -} -static void -restrict_rename_set(std::string const & type, - std::map const & renames, - std::map & included, - std::map & excluded, - app_state & app) -{ - for (std::map::const_iterator i = renames.begin(); - i != renames.end(); ++i) + for (std::map::const_iterator i = cs.files_added.begin(); + i != cs.files_added.end(); ++i) { - // include renames if either source or target name is included in the restriction - if (app.restriction_includes(i->first) || app.restriction_includes(i->second)) - { - L(F("restriction includes %s '%s' to '%s'\n") % type % i->first % i->second); - included.insert(*i); - } + if (app.restriction_includes(i->first)) + included.files_added.insert(*i); else - { - L(F("restriction excludes %s '%s' to '%s'\n") % type % i->first % i->second); - excluded.insert(*i); - } + excluded.files_added.insert(*i); } -} -void -restrict_path_rearrangement(change_set::path_rearrangement const & work, - change_set::path_rearrangement & included, - change_set::path_rearrangement & excluded, - app_state & app) -{ - restrict_path_set("delete file", work.deleted_files, - included.deleted_files, excluded.deleted_files, app); - restrict_path_set("delete dir", work.deleted_dirs, - included.deleted_dirs, excluded.deleted_dirs, app); + for (std::map >::const_iterator i = + cs.deltas_applied.begin(); i != cs.deltas_applied.end(); ++i) + { + if (app.restriction_includes(i->first)) + included.deltas_applied.insert(*i); + else + excluded.deltas_applied.insert(*i); + } - restrict_rename_set("rename file", work.renamed_files, - included.renamed_files, excluded.renamed_files, app); - restrict_rename_set("rename dir", work.renamed_dirs, - included.renamed_dirs, excluded.renamed_dirs, app); + for (std::set >::const_iterator i = + cs.attrs_cleared.begin(); i != cs.attrs_cleared.end(); ++i) + { + if (app.restriction_includes(i->first)) + included.attrs_cleared.insert(*i); + else + excluded.attrs_cleared.insert(*i); + } - restrict_path_set("add file", work.added_files, - included.added_files, excluded.added_files, app); + for (std::map, attr_value>::const_iterator i = + cs.attrs_set.begin(); i != cs.attrs_set.end(); ++i) + { + if (app.restriction_includes(i->first.first)) + included.attrs_set.insert(*i); + else + excluded.attrs_set.insert(*i); + } } + +// Project the old_paths through r_old + work, to find the new names of the +// paths (if they survived work) + static void -restrict_delta_map(change_set::delta_map const & deltas, - change_set::delta_map & included, - change_set::delta_map & excluded, - app_state & app) +remap_paths(path_set const & old_paths, + roster_t const & r_old, + cset const & work, + path_set & new_paths) { - for (change_set::delta_map::const_iterator i = deltas.begin(); i!= deltas.end(); ++i) + new_paths.clear(); + temp_node_id_source nis; + roster_t r_tmp = r_old; + editable_roster_base er(r_tmp, nis); + work.apply_to(er); + for (path_set::const_iterator i = old_paths.begin(); + i != old_paths.end(); ++i) { - if (app.restriction_includes(i->first)) + node_t n_old = r_old.get_node(*i); + if (r_tmp.has_node(n_old->self)) { - L(F("restriction includes delta on %s\n") % i->first); - included.insert(*i); + split_path new_sp; + r_tmp.get_name(n_old->self, new_sp); + new_paths.insert(new_sp); } - else - { - L(F("restriction excludes delta on %s\n") % i->first); - excluded.insert(*i); - } } } void -calculate_restricted_rearrangement(app_state & app, - std::vector const & args, - manifest_id & old_manifest_id, - revision_id & old_revision_id, - manifest_map & m_old, - path_set & old_paths, - path_set & new_paths, - change_set::path_rearrangement & included, - change_set::path_rearrangement & excluded) +get_base_roster_and_working_cset(app_state & app, + std::vector const & args, + revision_id & old_revision_id, + manifest_id & old_manifest_id, + roster_t & old_roster, + path_set & old_paths, + path_set & new_paths, + cset & included, + cset & excluded) { - change_set::path_rearrangement work; + cset work; - get_base_revision(app, - old_revision_id, - old_manifest_id, m_old); + get_base_revision(app, old_revision_id, old_roster); + get_work_cset(work); - extract_path_set(m_old, old_paths); + old_roster.extract_path_set(old_paths); - get_path_rearrangement(work); - path_set valid_paths(old_paths); extract_rearranged_paths(work, valid_paths); add_intermediate_paths(valid_paths); - app.set_restriction(valid_paths, args); - restrict_path_rearrangement(work, included, excluded, app); - - apply_path_rearrangement(old_paths, included, new_paths); + restrict_cset(work, included, excluded, app); + remap_paths(old_paths, old_roster, work, new_paths); } void -calculate_restricted_revision(app_state & app, - std::vector const & args, - revision_set & rev, - manifest_map & m_old, - manifest_map & m_new, - change_set::path_rearrangement & excluded) +get_working_revision_and_rosters(app_state & app, + std::vector const & args, + revision_set & rev, + roster_t & old_roster, + roster_t & new_roster, + cset & excluded) { + revision_id old_revision_id; manifest_id old_manifest_id; - revision_id old_revision_id; - boost::shared_ptr cs(new change_set()); + boost::shared_ptr cs(new cset()); path_set old_paths, new_paths; rev.edges.clear(); - m_old.clear(); - m_new.clear(); - - calculate_restricted_rearrangement(app, args, - old_manifest_id, old_revision_id, - m_old, old_paths, new_paths, - cs->rearrangement, excluded); - - build_restricted_manifest_map(new_paths, m_old, m_new, app); - complete_change_set(m_old, m_new, *cs); - - calculate_ident(m_new, rev.new_manifest); - L(F("new manifest is %s\n") % rev.new_manifest); - + get_base_roster_and_working_cset(app, args, + old_revision_id, + old_manifest_id, + old_roster, + old_paths, + new_paths, + *cs, excluded); + + build_restricted_roster(new_paths, old_roster, new_roster, app); + calculate_ident(new_roster, rev.new_manifest); + L(F("new manifest_id is %s\n") % rev.new_manifest); + rev.edges.insert(std::make_pair(old_revision_id, std::make_pair(old_manifest_id, cs))); } void -calculate_restricted_revision(app_state & app, - std::vector const & args, - revision_set & rev, - manifest_map & m_old, - manifest_map & m_new) +get_working_revision_and_rosters(app_state & app, + std::vector const & args, + revision_set & rev, + roster_t & old_roster, + roster_t & new_roster) { - change_set::path_rearrangement work; - calculate_restricted_revision(app, args, rev, m_old, m_new, work); + cset excluded; + get_working_revision_and_rosters(app, args, rev, + old_roster, new_roster, excluded); } void -calculate_unrestricted_revision(app_state & app, - revision_set & rev, - manifest_map & m_old, - manifest_map & m_new) +get_unrestricted_working_revision_and_rosters(app_state & app, + revision_set & rev, + roster_t & old_roster, + roster_t & new_roster) { std::vector empty_args; std::set saved_exclude_patterns(app.exclude_patterns); app.exclude_patterns.clear(); - calculate_restricted_revision(app, empty_args, rev, m_old, m_new); + get_working_revision_and_rosters(app, empty_args, rev, old_roster, new_roster); app.exclude_patterns = saved_exclude_patterns; } + +static void +extract_changed_paths(cset const & cs, path_set & paths) +{ + extract_rearranged_paths(cs, paths); + + for (std::map >::const_iterator i + = cs.deltas_applied.begin(); i != cs.deltas_applied.end(); ++i) + paths.insert(i->first); + + for (std::set >::const_iterator i = + cs.attrs_cleared.begin(); i != cs.attrs_cleared.end(); ++i) + paths.insert(i->first); + + for (std::map, attr_value>::const_iterator i = + cs.attrs_set.begin(); i != cs.attrs_set.end(); ++i) + paths.insert(i->first.first); +} + void -calculate_restricted_change_set(app_state & app, - std::vector const & args, - change_set const & cs, - change_set & included, - change_set & excluded) +calculate_restricted_cset(app_state & app, + std::vector const & args, + cset const & cs, + cset & included, + cset & excluded) { path_set valid_paths; @@ -265,12 +263,5 @@ add_intermediate_paths(valid_paths); app.set_restriction(valid_paths, args); - - restrict_path_rearrangement(cs.rearrangement, - included.rearrangement, excluded.rearrangement, app); - - restrict_delta_map(cs.deltas, included.deltas, excluded.deltas, app); + restrict_cset(cs, included, excluded, app); } - - -*/ ======================================================================== --- restrictions.hh ab5ee1c29bdfd409847f5d9f369de9a69f2795b7 +++ restrictions.hh edac33b08225c94ec8cdee860aece9d2fb05c68f @@ -8,54 +8,60 @@ #include "app_state.hh" #include "cset.hh" +#include "roster.hh" #include "vocab.hh" -/* -// FIXME_ROSTERS: disabled until rewritten to use rosters +void +extract_rearranged_paths(cset const & rearrangement, + path_set & paths); -void extract_rearranged_paths(change_set::path_rearrangement - const & rearrangement, path_set & paths); +void +add_intermediate_paths(path_set & paths); -void add_intermediate_paths(path_set & paths); +void +restrict_cset(cset const & work, + cset & included, + cset & excluded, + app_state & app); -void restrict_path_rearrangement(change_set::path_rearrangement const & work, - change_set::path_rearrangement & included, - change_set::path_rearrangement & excluded, - app_state & app); +void +get_base_roster_and_working_cset(app_state & app, + std::vector const & args, + revision_id & old_revision_id, + manifest_id & old_manifest_id, + roster_t & old_roster, + path_set & old_paths, + path_set & new_paths, + cset & included, + cset & excluded); -void calculate_restricted_rearrangement(app_state & app, - std::vector const & args, - manifest_id & old_manifest_id, - revision_id & old_revision_id, - manifest_map & m_old, - path_set & old_paths, - path_set & new_paths, - change_set::path_rearrangement & included, - change_set::path_rearrangement & excluded); +void +get_working_revision_and_rosters(app_state & app, + std::vector const & args, + revision_set & rev, + roster_t & old_roster, + roster_t & new_roster, + cset & excluded); -void calculate_restricted_revision(app_state & app, - std::vector const & args, - revision_set & rev, - manifest_map & m_old, - manifest_map & m_new, - change_set::path_rearrangement & excluded); +// Same as above, only without the "excluded" out-parameter. +void +get_working_revision_and_rosters(app_state & app, + std::vector const & args, + revision_set & rev, + roster_t & old_roster, + roster_t & new_roster); -void calculate_restricted_revision(app_state & app, - std::vector const & args, - revision_set & rev, - manifest_map & m_old, - manifest_map & m_new); +void +get_unrestricted_working_revision_and_rosters(app_state & app, + revision_set & rev, + roster_t & old_roster, + roster_t & new_roster); -void calculate_unrestricted_revision(app_state & app, - revision_set & rev, - manifest_map & m_old, - manifest_map & m_new); +void +calculate_restricted_cset(app_state & app, + std::vector const & args, + cset const & cs, + cset & included, + cset & excluded); -void calculate_restricted_change_set(app_state & app, - std::vector const & args, - change_set const & cs, - change_set & included, - change_set & excluded); -*/ - #endif // header guard ======================================================================== --- roster.cc 5879cd218111c8aff91974a36fc726a7fd2ed78f +++ roster.cc 74b027c27b8f4dfa1d19ed2e9971273cbd173054 @@ -14,6 +14,7 @@ #include "app_state.hh" #include "basic_io.hh" #include "cset.hh" +#include "inodeprint.hh" #include "roster.hh" #include "revision.hh" #include "vocab.hh" @@ -849,73 +850,77 @@ return n; } +editable_roster_base::editable_roster_base(roster_t & r, node_id_source & nis) + : r(r), nis(nis) +{} -namespace +node_id +editable_roster_base::detach_node(split_path const & src) { + // L(F("detach_node('%s')") % file_path(src)); + return r.detach_node(src); +} - // adaptor class to enable cset application on rosters. - class editable_roster_base - : public editable_tree - { - public: - editable_roster_base(roster_t & r, node_id_source & nis) - : r(r), nis(nis) - {} +void +editable_roster_base::drop_detached_node(node_id nid) +{ + // L(F("drop_detached_node(%d)") % nid); + r.drop_detached_node(nid); +} - virtual node_id detach_node(split_path const & src) - { - // L(F("detach_node('%s')") % file_path(src)); - return r.detach_node(src); - } - virtual void drop_detached_node(node_id nid) - { - // L(F("drop_detached_node(%d)") % nid); - r.drop_detached_node(nid); - } - virtual node_id create_dir_node() - { - // L(F("create_dir_node()\n")); - node_id n = r.create_dir_node(nis); - // L(F("create_dir_node() -> %d\n") % n); - return n; - } - virtual node_id create_file_node(file_id const & content) - { - // L(F("create_file_node('%s')\n") % content); - node_id n = r.create_file_node(content, nis); - // L(F("create_file_node('%s') -> %d\n") % content % n); - return n; - } - virtual void attach_node(node_id nid, split_path const & dst) - { - // L(F("attach_node(%d, '%s')") % nid % file_path(dst)); - r.attach_node(nid, dst); - } - virtual void apply_delta(split_path const & pth, - file_id const & old_id, - file_id const & new_id) - { - // L(F("clear_attr('%s', '%s', '%s')") % file_path(pth) % old_id % new_id); - r.apply_delta(pth, old_id, new_id); - } - virtual void clear_attr(split_path const & pth, - attr_key const & name) - { - // L(F("clear_attr('%s', '%s')") % file_path(pth) % name); - r.clear_attr(pth, name); - } - virtual void set_attr(split_path const & pth, - attr_key const & name, - attr_value const & val) - { - // L(F("set_attr('%s', '%s', '%s')") % file_path(pth) % name % val); - r.set_attr(pth, name, val); - } - protected: - roster_t & r; - node_id_source & nis; - }; +node_id +editable_roster_base::create_dir_node() +{ + // L(F("create_dir_node()\n")); + node_id n = r.create_dir_node(nis); + // L(F("create_dir_node() -> %d\n") % n); + return n; +} +node_id +editable_roster_base::create_file_node(file_id const & content) +{ + // L(F("create_file_node('%s')\n") % content); + node_id n = r.create_file_node(content, nis); + // L(F("create_file_node('%s') -> %d\n") % content % n); + return n; +} + +void +editable_roster_base::attach_node(node_id nid, split_path const & dst) +{ + // L(F("attach_node(%d, '%s')") % nid % file_path(dst)); + r.attach_node(nid, dst); +} + +void +editable_roster_base::apply_delta(split_path const & pth, + file_id const & old_id, + file_id const & new_id) +{ + // L(F("clear_attr('%s', '%s', '%s')") % file_path(pth) % old_id % new_id); + r.apply_delta(pth, old_id, new_id); +} + +void +editable_roster_base::clear_attr(split_path const & pth, + attr_key const & name) +{ + // L(F("clear_attr('%s', '%s')") % file_path(pth) % name); + r.clear_attr(pth, name); +} + +void +editable_roster_base::set_attr(split_path const & pth, + attr_key const & name, + attr_value const & val) +{ + // L(F("set_attr('%s', '%s', '%s')") % file_path(pth) % name % val); + r.set_attr(pth, name, val); +} + +namespace +{ struct testing_node_id_source : public node_id_source { @@ -1694,6 +1699,97 @@ } +/// getting rosters from the working copy + +inline static bool +inodeprint_unchanged(inodeprint_map const & ipm, file_path const & path) +{ + inodeprint_map::const_iterator old_ip = ipm.find(path); + if (old_ip != ipm.end()) + { + hexenc ip; + if (inodeprint_file(path, ip) && ip == old_ip->second) + return true; // unchanged + else + return false; // changed or unavailable + } + else + return false; // unavailable +} + +void +build_restricted_roster(path_set const & paths, + roster_t const & r_old, + roster_t & r_new, + app_state & app) +{ + temp_node_id_source nis; + r_new = r_old; + inodeprint_map ipm; + + if (in_inodeprints_mode()) + { + data dat; + read_inodeprints(dat); + read_inodeprint_map(dat, ipm); + } + + size_t missing_files = 0; + + // this code is speed critical, hence the use of inode fingerprints so be + // careful when making changes in here and preferably do some timing tests + + for (path_set::const_iterator i = paths.begin(); i != paths.end(); ++i) + { + node_t new_n = r_new.get_node(*i); + + // Only analyze files further, not dirs. + if (! is_file_t(new_n)) + continue; + + file_path fp(*i); + + // Only analyze restriction-included files. + if (!app.restriction_includes(fp)) + continue; + + // Only analyze changed files (or all files if inodeprints mode + // is disabled). + if (inodeprint_unchanged(ipm, fp)) + continue; + + file_t new_f = downcast_to_file_t(new_n); + if (!ident_existing_file(fp, new_f->content, app.lua)) + { + W(F("missing %s") % (fp)); + missing_files++; + } + } + + N(missing_files == 0, + F("%d missing files\n" + "to restore consistency, on each missing file run either\n" + "'monotone drop FILE' to remove it permanently, or\n" + "'monotone revert FILE' to restore it\n") + % missing_files); + +} + +void +roster_t::extract_path_set(path_set & paths) const +{ + paths.clear(); + I(has_root()); + for (dfs_iter i(root_dir); !i.finished(); ++i) + { + node_t curr = *i; + split_path pth; + get_name(curr->self, pth); + paths.insert(pth); + } +} + + //////////////////////////////////////////////////////////////////// // I/O routines //////////////////////////////////////////////////////////////////// ======================================================================== --- roster.hh bfe4af746e5615b2b419fd8a2501ce96649c4a5e +++ roster.hh 356168d5db89209841dfafc57a7b47fc708a9753 @@ -191,6 +191,8 @@ attr_key const & name, std::pair const & val); + void extract_path_set(path_set & paths) const; + node_map const & all_nodes() const { return nodes; @@ -239,12 +241,46 @@ struct app_state; struct revision_set; +// adaptor class to enable cset application on rosters. +class editable_roster_base + : public editable_tree +{ +public: + editable_roster_base(roster_t & r, node_id_source & nis); + virtual node_id detach_node(split_path const & src); + virtual void drop_detached_node(node_id nid); + virtual node_id create_dir_node(); + virtual node_id create_file_node(file_id const & content); + virtual void attach_node(node_id nid, split_path const & dst); + virtual void apply_delta(split_path const & pth, + file_id const & old_id, + file_id const & new_id); + virtual void clear_attr(split_path const & pth, + attr_key const & name); + virtual void set_attr(split_path const & pth, + attr_key const & name, + attr_value const & val); +protected: + roster_t & r; + node_id_source & nis; +}; + + void make_cset(roster_t const & from, roster_t const & to, cset & cs); +void +build_restricted_roster(path_set const & paths, + roster_t const & r_old, + roster_t & r_new, + app_state & app); +void +extract_roster_path_set(roster_t const & ros, + path_set & paths); + void make_roster_for_revision(revision_set const & rev, revision_id const & rid, ======================================================================== --- work.cc ee202edbc9284547d8ecd4bdbb9c45430de7bdf4 +++ work.cc a0ff264fdddfaa222eaa72a6bd70aa6a6801fc65 @@ -29,12 +29,14 @@ void file_itemizer::visit_file(file_path const & path) { - if (app.restriction_includes(path) && known.find(path) == known.end()) + split_path sp; + path.split(sp); + if (app.restriction_includes(path) && known.find(sp) == known.end()) { if (app.lua.hook_ignore_file(path)) - ignored.insert(path); + ignored.insert(sp); else - unknown.insert(path); + unknown.insert(sp); } } @@ -313,6 +315,7 @@ concatenate_rearrangements(pr, pr_new, pr_concatenated); pr = pr_concatenated; } +*/ // work file containing rearrangement from uncommitted adds/drops/renames @@ -324,7 +327,7 @@ L(F("work path is %s\n") % w_path); } -void get_path_rearrangement(change_set::path_rearrangement & w) +void get_work_cset(cset & w) { bookkeeping_path w_path; get_work_path(w_path); @@ -333,8 +336,8 @@ L(F("checking for un-committed work file %s\n") % w_path); data w_data; read_data(w_path, w_data); - read_path_rearrangement(w_data, w); - L(F("read rearrangement from %s\n") % w_path); + read_cset(w_data, w); + L(F("read cset from %s\n") % w_path); } else { @@ -342,7 +345,7 @@ } } -void remove_path_rearrangement() +void remove_work_cset() { bookkeeping_path w_path; get_work_path(w_path); @@ -350,7 +353,7 @@ delete_file(w_path); } -void put_path_rearrangement(change_set::path_rearrangement & w) +void put_work_cset(cset & w) { bookkeeping_path w_path; get_work_path(w_path); @@ -363,11 +366,10 @@ else { data w_data; - write_path_rearrangement(w, w_data); + write_cset(w, w_data); write_data(w_path, w_data); } } -*/ // revision file name @@ -414,11 +416,9 @@ void get_base_revision(app_state & app, revision_id & rid, - manifest_id & mid, - manifest_map & man) + roster_t & ros, + marking_map & mm) { - man.clear(); - get_revision_id(rid); if (!null_id(rid)) @@ -427,25 +427,28 @@ N(app.db.revision_exists(rid), F("base revision %s does not exist in database\n") % rid); - app.db.get_revision_manifest(rid, mid); - L(F("old manifest is %s\n") % mid); - - N(app.db.manifest_version_exists(mid), - F("base manifest %s does not exist in database\n") % mid); - - app.db.get_manifest(mid, man); + app.db.get_roster(rid, ros, mm); } - L(F("old manifest has %d entries\n") % man.size()); + L(F("base roster has %d entries\n") % ros.all_nodes().size()); } void -get_base_manifest(app_state & app, - manifest_map & man) +get_base_revision(app_state & app, + revision_id & rid, + roster_t & ros) { + marking_map mm; + get_base_revision(app, rid, ros, mm); +} + +void +get_base_roster(app_state & app, + roster_t & ros) +{ revision_id rid; - manifest_id mid; - get_base_revision(app, rid, mid, man); + marking_map mm; + get_base_revision(app, rid, ros, mm); } ======================================================================== --- work.hh f7b39329a294dbcf5371fcea21bfead980d371f6 +++ work.hh e69fe80720ad44a1b9079de769cbd9075db1d2ac @@ -13,8 +13,9 @@ #include "cset.hh" #include "manifest.hh" -#include "vocab.hh" #include "paths.hh" +#include "roster.hh" +#include "vocab.hh" // // this file defines structures to deal with the "working copy" of a tree @@ -28,7 +29,7 @@ // // MT/revision -- contains the id of the checked out revision // MT/work -- (optional) a set of added, deleted or moved pathnames -// this file is, syntactically, a path_rearrangement +// this file is, syntactically, a cset // MT/options -- the database, branch and key options currently in use // MT/log -- user edited log file // MT/inodeprints -- file fingerprint cache, presence turns on "reckless" @@ -39,15 +40,14 @@ // added or deleted or renamed (and the paths of those changes recorded in // 'MT/work'). // -// when it comes time to commit, the change_set is calculated by applying -// the path_rearrangement to the manifest and then calculating the -// delta_set between the modified manifest and the files in the working -// copy. +// when it comes time to commit, the cset in MT/work (which can have no +// deltas) is applied to the base roster, then a new roster is built by +// analyzing the content of every file in the roster, as it appears in the +// working copy. a final cset is calculated which contains the requisite +// deltas, and placed in a rev, which is written to the db. // // MT/inodes, if present, can be used to speed up this last step. -typedef std::set path_set; - struct file_itemizer : public tree_walker { app_state & app; @@ -80,14 +80,15 @@ app_state & app, change_set::path_rearrangement & pr); -// the "work" file contains the current path rearrangement representing -// uncommitted add/drop/rename operations in the serialized change set format +*/ -void get_path_rearrangement(change_set::path_rearrangement & w); -void remove_path_rearrangement(); -void put_path_rearrangement(change_set::path_rearrangement & w); -*/ +// the "work" file contains the current cset representing uncommitted +// add/drop/rename operations (not deltas) +void get_work_cset(cset & w); +void remove_work_cset(); +void put_work_cset(cset & w); + // the "revision" file contains the base revision id that the current working // copy was checked out from @@ -95,9 +96,12 @@ void put_revision_id(revision_id const & rev); void get_base_revision(app_state & app, revision_id & rid, - manifest_id & mid, - manifest_map & man); -void get_base_manifest(app_state & app, manifest_map & man); + roster_t & ros, + marking_map & mm); +void get_base_revision(app_state & app, + revision_id & rid, + roster_t & ros); +void get_base_roster(app_state & app, roster_t & ros); // the "user log" is a file the user can edit as they program to record // changes they make to their source code. Upon commit the file is read