/*
* ====================================================================
* 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.core.wc;
import java.io.File;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.wc2.compat.SvnCodec;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc2.*;
/**
* This class provides methods which allow to check out, update, switch and
* relocate a Working Copy as well as export an unversioned directory or file
* from a repository.
*
* <p>
* Here's a list of the <b>SVNUpdateClient</b>'s methods matched against
* corresponing commands of the SVN command line client:
*
* <table cellpadding="3" cellspacing="1" border="0" width="40%" bgcolor="#999933">
* <tr bgcolor="#ADB8D9" align="left">
* <td><b>SVNKit</b></td>
* <td><b>Subversion</b></td>
* </tr>
* <tr bgcolor="#EAEAEA" align="left">
* <td>doCheckout()</td>
* <td>'svn checkout'</td>
* </tr>
* <tr bgcolor="#EAEAEA" align="left">
* <td>doUpdate()</td>
* <td>'svn update'</td>
* </tr>
* <tr bgcolor="#EAEAEA" align="left">
* <td>doSwitch()</td>
* <td>'svn switch'</td>
* </tr>
* <tr bgcolor="#EAEAEA" align="left">
* <td>doRelocate()</td>
* <td>'svn switch --relocate oldURL newURL'</td>
* </tr>
* <tr bgcolor="#EAEAEA" align="left">
* <td>doExport()</td>
* <td>'svn export'</td>
* </tr>
* </table>
*
* @version 1.3
* @author TMate Software Ltd.
* @since 1.2
* @see <a target="_top" href="http://svnkit.com/kb/examples/">Examples</a>
*/
public class SVNUpdateClient extends SVNBasicClient {
private ISVNExternalsHandler myExternalsHandler;
private boolean updateLocksOnDemand;
private boolean exportExpandsKeywords;
/**
* Constructs and initializes an <b>SVNUpdateClient</b> object with the
* specified run-time configuration and authentication drivers.
*
* <p>
* If <code>options</code> is <span class="javakeyword">null</span>, then
* this <b>SVNUpdateClient</b> will be using a default run-time
* configuration driver which takes client-side settings from the default
* SVN's run-time configuration area but is not able to change those
* settings (read more on {@link ISVNOptions} and {@link SVNWCUtil}).
*
* <p>
* If <code>authManager</code> is <span class="javakeyword">null</span>,
* then this <b>SVNUpdateClient</b> will be using a default authentication
* and network layers driver (see
* {@link SVNWCUtil#createDefaultAuthenticationManager()}) which uses
* server-side settings and auth storage from the default SVN's run-time
* configuration area (or system properties if that area is not found).
*
* @param authManager
* an authentication and network layers driver
* @param options
* a run-time configuration options driver
*/
public SVNUpdateClient(ISVNAuthenticationManager authManager, ISVNOptions options) {
super(authManager, options);
}
/**
* Constructs and initializes an <b>SVNUpdateClient</b> object with the
* specified run-time configuration and authentication drivers.
*
* <p/>
* If <code>options</code> is <span class="javakeyword">null</span>, then
* this <b>SVNUpdateClient</b> will be using a default run-time
* configuration driver which takes client-side settings from the default
* SVN's run-time configuration area but is not able to change those
* settings (read more on {@link ISVNOptions} and {@link SVNWCUtil}).
*
* <p/>
* If <code>repositoryPool</code> is <span class="javakeyword">null</span>,
* then {@link org.tmatesoft.svn.core.io.SVNRepositoryFactory} will be used
* to create {@link SVNRepository repository access objects}.
*
* @param repositoryPool
* a repository pool object
* @param options
* a run-time configuration options driver
*/
public SVNUpdateClient(ISVNRepositoryPool repositoryPool, ISVNOptions options) {
super(repositoryPool, options);
}
public SVNUpdateClient(SvnOperationFactory of) {
super(of);
}
protected void initDefaults() {
setExternalsHandler(null);
}
/**
* Sets an externals handler to be used by this client object.
*
* @param externalsHandler
* user's implementation of {@link ISVNExternalsHandler}
* @see #getExternalsHandler()
* @since 1.2
*/
public void setExternalsHandler(ISVNExternalsHandler externalsHandler) {
myExternalsHandler = externalsHandler;
}
/**
* Returns an externals handler used by this update client.
*
* <p/>
* If no user's handler is provided then
* {@link ISVNExternalsHandler#DEFAULT} is returned and used by this client
* object by default.
*
* <p/>
* For more information what externals handlers are for, please, refer to
* {@link ISVNExternalsHandler}.
*
* @return externals handler being in use
* @see #setExternalsHandler(ISVNExternalsHandler)
* @since 1.2
*/
public ISVNExternalsHandler getExternalsHandler() {
if (myExternalsHandler == null) {
return ISVNExternalsHandler.DEFAULT;
}
return myExternalsHandler;
}
/**
* Brings the Working Copy item up-to-date with repository changes at the
* specified revision.
*
* <p>
* As a revision <b>SVNRevision</b>'s pre-defined constant fields can be
* used. For example, to update the Working Copy to the latest revision of
* the repository use {@link SVNRevision#HEAD HEAD}.
*
* @param file
* the Working copy item to be updated
* @param revision
* the desired revision against which the item will be updated
* @param recursive
* if <span class="javakeyword">true</span> and <code>file</code>
* is a directory then the entire tree will be updated, otherwise
* if <span class="javakeyword">false</span> - only items located
* immediately in the directory itself
* @return the revision number to which <code>file</code> was updated to
* @throws SVNException
* @deprecated use
* {@link #doUpdate(File, SVNRevision, SVNDepth, boolean, boolean)}
* instead
*/
public long doUpdate(File file, SVNRevision revision, boolean recursive) throws SVNException {
return doUpdate(file, revision, SVNDepth.fromRecurse(recursive), false, false);
}
/**
* @param file
* @param revision
* @param recursive
* @param force
* @return actual revision number
* @throws SVNException
* @deprecated use
* {@link #doUpdate(File, SVNRevision, SVNDepth, boolean, boolean)}
* instead
*/
public long doUpdate(File file, SVNRevision revision, boolean recursive, boolean force) throws SVNException {
return doUpdate(file, revision, SVNDepth.fromRecurse(recursive), force, false);
}
/**
* Updates working trees <code>paths</code> to <code>revision</code>.
* 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/>
* <code>revision</code> must represent a valid revision number (
* {@link SVNRevision#getNumber()} >= 0), or date (
* {@link SVNRevision#getDate()} != <span class="javakeyword">true</span>),
* or be equal to {@link SVNRevision#HEAD}. If <code>revision</code> does
* not meet these requirements, an exception with the error code
* {@link SVNErrorCode#CLIENT_BAD_REVISION} is thrown.
*
* <p/>
* The paths in <code>paths</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 {@link #isIgnoreExternals() ignored}, 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 target 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 <span
* class="javakeyword">true</span> then the update tolerates existing
* unversioned items that obstruct added paths. Only obstructions of the
* same type (file or dir) 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 <span
* class="javakeyword">false</span> then the update will abort if there are
* any unversioned obstructing items.
*
* <p/>
* If the caller's {@link ISVNEventHandler} is non-<span
* class="javakeyword">null</span>, 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).
*
* @param paths
* working copy paths
* @param revision
* revision to update to
* @param depth
* tree depth to update
* @param allowUnversionedObstructions
* flag that allows tolerating unversioned items during update
* @param depthIsSticky
* flag that controls whether the requested depth should be
* written to the working copy
* @return an array of <code>long</code> revisions with each element set to
* the revision to which <code>revision</code> was resolved
* @throws SVNException
* @since 1.2, SVN 1.5
*/
public long[] doUpdate(File[] paths, SVNRevision revision, SVNDepth depth, boolean allowUnversionedObstructions, boolean depthIsSticky) throws SVNException {
return doUpdate(paths, revision, depth, allowUnversionedObstructions, depthIsSticky, false);
}
public long[] doUpdate(File[] paths, SVNRevision revision, SVNDepth depth, boolean allowUnversionedObstructions, boolean depthIsSticky, boolean makeParents) throws SVNException {
if (paths == null || paths.length == 0) {
return new long[0];
}
SvnUpdate up = getOperationsFactory().createUpdate();
up.setUpdateLocksOnDemand(isUpdateLocksOnDemand());
for (int i = 0; i < paths.length; i++) {
up.addTarget(SvnTarget.fromFile(paths[i]));
}
up.setRevision(revision);
up.setDepth(depth);
up.setDepthIsSticky(depthIsSticky);
up.setAllowUnversionedObstructions(allowUnversionedObstructions);
up.setIgnoreExternals(isIgnoreExternals());
up.setMakeParents(makeParents);
up.setExternalsHandler(SvnCodec.externalsHandler(getExternalsHandler()));
return up.run();
}
/**
* Updates working copy <code></code> to <code>revision</code>. 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/>
* <code>revision</code> must represent a valid revision number (
* {@link SVNRevision#getNumber()} >= 0), or date (
* {@link SVNRevision#getDate()} != <span class="javakeyword">true</span>),
* or be equal to {@link SVNRevision#HEAD}. If <code>revision</code> does
* not meet these requirements, an exception with the error code
* {@link SVNErrorCode#CLIENT_BAD_REVISION} is thrown.
*
* <p/>
* If externals are {@link #isIgnoreExternals() ignored}, 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 <code>path</code> and its file entries,
* but not its subdirectories. Else if {@link SVNDepth#EMPTY}, updates
* exactly <code>path</code>, nonrecursively (essentially, updates the
* target's properties).
*
* <p/>
* If <code>depth</code> is {@link SVNDepth#UNKNOWN}, takes the working
* depth from <code>path</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>path</code>,
* also sets its sticky ambient depth value to <code>depth</codes>.
*
* <p/>
* If <code>allowUnversionedObstructions</code> is <span
* class="javakeyword">true</span> then the update tolerates existing
* unversioned items that obstruct added paths. Only obstructions of the
* same type (file or dir) 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 <span
* class="javakeyword">false</span> then the update will abort if there are
* any unversioned obstructing items.
*
* <p/>
* If the caller's {@link ISVNEventHandler} is non-<span
* class="javakeyword">null</span>, 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).
*
* @param path
* working copy path
* @param revision
* revision to update to
* @param depth
* tree depth to update
* @param allowUnversionedObstructions
* flag that allows tollerating unversioned items during update
* @param depthIsSticky
* flag that controls whether the requested depth should be
* written to the working copy
* @return revision to which <code>revision</code> was resolved
* @throws SVNException
* @since 1.2, SVN 1.5
*/
public long doUpdate(File path, SVNRevision revision, SVNDepth depth, boolean allowUnversionedObstructions, boolean depthIsSticky) throws SVNException {
long[] result = doUpdate(new File[] {path}, revision, depth, allowUnversionedObstructions, depthIsSticky);
return result[0];
}
/**
* Sets whether working copies should be locked on demand or not during an
* update process.
*
* <p>
* For additional description, please, refer to
* {@link #isUpdateLocksOnDemand()}.
*
* @param locksOnDemand
* <span class="javakeyword">true</span> to make update lock a
* working copy tree on demand only (for those subdirectories
* only which will be changed by update)
*/
public void setUpdateLocksOnDemand(boolean locksOnDemand) {
this.updateLocksOnDemand = locksOnDemand;
}
/**
* Says whether the entire working copy should be locked while updating or
* not.
*
* <p/>
* If this method returns <span class="javakeyword">false</span>, then the
* working copy will be closed for all paths involved in the update.
* Otherwise only those working copy subdirectories will be locked, which
* will be either changed by the update or which contain deleted files that
* should be restored during the update; all other versioned subdirectories
* than won't be touched by the update will remain opened for read only
* access without locking.
*
* <p/>
* Locking working copies on demand is intended to improve update
* performance for large working copies because even a no-op update on a
* huge working copy always locks the entire tree by default. And locking a
* working copy tree means opening special lock files for privileged access
* for all subdirectories involved. This makes an update process work
* slower. Locking wc on demand feature suggests such a workaround to
* enhance update performance.
*
* @return <span class="javakeyword">true</span> when locking wc on demand
*/
public boolean isUpdateLocksOnDemand() {
return this.updateLocksOnDemand;
}
/**
* Updates the Working Copy item to mirror a new URL.
*
* <p>
* As a revision <b>SVNRevision</b>'s pre-defined constant fields can be
* used. For example, to update the Working Copy to the latest revision of
* the repository use {@link SVNRevision#HEAD HEAD}.
*
* <p>
* Calling this method is equivalent to
* <code>doSwitch(file, url, SVNRevision.UNDEFINED, revision, recursive)</code>.
*
* @param file
* the Working copy item to be switched
* @param url
* the repository location as a target against which the item
* will be switched
* @param revision
* the desired revision of the repository target
* @param recursive
* if <span class="javakeyword">true</span> and <code>file</code>
* is a directory then the entire tree will be updated, otherwise
* if <span class="javakeyword">false</span> - only items located
* immediately in the directory itself
* @return the revision number to which <code>file</code> was updated to
* @throws SVNException
* @deprecated use
* {@link #doSwitch(File, SVNURL, SVNRevision, SVNRevision, SVNDepth, boolean, boolean)}
* instead
*/
public long doSwitch(File file, SVNURL url, SVNRevision revision, boolean recursive) throws SVNException {
return doSwitch(file, url, SVNRevision.UNDEFINED, revision, SVNDepth.getInfinityOrFilesDepth(recursive), false, false);
}
/**
* Updates the Working Copy item to mirror a new URL.
*
* <p>
* As a revision <b>SVNRevision</b>'s pre-defined constant fields can be
* used. For example, to update the Working Copy to the latest revision of
* the repository use {@link SVNRevision#HEAD HEAD}.
*
* @param file
* the Working copy item to be switched
* @param url
* the repository location as a target against which the item
* will be switched
* @param pegRevision
* a revision in which <code>file</code> is first looked up in
* the repository
* @param revision
* the desired revision of the repository target
* @param recursive
* if <span class="javakeyword">true</span> and <code>file</code>
* is a directory then the entire tree will be updated, otherwise
* if <span class="javakeyword">false</span> - only items located
* immediately in the directory itself
* @return the revision number to which <code>file</code> was updated to
* @throws SVNException
* @deprecated use
* {@link #doSwitch(File, SVNURL, SVNRevision, SVNRevision, SVNDepth, boolean, boolean)}
* instead
*/
public long doSwitch(File file, SVNURL url, SVNRevision pegRevision, SVNRevision revision, boolean recursive) throws SVNException {
return doSwitch(file, url, pegRevision, revision, SVNDepth.getInfinityOrFilesDepth(recursive), false, false);
}
/**
* @param file
* @param url
* @param pegRevision
* @param revision
* @param recursive
* @param force
* @return actual revision number
* @throws SVNException
* @deprecated use
* {@link #doSwitch(File, SVNURL, SVNRevision, SVNRevision, SVNDepth, boolean, boolean)}
* instead
*/
public long doSwitch(File file, SVNURL url, SVNRevision pegRevision, SVNRevision revision, boolean recursive, boolean force) throws SVNException {
return doSwitch(file, url, pegRevision, revision, SVNDepth.getInfinityOrFilesDepth(recursive), force, false);
}
/**
* Switches working tree <code>path</code> to <code>url</code>\
* <code>pegRevision</code> at <code>revision</code>.
*
* <p/>
* Summary of purpose: this is normally used to switch a working directory
* over to another line of development, such as a branch or a tag. Switching
* an existing working directory is more efficient than checking out
* <code>url</code> from scratch.
*
* <p/>
* <code>revision</code> must represent a valid revision number (
* {@link SVNRevision#getNumber()} >= 0), or date (
* {@link SVNRevision#getDate()} != <span class="javakeyword">true</span>),
* or be equal to {@link SVNRevision#HEAD}. If <code>revision</code> does
* not meet these requirements, an exception with the error code
* {@link SVNErrorCode#CLIENT_BAD_REVISION} is thrown.
*
* <p/>
* If <code>depth</code> is {@link SVNDepth#INFINITY}, switches fully
* recursively. Else if it is {@link SVNDepth#IMMEDIATES}, switches
* <code>path</code> and its file children (if any), and switches
* subdirectories but does not update them. Else if {@link SVNDepth#FILES},
* switches just file children, ignoring subdirectories completely. Else if
* {@link SVNDepth#EMPTY}, switches just <code>path</code> and touches
* nothing underneath it.
*
* <p/>
* If <code>depthIsSticky</code> is set and <code>depth</code> is not
* {@link SVNDepth#UNKNOWN}, then in addition to switching <code>path</code>
* , also sets its sticky ambient depth value to <code>depth</code>.
*
* <p/>
* If externals are {@link #isIgnoreExternals() ignored}, doesn't process
* externals definitions as part of this operation.
*
* <p/>
* If <code>allowUnversionedObstructions</code> is <span
* class="javakeyword">true</span> then the switch tolerates existing
* unversioned items that obstruct added paths. Only obstructions of the
* same type (file or dir) as the added item are tolerated. The text of
* obstructing files is left as-is, effectively treating it as a user
* modification after the switch. Working properties of obstructing items
* are set equal to the base properties. If
* <code>allowUnversionedObstructions</code> is <span
* class="javakeyword">false</span> then the switch will abort if there are
* any unversioned obstructing items.
*
* <p/>
* If the caller's {@link ISVNEventHandler} is non-<span
* class="javakeyword">null</span>, it is invoked for paths affected by the
* switch, and also for files restored from text-base. Also
* {@link ISVNEventHandler#checkCancelled()} will be used at various places
* during the switch to check whether the caller wants to stop the switch.
*
* <p/>
* This operation requires repository access (in case the repository is not
* on the same machine, network connection is established).
*
* @param path
* the Working copy item to be switched
* @param url
* the repository location as a target against which the item
* will be switched
* @param pegRevision
* a revision in which <code>path</code> is first looked up in
* the repository
* @param revision
* the desired revision of the repository target
* @param depth
* tree depth to update
* @param allowUnversionedObstructions
* flag that allows tollerating unversioned items during update
* @param depthIsSticky
* flag that controls whether the requested depth should be
* written into the working copy
* @return value of the revision to which the working copy was actually
* switched
* @throws SVNException
* @since 1.2, SVN 1.5
*/
public long doSwitch(File path, SVNURL url, SVNRevision pegRevision, SVNRevision revision, SVNDepth depth, boolean allowUnversionedObstructions, boolean depthIsSticky) throws SVNException {
return doSwitch(path, url, pegRevision, revision, depth, allowUnversionedObstructions, depthIsSticky, true);
}
public long doSwitch(File path, SVNURL url, SVNRevision pegRevision, SVNRevision revision, SVNDepth depth, boolean allowUnversionedObstructions, boolean depthIsSticky, boolean ignoreAncestry) throws SVNException {
SvnSwitch sw = getOperationsFactory().createSwitch();
sw.setUpdateLocksOnDemand(isUpdateLocksOnDemand());
sw.setSwitchTarget(SvnTarget.fromURL(url, pegRevision));
sw.setSingleTarget(SvnTarget.fromFile(path));
sw.setRevision(revision);
sw.setDepth(depth);
sw.setDepthIsSticky(depthIsSticky);
sw.setAllowUnversionedObstructions(allowUnversionedObstructions);
sw.setIgnoreAncestry(ignoreAncestry);
sw.setIgnoreExternals(isIgnoreExternals());
sw.setExternalsHandler(SvnCodec.externalsHandler(getExternalsHandler()));
return sw.run();
}
/**
* Checks out a Working Copy from a repository.
*
* <p>
* If the destination path (<code>dstPath</code>) is <span
* class="javakeyword">null</span> then the last component of
* <code>url</code> is used for the local directory name.
*
* <p>
* As a revision <b>SVNRevision</b>'s pre-defined constant fields can be
* used. For example, to check out a Working Copy at the latest revision of
* the repository use {@link SVNRevision#HEAD HEAD}.
*
* @param url
* a repository location from where a Working Copy will be
* checked out
* @param dstPath
* the local path where the Working Copy will be placed
* @param pegRevision
* the revision at which <code>url</code> will be firstly seen in
* the repository to make sure it's the one that is needed
* @param revision
* the desired revision of the Working Copy to be checked out
* @param recursive
* if <span class="javakeyword">true</span> and <code>url</code>
* is a directory then the entire tree will be checked out,
* otherwise if <span class="javakeyword">false</span> - only
* items located immediately in the directory itself
* @return the revision number of the Working Copy
* @throws SVNException
* <code>url</code> refers to a file, not a directory;
* <code>dstPath</code> already exists but it is a file, not a
* directory; <code>dstPath</code> already exists and is a
* versioned directory but has a different URL (repository
* location against which the directory is controlled)
* @deprecated use
* {@link #doCheckout(SVNURL, File, SVNRevision, SVNRevision, SVNDepth, boolean)}
* instead
*/
public long doCheckout(SVNURL url, File dstPath, SVNRevision pegRevision, SVNRevision revision, boolean recursive) throws SVNException {
return doCheckout(url, dstPath, pegRevision, revision, SVNDepth.fromRecurse(recursive), false);
}
/**
* @param url
* @param dstPath
* @param pegRevision
* @param revision
* @param recursive
* @param force
* @return actual revision number
* @throws SVNException
* @deprecated use
* {@link #doCheckout(SVNURL, File, SVNRevision, SVNRevision, SVNDepth, boolean)}
* instead
*/
public long doCheckout(SVNURL url, File dstPath, SVNRevision pegRevision, SVNRevision revision, boolean recursive, boolean force) throws SVNException {
return doCheckout(url, dstPath, pegRevision, revision, SVNDepth.fromRecurse(recursive), force);
}
/**
* Checks out a working copy of <code>url</code> at <code>revision</code>,
* looked up at <code>pegRevision</code>, using <code>dstPath</code> as the
* root directory of the newly checked out working copy.
*
* <p/>
* If <code>pegRevision</code> is {@link SVNRevision#UNDEFINED}, then it
* defaults to {@link SVNRevision#HEAD}.
*
* <p/>
* <code>revision</code> must represent a valid revision number (
* {@link SVNRevision#getNumber()} >= 0), or date (
* {@link SVNRevision#getDate()} != <span class="javakeyword">true</span>),
* or be equal to {@link SVNRevision#HEAD}. If <code>revision</code> does
* not meet these requirements, an exception with the error code
* {@link SVNErrorCode#CLIENT_BAD_REVISION} is thrown.
*
* <p/>
* If <code>depth</code> is {@link SVNDepth#INFINITY}, checks out fully
* recursively. Else if it is {@link SVNDepth#IMMEDIATES}, checks out
* <code>url</code> and its immediate entries (subdirectories will be
* present, but will be at depth {@link SVNDepth#EMPTY} themselves); else
* {@link SVNDepth#FILES}, checks out <code>url</code> and its file entries,
* but no subdirectories; else if {@link SVNDepth#EMPTY}, checks out
* <code>url</code> as an empty directory at that depth, with no entries
* present.
*
* <p/>
* If <code>depth</code> is {@link SVNDepth#UNKNOWN}, then behave as if for
* {@link SVNDepth#INFINITY}, except in the case of resuming a previous
* checkout of <code>dstPath</code> (i.e., updating), in which case uses the
* depth of the existing working copy.
*
* <p/>
* If externals are {@link #isIgnoreExternals() ignored}, doesn't process
* externals definitions as part of this operation.
*
* <p/>
* If <code>allowUnversionedObstructions</code> is <span
* class="javakeyword">true</span> then the checkout tolerates existing
* unversioned items that obstruct added paths from <code>url</code>. Only
* obstructions of the same type (file or dir) as the added item are
* tolerated. The text of obstructing files is left as-is, effectively
* treating it as a user modification after the checkout. Working properties
* of obstructing items are set equal to the base properties. If
* <code>allowUnversionedObstructions</code> is <span
* class="javakeyword">false</span> then the checkout will abort if there
* are any unversioned obstructing items.
*
* <p/>
* If the caller's {@link ISVNEventHandler} is non-<span
* class="javakeyword">null</span>, it is invoked as the checkout processes.
* Also {@link ISVNEventHandler#checkCancelled()} will be used at various
* places during the checkout to check whether the caller wants to stop the
* checkout.
*
* <p/>
* This operation requires repository access (in case the repository is not
* on the same machine, network connection is established).
*
* @param url
* a repository location from where a Working Copy will be
* checked out
* @param dstPath
* the local path where the Working Copy will be placed
* @param pegRevision
* the revision at which <code>url</code> will be firstly seen in
* the repository to make sure it's the one that is needed
* @param revision
* the desired revision of the Working Copy to be checked out
* @param depth
* tree depth
* @param allowUnversionedObstructions
* flag that allows tollerating unversioned items during
* @return value of the revision actually checked out from the repository
* @throws SVNException
* <ul>
* <li/>{@link SVNErrorCode#UNSUPPORTED_FEATURE} - if <code>url
* </code> refers to a file rather than a directory <li/>
* {@link SVNErrorCode#RA_ILLEGAL_URL} - if <code>url</code>
* does not exist
* </ul>
* @since 1.2, SVN 1.5
*/
public long doCheckout(SVNURL url, File dstPath, SVNRevision pegRevision, SVNRevision revision, SVNDepth depth, boolean allowUnversionedObstructions) throws SVNException {
return doCheckout(url, dstPath, pegRevision, revision, depth, allowUnversionedObstructions, -1);
}
public long doCheckout(SVNURL url, File dstPath, SVNRevision pegRevision, SVNRevision revision, SVNDepth depth, boolean allowUnversionedObstructions, int targetFormat) throws SVNException {
SvnCheckout co = getOperationsFactory().createCheckout();
co.setUpdateLocksOnDemand(isUpdateLocksOnDemand());
co.setSource(SvnTarget.fromURL(url, pegRevision));
co.setSingleTarget(SvnTarget.fromFile(dstPath));
co.setRevision(revision);
co.setDepth(depth);
co.setAllowUnversionedObstructions(allowUnversionedObstructions);
co.setIgnoreExternals(isIgnoreExternals());
co.setExternalsHandler(SvnCodec.externalsHandler(getExternalsHandler()));
co.setTargetWorkingCopyFormat(targetFormat);
return co.run();
}
/**
* Exports a clean directory or single file from a repository.
*
* <p>
* If <code>eolStyle</code> is not <span class="javakeyword">null</span>
* then it should denote a specific End-Of-Line marker for the files to be
* exported. Significant values for <code>eolStyle</code> are:
* <ul>
* <li>"CRLF" (Carriage Return Line Feed) - this causes files to contain
* '\r\n' line ending sequences for EOL markers, regardless of the operating
* system in use (for instance, this EOL marker is used by software on the
* Windows platform).
* <li>"LF" (Line Feed) - this causes files to contain '\n' line ending
* sequences for EOL markers, regardless of the operating system in use (for
* instance, this EOL marker is used by software on the Unix platform).
* <li>"CR" (Carriage Return) - this causes files to contain '\r' line
* ending sequences for EOL markers, regardless of the operating system in
* use (for instance, this EOL marker was used by software on older
* Macintosh platforms).
* <li>"native" - this causes files to contain the EOL markers that are
* native to the operating system on which SVNKit is run.
* </ul>
*
* @param url
* a repository location from where the unversioned
* directory/file will be exported
* @param dstPath
* the local path where the repository items will be exported to
* @param pegRevision
* the revision at which <code>url</code> will be firstly seen in
* the repository to make sure it's the one that is needed
* @param revision
* the desired revision of the directory/file to be exported
* @param eolStyle
* a string that denotes a specific End-Of-Line charecter;
* @param force
* <span class="javakeyword">true</span> to fore the operation
* even if there are local files with the same names as those in
* the repository (local ones will be replaced)
* @param recursive
* if <span class="javakeyword">true</span> and <code>url</code>
* is a directory then the entire tree will be exported,
* otherwise if <span class="javakeyword">false</span> - only
* items located immediately in the directory itself
* @return the revision number of the exported directory/file
* @throws SVNException
* @deprecated use
* {@link #doExport(SVNURL, File, SVNRevision, SVNRevision, String, boolean, SVNDepth)}
*/
public long doExport(SVNURL url, File dstPath, SVNRevision pegRevision, SVNRevision revision, String eolStyle, boolean force, boolean recursive) throws SVNException {
return doExport(url, dstPath, pegRevision, revision, eolStyle, force, SVNDepth.fromRecurse(recursive));
}
/**
* Exports the contents of a subversion repository into a 'clean' directory
* (meaning a directory with no administrative directories).
*
* <p/>
* <code>pegRevision</code> is the revision where the path is first looked
* up. If <code>pegRevision</code> is {@link SVNRevision#UNDEFINED}, then it
* defaults to {@link SVNRevision#HEAD}.
*
* <p/>
* If externals are {@link #isIgnoreExternals() ignored}, doesn't process
* externals definitions as part of this operation.
*
* <p/>
* <code>eolStyle</code> allows you to override the standard eol marker on
* the platform you are running on. Can be either "LF", "CR" or "CRLF" or
* <span class="javakeyword">null</span>. If <span
* class="javakeyword">null</span> will use the standard eol marker. Any
* other value will cause an exception with the error code
* {@link SVNErrorCode#IO_UNKNOWN_EOL} error to be returned.
*
* <p>
* If <code>depth</code> is {@link SVNDepth#INFINITY}, exports fully
* recursively. Else if it is {@link SVNDepth#IMMEDIATES}, exports
* <code>url</code> and its immediate children (if any), but with
* subdirectories empty and at {@link SVNDepth#EMPTY}. Else if
* {@link SVNDepth#FILES}, exports <code>url</code> and its immediate file
* children (if any) only. If <code>depth</code> is {@link SVNDepth#EMPTY},
* then exports exactly <code>url</code> and none of its children.
*
* @param url
* repository url to export from
* @param dstPath
* path to export to
* @param pegRevision
* the revision at which <code>url</code> will be firstly seen in
* the repository to make sure it's the one that is needed
* @param revision
* the desired revision of the directory/file to be exported
* @param eolStyle
* a string that denotes a specific End-Of-Line charecter
* @param overwrite
* if <span class="javakeyword">true</span>, will cause the
* export to overwrite files or directories
* @param depth
* tree depth
* @return value of the revision actually exported
* @throws SVNException
* @since 1.2, SVN 1.5
*/
public long doExport(SVNURL url, File dstPath, SVNRevision pegRevision, SVNRevision revision, String eolStyle, boolean overwrite, SVNDepth depth) throws SVNException {
SvnExport export = getOperationsFactory().createExport();
export.setUpdateLocksOnDemand(isUpdateLocksOnDemand());
export.setSingleTarget(SvnTarget.fromFile(dstPath));
export.setSource(SvnTarget.fromURL(url, pegRevision));
export.setRevision(revision);
export.setEolStyle(eolStyle);
export.setForce(overwrite);
export.setDepth(depth);
export.setExpandKeywords(isExportExpandsKeywords());
export.setIgnoreExternals(isIgnoreExternals());
export.setExternalsHandler(SvnCodec.externalsHandler(getExternalsHandler()));
return export.run();
}
/**
* Exports a clean directory or single file from eihter a source Working
* Copy or a repository.
*
* <p>
* How this method works:
* <ul>
* <li>If <code>revision</code> is different from {@link SVNRevision#BASE
* BASE}, {@link SVNRevision#WORKING WORKING}, {@link SVNRevision#COMMITTED
* COMMITTED}, {@link SVNRevision#UNDEFINED UNDEFINED} - then the repository
* origin of <code>srcPath</code> will be exported (what is done by "remote"
* {@link #doExport(SVNURL, File, SVNRevision, SVNRevision, String, boolean, boolean)
* doExport()}).
* <li>In other cases a clean unversioned copy of <code>srcPath</code> -
* either a directory or a single file - is exported to <code>dstPath</code>.
* </ul>
*
* <p>
* If <code>eolStyle</code> is not <span class="javakeyword">null</span>
* then it should denote a specific End-Of-Line marker for the files to be
* exported. Significant values for <code>eolStyle</code> are:
* <ul>
* <li>"CRLF" (Carriage Return Line Feed) - this causes files to contain
* '\r\n' line ending sequences for EOL markers, regardless of the operating
* system in use (for instance, this EOL marker is used by software on the
* Windows platform).
* <li>"LF" (Line Feed) - this causes files to contain '\n' line ending
* sequences for EOL markers, regardless of the operating system in use (for
* instance, this EOL marker is used by software on the Unix platform).
* <li>"CR" (Carriage Return) - this causes files to contain '\r' line
* ending sequences for EOL markers, regardless of the operating system in
* use (for instance, this EOL marker was used by software on older
* Macintosh platforms).
* <li>"native" - this causes files to contain the EOL markers that are
* native to the operating system on which SVNKit is run.
* </ul>
*
* @param srcPath
* a repository location from where the unversioned
* directory/file will be exported
* @param dstPath
* the local path where the repository items will be exported to
* @param pegRevision
* the revision at which <code>url</code> will be firstly seen in
* the repository to make sure it's the one that is needed
* @param revision
* the desired revision of the directory/file to be exported
* @param eolStyle
* a string that denotes a specific End-Of-Line charecter;
* @param force
* <span class="javakeyword">true</span> to fore the operation
* even if there are local files with the same names as those in
* the repository (local ones will be replaced)
* @param recursive
* if <span class="javakeyword">true</span> and <code>url</code>
* is a directory then the entire tree will be exported,
* otherwise if <span class="javakeyword">false</span> - only
* items located immediately in the directory itself
* @return the revision number of the exported directory/file
* @throws SVNException
* @deprecated use
* {@link #doExport(File, File, SVNRevision, SVNRevision, String, boolean, SVNDepth)}
*/
public long doExport(File srcPath, final File dstPath, SVNRevision pegRevision, SVNRevision revision, String eolStyle, final boolean force, boolean recursive) throws SVNException {
return doExport(srcPath, dstPath, pegRevision, revision, eolStyle, force, SVNDepth.fromRecurse(recursive));
}
/**
* Exports the contents of either a subversion repository or a subversion
* working copy into a 'clean' directory (meaning a directory with no
* administrative directories).
*
* <p/>
* <code>pegRevision</code> is the revision where the path is first looked
* up when exporting from a repository. If <code>pegRevision</code> is
* {@link SVNRevision#UNDEFINED}, then it defaults to
* {@link SVNRevision#WORKING}.
*
* <p/>
* If <code>revision</code> is one of:
* <ul>
* <li/>{@link SVNRevision#BASE}
* <li/>{@link SVNRevision#WORKING}
* <li/>{@link SVNRevision#COMMITTED}
* <li/>{@link SVNRevision#UNDEFINED}
* </ul>
* then local export is performed. Otherwise exporting from the repository.
*
* <p/>
* If externals are {@link #isIgnoreExternals() ignored}, doesn't process
* externals definitions as part of this operation.
*
* <p/>
* <code>eolStyle</code> allows you to override the standard eol marker on
* the platform you are running on. Can be either "LF", "CR" or "CRLF" or
* <span class="javakeyword">null</span>. If <span
* class="javakeyword">null</span> will use the standard eol marker. Any
* other value will cause an exception with the error code
* {@link SVNErrorCode#IO_UNKNOWN_EOL} error to be returned.
*
* <p>
* If <code>depth</code> is {@link SVNDepth#INFINITY}, exports fully
* recursively. Else if it is {@link SVNDepth#IMMEDIATES}, exports
* <code>srcPath</code> and its immediate children (if any), but with
* subdirectories empty and at {@link SVNDepth#EMPTY}. Else if
* {@link SVNDepth#FILES}, exports <code>srcPath</code> and its immediate
* file children (if any) only. If <code>depth</code> is
* {@link SVNDepth#EMPTY}, then exports exactly <code>srcPath</code> and
* none of its children.
*
* @param srcPath
* working copy path
* @param dstPath
* path to export to
* @param pegRevision
* the revision at which <code>url</code> will be firstly seen in
* the repository to make sure it's the one that is needed
* @param revision
* the desired revision of the directory/file to be exported;
* used only when exporting from a repository
* @param eolStyle
* a string that denotes a specific End-Of-Line charecter
* @param overwrite
* if <span class="javakeyword">true</span>, will cause the
* export to overwrite files or directories
* @param depth
* tree depth
* @return value of the revision actually exported
* @throws SVNException
* @since 1.2, SVN 1.5
*/
public long doExport(File srcPath, final File dstPath, SVNRevision pegRevision, SVNRevision revision, String eolStyle, final boolean overwrite, SVNDepth depth) throws SVNException {
SvnExport export = getOperationsFactory().createExport();
export.setUpdateLocksOnDemand(isUpdateLocksOnDemand());
export.setSingleTarget(SvnTarget.fromFile(dstPath));
export.setSource(SvnTarget.fromFile(srcPath, pegRevision));
export.setRevision(revision);
export.setEolStyle(eolStyle);
export.setForce(overwrite);
export.setIgnoreExternals(isIgnoreExternals());
export.setDepth(depth);
export.setExpandKeywords(isExportExpandsKeywords());
export.setExternalsHandler(SvnCodec.externalsHandler(getExternalsHandler()));
return export.run();
}
/**
* Substitutes the beginning part of a Working Copy's URL with a new one.
*
* <p>
* When a repository root location or a URL schema is changed the old URL of
* the Working Copy which starts with <code>oldURL</code> should be
* substituted for a new URL beginning - <code>newURL</code>.
*
* @param dst
* a Working Copy item's path
* @param oldURL
* the old beginning part of the repository's URL that should be
* overwritten
* @param newURL
* a new beginning part for the repository location that will
* overwrite <code>oldURL</code>
* @param recursive
* if <span class="javakeyword">true</span> and <code>dst</code>
* is a directory then the entire tree will be relocated,
* otherwise if <span class="javakeyword">false</span> - only
* <code>dst</code> itself
* @throws SVNException
*/
public void doRelocate(File dst, SVNURL oldURL, SVNURL newURL, boolean recursive) throws SVNException {
SvnRelocate relocate = getOperationsFactory().createRelocate();
relocate.setSingleTarget(SvnTarget.fromFile(dst));
relocate.setFromUrl(oldURL);
relocate.setToUrl(newURL);
relocate.setRecursive(recursive);
relocate.run();
}
/**
* Canonicalizes all urls in the specified Working Copy.
*
* @param dst
* a WC path
* @param omitDefaultPort
* if <span class="javakeyword">true</span> then removes all port
* numbers from urls which equal to default ones, otherwise does
* not
* @param recursive
* recurses an operation
* @throws SVNException
*/
public void doCanonicalizeURLs(File dst, boolean omitDefaultPort, boolean recursive) throws SVNException {
SvnCanonicalizeUrls cu = getOperationsFactory().createCanonicalizeUrls();
cu.setSingleTarget(SvnTarget.fromFile(dst));
cu.setDepth(recursive ? SVNDepth.INFINITY : SVNDepth.IMMEDIATES);
cu.setOmitDefaultPort(omitDefaultPort);
cu.setIgnoreExternals(isIgnoreExternals());
cu.run();
}
/**
* Sets whether keywords must be expanded during an export operation.
*
* @param expand
* <span class="javakeyword">true</span> to expand; otherwise
* <span class="javakeyword">false</span>
* @since 1.3
*/
public void setExportExpandsKeywords(boolean expand) {
this.exportExpandsKeywords = expand;
}
/**
* Says whether keywords expansion during export operations is turned on or
* not.
*
* @return <span class="javakeyword">true</span> if expanding keywords;
* <span class="javakeyword">false</span> otherwise
* @since 1.3
*/
public boolean isExportExpandsKeywords() {
return this.exportExpandsKeywords;
}
}