tikhomirov@239: /*
tikhomirov@403:  * Copyright (c) 2011-2012 TMate Software Ltd
tikhomirov@239:  *  
tikhomirov@239:  * This program is free software; you can redistribute it and/or modify
tikhomirov@239:  * it under the terms of the GNU General Public License as published by
tikhomirov@239:  * the Free Software Foundation; version 2 of the License.
tikhomirov@239:  *
tikhomirov@239:  * This program is distributed in the hope that it will be useful,
tikhomirov@239:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
tikhomirov@239:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
tikhomirov@239:  * GNU General Public License for more details.
tikhomirov@239:  *
tikhomirov@239:  * For information on how to redistribute this software under
tikhomirov@239:  * the terms of a license other than GNU General Public License
tikhomirov@239:  * contact TMate Software at support@hg4j.com
tikhomirov@239:  */
tikhomirov@239: package org.tmatesoft.hg.repo;
tikhomirov@239: 
tikhomirov@239: import java.io.File;
tikhomirov@239: 
tikhomirov@423: import org.tmatesoft.hg.core.HgRepositoryNotFoundException;
tikhomirov@442: import org.tmatesoft.hg.core.Nodeid;
tikhomirov@239: import org.tmatesoft.hg.util.Path;
tikhomirov@239: 
tikhomirov@239: /**
tikhomirov@467:  * Descriptor for subrepository location
tikhomirov@442:  * 
tikhomirov@442:  * @see http://mercurial.selenic.com/wiki/Subrepository
tikhomirov@239:  * @author Artem Tikhomirov
tikhomirov@239:  * @author TMate Software Ltd.
tikhomirov@239:  */
tikhomirov@239: public class HgSubrepoLocation {
tikhomirov@239: 	
tikhomirov@239: 	private final HgRepository owner;
tikhomirov@239: 	private final Kind kind;
tikhomirov@239: 	private final Path location;
tikhomirov@239: 	private final String source;
tikhomirov@442: 	private final Nodeid revInfo;
tikhomirov@239: 
tikhomirov@239: 	public enum Kind { Hg, SVN, Git, }
tikhomirov@239: 	
tikhomirov@442: 	/**
tikhomirov@442: 	 * 
tikhomirov@442: 	 * @param parentRepo
tikhomirov@442: 	 * @param repoLocation path, shall be valid directory (i.e. even if .hgsub doesn't specify trailing slash, this one shall)
tikhomirov@442: 	 * @param actualLocation
tikhomirov@442: 	 * @param type
tikhomirov@442: 	 * @param revision may be null
tikhomirov@442: 	 */
tikhomirov@442: 	/*package-local*/ HgSubrepoLocation(HgRepository parentRepo, Path repoLocation, String actualLocation, Kind type, Nodeid revision) {
tikhomirov@239: 		owner = parentRepo;
tikhomirov@442: 		location = repoLocation;
tikhomirov@239: 		source = actualLocation;
tikhomirov@239: 		kind = type;
tikhomirov@239: 		revInfo = revision;
tikhomirov@239: 	}
tikhomirov@239: 	
tikhomirov@442: 	/**
tikhomirov@442: 	 * Sub-repository's location within owning repository, always directory, path/to/nested.
tikhomirov@442: 	 * 
tikhomirov@442: 	 * May differ from left-hand, key value from .hgsub if the latter doesn't include trailing slash, which is required 
tikhomirov@442: 	 * for {@link Path} objects
tikhomirov@442: 	 * 
tikhomirov@442: 	 * @return path to nested repository relative to owner's location
tikhomirov@442: 	 */
tikhomirov@239: 	public Path getLocation() {
tikhomirov@239: 		return location;
tikhomirov@239: 	}
tikhomirov@239: 
tikhomirov@442: 	/**
tikhomirov@442: 	 * Right-hand value from .hgsub, with [kind] stripped, if any.
tikhomirov@442: 	 * @return sub-repository's source
tikhomirov@442: 	 */
tikhomirov@239: 	public String getSource() {
tikhomirov@239: 		return source;
tikhomirov@239: 	}
tikhomirov@239: 	
tikhomirov@442: 	/**
tikhomirov@442: 	 * Sub-repository kind, either Mercurial, Subversion or Git
tikhomirov@442: 	 * @return one of predefined constants
tikhomirov@442: 	 */
tikhomirov@239: 	public Kind getType() {
tikhomirov@239: 		return kind;
tikhomirov@239: 	}
tikhomirov@239: 	
tikhomirov@442: 	/**
tikhomirov@442: 	 * For a nested repository that has been committed at least once, returns
tikhomirov@442: 	 * its revision as known from .hgsubstate
tikhomirov@442: 	 * 
tikhomirov@442: 	 * 
Note, this revision belongs to the nested repository history, not that of owning repository.
tikhomirov@442: 	 * 
tikhomirov@442: 	 * @return revision of the nested repository, or null if not yet committed
tikhomirov@442: 	 */
tikhomirov@442: 	public Nodeid getRevision() {
tikhomirov@239: 		return revInfo;
tikhomirov@239: 	}
tikhomirov@239: 
tikhomirov@239: 	/**
tikhomirov@442: 	 * Answers whether this sub repository has ever been part of a commit of the owner repository
tikhomirov@442: 	 * 
tikhomirov@442: 	 * @return true if owning repository records {@link #getRevision() revision} of this sub-repository  
tikhomirov@239: 	 */
tikhomirov@239: 	public boolean isCommitted() {
tikhomirov@239: 		return revInfo != null;
tikhomirov@239: 	}
tikhomirov@239: 	
tikhomirov@239: 	/**
tikhomirov@442: 	 * Answers whether there are local changes in the sub-repository,  
tikhomirov@442: 	 * @return true if it's dirty
tikhomirov@239: 	 */
tikhomirov@239: 	public boolean hasChanges() {
tikhomirov@239: 		throw HgRepository.notImplemented();
tikhomirov@239: 	}
tikhomirov@442: 
tikhomirov@442: 	/**
tikhomirov@442: 	 * Access repository that owns nested one described by this object
tikhomirov@442: 	 */
tikhomirov@239: 	public HgRepository getOwner() {
tikhomirov@239: 		return owner;
tikhomirov@239: 	}
tikhomirov@239: 
tikhomirov@423: 	/**
tikhomirov@442: 	 * Access nested repository as a full-fledged Mercurial repository
tikhomirov@423: 	 * 
tikhomirov@423: 	 * @return object to access sub-repository
tikhomirov@423: 	 * @throws HgRepositoryNotFoundException if failed to find repository
tikhomirov@423: 	 * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception
tikhomirov@423: 	 */
tikhomirov@423: 	public HgRepository getRepo() throws HgRepositoryNotFoundException {
tikhomirov@239: 		if (kind != Kind.Hg) {
tikhomirov@423: 			throw new HgInvalidStateException(String.format("Unsupported subrepository %s", kind));
tikhomirov@239: 		}
tikhomirov@239: 		return new HgLookup().detect(new File(owner.getWorkingDir(), source));
tikhomirov@239: 	}
tikhomirov@239: }