# # # patch "rcs_import.cc" # from [8ee1249aab9cb258c808ad0afe117815b7d67ab2] # to [2c3a2f2133417e92823956d72bddeabc19aa7043] # ============================================================ --- rcs_import.cc 8ee1249aab9cb258c808ad0afe117815b7d67ab2 +++ rcs_import.cc 2c3a2f2133417e92823956d72bddeabc19aa7043 @@ -30,6 +30,7 @@ #include #include #include +#include #include "app_state.hh" #include "cert.hh" @@ -1159,13 +1160,13 @@ protected: : public boost::dfs_visitor<> { protected: + shared_ptr< cvs_branch > branch; vector< MyEdge > & back_edges; - cvs_branch & branch; public: - blob_splitter(cvs_branch & b, vector< MyEdge > & be) - : back_edges(be), - branch(b) + blob_splitter(shared_ptr< cvs_branch > b, vector< MyEdge > & be) + : branch(b), + back_edges(be) { } template < class Edge, class Graph > @@ -1228,7 +1229,7 @@ typedef boost::adjacency_list< boost::ve typedef pair< cvs_blob_index, cvs_blob_index > Edge; typedef boost::adjacency_list< boost::vecS, boost::vecS, - boost::directedS > Graph; + boost::bidirectionalS > Graph; void add_blob_dependency_edges(shared_ptr const & branch, @@ -1264,7 +1265,7 @@ split_blobs_at(shared_ptr co // we can only split commit events, not branches or tags I(target_blob_digest.is_commit()); - vector< cvs_event_ptr > & blob_events(branch->blobs[e.second].get_events()); + vector< cvs_event_ptr > blob_events(branch->blobs[e.second].get_events()); // sort the blob events by timestamp sort(blob_events.begin(), blob_events.end()); @@ -1292,20 +1293,94 @@ split_blobs_at(shared_ptr co L(FL("max. time difference is: %d") % max_diff); + // add a blob + cvs_event_digest d = branch->blobs[e.second].get_digest(); + cvs_blob_index new_blob = branch->add_blob(d)->second; + + // reassign all events and split into the two blobs + branch->blobs[e.second].get_events().clear(); + I(!blob_events.empty()); + I(branch->blobs[e.second].empty()); + for (i = blob_events.begin(); i != blob_events.end(); ++i) - { - if ((*i)->time < (*max_at)->time) - { - L(FL("before split: %d (time: %d)") % (*i)->path % (*i)->time); - } - else - { - L(FL("after split: %d (time: %d)") % (*i)->path % (*i)->time); - } - } + if ((*i)->time >= (*max_at)->time) + branch->blobs[new_blob].push_back(*i); + else + branch->blobs[e.second].push_back(*i); - // TODO - I(false); + { + // in edges, blobs which depend on this one blob we should split + pair< boost::graph_traits::in_edge_iterator, + boost::graph_traits::in_edge_iterator > range; + + range = in_edges(e.second, g); + + vector< cvs_blob_index > in_deps_from; + + // get all blobs with dependencies to the blob which has been split + for (boost::graph_traits::in_edge_iterator ity = range.first; + ity != range.second; ++ity) + { + L(FL("removing in edge %s") % *ity); + in_deps_from.push_back(ity->m_source); + I(ity->m_target == e.second); + } + + // remove all those edges + for (vector< cvs_blob_index >::const_iterator ity = in_deps_from.begin(); + ity != in_deps_from.end(); ++ity) + remove_edge(*ity, e.second, const_cast(g)); + + // now check each in_deps_from blob and add proper edges to the + // newly splitted blobs + for (vector< cvs_blob_index >::const_iterator ity = in_deps_from.begin(); + ity != in_deps_from.end(); ++ity) + { + cvs_blob & other_blob = branch->blobs[*ity]; + + for (vector< cvs_event_ptr >::const_iterator j = + other_blob.get_events().begin(); + j != other_blob.get_events().end(); ++j) + { + for (dependency_iter ob_dep = (*j)->dependencies.begin(); + ob_dep != (*j)->dependencies.end(); ++ob_dep) + + if ((*ob_dep)->get_digest() == d) + { + if ((*ob_dep)->time >= (*max_at)->time) + { + L(FL("adding new edge %d -> %d") % *ity % new_blob); + add_edge(*ity, new_blob, const_cast(g)); + } + else + { + L(FL("keeping edge %d -> %d") % *ity % new_blob); + add_edge(*ity, e.second, const_cast(g)); + } + } + } + } + } + + // adjust out edges of the new blob + { + // in edges, blobs which depend on this one blob which we are splitting + pair< boost::graph_traits::out_edge_iterator, + boost::graph_traits::out_edge_iterator > range; + + range = out_edges(e.second, g); + + // remove all existing out edges + for (boost::graph_traits::out_edge_iterator ity = range.first; + ity != range.second; ++ity) + { + L(FL("removing out edge %s") % *ity); + remove_edge(ity->m_source, ity->m_target, const_cast(g)); + } + + add_blob_dependency_edges(branch, e.second, const_cast(g)); + add_blob_dependency_edges(branch, new_blob, const_cast(g)); + } } // @@ -1331,14 +1406,17 @@ resolve_blob_dependencies(cvs_history &c // check for cycles vector< Edge > back_edges; - blob_splitter< Edge > vis(*branch, back_edges); + blob_splitter< Edge > vis(branch, back_edges); do { + back_edges.clear(); depth_first_search(g, visitor(vis)); - for (vector< Edge >::const_iterator i = back_edges.begin(); - i != back_edges.end(); ++i) - split_blobs_at(branch, *i, g); + + // Just split the first blob which had a back edge + if (back_edges.begin() != back_edges.end()) + split_blobs_at(branch, *back_edges.begin(), g); + } while (!back_edges.empty()); // start the topological sort, which calls our revision