package org.tmatesoft.svn.core.internal.wc2.ng; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.wc.*; import org.tmatesoft.svn.core.internal.wc17.*; import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb; import org.tmatesoft.svn.core.internal.wc17.db.Structure; import org.tmatesoft.svn.core.internal.wc17.db.StructureFields; import org.tmatesoft.svn.core.internal.wc17.db.SvnWcDbExternals; import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration; import org.tmatesoft.svn.core.io.ISVNEditor; import org.tmatesoft.svn.core.io.SVNCapability; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.wc.*; import org.tmatesoft.svn.core.wc2.ISvnObjectReceiver; import org.tmatesoft.svn.core.wc2.SvnGetStatus; import org.tmatesoft.svn.core.wc2.SvnStatus; import org.tmatesoft.svn.core.wc2.SvnTarget; import org.tmatesoft.svn.util.SVNLogType; import java.io.File; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class SvnNgGetStatus extends SvnNgOperationRunner<SvnStatus, SvnGetStatus> implements ISvnObjectReceiver<SvnStatus> { private boolean targetDeletedInRepository; @Override protected SvnStatus run(SVNWCContext context) throws SVNException { File directoryPath; String targetName; SVNNodeKind kind = context.readKind(getFirstTarget(), false); SVNDepth depth = getOperation().getDepth(); if (kind == SVNNodeKind.DIR) { directoryPath = getFirstTarget(); targetName = ""; } else { directoryPath = SVNFileUtil.getParentFile(getFirstTarget()); targetName = SVNFileUtil.getFileName(getFirstTarget()); if (kind == SVNNodeKind.FILE) { if (depth == SVNDepth.EMPTY) { depth = SVNDepth.FILES; } } else { boolean notAWc = false; try { kind = context.readKind(directoryPath, false); notAWc = kind != SVNNodeKind.DIR; } catch (SVNException e) { notAWc = true; } if (notAWc) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_PATH_NOT_FOUND, "The node ''{0}'' was not found", getFirstTarget()); SVNErrorManager.error(err, SVNLogType.WC); } } } String[] globalIgnores = context.getOptions().getIgnorePatterns(); if (getOperation().isRemote()) { SVNURL url = context.getUrlFromPath(directoryPath); if (url == null) { SVNErrorMessage error = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "Entry ''{0}'' has no URL", directoryPath); SVNErrorManager.error(error, SVNLogType.WC); } SVNRepository repository = getRepositoryAccess().createRepository(url, null, true); long rev; if (getOperation().getRevision() == SVNRevision.HEAD) { rev = -1; } else { rev = context.getRevisionNumber(getOperation().getRevision(), null, repository, getFirstTarget()); } kind = repository.checkPath("", rev); checkCancelled(); SVNStatusEditor17 editor = null; SVNReporter17 reporter = null; if (kind == SVNNodeKind.NONE) { boolean added = context.isNodeAdded(directoryPath); if (added) { boolean replaced = context.isNodeReplaced(directoryPath); if (replaced) { added = false; } } setTargetDeletedInRepository(!added); editor = new SVNStatusEditor17(getFirstTarget(), context, getOperation().getOptions(), getOperation().isReportIgnored(), getOperation().isReportAll(), depth, this); editor.setFileListHook(getOperation().getFileListHook()); checkCancelled(); editor.closeEdit(); } else { editor = new SVNRemoteStatusEditor17(directoryPath, targetName, context, getOperation().getOptions(), getOperation().isReportIgnored(), getOperation().isReportAll(), depth, this); editor.setFileListHook(getOperation().getFileListHook()); SVNRepository locksRepos = getRepositoryAccess().createRepository(url, null, false); checkCancelled(); boolean serverSupportsDepth = repository.hasCapability(SVNCapability.DEPTH); reporter = new SVNReporter17(getFirstTarget(), context, false, !serverSupportsDepth, depth, false, true, true, false, null); SVNStatusReporter17 statusReporter = new SVNStatusReporter17(locksRepos, reporter, editor); String target = "".equals(targetName) ? null : targetName; SVNDepth statusDepth = getOperation().isDepthAsSticky() ? depth : SVNDepth.UNKNOWN; repository.status(rev, target, statusDepth, statusReporter, SVNCancellableEditor.newInstance((ISVNEditor) editor, this, null)); } getOperation().setRemoteRevision(editor.getTargetRevision()); long reportedFiles = reporter != null ? reporter.getReportedFilesCount() : 0; long totalFiles = reporter != null ? reporter.getTotalFilesCount() : 0; SVNEvent event = SVNEventFactory.createSVNEvent(getFirstTarget(), SVNNodeKind.NONE, null, editor.getTargetRevision(), SVNEventAction.STATUS_COMPLETED, null, null, null, reportedFiles, totalFiles); handleEvent(event, ISVNEventHandler.UNKNOWN); } else { SVNStatusEditor17 editor = new SVNStatusEditor17(directoryPath, context, context.getOptions(), getOperation().isReportIgnored(), getOperation().isReportAll(), depth, this); editor.setFileListHook(getOperation().getFileListHook()); try { editor.walkStatus(getFirstTarget(), depth, getOperation().isReportAll(), getOperation().isReportIgnored(), false, globalIgnores != null ? Arrays.asList(globalIgnores) : null); } catch (SVNException e) { if (e.getErrorMessage().getErrorCode() == SVNErrorCode.WC_MISSING) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_NOT_WORKING_COPY, "''{0}'' is not a working copy", getFirstTarget()); SVNErrorManager.error(err, SVNLogType.WC); } throw e; } } if (depth.isRecursive() && getOperation().isReportExternals()) { Map<File, File> externals = context.getDb().getExternalsDefinedBelow(getFirstTarget()); doExternalStatus(externals); } return getOperation().first(); } private void doExternalStatus(Map<File, File> externalsNew) throws SVNException { for (Iterator<File> paths = externalsNew.keySet().iterator(); paths.hasNext(); ) { File fullPath = paths.next(); File wcRootAbsPath = externalsNew.get(fullPath); Structure<StructureFields.ExternalNodeInfo> externalInfo = SvnWcDbExternals.readExternal(getWcContext(), fullPath, wcRootAbsPath, StructureFields.ExternalNodeInfo.kind); ISVNWCDb.SVNWCDbKind externalKind = externalInfo.get(StructureFields.ExternalNodeInfo.kind); if (externalKind != ISVNWCDb.SVNWCDbKind.Dir) { continue; } if (SVNFileType.getType(fullPath) != SVNFileType.DIRECTORY) { continue; } handleEvent(SVNEventFactory.createSVNEvent(fullPath, SVNNodeKind.DIR, null, SVNRepository.INVALID_REVISION, SVNEventAction.STATUS_EXTERNAL, null, null, null), ISVNEventHandler.UNKNOWN); try { SvnGetStatus getStatus = getOperation().getOperationFactory().createGetStatus(); getStatus.setSingleTarget(SvnTarget.fromFile(fullPath)); getStatus.setRevision(SVNRevision.HEAD); getStatus.setDepth(getOperation().getDepth()); getStatus.setRemote(getOperation().isRemote()); getStatus.setReportAll(getOperation().isReportAll()); getStatus.setReportIgnored(getOperation().isReportIgnored()); getStatus.setReportExternals(getOperation().isReportExternals()); getStatus.setReceiver(getOperation().getReceiver()); getStatus.setFileListHook(getOperation().getFileListHook()); getStatus.run(); } catch (SVNException e) { if (e instanceof SVNCancelException) { throw e; } } } } private void setTargetDeletedInRepository(boolean deleted) { this.targetDeletedInRepository = deleted; } private boolean isTargetDeletedInRepository() { return targetDeletedInRepository; } public void receive(SvnTarget target, SvnStatus object) throws SVNException { if (getOperation().getApplicableChangelists() != null && !getOperation().getApplicableChangelists().isEmpty()) { if (!getOperation().getApplicableChangelists().contains(object.getChangelist())) { return; } } if (isTargetDeletedInRepository()) { object.setRepositoryNodeStatus(SVNStatusType.STATUS_DELETED); } getOperation().receive(target, object); } @Override public void reset(SvnWcGeneration wcGeneration) { super.reset(wcGeneration); setTargetDeletedInRepository(false); } }