Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/status.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/status.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/status.c 
(original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/status.c Wed Mar  
4 15:56:18 2015
@@ -53,6 +53,26 @@
 #include "private/svn_editor.h"
 
 
+/* The file internal variant of svn_wc_status3_t, with slightly more
+   data.
+
+   Instead of directly creating svn_wc_status3_t instances, we really
+   create instances of this struct with slightly more data for processing
+   by the status walker and status editor.
+
+   svn_wc_status3_dup() allocates space for this struct, but doesn't
+   copy the actual data. The remaining fields are copied by hash_stash(),
+   which is where the status editor stashes information for producing
+   later. */
+typedef struct svn_wc__internal_status_t
+{
+  svn_wc_status3_t s; /* First member; same pointer*/
+
+  svn_boolean_t has_descendants;
+
+  /* Make sure to update hash_stash() when adding values here */
+} svn_wc__internal_status_t;
+
 
 /*** Baton used for walking the local status */
 struct walk_status_baton
@@ -126,7 +146,7 @@ struct edit_baton
   const apr_array_header_t *ignores;
 
   /* Status item for the path represented by the anchor of the edit. */
-  svn_wc_status3_t *anchor_status;
+  svn_wc__internal_status_t *anchor_status;
 
   /* Was open_root() called for this edit drive? */
   svn_boolean_t root_opened;
@@ -288,7 +308,7 @@ get_repos_root_url_relpath(const char **
 }
 
 static svn_error_t *
-internal_status(svn_wc_status3_t **status,
+internal_status(svn_wc__internal_status_t **status,
                 svn_wc__db_t *db,
                 const char *local_abspath,
                 svn_boolean_t check_working_copy,
@@ -315,7 +335,7 @@ internal_status(svn_wc_status3_t **statu
    The status struct's repos_lock field will be set to REPOS_LOCK.
 */
 static svn_error_t *
-assemble_status(svn_wc_status3_t **status,
+assemble_status(svn_wc__internal_status_t **status,
                 svn_wc__db_t *db,
                 const char *local_abspath,
                 const char *parent_repos_root_url,
@@ -330,6 +350,7 @@ assemble_status(svn_wc_status3_t **statu
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
 {
+  svn_wc__internal_status_t *inner_stat;
   svn_wc_status3_t *stat;
   svn_boolean_t switched_p = FALSE;
   svn_boolean_t copied = FALSE;
@@ -582,7 +603,9 @@ assemble_status(svn_wc_status3_t **statu
 
   /* 6. Build and return a status structure. */
 
-  stat = apr_pcalloc(result_pool, sizeof(**status));
+  inner_stat = apr_pcalloc(result_pool, sizeof(*inner_stat));
+  stat = &inner_stat->s;
+  inner_stat->has_descendants = info->has_descendants;
 
   switch (info->kind)
     {
@@ -598,6 +621,7 @@ assemble_status(svn_wc_status3_t **statu
         stat->kind = svn_node_unknown;
     }
   stat->depth = info->depth;
+
   if (dirent)
     {
       stat->filesize = (dirent->kind == svn_node_file)
@@ -670,7 +694,7 @@ assemble_status(svn_wc_status3_t **statu
 
   stat->file_external = info->file_external;
 
-  *status = stat;
+  *status = inner_stat;
 
   return SVN_NO_ERROR;
 }
@@ -684,7 +708,7 @@ assemble_status(svn_wc_status3_t **statu
    node_status to svn_wc_status_unversioned.
  */
 static svn_error_t *
-assemble_unversioned(svn_wc_status3_t **status,
+assemble_unversioned(svn_wc__internal_status_t **status,
                      svn_wc__db_t *db,
                      const char *local_abspath,
                      const svn_io_dirent2_t *dirent,
@@ -693,10 +717,12 @@ assemble_unversioned(svn_wc_status3_t **
                      apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool)
 {
+  svn_wc__internal_status_t *inner_status;
   svn_wc_status3_t *stat;
 
   /* return a fairly blank structure. */
-  stat = apr_pcalloc(result_pool, sizeof(*stat));
+  inner_status = apr_pcalloc(result_pool, sizeof(*inner_status));
+  stat = &inner_status->s;
 
   /*stat->versioned = FALSE;*/
   stat->kind = svn_node_unknown; /* not versioned */
@@ -751,7 +777,7 @@ assemble_unversioned(svn_wc_status3_t **
   stat->conflicted = tree_conflicted;
   stat->changelist = NULL;
 
-  *status = stat;
+  *status = inner_status;
   return SVN_NO_ERROR;
 }
 
@@ -772,7 +798,7 @@ send_status_structure(const struct walk_
                       void *status_baton,
                       apr_pool_t *scratch_pool)
 {
-  svn_wc_status3_t *statstruct;
+  svn_wc__internal_status_t *statstruct;
   const svn_lock_t *repos_lock = NULL;
 
   /* Check for a repository lock. */
@@ -806,7 +832,8 @@ send_status_structure(const struct walk_
 
   if (statstruct && status_func)
     return svn_error_trace((*status_func)(status_baton, local_abspath,
-                                          statstruct, scratch_pool));
+                                          &statstruct->s,
+                                          scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -962,7 +989,7 @@ send_unversioned_item(const struct walk_
 {
   svn_boolean_t is_ignored;
   svn_boolean_t is_external;
-  svn_wc_status3_t *status;
+  svn_wc__internal_status_t *status;
   const char *base_name = svn_dirent_basename(local_abspath, NULL);
 
   is_ignored = svn_wc_match_ignore_list(base_name, patterns, scratch_pool);
@@ -974,12 +1001,12 @@ send_unversioned_item(const struct walk_
 
   is_external = is_external_path(wb->externals, local_abspath, scratch_pool);
   if (is_external)
-    status->node_status = svn_wc_status_external;
+    status->s.node_status = svn_wc_status_external;
 
   /* We can have a tree conflict on an unversioned path, i.e. an incoming
    * delete on a locally deleted path during an update. Don't ever ignore
    * those! */
-  if (status->conflicted)
+  if (status->s.conflicted)
     is_ignored = FALSE;
 
   /* If we aren't ignoring it, or if it's an externals path, pass this
@@ -988,7 +1015,7 @@ send_unversioned_item(const struct walk_
       || !is_ignored
       || is_external)
     return svn_error_trace((*status_func)(status_baton, local_abspath,
-                                          status, scratch_pool));
+                                          &status->s, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1091,7 +1118,7 @@ one_child_status(const struct walk_statu
 
       /* Descend in subdirectories. */
       if (depth == svn_depth_infinity
-          && info->kind == svn_node_dir)
+          && info->has_descendants /* is dir, or was dir and tc descendants */)
         {
           SVN_ERR(get_dir_status(wb, local_abspath, TRUE,
                                  dir_repos_root_url, dir_repos_relpath,
@@ -1451,9 +1478,15 @@ hash_stash(void *baton,
 {
   apr_hash_t *stat_hash = baton;
   apr_pool_t *hash_pool = apr_hash_pool_get(stat_hash);
+  void *new_status = svn_wc_dup_status3(status, hash_pool);
+  const svn_wc__internal_status_t *old_status = (const void*)status;
+
+  /* Copy the internal/private data. */
+  svn_wc__internal_status_t *is = new_status;
+  is->has_descendants = old_status->has_descendants;
+
   assert(! svn_hash_gets(stat_hash, path));
-  svn_hash_sets(stat_hash, apr_pstrdup(hash_pool, path),
-                svn_wc_dup_status3(status, hash_pool));
+  svn_hash_sets(stat_hash, apr_pstrdup(hash_pool, path), new_status);
 
   return SVN_NO_ERROR;
 }
@@ -1518,6 +1551,7 @@ tweak_statushash(void *baton,
   /* If not, make it so. */
   if (! statstruct)
     {
+      svn_wc__internal_status_t *i_stat;
       /* If this item isn't being added, then we're most likely
          dealing with a non-recursive (or at least partially
          non-recursive) working copy.  Due to bugs in how the client
@@ -1533,8 +1567,9 @@ tweak_statushash(void *baton,
         return SVN_NO_ERROR;
 
       /* Use the public API to get a statstruct, and put it into the hash. */
-      SVN_ERR(internal_status(&statstruct, db, local_abspath,
+      SVN_ERR(internal_status(&i_stat, db, local_abspath,
                               check_working_copy, pool, scratch_pool));
+      statstruct = &i_stat->s;
       statstruct->repos_lock = repos_lock;
       svn_hash_sets(statushash, apr_pstrdup(pool, local_abspath), statstruct);
     }
@@ -1573,9 +1608,9 @@ tweak_statushash(void *baton,
             statstruct->repos_relpath = apr_pstrdup(pool, b->repos_relpath);
 
           statstruct->repos_root_url =
-                              b->edit_baton->anchor_status->repos_root_url;
+                              b->edit_baton->anchor_status->s.repos_root_url;
           statstruct->repos_uuid =
-                              b->edit_baton->anchor_status->repos_uuid;
+                              b->edit_baton->anchor_status->s.repos_uuid;
         }
 
       /* The last committed date, and author for deleted items
@@ -1615,9 +1650,9 @@ tweak_statushash(void *baton,
         {
           statstruct->repos_relpath = apr_pstrdup(pool, b->repos_relpath);
           statstruct->repos_root_url =
-                          b->edit_baton->anchor_status->repos_root_url;
+                          b->edit_baton->anchor_status->s.repos_root_url;
           statstruct->repos_uuid =
-                          b->edit_baton->anchor_status->repos_uuid;
+                          b->edit_baton->anchor_status->s.repos_uuid;
         }
       statstruct->ood_kind = b->ood_kind;
       if (b->ood_changed_author)
@@ -1633,7 +1668,7 @@ find_dir_repos_relpath(const struct dir_
 {
   /* If we have no name, we're the root, return the anchor URL. */
   if (! db->name)
-    return db->edit_baton->anchor_status->repos_relpath;
+    return db->edit_baton->anchor_status->s.repos_relpath;
   else
     {
       const char *repos_relpath;
@@ -1665,7 +1700,7 @@ make_dir_baton(void **dir_baton,
   struct edit_baton *eb = edit_baton;
   struct dir_baton *d;
   const char *local_abspath;
-  const svn_wc_status3_t *status_in_parent;
+  const svn_wc__internal_status_t *status_in_parent;
   apr_pool_t *dir_pool;
 
   if (parent_baton)
@@ -1724,8 +1759,7 @@ make_dir_baton(void **dir_baton,
     status_in_parent = eb->anchor_status;
 
   if (status_in_parent
-      && status_in_parent->versioned
-      && (status_in_parent->kind == svn_node_dir)
+      && (status_in_parent->has_descendants)
       && (! d->excluded)
       && (d->depth == svn_depth_unknown
           || d->depth == svn_depth_infinity
@@ -1737,9 +1771,9 @@ make_dir_baton(void **dir_baton,
       const apr_array_header_t *ignores = eb->ignores;
 
       SVN_ERR(get_dir_status(&eb->wb, local_abspath, TRUE,
-                             status_in_parent->repos_root_url,
+                             status_in_parent->s.repos_root_url,
                              NULL /*parent_repos_relpath*/,
-                             status_in_parent->repos_uuid,
+                             status_in_parent->s.repos_uuid,
                              NULL,
                              NULL /* dirent */, ignores,
                              d->depth == svn_depth_files
@@ -1754,7 +1788,7 @@ make_dir_baton(void **dir_baton,
       this_dir_status = svn_hash_gets(d->statii, d->local_abspath);
       if (this_dir_status && this_dir_status->versioned
           && (d->depth == svn_depth_unknown
-              || d->depth > status_in_parent->depth))
+              || d->depth > status_in_parent->s.depth))
         {
           d->depth = this_dir_status->depth;
         }
@@ -1800,10 +1834,11 @@ make_file_baton(struct dir_baton *parent
  * This implementation should match the filter in assemble_status()
  */
 static svn_boolean_t
-is_sendable_status(const svn_wc_status3_t *status,
+is_sendable_status(const svn_wc__internal_status_t *i_status,
                    svn_boolean_t no_ignore,
                    svn_boolean_t get_all)
 {
+  const svn_wc_status3_t *status = &i_status->s;
   /* If the repository status was touched at all, it's interesting. */
   if (status->repos_node_status != svn_wc_status_none)
     return TRUE;
@@ -1829,8 +1864,8 @@ is_sendable_status(const svn_wc_status3_
     return TRUE;
 
   /* If the text, property or tree state is interesting, send it. */
-  if ((status->node_status != svn_wc_status_none
-       && (status->node_status != svn_wc_status_normal)))
+  if ((status->node_status != svn_wc_status_none)
+       && (status->node_status != svn_wc_status_normal))
     return TRUE;
 
   /* If it's switched, send it. */
@@ -1913,14 +1948,14 @@ handle_statii(struct edit_baton *eb,
   for (hi = apr_hash_first(pool, statii); hi; hi = apr_hash_next(hi))
     {
       const char *local_abspath = apr_hash_this_key(hi);
-      svn_wc_status3_t *status = apr_hash_this_val(hi);
+      svn_wc__internal_status_t *status = apr_hash_this_val(hi);
 
       /* Clear the subpool. */
       svn_pool_clear(iterpool);
 
       /* Now, handle the status.  We don't recurse for svn_depth_immediates
          because we already have the subdirectories' statii. */
-      if (status->versioned && status->kind == svn_node_dir
+      if (status->has_descendants
           && (depth == svn_depth_unknown
               || depth == svn_depth_infinity))
         {
@@ -1936,9 +1971,9 @@ handle_statii(struct edit_baton *eb,
                                  iterpool));
         }
       if (dir_was_deleted)
-        status->repos_node_status = svn_wc_status_deleted;
+        status->s.repos_node_status = svn_wc_status_deleted;
       if (is_sendable_status(status, eb->no_ignore, eb->get_all))
-        SVN_ERR((eb->status_func)(eb->status_baton, local_abspath, status,
+        SVN_ERR((eb->status_func)(eb->status_baton, local_abspath, &status->s,
                                   iterpool));
     }
 
@@ -2138,17 +2173,17 @@ close_directory(void *dir_baton,
           /* We're editing the root dir of the WC.  As its repos
              status info isn't otherwise set, set it directly to
              trigger invocation of the status callback below. */
-          eb->anchor_status->repos_node_status = repos_node_status;
-          eb->anchor_status->repos_prop_status = repos_prop_status;
-          eb->anchor_status->repos_text_status = repos_text_status;
+          eb->anchor_status->s.repos_node_status = repos_node_status;
+          eb->anchor_status->s.repos_prop_status = repos_prop_status;
+          eb->anchor_status->s.repos_text_status = repos_text_status;
 
           /* If the root dir is out of date set the ood info directly too. */
-          if (db->ood_changed_rev != eb->anchor_status->revision)
+          if (db->ood_changed_rev != eb->anchor_status->s.revision)
             {
-              eb->anchor_status->ood_changed_rev = db->ood_changed_rev;
-              eb->anchor_status->ood_changed_date = db->ood_changed_date;
-              eb->anchor_status->ood_kind = db->ood_kind;
-              eb->anchor_status->ood_changed_author =
+              eb->anchor_status->s.ood_changed_rev = db->ood_changed_rev;
+              eb->anchor_status->s.ood_changed_date = db->ood_changed_date;
+              eb->anchor_status->s.ood_kind = db->ood_kind;
+              eb->anchor_status->s.ood_changed_author =
                 apr_pstrdup(pool, db->ood_changed_author);
             }
         }
@@ -2159,25 +2194,25 @@ close_directory(void *dir_baton,
   if (pb && ! db->excluded)
     {
       svn_boolean_t was_deleted = FALSE;
-      const svn_wc_status3_t *dir_status;
+      svn_wc__internal_status_t *dir_status;
 
       /* See if the directory was deleted or replaced. */
       dir_status = svn_hash_gets(pb->statii, db->local_abspath);
       if (dir_status &&
-          ((dir_status->repos_node_status == svn_wc_status_deleted)
-           || (dir_status->repos_node_status == svn_wc_status_replaced)))
+          ((dir_status->s.repos_node_status == svn_wc_status_deleted)
+           || (dir_status->s.repos_node_status == svn_wc_status_replaced)))
         was_deleted = TRUE;
 
       /* Now do the status reporting. */
       SVN_ERR(handle_statii(eb,
-                            dir_status ? dir_status->repos_root_url : NULL,
-                            dir_status ? dir_status->repos_relpath : NULL,
-                            dir_status ? dir_status->repos_uuid : NULL,
+                            dir_status ? dir_status->s.repos_root_url : NULL,
+                            dir_status ? dir_status->s.repos_relpath : NULL,
+                            dir_status ? dir_status->s.repos_uuid : NULL,
                             db->statii, was_deleted, db->depth, scratch_pool));
       if (dir_status && is_sendable_status(dir_status, eb->no_ignore,
                                            eb->get_all))
         SVN_ERR((eb->status_func)(eb->status_baton, db->local_abspath,
-                                  dir_status, scratch_pool));
+                                  &dir_status->s, scratch_pool));
       svn_hash_sets(pb->statii, db->local_abspath, NULL);
     }
   else if (! pb)
@@ -2186,13 +2221,12 @@ close_directory(void *dir_baton,
          target, we should only report the target. */
       if (*eb->target_basename)
         {
-          const svn_wc_status3_t *tgt_status;
+          const svn_wc__internal_status_t *tgt_status;
 
           tgt_status = svn_hash_gets(db->statii, eb->target_abspath);
           if (tgt_status)
             {
-              if (tgt_status->versioned
-                  && tgt_status->kind == svn_node_dir)
+              if (tgt_status->has_descendants)
                 {
                   SVN_ERR(get_dir_status(&eb->wb,
                                          eb->target_abspath, TRUE,
@@ -2207,7 +2241,7 @@ close_directory(void *dir_baton,
                 }
               if (is_sendable_status(tgt_status, eb->no_ignore, eb->get_all))
                 SVN_ERR((eb->status_func)(eb->status_baton, eb->target_abspath,
-                                          tgt_status, scratch_pool));
+                                          &tgt_status->s, scratch_pool));
             }
         }
       else
@@ -2216,15 +2250,15 @@ close_directory(void *dir_baton,
              Note that our directory couldn't have been deleted,
              because it is the root of the edit drive. */
           SVN_ERR(handle_statii(eb,
-                                eb->anchor_status->repos_root_url,
-                                eb->anchor_status->repos_relpath,
-                                eb->anchor_status->repos_uuid,
+                                eb->anchor_status->s.repos_root_url,
+                                eb->anchor_status->s.repos_relpath,
+                                eb->anchor_status->s.repos_uuid,
                                 db->statii, FALSE, eb->default_depth,
                                 scratch_pool));
           if (is_sendable_status(eb->anchor_status, eb->no_ignore,
                                  eb->get_all))
             SVN_ERR((eb->status_func)(eb->status_baton, db->local_abspath,
-                                      eb->anchor_status, scratch_pool));
+                                      &eb->anchor_status->s, scratch_pool));
           eb->anchor_status = NULL;
         }
     }
@@ -2645,7 +2679,7 @@ svn_wc__internal_walk_status(svn_wc__db_
     }
 
   if (info
-      && info->kind == svn_node_dir
+      && info->has_descendants /* is dir, or was dir and has tc descendants */
       && info->status != svn_wc__db_status_not_present
       && info->status != svn_wc__db_status_excluded
       && info->status != svn_wc__db_status_server_excluded)
@@ -2765,7 +2799,7 @@ svn_wc_get_default_ignores(apr_array_hea
 
 /* */
 static svn_error_t *
-internal_status(svn_wc_status3_t **status,
+internal_status(svn_wc__internal_status_t **status,
                 svn_wc__db_t *db,
                 const char *local_abspath,
                 svn_boolean_t check_working_copy,
@@ -2872,17 +2906,21 @@ svn_wc_status3(svn_wc_status3_t **status
                apr_pool_t *result_pool,
                apr_pool_t *scratch_pool)
 {
-  return svn_error_trace(
-      internal_status(status, wc_ctx->db, local_abspath,
-                      TRUE /* check_working_copy */,
-                      result_pool, scratch_pool));
+  svn_wc__internal_status_t *stat;
+  SVN_ERR(internal_status(&stat, wc_ctx->db, local_abspath,
+                          TRUE /* check_working_copy */,
+                          result_pool, scratch_pool));
+  *status = &stat->s;
+  return SVN_NO_ERROR;
 }
 
 svn_wc_status3_t *
 svn_wc_dup_status3(const svn_wc_status3_t *orig_stat,
                    apr_pool_t *pool)
 {
-  svn_wc_status3_t *new_stat = apr_palloc(pool, sizeof(*new_stat));
+  /* Allocate slightly more room */
+  svn_wc__internal_status_t *new_istat = apr_palloc(pool, sizeof(*new_istat));
+  svn_wc_status3_t *new_stat = &new_istat->s;
 
   /* Shallow copy all members. */
   *new_stat = *orig_stat;

Modified: 
subversion/branches/reuse-ra-session/subversion/libsvn_wc/update_editor.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/update_editor.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/update_editor.c 
(original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/update_editor.c 
Wed Mar  4 15:56:18 2015
@@ -1937,7 +1937,12 @@ add_directory(const char *path,
     }
   else if (status == svn_wc__db_status_normal)
     {
-      if (wc_kind == svn_node_dir)
+      svn_boolean_t root;
+
+      SVN_ERR(svn_wc__db_is_wcroot(&root, eb->db, db->local_abspath,
+                                   scratch_pool));
+
+      if (root)
         {
           /* !! We found the root of a working copy obstructing the wc !!
 
@@ -1949,9 +1954,16 @@ add_directory(const char *path,
              resolved.  Note that svn_wc__db_base_add_not_present_node()
              explicitly adds the node into the parent's node database. */
 
-          svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, db->name),
+          svn_hash_sets(pb->not_present_nodes,
+                        apr_pstrdup(pb->pool, db->name),
                         svn_node_kind_to_word(svn_node_dir));
         }
+      else if (wc_kind == svn_node_dir)
+        {
+          /* We have an editor violation. Github sometimes does this
+             in its subversion compatibility code, when changing the
+             depth of a working copy, or on updates from incomplete */
+        }
       else
         {
           /* We found a file external occupating the place we need in BASE.
@@ -3108,18 +3120,32 @@ add_file(const char *path,
     }
   else if (status == svn_wc__db_status_normal)
     {
-      if (wc_kind == svn_node_dir)
+      svn_boolean_t root;
+
+      SVN_ERR(svn_wc__db_is_wcroot(&root, eb->db, fb->local_abspath,
+                                   scratch_pool));
+
+      if (root)
         {
           /* !! We found the root of a working copy obstructing the wc !!
 
              If the directory would be part of our own working copy then
-             we wouldn't have been called as an add_file().
+             we wouldn't have been called as an add_directory().
 
              The only thing we can do is add a not-present node, to allow
              a future update to bring in the new files when the problem is
-             resolved. */
-          svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, fb->name),
-                        svn_node_kind_to_word(svn_node_file));
+             resolved.  Note that svn_wc__db_base_add_not_present_node()
+             explicitly adds the node into the parent's node database. */
+
+          svn_hash_sets(pb->not_present_nodes,
+                        apr_pstrdup(pb->pool, fb->name),
+                        svn_node_kind_to_word(svn_node_dir));
+        }
+      else if (wc_kind == svn_node_dir)
+        {
+          /* We have an editor violation. Github sometimes does this
+             in its subversion compatibility code, when changing the
+             depth of a working copy, or on updates from incomplete */
         }
       else
         {

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/upgrade.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/upgrade.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/upgrade.c 
(original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/upgrade.c Wed Mar 
 4 15:56:18 2015
@@ -2366,40 +2366,6 @@ is_old_wcroot(const char *local_abspath,
     svn_dirent_local_style(parent_abspath, scratch_pool));
 }
 
-/* Data for upgrade_working_copy_txn(). */
-typedef struct upgrade_working_copy_baton_t
-{
-  svn_wc__db_t *db;
-  const char *dir_abspath;
-  svn_wc_upgrade_get_repos_info_t repos_info_func;
-  void *repos_info_baton;
-  apr_hash_t *repos_cache;
-  const struct upgrade_data_t *data;
-  svn_cancel_func_t cancel_func;
-  void *cancel_baton;
-  svn_wc_notify_func2_t notify_func;
-  void *notify_baton;
-  apr_pool_t *result_pool;
-} upgrade_working_copy_baton_t;
-
-
-/* Helper for svn_wc_upgrade. Implements svn_sqlite__transaction_callback_t */
-static svn_error_t *
-upgrade_working_copy_txn(void *baton,
-                         svn_sqlite__db_t *sdb,
-                         apr_pool_t *scratch_pool)
-{
-  upgrade_working_copy_baton_t *b = baton;
-
-  /* Upgrade the pre-wcng into a wcng in a temporary location. */
-  return(upgrade_working_copy(NULL, b->db, b->dir_abspath,
-                              b->repos_info_func, b->repos_info_baton,
-                              b->repos_cache, b->data,
-                              b->cancel_func, b->cancel_baton,
-                              b->notify_func, b->notify_baton,
-                              b->result_pool, scratch_pool));
-}
-
 svn_error_t *
 svn_wc_upgrade(svn_wc_context_t *wc_ctx,
                const char *local_abspath,
@@ -2419,7 +2385,6 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
   svn_wc_entry_t *this_dir;
   apr_hash_t *entries;
   const char *root_adm_abspath;
-  upgrade_working_copy_baton_t cb_baton;
   svn_error_t *err;
   int result_format;
   svn_boolean_t bumped_format;
@@ -2517,22 +2482,14 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx,
   SVN_ERR(svn_wc__db_wclock_obtain(db, data.root_abspath, 0, FALSE,
                                    scratch_pool));
 
-  cb_baton.db = db;
-  cb_baton.dir_abspath = local_abspath;
-  cb_baton.repos_info_func = repos_info_func;
-  cb_baton.repos_info_baton = repos_info_baton;
-  cb_baton.repos_cache = repos_cache;
-  cb_baton.data = &data;
-  cb_baton.cancel_func = cancel_func;
-  cb_baton.cancel_baton = cancel_baton;
-  cb_baton.notify_func = notify_func;
-  cb_baton.notify_baton = notify_baton;
-  cb_baton.result_pool = scratch_pool;
-
-  SVN_ERR(svn_sqlite__with_lock(data.sdb,
-                                upgrade_working_copy_txn,
-                                &cb_baton,
-                                scratch_pool));
+  SVN_SQLITE__WITH_LOCK(
+    upgrade_working_copy(NULL, db, local_abspath,
+                         repos_info_func, repos_info_baton,
+                         repos_cache, &data,
+                         cancel_func, cancel_baton,
+                         notify_func, notify_baton,
+                         scratch_pool, scratch_pool),
+    data.sdb);
 
   /* A workqueue item to move the pristine dir into place */
   pristine_from = svn_wc__adm_child(data.root_abspath, 
PRISTINE_STORAGE_RELPATH,

Modified: 
subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc-queries.sql
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc-queries.sql?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc-queries.sql 
(original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc-queries.sql 
Wed Mar  4 15:56:18 2015
@@ -46,7 +46,7 @@ SELECT op_depth, nodes.repos_id, nodes.r
   lock_token, lock_owner, lock_comment, lock_date
 FROM nodes
 LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
-  AND nodes.repos_path = lock.repos_relpath
+  AND nodes.repos_path = lock.repos_relpath AND nodes.op_depth=0
 WHERE wc_id = ?1 AND local_relpath = ?2
 ORDER BY op_depth DESC
 
@@ -134,7 +134,7 @@ SELECT op_depth, nodes.repos_id, nodes.r
   lock_comment, lock_date, local_relpath, moved_here, moved_to, file_external
 FROM nodes
 LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
-  AND nodes.repos_path = lock.repos_relpath AND op_depth = 0
+  AND nodes.repos_path = lock.repos_relpath AND nodes.op_depth = 0
 WHERE wc_id = ?1 AND parent_relpath = ?2
 ORDER BY local_relpath DESC, op_depth DESC
 
@@ -148,7 +148,7 @@ SELECT op_depth, nodes.repos_id, nodes.r
   lock_comment, lock_date, local_relpath, moved_here, moved_to, file_external
 FROM nodes
 LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
-  AND nodes.repos_path = lock.repos_relpath AND op_depth = 0
+  AND nodes.repos_path = lock.repos_relpath
 WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = 0
 ORDER BY local_relpath DESC
 
@@ -249,7 +249,8 @@ WHERE wc_id = ?1 AND IS_STRICT_DESCENDAN
 
 -- STMT_DELETE_BASE_RECURSIVE
 DELETE FROM nodes
-WHERE wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+WHERE wc_id = ?1 AND (local_relpath = ?2 
+                      OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
   AND op_depth = 0
 
 -- STMT_DELETE_WORKING_OP_DEPTH
@@ -954,6 +955,14 @@ SELECT local_dir_relpath FROM wc_lock
 WHERE wc_id = ?1
   AND IS_STRICT_DESCENDANT_OF(local_dir_relpath, ?2)
 
+-- STMT_FIND_CONFLICT_DESCENDANT
+SELECT 1 FROM actual_node
+WHERE wc_id = ?1
+  AND local_relpath > (?2 || '/')
+  AND local_relpath < (?2 || '0') /* '0' = ascii('/') +1 */
+  AND conflict_data IS NOT NULL
+LIMIT 1
+
 -- STMT_DELETE_WC_LOCK_ORPHAN
 DELETE FROM wc_lock
 WHERE wc_id = ?1 AND local_dir_relpath = ?2

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.c Wed Mar  
4 15:56:18 2015
@@ -2125,11 +2125,13 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
   int op_depth;
   svn_node_kind_t wrk_kind;
   svn_boolean_t no_delete_wc = FALSE;
+  svn_boolean_t file_external;
 
   SVN_ERR(svn_wc__db_base_get_info_internal(&status, &kind, &revision,
                                             &repos_relpath, &repos_id,
                                             NULL, NULL, NULL, NULL, NULL,
-                                            NULL, NULL, NULL, NULL, NULL,
+                                            NULL, NULL, NULL, NULL,
+                                            &file_external,
                                             wcroot, local_relpath,
                                             scratch_pool, scratch_pool));
 
@@ -2360,35 +2362,69 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
   SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step_done(stmt));
 
-  /* Step 5: handle the BASE node itself */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_DELETE_BASE_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
-  SVN_ERR(svn_sqlite__step_done(stmt));
-
   SVN_ERR(db_retract_parent_delete(wcroot, local_relpath, 0, scratch_pool));
 
   if (mark_not_present || mark_excluded)
     {
       struct insert_base_baton_t ibb;
-      blank_ibb(&ibb);
+      svn_boolean_t no_marker = FALSE;
 
-      ibb.repos_id = repos_id;
-      ibb.status = mark_excluded ? svn_wc__db_status_excluded
-                                 : svn_wc__db_status_not_present;
-      ibb.kind = kind;
-      ibb.repos_relpath = repos_relpath;
-      ibb.revision = SVN_IS_VALID_REVNUM(marker_revision)
-                        ? marker_revision
-                        : revision;
-
-      /* Depending upon KIND, any of these might get used. */
-      ibb.children = NULL;
-      ibb.depth = svn_depth_unknown;
-      ibb.checksum = NULL;
-      ibb.target = NULL;
+      if (file_external)
+        {
+          const char *parent_local_relpath;
+          const char *name;
+          svn_error_t *err;
 
-      SVN_ERR(insert_base_node(&ibb, wcroot, local_relpath, scratch_pool));
+          /* For file externals we only want to place a not present marker
+             if there is a BASE parent */
+          
+          svn_relpath_split(&parent_local_relpath, &name, local_relpath,
+                            scratch_pool);
+
+          err = svn_wc__db_base_get_info_internal(NULL, NULL, NULL,
+                                                  &repos_relpath, &repos_id,
+                                                  NULL, NULL, NULL, NULL, NULL,
+                                                  NULL, NULL, NULL, NULL, NULL,
+                                                  wcroot, parent_local_relpath,
+                                                  scratch_pool, scratch_pool);
+
+          if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+            return svn_error_trace(err);
+          else if (err)
+            {
+              svn_error_clear(err);
+              no_marker = TRUE;
+            }
+          else
+            {
+              /* Replace the repos_relpath with something more expected than
+                 the unrelated old file external repository relpath, which
+                 one day may come from a different repository */
+              repos_relpath = svn_relpath_join(repos_relpath, name, 
scratch_pool);
+            }
+        }
+
+      if (!no_marker)
+        {
+          blank_ibb(&ibb);
+
+          ibb.repos_id = repos_id;
+          ibb.status = mark_excluded ? svn_wc__db_status_excluded
+                                     : svn_wc__db_status_not_present;
+          ibb.kind = kind;
+          ibb.repos_relpath = repos_relpath;
+          ibb.revision = SVN_IS_VALID_REVNUM(marker_revision)
+                            ? marker_revision
+                            : revision;
+
+          /* Depending upon KIND, any of these might get used. */
+          ibb.children = NULL;
+          ibb.depth = svn_depth_unknown;
+          ibb.checksum = NULL;
+          ibb.target = NULL;
+
+          SVN_ERR(insert_base_node(&ibb, wcroot, local_relpath, scratch_pool));
+        }
     }
 
   SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
@@ -3007,6 +3043,11 @@ svn_wc__db_depth_get_info(svn_wc__db_sta
   return svn_error_compose_create(err, svn_sqlite__reset(stmt));
 }
 
+/* A callback which supplies WCROOTs and LOCAL_RELPATHs. */
+typedef svn_error_t *(*svn_wc__db_txn_callback_t)(void *baton,
+                                          svn_wc__db_wcroot_t *wcroot,
+                                          const char *local_relpath,
+                                          apr_pool_t *scratch_pool);
 
 /* Baton for passing args to with_triggers(). */
 struct with_triggers_baton_t {
@@ -3083,8 +3124,13 @@ with_finalization(svn_wc__db_wcroot_t *w
   svn_error_t *err1;
   svn_error_t *err2;
 
-  err1 = svn_wc__db_with_txn(wcroot, local_relpath, txn_cb, txn_baton,
-                             scratch_pool);
+  err1 = svn_sqlite__begin_savepoint(wcroot->sdb);
+  if (!err1)
+    {
+      err1 = txn_cb(txn_baton, wcroot, local_relpath, scratch_pool);
+
+      err1 = svn_sqlite__finish_savepoint(wcroot->sdb, err1);
+    }
 
   if (err1 == NULL && notify_func != NULL)
     {
@@ -3470,11 +3516,18 @@ db_external_remove(const svn_skel_t *wor
                    apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
+  int affected_rows;
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_DELETE_EXTERNAL));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
-  SVN_ERR(svn_sqlite__step_done(stmt));
+  SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+
+  if (!affected_rows)
+    return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+                             _("The node '%s' is not an external."),
+                             path_for_error_message(wcroot, local_relpath,
+                                                    scratch_pool));
 
   SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
 
@@ -3957,14 +4010,14 @@ get_moved_to(const char **moved_to_relpa
 /* The body of svn_wc__db_scan_deletion().
  */
 static svn_error_t *
-scan_deletion_txn(const char **base_del_relpath,
-                  const char **moved_to_relpath,
-                  const char **work_del_relpath,
-                  const char **moved_to_op_root_relpath,
-                  svn_wc__db_wcroot_t *wcroot,
-                  const char *local_relpath,
-                  apr_pool_t *result_pool,
-                  apr_pool_t *scratch_pool)
+scan_deletion(const char **base_del_relpath,
+              const char **moved_to_relpath,
+              const char **work_del_relpath,
+              const char **moved_to_op_root_relpath,
+              svn_wc__db_wcroot_t *wcroot,
+              const char *local_relpath,
+              apr_pool_t *result_pool,
+              apr_pool_t *scratch_pool)
 {
   const char *current_relpath = local_relpath;
   svn_sqlite__stmt_t *stmt;
@@ -4109,6 +4162,25 @@ scan_deletion_txn(const char **base_del_
 }
 
 svn_error_t *
+svn_wc__db_scan_deletion_internal(
+              const char **base_del_relpath,
+              const char **moved_to_relpath,
+              const char **work_del_relpath,
+              const char **moved_to_op_root_relpath,
+              svn_wc__db_wcroot_t *wcroot,
+              const char *local_relpath,
+              apr_pool_t *result_pool,
+              apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(
+            scan_deletion(base_del_relpath, moved_to_relpath, work_del_relpath,
+                          moved_to_op_root_relpath,
+                          wcroot, local_relpath,
+                          result_pool, scratch_pool));
+}
+
+
+svn_error_t *
 svn_wc__db_scan_deletion(const char **base_del_abspath,
                          const char **moved_to_abspath,
                          const char **work_del_abspath,
@@ -4130,9 +4202,9 @@ svn_wc__db_scan_deletion(const char **ba
   VERIFY_USABLE_WCROOT(wcroot);
 
   SVN_WC__DB_WITH_TXN(
-    scan_deletion_txn(&base_del_relpath, &moved_to_relpath,
-                      &work_del_relpath, &moved_to_op_root_relpath,
-                      wcroot, local_relpath, result_pool, scratch_pool),
+    scan_deletion(&base_del_relpath, &moved_to_relpath,
+                  &work_del_relpath, &moved_to_op_root_relpath,
+                  wcroot, local_relpath, result_pool, scratch_pool),
     wcroot);
 
   if (base_del_abspath)
@@ -4230,10 +4302,10 @@ get_info_for_copy(apr_int64_t *copyfrom_
     {
       const char *base_del_relpath, *work_del_relpath;
 
-      SVN_ERR(scan_deletion_txn(&base_del_relpath, NULL,
-                                &work_del_relpath,
-                                NULL, src_wcroot, local_relpath,
-                                scratch_pool, scratch_pool));
+      SVN_ERR(scan_deletion(&base_del_relpath, NULL,
+                            &work_del_relpath,
+                            NULL, src_wcroot, local_relpath,
+                            scratch_pool, scratch_pool));
       if (work_del_relpath)
         {
           const char *op_root_relpath;
@@ -8990,10 +9062,8 @@ read_info(svn_wc__db_status_t *status,
     err = svn_error_compose_create(err, svn_sqlite__reset(stmt_act));
 
   if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
-    err = svn_error_quick_wrap(err,
-                               apr_psprintf(scratch_pool,
-                                            _("Error reading node '%s'"),
-                                            local_relpath));
+    err = svn_error_quick_wrapf(err, _("Error reading node '%s'"),
+                                local_relpath);
 
   SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt_info)));
 
@@ -9113,6 +9183,27 @@ is_wclocked(svn_boolean_t *locked,
             const char *dir_relpath,
             apr_pool_t *scratch_pool);
 
+/* Helper for read_children_info and single variant */
+static svn_error_t *
+find_conflict_descendants(svn_boolean_t *conflict_exists,
+                          svn_wc__db_wcroot_t *wcroot,
+                          const char *local_relpath,
+                          apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+
+  /* Only used on files, so certainly not wcroot*/
+  assert(local_relpath[0] != '\0');
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_FIND_CONFLICT_DESCENDANT));
+
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(conflict_exists, stmt));
+
+  return svn_error_trace(svn_sqlite__reset(stmt));
+}
+
 /* What we really want to store about a node.  This relies on the
    offset of svn_wc__db_info_t being zero. */
 struct read_children_info_item_t
@@ -9120,6 +9211,7 @@ struct read_children_info_item_t
   struct svn_wc__db_info_t info;
   int op_depth;
   int nr_layers;
+  svn_boolean_t was_dir;
 };
 
 /* Implementation of svn_wc__db_read_children_info */
@@ -9169,7 +9261,7 @@ read_children_info(svn_wc__db_wcroot_t *
       op_depth = svn_sqlite__column_int(stmt, 0);
 
       /* Do we have new or better information? */
-      if (new_child || op_depth > child_item->op_depth)
+      if (new_child)
         {
           struct svn_wc__db_info_t *child = &child_item->info;
           child_item->op_depth = op_depth;
@@ -9250,6 +9342,8 @@ read_children_info(svn_wc__db_wcroot_t *
             child->depth = svn_depth_unknown;
           else
             {
+              child->has_descendants = TRUE;
+              child_item->was_dir = TRUE;
               child->depth = svn_sqlite__column_token_null(stmt, 11, depth_map,
                                                            svn_depth_unknown);
               if (new_child)
@@ -9292,6 +9386,17 @@ read_children_info(svn_wc__db_wcroot_t *
           if (new_child)
             svn_hash_sets(nodes, apr_pstrdup(result_pool, name), child);
         }
+      else if (!child_item->was_dir
+               && svn_sqlite__column_token(stmt, 4, kind_map) == svn_node_dir)
+        {
+          child_item->was_dir = TRUE;
+
+          err = find_conflict_descendants(&child_item->info.has_descendants,
+                                          wcroot, child_relpath,
+                                          scratch_pool);
+          if (err)
+            SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+        }
 
       if (op_depth == 0)
         {
@@ -9600,6 +9705,12 @@ read_single_info(const struct svn_wc__db
   if (!base_tree_only && mtb->kind == svn_node_dir)
     SVN_ERR(is_wclocked(&mtb->locked, wcroot, local_relpath, scratch_pool));
 
+  if (mtb->kind == svn_node_dir)
+    mtb->has_descendants = TRUE;
+  else
+    SVN_ERR(find_conflict_descendants(&mtb->has_descendants,
+                                      wcroot, local_relpath, scratch_pool));
+
   *info = mtb;
 
   return SVN_NO_ERROR;
@@ -9965,12 +10076,12 @@ db_read_repos_info(svn_revnum_t *revisio
           const char *base_del_relpath;
           const char *work_del_relpath;
 
-          SVN_ERR(scan_deletion_txn(&base_del_relpath, NULL,
-                                    &work_del_relpath,
-                                    NULL, wcroot,
-                                    local_relpath,
-                                    scratch_pool,
-                                    scratch_pool));
+          SVN_ERR(scan_deletion(&base_del_relpath, NULL,
+                                &work_del_relpath,
+                                NULL, wcroot,
+                                local_relpath,
+                                scratch_pool,
+                                scratch_pool));
 
           if (work_del_relpath)
             {
@@ -11197,11 +11308,11 @@ relocate_txn(svn_wc__db_wcroot_t *wcroot
         {
           const char *work_del_relpath;
 
-          SVN_ERR(scan_deletion_txn(NULL, NULL,
-                                    &work_del_relpath, NULL,
-                                    wcroot, local_dir_relpath,
-                                    scratch_pool,
-                                    scratch_pool));
+          SVN_ERR(scan_deletion(NULL, NULL,
+                                &work_del_relpath, NULL,
+                                wcroot, local_dir_relpath,
+                                scratch_pool,
+                                scratch_pool));
           if (work_del_relpath)
             {
               /* Deleted within a copy/move */
@@ -11289,59 +11400,86 @@ svn_wc__db_global_relocate(svn_wc__db_t
 }
 
 
-/* Set *REPOS_ID and *REPOS_RELPATH to the BASE repository location of
+/* Helper for commit_node()
+   Set *REPOS_ID and *REPOS_RELPATH to the BASE repository location of
    (WCROOT, LOCAL_RELPATH), directly if its BASE row exists or implied from
    its parent's BASE row if not. In the latter case, error if the parent
    BASE row does not exist.  */
 static svn_error_t *
-determine_repos_info(apr_int64_t *repos_id,
-                     const char **repos_relpath,
-                     svn_wc__db_wcroot_t *wcroot,
-                     const char *local_relpath,
-                     apr_pool_t *result_pool,
-                     apr_pool_t *scratch_pool)
+determine_commit_repos_info(apr_int64_t *repos_id,
+                            const char **repos_relpath,
+                            svn_wc__db_wcroot_t *wcroot,
+                            const char *local_relpath,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
-  const char *repos_parent_relpath;
-  const char *local_parent_relpath, *name;
-
-  /* ### is it faster to fetch fewer columns? */
+  int op_depth;
 
   /* Prefer the current node's repository information.  */
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_SELECT_BASE_NODE));
+                                    STMT_SELECT_NODE_INFO));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
-  if (have_row)
+  if (!have_row)
+    return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
+                             svn_sqlite__reset(stmt),
+                             _("The node '%s' was not found."),
+                             path_for_error_message(wcroot, local_relpath,
+                                                    scratch_pool));
+
+  op_depth = svn_sqlite__column_int(stmt, 0);
+
+  if (op_depth > 0)
     {
-      SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 0));
-      SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 1));
+      svn_wc__db_status_t presence = svn_sqlite__column_token(stmt, 3,
+                                                              presence_map);
 
-      *repos_id = svn_sqlite__column_int64(stmt, 0);
-      *repos_relpath = svn_sqlite__column_text(stmt, 1, result_pool);
+      if (presence == svn_wc__db_status_base_deleted)
+        {
+          SVN_ERR(svn_sqlite__step_row(stmt)); /* There must be a row */
+          op_depth = svn_sqlite__column_int(stmt, 0);
+        }
+      else
+        {
+          const char *parent_repos_relpath;
+          const char *parent_relpath;
+          const char *name;
 
-      return svn_error_trace(svn_sqlite__reset(stmt));
+          SVN_ERR(svn_sqlite__reset(stmt));
+
+          /* The repository relative path of an add/copy is based on its
+             ancestor, not on the shadowed base layer.
+
+             As this function is only used from the commit processing we know
+             the parent directory has only a BASE row, so we can just obtain
+             the information directly by recursing (once!)  */
+
+          svn_relpath_split(&parent_relpath, &name, local_relpath,
+                            scratch_pool);
+
+          SVN_ERR(determine_commit_repos_info(repos_id, &parent_repos_relpath,
+                                              wcroot, parent_relpath,
+                                              scratch_pool, scratch_pool));
+
+          *repos_relpath = svn_relpath_join(parent_repos_relpath, name,
+                                            result_pool);
+          return SVN_NO_ERROR;
+        }
     }
 
-  SVN_ERR(svn_sqlite__reset(stmt));
 
-  /* This was a child node within this wcroot. We want to look at the
-     BASE node of the directory.  */
-  svn_relpath_split(&local_parent_relpath, &name, local_relpath, scratch_pool);
+  SVN_ERR_ASSERT(op_depth == 0); /* And that row must be BASE */
 
-  /* The REPOS_ID will be the same (### until we support mixed-repos)  */
-  SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL,
-                                            &repos_parent_relpath, repos_id,
-                                            NULL, NULL, NULL, NULL, NULL,
-                                            NULL, NULL, NULL, NULL, NULL,
-                                            wcroot, local_parent_relpath,
-                                            scratch_pool, scratch_pool));
+  SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 1));
+  SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 2));
 
-  *repos_relpath = svn_relpath_join(repos_parent_relpath, name, result_pool);
+  *repos_id = svn_sqlite__column_int64(stmt, 1);
+  *repos_relpath = svn_sqlite__column_text(stmt, 2, result_pool);
 
-  return SVN_NO_ERROR;
+  return svn_error_trace(svn_sqlite__reset(stmt));
 }
 
 static svn_error_t *
@@ -11548,9 +11686,9 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
 
      For existing nodes, we should retain the (potentially-switched)
      repository information.  */
-  SVN_ERR(determine_repos_info(&repos_id, &repos_relpath,
-                               wcroot, local_relpath,
-                               scratch_pool, scratch_pool));
+  SVN_ERR(determine_commit_repos_info(&repos_id, &repos_relpath,
+                                      wcroot, local_relpath,
+                                      scratch_pool, scratch_pool));
 
   /* ### is it better to select only the data needed?  */
   SVN_ERR(svn_sqlite__get_statement(&stmt_info, wcroot->sdb,
@@ -12747,6 +12885,27 @@ scan_addition(svn_wc__db_status_t *statu
 }
 
 svn_error_t *
+svn_wc__db_scan_addition_internal(
+              svn_wc__db_status_t *status,
+              const char **op_root_relpath_p,
+              const char **repos_relpath,
+              apr_int64_t *repos_id,
+              const char **original_repos_relpath,
+              apr_int64_t *original_repos_id,
+              svn_revnum_t *original_revision,
+              svn_wc__db_wcroot_t *wcroot,
+              const char *local_relpath,
+              apr_pool_t *result_pool,
+              apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(
+      scan_addition(status, op_root_relpath_p, repos_relpath, repos_id,
+                    original_repos_relpath, original_repos_id,
+                    original_revision, NULL, NULL, NULL,
+                    wcroot, local_relpath, result_pool, scratch_pool));
+}
+
+svn_error_t *
 svn_wc__db_scan_addition(svn_wc__db_status_t *status,
                          const char **op_root_abspath,
                          const char **repos_relpath,

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.h?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db.h Wed Mar  
4 15:56:18 2015
@@ -20,7 +20,7 @@
  * ====================================================================
  * @endcopyright
  *
- * @file svn_wc_db.h
+ * @file wc_db.h
  * @brief The Subversion Working Copy Library - Metadata/Base-Text Support
  *
  * Requires:
@@ -2019,6 +2019,7 @@ struct svn_wc__db_info_t {
   svn_boolean_t moved_here;     /* Only on op-roots. */
 
   svn_boolean_t file_external;
+  svn_boolean_t has_descendants; /* Is dir, or has tc descendants */
 };
 
 /* Return in *NODES a hash mapping name->struct svn_wc__db_info_t for

Modified: 
subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_private.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_private.h?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_private.h 
(original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_private.h 
Wed Mar  4 15:56:18 2015
@@ -313,6 +313,32 @@ svn_wc__db_depth_get_info(svn_wc__db_sta
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool);
 
+svn_error_t *
+svn_wc__db_scan_addition_internal(
+              svn_wc__db_status_t *status,
+              const char **op_root_relpath_p,
+              const char **repos_relpath,
+              apr_int64_t *repos_id,
+              const char **original_repos_relpath,
+              apr_int64_t *original_repos_id,
+              svn_revnum_t *original_revision,
+              svn_wc__db_wcroot_t *wcroot,
+              const char *local_relpath,
+              apr_pool_t *result_pool,
+              apr_pool_t *scratch_pool);
+
+svn_error_t *
+svn_wc__db_scan_deletion_internal(
+                  const char **base_del_relpath,
+                  const char **moved_to_relpath,
+                  const char **work_del_relpath,
+                  const char **moved_to_op_root_relpath,
+                  svn_wc__db_wcroot_t *wcroot,
+                  const char *local_relpath,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool);
+
+
 /* Look up REPOS_ID in WCROOT->SDB and set *REPOS_ROOT_URL and/or *REPOS_UUID
    to its root URL and UUID respectively.  If REPOS_ID is INVALID_REPOS_ID,
    use NULL for both URL and UUID.  Either or both output parameters may be
@@ -345,23 +371,6 @@ svn_wc__db_mark_conflict_internal(svn_wc
 
 /* Transaction handling */
 
-/* A callback which supplies WCROOTs and LOCAL_RELPATHs. */
-typedef svn_error_t *(*svn_wc__db_txn_callback_t)(void *baton,
-                                          svn_wc__db_wcroot_t *wcroot,
-                                          const char *local_relpath,
-                                          apr_pool_t *scratch_pool);
-
-
-/* Run CB_FUNC in a SQLite transaction with CB_BATON, using WCROOT and
-   LOCAL_RELPATH.  If callbacks require additional information, they may
-   provide it using CB_BATON. */
-svn_error_t *
-svn_wc__db_with_txn(svn_wc__db_wcroot_t *wcroot,
-                    const char *local_relpath,
-                    svn_wc__db_txn_callback_t cb_func,
-                    void *cb_baton,
-                    apr_pool_t *scratch_pool);
-
 /* Evaluate the expression EXPR within a transaction.
  *
  * Begin a transaction in WCROOT's DB; evaluate the expression EXPR, which 
would

Modified: 
subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_update_move.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_update_move.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- 
subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_update_move.c 
(original)
+++ 
subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_update_move.c 
Wed Mar  4 15:56:18 2015
@@ -400,7 +400,7 @@ create_tree_conflict(svn_skel_t **confli
 
       if (conflict_operation != svn_wc_operation_update
           && conflict_operation != svn_wc_operation_switch)
-        return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+        return svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL,
                                  _("'%s' already in conflict"),
                                  path_for_error_message(wcroot, local_relpath,
                                                         scratch_pool));
@@ -424,7 +424,7 @@ create_tree_conflict(svn_skel_t **confli
                   && strcmp(move_src_op_root_relpath,
                             svn_dirent_skip_ancestor(wcroot->abspath,
                                                      existing_abspath))))
-            return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
+            return svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL,
                                      _("'%s' already in conflict"),
                                      path_for_error_message(wcroot,
                                                             local_relpath,
@@ -2487,7 +2487,7 @@ static svn_error_t *
 break_moved_away(svn_wc__db_wcroot_t *wcroot,
                  svn_wc__db_t *db,
                  const char *local_relpath,
-                 int src_op_depth,
+                 int parent_src_op_depth,
                  apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
@@ -2501,7 +2501,7 @@ break_moved_away(svn_wc__db_wcroot_t *wc
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_MOVED_DESCENDANTS_SRC));
   SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
-                                         src_op_depth));
+                            parent_src_op_depth));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
   iterpool = svn_pool_create(scratch_pool);

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_util.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_util.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_util.c 
(original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_util.c Wed 
Mar  4 15:56:18 2015
@@ -152,63 +152,3 @@ svn_wc__db_util_open_db(svn_sqlite__db_t
   return SVN_NO_ERROR;
 }
 
-
-/* Some helpful transaction helpers.
-
-   Instead of directly using SQLite transactions, these wrappers
-   relieve the consumer from the need to wrap the wcroot and
-   local_relpath, which are almost always used within the transaction.
-
-   This also means if we later want to implement some wc_db-specific txn
-   handling, we have a convenient place to do it.
-   */
-
-/* A callback which supplies WCROOTs and LOCAL_RELPATHs. */
-typedef svn_error_t *(*db_txn_callback_t)(void *baton,
-                                          svn_wc__db_wcroot_t *wcroot,
-                                          const char *local_relpath,
-                                          apr_pool_t *scratch_pool);
-
-/* Baton for use with run_txn() and with_db_txn(). */
-struct txn_baton_t
-{
-  svn_wc__db_wcroot_t *wcroot;
-  const char *local_relpath;
-
-  db_txn_callback_t cb_func;
-  void *cb_baton;
-};
-
-
-/* Unwrap the sqlite transaction into a wc_db txn.
-   Implements svn_sqlite__transaction_callback_t. */
-static svn_error_t *
-run_txn(void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool)
-{
-  struct txn_baton_t *tb = baton;
-
-  return svn_error_trace(
-    tb->cb_func(tb->cb_baton, tb->wcroot, tb->local_relpath, scratch_pool));
-}
-
-
-/* Run CB_FUNC in a SQLite transaction with CB_BATON, using WCROOT and
-   LOCAL_RELPATH.  If callbacks require additional information, they may
-   provide it using CB_BATON. */
-svn_error_t *
-svn_wc__db_with_txn(svn_wc__db_wcroot_t *wcroot,
-                    const char *local_relpath,
-                    svn_wc__db_txn_callback_t cb_func,
-                    void *cb_baton,
-                    apr_pool_t *scratch_pool)
-{
-  struct txn_baton_t tb;
-
-  tb.wcroot = wcroot;
-  tb.local_relpath = local_relpath;
-  tb.cb_func = cb_func;
-  tb.cb_baton = cb_baton;
-
-  return svn_error_trace(
-    svn_sqlite__with_lock(wcroot->sdb, run_txn, &tb, scratch_pool));
-}

Modified: 
subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_wcroot.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_wcroot.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_wcroot.c 
(original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_wc/wc_db_wcroot.c 
Wed Mar  4 15:56:18 2015
@@ -702,11 +702,9 @@ try_symlink_as_dir:
       if (err)
         {
           if (err->apr_err == SVN_ERR_WC_CORRUPT)
-            return svn_error_quick_wrap(
-              err, apr_psprintf(scratch_pool,
-                                _("Missing a row in WCROOT for '%s'."),
-                                svn_dirent_local_style(original_abspath,
-                                                       scratch_pool)));
+            return svn_error_quick_wrapf(
+              err, _("Missing a row in WCROOT for '%s'."),
+              svn_dirent_local_style(original_abspath, scratch_pool));
           return svn_error_trace(err);
         }
 

Modified: subversion/branches/reuse-ra-session/subversion/svn/cl.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/svn/cl.h?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/svn/cl.h (original)
+++ subversion/branches/reuse-ra-session/subversion/svn/cl.h Wed Mar  4 
15:56:18 2015
@@ -167,7 +167,6 @@ typedef struct svn_cl__opt_state_t
   svn_boolean_t version;         /* print version information */
   svn_boolean_t verbose;         /* be verbose */
   svn_boolean_t update;          /* contact the server for the full story */
-  svn_boolean_t strict;          /* do strictly what was requested */
   svn_stringbuf_t *filedata;     /* contents of file used as option data
                                     (not converted to UTF-8) */
   const char *encoding;          /* the locale/encoding of 'message' and of
@@ -249,6 +248,7 @@ typedef struct svn_cl__opt_state_t
   svn_boolean_t no_newline;        /* do not output the trailing newline */
   svn_boolean_t show_passwords;    /* show cached passwords */
   svn_boolean_t pin_externals;     /* pin externals to last-changed revisions 
*/
+  const char *show_item;           /* print only the given item */
 } svn_cl__opt_state_t;
 
 
@@ -855,6 +855,48 @@ svn_cl__deprecated_merge_reintegrate(con
                                      svn_client_ctx_t *ctx,
                                      apr_pool_t *pool);
 
+
+/* Forward declaration of the similarity check context. */
+typedef struct svn_cl__simcheck_context_t svn_cl__simcheck_context_t;
+
+/* Token definition for the similarity check. */
+typedef struct svn_cl__simcheck_t
+{
+  /* The token we're checking for similarity. */
+  svn_string_t token;
+
+  /* User data associated with this token. */
+  const void *data;
+
+  /*
+   * The following fields are populated by svn_cl__similarity_check.
+   */
+
+  /* Similarity score [0..SVN_STRING__SIM_RANGE_MAX] */
+  apr_size_t score;
+
+  /* Number of characters of difference from the key. */
+  apr_size_t diff;
+
+  /* Similarity check context (private) */
+  svn_cl__simcheck_context_t *context;
+} svn_cl__simcheck_t;
+
+/* Find the entries in TOKENS that are most similar to KEY.
+ * TOKEN_COUNT is the number of entries in the (mutable) TOKENS array.
+ * Use SCRATCH_POOL for temporary allocations.
+ *
+ * On return, the TOKENS array will be sorted according to similarity
+ * to KEY, in descending order. The return value will be zero if the
+ * first token is an exact match; otherwise, it will be one more than
+ * the number of tokens that are at least two-thirds similar to KEY.
+ */
+apr_size_t
+svn_cl__similarity_check(const char *key,
+                         svn_cl__simcheck_t **tokens,
+                         apr_size_t token_count,
+                         apr_pool_t *scratch_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/reuse-ra-session/subversion/svn/info-cmd.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/svn/info-cmd.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/svn/info-cmd.c (original)
+++ subversion/branches/reuse-ra-session/subversion/svn/info-cmd.c Wed Mar  4 
15:56:18 2015
@@ -76,6 +76,168 @@ schedule_str(svn_wc_schedule_t schedule)
     }
 }
 
+/* Return a relative URL from information in INFO using POOL for
+   temporary allocation. */
+static const char*
+relative_url(const svn_client_info2_t *info, apr_pool_t *pool)
+{
+  return apr_pstrcat(pool, "^/",
+                     svn_path_uri_encode(
+                         svn_uri_skip_ancestor(info->repos_root_URL,
+                                               info->URL, pool),
+                         pool), SVN_VA_NULL);
+}
+
+
+/* The kinds of items for print_info_item(). */
+typedef enum
+{
+  /* Entry kind */
+  info_item_kind,
+
+  /* Repository location. */
+  info_item_url,
+  info_item_relative_url,
+  info_item_repos_root_url,
+  info_item_repos_uuid,
+
+  /* Working copy revision or repository HEAD revision */
+  info_item_revision,
+
+  /* Commit details. */
+  info_item_last_changed_rev,
+  info_item_last_changed_date,
+  info_item_last_changed_author,
+
+  /* Working copy information */
+  info_item_wc_root
+} info_item_t;
+
+/* Mapping between option keywords and info_item_t. */
+typedef struct info_item_map_t
+{
+  const svn_string_t keyword;
+  const info_item_t print_what;
+} info_item_map_t;
+
+#define MAKE_STRING(x) { x, sizeof(x) - 1 }
+static const info_item_map_t info_item_map[] =
+  {
+    { MAKE_STRING("kind"),                info_item_kind },
+    { MAKE_STRING("url"),                 info_item_url },
+    { MAKE_STRING("relative-url"),        info_item_relative_url },
+    { MAKE_STRING("repos-root-url"),      info_item_repos_root_url },
+    { MAKE_STRING("repos-uuid"),          info_item_repos_uuid },
+    { MAKE_STRING("revision"),            info_item_revision },
+    { MAKE_STRING("last-changed-revision"),
+                                          info_item_last_changed_rev },
+    { MAKE_STRING("last-changed-date"),   info_item_last_changed_date },
+    { MAKE_STRING("last-changed-author"), info_item_last_changed_author },
+    { MAKE_STRING("wc-root"),             info_item_wc_root }
+  };
+#undef MAKE_STRING
+
+static const apr_size_t info_item_map_len =
+  (sizeof(info_item_map) / sizeof(info_item_map[0]));
+
+
+/* The baton type used by the info receiver functions. */
+typedef struct print_info_baton_t
+{
+  /* The path prefix that output paths should be normalized to. */
+  const char *path_prefix;
+
+  /*
+   * The following fields are used by print_info_item().
+   */
+
+  /* Which item to print. */
+  info_item_t print_what;
+
+  /* Do we expect to show info for multiple targets? */
+  svn_boolean_t multiple_targets;
+
+  /* TRUE iff the current is a local path. */
+  svn_boolean_t target_is_path;
+
+  /* Did we already print a line of output? */
+  svn_boolean_t start_new_line;
+} print_info_baton_t;
+
+
+/* Find the appropriate info_item_t for KEYWORD and initialize
+ * RECEIVER_BATON for print_info_item(). Use SCRATCH_POOL for
+ * temporary allocation.
+ */
+static svn_error_t *
+find_print_what(const char *keyword,
+                print_info_baton_t *receiver_baton,
+                apr_pool_t *scratch_pool)
+{
+  svn_cl__simcheck_t **keywords = apr_palloc(
+      scratch_pool, info_item_map_len * sizeof(svn_cl__simcheck_t*));
+  svn_cl__simcheck_t *kwbuf = apr_palloc(
+      scratch_pool, info_item_map_len * sizeof(svn_cl__simcheck_t));
+  apr_size_t i;
+
+  for (i = 0; i < info_item_map_len; ++i)
+    {
+      keywords[i] = &kwbuf[i];
+      kwbuf[i].token.data = info_item_map[i].keyword.data;
+      kwbuf[i].token.len = info_item_map[i].keyword.len;
+      kwbuf[i].data = &info_item_map[i];
+    }
+
+  switch (svn_cl__similarity_check(keyword, keywords,
+                                   info_item_map_len, scratch_pool))
+    {
+      const info_item_map_t *kw0;
+      const info_item_map_t *kw1;
+      const info_item_map_t *kw2;
+
+    case 0:                     /* Exact match. */
+      kw0 = keywords[0]->data;
+      receiver_baton->print_what = kw0->print_what;
+      return SVN_NO_ERROR;
+
+    case 1:
+      /* The best alternative isn't good enough */
+      return svn_error_createf(
+          SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+          _("'%s' is not a valid value for --show-item"),
+          keyword);
+
+    case 2:
+      /* There is only one good candidate */
+      kw0 = keywords[0]->data;
+      return svn_error_createf(
+          SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+          _("'%s' is not a valid value for --show-item;"
+            " did you mean '%s'?"),
+          keyword, kw0->keyword.data);
+
+    case 3:
+      /* Suggest a list of the most likely candidates */
+      kw0 = keywords[0]->data;
+      kw1 = keywords[1]->data;
+      return svn_error_createf(
+          SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+          _("'%s' is not a valid value for --show-item;"
+            " did you mean '%s' or '%s'?"),
+          keyword, kw0->keyword.data, kw1->keyword.data);
+
+    default:
+      /* Never suggest more than three candidates */
+      kw0 = keywords[0]->data;
+      kw1 = keywords[1]->data;
+      kw2 = keywords[2]->data;
+      return svn_error_createf(
+          SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+          _("'%s' is not a valid value for --show-item;"
+            " did you mean '%s', '%s' or '%s'?"),
+          keyword, kw0->keyword.data, kw1->keyword.data, kw2->keyword.data);
+    }
+}
 
 /* A callback of type svn_client_info_receiver2_t.
    Prints svn info in xml mode to standard out */
@@ -87,7 +249,7 @@ print_info_xml(void *baton,
 {
   svn_stringbuf_t *sb = svn_stringbuf_create_empty(pool);
   const char *rev_str;
-  const char *path_prefix = baton;
+  print_info_baton_t *const receiver_baton = baton;
 
   if (SVN_IS_VALID_REVNUM(info->rev))
     rev_str = apr_psprintf(pool, "%ld", info->rev);
@@ -97,7 +259,7 @@ print_info_xml(void *baton,
   /* "<entry ...>" */
   svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "entry",
                         "path", svn_cl__local_style_skip_ancestor(
-                                  path_prefix, target, pool),
+                                  receiver_baton->path_prefix, target, pool),
                         "kind", svn_cl__node_kind_str_xml(info->kind),
                         "revision", rev_str,
                         SVN_VA_NULL);
@@ -109,13 +271,7 @@ print_info_xml(void *baton,
     {
       /* "<relative-url> xx </relative-url>" */
       svn_cl__xml_tagged_cdata(&sb, pool, "relative-url",
-                               apr_pstrcat(pool, "^/",
-                                           svn_path_uri_encode(
-                                               svn_uri_skip_ancestor(
-                                                   info->repos_root_URL,
-                                                   info->URL, pool),
-                                               pool),
-                                           SVN_VA_NULL));
+                               relative_url(info, pool));
     }
 
   if (info->repos_root_URL || info->repos_UUID)
@@ -263,11 +419,11 @@ print_info(void *baton,
            const svn_client_info2_t *info,
            apr_pool_t *pool)
 {
-  const char *path_prefix = baton;
+  print_info_baton_t *const receiver_baton = baton;
 
   SVN_ERR(svn_cmdline_printf(pool, _("Path: %s\n"),
                              svn_cl__local_style_skip_ancestor(
-                               path_prefix, target, pool)));
+                               receiver_baton->path_prefix, target, pool)));
 
   /* ### remove this someday:  it's only here for cmdline output
      compatibility with svn 1.1 and older.  */
@@ -285,11 +441,8 @@ print_info(void *baton,
     SVN_ERR(svn_cmdline_printf(pool, _("URL: %s\n"), info->URL));
 
   if (info->URL && info->repos_root_URL)
-    SVN_ERR(svn_cmdline_printf(pool, _("Relative URL: ^/%s\n"),
-                               svn_path_uri_encode(
-                                   svn_uri_skip_ancestor(info->repos_root_URL,
-                                                         info->URL, pool),
-                                   pool)));
+    SVN_ERR(svn_cmdline_printf(pool, _("Relative URL: %s\n"),
+                               relative_url(info, pool)));
 
   if (info->repos_root_URL)
     SVN_ERR(svn_cmdline_printf(pool, _("Repository Root: %s\n"),
@@ -391,14 +544,14 @@ print_info(void *baton,
       if (info->wc_info->moved_from_abspath)
         SVN_ERR(svn_cmdline_printf(pool, _("Moved From: %s\n"),
                                    svn_cl__local_style_skip_ancestor(
-                                      path_prefix,
+                                      receiver_baton->path_prefix,
                                       info->wc_info->moved_from_abspath,
                                       pool)));
 
       if (info->wc_info->moved_to_abspath)
         SVN_ERR(svn_cmdline_printf(pool, _("Moved To: %s\n"),
                                    svn_cl__local_style_skip_ancestor(
-                                      path_prefix,
+                                      receiver_baton->path_prefix,
                                       info->wc_info->moved_to_abspath,
                                       pool)));
     }
@@ -446,21 +599,24 @@ print_info(void *baton,
                       SVN_ERR(svn_cmdline_printf(pool,
                                 _("Conflict Previous Base File: %s\n"),
                                 svn_cl__local_style_skip_ancestor(
-                                        path_prefix, conflict->base_abspath,
+                                        receiver_baton->path_prefix,
+                                        conflict->base_abspath,
                                         pool)));
 
                     if (conflict->my_abspath)
                       SVN_ERR(svn_cmdline_printf(pool,
                                 _("Conflict Previous Working File: %s\n"),
                                 svn_cl__local_style_skip_ancestor(
-                                        path_prefix, conflict->my_abspath,
+                                        receiver_baton->path_prefix,
+                                        conflict->my_abspath,
                                         pool)));
 
                     if (conflict->their_abspath)
                       SVN_ERR(svn_cmdline_printf(pool,
                                 _("Conflict Current Base File: %s\n"),
                                 svn_cl__local_style_skip_ancestor(
-                                        path_prefix, conflict->their_abspath,
+                                        receiver_baton->path_prefix,
+                                        conflict->their_abspath,
                                         pool)));
                   break;
 
@@ -469,7 +625,7 @@ print_info(void *baton,
                       SVN_ERR(svn_cmdline_printf(pool,
                                 _("Conflict Properties File: %s\n"),
                                 svn_cl__local_style_skip_ancestor(
-                                        path_prefix,
+                                        receiver_baton->path_prefix,
                                         conflict->prop_reject_abspath,
                                         pool)));
                     printed_prop_conflict_file = TRUE;
@@ -577,6 +733,123 @@ print_info(void *baton,
 }
 
 
+/* Helper for print_info_item(): Print the value TEXT for TARGET_PATH,
+   either of which may be NULL. Use POOL for temporary allocation. */
+static svn_error_t *
+print_info_item_string(const char *text, const char *target_path,
+                       apr_pool_t *pool)
+{
+  if (text)
+    {
+      if (target_path)
+        SVN_ERR(svn_cmdline_printf(pool, "%-10s %s", text, target_path));
+      else
+        SVN_ERR(svn_cmdline_fputs(text, stdout, pool));
+    }
+  else if (target_path)
+    SVN_ERR(svn_cmdline_printf(pool, "%-10s %s", "", target_path));
+
+  return SVN_NO_ERROR;
+}
+
+/* Helper for print_info_item(): Print the revision number REV, which
+   may be SVN_INVALID_REVNUM, for TARGET_PATH, which may be NULL. Use
+   POOL for temporary allocation. */
+static svn_error_t *
+print_info_item_revision(svn_revnum_t rev, const char *target_path,
+                         apr_pool_t *pool)
+{
+  if (SVN_IS_VALID_REVNUM(rev))
+    {
+      if (target_path)
+        SVN_ERR(svn_cmdline_printf(pool, "%-10ld %s", rev, target_path));
+      else
+        SVN_ERR(svn_cmdline_printf(pool, "%-10ld", rev));
+    }
+  else if (target_path)
+    SVN_ERR(svn_cmdline_printf(pool, "%-10s %s", "", target_path));
+
+  return SVN_NO_ERROR;
+}
+
+/* A callback of type svn_client_info_receiver2_t. */
+static svn_error_t *
+print_info_item(void *baton,
+                  const char *target,
+                  const svn_client_info2_t *info,
+                  apr_pool_t *pool)
+{
+  print_info_baton_t *const receiver_baton = baton;
+  const char *const target_path =
+    (!receiver_baton->multiple_targets ? NULL
+     : (!receiver_baton->target_is_path ? info->URL
+        : svn_cl__local_style_skip_ancestor(
+            receiver_baton->path_prefix, target, pool)));
+
+  if (receiver_baton->start_new_line)
+    SVN_ERR(svn_cmdline_fputs("\n", stdout, pool));
+
+  switch (receiver_baton->print_what)
+    {
+    case info_item_kind:
+      SVN_ERR(print_info_item_string(svn_node_kind_to_word(info->kind),
+                                     target_path, pool));
+      break;
+
+    case info_item_url:
+      SVN_ERR(print_info_item_string(info->URL, target_path, pool));
+      break;
+
+    case info_item_relative_url:
+      SVN_ERR(print_info_item_string(relative_url(info, pool),
+                                     target_path, pool));
+      break;
+
+    case info_item_repos_root_url:
+      SVN_ERR(print_info_item_string(info->repos_root_URL, target_path, pool));
+      break;
+
+    case info_item_repos_uuid:
+      SVN_ERR(print_info_item_string(info->repos_UUID, target_path, pool));
+      break;
+
+    case info_item_revision:
+      SVN_ERR(print_info_item_revision(info->rev, target_path, pool));
+      break;
+
+    case info_item_last_changed_rev:
+      SVN_ERR(print_info_item_revision(info->last_changed_rev,
+                                       target_path, pool));
+      break;
+
+    case info_item_last_changed_date:
+      SVN_ERR(print_info_item_string(
+                  (!info->last_changed_date ? NULL
+                   : svn_time_to_cstring(info->last_changed_date, pool)),
+                  target_path, pool));
+      break;
+
+    case info_item_last_changed_author:
+      SVN_ERR(print_info_item_string(info->last_changed_author,
+                                     target_path, pool));
+      break;
+
+    case info_item_wc_root:
+      SVN_ERR(print_info_item_string(
+                  (info->wc_info && info->wc_info->wcroot_abspath
+                   ? info->wc_info->wcroot_abspath : NULL),
+                  target_path, pool));
+      break;
+
+    default:
+      SVN_ERR_MALFUNCTION();
+    }
+
+  receiver_baton->start_new_line = TRUE;
+  return SVN_NO_ERROR;
+}
+
+
 /* This implements the `svn_opt_subcommand_t' interface. */
 svn_error_t *
 svn_cl__info(apr_getopt_t *os,
@@ -592,7 +865,7 @@ svn_cl__info(apr_getopt_t *os,
   svn_boolean_t seen_nonexistent_target = FALSE;
   svn_opt_revision_t peg_revision;
   svn_client_info_receiver2_t receiver;
-  const char *path_prefix;
+  print_info_baton_t receiver_baton = { 0 };
 
   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                       opt_state->targets,
@@ -605,26 +878,59 @@ svn_cl__info(apr_getopt_t *os,
     {
       receiver = print_info_xml;
 
+      if (opt_state->show_item)
+        return svn_error_create(
+            SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+            _("--show-item is not valid in --xml mode"));
+      if (opt_state->no_newline)
+        return svn_error_create(
+            SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+            _("--no-newline is not valid in --xml mode"));
+
       /* If output is not incremental, output the XML header and wrap
          everything in a top-level element. This makes the output in
          its entirety a well-formed XML document. */
       if (! opt_state->incremental)
         SVN_ERR(svn_cl__xml_print_header("info", pool));
     }
+  else if (opt_state->show_item)
+    {
+      receiver = print_info_item;
+
+      if (opt_state->incremental)
+        return svn_error_create(
+            SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+            _("--incremental is only valid in --xml mode"));
+
+      receiver_baton.multiple_targets = (opt_state->depth > svn_depth_empty
+                                         || targets->nelts > 1);
+      if (receiver_baton.multiple_targets && opt_state->no_newline)
+        return svn_error_create(
+            SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+            _("--no-newline is only available for single-target,"
+              " non-recursive info operations"));
+
+      SVN_ERR(find_print_what(opt_state->show_item, &receiver_baton, pool));
+      receiver_baton.start_new_line = FALSE;
+    }
   else
     {
       receiver = print_info;
 
       if (opt_state->incremental)
-        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                                _("'incremental' option only valid in XML "
-                                  "mode"));
+        return svn_error_create(
+            SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+            _("--incremental is only valid in --xml mode"));
+      if (opt_state->no_newline)
+        return svn_error_create(
+            SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+            _("--no-newline' is only valid with --show-item"));
     }
 
   if (opt_state->depth == svn_depth_unknown)
     opt_state->depth = svn_depth_empty;
 
-  SVN_ERR(svn_dirent_get_absolute(&path_prefix, "", pool));
+  SVN_ERR(svn_dirent_get_absolute(&receiver_baton.path_prefix, "", pool));
 
   for (i = 0; i < targets->nelts; i++)
     {
@@ -642,10 +948,12 @@ svn_cl__info(apr_getopt_t *os,
         {
           if (peg_revision.kind == svn_opt_revision_unspecified)
             peg_revision.kind = svn_opt_revision_head;
+          receiver_baton.target_is_path = FALSE;
         }
       else
         {
           SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, subpool));
+          receiver_baton.target_is_path = TRUE;
         }
 
       err = svn_client_info4(truepath,
@@ -655,7 +963,7 @@ svn_cl__info(apr_getopt_t *os,
                              TRUE /* fetch_actual_only */,
                              opt_state->include_externals,
                              opt_state->changelists,
-                             receiver, (void *) path_prefix,
+                             receiver, &receiver_baton,
                              ctx, subpool);
 
       if (err)
@@ -682,6 +990,9 @@ svn_cl__info(apr_getopt_t *os,
 
   if (opt_state->xml && (! opt_state->incremental))
     SVN_ERR(svn_cl__xml_print_footer("info", pool));
+  else if (opt_state->show_item && !opt_state->no_newline
+           && receiver_baton.start_new_line)
+    SVN_ERR(svn_cmdline_fputs("\n", stdout, pool));
 
   if (seen_nonexistent_target)
     return svn_error_create(

Modified: subversion/branches/reuse-ra-session/subversion/svn/propget-cmd.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/svn/propget-cmd.c?rev=1664059&r1=1664058&r2=1664059&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/svn/propget-cmd.c (original)
+++ subversion/branches/reuse-ra-session/subversion/svn/propget-cmd.c Wed Mar  
4 15:56:18 2015
@@ -322,11 +322,11 @@ svn_cl__propget(apr_getopt_t *os,
   svn_stream_t *out;
   svn_boolean_t warned = FALSE;
 
-  if (opt_state->verbose && (opt_state->revprop || opt_state->strict
+  if (opt_state->verbose && (opt_state->revprop || opt_state->no_newline
                              || opt_state->xml))
     return svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
                             _("--verbose cannot be used with --revprop or "
-                              "--strict or --xml"));
+                              "--no-newline or --xml"));
 
   /* PNAME is first argument (and PNAME_UTF8 will be a UTF-8 version
      thereof) */
@@ -411,7 +411,7 @@ svn_cl__propget(apr_getopt_t *os,
 
               SVN_ERR(stream_write(out, printable_val->data,
                                    printable_val->len));
-              if (! opt_state->strict)
+              if (! opt_state->no_newline)
                 SVN_ERR(stream_write(out, APR_EOL_STR, strlen(APR_EOL_STR)));
             }
         }
@@ -427,16 +427,16 @@ svn_cl__propget(apr_getopt_t *os,
       if (opt_state->depth == svn_depth_unknown)
         opt_state->depth = svn_depth_empty;
 
-      /* Strict mode only makes sense for a single target.  So make
+      /* No-newline mode only makes sense for a single target.  So make
          sure we have only a single target, and that we're not being
          asked to recurse on that target. */
-      if (opt_state->strict
+      if (opt_state->no_newline
           && ((targets->nelts > 1) || (opt_state->depth != svn_depth_empty)
               || (opt_state->show_inherited_props)))
         return svn_error_create
           (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-           _("Strict output of property values only available for single-"
-             "target, non-recursive propget operations"));
+           _("--no-newline is only available for single-target,"
+             " non-recursive propget operations"));
 
       for (i = 0; i < targets->nelts; i++)
         {
@@ -472,15 +472,15 @@ svn_cl__propget(apr_getopt_t *os,
           /* Any time there is more than one thing to print, or where
              the path associated with a printed thing is not obvious,
              we'll print filenames.  That is, unless we've been told
-             not to do so with the --strict option. */
+             not to do so with the --no-newline option. */
           print_filenames = ((opt_state->depth > svn_depth_empty
                               || targets->nelts > 1
                               || apr_hash_count(props) > 1
                               || opt_state->verbose
                               || opt_state->show_inherited_props)
-                             && (! opt_state->strict));
-          omit_newline = opt_state->strict;
-          like_proplist = opt_state->verbose && !opt_state->strict;
+                             && (! opt_state->no_newline));
+          omit_newline = opt_state->no_newline;
+          like_proplist = opt_state->verbose && !opt_state->no_newline;
 
           /* If there are no properties, and exactly one node was queried,
              then warn. */


Reply via email to