/* Follow a path's history, invoking commands whenever the path is patched or added. Copyright (C) 2005 Walter Landry This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "boost/filesystem/operations.hpp" #include "Parsed_Name.hpp" #include "Patch_Log.hpp" #include "Temp_Directory.hpp" #include "make_patch.hpp" #include "find_or_make_pristine.hpp" #include "Patch_Info.hpp" template void follow_path(T &functor, const std::string &path_string, const Parsed_Name &start_name, const boost::filesystem::path &root, const int &path_type) { Parsed_Name name(start_name); bool done=false; std::string current_name(path_string), suffix; if(path_type==arx_file) { suffix="-files"; } else { suffix="-directories"; } { /* First, we have to check for local modifications */ Temp_Directory local_diff(root,"diff"); make_patch(find_or_make_pristine(root,local_diff.path/"pristine",name), root,local_diff.path/"patch",Path_List()); /* If there is a patch, then parse the patch. */ Patch_Info patch_info(local_diff.path/"patch",false,false,"",""); if(exists(local_diff.path/"patch"/"patches"/(current_name+".patch"))) { functor.patch(current_name,"local",local_diff.path/"patch"); } /* If it has moved, then we need to change the name. */ for(std::list >::iterator i=patch_info.moved[path_type].begin(); i!=patch_info.moved[path_type].end(); ++i) { if(i->second==current_name) { functor.rename("local"); current_name=i->first; break; } } /* If it has been added, then we are done. */ for(std::list::iterator i=patch_info.mod_only[path_type].begin(); i!=patch_info.mod_only[path_type].end(); ++i) { if(*i==current_name) { functor.add("local"); done=true; break; } } } /* Get annotations from all of the regular patches. */ while(!done) { /* Read patch log from the tree. It is more reliable to read it from the archive, but can also be much slower. */ Patch_Log log(root,name); /* Check whether the path is added in this patch. If so, then we can stop now */ if(log.header_lists.find("New"+suffix)!=log.header_lists.end() && find(log.header_lists["New"+suffix].begin(), log.header_lists["New"+suffix].end(),current_name) !=log.header_lists["New"+suffix].end()) { /* Invoke the hook for adding the path. */ functor.add(name); done=true; } else { /* Check whether the path is patched */ if(log.header_lists.find("Modified"+suffix)!=log.header_lists.end()) { if(find(log.header_lists["Modified"+suffix].begin(), log.header_lists["Modified"+suffix].end(), current_name)!=log.header_lists["Modified"+suffix].end()) { /* Invoke the hook for patching the path */ functor.patch(current_name,name); } } /* Check whether the path is renamed */ if(log.rename_lists.find("Renamed"+suffix)!=log.rename_lists.end()) { for(std::list >::iterator i=log.rename_lists["Renamed"+suffix].begin(); i!=log.rename_lists["Renamed"+suffix].end(); ++i) { if(i->second==current_name) { functor.rename(name); current_name=i->first; } } } /* Check for continuations. */ if(log.headers.find("Continuation-of")!=log.headers.end()) { name=Parsed_Name(log.headers["Continuation-of"]); } else if(name.patch_number()!=0) { --name; } else { /* We have no farther that we can go */ functor.finish(); done=true; } } } }