If many components are changed simultaneously (in the same patch) along a file path, moving them is confusing, especially since swaps (a → b and b → a in the same patch) must be handled properly.
This fix takes care of this by introducing a map to remember which files were moved to a temporary location, and using that map instead of fs::inode_filename to get the temporary path instead of the actual one.
C5MZXLVCVS6JVFYUASM4YH7KCC75D2BH3ARTJ5WCRAVEDQIQSSEQC 3QXUJMZDPH2EDJY6UXIRA5ZQK3GRS2R422S7CKN56I36O4POAQXQC PEUUYRZ5MHYM2IQTN3ASXPIFZSK5KI32LIHWM6RIWVRRXIQ5GTNQC SXEYMYF7P4RZMZ46WPL4IZUTSQ2ATBWYZX7QNVMS3SGOYXYOHAGQC RMDMAYRXYBU5OQXV5HSF6LFD4NBMKRNH5EPIVW3K5HAV6D56IG6QC HBUMCAFVS4W5FHWNZR7ITJFEEUCVZ4Q2U4KGWYN7XZGDZ75JMFTQC ZDK3GNDBWXJ2OXFDYB72ZCEBGLBF4MKE5K3PVHDZATHJ7HJIDPRQC VNBLGT6GAN2AHKRFKTKED7WNDDRGNULY5H343ZYV3ETSDZZKGBTAC 2RXOCWUWOGHEKHT5W73LAHJSOZVRTOGS7BWLSIGEEEBJGMCZBXQAC FXEDPLRI7PXLDXV634ZA6D5Q3ZWG3ESTKJTMRPJ4MAHI7PKU3M6AC I24UEJQLCH2SOXA4UHIYWTRDCHSOPU7AFTRUOTX7HZIAV4AZKYEQC CCLLB7OIFNFYJZTG3UCI7536TOCWSCSXR67VELSB466R24WLJSDAC VO5OQW4W2656DIYYRNZ3PO7TQ4JOKQ3GVWE5ALUTYVMX3WMXJOYQC YCEZL7VFBZNOZTSSI24D36ACJVZKXCCEOIFWIHQWK22QPB4PDTRAC YN63NUZO4LVJ7XPMURDULTXBVJKW5MVCTZ24R7Z52QMHO3HPDUVQC for (a, b) in state.actual_moves.iter() {
// Since we did a depth-first search of the output paths, we need// to move in reverse order of the search.for (a, b) in state.actual_moves.iter().rev() {debug!("actual move: {:?} {:?}", a, b);
if let Some(ref current_name) = inode_filename(&*txn_, inode)? {debug!("current_name = {:?}, path = {:?}", current_name, path);if current_name != path {
if let Some(ref current_name) = inode_filename(&*txn_, inode, move_map)? {let actual_path = if let Some(tmp) = tmp.take() {Cow::Owned(tmp)} else {Cow::Borrowed(path)};debug!("current_name = {:?}, path = {:?}, actual_path = {:?}",current_name, path, actual_path);if current_name.as_str() != &actual_path {
actual_moves.push((tmp_path, path.to_string()));
let mut tmp_ = actual_path.to_string();crate::path::pop(&mut tmp_);crate::path::push(&mut tmp_, &s);debug!("rename {:?} {:?}", current_name, tmp_);repo.rename(¤t_name, &tmp_).map_err(OutputError::WorkingCopy)?;move_map.insert(inode, tmp_.to_string());actual_moves.push((tmp_.to_string(), actual_path.to_string()));*tmp = Some(tmp_);
}fn inode_filename<T: TreeTxnT>(txn: &T,inode: Inode,tmp: &HashMap<Inode, String>,) -> Result<Option<String>, TreeErr<T::TreeError>> {debug!("inode_filename {:?}", inode);let mut components = Vec::new();let mut current = inode;loop {if let Some(tmp) = tmp.get(¤t) {components.push(SmallString::from_str(tmp));break;}match txn.get_revtree(¤t, None)? {Some(v) => {components.push(v.basename.to_owned());current = v.parent_inode;if current == Inode::ROOT {break;}}None => {debug!("filename_of_inode: not in tree");return Ok(None);}}}let mut path = String::new();for c in components.iter().rev() {if !path.is_empty() {path.push('/')}path.push_str(c.as_str());}debug!("inode_filename = {:?}", path);Ok(Some(path))