/// <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));
        }
        /// <exception cref="System.IO.IOException"></exception>
        public override bool IsNameConflicting(string name)
        {
            RefList <Ref> packed = GetPackedRefs();
            RefList <RefDirectory.LooseRef> loose = GetLooseRefs();
            // Cannot be nested within an existing reference.
            int lastSlash = name.LastIndexOf('/');

            while (0 < lastSlash)
            {
                string needle = Sharpen.Runtime.Substring(name, 0, lastSlash);
                if (loose.Contains(needle) || packed.Contains(needle))
                {
                    return(true);
                }
                lastSlash = name.LastIndexOf('/', lastSlash - 1);
            }
            // Cannot be the container of an existing reference.
            string prefix = name + '/';
            int    idx;

            idx = -(packed.Find(prefix) + 1);
            if (idx < packed.Size() && packed.Get(idx).GetName().StartsWith(prefix))
            {
                return(true);
            }
            idx = -(loose.Find(prefix) + 1);
            if (idx < loose.Size() && loose.Get(idx).GetName().StartsWith(prefix))
            {
                return(true);
            }
            return(false);
        }
 /// <exception cref="System.IO.IOException"></exception>
 private Ref Resolve(Ref @ref, int depth, string prefix, RefList <RefDirectory.LooseRef
                                                                  > loose, RefList <Ref> packed)
 {
     if (@ref.IsSymbolic())
     {
         Ref dst = @ref.GetTarget();
         if (MAX_SYMBOLIC_REF_DEPTH <= depth)
         {
             return(null);
         }
         // claim it doesn't exist
         // If the cached value can be assumed to be current due to a
         // recent scan of the loose directory, use it.
         if (loose != null && dst.GetName().StartsWith(prefix))
         {
             int idx;
             if (0 <= (idx = loose.Find(dst.GetName())))
             {
                 dst = loose.Get(idx);
             }
             else
             {
                 if (0 <= (idx = packed.Find(dst.GetName())))
                 {
                     dst = packed.Get(idx);
                 }
                 else
                 {
                     return(@ref);
                 }
             }
         }
         else
         {
             dst = ReadRef(dst.GetName(), packed);
             if (dst == null)
             {
                 return(@ref);
             }
         }
         dst = Resolve(dst, depth + 1, prefix, loose, packed);
         if (dst == null)
         {
             return(null);
         }
         return(new SymbolicRef(@ref.GetName(), dst));
     }
     return(@ref);
 }
        /// <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);
        }