I think I have finally got all of the i's crossed and the t's dotted this time.
I apologize for the length of time it took me to get this turned around, after
the fine reviews by Phillip Martin and Julian Foad. I was stuck on a very
subtle failure in a single test case involving the lone code path which could
possibly leave a keywords hash uninitialized. I went back and made sure that
all hash variables were initialized to NULL unless the next executable statement
would initialize it (so there isn't a possibility of branching before the hash
is init'd).
Log message included below and patch attached. I'll do the documentation patch
ASAP, including the #2219 canonicalized keywords changes.
John
[[[
Implement printf-like format characters for keyword expansion. Change all
other libraries to use new keyword hash functions from libsvn_subst.
Includes a new keyword, UUID, and tests for same.
See issue #890 for details.
* subversion/includes/svn_subst.h:
(svn_subst_keywords_t): Deprecated.
(svn_subst_build_keywords2): Interface change. A new argument
const char *uuid.
(svn_subst_build_keywords): Convert to API compatibility wrapper.
(svn_subst_keywords_differ2): Interface change. A new argument
apr_pool_t *pool and use hash instead of struct.
(svn_subst_keywords_differ): API compatibility wrapper.
(svn_subst_copy_and_translate3): Interface change; hash instead of struct
(svn_subst_copy_and_translate2): API compatibility wrapper
(svn_subst_copy_and_translate): API compatibility wrapper
(svn_subst_translate_cstring2): Interface change; hash instead of struct
(svn_subst_translate_cstring): API compatibility wrapper
(svn_subst_translate_stream2): Interface change; hash instead of struct
(svn_subst_translate_stream): API compatibility wrapper
* subversion/includes/svn_types.h:
(SVN_KEYWORD_REVISION_FORMAT,
SVN_KEYWORD_DATE_FORMAT,
SVN_KEYWORD_AUTHOR_FORMAT,
SVN_KEYWORD_URL_FORMAT,
SVN_KEYWORD_UUID_FORMAT,
SVN_KEYWORD_ID_FORMAT): New format strings for keyword expansion.
* subversion/libsvn_wc/merge.c
(svn_wc_merge): use key hashes, new svn_wc__get_keywords() parameters,
and svn_subst_copy_and_translate3()
* subversion/libsvn_wc/translate.h
(svn_wc__get_keywords): change signature to use keyword hash
* subversion/libsvn_wc/props.c
(validate_eol_prop_against_file, svn_wc_prop_set):
use svn_subst_translate_stream2(), keyword hashes, and new
svn_wc__get_keywords()
* subversion/libsvn_wc/adm_crawler.c
(restore_file): use keyword hashes, svn_subst_copy_and_translate3(),
and new svn_wc__get_keywords()
* subversion/libsvn_wc/log.c
(file_xfer_under_path, install_committed_file): use keyword hashes,
new svn_wc__get_keywords(), and svn_subst_copy_and_translate3()
* subversion/libsvn_wc/adm_ops.c
(revert_admin_things): use keyword hashes, new svn_wc__get_keywords(),
and svn_subst_copy_and_translate3()
* subversion/libsvn_wc/translate.c
(svn_wc_translated_file): use keyword hashes, new svn_wc__get_keywords(),
and svn_subst_copy_and_translate3()
(svn_wc__get_keywords): change signature to use keyword hashes and
svn_subst_build_keywords2()
* subversion/libsvn_subr/svn_subst.c:
(keyword_printf): New private function; printf-style formatting of
keywords based on format strings
(keywords_to_keyhash): New private function; convert keywords struct into
keywords hash
(keyhash_to_keywords): New private function; convert keywords hash into
keywords struct
(svn_subst_build_keywords): API combatibility wrapper
(svn_subst_build_keywords2): Build keywords using keyword_printf().
(translate_keyword): Interface changes. It now looks up keyword
passed in buffer, instead of predefined constant string.
(svn_subst_translate_stream): API combatibility wrapper
(svn_subst_translate_stream2): Loop over all elements of keyword hash
instead of structure elements.
(svn_subst_keywords_differ): API combatibility wrapper
(svn_subst_keywords_differ2): Compare two hashes instead of comparing
individual structure elements.
(svn_subst_copy_and_translate): API combatibility wrapper
(svn_subst_copy_and_translate2): API combatibility wrapper
(svn_subst_copy_and_translate3): uses keywords hash instead of struct.
* subversion/libsvn_client/export.c
(copy_one_versioned_file): use keyword hashes, new svn_wc__get_keywords(),
and svn_subst_copy_and_translate3()
(copy_versioned_files): retrieve uuid for call to copy_one_versioned_file
(struct edit_baton, struct file_baton): add uuid member
(add_file): copy uuid from edit baton to file baton during initialization
(close_file): initialize keyword hash, populate it with
svn_subst_build_keywords2(), and call svn_subst_copy_and_translate3()
(svn_client_export3): retrieve uuid and store in edit baton
* subversion/libsvn_client/cat.c
(svn_client_cat2): use keyword hashes, svn_subst_build_keywords2(),
and svn_subst_translate_stream2()
* subversion/libsvn_client/commit.c
(send_file_contents): use keyword hashes, svn_subst_build_keywords2(),
and svn_subst_translate_stream2()
* subversion/clients/cmdline/util.c
(svn_cl__edit_externally): use new svn_subst_translate_cstring2()
* subversion/tests/libsvn_wc/translate-test.c
(substitute_and_verify): use keyword hashes and add uuid parameter
(expand_uuid, unexpand_uuid): new tests for UUID keyword
(multiple test cases): reformat parameters and add uuid
]]]
--
John Peacock
Director of Information Research and Technology
Rowman & Littlefield Publishing Group
4720 Boston Way
Lanham, MD 20706
301-459-3366 x.5010
fax 301-429-5747
--- subversion/include/svn_subst.h (/mirror/trunk) (revision 13005)
+++ subversion/include/svn_subst.h (/local/keywords) (revision 13005)
@@ -75,7 +75,10 @@
const char *value);
-/** Values used in keyword expansion. */
+/** Values used in keyword expansion.
+ *
+ * @deprecated Provided for backward compatibility with the 1.1 API.
+ */
typedef struct svn_subst_keywords_t
{
const svn_string_t *revision;
@@ -86,16 +89,36 @@
} svn_subst_keywords_t;
-/** Fill in an <tt>svn_subst_keywords_t *</tt> @a kw with the appropriate
- * contents given an @a keywords_string (the contents of the svn:keywords
+/**
+ * @since New in 1.2.
+ *
+ * Fill in an <tt>apr_hash_t*</tt> @a kw with the appropriate contents
+ * given an @a keywords_string (the contents of the svn:keywords
* property for the file in question), the revision @a rev, the @a url,
- * the @a date the file was committed on, and the @a author of the last
- * commit. Any of these can be @c NULL to indicate that the information is
- * not present, or @c 0 for @a date.
+ * the @a date the file was committed on, the @a author of the last
+ * commit, and the @a uuid of the repository. Any of these can be @c NULL
+ * to indicate that the information is not present, or @c 0 for @a date.
+ *
+ * Both hash keys and values are (const char *) types.
*
* All memory is allocated out of @a pool.
*/
svn_error_t *
+svn_subst_build_keywords2 (apr_hash_t **kw,
+ const char *keywords_string,
+ const char *rev,
+ const char *url,
+ apr_time_t date,
+ const char *author,
+ const char *uuid,
+ apr_pool_t *pool);
+
+/** Similar to svn_subst_build_keywords2() except that it populates
+ * a svn_subst_keywords_t struct instead of a keywords hash.
+ *
+ * @deprecated Provided for backward compatibility with the 1.1 API.
+ */
+svn_error_t *
svn_subst_build_keywords (svn_subst_keywords_t *kw,
const char *keywords_string,
const char *rev,
@@ -107,6 +130,9 @@
/** Return @c TRUE if @a a and @a b do not hold the same keywords.
*
+ * @a a and @a b are hashes mapping @c (const char *) keyword names to
+ * @c (const * char *) keyword values.
+ *
* If @a compare_values is @c TRUE, "same" means that the @a a and @a b
* contain exactly the same set of keywords, and the values of corresponding
* keywords match as well. Else if @a compare_values is @c FALSE, then
@@ -117,6 +143,19 @@
* equivalent to holding no keywords.
*/
svn_boolean_t
+svn_subst_keywords_differ2 (const apr_hash_t *a,
+ const apr_hash_t *b,
+ svn_boolean_t compare_values,
+ apr_pool_t *pool);
+
+/** Similar to svn_subst_keywords_differ2() except that it compares
+ * two svn_subst_keywords_t structs instead of keyword hashes.
+ *
+ * Note: this function created and uses a temporary top-level pool.
+ *
+ * @deprecated Provided for backward compatibility with the 1.1 API.
+ */
+svn_boolean_t
svn_subst_keywords_differ (const svn_subst_keywords_t *a,
const svn_subst_keywords_t *b,
svn_boolean_t compare_values);
@@ -137,8 +176,8 @@
* re-expand expanded keywords. If @a expand is @c FALSE, contract expanded
* keywords and ignore contracted ones. @c NULL for any of the keyword
* values (@a keywords->revision, e.g.) indicates that keyword should be
- * ignored (not contracted or expanded). If the @a keywords structure
- * itself is @c NULL, keyword substitution will be altogether ignored.
+ * ignored (not contracted or expanded). If the @a keywords hash
+ * itself is empty, keyword substitution will be altogether ignored.
*
* Detect only keywords that are no longer than @c SVN_IO_MAX_KEYWORD_LEN
* bytes, including the delimiters and the keyword itself.
@@ -147,7 +186,7 @@
* @a keywords must be non-@c NULL.
*
* Recommendation: if @a expand is false, then you don't care about the
- * keyword values, so pass empty strings as non-null signifiers.
+ * keyword values, so pass a @c NULL pointer instead of an empty hash.
*
* Notes:
*
@@ -155,6 +194,19 @@
* convenient way to get @a eol_str and @a keywords if in libsvn_wc.
*/
svn_error_t *
+svn_subst_translate_stream2 (svn_stream_t *src,
+ svn_stream_t *dst,
+ const char *eol_str,
+ svn_boolean_t repair,
+ apr_hash_t *keywords,
+ svn_boolean_t expand);
+
+/** Similar to svn_subst_translate_stream2() except relies upon a
+ * svn_subst_keywords_t struct instead of a hash for the keywords.
+ *
+ * @deprecated Provided for backward compatibility with the 1.1 API.
+ */
+svn_error_t *
svn_subst_translate_stream (svn_stream_t *src,
svn_stream_t *dst,
const char *eol_str,
@@ -162,25 +214,9 @@
const svn_subst_keywords_t *keywords,
svn_boolean_t expand);
-
/**
- * @deprecated Provided for backward compatibility with the 1.0 API.
+ * @since New in 1.2.
*
- * Similar to svn_subst_copy_and_translate2 except that @a special is
- * always set to @c FALSE.
- */
-svn_error_t *
-svn_subst_copy_and_translate (const char *src,
- const char *dst,
- const char *eol_str,
- svn_boolean_t repair,
- const svn_subst_keywords_t *keywords,
- svn_boolean_t expand,
- apr_pool_t *pool);
-
-/**
- * @since New in 1.1.
- *
* Convenience routine: a variant of @c svn_subst_translate_stream
* which operates on files. (See previous docstring for details.) In
* addition, it will create/detranslate a special file if @a special
@@ -197,6 +233,24 @@
* copy.
*/
svn_error_t *
+svn_subst_copy_and_translate3 (const char *src,
+ const char *dst,
+ const char *eol_str,
+ svn_boolean_t repair,
+ apr_hash_t *keywords,
+ svn_boolean_t expand,
+ svn_boolean_t special,
+ apr_pool_t *pool);
+
+/**
+ * @since New in 1.1.
+ *
+ * Similar to svn_subst_copy_and_translate3 except that struct-style
+ * keywords are converted to hash-style.
+ *
+ * @deprecated Provided for backward compatibility with the 1.1 API.
+ */
+svn_error_t *
svn_subst_copy_and_translate2 (const char *src,
const char *dst,
const char *eol_str,
@@ -206,7 +260,24 @@
svn_boolean_t special,
apr_pool_t *pool);
-/** Convenience routine: a variant of @c svn_subst_translate_stream which
+/**
+ * @deprecated Provided for backward compatibility with the 1.0 API.
+ *
+ * Similar to svn_subst_copy_and_translate2 except that @a special is
+ * always set to @c FALSE.
+ */
+svn_error_t *
+svn_subst_copy_and_translate (const char *src,
+ const char *dst,
+ const char *eol_str,
+ svn_boolean_t repair,
+ const svn_subst_keywords_t *keywords,
+ svn_boolean_t expand,
+ apr_pool_t *pool);
+
+/** @since New in 1.2.
+ *
+ * Convenience routine: a variant of @c svn_subst_translate_stream2 which
* operates on cstrings. (See previous docstring for details.)
*
* Return a new string in @a *dst, allocated in @a pool, by copying the
@@ -217,6 +288,20 @@
* copy.
*/
svn_error_t *
+svn_subst_translate_cstring2 (const char *src,
+ const char **dst,
+ const char *eol_str,
+ svn_boolean_t repair,
+ apr_hash_t *keywords,
+ svn_boolean_t expand,
+ apr_pool_t *pool);
+
+/** @deprecated Provided for backward compatibility with the 1.1 API.
+ *
+ * Similar to svn_subst_translate_cstring2() except that keywords struct
+ * is converted to keywords hash
+ */
+svn_error_t *
svn_subst_translate_cstring (const char *src,
const char **dst,
const char *eol_str,
--- subversion/include/svn_types.h (/mirror/trunk) (revision 13005)
+++ subversion/include/svn_types.h (/local/keywords) (revision 13005)
@@ -216,35 +216,6 @@
/** Keyword substitution.
*
* All the keywords Subversion recognizes.
- *
- * Note that there is a better, more general proposal out there, which
- * would take care of both internationalization issues and custom
- * keywords (e.g., $NetBSD$). See
- *
- *<pre> http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=8921
- * =====
- * From: "Jonathan M. Manning" <jmanning@alisa-jon.net>
- * To: dev@subversion.tigris.org
- * Date: Fri, 14 Dec 2001 11:56:54 -0500
- * Message-ID: <87970000.1008349014@bdldevel.bl.bdx.com>
- * Subject: Re: keywords</pre>
- *
- * and Eric Gillespie's support of same:
- *
- *<pre> http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=8757
- * =====
- * From: "Eric Gillespie, Jr." <epg@pretzelnet.org>
- * To: dev@subversion.tigris.org
- * Date: Wed, 12 Dec 2001 09:48:42 -0500
- * Message-ID: <87k7vsebp1.fsf@vger.pretzelnet.org>
- * Subject: Re: Customizable Keywords</pre>
- *
- * However, it is considerably more complex than the scheme below.
- * For now we're going with simplicity, hopefully the more general
- * solution can be done post-1.0.
- *
- * @defgroup svn_types_keywords keywords
- * @{
*/
/** The maximum size of an expanded or un-expanded keyword. */
@@ -256,6 +227,9 @@
/** Short version of LastChangedRevision */
#define SVN_KEYWORD_REVISION_SHORT "Rev"
+/** Format string for Revision */
+#define SVN_KEYWORD_REVISION_FORMAT "%r"
+
/** Medium version of LastChangedRevision, matching the one CVS uses */
#define SVN_KEYWORD_REVISION_MEDIUM "Revision"
@@ -265,25 +239,42 @@
/** Short version of LastChangedDate */
#define SVN_KEYWORD_DATE_SHORT "Date"
+/** Format string for Date */
+#define SVN_KEYWORD_DATE_FORMAT "%D"
+
/** Who most recently committed to this file. */
#define SVN_KEYWORD_AUTHOR_LONG "LastChangedBy"
/** Short version of LastChangedBy */
#define SVN_KEYWORD_AUTHOR_SHORT "Author"
+/** Format string for Author */
+#define SVN_KEYWORD_AUTHOR_FORMAT "%a"
+
/** The URL for the head revision of this file. */
#define SVN_KEYWORD_URL_LONG "HeadURL"
/** Short version of HeadURL */
#define SVN_KEYWORD_URL_SHORT "URL"
-/** A compressed combination of the other four keywords.
- *
- * (But see comments above about a more general solution to keyword
- * combinations.)
- */
+/** Format string for URL */
+#define SVN_KEYWORD_URL_FORMAT "%u"
+
+/** The repository UUID. */
+#define SVN_KEYWORD_UUID_LONG "RepositoryUUID"
+
+/** Short version RepositoryUUID */
+#define SVN_KEYWORD_UUID_SHORT "UUID"
+
+/** Format string for URL */
+#define SVN_KEYWORD_UUID_FORMAT "%U"
+
+/** A compressed combination of the other four keywords */
#define SVN_KEYWORD_ID "Id"
+/** Format string for ID */
+#define SVN_KEYWORD_ID_FORMAT "%b %d %a %r"
+
/** @} */
--- subversion/libsvn_wc/merge.c (/mirror/trunk) (revision 13005)
+++ subversion/libsvn_wc/merge.c (/local/keywords) (revision 13005)
@@ -48,7 +48,7 @@
const char *mt_pt, *mt_bn;
apr_file_t *tmp_f, *result_f;
svn_boolean_t is_binary;
- svn_subst_keywords_t *keywords;
+ apr_hash_t *keywords = NULL;
const char *eol;
const svn_wc_entry_t *entry;
svn_boolean_t contains_conflicts, special;
@@ -235,12 +235,12 @@
pool));
SVN_ERR (svn_wc__get_special (&special, merge_target, adm_access,
pool));
- SVN_ERR (svn_subst_copy_and_translate2 (left,
+ SVN_ERR (svn_subst_copy_and_translate3 (left,
left_copy,
eol, eol ? TRUE : FALSE,
keywords, TRUE, special,
pool));
- SVN_ERR (svn_subst_copy_and_translate2 (right,
+ SVN_ERR (svn_subst_copy_and_translate3 (right,
right_copy,
eol, eol ? TRUE : FALSE,
keywords, TRUE, special,
@@ -294,7 +294,7 @@
pool));
SVN_ERR (svn_wc__get_special (&special, merge_target, adm_access,
pool));
- SVN_ERR (svn_subst_copy_and_translate2 (result_target, merge_target,
+ SVN_ERR (svn_subst_copy_and_translate3 (result_target, merge_target,
eol, eol ? TRUE : FALSE,
keywords, TRUE, special,
pool));
--- subversion/libsvn_wc/translate.h (/mirror/trunk) (revision 13005)
+++ subversion/libsvn_wc/translate.h (/local/keywords) (revision 13005)
@@ -67,19 +67,20 @@
const char *eol);
/* Expand keywords for the file at PATH, by parsing a
- whitespace-delimited list of keywords. If any keywords are found
- in the list, allocate *KEYWORDS from POOL, and then populate its
- entries with the related keyword values (also allocated in POOL).
- If no keywords are found in the list, or if there is no list, set
- *KEYWORDS to NULL. ADM_ACCESS must be an access baton for PATH.
+ whitespace-delimited list of keywords. Calling function must have
+ already allocated KEYWORDS from POOL. If any keywords are found
+ in the list, then populate the KEYWORDS hash entries with the related
+ keyword values (also allocated in POOL). If no keywords are found in
+ the list, or if there is no list, leave KEYWORDS hash empty. ADM_ACCESS
+ must be an access baton for PATH.
If FORCE_LIST is non-null, use it as the list; else use the
SVN_PROP_KEYWORDS property for PATH. In either case, use PATH to
expand keyword values. If a keyword is in the list, but no
- corresponding value is available, set that element of *KEYWORDS to
+ corresponding value is available, set that hash element of KEYWORDS to
the empty string ("").
*/
-svn_error_t *svn_wc__get_keywords (svn_subst_keywords_t **keywords,
+svn_error_t *svn_wc__get_keywords (apr_hash_t **keywords,
const char *path,
svn_wc_adm_access_t *adm_access,
const char *force_list,
--- subversion/libsvn_wc/props.c (/mirror/trunk) (revision 13005)
+++ subversion/libsvn_wc/props.c (/local/keywords) (revision 13005)
@@ -973,8 +973,8 @@
here is whether or not the function fails on inconsistent line
endings. The function is "translating" to an empty stream. This
is sneeeeeeeeeeeaky. */
- err = svn_subst_translate_stream (read_stream, write_stream,
- "", FALSE, NULL, FALSE);
+ err = svn_subst_translate_stream2 (read_stream, write_stream,
+ "", FALSE, NULL, FALSE);
if (err && err->apr_err == SVN_ERR_IO_INCONSISTENT_EOL)
return svn_error_createf (SVN_ERR_ILLEGAL_TARGET, err,
_("File '%s' has inconsistent newlines"),
@@ -1074,7 +1074,7 @@
svn_error_t *err;
apr_hash_t *prophash;
apr_file_t *fp = NULL;
- svn_subst_keywords_t *old_keywords;
+ apr_hash_t *old_keywords = NULL;
svn_stringbuf_t *new_value = NULL;
svn_node_kind_t kind;
enum svn_prop_kind prop_kind = svn_property_kind (NULL, name);
@@ -1210,11 +1210,11 @@
if (kind == svn_node_file && strcmp (name, SVN_PROP_KEYWORDS) == 0)
{
- svn_subst_keywords_t *new_keywords;
+ apr_hash_t *new_keywords;
SVN_ERR (svn_wc__get_keywords (&new_keywords, path, adm_access, NULL,
pool));
- if (svn_subst_keywords_differ (old_keywords, new_keywords, FALSE))
+ if (svn_subst_keywords_differ2 (old_keywords, new_keywords, FALSE, pool))
{
const char *base_name;
svn_wc_entry_t tmp_entry;
--- subversion/libsvn_wc/adm_crawler.c (/mirror/trunk) (revision 13005)
+++ subversion/libsvn_wc/adm_crawler.c (/local/keywords) (revision 13005)
@@ -61,7 +61,7 @@
apr_pool_t *pool)
{
const char *text_base_path, *tmp_text_base_path;
- svn_subst_keywords_t *keywords;
+ apr_hash_t *keywords = NULL;
const char *eol;
const svn_wc_entry_t *entry;
svn_wc_entry_t newentry;
@@ -87,7 +87,7 @@
sure to do any eol translations or keyword substitutions,
as dictated by the property values. If these properties
are turned off, then this is just a normal copy. */
- SVN_ERR (svn_subst_copy_and_translate2 (tmp_text_base_path,
+ SVN_ERR (svn_subst_copy_and_translate3 (tmp_text_base_path,
file_path,
eol, FALSE, /* don't repair */
keywords,
--- subversion/libsvn_wc/log.c (/mirror/trunk) (revision 13005)
+++ subversion/libsvn_wc/log.c (/local/keywords) (revision 13005)
@@ -112,7 +112,7 @@
case svn_wc__xfer_cp_and_translate:
{
- svn_subst_keywords_t *keywords;
+ apr_hash_t *keywords = NULL;
const char *eol_str;
svn_boolean_t special;
@@ -124,7 +124,7 @@
SVN_ERR (svn_wc__get_special (&special, full_dest_path, adm_access,
pool));
- SVN_ERR (svn_subst_copy_and_translate2 (full_from_path,
+ SVN_ERR (svn_subst_copy_and_translate3 (full_from_path,
full_dest_path,
eol_str,
TRUE,
@@ -140,7 +140,7 @@
case svn_wc__xfer_cp_and_detranslate:
{
- svn_subst_keywords_t *keywords;
+ apr_hash_t *keywords = NULL;
const char *eol_str;
svn_boolean_t special;
@@ -155,7 +155,7 @@
/* If any specific eol style was indicated, then detranslate
back to repository normal form ("\n"), repairingly. But if
no style indicated, don't touch line endings at all. */
- return svn_subst_copy_and_translate2 (full_from_path,
+ return svn_subst_copy_and_translate3 (full_from_path,
full_dest_path,
(eol_str ? "\n" : NULL),
(eol_str ? TRUE : FALSE),
@@ -214,7 +214,7 @@
const char *filepath;
const char *tmp_text_base;
svn_node_kind_t kind;
- svn_subst_keywords_t *keywords;
+ apr_hash_t *keywords = NULL;
apr_file_t *ignored;
svn_boolean_t same, did_set;
const char *tmp_wfile, *pdir, *bname;
@@ -261,7 +261,7 @@
SVN_ERR (svn_io_check_path (tmp_text_base, &kind, pool));
if (kind == svn_node_file)
- SVN_ERR (svn_subst_copy_and_translate2 (tmp_text_base,
+ SVN_ERR (svn_subst_copy_and_translate3 (tmp_text_base,
tmp_wfile,
eol_str,
FALSE, /* don't repair eol */
@@ -270,7 +270,7 @@
special,
pool));
else
- SVN_ERR (svn_subst_copy_and_translate2 (filepath,
+ SVN_ERR (svn_subst_copy_and_translate3 (filepath,
tmp_wfile,
eol_str,
FALSE, /* don't repair eol */
--- subversion/libsvn_wc/adm_ops.c (/mirror/trunk) (revision 13005)
+++ subversion/libsvn_wc/adm_ops.c (/local/keywords) (revision 13005)
@@ -1281,7 +1281,7 @@
missing altogether), copy the text-base out into
the working copy, and update the timestamp in the entries
file. */
- svn_subst_keywords_t *keywords;
+ apr_hash_t *keywords = NULL;
const char *eol;
svn_boolean_t special;
@@ -1295,7 +1295,7 @@
sure to do any eol translations or keyword substitutions,
as dictated by the property values. If these properties
are turned off, then this is just a normal copy. */
- if ((err = svn_subst_copy_and_translate2 (base_thing,
+ if ((err = svn_subst_copy_and_translate3 (base_thing,
fullpath,
eol,
FALSE, /* don't repair */
--- subversion/libsvn_wc/translate.c (/mirror/trunk) (revision 13005)
+++ subversion/libsvn_wc/translate.c (/local/keywords) (revision 13005)
@@ -49,7 +49,7 @@
{
svn_subst_eol_style_t style;
const char *eol;
- svn_subst_keywords_t *keywords;
+ apr_hash_t *keywords = NULL;
svn_boolean_t special;
SVN_ERR (svn_wc__get_eol_style (&style, &eol, vfile, adm_access, pool));
@@ -86,7 +86,7 @@
if (style == svn_subst_eol_style_fixed)
{
- SVN_ERR (svn_subst_copy_and_translate2 (vfile,
+ SVN_ERR (svn_subst_copy_and_translate3 (vfile,
tmp_vfile,
eol,
TRUE,
@@ -97,7 +97,7 @@
}
else if (style == svn_subst_eol_style_native)
{
- SVN_ERR (svn_subst_copy_and_translate2 (vfile,
+ SVN_ERR (svn_subst_copy_and_translate3 (vfile,
tmp_vfile,
SVN_WC__DEFAULT_EOL_MARKER,
force_repair,
@@ -108,7 +108,7 @@
}
else if (style == svn_subst_eol_style_none)
{
- SVN_ERR (svn_subst_copy_and_translate2 (vfile,
+ SVN_ERR (svn_subst_copy_and_translate3 (vfile,
tmp_vfile,
NULL,
force_repair,
@@ -169,19 +169,15 @@
svn_error_t *
-svn_wc__get_keywords (svn_subst_keywords_t **keywords,
+svn_wc__get_keywords (apr_hash_t **keywords,
const char *path,
svn_wc_adm_access_t *adm_access,
const char *force_list,
apr_pool_t *pool)
{
const char *list;
- svn_subst_keywords_t tmp_keywords = { 0 };
const svn_wc_entry_t *entry = NULL;
- /* Start by assuming no keywords. */
- *keywords = NULL;
-
/* Choose a property list to parse: either the one that came into
this function, or the one attached to PATH. */
if (force_list == NULL)
@@ -202,17 +198,16 @@
SVN_ERR (svn_wc_entry (&entry, path, adm_access, FALSE, pool));
- SVN_ERR (svn_subst_build_keywords (&tmp_keywords,
- list,
- apr_psprintf (pool, "%ld",
- entry->cmt_rev),
- entry->url,
- entry->cmt_date,
- entry->cmt_author,
- pool));
+ SVN_ERR (svn_subst_build_keywords2 (keywords,
+ list,
+ apr_psprintf (pool, "%ld",
+ entry->cmt_rev),
+ entry->url,
+ entry->cmt_date,
+ entry->cmt_author,
+ entry->uuid,
+ pool));
- *keywords = apr_pmemdup (pool, &tmp_keywords, sizeof (tmp_keywords));
-
return SVN_NO_ERROR;
}
--- subversion/libsvn_subr/subst.c (/mirror/trunk) (revision 13005)
+++ subversion/libsvn_subr/subst.c (/local/keywords) (revision 13005)
@@ -118,6 +118,194 @@
return SVN_NO_ERROR;
}
+
+/* Helper function for svn_subst_build_keywords */
+
+/** Given a printf-like format string, return a string with proper
+ * information filled in.
+ *
+ * The codes of format:
+ *
+ * %a author of this revision
+ * %b basename of the URL of this file
+ * %d short format of date of this revision
+ * %D long format of date of this revision
+ * %r number of this revision
+ * %u URL of this file
+ * %U UUID of the repository
+ *
+ * All memory is allocated out of @a pool.
+ */
+static svn_string_t *
+keyword_printf (const char *fmt,
+ const char *rev,
+ const char *url,
+ apr_time_t date,
+ const char *author,
+ const char *uuid,
+ apr_pool_t *pool)
+{
+ svn_stringbuf_t *value = svn_stringbuf_ncreate ("", 0, pool);
+ const char *cur;
+ char ch;
+ int n;
+
+ for (;;)
+ {
+ for (cur = fmt; (ch = *cur) != '\0' && ch != '%'; cur++)
+ /* void */;
+ if ( (n = cur - fmt) > 0) /* Do we have a as-is string? */
+ svn_stringbuf_appendbytes (value, fmt, n);
+
+ if (ch == '\0')
+ break;
+
+ cur++; /* skip '%' */
+ ch = *cur++;
+ switch (ch)
+ {
+ case 'a': /* author of this revision */
+ if (author)
+ svn_stringbuf_appendcstr (value, author);
+ break;
+ case 'b': /* basename of this file */
+ if (url)
+ {
+ const char *base_name = NULL;
+ base_name = svn_path_basename (url, pool);
+
+ svn_stringbuf_appendcstr (value, base_name);
+ }
+ break;
+ case 'd': /* short format of date of this revision */
+ if (date)
+ {
+ const char *human_date = NULL;
+
+ if (!date_prop_to_human (&human_date, FALSE, date, pool))
+ svn_stringbuf_appendcstr (value, human_date);
+ }
+ break;
+ case 'D': /* long format of date of this revision */
+ if (date)
+ {
+ const char *human_date = NULL;
+
+ if (!date_prop_to_human (&human_date, TRUE, date, pool))
+ svn_stringbuf_appendcstr (value, human_date);
+ }
+ break;
+ case 'r': /* number of this revision */
+ if (rev)
+ svn_stringbuf_appendcstr (value, rev);
+ break;
+ case 'u': /* URL of this file */
+ if (url)
+ svn_stringbuf_appendcstr (value, url);
+ break;
+ case 'U': /* UUID of the repository */
+ if (uuid)
+ svn_stringbuf_appendcstr (value, uuid);
+ break;
+ default: /* %?, print ? as is. */
+ svn_stringbuf_appendbytes (value, &ch, 1);
+ break;
+ }
+
+ /* Format code is processed. Get ready for next chunk. */
+ fmt = cur;
+ }
+
+ return svn_string_create_from_buf (value, pool);
+}
+
+/* Convert the old-style keywords struct into the new keywords hash */
+static apr_hash_t *
+keywords_to_keyhash (const svn_subst_keywords_t *kw,
+ apr_pool_t *pool)
+{
+ apr_hash_t *khash = apr_hash_make(pool);
+
+ /* if there are no keywords set, just return immediately */
+ if (kw == NULL)
+ return khash;
+
+ if (kw->revision)
+ {
+ apr_hash_set (khash, SVN_KEYWORD_REVISION_LONG,
+ APR_HASH_KEY_STRING, kw->revision);
+ apr_hash_set (khash, SVN_KEYWORD_REVISION_MEDIUM,
+ APR_HASH_KEY_STRING, kw->revision);
+ apr_hash_set (khash, SVN_KEYWORD_REVISION_SHORT,
+ APR_HASH_KEY_STRING, kw->revision);
+ }
+ if (kw->date)
+ {
+ apr_hash_set (khash, SVN_KEYWORD_DATE_LONG,
+ APR_HASH_KEY_STRING, kw->date);
+ apr_hash_set (khash, SVN_KEYWORD_DATE_SHORT,
+ APR_HASH_KEY_STRING, kw->date);
+ }
+ if (kw->author)
+ {
+ apr_hash_set (khash, SVN_KEYWORD_AUTHOR_LONG,
+ APR_HASH_KEY_STRING, kw->author);
+ apr_hash_set (khash, SVN_KEYWORD_AUTHOR_SHORT,
+ APR_HASH_KEY_STRING, kw->author);
+ }
+ if (kw->url)
+ {
+ apr_hash_set (khash, SVN_KEYWORD_URL_LONG,
+ APR_HASH_KEY_STRING, kw->url);
+ apr_hash_set (khash, SVN_KEYWORD_URL_SHORT,
+ APR_HASH_KEY_STRING, kw->url);
+ }
+ if (kw->id)
+ {
+ apr_hash_set (khash, SVN_KEYWORD_ID,
+ APR_HASH_KEY_STRING, kw->id);
+ }
+
+ return khash;
+}
+
+/* Convert new style keyhash into keyword struct */
+static void
+keyhash_to_keywords (svn_subst_keywords_t *kw,
+ apr_hash_t *khash,
+ apr_pool_t *pool)
+{
+ /* Attempt to fill all of the default keyword slots
+ * In each case, if the hash doesn't contain the corresponding
+ * keyword value, the struct element will be null
+ */
+
+ kw->revision = apr_hash_get(khash, SVN_KEYWORD_REVISION_LONG,
+ APR_HASH_KEY_STRING);
+ if (kw->revision == NULL)
+ kw->revision = svn_string_create ("", pool);
+
+ kw->date = apr_hash_get(khash, SVN_KEYWORD_DATE_LONG,
+ APR_HASH_KEY_STRING);
+ if (kw->date == NULL)
+ kw->date = svn_string_create ("", pool);
+
+ kw->author = apr_hash_get(khash, SVN_KEYWORD_AUTHOR_LONG,
+ APR_HASH_KEY_STRING);
+ if (kw->author == NULL)
+ kw->author = svn_string_create ("", pool);
+
+ kw->url = apr_hash_get(khash, SVN_KEYWORD_URL_LONG,
+ APR_HASH_KEY_STRING);
+ if (kw->url == NULL)
+ kw->url = svn_string_create ("", pool);
+
+ kw->id = apr_hash_get(khash, SVN_KEYWORD_ID,
+ APR_HASH_KEY_STRING);
+ if (kw->id == NULL)
+ kw->id = svn_string_create ("", pool);
+}
+
svn_error_t *
svn_subst_build_keywords (svn_subst_keywords_t *kw,
const char *keywords_val,
@@ -127,8 +315,30 @@
const char *author,
apr_pool_t *pool)
{
+ apr_hash_t *khash;
+ svn_error_t * kerror = svn_subst_build_keywords2(&khash, keywords_val, rev,
+ url, date, author, NULL,
+ pool);
+
+ keyhash_to_keywords (kw, khash, pool);
+
+ return kerror;
+}
+
+svn_error_t *
+svn_subst_build_keywords2 (apr_hash_t **kw,
+ const char *keywords_val,
+ const char *rev,
+ const char *url,
+ apr_time_t date,
+ const char *author,
+ const char *uuid,
+ apr_pool_t *pool)
+{
apr_array_header_t *keyword_tokens;
int i;
+ apr_hash_t *khash = apr_hash_make (pool);
+ *kw = khash;
keyword_tokens = svn_cstring_split (keywords_val, " \t\v\n\b\r\f",
TRUE /* chop */, pool);
@@ -141,45 +351,92 @@
|| (! strcmp (keyword, SVN_KEYWORD_REVISION_MEDIUM))
|| (! strcasecmp (keyword, SVN_KEYWORD_REVISION_SHORT)))
{
- kw->revision = svn_string_create (rev, pool);
- }
+ svn_string_t *revision_val;
+
+ revision_val = keyword_printf (SVN_KEYWORD_REVISION_FORMAT,
+ rev, url, date, author,
+ uuid, pool);
+ apr_hash_set (khash, SVN_KEYWORD_REVISION_LONG,
+ APR_HASH_KEY_STRING, revision_val);
+ apr_hash_set (khash, SVN_KEYWORD_REVISION_MEDIUM,
+ APR_HASH_KEY_STRING, revision_val);
+ apr_hash_set (khash, SVN_KEYWORD_REVISION_SHORT,
+ APR_HASH_KEY_STRING, revision_val);
+ }
else if ((! strcmp (keyword, SVN_KEYWORD_DATE_LONG))
|| (! strcasecmp (keyword, SVN_KEYWORD_DATE_SHORT)))
{
if (date)
{
- const char *human_date;
+ svn_string_t *date_val;
- SVN_ERR (date_prop_to_human (&human_date, TRUE, date, pool));
+ date_val = keyword_printf (SVN_KEYWORD_DATE_FORMAT,
+ rev, url, date, author,
+ uuid, pool);
+ apr_hash_set (khash, SVN_KEYWORD_DATE_LONG,
+ APR_HASH_KEY_STRING, date_val);
+ apr_hash_set (khash, SVN_KEYWORD_DATE_SHORT,
+ APR_HASH_KEY_STRING, date_val);
+ }
+ else
+ {
+ svn_string_t *date_val;
- kw->date = svn_string_create (human_date, pool);
+ date_val = svn_string_create ("", pool);
+ apr_hash_set (khash, SVN_KEYWORD_DATE_LONG,
+ APR_HASH_KEY_STRING, date_val);
+ apr_hash_set (khash, SVN_KEYWORD_DATE_SHORT,
+ APR_HASH_KEY_STRING, date_val);
}
- else
- kw->date = svn_string_create ("", pool);
}
else if ((! strcmp (keyword, SVN_KEYWORD_AUTHOR_LONG))
|| (! strcasecmp (keyword, SVN_KEYWORD_AUTHOR_SHORT)))
{
- kw->author = svn_string_create (author ? author : "", pool);
+ svn_string_t *author_val;
+
+ author_val = keyword_printf (SVN_KEYWORD_AUTHOR_FORMAT,
+ rev, url, date, author,
+ uuid, pool);
+ apr_hash_set (khash, SVN_KEYWORD_AUTHOR_LONG,
+ APR_HASH_KEY_STRING, author_val);
+ apr_hash_set (khash, SVN_KEYWORD_AUTHOR_SHORT,
+ APR_HASH_KEY_STRING, author_val);
}
else if ((! strcmp (keyword, SVN_KEYWORD_URL_LONG))
|| (! strcasecmp (keyword, SVN_KEYWORD_URL_SHORT)))
{
- kw->url = svn_string_create (url ? url : "", pool);
+ svn_string_t *url_val;
+
+ url_val = keyword_printf (SVN_KEYWORD_URL_FORMAT,
+ rev, url, date, author,
+ uuid, pool);
+ apr_hash_set (khash, SVN_KEYWORD_URL_LONG,
+ APR_HASH_KEY_STRING, url_val);
+ apr_hash_set (khash, SVN_KEYWORD_URL_SHORT,
+ APR_HASH_KEY_STRING, url_val);
}
+ else if ((! strcmp (keyword, SVN_KEYWORD_UUID_LONG))
+ || (! strcasecmp (keyword, SVN_KEYWORD_UUID_SHORT)))
+ {
+ svn_string_t *uuid_val;
+
+ uuid_val = keyword_printf (SVN_KEYWORD_UUID_FORMAT,
+ rev, url, date, author,
+ uuid, pool);
+ apr_hash_set (khash, SVN_KEYWORD_UUID_LONG,
+ APR_HASH_KEY_STRING, uuid_val);
+ apr_hash_set (khash, SVN_KEYWORD_UUID_SHORT,
+ APR_HASH_KEY_STRING, uuid_val);
+ }
else if ((! strcasecmp (keyword, SVN_KEYWORD_ID)))
{
- const char *base_name = url ? svn_path_basename (url, pool) : "";
- const char *human_date = NULL;
+ svn_string_t *id_val;
- if (date)
- SVN_ERR (date_prop_to_human (&human_date, FALSE, date, pool));
-
- kw->id = svn_string_createf (pool, "%s %s %s %s",
- base_name,
- rev,
- human_date ? human_date : "",
- author ? author : "");
+ id_val = keyword_printf (SVN_KEYWORD_ID_FORMAT,
+ rev, url, date, author,
+ uuid, pool);
+ apr_hash_set (khash, SVN_KEYWORD_ID,
+ APR_HASH_KEY_STRING, id_val);
}
}
@@ -377,8 +634,12 @@
translate_keyword (char *buf,
apr_size_t *len,
svn_boolean_t expand,
- const svn_subst_keywords_t *keywords)
+ const apr_hash_t *keywords)
{
+ const svn_string_t *value;
+ char key[SVN_KEYWORD_MAX_LEN + 1];
+ int i;
+
/* Make sure we gotz good stuffs. */
assert (*len <= SVN_KEYWORD_MAX_LEN);
assert ((buf[0] == '$') && (buf[*len - 1] == '$'));
@@ -387,86 +648,20 @@
if (! keywords)
return FALSE;
- /* Revision */
- if (keywords->revision)
- {
- if (translate_keyword_subst (buf, len,
- SVN_KEYWORD_REVISION_LONG,
- (sizeof (SVN_KEYWORD_REVISION_LONG)) - 1,
- expand ? keywords->revision : NULL))
- return TRUE;
+ for (i = 0; i < *len - 2 && buf[i + 1] != ':'; i++)
+ key[i] = *(buf + i + 1);
+ key[i] = 0;
- if (translate_keyword_subst (buf, len,
- SVN_KEYWORD_REVISION_MEDIUM,
- (sizeof (SVN_KEYWORD_REVISION_MEDIUM)) - 1,
- expand ? keywords->revision : NULL))
- return TRUE;
+ value = apr_hash_get ((apr_hash_t *)keywords, key, APR_HASH_KEY_STRING);
- if (translate_keyword_subst (buf, len,
- SVN_KEYWORD_REVISION_SHORT,
- (sizeof (SVN_KEYWORD_REVISION_SHORT)) - 1,
- expand ? keywords->revision : NULL))
- return TRUE;
- }
-
- /* Date */
- if (keywords->date)
+ if (value)
{
if (translate_keyword_subst (buf, len,
- SVN_KEYWORD_DATE_LONG,
- (sizeof (SVN_KEYWORD_DATE_LONG)) - 1,
- expand ? keywords->date : NULL))
+ key, strlen(key),
+ expand ? value : NULL))
return TRUE;
-
- if (translate_keyword_subst (buf, len,
- SVN_KEYWORD_DATE_SHORT,
- (sizeof (SVN_KEYWORD_DATE_SHORT)) - 1,
- expand ? keywords->date : NULL))
- return TRUE;
}
- /* Author */
- if (keywords->author)
- {
- if (translate_keyword_subst (buf, len,
- SVN_KEYWORD_AUTHOR_LONG,
- (sizeof (SVN_KEYWORD_AUTHOR_LONG)) - 1,
- expand ? keywords->author : NULL))
- return TRUE;
-
- if (translate_keyword_subst (buf, len,
- SVN_KEYWORD_AUTHOR_SHORT,
- (sizeof (SVN_KEYWORD_AUTHOR_SHORT)) - 1,
- expand ? keywords->author : NULL))
- return TRUE;
- }
-
- /* URL */
- if (keywords->url)
- {
- if (translate_keyword_subst (buf, len,
- SVN_KEYWORD_URL_LONG,
- (sizeof (SVN_KEYWORD_URL_LONG)) - 1,
- expand ? keywords->url : NULL))
- return TRUE;
-
- if (translate_keyword_subst (buf, len,
- SVN_KEYWORD_URL_SHORT,
- (sizeof (SVN_KEYWORD_URL_SHORT)) - 1,
- expand ? keywords->url : NULL))
- return TRUE;
- }
-
- /* Id */
- if (keywords->id)
- {
- if (translate_keyword_subst (buf, len,
- SVN_KEYWORD_ID,
- (sizeof (SVN_KEYWORD_ID)) - 1,
- expand ? keywords->id : NULL))
- return TRUE;
- }
-
/* No translations were successful. Return FALSE. */
return FALSE;
}
@@ -525,66 +720,67 @@
const svn_subst_keywords_t *b,
svn_boolean_t compare_values)
{
- if (((a == NULL) && (b == NULL)) /* no A or B */
- /* no A, and B has no contents */
- || ((a == NULL)
- && (b->revision == NULL)
- && (b->date == NULL)
- && (b->author == NULL)
- && (b->url == NULL))
- /* no B, and A has no contents */
- || ((b == NULL) && (a->revision == NULL)
- && (a->date == NULL)
- && (a->author == NULL)
- && (a->url == NULL))
- /* neither A nor B has any contents */
- || ((a != NULL) && (b != NULL)
- && (b->revision == NULL)
- && (b->date == NULL)
- && (b->author == NULL)
- && (b->url == NULL)
- && (a->revision == NULL)
- && (a->date == NULL)
- && (a->author == NULL)
- && (a->url == NULL)))
+ svn_boolean_t result = FALSE;
+ /* we have to create a new top level pool because we have none
+ * but it is destroyed as soon as the real function is called */
+ apr_pool_t *pool = svn_pool_create (NULL);
+
+ /* first we have to create a hash of each of the keyword struct's */
+ apr_hash_t *ahash = keywords_to_keyhash(a, pool);
+ apr_hash_t *bhash = keywords_to_keyhash(b, pool);
+
+ /* and then call the real function */
+ result = svn_subst_keywords_differ2 (ahash, bhash, compare_values, pool);
+
+ /* Always clean up after ourselves */
+ svn_pool_destroy (pool);
+ return result;
+}
+
+svn_boolean_t
+svn_subst_keywords_differ2 (const apr_hash_t *a,
+ const apr_hash_t *b,
+ svn_boolean_t compare_values,
+ apr_pool_t *pool)
+{
+ svn_boolean_t result = FALSE;
+ apr_hash_index_t *hi;
+ apr_hash_t *lame_a, *lame_b;
+
+ lame_a = (apr_hash_t *) a;
+ lame_b = (apr_hash_t *) b;
+
+
+ if (((a == NULL) && (b == NULL)) /* no A or B */
+ || ((a == NULL) && (b != NULL)) /* no A but B */
+ || ((a != NULL) && (b == NULL)) /* no B but A */
+ /* Unequal number of contents */
+ || (apr_hash_count(lame_a) != apr_hash_count(lame_b)))
{
- return FALSE;
+ return TRUE;
}
- else if ((a == NULL) || (b == NULL))
- return TRUE;
-
- /* Else both A and B have some keywords. */
-
- if ((! a->revision) != (! b->revision))
- return TRUE;
- else if ((compare_values && (a->revision != NULL))
- && (strcmp (a->revision->data, b->revision->data) != 0))
- return TRUE;
-
- if ((! a->date) != (! b->date))
- return TRUE;
- else if ((compare_values && (a->date != NULL))
- && (strcmp (a->date->data, b->date->data) != 0))
- return TRUE;
-
- if ((! a->author) != (! b->author))
- return TRUE;
- else if ((compare_values && (a->author != NULL))
- && (strcmp (a->author->data, b->author->data) != 0))
- return TRUE;
-
- if ((! a->url) != (! b->url))
- return TRUE;
- else if ((compare_values && (a->url != NULL))
- && (strcmp (a->url->data, b->url->data) != 0))
- return TRUE;
-
- /* Else we never found a difference, so they must be the same. */
-
- return FALSE;
+
+ /* If compare_values is FALSE, we can say A and B are the same now. */
+ if (!compare_values)
+ return FALSE;
+
+ /* compare_values is TRUE. Compare value by value */
+ for (hi = apr_hash_first(pool, lame_a);
+ hi && !result;
+ hi = apr_hash_next(hi))
+ {
+ const void *key;
+ apr_hash_this (hi, &key, NULL, NULL);
+ if (!svn_string_compare (apr_hash_get (lame_a, key,
+ APR_HASH_KEY_STRING),
+ apr_hash_get (lame_b, key,
+ APR_HASH_KEY_STRING)))
+ result = TRUE;
+ }
+
+ return result;
}
-
svn_error_t *
svn_subst_translate_stream (svn_stream_t *s, /* src stream */
svn_stream_t *d, /* dst stream */
@@ -593,6 +789,28 @@
const svn_subst_keywords_t *keywords,
svn_boolean_t expand)
{
+ /* we have to create a new top level pool because we have none
+ * but it is destroyed as soon as the real function is called */
+ apr_pool_t *pool = svn_pool_create (NULL);
+ apr_hash_t *kh = keywords_to_keyhash (keywords, pool);
+
+ /* call the real function */
+ svn_error_t *err = svn_subst_translate_stream2 (s, d, eol_str,
+ repair, kh, expand);
+
+ /* Always clean up after ourselves */
+ svn_pool_destroy (pool);
+ return err;
+}
+
+svn_error_t *
+svn_subst_translate_stream2 (svn_stream_t *s, /* src stream */
+ svn_stream_t *d, /* dst stream */
+ const char *eol_str,
+ svn_boolean_t repair,
+ apr_hash_t *keywords,
+ svn_boolean_t expand)
+{
char buf[SVN_STREAM_CHUNK_SIZE + 1];
const char *p, *interesting;
apr_size_t len, readlen;
@@ -711,6 +929,21 @@
svn_boolean_t expand,
apr_pool_t *pool)
{
+ apr_hash_t *kh = keywords_to_keyhash (keywords, pool);
+
+ return svn_subst_translate_cstring2 (src, dst, eol_str, repair,
+ kh, expand, pool);
+}
+
+svn_error_t *
+svn_subst_translate_cstring2 (const char *src,
+ const char **dst,
+ const char *eol_str,
+ svn_boolean_t repair,
+ apr_hash_t *keywords,
+ svn_boolean_t expand,
+ apr_pool_t *pool)
+{
svn_stringbuf_t *src_stringbuf, *dst_stringbuf;
svn_stream_t *src_stream, *dst_stream;
svn_error_t *err;
@@ -730,8 +963,8 @@
dst_stream = svn_stream_from_stringbuf (dst_stringbuf, pool);
/* Translate src stream into dst stream. */
- err = svn_subst_translate_stream (src_stream, dst_stream,
- eol_str, repair, keywords, expand);
+ err = svn_subst_translate_stream2 (src_stream, dst_stream,
+ eol_str, repair, keywords, expand);
if (err)
{
svn_error_clear (svn_stream_close (src_stream));
@@ -920,6 +1153,23 @@
svn_boolean_t special,
apr_pool_t *pool)
{
+ apr_hash_t *kh = keywords_to_keyhash (keywords, pool);
+
+ return svn_subst_copy_and_translate3 (src, dst, eol_str,
+ repair, kh, expand, special,
+ pool);
+}
+
+svn_error_t *
+svn_subst_copy_and_translate3 (const char *src,
+ const char *dst,
+ const char *eol_str,
+ svn_boolean_t repair,
+ apr_hash_t *keywords,
+ svn_boolean_t expand,
+ svn_boolean_t special,
+ apr_pool_t *pool)
+{
const char *dst_tmp = NULL;
svn_stream_t *src_stream, *dst_stream;
apr_file_t *s = NULL, *d = NULL; /* init to null important for APR */
@@ -972,8 +1222,8 @@
dst_stream = svn_stream_from_aprfile (d, subpool);
/* Translate src stream into dst stream. */
- err = svn_subst_translate_stream (src_stream, dst_stream,
- eol_str, repair, keywords, expand);
+ err = svn_subst_translate_stream2 (src_stream, dst_stream,
+ eol_str, repair, keywords, expand);
if (err)
{
if (err->apr_err == SVN_ERR_IO_INCONSISTENT_EOL)
@@ -1043,13 +1293,13 @@
SVN_ERR (svn_utf_cstring_to_utf8 (&val_utf8, value->data, pool));
}
- SVN_ERR (svn_subst_translate_cstring (val_utf8,
- &val_utf8_lf,
- "\n", /* translate to LF */
- FALSE, /* no repair */
- NULL, /* no keywords */
- FALSE, /* no expansion */
- pool));
+ SVN_ERR (svn_subst_translate_cstring2 (val_utf8,
+ &val_utf8_lf,
+ "\n", /* translate to LF */
+ FALSE, /* no repair */
+ NULL, /* no keywords */
+ FALSE, /* no expansion */
+ pool));
*new_value = svn_string_create (val_utf8_lf, pool);
@@ -1073,13 +1323,13 @@
return SVN_NO_ERROR;
}
- SVN_ERR (svn_subst_translate_cstring (value->data,
- &val_neol,
- APR_EOL_STR, /* 'native' eol */
- FALSE, /* no repair */
- NULL, /* no keywords */
- FALSE, /* no expansion */
- pool));
+ SVN_ERR (svn_subst_translate_cstring2 (value->data,
+ &val_neol,
+ APR_EOL_STR, /* 'native' eol */
+ FALSE, /* no repair */
+ NULL, /* no keywords */
+ FALSE, /* no expansion */
+ pool));
if (for_output)
{
--- subversion/libsvn_client/export.c (/mirror/trunk) (revision 13005)
+++ subversion/libsvn_client/export.c (/local/keywords) (revision 13005)
@@ -96,10 +96,11 @@
svn_wc_adm_access_t *adm_access,
svn_opt_revision_t *revision,
const char *native_eol,
+ const char *uuid,
apr_pool_t *pool)
{
const svn_wc_entry_t *entry;
- svn_subst_keywords_t kw = { 0 };
+ apr_hash_t *kw = NULL;
svn_subst_eol_style_t style;
apr_hash_t *props;
const char *base;
@@ -188,14 +189,14 @@
author = entry->cmt_author;
}
- SVN_ERR (svn_subst_build_keywords
+ SVN_ERR (svn_subst_build_keywords2
(&kw, keywords->data,
apr_psprintf (pool, fmt, entry->cmt_rev),
- entry->url, tm, author, pool));
+ entry->url, tm, author, uuid, pool));
}
- SVN_ERR (svn_subst_copy_and_translate2 (base, to, eol, FALSE,
- &kw, TRUE,
+ SVN_ERR (svn_subst_copy_and_translate3 (base, to, eol, FALSE,
+ kw, TRUE,
special ? TRUE : FALSE,
pool));
if (executable)
@@ -225,6 +226,7 @@
apr_hash_t *entries;
apr_hash_index_t *hi;
apr_finfo_t finfo;
+ const char *uuid;
SVN_ERR (svn_wc_adm_probe_open3 (&adm_access, NULL, from, FALSE,
0, ctx->cancel_func, ctx->cancel_baton,
@@ -243,6 +245,10 @@
svn_path_local_style (from, pool));
}
+ /* Get the UUID to later pass in to keyword handling*/
+ SVN_ERR (svn_client_uuid_from_url
+ (&uuid, entry->url, ctx, pool));
+
/* Only export 'added' files when the revision is WORKING.
Otherwise, skip the 'added' files, since they didn't exist
in the BASE revision and don't have an associated text-base.
@@ -325,7 +331,7 @@
SVN_ERR (copy_one_versioned_file (new_from, new_to, adm_access,
revision, native_eol,
- iterpool));
+ uuid, iterpool));
}
}
svn_pool_destroy (iterpool);
@@ -333,7 +339,7 @@
else if (entry->kind == svn_node_file)
{
SVN_ERR (copy_one_versioned_file (from, to, adm_access, revision,
- native_eol, pool));
+ native_eol, uuid, pool));
}
SVN_ERR (svn_wc_adm_close (adm_access));
@@ -396,6 +402,7 @@
{
const char *root_path;
const char *root_url;
+ const char *uuid;
svn_boolean_t force;
svn_revnum_t *target_revision;
apr_hash_t *externals;
@@ -439,6 +446,7 @@
const char *url;
const char *author;
apr_time_t date;
+ const char *uuid;
/* Pool associated with this baton. */
apr_pool_t *pool;
@@ -555,6 +563,7 @@
fb->edit_baton = eb;
fb->path = full_path;
fb->url = full_url;
+ fb->uuid = eb->uuid;
fb->pool = pool;
*baton = fb;
@@ -700,22 +709,22 @@
{
svn_subst_eol_style_t style;
const char *eol;
- svn_subst_keywords_t final_kw = {0};
+ apr_hash_t *final_kw = NULL;
if (fb->eol_style_val)
SVN_ERR (get_eol_style (&style, &eol, fb->eol_style_val->data,
eb->native_eol));
if (fb->keywords_val)
- SVN_ERR (svn_subst_build_keywords (&final_kw, fb->keywords_val->data,
- fb->revision, fb->url, fb->date,
- fb->author, pool));
+ SVN_ERR (svn_subst_build_keywords2 (&final_kw, fb->keywords_val->data,
+ fb->revision, fb->url, fb->date,
+ fb->author, fb->uuid, pool));
- SVN_ERR (svn_subst_copy_and_translate2
+ SVN_ERR (svn_subst_copy_and_translate3
(fb->tmppath, fb->path,
fb->eol_style_val ? eol : NULL,
fb->eol_style_val ? TRUE : FALSE, /* repair */
- fb->keywords_val ? &final_kw : NULL,
+ fb->keywords_val ? final_kw : NULL,
TRUE, /* expand */
fb->special,
pool));
@@ -761,6 +770,7 @@
{
svn_revnum_t edit_revision = SVN_INVALID_REVNUM;
const char *url;
+ const char *uuid;
if (svn_path_is_url (from) ||
! (revision->kind == svn_opt_revision_base ||
@@ -778,8 +788,12 @@
&url, from, peg_revision,
revision, ctx, pool));
+ /* Get the UUID to later populate the file_baton */
+ SVN_ERR (svn_client_uuid_from_url (&uuid, url, ctx, pool));
+
eb->root_path = to;
eb->root_url = url;
+ eb->uuid = uuid;
eb->force = force;
eb->target_revision = &edit_revision;
eb->notify_func = ctx->notify_func;
--- subversion/libsvn_client/cat.c (/mirror/trunk) (revision 13005)
+++ subversion/libsvn_client/cat.c (/local/keywords) (revision 13005)
@@ -78,7 +78,7 @@
}
else
{
- svn_subst_keywords_t kw = { 0 };
+ apr_hash_t *kw = NULL;
svn_subst_eol_style_t style;
const char *temp_dir;
const char *tmp_filename;
@@ -110,6 +110,7 @@
if (keywords)
{
+ const char *uuid;
svn_string_t *cmt_rev, *cmt_date, *cmt_author;
apr_time_t when = 0;
@@ -119,20 +120,23 @@
APR_HASH_KEY_STRING);
cmt_author = apr_hash_get (props, SVN_PROP_ENTRY_LAST_AUTHOR,
APR_HASH_KEY_STRING);
+ SVN_ERR (svn_client_uuid_from_url (&uuid, url, ctx, pool));
+
if (cmt_date)
SVN_ERR (svn_time_from_cstring (&when, cmt_date->data, pool));
- SVN_ERR (svn_subst_build_keywords
+ SVN_ERR (svn_subst_build_keywords2
(&kw, keywords->data,
cmt_rev->data,
url,
when,
cmt_author ? cmt_author->data : NULL,
+ uuid,
pool));
}
- SVN_ERR (svn_subst_translate_stream (tmp_stream, out, eol, FALSE, &kw,
- TRUE));
+ SVN_ERR (svn_subst_translate_stream2 (tmp_stream, out, eol, FALSE, kw,
+ TRUE));
SVN_ERR (svn_stream_close (tmp_stream));
}
--- subversion/libsvn_client/commit.c (/mirror/trunk) (revision 13005)
+++ subversion/libsvn_client/commit.c (/local/keywords) (revision 13005)
@@ -89,7 +89,7 @@
Keywords get unexpanded. */
if (eol_style_val || keywords_val || special)
{
- svn_subst_keywords_t keywords = {0};
+ apr_hash_t *keywords = NULL;
const char *temp_dir;
apr_file_t *tmp_f;
@@ -103,14 +103,14 @@
/* Generate a keyword structure. */
if (keywords_val)
- SVN_ERR (svn_subst_build_keywords (&keywords, keywords_val->data,
- APR_STRINGIFY(SVN_INVALID_REVNUM),
- "", 0, "", pool));
+ SVN_ERR (svn_subst_build_keywords2 (&keywords, keywords_val->data,
+ APR_STRINGIFY(SVN_INVALID_REVNUM),
+ "", 0, "", "", pool));
- if ((err = svn_subst_copy_and_translate2 (path, tmpfile_path,
+ if ((err = svn_subst_copy_and_translate3 (path, tmpfile_path,
eol_style_val ? "\n" : NULL,
FALSE,
- keywords_val ? &keywords : NULL,
+ keywords_val ? keywords : NULL,
FALSE,
special,
pool)))
--- subversion/clients/cmdline/util.c (/mirror/trunk) (revision 13005)
+++ subversion/clients/cmdline/util.c (/local/keywords) (revision 13005)
@@ -129,9 +129,9 @@
if (as_text)
{
const char *translated;
- SVN_ERR (svn_subst_translate_cstring (contents->data, &translated,
- APR_EOL_STR, FALSE,
- NULL, FALSE, pool));
+ SVN_ERR (svn_subst_translate_cstring2 (contents->data, &translated,
+ APR_EOL_STR, FALSE,
+ NULL, FALSE, pool));
translated_contents = svn_string_create ("", pool);
if (encoding)
SVN_ERR (svn_utf_cstring_from_utf8_ex (&translated_contents->data,
--- subversion/tests/libsvn_wc/translate-test.c (/mirror/trunk) (revision 13005)
+++ subversion/tests/libsvn_wc/translate-test.c (/local/keywords) (revision 13005)
@@ -125,7 +125,13 @@
".$veR$Author$",
"$",
"$$",
- "Line 74: end of subst test data."
+ "Line 74: Valid $RepositoryUUID$, started unexpanded.",
+ "Line 75: Valid $UUID$, started unexpanded.",
+ "Line 76: Valid $RepositoryUUID: 01234567-89ab-cdef-89ab-cdef01234567 $, "
+ "started expanded.",
+ "Line 77: Valid $UUID: 01234567-89ab-cdef-89ab-cdef01234567 $, "
+ "started expanded.",
+ "Line 78: end of subst test data."
};
@@ -258,31 +264,68 @@
const char *date,
const char *author,
const char *url,
+ const char *uuid,
svn_boolean_t expand,
apr_pool_t *pool)
{
svn_error_t *err;
svn_stringbuf_t *contents;
- svn_subst_keywords_t keywords;
+ apr_hash_t *keywords = apr_hash_make(pool);
apr_size_t idx = 0;
apr_size_t i;
const char *expect[(sizeof (lines) / sizeof (*lines))];
const char *src_fname = apr_pstrcat (pool, test_name, ".src", NULL);
const char *dst_fname = apr_pstrcat (pool, test_name, ".dst", NULL);
+ svn_string_t *val;
/** Clean up from previous tests, set up src data, and convert. **/
SVN_ERR (remove_file (src_fname, pool));
SVN_ERR (remove_file (dst_fname, pool));
SVN_ERR (create_file (src_fname, src_eol, pool));
- keywords.revision = rev ? svn_string_create (rev, pool) : NULL;
- keywords.date = date ? svn_string_create (date, pool) : NULL;
- keywords.author = author ? svn_string_create (author, pool) : NULL;
- keywords.url = url ? svn_string_create (url, pool) : NULL;
- keywords.id = NULL;
- err = svn_subst_copy_and_translate (src_fname, dst_fname, dst_eol, repair,
- &keywords, expand, pool);
+ if (rev)
+ {
+ val = svn_string_create (rev, pool);
+ apr_hash_set(keywords, SVN_KEYWORD_REVISION_LONG,
+ APR_HASH_KEY_STRING, val);
+ apr_hash_set(keywords, SVN_KEYWORD_REVISION_SHORT,
+ APR_HASH_KEY_STRING, val);
+ }
+ if (date)
+ {
+ val = svn_string_create (date, pool);
+ apr_hash_set(keywords, SVN_KEYWORD_DATE_LONG,
+ APR_HASH_KEY_STRING, val);
+ apr_hash_set(keywords, SVN_KEYWORD_DATE_SHORT,
+ APR_HASH_KEY_STRING, val);
+ }
+ if (author)
+ {
+ val = svn_string_create (author, pool);
+ apr_hash_set(keywords, SVN_KEYWORD_AUTHOR_LONG,
+ APR_HASH_KEY_STRING, val);
+ apr_hash_set(keywords, SVN_KEYWORD_AUTHOR_SHORT,
+ APR_HASH_KEY_STRING, val);
+ }
+ if (url)
+ {
+ val = svn_string_create (url, pool);
+ apr_hash_set(keywords, SVN_KEYWORD_URL_LONG,
+ APR_HASH_KEY_STRING, val);
+ apr_hash_set(keywords, SVN_KEYWORD_URL_SHORT,
+ APR_HASH_KEY_STRING, val);
+ }
+ if (uuid)
+ {
+ val = svn_string_create (uuid, pool);
+ apr_hash_set(keywords, SVN_KEYWORD_UUID_LONG,
+ APR_HASH_KEY_STRING, val);
+ apr_hash_set(keywords, SVN_KEYWORD_UUID_SHORT,
+ APR_HASH_KEY_STRING, val);
+ }
+ err = svn_subst_copy_and_translate3 (src_fname, dst_fname, dst_eol, repair,
+ keywords, expand, FALSE, pool);
/* Conversion should have failed, if src has mixed eol, and the
@@ -481,6 +524,37 @@
}
}
+ if (uuid)
+ {
+ if (expand)
+ {
+ expect[74 - 1] =
+ apr_pstrcat (pool, "Line 74: ",
+ "Valid $RepositoryUUID: ", uuid,
+ " $, started unexpanded.", NULL);
+ expect[75 - 1] =
+ apr_pstrcat (pool, "Line 75: ",
+ "Valid $UUID: ", uuid,
+ " $, started unexpanded.", NULL);
+ expect[76 - 1] =
+ apr_pstrcat (pool, "Line 76: ",
+ "Valid $RepositoryUUID: ", uuid,
+ " $, started expanded.", NULL);
+ expect[77 - 1] =
+ apr_pstrcat (pool, "Line 77: ",
+ "Valid $UUID: ", uuid,
+ " $, started expanded.", NULL);
+ }
+ else /* unexpand */
+ {
+ /* Lines 74 and 75 remain unchanged. */
+ expect[76 - 1] =
+ "Line 76: Valid $RepositoryUUID$, started expanded.";
+ expect[77 - 1] =
+ "Line 77: Valid $UUID$, started expanded.";
+ }
+ }
+
if (rev)
{
if (expand)
@@ -669,16 +743,20 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("noop", NULL, NULL, 0, NULL, NULL, NULL, NULL, 1, pool));
+ ("noop", NULL, NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
SVN_ERR (substitute_and_verify
- ("noop", "\r", NULL, 0, NULL, NULL, NULL, NULL, 1, pool));
+ ("noop", "\r", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
SVN_ERR (substitute_and_verify
- ("noop", "\n", NULL, 0, NULL, NULL, NULL, NULL, 1, pool));
+ ("noop", "\n", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
SVN_ERR (substitute_and_verify
- ("noop", "\r\n", NULL, 0, NULL, NULL, NULL, NULL, 1, pool));
+ ("noop", "\r\n", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -700,7 +778,7 @@
SVN_ERR (substitute_and_verify
("crlf_to_crlf", "\r\n", "\r\n", 0,
- NULL, NULL, NULL, NULL, 1, pool));
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -717,7 +795,8 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("lf_to_crlf", "\n", "\r\n", 0, NULL, NULL, NULL, NULL, 1, pool));
+ ("lf_to_crlf", "\n", "\r\n", 0,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -734,7 +813,8 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("cr_to_crlf", "\r", "\r\n", 0, NULL, NULL, NULL, NULL, 1, pool));
+ ("cr_to_crlf", "\r", "\r\n", 0,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -752,7 +832,7 @@
SVN_ERR (substitute_and_verify
("mixed_to_crlf", NULL, "\r\n", 1,
- NULL, NULL, NULL, NULL, 1, pool));
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -769,7 +849,8 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("lf_to_lf", "\n", "\n", 0, NULL, NULL, NULL, NULL, 1, pool));
+ ("lf_to_lf", "\n", "\n", 0,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -786,7 +867,8 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("crlf_to_lf", "\r\n", "\n", 0, NULL, NULL, NULL, NULL, 1, pool));
+ ("crlf_to_lf", "\r\n", "\n", 0,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -803,7 +885,8 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("cr_to_lf", "\r", "\n", 0, NULL, NULL, NULL, NULL, 1, pool));
+ ("cr_to_lf", "\r", "\n", 0,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -820,7 +903,8 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("cr_to_lf", NULL, "\n", 1, NULL, NULL, NULL, NULL, 1, pool));
+ ("cr_to_lf", NULL, "\n", 1,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -837,7 +921,8 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("crlf_to_cr", "\r\n", "\r", 0, NULL, NULL, NULL, NULL, 1, pool));
+ ("crlf_to_cr", "\r\n", "\r", 0,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -854,7 +939,8 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("lf_to_cr", "\n", "\r", 0, NULL, NULL, NULL, NULL, 1, pool));
+ ("lf_to_cr", "\n", "\r", 0,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -871,7 +957,8 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("cr_to_cr", "\r", "\r", 0, NULL, NULL, NULL, NULL, 1, pool));
+ ("cr_to_cr", "\r", "\r", 0,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -888,7 +975,8 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("mixed_to_cr", NULL, "\r", 1, NULL, NULL, NULL, NULL, 1, pool));
+ ("mixed_to_cr", NULL, "\r", 1,
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -906,11 +994,11 @@
SVN_ERR (substitute_and_verify
("mixed_no_repair", NULL, "\n", 0,
- NULL, NULL, NULL, NULL, 1, pool));
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
SVN_ERR (substitute_and_verify
("mixed_no_repair", NULL, "\r\n", 0,
- NULL, NULL, NULL, NULL, 1, pool));
+ NULL, NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -930,10 +1018,12 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("author", "\n", NULL, 0, NULL, NULL, "jrandom", NULL, 1, pool));
+ ("author", "\n", NULL, 0,
+ NULL, NULL, "jrandom", NULL, NULL, 1, pool));
SVN_ERR (substitute_and_verify
- ("author", "\r\n", NULL, 0, NULL, NULL, "jrandom", NULL, 1, pool));
+ ("author", "\r\n", NULL, 0,
+ NULL, NULL, "jrandom", NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -951,11 +1041,11 @@
SVN_ERR (substitute_and_verify
("date", "\n", NULL, 0,
- NULL, "Wed Jan 9 07:49:05 2002", NULL, NULL, 1, pool));
+ NULL, "Wed Jan 9 07:49:05 2002", NULL, NULL, NULL, 1, pool));
SVN_ERR (substitute_and_verify
("date", "\r\n", NULL, 0,
- NULL, "Wed Jan 9 07:49:05 2002", NULL, NULL, 1, pool));
+ NULL, "Wed Jan 9 07:49:05 2002", NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -973,11 +1063,11 @@
SVN_ERR (substitute_and_verify
("author_date", "\n", NULL, 0,
- NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, 1, pool));
+ NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, NULL, 1, pool));
SVN_ERR (substitute_and_verify
("author_date", "\r\n", NULL, 0,
- NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, 1, pool));
+ NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -995,11 +1085,11 @@
SVN_ERR (substitute_and_verify
("author_rev", "\n", NULL, 0,
- "1729", NULL, "jrandom", NULL, 1, pool));
+ "1729", NULL, "jrandom", NULL, NULL, 1, pool));
SVN_ERR (substitute_and_verify
("author_rev", "\r\n", NULL, 0,
- "1729", NULL, "jrandom", NULL, 1, pool));
+ "1729", NULL, "jrandom", NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -1017,11 +1107,11 @@
SVN_ERR (substitute_and_verify
("rev", "\n", NULL, 0,
- "1729", NULL, NULL, NULL, 1, pool));
+ "1729", NULL, NULL, NULL, NULL, 1, pool));
SVN_ERR (substitute_and_verify
("rev", "\r\n", NULL, 0,
- "1729", NULL, NULL, NULL, 1, pool));
+ "1729", NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -1039,11 +1129,13 @@
SVN_ERR (substitute_and_verify
("rev_url", "\n", NULL, 0,
- "1729", NULL, NULL, "http://subversion.tigris.org", 1, pool));
+ "1729", NULL, NULL, "http://subversion.tigris.org",
+ NULL, 1, pool));
SVN_ERR (substitute_and_verify
("rev_url", "\r\n", NULL, 0,
- "1729", NULL, NULL, "http://subversion.tigris.org", 1, pool));
+ "1729", NULL, NULL, "http://subversion.tigris.org",
+ NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -1065,6 +1157,7 @@
"Wed Jan 9 07:49:05 2002",
"jrandom",
"http://subversion.tigris.org",
+ NULL,
1, pool));
SVN_ERR (substitute_and_verify
@@ -1073,12 +1166,37 @@
"Wed Jan 9 07:49:05 2002",
"jrandom",
"http://subversion.tigris.org",
+ NULL,
1, pool));
return SVN_NO_ERROR;
}
+static svn_error_t *
+expand_uuid (const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ *msg = "expand uuid";
+
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ SVN_ERR (substitute_and_verify
+ ("uuid", "\n", NULL, 0,
+ NULL, NULL, NULL, NULL, "01234567-89ab-cdef-89ab-cdef01234567",
+ 1, pool));
+
+ SVN_ERR (substitute_and_verify
+ ("uuid", "\r\n", NULL, 0,
+ NULL, NULL, NULL, NULL, "01234567-89ab-cdef-89ab-cdef01234567",
+ 1, pool));
+
+ return SVN_NO_ERROR;
+}
+
+
/** Keyword expansion and EOL conversion together. **/
@@ -1094,7 +1212,7 @@
SVN_ERR (substitute_and_verify
("lf_to_crlf_author", "\n", "\r\n", 0,
- NULL, NULL, "jrandom", NULL, 1, pool));
+ NULL, NULL, "jrandom", NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -1112,7 +1230,7 @@
SVN_ERR (substitute_and_verify
("mixed_to_lf_author_date", NULL, "\n", 1,
- NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, 1, pool));
+ NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -1130,7 +1248,7 @@
SVN_ERR (substitute_and_verify
("crlf_to_cr_author_rev", "\r\n", "\r", 0,
- "1729", NULL, "jrandom", NULL, 1, pool));
+ "1729", NULL, "jrandom", NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -1148,7 +1266,7 @@
SVN_ERR (substitute_and_verify
("cr_to_crlf_rev", "\r", "\r\n", 0,
- "1729", NULL, NULL, NULL, 1, pool));
+ "1729", NULL, NULL, NULL, NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -1166,7 +1284,7 @@
SVN_ERR (substitute_and_verify
("cr_to_crlf_rev_url", "\r", "\r\n", 0,
- "1729", NULL, NULL, "http://subversion.tigris.org", 1, pool));
+ "1729", NULL, NULL, "http://subversion.tigris.org", NULL, 1, pool));
return SVN_NO_ERROR;
}
@@ -1188,7 +1306,7 @@
"Wed Jan 9 07:49:05 2002",
"jrandom",
"http://subversion.tigris.org",
- 1,
+ NULL, 1,
pool));
return SVN_NO_ERROR;
@@ -1209,10 +1327,12 @@
return SVN_NO_ERROR;
SVN_ERR (substitute_and_verify
- ("author", "\n", NULL, 0, NULL, NULL, "jrandom", NULL, 0, pool));
+ ("author", "\n", NULL, 0,
+ NULL, NULL, "jrandom", NULL, NULL, 0, pool));
SVN_ERR (substitute_and_verify
- ("author", "\r\n", NULL, 0, NULL, NULL, "jrandom", NULL, 0, pool));
+ ("author", "\r\n", NULL, 0,
+ NULL, NULL, "jrandom", NULL, NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1230,11 +1350,11 @@
SVN_ERR (substitute_and_verify
("date", "\n", NULL, 0,
- NULL, "Wed Jan 9 07:49:05 2002", NULL, NULL, 0, pool));
+ NULL, "Wed Jan 9 07:49:05 2002", NULL, NULL, NULL, 0, pool));
SVN_ERR (substitute_and_verify
("date", "\r\n", NULL, 0,
- NULL, "Wed Jan 9 07:49:05 2002", NULL, NULL, 0, pool));
+ NULL, "Wed Jan 9 07:49:05 2002", NULL, NULL, NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1252,11 +1372,11 @@
SVN_ERR (substitute_and_verify
("author_date", "\n", NULL, 0,
- NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, 0, pool));
+ NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, NULL, 0, pool));
SVN_ERR (substitute_and_verify
("author_date", "\r\n", NULL, 0,
- NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, 0, pool));
+ NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1274,11 +1394,11 @@
SVN_ERR (substitute_and_verify
("author_rev", "\n", NULL, 0,
- "1729", NULL, "jrandom", NULL, 0, pool));
+ "1729", NULL, "jrandom", NULL, NULL, 0, pool));
SVN_ERR (substitute_and_verify
("author_rev", "\r\n", NULL, 0,
- "1729", NULL, "jrandom", NULL, 0, pool));
+ "1729", NULL, "jrandom", NULL, NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1296,11 +1416,11 @@
SVN_ERR (substitute_and_verify
("rev", "\n", NULL, 0,
- "1729", NULL, NULL, NULL, 0, pool));
+ "1729", NULL, NULL, NULL, NULL, 0, pool));
SVN_ERR (substitute_and_verify
("rev", "\r\n", NULL, 0,
- "1729", NULL, NULL, NULL, 0, pool));
+ "1729", NULL, NULL, NULL, NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1318,11 +1438,11 @@
SVN_ERR (substitute_and_verify
("rev_url", "\n", NULL, 0,
- "1729", NULL, NULL, "http://subversion.tigris.org", 0, pool));
+ "1729", NULL, NULL, "http://subversion.tigris.org", NULL, 0, pool));
SVN_ERR (substitute_and_verify
("rev_url", "\r\n", NULL, 0,
- "1729", NULL, NULL, "http://subversion.tigris.org", 0, pool));
+ "1729", NULL, NULL, "http://subversion.tigris.org", NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1344,7 +1464,7 @@
"Wed Jan 9 07:49:05 2002",
"jrandom",
"http://subversion.tigris.org",
- 1, pool));
+ NULL, 1, pool));
SVN_ERR (substitute_and_verify
("author_date_rev_url", "\r\n", NULL, 0,
@@ -1352,12 +1472,36 @@
"Wed Jan 9 07:49:05 2002",
"jrandom",
"http://subversion.tigris.org",
- 1, pool));
+ NULL, 1, pool));
return SVN_NO_ERROR;
}
+static svn_error_t *
+unexpand_uuid (const char **msg,
+ svn_boolean_t msg_only,
+ apr_pool_t *pool)
+{
+ *msg = "unexpand uuid";
+
+ if (msg_only)
+ return SVN_NO_ERROR;
+
+ SVN_ERR (substitute_and_verify
+ ("uuid", "\n", NULL, 0,
+ NULL, NULL, NULL, NULL, "01234567-89ab-cdef-89ab-cdef01234567",
+ 0, pool));
+
+ SVN_ERR (substitute_and_verify
+ ("uuid", "\r\n", NULL, 0,
+ NULL, NULL, NULL, NULL, "01234567-89ab-cdef-89ab-cdef01234567",
+ 0, pool));
+
+ return SVN_NO_ERROR;
+}
+
+
/** Keyword unexpansion and EOL conversion together. **/
@@ -1373,7 +1517,7 @@
SVN_ERR (substitute_and_verify
("lf_to_crlf_author", "\n", "\r\n", 0,
- NULL, NULL, "jrandom", NULL, 0, pool));
+ NULL, NULL, "jrandom", NULL, NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1391,7 +1535,7 @@
SVN_ERR (substitute_and_verify
("mixed_to_lf_author_date", NULL, "\n", 1,
- NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, 0, pool));
+ NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1409,7 +1553,7 @@
SVN_ERR (substitute_and_verify
("crlf_to_cr_author_rev", "\r\n", "\r", 0,
- "1729", NULL, "jrandom", NULL, 0, pool));
+ "1729", NULL, "jrandom", NULL, NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1427,7 +1571,7 @@
SVN_ERR (substitute_and_verify
("cr_to_crlf_rev", "\r", "\r\n", 0,
- "1729", NULL, NULL, NULL, 0, pool));
+ "1729", NULL, NULL, NULL, NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1445,7 +1589,7 @@
SVN_ERR (substitute_and_verify
("cr_to_crlf_rev_url", "\r", "\r\n", 0,
- "1729", NULL, NULL, "http://subversion.tigris.org", 0, pool));
+ "1729", NULL, NULL, "http://subversion.tigris.org", NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1467,7 +1611,7 @@
"Wed Jan 9 07:49:05 2002",
"jrandom",
"http://subversion.tigris.org",
- 0,
+ NULL, 0,
pool));
return SVN_NO_ERROR;
@@ -1505,6 +1649,7 @@
SVN_TEST_PASS (expand_author_date),
SVN_TEST_PASS (expand_author_rev),
SVN_TEST_PASS (expand_rev),
+ SVN_TEST_PASS (expand_uuid),
SVN_TEST_PASS (expand_rev_url),
SVN_TEST_PASS (expand_author_date_rev_url),
/* Keyword expansion and eol conversion together. */
@@ -1520,6 +1665,7 @@
SVN_TEST_PASS (unexpand_author_date),
SVN_TEST_PASS (unexpand_author_rev),
SVN_TEST_PASS (unexpand_rev),
+ SVN_TEST_PASS (unexpand_uuid),
SVN_TEST_PASS (unexpand_rev_url),
SVN_TEST_PASS (unexpand_author_date_rev_url),
/* Keyword unexpansion and eol conversion together. */
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri Mar 18 03:54:57 2005