# # # patch "mtn_cvs/cvs_sync.cc" # from [bdd253603f1f4beb39ddbd60dc81925ea82a6241] # to [9b8caf467cd89e5b6f37c5379491bfc435c17229] # # patch "mtn_cvs/cvs_sync.hh" # from [edb911b87d1be61d1c2e262011b5a9fe5ed0c1a2] # to [ca1c58a8bd8442a6ce10a88c3311f31350c1eba0] # # patch "mtn_cvs/mtn_automate.cc" # from [656e9c395e44320a89e4dd73e5f42a052e0eaeaf] # to [0b417ef9132a4268efe861f0d9fd1b914fb0ef7a] # # patch "mtn_cvs/mtn_automate.hh" # from [24ac22d7314deb86d1605e41472d8e3be56c0c1b] # to [f80c0a28bfeb840e5f7ebdd596c1d026292b917b] # # patch "mtn_cvs/mtn_cvs.cc" # from [259efc8c8cccc1c3ff8aa532939e6a9be671b45d] # to [76fc48d3793c3695dece4786fa1183dc2d4e61ce] # # patch "mtn_cvs/tests/push_add_drop/__driver__.lua" # from [4f268a89b7a657b6a76d288ba4485bfc5dede497] # to [ff1d06c511003ab2f84e62fe2f695649ba3cd1ef] # # patch "mtn_cvs/tests/push_pull_with_changes/__driver__.lua" # from [97e526f2a8b5dbbe5ca70c17ee51e2c56ed4e638] # to [ec1abdb8954e744b840636d36e4f66428fbe2e43] # ============================================================ --- mtn_cvs/cvs_sync.cc bdd253603f1f4beb39ddbd60dc81925ea82a6241 +++ mtn_cvs/cvs_sync.cc 9b8caf467cd89e5b6f37c5379491bfc435c17229 @@ -600,9 +600,15 @@ void cvs_repository::fill_manifests(std: } } -void cvs_repository::attach_sync_state(cvs_edge & e,mtn_automate::manifest_map const& oldmanifest, +bool cvs_repository::attach_sync_state(cvs_edge & e, mtn_automate::manifest_map const& oldmanifest, mtn_automate::cset &cs) { mtn_automate::sync_map_t state=create_sync_state(e); + return attach_sync_state(state, oldmanifest, cs); +} + +bool cvs_repository::attach_sync_state(mtn_automate::sync_map_t & state, mtn_automate::manifest_map const& oldmanifest, + mtn_automate::cset &cs) +{ bool any_change=false; // added and changed attributes for (mtn_automate::sync_map_t::const_iterator i=state.begin(); @@ -622,7 +628,10 @@ void cvs_repository::attach_sync_state(c { mtn_automate::attr_map_t::const_iterator a = f->second.second.find(i->first.second); - if (a==f->second.second.end()) cs.attrs_set[i->first]=i->second; + if (a==f->second.second.end()) + { cs.attrs_set[i->first]=i->second; + any_change=true; + } else if (a->second!=i->second) { cs.attrs_set[i->first]=i->second; @@ -656,10 +665,7 @@ void cvs_repository::attach_sync_state(c any_change=true; } } - if (!any_change) // this happens if only deletions happened - { cs.attrs_set[std::make_pair(split_path(1,the_null_component),attr_key(app.opts.domain()+":touch"))] - =attr_value("synchronized"); - } + return any_change; } mtn_automate::sync_map_t cvs_repository::create_sync_state(cvs_edge const& e) @@ -710,6 +716,32 @@ mtn_automate::sync_map_t cvs_repository: return state; } +void cvs_repository::update_sync_state(mtn_automate::sync_map_t &state, std::set::iterator e) +{ + for (cvs_manifest::const_iterator i=e->xfiles.begin(); i!=e->xfiles.end(); ++i) + { + split_path sp; + file_path_internal(i->first).split(sp); + if (i->second == remove_state) + { + state.erase(std::make_pair(sp,attr_key(app.opts.domain()+":revision"))); + state.erase(std::make_pair(sp,attr_key(app.opts.domain()+":keyword"))); + state.erase(std::make_pair(sp,attr_key(app.opts.domain()+":sha1"))); + } else + { + I(!i->second->cvs_version.empty()); + state[std::make_pair(sp,attr_key(app.opts.domain()+":revision"))] + =attr_value(i->second->cvs_version); + if (!i->second->keyword_substitution.empty()) + state[std::make_pair(sp,attr_key(app.opts.domain()+":keyword"))] + =attr_value(i->second->keyword_substitution); + if (!i->second->sha1sum.inner()().empty()) + state[std::make_pair(sp,attr_key(app.opts.domain()+":sha1"))] + =attr_value(i->second->sha1sum.inner()().substr(0,6)); + } + } +} + // commit CVS revisions to monotone (pull) void cvs_repository::commit_cvs2mtn(std::set::iterator e) { revision_id parent_rid; @@ -765,12 +797,13 @@ void cvs_repository::commit_cvs2mtn(std: L(FL("CVS Sync: Inserted revision %s into repository\n") % child_rid); e->revision=child_rid; - app.cert_revision(child_rid,"branch",app.opts.branch_name()); + app.cert_revision(child_rid, branch_cert_name_s, app.opts.branch_name()); std::string author=e->author; if (author.find('@')==std::string::npos) author+="@"+host; - app.cert_revision(child_rid, "author", author); - app.cert_revision(child_rid, "changelog", e->changelog); - app.cert_revision(child_rid, "date", time_t2monotone(e->time)); + app.cert_revision(child_rid, author_cert_name_s, author); + app.cert_revision(child_rid, changelog_cert_name_s, e->changelog); + app.cert_revision(child_rid, date_cert_name_s, time_t2monotone(e->time)); + app.cert_revision(child_rid, sync_cert_name_s, app.opts.domain()); parent_rid = child_rid; } } @@ -826,7 +859,7 @@ void cvs_repository::prime() if (!branch_point.empty()) { time_t root_time(0); - // FIXME: look for this edge already in the database +#warning FIXME: look for this edge already in the database if (edges.begin()!=edges.end()) root_time=edges.begin()->time-1; std::set::iterator root_edge =edges.insert(cvs_edge(branch+" branching point",root_time,app_signing_key)).first; @@ -1014,62 +1047,59 @@ std::set::iterator cvs_reposit % a.new_content.size()); } - if (commits.empty()) - { W(F("revision %s: nothing to commit") % e.revision.inner()()); - e.delta_base=parent->revision; - cert_cvs(e); - revision_lookup[e.revision]=edges.insert(e).first; - fail=false; - return --(edges.end()); - } - std::string changelog; - changelog=e.changelog+"\nmonotone "+e.author+" " - +cvs_client::time_t2rfc822(e.time)+" "+e.revision.inner()().substr(0,6)+"\n"; - // gather information CVS does not know about into the changelog - changelog+=gather_merge_information(e.revision); - std::map > result - =Commit(changelog,e.time,commits); - if (result.empty()) { fail=true; return edges.end(); } - - e.delta_base=parent->revision; - - // the result of the commit: create history entry (file state) - // FIXME: is this really necessary? - for (std::map >::const_iterator - i=result.begin(); i!=result.end(); ++i) - { if (i->second.first.empty()) - { e.xfiles[i->first]=remove_state; - } - else - { MM(i->first); - file_state fs(e.time,i->second.first); - fs.log_msg=e.changelog; - fs.author=e.author; - fs.keyword_substitution=i->second.second; - split_path sp; - file_path_internal(i->first).split(sp); - std::map >::const_iterator mydelta=cs->deltas_applied.find(sp); - if (mydelta!=cs->deltas_applied.end()) - { fs.sha1sum=mydelta->second.second; + if (!commits.empty()) + { + std::string changelog; + changelog=e.changelog+"\nmonotone "+e.author+" " + +cvs_client::time_t2rfc822(e.time)+" "+e.revision.inner()().substr(0,6)+"\n"; + // gather information CVS does not know about into the changelog + changelog+=gather_merge_information(e.revision); + std::map > result + =Commit(changelog,e.time,commits); + + if (result.empty()) { fail=true; return edges.end(); } + + // parse history data (file state) from the result of the commit + for (std::map >::const_iterator + i=result.begin(); i!=result.end(); ++i) + { std::string cvs_file_rev(i->second.first); + if (cvs_file_rev.empty()) + { e.xfiles[i->first]=remove_state; } - else // newly added? - { std::map::const_iterator myadd=cs->files_added.find(sp); - if (myadd!=cs->files_added.end()) - { fs.sha1sum=myadd->second; + else + { MM(i->first); + file_state fs(e.time,cvs_file_rev); + fs.log_msg=e.changelog; + fs.author=e.author; + fs.keyword_substitution=i->second.second; + split_path sp; + file_path_internal(i->first).split(sp); + std::map >::const_iterator mydelta=cs->deltas_applied.find(sp); + if (mydelta!=cs->deltas_applied.end()) + { fs.sha1sum=mydelta->second.second; } - else // renamed? - { std::map::const_iterator myrename=renamed_ids.find(sp); - I(myrename!=renamed_ids.end()); - fs.sha1sum=myrename->second; + else // newly added? + { std::map::const_iterator myadd=cs->files_added.find(sp); + if (myadd!=cs->files_added.end()) + { fs.sha1sum=myadd->second; + } + else // renamed? + { std::map::const_iterator myrename=renamed_ids.find(sp); + I(myrename!=renamed_ids.end()); + fs.sha1sum=myrename->second; + } } + std::pair::iterator,bool> newelem= + files[i->first].known_states.insert(fs); + I(newelem.second); + e.xfiles[i->first]=newelem.first; } - std::pair::iterator,bool> newelem= - files[i->first].known_states.insert(fs); - I(newelem.second); - e.xfiles[i->first]=newelem.first; } + } - cert_cvs(e); + else W(F("revision %s: nothing to commit") % e.revision.inner()()); + + e.delta_base=parent->revision; revision_lookup[e.revision]=edges.insert(e).first; if (global_sanity.debug) L(FL("%s") % debug()); fail=false; @@ -1112,13 +1142,13 @@ std::string cvs_repository::gather_merge for (std::vector::const_iterator j=certs.begin();j!=certs.end();++j) { if (!j->trusted || j->signature!=mtn_automate::certificate::ok) continue; - if (j->name=="date") + if (j->name==date_cert_name_s) { date=cvs_repository::posix2time_t(j->value); } - else if (j->name=="author") + else if (j->name==author_cert_name_s) { author=j->value; } - else if (j->name=="changelog") + else if (j->name==changelog_cert_name_s) { changelog=j->value; } } @@ -1130,21 +1160,10 @@ std::string cvs_repository::gather_merge return result; } -namespace { -struct is_branch -{ std::string comparison; - is_branch(std::string const& br) : comparison(br) {} - bool operator()(mtn_automate::certificate const& cert) - { return cert.trusted - && cert.signature==mtn_automate::certificate::ok - && cert.name=="branch" - && cert.value==comparison; - } -}; -} - void cvs_repository::commit() { retrieve_modules(); + N(!edges.empty(), F("you can't push from a branch you haven't already pulled into from cvs")); +#if 0 if (edges.empty()) { // search for a matching start of history // take first head @@ -1177,7 +1196,12 @@ void cvs_repository::commit() I(!fail); } +#endif std::set::iterator now_iter=last_known_revision(); + bool update_sync_info = false; + + mtn_automate::sync_map_t sync_state=create_sync_state(*now_iter); + while (now_iter!=edges.end()) { const cvs_edge &now=*now_iter; I(!now.revision.inner()().empty()); @@ -1190,14 +1214,13 @@ void cvs_repository::commit() // ignore revisions not belonging to the specified branch for (std::vector::iterator i=children.begin(); i!=children.end();) - { std::vector certs - = app.get_revision_certs(*i); - if (std::remove_if(certs.begin(),certs.end(),is_branch(app.opts.branch_name()))==certs.begin()) + { + if (!app.in_branch(*i, app.opts.branch_name())) i=children.erase(i); else ++i; } } - if (children.empty()) return; + if (children.empty()) break; revision_id next; if (children.size()>1 && !app.opts.first) { for (std::vector::const_iterator i=app.opts.revisions.begin(); @@ -1217,18 +1240,57 @@ void cvs_repository::commit() { W(F("%s\n") % *i); } W(F("please specify direction using --revision\n")); - return; + break; } } else next=*children.begin(); bool fail=bool(); now_iter=commit_mtn2cvs(now_iter,next,fail); - - if (!fail) - P(F("checked %s into cvs repository") % now.revision); + + if (fail) + { + W(F("failed to commit %s into cvs repository - aborting push") % next); + break; + } + P(F("checked %s into cvs repository") % next); + + update_sync_state(sync_state, now_iter); + update_sync_info = true; + // we'd better seperate the commits so that ordering them is possible if (now_iter!=edges.end()) sleep(2); } + if (update_sync_info) + { + mtn_automate::cset cs; + now_iter=last_known_revision(); + revision_id last_rev(now_iter->revision); + + //std::cerr<< "attempting to attach sync state after rev: " << last_rev << std::endl; + //std::cerr << "sync changes: " << app.print_sync_info(sync_state) << std::endl; + + if (attach_sync_state(sync_state, app.get_manifest_of(last_rev), cs)) + { + revision_id child_rid=app.put_revision(last_rev,cs); + app.cert_revision(child_rid, branch_cert_name_s, app.opts.branch_name()); + app.cert_revision(child_rid, author_cert_name_s, "mtn_cvs"); + app.cert_revision(child_rid, changelog_cert_name_s, "Updated sync information after mtn_cvs push"); + app.cert_revision(child_rid, date_cert_name_s, time_t2monotone(now_iter->time)); + app.cert_revision(child_rid, sync_cert_name_s, app.opts.domain()); + + if (revision_ticker.get()) ++(*revision_ticker); + + P(F("Committed sync revision %s to repository\n") % child_rid); + } + else + { // we were already synced. Make sure we have a sync cert + if (!app.is_synchronized(last_rev, app.opts.domain())) + app.cert_revision(last_rev, sync_cert_name_s, app.opts.domain()); + } + + // std::cerr << "built cset: " << app.print_cset_info(cs) << std::endl; + + } // store_modules(); } @@ -1333,9 +1395,15 @@ void cvs_sync::pull(const std::string &_ { cvs_repository *repo=prepare_sync(_repository,_module,_branch,app); // initial checkout - if (repo->empty()) + if (repo->empty()) + { + // std::cerr << "pulling fresh" << std::endl; repo->prime(); - else repo->update(); + } else + { + // std::cerr << "updating" << std::endl; + repo->update(); + } delete repo; } @@ -1448,7 +1516,7 @@ void cvs_repository::update() std::vector results; const cvs_manifest &m=get_files(now); file_revisions.reserve(m.size()); -#warning FIXME: changed files +// #warning FIXME: changed files for (cvs_manifest::const_iterator i=m.begin();i!=m.end();++i) file_revisions.push_back(update_args(i->first,i->second->cvs_version, std::string(),i->second->keyword_substitution)); @@ -1879,9 +1947,3 @@ void cvs_repository::retrieve_modules() void cvs_repository::retrieve_modules() { if (!GetServerDir().empty()) return; } - -// we could pass delta_base and forget about it later -void cvs_repository::cert_cvs(cvs_edge const& e) -{ mtn_automate::sync_map_t content=create_sync_state(e); - app.put_sync_info(e.revision,app.opts.domain(),content); -} ============================================================ --- mtn_cvs/cvs_sync.hh edb911b87d1be61d1c2e262011b5a9fe5ed0c1a2 +++ mtn_cvs/cvs_sync.hh ca1c58a8bd8442a6ce10a88c3311f31350c1eba0 @@ -172,9 +172,12 @@ private: void store_modules(); void retrieve_modules(); std::string gather_merge_information(revision_id const& id); - void attach_sync_state(cvs_edge & e,mtn_automate::manifest_map const& oldmanifest, + bool attach_sync_state(cvs_edge & e,mtn_automate::manifest_map const& oldmanifest, mtn_automate::cset &cs); + bool attach_sync_state(mtn_automate::sync_map_t & state, mtn_automate::manifest_map const& oldmanifest, + mtn_automate::cset &cs); mtn_automate::sync_map_t create_sync_state(cvs_edge const& e); + void update_sync_state(mtn_automate::sync_map_t & state, std::set::iterator e); public: // semi public interface for push/pull void prime(); ============================================================ --- mtn_cvs/mtn_automate.cc 656e9c395e44320a89e4dd73e5f42a052e0eaeaf +++ mtn_cvs/mtn_automate.cc 0b417ef9132a4268efe861f0d9fd1b914fb0ef7a @@ -18,7 +18,11 @@ using std::pair; using std::make_pair; using std::pair; -cert_name const branch_cert_name("branch"); +std::string const branch_cert_name_s("branch"); +std::string const date_cert_name_s("date"); +std::string const author_cert_name_s("author"); +std::string const changelog_cert_name_s("changelog"); +std::string const sync_cert_name_s("mtn-cvs-sync"); void mtn_automate::check_interface_revision(std::string const& minimum) { std::string present=automate("interface_version"); @@ -285,7 +289,7 @@ mtn_automate::manifest_map mtn_automate: return result; } -void mtn_automate::cert_revision(revision_id const& rid, std::string const& name, std::string const& value) +void mtn_automate::cert_revision(revision_id const& rid, string const& name, std::string const& value) { std::vector args; args.push_back(rid.inner()()); args.push_back(name); @@ -338,10 +342,10 @@ std::vector m return result; } -std::vector mtn_automate::get_revision_certs(revision_id const& rid, cert_name const& name) +std::vector mtn_automate::get_revision_certs(revision_id const& rid, string const& name) { std::vector result=get_revision_certs(rid); for (std::vector::iterator i=result.begin();i!=result.end();) - { if (i->name!=name()) i=result.erase(i); + { if (i->name!=name) i=result.erase(i); else ++i; } return result; @@ -506,7 +510,7 @@ dump(file_path const& fp, string & out) { out=fp.as_internal(); } -static std::string print_sync_info(mtn_automate::sync_map_t const& data) +std::string mtn_automate::print_sync_info(mtn_automate::sync_map_t const& data) { basic_io::printer printer; for (mtn_automate::sync_map_t::const_iterator i = data.begin(); i != data.end(); ++i) { @@ -519,9 +523,11 @@ static std::string print_sync_info(mtn_a return printer.buf; } -// needed by find_newest_sync: check whether a revision has up to date synch information -static const char *const sync_prefix="x-sync-attr-"; -typedef std::map, attr_value> sync_map_t; +std::string mtn_automate::print_cset_info(mtn_automate::cset const& data) +{ basic_io::printer printer; + print_cset(printer, data); + return printer.buf; +} static bool begins_with(const std::string &s, const std::string &sub) { std::string::size_type len=sub.size(); @@ -532,7 +538,7 @@ bool mtn_automate::in_branch(revision_id bool mtn_automate::in_branch(revision_id const& rid, std::string const& branch) { - std::vector branch_certs = get_revision_certs(rid, branch_cert_name); + std::vector branch_certs = get_revision_certs(rid, branch_cert_name_s); for (std::vector::const_iterator cert=branch_certs.begin(); cert!=branch_certs.end(); ++cert) { @@ -547,24 +553,16 @@ bool mtn_automate::is_synchronized(revis bool mtn_automate::is_synchronized(revision_id const& rid, std::string const& domain) { - std::string prefix=domain+":"; - revision_t const& rev = get_revision(rid); - // merge nodes should never have up to date sync attributes - if (rev.edges.size()==1) - { - L(FL("is_synch: rev %s testing changeset\n") % rid); - boost::shared_ptr cs=rev.edges.begin()->second; - for (std::map, attr_value>::const_iterator i=cs->attrs_set.begin(); - i!=cs->attrs_set.end();++i) - { if (begins_with(i->first.second(),prefix)) // TODO: omit some attribute changes (repository, keyword, directory) - return true; - } - } - // look for a certificate std::vector certs; - certs=get_revision_certs(rid,cert_name(sync_prefix+domain)); - return !certs.empty(); + certs=get_revision_certs(rid,sync_cert_name_s); + for (std::vector::iterator i=certs.begin();i!=certs.end();) + { if (!i->trusted || i->signature!=mtn_automate::certificate::ok) + continue; + if (i->value==domain) + return true; + } + return false; } // Name: find_newest_sync @@ -600,7 +598,7 @@ revision_id mtn_automate::find_newest_sy { rid = *heads.begin(); L(FL("find_newest_sync: testing node %s") % rid); - std::cerr << "find_newest_sync: testing node " << rid << std::endl; + // std::cerr << "find_newest_sync: testing node " << rid << std::endl; heads.erase(heads.begin()); if (is_synchronized(rid,domain)) return rid; @@ -630,169 +628,30 @@ revision_id mtn_automate::find_newest_sy % branch % domain); } -static void parse_attributes(std::string const& in, sync_map_t& result) +mtn_automate::sync_map_t mtn_automate::get_sync_info(revision_id const& rid, string const& domain) { - basic_io::input_source source(in,"parse_attributes"); - basic_io::tokenizer tokenizer(source); - basic_io::parser parser(tokenizer); - - std::string t1, t2; - split_path p1; - while (parser.symp(syms::clear)) - { - parser.sym(); - parse_path(parser, p1); - parser.esym(syms::attr); - parser.str(t1); - pair new_pair(p1, attr_key(t1)); - safe_erase(result, new_pair); - } - while (parser.symp(syms::set)) - { - parser.sym(); - parse_path(parser, p1); - parser.esym(syms::attr); - parser.str(t1); - pair new_pair(p1, attr_key(t1)); - parser.esym(syms::value); - parser.str(t2); - safe_insert(result, make_pair(new_pair, attr_value(t2))); - } -} - -sync_map_t mtn_automate::get_sync_info(revision_id const& rid, string const& domain, int &depth) -{ - /* sync information is initially coded in DOMAIN: prefixed attributes - if information needs to be changed after commit then it gets - (base_revision_id+xdiff).gz encoded in certificates - - SPECIAL CASE of no parent: certificate is (40*' '+plain_data).gz encoded + /* sync information is coded in DOMAIN: prefixed attributes */ sync_map_t result; - - L(FL("get_sync_info: checking revision certificates %s") % rid); - std::vector certs; - certs=get_revision_certs(rid,cert_name(sync_prefix+domain)); - I(certs.size()<=1); // FIXME: what to do with multiple certs ... - if (certs.size()==1) - { std::string decomp_cert_val=xform(idx(certs,0).value); - I(decomp_cert_val.size()>constants::idlen+1); - I(decomp_cert_val[constants::idlen]=='\n'); - if (decomp_cert_val[0]!=' ') - { revision_id old_rid=revision_id(decomp_cert_val.substr(0,constants::idlen)); - result=get_sync_info(old_rid,domain,depth); - ++depth; - } - else depth=0; - parse_attributes(decomp_cert_val.substr(constants::idlen+1),result); - return result; - } - +#warning should check for presence of sync cert on revision revision_t rev=get_revision(rid); - if (rev.edges.size()==1) - { - L(FL("get_sync_info: checking revision attributes %s") % rid); - manifest_map m=get_manifest_of(rid); - std::string prefix=domain+":"; - for (manifest_map::const_iterator i = m.begin(); - i != m.end(); ++i) + L(FL("get_sync_info: checking revision attributes %s") % rid); + manifest_map m=get_manifest_of(rid); + std::string prefix=domain+":"; + for (manifest_map::const_iterator i = m.begin(); + i != m.end(); ++i) + { + for (attr_map_t::const_iterator j = i->second.second.begin(); + j != i->second.second.end(); ++j) { - for (attr_map_t::const_iterator j = i->second.second.begin(); - j != i->second.second.end(); ++j) - { - if (begins_with(j->first(),prefix)) - { - split_path sp; - i->first.split(sp); - result[std::make_pair(sp,j->first)]=j->second; - // else W(F("undefined value of %s %s\n") % sp % j->first()); - } + if (begins_with(j->first(),prefix)) + { + split_path sp; + i->first.split(sp); + result[std::make_pair(sp,j->first)]=j->second; + // else W(F("undefined value of %s %s\n") % sp % j->first()); } } - depth=0; } - N(!result.empty(), F("no sync cerficate found in revision %s for domain %s") - % rid % domain); return result; } - -// Name: get_sync_info -// Arguments: -// revision -// sync-domain -// Purpose: -// Get the sync information for a given revision -mtn_automate::sync_map_t mtn_automate::get_sync_info(revision_id const& rid, std::string const& domain) -{ - int dummy=0; - return get_sync_info(rid,domain,dummy); -} - -// Name: put_sync_info -// Arguments: -// revision -// sync-domain -// data -// Purpose: -// Set the sync information for a given revision -void mtn_automate::put_sync_info(revision_id const& rid, std::string const& domain, sync_map_t const& newinfo) -{ - revision_t rev=get_revision(rid); - - static const int max_indirection_nest=30; - std::string new_data=print_sync_info(newinfo); - - for (edge_map::const_iterator e = rev.edges.begin(); - e != rev.edges.end(); ++e) - { - if (null_id(e->first)) continue; - try - { - int depth=0; - sync_map_t oldinfo=get_sync_info(e->first,domain,depth); - if (depth>=max_indirection_nest) continue; // do not nest deeper - - basic_io::printer printer; - for (sync_map_t::const_iterator o=oldinfo.begin(),n=newinfo.begin(); - o!=oldinfo.end() && n!=newinfo.end();) - { if (n==newinfo.end() || o->firstfirst - /*|| (o->first==n->first && o->second!=n->second)*/) - { basic_io::stanza st; - st.push_file_pair(syms::clear, file_path(o->first.first)); - st.push_str_pair(syms::attr, o->first.second()); - printer.print_stanza(st); - if (o->first==n->first) ++n; - ++o; - } - else ++n; - } - for (sync_map_t::const_iterator o=oldinfo.begin(),n=newinfo.begin(); - o!=oldinfo.end() && n!=newinfo.end();) - { if (o==oldinfo.end() || o->first>n->first - || (o->first==n->first && o->second!=n->second)) - { basic_io::stanza st; - st.push_file_pair(syms::set, file_path(n->first.first)); - st.push_str_pair(syms::attr, n->first.second()); - st.push_str_pair(syms::value, n->second()); - printer.print_stanza(st); - if (o->first==n->first) ++o; - ++n; - } - else ++o; - } - if (printer.buf.size()>=new_data.size()) continue; // look for a shorter form - - I(e->first.inner()().size()==constants::idlen); - std::string cv=xform(e->first.inner()()+"\n"+printer.buf); - cert_revision(rid,sync_prefix+domain,cv); - L(FL("sync info encoded as delta from %s") % e->first); - return; - } - catch (informative_failure &er) {} - catch (std::runtime_error &er) {} - } - std::string cv=xform(string(constants::idlen,' ')+"\n"+new_data); - cert_revision(rid,sync_prefix+domain,cv); - L(FL("sync info attached to %s") % rid); -} - ============================================================ --- mtn_cvs/mtn_automate.hh 24ac22d7314deb86d1605e41472d8e3be56c0c1b +++ mtn_cvs/mtn_automate.hh f80c0a28bfeb840e5f7ebdd596c1d026292b917b @@ -55,14 +55,15 @@ struct mtn_automate : mtn_pipe revision_id find_newest_sync(std::string const& domain, std::string const& branch=""); sync_map_t get_sync_info(revision_id const& rid, std::string const& domain); - void put_sync_info(revision_id const& rid, std::string const& domain, sync_map_t const& data); + std::string print_sync_info(mtn_automate::sync_map_t const& data); + std::string print_cset_info(mtn_automate::cset const& data); file_id put_file(file_data const& d, file_id const& base=file_id()); manifest_map get_manifest_of(revision_id const& rid); revision_id put_revision(revision_id const& parent, cset const& changes); void cert_revision(revision_id const& rid, std::string const& name, std::string const& value); std::vector get_revision_certs(revision_id const& rid); - std::vector get_revision_certs(revision_id const& rid, cert_name const& name); + std::vector get_revision_certs(revision_id const& rid, std::string const& name); file_data get_file(file_id const& fid); std::vector get_revision_children(revision_id const& rid); std::vector get_revision_parents(revision_id const& rid); @@ -70,12 +71,13 @@ struct mtn_automate : mtn_pipe std::vector heads(std::string const& branch); bool in_branch(revision_id const& rid, std::string const& branch); std::string get_option(std::string const& name); - -private: bool is_synchronized(revision_id const& rid, std::string const& domain); - sync_map_t get_sync_info(revision_id const& rid, std::string const& domain, int &depth); }; -extern cert_name const branch_cert_name; +extern std::string const branch_cert_name_s; +extern std::string const date_cert_name_s; +extern std::string const author_cert_name_s; +extern std::string const changelog_cert_name_s; +extern std::string const sync_cert_name_s; #endif ============================================================ --- mtn_cvs/mtn_cvs.cc 259efc8c8cccc1c3ff8aa532939e6a9be671b45d +++ mtn_cvs/mtn_cvs.cc 76fc48d3793c3695dece4786fa1183dc2d4e61ce @@ -131,6 +131,7 @@ CMD(push, N_("network"), N_("[CVS-REPOSI branch=idx(args, 2)(); } mtncvs_state &myapp=mtncvs_state::upcast(app); + cvs_sync::push(repository,module,branch,myapp); } ============================================================ --- mtn_cvs/tests/push_add_drop/__driver__.lua 4f268a89b7a657b6a76d288ba4485bfc5dede497 +++ mtn_cvs/tests/push_add_drop/__driver__.lua ff1d06c511003ab2f84e62fe2f695649ba3cd1ef @@ -34,6 +34,7 @@ check(not exists("test/A")) -- Now, without any CVS changes, check if another pull pulls anything across +check(indir("testbr", mtn("up")), 0, false, false) writefile("testbr/B","change\n") check(indir("testbr", mtn("ci", "-m", "B changed")), 0, false, false) check(mtn_cvs("--branch=testbranch","pull",cvsroot,"test"),0, false,false) -- should be noop. ============================================================ --- mtn_cvs/tests/push_pull_with_changes/__driver__.lua 97e526f2a8b5dbbe5ca70c17ee51e2c56ed4e638 +++ mtn_cvs/tests/push_pull_with_changes/__driver__.lua ec1abdb8954e744b840636d36e4f66428fbe2e43 @@ -46,7 +46,7 @@ check(indir("test-cvs-wc", cvs("commit", writefile("test-cvs-wc/B","and again\n") check(indir("test-cvs-wc", cvs("commit", "-m", "A again")), 0, false, false) -skip_if(true) -- the following line causes mtn_cvs to freeze +-- skip_if(true) -- the following line causes mtn_cvs to freeze check(mtn_cvs("--branch=testbranch","pull",cvsroot,"test"),0, false,false)