Hi all,
I just spent my spare time to try to solve issue #890
(http://subversion.tigris.org/issues/show_bug.cgi?id=890), Custom
keywords. So far, I've implemented the printf-like format charater.
But I'm not sure what to do next (ie., where should the custom formats
be placed), I'll leave it here.
I changed the behavior of original keyword expansion routines, so they
use format string to do keyword expansion now. A custom keyword named
'Plasma' is hardcoded for testing purpose. It's defined in
svn_types.h as
"I'm plasma. kw is %p(svn:keywords). %a"
Enable it by setting svn:keywords and you'll get a string like this:
$Plasma: I'm plasma. kw is Id Author Date Rev Plasma. plasma $
The format characters are defined as:
%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
%p property value
%r number of this revision
%u URL of this file
And translate-test in make check seems fine:
Running all tests in translate-test...success
plasma
LOG:
Implement printf-like format characters for keyword expansion. See
Issue #890 for further information.
* svn_types.h:
Define keyword format string for Revision, Date, Author, URL, ID,
and Plasma (this is for testing purpose).
* libsvn_subr/svn_subst.h:
(struct svn_subst_keywords_t): Redefine svn_subst_keywords_t as an
alias of apr_hash_t.
(svn_subst_create_keywords, svn_subst_keyword_printf): New
functions.
(svn_subst_build_keywords): Interface change. A new argument
apr_hash_t *props.
(svn_subst_keywords_differ, svn_subst_translate_stream): Interface
change. A new apr_pool_t *pool.
* libsvn_subr/svn_subst.c:
(svn_subst_create_keywords, svn_subst_keyword_printf): New
functions.
(svn_subst_build_keywords): Build keywords by
svn_subst_keyword_printf().
(translate_keyword): Interface changes. It now looks up keyword
passed in buffer, instead of predefined constant string.
(svn_subst_keywords_differ): Interface changes.
(svn_subst_translate_stream): Interface changes.
* libsvn_wc/props.c
(validate_eol_prop_against_file): Interface of
svn_subst_translate_stream() and svn_subst_keywords_differ()
changes.
* libsvn_wc/translate.c
(svn_wc__get_keywords):
struct svn_subst_keywords_t changes.
Interface of svn_subst_create_keywords() and
svn_subst_build_keywords() changes.
* libsvn_client/cat.c: Changes because interfaces of
svn_subst_build_keywords() and svn_subst_translate_stream() change.
* libsvn_client/export.c
(struct file_baton): Add a new apr_hash_t *props field.
(add_file): Initialize props in struct file_baton.
(change_file_prop): Store every property in props in struct
file_baton.
(close_file): Interface of svn_subst_create_keywords() and
svn_subst_build_keywords() changes.
* tests/libsvn_wc/translate-test.c:
(substitute_and_verify): Properly assign values to struct
svn_subst_keywords_t due to interface changes. Interface of
svn_subst_copy_and_translate() changes.
PATCH:
Index: subversion/include/svn_types.h
===================================================================
--- subversion/include/svn_types.h (revision 756)
+++ subversion/include/svn_types.h (revision 760)
@@ -217,24 +217,36 @@
/** Short version of LastChangedRevision */
#define SVN_KEYWORD_REVISION_SHORT "Rev"
+/** Format string for Revision */
+#define SVN_KEYWORD_REVISION_FORMAT "%r"
+
/** The most recent date (repository time) when this file was changed. */
#define SVN_KEYWORD_DATE_LONG "LastChangedDate"
/** 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"
+/** Format string for Author */
+#define SVN_KEYWORD_URL_FORMAT "%u"
+
/** A compressed combination of the other four keywords.
*
* (But see comments above about a more general solution to keyword
@@ -242,6 +254,11 @@
*/
#define SVN_KEYWORD_ID "Id"
+/** Format string for ID */
+#define SVN_KEYWORD_ID_FORMAT "%b %d %a %r"
+
+#define SVN_KEYWORD_PLASMA "Plasma"
+#define SVN_KEYWORD_PLASMA_FORMAT "I'm plasma. kw is %p(svn:keywords). %a"
/** @} */
Index: subversion/include/svn_subst.h
===================================================================
--- subversion/include/svn_subst.h (revision 756)
+++ subversion/include/svn_subst.h (revision 760)
@@ -74,15 +74,15 @@
/** Values used in keyword expansion. */
-typedef struct svn_subst_keywords_t
-{
- const svn_string_t *revision;
- const svn_string_t *date;
- const svn_string_t *author;
- const svn_string_t *url;
- const svn_string_t *id;
-} svn_subst_keywords_t;
+typedef apr_hash_t svn_subst_keywords_t;
+/** Create an <tt>svn_subst_keywords_t *</tt> structure.
+ *
+ * All memory is allocated out of @a pool.
+ */
+svn_error_t *
+svn_subst_create_keywords (svn_subst_keywords_t **kw,
+ apr_pool_t *pool);
/** 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
@@ -100,9 +100,34 @@
const char *url,
apr_time_t date,
const char *author,
+ apr_hash_t *props,
apr_pool_t *pool);
+/** Given an 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
+ * %p property value
+ * %r number of this revision
+ * %u URL of this file
+ *
+ * All memory is allocated out of @a pool.
+ */
+svn_string_t *
+svn_subst_keyword_printf (const char *fmt,
+ const char *rev,
+ const char *url,
+ apr_time_t date,
+ const char *author,
+ apr_hash_t *props,
+ apr_pool_t *pool);
+
/** Return @c TRUE if @a a and @a b do not hold the same keywords.
*
* If @a compare_values is @c TRUE, "same" means that the @a a and @a b
@@ -117,7 +142,8 @@
svn_boolean_t
svn_subst_keywords_differ (const svn_subst_keywords_t *a,
const svn_subst_keywords_t *b,
- svn_boolean_t compare_values);
+ svn_boolean_t compare_values,
+ apr_pool_t *pool);
/** Copy and translate the data in stream @a src into stream @a dst. It is
@@ -158,7 +184,8 @@
const char *eol_str,
svn_boolean_t repair,
const svn_subst_keywords_t *keywords,
- svn_boolean_t expand);
+ svn_boolean_t expand,
+ apr_pool_t *pool);
/** Convenience routine: a variant of @c svn_subst_translate_stream which
Index: subversion/libsvn_wc/props.c
===================================================================
--- subversion/libsvn_wc/props.c (revision 756)
+++ subversion/libsvn_wc/props.c (revision 760)
@@ -1083,7 +1083,7 @@
endings. The function is "translating" to an empty stream. This
is sneeeeeeeeeeeaky. */
err = svn_subst_translate_stream (read_stream, write_stream,
- "", FALSE, NULL, FALSE);
+ "", FALSE, NULL, FALSE, pool);
if (err && err->apr_err == SVN_ERR_IO_INCONSISTENT_EOL)
return svn_error_createf (SVN_ERR_ILLEGAL_TARGET, err,
"File '%s' has inconsistent newlines", path);
@@ -1225,7 +1225,7 @@
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_differ (old_keywords, new_keywords, FALSE, pool))
{
const char *base_name;
svn_wc_entry_t tmp_entry;
Index: subversion/libsvn_wc/translate.c
===================================================================
--- subversion/libsvn_wc/translate.c (revision 756)
+++ subversion/libsvn_wc/translate.c (revision 760)
@@ -182,11 +182,14 @@
apr_pool_t *pool)
{
const char *list;
- svn_subst_keywords_t tmp_keywords = { 0 };
+ svn_subst_keywords_t *tmp_keywords;
const svn_wc_entry_t *entry = NULL;
+ apr_hash_t *props;
+ SVN_ERR (svn_subst_create_keywords (&tmp_keywords, pool));
+
/* Start by assuming no keywords. */
- *keywords = NULL;
+ SVN_ERR (svn_subst_create_keywords (keywords, pool));
/* Choose a property list to parse: either the one that came into
this function, or the one attached to PATH. */
@@ -208,16 +211,18 @@
SVN_ERR (svn_wc_entry (&entry, path, adm_access, FALSE, pool));
- SVN_ERR (svn_subst_build_keywords (&tmp_keywords,
+ SVN_ERR (svn_wc_prop_list (&props, path, adm_access, pool));
+ SVN_ERR (svn_subst_build_keywords (tmp_keywords,
list,
apr_psprintf (pool, "%" SVN_REVNUM_T_FMT,
entry->revision),
entry->url,
entry->cmt_date,
entry->cmt_author,
+ props,
pool));
- *keywords = apr_pmemdup (pool, &tmp_keywords, sizeof (tmp_keywords));
+ *keywords = tmp_keywords;
return SVN_NO_ERROR;
}
Index: subversion/libsvn_subr/subst.c
===================================================================
--- subversion/libsvn_subr/subst.c (revision 756)
+++ subversion/libsvn_subr/subst.c (revision 760)
@@ -112,12 +112,22 @@
}
svn_error_t *
+svn_subst_create_keywords (svn_subst_keywords_t **kw,
+ apr_pool_t *pool)
+{
+ *kw = apr_hash_make(pool);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_subst_build_keywords (svn_subst_keywords_t *kw,
const char *keywords_val,
const char *rev,
const char *url,
apr_time_t date,
const char *author,
+ apr_hash_t *props,
apr_pool_t *pool)
{
apr_array_header_t *keyword_tokens;
@@ -133,51 +143,217 @@
if ((! strcmp (keyword, SVN_KEYWORD_REVISION_LONG))
|| (! strcasecmp (keyword, SVN_KEYWORD_REVISION_SHORT)))
{
- kw->revision = svn_string_create (rev, pool);
- }
+ svn_string_t *revision_val;
+
+ /* revision_val = svn_string_create (rev, pool); */
+ revision_val = svn_subst_keyword_printf(SVN_KEYWORD_REVISION_FORMAT,
+ rev, url, date, author,
+ props, pool);
+ apr_hash_set(kw, SVN_KEYWORD_REVISION_LONG,
+ APR_HASH_KEY_STRING, revision_val);
+ apr_hash_set(kw, 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;
+ /* const char *human_date; */
+ svn_string_t *date_val;
+ /*
SVN_ERR (date_prop_to_human (&human_date, TRUE, date, pool));
- kw->date = svn_string_create (human_date, pool);
+ date_val = svn_string_create (human_date, pool);
+ */
+ date_val = svn_subst_keyword_printf(SVN_KEYWORD_DATE_FORMAT,
+ rev, url, date, author,
+ props, pool);
+ apr_hash_set(kw, SVN_KEYWORD_DATE_LONG,
+ APR_HASH_KEY_STRING, date_val);
+ apr_hash_set(kw, SVN_KEYWORD_DATE_SHORT,
+ APR_HASH_KEY_STRING, date_val);
}
else
- kw->date = svn_string_create ("", pool);
+ {
+ svn_string_t *date_val;
+
+ date_val = svn_string_create ("", pool);
+ apr_hash_set(kw, SVN_KEYWORD_DATE_LONG,
+ APR_HASH_KEY_STRING, date_val);
+ apr_hash_set(kw, SVN_KEYWORD_DATE_SHORT,
+ APR_HASH_KEY_STRING, date_val);
+ }
}
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 = svn_string_create (author ? author : "", pool); */
+ author_val = svn_subst_keyword_printf(SVN_KEYWORD_AUTHOR_FORMAT,
+ rev, url, date, author,
+ props, pool);
+ apr_hash_set(kw, SVN_KEYWORD_AUTHOR_LONG,
+ APR_HASH_KEY_STRING, author_val);
+ apr_hash_set(kw, 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 = svn_string_create (url ? url : "", pool); */
+ url_val = svn_subst_keyword_printf(SVN_KEYWORD_URL_FORMAT,
+ rev, url, date, author,
+ props, pool);
+ apr_hash_set(kw, SVN_KEYWORD_URL_LONG,
+ APR_HASH_KEY_STRING, url_val);
+ apr_hash_set(kw, SVN_KEYWORD_URL_SHORT,
+ APR_HASH_KEY_STRING, url_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",
+ id_val = svn_string_createf (pool, "%s %s %s %s",
base_name,
rev,
human_date ? human_date : "",
author ? author : "");
+ */
+ id_val = svn_subst_keyword_printf(SVN_KEYWORD_ID_FORMAT,
+ rev, url, date, author,
+ props, pool);
+
+ apr_hash_set(kw, SVN_KEYWORD_ID,
+ APR_HASH_KEY_STRING, id_val);
}
+ else if ((! strcasecmp (keyword, SVN_KEYWORD_PLASMA)))
+ {
+ /* This is a test keyword. :) */
+ svn_string_t *plasma_val;
+
+ plasma_val = svn_subst_keyword_printf(SVN_KEYWORD_PLASMA_FORMAT,
+ rev, url, date, author,
+ props, pool);
+ apr_hash_set(kw, SVN_KEYWORD_PLASMA,
+ APR_HASH_KEY_STRING, plasma_val);
+ }
+
}
return SVN_NO_ERROR;
}
+svn_string_t *
+svn_subst_keyword_printf (const char *fmt,
+ const char *rev,
+ const char *url,
+ apr_time_t date,
+ const char *author,
+ apr_hash_t *props,
+ 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 'p': /* property value */
+ /* Fetch property name */
+ if (*cur != '(') /* Invalid format */
+ break;
+ for (fmt = ++cur; (ch = *cur) != '\0' && ch != ')'; cur++)
+ /* void */;
+ if (ch == '\0') /* Invalid format, rewind. */
+ {
+ cur = fmt - 1;
+ break;
+ }
+
+ /* Look up in props hash*/
+ if (props)
+ {
+ svn_string_t *prop_val;
+
+ prop_val = apr_hash_get(props, fmt, cur - fmt);
+ svn_stringbuf_appendcstr (value, prop_val->data);
+ }
+ cur++;
+ 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;
+ 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);
+}
+
/*** Helpers for svn_subst_translate_stream ***/
@@ -326,8 +502,16 @@
translate_keyword (char *buf,
apr_size_t *len,
svn_boolean_t expand,
- const svn_subst_keywords_t *keywords)
+ const svn_subst_keywords_t *keywords,
+ apr_pool_t *pool)
{
+ const svn_string_t *value;
+ char key[SVN_KEYWORD_MAX_LEN + 1];
+ svn_subst_keywords_t *lame_keywords;
+ int i;
+
+ lame_keywords = (svn_subst_keywords_t *) keywords;
+
/* Make sure we gotz good stuffs. */
assert (*len <= SVN_KEYWORD_MAX_LEN);
assert ((buf[0] == '$') && (buf[*len - 1] == '$'));
@@ -336,81 +520,24 @@
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_SHORT,
- (sizeof (SVN_KEYWORD_REVISION_SHORT)) - 1,
- expand ? keywords->revision : NULL))
- return TRUE;
- }
+ /* key = apr_pstrndup(pool, buf + 1, *len - 2); */
+ /* key = svn_string_ncreate (buf + 1, *len - 2, pool); */
+ /* value = apr_hash_get (keywords->keywords, key->data, APR_HASH_KEY_STRING); */
+ value = apr_hash_get (lame_keywords, key, APR_HASH_KEY_STRING);
- /* 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;
}
@@ -470,65 +597,39 @@
svn_boolean_t
svn_subst_keywords_differ (const svn_subst_keywords_t *a,
const svn_subst_keywords_t *b,
- svn_boolean_t compare_values)
+ svn_boolean_t compare_values,
+ apr_pool_t *pool)
{
+ svn_boolean_t result = FALSE;
+ apr_hash_index_t *hi;
+ svn_subst_keywords_t *lame_a, *lame_b;
+
+ lame_a = (svn_subst_keywords_t *) a;
+ lame_b = (svn_subst_keywords_t *) b;
+
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)))
+ /* Unequal number of contents */
+ || (apr_hash_count(lame_a) != apr_hash_count(lame_b)))
+ return TRUE;
+
+ /* 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))
{
- return FALSE;
+ const char *key;
+
+ apr_hash_this (hi, (const void**) &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;
}
- 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;
+
+ return result;
}
@@ -539,7 +640,8 @@
const char *eol_str,
svn_boolean_t repair,
const svn_subst_keywords_t *keywords,
- svn_boolean_t expand)
+ svn_boolean_t expand,
+ apr_pool_t *pool)
{
svn_error_t *err = SVN_NO_ERROR;
svn_error_t *read_err, *close_err;
@@ -645,7 +747,7 @@
/* Else, it must be the end of one! Attempt to translate
the buffer. */
len = keyword_off;
- if (translate_keyword (keyword_buf, &len, expand, keywords))
+ if (translate_keyword (keyword_buf, &len, expand, keywords, pool))
{
/* We successfully found and translated a keyword. We
can write out this buffer now. */
@@ -805,7 +907,7 @@
/* Translate src stream into dst stream. */
err = svn_subst_translate_stream (src_stream, dst_stream,
- eol_str, repair, keywords, expand);
+ eol_str, repair, keywords, expand, pool);
if (err)
{
svn_stream_close (src_stream);
@@ -860,7 +962,7 @@
/* Translate src stream into dst stream. */
err = svn_subst_translate_stream (src_stream, dst_stream,
- eol_str, repair, keywords, expand);
+ eol_str, repair, keywords, expand, pool);
if (err)
{
Index: subversion/libsvn_client/cat.c
===================================================================
--- subversion/libsvn_client/cat.c (revision 756)
+++ subversion/libsvn_client/cat.c (revision 760)
@@ -102,7 +102,7 @@
}
else
{
- svn_subst_keywords_t kw = { 0 };
+ svn_subst_keywords_t *kw;
svn_subst_eol_style_t style;
const char *tmp_filename;
svn_stream_t *tmp_stream;
@@ -111,6 +111,8 @@
apr_off_t off = 0;
const char *eol = NULL;
+ SVN_ERR (svn_subst_create_keywords (&kw, pool));
+
/* grab a temporary file to write the target to. */
SVN_ERR (svn_io_open_unique_file (&tmp_file, &tmp_filename, "", ".tmp",
TRUE, pool));
@@ -145,16 +147,17 @@
SVN_ERR (svn_time_from_cstring (&when, date->data, pool));
SVN_ERR (svn_subst_build_keywords
- (&kw, keywords->data,
+ (kw, keywords->data,
apr_psprintf (pool, "%" SVN_REVNUM_T_FMT, rev),
url,
when,
author ? author->data : NULL,
+ revprops,
pool));
}
- SVN_ERR (svn_subst_translate_stream (tmp_stream, out, eol, FALSE, &kw,
- TRUE));
+ SVN_ERR (svn_subst_translate_stream (tmp_stream, out, eol, FALSE, kw,
+ TRUE, pool));
SVN_ERR (svn_stream_close (tmp_stream));
}
Index: subversion/libsvn_client/export.c
===================================================================
--- subversion/libsvn_client/export.c (revision 756)
+++ subversion/libsvn_client/export.c (revision 760)
@@ -227,6 +227,8 @@
const char *author;
apr_time_t date;
+
+ apr_hash_t *props;
};
@@ -318,6 +320,7 @@
fb->edit_baton = eb;
fb->path = full_path;
fb->url = full_url;
+ fb->props = apr_hash_make (pool);
*baton = fb;
return SVN_NO_ERROR;
@@ -381,6 +384,9 @@
if (! value)
return SVN_NO_ERROR;
+ /* Store every property */
+ apr_hash_set(fb->props, name, APR_HASH_KEY_STRING, value);
+
/* Store only the magic three properties. */
if (strcmp (name, SVN_PROP_EOL_STYLE) == 0)
fb->eol_style_val = svn_string_dup (value, pool);
@@ -448,21 +454,23 @@
{
svn_subst_eol_style_t style;
const char *eol;
- svn_subst_keywords_t final_kw = {0};
+ svn_subst_keywords_t *final_kw;
+ SVN_ERR (svn_subst_create_keywords (&final_kw, pool));
+
if (fb->eol_style_val)
svn_subst_eol_style_from_value (&style, &eol, fb->eol_style_val->data);
if (fb->keywords_val)
- SVN_ERR (svn_subst_build_keywords (&final_kw, fb->keywords_val->data,
+ SVN_ERR (svn_subst_build_keywords (final_kw, fb->keywords_val->data,
fb->revision, fb->url, fb->date,
- fb->author, pool));
+ fb->author, fb->props, pool));
SVN_ERR (svn_subst_copy_and_translate
(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,
fb->keywords_val ? TRUE : FALSE, /* expand */
pool));
Index: subversion/tests/libsvn_wc/translate-test.c
===================================================================
--- subversion/tests/libsvn_wc/translate-test.c (revision 756)
+++ subversion/tests/libsvn_wc/translate-test.c (revision 760)
@@ -264,25 +264,72 @@
{
svn_error_t *err;
svn_stringbuf_t *contents;
- svn_subst_keywords_t keywords;
+ svn_subst_keywords_t *keywords;
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;
+ SVN_ERR (svn_subst_create_keywords (&keywords, pool));
+
/** 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;
+ if (rev)
+ {
+ /*svn_string_t *revision_val;
+ revision_val = svn_string_create (rev, pool);
+ */
+ 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)
+ {
+ /*svn_string_t *date_val;
+
+ date_val = svn_string_create (date, pool);
+ */
+ 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)
+ {
+ /*svn_string_t *author_val;
+
+ author_val = svn_string_create (author, pool);
+ */
+ 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)
+ {
+ /*svn_string_t *url_val;
+
+ url_val = svn_string_create (url, pool);
+ */
+ 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);
+ }
+
err = svn_subst_copy_and_translate (src_fname, dst_fname, dst_eol, repair,
- &keywords, expand, pool);
+ keywords, expand, pool);
/* Conversion should have failed, if src has mixed eol, and the
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Mon May 26 07:38:00 2003