private void putLooseRef(LooseRef @ref)
        {
            RefList <LooseRef> cList, nList;

            do
            {
                cList = looseRefs.get();
                nList = cList.put(@ref);
            } while (!looseRefs.compareAndSet(cList, nList));
            modCnt.incrementAndGet();
            fireRefsChanged();
        }
        public override Ref peel(Ref @ref)
        {
            Ref leaf = @ref.getLeaf();

            if (leaf.isPeeled() || leaf.getObjectId() == null)
            {
                return(@ref);
            }

            RevWalk.RevWalk rw  = new RevWalk.RevWalk(getRepository());
            RevObject       obj = rw.parseAny(leaf.getObjectId());
            ObjectIdRef     newLeaf;

            if (obj is RevTag)
            {
                do
                {
                    obj = rw.parseAny(((RevTag)obj).getObject());
                } while (obj is RevTag);

                newLeaf = new PeeledTag(leaf.getStorage(), leaf
                                        .getName(), leaf.getObjectId(), obj.Copy());
            }
            else
            {
                newLeaf = new PeeledNonTag(leaf.getStorage(), leaf
                                           .getName(), leaf.getObjectId());
            }

            // 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 <LooseRef> curList = looseRefs.get();
                int idx = curList.find(leaf.getName());
                if (0 <= idx && curList.get(idx) == leaf)
                {
                    LooseRef           asPeeled = ((LooseRef)leaf).peel(newLeaf);
                    RefList <LooseRef> newList  = curList.set(idx, asPeeled);
                    looseRefs.compareAndSet(curList, newList);
                }
            }

            return(recreate(@ref, newLeaf));
        }
        private Ref readRef(string name, RefList <Ref> packed)
        {
            RefList <LooseRef> curList = looseRefs.get();
            int idx = curList.find(name);

            if (0 <= idx)
            {
                LooseRef o = curList.get(idx);
                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);
            }

            LooseRef n2 = scanRef(null, name);

            if (n2 == null)
            {
                return(packed.get(name));
            }
            if (looseRefs.compareAndSet(curList, curList.add(idx, n2)))
            {
                modCnt.incrementAndGet();
            }
            return(n2);
        }
        private LooseRef scanRef(LooseRef @ref, string name)
        {
            FileInfo path     = fileFor(name);
            long     modified = 0;

            modified = path.lastModified();

            if (@ref != null)
            {
                if (@ref.getLastModified() == modified)
                {
                    return(@ref);
                }
                name = @ref.getName();
            }
            else if (modified == 0)
            {
                return(null);
            }

            byte[] buf;
            try
            {
                buf = IO.ReadFully(path, 4096);
            }
            catch (FileNotFoundException)
            {
                return(null); // doesn't exist; not a reference.
            }
            catch (DirectoryNotFoundException)
            {
                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))
            {
                // 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("Not a ref: " + name + ": " + content);
                }
                string target = RawParseUtils.decode(buf, 5, n);
                return(newSymbolicRef(modified, 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);
            }
            catch (ArgumentException)
            {
                while (0 < n && Char.IsWhiteSpace((char)buf[n - 1]))
                {
                    n--;
                }
                string content = RawParseUtils.decode(buf, 0, n);
                throw new IOException("Not a ref: " + name + ": " + content);
            }
            return(new LooseUnpeeled(modified, name, id));
        }