subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From julianf...@apache.org
Subject svn commit: r1820696 - in /subversion/branches/shelve-checkpoint/subversion: include/svn_opt.h libsvn_client/client.h libsvn_client/prop_commands.c libsvn_client/shelve.c libsvn_subr/opt.c svn/props.c
Date Tue, 09 Jan 2018 20:42:27 GMT
Author: julianfoad
Date: Tue Jan  9 20:42:27 2018
New Revision: 1820696

URL: http://svn.apache.org/viewvc?rev=1820696&view=rev
Log:
On the 'shelve-checkpoint' branch: Let revision specifiers access shelves.

Support a new kind of revision specifier: '-r SHELF_NAME' or
'path@SHELF_NAME', in the CLI and in svn_opt_revision_t.

Initially this is implemented just for revprop commands, to access the
shelf's log message. These work:

$ svn propset -r foo --revprop svn:log 'New log msg.'

$ svn propget -r foo --revprop svn:log 
New log msg.

And 'proplist' and 'propedit' and 'propdel'.

Error handling for the rev spec is not in place; any rev spec other than a
previously known kind is now assumed to be the name of a shelf.

* subversion/include/svn_opt.h
  (svn_opt_revision_kind): Add a new kind, 'svn_opt_revision_shelf'.
  (svn_opt_revision_value_t): Add a new value store, 'shelf'.
  (svn_opt_parse_path): Document new pool lifetime consideration.

* subversion/libsvn_client/client.h
  (svn_client__shelf_revprop_set,
   svn_client__shelf_revprop_get,
   svn_client__shelf_revprop_list): New.

* subversion/libsvn_client/shelve.c
  (shelf_read_log_message): Read the whole log message instead of just the
    first line. Simplify.
  (shelf_write_log_message): Truncate the file, so that shortening the log
    message works properly.
  (svn_client__shelf_revprop_set,
   svn_client__shelf_revprop_get,
   svn_client__shelf_revprop_list): New.
  (svn_client_shelf_set_log_message): Adjust

* subversion/libsvn_client/prop_commands.c
  (svn_client_revprop_set2,
   svn_client_revprop_get, 
   svn_client_revprop_list): Read/write to a shelf if revision says so.

* subversion/libsvn_subr/opt.c
  (parse_one_rev): Allow only a single 'r' prefix on a number, instead of any
    number of 'r's on any rev spec.
  (svn_opt__revision_to_string): Support shelf rev specs.
  (svn_opt_parse_revision_to_range,
   svn_opt_parse_path): If no other kind of rev spec matches, assume it's a
    shelf specifier.

* subversion/svn/props.c
  (svn_cl__revprop_prepare): Support shelf rev-specs.

Modified:
    subversion/branches/shelve-checkpoint/subversion/include/svn_opt.h
    subversion/branches/shelve-checkpoint/subversion/libsvn_client/client.h
    subversion/branches/shelve-checkpoint/subversion/libsvn_client/prop_commands.c
    subversion/branches/shelve-checkpoint/subversion/libsvn_client/shelve.c
    subversion/branches/shelve-checkpoint/subversion/libsvn_subr/opt.c
    subversion/branches/shelve-checkpoint/subversion/svn/props.c

Modified: subversion/branches/shelve-checkpoint/subversion/include/svn_opt.h
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/include/svn_opt.h?rev=1820696&r1=1820695&r2=1820696&view=diff
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/include/svn_opt.h (original)
+++ subversion/branches/shelve-checkpoint/subversion/include/svn_opt.h Tue Jan  9 20:42:27
2018
@@ -369,7 +369,10 @@ enum svn_opt_revision_kind {
   svn_opt_revision_working,
 
   /** repository youngest */
-  svn_opt_revision_head
+  svn_opt_revision_head,
+
+  /** shelf */
+  svn_opt_revision_shelf
 
   /* please update svn_opt__revision_to_string() when extending this enum */
 };
@@ -390,6 +393,10 @@ typedef union svn_opt_revision_value_t
 
   /** the date of the revision */
   apr_time_t date;
+
+  /** a shelf identifier;
+   * @since New in 1.X. */
+  const char *shelf;
 } svn_opt_revision_value_t;
 
 /** A revision, specified in one of @c svn_opt_revision_kind ways. */
@@ -660,6 +667,8 @@ svn_opt_parse_all_args(apr_array_header_
  * specifier with no path before it, such as "@abc".
  * @since Since 1.9.0, this no longer returns an error if @a path contains a peg
  * specifier with no path before it, such as "@abc".
+ * @since Since 1.X, if @a *rev refers to a shelf then its lifetime is
+ * restricted to that of @a pool.
  */
 svn_error_t *
 svn_opt_parse_path(svn_opt_revision_t *rev,

Modified: subversion/branches/shelve-checkpoint/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_client/client.h?rev=1820696&r1=1820695&r2=1820696&view=diff
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/libsvn_client/client.h (original)
+++ subversion/branches/shelve-checkpoint/subversion/libsvn_client/client.h Tue Jan  9 20:42:27
2018
@@ -1267,6 +1267,35 @@ svn_client__merge_locked(svn_client__con
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool);
 
+/** Set @a shelf's revprop @a prop_name to @a prop_val.
+ *
+ * (Initially only implements svn:log; others ignored.)
+ */
+svn_error_t *
+svn_client__shelf_revprop_set(svn_client_shelf_t *shelf,
+                               const char *prop_name,
+                               const svn_string_t *prop_val,
+                               apr_pool_t *scratch_pool);
+
+/** Get @a shelf's revprop @a prop_name into @a prop_val.
+ *
+ * (Initially only implements svn:log; others get NULL.)
+ */
+svn_error_t *
+svn_client__shelf_revprop_get(svn_string_t **prop_val,
+                               svn_client_shelf_t *shelf,
+                               const char *prop_name,
+                               apr_pool_t *result_pool);
+
+/** Get @a shelf's revprops into @a props.
+ *
+ * (Initially only implements svn:log.)
+ */
+svn_error_t *
+svn_client__shelf_revprop_list(apr_hash_t **props,
+                               svn_client_shelf_t *shelf,
+                               apr_pool_t *result_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/shelve-checkpoint/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_client/prop_commands.c?rev=1820696&r1=1820695&r2=1820696&view=diff
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/shelve-checkpoint/subversion/libsvn_client/prop_commands.c Tue Jan
 9 20:42:27 2018
@@ -476,6 +476,18 @@ svn_client_revprop_set2(const char *prop
     return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
                              _("Bad property name: '%s'"), propname);
 
+  if (revision->kind == svn_opt_revision_shelf)
+    {
+      svn_client_shelf_t *shelf;
+
+      SVN_ERR(svn_client_shelf_open(&shelf, revision->value.shelf,
+                                    URL, ctx, pool));
+      SVN_ERR(svn_client__shelf_revprop_set(shelf, propname, propval, pool));
+      SVN_ERR(svn_client_shelf_close(shelf, pool));
+      *set_rev = SVN_INVALID_REVNUM;
+      return SVN_NO_ERROR;
+    }
+
   /* Open an RA session for the URL. */
   SVN_ERR(svn_client_open_ra_session2(&ra_session, URL, NULL,
                                       ctx, pool, pool));
@@ -976,6 +988,18 @@ svn_client_revprop_get(const char *propn
   apr_pool_t *subpool = svn_pool_create(pool);
   svn_error_t *err;
 
+  if (revision->kind == svn_opt_revision_shelf)
+    {
+      svn_client_shelf_t *shelf;
+
+      SVN_ERR(svn_client_shelf_open(&shelf, revision->value.shelf,
+                                    URL, ctx, pool));
+      SVN_ERR(svn_client__shelf_revprop_get(propval, shelf, propname, pool));
+      SVN_ERR(svn_client_shelf_close(shelf, pool));
+      *set_rev = SVN_INVALID_REVNUM;
+      return SVN_NO_ERROR;
+    }
+
   /* Open an RA session for the URL. Note that we don't have a local
      directory, nor a place to put temp files. */
   SVN_ERR(svn_client_open_ra_session2(&ra_session, URL, NULL,
@@ -1554,6 +1578,18 @@ svn_client_revprop_list(apr_hash_t **pro
   apr_pool_t *subpool = svn_pool_create(pool);
   svn_error_t *err;
 
+  if (revision->kind == svn_opt_revision_shelf)
+    {
+      svn_client_shelf_t *shelf;
+
+      SVN_ERR(svn_client_shelf_open(&shelf, revision->value.shelf,
+                                    URL, ctx, pool));
+      SVN_ERR(svn_client__shelf_revprop_list(props, shelf, pool));
+      SVN_ERR(svn_client_shelf_close(shelf, pool));
+      *set_rev = SVN_INVALID_REVNUM;
+      return SVN_NO_ERROR;
+    }
+
   /* Open an RA session for the URL. Note that we don't have a local
      directory, nor a place to put temp files. */
   SVN_ERR(svn_client_open_ra_session2(&ra_session, URL, NULL,

Modified: subversion/branches/shelve-checkpoint/subversion/libsvn_client/shelve.c
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_client/shelve.c?rev=1820696&r1=1820695&r2=1820696&view=diff
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/libsvn_client/shelve.c (original)
+++ subversion/branches/shelve-checkpoint/subversion/libsvn_client/shelve.c Tue Jan  9 20:42:27
2018
@@ -123,25 +123,18 @@ get_log_abspath(char **log_abspath,
 }
 
 /* Set SHELF->log_message by reading from its file storage.
- *
- * ### Currently just reads the first line.
  */
 static svn_error_t *
 shelf_read_log_message(svn_client_shelf_t *shelf,
                        apr_pool_t *result_pool)
 {
   char *log_abspath;
-  apr_file_t *file;
   svn_error_t *err;
-  svn_stream_t *stream;
-  svn_boolean_t eof;
-  svn_stringbuf_t *line;
+  svn_stringbuf_t *log_msg_str;
 
   SVN_ERR(get_log_abspath(&log_abspath, shelf, result_pool, result_pool));
 
-  err = svn_io_file_open(&file, log_abspath,
-                         APR_FOPEN_READ,
-                         APR_FPROT_OS_DEFAULT, result_pool);
+  err = svn_stringbuf_from_file2(&log_msg_str, log_abspath, result_pool);
   if (err && err->apr_err == APR_ENOENT)
     {
       svn_error_clear(err);
@@ -150,11 +143,7 @@ shelf_read_log_message(svn_client_shelf_
     }
   else
     SVN_ERR(err);
-  stream = svn_stream_from_aprfile2(file, FALSE /*disown*/, result_pool);
-
-  SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, result_pool));
-  SVN_ERR(svn_stream_close(stream));
-  shelf->log_message = line->data;
+  shelf->log_message = log_msg_str->data;
   return SVN_NO_ERROR;
 }
 
@@ -171,7 +160,7 @@ shelf_write_log_message(svn_client_shelf
   SVN_ERR(get_log_abspath(&log_abspath, shelf, scratch_pool, scratch_pool));
 
   SVN_ERR(svn_io_file_open(&file, log_abspath,
-                           APR_FOPEN_WRITE | APR_FOPEN_CREATE,
+                           APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE,
                            APR_FPROT_OS_DEFAULT, scratch_pool));
   stream = svn_stream_from_aprfile2(file, FALSE /*disown*/, scratch_pool);
 
@@ -180,6 +169,48 @@ shelf_write_log_message(svn_client_shelf
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_client__shelf_revprop_set(svn_client_shelf_t *shelf,
+                               const char *prop_name,
+                               const svn_string_t *prop_val,
+                               apr_pool_t *scratch_pool)
+{
+  if (strcmp(prop_name, "svn:log") == 0)
+    {
+      shelf->log_message = apr_pstrdup(shelf->pool, prop_val->data);
+      SVN_ERR(shelf_write_log_message(shelf, scratch_pool));
+    }
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client__shelf_revprop_get(svn_string_t **prop_val,
+                               svn_client_shelf_t *shelf,
+                               const char *prop_name,
+                               apr_pool_t *result_pool)
+{
+  if (strcmp(prop_name, "svn:log") == 0)
+    {
+      *prop_val = svn_string_create(shelf->log_message, result_pool);
+    }
+  else
+    {
+      *prop_val = NULL;
+    }
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client__shelf_revprop_list(apr_hash_t **props,
+                               svn_client_shelf_t *shelf,
+                               apr_pool_t *result_pool)
+{
+  *props = apr_hash_make(result_pool);
+  svn_hash_sets(*props, "svn:log",
+                svn_string_create(shelf->log_message, result_pool));
+  return SVN_NO_ERROR;
+}
+
 /*  */
 static char *
 get_current_abspath(svn_client_shelf_t *shelf,

Modified: subversion/branches/shelve-checkpoint/subversion/libsvn_subr/opt.c
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_subr/opt.c?rev=1820696&r1=1820695&r2=1820696&view=diff
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/libsvn_subr/opt.c (original)
+++ subversion/branches/shelve-checkpoint/subversion/libsvn_subr/opt.c Tue Jan  9 20:42:27
2018
@@ -488,20 +488,6 @@ static char *parse_one_rev(svn_opt_revis
 {
   char *end, save;
 
-  /* Allow any number of 'r's to prefix a revision number, because
-     that way if a script pastes svn output into another svn command
-     (like "svn log -r${REV_COPIED_FROM_OUTPUT}"), it'll Just Work,
-     even when compounded.
-
-     As it happens, none of our special revision words begins with
-     "r".  If any ever do, then this code will have to get smarter.
-
-     Incidentally, this allows "r{DATE}".  We could avoid that with
-     some trivial code rearrangement, but it's not clear what would
-     be gained by doing so. */
-  while (*str == 'r')
-    str++;
-
   if (*str == '{')
     {
       svn_boolean_t matched;
@@ -526,9 +512,19 @@ static char *parse_one_rev(svn_opt_revis
       revision->value.date = tm;
       return end + 1;
     }
-  else if (svn_ctype_isdigit(*str))
+  else if (svn_ctype_isdigit(*str)
+           || (str[0] == 'r' && svn_ctype_isdigit(str[1])))
     {
       /* It's a number. */
+
+      /* Allow an 'r' to prefix a revision number, because
+         that way if a script pastes svn output into another svn command
+         (like "svn log -r${REV_COPIED_FROM_OUTPUT}"), it'll Just Work.
+
+         Previously we stripped any number of leading 'r's from any
+         revision spec. */
+      if (str[0] == 'r')
+        str++;
       end = str + 1;
       while (svn_ctype_isdigit(*end))
         end++;
@@ -594,7 +590,10 @@ svn_opt_parse_revision_to_range(apr_arra
 
   if (svn_opt_parse_revision(&(range->start), &(range->end),
                              arg, pool) == -1)
-    return -1;
+    {
+      range->start.kind = svn_opt_revision_shelf;
+      range->start.value.shelf = apr_pstrdup(pool, arg);
+    }
 
   APR_ARRAY_PUSH(opt_ranges, svn_opt_revision_range_t *) = range;
   return 0;
@@ -651,6 +650,8 @@ svn_opt__revision_to_string(const svn_op
         return "working";
       case svn_opt_revision_head:
         return "head";
+      case svn_opt_revision_shelf:
+        return apr_pstrdup(result_pool, revision->value.shelf);
       default:
         return NULL;
     }
@@ -810,6 +811,11 @@ svn_opt_parse_path(svn_opt_revision_t *r
           ret = svn_opt_parse_revision(&start_revision,
                                        &end_revision,
                                        rev_str, pool);
+          if (ret == -1)
+            {
+              start_revision.kind = svn_opt_revision_shelf;
+              end_revision.value.shelf = rev_str;  /* is allocated in POOL */
+            }
         }
 
       if (ret || end_revision.kind != svn_opt_revision_unspecified)

Modified: subversion/branches/shelve-checkpoint/subversion/svn/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/svn/props.c?rev=1820696&r1=1820695&r2=1820696&view=diff
==============================================================================
--- subversion/branches/shelve-checkpoint/subversion/svn/props.c (original)
+++ subversion/branches/shelve-checkpoint/subversion/svn/props.c Tue Jan  9 20:42:27 2018
@@ -41,6 +41,7 @@
 #include "svn_opt.h"
 #include "svn_xml.h"
 #include "svn_base64.h"
+#include "svn_path.h"
 #include "cl.h"
 
 #include "private/svn_string_private.h"
@@ -60,10 +61,11 @@ svn_cl__revprop_prepare(const svn_opt_re
 
   if (revision->kind != svn_opt_revision_number
       && revision->kind != svn_opt_revision_date
-      && revision->kind != svn_opt_revision_head)
+      && revision->kind != svn_opt_revision_head
+      && revision->kind != svn_opt_revision_shelf)
     return svn_error_create
       (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-       _("Must specify the revision as a number, a date or 'HEAD' "
+       _("Must specify the revision as a number, a date, 'HEAD' or a shelf "
          "when operating on a revision property"));
 
   /* There must be exactly one target at this point.  If it was optional and
@@ -72,9 +74,19 @@ svn_cl__revprop_prepare(const svn_opt_re
     return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                             _("Wrong number of targets specified"));
 
+  target = APR_ARRAY_IDX(targets, 0, const char *);
+
+  if (revision->kind == svn_opt_revision_shelf)
+    {
+      if (svn_path_is_url(target))
+        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                _("A shelf needs a local path not a URL"));
+      *URL = apr_pstrdup(pool, target);
+      return SVN_NO_ERROR;
+    }
+
   /* (The docs say the target must be either a URL or implicit '.', but
      explicit WC targets are also accepted.) */
-  target = APR_ARRAY_IDX(targets, 0, const char *);
   SVN_ERR(svn_client_url_from_path2(URL, target, ctx, pool, pool));
   if (*URL == NULL)
     return svn_error_create



Mime
View raw message