You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by gb...@apache.org on 2013/11/17 11:02:41 UTC

svn commit: r1542685 [2/5] - in /subversion/branches/invoke-diff-cmd-feature: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/server-side/svncutter/ notes/ subversion/bindings/javahl/native/ subversion/bindin...

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java Sun Nov 17 10:02:39 2013
@@ -46,6 +46,14 @@ public class ClientNotifyInformation ext
     private static final long serialVersionUID = 2L;
 
     /**
+     * Path, either absolute or relative to the current working
+     * directory (i.e., not relative to an anchor). <code>path</code>
+     * is <code>null</vode> when the real target is an URL that is
+     * available in {@link #url}.
+     */
+    private String path;
+
+    /**
      * The {@link Action} which triggered this event.
      */
     private Action action;
@@ -107,6 +115,12 @@ public class ClientNotifyInformation ext
     private RevisionRange mergeRange;
 
     /**
+     * Similar to {@link #path}, but when not <code>null</code>, the
+     * notification is about a UR>.
+     */
+    private String url;
+
+    /**
      * A common absolute path prefix that can be subtracted from .path.
      */
     private String pathPrefix;
@@ -147,31 +161,35 @@ public class ClientNotifyInformation ext
      * @param changelistName The name of the changelist.
      * @param mergeRange The range of the merge just beginning to occur.
      * @param pathPrefix A common path prefix.
+     * @since 1.9
      */
     public ClientNotifyInformation(String path, Action action, NodeKind kind,
                              String mimeType, Lock lock, String errMsg,
+                             List<ClientException.ErrorMessage> errMsgStack,
                              Status contentState, Status propState,
                              LockStatus lockState, long revision,
                              String changelistName, RevisionRange mergeRange,
-                             String pathPrefix, String propName,
+                             String url, String pathPrefix, String propName,
                              Map<String, String> revProps, long oldRevision,
                              long hunkOriginalStart, long hunkOriginalLength,
                              long hunkModifiedStart, long hunkModifiedLength,
                              long hunkMatchedLine, int hunkFuzz)
     {
-        super(path == null ? "" : path);
+        super(path != null ? path : (url != null ? url : ""));
+        this.path = path;
         this.action = action;
         this.kind = kind;
         this.mimeType = mimeType;
         this.lock = lock;
         this.errMsg = errMsg;
-        this.errMsgStack = null;
+        this.errMsgStack = errMsgStack;
         this.contentState = contentState;
         this.propState = propState;
         this.lockState = lockState;
         this.revision = revision;
         this.changelistName = changelistName;
         this.mergeRange = mergeRange;
+        this.url = url;
         this.pathPrefix = pathPrefix;
         this.propName = propName;
         this.revProps = revProps;
@@ -185,14 +203,11 @@ public class ClientNotifyInformation ext
     }
 
     /**
-     * This constructor will be called only by the native code.
-     *
-     * In addition to all the other parameters, sets the detailed
-     * message stack.
+     * @deprecated Constructor compatible with teh 1.8 API; uses
+     * <code>null</code> URL and errMsgStack values.
      */
-    protected ClientNotifyInformation(String path, Action action, NodeKind kind,
+    public ClientNotifyInformation(String path, Action action, NodeKind kind,
                              String mimeType, Lock lock, String errMsg,
-                             List<ClientException.ErrorMessage> errMsgStack,
                              Status contentState, Status propState,
                              LockStatus lockState, long revision,
                              String changelistName, RevisionRange mergeRange,
@@ -202,18 +217,18 @@ public class ClientNotifyInformation ext
                              long hunkModifiedStart, long hunkModifiedLength,
                              long hunkMatchedLine, int hunkFuzz)
     {
-        this(path, action, kind, mimeType, lock, errMsg,
+        this(path, action, kind, mimeType, lock, errMsg, null,
              contentState, propState, lockState, revision,
-             changelistName, mergeRange, pathPrefix, propName,
-             revProps, oldRevision,
+             changelistName, mergeRange, null, pathPrefix,
+             propName, revProps, oldRevision,
              hunkOriginalStart, hunkOriginalLength,
              hunkModifiedStart, hunkModifiedLength,
              hunkMatchedLine, hunkFuzz);
-        this.errMsgStack = errMsgStack;
     }
 
     /**
      * @return The path of the item, which is the source of the event.
+     *         This may actually be a URL.
      */
     public String getPath()
     {
@@ -221,6 +236,15 @@ public class ClientNotifyInformation ext
     }
 
     /**
+     * @return {@link #path}, which may be <code>null</code>.
+     * @since 1.9
+     */
+    public String getNotifiedPath()
+    {
+        return this.path;
+    }
+
+    /**
      * @return The {@link Action} which triggered this event.
      */
     public Action getAction()
@@ -317,6 +341,15 @@ public class ClientNotifyInformation ext
     }
 
     /**
+     * @return {@link #url}, which may be <code>null</code>
+     * @since 1.9
+     */
+    public String getUrl()
+    {
+        return this.url;
+    }
+
+    /**
      * @return The common absolute path prefix.
      */
     public String getPathPrefix()

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java Sun Nov 17 10:02:39 2013
@@ -1082,6 +1082,19 @@ public interface ISVNClient
     String getConfigDirectory() throws ClientException;
 
     /**
+     * Set an event handler that will be called every time the
+     * configuration is loaded by this client object.
+     */
+    void setConfigEventHandler(ConfigEvent configHandler)
+            throws ClientException;
+
+    /**
+     * Return a reference to the installed configuration event
+     * handler. The returned value may be <code>null</code>.
+     */
+    ConfigEvent getConfigEventHandler() throws ClientException;
+
+    /**
      * cancel the active operation
      * @throws ClientException
      */

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java Sun Nov 17 10:02:39 2013
@@ -578,6 +578,12 @@ public class SVNClient implements ISVNCl
     public native String getConfigDirectory()
             throws ClientException;
 
+    public native void setConfigEventHandler(ConfigEvent configHandler)
+            throws ClientException;
+
+    public native ConfigEvent getConfigEventHandler()
+            throws ClientException;
+
     public native void cancelOperation()
             throws ClientException;
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java Sun Nov 17 10:02:39 2013
@@ -29,12 +29,16 @@ import org.apache.subversion.javahl.util
 
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
 public class SVNUtil
 {
     //
     // Global configuration
     //
+    private static final ConfigLib configLib = new ConfigLib();
 
     /**
      * Enable storing authentication credentials in Subversion's
@@ -51,7 +55,7 @@ public class SVNUtil
     public static void enableNativeCredentialsStore()
         throws ClientException
       {
-          new ConfigLib().enableNativeCredentialsStore();
+          configLib.enableNativeCredentialsStore();
       }
 
     /**
@@ -75,7 +79,7 @@ public class SVNUtil
     public static void disableNativeCredentialsStore()
         throws ClientException
       {
-          new ConfigLib().disableNativeCredentialsStore();
+          configLib.disableNativeCredentialsStore();
       }
 
     /**
@@ -84,37 +88,13 @@ public class SVNUtil
     public static boolean isNativeCredentialsStoreEnabled()
         throws ClientException
       {
-          return new ConfigLib().isNativeCredentialsStoreEnabled();
-      }
-
-    /**
-     * Set an event handler that will be called every time the
-     * configuration is loaded.
-     * <p>
-     * This setting will be inherited by all ISVNClient and ISVNRemote
-     * objects. Changing the setting will not affect existing such
-     * objects.
-     * @throws ClientException
-     */
-    public static void setConfigEventHandler(ConfigEvent configHandler)
-        throws ClientException
-      {
-          new ConfigLib().setConfigEventHandler(configHandler);
-      }
-
-    /**
-     * Return a reference to the installed configuration event
-     * handler. The returned value may be <code>null</code>.
-     */
-    public static ConfigEvent getConfigEventHandler()
-        throws ClientException
-      {
-          return new ConfigLib().getConfigEventHandler();
+          return configLib.isNativeCredentialsStoreEnabled();
       }
 
     //
     // Diff and Merge
     //
+    private static final DiffLib diffLib = new DiffLib();
 
     /**
      * Options to control the behaviour of the file diff routines.
@@ -233,10 +213,10 @@ public class SVNUtil
                                    OutputStream resultStream)
         throws ClientException
     {
-        return new DiffLib().fileDiff(originalFile, modifiedFile, diffOptions,
-                                      originalHeader, modifiedHeader,
-                                      headerEncoding,
-                                      relativeToDir, resultStream);
+        return diffLib.fileDiff(originalFile, modifiedFile, diffOptions,
+                                originalHeader, modifiedHeader,
+                                headerEncoding,
+                                relativeToDir, resultStream);
     }
 
 
@@ -277,16 +257,17 @@ public class SVNUtil
                                     OutputStream resultStream)
         throws ClientException
     {
-        return new DiffLib().fileMerge(originalFile, modifiedFile, latestFile,
-                                       diffOptions,
-                                       conflictOriginal, conflictModified,
-                                       conflictLatest, conflictSeparator,
-                                       conflictStyle, resultStream);
+        return diffLib.fileMerge(originalFile, modifiedFile, latestFile,
+                                 diffOptions,
+                                 conflictOriginal, conflictModified,
+                                 conflictLatest, conflictSeparator,
+                                 conflictStyle, resultStream);
     }
 
     //
     // Property validation and parsing
     //
+    private static final PropLib propLib = new PropLib();
 
     /**
      * Validate the value of an <code>svn:</code> property on file or
@@ -308,7 +289,7 @@ public class SVNUtil
         String mimeType)
         throws ClientException
     {
-        return new PropLib().canonicalizeNodeProperty(
+        return propLib.canonicalizeNodeProperty(
             name, value, path, kind, mimeType, null);
     }
 
@@ -337,7 +318,335 @@ public class SVNUtil
         String mimeType, InputStream fileContents)
         throws ClientException
     {
-        return new PropLib().canonicalizeNodeProperty(
+        return propLib.canonicalizeNodeProperty(
             name, value, path, kind, mimeType, fileContents);
     }
+
+    /**
+     * Parse <code>description</code>, assuming it is an externals
+     * specification in the format required for the
+     * <code>svn:externals</code> property, and return a list of
+     * parsed external items.
+     * @param description The externals description.
+     * @param parentDirectory Used to construct error messages.
+     * @param canonicalizeUrl Whe <code>true</code>, canonicalize the
+     *     <code>url</code> member of the returned objects. If the
+     *     <code>url</code> member refers to an absolute URL, it will
+     *     be canonicalized as URL consistent with the way URLs are
+     *     canonicalized throughout the Subversion API. If, however,
+     *     the <code>url</code> member makes use of the recognized
+     *     (SVN-specific) relative URL syntax for
+     *     <code>svn:externals</code>, "canonicalization" is an
+     *     ill-defined concept which may even result in munging the
+     *     relative URL syntax beyond recognition. You've been warned.
+     * @return a list of {@link ExternalItem}s
+     */
+    public static List<ExternalItem> parseExternals(byte[] description,
+                                                    String parentDirectory,
+                                                    boolean canonicalizeUrl)
+        throws ClientException
+    {
+        return propLib.parseExternals(description, parentDirectory,
+                                      canonicalizeUrl);
+    }
+
+    /**
+     * Unparse and list of external items into a format suitable for
+     * the value of the <code>svn:externals</code> property and
+     * validate the result.
+     * @param items The list of {@link ExternalItem}s
+     * @param parentDirectory Used to construct error messages.
+     * @param compatibleWithSvn1_5 When <code>true</code>, the format
+     *     of the returned property value will be compatible with
+     *     clients older than Subversion 1.5.
+     */
+    public static byte[] unparseExternals(List<ExternalItem> items,
+                                          String parentDirectory)
+        throws SubversionException
+    {
+        return propLib.unparseExternals(items, parentDirectory, false);
+    }
+
+    /**
+     * Unparse and list of external items into a format suitable for
+     * the value of the <code>svn:externals</code> property compatible
+     * with Subversion clients older than release 1.5, and validate
+     * the result.
+     * @param items The list of {@link ExternalItem}s
+     * @param parentDirectory Used to construct error messages.
+     */
+    public static byte[] unparseExternalsForAncientUnsupportedClients(
+        List<ExternalItem> items, String parentDirectory)
+        throws SubversionException
+    {
+        return propLib.unparseExternals(items, parentDirectory, true);
+    }
+
+    /**
+     * If the URL in <code>external</code> is relative, resolve it to
+     * an absolute URL, using <code>reposRootUrl</code> and
+     * <code>parentDirUrl</code> to provide contest.
+     *<p>
+     * Regardless if the URL is absolute or not, if there are no
+     * errors, the returned URL will be canonicalized.
+     *<p>
+     * The following relative URL formats are supported:
+     * <dl>
+     *  <dt><code>../</code></dt>
+     *  <dd>relative to the parent directory of the external</dd>
+     *  <dt><code>^/</code></dt>
+     *  <dd>relative to the repository root</dd>
+     *  <dt><code>//</code></dt>
+     *  <dd>relative to the scheme</dd>
+     *  <dt><code>/</code></dt>
+     *  <dd>relative to the server's hostname</dd>
+     * </dl>
+     *<p>
+     * The <code>../<code> and ^/ relative URLs may use <code>..<code>
+     * to remove path elements up to the server root.
+     *<p>
+     * The external URL should not be canonicalized before calling
+     * this function, as otherwise the scheme relative URL
+     * '<code>//host/some/path</code>' would have been canonicalized
+     * to '<code>/host/some/path</code>' and we would not be able to
+     * match on the leading '<code>//</code>'.
+    */
+    public static String resolveExternalsUrl(ExternalItem external,
+                                             String reposRootUrl,
+                                             String parentDirUrl)
+        throws ClientException
+    {
+        return propLib.resolveExternalsUrl(
+                   external, reposRootUrl, parentDirUrl);
+    }
+
+    //
+    // Newline translation and keyword expansion
+    //
+    private static final SubstLib substLib = new SubstLib();
+
+    /**
+     * Use the linefeed code point ('<code>\x0a</code>')
+     * for the newline separator.
+     * @see translateStream
+     * @see untranslateStream
+     */
+    public static final byte[] EOL_LF = substLib.EOL_LF;
+
+    /**
+     * Use the carraige-return code point ('<code>\x0d</code>')
+     * for the newline separator.
+     * @see translateStream
+     * @see untranslateStream
+     */
+    public static final byte[] EOL_CR = substLib.EOL_CR;
+
+    /**
+     * Use carriage-return/linefeed sequence ('<code>\x0d\x0a</code>')
+     * for the newline separator.
+     * @see translateStream
+     * @see untranslateStream
+     */
+    public static final byte[] EOL_CRLF = substLib.EOL_CRLF;
+
+
+    /**
+     * Build a dictionary of expanded keyword values, given the
+     * contents of a file's <code>svn:keywords</code> property, its
+     * revision, URL, the date it was committed on, the author of the
+     * commit and teh URL of the repository root.
+     *<p>
+     * Custom keywords defined in <code>svn:keywords</code> properties
+     * are expanded using the provided parameters and in accordance
+     * with the following format substitutions in the
+     * <code>keywordsValue</code>:
+     * <dl>
+     *   <dt><code>%a</dt></code>
+     * <dd>The author.</dd>
+     *   <dt><code>%b</dt></code>
+     * <dd>The basename of the URL.</dd>
+     *   <dt><code>%d</dt></code>
+     * <dd>Short format of the date.</dd>
+     *   <dt><code>%D</dt></code>
+     * <dd>Long format of the date.</dd>
+     *   <dt><code>%P</dt></code>
+     * <dd>The file's path, relative to the repository root URL.</dd>
+     *   <dt><code>%r</dt></code>
+     * <dd>The revision.</dd>
+     *   <dt><code>%R</dt></code>
+     * <dd>The URL to the root of the repository.</dd>
+     *   <dt><code>%u</dt></code>
+     * <dd>The URL of the file.</dd>
+     *   <dt><code>%_</dt></code>
+     * <dd>A space (keyword definitions cannot contain a literal space).</dd>
+     *   <dt><code>%%</dt></code>
+     * <dd>A literal '%'.</dd>
+     *   <dt><code>%H</dt></code>
+     * <dd>Equivalent to <code>%P%_%r%_%d%_%a</code>.</dd>
+     *   <dt><code>%I</dt></code>
+     * <dd>Equivalent to <code>%b%_%r%_%d%_%a</code>.</dd>
+     * </dl>
+     *<p>
+     * Custom keywords are defined by appending '=' to the keyword
+     * name, followed by a string containing any combination of the
+     * format substitutions.
+     *<p>
+     * Any of the <code>revision</code>, <code>url</code>,
+     * <code>reposRootUrl</code>, <code>date</code> and
+     * <code>author</code> parameters may be <code>null</code>, or
+     * {@link Revision#SVN_INVALID_REVNUM} for <code>revision</code>,
+     * to indicate that the information is not present. Each piece of
+     * information that is not present expands to the empty string
+     * wherever it appears in an expanded keyword value.  (This can
+     * result in multiple adjacent spaces in the expansion of a
+     * multi-valued keyword such as "<code>Id</code>".)
+     */
+    public static Map<String, byte[]> buildKeywords(byte[] keywordsValue,
+                                                    long revision,
+                                                    String url,
+                                                    String reposRootUrl,
+                                                    Date date,
+                                                    String author)
+        throws SubversionException, ClientException
+    {
+        return substLib.buildKeywords(keywordsValue, revision,
+                                      url, reposRootUrl, date, author);
+    }
+
+    /**
+     * Return a stream which performs end-of-line translation and
+     * keyword expansion when read from.
+     *<p>
+     * Make sure you close the reurned stream stream to ensure all
+     * data are flushed and cleaned up (this will also close the
+     * provided stream).
+     *<p>
+     * If <code>eolMarker</code> is not <code>null</code>, replace
+     * whatever any end-of-line sequences in the input with
+     * <code>eolMarker</code>.  If the input has an inconsistent line
+     * ending style, then:
+     * <ul>
+     *   <li>if <code>repairEol</code> is <code>false</code>, then a
+     *       subsequent read or other operation on the stream will
+     *       generate an error when the inconsistency is detected;</li>
+     *   <li>if <code>repaorEol</code> is <code>true</code>, convert any
+     *       line ending to <code>eolMarker</code>.<br/>
+     *       Recognized line endings are: "\n", "\r", and "\r\n".</li>
+     * </ul>
+     *<p>
+     * Expand or contract keywords using the contents of
+     * <code>keywords</code> as the new values.  If
+     * <code>expandKeywords</code> is <code>true</code>, expand
+     * contracted keywords and re-expand expanded keywords; otherwise,
+     * contract expanded keywords and ignore contracted ones.
+     * Keywords not found in the dictionary are ignored (not
+     * contracted or expanded).  If the <code>keywords</code> itself
+     * is <code>null</code>, keyword substitution will be altogether
+     * ignored.
+     *<p>
+     * Detect only keywords that are no longer than
+     * <code>SVN_KEYWORD_MAX_LEN</code> bytes (currently: 255),
+     * including the delimiters and the keyword itself.
+     *<p>
+     * Recommendation: if <code>expandKeywords</code> is
+     * <code>false</code>, then you don't care about the keyword
+     * values, so just put <code>null</code> values into the
+     * <code>keywords</code> dictionary.
+     *<p>
+     * If the inner stream implements marking and seeking via
+     * {@link InputStream#mark} and {@link InputStream#reset}, the
+     * translated stream will too.
+     *
+     * @param source the source (untranslated) stream.
+     * @param eolMarker the byte sequence to use as the end-of-line marker;
+     *     must be one of {@link #EOL_LF}, {@link #EOL_CR}
+     *     or {@link #EOL_CRLF}.
+     * @param repairEol flag to repair end-of-lines; see above
+     * @param keywords the keyword dictionary; see {@link buildKeywords}
+     * @param expandKeywords flag to expand keywords
+     */
+    public static InputStream translateStream(InputStream source,
+                                              byte[] eolMarker,
+                                              boolean repairEol,
+                                              Map<String, byte[]> keywords,
+                                              boolean expandKeywords)
+        throws SubversionException, ClientException
+    {
+        return substLib.translateInputStream(
+                    source, eolMarker, repairEol,
+                    keywords, true, expandKeywords,
+                    null, Revision.SVN_INVALID_REVNUM,
+                    null, null, null, null);
+    }
+
+    /**
+     * Expand keywords and return a stream which performs end-of-line
+     * translation and keyword expansion when read from.
+     * @see buildKeywords
+     * @see translateStream(InputStream,byte[],boolean,Map,boolean)
+     */
+    public static InputStream translateStream(InputStream source,
+                                              byte[] eolMarker,
+                                              boolean repairEol,
+                                              boolean expandKeywords,
+                                              byte[] keywordsValue,
+                                              long revision,
+                                              String url,
+                                              String reposRootUrl,
+                                              Date date,
+                                              String author)
+        throws SubversionException, ClientException
+    {
+        return substLib.translateInputStream(
+                    source, eolMarker, repairEol,
+                    null, false, expandKeywords,
+                    keywordsValue, revision,
+                    url, reposRootUrl, date, author);
+    }
+
+    /**
+     * Return a stream which performs end-of-line translation and
+     * keyword expansion when written to. Behaves like
+     * {@link #translateStream(InputStream,byte[],boolean,Map,boolean)},
+     * except that it translates an <code>OutputStream</code> and never
+     * supports marking and seeking.
+     */
+    public static OutputStream translateStream(OutputStream destination,
+                                               byte[] eolMarker,
+                                               boolean repairEol,
+                                               Map<String, byte[]> keywords,
+                                               boolean expandKeywords)
+        throws SubversionException, ClientException
+    {
+        return substLib.translateOutputStream(
+                    destination, eolMarker, repairEol,
+                    keywords, true, expandKeywords,
+                    null, Revision.SVN_INVALID_REVNUM,
+                    null, null, null, null);
+    }
+
+    /**
+     * Expand keywords and return a stream which performs end-of-line
+     * translation and keyword expansion when written to.
+     * @see buildKeywords
+     * @see translateStream(OutputStream,byte[],boolean,Map,boolean)
+     */
+    public static OutputStream translateStream(OutputStream destination,
+                                               byte[] eolMarker,
+                                               boolean repairEol,
+                                               boolean expandKeywords,
+                                               byte[] keywordsValue,
+                                               long revision,
+                                               String url,
+                                               String reposRootUrl,
+                                               Date date,
+                                               String author)
+        throws SubversionException, ClientException
+    {
+        return substLib.translateOutputStream(
+                    destination, eolMarker, repairEol,
+                    null, false, expandKeywords,
+                    keywordsValue, revision,
+                    url, reposRootUrl, date, author);
+    }
 }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java Sun Nov 17 10:02:39 2013
@@ -60,6 +60,7 @@ public class RemoteFactory
                          String username, String password,
                          UserPasswordCallback prompt,
                          ProgressCallback progress,
+                         ConfigEvent configHandler,
                          TunnelAgent tunnelAgent)
     {
         setConfigDirectory(configDirectory);
@@ -67,6 +68,7 @@ public class RemoteFactory
         setPassword(password);
         setPrompt(prompt);
         setProgressCallback(progress);
+        setConfigEventHandler(configHandler);
         setTunnelAgent(tunnelAgent);
     }
 
@@ -127,6 +129,16 @@ public class RemoteFactory
     }
 
     /**
+     * Set an event handler that will be called every time the
+     * configuration is loaded by the ISVNRemote objects created by
+     * this factory.
+     */
+    public void setConfigEventHandler(ConfigEvent configHandler)
+    {
+        this.configHandler = configHandler;
+    }
+
+    /**
      * Set callbacks for ra_svn tunnel handling.
      */
     public void setTunnelAgent(TunnelAgent tunnelAgent)
@@ -151,7 +163,8 @@ public class RemoteFactory
             throws ClientException, SubversionException
     {
         return open(1, url, null, configDirectory,
-                    username, password, prompt, progress, tunnelAgent);
+                    username, password, prompt, progress,
+                    configHandler, tunnelAgent);
     }
 
     /**
@@ -178,7 +191,8 @@ public class RemoteFactory
             throw new IllegalArgumentException(
                 "retryAttempts must be positive");
         return open(retryAttempts, url, null, configDirectory,
-                    username, password, prompt, progress, tunnelAgent);
+                    username, password, prompt, progress,
+                    configHandler, tunnelAgent);
     }
 
     /**
@@ -205,7 +219,8 @@ public class RemoteFactory
         if (reposUUID == null)
             throw new IllegalArgumentException("reposUUID may not be null");
         return open(1, url, reposUUID, configDirectory,
-                    username, password, prompt, progress, tunnelAgent);
+                    username, password, prompt, progress,
+                    configHandler, tunnelAgent);
     }
 
     /**
@@ -239,7 +254,8 @@ public class RemoteFactory
             throw new IllegalArgumentException(
                 "retryAttempts must be positive");
         return open(retryAttempts, url, reposUUID, configDirectory,
-                    username, password, prompt, progress, tunnelAgent);
+                    username, password, prompt, progress,
+                    configHandler, tunnelAgent);
     }
 
     private String configDirectory;
@@ -247,6 +263,7 @@ public class RemoteFactory
     private String password;
     private UserPasswordCallback prompt;
     private ProgressCallback progress;
+    private ConfigEvent configHandler;
     private TunnelAgent tunnelAgent;
 
     /* Native factory implementation. */
@@ -256,6 +273,7 @@ public class RemoteFactory
                                           String username, String password,
                                           UserPasswordCallback prompt,
                                           ProgressCallback progress,
+                                          ConfigEvent configHandler,
                                           TunnelAgent tunnelAgent)
             throws ClientException, SubversionException;
 }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Revision.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Revision.java?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Revision.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Revision.java Sun Nov 17 10:02:39 2013
@@ -277,6 +277,16 @@ public class Revision implements java.io
                 throw new IllegalArgumentException("a date must be specified");
             revDate = date;
         }
+
+        /**
+         * Create a revision from a timestamp in milliseconds.
+         * Used by the native implementaiton.
+         */
+        private DateSpec(long milliseconds)
+        {
+            this(new Date(milliseconds));
+        }
+
         /**
          * Returns the date of the revision
          * @return the date
@@ -316,7 +326,6 @@ public class Revision implements java.io
         {
             return revDate.hashCode();
         }
-
     }
 
     /**

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java Sun Nov 17 10:02:39 2013
@@ -54,12 +54,4 @@ public class ConfigLib
     /** @see SVNUtil.isNativeCredentialsStoreEnabled */
     public native boolean isNativeCredentialsStoreEnabled()
         throws ClientException;
-
-    /** @see SVNUtil.setConfigEventHandler */
-    public native void setConfigEventHandler(ConfigEvent configHandler)
-        throws ClientException;
-
-    /** @see SVNUtil.setConfigEventHandler */
-    public native ConfigEvent getConfigEventHandler()
-        throws ClientException;
 }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/PropLib.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/PropLib.java?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/PropLib.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/PropLib.java Sun Nov 17 10:02:39 2013
@@ -25,10 +25,13 @@ package org.apache.subversion.javahl.uti
 
 import org.apache.subversion.javahl.SVNUtil;
 import org.apache.subversion.javahl.ClientException;
+import org.apache.subversion.javahl.SubversionException;
 import org.apache.subversion.javahl.NativeResources;
+import org.apache.subversion.javahl.types.ExternalItem;
 import org.apache.subversion.javahl.types.NodeKind;
 import org.apache.subversion.javahl.types.Revision;
 
+import java.util.List;
 import java.io.InputStream;
 
 /**
@@ -45,7 +48,7 @@ public class PropLib
         NativeResources.loadNativeLibrary();
     }
 
-    /** @see SVNUtil.canonicalizeSvnProperty */
+    /** @see SVNUtil#canonicalizeSvnProperty */
     public byte[] canonicalizeNodeProperty(String name, byte[] value,
                                            String path, NodeKind kind,
                                            String mimeType,
@@ -64,4 +67,24 @@ public class PropLib
                                         InputStream fileContents,
                                         boolean skipSomeChecks)
         throws ClientException;
+
+
+    /** @see SVNUtil.parseExternals */
+    public native List<ExternalItem> parseExternals(byte[] description,
+                                                    String parentDirectory,
+                                                    boolean canonicalizeUrl)
+        throws ClientException;
+
+    /** @see SVNUtil#unparseExternals */
+    public native byte[] unparseExternals(List<ExternalItem> items,
+                                          String parentDirectory,
+                                          boolean old_format)
+        throws SubversionException;
+
+
+    /** @see SVNUtil#resolveExternalsUrl */
+    public native String resolveExternalsUrl(ExternalItem external,
+                                             String reposRootUrl,
+                                             String parentDirUrl)
+        throws ClientException;
 }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java Sun Nov 17 10:02:39 2013
@@ -3965,6 +3965,7 @@ public class BasicTests extends SVNTests
     {
         public void doChangelist(String path, String changelist)
         {
+            path = fileToSVNPath(new File(path), true);
             if (super.containsKey(path))
             {
                 // Append the changelist to the existing list

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java Sun Nov 17 10:02:39 2013
@@ -112,7 +112,7 @@ public class SVNRemoteTests extends SVNT
                 super.conf.getAbsolutePath(),
                 USERNAME, PASSWORD,
                 new DefaultPromptUserPassword(),
-                null, null)
+                null, null, null)
                 .openRemoteSession(getTestRepoUrl());
         }
         catch (ClientException ex)
@@ -140,7 +140,7 @@ public class SVNRemoteTests extends SVNT
                     super.conf.getAbsolutePath(),
                     USERNAME, PASSWORD,
                     new DefaultPromptUserPassword(),
-                    null, null)
+                    null, null, null)
                     .openRemoteSession(prefix + "repositorydoesnotexisthere");
             }
             finally
@@ -843,15 +843,24 @@ public class SVNRemoteTests extends SVNT
                         cat.enumerate(sec, en);
                     }
                 }
+
             };
 
-        try {
-            SVNUtil.setConfigEventHandler(handler);
-            ISVNRemote session = getSession();
-            session.getLatestRevision();
-        } finally {
-            SVNUtil.setConfigEventHandler(null);
+        ISVNRemote session;
+        try
+        {
+            session = new RemoteFactory(
+                super.conf.getAbsolutePath(),
+                USERNAME, PASSWORD,
+                new DefaultPromptUserPassword(),
+                null, handler, null)
+                .openRemoteSession(getTestRepoUrl());
+        }
+        catch (ClientException ex)
+        {
+            throw new RuntimeException(ex);
         }
+        session.getLatestRevision();
     }
 
     private static class RemoteStatusReceiver implements RemoteStatus

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java Sun Nov 17 10:02:39 2013
@@ -23,13 +23,19 @@
 
 package org.apache.subversion.javahl;
 
+import org.apache.subversion.javahl.types.ExternalItem;
 import org.apache.subversion.javahl.types.NodeKind;
+import org.apache.subversion.javahl.types.Revision;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Tests the JavaHL SVNUtil APIs.
@@ -188,4 +194,219 @@ public class UtilTests extends SVNTests
         }
         assertTrue(caught_exception);
     }
+
+
+    private static List<ExternalItem> externals = null;
+    static {
+        try {
+            externals = new ArrayList<ExternalItem>(25);
+            externals.add(new ExternalItem("a", "http://server/repo/path",
+                                           null, null));
+            externals.add(new ExternalItem("b", "//server/repo/path",
+                                           null, null));
+            externals.add(new ExternalItem("c", "/repo/path",
+                                           null, null));
+            externals.add(new ExternalItem("d", "^/path",
+                                           null, null));
+            externals.add(new ExternalItem("e", "^/../oper/path",
+                                           null, null));
+
+            externals.add(new ExternalItem("f", "http://server/repo/path",
+                                           Revision.getInstance(42), null));
+            externals.add(new ExternalItem("g", "//server/repo/path",
+                                           Revision.getInstance(42), null));
+            externals.add(new ExternalItem("h", "/repo/path",
+                                           Revision.getInstance(42), null));
+            externals.add(new ExternalItem("j", "^/path",
+                                           Revision.getInstance(42), null));
+            externals.add(new ExternalItem("j", "^/../oper/path",
+                                           Revision.getInstance(42), null));
+
+            externals.add(new ExternalItem("k", "http://server/repo/path",
+                                           null, Revision.getInstance(42)));
+            externals.add(new ExternalItem("l", "//server/repo/path",
+                                           null, Revision.getInstance(42)));
+            externals.add(new ExternalItem("m", "/repo/path",
+                                           null, Revision.getInstance(42)));
+            externals.add(new ExternalItem("n", "^/path",
+                                           null, Revision.getInstance(42)));
+            externals.add(new ExternalItem("o", "^/../oper/path",
+                                           null, Revision.getInstance(42)));
+
+            externals.add(new ExternalItem("p", "http://server/repo/path",
+                                           Revision.getInstance(69),
+                                           Revision.getInstance(71)));
+            externals.add(new ExternalItem("q", "//server/repo/path",
+                                           Revision.getInstance(69),
+                                           Revision.getInstance(71)));
+            externals.add(new ExternalItem("r", "/repo/path",
+                                           Revision.getInstance(69),
+                                           Revision.getInstance(71)));
+            externals.add(new ExternalItem("s", "^/path",
+                                           Revision.getInstance(69),
+                                           Revision.getInstance(71)));
+            externals.add(new ExternalItem("t", "^/../oper/path",
+                                           Revision.getInstance(69),
+                                           Revision.getInstance(71)));
+
+            externals.add(new ExternalItem("u", "http://server/repo/path",
+                                           Revision.getInstance(42),
+                                           Revision.getInstance(42)));
+            externals.add(new ExternalItem("v", "//server/repo/path",
+                                           Revision.getInstance(42),
+                                           Revision.getInstance(42)));
+            externals.add(new ExternalItem("w", "/repo/path",
+                                           Revision.getInstance(42),
+                                           Revision.getInstance(42)));
+            externals.add(new ExternalItem("x", "^/path",
+                                           Revision.getInstance(42),
+                                           Revision.getInstance(42)));
+            externals.add(new ExternalItem("y", "^/../oper/path",
+                                           Revision.getInstance(42),
+                                           Revision.getInstance(42)));
+        } catch (SubversionException ex) {
+            externals = null;
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private static final byte[] externals_propval =
+        ("http://server/repo/path a\n" +
+         "//server/repo/path b\n" +
+         "/repo/path c\n" +
+         "^/path d\n" +
+         "^/../oper/path e\n" +
+         "-r42 http://server/repo/path f\n" +
+         "-r42 //server/repo/path g\n" +
+         "-r42 /repo/path h\n" +
+         "-r42 ^/path j\n" +
+         "-r42 ^/../oper/path j\n" +
+         "http://server/repo/path@42 k\n" +
+         "//server/repo/path@42 l\n" +
+         "/repo/path@42 m\n" +
+         "^/path@42 n\n" +
+         "^/../oper/path@42 o\n" +
+         "-r69 http://server/repo/path@71 p\n" +
+         "-r69 //server/repo/path@71 q\n" +
+         "-r69 /repo/path@71 r\n" +
+         "-r69 ^/path@71 s\n" +
+         "-r69 ^/../oper/path@71 t\n" +
+         "http://server/repo/path@42 u\n" +
+         "//server/repo/path@42 v\n" +
+         "/repo/path@42 w\n" +
+         "^/path@42 x\n" +
+         "^/../oper/path@42 y\n").getBytes();
+
+    private static List<ExternalItem> old_externals = null;
+    static {
+        try {
+            old_externals = new ArrayList<ExternalItem>(3);
+            old_externals.add(new ExternalItem("X", "http://server/repo/path",
+                                               null, null));
+            old_externals.add(new ExternalItem("Y", "http://server/repo/path",
+                                               null, Revision.getInstance(42)));
+
+            old_externals.add(new ExternalItem("Z", "http://server/repo/path",
+                                               null, Revision.getInstance(new Date(0L))));
+        } catch (SubversionException ex) {
+            old_externals = null;
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private static final byte[] old_externals_propval =
+        ("X http://server/repo/path\n" +
+         "Y -r42 http://server/repo/path\n" +
+         "Z -r{1970-01-01T00:00:00.000000Z} http://server/repo/path\n").getBytes();
+
+    private static void compare_item_lists(List<ExternalItem> a,
+                                           List<ExternalItem> b,
+                                           String list_name)
+    {
+        final int length = a.size();
+        assertEquals(length, b.size());
+        for (int i = 0; i < length; ++i)
+            assertTrue("Items in " + list_name + " at index " + i + " differ",
+                       a.get(i).equals(b.get(i)));
+    }
+
+    public void testParseExternals() throws Throwable
+    {
+        List<ExternalItem> items;
+
+        items = SVNUtil.parseExternals(externals_propval, "dirname", false);
+        compare_item_lists(items, externals, "externals");
+
+        items = SVNUtil.parseExternals(old_externals_propval, "dirname", false);
+        compare_item_lists(items, old_externals, "old_externals");
+    }
+
+    public void testUnparseExternals() throws Throwable
+    {
+        byte[] props = SVNUtil.unparseExternals(externals, "dirname");
+        assertTrue(Arrays.equals(externals_propval, props));
+    }
+
+    public void testUnparseExternalsOldstyle() throws Throwable
+    {
+        byte[] props;
+
+        props = SVNUtil.unparseExternalsForAncientUnsupportedClients(
+                     old_externals, "dirname");
+        assertTrue(Arrays.equals(old_externals_propval, props));
+
+        // The fancy new features are not supported in the old format
+        boolean caught_exception = false;
+        try {
+            props = SVNUtil.unparseExternalsForAncientUnsupportedClients(
+                         externals, "dirname");
+        } catch (SubversionException ex) {
+            caught_exception = true;
+        }
+        assertTrue(caught_exception);
+    }
+
+    public void testResolveExternalsUrl() throws Throwable
+    {
+        assertEquals("http://a/b/c",
+                     SVNUtil.resolveExternalsUrl(
+                         new ExternalItem("x", "http://a/b/c/", null, null),
+                         "http://a", "http://a/b"));
+
+        assertEquals("http://a/b/c",
+                     SVNUtil.resolveExternalsUrl(
+                         new ExternalItem("x", "^/b/c", null, null),
+                         "http://a", "http://a/b"));
+
+        assertEquals("http://a/b/c",
+                     SVNUtil.resolveExternalsUrl(
+                         new ExternalItem("x", "../b/c", null, null),
+                         "http://a", "http://a/b"));
+
+        assertEquals("http://a/b/c",
+                     SVNUtil.resolveExternalsUrl(
+                         new ExternalItem("x", "/b/c", null, null),
+                         "http://a", "http://a/b"));
+
+        assertEquals("http://a/b/c",
+                     SVNUtil.resolveExternalsUrl(
+                         new ExternalItem("x", "//a/b/c", null, null),
+                         "http://a", "http://a/b"));
+    }
+
+    public void testBuildKeywords() throws Throwable
+    {
+        final byte[] kwval = "TEST=%H%_%b%_%u".getBytes();
+
+        Map<String, byte[]> result;
+
+        result = SVNUtil.buildKeywords(kwval, Revision.SVN_INVALID_REVNUM,
+                                       null, null, null, null);
+        assertEquals("     ", new String(result.get("TEST")));
+
+        result = SVNUtil.buildKeywords(kwval, 48, "http://a/b/c",
+                                       "http://a", new Date(1), "X");
+        assertEquals("b/c 48 1970-01-01 00:00:00Z X c http://a/b/c",
+                     new String(result.get("TEST")));
+    }
 }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_diff_tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_diff_tree.h?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_diff_tree.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_diff_tree.h Sun Nov 17 10:02:39 2013
@@ -20,13 +20,13 @@
  * ====================================================================
  * @endcopyright
  *
- * @file svn_wc.h
+ * @file svn_diff_tree.h
  * @brief Generic diff handler. Replacing the old svn_wc_diff_callbacks4_t
  * infrastructure
  */
 
-#ifndef SVN_DIFF_PROCESSOR_H
-#define SVN_DIFF_PROCESSOR_H
+#ifndef SVN_DIFF_TREE_H
+#define SVN_DIFF_TREE_H
 
 #include "svn_types.h"
 
@@ -353,5 +353,5 @@ svn_diff__source_create(svn_revnum_t rev
 }
 #endif /* __cplusplus */
 
-#endif  /* SVN_DIFF_PROCESSOR_H */
+#endif  /* SVN_DIFF_TREE_H */
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_repos_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_repos_private.h?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_repos_private.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_repos_private.h Sun Nov 17 10:02:39 2013
@@ -34,6 +34,8 @@
 #include "svn_editor.h"
 #include "svn_config.h"
 
+#include "private/svn_string_private.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -160,19 +162,22 @@ svn_repos__retrieve_config(svn_config_t 
  */
 typedef struct svn_repos__config_pool_t svn_repos__config_pool_t;
 
-/* Create a new configuration pool object with a minim lifetime determined
+/* Create a new configuration pool object with a minimum lifetime determined
  * by POOL and return it in *CONFIG_POOL.  References to any configuration
  * in the *CONFIG_POOL will keep the latter alive beyond POOL cleanup.
+ * The THREAD_SAFE flag indicates whether the pool actually needs to be
+ * thread-safe.
  */
 svn_error_t *
 svn_repos__config_pool_create(svn_repos__config_pool_t **config_pool,
+                              svn_boolean_t thread_safe,
                               apr_pool_t *pool);
 
 /* Set *CFG to a read-only reference to the current contents of the
  * configuration specified by PATH.  If the latter is a URL, we read the
- * data from a local repository.  REGISTRY: urls are not supported.
- * CONFIG_POOL will store the configuration and make further callers use
- * the same instance if the content matches.
+ * data from a local repository.  CONFIG_POOL will store the configuration
+ * and make further callers use the same instance if the content matches.
+ * If KEY is not NULL, *KEY will be set to a unique ID - if available.
  *
  * If MUST_EXIST is TRUE, a missing config file is also an error, *CFG
  * is otherwise simply NULL.  The CASE_SENSITIVE controls the lookup
@@ -184,11 +189,10 @@ svn_repos__config_pool_create(svn_repos_
  * return the latest content.
  *
  * POOL determines the minimum lifetime of *CFG.
- *
- * Note: The read-only behavior is not enforced, yet. 
  */
 svn_error_t *
 svn_repos__config_pool_get(svn_config_t **cfg,
+                           svn_membuf_t **key,
                            svn_repos__config_pool_t *config_pool,
                            const char *path,
                            svn_boolean_t must_exist,
@@ -198,7 +202,103 @@ svn_repos__config_pool_get(svn_config_t 
 
 /** @} */
 
+/**
+ * @defgroup svn_authz_pool Authz object pool API
+ * @{
+ */
+
+/* Opaque thread-safe factory and container for authorization objects.
+ *
+ * Instances handed out are read-only and may be given to multiple callers
+ * from multiple threads.  Authorization objects no longer referenced by
+ * any user may linger for a while before being cleaned up.
+ */
+typedef struct svn_repos__authz_pool_t svn_repos__authz_pool_t;
+
+/* Create a new authorization pool object with a minimum lifetime determined
+ * by POOL and return it in *AUTHZ_POOL.  CONFIG_POOL will be the common
+ * source for the configuration data underlying the authz objects.
+ * The THREAD_SAFE flag indicates whether the pool actually needs to be
+ * thread-safe.
+ * 
+ * References to any authorization object in the *AUTHZ_POOL will keep the
+ * latter alive beyond POOL cleanup.
+ */
+svn_error_t *
+svn_repos__authz_pool_create(svn_repos__authz_pool_t **authz_pool,
+                             svn_repos__config_pool_t *config_pool,
+                             svn_boolean_t thread_safe,
+                             apr_pool_t *pool);
+
+/* Set *AUTHZ_P to a read-only reference to the current contents of the
+ * authorization specified by PATH and GROUPS_PATH.  If these are URLs,
+ * we read the data from a local repository (see #svn_repos_authz_read2).
+ * AUTHZ_POOL will store the authz data and make further callers use the
+ * same instance if the content matches.
+ *
+ * If MUST_EXIST is TRUE, a missing config file is also an error, *AUTHZ_P
+ * is otherwise simply NULL.
+ *
+ * PREFERRED_REPOS is only used if it is not NULL and PATH is a URL.
+ * If it matches the URL, access the repository through this object
+ * instead of creating a new repo instance.  Note that this might not
+ * return the latest content.
+ *
+ * POOL determines the minimum lifetime of *AUTHZ_P.
+ */
+svn_error_t *
+svn_repos__authz_pool_get(svn_authz_t **authz_p,
+                          svn_repos__authz_pool_t *authz_pool,
+                          const char *path,
+                          const char *groups_path,
+                          svn_boolean_t must_exist,
+                          svn_repos_t *preferred_repos,
+                          apr_pool_t *pool);
+
+/** @} */
+
+/**
+ * @defgroup svn_repos_pool svn_repos_t object pool API
+ * @{
+ */
 
+/* Opaque thread-safe factory and container for svn_repos_t objects.
+ */
+typedef struct svn_repos__repos_pool_t svn_repos__repos_pool_t;
+
+/* Create a new repository pool object with a minimum lifetime determined
+ * by POOL and return it in *REPOS_POOL.  All repositories share the same
+ * FS_CONFIG configuration which may be NULL.  The THREAD_SAFE flag
+ * indicates whether the pool actually needs to be thread-safe.
+ *
+ * References to any repository instances in *REPOS_POOL will keep the
+ * latter alive beyond POOL cleanup.
+ */
+svn_error_t *
+svn_repos__repos_pool_create(svn_repos__repos_pool_t **repos_pool,
+                             apr_hash_t *fs_config,
+                             svn_boolean_t thread_safe,
+                             apr_pool_t *pool);
+
+/* Set *REPOS_P to an open repository object for the repository at local
+ * path REPOS_ROOT.  If UUID is given, the repository's UUID must match it;
+ * otherwise we re-read from disk.
+ *
+ * Once POOL gets cleared or destroyed, REPOS_POOL will store the repository
+ * instance and make further callers may return that same instance.  POOL
+ * determines the minimum lifetime of *REPOS_P.
+ *
+ * Note that you may need to update the youngest revision info cached
+ * inside *REPOS_P. 
+ */
+svn_error_t *
+svn_repos__repos_pool_get(svn_repos_t **repos_p,
+                          svn_repos__repos_pool_t *repos_pool,
+                          const char *repos_root,
+                          const char *uuid,
+                          apr_pool_t *pool);
+
+/** @} */
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_subr_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_subr_private.h?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_subr_private.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/include/private/svn_subr_private.h Sun Nov 17 10:02:39 2013
@@ -495,6 +495,18 @@ svn_config_t *
 svn_config__shallow_copy(svn_config_t *src,
                          apr_pool_t *pool);
 
+/* Add / replace SECTION in TARGET with the same section from SOURCE by
+ * simply adding a reference to it.  If TARGET is read-only, the sections
+ * list in target gets duplicated before the modification.
+ *
+ * This is an API tailored for use by the svn_repos__authz_pool_t API to
+ * prevent breach of encapsulation.
+ */
+void
+svn_config__shallow_replace_section(svn_config_t *target,
+                                    svn_config_t *source,
+                                    const char *section);
+
 /** @} */
 
 #ifdef __cplusplus

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_config.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_config.h?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_config.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/include/svn_config.h Sun Nov 17 10:02:39 2013
@@ -98,6 +98,12 @@ typedef struct svn_config_t svn_config_t
 /** @since New in 1.9. */
 #define SVN_CONFIG_OPTION_HTTP_CHUNKED_REQUESTS     "http-chunked-requests"
 
+/** @since New in 1.9. */
+#define SVN_CONFIG_OPTION_SERF_LOG_COMPONENTS       "serf-log-components"
+/** @since New in 1.9. */
+#define SVN_CONFIG_OPTION_SERF_LOG_LEVEL            "serf-log-level"
+
+
 #define SVN_CONFIG_CATEGORY_CONFIG          "config"
 #define SVN_CONFIG_SECTION_AUTH                 "auth"
 #define SVN_CONFIG_OPTION_PASSWORD_STORES           "password-stores"

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/merge.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_client/merge.c Sun Nov 17 10:02:39 2013
@@ -9425,7 +9425,7 @@ do_mergeinfo_aware_dir_merge(svn_mergein
     {
       if (!merge_b->record_only)
         {
-          /* Reset cur_ancestor_abspath to null so that subsequent cherry
+          /* Reset the last notification path so that subsequent cherry
              picked revision ranges will be notified upon subsequent
              operative merge. */
           merge_b->notify_begin.last_abspath = NULL;

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/hotcopy.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/hotcopy.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/hotcopy.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/hotcopy.c Sun Nov 17 10:02:39 2013
@@ -1,4 +1,4 @@
-/* hotcopys.c --- FS hotcopy functionality for FSFS
+/* hotcopy.c --- FS hotcopy functionality for FSFS
  *
  * ====================================================================
  *    Licensed to the Apache Software Foundation (ASF) under one
@@ -733,16 +733,18 @@ hotcopy_body(void *baton, apr_pool_t *po
           SVN_ERR(hotcopy_remove_rev_files(dst_fs, rev,
                                            rev + max_files_per_dir,
                                            max_files_per_dir, iterpool));
-          SVN_ERR(hotcopy_remove_revprop_files(dst_fs, rev,
-                                               rev + max_files_per_dir,
-                                               max_files_per_dir, iterpool));
+          if (dst_ffd->format >= SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT)
+            SVN_ERR(hotcopy_remove_revprop_files(dst_fs, rev,
+                                                 rev + max_files_per_dir,
+                                                 max_files_per_dir,
+                                                 iterpool));
         }
 
       /* Now that all revisions have moved into the pack, the original
        * rev dir can be removed. */
       SVN_ERR(remove_folder(svn_fs_fs__path_rev_shard(dst_fs, rev, iterpool),
                             cancel_func, cancel_baton, iterpool));
-      if (rev > 0)
+      if (rev > 0 && dst_ffd->format >= SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT)
         SVN_ERR(remove_folder(svn_fs_fs__path_revprops_shard(dst_fs, rev,
                                                              iterpool),
                               cancel_func, cancel_baton, iterpool));

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/transaction.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/transaction.c Sun Nov 17 10:02:39 2013
@@ -628,8 +628,7 @@ replace_change(svn_fs_path_change2_t *ol
 
 /* Merge the internal-use-only CHANGE into a hash of public-FS
    svn_fs_path_change2_t CHANGES, collapsing multiple changes into a
-   single summarical (is that real word?) change per path.  Also keep
-   the COPYFROM_CACHE up to date with new adds and replaces.  */
+   single summarical (is that real word?) change per path.  */
 static svn_error_t *
 fold_change(apr_hash_t *changes,
             const change_t *change)

Propchange: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
  Merged /subversion/trunk/subversion/libsvn_fs_x:r1538049-1542682

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_x/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_x/transaction.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_x/transaction.c Sun Nov 17 10:02:39 2013
@@ -675,8 +675,7 @@ replace_change(svn_fs_path_change2_t *ol
 
 /* Merge the internal-use-only CHANGE into a hash of public-FS
    svn_fs_path_change2_t CHANGES, collapsing multiple changes into a
-   single summarical (is that real word?) change per path.  Also keep
-   the COPYFROM_CACHE up to date with new adds and replaces.  */
+   single summarical (is that real word?) change per path.  */
 static svn_error_t *
 fold_change(apr_hash_t *changes,
             const change_t *change)

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_ra_serf/serf.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_ra_serf/serf.c Sun Nov 17 10:02:39 2013
@@ -157,6 +157,10 @@ load_config(svn_ra_serf__session_t *sess
   const char *exceptions;
   apr_port_t proxy_port;
   svn_tristate_t chunked_requests;
+#if SERF_VERSION_AT_LEAST(1, 4, 0) && !defined(SVN_SERF_NO_LOGGING)
+  apr_int64_t log_components;
+  apr_int64_t log_level;
+#endif
 
   if (config_hash)
     {
@@ -239,6 +243,17 @@ load_config(svn_ra_serf__session_t *sess
                                   SVN_CONFIG_OPTION_HTTP_CHUNKED_REQUESTS,
                                   "auto", svn_tristate_unknown));
 
+#if SERF_VERSION_AT_LEAST(1, 4, 0) && !defined(SVN_SERF_NO_LOGGING)
+  SVN_ERR(svn_config_get_int64(config, &log_components,
+                               SVN_CONFIG_SECTION_GLOBAL,
+                               SVN_CONFIG_OPTION_SERF_LOG_COMPONENTS,
+                               SERF_LOGCOMP_NONE));
+  SVN_ERR(svn_config_get_int64(config, &log_level,
+                               SVN_CONFIG_SECTION_GLOBAL,
+                               SVN_CONFIG_OPTION_SERF_LOG_LEVEL,
+                               SERF_LOG_INFO));
+#endif
+
   if (config)
     server_group = svn_config_find_group(config,
                                          session->session_url.hostname,
@@ -301,7 +316,37 @@ load_config(svn_ra_serf__session_t *sess
                                       server_group,
                                       SVN_CONFIG_OPTION_HTTP_CHUNKED_REQUESTS,
                                       "auto", chunked_requests));
+
+#if SERF_VERSION_AT_LEAST(1, 4, 0) && !defined(SVN_SERF_NO_LOGGING)
+      SVN_ERR(svn_config_get_int64(config, &log_components,
+                                   server_group,
+                                   SVN_CONFIG_OPTION_SERF_LOG_COMPONENTS,
+                                   log_components));
+       SVN_ERR(svn_config_get_int64(config, &log_level,
+                                    server_group,
+                                    SVN_CONFIG_OPTION_SERF_LOG_LEVEL,
+                                    log_level));
+#endif
+    }
+
+#if SERF_VERSION_AT_LEAST(1, 4, 0) && !defined(SVN_SERF_NO_LOGGING)
+  if (log_components != SERF_LOGCOMP_NONE)
+    {
+      serf_log_output_t *output;
+      apr_status_t status;
+
+      status = serf_logging_create_stream_output(&output,
+                                                 session->context,
+                                                 (apr_uint32_t)log_level,
+                                                 (apr_uint32_t)log_components,
+                                                 SERF_LOG_DEFAULT_LAYOUT,
+                                                 stderr,
+                                                 pool);
+
+      if (!status)
+          serf_logging_add_output(session->context, output);
     }
+#endif
 
   /* Don't allow the http-max-connections value to be larger than our
      compiled-in limit, or to be too small to operate.  Broken

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_ra_svn/marshal.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_ra_svn/marshal.c Sun Nov 17 10:02:39 2013
@@ -119,16 +119,6 @@ svn_ra_svn_conn_t *svn_ra_svn_create_con
             && apr_sockaddr_ip_get(&conn->remote_ip, sa) == APR_SUCCESS))
         conn->remote_ip = NULL;
       svn_ra_svn__stream_timeout(conn->stream, get_timeout(conn));
-
-      /* We are using large r/w buffers already.
-       * So, once we decide to actually send data, we want it to go over
-       * the wire a.s.a.p..  So disable Nagle's algorithm.
-       *
-       * We ignore the result of this call since it safe to continue even
-       * if we keep delaying.  The only negative effect is increased
-       * latency (can be additional 5 .. 10ms depending on circumstances).
-       */
-      apr_socket_opt_set(sock, APR_TCP_NODELAY, 1);
     }
   else
     {

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/authz.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/authz.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/authz.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_repos/authz.c Sun Nov 17 10:02:39 2013
@@ -78,8 +78,8 @@ struct authz_validate_baton {
                            enumerator, if any. */
 };
 
-/* Currently this structure is just a wrapper around a
-   svn_config_t. */
+/* Currently this structure is just a wrapper around a svn_config_t.
+   Please update authz_pool if you modify this structure. */
 struct svn_authz_t
 {
   svn_config_t *cfg;
@@ -750,9 +750,8 @@ static svn_boolean_t authz_validate_sect
 }
 
 
-/* Walk the configuration in AUTHZ looking for any errors. */
-static svn_error_t *
-authz_validate(svn_authz_t *authz, apr_pool_t *pool)
+svn_error_t *
+svn_repos__authz_validate(svn_authz_t *authz, apr_pool_t *pool)
 {
   struct authz_validate_baton baton = { 0 };
 
@@ -971,7 +970,7 @@ svn_repos__authz_read(svn_authz_t **auth
     }
 
   /* Make sure there are no errors in the configuration. */
-  SVN_ERR(authz_validate(authz, pool));
+  SVN_ERR(svn_repos__authz_validate(authz, pool));
 
   *authz_p = authz;
   return SVN_NO_ERROR;
@@ -1011,7 +1010,7 @@ svn_repos_authz_parse(svn_authz_t **auth
     }
 
   /* Make sure there are no errors in the configuration. */
-  SVN_ERR(authz_validate(authz, pool));
+  SVN_ERR(svn_repos__authz_validate(authz, pool));
 
   *authz_p = authz;
   return SVN_NO_ERROR;