private Ref readRef(String name, RefList<Ref> packed) throws IOException { final RefList<LooseRef> curList = looseRefs.get(); final int idx = curList.find(name); if (0 <= idx) { final LooseRef o = curList.get(idx); final 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; } final LooseRef n = scanRef(null, name); if (n == 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; if (looseRefs.compareAndSet(curList, curList.add(idx, n))) modCnt.incrementAndGet(); return n; }
/** * Adds a set of refs to the set of packed-refs. Only non-symbolic refs are added. If a ref with * the given name already existed in packed-refs it is updated with the new value. Each loose ref * which was added to the packed-ref file is deleted. If a given ref can't be locked it will not * be added to the pack file. * * @param refs the refs to be added. Must be fully qualified. * @throws IOException */ public void pack(List<String> refs) throws IOException { if (refs.size() == 0) return; FS fs = parent.getFS(); // Lock the packed refs file and read the content LockFile lck = new LockFile(packedRefsFile); if (!lck.lock()) throw new IOException(MessageFormat.format(JGitText.get().cannotLock, packedRefsFile)); try { final PackedRefList packed = getPackedRefs(); RefList<Ref> cur = readPackedRefs(); // Iterate over all refs to be packed for (String refName : refs) { Ref ref = readRef(refName, cur); if (ref.isSymbolic()) continue; // can't pack symbolic refs // Add/Update it to packed-refs int idx = cur.find(refName); if (idx >= 0) cur = cur.set(idx, peeledPackedRef(ref)); else cur = cur.add(idx, peeledPackedRef(ref)); } // The new content for packed-refs is collected. Persist it. commitPackedRefs(lck, cur, packed); // Now delete the loose refs which are now packed for (String refName : refs) { // Lock the loose ref File refFile = fileFor(refName); if (!fs.exists(refFile)) continue; LockFile rLck = new LockFile(refFile); if (!rLck.lock()) continue; try { LooseRef currentLooseRef = scanRef(null, refName); if (currentLooseRef == null || currentLooseRef.isSymbolic()) continue; Ref packedRef = cur.get(refName); ObjectId clr_oid = currentLooseRef.getObjectId(); if (clr_oid != null && clr_oid.equals(packedRef.getObjectId())) { RefList<LooseRef> curLoose, newLoose; do { curLoose = looseRefs.get(); int idx = curLoose.find(refName); if (idx < 0) break; newLoose = curLoose.remove(idx); } while (!looseRefs.compareAndSet(curLoose, newLoose)); int levels = levelsIn(refName) - 2; delete(refFile, levels, rLck); } } finally { rLck.unlock(); } } // Don't fire refsChanged. The refs have not change, only their // storage. } finally { lck.unlock(); } }