/*
 * Copyright (C) 2009, Google Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.storage.file;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.jgit.errors.PackMismatchException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectDatabase;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.storage.pack.CachedPack;
import org.eclipse.jgit.storage.pack.ObjectToPack;
import org.eclipse.jgit.storage.pack.PackWriter;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;

/**
 * Traditional file system based {@link ObjectDatabase}.
 * <p>
 * This is the classical object database representation for a Git repository,
 * where objects are stored loose by hashing them into directories by their
 * {@link ObjectId}, or are stored in compressed containers known as
 * {@link PackFile}s.
 * <p>
 * Optionally an object database can reference one or more alternates; other
 * ObjectDatabase instances that are searched in addition to the current
 * database.
 * <p>
 * Databases are divided into two halves: a half that is considered to be fast
 * to search (the {@code PackFile}s), and a half that is considered to be slow
 * to search (loose objects). When alternates are present the fast half is fully
 * searched (recursively through all alternates) before the slow half is
 * considered.
 */
public class ObjectDirectory extends FileObjectDatabase {
	private static final PackList NO_PACKS = new PackList(
			FileSnapshot.DIRTY, new PackFile[0]);

	/** Maximum number of candidates offered as resolutions of abbreviation. */
	private static final int RESOLVE_ABBREV_LIMIT = 256;

	private final Config config;

	private final File objects;

	private final File infoDirectory;

	private final File packDirectory;

	private final File alternatesFile;

	private final File cachedPacksFile;

	private final AtomicReference<PackList> packList;

	private final AtomicReference<CachedPackList> cachedPacks;

	private final FS fs;

	private final AtomicReference<AlternateHandle[]> alternates;

	private final UnpackedObjectCache unpackedObjectCache;

	/**
	 * Initialize a reference to an on-disk object directory.
	 *
	 * @param cfg
	 *            configuration this directory consults for write settings.
	 * @param dir
	 *            the location of the <code>objects</code> directory.
	 * @param alternatePaths
	 *            a list of alternate object directories
	 * @param fs
	 *            the file system abstraction which will be necessary to perform
	 *            certain file system operations.
	 * @throws IOException
	 *             an alternate object cannot be opened.
	 */
	public ObjectDirectory(final Config cfg, final File dir,
			File[] alternatePaths, FS fs) throws IOException {
		config = cfg;
		objects = dir;
		infoDirectory = new File(objects, "info");
		packDirectory = new File(objects, "pack");
		alternatesFile = new File(infoDirectory, "alternates");
		cachedPacksFile = new File(infoDirectory, "cached-packs");
		packList = new AtomicReference<PackList>(NO_PACKS);
		cachedPacks = new AtomicReference<CachedPackList>();
		unpackedObjectCache = new UnpackedObjectCache();
		this.fs = fs;

		alternates = new AtomicReference<AlternateHandle[]>();
		if (alternatePaths != null) {
			AlternateHandle[] alt;

			alt = new AlternateHandle[alternatePaths.length];
			for (int i = 0; i < alternatePaths.length; i++)
				alt[i] = openAlternate(alternatePaths[i]);
			alternates.set(alt);
		}
	}

	/**
	 * @return the location of the <code>objects</code> directory.
	 */
	public final File getDirectory() {
		return objects;
	}

	@Override
	public boolean exists() {
		return objects.exists();
	}

	@Override
	public void create() throws IOException {
		FileUtils.mkdirs(objects);
		FileUtils.mkdir(infoDirectory);
		FileUtils.mkdir(packDirectory);
	}

	@Override
	public ObjectDirectoryInserter newInserter() {
		return new ObjectDirectoryInserter(this, config);
	}

	@Override
	public void close() {
		unpackedObjectCache.clear();

		final PackList packs = packList.get();
		packList.set(NO_PACKS);
		for (final PackFile p : packs.packs)
			p.close();

		// Fully close all loaded alternates and clear the alternate list.
		AlternateHandle[] alt = alternates.get();
		if (alt != null) {
			alternates.set(null);
			for(final AlternateHandle od : alt)
				od.close();
		}
	}

	/**
	 * Compute the location of a loose object file.
	 *
	 * @param objectId
	 *            identity of the loose object to map to the directory.
	 * @return location of the object, if it were to exist as a loose object.
	 */
	@Override
	public File fileFor(final AnyObjectId objectId) {
		return super.fileFor(objectId);
	}

	/**
	 * @return unmodifiable collection of all known pack files local to this
	 *         directory. Most recent packs are presented first. Packs most
	 *         likely to contain more recent objects appear before packs
	 *         containing objects referenced by commits further back in the
	 *         history of the repository.
	 */
	public Collection<PackFile> getPacks() {
		PackList list = packList.get();
		if (list == NO_PACKS)
			list = scanPacks(list);
		PackFile[] packs = list.packs;
		return Collections.unmodifiableCollection(Arrays.asList(packs));
	}

	@Override
	Collection<? extends CachedPack> getCachedPacks() throws IOException {
		CachedPackList list = cachedPacks.get();
		if (list == null || list.snapshot.isModified(cachedPacksFile))
			list = scanCachedPacks(list);

		Collection<CachedPack> result = list.getCachedPacks();
		boolean resultIsCopy = false;

		for (AlternateHandle h : myAlternates()) {
			Collection<CachedPack> altPacks = h.getCachedPacks();
			if (altPacks.isEmpty())
				continue;

			if (result.isEmpty()) {
				result = altPacks;
				continue;
			}

			if (!resultIsCopy) {
				result = new ArrayList<CachedPack>(result);
				resultIsCopy = true;
			}
			result.addAll(altPacks);
		}
		return result;
	}

	private CachedPackList scanCachedPacks(CachedPackList old)
			throws IOException {
		FileSnapshot s = FileSnapshot.save(cachedPacksFile);
		byte[] buf;
		try {
			buf = IO.readFully(cachedPacksFile);
		} catch (FileNotFoundException e) {
			buf = new byte[0];
		}

		if (old != null && old.snapshot.equals(s)
				&& Arrays.equals(old.raw, buf)) {
			old.snapshot.setClean(s);
			return old;
		}

		ArrayList<LocalCachedPack> list = new ArrayList<LocalCachedPack>(4);
		Set<ObjectId> tips = new HashSet<ObjectId>();
		int ptr = 0;
		while (ptr < buf.length) {
			if (buf[ptr] == '#' || buf[ptr] == '\n') {
				ptr = RawParseUtils.nextLF(buf, ptr);
				continue;
			}

			if (buf[ptr] == '+') {
				tips.add(ObjectId.fromString(buf, ptr + 2));
				ptr = RawParseUtils.nextLF(buf, ptr + 2);
				continue;
			}

			List<String> names = new ArrayList<String>(4);
			while (ptr < buf.length && buf[ptr] == 'P') {
				int end = RawParseUtils.nextLF(buf, ptr);
				if (buf[end - 1] == '\n')
					end--;
				names.add(RawParseUtils.decode(buf, ptr + 2, end));
				ptr = RawParseUtils.nextLF(buf, end);
			}

			if (!tips.isEmpty() && !names.isEmpty()) {
				list.add(new LocalCachedPack(this, tips, names));
				tips = new HashSet<ObjectId>();
			}
		}
		list.trimToSize();
		return new CachedPackList(s, Collections.unmodifiableList(list), buf);
	}

	/**
	 * Add a single existing pack to the list of available pack files.
	 *
	 * @param pack
	 *            path of the pack file to open.
	 * @param idx
	 *            path of the corresponding index file.
	 * @return the pack that was opened and added to the database.
	 * @throws IOException
	 *             index file could not be opened, read, or is not recognized as
	 *             a Git pack file index.
	 */
	public PackFile openPack(final File pack, final File idx)
			throws IOException {
		final String p = pack.getName();
		final String i = idx.getName();

		if (p.length() != 50 || !p.startsWith("pack-") || !p.endsWith(".pack"))
			throw new IOException(MessageFormat.format(JGitText.get().notAValidPack, pack));

		if (i.length() != 49 || !i.startsWith("pack-") || !i.endsWith(".idx"))
			throw new IOException(MessageFormat.format(JGitText.get().notAValidPack, idx));

		if (!p.substring(0, 45).equals(i.substring(0, 45)))
			throw new IOException(MessageFormat.format(JGitText.get().packDoesNotMatchIndex, pack));

		PackFile res = new PackFile(idx, pack);
		insertPack(res);
		return res;
	}

	@Override
	public String toString() {
		return "ObjectDirectory[" + getDirectory() + "]";
	}

	boolean hasObject1(final AnyObjectId objectId) {
		if (unpackedObjectCache.isUnpacked(objectId))
			return true;
		for (final PackFile p : packList.get().packs) {
			try {
				if (p.hasObject(objectId)) {
					return true;
				}
			} catch (IOException e) {
				// The hasObject call should have only touched the index,
				// so any failure here indicates the index is unreadable
				// by this process, and the pack is likewise not readable.
				//
				removePack(p);
				continue;
			}
		}
		return false;
	}

	void resolve(Set<ObjectId> matches, AbbreviatedObjectId id)
			throws IOException {
		// Go through the packs once. If we didn't find any resolutions
		// scan for new packs and check once more.
		//
		int oldSize = matches.size();
		PackList pList = packList.get();
		for (;;) {
			for (PackFile p : pList.packs) {
				try {
					p.resolve(matches, id, RESOLVE_ABBREV_LIMIT);
				} catch (IOException e) {
					// Assume the pack is corrupted.
					//
					removePack(p);
				}
				if (matches.size() > RESOLVE_ABBREV_LIMIT)
					return;
			}
			if (matches.size() == oldSize) {
				PackList nList = scanPacks(pList);
				if (nList == pList || nList.packs.length == 0)
					break;
				pList = nList;
				continue;
			}
			break;
		}

		String fanOut = id.name().substring(0, 2);
		String[] entries = new File(getDirectory(), fanOut).list();
		if (entries != null) {
			for (String e : entries) {
				if (e.length() != Constants.OBJECT_ID_STRING_LENGTH - 2)
					continue;
				try {
					ObjectId entId = ObjectId.fromString(fanOut + e);
					if (id.prefixCompare(entId) == 0)
						matches.add(entId);
				} catch (IllegalArgumentException notId) {
					continue;
				}
				if (matches.size() > RESOLVE_ABBREV_LIMIT)
					return;
			}
		}

		for (AlternateHandle alt : myAlternates()) {
			alt.db.resolve(matches, id);
			if (matches.size() > RESOLVE_ABBREV_LIMIT)
				return;
		}
	}

	ObjectLoader openObject1(final WindowCursor curs,
			final AnyObjectId objectId) throws IOException {
		if (unpackedObjectCache.isUnpacked(objectId)) {
			ObjectLoader ldr = openObject2(curs, objectId.name(), objectId);
			if (ldr != null)
				return ldr;
			else
				unpackedObjectCache.remove(objectId);
		}

		PackList pList = packList.get();
		SEARCH: for (;;) {
			for (final PackFile p : pList.packs) {
				try {
					final ObjectLoader ldr = p.get(curs, objectId);
					if (ldr != null)
						return ldr;
				} catch (PackMismatchException e) {
					// Pack was modified; refresh the entire pack list.
					//
					pList = scanPacks(pList);
					continue SEARCH;
				} catch (IOException e) {
					// Assume the pack is corrupted.
					//
					removePack(p);
				}
			}
			return null;
		}
	}

	long getObjectSize1(final WindowCursor curs, final AnyObjectId objectId)
			throws IOException {
		PackList pList = packList.get();
		SEARCH: for (;;) {
			for (final PackFile p : pList.packs) {
				try {
					long sz = p.getObjectSize(curs, objectId);
					if (0 <= sz)
						return sz;
				} catch (PackMismatchException e) {
					// Pack was modified; refresh the entire pack list.
					//
					pList = scanPacks(pList);
					continue SEARCH;
				} catch (IOException e) {
					// Assume the pack is corrupted.
					//
					removePack(p);
				}
			}
			return -1;
		}
	}

	@Override
	long getObjectSize2(WindowCursor curs, String objectName,
			AnyObjectId objectId) throws IOException {
		try {
			File path = fileFor(objectName);
			FileInputStream in = new FileInputStream(path);
			try {
				return UnpackedObject.getSize(in, objectId, curs);
			} finally {
				in.close();
			}
		} catch (FileNotFoundException noFile) {
			return -1;
		}
	}

	@Override
	void selectObjectRepresentation(PackWriter packer, ObjectToPack otp,
			WindowCursor curs) throws IOException {
		PackList pList = packList.get();
		SEARCH: for (;;) {
			for (final PackFile p : pList.packs) {
				try {
					LocalObjectRepresentation rep = p.representation(curs, otp);
					if (rep != null)
						packer.select(otp, rep);
				} catch (PackMismatchException e) {
					// Pack was modified; refresh the entire pack list.
					//
					pList = scanPacks(pList);
					continue SEARCH;
				} catch (IOException e) {
					// Assume the pack is corrupted.
					//
					removePack(p);
				}
			}
			break SEARCH;
		}

		for (AlternateHandle h : myAlternates())
			h.db.selectObjectRepresentation(packer, otp, curs);
	}

	boolean hasObject2(final String objectName) {
		return fileFor(objectName).exists();
	}

	ObjectLoader openObject2(final WindowCursor curs,
			final String objectName, final AnyObjectId objectId)
			throws IOException {
		try {
			File path = fileFor(objectName);
			FileInputStream in = new FileInputStream(path);
			try {
				unpackedObjectCache.add(objectId);
				return UnpackedObject.open(in, path, objectId, curs);
			} finally {
				in.close();
			}
		} catch (FileNotFoundException noFile) {
			unpackedObjectCache.remove(objectId);
			return null;
		}
	}

	@Override
	InsertLooseObjectResult insertUnpackedObject(File tmp, ObjectId id,
			boolean createDuplicate) throws IOException {
		// If the object is already in the repository, remove temporary file.
		//
		if (unpackedObjectCache.isUnpacked(id)) {
			FileUtils.delete(tmp);
			return InsertLooseObjectResult.EXISTS_LOOSE;
		}
		if (!createDuplicate && has(id)) {
			FileUtils.delete(tmp);
			return InsertLooseObjectResult.EXISTS_PACKED;
		}

		final File dst = fileFor(id);
		if (dst.exists()) {
			// We want to be extra careful and avoid replacing an object
			// that already exists. We can't be sure renameTo() would
			// fail on all platforms if dst exists, so we check first.
			//
			FileUtils.delete(tmp);
			return InsertLooseObjectResult.EXISTS_LOOSE;
		}
		if (tmp.renameTo(dst)) {
			dst.setReadOnly();
			unpackedObjectCache.add(id);
			return InsertLooseObjectResult.INSERTED;
		}

		// Maybe the directory doesn't exist yet as the object
		// directories are always lazily created. Note that we
		// try the rename first as the directory likely does exist.
		//
		FileUtils.mkdir(dst.getParentFile());
		if (tmp.renameTo(dst)) {
			dst.setReadOnly();
			unpackedObjectCache.add(id);
			return InsertLooseObjectResult.INSERTED;
		}

		if (!createDuplicate && has(id)) {
			FileUtils.delete(tmp);
			return InsertLooseObjectResult.EXISTS_PACKED;
		}

		// The object failed to be renamed into its proper
		// location and it doesn't exist in the repository
		// either. We really don't know what went wrong, so
		// fail.
		//
		FileUtils.delete(tmp);
		return InsertLooseObjectResult.FAILURE;
	}

	boolean tryAgain1() {
		final PackList old = packList.get();
		if (old.snapshot.isModified(packDirectory))
			return old != scanPacks(old);
		return false;
	}

	Config getConfig() {
		return config;
	}

	@Override
	FS getFS() {
		return fs;
	}

	private void insertPack(final PackFile pf) {
		PackList o, n;
		do {
			o = packList.get();

			// If the pack in question is already present in the list
			// (picked up by a concurrent thread that did a scan?) we
			// do not want to insert it a second time.
			//
			final PackFile[] oldList = o.packs;
			final String name = pf.getPackFile().getName();
			for (PackFile p : oldList) {
				if (PackFile.SORT.compare(pf, p) < 0)
					break;
				if (name.equals(p.getPackFile().getName()))
					return;
			}

			final PackFile[] newList = new PackFile[1 + oldList.length];
			newList[0] = pf;
			System.arraycopy(oldList, 0, newList, 1, oldList.length);
			n = new PackList(o.snapshot, newList);
		} while (!packList.compareAndSet(o, n));
	}

	private void removePack(final PackFile deadPack) {
		PackList o, n;
		do {
			o = packList.get();

			final PackFile[] oldList = o.packs;
			final int j = indexOf(oldList, deadPack);
			if (j < 0)
				break;

			final PackFile[] newList = new PackFile[oldList.length - 1];
			System.arraycopy(oldList, 0, newList, 0, j);
			System.arraycopy(oldList, j + 1, newList, j, newList.length - j);
			n = new PackList(o.snapshot, newList);
		} while (!packList.compareAndSet(o, n));
		deadPack.close();
	}

	private static int indexOf(final PackFile[] list, final PackFile pack) {
		for (int i = 0; i < list.length; i++) {
			if (list[i] == pack)
				return i;
		}
		return -1;
	}

	private PackList scanPacks(final PackList original) {
		synchronized (packList) {
			PackList o, n;
			do {
				o = packList.get();
				if (o != original) {
					// Another thread did the scan for us, while we
					// were blocked on the monitor above.
					//
					return o;
				}
				n = scanPacksImpl(o);
				if (n == o)
					return n;
			} while (!packList.compareAndSet(o, n));
			return n;
		}
	}

	private PackList scanPacksImpl(final PackList old) {
		final Map<String, PackFile> forReuse = reuseMap(old);
		final FileSnapshot snapshot = FileSnapshot.save(packDirectory);
		final Set<String> names = listPackDirectory();
		final List<PackFile> list = new ArrayList<PackFile>(names.size() >> 2);
		boolean foundNew = false;
		for (final String indexName : names) {
			// Must match "pack-[0-9a-f]{40}.idx" to be an index.
			//
			if (indexName.length() != 49 || !indexName.endsWith(".idx"))
				continue;

			final String base = indexName.substring(0, indexName.length() - 4);
			final String packName = base + ".pack";
			if (!names.contains(packName)) {
				// Sometimes C Git's HTTP fetch transport leaves a
				// .idx file behind and does not download the .pack.
				// We have to skip over such useless indexes.
				//
				continue;
			}

			final PackFile oldPack = forReuse.remove(packName);
			if (oldPack != null) {
				list.add(oldPack);
				continue;
			}

			final File packFile = new File(packDirectory, packName);
			final File idxFile = new File(packDirectory, indexName);
			list.add(new PackFile(idxFile, packFile));
			foundNew = true;
		}

		// If we did not discover any new files, the modification time was not
		// changed, and we did not remove any files, then the set of files is
		// the same as the set we were given. Instead of building a new object
		// return the same collection.
		//
		if (!foundNew && forReuse.isEmpty() && snapshot.equals(old.snapshot)) {
			old.snapshot.setClean(snapshot);
			return old;
		}

		for (final PackFile p : forReuse.values()) {
			p.close();
		}

		if (list.isEmpty())
			return new PackList(snapshot, NO_PACKS.packs);

		final PackFile[] r = list.toArray(new PackFile[list.size()]);
		Arrays.sort(r, PackFile.SORT);
		return new PackList(snapshot, r);
	}

	private static Map<String, PackFile> reuseMap(final PackList old) {
		final Map<String, PackFile> forReuse = new HashMap<String, PackFile>();
		for (final PackFile p : old.packs) {
			if (p.invalid()) {
				// The pack instance is corrupted, and cannot be safely used
				// again. Do not include it in our reuse map.
				//
				p.close();
				continue;
			}

			final PackFile prior = forReuse.put(p.getPackFile().getName(), p);
			if (prior != null) {
				// This should never occur. It should be impossible for us
				// to have two pack files with the same name, as all of them
				// came out of the same directory. If it does, we promised to
				// close any PackFiles we did not reuse, so close the second,
				// readers are likely to be actively using the first.
				//
				forReuse.put(prior.getPackFile().getName(), prior);
				p.close();
			}
		}
		return forReuse;
	}

	private Set<String> listPackDirectory() {
		final String[] nameList = packDirectory.list();
		if (nameList == null)
			return Collections.emptySet();
		final Set<String> nameSet = new HashSet<String>(nameList.length << 1);
		for (final String name : nameList) {
			if (name.startsWith("pack-"))
				nameSet.add(name);
		}
		return nameSet;
	}

	AlternateHandle[] myAlternates() {
		AlternateHandle[] alt = alternates.get();
		if (alt == null) {
			synchronized (alternates) {
				alt = alternates.get();
				if (alt == null) {
					try {
						alt = loadAlternates();
					} catch (IOException e) {
						alt = new AlternateHandle[0];
					}
					alternates.set(alt);
				}
			}
		}
		return alt;
	}

	private AlternateHandle[] loadAlternates() throws IOException {
		final List<AlternateHandle> l = new ArrayList<AlternateHandle>(4);
		final BufferedReader br = open(alternatesFile);
		try {
			String line;
			while ((line = br.readLine()) != null) {
				l.add(openAlternate(line));
			}
		} finally {
			br.close();
		}
		return l.toArray(new AlternateHandle[l.size()]);
	}

	private static BufferedReader open(final File f)
			throws FileNotFoundException {
		return new BufferedReader(new FileReader(f));
	}

	private AlternateHandle openAlternate(final String location)
			throws IOException {
		final File objdir = fs.resolve(objects, location);
		return openAlternate(objdir);
	}

	private AlternateHandle openAlternate(File objdir) throws IOException {
		final File parent = objdir.getParentFile();
		if (FileKey.isGitRepository(parent, fs)) {
			FileKey key = FileKey.exact(parent, fs);
			FileRepository db = (FileRepository) RepositoryCache.open(key);
			return new AlternateRepository(db);
		}

		ObjectDirectory db = new ObjectDirectory(config, objdir, null, fs);
		return new AlternateHandle(db);
	}

	private static final class PackList {
		/** State just before reading the pack directory. */
		final FileSnapshot snapshot;

		/** All known packs, sorted by {@link PackFile#SORT}. */
		final PackFile[] packs;

		PackList(final FileSnapshot monitor, final PackFile[] packs) {
			this.snapshot = monitor;
			this.packs = packs;
		}
	}

	private static final class CachedPackList {
		final FileSnapshot snapshot;

		final Collection<LocalCachedPack> packs;

		final byte[] raw;

		CachedPackList(FileSnapshot sn, List<LocalCachedPack> list, byte[] buf) {
			snapshot = sn;
			packs = list;
			raw = buf;
		}

		@SuppressWarnings("unchecked")
		Collection<CachedPack> getCachedPacks() {
			Collection p = packs;
			return p;
		}
	}

	@Override
	public ObjectDatabase newCachedDatabase() {
		return newCachedFileObjectDatabase();
	}

	FileObjectDatabase newCachedFileObjectDatabase() {
		return new CachedObjectDirectory(this);
	}
}
