# # patch "cvs_client.cc" # from [6125cb5e67f1cb877f47744dd54b1a64795bb3dc] # to [b7ed7222b2bf94ae75be590aaf351e4287fab4d7] # # patch "cvs_client.hh" # from [e2dcc908c5e48b7db93d1b36df9796d87f0cb5d3] # to [bd10bec52ff75979a0ca78686c87743561ee38ee] # # patch "cvs_sync.cc" # from [f7e191205f465fb1a4bfe06fccccb348cb443827] # to [814b63c49ddc2fa040d2ddc0e5a6ac51cca695e1] # # patch "tests/t_cvspull_cvsbranch.at" # from [b89bed1bc2c4694199356f414b65cb1afca18b82] # to [f1a3b5a55047f026a496940e4b5a5d8a413f1409] # ======================================================================== --- cvs_client.cc 6125cb5e67f1cb877f47744dd54b1a64795bb3dc +++ cvs_client.cc b7ed7222b2bf94ae75be590aaf351e4287fab4d7 @@ -136,6 +136,12 @@ writestr(cmd+std::string("\n")); } +void cvs_client::SendCommand(std::string const& cmd, std::vector const&args) +{ for (std::vector::const_iterator i=args.begin();i!=args.end();++i) + writestr("Argument "+*i+"\n"); + writestr(cmd+"\n"); +} + bool cvs_client::begins_with(const std::string &s, const std::string &sub, unsigned &len) { std::string::size_type sublen=sub.size(); if (s.size()old_revision.empty()) { std::string bname=basename(i->file); - writestr("Entry /"+bname+"/"+i->old_revision+"//"+i->keyword_substitution+"/\n"); + std::string branchpart; + if (!branch.empty()) branchpart="T"+branch; + writestr("Entry /"+bname+"/"+i->old_revision+"//" + +i->keyword_substitution+"/"+branchpart+"\n"); writestr("Unchanged "+bname+"\n"); } -// else I(file_revisions.size()==1); // this is only designed to work this way } if (file_revisions.size()==1 && !file_revisions.begin()->new_revision.empty()) - { if (file_revisions.begin()->old_revision.empty()) - SendCommand("update","-d","-C","-A", - "-r",file_revisions.begin()->new_revision.c_str(), - "--",basename(file_revisions.begin()->file).c_str(),(void*)0); + { std::vector args; + args.push_back("-d"); // create new directories + args.push_back("-C"); // ignore previous context + if (file_revisions.begin()->old_revision.empty()) + { + if (branch.empty()) + args.push_back("-A"); + } else - SendCommand("update","-d","-C","-u", - "-r",file_revisions.begin()->new_revision.c_str(), - "--",basename(file_revisions.begin()->file).c_str(),(void*)0); + args.push_back("-u"); // send back diff + args.push_back("-r"); + args.push_back(file_revisions.begin()->new_revision); + args.push_back(file_revisions.begin()->file); + SendCommand(std::string("update"),args); } else - { // needed for 1.11 - Directory("."); - SendCommand("update","-d","-C","-u",(void*)0); + { std::vector args; + args.push_back("-d"); // create new directories + args.push_back("-C"); // ignore previous context + args.push_back("-u"); // send back diff + if (!branch.empty()) + args.push_back("-r"+branch); + Directory("."); // needed for 1.11 + SendCommand(std::string("update"),args); } std::vector > lresult; std::string dir,dir2,rcsfile; enum { st_normal, st_merge } state=st_normal; - std::vector bugged; while (fetch_result(lresult)) { I(!lresult.empty()); unsigned len=0; @@ -1185,12 +1203,8 @@ if (result.file[0]=='/') result.file=rcs_file2path(result.file); result.contents=lresult[6].second; // strictly this is unnecessary ... parse_entry(lresult[3].second,result.new_revision,result.keyword_substitution); - W(F("Update ->%s of %s exposed CVS bug\n") + E(false, F("Update ->%s of %s exposed CVS bug\n") % result.new_revision % result.file); - bugged.push_back(update_args(result.file,std::string(), - result.new_revision,result.keyword_substitution)); - result=update(); - state=st_normal; } else if (lresult[0].second=="error") { I(state==st_merge); @@ -1238,23 +1252,6 @@ { W(F("Update: unrecognized response %s\n") % lresult[0].second); } } - -// cater for encountered bugs ... -// actually this code should not be necessary with the current options -// without -C some revisions interacted with each other badly - for (std::vector::const_iterator i=bugged.begin(); - i!=bugged.end();++i) - { result=update(); - checkout result2=CheckOut(i->file,i->new_revision); - result.contents=result2.contents; - result.patch=std::string(); - result.checksum=std::string(); - result.removed=result2.dead; - result.new_revision=i->new_revision; - result.keyword_substitution=result2.keyword_substitution; - result.file=i->file; - cb(result); - } } void cvs_client::parse_entry(const std::string &line, std::string &new_revision, @@ -1284,8 +1281,11 @@ Directory(olddir); } std::string bname=basename(i->file); + std::string branchpart; + if (!branch.empty()) branchpart="T"+branch; writestr("Entry /"+bname+"/"+(i->removed?"-":"") - +i->old_revision+"//"+i->keyword_substitution+"/\n"); + +i->old_revision+"//"+i->keyword_substitution+"/" + +branchpart+"\n"); if (!i->removed) { writestr("Checkin-time "+time_t2rfc822(when)+"\n"); writestr("Modified "+bname+"\n"); ======================================================================== --- cvs_client.hh e2dcc908c5e48b7db93d1b36df9796d87f0cb5d3 +++ cvs_client.hh bd10bec52ff75979a0ca78686c87743561ee38ee @@ -112,6 +112,7 @@ void SendCommand(const char *cmd,...); void SendCommand(const char *cmd, va_list ap); + void SendCommand(std::string const& cmd, std::vector const&args); void SendArgument(const std::string &a); // false if none available bool fetch_result(std::string &result); ======================================================================== --- cvs_sync.cc f7e191205f465fb1a4bfe06fccccb348cb443827 +++ cvs_sync.cc 814b63c49ddc2fa040d2ddc0e5a6ac51cca695e1 @@ -655,15 +655,10 @@ I(srev.is_parent_of(s2->cvs_version)); if (s->dead) { -#if 0 - cvs_client::checkout c=CheckOut2(file,s2->cvs_version); - I(!c.dead); // dead->dead is no change, so shouldn't get a number -#else // this might fail (?) because we issued an Entry somewhere above // but ... we can specify the correct directory! cvs_client::update c=Update(file,s2->cvs_version); - I(!c.removed); -#endif + I(!c.removed); // dead->dead is no change, so shouldn't get a number I(!s2->dead); // I(s2->since_when==c.mod_time); if (c.mod_time!=s2->since_when && c.mod_time!=-1 && s2->since_when!=sync_since) @@ -738,7 +733,9 @@ { std::set::iterator next_edge=e; ++next_edge; for (std::map::const_iterator f=files.begin();f!=files.end();++f) - { I(!f->second.known_states.empty()); + { I(!branch.empty() || !f->second.known_states.empty()); + // this file does not belong to this branch + if (f->second.known_states.empty()) continue; if (!(*(f->second.known_states.begin()) <= (*e))) // the file does not exist yet (first is not below/equal current edge) { L(F("%s before beginning %d/%d+%d\n") % f->first @@ -746,15 +743,6 @@ % e->time % (e->time2-e->time)); continue; } -#if 0 - if ((*(f->second.known_states.rend()) < (*e))) - // the last revision was already processed (it remains this state) - { W(F("%s beyond end %d/%d+%d\n") % f->first - % f->second.known_states.rend()->since_when - % e->time % (e->time2-e->time)); - continue; - } -#endif cvs_manifest::iterator mi=current_manifest.find(f->first); if (mi==current_manifest.end()) // the file is currently dead { cvs_file_state s=f->second.known_states.end(); @@ -901,14 +889,14 @@ { std::vector args; if (!branch.empty()) - { args.push_back("-r"); - args.push_back(branch); - } + args.push_back("-r"+branch); + else + args.push_back("-b"); + if (sync_since!=-1) { args.push_back("-d"); size_t date_index=args.size(); args.push_back(time_t2rfc822(sync_since)); - args.push_back("-b"); // state _at_ this point in time Log(prime_log_cb(*this,i,sync_since),i->first,args); // -d Jun 20 09:38:29 1997< @@ -917,9 +905,7 @@ Log(prime_log_cb(*this,i,sync_since),i->first,args); } else - { args.push_back("-b"); Log(prime_log_cb(*this,i),i->first,args); - } } // remove duplicate states (because some edges were added by the // get_all_files method) @@ -941,7 +927,8 @@ // get the contents for (std::map::iterator i=files.begin();i!=files.end();++i) { std::string file_contents; - I(!i->second.known_states.empty()); + I(!branch.empty() || !i->second.known_states.empty()); + if (!i->second.known_states.empty()) { std::set::iterator s2=i->second.known_states.begin(); cvs_client::update c=Update(i->first,s2->cvs_version); store_checkout(s2,c,file_contents); @@ -956,14 +943,6 @@ } drop_connection(); -#if 0 - if (sync_since!=-1 && edges.empty() && !files.empty()) - // no change happened since sync_since, so we didn't see an edge, - // fake one - { cvs_edge new_edge("initial state for cvs_pull --since",sync_since,app.signing_key()); - edges.insert(new_edge); - } -#endif // fill in file states at given point fill_manifests(edges.begin()); ======================================================================== --- tests/t_cvspull_cvsbranch.at b89bed1bc2c4694199356f414b65cb1afca18b82 +++ tests/t_cvspull_cvsbranch.at f1a3b5a55047f026a496940e4b5a5d8a413f1409 @@ -33,6 +33,7 @@ AT_CHECK(mkdir cvstemp) AT_CHECK(cp d_import cvstemp/A) +AT_CHECK(cp d_import cvstemp/A2) AT_CHECK([cd cvstemp ; cvs -q -d $CVSROOT import -m 'initial import' test vendor_tag initial_import], [], [ignore], [ignore]) # change the repository in various ways @@ -40,7 +41,9 @@ AT_CHECK([cvs -q -d $CVSROOT co test], [], [ignore], [ignore]) AT_CHECK([cd test;cvs -Q tag -b branch]) AT_CHECK(cp d_add test/B) +AT_CHECK(cp d_add test/B2) AT_CHECK([cd test;cvs -Q add B]) +AT_CHECK([cd test;cvs -Q add B2]) AT_CHECK([sleep 1;cd test;cvs -Q ci -m 'B added to HEAD']) AT_CHECK([cd test;cvs update -r branch], [], [ignore], [ignore]) @@ -67,18 +70,19 @@ # check presence of files -#AT_CHECK(MONOTONE automate get_file $TSHA0, [], [ignore]) +AT_CHECK(MONOTONE automate get_file $TSHA0, [], [ignore]) #AT_CHECK(MONOTONE automate get_file $TSHA1, [], [ignore]) -#AT_CHECK(MONOTONE automate get_file $TSHA2, [], [ignore]) -#AT_CHECK(MONOTONE automate get_file $TSHA3, [], [ignore]) -#AT_CHECK(MONOTONE automate get_file $TSHA4, [], [ignore]) +AT_CHECK(MONOTONE automate get_file $TSHA2, [], [ignore]) +AT_CHECK(MONOTONE automate get_file $TSHA3, [], [ignore]) +AT_CHECK(MONOTONE automate get_file $TSHA4, [], [ignore]) # also check that history is okay -- has a unique head, and it's the # right one. -#AT_CHECK(MONOTONE checkout --branch=testbranch mtcodir, [], [ignore], [ignore]) -#AT_CHECK(cmp d_readd mtcodir/A) -#AT_CHECK(cmp d_change mtcodir/B) -#AT_CHECK(cmp d_subdir mtcodir/dir/D) +AT_CHECK(MONOTONE checkout --branch=testbranch mtcodir, [], [ignore], [ignore]) +AT_CHECK(cmp d_import mtcodir/A2) +AT_CHECK(cmp d_readd mtcodir/A) +AT_CHECK(cmp d_change mtcodir/B) +AT_CHECK(cmp d_subdir mtcodir/dir/D) AT_CLEANUP