You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/11/27 09:19:51 UTC

svn commit: r1545958 [4/15] - in /subversion/branches/log-addressing: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/server-side/ contrib/server-side/svncutter/ notes/ subversion/bindings/javahl/native/ subv...

Modified: subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java (original)
+++ subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java Wed Nov 27 08:19:45 2013
@@ -38,6 +38,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.nio.charset.Charset;
 import java.security.MessageDigest;
@@ -112,7 +113,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 +141,7 @@ public class SVNRemoteTests extends SVNT
                     super.conf.getAbsolutePath(),
                     USERNAME, PASSWORD,
                     new DefaultPromptUserPassword(),
-                    null, null)
+                    null, null, null)
                     .openRemoteSession(prefix + "repositorydoesnotexisthere");
             }
             finally
@@ -162,9 +163,13 @@ public class SVNRemoteTests extends SVNT
         }
         catch (ClientException ex)
         {
-            svnErrorCode = ex.getAllMessages().get(0).getCode();
+            List<ClientException.ErrorMessage> msgs = ex.getAllMessages();
+            svnErrorCode = msgs.get(msgs.size() - 1).getCode();
         }
-        assertEquals(180001, svnErrorCode);
+
+        assertTrue(svnErrorCode == 180001    // file:
+                   || svnErrorCode == 210005 // svn:
+                   || svnErrorCode == 2);    // http:
     }
 
     public void testDatedRev() throws Exception
@@ -447,10 +452,13 @@ public class SVNRemoteTests extends SVNT
         }
     }
 
-    private final class CommitContext implements CommitCallback
+    private static final class CommitContext implements CommitCallback
     {
         public final ISVNEditor editor;
-        public CommitContext(ISVNRemote session, String logstr)
+        public CommitContext(ISVNRemote session, String logstr,
+                             ISVNEditor.ProvideBaseCallback getBase,
+                             ISVNEditor.ProvidePropsCallback getProps,
+                             ISVNEditor.GetNodeKindCallback getKind)
             throws ClientException
         {
             Charset UTF8 = Charset.forName("UTF-8");
@@ -459,7 +467,19 @@ public class SVNRemoteTests extends SVNT
                           : logstr.getBytes(UTF8));
             HashMap<String, byte[]> revprops = new HashMap<String, byte[]>();
             revprops.put("svn:log", log);
-            editor = session.getCommitEditor(revprops, this, null, false);
+
+            // Run the getCommitEditor overloads through their paces, too.
+            if (getBase == null && getProps == null && getKind == null)
+                editor = session.getCommitEditor(revprops, this, null, false);
+            else
+                editor = session.getCommitEditor(revprops, this, null, false,
+                                                 getBase, getProps, getKind);
+        }
+
+        public CommitContext(ISVNRemote session, String logstr)
+            throws ClientException
+        {
+            this(session, logstr, null, null, null);
         }
 
         public void commitInfo(CommitInfo info) { this.info = info; }
@@ -468,11 +488,67 @@ public class SVNRemoteTests extends SVNT
         private CommitInfo info;
     }
 
-    public void testEditorCopy() throws Exception
+    private static final class EditorCallbacks
+    {
+        private final String wcpath;
+        private final long revision;
+        private final Map<String, byte[]> props;
+        private final NodeKind kind;
+
+        public EditorCallbacks(String wcpath, long revision,
+                               Map<String, byte[]> props,
+                               NodeKind kind)
+        {
+            this.wcpath = wcpath;
+            this.revision = revision;
+            this.props = props;
+            this.kind = kind;
+        }
+
+        public final ISVNEditor.ProvideBaseCallback getBase =
+            new ISVNEditor.ProvideBaseCallback()
+            {
+                public ISVNEditor.ProvideBaseCallback.ReturnValue
+                getContents(String relpath)
+                {
+                    try {
+                        return new ISVNEditor.ProvideBaseCallback.ReturnValue(
+                            new FileInputStream(wcpath + relpath), revision);
+                    } catch (java.io.FileNotFoundException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+            };
+
+        public final ISVNEditor.ProvidePropsCallback getProps =
+            new ISVNEditor.ProvidePropsCallback()
+            {
+                public ISVNEditor.ProvidePropsCallback.ReturnValue
+                getProperties(String relpath)
+                {
+                    return new ISVNEditor.ProvidePropsCallback.ReturnValue(
+                        props, revision);
+                }
+            };
+
+        public final ISVNEditor.GetNodeKindCallback getKind =
+            new ISVNEditor.GetNodeKindCallback()
+            {
+                public NodeKind getKind(String relpath, long revision)
+                {
+                    return kind;
+                }
+            };
+    };
+
+    private void testEditorCopy(EditorCallbacks cb) throws Exception
     {
         ISVNRemote session = getSession();
         CommitContext cc =
-            new CommitContext(session, "Copy A/B/lambda -> A/B/omega");
+            (cb != null
+             ? new CommitContext(session, "Copy A/B/lambda -> A/B/omega",
+                                 cb.getBase, cb.getProps, cb.getKind)
+             : new CommitContext(session, "Copy A/B/lambda -> A/B/omega"));
 
         try {
             // FIXME: alter dir A/B first
@@ -493,6 +569,18 @@ public class SVNRemoteTests extends SVNT
                                        Revision.SVN_INVALID_REVNUM));
     }
 
+    public void testEditorCopy() throws Exception
+    {
+        testEditorCopy(null);
+    }
+
+    public void testEditorCopy_WithCallbacks() throws Exception
+    {
+        testEditorCopy(new EditorCallbacks(thisTest.getWCPath(), 1L,
+                                           new HashMap<String, byte[]>(),
+                                           NodeKind.file));
+    }
+
     public void testEditorMove() throws Exception
     {
         ISVNRemote session = getSession();
@@ -576,7 +664,7 @@ public class SVNRemoteTests extends SVNT
                                        Revision.SVN_INVALID_REVNUM));
     }
 
-    public void testEditorSetDirProps() throws Exception
+    private void testEditorSetDirProps(EditorCallbacks cb) throws Exception
     {
         Charset UTF8 = Charset.forName("UTF-8");
         ISVNRemote session = getSession();
@@ -585,7 +673,11 @@ public class SVNRemoteTests extends SVNT
         HashMap<String, byte[]> props = new HashMap<String, byte[]>();
         props.put("svn:ignore", ignoreval);
 
-        CommitContext cc = new CommitContext(session, "Add svn:ignore");
+        CommitContext cc =
+            (cb != null
+             ? new CommitContext(session, "Add svn:ignore",
+                                 cb.getBase, cb.getProps, cb.getKind)
+             : new CommitContext(session, "Add svn:ignore"));
         try {
             cc.editor.alterDirectory("", 1, null, props);
             cc.editor.complete();
@@ -602,6 +694,18 @@ public class SVNRemoteTests extends SVNT
                                                     Revision.HEAD)));
     }
 
+    public void testEditorSetDirProps() throws Exception
+    {
+        testEditorSetDirProps(null);
+    }
+
+    public void testEditorSetDirProps_WithCallbacks() throws Exception
+    {
+        testEditorSetDirProps(new EditorCallbacks(thisTest.getWCPath(), 1L,
+                                                  new HashMap<String, byte[]>(),
+                                                  NodeKind.dir));
+    }
+
     private static byte[] SHA1(byte[] text) throws NoSuchAlgorithmException
     {
         MessageDigest md = MessageDigest.getInstance("SHA-1");
@@ -644,7 +748,54 @@ public class SVNRemoteTests extends SVNT
         assertTrue(Arrays.equals(eolstyle, propval));
     }
 
-    public void testEditorSetFileContents() throws Exception
+    public void testEditorDeleteFileProps() throws Exception
+    {
+        Charset UTF8 = Charset.forName("UTF-8");
+        client.propertySetRemote(
+             thisTest.getUrl() + "/iota", 1L,
+             "name", "value".getBytes(UTF8),
+             new CommitMessageCallback() {
+                 public String getLogMessage(Set<CommitItem> elements) {
+                     return "Set property 'name' to 'value'";
+                 }
+             }, false, null, null);
+
+        ISVNRemote session = getSession();
+        HashMap<String, byte[]> props = new HashMap<String, byte[]>();
+        assertEquals(2L, session.getFile(Revision.SVN_INVALID_REVNUM, "iota",
+                                         null, props));
+
+        int propcount = 0;
+        for (Map.Entry<String, byte[]> e : props.entrySet()) {
+            final String key = e.getKey();
+            if (key.startsWith("svn:entry:") || key.startsWith("svn:wc:"))
+                continue;
+            ++propcount;
+        }
+        assertEquals(1, propcount);
+
+        CommitContext cc = new CommitContext(session, "Remove all props");
+        try {
+            props.clear();
+            cc.editor.alterFile("iota", 2L, null, null, props);
+            cc.editor.complete();
+        } finally {
+            cc.editor.dispose();
+        }
+
+        assertEquals(3L, session.getFile(Revision.SVN_INVALID_REVNUM, "iota",
+                                         null, props));
+        propcount = 0;
+        for (Map.Entry<String, byte[]> e : props.entrySet()) {
+            final String key = e.getKey();
+            if (key.startsWith("svn:entry:") || key.startsWith("svn:wc:"))
+                continue;
+            ++propcount;
+        }
+        assertEquals(0, propcount);
+    }
+
+    private void testEditorSetFileContents(EditorCallbacks cb) throws Exception
     {
         Charset UTF8 = Charset.forName("UTF-8");
         ISVNRemote session = getSession();
@@ -654,7 +805,10 @@ public class SVNRemoteTests extends SVNT
         ByteArrayInputStream stream = new ByteArrayInputStream(contents);
 
         CommitContext cc =
-            new CommitContext(session, "Change contents of A/B/E/alpha");
+            (cb != null
+             ? new CommitContext(session, "Change contents of A/B/E/alpha",
+                                 cb.getBase, cb.getProps, cb.getKind)
+             : new CommitContext(session, "Change contents of A/B/E/alpha"));
         try {
             cc.editor.alterFile("A/B/E/alpha", 1, hash, stream, null);
             cc.editor.complete();
@@ -670,6 +824,18 @@ public class SVNRemoteTests extends SVNT
         assertTrue(Arrays.equals(contents, checkcontents.toByteArray()));
     }
 
+    public void testEditorSetFileContents() throws Exception
+    {
+        testEditorSetFileContents(null);
+    }
+
+    public void testEditorSetFileContents_WithCallbacks() throws Exception
+    {
+        testEditorSetFileContents(new EditorCallbacks(thisTest.getWCPath(), 1L,
+                                                      new HashMap<String, byte[]>(),
+                                                      NodeKind.file));
+    }
+
     // Sanity check so that we don't forget about unimplemented methods.
     public void testEditorNotImplemented() throws Exception
     {
@@ -796,15 +962,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/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java (original)
+++ subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java Wed Nov 27 08:19:45 2013
@@ -927,7 +927,7 @@ class SVNTests extends TestCase
 
         public Status[] getStatusArray()
         {
-            return (Status[]) statuses.toArray(new Status[statuses.size()]);
+            return statuses.toArray(new Status[statuses.size()]);
         }
     }
 }

Modified: subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java (original)
+++ subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java Wed Nov 27 08:19:45 2013
@@ -23,10 +23,23 @@
 
 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.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
 
 /**
  * Tests the JavaHL SVNUtil APIs.
@@ -135,4 +148,443 @@ public class UtilTests extends SVNTests
                                  "\nN-3\nN-2\nN-1\nN\n").getBytes();
         assertTrue(Arrays.equals(expected, result.toByteArray()));
     }
+
+    public void testValidateProp() throws Throwable
+    {
+        File temp = File.createTempFile("propcheck", ".file", localTmp);
+        FileOutputStream out = new FileOutputStream(temp);
+        out.write("normal text\n".getBytes());
+        out.close();
+
+        byte[] prop = SVNUtil.canonicalizeNodeProperty(
+                           "svn:eol-style", "  native".getBytes(),
+                           "propcheck.file", NodeKind.file,
+                           "text/plain");
+        assertEquals("native", new String(prop));
+
+        prop = SVNUtil.canonicalizeNodeProperty(
+                    "svn:eol-style", " native  ".getBytes(),
+                    "propcheck.file", NodeKind.file,
+                    "text/plain", new FileInputStream(temp));
+        assertEquals("native", new String(prop));
+
+        boolean caught_exception = false;
+        try {
+            prop = SVNUtil.canonicalizeNodeProperty(
+                        "svn:eol-style", " weird  ".getBytes(),
+                        "propcheck.file", NodeKind.file,
+                        "text/plain");
+        } catch (ClientException ex) {
+            assertEquals("Unrecognized line ending style",
+                         ex.getAllMessages().get(0).getMessage());
+            caught_exception = true;
+        }
+        assertTrue(caught_exception);
+
+        out = new FileOutputStream(temp);
+        out.write("inconsistent\r\ntext\n".getBytes());
+        out.close();
+
+        caught_exception = false;
+        try {
+            prop = SVNUtil.canonicalizeNodeProperty(
+                        "svn:eol-style", " native  ".getBytes(),
+                        "propcheck.file", NodeKind.file,
+                        "text/plain", new FileInputStream(temp));
+        } catch (ClientException ex) {
+            assertEquals("Inconsistent line ending style",
+                         ex.getAllMessages().get(2).getMessage());
+            caught_exception = true;
+        }
+        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 = "Id 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("Id")));
+        assertEquals("     ", new String(result.get("TEST")));
+
+        result = SVNUtil.buildKeywords(kwval, 42, "http://a/b/c",
+                                       "http://a", new Date(1), "X");
+        assertEquals("c 42 1970-01-01 00:00:00Z X",
+                     new String(result.get("Id")));
+        assertEquals("b/c 42 1970-01-01 00:00:00Z X c http://a/b/c",
+                     new String(result.get("TEST")));
+    }
+
+    public void testTranslateStream() throws Throwable
+    {
+        final byte[] keywordsValue = "Id TEST=%H%_%b%_%u".getBytes();
+        final byte[] contentsContracted = "$Id$\n$TEST$\n".getBytes();
+        final byte[] contentsExpanded =
+            ("$Id: c 42 1970-01-01 00:00:00Z X $\r" +
+             "$TEST: b/c 42 1970-01-01 00:00:00Z X c http://a/b/c $\r"
+             ) .getBytes();
+        final Map<String, byte[]> keywords =
+            SVNUtil.buildKeywords(keywordsValue, 42, "http://a/b/c",
+                                  "http://a", new Date(1), "X");
+        final Map<String, byte[]> null_keywords = new HashMap<String, byte[]>();
+        byte[] buffer = new byte[1024];
+
+        for (Map.Entry<String, byte[]> e : keywords.entrySet())
+            null_keywords.put(e.getKey(), null);
+
+        // InputStream; expand
+        InputStream testin = null;
+        try {
+            testin = SVNUtil.translateStream(
+                         new ByteArrayInputStream(contentsContracted),
+                         SVNUtil.EOL_CR, true, keywords, true);
+            final int size = testin.read(buffer);
+            testin.close();
+            testin = null;
+
+            assertEquals("expand InputStream with concrete keywords",
+                         new String(contentsExpanded),
+                         new String(buffer, 0, size));
+        } finally {
+            if (testin != null) {
+                testin.close();
+                testin = null;
+            }
+        }
+
+        try {
+            testin = SVNUtil.translateStream(
+                         new ByteArrayInputStream(contentsContracted),
+                         SVNUtil.EOL_CR, true, true,
+                         keywordsValue, 42, "http://a/b/c",
+                         "http://a", new Date(1), "X");
+            final int size = testin.read(buffer);
+            testin.close();
+            testin = null;
+
+            assertEquals("expand InputStream with implied keywords",
+                         new String(contentsExpanded),
+                         new String(buffer, 0, size));
+        } finally {
+            if (testin != null) {
+                testin.close();
+                testin = null;
+            }
+        }
+
+        // InputStream; contract
+        try {
+            testin = SVNUtil.translateStream(
+                         new ByteArrayInputStream(contentsExpanded),
+                         SVNUtil.EOL_LF, true, null_keywords, false);
+            final int size = testin.read(buffer);
+            testin.close();
+            testin = null;
+
+            assertEquals("contract InputStream with concrete keywords",
+                         new String(contentsContracted),
+                         new String(buffer, 0, size));
+        } finally {
+            if (testin != null) {
+                testin.close();
+                testin = null;
+            }
+        }
+
+        try {
+            testin = SVNUtil.translateStream(
+                         new ByteArrayInputStream(contentsExpanded),
+                         SVNUtil.EOL_LF, true, false,
+                         keywordsValue, 0, "", "", new Date(1), "");
+            final int size = testin.read(buffer);
+            testin.close();
+            testin = null;
+
+            assertEquals("contract InputStream with implied keywords",
+                         new String(contentsContracted),
+                         new String(buffer, 0, size));
+        } finally {
+            if (testin != null) {
+                testin.close();
+                testin = null;
+            }
+        }
+
+
+        // OutputStream; expand
+        OutputStream testout = null;
+        try {
+            ByteArrayOutputStream result = new ByteArrayOutputStream();
+            testout = SVNUtil.translateStream(
+                         result, SVNUtil.EOL_CR, true, keywords, true);
+            testout.write(contentsContracted);
+            testout.close();
+            testout = null;
+
+            assertEquals("expand OutputStream with concrete keywords",
+                         new String(contentsExpanded), result.toString());
+        } finally {
+            if (testout != null) {
+                testout.close();
+                testout = null;
+            }
+        }
+
+        try {
+            ByteArrayOutputStream result = new ByteArrayOutputStream();
+            testout = SVNUtil.translateStream(
+                         result, SVNUtil.EOL_CR, true, true,
+                         keywordsValue, 42, "http://a/b/c",
+                         "http://a", new Date(1), "X");
+            testout.write(contentsContracted);
+            testout.close();
+            testout = null;
+
+            assertEquals("expand OutputStream with implied keywords",
+                         new String(contentsExpanded), result.toString());
+        } finally {
+            if (testout != null) {
+                testout.close();
+                testout = null;
+            }
+        }
+
+        // OutputStream; contract
+        try {
+            ByteArrayOutputStream result = new ByteArrayOutputStream();
+            testout = SVNUtil.translateStream(
+                         result, SVNUtil.EOL_LF, true, null_keywords, false);
+            testout.write(contentsExpanded);
+            testout.close();
+            testout = null;
+
+            assertEquals("contract OutputStream with concrete keywords",
+                         new String(contentsContracted), result.toString());
+        } finally {
+            if (testout != null) {
+                testout.close();
+                testout = null;
+            }
+        }
+
+        try {
+            ByteArrayOutputStream result = new ByteArrayOutputStream();
+            testout = SVNUtil.translateStream(
+                         result, SVNUtil.EOL_LF, true, false,
+                         keywordsValue, 0, "", "", new Date(1), "");
+            testout.write(contentsExpanded);
+            testout.close();
+            testout = null;
+
+            assertEquals("contract OutputStream with implied keywords",
+                         new String(contentsContracted), result.toString());
+        } finally {
+            if (testout != null) {
+                testout.close();
+                testout = null;
+            }
+        }
+    }
 }

Modified: subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/WC.java
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/WC.java?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/WC.java (original)
+++ subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/WC.java Wed Nov 27 08:19:45 2013
@@ -34,11 +34,12 @@ import java.util.Date;
 
 import org.apache.subversion.javahl.types.*;
 
-import junit.framework.Assert;
+import junit.framework.TestCase;
+
 /**
  * This class describe the expected state of the working copy
  */
-public class WC
+public class WC extends TestCase
 {
     /**
      * the map of the items of the working copy. The relative path is the key
@@ -169,9 +170,9 @@ public class WC
         // since having no content signals a directory, changes of removing the
         // content or setting a former not set content is not allowed. That
         // would change the type of the item.
-        Assert.assertNotNull("cannot unset content", content);
+        assertNotNull("cannot unset content", content);
         Item i = items.get(path);
-        Assert.assertNotNull("cannot set content on directory", i.myContent);
+        assertNotNull("cannot set content on directory", i.myContent);
         i.myContent = content;
     }
 
@@ -304,13 +305,13 @@ public class WC
      */
     void check(DirEntry[] tested, String singleFilePath)
     {
-        Assert.assertEquals("not a single dir entry", 1, tested.length);
+        assertEquals("not a single dir entry", 1, tested.length);
         Item item = items.get(singleFilePath);
-        Assert.assertNotNull("not found in working copy", item);
-        Assert.assertNotNull("not a file", item.myContent);
-        Assert.assertEquals("state says file, working copy not",
-                tested[0].getNodeKind(),
-                item.nodeKind == null ? NodeKind.file : item.nodeKind);
+        assertNotNull("not found in working copy", item);
+        assertNotNull("not a file", item.myContent);
+        assertEquals("state says file, working copy not",
+                     tested[0].getNodeKind(),
+                     item.nodeKind == null ? NodeKind.file : item.nodeKind);
     }
 
     /**
@@ -342,19 +343,18 @@ public class WC
         {
             String name = basePath + entry.getPath();
             Item item = items.get(name);
-            Assert.assertNotNull("null paths won't be found in working copy",
-                                 item);
+            assertNotNull("null paths won't be found in working copy", item);
             if (item.myContent != null)
             {
-                Assert.assertEquals("Expected '" + entry + "' to be file",
-                        entry.getNodeKind(),
-                        item.nodeKind == null ? NodeKind.file : item.nodeKind);
+                assertEquals("Expected '" + entry + "' to be file",
+                             entry.getNodeKind(),
+                             item.nodeKind == null ? NodeKind.file : item.nodeKind);
             }
             else
             {
-                Assert.assertEquals("Expected '" + entry + "' to be dir",
-                        entry.getNodeKind(),
-                        item.nodeKind == null ? NodeKind.dir : item.nodeKind);
+                assertEquals("Expected '" + entry + "' to be dir",
+                             entry.getNodeKind(),
+                             item.nodeKind == null ? NodeKind.dir : item.nodeKind);
             }
             item.touched = true;
         }
@@ -369,9 +369,9 @@ public class WC
                         !item.myPath.equals(basePath))
                 {
                     // Non-recursive checks will fail here.
-                    Assert.assertFalse("Expected path '" + item.myPath +
-                                       "' not found in dir entries",
-                                       recursive);
+                    assertFalse("Expected path '" + item.myPath +
+                                "' not found in dir entries",
+                                recursive);
 
                     // Look deeper under the tree.
                     boolean found = false;
@@ -387,8 +387,8 @@ public class WC
                             }
                         }
                     }
-                    Assert.assertTrue("Expected path '" + item.myPath +
-                                       "' not found in dir entries", found);
+                    assertTrue("Expected path '" + item.myPath +
+                               "' not found in dir entries", found);
                 }
             }
         }
@@ -436,14 +436,14 @@ public class WC
         for (Status status : tested)
         {
             String path = status.getPath();
-            Assert.assertTrue("status path starts not with working copy path",
-                    path.startsWith(normalizeWCPath));
+            assertTrue("status path starts not with working copy path",
+                       path.startsWith(normalizeWCPath));
 
             // we calculate the relative path to the working copy root
             if (path.length() > workingCopyPath.length() + 1)
             {
-                Assert.assertEquals("missing '/' in status path",
-                        path.charAt(workingCopyPath.length()), '/');
+                assertEquals("missing '/' in status path",
+                             path.charAt(workingCopyPath.length()), '/');
                 path = path.substring(workingCopyPath.length() + 1);
             }
             else
@@ -451,25 +451,23 @@ public class WC
                 path = "";
 
             Item item = items.get(path);
-            Assert.assertNotNull("status not found in working copy: " + path,
-                    item);
-            Assert.assertEquals("wrong text status in working copy: " + path,
-                    item.textStatus, status.getTextStatus());
+            assertNotNull("status not found in working copy: " + path, item);
+            assertEquals("wrong text status in working copy: " + path,
+                         item.textStatus, status.getTextStatus());
             if (item.workingCopyRev != -1)
-                Assert.assertEquals("wrong revision number in working copy: "
-                            + path,
-                        item.workingCopyRev, status.getRevisionNumber());
-            Assert.assertEquals("lock status wrong: " + path,
-                    item.isLocked, status.isLocked());
-            Assert.assertEquals("switch status wrong: " + path,
-                    item.isSwitched, status.isSwitched());
-            Assert.assertEquals("wrong prop status in working copy: " + path,
-                    item.propStatus, status.getPropStatus());
+                assertEquals("wrong revision number in working copy: " + path,
+                             item.workingCopyRev, status.getRevisionNumber());
+            assertEquals("lock status wrong: " + path,
+                         item.isLocked, status.isLocked());
+            assertEquals("switch status wrong: " + path,
+                         item.isSwitched, status.isSwitched());
+            assertEquals("wrong prop status in working copy: " + path,
+                         item.propStatus, status.getPropStatus());
             if (item.myContent != null)
             {
-                Assert.assertEquals("state says file, working copy not: " + path,
-                        status.getNodeKind(),
-                        item.nodeKind == null ? NodeKind.file : item.nodeKind);
+                assertEquals("state says file, working copy not: " + path,
+                             status.getNodeKind(),
+                             item.nodeKind == null ? NodeKind.file : item.nodeKind);
                 if (status.getTextStatus() == Status.Kind.normal ||
                         item.checkContent)
                 {
@@ -483,26 +481,26 @@ public class WC
                         buffer.append((char) ch);
                     }
                     rd.close();
-                    Assert.assertEquals("content mismatch: " + path,
-                            buffer.toString(), item.myContent);
+                    assertEquals("content mismatch: " + path,
+                                 buffer.toString(), item.myContent);
                 }
             }
             else
             {
-                Assert.assertEquals("state says dir, working copy not: " + path,
-                        status.getNodeKind(),
-                        item.nodeKind == null ? NodeKind.dir : item.nodeKind);
+                assertEquals("state says dir, working copy not: " + path,
+                             status.getNodeKind(),
+                             item.nodeKind == null ? NodeKind.dir : item.nodeKind);
             }
 
             if (checkRepos)
             {
-                Assert.assertEquals("Last commit revisions for OOD path '"
-                                    + item.myPath + "' don't match:",
-                                    item.reposLastCmtRevision,
-                                    status.getReposLastCmtRevisionNumber());
-                Assert.assertEquals("Last commit kinds for OOD path '"
-                                    + item.myPath + "' don't match:",
-                                    item.reposKind, status.getReposKind());
+                assertEquals("Last commit revisions for OOD path '"
+                             + item.myPath + "' don't match:",
+                             item.reposLastCmtRevision,
+                             status.getReposLastCmtRevisionNumber());
+                assertEquals("Last commit kinds for OOD path '"
+                             + item.myPath + "' don't match:",
+                             item.reposKind, status.getReposKind());
 
                 // Only the last committed rev and kind is available for
                 // paths deleted in the repos.
@@ -511,17 +509,17 @@ public class WC
                     long lastCmtTime =
                         (status.getReposLastCmtDate() == null ?
                          0 : status.getReposLastCmtDate().getTime());
-                    Assert.assertEquals("Last commit dates for OOD path '" +
-                                        item.myPath + "' don't match:",
-                                        new Date(item.reposLastCmtDate),
-                                        new Date(lastCmtTime));
-                    Assert.assertEquals("Last commit authors for OOD path '"
-                                        + item.myPath + "' don't match:",
-                                        item.reposLastCmtAuthor,
-                                        status.getReposLastCmtAuthor());
-                    Assert.assertNotNull("URL for path " + item.myPath
-                                         + " should not be null",
-                                         status.getUrl());
+                    assertEquals("Last commit dates for OOD path '" +
+                                 item.myPath + "' don't match:",
+                                 new Date(item.reposLastCmtDate),
+                                 new Date(lastCmtTime));
+                    assertEquals("Last commit authors for OOD path '"
+                                 + item.myPath + "' don't match:",
+                                 item.reposLastCmtAuthor,
+                                 status.getReposLastCmtAuthor());
+                    assertNotNull("URL for path " + item.myPath
+                                  + " should not be null",
+                                  status.getUrl());
                 }
             }
             item.touched = true;
@@ -531,9 +529,9 @@ public class WC
         // result array
         for (Item item : items.values())
         {
-            Assert.assertTrue("item '" + item.myPath +
-                              "' in working copy not found in status",
-                    item.touched);
+            assertTrue("item '" + item.myPath +
+                       "' in working copy not found in status",
+                       item.touched);
         }
     }
 

Modified: subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java (original)
+++ subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java Wed Nov 27 08:19:45 2013
@@ -3360,9 +3360,12 @@ public class BasicTests extends SVNTests
     private class MyChangelistCallback extends HashMap
         implements ChangelistCallback
     {
+        private static final long serialVersionUID = 1L;
+
         @SuppressWarnings("unchecked")
         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/log-addressing/subversion/bindings/swig/core.i
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/bindings/swig/core.i?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/bindings/swig/core.i (original)
+++ subversion/branches/log-addressing/subversion/bindings/swig/core.i Wed Nov 27 08:19:45 2013
@@ -820,7 +820,6 @@ core_set_current_pool (apr_pool_t *pool)
 
 
 
-#ifdef SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC
 %inline %{
 /* Helper function to set the gnome-keyring unlock prompt function. This
  * C function accepts an auth baton, a function and a prompt baton, but
@@ -844,7 +843,6 @@ static void svn_auth_set_gnome_keyring_u
                            prompt_baton);
 }
 %}
-#endif
 
 #if defined(SWIGPERL) || defined(SWIGRUBY)
 %include svn_md5_h.swg

Modified: subversion/branches/log-addressing/subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.c?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.c (original)
+++ subversion/branches/log-addressing/subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.c Wed Nov 27 08:19:45 2013
@@ -25,6 +25,9 @@
 #include <apr_general.h>
 #include <apr_portable.h>
 
+/* Windows hack: Allow overriding some <perl.h> defaults */
+#include "swigutil_pl__pre_perl.h"
+
 #include <EXTERN.h>
 #include <perl.h>
 #include <XSUB.h>

Modified: subversion/branches/log-addressing/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb__pre_ruby.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb__pre_ruby.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb__pre_ruby.h (original)
+++ subversion/branches/log-addressing/subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb__pre_ruby.h Wed Nov 27 08:19:45 2013
@@ -30,8 +30,6 @@
  */
 
 #include <ruby/config.h>
-#ifdef _MSC_VER
-#endif
 
 #undef NORETURN
 #undef DEPRECATED
@@ -87,6 +85,10 @@ typedef unsigned __int64   uint64_t;
 #undef HAVE_INTTYPES_H
 #endif
 
+#ifdef _MSC_VER
+#pragma warning(disable: 4702) /* warning C4702: unreachable code */
+#endif
+
 #endif /* defined(SVN_SWIG_RUBY__CUSTOM_RUBY_CONFIG) && defined(_MSC_VER) */
 
 #endif /* SVN_SWIG_SWIGUTIL_RB__PRE_RUBY_H */

Modified: subversion/branches/log-addressing/subversion/include/private/svn_diff_tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/private/svn_diff_tree.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/private/svn_diff_tree.h (original)
+++ subversion/branches/log-addressing/subversion/include/private/svn_diff_tree.h Wed Nov 27 08:19:45 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/log-addressing/subversion/include/private/svn_ra_svn_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/private/svn_ra_svn_private.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/private/svn_ra_svn_private.h (original)
+++ subversion/branches/log-addressing/subversion/include/private/svn_ra_svn_private.h Wed Nov 27 08:19:45 2013
@@ -43,6 +43,12 @@ svn_ra_svn__set_shim_callbacks(svn_ra_sv
                                svn_delta_shim_callbacks_t *shim_callbacks);
 
 /**
+ * Return the memory pool used to allocate @a conn.
+ */
+apr_pool_t *
+svn_ra_svn__get_pool(svn_ra_svn_conn_t *conn);
+
+/**
  * @defgroup ra_svn_deprecated ra_svn low-level functions
  * @{
  */
@@ -250,6 +256,33 @@ svn_ra_svn__read_cmd_response(svn_ra_svn
                               apr_pool_t *pool,
                               const char *fmt, ...);
 
+/** Check the receive buffer and socket of @a conn whether there is some
+ * unprocessed incomming data without waiting for new data to come in.
+ * If data is found, set @a *has_command to TRUE.  If the connection does
+ * not contain any more data and has been closed, set @a *terminated to
+ * TRUE.
+ */
+svn_error_t *
+svn_ra_svn__has_command(svn_boolean_t *has_command,
+                        svn_boolean_t *terminated,
+                        svn_ra_svn_conn_t *conn,
+                        apr_pool_t *pool);
+
+/** Accept a single command from @a conn and handle them according
+ * to @a cmd_hash.  Command handlers will be passed @a conn, @a pool,
+ * the parameters of the command, and @a baton.  @a *terminate will be
+ * set if either @a error_on_disconnect is FALSE and the connection got
+ * closed, or if the command being handled has the "terminate" flag set
+ * in the command table.
+ */
+svn_error_t *
+svn_ra_svn__handle_command(svn_boolean_t *terminate,
+                           apr_hash_t *cmd_hash,
+                           void *baton,
+                           svn_ra_svn_conn_t *conn,
+                           svn_boolean_t error_on_disconnect,
+                           apr_pool_t *pool);
+
 /** Accept commands over the network and handle them according to @a
  * commands.  Command handlers will be passed @a conn, a subpool of @a
  * pool (cleared after each command is handled), the parameters of the

Modified: subversion/branches/log-addressing/subversion/include/private/svn_repos_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/private/svn_repos_private.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/private/svn_repos_private.h (original)
+++ subversion/branches/log-addressing/subversion/include/private/svn_repos_private.h Wed Nov 27 08:19:45 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 */
@@ -134,7 +136,8 @@ svn_repos__replay_ev2(svn_fs_root_t *roo
  *
  * If PATH cannot be parsed as a config file then an error is returned.  The
  * contents of CFG_P is then undefined.  If MUST_EXIST is TRUE, a missing
- * authz file is also an error.
+ * authz file is also an error.  The CASE_SENSITIVE controls the lookup
+ * behavior for section and option names alike.
  *
  * REPOS_ROOT points at the root of the repos you are
  * going to apply the authz against, can be NULL if you are sure that you
@@ -143,6 +146,7 @@ svn_error_t *
 svn_repos__retrieve_config(svn_config_t **cfg_p,
                            const char *path,
                            svn_boolean_t must_exist,
+                           svn_boolean_t case_sensitive,
                            apr_pool_t *pool);
 
 /**
@@ -158,33 +162,143 @@ 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
+ * behavior for section and option names alike.
+ *
+ * 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 *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,
+                           svn_boolean_t case_sensitive,
+                           svn_repos_t *preferred_repos,
                            apr_pool_t *pool);
 
 /** @} */
 
+/**
+ * @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/log-addressing/subversion/include/private/svn_sqlite.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/private/svn_sqlite.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/private/svn_sqlite.h (original)
+++ subversion/branches/log-addressing/subversion/include/private/svn_sqlite.h Wed Nov 27 08:19:45 2013
@@ -487,6 +487,32 @@ svn_sqlite__with_immediate_transaction(s
     SVN_ERR(svn_sqlite__finish_savepoint(svn_sqlite__db, svn_sqlite__err));   \
   } while (0)
 
+/* Evaluate the expression EXPR1..EXPR4 within a 'savepoint'.  Savepoints can
+ * be nested.
+ *
+ * Begin a savepoint in DB; evaluate the expression EXPR1, which would
+ * typically be a function call that does some work in DB; if no error occurred,
+ * run EXPR2; if no error occurred EXPR3; ... and finally release
+ * the savepoint if EXPR evaluated to SVN_NO_ERROR, otherwise roll back
+ * to the savepoint and then release it.
+ */
+#define SVN_SQLITE__WITH_LOCK4(expr1, expr2, expr3, expr4, db)                \
+  do {                                                                        \
+    svn_sqlite__db_t *svn_sqlite__db = (db);                                  \
+    svn_error_t *svn_sqlite__err;                                             \
+                                                                              \
+    SVN_ERR(svn_sqlite__begin_savepoint(svn_sqlite__db));                     \
+    svn_sqlite__err = (expr1);                                                \
+    if (!svn_sqlite__err)                                                     \
+      svn_sqlite__err = (expr2);                                              \
+    if (!svn_sqlite__err)                                                     \
+      svn_sqlite__err = (expr3);                                              \
+    if (!svn_sqlite__err)                                                     \
+      svn_sqlite__err = (expr4);                                              \
+    SVN_ERR(svn_sqlite__finish_savepoint(svn_sqlite__db, svn_sqlite__err));   \
+  } while (0)
+
+
 /* Helper function to handle several SQLite operations inside a shared lock.
    This callback is similar to svn_sqlite__with_transaction(), but can be
    nested (even with a transaction).

Modified: subversion/branches/log-addressing/subversion/include/private/svn_subr_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/private/svn_subr_private.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/private/svn_subr_private.h (original)
+++ subversion/branches/log-addressing/subversion/include/private/svn_subr_private.h Wed Nov 27 08:19:45 2013
@@ -537,6 +537,28 @@ svn_config__is_expanded(svn_config_t *cf
                         const char *section,
                         const char *option);
 
+/* Return a shallow copy of SCR in POOL.  If SRC is read-only, different
+ * shallow copies may be used from different threads.
+ *
+ * Any single r/o svn_config_t or shallow copy is not thread-safe because
+ * it contains shared buffers for tempoary data.
+ */
+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/log-addressing/subversion/include/private/svn_utf_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/private/svn_utf_private.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/private/svn_utf_private.h (original)
+++ subversion/branches/log-addressing/subversion/include/private/svn_utf_private.h Wed Nov 27 08:19:45 2013
@@ -134,6 +134,22 @@ svn_utf__normcmp(int *result,
                  const char *str2, apr_size_t len2,
                  svn_membuf_t *buf1, svn_membuf_t *buf2);
 
+/* Normalize the UTF-8 string STR to form C, using BUF for temporary
+ * storage. If LEN is SVN_UTF__UNKNOWN_LENGTH, assume STR is
+ * null-terminated; otherwise, consider the string only up to the
+ * given length.
+ *
+ * Return the normalized string in *RESULT, which shares storage with
+ * BUF and is valid only until the next time BUF is modified.
+ *
+ * A returned error may indicate that STRING contains invalid UTF-8 or
+ * invalid Unicode codepoints.
+ */
+svn_error_t*
+svn_utf__normalize(const char **result,
+                   const char *str, apr_size_t len,
+                   svn_membuf_t *buf);
+
 /* Check if STRING is a valid, NFC-normalized UTF-8 string.  Note that
  * a FALSE return value may indicate that STRING is not valid UTF-8 at
  * all.

Modified: subversion/branches/log-addressing/subversion/include/svn_auth.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/svn_auth.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/svn_auth.h (original)
+++ subversion/branches/log-addressing/subversion/include/svn_auth.h Wed Nov 27 08:19:45 2013
@@ -884,7 +884,11 @@ svn_auth_get_platform_specific_client_pr
  * @note An administrative password reset may invalidate the account's
  * secret key. This function will detect that situation and behave as
  * if the password were not cached at all.
+ * @deprecated Provided for backwards compatibility with the 1.8 API.  Use 
+ * svn_auth_get_platform_specific_provider with provider_name of "windows"
+ * and provider_type of "simple".
  */
+SVN_DEPRECATED
 void
 svn_auth_get_windows_simple_provider(svn_auth_provider_object_t **provider,
                                      apr_pool_t *pool);
@@ -906,7 +910,11 @@ svn_auth_get_windows_simple_provider(svn
  * @note An administrative password reset may invalidate the account's
  * secret key. This function will detect that situation and behave as
  * if the password were not cached at all.
+ * @deprecated Provided for backwards compatibility with the 1.8 API.
+ * Use svn_auth_get_platform_specific_provider with provider_name
+ * of "windows" and provider_type of "ssl_client_cert_pw".
  */
+SVN_DEPRECATED
 void
 svn_auth_get_windows_ssl_client_cert_pw_provider(
   svn_auth_provider_object_t **provider,
@@ -923,7 +931,11 @@ svn_auth_get_windows_ssl_client_cert_pw_
  *
  * @since New in 1.5.
  * @note This function is only available on Windows.
+ * @deprecated Provided for backwards compatibility with the 1.8 API.
+ * Use svn_auth_get_platform_specific_provider with provider_name
+ * of "windows" and provider_type of "ssl_server_trust".
  */
+SVN_DEPRECATED
 void
 svn_auth_get_windows_ssl_server_trust_provider(
   svn_auth_provider_object_t **provider,
@@ -943,7 +955,11 @@ svn_auth_get_windows_ssl_server_trust_pr
  *
  * @since New in 1.4
  * @note This function is only available on Mac OS 10.2 and higher.
+ * @deprecated Provided for backwards compatibility with the 1.8 API.
+ * Use svn_auth_get_platform_specific_provider with provider_name
+ * of "keychain" and provider_type of "simple".
  */
+SVN_DEPRECATED
 void
 svn_auth_get_keychain_simple_provider(svn_auth_provider_object_t **provider,
                                       apr_pool_t *pool);
@@ -959,14 +975,21 @@ svn_auth_get_keychain_simple_provider(sv
  *
  * @since New in 1.6
  * @note This function is only available on Mac OS 10.2 and higher.
+ * @deprecated Provided for backwards compatibility with the 1.8 API.
+ * Use svn_auth_get_platform_specific_provider with provider_name
+ * of "keychain" and provider_type of "ssl_client_cert_pw".
  */
+SVN_DEPRECATED
 void
 svn_auth_get_keychain_ssl_client_cert_pw_provider(
   svn_auth_provider_object_t **provider,
   apr_pool_t *pool);
 #endif /* DARWIN || DOXYGEN */
 
-#if (!defined(DARWIN) && !defined(WIN32)) || defined(DOXYGEN)
+/* Note that the gnome keyring unlock prompt related items below must be
+ * declared for all platforms in order to allow SWIG interfaces to be
+ * used regardless of the platform. */
+
 /** A type of callback function for obtaining the GNOME Keyring password.
  *
  * In this callback, the client should ask the user for default keyring
@@ -996,7 +1019,7 @@ typedef svn_error_t *(*svn_auth_gnome_ke
  * @c *SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC. */
 #define SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_BATON "gnome-keyring-unlock-prompt-baton"
 
-
+#if (!defined(DARWIN) && !defined(WIN32)) || defined(DOXYGEN)
 /**
  * Get libsvn_auth_gnome_keyring version information.
  *
@@ -1026,7 +1049,11 @@ svn_auth_gnome_keyring_version(void);
  * @since New in 1.6
  * @note This function actually works only on systems with
  * libsvn_auth_gnome_keyring and GNOME Keyring installed.
+ * @deprecated Provided for backwards compatibility with the 1.8 API.
+ * Use svn_auth_get_platform_specific_provider with provider_name
+ * of "gnome_keyring" and provider_type of "simple".
  */
+SVN_DEPRECATED
 void
 svn_auth_get_gnome_keyring_simple_provider(
   svn_auth_provider_object_t **provider,
@@ -1053,7 +1080,11 @@ svn_auth_get_gnome_keyring_simple_provid
  * @since New in 1.6
  * @note This function actually works only on systems with
  * libsvn_auth_gnome_keyring and GNOME Keyring installed.
+ * @deprecated Provided for backwards compatibility with the 1.8 API.
+ * Use svn_auth_get_platform_specific_provider with provider_name
+ * of "gnome_keyring" and provider_type of "ssl_client_cert_pw".
  */
+SVN_DEPRECATED
 void
 svn_auth_get_gnome_keyring_ssl_client_cert_pw_provider(
   svn_auth_provider_object_t **provider,
@@ -1081,7 +1112,11 @@ svn_auth_kwallet_version(void);
  * @since New in 1.6
  * @note This function actually works only on systems with libsvn_auth_kwallet
  * and KWallet installed.
+ * @deprecated Provided for backwards compatibility with the 1.8 API.
+ * Use svn_auth_get_platform_specific_provider with provider_name
+ * of "kwallet" and provider_type of "simple".
  */
+SVN_DEPRECATED
 void
 svn_auth_get_kwallet_simple_provider(svn_auth_provider_object_t **provider,
                                      apr_pool_t *pool);
@@ -1099,7 +1134,11 @@ svn_auth_get_kwallet_simple_provider(svn
  * @since New in 1.6
  * @note This function actually works only on systems with libsvn_auth_kwallet
  * and KWallet installed.
+ * @deprecated Provided for backwards compatibility with the 1.8 API.
+ * Use svn_auth_get_platform_specific_provider with provider_name
+ * of "kwallet" and provider_type of "ssl_client_cert_pw".
  */
+SVN_DEPRECATED
 void
 svn_auth_get_kwallet_ssl_client_cert_pw_provider(
   svn_auth_provider_object_t **provider,
@@ -1121,7 +1160,11 @@ svn_auth_get_kwallet_ssl_client_cert_pw_
  * @since New in 1.8
  * @note This function actually works only on systems with
  * GNU Privacy Guard installed.
+ * @deprecated Provided for backwards compatibility with the 1.8 API.
+ * Use svn_auth_get_platform_specific_provider with provider_name
+ * of "gpg_agent" and provider_type of "simple".
  */
+SVN_DEPRECATED
 void
 svn_auth_get_gpg_agent_simple_provider
     (svn_auth_provider_object_t **provider,

Modified: subversion/branches/log-addressing/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/svn_client.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/svn_client.h (original)
+++ subversion/branches/log-addressing/subversion/include/svn_client.h Wed Nov 27 08:19:45 2013
@@ -5716,10 +5716,12 @@ svn_client_ls(apr_hash_t **dirents,
 /**
  * Output the content of a file.
  *
- * @param[in] out           The stream to which the content will be written.
- * @param[in] path_or_url   The path or URL of the file.
- * @param[in] peg_revision  The peg revision.
- * @param[in] revision  The operative revision.
+ * @param[out] props           Optional output argument to obtain properties.
+ * @param[in] out              The stream to which the content will be written.
+ * @param[in] path_or_url      The path or URL of the file.
+ * @param[in] peg_revision     The peg revision.
+ * @param[in] revision         The operative revision.
+ * @param[in] expand_keywords  When true, keywords (when set) are expanded.
  * @param[in] ctx   The standard client context, used for possible
  *                  authentication.
  * @param[in] pool  Used for any temporary allocation.
@@ -5734,12 +5736,30 @@ svn_client_ls(apr_hash_t **dirents,
  *         determined. <br>
  *         If no error occurred, return #SVN_NO_ERROR.
  *
- * @since New in 1.2.
- *
  * @see #svn_client_ctx_t <br> @ref clnt_revisions for
  *      a discussion of operative and peg revisions.
+ *
+ * @since New in 1.9.
  */
 svn_error_t *
+svn_client_cat3(apr_hash_t **props,
+                svn_stream_t *out,
+                const char *path_or_url,
+                const svn_opt_revision_t *peg_revision,
+                const svn_opt_revision_t *revision,
+                svn_boolean_t expand_keywords,
+                svn_client_ctx_t *ctx,
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool);
+
+/**
+ * Similar to svn_client_cat3() except without the option of directly
+ * reading the properties, and with @a expand_keywords always TRUE.
+ *
+ * @deprecated Provided for backward compatibility with the 1.8 API.
+ */
+SVN_DEPRECATED
+svn_error_t *
 svn_client_cat2(svn_stream_t *out,
                 const char *path_or_url,
                 const svn_opt_revision_t *peg_revision,

Modified: subversion/branches/log-addressing/subversion/include/svn_config.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/svn_config.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/svn_config.h (original)
+++ subversion/branches/log-addressing/subversion/include/svn_config.h Wed Nov 27 08:19:45 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/log-addressing/subversion/include/svn_dirent_uri.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/svn_dirent_uri.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/svn_dirent_uri.h (original)
+++ subversion/branches/log-addressing/subversion/include/svn_dirent_uri.h Wed Nov 27 08:19:45 2013
@@ -218,7 +218,7 @@ svn_dirent_join(const char *base,
 char *
 svn_dirent_join_many(apr_pool_t *result_pool,
                      const char *base,
-                     ...);
+                     ...) SVN_NEEDS_SENTINEL_NULL;
 
 /** Join a base relpath (@a base) with a component (@a component).
  * @a component need not be a single component.
@@ -354,6 +354,19 @@ char *
 svn_relpath_dirname(const char *relpath,
                     apr_pool_t *result_pool);
 
+/** Return a maximum of @a max_components components of @a relpath. This is
+ * an efficient way of calling svn_relpath_dirname() multiple times until only
+ * a specific number of components is left.
+ *
+ * Allocate the result in @a result_pool (or statically in case of 0)
+ *
+ * @since New in 1.9.
+ */
+const char *
+svn_relpath_limit(const char *relpath,
+                  int max_components,
+                  apr_pool_t *result_pool);
+
 
 /** Divide the canonicalized @a uri into a uri @a *dirpath and a
  * (URI-decoded) relpath @a *base_name.

Modified: subversion/branches/log-addressing/subversion/include/svn_error.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/svn_error.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/svn_error.h (original)
+++ subversion/branches/log-addressing/subversion/include/svn_error.h Wed Nov 27 08:19:45 2013
@@ -268,6 +268,10 @@ svn_error__locate(const char *file,
  * what code that used to call svn_handle_error() and now calls
  * svn_handle_error2() does.
  *
+ * Note that this should only be used from commandline specific code, or
+ * code that knows that @a stream is really where the application wants
+ * to receive its errors on.
+ *
  * @since New in 1.2.
  */
 void
@@ -387,10 +391,17 @@ svn_error_t *svn_error_purge_tracing(svn
   } while (0)
 
 
-/** A statement macro, similar to @c SVN_ERR, but returns an integer.
+/** A statement macro intended for the main() function of the 'svn' program.
+ *
+ * Evaluate @a expr. If it yields an error, display the error on stdout
+ * and return @c EXIT_FAILURE.
+ *
+ * @note Not for use in the library, as it prints to stderr. This macro
+ * no longer suits the needs of the 'svn' program, and is not generally
+ * suitable for third-party use as it assumes the program name is 'svn'.
  *
- * Evaluate @a expr. If it yields an error, handle that error and
- * return @c EXIT_FAILURE.
+ * @deprecated Provided for backward compatibility with the 1.8 API. Consider
+ * using svn_handle_error2() or svn_cmdline_handle_exit_error() instead.
  */
 #define SVN_INT_ERR(expr)                                        \
   do {                                                           \

Modified: subversion/branches/log-addressing/subversion/include/svn_path.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/svn_path.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/svn_path.h (original)
+++ subversion/branches/log-addressing/subversion/include/svn_path.h Wed Nov 27 08:19:45 2013
@@ -131,7 +131,9 @@ svn_path_join(const char *base, const ch
  */
 SVN_DEPRECATED
 char *
-svn_path_join_many(apr_pool_t *pool, const char *base, ...);
+svn_path_join_many(apr_pool_t *pool,
+                   const char *base,
+                   ...) SVN_NEEDS_SENTINEL_NULL;
 
 
 /** Get the basename of the specified canonicalized @a path.  The

Modified: subversion/branches/log-addressing/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/svn_repos.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/svn_repos.h (original)
+++ subversion/branches/log-addressing/subversion/include/svn_repos.h Wed Nov 27 08:19:45 2013
@@ -284,8 +284,43 @@ typedef enum svn_repos_notify_warning_t
    * @see svn_fs.h:"Directory entry names and directory paths" */
   /* ### TODO(doxygen): make that a proper doxygen link */
   /* See svn_fs__path_valid(). */
-  svn_repos_notify_warning_invalid_fspath
+  svn_repos_notify_warning_invalid_fspath,
 
+  /**
+   * Found a denormalized name. Reported when the name of a directoy
+   * entry is not normalized to Unicode Normalization Form C.
+   *
+   * @since New in 1.9.
+   */
+  svn_repos_notify_warning_denormalized_name,
+
+  /**
+   * Detected a name collision. Reported when the names of two or more
+   * entries in the same directory differ only in character
+   * representation (normalization), but are otherwise identical.
+   *
+   * @since New in 1.9.
+   */
+  svn_repos_notify_warning_name_collision,
+
+  /**
+   * Found a denormalized mergeinfo entry. Reported when the path in
+   * an entry in the svn:mergeinfo property is not normalized to
+   * Unicode Normalization Form C.
+   *
+   * @since New in 1.9.
+   */
+  svn_repos_notify_warning_denormalized_mergeinfo,
+
+  /**
+   * Detected a mergeinfo path collision. Reported when the paths in
+   * two or more entries in the same svn:mergeinfo property differ
+   * only in character representation (normalization), but are
+   * otherwise identical.
+   *
+   * @since New in 1.9.
+   */
+  svn_repos_notify_warning_mergeinfo_collision
 } svn_repos_notify_warning_t;
 
 /**
@@ -558,6 +593,13 @@ svn_repos_capabilities(apr_hash_t **capa
 svn_fs_t *
 svn_repos_fs(svn_repos_t *repos);
 
+/** Return the type of filesystem associated with repository object
+ * @a repos allocated in @a pool.
+ *
+ * @since New in 1.9.
+ */
+const char *
+svn_repos_fs_type(svn_repos_t *repos, apr_pool_t *pool);
 
 /** Make a hot copy of the Subversion repository found at @a src_path
  * to @a dst_path.
@@ -2652,6 +2694,12 @@ svn_repos_info_format(int *repos_format,
  * not notified. Finally, return an error if there were any failures during
  * verification, or SVN_NO_ERROR if there were no failures.
  *
+ * If @a check_ucs_norm is @c TRUE, verify that all path names in the
+ * repository and in svn:mergeinfo entries are normaized to Unicode
+ * Normalization Form C, and report any name collisions within the
+ * same directory or svn:mergeinfo property where the names differ only
+ * in character representation, but are otherwise identical.
+ *
  * @since New in 1.9.
  */
 svn_error_t *
@@ -2659,6 +2707,7 @@ svn_repos_verify_fs3(svn_repos_t *repos,
                      svn_revnum_t start_rev,
                      svn_revnum_t end_rev,
                      svn_boolean_t keep_going,
+                     svn_boolean_t check_ucs_norm,
                      svn_repos_notify_func_t notify_func,
                      void *notify_baton,
                      svn_cancel_func_t cancel,
@@ -2666,7 +2715,8 @@ svn_repos_verify_fs3(svn_repos_t *repos,
                      apr_pool_t *scratch_pool);
 
 /**
- * Like svn_repos_verify_fs3(), but with @a keep_going set to @c FALSE.
+ * Like svn_repos_verify_fs3(), but with @a keep_going and
+ * @a check_ucs_norm set to @c FALSE.
  *
  * @since New in 1.7.
  * @deprecated Provided for backward compatibility with the 1.8 API.

Modified: subversion/branches/log-addressing/subversion/include/svn_types.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/svn_types.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/svn_types.h (original)
+++ subversion/branches/log-addressing/subversion/include/svn_types.h Wed Nov 27 08:19:45 2013
@@ -89,6 +89,24 @@ extern "C" {
 # endif
 #endif
 
+/** Macro used to mark functions that require a final null sentinel argument.
+ *
+ * @since New in 1.9.
+ */
+#ifndef SVN_NEEDS_SENTINEL_NULL
+#  if defined(__has_attribute)
+#    if __has_attribute(__sentinel__)
+#      define SVN_NEEDS_SENTINEL_NULL __attribute__((sentinel))
+#    else
+#      define SVN_NEEDS_SENTINEL_NULL
+#    endif
+#  elif defined(__GNUC__) && (__GNUC__ >= 4)
+#    define SVN_NEEDS_SENTINEL_NULL __attribute__((sentinel))
+#  else
+#    define SVN_NEEDS_SENTINEL_NULL
+#  endif
+#endif
+
 
 /** Indicate whether the current platform supports unaligned data access.
  *

Modified: subversion/branches/log-addressing/subversion/include/svn_xml.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/svn_xml.h?rev=1545958&r1=1545957&r2=1545958&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/svn_xml.h (original)
+++ subversion/branches/log-addressing/subversion/include/svn_xml.h Wed Nov 27 08:19:45 2013
@@ -323,7 +323,7 @@ svn_xml_make_open_tag(svn_stringbuf_t **
                       apr_pool_t *pool,
                       enum svn_xml_open_tag_style style,
                       const char *tagname,
-                      ...);
+                      ...) SVN_NEEDS_SENTINEL_NULL;
 
 
 /** Like svn_xml_make_open_tag(), but takes a @c va_list instead of being