# # # add_dir "mtn_cvs/tests/push_loop_check_log" # # add_file "mtn_cvs/tests/push_loop_check_log/__driver__.lua" # content [6c3f86bc27a79e80291f69bc59fb5212e5fe944c] # # patch "mtn_cvs/cvs_sync.cc" # from [d63379693f0a74f149378a9889060148378145f1] # to [049fbcc0f335e876801c0437df6658d33c872b61] # # patch "mtn_cvs/cvs_sync.hh" # from [ca1c58a8bd8442a6ce10a88c3311f31350c1eba0] # to [3ddc4a1afe54846745f3c46f5e339a4e0946de14] # ============================================================ --- mtn_cvs/tests/push_loop_check_log/__driver__.lua 6c3f86bc27a79e80291f69bc59fb5212e5fe944c +++ mtn_cvs/tests/push_loop_check_log/__driver__.lua 6c3f86bc27a79e80291f69bc59fb5212e5fe944c @@ -0,0 +1,106 @@ +-- CVS push with fork and merge + +include("/common/cvs.lua") +mtn_setup() +cvs_setup() + +function countMatch(data, match) + count = 0 + for word in string.gmatch(data, match) do + count = count + 1 + end + return count +end + +-- create a test project + +mkdir("cvstemp") +writefile("cvstemp/A","A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\n") +check(indir("cvstemp", cvs("import","-m","initial import", "test", "vendor_tag", "initial_import")), 0, false, false) + +-- change the repository in various ways +check(mtn_cvs("--branch=testbranch","pull",cvsroot,"test"),0, false,false) + +check(mtn("automate", "heads"), 0, true, false) +canonicalize("stdout") +heads = readfile("stdout") +base = string.sub(heads,0,40) + +check(cvs("co", "test"), 0, false, false) +writefile("test/A","A\nchange\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\n") +check(indir("test", cvs("ci", "-m", "messageA")), 0, false, false) + +check(mtn_cvs("--branch=testbranch","pull",cvsroot,"test"),0, false,false) + +check(mtn("automate", "heads"), 0, true, false) +canonicalize("stdout") +heads = readfile("stdout") +rev1 = string.sub(heads,0,40) + +writefile("test/A","A\ncahnge\nB\nchange\nC\nD\nE\nF\nG\nH\nI\nJ\nK\n") +check(indir("test", cvs("ci", "-m", "messageB")), 0, false, false) + +check(mtn_cvs("--branch=testbranch","pull",cvsroot,"test"),0, false,false) + +check(mtn("automate", "heads"), 0, true, false) +canonicalize("stdout") +heads = readfile("stdout") +rev2 = string.sub(heads,0,40) + +check(mtn("co","--branch=testbranch","test-mtn"),0, false, false) + +check(indir("test-mtn", mtn("up", "-r", base)), 0, false, false) + +writefile("test-mtn/A","A\nB\nC\nchange\nD\nE\nF\nG\nH\nI\nJ\nK\n") +check(indir("test-mtn", mtn("ci", "-m", "mtn-messageC")), 0, false, false) + +writefile("test-mtn/A","A\nB\nC\nchange\nD\nchange\nE\nF\nG\nH\nI\nJ\nK\n") +check(indir("test-mtn", mtn("ci", "-m", "mtn-messageD")), 0, false, false) + +check(indir("test-mtn", mtn("up", "-r", rev1)), 0, false, false) + +writefile("test-mtn/A","A\nchange\nB\nC\nD\nE\nchange\nF\nG\nH\nI\nJ\nK\n") +check(indir("test-mtn", mtn("ci", "-m", "mtn-messageE")), 0, false, false) +writefile("test-mtn/A","A\nchange\nB\nC\nD\nE\nchange\nF\nchange\nG\nH\nI\nJ\nK\n") +check(indir("test-mtn", mtn("ci", "-m", "mtn-messageF")), 0, false, false) + +check(mtn("merge"), 0, false, false) + +check(indir("test-mtn", mtn("up")), 0, false, false) + +writefile("test-mtn/A","A\nB\nC\nD\nE\nF\nG\nchange\nH\nI\nJ\nK\n") +check(indir("test-mtn", mtn("ci", "-m", "mtn-messageG")), 0, false, false) + +writefile("test-mtn/A","A\nB\nC\nD\nE\nF\nG\nchange\nH\nchange\nI\nJ\nK\n") +check(indir("test-mtn", mtn("ci", "-m", "mtn-messageH")), 0, false, false) + + +check(indir("test-mtn", mtn("up", "-r", rev2)), 0, false, false) + +writefile("test-mtn/A","A\ncahnge\nB\nchange\nC\nD\nE\nF\nG\nH\nI\nchange\nJ\nK\n") +check(indir("test-mtn", mtn("ci", "-m", "mtn-messageI")), 0, false, false) + +writefile("test-mtn/A","A\ncahnge\nB\nchange\nC\nD\nE\nF\nG\nH\nI\nchange\nJ\nchange\nK\n") +check(indir("test-mtn", mtn("ci", "-m", "mtn-messageJ")), 0, false, false) + +check(mtn("merge"), 0, false, false) + +check(mtn_cvs("--branch=testbranch","push","--first"),0, false,false) + +check(indir("test", cvs("up")), 0, false, false) + +check(indir("test", cvs("log", "A")), 0, true, false) +canonicalize("stdout") +log = readfile("stdout") + +check(countMatch(log, "messageA") == 1, true, false, false) +check(countMatch(log, "messageB") == 1, true, false, false) +check(countMatch(log, "messageC") == 1, true, false, false) +check(countMatch(log, "messageD") == 1, true, false, false) +check(countMatch(log, "messageE") == 1, true, false, false) +check(countMatch(log, "messageF") == 1, true, false, false) +check(countMatch(log, "messageG") == 1, true, false, false) +check(countMatch(log, "messageH") == 1, true, false, false) +check(countMatch(log, "messageI") == 1, true, false, false) +check(countMatch(log, "messageJ") == 1, true, false, false) + ============================================================ --- mtn_cvs/cvs_sync.cc d63379693f0a74f149378a9889060148378145f1 +++ mtn_cvs/cvs_sync.cc 049fbcc0f335e876801c0437df6658d33c872b61 @@ -1115,6 +1115,112 @@ std::string cvs_repository::gather_merge // TODO: This is broken. What we really want to do is get ancestors of this revision, // and then remove ancestors of the synced revisions. Need to be careful as pushed // revs aren't marked as synced until the end of the sequence of pushes. + + // note that we only want log info for ancestors of id, not for id itself. + +#warning fix the gathering of log information when pushing merge nodes + + // or - topologically ordered search back from the head (like find last sync) + // mark nodes that are ancestors of a sync node during the search + // mark nodes that are ancestors of the rev_id during the search + // stop when there are no ancestors of the rev_id that are not also + // ancestors of a sync node. (and after you've seen rev_id) + // need to add a new argument to pass an "unmarked already synced node" if we're + // pushing a whole string of nodes at once. + // could possibly do this search once for the whole push, rather than repeat for + // each node - but that's an advanced option. + + std::vector heads; + std::set nodes_checked; + std::set synced(known_synced); + std::set ancestor; + heads=app.heads(app.opts.branch_name()); + revision_id rid; + string result; + + ancestor.insert(id); + bool found_id = false; + + // heads contains the nodes who have had all their decendents checked + + if (heads.empty()) + return result; + + while (!heads.empty()) + { + bool more_search = false; + for (uint i=0; i certs=app.get_revision_certs(rid); + std::string author,changelog; + time_t date=0; + 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_cert_name_s) + { date=cvs_repository::posix2time_t(j->value); + } + else if (j->name==author_cert_name_s) + { author=j->value; + } + else if (j->name==changelog_cert_name_s) + { changelog=j->value; + } + } + result+="-------------------\n" + +changelog+"\nmonotone "+author+" " + +cvs_client::time_t2rfc822(date)+" "+rid.inner()()+"\n"; + } + + // add to heads all parents (i) whose children (j) have all been checked + // each node will be added just after its last child is checked + std::vector parents=app.get_revision_parents(rid); + for (std::vector::const_iterator i=parents.begin(); + i!=parents.end(); ++i) + { + if (ancestor.find(rid) != ancestor.end()) + ancestor.insert(*i); // your parent is an ancestor if you were + if (synced.find(rid) != synced.end()) + synced.insert(*i); // your parent is synced if you were + std::vector children = app.get_revision_children(*i); + std::vector::const_iterator j; + for (j=children.begin(); j!=children.end(); ++j) + { + if (nodes_checked.find(*j) != nodes_checked.end()) + continue; + if (!app.in_branch(*j, app.opts.branch_name())) + continue; + + break; + } + if (j == children.end()) + heads.push_back(*i); + } + } + +#if 0 std::vector parents=app.get_revision_parents(id); std::string result; for (std::vector::const_iterator i=parents.begin();i!=parents.end();++i) @@ -1155,6 +1261,7 @@ std::string cvs_repository::gather_merge +cvs_client::time_t2rfc822(date)+" "+i->inner()()+"\n"; result+=gather_merge_information(*i); } +#endif return result; } @@ -1252,6 +1359,7 @@ void cvs_repository::commit() } P(F("checked %s into cvs repository") % next); + known_synced.insert(now_iter->revision); update_sync_state(sync_state, now_iter); update_sync_info = true; ============================================================ --- mtn_cvs/cvs_sync.hh ca1c58a8bd8442a6ce10a88c3311f31350c1eba0 +++ mtn_cvs/cvs_sync.hh 3ddc4a1afe54846745f3c46f5e339a4e0946de14 @@ -129,6 +129,9 @@ private: std::set remove_set; // remove_state lives here cvs_file_state remove_state; + // for gathering merge information + std::set known_synced; // for revs that we have synced, but not marked as synced yet + time_t sync_since; public: