# # # add_dir "tests/importing_cvs_cycle_splitter3" # # add_dir "tests/importing_cvs_cycle_splitter3/cvs-repository" # # add_dir "tests/importing_cvs_cycle_splitter3/cvs-repository/test" # # add_file "tests/importing_cvs_cycle_splitter3/__driver__.lua" # content [69dec946a87a8eeb249be59d689faeba4eabd1d9] # # add_file "tests/importing_cvs_cycle_splitter3/cvs-repository/test/file1,v" # content [fdf75664034555e2c2f3f37ee47057006ead3d01] # # add_file "tests/importing_cvs_cycle_splitter3/cvs-repository/test/file2,v" # content [4eae152c176b7c28fb4a617d786846bd5ac15b8a] # # patch "rcs_import.cc" # from [302387a9afb2cca447b6ba8ff39e16cb6ed0617f] # to [148f7910bcafa607dff95625174272da46f6b6a7] # ============================================================ --- tests/importing_cvs_cycle_splitter3/__driver__.lua 69dec946a87a8eeb249be59d689faeba4eabd1d9 +++ tests/importing_cvs_cycle_splitter3/__driver__.lua 69dec946a87a8eeb249be59d689faeba4eabd1d9 @@ -0,0 +1,15 @@ + +mtn_setup() + +check(get("cvs-repository")) + +-- A carefully handcrafted CVS repository, exercising the cycle splitter: We +-- have two commits and a branch start in between. The silly thing being, +-- that the ordering is reversed, so we end up with a cycle involving those +-- two commits as well as the branch start. +-- +-- For additional cruelty, all commits have equal timestamps. + +-- import into monotone and check presence of files +check(mtn("--branch=test", "cvs_import", "--debug", "cvs-repository/test"), 0, false, false) + ============================================================ --- tests/importing_cvs_cycle_splitter3/cvs-repository/test/file1,v fdf75664034555e2c2f3f37ee47057006ead3d01 +++ tests/importing_cvs_cycle_splitter3/cvs-repository/test/file1,v fdf75664034555e2c2f3f37ee47057006ead3d01 @@ -0,0 +1,44 @@ +head 1.1; +access; +symbols + CONFLICTING_BRANCH:1.1; +locks; strict; +comment @# @; + + +1.2 +date 2008.04.29.19.18.49; author markus; state Exp; +branches + 1.1.2.1; +next ; + +1.1 +date 2008.04.29.19.18.49; author markus; state Exp; +branches; +next ; + + +desc +@@ + + +1.2 +log address@hidden A +@ +text address@hidden 1.2 of test file1 +@ + + +1.1 +log address@hidden B +@ +text address@hidden 1 +a1 1 +version 1.1 of test file1 +@ + + ============================================================ --- tests/importing_cvs_cycle_splitter3/cvs-repository/test/file2,v 4eae152c176b7c28fb4a617d786846bd5ac15b8a +++ tests/importing_cvs_cycle_splitter3/cvs-repository/test/file2,v 4eae152c176b7c28fb4a617d786846bd5ac15b8a @@ -0,0 +1,44 @@ +head 1.1; +access; +symbols + CONFLICTING_BRANCH:1.1.0.2; +locks; strict; +comment @# @; + + +1.1 +date 2008.04.29.19.18.49; author markus; state Exp; +branches + 1.1.2.1; +next ; + +1.1.2.1 +date 2008.04.29.19.18.49; author markus; state Exp; +branches; +next ; + + +desc +@@ + + +1.1 +log address@hidden A +@ +text address@hidden 1.1 of test file2 +@ + + +1.1.2.1 +log address@hidden B +@ +text address@hidden 1 +a1 1 +version 1.1.2.1 of test file2 +@ + + ============================================================ --- rcs_import.cc 302387a9afb2cca447b6ba8ff39e16cb6ed0617f +++ rcs_import.cc 148f7910bcafa607dff95625174272da46f6b6a7 @@ -3298,12 +3298,18 @@ split_cycle(cvs_history & cvs, set< cvs_ L(FL("choosing a blob to split (out of %d blobs)") % cycle_members.size()); + set symbol_blobs; typedef set::const_iterator cm_ity; // find the oldest event in the cycle time_i oldest_event_in_cycle = 0; for (cm_ity cc = cycle_members.begin(); cc != cycle_members.end(); ++cc) { + // tags shouldn't ever occur in cycles, because no other event ever + // depends on a tag or branch end event + I(!cvs.blobs[*cc].get_digest().is_tag()); + I(!cvs.blobs[*cc].get_digest().is_branch_end()); + time_i bt(cvs.blobs[*cc].get_oldest_event_time()); if ((oldest_event_in_cycle == 0) || (bt < oldest_event_in_cycle)) @@ -3322,6 +3328,10 @@ split_cycle(cvs_history & cvs, set< cvs_ cvs.blobs[*cc].get_digest().is_tag()) continue; + // remember symbol blobs + if (cvs.blobs[*cc].get_digest().is_symbol()) + symbol_blobs.insert(*cc); + // make sure the blob's events are sorted by timestamp cvs.blobs[*cc].sort_events(); vector< cvs_event_ptr > & blob_events = cvs.blobs[*cc].get_events(); @@ -3372,6 +3382,12 @@ split_cycle(cvs_history & cvs, set< cvs_ return; } + // Otherwise, there might be a symbol blob in the cycle. If so, we + // split that one. + if (!symbol_blobs.empty()) + W(F("FIXME: we should better favor splitting one of the %d symbol " + "blobs in the cycle.") % symbol_blobs.size()); + // If we get here, there's no gap in any of the blobs in the cycle, // thus we must decide on a blob to split by other means. @@ -3388,6 +3404,10 @@ split_cycle(cvs_history & cvs, set< cvs_ cvs.blobs[*cc].get_digest().is_tag()) continue; + // we cannot split blobs which consist of only one event + if (cvs.blobs[*cc].get_events().size() <= 1) + continue; + // loop over every event of every blob in cycle_members int count_independent_events = 0; int count_total_events = 0; @@ -3446,8 +3466,10 @@ split_cycle(cvs_history & cvs, set< cvs_ count_independent_events++; } - if (count_independent_events >= count_total_events) - W(F("split_cycle: no dependencies to any cycle member!")); + // every blob in cycle_members must have at least one event which + // depends on another blob of the cycle. Otherwise, it wouldn't be + // part of the cycle. + I(count_independent_events < count_total_events); float ir = (float) count_independent_events / count_total_events; if (ir > most_independent_events)