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 2018/05/19 16:26:28 UTC

svn commit: r1831908 - in /subversion/trunk/subversion: include/svn_client.h libsvn_client/shelf.c libsvn_client/status.c tests/cmdline/shelf_tests.py

Author: julianfoad
Date: Sat May 19 16:26:28 2018
New Revision: 1831908

URL: http://svn.apache.org/viewvc?rev=1831908&view=rev
Log:
Shelving: implement 'svn status' for a shelf.

The interface uses a special form of changelist name, 'svn:shelf:SHELFNAME',
to request operating on a shelf.

Example:

  $ svn st --cl svn:shelf:foo
  --- Changelist 'svn:shelf:foo':
  A       add.txt
  MM      mod.txt
  D       del.txt

TODO: specialize the command-line syntax and output format to say 'shelf'
and hide the 'svn:shelf:' prefix.

* subversion/include/svn_client.h
  (svn_client_shelf_version_status_walk): New.

* subversion/libsvn_client/shelf.c
  (wc_status_unserialize): Rename the unused pool parameter.
  (status_read): Fill in the changelist name as 'svn:shelf:SHELFNAME'.
  (shelf_status_baton_t,
   shelf_status_visitor,
   shelf_status_visit_path,
   shelf_status_walk): Allow starting the walk at a given top relpath.
  (wc_status_baton_t,
   wc_status_visitor,
   svn_client_shelf_version_status_walk): New.
  (shelf_paths_changed,
   svn_client_shelf_apply,
   svn_client_shelf_export_patch): Adjust callers (top relpath = "").

* subversion/libsvn_client/status.c
  (shelf_status,
   shelves_status): New.
  (svn_client_status6): Run status on any requested shelves, before the
    main WC.

* subversion/tests/cmdline/shelf_tests.py
  (shelf_status): New test.
  (test_list): Run it.

Modified:
    subversion/trunk/subversion/include/svn_client.h
    subversion/trunk/subversion/libsvn_client/shelf.c
    subversion/trunk/subversion/libsvn_client/status.c
    subversion/trunk/subversion/tests/cmdline/shelf_tests.py

Modified: subversion/trunk/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=1831908&r1=1831907&r2=1831908&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Sat May 19 16:26:28 2018
@@ -7274,6 +7274,15 @@ svn_client_shelf_list(apr_hash_t **shelf
                       apr_pool_t *result_pool,
                       apr_pool_t *scratch_pool);
 
+/* Report the shelved status of all the shelved paths in SHELF_VERSION
+ * via WALK_FUNC(WALK_BATON, ...).
+ */
+svn_error_t *
+svn_client_shelf_version_status_walk(svn_client_shelf_version_t *shelf_version,
+                                     const char *wc_relpath,
+                                     svn_wc_status_func4_t walk_func,
+                                     void *walk_baton,
+                                     apr_pool_t *scratch_pool);
 /** @} */
 
 /** Changelist commands

Modified: subversion/trunk/subversion/libsvn_client/shelf.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/shelf.c?rev=1831908&r1=1831907&r2=1831908&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/shelf.c (original)
+++ subversion/trunk/subversion/libsvn_client/shelf.c Sat May 19 16:26:28 2018
@@ -485,7 +485,7 @@ wc_status_serialize(svn_stream_t *stream
 static svn_error_t *
 wc_status_unserialize(svn_wc_status3_t *status,
                       svn_stream_t *stream,
-                      apr_pool_t *scratch_pool)
+                      apr_pool_t *result_pool)
 {
   char string[5];
   apr_size_t len = 5;
@@ -527,9 +527,10 @@ static svn_error_t *
 status_read(svn_wc_status3_t **status,
             svn_client_shelf_version_t *shelf_version,
             const char *relpath,
+            apr_pool_t *result_pool,
             apr_pool_t *scratch_pool)
 {
-  svn_wc_status3_t *s = apr_pcalloc(scratch_pool, sizeof(*s));
+  svn_wc_status3_t *s = apr_pcalloc(result_pool, sizeof(*s));
   char *file_abspath;
   svn_stream_t *stream;
 
@@ -537,9 +538,11 @@ status_read(svn_wc_status3_t **status,
                                scratch_pool, scratch_pool));
   SVN_ERR(svn_stream_open_readonly(&stream, file_abspath,
                                    scratch_pool, scratch_pool));
-  SVN_ERR(wc_status_unserialize(s, stream, scratch_pool));
+  SVN_ERR(wc_status_unserialize(s, stream, result_pool));
   SVN_ERR(svn_stream_close(stream));
 
+  s->changelist = apr_psprintf(result_pool, "svn:shelf:%s",
+                               shelf_version->shelf->name);
   *status = s;
   return SVN_NO_ERROR;
 }
@@ -557,6 +560,7 @@ typedef svn_error_t *(*shelf_status_visi
 struct shelf_status_baton_t
 {
   svn_client_shelf_version_t *shelf_version;
+  const char *top_relpath;
   const char *walk_root_abspath;
   shelf_status_visitor_t walk_func;
   void *walk_baton;
@@ -581,7 +585,11 @@ shelf_status_visitor(void *baton,
       svn_wc_status3_t *s;
 
       relpath = apr_pstrndup(scratch_pool, relpath, strlen(relpath) - 5);
-      SVN_ERR(status_read(&s, b->shelf_version, relpath, scratch_pool));
+      if (!svn_relpath_skip_ancestor(b->top_relpath, relpath))
+        return SVN_NO_ERROR;
+
+      SVN_ERR(status_read(&s, b->shelf_version, relpath,
+                          scratch_pool, scratch_pool));
       SVN_ERR(b->walk_func(b->walk_baton, relpath, s, scratch_pool));
     }
   return SVN_NO_ERROR;
@@ -602,6 +610,7 @@ shelf_status_visit_path(svn_client_shelf
   apr_finfo_t finfo;
 
   baton.shelf_version = shelf_version;
+  baton.top_relpath = wc_relpath;
   baton.walk_root_abspath = shelf_version->files_dir_abspath;
   baton.walk_func = walk_func;
   baton.walk_baton = walk_baton;
@@ -617,6 +626,7 @@ shelf_status_visit_path(svn_client_shelf
  */
 static svn_error_t *
 shelf_status_walk(svn_client_shelf_version_t *shelf_version,
+                  const char *wc_relpath,
                   shelf_status_visitor_t walk_func,
                   void *walk_baton,
                   apr_pool_t *scratch_pool)
@@ -625,6 +635,7 @@ shelf_status_walk(svn_client_shelf_versi
   svn_error_t *err;
 
   baton.shelf_version = shelf_version;
+  baton.top_relpath = wc_relpath;
   baton.walk_root_abspath = shelf_version->files_dir_abspath;
   baton.walk_func = walk_func;
   baton.walk_baton = walk_baton;
@@ -639,6 +650,45 @@ shelf_status_walk(svn_client_shelf_versi
   return SVN_NO_ERROR;
 }
 
+typedef struct wc_status_baton_t
+{
+  svn_client_shelf_version_t *shelf_version;
+  svn_wc_status_func4_t walk_func;
+  void *walk_baton;
+} wc_status_baton_t;
+
+static svn_error_t *
+wc_status_visitor(void *baton,
+                      const char *relpath,
+                      svn_wc_status3_t *status,
+                      apr_pool_t *scratch_pool)
+{
+  struct wc_status_baton_t *b = baton;
+  svn_client_shelf_t *shelf = b->shelf_version->shelf;
+  const char *abspath = svn_dirent_join(shelf->wc_root_abspath, relpath,
+                                        scratch_pool);
+  SVN_ERR(b->walk_func(b->walk_baton, abspath, status, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_shelf_version_status_walk(svn_client_shelf_version_t *shelf_version,
+                                     const char *wc_relpath,
+                                     svn_wc_status_func4_t walk_func,
+                                     void *walk_baton,
+                                     apr_pool_t *scratch_pool)
+{
+  wc_status_baton_t baton;
+
+  baton.shelf_version = shelf_version;
+  baton.walk_func = walk_func;
+  baton.walk_baton = walk_baton;
+  SVN_ERR(shelf_status_walk(shelf_version, wc_relpath,
+                            wc_status_visitor, &baton,
+                            scratch_pool));
+  return SVN_NO_ERROR;
+}
+
 /* A baton for use with walk_callback(). */
 typedef struct write_changes_baton_t {
   const char *wc_root_abspath;
@@ -1158,7 +1208,7 @@ shelf_paths_changed(apr_hash_t **paths_h
   baton.as_abspath = as_abspath;
   baton.wc_root_abspath = shelf->wc_root_abspath;
   baton.pool = result_pool;
-  SVN_ERR(shelf_status_walk(shelf_version,
+  SVN_ERR(shelf_status_walk(shelf_version, "",
                             paths_changed_visitor, &baton,
                             scratch_pool));
 
@@ -1508,7 +1558,7 @@ svn_client_shelf_apply(svn_client_shelf_
 
   baton.shelf_version = shelf_version;
   baton.ctx = shelf_version->shelf->ctx;
-  SVN_ERR(shelf_status_walk(shelf_version,
+  SVN_ERR(shelf_status_walk(shelf_version, "",
                             apply_file_visitor, &baton,
                             scratch_pool));
 
@@ -1579,7 +1629,7 @@ svn_client_shelf_export_patch(svn_client
 
   baton.shelf_version = shelf_version;
   baton.outstream = outstream;
-  SVN_ERR(shelf_status_walk(shelf_version,
+  SVN_ERR(shelf_status_walk(shelf_version, "",
                             diff_visitor, &baton,
                             scratch_pool));
   return SVN_NO_ERROR;

Modified: subversion/trunk/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/status.c?rev=1831908&r1=1831907&r2=1831908&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/status.c (original)
+++ subversion/trunk/subversion/libsvn_client/status.c Sat May 19 16:26:28 2018
@@ -329,6 +329,77 @@ do_external_status(svn_client_ctx_t *ctx
 
   return SVN_NO_ERROR;
 }
+
+/* Run status on shelf SHELF_NAME, if it exists.
+ */
+static svn_error_t *
+shelf_status(const char *shelf_name,
+             const char *target_abspath,
+             svn_wc_status_func4_t status_func,
+             void *status_baton,
+             svn_client_ctx_t *ctx,
+             apr_pool_t *scratch_pool)
+{
+  svn_error_t *err;
+  svn_client_shelf_t *shelf;
+  svn_client_shelf_version_t *shelf_version;
+  const char *wc_relpath;
+
+  err = svn_client_shelf_open_existing(&shelf,
+                                       shelf_name, target_abspath,
+                                       ctx, scratch_pool);
+  if (err && err->apr_err == SVN_ERR_ILLEGAL_TARGET)
+    {
+      svn_error_clear(err);
+      return SVN_NO_ERROR;
+    }
+  else
+    SVN_ERR(err);
+
+  SVN_ERR(svn_client_shelf_version_open(&shelf_version,
+                                        shelf, shelf->max_version,
+                                        scratch_pool, scratch_pool));
+  wc_relpath = svn_dirent_skip_ancestor(shelf->wc_root_abspath, target_abspath);
+  SVN_ERR(svn_client_shelf_version_status_walk(shelf_version, wc_relpath,
+                                               status_func, status_baton,
+                                               scratch_pool));
+  SVN_ERR(svn_client_shelf_close(shelf, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Run status on all shelves named in CHANGELISTS by a changelist name
+ * of the form "svn:shelf:SHELF_NAME", if they exist.
+ */
+static svn_error_t *
+shelves_status(const apr_array_header_t *changelists,
+               const char *target_abspath,
+               svn_wc_status_func4_t status_func,
+               void *status_baton,
+               svn_client_ctx_t *ctx,
+               apr_pool_t *scratch_pool)
+{
+  static const char PREFIX[] = "svn:shelf:";
+  static const int PREFIX_LEN = 10;
+  int i;
+
+  for (i = 0; i < changelists->nelts; i++)
+    {
+      const char *cl = APR_ARRAY_IDX(changelists, i, const char *);
+
+      if (strncmp(cl, PREFIX, PREFIX_LEN) == 0)
+        {
+          const char *shelf_name = cl + PREFIX_LEN;
+
+          SVN_ERR(shelf_status(shelf_name, target_abspath,
+                               status_func, status_baton,
+                               ctx, scratch_pool));
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
 
 /*** Public Interface. ***/
 
@@ -586,6 +657,9 @@ svn_client_status6(svn_revnum_t *result_
     }
   else
     {
+      SVN_ERR(shelves_status(changelists, target_abspath,
+                             tweak_status, &sb,
+                             ctx, pool));
       err = svn_wc_walk_status(ctx->wc_ctx, target_abspath,
                                depth, get_all, no_ignore, FALSE, ignores,
                                tweak_status, &sb,

Modified: subversion/trunk/subversion/tests/cmdline/shelf_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/shelf_tests.py?rev=1831908&r1=1831907&r2=1831908&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/shelf_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/shelf_tests.py Sat May 19 16:26:28 2018
@@ -414,6 +414,29 @@ def shelve_with_log_message(sbox):
 
   os.chdir(was_cwd)
 
+#----------------------------------------------------------------------
+
+def shelf_status(sbox):
+  "shelf status"
+
+  sbox.build(empty=True)
+  was_cwd = os.getcwd()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
+
+  sbox.simple_add_text('New file', 'f')
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'shelve', 'foo')
+  expected_output = svntest.verify.RegexListOutput(
+    ["",
+     "--- Changelist 'svn:shelf:foo':",
+     "A       f",
+    ])
+  svntest.actions.run_and_verify_svn(expected_output, [],
+                                     'status', '--cl=svn:shelf:foo')
+
+  os.chdir(was_cwd)
+
 
 ########################################################################
 # Run the tests
@@ -436,6 +459,7 @@ test_list = [ None,
               shelve_binary_file_del,
               shelve_binary_file_replace,
               shelve_with_log_message,
+              shelf_status,
              ]
 
 if __name__ == '__main__':