view src/org/tmatesoft/hg/internal/ManifestRevision.java @ 621:99ad1e3a4e4d

RevlogStream: be aware of existence (not HgDataFile), facilitate use of an added HgDataFile over a commit; Rollback: be more sensitive about file changes (file size is not enough: write/rollback leaves it intact); tests
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Sat, 18 May 2013 22:23:57 +0200
parents dd4f6311af52
children 7743a9c10bfa
line wrap: on
line source
/*
 * Copyright (c) 2011-2013 TMate Software Ltd
 *  
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * For information on how to redistribute this software under
 * the terms of a license other than GNU General Public License
 * contact TMate Software at support@hg4j.com
 */
package org.tmatesoft.hg.internal;

import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION;

import java.util.Collection;
import java.util.TreeMap;

import org.tmatesoft.hg.core.Nodeid;
import org.tmatesoft.hg.repo.HgManifest;
import org.tmatesoft.hg.util.Convertor;
import org.tmatesoft.hg.util.Path;

/**
 * Specific revision of the manifest. 
 * Note, suited to keep single revision only ({@link #revision()}), which is linked to changeset {@link #changesetRevisionIndex()}.
 *
 * @author Artem Tikhomirov
 * @author TMate Software Ltd.
 */
public final class ManifestRevision implements HgManifest.Inspector {
	private final TreeMap<Path, Nodeid> idsMap;
	private final TreeMap<Path, HgManifest.Flags> flagsMap;
	private final Convertor<Nodeid> idsPool;
	private final Convertor<Path> namesPool;
	private Nodeid manifestRev = Nodeid.NULL;
	private int changelogRevIndex = NO_REVISION, manifestRevIndex = NO_REVISION;

	// optional pools for effective management of nodeids and filenames (they are likely
	// to be duplicated among different manifest revisions
	public ManifestRevision(Pool<Nodeid> nodeidPool, Convertor<Path> filenamePool) {
		idsPool = nodeidPool;
		namesPool = filenamePool;
		idsMap = new TreeMap<Path, Nodeid>();
		flagsMap = new TreeMap<Path, HgManifest.Flags>();
	}
	
	public Collection<Path> files() {
		return idsMap.keySet();
	}

	public Nodeid nodeid(Path fname) {
		return idsMap.get(fname);
	}

	public HgManifest.Flags flags(Path fname) {
		HgManifest.Flags f = flagsMap.get(fname);
		return f == null ? HgManifest.Flags.RegularFile : f;
	}

	/**
	 * @return identifier of this manifest revision
	 */
	public Nodeid revision() {
		return manifestRev;
	}
	
	public int revisionIndex() {
		return manifestRevIndex;
	}
	
	/**
	 * @return revision index for the changelog this manifest revision is linked to
	 */
	public int changesetRevisionIndex() {
		return changelogRevIndex;
	}
	
	//

	public boolean next(Nodeid nid, Path fname, HgManifest.Flags flags) {
		if (namesPool != null) {
			fname = namesPool.mangle(fname);
		}
		if (idsPool != null) {
			nid = idsPool.mangle(nid);
		}
		idsMap.put(fname, nid);
		if (flags != HgManifest.Flags.RegularFile) {
			// TreeMap$Entry takes 32 bytes. No reason to keep regular file attribute (in fact, no flags state) 
			// for such price
			// Alternatively, Map<Path, Pair<Nodeid, Flags>> might come as a solution
			// however, with low rate of elements with flags this would consume more memory
			// than two distinct maps (sizeof(Pair) == 16).  
			// Map<Pair>: n*(32+16)
			// 2 Maps:    n*32 + m*32  <-- consumes more with m>n/2 
			flagsMap.put(fname, flags);
		}
		return true;
	}

	public boolean end(int revision) {
		// in fact, this class cares about single revision
		return false; 
	}

	public boolean begin(int revisionIndex, Nodeid revision, int changelogRevisionIndex) {
		if (manifestRev != null) {
			idsMap.clear();
			flagsMap.clear();
		}
		manifestRev = revision;
		manifestRevIndex = revisionIndex;
		changelogRevIndex = changelogRevisionIndex;
		return true;
	}
}