/* * ==================================================================== * Copyright (c) 2004-2012 TMate Software Ltd. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://svnkit.com/license.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * ==================================================================== */ package org.tmatesoft.svn.cli.svn; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.tmatesoft.svn.cli.SVNCommandUtil; 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.SVNLock; import org.tmatesoft.svn.core.SVNNodeKind; import org.tmatesoft.svn.core.internal.util.SVNDate; import org.tmatesoft.svn.core.internal.util.SVNHashMap; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.internal.util.SVNXMLUtil; import org.tmatesoft.svn.core.internal.wc.SVNConflictVersion; import org.tmatesoft.svn.core.internal.wc.SVNErrorManager; import org.tmatesoft.svn.core.internal.wc.SVNPath; import org.tmatesoft.svn.core.internal.wc.SVNTreeConflictUtil; import org.tmatesoft.svn.core.wc.ISVNInfoHandler; import org.tmatesoft.svn.core.wc.SVNConflictAction; import org.tmatesoft.svn.core.wc.SVNConflictReason; import org.tmatesoft.svn.core.wc.SVNInfo; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNTreeConflictDescription; import org.tmatesoft.svn.core.wc.SVNWCClient; import org.tmatesoft.svn.util.SVNLogType; /** * @version 1.3 * @author TMate Software Ltd. */ public class SVNInfoCommand extends SVNXMLCommand implements ISVNInfoHandler { public SVNInfoCommand() { super("info", null); } protected Collection createSupportedOptions() { Collection options = new LinkedList(); options.add(SVNOption.REVISION); options.add(SVNOption.RECURSIVE); options.add(SVNOption.DEPTH); options.add(SVNOption.TARGETS); options.add(SVNOption.INCREMENTAL); options.add(SVNOption.XML); options.add(SVNOption.CHANGELIST); return options; } public void run() throws SVNException { List targets = new ArrayList(); if (getSVNEnvironment().getTargets() != null) { targets.addAll(getSVNEnvironment().getTargets()); } targets = getSVNEnvironment().combineTargets(targets, true); if (targets.isEmpty()) { targets.add(""); } if (getSVNEnvironment().isXML()) { if (!getSVNEnvironment().isIncremental()) { printXMLHeader("info"); } } else if (getSVNEnvironment().isIncremental()) { SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.CL_ARG_PARSING_ERROR, "'incremental' option only valid in XML mode"), SVNLogType.CLIENT); } SVNDepth depth = getSVNEnvironment().getDepth(); if (depth == SVNDepth.UNKNOWN) { depth = SVNDepth.EMPTY; } SVNWCClient client = getSVNEnvironment().getClientManager().getWCClient(); boolean seenNonExistingTargets = false; for(int i = 0; i < targets.size(); i++) { String targetName = (String) targets.get(i); SVNPath target = new SVNPath(targetName, true); SVNRevision pegRevision = target.getPegRevision(); if (target.isURL() && pegRevision == SVNRevision.UNDEFINED) { pegRevision = SVNRevision.HEAD; } try { if (target.isFile()) { client.doInfo(target.getFile(), pegRevision, getSVNEnvironment().getStartRevision(), depth, getSVNEnvironment().getChangelistsCollection(), this); } else { client.doInfo(target.getURL(), pegRevision, getSVNEnvironment().getStartRevision(), depth, this); } } catch (SVNException e) { SVNErrorMessage err = e.getErrorMessage(); if (err.getErrorCode() == SVNErrorCode.UNVERSIONED_RESOURCE) { getSVNEnvironment().getErr().print(SVNCommandUtil.getLocalPath(target.getTarget()) + ": (Not a versioned resource)\n\n"); } else { getSVNEnvironment().handleWarning(err, new SVNErrorCode[] {SVNErrorCode.RA_ILLEGAL_URL, SVNErrorCode.WC_PATH_NOT_FOUND}, getSVNEnvironment().isQuiet()); getSVNEnvironment().getErr().println(); seenNonExistingTargets = true; } } } if (getSVNEnvironment().isXML() && !getSVNEnvironment().isIncremental()) { printXMLFooter("info"); } if (seenNonExistingTargets) { SVNErrorManager.error(SVNErrorMessage.create(SVNErrorCode.ILLEGAL_TARGET, "Could not display info for all targets because some targets don't exist"), SVNLogType.CLIENT); } } public void handleInfo(SVNInfo info) throws SVNException { if (!getSVNEnvironment().isXML()) { printInfo(info); } else { printInfoXML(info); } } protected void printInfo(SVNInfo info) { StringBuffer buffer = new StringBuffer(); String path = null; if (info.getFile() != null) { path = getSVNEnvironment().getRelativePath(info.getFile()); path = SVNCommandUtil.getLocalPath(path); } else { path = info.getPath(); if ("".equals(path) && info.getURL() != null) { path = SVNPathUtil.tail(info.getURL().getPath()); } } buffer.append("Path: " + path + "\n"); if (info.getKind() != SVNNodeKind.DIR) { buffer.append("Name: " + SVNPathUtil.tail(path.replace(File.separatorChar, '/')) + "\n"); } if (info.getWorkingCopyRoot() != null) { buffer.append("Working Copy Root Path: " + SVNPathUtil.validateFilePath(info.getWorkingCopyRoot().getAbsolutePath())+ "\n"); } buffer.append("URL: " + info.getURL() + "\n"); if (info.getRepositoryRootURL() != null) { buffer.append("Repository Root: " + info.getRepositoryRootURL() + "\n"); } if (info.getRepositoryUUID() != null) { buffer.append("Repository UUID: " + info.getRepositoryUUID() + "\n"); } if (info.getRevision() != null && info.getRevision().isValid()) { buffer.append("Revision: " + info.getRevision() + "\n"); } String kind = info.getKind() == SVNNodeKind.DIR ? "directory" : (info.getKind() != null ? info.getKind().toString() : "none"); buffer.append("Node Kind: " + kind + "\n"); if (!info.isRemote()) { if (info.getSchedule() == null) { buffer.append("Schedule: normal\n"); } else { buffer.append("Schedule: " + info.getSchedule() + "\n"); } if (info.getDepth() != null) { if (info.getDepth() != SVNDepth.UNKNOWN && info.getDepth() != SVNDepth.INFINITY) { buffer.append("Depth: " + info.getDepth() + "\n"); } } if (info.getCopyFromURL() != null) { buffer.append("Copied From URL: " + info.getCopyFromURL() + "\n"); } if (info.getCopyFromRevision() != null && info.getCopyFromRevision().getNumber() >= 0) { buffer.append("Copied From Rev: " + info.getCopyFromRevision() + "\n"); } } if (info.getAuthor() != null) { buffer.append("Last Changed Author: " + info.getAuthor() + "\n"); } if (info.getCommittedRevision() != null && info.getCommittedRevision().getNumber() >= 0) { buffer.append("Last Changed Rev: " + info.getCommittedRevision() + "\n"); } if (info.getCommittedDate() != null) { buffer.append("Last Changed Date: " + SVNDate.formatHumanDate(info.getCommittedDate(), getSVNEnvironment().getClientManager().getOptions()) + "\n"); } if (!info.isRemote()) { if (info.getTextTime() != null) { buffer.append("Text Last Updated: " + SVNDate.formatHumanDate(info.getTextTime(), getSVNEnvironment().getClientManager().getOptions()) + "\n"); } if (info.getPropTime() != null) { buffer.append("Properties Last Updated: " + SVNDate.formatHumanDate(info.getPropTime(), getSVNEnvironment().getClientManager().getOptions()) + "\n"); } if (info.getChecksum() != null) { buffer.append("Checksum: " + info.getChecksum() + "\n"); } if (info.getConflictOldFile() != null) { String cpath = getSVNEnvironment().getRelativePath(info.getConflictOldFile()); cpath = SVNCommandUtil.getLocalPath(cpath); buffer.append("Conflict Previous Base File: " + cpath + "\n"); } if (info.getConflictWrkFile() != null) { String cpath = getSVNEnvironment().getRelativePath(info.getConflictWrkFile()); cpath = SVNCommandUtil.getLocalPath(cpath); buffer.append("Conflict Previous Working File: " + cpath + "\n"); } if (info.getConflictNewFile() != null) { String cpath = getSVNEnvironment().getRelativePath(info.getConflictNewFile()); cpath = SVNCommandUtil.getLocalPath(cpath); buffer.append("Conflict Current Base File: " + cpath + "\n"); } if (info.getPropConflictFile() != null) { String cpath = getSVNEnvironment().getRelativePath(info.getPropConflictFile()); cpath = SVNCommandUtil.getLocalPath(cpath); buffer.append("Conflict Properties File: " + cpath + "\n"); } } if (info.getLock() != null) { SVNLock lock = info.getLock(); if (lock.getID() != null) { buffer.append("Lock Token: " + lock.getID() + "\n"); } if (lock.getOwner() != null) { buffer.append("Lock Owner: " + lock.getOwner() + "\n"); } if (lock.getCreationDate() != null && lock.getCreationDate().getTime() != 0) { buffer.append("Lock Created: " + SVNDate.formatHumanDate(lock.getCreationDate(), getSVNEnvironment().getClientManager().getOptions()) + "\n"); } if (lock.getExpirationDate() != null && lock.getExpirationDate().getTime() != 0) { buffer.append("Lock Expires: " + SVNDate.formatHumanDate(lock.getExpirationDate(), getSVNEnvironment().getClientManager().getOptions()) + "\n"); } if (lock.getComment() != null) { buffer.append("Lock Comment "); int lineCount = SVNCommandUtil.getLinesCount(lock.getComment()); buffer.append(lineCount > 1 ? "(" + lineCount + " lines)" : "(1 line)"); buffer.append(":\n"); buffer.append(lock.getComment()); buffer.append("\n"); } } if (info.getChangelistName() != null) { buffer.append("Changelist: " + info.getChangelistName() + "\n"); } if (info.getTreeConflict() != null) { SVNTreeConflictDescription tc = info.getTreeConflict(); String description = SVNTreeConflictUtil.getHumanReadableConflictDescription(tc); buffer.append("Tree conflict: " + description + "\n"); SVNConflictVersion left = tc.getSourceLeftVersion(); buffer.append(" Source left: " + SVNTreeConflictUtil.getHumanReadableConflictVersion(left) + "\n"); SVNConflictVersion right = tc.getSourceRightVersion(); buffer.append(" Source right: " + SVNTreeConflictUtil.getHumanReadableConflictVersion(right) + "\n"); } buffer.append("\n"); getSVNEnvironment().getOut().print(buffer.toString()); } protected void printInfoXML(SVNInfo info) { StringBuffer buffer = new StringBuffer(); String path = null; if (info.getFile() != null) { path = getSVNEnvironment().getRelativePath(info.getFile()); path = SVNCommandUtil.getLocalPath(path); } else { path = info.getPath(); } Map attrs = new LinkedHashMap(); attrs.put("kind", info.getKind().toString()); attrs.put("path", path); attrs.put("revision", info.getRevision() != SVNRevision.UNDEFINED ? info.getRevision().toString() : "Resource is not under version control."); buffer = openXMLTag("entry", SVNXMLUtil.XML_STYLE_NORMAL, attrs, buffer); String url = info.getURL() != null ? info.getURL().toString() : null; buffer = openCDataTag("url", url, buffer); String rootURL = info.getRepositoryRootURL() != null ? info.getRepositoryRootURL().toString() : null; String uuid = info.getRepositoryUUID(); if (rootURL != null || uuid != null) { buffer = openXMLTag("repository", SVNXMLUtil.XML_STYLE_NORMAL, null, buffer); buffer = openCDataTag("root", rootURL, buffer); buffer = openCDataTag("uuid", uuid, buffer); buffer = closeXMLTag("repository", buffer); } if (info.getFile() != null) { buffer = openXMLTag("wc-info", SVNXMLUtil.XML_STYLE_NORMAL, null, buffer); if (info.getWorkingCopyRoot() != null) { buffer = openCDataTag("wcroot-abspath", SVNPathUtil.validateFilePath(info.getWorkingCopyRoot().getAbsolutePath()), buffer); } String schedule = info.getSchedule(); if (schedule == null || "".equals(schedule)) { schedule = "normal"; } buffer = openCDataTag("schedule", schedule, buffer); if (info.getDepth() != null) { SVNDepth depth = info.getDepth(); if (depth == SVNDepth.UNKNOWN && info.getKind() == SVNNodeKind.FILE) { depth = SVNDepth.INFINITY; } buffer = openCDataTag("depth", depth.getName(), buffer); } if (info.getCopyFromURL() != null) { buffer = openCDataTag("copy-from-url", info.getCopyFromURL().toString(), buffer); } if (info.getCopyFromRevision() != null && info.getCopyFromRevision().isValid()) { buffer = openCDataTag("copy-from-rev", info.getCopyFromRevision().toString(), buffer); } if (info.getTextTime() != null) { buffer = openCDataTag("text-updated", ((SVNDate) info.getTextTime()).format(), buffer); } if (info.getPropTime() != null) { buffer = openCDataTag("prop-updated", ((SVNDate) info.getPropTime()).format(), buffer); } buffer = openCDataTag("checksum", info.getChecksum(), buffer); buffer = openCDataTag("changelist", info.getChangelistName(), buffer); buffer = closeXMLTag("wc-info", buffer); } if (info.getAuthor() != null || info.getCommittedRevision().isValid() || info.getCommittedDate() != null) { openXMLTag("commit", SVNXMLUtil.XML_STYLE_NORMAL, "revision", info.getCommittedRevision().toString(), buffer); buffer = openCDataTag("author", info.getAuthor(), buffer); if (info.getCommittedDate() != null) { buffer = openCDataTag("date", ((SVNDate) info.getCommittedDate()).format(), buffer); } buffer = closeXMLTag("commit", buffer); } if (info.getConflictNewFile() != null || info.getConflictOldFile() != null || info.getConflictWrkFile() != null || info.getPropConflictFile() != null) { buffer = openXMLTag("conflict", SVNXMLUtil.XML_STYLE_NORMAL, null, buffer); if (info.getConflictOldFile() != null) { buffer = openCDataTag("prev-base-file", info.getConflictOldFile().getName(), buffer); } if (info.getConflictWrkFile() != null) { buffer = openCDataTag("prev-wc-file", info.getConflictWrkFile().getName(), buffer); } if (info.getConflictNewFile() != null) { buffer = openCDataTag("cur-base-file", info.getConflictNewFile().getName(), buffer); } if (info.getPropConflictFile() != null) { buffer = openCDataTag("prop-file", info.getPropConflictFile().getName(), buffer); } buffer = closeXMLTag("conflict", buffer); } if (info.getLock() != null) { SVNLock lock = info.getLock(); buffer = openXMLTag("lock", SVNXMLUtil.XML_STYLE_NORMAL, null, buffer); buffer = openCDataTag("token", lock.getID(), buffer); buffer = openCDataTag("owner", lock.getOwner(), buffer); buffer = openCDataTag("comment", lock.getComment(), buffer); if (lock.getCreationDate() != null) { buffer = openCDataTag("created", ((SVNDate) lock.getCreationDate()).format(), buffer); } if (lock.getExpirationDate() != null) { buffer = openCDataTag("expires", ((SVNDate) lock.getExpirationDate()).format(), buffer); } buffer = closeXMLTag("lock", buffer); } if (info.getTreeConflict() != null) { SVNTreeConflictDescription tc = info.getTreeConflict(); Map attributes = new SVNHashMap(); attributes.put("victim", tc.getPath().getName()); attributes.put("kind", tc.getNodeKind().toString()); attributes.put("operation", tc.getOperation().getName()); if (tc.getConflictAction() == SVNConflictAction.EDIT) { attributes.put("action", "edit"); } else if (tc.getConflictAction() == SVNConflictAction.ADD) { attributes.put("action", "add"); } else if (tc.getConflictAction() == SVNConflictAction.DELETE) { attributes.put("action", "delete"); } if (tc.getConflictReason() == SVNConflictReason.EDITED) { attributes.put("reason", "edit"); } else if (tc.getConflictReason() == SVNConflictReason.OBSTRUCTED) { attributes.put("reason", "obstruction"); } else if (tc.getConflictReason() == SVNConflictReason.DELETED) { attributes.put("reason", "delete"); } else if (tc.getConflictReason() == SVNConflictReason.ADDED) { attributes.put("reason", "add"); } else if (tc.getConflictReason() == SVNConflictReason.MISSING) { attributes.put("reason", "missing"); } else if (tc.getConflictReason() == SVNConflictReason.UNVERSIONED) { attributes.put("reason", "unversioned"); } buffer = openXMLTag("tree-conflict", SVNXMLUtil.XML_STYLE_NORMAL, attributes, buffer); SVNConflictVersion left = tc.getSourceLeftVersion(); if (left != null) { buffer = printConflictVersionXML(left, "source-left", buffer); } SVNConflictVersion right = tc.getSourceLeftVersion(); if (right != null) { buffer = printConflictVersionXML(right, "source-right", buffer); } buffer = closeXMLTag("tree-conflict", buffer); } buffer = closeXMLTag("entry", buffer); getSVNEnvironment().getOut().print(buffer.toString()); } private StringBuffer printConflictVersionXML(SVNConflictVersion version, String name, StringBuffer target) { Map attributes = new SVNHashMap(); attributes.put("side", name); if (version.getRepositoryRoot() != null) { attributes.put("repos-url", version.getRepositoryRoot().toString()); } if (version.getPath() != null) { attributes.put("path-in-repos", version.getPath()); } if (version.getPegRevision() >= 0) { attributes.put("revision", Long.toString(version.getPegRevision())); } if (version.getKind() != SVNNodeKind.UNKNOWN) { attributes.put("kind", version.getKind().toString()); } return openXMLTag("version", SVNXMLUtil.XML_STYLE_SELF_CLOSING, attributes, target); } }