public void stored(RefDirectoryUpdate update, long modified)
        {
            ObjectId target = update.getNewObjectId().Copy();
            Ref      leaf   = update.getRef().getLeaf();

            putLooseRef(new LooseUnpeeled(modified, leaf.getName(), target));
        }
        public void delete(RefDirectoryUpdate update)
        {
            Ref    dst  = update.getRef().getLeaf();
            string name = dst.getName();

            // Write the packed-refs file using an atomic update. We might
            // wind up reading it twice, before and after the lock, to ensure
            // we don't miss an edit made externally.
            PackedRefList packed = getPackedRefs();

            if (packed.contains(name))
            {
                var lck = new LockFile(packedRefsFile);
                if (!lck.Lock())
                {
                    throw new IOException("Cannot lock " + packedRefsFile);
                }
                try
                {
                    PackedRefList cur = readPackedRefs(0, 0);
                    int           idx = cur.find(name);
                    if (0 <= idx)
                    {
                        commitPackedRefs(lck, cur.remove(idx), packed);
                    }
                }
                finally
                {
                    lck.Unlock();
                }
            }

            RefList <LooseRef> curLoose, newLoose;

            do
            {
                curLoose = looseRefs.get();
                int idx = curLoose.find(name);
                if (idx < 0)
                {
                    break;
                }
                newLoose = curLoose.remove(idx);
            } while (!looseRefs.compareAndSet(curLoose, newLoose));

            int levels = levelsIn(name) - 2;

            delete(logFor(name), levels);
            if (dst.getStorage().IsLoose)
            {
                update.unlock();
                delete(fileFor(name), levels);
            }

            modCnt.incrementAndGet();
            fireRefsChanged();
        }
        protected override RefUpdate.RefUpdateResult doRename()
        {
            if (source.getRef().isSymbolic())
            {
                return(RefUpdate.RefUpdateResult.IO_FAILURE); // not supported
            }
            var rw = new RevWalk.RevWalk(_refdb.getRepository());

            _objId      = source.getOldObjectId();
            _updateHead = needToUpdateHEAD();
            _tmp        = _refdb.newTemporaryUpdate();
            try
            {
                // First backup the source so its never unreachable.
                _tmp.setNewObjectId(_objId);
                _tmp.setForceUpdate(true);
                _tmp.disableRefLog();
                switch (_tmp.update(rw))
                {
                case RefUpdate.RefUpdateResult.NEW:
                case RefUpdate.RefUpdateResult.FORCED:
                case RefUpdate.RefUpdateResult.NO_CHANGE:
                    break;

                default:
                    return(_tmp.getResult());
                }

                // 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.RefUpdateResult.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.RefUpdateResult.LOCK_FAILURE);
                    }

                    // Replace the update operation so HEAD will log the rename.
                    dst = _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.RefUpdateResult.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.RefUpdateResult.IO_FAILURE);
                }

                // Create the destination, logging the rename during the creation.
                dst.setExpectedOldObjectId(ObjectId.ZeroId);
                dst.setNewObjectId(_objId);
                if (dst.update(rw) != RefUpdate.RefUpdateResult.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.RefUpdateResult.RENAMED);
            }
            finally
            {
                // Always try to free the temporary name.
                try
                {
                    _refdb.delete(_tmp);
                }
                catch (IOException)
                {
                    _refdb.fileFor(_tmp.getName()).Delete();
                }
            }
        }
 public RefDirectoryRename(RefDirectoryUpdate src, RefDirectoryUpdate dst)
     : base(src, dst)
 {
     _refdb = (RefDirectory)src.getRefDatabase();
 }
        protected override RefUpdate.RefUpdateResult doRename()
        {
            if (source.getRef().isSymbolic())
                return RefUpdate.RefUpdateResult.IO_FAILURE; // not supported

            var rw = new RevWalk.RevWalk(_refdb.getRepository());
            _objId = source.getOldObjectId();
            _updateHead = needToUpdateHEAD();
            _tmp = _refdb.newTemporaryUpdate();
            try
            {
                // First backup the source so its never unreachable.
                _tmp.setNewObjectId(_objId);
                _tmp.setForceUpdate(true);
                _tmp.disableRefLog();
                switch (_tmp.update(rw))
                {
                    case RefUpdate.RefUpdateResult.NEW:
                    case RefUpdate.RefUpdateResult.FORCED:
                    case RefUpdate.RefUpdateResult.NO_CHANGE:
                        break;
                    default:
                        return _tmp.getResult();
                }

                // 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.RefUpdateResult.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.RefUpdateResult.LOCK_FAILURE;
                    }

                    // Replace the update operation so HEAD will log the rename.
                    dst = _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.RefUpdateResult.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.RefUpdateResult.IO_FAILURE;
                }

                // Create the destination, logging the rename during the creation.
                dst.setExpectedOldObjectId(ObjectId.ZeroId);
                dst.setNewObjectId(_objId);
                if (dst.update(rw) != RefUpdate.RefUpdateResult.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.RefUpdateResult.RENAMED;
            }
            finally
            {
                // Always try to free the temporary name.
                try
                {
                    _refdb.delete(_tmp);
                }
                catch (IOException)
                {
                    _refdb.fileFor(_tmp.getName()).Delete();
                }
            }
        }
 public RefDirectoryRename(RefDirectoryUpdate src, RefDirectoryUpdate dst)
     : base(src, dst)
 {
     _refdb = (RefDirectory)src.getRefDatabase();
 }
 public void storedSymbolicRef(RefDirectoryUpdate u, long modified, string target)
 {
     putLooseRef(newSymbolicRef(modified, u.getRef().getName(), target));
     fireRefsChanged();
 }