subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From v...@apache.org
Subject svn commit: r1425415 [5/13] - in /subversion/branches/javahl-ra: ./ build/generator/templates/ notes/ notes/directory-index/ subversion/bindings/swig/python/svn/ subversion/bindings/swig/ruby/test/ subversion/include/ subversion/include/private/ subver...
Date Sun, 23 Dec 2012 06:03:17 GMT
Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_fs/structure
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/structure?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/structure (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/structure Sun Dec 23 06:03:14 2012
@@ -40,6 +40,9 @@ repository) is:
   revprops/           Subdirectory containing rev-props
     <shard>/          Shard directory, if sharding is in use (see below)
       <revnum>        File containing rev-props for <revnum>
+    <shard>.pack/     Pack directory, if the repo has been packed (see below)
+      <rev>.<count>   Pack file, if the repository has been packed (see below)
+      manifest        Pack manifest file, if a pack file exists (see below)
     revprops.db       SQLite database of the packed revision properties
   transactions/       Subdirectory containing transactions
     <txnid>.txn/      Directory containing transaction <txnid>
@@ -134,6 +137,7 @@ The formats are:
   Format 3, understood by Subversion 1.5+
   Format 4, understood by Subversion 1.6+
   Format 5, understood by Subversion 1.7-dev, never released
+  Format 6, understood by Subversion 1.8
 
 The differences between the formats are:
 
@@ -173,6 +177,12 @@ Revision changed paths list:
   Format 1-3: Does not contain the node's kind.
   Format 4+:  Contains the node's kind.
 
+Shard packing:
+  Format 4:   Applied to revision data only.
+  Format 5:   Revprops would be packed independently of revision data.
+  Format 6+:  Applied equally to revision data and revprop data
+    (i.e. same min packed revision)
+
 # Incomplete list.  See SVN_FS_FS__MIN_*_FORMAT
 
 
@@ -232,6 +242,79 @@ See r1143829 of this file:
 http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/structure?view=markup&pathrev=1143829
 
 
+Packing revision properties (format 6+)
+---------------------------
+
+Similarly to the revision data, packing will concatenate multiple
+revprops into a single file.  Since they are mutable data, we put an
+upper limit to the size of these files:  We will concatenate the data
+up to the limit and then use a new file for the following revisions.
+
+The limit can be set and changed at will in the configuration file. 
+It is 64kB by default.  Because a pack file must contain at least one
+complete property list, files containing just one revision may exceed
+that limit.
+
+Furthermore, pack files can be compressed which saves about 75% of
+disk space.  A configuration file flag enables the compression; it is
+off by default and may be switched on and off at will.  The pack size
+limit is always applied to the uncompressed data.  For this reason,
+the default is 256kB while compression has been enabled.
+
+Files are named after their start revision as "<rev>.<counter>" where
+counter will be increased whenever we rewrite a pack file due to a
+revprop change.  The manifest file contains the list of pack file
+names, one line for each revision.
+
+Many tools track repository global data in revision properties at 
+revision 0.  To minimize I/O overhead for those applications,  we
+will never pack that revision, i.e. its data is always being kept
+in revprops/0/0.
+
+Pack file format
+
+  Top level: <length><packed container>
+
+  We always apply data compression to the pack file - using the
+  SVN_DELTA_COMPRESSION_LEVEL_NONE level if compression is disabled.
+  <length> is being encoded using the variable-length svndiff integer
+  format.
+
+  container := header '\n' (revprops)+
+  header    := start_rev '\n' rev_count '\n' (size '\n')+
+
+  All numbers in the header are given as ASCII decimals.  rev_count
+  is the number of revisions packed into this container.  There must
+  be exactly as many "size" and serialized "revprops".  The "size"
+  values in the list are the length in bytes of the serialized
+  revprops of the respective revision.
+
+Writing to packed revprops
+
+  The old pack file is being read and the new revprops serialized.
+  If they fit into the same pack file, a temp file with the new
+  content gets written and moved into place just like an non-packed
+  revprop file would. No name change or manifest update required.
+
+  If they don't fit into the same pack file,  i.e. exceed the pack
+  size limit,  the pack will be split into 2 or 3 new packs just
+  before and / or after the modified revision.
+
+  In the current implementation, they will never be merged again.
+  To minimize fragmentation, the initial packing process will only
+  use about 90% of the limit, i.e. leave some room for growth.
+
+  When a pack file gets split, its counter is being increased
+  creating a new file and leaving the old content in place and
+  available for concurrent readers.  Only after the new manifest
+  file got moved into place, will the old pack files be deleted. 
+
+  Write access to revprops is being serialized by the global
+  filesystem write lock.  We only need to build a few retries into
+  the reader code to gracefully handle manifest changes and pack
+  file deletions.
+
+
 Node-revision IDs
 -----------------
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/tree.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/tree.c Sun Dec 23 06:03:14 2012
@@ -3901,8 +3901,9 @@ svn_fs_fs__verify_root(svn_fs_root_t *ro
         if (pred_rev+1 != root->rev)
           /* Issue #4129. */
           return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
-                                   "r%ld's root node's predecessor is r%ld",
-                                   root->rev, pred_rev);
+                                   "r%ld's root node's predecessor is r%ld"
+                                   " but should be r%ld",
+                                   root->rev, pred_rev, root->rev - 1);
       }
   }
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra/ra_loader.h?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra/ra_loader.h Sun Dec 23 06:03:14 2012
@@ -58,7 +58,7 @@ typedef struct svn_ra__vtable_t {
      time this is called.  SESSION->priv may be set by this function. */
   svn_error_t *(*open_session)(svn_ra_session_t *session,
                                const char **corrected_url,
-                               const char *repos_URL,
+                               const char *session_URL,
                                const svn_ra_callbacks2_t *callbacks,
                                void *callback_baton,
                                apr_hash_t *config,

Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/serf.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/serf.c Sun Dec 23 06:03:14 2012
@@ -344,7 +344,7 @@ svn_ra_serf__progress(void *progress_bat
 static svn_error_t *
 svn_ra_serf__open(svn_ra_session_t *session,
                   const char **corrected_url,
-                  const char *repos_URL,
+                  const char *session_URL,
                   const svn_ra_callbacks2_t *callbacks,
                   void *callback_baton,
                   apr_hash_t *config,
@@ -374,12 +374,12 @@ svn_ra_serf__open(svn_ra_session_t *sess
                                        serf_sess->pool));
 
 
-  status = apr_uri_parse(serf_sess->pool, repos_URL, &url);
+  status = apr_uri_parse(serf_sess->pool, session_URL, &url);
   if (status)
     {
       return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
-                               _("Illegal repository URL '%s'"),
-                               repos_URL);
+                               _("Illegal URL '%s'"),
+                               session_URL);
     }
   /* Contrary to what the comment for apr_uri_t.path says in apr-util 1.2.12 and
      older, for root paths url.path will be "", where serf requires "/". */
@@ -390,7 +390,7 @@ svn_ra_serf__open(svn_ra_session_t *sess
       url.port = apr_uri_port_of_scheme(url.scheme);
     }
   serf_sess->session_url = url;
-  serf_sess->session_url_str = apr_pstrdup(serf_sess->pool, repos_URL);
+  serf_sess->session_url_str = apr_pstrdup(serf_sess->pool, session_URL);
   serf_sess->using_ssl = (svn_cstring_casecmp(url.scheme, "https") == 0);
 
   serf_sess->supports_deadprop_count = svn_tristate_unknown;
@@ -471,14 +471,16 @@ svn_ra_serf__reparent(svn_ra_session_t *
             "URL '%s'"), url, session->repos_root_str);
     }
 
-  status = apr_uri_parse(session->pool, url, &new_url);
+  status = apr_uri_parse(pool, url, &new_url);
   if (status)
     {
       return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
                                _("Illegal repository URL '%s'"), url);
     }
 
-  session->session_url.path = new_url.path;
+  /* Maybe we should use a string buffer for these strings so we don't
+     allocate memory in the session on every reparent? */
+  session->session_url.path = apr_pstrdup(session->pool, new_url.path);
   session->session_url_str = apr_pstrdup(session->pool, url);
 
   return SVN_NO_ERROR;

Modified: subversion/branches/javahl-ra/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_repos/dump.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_repos/dump.c Sun Dec 23 06:03:14 2012
@@ -72,7 +72,8 @@ store_delta(apr_file_t **tempfile, svn_f
   /* Compute the delta and send it to the temporary file. */
   SVN_ERR(svn_fs_get_file_delta_stream(&delta_stream, oldroot, oldpath,
                                        newroot, newpath, pool));
-  svn_txdelta_to_svndiff2(&wh, &whb, temp_stream, 0, pool);
+  svn_txdelta_to_svndiff3(&wh, &whb, temp_stream, 0,
+                          SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
   SVN_ERR(svn_txdelta_send_txstream(delta_stream, wh, whb, pool));
 
   /* Get the length of the temporary file and rewind it. */

Modified: subversion/branches/javahl-ra/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_repos/fs-wrap.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_repos/fs-wrap.c Sun Dec 23 06:03:14 2012
@@ -659,8 +659,8 @@ svn_repos_fs_get_mergeinfo(svn_mergeinfo
      the change itself. */
   /* ### TODO(reint): ... but how about descendant merged-to paths? */
   if (readable_paths->nelts > 0)
-    SVN_ERR(svn_fs_get_mergeinfo(mergeinfo, root, readable_paths, inherit,
-                                 include_descendants, pool));
+    SVN_ERR(svn_fs_get_mergeinfo2(mergeinfo, root, readable_paths, inherit,
+                                  include_descendants, TRUE, pool, pool));
   else
     *mergeinfo = apr_hash_make(pool);
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_repos/repos.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_repos/repos.c Sun Dec 23 06:03:14 2012
@@ -1564,7 +1564,8 @@ svn_repos_has_capability(svn_repos_t *re
 
       SVN_ERR(svn_fs_revision_root(&root, repos->fs, 0, pool));
       APR_ARRAY_PUSH(paths, const char *) = "";
-      err = svn_fs_get_mergeinfo(&ignored, root, paths, FALSE, FALSE, pool);
+      err = svn_fs_get_mergeinfo2(&ignored, root, paths, FALSE, FALSE,
+                                  TRUE, pool, pool);
 
       if (err)
         {

Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/deprecated.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/deprecated.c Sun Dec 23 06:03:14 2012
@@ -1056,14 +1056,6 @@ svn_path_canonicalize(const char *path, 
     return svn_dirent_canonicalize(path, pool);
 }
 
-svn_boolean_t
-svn_path_is_canonical(const char *path, apr_pool_t *pool)
-{
-  return svn_uri_is_canonical(path, pool) ||
-      svn_dirent_is_canonical(path, pool) ||
-      svn_relpath_is_canonical(path);
-}
-
 
 /*** From mergeinfo.c ***/
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/io.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/io.c Sun Dec 23 06:03:14 2012
@@ -185,7 +185,7 @@ try_utf8_from_internal_style(const char 
   /* Special case. */
   if (path == NULL)
     return "(NULL)";
-  
+
   /* (try to) convert PATH to UTF-8. If that fails, continue with the plain
    * PATH because it is the best we have. It may actually be UTF-8 already.
    */
@@ -1311,6 +1311,43 @@ svn_io_filesizes_different_p(svn_boolean
 
 
 svn_error_t *
+svn_io_filesizes_three_different_p(svn_boolean_t *different_p12,
+                                   svn_boolean_t *different_p23,
+                                   svn_boolean_t *different_p13,
+                                   const char *file1,
+                                   const char *file2,
+                                   const char *file3,
+                                   apr_pool_t *scratch_pool)
+{
+  apr_finfo_t finfo1, finfo2, finfo3;
+  apr_status_t status1, status2, status3;
+  const char *file1_apr, *file2_apr, *file3_apr;
+
+  /* Not using svn_io_stat() because don't want to generate
+     svn_error_t objects for non-error conditions. */
+
+  SVN_ERR(cstring_from_utf8(&file1_apr, file1, scratch_pool));
+  SVN_ERR(cstring_from_utf8(&file2_apr, file2, scratch_pool));
+  SVN_ERR(cstring_from_utf8(&file3_apr, file3, scratch_pool));
+
+  /* Stat all three files */
+  status1 = apr_stat(&finfo1, file1_apr, APR_FINFO_MIN, scratch_pool);
+  status2 = apr_stat(&finfo2, file2_apr, APR_FINFO_MIN, scratch_pool);
+  status3 = apr_stat(&finfo3, file3_apr, APR_FINFO_MIN, scratch_pool);
+
+  /* If we got an error stat'ing a file, it could be because the
+     file was removed... or who knows.  Whatever the case, we
+     don't know if the filesizes are definitely different, so
+     assume that they're not. */
+  *different_p12 = !status1 && !status2 && finfo1.size != finfo2.size;
+  *different_p23 = !status2 && !status3 && finfo2.size != finfo3.size;
+  *different_p13 = !status1 && !status3 && finfo1.size != finfo3.size;
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
 svn_io_file_checksum2(svn_checksum_t **checksum,
                       const char *file,
                       svn_checksum_kind_t kind,
@@ -1994,7 +2031,7 @@ svn_io_unlock_open_file(apr_file_t *lock
   if (apr_err)
     return svn_error_wrap_apr(apr_err, _("Can't unlock file '%s'"),
                               try_utf8_from_internal_style(fname, pool));
-  
+
 /* On Windows and OS/2 file locks are automatically released when
    the file handle closes */
 #if !defined(WIN32) && !defined(__OS2__)
@@ -4076,6 +4113,138 @@ contents_identical_p(svn_boolean_t *iden
 
 
 
+/* Do a byte-for-byte comparison of FILE1, FILE2 and FILE3. */
+static svn_error_t *
+contents_three_identical_p(svn_boolean_t *identical_p12,
+                           svn_boolean_t *identical_p23,
+                           svn_boolean_t *identical_p13,
+                           const char *file1,
+                           const char *file2,
+                           const char *file3,
+                           apr_pool_t *scratch_pool)
+{
+  svn_error_t *err;
+  apr_size_t bytes_read1, bytes_read2, bytes_read3;
+  char *buf1 = apr_palloc(scratch_pool, SVN__STREAM_CHUNK_SIZE);
+  char *buf2 = apr_palloc(scratch_pool, SVN__STREAM_CHUNK_SIZE);
+  char *buf3 = apr_palloc(scratch_pool, SVN__STREAM_CHUNK_SIZE);
+  apr_file_t *file1_h;
+  apr_file_t *file2_h;
+  apr_file_t *file3_h;
+  svn_boolean_t eof1 = FALSE;
+  svn_boolean_t eof2 = FALSE;
+  svn_boolean_t eof3 = FALSE;
+  svn_boolean_t read_1, read_2, read_3;
+
+  SVN_ERR(svn_io_file_open(&file1_h, file1, APR_READ, APR_OS_DEFAULT,
+                           scratch_pool));
+
+  err = svn_io_file_open(&file2_h, file2, APR_READ, APR_OS_DEFAULT,
+                         scratch_pool);
+
+  if (err)
+    return svn_error_trace(
+               svn_error_compose_create(err,
+                                        svn_io_file_close(file1_h, scratch_pool)));
+
+  err = svn_io_file_open(&file3_h, file3, APR_READ, APR_OS_DEFAULT,
+                         scratch_pool);
+
+  if (err)
+      return svn_error_trace(
+               svn_error_compose_create(
+                    err,
+                    svn_error_compose_create(svn_io_file_close(file1_h,
+                                                          scratch_pool),
+                                             svn_io_file_close(file2_h,
+                                                          scratch_pool))));
+
+  /* assume TRUE, until disproved below */
+  *identical_p12 = *identical_p23 = *identical_p13 = TRUE;
+  /* We need to read as long as no error occurs, and as long as one of the
+   * flags could still change due to a read operation */
+  while (!err
+        && ((*identical_p12 && !eof1 && !eof2)
+            || (*identical_p23 && !eof2 && !eof3)
+            || (*identical_p13 && !eof1 && !eof3)))
+    {
+      read_1 = read_2 = read_3 = FALSE;
+
+      /* As long as a file is not at the end yet, and it is still
+       * potentially identical to another file, we read the next chunk.*/
+      if (!eof1 && (identical_p12 || identical_p13))
+        {
+          err = svn_io_file_read_full2(file1_h, buf1,
+                                   SVN__STREAM_CHUNK_SIZE, &bytes_read1,
+                                   &eof1, scratch_pool);
+          if (err)
+              break;
+          read_1 = TRUE;
+        }
+
+      if (!eof2 && (identical_p12 || identical_p23))
+        {
+          err = svn_io_file_read_full2(file2_h, buf2,
+                                   SVN__STREAM_CHUNK_SIZE, &bytes_read2,
+                                   &eof2, scratch_pool);
+          if (err)
+              break;
+          read_2 = TRUE;
+        }
+
+      if (!eof3 && (identical_p13 || identical_p23))
+        {
+          err = svn_io_file_read_full2(file3_h, buf3,
+                                   SVN__STREAM_CHUNK_SIZE, &bytes_read3,
+                                   &eof3, scratch_pool);
+          if (err)
+              break;
+          read_3 = TRUE;
+        }
+
+      /* If the files are still marked identical, and at least one of them
+       * is not at the end of file, we check whether they differ, and set
+       * their flag to false then. */
+      if (*identical_p12
+          && (read_1 || read_2)
+          && ((eof1 != eof2)
+              || (bytes_read1 != bytes_read2)
+              || memcmp(buf1, buf2, bytes_read1)))
+        {
+          *identical_p12 = FALSE;
+        }
+
+      if (*identical_p23
+          && (read_2 || read_3)
+          && ((eof2 != eof3)
+              || (bytes_read2 != bytes_read3)
+              || memcmp(buf2, buf3, bytes_read2)))
+        {
+          *identical_p23 = FALSE;
+        }
+
+      if (*identical_p13
+          && (read_1 || read_3)
+          && ((eof1 != eof3)
+              || (bytes_read1 != bytes_read3)
+              || memcmp(buf1, buf3, bytes_read3)))
+        {
+          *identical_p13 = FALSE;
+        }
+    }
+
+  return svn_error_trace(
+           svn_error_compose_create(
+                err,
+                svn_error_compose_create(
+                    svn_io_file_close(file1_h, scratch_pool),
+                    svn_error_compose_create(
+                        svn_io_file_close(file2_h, scratch_pool),
+                        svn_io_file_close(file3_h, scratch_pool)))));
+}
+
+
+
 svn_error_t *
 svn_io_files_contents_same_p(svn_boolean_t *same,
                              const char *file1,
@@ -4102,6 +4271,55 @@ svn_io_files_contents_same_p(svn_boolean
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_io_files_contents_three_same_p(svn_boolean_t *same12,
+                                   svn_boolean_t *same23,
+                                   svn_boolean_t *same13,
+                                   const char *file1,
+                                   const char *file2,
+                                   const char *file3,
+                                   apr_pool_t *scratch_pool)
+{
+  svn_boolean_t diff_size12, diff_size23, diff_size13;
+
+  SVN_ERR(svn_io_filesizes_three_different_p(&diff_size12,
+                                             &diff_size23,
+                                             &diff_size13,
+                                             file1,
+                                             file2,
+                                             file3,
+                                             scratch_pool));
+
+  if (diff_size12 && diff_size23 && diff_size13)
+    {
+      *same12 = *same23 = *same13 = FALSE;
+    }
+  else if (diff_size12 && diff_size23)
+    {
+      *same12 = *same23 = FALSE;
+      SVN_ERR(contents_identical_p(same13, file1, file3, scratch_pool));
+    }
+  else if (diff_size23 && diff_size13)
+    {
+      *same23 = *same13 = FALSE;
+      SVN_ERR(contents_identical_p(same12, file1, file2, scratch_pool));
+    }
+  else if (diff_size12 && diff_size13)
+    {
+      *same12 = *same13 = FALSE;
+      SVN_ERR(contents_identical_p(same23, file2, file3, scratch_pool));
+    }
+  else
+    {
+      SVN_ERR_ASSERT(!diff_size12 && !diff_size23 && !diff_size13);
+      SVN_ERR(contents_three_identical_p(same12, same23, same13,
+                                         file1, file2, file3,
+                                         scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 #ifdef WIN32
 /* Counter value of file_mktemp request (used in a threadsafe way), to make
    sure that a single process normally never generates the same tempname
@@ -4351,3 +4569,86 @@ svn_io_open_unique_file3(apr_file_t **fi
 
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_io_file_readline(apr_file_t *file,
+                     svn_stringbuf_t **stringbuf,
+                     const char **eol,
+                     svn_boolean_t *eof,
+                     apr_size_t max_len,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
+{
+  svn_stringbuf_t *str;
+  const char *eol_str;
+  apr_size_t numbytes;
+  char c;
+  apr_size_t len;
+  svn_boolean_t found_eof;
+
+  str = svn_stringbuf_create_ensure(80, result_pool);
+
+  /* Read bytes into STR up to and including, but not storing,
+   * the next EOL sequence. */
+  eol_str = NULL;
+  numbytes = 1;
+  len = 0;
+  found_eof = FALSE;
+  while (!found_eof)
+    {
+      if (len < max_len)
+        SVN_ERR(svn_io_file_read_full2(file, &c, sizeof(c), &numbytes,
+                                       &found_eof, scratch_pool));
+      len++;
+      if (numbytes != 1 || len > max_len)
+        {
+          found_eof = TRUE;
+          break;
+        }
+
+      if (c == '\n')
+        {
+          eol_str = "\n";
+        }
+      else if (c == '\r')
+        {
+          eol_str = "\r";
+
+          if (!found_eof && len < max_len)
+            {
+              apr_off_t pos;
+
+              /* Check for "\r\n" by peeking at the next byte. */
+              pos = 0;
+              SVN_ERR(svn_io_file_seek(file, APR_CUR, &pos, scratch_pool));
+              SVN_ERR(svn_io_file_read_full2(file, &c, sizeof(c), &numbytes,
+                                             &found_eof, scratch_pool));
+              if (numbytes == 1 && c == '\n')
+                {
+                  eol_str = "\r\n";
+                  len++;
+                }
+              else
+                {
+                  /* Pretend we never peeked. */
+                  SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, scratch_pool));
+                  found_eof = FALSE;
+                  numbytes = 1;
+                }
+            }
+        }
+      else
+        svn_stringbuf_appendbyte(str, c);
+
+      if (eol_str)
+        break;
+    }
+
+  if (eol)
+    *eol = eol_str;
+  if (eof)
+    *eof = found_eof;
+  *stringbuf = str;
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/path.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/path.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/path.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/path.c Sun Dec 23 06:03:14 2012
@@ -91,16 +91,33 @@ is_canonical(const char *path,
 #endif
 
 
-char *svn_path_join(const char *base,
-                    const char *component,
-                    apr_pool_t *pool)
+/* functionality of svn_path_is_canonical but without the deprecation */
+static svn_boolean_t
+svn_path_is_canonical_internal(const char *path, apr_pool_t *pool)
+{
+  return svn_uri_is_canonical(path, pool) ||
+      svn_dirent_is_canonical(path, pool) ||
+      svn_relpath_is_canonical(path);
+}
+
+svn_boolean_t
+svn_path_is_canonical(const char *path, apr_pool_t *pool)
+{
+  return svn_path_is_canonical_internal(path, pool);
+}
+
+/* functionality of svn_path_join but without the deprecation */
+static char *
+svn_path_join_internal(const char *base,
+                       const char *component,
+                       apr_pool_t *pool)
 {
   apr_size_t blen = strlen(base);
   apr_size_t clen = strlen(component);
   char *path;
 
-  assert(svn_path_is_canonical(base, pool));
-  assert(svn_path_is_canonical(component, pool));
+  assert(svn_path_is_canonical_internal(base, pool));
+  assert(svn_path_is_canonical_internal(component, pool));
 
   /* If the component is absolute, then return it.  */
   if (*component == '/')
@@ -124,6 +141,13 @@ char *svn_path_join(const char *base,
   return path;
 }
 
+char *svn_path_join(const char *base,
+                    const char *component,
+                    apr_pool_t *pool)
+{
+  return svn_path_join_internal(base, component, pool);
+}
+
 char *svn_path_join_many(apr_pool_t *pool, const char *base, ...)
 {
 #define MAX_SAVED_LENGTHS 10
@@ -140,7 +164,7 @@ char *svn_path_join_many(apr_pool_t *poo
 
   total_len = strlen(base);
 
-  assert(svn_path_is_canonical(base, pool));
+  assert(svn_path_is_canonical_internal(base, pool));
 
   if (total_len == 1 && *base == '/')
     base_is_root = TRUE;
@@ -160,7 +184,7 @@ char *svn_path_join_many(apr_pool_t *poo
     {
       len = strlen(s);
 
-      assert(svn_path_is_canonical(s, pool));
+      assert(svn_path_is_canonical_internal(s, pool));
 
       if (SVN_PATH_IS_EMPTY(s))
         continue;
@@ -353,7 +377,7 @@ svn_path_dirname(const char *path, apr_p
 {
   apr_size_t len = strlen(path);
 
-  assert(svn_path_is_canonical(path, pool));
+  assert(svn_path_is_canonical_internal(path, pool));
 
   return apr_pstrmemdup(pool, path, previous_segment(path, len));
 }
@@ -365,7 +389,7 @@ svn_path_basename(const char *path, apr_
   apr_size_t len = strlen(path);
   apr_size_t start;
 
-  assert(svn_path_is_canonical(path, pool));
+  assert(svn_path_is_canonical_internal(path, pool));
 
   if (len == 1 && path[0] == '/')
     start = 0;
@@ -593,7 +617,7 @@ svn_path_decompose(const char *path,
   apr_array_header_t *components =
     apr_array_make(pool, 1, sizeof(const char *));
 
-  assert(svn_path_is_canonical(path, pool));
+  assert(svn_path_is_canonical_internal(path, pool));
 
   if (SVN_PATH_IS_EMPTY(path))
     return components;  /* ### Should we return a "" component? */

Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/simple_providers.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/simple_providers.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/simple_providers.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/simple_providers.c Sun Dec 23 06:03:14 2012
@@ -202,9 +202,7 @@ svn_auth__simple_creds_cache_get(void **
             }
           else
             {
-              if (0 == strcmp(default_username, username))
-                need_to_save = FALSE;
-              else
+              if (strcmp(default_username, username) != 0)
                 need_to_save = TRUE;
             }
         }
@@ -226,9 +224,7 @@ svn_auth__simple_creds_cache_get(void **
                 }
               else
                 {
-                  if (0 == strcmp(default_password, password))
-                    need_to_save = FALSE;
-                  else
+                  if (strcmp(default_password, password) != 0)
                     need_to_save = TRUE;
                 }
             }

Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/skel.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/skel.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/skel.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/skel.c Sun Dec 23 06:03:14 2012
@@ -532,6 +532,33 @@ svn_skel__make_empty_list(apr_pool_t *po
   return skel;
 }
 
+svn_skel_t *svn_skel__dup(const svn_skel_t *src_skel, svn_boolean_t dup_data,
+                          apr_pool_t *result_pool)
+{
+  svn_skel_t *skel = apr_pmemdup(result_pool, src_skel, sizeof(svn_skel_t));
+
+  if (dup_data && skel->data)
+    {
+      if (skel->is_atom)
+        skel->data = apr_pmemdup(result_pool, skel->data, skel->len);
+      else
+        {
+          /* When creating a skel this would be NULL, 0 for a list.
+             When parsing a string to a skel this might point to real data
+             delimiting the sublist. We don't copy that from here. */
+          skel->data = NULL;
+          skel->len = 0;
+        }
+    }
+
+  if (skel->children)
+    skel->children = svn_skel__dup(skel->children, dup_data, result_pool);
+
+  if (skel->next)
+    skel->next = svn_skel__dup(skel->next, dup_data, result_pool);
+
+  return skel;
+}
 
 void
 svn_skel__prepend(svn_skel_t *skel, svn_skel_t *list_skel)

Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/adm_ops.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/adm_ops.c Sun Dec 23 06:03:14 2012
@@ -52,6 +52,7 @@
 
 #include "wc.h"
 #include "adm_files.h"
+#include "conflicts.h"
 #include "props.h"
 #include "translate.h"
 #include "workqueue.h"
@@ -127,8 +128,6 @@ process_committed_leaf(svn_wc__db_t *db,
   const svn_checksum_t *copied_checksum;
   svn_revnum_t new_changed_rev = new_revnum;
   svn_boolean_t have_base;
-  svn_boolean_t have_work;
-  svn_boolean_t had_props;
   svn_boolean_t prop_mods;
   svn_skel_t *work_item = NULL;
 
@@ -137,8 +136,8 @@ process_committed_leaf(svn_wc__db_t *db,
   SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, &copied_checksum,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, &had_props, &prop_mods,
-                               &have_base, NULL, &have_work,
+                               NULL, NULL, NULL, NULL, NULL, &prop_mods,
+                               &have_base, NULL, NULL,
                                db, local_abspath,
                                scratch_pool, scratch_pool));
 
@@ -156,10 +155,15 @@ process_committed_leaf(svn_wc__db_t *db,
     {
       return svn_error_trace(
                 svn_wc__db_op_remove_node(
+                                NULL,
                                 db, local_abspath,
+                                FALSE, FALSE,
                                 (have_base && !via_recurse)
                                     ? new_revnum : SVN_INVALID_REVNUM,
+                                svn_wc__db_status_not_present,
                                 kind,
+                                NULL, NULL,
+                                NULL, NULL,
                                 scratch_pool));
     }
   else if (status == svn_wc__db_status_not_present)
@@ -598,6 +602,72 @@ erase_unversioned_from_wc(const char *pa
   return SVN_NO_ERROR;
 }
 
+/* Helper for svn_wc__delete and svn_wc__delete_many */
+static svn_error_t *
+create_delete_wq_items(svn_skel_t **work_items,
+                       svn_wc__db_t *db,
+                       const char *local_abspath,
+                       svn_kind_t kind,
+                       svn_boolean_t conflicted,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
+{
+  *work_items = NULL;
+
+  /* Schedule the on-disk delete */
+  if (kind == svn_kind_dir)
+    SVN_ERR(svn_wc__wq_build_dir_remove(work_items, db, local_abspath,
+                                        local_abspath,
+                                        TRUE /* recursive */,
+                                        result_pool, scratch_pool));
+  else
+    SVN_ERR(svn_wc__wq_build_file_remove(work_items, db, local_abspath,
+                                         local_abspath,
+                                         result_pool, scratch_pool));
+
+  /* Read conflicts, to allow deleting the markers after updating the DB */
+  if (conflicted)
+    {
+      svn_skel_t *conflict;
+      const apr_array_header_t *markers;
+      int i;
+
+      SVN_ERR(svn_wc__db_read_conflict(&conflict, db, local_abspath,
+                                       scratch_pool, scratch_pool));
+
+      SVN_ERR(svn_wc__conflict_read_markers(&markers, db, local_abspath,
+                                            conflict,
+                                            scratch_pool, scratch_pool));
+
+      /* Maximum number of markers is 4, so no iterpool */
+      for (i = 0; markers && i < markers->nelts; i++)
+        {
+          const char *marker_abspath;
+          svn_node_kind_t marker_kind;
+
+          marker_abspath = APR_ARRAY_IDX(markers, i, const char *);
+          SVN_ERR(svn_io_check_path(marker_abspath, &marker_kind,
+                                    scratch_pool));
+
+          if (marker_kind == svn_node_file)
+            {
+              svn_skel_t *work_item;
+
+              SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+                                                   local_abspath,
+                                                   marker_abspath,
+                                                   scratch_pool,
+                                                   result_pool));
+
+              *work_items = svn_wc__wq_merge(*work_items, work_item,
+                                             result_pool);
+            }
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_wc__delete_many(svn_wc_context_t *wc_ctx,
                     const apr_array_header_t *targets,
@@ -613,7 +683,7 @@ svn_wc__delete_many(svn_wc_context_t *wc
   svn_error_t *err;
   svn_wc__db_status_t status;
   svn_kind_t kind;
-  const apr_array_header_t *conflicts = NULL;
+  svn_skel_t *work_items = NULL;
   apr_array_header_t *versioned_targets;
   const char *local_abspath;
   int i;
@@ -689,74 +759,39 @@ svn_wc__delete_many(svn_wc_context_t *wc
                                                          iterpool),
                                   iterpool));
 
-      /* Read conflicts, to allow deleting the markers after updating the DB */
-      if (!keep_local && conflicted)
-        SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, local_abspath,
-                                          scratch_pool, iterpool));
+      /* Prepare the on-disk delete */
+      if (!keep_local)
+        {
+          svn_skel_t *work_item;
 
+          SVN_ERR(create_delete_wq_items(&work_item, db, local_abspath, kind,
+                                         conflicted,
+                                         scratch_pool, iterpool));
+
+          work_items = svn_wc__wq_merge(work_items, work_item,
+                                        scratch_pool);
+        }
     }
 
   if (versioned_targets->nelts == 0)
     return SVN_NO_ERROR;
 
   SVN_ERR(svn_wc__db_op_delete_many(db, versioned_targets,
+                                    !keep_local /* delete_dir_externals */,
+                                    work_items,
                                     cancel_func, cancel_baton,
-                                    notify_func, notify_baton, scratch_pool));
-
-  if (!keep_local && conflicts != NULL)
-    {
-      svn_pool_clear(iterpool);
-
-      /* Do we have conflict markers that should be removed? */
-      for (i = 0; i < conflicts->nelts; i++)
-        {
-          const svn_wc_conflict_description2_t *desc;
-
-          desc = APR_ARRAY_IDX(conflicts, i,
-                               const svn_wc_conflict_description2_t*);
-
-          if (desc->kind == svn_wc_conflict_kind_text)
-            {
-              if (desc->base_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->base_abspath, TRUE,
-                                              iterpool));
-                }
-              if (desc->their_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
-                                              iterpool));
-                }
-              if (desc->my_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->my_abspath, TRUE,
-                                              iterpool));
-                }
-            }
-          else if (desc->kind == svn_wc_conflict_kind_property
-                   && desc->their_abspath != NULL)
-            {
-              SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
-                                          iterpool));
-            }
-        }
-    }
+                                    notify_func, notify_baton,
+                                    iterpool));
 
-  /* By the time we get here, the db knows that all targets are now
-   * unversioned. */
-  if (!keep_local)
+  if (work_items != NULL)
     {
-      for (i = 0; i < versioned_targets->nelts; i++)
-        {
-          svn_pool_clear(iterpool);
+      /* Our only caller locked the wc, so for now assume it only passed
+         nodes from a single wc (asserted in svn_wc__db_op_delete_many) */
+      local_abspath = APR_ARRAY_IDX(versioned_targets, 0, const char *);
 
-          local_abspath = APR_ARRAY_IDX(versioned_targets, i, const char *);
-          SVN_ERR(erase_unversioned_from_wc(local_abspath, TRUE,
-                                            cancel_func, cancel_baton,
-                                            iterpool));
-        }
+      SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+                             iterpool));
     }
-
   svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
@@ -780,7 +815,7 @@ svn_wc__delete_internal(svn_wc_context_t
   svn_wc__db_status_t status;
   svn_kind_t kind;
   svn_boolean_t conflicted;
-  const apr_array_header_t *conflicts;
+  svn_skel_t *work_items = NULL;
 
   err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
                              NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -834,63 +869,24 @@ svn_wc__delete_internal(svn_wc_context_t
   SVN_ERR(svn_wc__write_check(db, svn_dirent_dirname(local_abspath, pool),
                               pool));
 
-  /* Read conflicts, to allow deleting the markers after updating the DB */
-  if (!keep_local && conflicted)
-    SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, local_abspath,
-                                      scratch_pool, scratch_pool));
+  /* Prepare the on-disk delete */
+      if (!keep_local)
+        {
+          SVN_ERR(create_delete_wq_items(&work_items, db, local_abspath, kind,
+                                         conflicted,
+                                         scratch_pool, scratch_pool));
+        }
 
   SVN_ERR(svn_wc__db_op_delete(db, local_abspath, moved_to_abspath,
-                               notify_func, notify_baton,
+                               !keep_local /* delete_dir_externals */,
+                               NULL, work_items,
                                cancel_func, cancel_baton,
+                               notify_func, notify_baton,
                                pool));
 
-  if (!keep_local && conflicted && conflicts != NULL)
-    {
-      int i;
-
-      /* Do we have conflict markers that should be removed? */
-      for (i = 0; i < conflicts->nelts; i++)
-        {
-          const svn_wc_conflict_description2_t *desc;
-
-          desc = APR_ARRAY_IDX(conflicts, i,
-                               const svn_wc_conflict_description2_t*);
-
-          if (desc->kind == svn_wc_conflict_kind_text)
-            {
-              if (desc->base_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->base_abspath, TRUE,
-                                              scratch_pool));
-                }
-              if (desc->their_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
-                                              scratch_pool));
-                }
-              if (desc->my_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->my_abspath, TRUE,
-                                              scratch_pool));
-                }
-            }
-          else if (desc->kind == svn_wc_conflict_kind_property
-                   && desc->their_abspath != NULL)
-            {
-              SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
-                                          scratch_pool));
-            }
-        }
-    }
-
-  /* By the time we get here, the db knows that everything that is still at
-     LOCAL_ABSPATH is unversioned. */
-  if (!keep_local)
-    {
-        SVN_ERR(erase_unversioned_from_wc(local_abspath, TRUE,
-                                          cancel_func, cancel_baton,
-                                          pool));
-    }
+  if (work_items)
+    SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+                           scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1609,10 +1605,7 @@ revert_restore(svn_wc__db_t *db,
   svn_kind_t kind;
   svn_node_kind_t on_disk;
   svn_boolean_t notify_required;
-  const char *conflict_old;
-  const char *conflict_new;
-  const char *conflict_working;
-  const char *prop_reject;
+  const apr_array_header_t *conflict_files;
   svn_filesize_t recorded_size;
   apr_time_t recorded_mod_time;
   apr_finfo_t finfo;
@@ -1626,8 +1619,7 @@ revert_restore(svn_wc__db_t *db,
     SVN_ERR(cancel_func(cancel_baton));
 
   SVN_ERR(svn_wc__db_revert_list_read(&notify_required,
-                                      &conflict_old, &conflict_new,
-                                      &conflict_working, &prop_reject,
+                                      &conflict_files,
                                       &copied_here, &reverted_kind,
                                       db, local_abspath,
                                       scratch_pool, scratch_pool));
@@ -1894,14 +1886,17 @@ revert_restore(svn_wc__db_t *db,
       notify_required = TRUE;
     }
 
-  SVN_ERR(remove_conflict_file(&notify_required, conflict_old,
-                               local_abspath, scratch_pool));
-  SVN_ERR(remove_conflict_file(&notify_required, conflict_new,
-                               local_abspath, scratch_pool));
-  SVN_ERR(remove_conflict_file(&notify_required, conflict_working,
-                               local_abspath, scratch_pool));
-  SVN_ERR(remove_conflict_file(&notify_required, prop_reject,
-                               local_abspath, scratch_pool));
+  if (conflict_files)
+    {
+      int i;
+      for (i = 0; i < conflict_files->nelts; i++)
+        {
+          SVN_ERR(remove_conflict_file(&notify_required,
+                                       APR_ARRAY_IDX(conflict_files, i,
+                                                     const char *),
+                                       local_abspath, scratch_pool));
+        }
+    }
 
   if (notify_func && notify_required)
     notify_func(notify_baton,
@@ -2127,7 +2122,7 @@ revert_partial(svn_wc__db_t *db,
         {
           svn_kind_t kind;
 
-          SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath,
+          SVN_ERR(svn_wc__db_read_kind(&kind, db, child_abspath,
                                        FALSE /* allow_missing */,
                                        FALSE /* show_hidden */,
                                        iterpool));
@@ -2330,214 +2325,68 @@ svn_error_t *
 svn_wc__internal_remove_from_revision_control(svn_wc__db_t *db,
                                               const char *local_abspath,
                                               svn_boolean_t destroy_wf,
-                                              svn_boolean_t instant_error,
                                               svn_cancel_func_t cancel_func,
                                               void *cancel_baton,
                                               apr_pool_t *scratch_pool)
 {
-  svn_error_t *err;
   svn_boolean_t left_something = FALSE;
-  svn_wc__db_status_t status;
-  svn_kind_t kind;
-
-  /* ### This whole function should be rewritten to run inside a transaction,
-     ### to allow a stable cancel behavior.
-     ###
-     ### Subversion < 1.7 marked the directory as incomplete to allow updating
-     ### it from a canceled state. But this would not work because update
-     ### doesn't retrieve deleted items.
-     ###
-     ### WC-NG doesn't support a delete+incomplete state, but we can't build
-     ### transactions over multiple databases yet. */
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  /* Check cancellation here, so recursive calls get checked early. */
-  if (cancel_func)
-    SVN_ERR(cancel_func(cancel_baton));
-
-  SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL,
-                               db, local_abspath, scratch_pool, scratch_pool));
+  svn_boolean_t is_root;
+  svn_error_t *err = NULL;
 
-  if (kind == svn_kind_file || kind == svn_kind_symlink)
-    {
-      svn_boolean_t text_modified_p = FALSE;
+  SVN_ERR(svn_wc__db_is_wcroot(&is_root, db, local_abspath, scratch_pool));
 
-      if (instant_error || destroy_wf)
-        {
-          svn_node_kind_t on_disk;
-          SVN_ERR(svn_io_check_path(local_abspath, &on_disk, scratch_pool));
-          if (on_disk == svn_node_file)
-            {
-              /* Check for local mods. before removing entry */
-              SVN_ERR(svn_wc__internal_file_modified_p(&text_modified_p, db,
-                                                       local_abspath, FALSE,
-                                                       scratch_pool));
-              if (text_modified_p && instant_error)
-                return svn_error_createf(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL,
-                       _("File '%s' has local modifications"),
-                       svn_dirent_local_style(local_abspath, scratch_pool));
-            }
-        }
+  SVN_ERR(svn_wc__db_op_remove_node(&left_something,
+                                    db, local_abspath,
+                                    destroy_wf /* destroy_wc */,
+                                    destroy_wf /* destroy_changes */,
+                                    SVN_INVALID_REVNUM,
+                                    svn_wc__db_status_not_present,
+                                    svn_kind_none,
+                                    NULL, NULL,
+                                    cancel_func, cancel_baton,
+                                    scratch_pool));
 
-      /* Remove NAME from DB */
-      SVN_ERR(svn_wc__db_op_remove_node(db, local_abspath,
-                                        SVN_INVALID_REVNUM,
-                                        svn_kind_unknown,
-                                        scratch_pool));
-
-      /* If we were asked to destroy the working file, do so unless
-         it has local mods. */
-      if (destroy_wf)
-        {
-          /* Don't kill local mods. */
-          if (text_modified_p)
-            return svn_error_create(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL, NULL);
-          else  /* The working file is still present; remove it. */
-            SVN_ERR(svn_io_remove_file2(local_abspath, TRUE, scratch_pool));
-        }
+  SVN_ERR(svn_wc__wq_run(db, local_abspath,
+                         cancel_func, cancel_baton,
+                         scratch_pool));
 
-    }  /* done with file case */
-  else /* looking at THIS_DIR */
+  if (is_root)
     {
-      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-      const apr_array_header_t *children;
-      int i;
-
-      /* ### sanity check:  check 2 places for DELETED flag? */
-
-      /* Walk over every entry. */
-      SVN_ERR(svn_wc__db_read_children(&children, db, local_abspath,
-                                       scratch_pool, iterpool));
-
-      for (i = 0; i < children->nelts; i++)
-        {
-          const char *node_name = APR_ARRAY_IDX(children, i, const char*);
-          const char *node_abspath;
-          svn_wc__db_status_t node_status;
-          svn_kind_t node_kind;
-
-          svn_pool_clear(iterpool);
-
-          node_abspath = svn_dirent_join(local_abspath, node_name, iterpool);
-
-          SVN_ERR(svn_wc__db_read_info(&node_status, &node_kind, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL,
-                                       db, node_abspath,
-                                       iterpool, iterpool));
-
-          if (node_status == svn_wc__db_status_normal
-              && node_kind == svn_kind_dir)
-            {
-              svn_boolean_t is_root;
-
-              SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, NULL,
-                                            db, node_abspath, iterpool));
-
-              if (is_root)
-                continue; /* Just skip working copies as obstruction */
-            }
-
-          if (node_status != svn_wc__db_status_normal
-              && node_status != svn_wc__db_status_added
-              && node_status != svn_wc__db_status_incomplete)
-            {
-              /* The node is already 'deleted', so nothing to do on
-                 versioned nodes */
-              SVN_ERR(svn_wc__db_op_remove_node(db, node_abspath,
-                                                SVN_INVALID_REVNUM,
-                                                svn_kind_unknown,
-                                                iterpool));
-
-              continue;
-            }
-
-          err = svn_wc__internal_remove_from_revision_control(
-                            db, node_abspath,
-                            destroy_wf, instant_error,
-                            cancel_func, cancel_baton,
-                            iterpool);
-
-          if (err && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
-            {
-              if (instant_error)
-                return svn_error_trace(err);
-              else
-                {
-                  svn_error_clear(err);
-                  left_something = TRUE;
-                }
-            }
-          else if (err)
-            return svn_error_trace(err);
-        }
-
-      /* At this point, every directory below this one has been
-         removed from revision control. */
-
-      /* Remove self from parent's entries file, but only if parent is
-         a working copy.  If it's not, that's fine, we just move on. */
-      {
-        svn_boolean_t is_root;
-
-        SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, NULL,
-                                      db, local_abspath, iterpool));
-
-        /* If full_path is not the top of a wc, then its parent
-           directory is also a working copy and has an entry for
-           full_path.  We need to remove that entry: */
-        if (! is_root)
-          {
-            SVN_ERR(svn_wc__db_op_remove_node(db, local_abspath,
-                                              SVN_INVALID_REVNUM,
-                                              svn_kind_unknown,
-                                              iterpool));
-          }
-        else
-          {
-            /* Remove the entire administrative .svn area, thereby removing
-               _this_ dir from revision control too.  */
-            SVN_ERR(svn_wc__adm_destroy(db, local_abspath,
-                                        cancel_func, cancel_baton, iterpool));
-          }
-      }
-
-      /* If caller wants us to recursively nuke everything on disk, go
-         ahead, provided that there are no dangling local-mod files
-         below */
-      if (destroy_wf && (! left_something))
-        {
-          /* If the dir is *truly* empty (i.e. has no unversioned
-             resources, all versioned files are gone, all .svn dirs are
-             gone, and contains nothing but empty dirs), then a
-             *non*-recursive dir_remove should work.  If it doesn't,
-             no big deal.  Just assume there are unversioned items in
-             there and set "left_something" */
-          err = svn_io_dir_remove_nonrecursive(local_abspath, iterpool);
-          if (err)
-            {
-              if (!APR_STATUS_IS_ENOENT(err->apr_err))
-                left_something = TRUE;
-              svn_error_clear(err);
-            }
-        }
-
-      svn_pool_destroy(iterpool);
+      /* Destroy the administrative area */
+      SVN_ERR(svn_wc__adm_destroy(db, local_abspath, cancel_func, cancel_baton,
+                                  scratch_pool));
 
-    }  /* end of directory case */
+      /* And if we didn't leave something interesting, remove the directory */
+      if (!left_something && destroy_wf)
+        err = svn_io_dir_remove_nonrecursive(local_abspath, scratch_pool);
+    }
 
-  if (left_something)
-    return svn_error_create(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL, NULL);
+  if (left_something || err)
+    return svn_error_create(SVN_ERR_WC_LEFT_LOCAL_MOD, err, NULL);
 
   return SVN_NO_ERROR;
 }
 
+/* Implements svn_wc_status_func4_t for svn_wc_remove_from_revision_control2 */
+static svn_error_t *
+remove_from_revision_status_callback(void *baton,
+                                     const char *local_abspath,
+                                     const svn_wc_status3_t *status,
+                                     apr_pool_t *scratch_pool)
+{
+  /* For legacy reasons we only check the file contents for changes */
+  if (status->versioned
+      && status->kind == svn_node_file
+      && (status->text_status == svn_wc_status_modified
+          || status->text_status == svn_wc_status_conflicted))
+    {
+      return svn_error_createf(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL,
+                               _("File '%s' has local modifications"),
+                               svn_dirent_local_style(local_abspath,
+                                                      scratch_pool));
+    }
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_wc_remove_from_revision_control2(svn_wc_context_t *wc_ctx,
@@ -2548,11 +2397,18 @@ svn_wc_remove_from_revision_control2(svn
                                     void *cancel_baton,
                                     apr_pool_t *scratch_pool)
 {
+  if (instant_error)
+    {
+      SVN_ERR(svn_wc_walk_status(wc_ctx, local_abspath, svn_depth_infinity,
+                                 FALSE, FALSE, FALSE, NULL,
+                                 remove_from_revision_status_callback, NULL,
+                                 cancel_func, cancel_baton,
+                                 scratch_pool));
+    }
   return svn_error_trace(
       svn_wc__internal_remove_from_revision_control(wc_ctx->db,
                                                     local_abspath,
                                                     destroy_wf,
-                                                    instant_error,
                                                     cancel_func,
                                                     cancel_baton,
                                                     scratch_pool));

Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/conflicts.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/conflicts.c Sun Dec 23 06:03:14 2012
@@ -136,7 +136,7 @@ conflict__prepend_location(svn_skel_t *s
 /* Deserialize a svn_wc_conflict_version_t from the skel.
    Set *LOCATION to NULL when the data is not a svn_wc_conflict_version_t. */
 static svn_error_t *
-conflict__read_location(const svn_wc_conflict_version_t **location,
+conflict__read_location(svn_wc_conflict_version_t **location,
                         const svn_skel_t *skel,
                         apr_pool_t *result_pool,
                         apr_pool_t *scratch_pool)
@@ -311,14 +311,12 @@ conflict__get_conflict(svn_skel_t **conf
                        const char *conflict_type)
 {
   svn_skel_t *c;
-  apr_size_t len;
+
   SVN_ERR_ASSERT(conflict_skel
                  && conflict_skel->children
                  && conflict_skel->children->next
                  && !conflict_skel->children->next->is_atom);
 
-  len = strlen(conflict_type);
-
   for(c = conflict_skel->children->next->children;
       c;
       c = c->next)
@@ -568,6 +566,91 @@ svn_wc__conflict_skel_add_tree_conflict(
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_wc__conflict_skel_resolve(svn_boolean_t *completely_resolved,
+                              svn_skel_t *conflict_skel,
+                              svn_wc__db_t *db,
+                              const char *wri_abspath,
+                              svn_boolean_t resolve_text,
+                              const char *resolve_prop,
+                              svn_boolean_t resolve_tree,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool)
+{
+  svn_skel_t *op;
+  svn_skel_t **pconflict;
+  SVN_ERR(conflict__get_operation(&op, conflict_skel));
+
+  if (!op)
+    return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,
+                            _("Not a completed conflict skel"));
+
+  /* We are going to drop items from a linked list. Instead of keeping
+     a pointer to the item we want to drop we store a pointer to the
+     pointer of what we may drop, to allow setting it to the next item. */
+
+  pconflict = &(conflict_skel->children->next->children);
+  while (*pconflict)
+    {
+      svn_skel_t *c = (*pconflict)->children;
+
+      if (resolve_text
+          && svn_skel__matches_atom(c, SVN_WC__CONFLICT_KIND_TEXT))
+        {
+          /* Remove the text conflict from the linked list */
+          *pconflict = (*pconflict)->next;
+          continue;
+        }
+      else if (resolve_prop
+               && svn_skel__matches_atom(c, SVN_WC__CONFLICT_KIND_PROP))
+        {
+          svn_skel_t **ppropnames = &(c->next->next->children);
+
+          if (resolve_prop[0] == '\0')
+            *ppropnames = NULL; /* remove all conflicted property names */
+          else
+            while (*ppropnames)
+              {
+                if (svn_skel__matches_atom(*ppropnames, resolve_prop))
+                  {
+                    *ppropnames = (*ppropnames)->next;
+                    break;
+                  }
+                ppropnames = &((*ppropnames)->next);
+              }
+
+          /* If no conflicted property names left */
+          if (!c->next->next->children)
+            {
+              /* Remove the propery conflict skel from the linked list */
+             *pconflict = (*pconflict)->next;
+             continue;
+            }
+        }
+      else if (resolve_tree
+               && svn_skel__matches_atom(c, SVN_WC__CONFLICT_KIND_TREE))
+        {
+          /* Remove the tree conflict from the linked list */
+          *pconflict = (*pconflict)->next;
+          continue;
+        }
+
+      pconflict = &((*pconflict)->next);
+    }
+
+  if (completely_resolved)
+    {
+      /* Nice, we can just call the complete function */
+      svn_boolean_t complete_conflict;
+      SVN_ERR(svn_wc__conflict_skel_is_complete(&complete_conflict,
+                                                conflict_skel));
+
+      *completely_resolved = !complete_conflict;
+    }
+  return SVN_NO_ERROR;
+}
+
+
 /* A map for svn_wc_operation_t values. */
 static const svn_token_map_t operation_map[] =
 {
@@ -872,6 +955,51 @@ svn_wc__conflict_read_tree_conflict(svn_
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_wc__conflict_read_markers(const apr_array_header_t **markers,
+                              svn_wc__db_t *db,
+                              const char *wri_abspath,
+                              const svn_skel_t *conflict_skel,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool)
+{
+  const svn_skel_t *conflict;
+  apr_array_header_t *list = NULL;
+
+  SVN_ERR_ASSERT(conflict_skel != NULL);
+
+  /* Walk the conflicts */
+  for (conflict = conflict_skel->children->next->children;
+       conflict;
+       conflict = conflict->next)
+    {
+      const svn_skel_t *marker;
+
+      /* Get the list of markers stored per conflict */
+      for (marker = conflict->children->next->children;
+           marker;
+           marker = marker->next)
+        {
+          /* Skip placeholders */
+          if (! marker->is_atom)
+            continue;
+
+          if (! list)
+            list = apr_array_make(result_pool, 4, sizeof(const char *));
+
+          SVN_ERR(svn_wc__db_from_relpath(
+                        &APR_ARRAY_PUSH(list, const char*),
+                        db, wri_abspath,
+                        apr_pstrmemdup(scratch_pool, marker->data,
+                                       marker->len),
+                        result_pool, scratch_pool));
+        }
+    }
+  *markers = list;
+
+  return SVN_NO_ERROR;
+}
+
 /* --------------------------------------------------------------------
  */
 /* Helper for svn_wc__conflict_create_markers */
@@ -957,6 +1085,12 @@ svn_wc__conflict_create_markers(svn_skel
 
   if (prop_conflicted)
     {
+      const char *marker_abspath = NULL;
+      svn_node_kind_t kind;
+      const char *marker_dir;
+      const char *marker_name;
+      const char *marker_relpath;
+
       /* Ok, currently we have to do a few things for property conflicts:
          - Create a marker file
          - Create a WQ item that sets the marker name
@@ -964,41 +1098,23 @@ svn_wc__conflict_create_markers(svn_skel
 
          This can be simplified once we really store conflict_skel in wc.db */
 
-      const char *marker_abspath;
-      const char *marker_relpath;
-
-      /* ### as the legacy code, check if we already have a prejfile.
-
-         ### Triggered by merge_tests.py 90 on a double property merge.
-         ### Needs further review as we will probably loose the original
-         ### conflict by overwriting. (Legacy issue)  */
-      SVN_ERR(svn_wc__get_prejfile_abspath(&marker_abspath, db, local_abspath,
-                                           scratch_pool, scratch_pool));
+      SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
 
-      if (! marker_abspath)
+      if (kind == svn_node_dir)
         {
-          svn_node_kind_t kind;
-          const char *marker_dir;
-          const char *marker_name;
-
-          SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
-
-          if (kind == svn_node_dir)
-            {
-              marker_dir = local_abspath;
-              marker_name = SVN_WC__THIS_DIR_PREJ;
-            }
-          else
-            svn_dirent_split(&marker_dir, &marker_name, local_abspath,
-                             scratch_pool);
-
-          SVN_ERR(svn_io_open_uniquely_named(NULL, &marker_abspath,
-                                             marker_dir,
-                                             marker_name,
-                                             SVN_WC__PROP_REJ_EXT,
-                                             svn_io_file_del_none,
-                                             scratch_pool, scratch_pool));
+          marker_dir = local_abspath;
+          marker_name = SVN_WC__THIS_DIR_PREJ;
         }
+      else
+        svn_dirent_split(&marker_dir, &marker_name, local_abspath,
+                         scratch_pool);
+
+      SVN_ERR(svn_io_open_uniquely_named(NULL, &marker_abspath,
+                                         marker_dir,
+                                         marker_name,
+                                         SVN_WC__PROP_REJ_EXT,
+                                         svn_io_file_del_none,
+                                         scratch_pool, scratch_pool));
 
       SVN_ERR(svn_wc__db_to_relpath(&marker_relpath, db, local_abspath,
                                     marker_abspath, result_pool, result_pool));
@@ -1491,7 +1607,7 @@ eval_text_conflict_func_result(svn_skel_
     if (remove_source)
       {
         SVN_ERR(svn_wc__wq_build_file_remove(&work_item,
-                                             db, install_from,
+                                             db, local_abspath, install_from,
                                              result_pool, scratch_pool));
         *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
       }
@@ -1787,12 +1903,180 @@ svn_wc__conflict_invoke_resolver(svn_wc_
         {
           SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, TRUE, FALSE,
                                               FALSE, work_item, scratch_pool));
+          SVN_ERR(svn_wc__wq_run(db, local_abspath, NULL, NULL, scratch_pool));
         }
     }
 
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_wc__read_conflicts(const apr_array_header_t **conflicts,
+                       svn_wc__db_t *db,
+                       const char *local_abspath,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
+{
+  svn_skel_t *conflict_skel;
+  apr_array_header_t *cflcts;
+  svn_boolean_t prop_conflicted;
+  svn_boolean_t text_conflicted;
+  svn_boolean_t tree_conflicted;
+  svn_wc_operation_t operation;
+  const apr_array_header_t *locations;
+
+  SVN_ERR(svn_wc__db_read_conflict(&conflict_skel, db, local_abspath,
+                                   scratch_pool, scratch_pool));
+
+  if (!conflict_skel)
+    {
+      /* Some callers expect not NULL */
+      *conflicts = apr_array_make(result_pool, 0,
+                                  sizeof(svn_wc_conflict_description2_t*));;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(svn_wc__conflict_read_info(&operation, &locations, &text_conflicted,
+                                     &prop_conflicted, &tree_conflicted,
+                                     db, local_abspath, conflict_skel,
+                                     scratch_pool, scratch_pool));
+
+  cflcts = apr_array_make(result_pool, 4,
+                          sizeof(svn_wc_conflict_description2_t*));
+
+  if (prop_conflicted)
+    {
+      svn_wc_conflict_description2_t *desc;
+      desc  = svn_wc_conflict_description_create_prop2(local_abspath,
+                                                       svn_node_unknown,
+                                                       "",
+                                                       result_pool);
+
+      SVN_ERR(svn_wc__conflict_read_prop_conflict(&desc->their_abspath,
+                                                  NULL, NULL,  NULL, NULL,
+                                                  db, local_abspath,
+                                                  conflict_skel,
+                                                  result_pool, scratch_pool));
+
+      APR_ARRAY_PUSH(cflcts, svn_wc_conflict_description2_t*) = desc;
+    }
+
+  if (text_conflicted)
+    {
+      svn_wc_conflict_description2_t *desc;
+      desc  = svn_wc_conflict_description_create_text2(local_abspath,
+                                                       result_pool);
+
+      SVN_ERR(svn_wc__conflict_read_text_conflict(&desc->my_abspath,
+                                                  &desc->base_abspath,
+                                                  &desc->their_abspath,
+                                                  db, local_abspath,
+                                                  conflict_skel,
+                                                  result_pool, scratch_pool));
+
+      desc->merged_file = apr_pstrdup(result_pool, local_abspath);
+
+      APR_ARRAY_PUSH(cflcts, svn_wc_conflict_description2_t*) = desc;
+    }
+
+  if (tree_conflicted)
+    {
+      svn_wc_conflict_description2_t *desc;
+      svn_wc_conflict_version_t *v1;
+      svn_wc_conflict_version_t *v2;
+      svn_node_kind_t tc_kind;
+      svn_wc_conflict_reason_t local_change;
+      svn_wc_conflict_action_t incoming_change;
+
+      SVN_ERR(svn_wc__conflict_read_tree_conflict(&local_change,
+                                                  &incoming_change,
+                                                  db, local_abspath,
+                                                  conflict_skel,
+                                                  scratch_pool, scratch_pool));
+
+      v1 = (locations && locations->nelts > 0)
+                    ? APR_ARRAY_IDX(locations, 0, svn_wc_conflict_version_t *)
+                    : NULL;
+
+      v2 = (locations && locations->nelts > 1)
+                    ? APR_ARRAY_IDX(locations, 1, svn_wc_conflict_version_t *)
+                    : NULL;
+
+      if (incoming_change != svn_wc_conflict_action_delete
+          && (operation == svn_wc_operation_update
+              || operation == svn_wc_operation_switch))
+        {
+          svn_wc__db_status_t status;
+          svn_revnum_t revision;
+          const char *repos_relpath;
+          const char *repos_root_url;
+          const char *repos_uuid;
+          svn_kind_t kind;
+          svn_error_t *err;
+
+          /* ### Theoretically we should just fetch the BASE information
+                 here. This code might need tweaks until all tree conflicts
+                 are installed in the proper state */
+
+          SVN_ERR_ASSERT(v2 == NULL); /* Not set for update and switch */
+
+          /* With an update or switch we have to fetch the second location
+             for a tree conflict from WORKING. (For text or prop from BASE)
+           */
+          err = svn_wc__db_base_get_info(&status, &kind, &revision,
+                                         &repos_relpath, &repos_root_url,
+                                         &repos_uuid, NULL, NULL, NULL,
+                                         NULL, NULL, NULL, NULL, NULL, NULL,
+                                         db, local_abspath,
+                                         scratch_pool, scratch_pool);
+
+          if (err)
+            {
+              if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+                return svn_error_trace(err);
+
+              svn_error_clear(err);
+              /* Ignore BASE */
+
+              tc_kind = svn_node_file; /* Avoid assertion */
+            }
+          else if (repos_relpath)
+            {
+              v2 = svn_wc_conflict_version_create2(repos_root_url,
+                                                   repos_uuid,
+                                                   repos_relpath,
+                                                   revision,
+                                            svn__node_kind_from_kind(kind),
+                                                   scratch_pool);
+              tc_kind = svn__node_kind_from_kind(kind);
+            }
+          else
+            tc_kind = svn_node_file; /* Avoid assertion */
+        }
+      else
+        {
+          if (v1)
+            tc_kind = v1->node_kind;
+          else if (v2)
+            tc_kind = v2->node_kind;
+          else
+            tc_kind = svn_node_file; /* Avoid assertion */
+        }
+
+      desc  = svn_wc_conflict_description_create_tree2(local_abspath, tc_kind,
+                                                       operation, v1, v2,
+                                                       result_pool);
+
+      desc->reason = local_change;
+      desc->action = incoming_change;
+
+      APR_ARRAY_PUSH(cflcts, const svn_wc_conflict_description2_t *) = desc;
+    }
+
+  *conflicts = cflcts;
+  return SVN_NO_ERROR;
+}
+
 
 /*** Resolving a conflict automatically ***/
 
@@ -1820,42 +2104,42 @@ resolve_conflict_on_node(svn_boolean_t *
                          svn_wc_conflict_choice_t conflict_choice,
                          svn_cancel_func_t cancel_func_t,
                          void *cancel_baton,
-                         apr_pool_t *pool)
+                         apr_pool_t *scratch_pool)
 {
-  const char *conflict_old = NULL;
-  const char *conflict_new = NULL;
-  const char *conflict_working = NULL;
-  const char *prop_reject_file = NULL;
-  int i;
-  const apr_array_header_t *conflicts;
+  svn_skel_t *conflicts;
+  svn_boolean_t text_conflicted;
+  svn_boolean_t prop_conflicted;
+  svn_boolean_t tree_conflicted;
   svn_skel_t *work_items = NULL;
   svn_skel_t *work_item;
+  apr_pool_t *pool = scratch_pool;
 
   *did_resolve = FALSE;
 
-  SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, local_abspath,
-                                    pool, pool));
+  SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath,
+                                   scratch_pool, scratch_pool));
 
-  for (i = 0; i < conflicts->nelts; i++)
-    {
-      const svn_wc_conflict_description2_t *desc;
-
-      desc = APR_ARRAY_IDX(conflicts, i,
-                           const svn_wc_conflict_description2_t*);
+  if (!conflicts)
+    return SVN_NO_ERROR;
 
-      if (desc->kind == svn_wc_conflict_kind_text)
-        {
-          conflict_old = desc->base_abspath;
-          conflict_new = desc->their_abspath;
-          conflict_working = desc->my_abspath;
-        }
-      else if (desc->kind == svn_wc_conflict_kind_property)
-        prop_reject_file = desc->their_abspath;
-    }
+  SVN_ERR(svn_wc__conflict_read_info(NULL, NULL, &text_conflicted,
+                                     &prop_conflicted, &tree_conflicted,
+                                     db, local_abspath, conflicts,
+                                     scratch_pool, scratch_pool));
 
-  if (resolve_text)
+  if (resolve_text && text_conflicted)
     {
+      const char *conflict_old = NULL;
+      const char *conflict_new = NULL;
+      const char *conflict_working = NULL;
       const char *auto_resolve_src;
+      svn_node_kind_t node_kind;
+
+      SVN_ERR(svn_wc__conflict_read_text_conflict(&conflict_working,
+                                                  &conflict_old,
+                                                  &conflict_new,
+                                                  db, local_abspath, conflicts,
+                                                  scratch_pool, scratch_pool));
 
       /* Handle automatic conflict resolution before the temporary files are
        * deleted, if necessary. */
@@ -1927,11 +2211,6 @@ resolve_conflict_on_node(svn_boolean_t *
                     auto_resolve_src, local_abspath, pool, pool));
           work_items = svn_wc__wq_merge(work_items, work_item, pool);
         }
-    }
-
-  if (resolve_text)
-    {
-      svn_node_kind_t node_kind;
 
       /* Legacy behavior: Only report text conflicts as resolved when at least
          one conflict marker file exists.
@@ -1945,6 +2224,7 @@ resolve_conflict_on_node(svn_boolean_t *
           if (node_kind == svn_node_file)
             {
               SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+                                                   local_abspath,
                                                    conflict_old,
                                                    pool, pool));
               work_items = svn_wc__wq_merge(work_items, work_item, pool);
@@ -1958,6 +2238,7 @@ resolve_conflict_on_node(svn_boolean_t *
           if (node_kind == svn_node_file)
             {
               SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+                                                   local_abspath,
                                                    conflict_new,
                                                    pool, pool));
               work_items = svn_wc__wq_merge(work_items, work_item, pool);
@@ -1971,6 +2252,7 @@ resolve_conflict_on_node(svn_boolean_t *
           if (node_kind == svn_node_file)
             {
               SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+                                                   local_abspath,
                                                    conflict_working,
                                                    pool, pool));
               work_items = svn_wc__wq_merge(work_items, work_item, pool);
@@ -1978,9 +2260,16 @@ resolve_conflict_on_node(svn_boolean_t *
             }
         }
     }
-  if (resolve_props)
+
+  if (resolve_props && prop_conflicted)
     {
       svn_node_kind_t node_kind;
+      const char *prop_reject_file;
+
+      SVN_ERR(svn_wc__conflict_read_prop_conflict(&prop_reject_file,
+                                                  NULL, NULL, NULL, NULL,
+                                                  db, local_abspath, conflicts,
+                                                  scratch_pool, scratch_pool));
 
       /* Legacy behavior: Only report property conflicts as resolved when the
          property reject file exists
@@ -1994,6 +2283,7 @@ resolve_conflict_on_node(svn_boolean_t *
           if (node_kind == svn_node_file)
             {
               SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+                                                   local_abspath,
                                                    prop_reject_file,
                                                    pool, pool));
               work_items = svn_wc__wq_merge(work_items, work_item, pool);
@@ -2075,8 +2365,8 @@ conflict_status_walker(void *baton,
 
   iterpool = svn_pool_create(scratch_pool);
 
-  SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, local_abspath,
-                                    scratch_pool, iterpool));
+  SVN_ERR(svn_wc__read_conflicts(&conflicts, db, local_abspath,
+                                 scratch_pool, iterpool));
 
   for (i = 0; i < conflicts->nelts; i++)
     {

Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/conflicts.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/conflicts.h?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/conflicts.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/conflicts.h Sun Dec 23 06:03:14 2012
@@ -212,6 +212,42 @@ svn_wc__conflict_skel_add_tree_conflict(
                                         apr_pool_t *result_pool,
                                         apr_pool_t *scratch_pool);
 
+/* Allows resolving specific conflicts stored in CONFLICT_SKEL.
+
+   When RESOLVE_TEXT is TRUE and CONFLICT_SKEL contains a text conflict,
+   resolve/remove the text conflict in CONFLICT_SKEL.
+
+   When RESOLVE_PROP is "" and CONFLICT_SKEL contains a property conflict,
+   resolve/remove all property conflicts in CONFLICT_SKEL.
+
+   When RESOLVE_PROP is not NULL and not "", remove the property conflict on
+   the property RESOLVE_PROP in CONFLICT_SKEL. When RESOLVE_PROP was the last
+   property in CONFLICT_SKEL remove the property conflict info from
+   CONFLICT_SKEL.
+
+   When RESOLVE_TREE is TRUE and CONFLICT_SKEL contains a tree conflict,
+   resolve/remove the tree conflict in CONFLICT_SKEL.
+
+   If COMPLETELY_RESOLVED is not NULL, then set *COMPLETELY_RESOLVED to TRUE,
+   when no conflict registration is left in CONFLICT_SKEL after editting,
+   otherwise to FALSE.
+
+   Allocate data stored in the skel in RESULT_POOL.
+
+   This functions edits CONFLICT_SKEL. New skels might be created in
+   RESULT_POOL. Temporary allocations will use SCRATCH_POOL.
+ */
+/* ### db, wri_abspath is currently unused. Remove? */
+svn_error_t *
+svn_wc__conflict_skel_resolve(svn_boolean_t *completely_resolved,
+                              svn_skel_t *conflict_skel,
+                              svn_wc__db_t *db,
+                              const char *wri_abspath,
+                              svn_boolean_t resolve_text,
+                              const char *resolve_prop,
+                              svn_boolean_t resolve_tree,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool);
 
 /*
  * -----------------------------------------------------------
@@ -302,6 +338,19 @@ svn_wc__conflict_read_tree_conflict(svn_
                                     apr_pool_t *result_pool,
                                     apr_pool_t *scratch_pool);
 
+/* Reads in *MARKERS a list of const char * absolute paths of the marker files
+   referenced from CONFLICT_SKEL.
+ * Allocate the result in RESULT_POOL. Perform temporary allocations in
+ * SCRATCH_POOL.
+ */
+svn_error_t *
+svn_wc__conflict_read_markers(const apr_array_header_t **markers,
+                              svn_wc__db_t *db,
+                              const char *wri_abspath,
+                              const svn_skel_t *conflict_skel,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool);
+
 /* Create the necessary marker files for the conflicts stored in
  * CONFLICT_SKEL and return the work items to fill the markers from
  * the work queue.

Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/copy.c?rev=1425415&r1=1425414&r2=1425415&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/copy.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/copy.c Sun Dec 23 06:03:14 2012
@@ -218,8 +218,8 @@ copy_versioned_file(svn_wc__db_t *db,
           const char *conflict_working = NULL;
 
           /* Is there a text conflict at the source path? */
-          SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, src_abspath,
-                                            scratch_pool, scratch_pool));
+          SVN_ERR(svn_wc__read_conflicts(&conflicts, db, src_abspath,
+                                         scratch_pool, scratch_pool));
 
           for (i = 0; i < conflicts->nelts; i++)
             {
@@ -484,10 +484,6 @@ copy_versioned_dir(svn_wc__db_t *db,
           if (svn_wc_is_adm_dir(name, iterpool))
             continue;
 
-          if (marker_files &&
-              apr_hash_get(marker_files, name, APR_HASH_KEY_STRING))
-            continue;
-
           if (cancel_func)
             SVN_ERR(cancel_func(cancel_baton));
 
@@ -495,6 +491,11 @@ copy_versioned_dir(svn_wc__db_t *db,
           unver_src_abspath = svn_dirent_join(src_abspath, name, iterpool);
           unver_dst_abspath = svn_dirent_join(dst_abspath, name, iterpool);
 
+          if (marker_files &&
+              apr_hash_get(marker_files, unver_src_abspath,
+                           APR_HASH_KEY_STRING))
+            continue;
+
           SVN_ERR(copy_to_tmpdir(&work_item, NULL, db, unver_src_abspath,
                                  unver_dst_abspath, tmpdir_abspath,
                                  TRUE /* recursive */, TRUE /* unversioned */,
@@ -793,8 +794,8 @@ remove_node_conflict_markers(svn_wc__db_
 {
   const apr_array_header_t *conflicts;
 
-  SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, src_abspath,
-                                    scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__read_conflicts(&conflicts, db, src_abspath,
+                                 scratch_pool, scratch_pool));
 
   /* Do we have conflict markers that should be removed? */
   if (conflicts != NULL)



Mime
View raw message