You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pr...@apache.org on 2013/02/13 11:21:36 UTC

svn commit: r1445542 [3/16] - in /subversion/branches/verify-keep-going: ./ build/generator/ build/generator/swig/ build/generator/templates/ build/win32/ contrib/server-side/fsfsfixer/fixer/ contrib/server-side/svncutter/ notes/ notes/api-errata/1.7/ ...

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/diff_local.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/diff_local.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/diff_local.c Wed Feb 13 10:21:33 2013
@@ -287,9 +287,16 @@ arbitrary_diff_walker(void *baton, const
                       const apr_finfo_t *finfo,
                       apr_pool_t *scratch_pool);
 
-/* Produce a diff between two arbitrary directories at LOCAL_ABSPATH1 and
- * LOCAL_ABSPATH2, using the provided diff callbacks to show file changes
- * and, for versioned nodes, property changes.
+/* Another forward declaration. */
+static svn_error_t *
+arbitrary_diff_this_dir(struct arbitrary_diff_walker_baton *b,
+                        const char *local_abspath,
+                        svn_depth_t depth,
+                        apr_pool_t *scratch_pool);
+
+/* Produce a diff of depth DEPTH between two arbitrary directories at
+ * LOCAL_ABSPATH1 and LOCAL_ABSPATH2, using the provided diff callbacks
+ * to show file changes and, for versioned nodes, property changes.
  *
  * If ROOT_ABSPATH1 and ROOT_ABSPATH2 are not NULL, show paths in diffs
  * relative to these roots, rather than relative to LOCAL_ABSPATH1 and
@@ -300,6 +307,7 @@ do_arbitrary_dirs_diff(const char *local
                        const char *local_abspath2,
                        const char *root_abspath1,
                        const char *root_abspath2,
+                       svn_depth_t depth,
                        const svn_wc_diff_callbacks4_t *callbacks,
                        void *diff_baton,
                        svn_client_ctx_t *ctx,
@@ -331,22 +339,25 @@ do_arbitrary_dirs_diff(const char *local
                                    NULL, svn_io_file_del_on_pool_cleanup,
                                    scratch_pool, scratch_pool));
 
-  SVN_ERR(svn_io_dir_walk2(b.recursing_within_added_subtree ? local_abspath2
-                                                            : local_abspath1,
-                           0, arbitrary_diff_walker, &b, scratch_pool));
-
+  if (depth <= svn_depth_immediates)
+    SVN_ERR(arbitrary_diff_this_dir(&b, local_abspath1, depth, scratch_pool));
+  else if (depth == svn_depth_infinity)
+    SVN_ERR(svn_io_dir_walk2(b.recursing_within_added_subtree ? local_abspath2
+                                                              : local_abspath1,
+                             0, arbitrary_diff_walker, &b, scratch_pool));
   return SVN_NO_ERROR;
 }
 
-/* An implementation of svn_io_walk_func_t.
- * Note: LOCAL_ABSPATH is the path being crawled and can be on either side
+/* Produce a diff of depth DEPTH for the directory at LOCAL_ABSPATH,
+ * using information from the arbitrary_diff_walker_baton B.
+ * LOCAL_ABSPATH is the path being crawled and can be on either side
  * of the diff depending on baton->recursing_within_added_subtree. */
 static svn_error_t *
-arbitrary_diff_walker(void *baton, const char *local_abspath,
-                      const apr_finfo_t *finfo,
-                      apr_pool_t *scratch_pool)
+arbitrary_diff_this_dir(struct arbitrary_diff_walker_baton *b,
+                        const char *local_abspath,
+                        svn_depth_t depth,
+                        apr_pool_t *scratch_pool)
 {
-  struct arbitrary_diff_walker_baton *b = baton;
   const char *local_abspath1;
   const char *local_abspath2;
   svn_node_kind_t kind1;
@@ -359,12 +370,6 @@ arbitrary_diff_walker(void *baton, const
   int i;
   apr_pool_t *iterpool;
 
-  if (b->ctx->cancel_func)
-    SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton));
-
-  if (finfo->filetype != APR_DIR)
-    return SVN_NO_ERROR;
-
   if (b->recursing_within_adm_dir)
     {
       if (svn_dirent_skip_ancestor(b->adm_dir_abspath, local_abspath))
@@ -398,12 +403,15 @@ arbitrary_diff_walker(void *baton, const
                                    scratch_pool);
   SVN_ERR(svn_io_check_resolved_path(local_abspath2, &kind2, scratch_pool));
 
-  if (kind1 == svn_node_dir)
-    SVN_ERR(svn_io_get_dirents3(&dirents1, local_abspath1,
-                                TRUE, /* only_check_type */
-                                scratch_pool, scratch_pool));
-  else
-    dirents1 = apr_hash_make(scratch_pool);
+  if (depth > svn_depth_empty)
+    {
+      if (kind1 == svn_node_dir)
+        SVN_ERR(svn_io_get_dirents3(&dirents1, local_abspath1,
+                                    TRUE, /* only_check_type */
+                                    scratch_pool, scratch_pool));
+      else
+        dirents1 = apr_hash_make(scratch_pool);
+    }
 
   if (kind2 == svn_node_dir)
     {
@@ -425,14 +433,20 @@ arbitrary_diff_walker(void *baton, const
                                                 b->diff_baton,
                                                 scratch_pool));
 
-      /* Read directory entries. */
-      SVN_ERR(svn_io_get_dirents3(&dirents2, local_abspath2,
-                                  TRUE, /* only_check_type */
-                                  scratch_pool, scratch_pool));
+      if (depth > svn_depth_empty)
+        {
+          /* Read directory entries. */
+          SVN_ERR(svn_io_get_dirents3(&dirents2, local_abspath2,
+                                      TRUE, /* only_check_type */
+                                      scratch_pool, scratch_pool));
+        }
     }
-  else
+  else if (depth > svn_depth_empty)
     dirents2 = apr_hash_make(scratch_pool);
 
+  if (depth <= svn_depth_empty)
+    return SVN_NO_ERROR;
+
   /* Compare dirents1 to dirents2 and show added/deleted/changed files. */
   merged_dirents = apr_hash_merge(scratch_pool, dirents1, dirents2,
                                   NULL, NULL);
@@ -482,7 +496,25 @@ arbitrary_diff_walker(void *baton, const
 
       if (dirent1->kind == svn_node_dir &&
           dirent2->kind == svn_node_dir)
-        continue;
+        {
+          if (depth == svn_depth_immediates)
+            {
+              /* Not using the walker, so show property diffs on these dirs. */
+              SVN_ERR(do_arbitrary_dirs_diff(child1_abspath, child2_abspath,
+                                             b->root1_abspath, b->root2_abspath,
+                                             svn_depth_empty,
+                                             b->callbacks, b->diff_baton,
+                                             b->ctx, iterpool));
+            }
+          else
+            {
+              /* Either the walker will visit these directories (with
+               * depth=infinity) and they will be processed as 'this dir'
+               * later, or we're showing file children only (depth=files). */
+              continue;
+            }
+
+        }
 
       /* Files that exist only in dirents1. */
       if (dirent1->kind == svn_node_file &&
@@ -521,10 +553,14 @@ arbitrary_diff_walker(void *baton, const
 
       /* Directories that only exist in dirents2. These aren't crawled
        * by this walker so we have to crawl them separately. */
-      if (dirent2->kind == svn_node_dir &&
+      if (depth > svn_depth_files &&
+          dirent2->kind == svn_node_dir &&
           (dirent1->kind == svn_node_file || dirent1->kind == svn_node_none))
         SVN_ERR(do_arbitrary_dirs_diff(child1_abspath, child2_abspath,
                                        b->root1_abspath, b->root2_abspath,
+                                       depth <= svn_depth_immediates
+                                         ? svn_depth_empty
+                                         : svn_depth_infinity ,
                                        b->callbacks, b->diff_baton,
                                        b->ctx, iterpool));
     }
@@ -534,14 +570,32 @@ arbitrary_diff_walker(void *baton, const
   return SVN_NO_ERROR;
 }
 
-/* Produce a diff between two files or two directories at LOCAL_ABSPATH1
- * and LOCAL_ABSPATH2, using the provided diff callbacks to show changes
- * in files. The files and directories involved may be part of a working
- * copy or they may be unversioned. For versioned files, show property
- * changes, too. */
+/* An implementation of svn_io_walk_func_t.
+ * Note: LOCAL_ABSPATH is the path being crawled and can be on either side
+ * of the diff depending on baton->recursing_within_added_subtree. */
+static svn_error_t *
+arbitrary_diff_walker(void *baton, const char *local_abspath,
+                      const apr_finfo_t *finfo,
+                      apr_pool_t *scratch_pool)
+{
+  struct arbitrary_diff_walker_baton *b = baton;
+
+  if (b->ctx->cancel_func)
+    SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton));
+
+  if (finfo->filetype != APR_DIR)
+    return SVN_NO_ERROR;
+
+  SVN_ERR(arbitrary_diff_this_dir(b, local_abspath, svn_depth_infinity,
+                                  scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_client__arbitrary_nodes_diff(const char *local_abspath1,
                                  const char *local_abspath2,
+                                 svn_depth_t depth,
                                  const svn_wc_diff_callbacks4_t *callbacks,
                                  void *diff_baton,
                                  svn_client_ctx_t *ctx,
@@ -558,6 +612,9 @@ svn_client__arbitrary_nodes_diff(const c
                              _("'%s' is not the same node kind as '%s'"),
                              local_abspath1, local_abspath2);
 
+  if (depth == svn_depth_unknown)
+    depth = svn_depth_infinity;
+
   if (kind1 == svn_node_file)
     SVN_ERR(do_arbitrary_files_diff(local_abspath1, local_abspath2,
                                     svn_dirent_basename(local_abspath1,
@@ -567,7 +624,7 @@ svn_client__arbitrary_nodes_diff(const c
                                     ctx, scratch_pool));
   else if (kind1 == svn_node_dir)
     SVN_ERR(do_arbitrary_dirs_diff(local_abspath1, local_abspath2,
-                                   NULL, NULL,
+                                   NULL, NULL, depth,
                                    callbacks, diff_baton,
                                    ctx, scratch_pool));
   else

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/externals.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/externals.c Wed Feb 13 10:21:33 2013
@@ -212,9 +212,21 @@ switch_dir_external(const char *local_ab
 
              To do so, we need to know the repository root URL of the
              external working copy as it currently sits. */
-          SVN_ERR(svn_wc__node_get_repos_info(&repos_root_url, &repos_uuid,
-                                              ctx->wc_ctx, local_abspath,
-                                              pool, subpool));
+          err = svn_wc__node_get_repos_info(NULL, NULL,
+                                            &repos_root_url, &repos_uuid,
+                                            ctx->wc_ctx, local_abspath,
+                                            pool, subpool);
+          if (err)
+            {
+              if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND
+                  && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
+                return svn_error_trace(err);
+
+              svn_error_clear(err);
+              repos_root_url = NULL;
+              repos_uuid = NULL;
+            }
+
           if (repos_root_url)
             {
               /* If the new external target URL is not obviously a
@@ -315,7 +327,8 @@ switch_dir_external(const char *local_ab
                                         FALSE, FALSE, timestamp_sleep,
                                         ctx, pool));
 
-  SVN_ERR(svn_wc__node_get_repos_info(&repos_root_url,
+  SVN_ERR(svn_wc__node_get_repos_info(NULL, NULL,
+                                      &repos_root_url,
                                       &repos_uuid,
                                       ctx->wc_ctx, local_abspath,
                                       pool, pool));
@@ -739,6 +752,7 @@ handle_external_item_change(svn_client_c
             const char *local_repos_root_url;
             const char *local_repos_uuid;
             const char *ext_repos_relpath;
+            svn_error_t *err;
 
             /*
              * The working copy library currently requires that all files
@@ -749,11 +763,22 @@ handle_external_item_change(svn_client_c
              * sure both URLs point to the same repository. See issue #4087.
              */
 
-            SVN_ERR(svn_wc__node_get_repos_info(&local_repos_root_url,
-                                                &local_repos_uuid,
-                                                ctx->wc_ctx,
-                                                parent_dir_abspath,
-                                                scratch_pool, scratch_pool));
+            err = svn_wc__node_get_repos_info(NULL, NULL,
+                                              &local_repos_root_url,
+                                              &local_repos_uuid,
+                                              ctx->wc_ctx, parent_dir_abspath,
+                                              scratch_pool, scratch_pool);
+            if (err)
+              {
+                if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND
+                    && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
+                  return svn_error_trace(err);
+
+                svn_error_clear(err);
+                local_repos_root_url = NULL;
+                local_repos_uuid = NULL;
+              }
+
             ext_repos_relpath = svn_uri_skip_ancestor(new_loc->repos_root_url,
                                                       new_url, scratch_pool);
             if (local_repos_uuid == NULL || local_repos_root_url == NULL ||

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/locking_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/locking_commands.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/locking_commands.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/locking_commands.c Wed Feb 13 10:21:33 2013
@@ -189,6 +189,14 @@ condense_targets(const char **common_par
   return SVN_NO_ERROR;
 }
 
+/* Lock info. Used in organize_lock_targets.
+   ### Maybe return this instead of the ugly hashes? */
+struct wc_lock_item_t
+{
+  svn_revnum_t revision;
+  const char *lock_token;
+};
+
 /* Set *COMMON_PARENT_URL to the nearest common parent URL of all TARGETS.
  * If TARGETS are local paths, then the entry for each path is examined
  * and *COMMON_PARENT is set to the common parent URL for all the
@@ -225,7 +233,7 @@ organize_lock_targets(const char **commo
                       const apr_array_header_t *targets,
                       svn_boolean_t do_lock,
                       svn_boolean_t force,
-                      svn_client_ctx_t *ctx,
+                      svn_wc_context_t *wc_ctx,
                       apr_pool_t *result_pool,
                       apr_pool_t *scratch_pool)
 {
@@ -234,6 +242,7 @@ organize_lock_targets(const char **commo
   apr_hash_t *rel_targets_ret = apr_hash_make(result_pool);
   apr_hash_t *rel_fs_paths = NULL;
   apr_array_header_t *rel_targets;
+  apr_hash_t *wc_info = apr_hash_make(scratch_pool);
   svn_boolean_t url_mode;
   int i;
 
@@ -289,20 +298,38 @@ organize_lock_targets(const char **commo
                                    sizeof(const char *));
       for (i = 0; i < rel_targets->nelts; i++)
         {
-          const char *rel_target, *local_abspath, *target_url;
+          const char *rel_target;
+          const char *repos_relpath;
+          const char *repos_root_url;
+          const char *target_url;
+          struct wc_lock_item_t *wli;
+          const char *local_abspath;
 
           svn_pool_clear(iterpool);
 
           rel_target = APR_ARRAY_IDX(rel_targets, i, const char *);
-          local_abspath = svn_dirent_join(common_dirent, rel_target, iterpool);
-          SVN_ERR(svn_wc__node_get_url(&target_url, ctx->wc_ctx, local_abspath,
-                                       scratch_pool, iterpool));
-          if (! target_url)
-            return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
-                                     _("'%s' has no URL"),
+          local_abspath = svn_dirent_join(common_dirent, rel_target, scratch_pool);
+          wli = apr_pcalloc(scratch_pool, sizeof(*wli));
+
+          SVN_ERR(svn_wc__node_get_base(&wli->revision, &repos_relpath,
+                                        &repos_root_url, NULL,
+                                        &wli->lock_token,
+                                        wc_ctx, local_abspath,
+                                        result_pool, iterpool));
+
+          /* Node exists in BASE? */
+          if (! repos_root_url || !repos_relpath)
+            return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+                                     _("The node '%s' was not found."),
                                      svn_dirent_local_style(local_abspath,
                                                             iterpool));
 
+          apr_hash_set(wc_info, local_abspath, APR_HASH_KEY_STRING, wli);
+
+          target_url = svn_path_url_add_component2(repos_root_url,
+                                                   repos_relpath,
+                                                   scratch_pool);
+
           APR_ARRAY_PUSH(target_urls, const char *) = target_url;
         }
 
@@ -320,7 +347,8 @@ organize_lock_targets(const char **commo
       rel_fs_paths = apr_hash_make(result_pool);
       for (i = 0; i < rel_targets->nelts; i++)
         {
-          const char *rel_target, *rel_url, *abs_path;
+          const char *rel_target, *rel_url;
+          const char *local_abspath;
 
           svn_pool_clear(iterpool);
 
@@ -336,35 +364,49 @@ organize_lock_targets(const char **commo
              revision of the dirent target with which it is associated
              (if our caller is locking) or to a (possible empty) lock
              token string (if the caller is unlocking). */
-          abs_path = svn_dirent_join(common_dirent, rel_target, iterpool);
+          local_abspath = svn_dirent_join(common_dirent, rel_target, iterpool);
 
           if (do_lock) /* Lock. */
             {
               svn_revnum_t *revnum;
+              struct wc_lock_item_t *wli;
               revnum = apr_palloc(result_pool, sizeof(* revnum));
-              SVN_ERR(svn_wc__node_get_base(revnum, NULL, NULL, NULL,
-                                            ctx->wc_ctx, abs_path,
-                                            result_pool, iterpool));
+
+              wli = apr_hash_get(wc_info, local_abspath, APR_HASH_KEY_STRING);
+
+              SVN_ERR_ASSERT(wli != NULL);
+
+              *revnum = wli->revision;
+
               apr_hash_set(rel_targets_ret, rel_url,
                            APR_HASH_KEY_STRING, revnum);
             }
           else /* Unlock. */
             {
-              const char *lock_token = NULL;
+              const char *lock_token;
+              struct wc_lock_item_t *wli;
 
               /* If not forcing the unlock, get the lock token. */
               if (! force)
                 {
-                  SVN_ERR(svn_wc__node_get_lock_info(&lock_token, NULL, NULL,
-                                                     NULL, ctx->wc_ctx,
-                                                     abs_path, result_pool,
-                                                     iterpool));
-                  if (! lock_token)
+                  wli = apr_hash_get(wc_info, local_abspath,
+                                     APR_HASH_KEY_STRING);
+
+                  SVN_ERR_ASSERT(wli != NULL);
+
+                  if (! wli->lock_token)
                     return svn_error_createf(
                                SVN_ERR_CLIENT_MISSING_LOCK_TOKEN, NULL,
                                _("'%s' is not locked in this working copy"),
-                               abs_path);
+                               svn_dirent_local_style(local_abspath,
+                                                      scratch_pool));
+
+                  lock_token = wli->lock_token
+                                ? apr_pstrdup(result_pool, wli->lock_token)
+                                : NULL;
                 }
+              else
+                lock_token = NULL;
 
               /* If breaking a lock, we shouldn't pass any lock token. */
               apr_hash_set(rel_targets_ret, rel_url, APR_HASH_KEY_STRING,
@@ -444,7 +486,7 @@ svn_client_lock(const apr_array_header_t
 
   SVN_ERR(organize_lock_targets(&common_parent_url, &base_dir, &path_revs,
                                 &urls_to_paths, targets, TRUE, steal_lock,
-                                ctx, pool, pool));
+                                ctx->wc_ctx, pool, pool));
 
   /* Open an RA session to the common parent of TARGETS. */
   if (base_dir)
@@ -484,7 +526,7 @@ svn_client_unlock(const apr_array_header
 
   SVN_ERR(organize_lock_targets(&common_parent_url, &base_dir, &path_tokens,
                                 &urls_to_paths, targets, FALSE, break_lock,
-                                ctx, pool, pool));
+                                ctx->wc_ctx, pool, pool));
 
   /* Open an RA session. */
   if (base_dir)