You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2017/07/14 11:37:04 UTC

svn commit: r1801942 - in /subversion/branches/shelve-checkpoint: subversion/include/svn_client.h subversion/libsvn_client/checkpoint.c subversion/svn/checkpoint-cmd.c subversion/svn/cl.h subversion/svn/svn.c tools/client-side/bash_completion

Author: julianfoad
Date: Fri Jul 14 11:37:03 2017
New Revision: 1801942

URL: http://svn.apache.org/viewvc?rev=1801942&view=rev
Log:
On the 'shelve-checkpoint' branch: Prototype checkpointing.

Commands are:

    svn checkpoint save
    svn checkpoint revert
    svn checkpoint rollback NUMBER
    svn checkpoint list|--list
    svn checkpoints

* subversion/include/svn_client.h
  (svn_client_checkpoint_get_current,
   svn_client_checkpoint_save,
   svn_client_checkpoint_restore,
   svn_client_checkpoint_delete,
   svn_client_checkpoint_list): New.

* subversion/libsvn_client/checkpoint.c
  New file.

* subversion/svn/checkpoint-cmd.c
  New file.

* subversion/svn/cl.h
  (svn_opt_subcommand_t): Declare the checkpointing commands.

* subversion/svn/svn.c
  (svn_cl__cmd_table): Describe the checkpointing commands.

* tools/client-side/bash_completion
  (_svn): Add the checkpointing commands.

Added:
    subversion/branches/shelve-checkpoint/subversion/libsvn_client/checkpoint.c   (with props)
    subversion/branches/shelve-checkpoint/subversion/svn/checkpoint-cmd.c   (with props)
Modified:
    subversion/branches/shelve-checkpoint/subversion/include/svn_client.h
    subversion/branches/shelve-checkpoint/subversion/svn/cl.h
    subversion/branches/shelve-checkpoint/subversion/svn/svn.c
    subversion/branches/shelve-checkpoint/tools/client-side/bash_completion

Modified: subversion/branches/shelve-checkpoint/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/include/svn_client.h?rev=1801942&r1=1801941&r2=1801942&view=diff
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/include/svn_client.h (original)
+++ subversion/branches/shelve-checkpoint/subversion/include/svn_client.h Fri Jul 14 11:37:03 2017
@@ -6716,6 +6716,71 @@ svn_client_cat(svn_stream_t *out,
 
 
 
+/** Checkpointing commands
+ *
+ * @defgroup svn_client_checkpoint_funcs Client Checkpointing Functions
+ * @{
+ */
+
+/**
+ *
+ * @since New in 1.11.
+ */
+svn_error_t *
+svn_client_checkpoint_get_current(int *checkpoint_number_p,
+                                  const char *local_abspath,
+                                  svn_client_ctx_t *ctx,
+                                  apr_pool_t *scratch_pool);
+
+/**
+ *
+ * @since New in 1.11.
+ */
+svn_error_t *
+svn_client_checkpoint_save(int *checkpoint_number,
+                           const char *local_abspath,
+                           /*const apr_array_header_t *paths,
+                           svn_depth_t depth,
+                           const apr_array_header_t *changelists,*/
+                           svn_client_ctx_t *ctx,
+                           apr_pool_t *scratch_pool);
+
+/**
+ *
+ * @since New in 1.11.
+ */
+svn_error_t *
+svn_client_checkpoint_restore(int checkpoint_number,
+                              const char *local_abspath,
+                              svn_boolean_t dry_run,
+                              svn_client_ctx_t *ctx,
+                              apr_pool_t *scratch_pool);
+
+/**
+ *
+ * @since New in 1.11.
+ */
+svn_error_t *
+svn_client_checkpoint_delete(int checkpoint_number,
+                             const char *local_abspath,
+                             svn_boolean_t dry_run,
+                             svn_client_ctx_t *ctx,
+                             apr_pool_t *scratch_pool);
+
+/**
+ *
+ * @since New in 1.11.
+ */
+svn_error_t *
+svn_client_checkpoint_list(apr_array_header_t **checkpoints,
+                           const char *local_abspath,
+                           svn_client_ctx_t *ctx,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool);
+
+/** @} */
+
+
 /** Shelving commands
  *
  * @defgroup svn_client_shelve_funcs Client Shelving Functions

Added: subversion/branches/shelve-checkpoint/subversion/libsvn_client/checkpoint.c
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_client/checkpoint.c?rev=1801942&view=auto
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/libsvn_client/checkpoint.c (added)
+++ subversion/branches/shelve-checkpoint/subversion/libsvn_client/checkpoint.c Fri Jul 14 11:37:03 2017
@@ -0,0 +1,279 @@
+/*
+ * checkpoint.c:  implementation of the 'checkpoint' commands
+ *
+ * ====================================================================
+ *    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_client.h"
+#include "svn_wc.h"
+#include "svn_pools.h"
+#include "svn_dirent_uri.h"
+#include "svn_path.h"
+#include "svn_hash.h"
+#include "svn_utf.h"
+
+#include "client.h"
+#include "private/svn_wc_private.h"
+#include "private/svn_sorts_private.h"
+#include "svn_private_config.h"
+
+/*  */
+static svn_error_t *
+read_current(int *current,
+             const char *local_abspath,
+             svn_client_ctx_t *ctx,
+             apr_pool_t *scratch_pool)
+{
+  char *dir;
+  const char *current_abspath;
+
+  SVN_ERR(svn_wc__get_shelves_dir(&dir, ctx->wc_ctx, local_abspath,
+                                  scratch_pool, scratch_pool));
+  current_abspath = svn_dirent_join(dir, "current", scratch_pool);
+
+  {
+    FILE *fp = fopen(current_abspath, "r");
+
+    if (! fp)
+      {
+        *current = 0;
+        return SVN_NO_ERROR;
+      }
+    fscanf(fp, "%d", current);
+    fclose(fp);
+  }
+
+  return SVN_NO_ERROR;
+}
+
+/*  */
+static svn_error_t *
+write_current(int current,
+              const char *local_abspath,
+              svn_client_ctx_t *ctx,
+              apr_pool_t *scratch_pool)
+{
+  char *dir;
+  const char *current_abspath;
+
+  SVN_ERR(svn_wc__get_shelves_dir(&dir, ctx->wc_ctx, local_abspath,
+                                  scratch_pool, scratch_pool));
+  current_abspath = svn_dirent_join(dir, "current", scratch_pool);
+
+  {
+    FILE *fp = fopen(current_abspath, "w");
+    fprintf(fp, "%d", current);
+    fclose(fp);
+  }
+
+  return SVN_NO_ERROR;
+}
+
+/*  */
+static char *
+format_checkpoint_name(int checkpoint_number,
+                       apr_pool_t *result_pool)
+{
+  return apr_psprintf(result_pool, "checkpoint-%03d",
+                      checkpoint_number);
+}
+
+/* Write a checkpoint patch of the whole WC. */
+static svn_error_t *
+write_checkpoint(int checkpoint_number,
+                 /*const apr_array_header_t *paths,
+                   svn_depth_t depth,
+                   const apr_array_header_t *changelists,*/
+                 const char *local_abspath,
+                 svn_client_ctx_t *ctx,
+                 apr_pool_t *scratch_pool)
+{
+  const char *wc_root_abspath;
+  char *shelf_name = format_checkpoint_name(checkpoint_number, scratch_pool);
+
+  apr_array_header_t *paths = apr_array_make(scratch_pool, 1, sizeof(char *));
+
+  SVN_ERR(svn_client_get_wc_root(&wc_root_abspath, local_abspath,
+                                 ctx, scratch_pool, scratch_pool));
+  APR_ARRAY_PUSH(paths, const char *) = wc_root_abspath;
+  SVN_ERR(svn_client_shelf_write_patch(
+            shelf_name, wc_root_abspath,
+            TRUE /*overwrite_existing*/,
+            paths, svn_depth_infinity, NULL /*changelists*/,
+            ctx, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+/*  */
+static svn_error_t *
+apply_checkpoint(int checkpoint_number,
+                 const char *wc_root_abspath,
+                 svn_boolean_t reverse,
+                 svn_boolean_t dry_run,
+                 svn_client_ctx_t *ctx,
+                 apr_pool_t *scratch_pool)
+{
+  char *shelf_name = format_checkpoint_name(checkpoint_number, scratch_pool);
+
+  SVN_ERR(svn_client_shelf_apply_patch(shelf_name, wc_root_abspath,
+                                       reverse, dry_run,
+                                       ctx, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/*  */
+static svn_error_t *
+delete_checkpoint(int checkpoint_number,
+                  const char *wc_root_abspath,
+                  svn_client_ctx_t *ctx,
+                  apr_pool_t *scratch_pool)
+{
+  char *shelf_name = format_checkpoint_name(checkpoint_number, scratch_pool);
+
+  SVN_ERR(svn_client_shelf_delete_patch(shelf_name, wc_root_abspath,
+                                        ctx, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_checkpoint_get_current(int *checkpoint_number_p,
+                                  const char *local_abspath,
+                                  svn_client_ctx_t *ctx,
+                                  apr_pool_t *scratch_pool)
+{
+  SVN_ERR(read_current(checkpoint_number_p, local_abspath, ctx, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_checkpoint_save(int *checkpoint_number,
+                           const char *local_abspath,
+                           svn_client_ctx_t *ctx,
+                           apr_pool_t *scratch_pool)
+{
+  int current;
+
+  SVN_ERR(read_current(&current, local_abspath, ctx, scratch_pool));
+  current++;
+
+  SVN_ERR(write_checkpoint(current, local_abspath, ctx, scratch_pool));
+  SVN_ERR(write_current(current, local_abspath, ctx, scratch_pool));
+
+  *checkpoint_number = current;
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_checkpoint_restore(int checkpoint_number,
+                              const char *local_abspath,
+                              svn_boolean_t dry_run,
+                              svn_client_ctx_t *ctx,
+                              apr_pool_t *scratch_pool)
+{
+  const char *wc_root_abspath;
+
+  SVN_ERR(svn_client_get_wc_root(&wc_root_abspath, local_abspath,
+                                 ctx, scratch_pool, scratch_pool));
+
+  /* Save and revert the current state (of whole WC) */
+  /* (Even with dry_run, we write and use and delete a temp checkpoint) */
+  {
+    /* Write a temp checkpoint */
+    SVN_ERR(write_checkpoint(-1, local_abspath, ctx, scratch_pool));
+
+    /* Revert it */
+    SVN_ERR(apply_checkpoint(-1, wc_root_abspath,
+                             TRUE /*reverse*/, dry_run,
+                             ctx, scratch_pool));
+
+    /* Delete it */
+    SVN_ERR(delete_checkpoint(-1, wc_root_abspath,
+                              ctx, scratch_pool));
+  }
+
+  /* Restore the requested checkpoint (if > 0) */
+  if (checkpoint_number > 0)
+    {
+      SVN_ERR(apply_checkpoint(checkpoint_number, wc_root_abspath,
+                               FALSE /*reverse*/, dry_run,
+                               ctx, scratch_pool));
+    }
+
+  SVN_ERR(write_current(checkpoint_number, local_abspath, ctx, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_checkpoint_delete(int checkpoint_number,
+                             const char *local_abspath,
+                             svn_boolean_t dry_run,
+                             svn_client_ctx_t *ctx,
+                             apr_pool_t *scratch_pool)
+{
+  if (! dry_run)
+    {
+      SVN_ERR(delete_checkpoint(checkpoint_number, local_abspath,
+                                ctx, scratch_pool));
+    }
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_checkpoint_list(apr_array_header_t **checkpoints,
+                           const char *local_abspath,
+                           svn_client_ctx_t *ctx,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
+{
+  char *checkpoints_dir;
+  apr_hash_t *dirents;
+  apr_hash_index_t *hi;
+
+  SVN_ERR(svn_wc__get_shelves_dir(&checkpoints_dir, ctx->wc_ctx, local_abspath,
+                                  scratch_pool, scratch_pool));
+  SVN_ERR(svn_io_get_dirents3(&dirents, checkpoints_dir,
+                              TRUE /*only_check_type*/,
+                              scratch_pool, scratch_pool));
+
+  /* Remove non-checkpoint entries */
+  for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi))
+    {
+      const char *name = apr_hash_this_key(hi);
+
+      if (strncmp(name, "checkpoint-", 11) != 0)
+        {
+          svn_hash_sets(dirents, name, NULL);
+        }
+    }
+  *checkpoints = svn_sort__hash(dirents, svn_sort_compare_items_lexically,
+                                result_pool);
+
+  return SVN_NO_ERROR;
+}
+

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

Propchange: subversion/branches/shelve-checkpoint/subversion/libsvn_client/checkpoint.c
------------------------------------------------------------------------------
    svn:mime-type = text/x-csrc

Added: subversion/branches/shelve-checkpoint/subversion/svn/checkpoint-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/svn/checkpoint-cmd.c?rev=1801942&view=auto
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/svn/checkpoint-cmd.c (added)
+++ subversion/branches/shelve-checkpoint/subversion/svn/checkpoint-cmd.c Fri Jul 14 11:37:03 2017
@@ -0,0 +1,263 @@
+/*
+ * checkpoint-cmd.c -- Checkpoint commands.
+ *
+ * ====================================================================
+ *    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.
+ * ====================================================================
+ */
+
+#include "svn_client.h"
+#include "svn_error_codes.h"
+#include "svn_error.h"
+#include "svn_path.h"
+#include "svn_utf.h"
+
+#include "cl.h"
+
+#include "svn_private_config.h"
+#include "private/svn_sorts_private.h"
+
+
+/*  */
+static svn_error_t *
+checkpoint_list(const char *local_abspath,
+                svn_client_ctx_t *ctx,
+                apr_pool_t *scratch_pool)
+{
+  apr_array_header_t *checkpoints;
+  int current_checkpoint_number;
+  const char *current_checkpoint_name;
+  int i;
+
+  SVN_ERR(svn_client_checkpoint_list(&checkpoints,
+                                     local_abspath,
+                                     ctx, scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_client_checkpoint_get_current(&current_checkpoint_number,
+                                            local_abspath, ctx, scratch_pool));
+  current_checkpoint_name = apr_psprintf(scratch_pool, "checkpoint-%03d.patch",
+                                         current_checkpoint_number);
+
+  for (i = 0; i < checkpoints->nelts; i++)
+    {
+      svn_sort__item_t *item = &APR_ARRAY_IDX(checkpoints, i, svn_sort__item_t);
+      const char *name = item->key;
+      char marker = ((strcmp(name, current_checkpoint_name) == 0) ? '*' : ' ');
+
+      printf("%c %s\n", marker, name);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/*  */
+static svn_error_t *
+checkpoint_save(/*const apr_array_header_t *paths,
+                svn_depth_t depth,
+                const apr_array_header_t *changelists,*/
+                svn_boolean_t quiet,
+                const char *local_abspath,
+                svn_client_ctx_t *ctx,
+                apr_pool_t *scratch_pool)
+{
+  int checkpoint_number;
+
+  SVN_ERR(svn_client_checkpoint_save(&checkpoint_number,
+                                     /*paths, depth, changelists,*/
+                                     local_abspath, ctx, scratch_pool));
+  if (! quiet)
+    SVN_ERR(svn_cmdline_printf(scratch_pool, "saved checkpoint %d\n",
+                               checkpoint_number));
+
+  return SVN_NO_ERROR;
+}
+
+/*  */
+static svn_error_t *
+checkpoint_rollback(const char *arg,
+                    svn_boolean_t dry_run,
+                    svn_boolean_t quiet,
+                    const char *local_abspath,
+                    svn_client_ctx_t *ctx,
+                    apr_pool_t *scratch_pool)
+{
+  int old_checkpoint_number;
+  int new_checkpoint_number;
+  int i;
+
+  SVN_ERR(svn_client_checkpoint_get_current(&old_checkpoint_number,
+                                            local_abspath, ctx, scratch_pool));
+  if (arg)
+    {
+      SVN_ERR(svn_cstring_atoi(&new_checkpoint_number, arg));
+    }
+  else
+    {
+      new_checkpoint_number = old_checkpoint_number;
+    }
+
+  SVN_ERR(svn_client_checkpoint_restore(new_checkpoint_number,
+                                        local_abspath,
+                                        dry_run, ctx, scratch_pool));
+  /* Delete any newer checkpoints */
+  for (i = old_checkpoint_number; i > new_checkpoint_number; i--)
+    {
+      SVN_ERR(svn_client_checkpoint_delete(i, local_abspath,
+                                           dry_run, ctx, scratch_pool));
+      if (! quiet)
+        SVN_ERR(svn_cmdline_printf(scratch_pool, "deleted checkpoint %d\n",
+                                   i));
+    }
+
+  if (!quiet)
+    SVN_ERR(svn_cmdline_printf(scratch_pool, "reverted to checkpoint %d\n",
+                               new_checkpoint_number));
+
+  return SVN_NO_ERROR;
+}
+
+/* First argument should be the subsubcommand. */
+static svn_error_t *
+get_subsubcommand(const char **subsubcommand,
+                  apr_getopt_t *os,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
+{
+  apr_array_header_t *args;
+
+  SVN_ERR(svn_opt_parse_num_args(&args, os, 1, scratch_pool));
+  SVN_ERR(svn_utf_cstring_to_utf8(subsubcommand,
+                                  APR_ARRAY_IDX(args, 0, const char *),
+                                  result_pool));
+  return SVN_NO_ERROR;
+}
+
+/* This implements the `svn_opt_subcommand_t' interface. */
+svn_error_t *
+svn_cl__checkpoint(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;
+  const char *subsubcommand;
+  apr_array_header_t *targets;
+  const char *local_abspath;
+
+  if (opt_state->list)
+    subsubcommand = "list";
+  else
+    SVN_ERR(get_subsubcommand(&subsubcommand, os, pool, pool));
+
+  /* Parse the remaining arguments as paths. */
+  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
+                                                      opt_state->targets,
+                                                      ctx, FALSE, pool));
+  SVN_ERR(svn_dirent_get_absolute(&local_abspath, "", pool));
+
+  if (opt_state->quiet)
+    ctx->notify_func2 = NULL;
+
+  if (strcmp(subsubcommand, "list") == 0)
+    {
+      if (targets->nelts)
+        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                _("Too many arguments"));
+
+      SVN_ERR(checkpoint_list(local_abspath, ctx, pool));
+    }
+  else if (strcmp(subsubcommand, "save") == 0)
+    {
+      if (targets->nelts)
+        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                _("Too many arguments"));
+
+      /* ### TODO: Semantics for checkpointing selected paths.
+      svn_depth_t depth = opt_state->depth;
+
+      if (! targets->nelts)
+        return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, NULL, NULL);
+
+      SVN_ERR(svn_cl__check_targets_are_local_paths(targets));
+
+      if (depth == svn_depth_unknown)
+        depth = svn_depth_infinity;
+
+      SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));
+      */
+
+      SVN_ERR(checkpoint_save(/*targets, depth, opt_state->changelists,*/
+                              opt_state->quiet, local_abspath, ctx, pool));
+    }
+  else if (strcmp(subsubcommand, "revert") == 0)
+    {
+      if (targets->nelts)
+        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                _("Too many arguments"));
+
+      SVN_ERR(checkpoint_rollback(NULL, opt_state->dry_run, opt_state->quiet,
+                                  local_abspath, ctx, pool));
+    }
+  else if (strcmp(subsubcommand, "rollback") == 0)
+    {
+      const char *arg;
+
+      if (targets->nelts != 1)
+        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, NULL);
+
+      /* Which checkpoint number? */
+      arg = APR_ARRAY_IDX(targets, 0, char *);
+
+      SVN_ERR(checkpoint_rollback(arg, opt_state->dry_run, opt_state->quiet,
+                                  local_abspath, ctx, pool));
+    }
+  else
+    {
+      return svn_error_createf(SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
+                               _("checkpoint: Unknown checkpoint command '%s'; "
+                                 "try 'svn help checkpoint'"),
+                               subsubcommand);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* This implements the `svn_opt_subcommand_t' interface. */
+svn_error_t *
+svn_cl__checkpoints(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;
+  const char *local_abspath;
+
+  /* There should be no remaining arguments. */
+  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_ARG_PARSING_ERROR, NULL,
+                            _("Too many arguments"));
+
+  SVN_ERR(svn_dirent_get_absolute(&local_abspath, "", pool));
+
+  SVN_ERR(checkpoint_list(local_abspath, ctx, pool));
+  return SVN_NO_ERROR;
+}

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

Propchange: subversion/branches/shelve-checkpoint/subversion/svn/checkpoint-cmd.c
------------------------------------------------------------------------------
    svn:mime-type = text/x-csrc

Modified: subversion/branches/shelve-checkpoint/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/svn/cl.h?rev=1801942&r1=1801941&r2=1801942&view=diff
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/svn/cl.h (original)
+++ subversion/branches/shelve-checkpoint/subversion/svn/cl.h Fri Jul 14 11:37:03 2017
@@ -272,6 +272,8 @@ svn_opt_subcommand_t
   svn_cl__cat,
   svn_cl__changelist,
   svn_cl__checkout,
+  svn_cl__checkpoint,
+  svn_cl__checkpoints,
   svn_cl__cleanup,
   svn_cl__commit,
   svn_cl__copy,

Modified: subversion/branches/shelve-checkpoint/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/svn/svn.c?rev=1801942&r1=1801941&r2=1801942&view=diff
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/svn/svn.c (original)
+++ subversion/branches/shelve-checkpoint/subversion/svn/svn.c Fri Jul 14 11:37:03 2017
@@ -611,6 +611,31 @@ const svn_opt_subcommand_desc2_t svn_cl_
      "  reporting the action taken.\n"),
     {'r', 'q', 'N', opt_depth, opt_force, opt_ignore_externals} },
 
+  { "checkpoint", svn_cl__checkpoint, {0}, N_
+    ("Checkpoint the local changes.\n"
+     "usage: 1. checkpoint save\n"
+     "       2. checkpoint revert\n"
+     "       3. checkpoint rollback NUMBER\n"
+     "       4. checkpoint list|--list\n"
+     "\n"
+     "  1. Save the working state as a new checkpoint.\n"
+     "  2. Revert the working state to the current checkpoint.\n"
+     "  3. Roll back the working state to checkpoint NUMBER.\n"
+     "  4. List all checkpoints. A synonym for 'svn checkpoints'.\n"),
+    {'q',
+     /*'-N', opt_depth, opt_targets, opt_changelist,*/
+     /*SVN_CL__LOG_MSG_OPTIONS,*/
+     opt_list},
+    { {opt_list, N_("list all checkpoints")} }
+    },
+
+  { "checkpoints", svn_cl__checkpoints, {0}, N_
+    ("List all checkpoints.\n"
+     "usage: checkpoints\n"
+     "\n"
+     "  A synonym for 'svn checkpoint list'.\n"),
+    {} },
+
   { "cleanup", svn_cl__cleanup, {0}, N_
     ("Recursively clean up the working copy, removing write locks, resuming\n"
      "unfinished operations, etc.\n"

Modified: subversion/branches/shelve-checkpoint/tools/client-side/bash_completion
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/tools/client-side/bash_completion?rev=1801942&r1=1801941&r2=1801942&view=diff
==============================================================================
--- subversion/branches/shelve-checkpoint/tools/client-side/bash_completion (original)
+++ subversion/branches/shelve-checkpoint/tools/client-side/bash_completion Fri Jul 14 11:37:03 2017
@@ -248,6 +248,7 @@ _svn()
 	cmds="$cmds patch propdel pdel propedit pedit propget pget proplist"
 	cmds="$cmds plist propset pset relocate resolve resolved revert status"
 	cmds="$cmds switch unlock update upgrade"
+	cmds="$cmds checkpoint checkpoints"
 	cmds="$cmds shelve shelves unshelve"
 
 	# help options have a strange command status...
@@ -1020,6 +1021,12 @@ _svn()
 	upgrade)
 		cmdOpts="$qOpts $pOpts"
 		;;
+	checkpoint)
+		cmdOpts="$qOpts save revert rollback list --list"
+		;;
+	checkpoints)
+		cmdOpts="$qOpts"
+		;;
 	shelve)
 		cmdOpts="$qOpts --delete --list --dry-run $nOpts --targets $cOpts"
 		;;