Author: stsp
Date: Sat Jul 22 15:04:57 2017
New Revision: 1802697

URL: http://svn.apache.org/viewvc?rev=1802697&view=rev
Log:
On the addremove branch, implement a new 'svn addremove' sub-command
with some basic support for it in libsvn_client.

* subversion/include/svn_client.h
  (svn_client_addremove): Declare.

* subversion/libsvn_client/add.c
  (add_file): Expose to other files in libsvn_client by renaming to ...
  (svn_client__add_file): ... this.
  (add_dir_recursive): For the same reason, rename this to ...
  (svn_client__add_dir_recursive): ... this.
  (add): Track renames.

* subversion/libsvn_client/addremove.c,
  subversion/svn/addremove-cmd.c: New files with a basic implementation
   which will be expanded upon later.

* subversion/libsvn_client/client.h
  (svn_client__add_file, svn_client__add_dir_recursive): Declare.

* subversion/svn/cl.h
  (svn_opt_subcommand_t): Add svn_cl__addremove.

* subversion/svn/svn.c
  (svn_cl__cmd_table): Add the "addremove" subcommand.

* subversion/tests/cmdline/addremove_tests.py: New file, with one test so far.

Added:
    subversion/branches/addremove/subversion/libsvn_client/addremove.c   (with 
props)
    subversion/branches/addremove/subversion/svn/addremove-cmd.c   (with props)
    subversion/branches/addremove/subversion/tests/cmdline/addremove_tests.py   
(with props)
Modified:
    subversion/branches/addremove/subversion/include/svn_client.h
    subversion/branches/addremove/subversion/libsvn_client/add.c
    subversion/branches/addremove/subversion/libsvn_client/client.h
    subversion/branches/addremove/subversion/svn/cl.h
    subversion/branches/addremove/subversion/svn/svn.c

Modified: subversion/branches/addremove/subversion/include/svn_client.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/include/svn_client.h?rev=1802697&r1=1802696&r2=1802697&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/include/svn_client.h (original)
+++ subversion/branches/addremove/subversion/include/svn_client.h Sat Jul 22 
15:04:57 2017
@@ -1674,6 +1674,20 @@ svn_client_add(const char *path,
                svn_client_ctx_t *ctx,
                apr_pool_t *pool);
 
+/**
+ * Recurse into the versioned directory @a local_path, and put any unversioned
+ * nodes found into added status, and put any missing nodes found into deleted
+ * status.
+ *
+ * The level of recursion is specified by @a depth.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_addremove(const char *path,
+                     svn_depth_t depth,
+                     svn_client_ctx_t *ctx,
+                     apr_pool_t *scratch_pool);
 /** @} */
 
 /**

Modified: subversion/branches/addremove/subversion/libsvn_client/add.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_client/add.c?rev=1802697&r1=1802696&r2=1802697&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/libsvn_client/add.c (original)
+++ subversion/branches/addremove/subversion/libsvn_client/add.c Sat Jul 22 
15:04:57 2017
@@ -265,14 +265,13 @@ svn_client__get_paths_auto_props(apr_has
   return SVN_NO_ERROR;
 }
 
-/* Only call this if the on-disk node kind is a file. */
-static svn_error_t *
-add_file(const char *local_abspath,
-         svn_magic__cookie_t *magic_cookie,
-         apr_hash_t *autoprops,
-         svn_boolean_t no_autoprops,
-         svn_client_ctx_t *ctx,
-         apr_pool_t *pool)
+svn_error_t *
+svn_client__add_file(const char *local_abspath,
+                     svn_magic__cookie_t *magic_cookie,
+                     apr_hash_t *autoprops,
+                     svn_boolean_t no_autoprops,
+                     svn_client_ctx_t *ctx,
+                     apr_pool_t *pool)
 {
   apr_hash_t *properties;
   const char *mimetype;
@@ -324,48 +323,18 @@ add_file(const char *local_abspath,
   return SVN_NO_ERROR;
 }
 
-/* Schedule directory DIR_ABSPATH, and some of the tree under it, for
- * addition.  DEPTH is the depth at this point in the descent (it may
- * be changed for recursive calls).
- *
- * If DIR_ABSPATH (or any item below DIR_ABSPATH) is already scheduled for
- * addition, add will fail and return an error unless FORCE is TRUE.
- *
- * Use MAGIC_COOKIE (which may be NULL) to detect the mime-type of files
- * if necessary.
- *
- * If not NULL, CONFIG_AUTOPROPS is a hash representing the config file and
- * svn:auto-props autoprops which apply to DIR_ABSPATH.  It maps
- * const char * file patterns to another hash which maps const char *
- * property names to const char *property values.  If CONFIG_AUTOPROPS is
- * NULL and the config file and svn:auto-props autoprops are required by this
- * function, then such will be obtained.
- *
- * If IGNORES is not NULL, then it is an array of const char * ignore patterns
- * that apply to any children of DIR_ABSPATH.  If REFRESH_IGNORES is TRUE, then
- * the passed in value of IGNORES (if any) is itself ignored and this function
- * will gather all ignore patterns applicable to DIR_ABSPATH itself (allocated 
in
- * RESULT_POOL).  Any recursive calls to this function get the refreshed ignore
- * patterns.  If IGNORES is NULL and REFRESH_IGNORES is FALSE, then all 
children of DIR_ABSPATH
- * are unconditionally added.
- *
- * If CTX->CANCEL_FUNC is non-null, call it with CTX->CANCEL_BATON to allow
- * the user to cancel the operation.
- *
- * Use SCRATCH_POOL for temporary allocations.
- */
-static svn_error_t *
-add_dir_recursive(const char *dir_abspath,
-                  svn_depth_t depth,
-                  svn_boolean_t force,
-                  svn_boolean_t no_autoprops,
-                  svn_magic__cookie_t *magic_cookie,
-                  apr_hash_t *config_autoprops,
-                  svn_boolean_t refresh_ignores,
-                  apr_array_header_t *ignores,
-                  svn_client_ctx_t *ctx,
-                  apr_pool_t *result_pool,
-                  apr_pool_t *scratch_pool)
+svn_error_t *
+svn_client__add_dir_recursive(const char *dir_abspath,
+                              svn_depth_t depth,
+                              svn_boolean_t force,
+                              svn_boolean_t no_autoprops,
+                              svn_magic__cookie_t *magic_cookie,
+                              apr_hash_t *config_autoprops,
+                              svn_boolean_t refresh_ignores,
+                              apr_array_header_t *ignores,
+                              svn_client_ctx_t *ctx,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool)
 {
   svn_error_t *err;
   apr_pool_t *iterpool;
@@ -412,8 +381,8 @@ add_dir_recursive(const char *dir_abspat
 
      Since this set of autoprops applies to all unversioned children of
      DIR_ABSPATH, we will pass these along to any recursive calls to
-     add_dir_recursive() and calls to add_file() below.  Thus sparing
-     these callees from looking up the same information. */
+     svn_client__add_dir_recursive() and calls to svn_client__add_file() below.
+     Thus sparing these callees from looking up the same information. */
   if (!entry_exists && config_autoprops == NULL)
     {
       SVN_ERR(svn_client__get_all_auto_props(&config_autoprops, dir_abspath,
@@ -463,17 +432,17 @@ add_dir_recursive(const char *dir_abspat
           if (refresh_ignores && !entry_exists)
             refresh_ignores = FALSE;
 
-          SVN_ERR(add_dir_recursive(abspath, depth_below_here,
-                                    force, no_autoprops,
-                                    magic_cookie, config_autoprops,
-                                    refresh_ignores, ignores, ctx,
-                                    result_pool, iterpool));
+          SVN_ERR(svn_client__add_dir_recursive(abspath, depth_below_here,
+                                                force, no_autoprops,
+                                                magic_cookie, config_autoprops,
+                                                refresh_ignores, ignores, ctx,
+                                                result_pool, iterpool));
         }
       else if ((dirent->kind == svn_node_file || dirent->special)
                && depth >= svn_depth_files)
         {
-          err = add_file(abspath, magic_cookie, config_autoprops,
-                         no_autoprops, ctx, iterpool);
+          err = svn_client__add_file(abspath, magic_cookie, config_autoprops,
+                                     no_autoprops, ctx, iterpool);
           if (err && err->apr_err == SVN_ERR_ENTRY_EXISTS && force)
             svn_error_clear(err);
           else
@@ -835,17 +804,17 @@ add(const char *local_abspath,
   SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
   if (kind == svn_node_dir)
     {
-      /* We use add_dir_recursive for all directory targets
+      /* We use svn_client__add_dir_recursive for all directory targets
          and pass depth along no matter what it is, so that the
          target's depth will be set correctly. */
-      err = add_dir_recursive(local_abspath, depth, force,
-                              no_autoprops, magic_cookie, NULL,
-                              !no_ignore, ignores, ctx,
-                              scratch_pool, scratch_pool);
+      err = svn_client__add_dir_recursive(local_abspath, depth, force,
+                                          no_autoprops, magic_cookie, NULL,
+                                          !no_ignore, ignores, ctx,
+                                          scratch_pool, scratch_pool);
     }
   else if (kind == svn_node_file)
-    err = add_file(local_abspath, magic_cookie, NULL,
-                   no_autoprops, ctx, scratch_pool);
+    err = svn_client__add_file(local_abspath, magic_cookie, NULL,
+                               no_autoprops, ctx, scratch_pool);
   else if (kind == svn_node_none)
     {
       svn_boolean_t tree_conflicted;

Added: subversion/branches/addremove/subversion/libsvn_client/addremove.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_client/addremove.c?rev=1802697&view=auto
==============================================================================
--- subversion/branches/addremove/subversion/libsvn_client/addremove.c (added)
+++ subversion/branches/addremove/subversion/libsvn_client/addremove.c Sat Jul 
22 15:04:57 2017
@@ -0,0 +1,194 @@
+/*
+ * addremove.c: integrate unversioned structural changes into working copy
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+
+#include "svn_hash.h"
+#include "svn_wc.h"
+#include "svn_client.h"
+#include "svn_pools.h"
+#include "svn_error.h"
+#include "svn_dirent_uri.h"
+#include "svn_io.h"
+#include "client.h"
+
+#include "private/svn_client_private.h"
+#include "private/svn_wc_private.h"
+
+#include "svn_private_config.h"
+
+
+
+/*** Code. ***/
+
+struct addremove_status_baton {
+  /* Status info for missing paths. */
+  apr_hash_t *missing;
+
+  /* Status info for unversioned paths. */
+  apr_hash_t *unversioned;
+};
+
+/* Implements svn_wc_status_func4_t. */
+static svn_error_t *
+addremove_status_func(void *baton, const char *local_abspath,
+                      const svn_wc_status3_t *status,
+                      apr_pool_t *scratch_pool)
+{
+  struct addremove_status_baton *b = baton;
+
+  switch (status->node_status)
+    {
+      case svn_wc_status_unversioned:
+        {
+          apr_hash_t *hash = b->unversioned;
+          apr_pool_t *result_pool = apr_hash_pool_get(hash);
+
+          svn_hash_sets(hash, apr_pstrdup(result_pool, local_abspath),
+                        svn_wc_dup_status3(status, result_pool));
+          break;
+        }
+
+      case svn_wc_status_missing:
+        {
+
+          apr_hash_t *hash = b->missing;
+          apr_pool_t *result_pool = apr_hash_pool_get(hash);
+
+          svn_hash_sets(hash, apr_pstrdup(result_pool, local_abspath),
+                        svn_wc_dup_status3(status, result_pool));
+          break;
+        }
+
+        default:
+          break;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+addremove(const char *local_abspath, svn_depth_t depth,
+          svn_client_ctx_t *ctx, apr_pool_t *scratch_pool)
+{
+  struct addremove_status_baton b;
+  struct svn_wc_status3_t *status;
+  svn_node_kind_t kind_on_disk;
+  apr_hash_index_t *hi;
+  apr_pool_t *iterpool;
+
+  /* Our target must be a versioned directory. */
+  SVN_ERR(svn_wc_status3(&status, ctx->wc_ctx, local_abspath,
+                         scratch_pool, scratch_pool));
+  SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, scratch_pool));
+  if (status->kind != svn_node_dir || kind_on_disk != svn_node_dir ||
+      !status->versioned)
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a versioned directory"),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
+
+  b.missing = apr_hash_make(scratch_pool);
+  b.unversioned = apr_hash_make(scratch_pool);
+
+  SVN_ERR(svn_wc_walk_status(ctx->wc_ctx, local_abspath, depth,
+                             TRUE, FALSE, FALSE, NULL,
+                             addremove_status_func, &b,
+                             ctx->cancel_func, ctx->cancel_baton,
+                             scratch_pool));
+
+  iterpool = svn_pool_create(scratch_pool);
+  for (hi = apr_hash_first(scratch_pool, b.unversioned); hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *unversioned_abspath = apr_hash_this_key(hi);
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_io_check_path(unversioned_abspath, &kind_on_disk,
+                                scratch_pool));
+
+      if (kind_on_disk == svn_node_file)
+        {
+          SVN_ERR(svn_client__add_file(unversioned_abspath,
+                                       NULL, /* TODO: magic cookie */
+                                       NULL, /* TODO: autoprops */
+                                       TRUE, /* TODO: !no_autoprops */
+                                       ctx, iterpool));
+        }
+      else if (kind_on_disk == svn_node_dir && depth >= svn_depth_immediates)
+        {
+          svn_depth_t depth_below_here = depth;
+
+          if (depth == svn_depth_immediates)
+            depth_below_here = svn_depth_empty;
+
+          SVN_ERR(svn_client__add_dir_recursive(
+                    unversioned_abspath, depth_below_here,
+                    FALSE, /* force */
+                    TRUE, /* TODO: !no_autoprops */
+                    NULL, /* TODO: magic cookie */
+                    NULL, /* TODO: autoprops */
+                    FALSE, /* TODO: refresh_ignores */
+                    NULL, /* TODO: ignores */
+                    ctx, iterpool, iterpool));
+        }
+    }
+  svn_pool_destroy(iterpool);
+
+  for (hi = apr_hash_first(scratch_pool, b.missing); hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *missing_abspath = apr_hash_this_key(hi);
+
+      SVN_ERR(svn_wc_delete4(ctx->wc_ctx, missing_abspath,
+                             FALSE, /* keep_local */
+                             FALSE, /* delete_unversioned_target */
+                             ctx->cancel_func, ctx->cancel_baton,
+                             ctx->notify_func2, ctx->notify_baton2,
+                             scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_addremove(const char *local_path,
+                     svn_depth_t depth,
+                     svn_client_ctx_t *ctx,
+                     apr_pool_t *scratch_pool)
+{
+  const char *local_abspath;
+
+  SVN_ERR(svn_dirent_get_absolute(&local_abspath, local_path, scratch_pool));
+
+  SVN_WC__CALL_WITH_WRITE_LOCK(
+    addremove(local_abspath, depth, ctx, scratch_pool),
+    ctx->wc_ctx, local_abspath, TRUE, scratch_pool);
+
+  return SVN_NO_ERROR;
+}

Propchange: subversion/branches/addremove/subversion/libsvn_client/addremove.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/addremove/subversion/libsvn_client/client.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_client/client.h?rev=1802697&r1=1802696&r2=1802697&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/libsvn_client/client.h (original)
+++ subversion/branches/addremove/subversion/libsvn_client/client.h Sat Jul 22 
15:04:57 2017
@@ -1267,6 +1267,59 @@ svn_client__merge_locked(svn_client__con
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool);
 
+/* Internal helper for svn_client_add() and svn_client_addremove().
+ * Only call this if the on-disk node kind is a file. */
+svn_error_t *
+svn_client__add_file(const char *local_abspath,
+                     svn_magic__cookie_t *magic_cookie,
+                     apr_hash_t *autoprops,
+                     svn_boolean_t no_autoprops,
+                     svn_client_ctx_t *ctx,
+                     apr_pool_t *pool);
+
+/* Schedule directory DIR_ABSPATH, and some of the tree under it, for
+ * addition.  DEPTH is the depth at this point in the descent (it may
+ * be changed for recursive calls).
+ *
+ * If DIR_ABSPATH (or any item below DIR_ABSPATH) is already scheduled for
+ * addition, add will fail and return an error unless FORCE is TRUE.
+ *
+ * Use MAGIC_COOKIE (which may be NULL) to detect the mime-type of files
+ * if necessary.
+ *
+ * If not NULL, CONFIG_AUTOPROPS is a hash representing the config file and
+ * svn:auto-props autoprops which apply to DIR_ABSPATH.  It maps
+ * const char * file patterns to another hash which maps const char *
+ * property names to const char *property values.  If CONFIG_AUTOPROPS is
+ * NULL and the config file and svn:auto-props autoprops are required by this
+ * function, then such will be obtained.
+ *
+ * If IGNORES is not NULL, then it is an array of const char * ignore patterns
+ * that apply to any children of DIR_ABSPATH.  If REFRESH_IGNORES is TRUE, then
+ * the passed in value of IGNORES (if any) is itself ignored and this function
+ * will gather all ignore patterns applicable to DIR_ABSPATH itself (allocated 
in
+ * RESULT_POOL).  Any recursive calls to this function get the refreshed ignore
+ * patterns.  If IGNORES is NULL and REFRESH_IGNORES is FALSE, then all 
children of DIR_ABSPATH
+ * are unconditionally added.
+ *
+ * If CTX->CANCEL_FUNC is non-null, call it with CTX->CANCEL_BATON to allow
+ * the user to cancel the operation.
+ *
+ * Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_client__add_dir_recursive(const char *dir_abspath,
+                              svn_depth_t depth,
+                              svn_boolean_t force,
+                              svn_boolean_t no_autoprops,
+                              svn_magic__cookie_t *magic_cookie,
+                              apr_hash_t *config_autoprops,
+                              svn_boolean_t refresh_ignores,
+                              apr_array_header_t *ignores,
+                              svn_client_ctx_t *ctx,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Added: subversion/branches/addremove/subversion/svn/addremove-cmd.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/svn/addremove-cmd.c?rev=1802697&view=auto
==============================================================================
--- subversion/branches/addremove/subversion/svn/addremove-cmd.c (added)
+++ subversion/branches/addremove/subversion/svn/addremove-cmd.c Sat Jul 22 
15:04:57 2017
@@ -0,0 +1,106 @@
+/*
+ * addremove-cmd.c -- Subversion addremove command
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+#define APR_WANT_STDIO
+#include <apr_want.h>
+
+#include "svn_client.h"
+#include "svn_error.h"
+#include "svn_pools.h"
+#include "cl.h"
+
+#include "svn_private_config.h"
+
+
+/*** Code. ***/
+
+/* This implements the `svn_opt_subcommand_t' interface. */
+svn_error_t *
+svn_cl__addremove(apr_getopt_t *os,
+                  void *baton,
+                  apr_pool_t *pool)
+{
+  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
+  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
+  apr_array_header_t *targets;
+  int i;
+  apr_pool_t *iterpool;
+  apr_array_header_t *errors = apr_array_make(pool, 0, sizeof(apr_status_t));
+
+  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
+                                                      opt_state->targets,
+                                                      ctx, FALSE, pool));
+
+  if (! targets->nelts)
+    return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
+
+  if (opt_state->depth == svn_depth_unknown)
+    opt_state->depth = svn_depth_infinity;
+
+  SVN_ERR(svn_cl__check_targets_are_local_paths(targets));
+
+  iterpool = svn_pool_create(pool);
+  for (i = 0; i < targets->nelts; i++)
+    {
+      const char *target = APR_ARRAY_IDX(targets, i, const char *);
+
+      svn_pool_clear(iterpool);
+      SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
+      SVN_ERR(svn_cl__try
+              (svn_client_addremove(target, opt_state->depth, ctx, iterpool),
+               errors, opt_state->quiet,
+               SVN_ERR_ENTRY_EXISTS,
+               SVN_ERR_WC_PATH_NOT_FOUND,
+               0));
+    }
+
+  svn_pool_destroy(iterpool);
+
+  if (errors->nelts > 0)
+    {
+      svn_error_t *err;
+
+      err = svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL, NULL);
+      for (i = 0; i < errors->nelts; i++)
+        {
+          apr_status_t status = APR_ARRAY_IDX(errors, i, apr_status_t);
+          if (status == SVN_ERR_WC_PATH_NOT_FOUND)
+            err = svn_error_quick_wrap(err,
+                                       _("Could not add all targets because "
+                                         "some targets don't exist"));
+          else if (status == SVN_ERR_ENTRY_EXISTS)
+            err = svn_error_quick_wrap(err,
+                                       _("Could not add all targets because "
+                                         "some targets are already 
versioned"));
+        }
+
+      return svn_error_trace(err);
+    }
+
+  return SVN_NO_ERROR;
+}

Propchange: subversion/branches/addremove/subversion/svn/addremove-cmd.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/addremove/subversion/svn/cl.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/svn/cl.h?rev=1802697&r1=1802696&r2=1802697&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/svn/cl.h (original)
+++ subversion/branches/addremove/subversion/svn/cl.h Sat Jul 22 15:04:57 2017
@@ -266,6 +266,7 @@ typedef struct svn_cl__cmd_baton_t
 /* Declare all the command procedures */
 svn_opt_subcommand_t
   svn_cl__add,
+  svn_cl__addremove,
   svn_cl__auth,
   svn_cl__blame,
   svn_cl__cat,

Modified: subversion/branches/addremove/subversion/svn/svn.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/svn/svn.c?rev=1802697&r1=1802696&r2=1802697&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/svn/svn.c (original)
+++ subversion/branches/addremove/subversion/svn/svn.c Sat Jul 22 15:04:57 2017
@@ -513,6 +513,23 @@ const svn_opt_subcommand_desc2_t svn_cl_
      opt_no_autoprops, opt_parents },
      {{opt_parents, N_("add intermediate parents")}} },
 
+  { "addremove", svn_cl__addremove, {0}, N_
+    ("Put unversioned and missing items under version control.\n"
+     "usage: addremove PATH...\n"
+     "\n"
+     "  Recursively walk the specified paths in the working copy, putting\n"
+     "  unversioned files and directories under version control, and 
removing\n"
+     "  missing files and directories from version control.\n"
+     "\n"
+     "  The specified PATHs must be versioned directories.\n"
+     "\n"
+     "  Additions and deletions will be scheduled for the next commit and\n"
+     "  will not take effect in the repository unless they are committed.\n"
+     "\n"
+     "  The --depth option controls recursion (default: infinity).\n"
+     "  Use 'svn revert' to undo any undesirable additions and deletions.\n"),
+    {opt_targets, opt_depth }, },
+
   { "auth", svn_cl__auth, {0}, N_
    ("Manage cached authentication credentials.\n"
     "usage: 1. svn auth [PATTERN ...]\n"

Added: subversion/branches/addremove/subversion/tests/cmdline/addremove_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/addremove_tests.py?rev=1802697&view=auto
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/addremove_tests.py 
(added)
+++ subversion/branches/addremove/subversion/tests/cmdline/addremove_tests.py 
Sat Jul 22 15:04:57 2017
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+#
+#  addremove_tests.py:  testing svn addremove
+#
+#  Subversion is a tool for revision control.
+#  See http://subversion.apache.org for more information.
+#
+# ====================================================================
+#    Licensed to the Apache Software Foundation (ASF) under one
+#    or more contributor license agreements.  See the NOTICE file
+#    distributed with this work for additional information
+#    regarding copyright ownership.  The ASF licenses this file
+#    to you under the Apache License, Version 2.0 (the
+#    "License"); you may not use this file except in compliance
+#    with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing,
+#    software distributed under the License is distributed on an
+#    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#    KIND, either express or implied.  See the License for the
+#    specific language governing permissions and limitations
+#    under the License.
+######################################################################
+
+# General modules
+import shutil, stat, re, os, logging
+
+logger = logging.getLogger()
+
+# Our testing module
+import svntest
+from svntest import wc
+
+# (abbreviation)
+Skip = svntest.testcase.Skip_deco
+SkipUnless = svntest.testcase.SkipUnless_deco
+XFail = svntest.testcase.XFail_deco
+Issues = svntest.testcase.Issues_deco
+Issue = svntest.testcase.Issue_deco
+Wimp = svntest.testcase.Wimp_deco
+Item = wc.StateItem
+
+######################################################################
+# Tests
+#
+#   Each test must return on success or raise on failure.
+
+#----------------------------------------------------------------------
+
+def basic_addremove(sbox):
+  "basic addremove functionality"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # Delete a file
+  lambda_path = sbox.ospath('A/B/lambda')
+  os.remove(lambda_path)
+
+  # Delete a directory
+  C_path = sbox.ospath('A/C')
+  os.rmdir(C_path)
+
+  # Add an unversioned directory
+  newdir_path = sbox.ospath('A/newdir')
+  os.mkdir(newdir_path)
+
+  # Add an unversioned file inside the new directory
+  newfile_path = sbox.ospath('A/newdir/newfile')
+  svntest.main.file_append(newfile_path, 'This is a new file\n')
+
+  svntest.actions.run_and_verify_svn(None, [], 'addremove', wc_dir)
+
+  expected_output = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_output.tweak('A/B/lambda', status='D ')
+  expected_output.tweak('A/C', status='D ')
+  expected_output.add({
+    'A/newdir' : Item(status='A ', wc_rev=0),
+    'A/newdir/newfile' : Item(status='A ', wc_rev=0),
+  })
+
+  svntest.actions.run_and_verify_status(wc_dir, expected_output)
+
+########################################################################
+# Run the tests
+
+# list all tests here, starting with None:
+test_list = [ None,
+              basic_addremove,
+]
+
+if __name__ == '__main__':
+  svntest.main.run_tests(test_list)

Propchange: 
subversion/branches/addremove/subversion/tests/cmdline/addremove_tests.py
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
subversion/branches/addremove/subversion/tests/cmdline/addremove_tests.py
------------------------------------------------------------------------------
    svn:executable = *


Reply via email to