/// <exception cref="System.IO.IOException"></exception>
        public override Ref Peel(Ref @ref)
        {
            Ref leaf = @ref.GetLeaf();

            if (leaf.IsPeeled() || leaf.GetObjectId() == null)
            {
                return(@ref);
            }
            ObjectIdRef newLeaf = DoPeel(leaf);

            // Try to remember this peeling in the cache, so we don't have to do
            // it again in the future, but only if the reference is unchanged.
            if (leaf.GetStorage().IsLoose())
            {
                RefList <RefDirectory.LooseRef> curList = looseRefs.Get();
                int idx = curList.Find(leaf.GetName());
                if (0 <= idx && curList.Get(idx) == leaf)
                {
                    RefDirectory.LooseRef           asPeeled = ((RefDirectory.LooseRef)leaf).Peel(newLeaf);
                    RefList <RefDirectory.LooseRef> newList  = curList.Set(idx, asPeeled);
                    looseRefs.CompareAndSet(curList, newList);
                }
            }
            return(Recreate(@ref, newLeaf));
        }
        private void PutLooseRef(RefDirectory.LooseRef @ref)
        {
            RefList <RefDirectory.LooseRef> cList;
            RefList <RefDirectory.LooseRef> nList;

            do
            {
                cList = looseRefs.Get();
                nList = cList.Put(@ref);
            }while (!looseRefs.CompareAndSet(cList, nList));
            modCnt.IncrementAndGet();
            FireRefsChanged();
        }
        /// <exception cref="System.IO.IOException"></exception>
        private Ref ReadRef(string name, RefList <Ref> packed)
        {
            RefList <RefDirectory.LooseRef> curList = looseRefs.Get();
            int idx = curList.Find(name);

            if (0 <= idx)
            {
                RefDirectory.LooseRef o = curList.Get(idx);
                RefDirectory.LooseRef n = ScanRef(o, name);
                if (n == null)
                {
                    if (looseRefs.CompareAndSet(curList, curList.Remove(idx)))
                    {
                        modCnt.IncrementAndGet();
                    }
                    return(packed.Get(name));
                }
                if (o == n)
                {
                    return(n);
                }
                if (looseRefs.CompareAndSet(curList, curList.Set(idx, n)))
                {
                    modCnt.IncrementAndGet();
                }
                return(n);
            }
            RefDirectory.LooseRef n_1 = ScanRef(null, name);
            if (n_1 == null)
            {
                return(packed.Get(name));
            }
            // check whether the found new ref is the an additional ref. These refs
            // should not go into looseRefs
            for (int i = 0; i < additionalRefsNames.Length; i++)
            {
                if (name.Equals(additionalRefsNames[i]))
                {
                    return(n_1);
                }
            }
            if (looseRefs.CompareAndSet(curList, curList.Add(idx, n_1)))
            {
                modCnt.IncrementAndGet();
            }
            return(n_1);
        }
        /// <exception cref="System.IO.IOException"></exception>
        private RefDirectory.LooseRef ScanRef(RefDirectory.LooseRef @ref, string name)
        {
            FilePath     path            = FileFor(name);
            FileSnapshot currentSnapshot = null;

            if (@ref != null)
            {
                currentSnapshot = @ref.GetSnapShot();
                if (!currentSnapshot.IsModified(path))
                {
                    return(@ref);
                }
                name = @ref.GetName();
            }
            int limit = 4096;

            byte[]       buf;
            FileSnapshot otherSnapshot = FileSnapshot.Save(path);

            try
            {
                buf = IOUtil.ReadSome(path, limit);
            }
            catch (FileNotFoundException)
            {
                return(null);
            }
            // doesn't exist; not a reference.
            int n = buf.Length;

            if (n == 0)
            {
                return(null);
            }
            // empty file; not a reference.
            if (IsSymRef(buf, n))
            {
                if (n == limit)
                {
                    return(null);
                }
                // possibly truncated ref
                // trim trailing whitespace
                while (0 < n && char.IsWhiteSpace((char)buf[n - 1]))
                {
                    n--;
                }
                if (n < 6)
                {
                    string content = RawParseUtils.Decode(buf, 0, n);
                    throw new IOException(MessageFormat.Format(JGitText.Get().notARef, name, content)
                                          );
                }
                string target = RawParseUtils.Decode(buf, 5, n);
                if (@ref != null && @ref.IsSymbolic() && @ref.GetTarget().GetName().Equals(target
                                                                                           ))
                {
                    currentSnapshot.SetClean(otherSnapshot);
                    return(@ref);
                }
                return(NewSymbolicRef(otherSnapshot, name, target));
            }
            if (n < Constants.OBJECT_ID_STRING_LENGTH)
            {
                return(null);
            }
            // impossibly short object identifier; not a reference.
            ObjectId id;

            try
            {
                id = ObjectId.FromString(buf, 0);
                if (@ref != null && [email protected]() && @ref.GetTarget().GetObjectId().Equals(id
                                                                                                ))
                {
                    currentSnapshot.SetClean(otherSnapshot);
                    return(@ref);
                }
            }
            catch (ArgumentException)
            {
                while (0 < n && char.IsWhiteSpace((char)buf[n - 1]))
                {
                    n--;
                }
                string content = RawParseUtils.Decode(buf, 0, n);
                throw new IOException(MessageFormat.Format(JGitText.Get().notARef, name, content)
                                      );
            }
            return(new RefDirectory.LooseUnpeeled(otherSnapshot, name, id));
        }