package org.tmatesoft.svn.core.wc2; 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.internal.wc.SVNErrorManager; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.util.SVNLogType; /** * Represents update operation. Updates working copy to <code>revision</code>. * If no revision is given, it brings working copy up-to-date with {@link SVNRevision#HEAD} revision. * Unversioned paths that are direct children of a versioned path will cause * an update that attempts to add that path, other unversioned paths are * skipped. * * <p/> * The <code>targets</code> can be from multiple working copies from * multiple repositories, but even if they all come from the same repository * there is no guarantee that revision represented by * {@link SVNRevision#HEAD} will remain the same as each path is updated. * * <p/> * If externals are ignored (<code>ignoreExternals</code> is <code>true</code>), doesn't process * externals definitions as part of this operation. * * <p/> * If <code>depth</code> is {@link SVNDepth#INFINITY}, updates fully * recursively. Else if it is {@link SVNDepth#IMMEDIATES} or * {@link SVNDepth#FILES}, updates each <code>target</code> and its file entries, but not * its subdirectories. Else if {@link SVNDepth#EMPTY}, updates exactly each * target, nonrecursively (essentially, updates the target's properties). * * <p/> * If <code>depth</code> is {@link SVNDepth#UNKNOWN}, takes the working * depth from <code>paths</code> and then behaves as described above. * * <p/> * If <code>depthIsSticky</code> is set and <code>depth</code> is not * {@link SVNDepth#UNKNOWN}, then in addition to updating <code>paths</code> * , also sets their sticky ambient depth value to <code>depth</code>. * * <p/> * If <code>allowUnversionedObstructions</code> is <code> * true</code> then the update tolerates existing * unversioned items that obstruct added paths. Only obstructions of the * same type (file or directory) as the added item are tolerated. The text of * obstructing files is left as-is, effectively treating it as a user * modification after the update. Working properties of obstructing items * are set equal to the base properties. If * <code>allowUnversionedObstructions</code> is <code>false * </code> then the update will abort if there are * any unversioned obstructing items. * * <p/> * If the operation's {@link ISVNEventHandler} is non-<code>null</code>, * it is invoked for each item handled by * the update, and also for files restored from text-base. Also * {@link ISVNEventHandler#checkCancelled()} will be used at various places * during the update to check whether the caller wants to stop the update. * * <p/> * This operation requires repository access (in case the repository is not * on the same machine, network connection is established). * * <p/> * {@link #run()} method returns an array of <code>long</code> revisions with each element set to * the revision to which <code>revision</code> was resolved. * * {@link #run()} throws {@link org.tmatesoft.svn.core.SVNException} in the following cases: * <ul> * <li/>exception with {@link SVNErrorCode#ILLEGAL_TARGET} error code * - if <code>target</code> is not a local path * <li/>exception with {@link SVNErrorCode#RA_ILLEGAL_URL} error code * - if external item at the <code>revision</code> doesn't exist, * or if external item at the <code>revision</code> is not file or a directory * <li/>exception with {@link SVNErrorCode#ENTRY_MISSING_URL} error code * - if working copy item that has no URL * </ul> * * @author TMate Software Ltd. * @version 1.7 */ public class SvnUpdate extends AbstractSvnUpdate<long[]> { private boolean depthIsSticky; private boolean makeParents; private boolean treatAddsAsModifications; protected SvnUpdate(SvnOperationFactory factory) { super(factory); } @Override protected void ensureArgumentsAreValid() throws SVNException { for (SvnTarget target : getTargets()) { if (target.isURL()) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ILLEGAL_TARGET, "''{0}'' is not a local path", target.getURL()); SVNErrorManager.error(err, SVNLogType.WC); } } if (getDepth() == null) { setDepth(SVNDepth.UNKNOWN); } if (getDepth() == SVNDepth.UNKNOWN) { setDepthIsSticky(false); } super.ensureArgumentsAreValid(); } /** * Gets whether or not the requested depth should be written to the working copy. * * @return <code>true</code> if the requested depth should be written to the working copy, otherwise <code>false</code> */ public boolean isDepthIsSticky() { return depthIsSticky; } /** * Sets whether or not the requested depth should be written to the working copy. * * @param depthIsSticky <code>true</code> if the requested depth should be written to the working copy, otherwise <code>false</code> */ public void setDepthIsSticky(boolean depthIsSticky) { this.depthIsSticky = depthIsSticky; } /** * Gets whether or not intermediate directories should be made. * * @return <code>true</code> if intermediate directories should be made, otherwise <code>false</code> */ public boolean isMakeParents() { return makeParents; } /** * Sets whether or not intermediate directories should be made. * * @param makeParents <code>true</code> if intermediate directories should be made, otherwise <code>false</code> */ public void setMakeParents(boolean makeParents) { this.makeParents = makeParents; } /** * Gets whether or not adds should be treated as modifications. * * @return <code>true</code> if adds should be treated as modifications, otherwise <code>false</code> */ public boolean isTreatAddsAsModifications() { return treatAddsAsModifications; } /** * Sets whether or not adds should be treated as modifications. * * @param treatAddsAsModifications <code>true</code> if adds should be treated as modifications, otherwise <code>false</code> */ public void setTreatAddsAsModifications(boolean treatAddsAsModifications) { this.treatAddsAsModifications = treatAddsAsModifications; } @Override protected int getMaximumTargetsCount() { return Integer.MAX_VALUE; } /** * 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; } }