private bool RenameLog(RefUpdate src, RefUpdate dst) { FilePath srcLog = refdb.GetLogWriter().LogFor(src.GetName()); FilePath dstLog = refdb.GetLogWriter().LogFor(dst.GetName()); if (!srcLog.Exists()) { return(true); } if (!Rename(srcLog, dstLog)) { return(false); } try { int levels = RefDirectory.LevelsIn(src.GetName()) - 2; RefDirectory.Delete(srcLog, levels); return(true); } catch (IOException) { Rename(dstLog, srcLog); return(false); } }
/// <exception cref="System.IO.IOException"></exception> protected internal override RefUpdate.Result DoDelete(RefUpdate.Result status) { if (GetRef().GetLeaf().GetStorage() != RefStorage.NEW) { database.Delete(this); } return(status); }
/// <exception cref="System.IO.IOException"></exception> protected internal override RefUpdate.Result DoRename() { if (source.GetRef().IsSymbolic()) { return(RefUpdate.Result.IO_FAILURE); } // not supported objId = source.GetOldObjectId(); updateHEAD = NeedToUpdateHEAD(); tmp = refdb.NewTemporaryUpdate(); RevWalk rw = new RevWalk(refdb.GetRepository()); try { // First backup the source so its never unreachable. tmp.SetNewObjectId(objId); tmp.SetForceUpdate(true); tmp.DisableRefLog(); switch (tmp.Update(rw)) { case RefUpdate.Result.NEW: case RefUpdate.Result.FORCED: case RefUpdate.Result.NO_CHANGE: { break; } default: { return(tmp.GetResult()); break; } } // Save the source's log under the temporary name, we must do // this before we delete the source, otherwise we lose the log. if (!RenameLog(source, tmp)) { return(RefUpdate.Result.IO_FAILURE); } // If HEAD has to be updated, link it now to destination. // We have to link before we delete, otherwise the delete // fails because its the current branch. RefUpdate dst = destination; if (updateHEAD) { if (!LinkHEAD(destination)) { RenameLog(tmp, source); return(RefUpdate.Result.LOCK_FAILURE); } // Replace the update operation so HEAD will log the rename. dst = ((RefDirectoryUpdate)refdb.NewUpdate(Constants.HEAD, false)); dst.SetRefLogIdent(destination.GetRefLogIdent()); dst.SetRefLogMessage(destination.GetRefLogMessage(), false); } // Delete the source name so its path is free for replacement. source.SetExpectedOldObjectId(objId); source.SetForceUpdate(true); source.DisableRefLog(); if (source.Delete(rw) != RefUpdate.Result.FORCED) { RenameLog(tmp, source); if (updateHEAD) { LinkHEAD(source); } return(source.GetResult()); } // Move the log to the destination. if (!RenameLog(tmp, destination)) { RenameLog(tmp, source); source.SetExpectedOldObjectId(ObjectId.ZeroId); source.SetNewObjectId(objId); source.Update(rw); if (updateHEAD) { LinkHEAD(source); } return(RefUpdate.Result.IO_FAILURE); } // Create the destination, logging the rename during the creation. dst.SetExpectedOldObjectId(ObjectId.ZeroId); dst.SetNewObjectId(objId); if (dst.Update(rw) != RefUpdate.Result.NEW) { // If we didn't create the destination we have to undo // our work. Put the log back and restore source. if (RenameLog(destination, tmp)) { RenameLog(tmp, source); } source.SetExpectedOldObjectId(ObjectId.ZeroId); source.SetNewObjectId(objId); source.Update(rw); if (updateHEAD) { LinkHEAD(source); } return(dst.GetResult()); } return(RefUpdate.Result.RENAMED); } finally { // Always try to free the temporary name. try { refdb.Delete(tmp); } catch (IOException) { FileUtils.Delete(refdb.FileFor(tmp.GetName())); } rw.Release(); } }