package org.tmatesoft.svn.core.internal.wc2.ng;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.db.SVNSqlJetDb.Mode;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
import org.tmatesoft.svn.core.internal.wc17.SVNWCContext;
import org.tmatesoft.svn.core.internal.wc17.db.*;
import org.tmatesoft.svn.core.internal.wc17.db.SVNWCDb.DirParsedInfo;
import org.tmatesoft.svn.core.internal.wc17.db.StructureFields.InheritedProperties;
import org.tmatesoft.svn.core.internal.wc17.db.StructureFields.NodeInfo;
import org.tmatesoft.svn.core.internal.wc17.db.StructureFields.NodeOriginInfo;
import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
import org.tmatesoft.svn.core.internal.wc2.SvnRepositoryAccess.RepositoryInfo;
import org.tmatesoft.svn.core.internal.wc2.SvnRepositoryAccess.RevisionsPair;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnGetProperties;
import org.tmatesoft.svn.core.wc2.SvnInheritedProperties;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import org.tmatesoft.svn.util.SVNLogType;
public class SvnNgGetProperties extends SvnNgOperationRunner<SVNProperties, SvnGetProperties> {
@Override
protected SVNProperties run(SVNWCContext context) throws SVNException {
for (SvnTarget target : getOperation().getTargets()) {
if (target.isFile()) {
run(context, target.getFile());
}
}
return getOperation().first();
}
protected SVNProperties run(SVNWCContext context, File target) throws SVNException {
boolean pristine = getOperation().getRevision() == SVNRevision.COMMITTED || getOperation().getRevision() == SVNRevision.BASE;
SVNNodeKind kind = context.getDb().readKind(target, true, pristine, false);
if (kind == SVNNodeKind.UNKNOWN || kind == SVNNodeKind.NONE) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNVERSIONED_RESOURCE, "''{0}'' is not under version control", target);
SVNErrorManager.error(err, SVNLogType.WC);
}
if (getOperation().getTargetInheritedPropertiesReceiver() != null) {
SVNRevision pegRevision = getOperation().getFirstTarget().getResolvedPegRevision(SVNRevision.HEAD, SVNRevision.WORKING);
SVNRevision revision = getOperation().getRevision() == SVNRevision.UNDEFINED ? pegRevision : getOperation().getRevision();
final boolean hasLocalIProps = (pegRevision == SVNRevision.WORKING || pegRevision == SVNRevision.UNDEFINED) &&
(revision == SVNRevision.WORKING || revision == SVNRevision.UNDEFINED);
if (hasLocalIProps) {
getLocaliProps(context, target);
} else {
final Structure<NodeOriginInfo> origin = context.getNodeOrigin(target, false, NodeOriginInfo.isCopy, NodeOriginInfo.copyRootAbsPath, NodeOriginInfo.reposRelpath, NodeOriginInfo.reposRootUrl,
NodeOriginInfo.reposUuid, NodeOriginInfo.revision);
final File reposRelPath = origin.get(NodeOriginInfo.reposRelpath);
if (reposRelPath != null) {
final SVNURL rootURL = origin.get(NodeOriginInfo.reposRootUrl);
final SVNURL url = rootURL.appendPath(SVNFileUtil.getFilePath(reposRelPath), false);
Structure<RevisionsPair> revisionPair = null;
if (pegRevision.isLocal()) {
revisionPair = getRepositoryAccess().getRevisionNumber(null, getOperation().getFirstTarget(), pegRevision, revisionPair);
final long pegrevnum = revisionPair.lng(RevisionsPair.revNumber);
pegRevision = SVNRevision.create(pegrevnum);
}
if (revision.isLocal()) {
revisionPair = getRepositoryAccess().getRevisionNumber(null, getOperation().getFirstTarget(), revision, revisionPair);
long revnum = revisionPair.lng(RevisionsPair.revNumber);
revision = SVNRevision.create(revnum);
}
SvnTarget opTarget = getOperation().getFirstTarget();
Structure<RepositoryInfo> repositoryInfo = getRepositoryAccess().createRepositoryFor(SvnTarget.fromURL(url), revision, pegRevision, null);
final SVNRepository repository = repositoryInfo.<SVNRepository>get(RepositoryInfo.repository);
long revnum = repositoryInfo.lng(RepositoryInfo.revision);
repositoryInfo.release();
final SVNURL repositoryRoot = repository.getRepositoryRoot(true);
final Map<String, SVNProperties> inheritedProperties = repository.getInheritedProperties("", revnum, null);
final List<SvnInheritedProperties> result = new ArrayList<SvnInheritedProperties>();
for (String path : inheritedProperties.keySet()) {
final SvnInheritedProperties propItem = new SvnInheritedProperties();
propItem.setTarget(SvnTarget.fromURL(repositoryRoot.appendPath(path, false)));
propItem.setProperties(inheritedProperties.get(path));
result.add(propItem);
}
if (!result.isEmpty()) {
getOperation().getTargetInheritedPropertiesReceiver().receive(opTarget, result);
}
}
}
}
if (kind == SVNNodeKind.DIR) {
if (getOperation().getDepth() == SVNDepth.EMPTY) {
if (!matchesChangelist(target)) {
return getOperation().first();
}
SVNProperties properties = null;
if (pristine) {
properties = context.getDb().readPristineProperties(target);
} else {
properties = context.getDb().readProperties(target);
}
if (properties != null && !properties.isEmpty()) {
getOperation().receive(SvnTarget.fromFile(target), properties);
}
} else {
SVNWCDb db = (SVNWCDb) context.getDb();
db.readPropertiesRecursively(
target,
getOperation().getDepth(),
false,
pristine,
getOperation().getApplicableChangelists(),
getOperation());
}
} else {
SVNProperties properties = null;
if (pristine) {
properties = context.getDb().readPristineProperties(target);
} else {
if (!context.isNodeStatusDeleted(target)) {
properties = context.getDb().readProperties(target);
}
}
if (properties != null && !properties.isEmpty()) {
getOperation().receive(SvnTarget.fromFile(target), properties);
}
}
return getOperation().first();
}
private void getLocaliProps(SVNWCContext context, File target) throws SVNException {
final DirParsedInfo pdh = ((SVNWCDb) context.getDb()).parseDir(target, Mode.ReadOnly);
final SVNWCDbRoot wcRoot = pdh.wcDbDir.getWCRoot();
final List<Structure<InheritedProperties>> inheritedProps = SvnWcDbProperties.readInheritedProperties(wcRoot, pdh.localRelPath, null);
final List<SvnInheritedProperties> resultList = new ArrayList<SvnInheritedProperties>();
SVNURL repositoryRoot = null;
if (inheritedProps != null && !inheritedProps.isEmpty()) {
for (Structure<InheritedProperties> props : inheritedProps) {
final SvnInheritedProperties result = new SvnInheritedProperties();
result.setProperties(props.<SVNProperties>get(InheritedProperties.properties));
final String pathOrURL = props.<String>get(InheritedProperties.pathOrURL);
if (SVNPathUtil.isURL(pathOrURL)) {
result.setTarget(SvnTarget.fromURL(SVNURL.parseURIEncoded(pathOrURL)));
} else if (SVNPathUtil.isAbsolute(pathOrURL)) {
final File absolutePath = SVNFileUtil.createFilePath(pathOrURL);
result.setTarget(SvnTarget.fromFile(absolutePath));
} else {
if (repositoryRoot == null) {
final Structure<NodeInfo> info = context.getDb().readInfo(target, NodeInfo.reposRootUrl);
repositoryRoot = info.get(NodeInfo.reposRootUrl);
}
if (repositoryRoot == null) {
ISVNWCDb.WCDbAdditionInfo additionInfo = context.getDb().scanAddition(target, ISVNWCDb.WCDbAdditionInfo.AdditionInfoField.reposRootUrl);
repositoryRoot = additionInfo.reposRootUrl;
}
result.setTarget(SvnTarget.fromURL(repositoryRoot.appendPath(pathOrURL, false)));
}
resultList.add(result);
}
getOperation().getTargetInheritedPropertiesReceiver().receive(getOperation().getFirstTarget(), resultList);
}
}
@Override
public boolean isApplicable(SvnGetProperties operation, SvnWcGeneration wcGeneration) throws SVNException {
return !operation.isRevisionProperties() && super.isApplicable(operation, wcGeneration);
}
}