# # patch "ChangeLog" # from [e9de117a2044926f443013af7951cbe6069c62ae] # to [647015eb14f585af944198b25fbd7699b42cee62] # # patch "inodeprint.cc" # from [88e4c413bf8b723e01274e7377ab3ce8bfdadb0c] # to [3e50716f49cc55772d0473f5de61ca7891f980b2] # # patch "manifest.cc" # from [13650d15c6b7fde18fb7018c68ebbf2e82d2d125] # to [4710b6b5b9c464e22894e8408c71d6afdd1c5f3a] # --- ChangeLog +++ ChangeLog @@ -1,3 +1,11 @@ +2005-04-24 Nathaniel Smith + + * manifest.cc (build_restricted_manifest_map): Careful to only + stat things once on the inodeprints fast-path. + (read_manifest_map): Hand-code a parser, instead of using + boost::regex. + * inodeprint.cc (read_inodeprint_map): Likewise. + 2005-04-23 Derek Scherger * app_state.cc: --- inodeprint.cc +++ inodeprint.cc @@ -18,33 +18,38 @@ #include "inodeprint.hh" #include "sanity.hh" #include "platform.hh" +#include "constants.hh" // this file defines the inodeprint_map structure, and some operations on it. // it is currently heavily based on manifest.cc. // reading inodeprint_maps -struct -add_to_inodeprint_map -{ - inodeprint_map & ipm; - explicit add_to_inodeprint_map(inodeprint_map & ipm) : ipm(ipm) {} - bool operator()(boost::match_results const & res) - { - std::string ident(res[1].first, res[1].second); - std::string path(res[2].first, res[2].second); - file_path pth(path); - ipm.insert(inodeprint_entry(pth, hexenc(ident))); - return true; - } -}; - void read_inodeprint_map(data const & dat, inodeprint_map & ipm) { - boost::regex expr("^([[:xdigit:]]{40}) ([^[:space:]].*)$"); - boost::regex_grep(add_to_inodeprint_map(ipm), dat(), expr, boost::match_not_dot_newline); + std::string::size_type pos = 0; + while (pos != dat().size()) + { + // whenever we get here, pos points to the beginning of a inodeprint + // line + // inodeprint file has 40 characters hash, then 2 characters space, then + // everything until next \n is filename. + std::string ident = dat().substr(pos, constants::idlen); + std::string::size_type file_name_begin = pos + constants::idlen + 2; + pos = dat().find('\n', file_name_begin); + std::string file_name; + if (pos == std::string::npos) + file_name = dat().substr(file_name_begin); + else + file_name = dat().substr(file_name_begin, pos - file_name_begin); + ipm.insert(inodeprint_entry(file_path(file_name), + hexenc(ident))); + // skip past the '\n' + ++pos; + } + return; } // writing inodeprint_maps --- manifest.cc +++ manifest.cc @@ -23,6 +23,7 @@ #include "sanity.hh" #include "inodeprint.hh" #include "platform.hh" +#include "constants.hh" // this file defines the class of manifest_map objects, and various comparison // and i/o functions on them. a manifest specifies exactly which versions @@ -78,10 +79,11 @@ for (path_set::const_iterator i = paths.begin(); i != paths.end(); ++i) { - bool exists = file_exists(*i); bool included = app.restriction_includes(*i); - if (included && exists) + // first, make a try to see if we have a current inodeprint. if we do, + // we skip the rest of this block to go around the loop again. + if (included) { // compute the current sha1 id for included files // we might be able to avoid it, if we have an inode fingerprint... @@ -99,7 +101,14 @@ continue; } } - // ...ah, well, no good fingerprint, just check directly. + } + // ...ah, well, no good inodeprint, let's do proper checking. + // note that we carefully do not call file_exists() until _after_ we've + // given inodeprints a chance; this halves the number of stat calls in a + // typical large tree using inodeprints. + bool exists = file_exists(*i); + if (included && exists) + { hexenc ident; calculate_ident(*i, ident, app.lua); m_new.insert(manifest_entry(*i, file_id(ident))); @@ -127,27 +136,30 @@ // reading manifest_maps -struct -add_to_manifest_map -{ - manifest_map & man; - explicit add_to_manifest_map(manifest_map & m) : man(m) {} - bool operator()(match_results const & res) - { - std::string ident(res[1].first, res[1].second); - std::string path(res[2].first, res[2].second); - file_path pth(path); - man.insert(manifest_entry(pth, hexenc(ident))); - return true; - } -}; - void read_manifest_map(data const & dat, manifest_map & man) { - regex expr("^([[:xdigit:]]{40}) ([^[:space:]].*)$"); - regex_grep(add_to_manifest_map(man), dat(), expr, match_not_dot_newline); + std::string::size_type pos = 0; + while (pos != dat().size()) + { + // whenever we get here, pos points to the beginning of a manifest + // line + // manifest file has 40 characters hash, then 2 characters space, then + // everything until next \n is filename. + std::string ident = dat().substr(pos, constants::idlen); + std::string::size_type file_name_begin = pos + constants::idlen + 2; + pos = dat().find('\n', file_name_begin); + std::string file_name; + if (pos == std::string::npos) + file_name = dat().substr(file_name_begin); + else + file_name = dat().substr(file_name_begin, pos - file_name_begin); + man.insert(manifest_entry(file_path(file_name), hexenc(ident))); + // skip past the '\n' + ++pos; + } + return; } void