You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2013/06/26 23:30:06 UTC

svn commit: r1497111 - in /subversion/trunk/subversion/bindings/javahl: native/CommitEditor.cpp native/EnumMapper.cpp native/EnumMapper.h tests/org/apache/subversion/javahl/SVNRemoteTests.java

Author: brane
Date: Wed Jun 26 21:30:06 2013
New Revision: 1497111

URL: http://svn.apache.org/r1497111
Log:
Implement the EV2 add_file and alter_file ops in the JavaHL commit editor.

[in subversion/bindings/javahl/native]
* EnumMapper.h, EnumMapper.cpp (EnumMapper::toChecksumKind): New helper method.
* CommitEditor.cpp (build_checksum): New; converts a JavaHL Checksum object
   to a svn_checksum_t struct.
  (CommitEditor::addFile, CommitEditor::alterFile): Implement.
  (CommitEditor::alterDirectory): The properties hash can be NULL.

[in subversion/bindings/javahl/tests/org/apache/subversion/javahl]
* SVNRemoteTests.java (SHA1): New; SHA-1 hash from byte array.
  (SVNRemoteTests.testEditorAddFile,
   SVNRemoteTests.testEditorSetFileProps): New test cases.

Modified:
    subversion/trunk/subversion/bindings/javahl/native/CommitEditor.cpp
    subversion/trunk/subversion/bindings/javahl/native/EnumMapper.cpp
    subversion/trunk/subversion/bindings/javahl/native/EnumMapper.h
    subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java

Modified: subversion/trunk/subversion/bindings/javahl/native/CommitEditor.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/CommitEditor.cpp?rev=1497111&r1=1497110&r2=1497111&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/CommitEditor.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/CommitEditor.cpp Wed Jun 26 21:30:06 2013
@@ -24,14 +24,17 @@
  * @brief Implementation of the class CommitEditor
  */
 
-#include "EnumMapper.h"
 #include "CommitEditor.h"
+#include "EnumMapper.h"
+#include "InputStream.h"
 #include "Iterator.h"
+#include "JNIByteArray.h"
 #include "LockTokenTable.h"
 #include "RevpropTable.h"
 #include "RemoteSession.h"
 
 #include <apr_tables.h>
+#include "svn_checksum.h"
 #include "private/svn_editor.h"
 #include "private/svn_ra_private.h"
 #include "svn_private_config.h"
@@ -178,6 +181,55 @@ build_children(const Iterator& iter, SVN
     }
   return children;
 }
+
+svn_checksum_t
+build_checksum(jobject jchecksum, SVN::Pool& pool)
+{
+  apr_pool_t* result_pool = pool.getPool();
+  svn_checksum_t checksum = { 0 };
+  if (jchecksum)
+    {
+      JNIEnv *env = JNIUtil::getEnv();
+
+      static jmethodID digest_mid = 0;
+      static jmethodID kind_mid = 0;
+
+      jclass cls = env->FindClass(JAVA_PACKAGE"/types/Checksum");
+      if (JNIUtil::isJavaExceptionThrown())
+        return checksum;
+
+      if (0 == digest_mid)
+        {
+          digest_mid = env->GetMethodID(cls, "getDigest", "()[B");
+          if (JNIUtil::isJavaExceptionThrown())
+            return checksum;
+        }
+      if (0 == kind_mid)
+        {
+          kind_mid = env->GetMethodID(cls, "getKind", "()L"
+                                      JAVA_PACKAGE"/types/Checksum$Kind;");
+          if (JNIUtil::isJavaExceptionThrown())
+            return checksum;
+        }
+
+      jobject jdigest = env->CallObjectMethod(jchecksum, digest_mid);
+      if (JNIUtil::isJavaExceptionThrown())
+        return checksum;
+      jobject jkind = env->CallObjectMethod(jchecksum, kind_mid);
+      if (JNIUtil::isJavaExceptionThrown())
+        return checksum;
+      JNIByteArray bdigest((jbyteArray)jdigest, true);
+      if (JNIUtil::isJavaExceptionThrown())
+        return checksum;
+
+      void* digest = apr_palloc(result_pool, bdigest.getLength());
+      memcpy(digest, bdigest.getBytes(), bdigest.getLength());
+      checksum.digest = static_cast<const unsigned char*>(digest);
+      checksum.kind = EnumMapper::toChecksumKind(jkind);
+    }
+
+  return checksum;
+}
 } // anonymous namespace
 
 
@@ -220,7 +272,23 @@ void CommitEditor::addFile(jstring jrelp
       return;
     }
   SVN_JNI_ERR(m_session->m_context->checkCancel(m_session->m_context),);
-  throw_not_implemented("addFile");
+
+  JNIStringHolder relpath(jrelpath);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+  InputStream contents(jcontents);
+  RevpropTable properties(jproperties, true);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+
+  SVN::Pool subPool(pool);
+  svn_checksum_t checksum = build_checksum(jchecksum, subPool);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+  SVN_JNI_ERR(svn_editor_add_file(m_editor, relpath,
+                                  &checksum, contents.getStream(subPool),
+                                  properties.hash(subPool, false),
+                                  svn_revnum_t(jreplaces_revision)),);
 }
 
 void CommitEditor::addSymlink(jstring jrelpath,
@@ -272,7 +340,7 @@ void CommitEditor::alterDirectory(jstrin
   SVN_JNI_ERR(svn_editor_alter_directory(
                   m_editor, relpath, svn_revnum_t(jrevision),
                   (jchildren ? build_children(children, subPool) : NULL),
-                  properties.hash(subPool, false)),);
+                  properties.hash(subPool, true)),);
 }
 
 void CommitEditor::alterFile(jstring jrelpath, jlong jrevision,
@@ -285,7 +353,24 @@ void CommitEditor::alterFile(jstring jre
       return;
     }
   SVN_JNI_ERR(m_session->m_context->checkCancel(m_session->m_context),);
-  throw_not_implemented("alterFile");
+
+  JNIStringHolder relpath(jrelpath);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+  InputStream contents(jcontents);
+  RevpropTable properties(jproperties, true);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+
+  SVN::Pool subPool(pool);
+  svn_checksum_t checksum = build_checksum(jchecksum, subPool);
+  if (JNIUtil::isJavaExceptionThrown())
+    return;
+  SVN_JNI_ERR(svn_editor_alter_file(
+                  m_editor, relpath, svn_revnum_t(jrevision),
+                  (jcontents ? &checksum : NULL),
+                  (jcontents ? contents.getStream(subPool) : NULL),
+                  properties.hash(subPool, true)),);
 }
 
 void CommitEditor::alterSymlink(jstring jrelpath, jlong jrevision,

Modified: subversion/trunk/subversion/bindings/javahl/native/EnumMapper.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/EnumMapper.cpp?rev=1497111&r1=1497110&r2=1497111&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/EnumMapper.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/EnumMapper.cpp Wed Jun 26 21:30:06 2013
@@ -197,6 +197,12 @@ svn_node_kind_t EnumMapper::toNodeKind(j
       getOrdinal(JAVA_PACKAGE"/types/NodeKind", jNodeKind));
 }
 
+svn_checksum_kind_t EnumMapper::toChecksumKind(jobject jChecksumKind)
+{
+  return svn_checksum_kind_t(
+      getOrdinal(JAVA_PACKAGE"/types/Checksum$Kind", jChecksumKind));
+}
+
 svn_depth_t EnumMapper::toDepth(jobject jdepth)
 {
   // The offset for depths is -2

Modified: subversion/trunk/subversion/bindings/javahl/native/EnumMapper.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/EnumMapper.h?rev=1497111&r1=1497110&r2=1497111&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/EnumMapper.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/EnumMapper.h Wed Jun 26 21:30:06 2013
@@ -49,6 +49,7 @@ class EnumMapper
   static int toMergeinfoLogKind(jobject jLogKind);
   static int toLogLevel(jobject jLogLevel);
   static svn_node_kind_t toNodeKind(jobject jNodeKind);
+  static svn_checksum_kind_t toChecksumKind(jobject jChecksumKind);
 
   /* Converting from C enum's */
   static jint mapCommitMessageStateFlags(apr_byte_t flags);

Modified: subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java?rev=1497111&r1=1497110&r2=1497111&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java (original)
+++ subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java Wed Jun 26 21:30:06 2013
@@ -34,9 +34,12 @@ import java.util.Set;
 import java.util.Map;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 
 /**
  * This class is used for testing the SVNReposAccess class
@@ -504,12 +507,12 @@ public class SVNRemoteTests extends SVNT
     {
         Charset UTF8 = Charset.forName("UTF-8");
         ISVNRemote session = getSession();
-        CommitContext cc = new CommitContext(session, "Add svn:ignore");
 
         byte[] ignoreval = "*.pyc\n.gitignore\n".getBytes(UTF8);
         HashMap<String, byte[]> props = new HashMap<String, byte[]>();
         props.put("svn:ignore", ignoreval);
 
+        CommitContext cc = new CommitContext(session, "Add svn:ignore");
         try {
             cc.editor.alterDirectory("", 1, null, props);
             cc.editor.complete();
@@ -525,4 +528,74 @@ public class SVNRemoteTests extends SVNT
                                                     Revision.HEAD,
                                                     Revision.HEAD)));
     }
+
+    private static byte[] SHA1(byte[] text) throws NoSuchAlgorithmException
+    {
+        MessageDigest md = MessageDigest.getInstance("SHA-1");
+        return md.digest(text);
+    }
+
+    public void testEditorAddFile() throws Exception
+    {
+        Charset UTF8 = Charset.forName("UTF-8");
+        ISVNRemote session = getSession();
+
+        byte[] eolstyle = "native".getBytes(UTF8);
+        HashMap<String, byte[]> props = new HashMap<String, byte[]>();
+        props.put("svn:eol-style", eolstyle);
+
+        byte[] contents = "This is file 'xi'.".getBytes(UTF8);
+        Checksum hash = new Checksum(SHA1(contents), Checksum.Kind.SHA1);
+        ByteArrayInputStream stream = new ByteArrayInputStream(contents);
+
+        CommitContext cc = new CommitContext(session, "Add A/xi");
+        try {
+            // FIXME: alter dir A first
+            cc.editor.addFile("A/xi", hash, stream, props,
+                              Revision.SVN_INVALID_REVNUM);
+            cc.editor.complete();
+        } finally {
+            cc.editor.dispose();
+        }
+
+        assertEquals(2, cc.getRevision());
+        assertEquals(2, session.getLatestRevision());
+        assertEquals(NodeKind.file,
+                     session.checkPath("A/xi",
+                                       Revision.SVN_INVALID_REVNUM));
+
+        byte[] propval = client.propertyGet(session.getSessionUrl() + "/A/xi",
+                                            "svn:eol-style",
+                                            Revision.HEAD,
+                                            Revision.HEAD);
+        assertTrue(Arrays.equals(eolstyle, propval));
+    }
+
+    public void testEditorSetFileProps() throws Exception
+    {
+        Charset UTF8 = Charset.forName("UTF-8");
+        ISVNRemote session = getSession();
+
+        byte[] eolstyle = "CRLF".getBytes(UTF8);
+        HashMap<String, byte[]> props = new HashMap<String, byte[]>();
+        props.put("svn:eol-style", eolstyle);
+
+        CommitContext cc =
+            new CommitContext(session, "Change eol-style on A/B/E/alpha");
+        try {
+            cc.editor.alterFile("A/B/E/alpha", 1, null, null, props);
+            cc.editor.complete();
+        } finally {
+            cc.editor.dispose();
+        }
+
+        assertEquals(2, cc.getRevision());
+        assertEquals(2, session.getLatestRevision());
+        byte[] propval = client.propertyGet(session.getSessionUrl()
+                                            + "/A/B/E/alpha",
+                                            "svn:eol-style",
+                                            Revision.HEAD,
+                                            Revision.HEAD);
+        assertTrue(Arrays.equals(eolstyle, propval));
+    }
 }