package org.tmatesoft.svn.core.wc2; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.SVNEventAction; /** * Represents commit operation. Commits files or directories into repository. * * <p/> * If <code>targets</code> has zero elements, then do nothing and return * immediately without error. * * <p/> * If the caller's {@link ISVNEventHandler event handler} is not * <code>null</code> it will be called as the commit * progresses with any of the following actions: * {@link SVNEventAction#COMMIT_MODIFIED}, * {@link SVNEventAction#COMMIT_ADDED}, * {@link SVNEventAction#COMMIT_DELETED}, * {@link SVNEventAction#COMMIT_REPLACED}. If the commit succeeds, the * handler will be called with {@link SVNEventAction#COMMIT_COMPLETED} event * action. * * <p/> * If <code>depth</code> is {@link SVNDepth#INFINITY}, commits all changes * to and below named targets. If <code>depth</code> is * {@link SVNDepth#EMPTY}, commits only named targets (that is, only * property changes on named directory targets, and property and content * changes for named file targets). If <code>depth</code> is * {@link SVNDepth#FILES}, behaves as above for named file targets, and for * named directory targets, commits property changes on a named directory * and all changes to files directly inside that directory. If * {@link SVNDepth#IMMEDIATES}, behaves as for {@link SVNDepth#FILES}, and * for subdirectories of any named directory <code>target</code> commits as though for * {@link SVNDepth#EMPTY}. * * <p/> * Unlocks paths in the repository, unless <code>keepLocks</code> is <code>true</code>. * * <p/> * <code>changelists</code> used as a restrictive filter on items that are committed; that is, * doesn't commit anything unless it's a member of one of those changelists. * After the commit completes successfully, removes changelist associations * from the targets, unless <code>keepChangelist</code> is set. If * <code>changelists</code> is empty (or altogether <code>null</code>), no changelist filtering occurs. * * <p/> * If no exception is thrown and {@link SVNCommitInfo#getNewRevision()} is * invalid (<code><0</code>), then the commit was a no-op; nothing needed * to be committed. * * {@link #run()} returns {@link SVNCommitInfo} information about new committed revision. * * {@link #run()} throws {@link org.tmatesoft.svn.core.SVNException} in the following cases: * <ul> * <li/>exception with {@link SVNErrorCode#UNSUPPORTED_FEATURE} error code * - if it is commit from different working copies belonging to different repositories * <li/>exception with {@link SVNErrorCode#CLIENT_PROPERTY_NAME} error code * - if there is standard Subversion property among revision properties * <li/>exception with {@link SVNErrorCode#WC_FOUND_CONFLICT} error code * - if item is remaining in conflict * <li/>exception with {@link SVNErrorCode#ILLEGAL_TARGET} error code * - if item is not under version control * or item's parent is not known to exist in the repository and is not part of the commit, yet item is part of the commit * <li/>exception with {@link SVNErrorCode#WC_PATH_NOT_FOUND} error code * - if item is scheduled for addition within unversioned parent * or item is scheduled for addition, but is missing * <li/>exception with {@link SVNErrorCode#NODE_UNKNOWN_KIND} error code * - if item is of unknown kind * <li/>exception with {@link SVNErrorCode#NODE_UNEXPECTED_KIND} error code * - item has unexpectedly changed special status * <li/>exception with {@link SVNErrorCode#WC_NOT_LOCKED} error code * - if working copy directory/file is missing * <li/>exception with {@link SVNErrorCode#CLIENT_DUPLICATE_COMMIT_URL} error code * - if operation trying to commit different items referring to the same URL * <li/>exception with {@link SVNErrorCode#BAD_URL} error code * - if working copy directory/file is missing * <li/>exception with {@link SVNErrorCode#WC_NOT_LOCKED} error code * - if operation cannot compute base URL for commit operation * <li/>exception with {@link SVNErrorCode#WC_CORRUPT_TEXT_BASE} error code * - if working copy is corrupted * </ul> * * @author TMate Software Ltd. * @version 1.7 */ public class SvnCommit extends AbstractSvnCommit { private boolean keepChangelists; private boolean keepLocks; private ISvnCommitParameters commitParameters; private SvnCommitPacket packet; private boolean force; private boolean isFailOnMultipleRepositories; private boolean combinePackets; private SvnCommitPacket[] splitPackets; private boolean includeFileExternals; private boolean includeDirectoryExternals; protected SvnCommit(SvnOperationFactory factory) { super(factory); } /** * Gets whether or not <code>changelists</code> should be removed. * * @return <code>true</code> if <code>changelists</code> should be removed, otherwise <code>false</code> */ public boolean isKeepChangelists() { return keepChangelists; } /** * Sets whether or not <code>changelists</code> should be removed. * * @param keepChangelists <code>true</code> if <code>changelists</code> should be removed, otherwise <code>false</code> */ public void setKeepChangelists(boolean keepChangelists) { this.keepChangelists = keepChangelists; } /** * Gets whether or not to unlock files in the repository. * * @return <code>true</code> if files should not be unlocked in the repository, otherwise <code>false</code> */ public boolean isKeepLocks() { return keepLocks; } /** * Sets whether or not to unlock files in the repository. * * @param keepLocks <code>true</code> if files should not be unlocked in the repository, otherwise <code>false</code> */ public void setKeepLocks(boolean keepLocks) { this.keepLocks = keepLocks; } /** * Gets operation's parameters of the commit. * * @return commit parameters of the operation * @see ISvnCommitParameters */ public ISvnCommitParameters getCommitParameters() { return commitParameters; } /** * Sets operation's parameters of the commit. * * @param commitParameters commit parameters of the operation * @see ISvnCommitParameters */ public void setCommitParameters(ISvnCommitParameters commitParameters) { this.commitParameters = commitParameters; } /** * Returns operation's commit packet. * Checks arguments and calls {@link SvnOperationFactory#collectCommitItems(SvnCommit)} * if commit packet is <code>null</code>. * * @return commit packet of the operation */ public SvnCommitPacket collectCommitItems() throws SVNException { ensureArgumentsAreValid(); if (packet != null) { return packet; } packet = getOperationFactory().collectCommitItems(this); return packet; } public SvnCommitPacket[] splitCommitPackets(boolean combinePackets) throws SVNException { if (splitPackets != null) { return splitPackets; } splitPackets = collectCommitItems().split(combinePackets); return splitPackets; } /** * If commit packet is <code>null</code>, calls {@link #collectCommitItems()} * to create the commit packet, then executes the operation. */ public SVNCommitInfo run() throws SVNException { if (packet == null) { packet = collectCommitItems(); } return super.run(); } @Override protected void ensureArgumentsAreValid() throws SVNException { super.ensureArgumentsAreValid(); if (getDepth() == SVNDepth.UNKNOWN) { setDepth(SVNDepth.INFINITY); } } @Override protected int getMaximumTargetsCount() { return Integer.MAX_VALUE; } /** * Gets whether or not to force a non-recursive commit; if <code>depth</code> * is {@link SVNDepth#INFINITY} the <code>force</code> flag is ignored. * * @param force <code>true</code> if non-recursive commit should be forced, otherwise <code>false</code> */ public void setForce(boolean force) { this.force = force; } /** * Sets whether or not to force a non-recursive commit; if <code>depth</code> * is {@link SVNDepth#INFINITY} the <code>force</code> flag is ignored. * * @return <code>true</code> if non-recursive commit should be forced, otherwise <code>false</code> */ public boolean isForce() { return this.force; } /** * Gets whether the operation changes working copy * @return <code>true</code> if the operation changes the working copy, otherwise <code>false</code> */ @Override public boolean isChangesWorkingCopy() { return true; } public void setCombinePackets(boolean combine) { this.combinePackets = combine; } public boolean isCombinePackets() { return this.combinePackets; } public boolean isFailOnMultipleRepositories() { return this.isFailOnMultipleRepositories; } public void setFailOnMultipleRepositories(boolean fail) { this.isFailOnMultipleRepositories = fail; } public boolean isIncludeFileExternals() { return includeFileExternals; } public void setIncludeFileExternals(boolean includeFileExternals) { this.includeFileExternals = includeFileExternals; } public boolean isIncludeDirectoryExternals() { return includeDirectoryExternals; } public void setIncludeDirectoryExternals(boolean includeDirectoryExternals) { this.includeDirectoryExternals = includeDirectoryExternals; } @Override protected void initDefaults() { super.initDefaults(); setCombinePackets(true); } }