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