subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From julianf...@apache.org
Subject svn commit: r1429457 [19/21] - in /subversion/branches/tree-read-api: ./ build/ build/ac-macros/ build/generator/templates/ build/win32/ contrib/server-side/svncutter/ doc/ subversion/bindings/cxxhl/include/ subversion/bindings/cxxhl/include/svncxxhl/ ...
Date Sun, 06 Jan 2013 02:33:39 GMT
Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_repos/repos-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_repos/repos-test.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_repos/repos-test.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_repos/repos-test.c Sun Jan  6 02:33:34 2013
@@ -1123,30 +1123,104 @@ rmlocks(const svn_test_opts_t *opts,
 
 
 /* Helper for the authz test.  Set *AUTHZ_P to a representation of
-   AUTHZ_CONTENTS, using POOL for temporary allocation. */
+   AUTHZ_CONTENTS, using POOL for temporary allocation. If DISK
+   is TRUE then write the contents to a temp file and use
+   svn_repos_authz_read() to get the data if FALSE write the
+   data to a buffered stream and use svn_repos_authz_parse(). */
 static svn_error_t *
 authz_get_handle(svn_authz_t **authz_p, const char *authz_contents,
-                 apr_pool_t *pool)
+                 svn_boolean_t disk, apr_pool_t *pool)
 {
-  const char *authz_file_path;
+  if (disk)
+    {
+      const char *authz_file_path;
+
+      /* Create a temporary file. */
+      SVN_ERR_W(svn_io_write_unique(&authz_file_path, NULL,
+                                    authz_contents, strlen(authz_contents),
+                                    svn_io_file_del_on_pool_cleanup, pool),
+                "Writing temporary authz file");
+
+      /* Read the authz configuration back and start testing. */
+      SVN_ERR_W(svn_repos_authz_read(authz_p, authz_file_path, TRUE, pool),
+                "Opening test authz file");
+
+      /* Done with the file. */
+      SVN_ERR_W(svn_io_remove_file(authz_file_path, pool),
+                "Removing test authz file");
+    }
+  else
+    {
+      svn_stream_t *stream;
+
+      stream = svn_stream_buffered(pool);
+      SVN_ERR_W(svn_stream_puts(stream, authz_contents),
+                "Writing authz contents to stream");
 
-  /* Create a temporary file. */
-  SVN_ERR_W(svn_io_write_unique(&authz_file_path, NULL,
-                                authz_contents, strlen(authz_contents),
-                                svn_io_file_del_on_pool_cleanup, pool),
-            "Writing temporary authz file");
-
-  /* Read the authz configuration back and start testing. */
-  SVN_ERR_W(svn_repos_authz_read(authz_p, authz_file_path, TRUE, pool),
-            "Opening test authz file");
-
-  /* Done with the file. */
-  SVN_ERR_W(svn_io_remove_file(authz_file_path, pool),
-            "Removing test authz file");
+      SVN_ERR_W(svn_repos_authz_parse(authz_p, stream, pool),
+                "Parsing the authz contents");
+
+      SVN_ERR_W(svn_stream_close(stream),
+                "Closing the stream");
+    }
 
   return SVN_NO_ERROR;
 }
 
+struct check_access_tests {
+  const char *path;
+  const char *repo_name;
+  const char *user;
+  const svn_repos_authz_access_t required;
+  const svn_boolean_t expected;
+};
+
+/* Helper for the authz test.  Runs a set of tests against AUTHZ_CFG
+ * as defined in TESTS. */
+static svn_error_t *
+authz_check_access(svn_authz_t *authz_cfg,
+                   const struct check_access_tests *tests,
+                   apr_pool_t *pool)
+{
+  int i;
+  svn_boolean_t access_granted;
+
+  /* Loop over the test array and test each case. */
+  for (i = 0; !(tests[i].path == NULL
+               && tests[i].required == svn_authz_none); i++)
+    {
+      SVN_ERR(svn_repos_authz_check_access(authz_cfg,
+                                           tests[i].repo_name,
+                                           tests[i].path,
+                                           tests[i].user,
+                                           tests[i].required,
+                                           &access_granted, pool));
+
+      if (access_granted != tests[i].expected)
+        {
+          return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                                   "Authz incorrectly %s %s%s access "
+                                   "to %s%s%s for user %s",
+                                   access_granted ?
+                                   "grants" : "denies",
+                                   tests[i].required
+                                   & svn_authz_recursive ?
+                                   "recursive " : "",
+                                   tests[i].required
+                                   & svn_authz_read ?
+                                   "read" : "write",
+                                   tests[i].repo_name ?
+                                   tests[i].repo_name : "",
+                                   tests[i].repo_name ?
+                                   ":" : "",
+                                   tests[i].path,
+                                   tests[i].user ?
+                                   tests[i].user : "-");
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
 
 
 /* Test that authz is giving out the right authorizations. */
@@ -1158,36 +1232,30 @@ authz(apr_pool_t *pool)
   svn_error_t *err;
   svn_boolean_t access_granted;
   apr_pool_t *subpool = svn_pool_create(pool);
-  int i;
+
   /* Definition of the paths to test and expected replies for each. */
-  struct
-  {
-    const char *path;
-    const char *user;
-    const svn_repos_authz_access_t required;
-    const svn_boolean_t expected;
-  } test_set[] = {
+  struct check_access_tests test_set[] = {
     /* Test that read rules are correctly used. */
-    { "/A", NULL, svn_authz_read, TRUE },
-    { "/iota", NULL, svn_authz_read, FALSE },
+    { "/A", "greek", NULL, svn_authz_read, TRUE },
+    { "/iota", "greek", NULL, svn_authz_read, FALSE },
     /* Test that write rules are correctly used. */
-    { "/A", "plato", svn_authz_write, TRUE },
-    { "/A", NULL, svn_authz_write, FALSE },
+    { "/A", "greek", "plato", svn_authz_write, TRUE },
+    { "/A", "greek", NULL, svn_authz_write, FALSE },
     /* Test that pan-repository rules are found and used. */
-    { "/A/B/lambda", "plato", svn_authz_read, TRUE },
-    { "/A/B/lambda", NULL, svn_authz_read, FALSE },
+    { "/A/B/lambda", "greek", "plato", svn_authz_read, TRUE },
+    { "/A/B/lambda", "greek", NULL, svn_authz_read, FALSE },
     /* Test that authz uses parent path ACLs if no rule for the path
        exists. */
-    { "/A/C", NULL, svn_authz_read, TRUE },
+    { "/A/C", "greek", NULL, svn_authz_read, TRUE },
     /* Test that recursive access requests take into account the rules
        of subpaths. */
-    { "/A/D", "plato", svn_authz_read | svn_authz_recursive, TRUE },
-    { "/A/D", NULL, svn_authz_read | svn_authz_recursive, FALSE },
+    { "/A/D", "greek", "plato", svn_authz_read | svn_authz_recursive, TRUE },
+    { "/A/D", "greek", NULL, svn_authz_read | svn_authz_recursive, FALSE },
     /* Test global write access lookups. */
-    { NULL, "plato", svn_authz_read, TRUE },
-    { NULL, NULL, svn_authz_write, FALSE },
+    { NULL, "greek", "plato", svn_authz_read, TRUE },
+    { NULL, "greek", NULL, svn_authz_write, FALSE },
     /* Sentinel */
-    { NULL, NULL, svn_authz_none, FALSE }
+    { NULL, NULL, NULL, svn_authz_none, FALSE }
   };
 
   /* The test logic:
@@ -1239,37 +1307,14 @@ authz(apr_pool_t *pool)
     ""                                                                       NL;
 
   /* Load the test authz rules. */
-  SVN_ERR(authz_get_handle(&authz_cfg, contents, subpool));
+  SVN_ERR(authz_get_handle(&authz_cfg, contents, FALSE, subpool));
 
   /* Loop over the test array and test each case. */
-  for (i = 0; !(test_set[i].path == NULL
-               && test_set[i].required == svn_authz_none); i++)
-    {
-      SVN_ERR(svn_repos_authz_check_access(authz_cfg, "greek",
-                                           test_set[i].path,
-                                           test_set[i].user,
-                                           test_set[i].required,
-                                           &access_granted, subpool));
-
-      if (access_granted != test_set[i].expected)
-        {
-          return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
-                                   "Authz incorrectly %s %s%s access "
-                                   "to greek:%s for user %s",
-                                   access_granted ?
-                                   "grants" : "denies",
-                                   test_set[i].required
-                                   & svn_authz_recursive ?
-                                   "recursive " : "",
-                                   test_set[i].required
-                                   & svn_authz_read ?
-                                   "read" : "write",
-                                   test_set[i].path,
-                                   test_set[i].user ?
-                                   test_set[i].user : "-");
-        }
-    }
+  SVN_ERR(authz_check_access(authz_cfg, test_set, subpool));
 
+  /* Repeat the previous test on disk */
+  SVN_ERR(authz_get_handle(&authz_cfg, contents, TRUE, subpool));
+  SVN_ERR(authz_check_access(authz_cfg, test_set, subpool));
 
   /* The authz rules for the phase 2 tests, first case (cyclic
      dependency). */
@@ -1283,7 +1328,7 @@ authz(apr_pool_t *pool)
 
   /* Load the test authz rules and check that group cycles are
      reported. */
-  err = authz_get_handle(&authz_cfg, contents, subpool);
+  err = authz_get_handle(&authz_cfg, contents, FALSE, subpool);
   if (!err || err->apr_err != SVN_ERR_AUTHZ_INVALID_CONFIG)
     return svn_error_createf(SVN_ERR_TEST_FAILED, err,
                              "Got %s error instead of expected "
@@ -1298,7 +1343,7 @@ authz(apr_pool_t *pool)
     "@senate = r"                                                            NL;
 
   /* Check that references to undefined groups are reported. */
-  err = authz_get_handle(&authz_cfg, contents, subpool);
+  err = authz_get_handle(&authz_cfg, contents, FALSE, subpool);
   if (!err || err->apr_err != SVN_ERR_AUTHZ_INVALID_CONFIG)
     return svn_error_createf(SVN_ERR_TEST_FAILED, err,
                              "Got %s error instead of expected "
@@ -1315,7 +1360,7 @@ authz(apr_pool_t *pool)
     "* ="                                                                    NL;
 
   /* Load the test authz rules. */
-  SVN_ERR(authz_get_handle(&authz_cfg, contents, subpool));
+  SVN_ERR(authz_get_handle(&authz_cfg, contents, FALSE, subpool));
 
   /* Verify that the rule on /dir2/secret doesn't affect this
      request */
@@ -1333,7 +1378,7 @@ authz(apr_pool_t *pool)
   contents =
     "[greek:/dir2//secret]"                                                  NL
     "* ="                                                                    NL;
-  SVN_TEST_ASSERT_ERROR(authz_get_handle(&authz_cfg, contents, subpool),
+  SVN_TEST_ASSERT_ERROR(authz_get_handle(&authz_cfg, contents, FALSE, subpool),
                         SVN_ERR_AUTHZ_INVALID_CONFIG);
 
   /* That's a wrap! */
@@ -1341,6 +1386,119 @@ authz(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+
+/* Test in-repo authz paths */
+static svn_error_t *
+in_repo_authz(const svn_test_opts_t *opts,
+                                 apr_pool_t *pool)
+{
+  svn_repos_t *repos;
+  svn_fs_t *fs;
+  svn_fs_txn_t *txn;
+  svn_fs_root_t *txn_root;
+  svn_revnum_t youngest_rev;
+  svn_authz_t *authz_cfg;
+  const char *authz_contents;
+  const char *repos_root;
+  const char *repos_url;
+  const char *authz_url;
+  svn_error_t *err;
+  struct check_access_tests test_set[] = {
+    /* reads */
+    { "/A", NULL, NULL, svn_authz_read, FALSE },
+    { "/A", NULL, "plato", svn_authz_read, TRUE },
+    { "/A", NULL, "socrates", svn_authz_read, TRUE },
+    /* writes */
+    { "/A", NULL, NULL, svn_authz_write, FALSE },
+    { "/A", NULL, "socrates", svn_authz_write, FALSE },
+    { "/A", NULL, "plato", svn_authz_write, TRUE },
+    /* Sentinel */
+    { NULL, NULL, NULL, svn_authz_none, FALSE }
+  };
+
+  /* Test plan:
+   * Create an authz file and put it in the repository.
+   * Verify it can be read with an relative URL.
+   * Verify it can be read with an absolute URL.
+   * Verify non-existant path does not error out when must_exist is FALSE. 
+   * Verify non-existant path does error out when must_exist is TRUE.
+   * Verify that an http:// URL produces an error.
+   * Verify that an svn:// URL produces an error.
+   */
+
+  /* What we'll put in the authz file, it's simple since we're not testing
+   * the parsing, just that we got what we expected. */ 
+  authz_contents = 
+    ""                                                                       NL
+    ""                                                                       NL
+    "[/]"                                                                    NL
+    "plato = rw"                                                             NL
+    "socrates = r";
+
+  /* Create a filesystem and repository. */
+  SVN_ERR(svn_test__create_repos(&repos, "test-repo-in-repo-authz",
+                                 opts, pool));
+  fs = svn_repos_fs(repos);
+
+  /* Commit the authz file to the repo. */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_make_file(txn_root, "authz", pool));
+  SVN_ERR(svn_test__set_file_contents(txn_root, "authz", authz_contents,
+                                      pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+  SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
+
+  /* repos relative URL */
+  repos_root = svn_repos_path(repos, pool);
+  SVN_ERR(svn_repos_authz_read2(&authz_cfg, "^/authz", TRUE, repos_root,
+                                pool));
+  SVN_ERR(authz_check_access(authz_cfg, test_set, pool));
+
+  /* absolute file URL, repos_root is NULL to validate the contract that it
+   * is not needed except when a repos relative URL is passed. */
+  SVN_ERR(svn_uri_get_file_url_from_dirent(&repos_url, repos_root, pool));
+  authz_url = apr_pstrcat(pool, repos_url, "/authz", (char *)NULL);
+  SVN_ERR(svn_repos_authz_read2(&authz_cfg, authz_url, TRUE, NULL, pool));
+  SVN_ERR(authz_check_access(authz_cfg, test_set, pool));
+  
+  /* Non-existant path in the repo with must_exist set to FALSE */ 
+  SVN_ERR(svn_repos_authz_read2(&authz_cfg, "^/A/authz", FALSE, repos_root,
+                                pool));
+
+  /* Non-existant path in the repo with must_exist set to TRUE */ 
+  err = svn_repos_authz_read2(&authz_cfg, "^/A/authz", TRUE, repos_root,
+                              pool);
+  if (!err || err->apr_err != SVN_ERR_AUTHZ_INVALID_CONFIG)
+    return svn_error_createf(SVN_ERR_TEST_FAILED, err,
+                             "Got %s error instead of expected "
+                             "SVN_ERR_AUTHZ_INVALID_CONFIG",
+                             err ? "unexpected" : "no");
+  svn_error_clear(err);
+
+  /* http:// URL which is unsupported */
+  err = svn_repos_authz_read2(&authz_cfg, "http://example.com/repo/authz",
+                              TRUE, repos_root, pool);
+  if (!err || err->apr_err != SVN_ERR_RA_ILLEGAL_URL)
+    return svn_error_createf(SVN_ERR_TEST_FAILED, err,
+                             "Got %s error instead of expected "
+                             "SVN_ERR_RA_ILLEGAL_URL",
+                             err ? "unexpected" : "no");
+  svn_error_clear(err);
+
+  /* svn:// URL which is unsupported */
+  err = svn_repos_authz_read2(&authz_cfg, "svn://example.com/repo/authz",
+                              TRUE, repos_root, pool);
+  if (!err || err->apr_err != SVN_ERR_RA_ILLEGAL_URL)
+    return svn_error_createf(SVN_ERR_TEST_FAILED, err,
+                             "Got %s error instead of expected "
+                             "SVN_ERR_RA_ILLEGAL_URL",
+                             err ? "unexpected" : "no");
+  svn_error_clear(err);
+
+
+  return SVN_NO_ERROR;
+}
 
 
 /* Callback for the commit editor tests that relays requests to
@@ -1585,7 +1743,7 @@ commit_editor_authz(const svn_test_opts_
     "[/A/D/G]"                                                               NL
     "plato = r"; /* No newline at end of file. */
 
-  SVN_ERR(authz_get_handle(&authz_file, authz_contents, pool));
+  SVN_ERR(authz_get_handle(&authz_file, authz_contents, FALSE, pool));
 
   iterpool = svn_pool_create(pool);
   for (i = 0; i < (sizeof(path_actions) / sizeof(struct authz_path_action_t));
@@ -1720,15 +1878,17 @@ commit_continue_txn(const svn_test_opts_
 }
 
 
+
+/* A baton for check_location_segments(). */
 struct nls_receiver_baton
 {
   int count;
-  svn_location_segment_t *expected_segments;
+  const svn_location_segment_t *expected_segments;
 };
 
-
+/* Return a pretty-printed string representing SEGMENT. */
 static const char *
-format_segment(svn_location_segment_t *segment,
+format_segment(const svn_location_segment_t *segment,
                apr_pool_t *pool)
 {
   return apr_psprintf(pool, "[r%ld-r%ld: /%s]",
@@ -1737,14 +1897,15 @@ format_segment(svn_location_segment_t *s
                       segment->path ? segment->path : "(null)");
 }
 
-
+/* A location segment receiver for check_location_segments().
+ * Implements svn_location_segment_receiver_t. */
 static svn_error_t *
 nls_receiver(svn_location_segment_t *segment,
              void *baton,
              apr_pool_t *pool)
 {
   struct nls_receiver_baton *b = baton;
-  svn_location_segment_t *expected_segment = b->expected_segments + b->count;
+  const svn_location_segment_t *expected_segment = b->expected_segments + b->count;
 
   /* expected_segments->range_end can't be 0, so if we see that, it's
      our end-of-the-list sentry. */
@@ -1766,18 +1927,22 @@ nls_receiver(svn_location_segment_t *seg
   return SVN_NO_ERROR;
 }
 
-
+/* Run a svn_repos_node_location_segments() query with REPOS, PATH, PEG_REV,
+ * START_REV, END_REV.  Check that the result exactly matches the list of
+ * segments EXPECTED_SEGMENTS, which is terminated by an entry with
+ * 'range_end'==0.
+ */
 static svn_error_t *
 check_location_segments(svn_repos_t *repos,
                         const char *path,
                         svn_revnum_t peg_rev,
                         svn_revnum_t start_rev,
                         svn_revnum_t end_rev,
-                        svn_location_segment_t *expected_segments,
+                        const svn_location_segment_t *expected_segments,
                         apr_pool_t *pool)
 {
   struct nls_receiver_baton b;
-  svn_location_segment_t *segment;
+  const svn_location_segment_t *segment;
 
   /* Run svn_repos_node_location_segments() with a receiver that
      validates against EXPECTED_SEGMENTS.  */
@@ -1799,6 +1964,21 @@ check_location_segments(svn_repos_t *rep
   return SVN_NO_ERROR;
 }
 
+/* Inputs and expected outputs for svn_repos_node_location_segments() tests.
+ */
+typedef struct location_segment_test_t
+{
+  /* Path and peg revision to query */
+  const char *path;
+  svn_revnum_t peg;
+  /* Start (youngest) and end (oldest) revisions to query */
+  svn_revnum_t start;
+  svn_revnum_t end;
+
+  /* Expected segments */
+  svn_location_segment_t segments[10];
+
+} location_segment_test_t;
 
 static svn_error_t *
 node_location_segments(const svn_test_opts_t *opts,
@@ -1811,6 +1991,72 @@ node_location_segments(const svn_test_op
   svn_fs_root_t *txn_root, *root;
   svn_revnum_t youngest_rev = 0;
 
+  static const location_segment_test_t subtests[] =
+  {
+    { /* Check locations for /@HEAD. */
+      "", SVN_INVALID_REVNUM, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
+      {
+        { 0, 7, "" },
+        { 0 }
+      }
+    },
+    { /* Check locations for A/D@HEAD. */
+      "A/D", SVN_INVALID_REVNUM, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
+      {
+        { 7, 7, "A/D" },
+        { 3, 6, "A/D2" },
+        { 1, 2, "A/D" },
+        { 0 }
+      }
+    },
+    { /* Check a subset of the locations for A/D@HEAD. */
+      "A/D", SVN_INVALID_REVNUM, 5, 2,
+      {
+        { 3, 5, "A/D2" },
+        { 2, 2, "A/D" },
+        { 0 }
+      },
+    },
+    { /* Check a subset of locations for A/D2@5. */
+      "A/D2", 5, 3, 2,
+      {
+        { 3, 3, "A/D2" },
+        { 2, 2, "A/D" },
+        { 0 }
+      },
+    },
+    { /* Check locations for A/D@6. */
+      "A/D", 6, 6, SVN_INVALID_REVNUM,
+      {
+        { 1, 6, "A/D" },
+        { 0 }
+      },
+    },
+    { /* Check locations for A/D/G@HEAD. */
+      "A/D/G", SVN_INVALID_REVNUM, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
+      {
+        { 7, 7, "A/D/G" },
+        { 6, 6, "A/D2/G" },
+        { 5, 5, NULL },
+        { 3, 4, "A/D2/G" },
+        { 1, 2, "A/D/G" },
+        { 0 }
+      },
+    },
+    { /* Check a subset of the locations for A/D/G@HEAD. */
+      "A/D/G", SVN_INVALID_REVNUM, 3, 2,
+      {
+        { 3, 3, "A/D2/G" },
+        { 2, 2, "A/D/G" },
+        { 0 }
+      },
+    },
+    {
+      NULL
+    },
+  };
+  const location_segment_test_t *subtest;
+
   /* Bail (with success) on known-untestable scenarios */
   if ((strcmp(opts->fs_type, "bdb") == 0)
       && (opts->server_minor_version == 4))
@@ -1884,117 +2130,19 @@ node_location_segments(const svn_test_op
   SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
   svn_pool_clear(subpool);
 
-  /* Check locations for /@HEAD. */
-  {
-    svn_location_segment_t expected_segments[] =
-      {
-        { 0, 7, "" },
-        { 0 }
-      };
-    SVN_ERR(check_location_segments(repos, "",
-                                    SVN_INVALID_REVNUM,
-                                    SVN_INVALID_REVNUM,
-                                    SVN_INVALID_REVNUM,
-                                    expected_segments, pool));
-  }
-
-  /* Check locations for A/D@HEAD. */
-  {
-    svn_location_segment_t expected_segments[] =
-      {
-        { 7, 7, "A/D" },
-        { 3, 6, "A/D2" },
-        { 1, 2, "A/D" },
-        { 0 }
-      };
-    SVN_ERR(check_location_segments(repos, "A/D",
-                                    SVN_INVALID_REVNUM,
-                                    SVN_INVALID_REVNUM,
-                                    SVN_INVALID_REVNUM,
-                                    expected_segments, pool));
-  }
-
-  /* Check a subset of the locations for A/D@HEAD. */
-  {
-    svn_location_segment_t expected_segments[] =
-      {
-        { 3, 5, "A/D2" },
-        { 2, 2, "A/D" },
-        { 0 }
-      };
-    SVN_ERR(check_location_segments(repos, "A/D",
-                                    SVN_INVALID_REVNUM,
-                                    5,
-                                    2,
-                                    expected_segments, pool));
-  }
-
-  /* Check a subset of locations for A/D2@5. */
-  {
-    svn_location_segment_t expected_segments[] =
-      {
-        { 3, 3, "A/D2" },
-        { 2, 2, "A/D" },
-        { 0 }
-      };
-    SVN_ERR(check_location_segments(repos, "A/D2",
-                                    5,
-                                    3,
-                                    2,
-                                    expected_segments, pool));
-  }
-
-  /* Check locations for A/D@6. */
-  {
-    svn_location_segment_t expected_segments[] =
-      {
-        { 1, 6, "A/D" },
-        { 0 }
-      };
-    SVN_ERR(check_location_segments(repos, "A/D",
-                                    6,
-                                    6,
-                                    SVN_INVALID_REVNUM,
-                                    expected_segments, pool));
-  }
-
-  /* Check locations for A/D/G@HEAD. */
-  {
-    svn_location_segment_t expected_segments[] =
-      {
-        { 7, 7, "A/D/G" },
-        { 6, 6, "A/D2/G" },
-        { 5, 5, NULL },
-        { 3, 4, "A/D2/G" },
-        { 1, 2, "A/D/G" },
-        { 0 }
-      };
-    SVN_ERR(check_location_segments(repos, "A/D/G",
-                                    SVN_INVALID_REVNUM,
-                                    SVN_INVALID_REVNUM,
-                                    SVN_INVALID_REVNUM,
-                                    expected_segments, pool));
-  }
-
-  /* Check a subset of the locations for A/D/G@HEAD. */
-  {
-    svn_location_segment_t expected_segments[] =
-      {
-        { 3, 3, "A/D2/G" },
-        { 2, 2, "A/D/G" },
-        { 0 }
-      };
-    SVN_ERR(check_location_segments(repos, "A/D/G",
-                                    SVN_INVALID_REVNUM,
-                                    3,
-                                    2,
-                                    expected_segments, pool));
-  }
+  /*  */
+  for (subtest = subtests; subtest->path; subtest++)
+    {
+      SVN_ERR(check_location_segments(repos, subtest->path, subtest->peg,
+                                      subtest->start, subtest->end,
+                                      subtest->segments, pool));
+    }
 
   return SVN_NO_ERROR;
 }
 
 
+
 /* Test that the reporter doesn't send deltas under excluded paths. */
 static svn_error_t *
 reporter_depth_exclude(const svn_test_opts_t *opts,
@@ -2550,7 +2698,7 @@ issue_4060(const svn_test_opts_t *opts,
     "ozymandias = r"                                                       NL
     ""                                                                     NL;
 
-  SVN_ERR(authz_get_handle(&authz_cfg, authz_contents, subpool));
+  SVN_ERR(authz_get_handle(&authz_cfg, authz_contents, FALSE, subpool));
 
   SVN_ERR(svn_repos_authz_check_access(authz_cfg, "babylon",
                                        "/A/B/C", "ozymandias",
@@ -2595,6 +2743,8 @@ struct svn_test_descriptor_t test_funcs[
                        "test removal of defunct locks"),
     SVN_TEST_PASS2(authz,
                    "test authz access control"),
+    SVN_TEST_OPTS_PASS(in_repo_authz,
+                       "test authz stored in the repo"),
     SVN_TEST_OPTS_PASS(commit_editor_authz,
                        "test authz in the commit editor"),
     SVN_TEST_OPTS_PASS(commit_continue_txn,

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_subr/config-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_subr/config-test.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_subr/config-test.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_subr/config-test.c Sun Jan  6 02:33:34 2013
@@ -269,6 +269,31 @@ test_has_section_case_sensitive(apr_pool
 
   return SVN_NO_ERROR;
 }
+
+static svn_error_t *
+test_stream_interface(apr_pool_t *pool)
+{
+  svn_config_t *cfg;
+  const char *cfg_file;
+  svn_stream_t *stream;
+
+  if (!srcdir)
+    SVN_ERR(init_params(pool));
+
+  cfg_file = apr_pstrcat(pool, srcdir, "/", "config-test.cfg", (char *)NULL);
+  SVN_ERR(svn_stream_open_readonly(&stream, cfg_file, pool, pool));
+
+  SVN_ERR(svn_config_parse(&cfg, stream, TRUE, pool));
+
+  /* nominal test to make sure cfg is populated with something since
+   * svn_config_parse will happily return an empty cfg if the stream is
+   * empty. */
+  if (! svn_config_has_section(cfg, "section1"))
+    return fail(pool, "Failed to find section1");
+
+  return SVN_NO_ERROR;
+}
+
 /*
    ====================================================================
    If you add a new test to this file, update this array.
@@ -288,5 +313,7 @@ struct svn_test_descriptor_t test_funcs[
                    "test svn_config_has_section (case insensitive)"),
     SVN_TEST_PASS2(test_has_section_case_sensitive,
                    "test svn_config_has_section (case sensitive)"),
+    SVN_TEST_PASS2(test_stream_interface,
+                   "test svn_config_parse"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_subr/error-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_subr/error-test.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_subr/error-test.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_subr/error-test.c Sun Jan  6 02:33:34 2013
@@ -125,8 +125,9 @@ test_error_purge_tracing(apr_pool_t *poo
     svn_error_malfunction_handler_t orig_handler;
 
     /* For this test, use a random error status. */
-    err = svn_error_create(SVN_ERR_BAD_UUID, NULL, SVN_ERR__TRACED);
+    err = svn_error_create(SVN_ERR_BAD_UUID, NULL, "");
     err = svn_error_trace(err);
+    err->child->message = err->message;
 
     /* Register a malfunction handler that doesn't call abort() to
        check that a new error chain with an assertion error is

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_subr/mergeinfo-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_subr/mergeinfo-test.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_subr/mergeinfo-test.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_subr/mergeinfo-test.c Sun Jan  6 02:33:34 2013
@@ -1702,7 +1702,7 @@ struct svn_test_descriptor_t test_funcs[
                    "turning rangelist back into a string"),
     SVN_TEST_PASS2(test_mergeinfo_to_string,
                    "turning mergeinfo back into a string"),
-    SVN_TEST_XFAIL2(test_rangelist_merge,
+    SVN_TEST_PASS2(test_rangelist_merge,
                    "merge of rangelists"),
     SVN_TEST_PASS2(test_rangelist_diff,
                    "diff of rangelists"),

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_subr/named_atomic-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_subr/named_atomic-test.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_subr/named_atomic-test.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_subr/named_atomic-test.c Sun Jan  6 02:33:34 2013
@@ -178,17 +178,17 @@ init_test_shm(apr_pool_t *pool)
   SVN_ERR(svn_named_atomic__get(&atomic, ns, ATOMIC_NAME "2", TRUE));
   SVN_ERR(svn_named_atomic__write(NULL, 0, atomic));
 
-  apr_pool_clear(scratch);
+  svn_pool_clear(scratch);
 
   SVN_ERR(svn_atomic_namespace__create(&ns, name_namespace1, scratch));
   SVN_ERR(svn_named_atomic__get(&atomic, ns, ATOMIC_NAME, TRUE));
   SVN_ERR(svn_named_atomic__write(NULL, 0, atomic));
-  apr_pool_clear(scratch);
+  svn_pool_clear(scratch);
 
   SVN_ERR(svn_atomic_namespace__create(&ns, name_namespace2, scratch));
   SVN_ERR(svn_named_atomic__get(&atomic, ns, ATOMIC_NAME, TRUE));
   SVN_ERR(svn_named_atomic__write(NULL, 0, atomic));
-  apr_pool_clear(scratch);
+  svn_pool_clear(scratch);
 
   /* done */
 
@@ -256,7 +256,7 @@ APR_THREAD_FUNC test_thread(apr_thread_t
                                    params->thread_count,
                                    params->iterations,
                                    pool);
-  apr_pool_destroy(pool);
+  svn_pool_destroy(pool);
   apr_thread_exit(thread, APR_SUCCESS);
 
   return NULL;
@@ -401,7 +401,7 @@ calibrate_iterations(apr_pool_t *pool, i
       SVN_ERR(run_procs(pool, TEST_PROC, count, calib_iterations));
 
       taken = (double)(apr_time_now() - start);
-      apr_pool_destroy(scratch);
+      svn_pool_destroy(scratch);
     }
 
   /* scale that to 1s */

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_subr/path-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_subr/path-test.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_subr/path-test.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_subr/path-test.c Sun Jan  6 02:33:34 2013
@@ -1624,6 +1624,71 @@ test_path_condense_targets(apr_pool_t *p
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_path_is_repos_relative_url(apr_pool_t *pool)
+{
+  int i;
+  struct {
+    const char* path;
+    svn_boolean_t result;
+  } tests[] = {
+    { "^/A",           TRUE },
+    { "http://host/A", FALSE },
+    { "/A/B",          FALSE },
+  };
+
+  for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
+    {
+      svn_boolean_t result = svn_path_is_repos_relative_url(tests[i].path);
+
+      if (tests[i].result != result)
+        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                                 "svn_path_is_repos_relative_url(\"%s\")"
+                                 " returned \"%s\" expected \"%s\"",
+                                 tests[i].path,
+                                 result ? "TRUE" : "FALSE",
+                                 tests[i].result ? "TRUE" : "FALSE");
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_path_resolve_repos_relative_url(apr_pool_t *pool)
+{
+  int i;
+  struct {
+    const char *relative_url;
+    const char *repos_root_url;
+    const char *absolute_url;
+  } tests[] = {
+    { "^/A", "file:///Z/X", "file:///Z/X/A" },
+    { "^/A", "file:///Z/X/", "file:///Z/X//A" }, /* doesn't canonicalize */
+    { "^/A@2", "file:///Z/X", "file:///Z/X/A@2" }, /* peg rev */
+    { "^/A", "/Z/X", "/Z/X/A" }, /* doesn't verify repos_root is URL */
+  };
+
+  for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
+    {
+      const char *result;
+
+      SVN_ERR(svn_path_resolve_repos_relative_url(&result,
+                                                  tests[i].relative_url,
+                                                  tests[i].repos_root_url,
+                                                  pool));
+
+      if (strcmp(tests[i].absolute_url,result))
+        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                                 "svn_path_resolve_repos_relative_url(\"%s\","
+                                 "\"%s\") returned \"%s\" expected \"%s\"",
+                                 tests[i].relative_url,
+                                 tests[i].repos_root_url,
+                                 result, tests[i].absolute_url);
+    }
+  
+  return SVN_NO_ERROR;
+}
+
 
 /* local define to support XFail-ing tests on Windows/Cygwin only */
 #ifdef SVN_USE_DOS_PATHS
@@ -1688,5 +1753,9 @@ struct svn_test_descriptor_t test_funcs[
                    "test svn_path_internal_style"),
     SVN_TEST_PASS2(test_path_condense_targets,
                    "test svn_path_condense_targets"),
+    SVN_TEST_PASS2(test_path_is_repos_relative_url,
+                   "test svn_path_is_repos_relative_url"),
+    SVN_TEST_PASS2(test_path_resolve_repos_relative_url,
+                   "test svn_path_resolve_repos_relative_url"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_wc/conflict-data-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_wc/conflict-data-test.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_wc/conflict-data-test.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_wc/conflict-data-test.c Sun Jan  6 02:33:34 2013
@@ -202,8 +202,8 @@ test_read_write_tree_conflicts(const svn
 
   SVN_ERR(svn_test__sandbox_create(&sbox, "read_write_tree_conflicts", opts, pool));
   parent_abspath = svn_dirent_join(sbox.wc_abspath, "A", pool);
-  SVN_ERR(svn_wc__db_op_add_directory(sbox.wc_ctx->db, parent_abspath, NULL,
-                                      pool));
+  SVN_ERR(svn_wc__db_op_add_directory(sbox.wc_ctx->db, parent_abspath,
+                                      NULL /*props*/, NULL, pool));
   child1_abspath = svn_dirent_join(parent_abspath, "foo", pool);
   child2_abspath = svn_dirent_join(parent_abspath, "bar", pool);
 

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_wc/db-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_wc/db-test.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_wc/db-test.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_wc/db-test.c Sun Jan  6 02:33:34 2013
@@ -391,6 +391,7 @@ test_getting_info(apr_pool_t *pool)
   const svn_checksum_t *checksum;
   const char *target;
   svn_boolean_t had_props;
+  apr_hash_t *props;
   svn_boolean_t update_root;
   svn_wc__db_lock_t *lock;
   svn_wc__db_t *db;
@@ -403,7 +404,7 @@ test_getting_info(apr_pool_t *pool)
             &status, &kind, &revision,
             &repos_relpath, &repos_root_url, &repos_uuid,
             &changed_rev, &changed_date, &changed_author,&depth, &checksum,
-            &target, &lock, &had_props,
+            &target, &lock, &had_props, &props,
             &update_root,
             db, local_abspath,
             pool, pool));
@@ -420,6 +421,9 @@ test_getting_info(apr_pool_t *pool)
   SVN_TEST_ASSERT(checksum == NULL);
   SVN_TEST_ASSERT(target == NULL);
   SVN_TEST_ASSERT(lock == NULL);
+  SVN_TEST_ASSERT(had_props == FALSE);
+  SVN_TEST_ASSERT(apr_hash_count(props) == 0);
+  /* SVN_TEST_ASSERT(update_root == ???); */
 
   /* Test: file-specific values. */
   SVN_ERR(svn_wc__db_base_get_info(
@@ -427,7 +431,7 @@ test_getting_info(apr_pool_t *pool)
             &repos_relpath, &repos_root_url, &repos_uuid,
             NULL, NULL, NULL, NULL,
             &checksum, NULL, NULL,
-            NULL, NULL,
+            NULL, NULL, NULL,
             db, svn_dirent_join(local_abspath, "A", pool),
             pool, pool));
   SVN_TEST_ASSERT(kind == svn_kind_file);
@@ -442,7 +446,7 @@ test_getting_info(apr_pool_t *pool)
             &repos_relpath, &repos_root_url, &repos_uuid,
             &changed_rev, &changed_date, &changed_author,
             &depth, &checksum, &target, &lock,
-            NULL, NULL,
+            NULL, NULL, NULL,
             db, svn_dirent_join(local_abspath, "B", pool),
             pool, pool));
   SVN_TEST_ASSERT(kind == svn_kind_symlink);
@@ -465,7 +469,7 @@ test_getting_info(apr_pool_t *pool)
             NULL, NULL, NULL,
             NULL, NULL, NULL,
             NULL, NULL, NULL,
-            NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
             db, svn_dirent_join(local_abspath, "C", pool),
             pool, pool));
   SVN_TEST_ASSERT(kind == svn_kind_unknown);
@@ -477,7 +481,7 @@ test_getting_info(apr_pool_t *pool)
             NULL, NULL, NULL,
             NULL, NULL, NULL,
             NULL, NULL, NULL,
-            NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
             db, svn_dirent_join(local_abspath, "D", pool),
             pool, pool));
   SVN_TEST_ASSERT(status == svn_wc__db_status_not_present);
@@ -488,7 +492,7 @@ test_getting_info(apr_pool_t *pool)
             NULL, NULL, NULL,
             NULL, NULL, NULL,
             NULL, NULL, NULL,
-            NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
             db, svn_dirent_join(local_abspath, "E", pool),
             pool, pool));
   SVN_TEST_ASSERT(status == svn_wc__db_status_incomplete);
@@ -499,7 +503,7 @@ test_getting_info(apr_pool_t *pool)
             NULL, NULL, NULL,
             NULL, NULL, NULL,
             NULL, &checksum, NULL,
-            NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
             db, svn_dirent_join(local_abspath, "F", pool),
             pool, pool));
   SVN_TEST_STRING_ASSERT(SHA1_1,
@@ -511,7 +515,7 @@ test_getting_info(apr_pool_t *pool)
             &repos_relpath, &repos_root_url, &repos_uuid,
             &changed_rev, &changed_date, &changed_author,
             NULL, NULL, NULL,
-            NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
             db, svn_dirent_join(local_abspath, "G", pool),
             pool, pool));
   SVN_TEST_STRING_ASSERT(repos_relpath, "G-alt");
@@ -527,7 +531,7 @@ test_getting_info(apr_pool_t *pool)
             NULL, NULL, NULL,
             NULL, NULL, NULL,
             NULL, &checksum, &target,
-            NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
             db, svn_dirent_join(local_abspath, "H", pool),
             pool, pool));
   SVN_TEST_ASSERT(checksum == NULL);
@@ -539,7 +543,7 @@ test_getting_info(apr_pool_t *pool)
             NULL, NULL, NULL,
             NULL, NULL, NULL,
             NULL, NULL, NULL,
-            NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
             db, svn_dirent_join(local_abspath, "missing-file", pool),
             pool, pool);
   SVN_TEST_ASSERT(err != NULL && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND);
@@ -568,14 +572,12 @@ validate_node(svn_wc__db_t *db,
             NULL, NULL, NULL,
             NULL, NULL, NULL,
             NULL, NULL, NULL,
-            NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
             db, path,
             scratch_pool, scratch_pool));
   SVN_TEST_ASSERT(kind == expected_kind);
   SVN_TEST_ASSERT(status == expected_status);
 
-  SVN_ERR(svn_wc__db_base_get_props(&props, db, path,
-                                    scratch_pool, scratch_pool));
   switch (status)
     {
     case svn_wc__db_status_server_excluded:
@@ -583,13 +585,18 @@ validate_node(svn_wc__db_t *db,
     case svn_wc__db_status_incomplete:
     case svn_wc__db_status_not_present:
       /* Our tests aren't setting properties on these node types, so
-         short-circuit examination of name/value pairs. */
+         short-circuit examination of name/value pairs, to avoid having
+         to handle the error from svn_wc__db_base_get_props(). */
       return SVN_NO_ERROR;
-
     default:
-      SVN_TEST_ASSERT(props != NULL);
+      break; /* Fall through */
     }
 
+  SVN_ERR(svn_wc__db_base_get_props(&props, db, path,
+                                    scratch_pool, scratch_pool));
+
+  SVN_TEST_ASSERT(props != NULL);
+
   value = apr_hash_get(props, "p1", APR_HASH_KEY_STRING);
   SVN_TEST_STRING_ASSERT(value->data, "v1");
 
@@ -803,10 +810,10 @@ test_working_info(apr_pool_t *pool)
   svn_revnum_t changed_rev;
   apr_time_t changed_date;
   const char *changed_author;
-  apr_time_t last_mod_time;
+  apr_time_t recorded_time;
   svn_depth_t depth;
   const svn_checksum_t *checksum;
-  svn_filesize_t translated_size;
+  svn_filesize_t recorded_size;
   const char *target;
   const char *changelist;
   const char *original_repos_relpath;
@@ -832,7 +839,7 @@ test_working_info(apr_pool_t *pool)
             &changed_rev, &changed_date, &changed_author,
             &depth, &checksum, &target, &original_repos_relpath,
             &original_root_url, &original_uuid, &original_revnum,
-            &lock, &translated_size, &last_mod_time, &changelist,
+            &lock, &recorded_size, &recorded_time, &changelist,
             &conflicted, &op_root, &had_props, &props_mod,
             &have_base, &have_more_work, &have_work,
             db, svn_dirent_join(local_abspath, "I", pool),
@@ -848,18 +855,22 @@ test_working_info(apr_pool_t *pool)
   SVN_TEST_STRING_ASSERT(changed_author, AUTHOR_2);
   SVN_TEST_ASSERT(depth == svn_depth_immediates);
   SVN_TEST_ASSERT(checksum == NULL);
-  SVN_TEST_ASSERT(translated_size == SVN_INVALID_FILESIZE);
+  SVN_TEST_ASSERT(recorded_size == SVN_INVALID_FILESIZE);
   SVN_TEST_ASSERT(target == NULL);
   SVN_TEST_STRING_ASSERT(changelist, "changelist");
   SVN_TEST_STRING_ASSERT(original_repos_relpath, "some/dir");
   SVN_TEST_STRING_ASSERT(original_root_url, ROOT_TWO);
   SVN_TEST_STRING_ASSERT(original_uuid, UUID_TWO);
   SVN_TEST_ASSERT(original_revnum == 2);
+  SVN_TEST_ASSERT(had_props == FALSE);
   SVN_TEST_ASSERT(props_mod == FALSE);
   SVN_TEST_ASSERT(have_base == TRUE);
+  /* SVN_TEST_ASSERT(have_more_work...); */
   SVN_TEST_ASSERT(have_work == TRUE);
   SVN_TEST_ASSERT(conflicted == FALSE);
   SVN_TEST_ASSERT(lock == NULL);
+  /* SVN_TEST_ASSERT(last_mod_time...); */
+  /* SVN_TEST_ASSERT(op_root...); */
 
 
   /* ### we need a hojillion more tests in here. I just want to get this

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_wc/entries-compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_wc/entries-compat.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_wc/entries-compat.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_wc/entries-compat.c Sun Jan  6 02:33:34 2013
@@ -614,13 +614,13 @@ test_access_baton_like_locking(apr_pool_
                                repos_root_url, 0, svn_depth_infinity,
                                pool));
 
-    SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, NULL, wc_ctx->db, subdir,
-                                  pool));
+    SVN_ERR(svn_wc__db_is_switched(&is_root, NULL, NULL, wc_ctx->db, subdir,
+                                   pool));
 
     SVN_TEST_ASSERT(is_root);
 
-    SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, NULL, wc_ctx2->db, subdir,
-                                  pool));
+    SVN_ERR(svn_wc__db_is_switched(&is_root, NULL, NULL, wc_ctx2->db, subdir,
+                                   pool));
 
     /* This test was added to show a regression where the next check failed,
        but the check above this succeeded */

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_wc/op-depth-test.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_wc/op-depth-test.c Sun Jan  6 02:33:34 2013
@@ -35,6 +35,7 @@
 #include "svn_wc.h"
 #include "svn_client.h"
 #include "svn_hash.h"
+#include "svn_sorts.h"
 
 #include "utils.h"
 
@@ -98,19 +99,49 @@ typedef struct nodes_row_t {
     svn_boolean_t file_external;
     const char *moved_to;
     svn_boolean_t moved_here;
+    const char *props;  /* comma-separated list of prop names */
 } nodes_row_t;
 
 /* Macro for filling in the REPO_* fields of a non-base NODES_ROW_T
  * that has no copy-from info. */
 #define NO_COPY_FROM SVN_INVALID_REVNUM, NULL, FALSE
 #define MOVED_HERE FALSE, NULL, TRUE
+#define NOT_MOVED  FALSE, NULL, FALSE
+
+/* Return a comma-separated list of the prop names in PROPS, in lexically
+ * ascending order, or NULL if PROPS is empty or NULL.  (Here, we don't
+ * care about the difference between 'has no props' and 'can't have props',
+ * and we choose to represent both of those as NULL.) */
+static const char *
+props_hash_to_text(apr_hash_t *props, apr_pool_t *pool)
+{
+  apr_array_header_t *props_sorted;
+  svn_stringbuf_t *str;
+  int i;
+
+  if (! props)
+    return NULL;
+
+  str = svn_stringbuf_create_empty(pool);
+  props_sorted = svn_sort__hash(props, svn_sort_compare_items_lexically, pool);
+  for (i = 0; i < props_sorted->nelts; i++)
+    {
+      const svn_sort__item_t *item
+        = &APR_ARRAY_IDX(props_sorted, i, svn_sort__item_t);
+
+      if (str->len)
+        svn_stringbuf_appendbyte(str, ',');
+      svn_stringbuf_appendcstr(str, item->key);
+    }
+  return str->len ? str->data : NULL;
+}
 
 /* Return a human-readable string representing ROW. */
 static const char *
 print_row(const nodes_row_t *row,
           apr_pool_t *result_pool)
 {
-  const char *file_external_str, *moved_here_str, *moved_to_str;
+  const char *file_external_str, *moved_here_str, *moved_to_str, *props;
 
   if (row == NULL)
     return "(null)";
@@ -130,18 +161,23 @@ print_row(const nodes_row_t *row,
   else
     file_external_str = "";
 
+  if (row->props)
+    props = apr_psprintf(result_pool, ", p=(%s)", row->props);
+  else
+    props = "";
+
   if (row->repo_revnum == SVN_INVALID_REVNUM)
-    return apr_psprintf(result_pool, "%d, %s, %s%s%s%s",
+    return apr_psprintf(result_pool, "%d, %s, %s%s%s%s%s",
                         row->op_depth, row->local_relpath, row->presence,
                         moved_here_str, moved_to_str,
-                        file_external_str);
+                        file_external_str, props);
   else
-    return apr_psprintf(result_pool, "%d, %s, %s, %s ^/%s@%d%s%s%s",
+    return apr_psprintf(result_pool, "%d, %s, %s, %s ^/%s@%d%s%s%s%s",
                         row->op_depth, row->local_relpath, row->presence,
                         row->op_depth == 0 ? "base" : "copyfrom",
                         row->repo_relpath, (int)row->repo_revnum,
                         moved_here_str, moved_to_str,
-                        file_external_str);
+                        file_external_str, props);
 }
 
 /* A baton to pass through svn_hash_diff() to compare_nodes_rows(). */
@@ -188,7 +224,9 @@ compare_nodes_rows(const void *key, apr_
            || (expected->moved_to && !found->moved_to)
            || (!expected->moved_to && found->moved_to)
            || (expected->moved_to
-               && strcmp(expected->moved_to, found->moved_to)))
+               && strcmp(expected->moved_to, found->moved_to))
+           || (expected->props != NULL
+               && strcmp_null(expected->props, found->props) != 0))
     {
       b->errors = svn_error_createf(
                     SVN_ERR_TEST_FAILED, b->errors,
@@ -218,7 +256,8 @@ check_db_rows(svn_test__sandbox_t *b,
   svn_sqlite__stmt_t *stmt;
   static const char *const statements[] = {
     "SELECT op_depth, nodes.presence, nodes.local_relpath, revision,"
-    "       repos_path, file_external, def_local_relpath, moved_to, moved_here"
+    "       repos_path, file_external, def_local_relpath, moved_to, moved_here,"
+    "       properties"
     " FROM nodes "
     " LEFT OUTER JOIN externals"
     "             ON nodes.local_relpath = externals.local_relpath"
@@ -248,6 +287,7 @@ check_db_rows(svn_test__sandbox_t *b,
     {
       const char *key;
       nodes_row_t *row = apr_palloc(b->pool, sizeof(*row));
+      apr_hash_t *props_hash;
 
       row->op_depth = svn_sqlite__column_int(stmt, 0);
       row->presence = svn_sqlite__column_text(stmt, 1, b->pool);
@@ -261,6 +301,9 @@ check_db_rows(svn_test__sandbox_t *b,
                               "incomplete {%s}", print_row(row, b->pool));
       row->moved_to = svn_sqlite__column_text(stmt, 7, b->pool);
       row->moved_here = svn_sqlite__column_boolean(stmt, 8);
+      SVN_ERR(svn_sqlite__column_properties(&props_hash, stmt, 9,
+                                            b->pool, b->pool));
+      row->props = props_hash_to_text(props_hash, b->pool);
 
       key = apr_psprintf(b->pool, "%d %s", row->op_depth, row->local_relpath);
       apr_hash_set(found_hash, key, APR_HASH_KEY_STRING, row);
@@ -4284,6 +4327,8 @@ move_added(const svn_test_opts_t *opts, 
   return SVN_NO_ERROR;
 }
 
+/* Test the result of 'update' when the incoming changes are inside a
+ * directory that is locally moved. */
 static svn_error_t *
 move_update(const svn_test_opts_t *opts, apr_pool_t *pool)
 {
@@ -4291,16 +4336,39 @@ move_update(const svn_test_opts_t *opts,
 
   SVN_ERR(svn_test__sandbox_create(&b, "move_update", opts, pool));
 
+  /* r1: Create files 'f', 'h' */
   SVN_ERR(sbox_wc_mkdir(&b, "A"));
   SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
   sbox_file_write(&b, "A/B/f", "r1 content\n");
+  sbox_file_write(&b, "A/B/h", "r1 content\n");
   SVN_ERR(sbox_wc_add(&b, "A/B/f"));
+  SVN_ERR(sbox_wc_add(&b, "A/B/h"));
   SVN_ERR(sbox_wc_commit(&b, ""));
+
+  /* r2: Modify 'f' */
   sbox_file_write(&b, "A/B/f", "r1 content\nr2 content\n");
   SVN_ERR(sbox_wc_commit(&b, ""));
+
+  /* r3: Delete 'h', add 'g' */
   sbox_file_write(&b, "A/B/g", "r3 content\n");
   SVN_ERR(sbox_wc_add(&b, "A/B/g"));
+  SVN_ERR(sbox_wc_delete(&b, "A/B/h"));
   SVN_ERR(sbox_wc_commit(&b, ""));
+
+  /* r4: Add a new subtree 'X' */
+  SVN_ERR(sbox_wc_mkdir(&b, "X"));
+  sbox_file_write(&b, "X/f", "r4 content\n");
+  sbox_file_write(&b, "X/g", "r4 content\n");
+  sbox_file_write(&b, "X/h", "r4 content\n");
+  SVN_ERR(sbox_wc_add(&b, "X/f"));
+  SVN_ERR(sbox_wc_add(&b, "X/g"));
+  SVN_ERR(sbox_wc_add(&b, "X/h"));
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
+  /* r5: Add a subtree 'A/B/C' */
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
   SVN_ERR(sbox_wc_update(&b, "", 1));
 
   /* A is single-revision so A2 is a single-revision copy */
@@ -4311,12 +4379,15 @@ move_update(const svn_test_opts_t *opts,
       {0, "A",        "normal",       1, "A"},
       {0, "A/B",      "normal",       1, "A/B"},
       {0, "A/B/f",    "normal",       1, "A/B/f"},
+      {0, "A/B/h",    "normal",       1, "A/B/h"},
       {1, "A",        "base-deleted", NO_COPY_FROM, "A2"},
       {1, "A/B",      "base-deleted", NO_COPY_FROM},
       {1, "A/B/f",    "base-deleted", NO_COPY_FROM},
+      {1, "A/B/h",    "base-deleted", NO_COPY_FROM},
       {1, "A2",       "normal",       1, "A", MOVED_HERE},
       {1, "A2/B",     "normal",       1, "A/B", MOVED_HERE},
       {1, "A2/B/f",   "normal",       1, "A/B/f", MOVED_HERE},
+      {1, "A2/B/h",   "normal",       1, "A/B/h", MOVED_HERE},
       {0}
     };
     SVN_ERR(check_db_rows(&b, "", nodes));
@@ -4330,31 +4401,37 @@ move_update(const svn_test_opts_t *opts,
       {0, "A",        "normal",       2, "A"},
       {0, "A/B",      "normal",       2, "A/B"},
       {0, "A/B/f",    "normal",       2, "A/B/f"},
+      {0, "A/B/h",    "normal",       2, "A/B/h"},
       {1, "A",        "base-deleted", NO_COPY_FROM, "A2"},
       {1, "A/B",      "base-deleted", NO_COPY_FROM},
       {1, "A/B/f",    "base-deleted", NO_COPY_FROM},
+      {1, "A/B/h",    "base-deleted", NO_COPY_FROM},
       {1, "A2",       "normal",       1, "A", MOVED_HERE},
       {1, "A2/B",     "normal",       1, "A/B", MOVED_HERE},
       {1, "A2/B/f",   "normal",       1, "A/B/f", MOVED_HERE},
+      {1, "A2/B/h",   "normal",       1, "A/B/h", MOVED_HERE},
       {0}
     };
     SVN_ERR(check_db_rows(&b, "", nodes));
   }
 
   /* Resolve should update the move. */
-  SVN_ERR(sbox_wc_resolve(&b, "A"));
+  SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict));
   {
     nodes_row_t nodes[] = {
       {0, "",         "normal",       2, ""},
       {0, "A",        "normal",       2, "A"},
       {0, "A/B",      "normal",       2, "A/B"},
       {0, "A/B/f",    "normal",       2, "A/B/f"},
+      {0, "A/B/h",    "normal",       2, "A/B/h"},
       {1, "A",        "base-deleted", NO_COPY_FROM, "A2"},
       {1, "A/B",      "base-deleted", NO_COPY_FROM},
       {1, "A/B/f",    "base-deleted", NO_COPY_FROM},
+      {1, "A/B/h",    "base-deleted", NO_COPY_FROM},
       {1, "A2",       "normal",       2, "A", MOVED_HERE},
       {1, "A2/B",     "normal",       2, "A/B", MOVED_HERE},
       {1, "A2/B/f",   "normal",       2, "A/B/f", MOVED_HERE},
+      {1, "A2/B/h",   "normal",       2, "A/B/h", MOVED_HERE},
       {0}
     };
     SVN_ERR(check_db_rows(&b, "", nodes));
@@ -4376,13 +4453,13 @@ move_update(const svn_test_opts_t *opts,
       {1, "A2",       "normal",       2, "A", MOVED_HERE},
       {1, "A2/B",     "normal",       2, "A/B", MOVED_HERE},
       {1, "A2/B/f",   "normal",       2, "A/B/f", MOVED_HERE},
+      {1, "A2/B/h",   "normal",       2, "A/B/h", MOVED_HERE},
       {0}
     };
     SVN_ERR(check_db_rows(&b, "", nodes));
   }
 
-  /* Are we going to handle this case? */
-  SVN_ERR(sbox_wc_resolve(&b, "A"));
+  SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict));
   {
     nodes_row_t nodes[] = {
       {0, "",         "normal",       3, ""},
@@ -4403,6 +4480,150 @@ move_update(const svn_test_opts_t *opts,
     SVN_ERR(check_db_rows(&b, "", nodes));
   }
 
+  SVN_ERR(sbox_wc_delete(&b, "A2/B"));
+  {
+    nodes_row_t nodes[] = {
+      {0, "",         "normal",       3, ""},
+      {0, "A",        "normal",       3, "A"},
+      {0, "A/B",      "normal",       3, "A/B"},
+      {0, "A/B/f",    "normal",       3, "A/B/f"},
+      {0, "A/B/g",    "normal",       3, "A/B/g"},
+      {1, "A",        "base-deleted", NO_COPY_FROM, "A2"},
+      {1, "A/B",      "base-deleted", NO_COPY_FROM},
+      {1, "A/B/f",    "base-deleted", NO_COPY_FROM},
+      {1, "A/B/g",    "base-deleted", NO_COPY_FROM},
+      {1, "A2",       "normal",       3, "A", MOVED_HERE},
+      {1, "A2/B",     "normal",       3, "A/B", MOVED_HERE},
+      {1, "A2/B/f",   "normal",       3, "A/B/f", MOVED_HERE},
+      {1, "A2/B/g",   "normal",       3, "A/B/g", MOVED_HERE},
+      {2, "A2/B",     "base-deleted", NO_COPY_FROM},
+      {2, "A2/B/f",   "base-deleted", NO_COPY_FROM},
+      {2, "A2/B/g",   "base-deleted", NO_COPY_FROM},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+  SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict));
+  {
+    nodes_row_t nodes[] = {
+      {0, "",         "normal",       2, ""},
+      {0, "A",        "normal",       2, "A"},
+      {0, "A/B",      "normal",       2, "A/B"},
+      {0, "A/B/f",    "normal",       2, "A/B/f"},
+      {0, "A/B/h",    "normal",       2, "A/B/h"},
+      {1, "A",        "base-deleted", NO_COPY_FROM, "A2"},
+      {1, "A/B",      "base-deleted", NO_COPY_FROM},
+      {1, "A/B/f",    "base-deleted", NO_COPY_FROM},
+      {1, "A/B/h",    "base-deleted", NO_COPY_FROM},
+      {1, "A2",       "normal",       2, "A", MOVED_HERE},
+      {1, "A2/B",     "normal",       2, "A/B", MOVED_HERE},
+      {1, "A2/B/f",   "normal",       2, "A/B/f", MOVED_HERE},
+      {1, "A2/B/h",   "normal",       2, "A/B/h", MOVED_HERE},
+      {2, "A2/B",     "base-deleted", NO_COPY_FROM},
+      {2, "A2/B/f",   "base-deleted", NO_COPY_FROM},
+      {2, "A2/B/h",   "base-deleted", NO_COPY_FROM},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  SVN_ERR(sbox_wc_update(&b, "X", 4));
+  SVN_ERR(sbox_wc_copy(&b, "X", "A2/B"));
+  {
+    nodes_row_t nodes[] = {
+      {0, "",         "normal",       2, ""},
+      {0, "A",        "normal",       2, "A"},
+      {0, "A/B",      "normal",       2, "A/B"},
+      {0, "A/B/f",    "normal",       2, "A/B/f"},
+      {0, "A/B/h",    "normal",       2, "A/B/h"},
+      {0, "X",        "normal",       4, "X"},
+      {0, "X/f",      "normal",       4, "X/f"},
+      {0, "X/g",      "normal",       4, "X/g"},
+      {0, "X/h",      "normal",       4, "X/h"},
+      {1, "A",        "base-deleted", NO_COPY_FROM, "A2"},
+      {1, "A/B",      "base-deleted", NO_COPY_FROM},
+      {1, "A/B/f",    "base-deleted", NO_COPY_FROM},
+      {1, "A/B/h",    "base-deleted", NO_COPY_FROM},
+      {1, "A2",       "normal",       2, "A", MOVED_HERE},
+      {1, "A2/B",     "normal",       2, "A/B", MOVED_HERE},
+      {1, "A2/B/f",   "normal",       2, "A/B/f", MOVED_HERE},
+      {1, "A2/B/h",   "normal",       2, "A/B/h", MOVED_HERE},
+      {2, "A2/B",     "normal",       4, "X"},
+      {2, "A2/B/f",   "normal",       4, "X/f"},
+      {2, "A2/B/g",   "normal",       4, "X/g"},
+      {2, "A2/B/h",   "normal",       4, "X/h"},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  SVN_ERR(sbox_wc_update(&b, "", 4));
+  SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict));
+  {
+    nodes_row_t nodes[] = {
+      {0, "",         "normal",       4, ""},
+      {0, "A",        "normal",       4, "A"},
+      {0, "A/B",      "normal",       4, "A/B"},
+      {0, "A/B/f",    "normal",       4, "A/B/f"},
+      {0, "A/B/g",    "normal",       4, "A/B/g"},
+      {0, "X",        "normal",       4, "X"},
+      {0, "X/f",      "normal",       4, "X/f"},
+      {0, "X/g",      "normal",       4, "X/g"},
+      {0, "X/h",      "normal",       4, "X/h"},
+      {1, "A",        "base-deleted", NO_COPY_FROM, "A2"},
+      {1, "A/B",      "base-deleted", NO_COPY_FROM},
+      {1, "A/B/f",    "base-deleted", NO_COPY_FROM},
+      {1, "A/B/g",    "base-deleted", NO_COPY_FROM},
+      {1, "A2",       "normal",       4, "A", MOVED_HERE},
+      {1, "A2/B",     "normal",       4, "A/B", MOVED_HERE},
+      {1, "A2/B/f",   "normal",       4, "A/B/f", MOVED_HERE},
+      {1, "A2/B/g",   "normal",       4, "A/B/g", MOVED_HERE},
+      {2, "A2/B",     "normal",       4, "X"},
+      {2, "A2/B/f",   "normal",       4, "X/f"},
+      {2, "A2/B/g",   "normal",       4, "X/g"},
+      {2, "A2/B/h",   "normal",       4, "X/h"},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  SVN_ERR(sbox_wc_update(&b, "", 5));
+  SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict));
+  {
+    nodes_row_t nodes[] = {
+      {0, "",         "normal",       5, ""},
+      {0, "A",        "normal",       5, "A"},
+      {0, "A/B",      "normal",       5, "A/B"},
+      {0, "A/B/f",    "normal",       5, "A/B/f"},
+      {0, "A/B/g",    "normal",       5, "A/B/g"},
+      {0, "A/B/C",    "normal",       5, "A/B/C"},
+      {0, "X",        "normal",       5, "X"},
+      {0, "X/f",      "normal",       5, "X/f"},
+      {0, "X/g",      "normal",       5, "X/g"},
+      {0, "X/h",      "normal",       5, "X/h"},
+      {1, "A",        "base-deleted", NO_COPY_FROM, "A2"},
+      {1, "A/B",      "base-deleted", NO_COPY_FROM},
+      {1, "A/B/f",    "base-deleted", NO_COPY_FROM},
+      {1, "A/B/g",    "base-deleted", NO_COPY_FROM},
+      {1, "A/B/C",    "base-deleted", NO_COPY_FROM},
+      {1, "A2",       "normal",       5, "A", MOVED_HERE},
+      {1, "A2/B",     "normal",       5, "A/B", MOVED_HERE},
+      {1, "A2/B/f",   "normal",       5, "A/B/f", MOVED_HERE},
+      {1, "A2/B/g",   "normal",       5, "A/B/g", MOVED_HERE},
+      {1, "A2/B/C",   "normal",       5, "A/B/C", MOVED_HERE},
+      {2, "A2/B",     "normal",       4, "X"},
+      {2, "A2/B/f",   "normal",       4, "X/f"},
+      {2, "A2/B/g",   "normal",       4, "X/g"},
+      {2, "A2/B/h",   "normal",       4, "X/h"},
+      {2, "A2/B/C",   "base-deleted", NO_COPY_FROM},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+
   return SVN_NO_ERROR;
 }
 
@@ -4805,6 +5026,206 @@ mixed_rev_move(const svn_test_opts_t *op
   return SVN_NO_ERROR;
 }
 
+/* Test the result of 'update' when the incoming changes are inside a
+ * directory that is locally moved. */
+static svn_error_t *
+update_prop_mod_into_moved(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(svn_test__sandbox_create(&b, "update_prop_mod_into_moved", opts, pool));
+
+  /* r1: Create files 'f', 'h' */
+  SVN_ERR(sbox_wc_mkdir(&b, "A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+  sbox_file_write(&b, "A/B/f", "r1 content\n");
+  sbox_file_write(&b, "A/B/h", "r1 content\n");
+  SVN_ERR(sbox_wc_add(&b, "A/B/f"));
+  SVN_ERR(sbox_wc_add(&b, "A/B/h"));
+  SVN_ERR(sbox_wc_propset(&b, "pd", "f1", "A/B/f"));
+  SVN_ERR(sbox_wc_propset(&b, "pn", "f1", "A/B/f"));
+  SVN_ERR(sbox_wc_propset(&b, "pm", "f1", "A/B/f"));
+  SVN_ERR(sbox_wc_propset(&b, "p", "h1", "A/B/h"));
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
+  /* r2: Modify 'f'. Delete prop 'pd', modify prop 'pm', add prop 'pa',
+   * leave prop 'pn' unchanged. */
+  sbox_file_write(&b, "A/B/f", "r1 content\nr2 content\n");
+  SVN_ERR(sbox_wc_propset(&b, "pd", NULL, "A/B/f"));
+  SVN_ERR(sbox_wc_propset(&b, "pm", "f2", "A/B/f"));
+  SVN_ERR(sbox_wc_propset(&b, "pa", "f2", "A/B/f"));
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
+  /* r3: Delete 'h', add 'g' */
+  sbox_file_write(&b, "A/B/g", "r3 content\n");
+  SVN_ERR(sbox_wc_add(&b, "A/B/g"));
+  SVN_ERR(sbox_wc_propset(&b, "p", "g3", "A/B/g"));
+  SVN_ERR(sbox_wc_delete(&b, "A/B/h"));
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
+  SVN_ERR(sbox_wc_update(&b, "", 1));
+  {
+    nodes_row_t nodes[] = {
+      {0, "",         "normal",       1, ""},
+      {0, "A",        "normal",       1, "A"},
+      {0, "A/B",      "normal",       1, "A/B"},
+      {0, "A/B/f",    "normal",       1, "A/B/f", NOT_MOVED,  "pd,pm,pn"},
+      {0, "A/B/h",    "normal",       1, "A/B/h", NOT_MOVED,  "p"},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  /* A is single-revision so A2 is a single-revision copy */
+  SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+  {
+    nodes_row_t nodes[] = {
+      {0, "",         "normal",       1, ""},
+      {0, "A",        "normal",       1, "A"},
+      {0, "A/B",      "normal",       1, "A/B"},
+      {0, "A/B/f",    "normal",       1, "A/B/f", NOT_MOVED,  "pd,pm,pn"},
+      {0, "A/B/h",    "normal",       1, "A/B/h", NOT_MOVED,  "p"},
+      {1, "A",        "base-deleted", NO_COPY_FROM, "A2"},
+      {1, "A/B",      "base-deleted", NO_COPY_FROM},
+      {1, "A/B/f",    "base-deleted", NO_COPY_FROM},
+      {1, "A/B/h",    "base-deleted", NO_COPY_FROM},
+      {1, "A2",       "normal",       1, "A", MOVED_HERE},
+      {1, "A2/B",     "normal",       1, "A/B", MOVED_HERE},
+      {1, "A2/B/f",   "normal",       1, "A/B/f", MOVED_HERE, "pd,pm,pn"},
+      {1, "A2/B/h",   "normal",       1, "A/B/h", MOVED_HERE, "p"},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  /* Update causes a tree-conflict on A due to incoming text-change. */
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+  {
+    nodes_row_t nodes[] = {
+      {0, "",         "normal",       2, ""},
+      {0, "A",        "normal",       2, "A"},
+      {0, "A/B",      "normal",       2, "A/B"},
+      {0, "A/B/f",    "normal",       2, "A/B/f", NOT_MOVED,  "pa,pm,pn"},
+      {0, "A/B/h",    "normal",       2, "A/B/h", NOT_MOVED,  "p"},
+      {1, "A",        "base-deleted", NO_COPY_FROM, "A2"},
+      {1, "A/B",      "base-deleted", NO_COPY_FROM},
+      {1, "A/B/f",    "base-deleted", NO_COPY_FROM},
+      {1, "A/B/h",    "base-deleted", NO_COPY_FROM},
+      {1, "A2",       "normal",       1, "A", MOVED_HERE},
+      {1, "A2/B",     "normal",       1, "A/B", MOVED_HERE},
+      {1, "A2/B/f",   "normal",       1, "A/B/f", MOVED_HERE, "pd,pm,pn"},
+      {1, "A2/B/h",   "normal",       1, "A/B/h", MOVED_HERE, "p"},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  /* Resolve should update the move. */
+  SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict));
+  {
+    nodes_row_t nodes[] = {
+      {0, "",         "normal",       2, ""},
+      {0, "A",        "normal",       2, "A"},
+      {0, "A/B",      "normal",       2, "A/B"},
+      {0, "A/B/f",    "normal",       2, "A/B/f", NOT_MOVED,  "pa,pm,pn"},
+      {0, "A/B/h",    "normal",       2, "A/B/h", NOT_MOVED,  "p"},
+      {1, "A",        "base-deleted", NO_COPY_FROM, "A2"},
+      {1, "A/B",      "base-deleted", NO_COPY_FROM},
+      {1, "A/B/f",    "base-deleted", NO_COPY_FROM},
+      {1, "A/B/h",    "base-deleted", NO_COPY_FROM},
+      {1, "A2",       "normal",       2, "A", MOVED_HERE},
+      {1, "A2/B",     "normal",       2, "A/B", MOVED_HERE},
+      {1, "A2/B/f",   "normal",       2, "A/B/f", MOVED_HERE, "pa,pm,pn"},
+      {1, "A2/B/h",   "normal",       2, "A/B/h", MOVED_HERE, "p"},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+nested_move_update(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(svn_test__sandbox_create(&b, "nested_move_update", opts, pool));
+
+  /* r1: Create file 'f' */
+  SVN_ERR(sbox_wc_mkdir(&b, "A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+  sbox_file_write(&b, "A/B/C/f", "r1 content\n");
+  SVN_ERR(sbox_wc_add(&b, "A/B/C/f"));
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
+  /* r2: Modify 'f' */
+  sbox_file_write(&b, "A/B/C/f", "r1 content\nr2 content\n");
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
+  SVN_ERR(sbox_wc_update(&b, "", 1));
+
+  SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+  SVN_ERR(sbox_wc_move(&b, "A2/B/C", "A2/B/C2"));
+  {
+    nodes_row_t nodes[] = {
+      {0, "",          "normal",       1, ""},
+      {0, "A",         "normal",       1, "A"},
+      {0, "A/B",       "normal",       1, "A/B"},
+      {0, "A/B/C",     "normal",       1, "A/B/C"},
+      {0, "A/B/C/f",   "normal",       1, "A/B/C/f"},
+      {1, "A",         "base-deleted", NO_COPY_FROM, "A2"},
+      {1, "A/B",       "base-deleted", NO_COPY_FROM},
+      {1, "A/B/C",     "base-deleted", NO_COPY_FROM},
+      {1, "A/B/C/f",   "base-deleted", NO_COPY_FROM},
+      {1, "A2",        "normal",       1, "A", MOVED_HERE},
+      {1, "A2/B",      "normal",       1, "A/B", MOVED_HERE},
+      {1, "A2/B/C",    "normal",       1, "A/B/C", MOVED_HERE},
+      {1, "A2/B/C/f",  "normal",       1, "A/B/C/f", MOVED_HERE},
+      {3, "A2/B/C",    "base-deleted", NO_COPY_FROM, "A2/B/C2"},
+      {3, "A2/B/C/f",  "base-deleted", NO_COPY_FROM},
+      {3, "A2/B/C2",   "normal",       1, "A/B/C", MOVED_HERE},
+      {3, "A2/B/C2/f", "normal",       1, "A/B/C/f", MOVED_HERE},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+
+  /* Following the A->A2 move should raise a tree-conflict on A2/B/C,
+     resolving that may require an explicit resolve. */
+  SVN_ERR(sbox_wc_resolve(&b, "A", svn_wc_conflict_choose_mine_conflict));
+  SVN_ERR(sbox_wc_resolve(&b, "A2/B/C", svn_wc_conflict_choose_mine_conflict));
+  {
+    nodes_row_t nodes[] = {
+      {0, "",          "normal",       2, ""},
+      {0, "A",         "normal",       2, "A"},
+      {0, "A/B",       "normal",       2, "A/B"},
+      {0, "A/B/C",     "normal",       2, "A/B/C"},
+      {0, "A/B/C/f",   "normal",       2, "A/B/C/f"},
+      {1, "A",         "base-deleted", NO_COPY_FROM, "A2"},
+      {1, "A/B",       "base-deleted", NO_COPY_FROM},
+      {1, "A/B/C",     "base-deleted", NO_COPY_FROM},
+      {1, "A/B/C/f",   "base-deleted", NO_COPY_FROM},
+      {1, "A2",        "normal",       2, "A", MOVED_HERE},
+      {1, "A2/B",      "normal",       2, "A/B", MOVED_HERE},
+      {1, "A2/B/C",    "normal",       2, "A/B/C", MOVED_HERE},
+      {1, "A2/B/C/f",  "normal",       2, "A/B/C/f", MOVED_HERE},
+      {3, "A2/B/C",    "base-deleted", NO_COPY_FROM, "A2/B/C2"},
+      {3, "A2/B/C/f",  "base-deleted", NO_COPY_FROM},
+      {3, "A2/B/C2",   "normal",       2, "A/B/C", MOVED_HERE},
+      {3, "A2/B/C2/f", "normal",       2, "A/B/C/f", MOVED_HERE},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+
+  return SVN_NO_ERROR;
+}
+
 
 /* ---------------------------------------------------------------------- */
 /* The list of test functions */
@@ -4894,7 +5315,7 @@ struct svn_test_descriptor_t test_funcs[
                        "move_on_move2"),
     SVN_TEST_OPTS_PASS(move_added,
                        "move_added"),
-    SVN_TEST_OPTS_XFAIL(move_update,
+    SVN_TEST_OPTS_PASS(move_update,
                        "move_update"),
     SVN_TEST_OPTS_PASS(test_scan_delete,
                        "scan_delete"),
@@ -4902,5 +5323,9 @@ struct svn_test_descriptor_t test_funcs[
                        "follow_moved_to"),
     SVN_TEST_OPTS_PASS(mixed_rev_move,
                        "mixed_rev_move"),
+    SVN_TEST_OPTS_PASS(update_prop_mod_into_moved,
+                       "update_prop_mod_into_moved"),
+    SVN_TEST_OPTS_PASS(nested_move_update,
+                       "nested_move_update"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_wc/utils.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_wc/utils.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_wc/utils.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_wc/utils.c Sun Jan  6 02:33:34 2013
@@ -174,7 +174,8 @@ sbox_wc_add(svn_test__sandbox_t *b, cons
   parent_abspath = svn_dirent_dirname(path, b->pool);
   SVN_ERR(svn_wc__acquire_write_lock(NULL, b->wc_ctx, parent_abspath, FALSE,
                                      b->pool, b->pool));
-  SVN_ERR(svn_wc_add_from_disk(b->wc_ctx, path, NULL, NULL, b->pool));
+  SVN_ERR(svn_wc_add_from_disk2(b->wc_ctx, path, NULL /*props*/,
+                                NULL, NULL, b->pool));
   SVN_ERR(svn_wc__release_write_lock(b->wc_ctx, parent_abspath, b->pool));
   return SVN_NO_ERROR;
 }
@@ -294,8 +295,12 @@ sbox_wc_commit(svn_test__sandbox_t *b, c
 
   APR_ARRAY_PUSH(targets, const char *) = sbox_wc_path(b, path);
   SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool));
-  return svn_client_commit5(targets, svn_depth_infinity,
-                            FALSE, FALSE, TRUE, /* keep locks/cl's/use_ops*/
+  return svn_client_commit6(targets, svn_depth_infinity,
+                            FALSE /* keep_locks */,
+                            FALSE /* keep_changelist */,
+                            TRUE  /* commit_as_operations */,
+                            TRUE  /* include_file_externals */,
+                            FALSE /* include_dir_externals */,
                             NULL, NULL, NULL, NULL, ctx, b->pool);
 }
 
@@ -321,22 +326,24 @@ sbox_wc_update(svn_test__sandbox_t *b, c
 svn_error_t *
 sbox_wc_resolved(svn_test__sandbox_t *b, const char *path)
 {
-  svn_client_ctx_t *ctx;
-
-  SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool));
-  return svn_client_resolve(sbox_wc_path(b, path), svn_depth_infinity,
-                            svn_wc_conflict_choose_merged, ctx, b->pool);
+  return sbox_wc_resolve(b, path, svn_wc_conflict_choose_merged);
 }
 
 svn_error_t *
-sbox_wc_resolve(svn_test__sandbox_t *b, const char *path)
+sbox_wc_resolve(svn_test__sandbox_t *b, const char *path,
+                svn_wc_conflict_choice_t conflict_choice)
 {
-  svn_client_ctx_t *ctx;
-
-  SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool));
-  return svn_client_resolve(sbox_wc_path(b, path), svn_depth_infinity,
-                            svn_wc_conflict_choose_mine_conflict,
-                            ctx, b->pool);
+  SVN_ERR(svn_wc__resolve_conflicts(b->wc_ctx, sbox_wc_path(b, path),
+                                    svn_depth_infinity,
+                                    TRUE /* resolve_text */,
+                                    "" /* resolve_prop (ALL props) */,
+                                    TRUE /* resolve_tree */,
+                                    conflict_choice,
+                                    NULL, NULL, /* conflict func */
+                                    NULL, NULL, /* cancellation */
+                                    NULL, NULL, /* notification */
+                                    b->pool));
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
@@ -361,12 +368,13 @@ sbox_wc_propset(svn_test__sandbox_t *b,
   svn_client_ctx_t *ctx;
   apr_array_header_t *paths = apr_array_make(b->pool, 1,
                                              sizeof(const char *));
+  svn_string_t *pval = value ? svn_string_create(value, b->pool) : NULL;
 
   SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool));
   APR_ARRAY_PUSH(paths, const char *) = sbox_wc_path(b, path);
-  return svn_client_propset_local(name, svn_string_create(value, b->pool),
-                                  paths, svn_depth_empty, TRUE, NULL, ctx,
-                                  b->pool);
+  return svn_client_propset_local(name, pval, paths, svn_depth_empty,
+                                  TRUE /* skip_checks */,
+                                  NULL, ctx, b->pool);
 }
 
 svn_error_t *

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_wc/utils.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_wc/utils.h?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_wc/utils.h (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_wc/utils.h Sun Jan  6 02:33:34 2013
@@ -130,13 +130,14 @@ sbox_wc_resolved(svn_test__sandbox_t *b,
 
 /* */
 svn_error_t *
-sbox_wc_resolve(svn_test__sandbox_t *b, const char *path);
+sbox_wc_resolve(svn_test__sandbox_t *b, const char *path,
+                svn_wc_conflict_choice_t conflict_choice);
 
 /* */
 svn_error_t *
 sbox_wc_move(svn_test__sandbox_t *b, const char *src, const char *dst);
 
-/* */
+/* Set property NAME to VALUE on PATH. If VALUE=NULL, delete the property. */
 svn_error_t *
 sbox_wc_propset(svn_test__sandbox_t *b,
            const char *name,

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_wc/wc-queries-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_wc/wc-queries-test.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_wc/wc-queries-test.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_wc/wc-queries-test.c Sun Jan  6 02:33:34 2013
@@ -87,7 +87,6 @@ static const int slow_statements[] =
 
   /* Is there a record? ### Can we somehow check for LIMIT 1? */
   STMT_LOOK_FOR_WORK,
-  STMT_HAS_WORKING_NODES,
 
   /* Full temporary table read */
   STMT_INSERT_ACTUAL_EMPTIES,

Modified: subversion/branches/tree-read-api/subversion/tests/svn_test_main.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/svn_test_main.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/svn_test_main.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/svn_test_main.c Sun Jan  6 02:33:34 2013
@@ -1,5 +1,5 @@
 /*
- * tests-main.c:  shared main() & friends for SVN test-suite programs
+ * svn_test_main.c:  shared main() & friends for SVN test-suite programs
  *
  * ====================================================================
  *    Licensed to the Apache Software Foundation (ASF) under one

Modified: subversion/branches/tree-read-api/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd (original)
+++ subversion/branches/tree-read-api/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd Sun Jan  6 02:33:34 2013
@@ -61,6 +61,7 @@ taskkill /im fs-test.exe /f 2> nul:
 taskkill /im op-depth-test.exe /f 2> nul:
 taskkill /im java.exe /f 2> nul:
 taskkill /im perl.exe /f 2> nul:
+taskkill /im mspdbsrv.exe /f 2> nul:
 IF EXIST "%TESTDIR%\tests\subversion\tests\cmdline\httpd\" (
   rmdir /s /q  "%TESTDIR%\tests\subversion\tests\cmdline\httpd"
 )

Modified: subversion/branches/tree-read-api/tools/client-side/svn-bench/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/tools/client-side/svn-bench/cl.h?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/tools/client-side/svn-bench/cl.h (original)
+++ subversion/branches/tree-read-api/tools/client-side/svn-bench/cl.h Sun Jan  6 02:33:34 2013
@@ -149,21 +149,6 @@ svn_error_t *
 svn_cl__check_cancel(void *baton);
 
 
-/* Print to stdout a hash that maps property names (char *) to property
-   values (svn_string_t *).  The names are assumed to be in UTF-8 format;
-   the values are either in UTF-8 (the special Subversion props) or
-   plain binary values.
-
-   If OUT is not NULL, then write to it rather than stdout.
-
-   If NAMES_ONLY is true, print just names, else print names and
-   values. */
-svn_error_t *
-svn_cl__print_prop_hash(svn_stream_t *out,
-                        apr_hash_t *prop_hash,
-                        svn_boolean_t names_only,
-                        apr_pool_t *pool);
-
 
 /*** Notification functions to display results on the terminal. */
 

Modified: subversion/branches/tree-read-api/tools/client-side/svn-bench/null-log-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/tools/client-side/svn-bench/null-log-cmd.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/tools/client-side/svn-bench/null-log-cmd.c (original)
+++ subversion/branches/tree-read-api/tools/client-side/svn-bench/null-log-cmd.c Sun Jan  6 02:33:34 2013
@@ -134,7 +134,7 @@ svn_cl__null_log(apr_getopt_t *os,
   svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
   svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
   apr_array_header_t *targets;
-  struct log_receiver_baton lb;
+  struct log_receiver_baton lb = { 0 };
   const char *target;
   int i;
   apr_array_header_t *revprops;

Modified: subversion/branches/tree-read-api/tools/dev/contribulyze.py
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/tools/dev/contribulyze.py?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/tools/dev/contribulyze.py (original)
+++ subversion/branches/tree-read-api/tools/dev/contribulyze.py Sun Jan  6 02:33:34 2013
@@ -511,8 +511,13 @@ class LogMessage(object):
 log_separator = '-' * 72 + '\n'
 log_header_re = re.compile\
                 ('^(r[0-9]+) \| ([^|]+) \| ([^|]+) \| ([0-9]+)[^0-9]')
-field_re = re.compile('^(Patch|Review(ed)?|Suggested|Found|Inspired) by:\s*\S.*$')
-field_aliases = { 'Reviewed' : 'Review' }
+field_re = re.compile(
+           '^(Patch|Review(ed)?|Suggested|Found|Inspired|Tested|Reported) by:'
+           '\s*\S.*$')
+field_aliases = {
+  'Reviewed' : 'Review',
+  'Reported' : 'Found',
+}
 parenthetical_aside_re = re.compile('^\s*\(.*\)\s*$')
 
 def graze(input):

Propchange: subversion/branches/tree-read-api/tools/dist/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Sun Jan  6 02:33:34 2013
@@ -1,3 +1,4 @@
 prefix
 tempdir
 deploy
+*.pyc

Modified: subversion/branches/tree-read-api/tools/dist/backport.pl
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/tools/dist/backport.pl?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/tools/dist/backport.pl (original)
+++ subversion/branches/tree-read-api/tools/dist/backport.pl Sun Jan  6 02:33:34 2013
@@ -110,10 +110,6 @@ $SVNq up
 $SVNq merge $mergeargs
 $VIM -e -s -n -N -i NONE -u NONE -c '/$pattern/normal! dap' -c wq $STATUS
 if $WET_RUN; then
-  if [ -n "\$PRINT_SOMETHING_BETWEEN_PROMPTS" ]; then
-    # hack for pw-driver.pl to see some output between prompts
-    head -n1 $logmsg_filename
-  fi
   $SVNq commit -F $logmsg_filename
 else
   echo "Committing:"
@@ -233,6 +229,9 @@ sub main {
   die "A vim with the +ex_extra feature is required"
       if `${VIM} --version` !~ /[+]ex_extra/;
 
+  # ### TODO: need to run 'revert' here
+  # ### TODO: both here and in merge(), unlink files that previous merges added
+  die "Local mods to STATUS file $STATUS" if `$SVN status -q $STATUS`;
   @ARGV = $STATUS;
 
   # Skip most of the file



Mime
View raw message