[[ Adding users@subversion.apache.org ]]

He folks. I am in no way a Subversion expert, however per request I've taken the FreeBSD patch for adding custom keyword expansion and forward ported it to what is soon to be Subversion 1.8.

I am wondering if anyone can help me test this or give me some things to try to ensure that it works properly.

-Alfred

On 2/1/13 7:40 AM, Alfred Perlstein wrote:
[[ bringing in Lev Serebryakov, FreeBSD port maintainer for Subversion ]]

Hello Lev,

Stefan of the Subversion project asked me about bringing in our keywords patch for subversion 1.8.

I've taken a bit of time and gotten the patch to apply to subversion trunk (untested).

Can you have a look and let us know what we need to do with regards to testing or anything else?


Stefan, any suggestions on going forward?

-Alfred

On 2/1/13 8:34 AM, Stefan Sperling wrote:
On Fri, Feb 01, 2013 at 08:01:02AM -0500, Alfred Perlstein wrote:
[[ reply private ]]

First of all, thank you very much for taking the time to explain this.

I've forwarded your response to a few people who are more
knowledgeable about Subversion in our community (John Baldwin /
Peter Wemm) to hopefully get back us on the issue of mergeinfo and
reintegrate.
Thanks!

Regarding the patch: http://subversion.tigris.org/issues/show_bug.cgi?id=890
I just read this.  What can I do to help on this issue?
See the mailing list thread linked from
http://subversion.tigris.org/issues/show_bug.cgi?id=890#desc40
That's the last time the patch got reviewed. It needs to be updated
to Subversion's trunk (to-be-1.8) before it can be committed.



Index: subversion/include/private/svn_subst_private.h
===================================================================
--- subversion/include/private/svn_subst_private.h      (revision 0)
+++ subversion/include/private/svn_subst_private.h      (working copy)
@@ -0,0 +1,68 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file svn_subst_private.h
+ * @brief Non-public subst utility functions.
+ */
+
+
+#ifndef SVN_SUBST_PRIVATE_H
+#define SVN_SUBST_PRIVATE_H
+
+#include "svn_subst.h"    /* for svn_boolean_t, svn_error_t */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Set @a *kw to a new keywords hash filled with the appropriate contents
+ * given a @a keywords_string (the contents of the svn:keywords
+ * property for the file in question), the revision @a rev, the @a url,
+ * the url of the root of the @a repos, 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.
+ *
+ * Hash keys are of type <tt>const char *</tt>.
+ * Hash values are of type <tt>svn_string_t *</tt>.
+ *
+ * All memory is allocated out of @a pool.
+ *
+ * @since New in 1.6
+ */
+svn_error_t *
+svn_subst_build_keywords3(apr_hash_t **kw,
+                          const char *keywords_string,
+                          const char *rev,
+                          const char *url,
+                          const char *repos,
+                          apr_time_t date,
+                          const char *author,
+                          apr_pool_t *pool);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* SVN_SUBST_PRIVATE_H */
Index: subversion/libsvn_client/cat.c
===================================================================
--- subversion/libsvn_client/cat.c      (revision 1441445)
+++ subversion/libsvn_client/cat.c      (working copy)
@@ -40,6 +40,7 @@
 
 #include "svn_private_config.h"
 #include "private/svn_wc_private.h"
+#include "private/svn_subst_private.h"
 
 
 /*** Code. ***/
@@ -124,12 +125,15 @@
       const char *author;
       const char *url;
       apr_time_t tm;
+      const char *repos;
 
       SVN_ERR(svn_wc__node_get_changed_info(&changed_rev, &tm, &author, wc_ctx,
                                             local_abspath, scratch_pool,
                                             scratch_pool));
       SVN_ERR(svn_wc__node_get_url(&url, wc_ctx, local_abspath, scratch_pool,
                                    scratch_pool));
+      SVN_ERR(svn_wc__node_get_repos_info(&repos, NULL, wc_ctx, local_abspath,
+                                         scratch_pool, scratch_pool));
 
       if (local_mod)
         {
@@ -152,8 +156,8 @@
           rev_str = apr_psprintf(scratch_pool, "%ld", changed_rev);
         }
 
-      SVN_ERR(svn_subst_build_keywords2(&kw, keywords->data, rev_str, url, tm,
-                                        author, scratch_pool));
+      SVN_ERR(svn_subst_build_keywords3(&kw, keywords->data, rev_str, url, 
+                                        repos, tm, author, scratch_pool));
     }
 
   /* Wrap the output stream if translation is needed. */
@@ -181,6 +185,7 @@
   svn_string_t *eol_style;
   svn_string_t *keywords;
   apr_hash_t *props;
+  const char *repos_root_url;
   svn_stream_t *output = out;
   svn_error_t *err;
 
@@ -225,6 +230,9 @@
                                             peg_revision,
                                             revision, ctx, pool));
 
+  /* Find the repos root URL */
+  SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url, pool));
+
   /* Grab some properties we need to know in order to figure out if anything
      special needs to be done with this file. */
   err = svn_ra_get_file(ra_session, "", loc->rev, NULL, NULL, &props, pool);
@@ -275,10 +283,11 @@
           if (cmt_date)
             SVN_ERR(svn_time_from_cstring(&when, cmt_date->data, pool));
 
-          SVN_ERR(svn_subst_build_keywords2
+          SVN_ERR(svn_subst_build_keywords3
                   (&kw, keywords->data,
                    cmt_rev->data,
                    loc->url,
+                  repos_root_url,
                    when,
                    cmt_author ? cmt_author->data : NULL,
                    pool));
Index: subversion/libsvn_client/commit.c
===================================================================
--- subversion/libsvn_client/commit.c   (revision 1441445)
+++ subversion/libsvn_client/commit.c   (working copy)
@@ -44,6 +44,7 @@
 #include "client.h"
 #include "private/svn_wc_private.h"
 #include "private/svn_ra_private.h"
+#include "private/svn_subst_private.h"
 
 #include "svn_private_config.h"
 
Index: subversion/libsvn_client/export.c
===================================================================
--- subversion/libsvn_client/export.c   (revision 1441445)
+++ subversion/libsvn_client/export.c   (working copy)
@@ -45,6 +45,7 @@
 #include "private/svn_subr_private.h"
 #include "private/svn_delta_private.h"
 #include "private/svn_wc_private.h"
+#include "private/svn_subst_private.h"
 
 #ifndef ENABLE_EV2_IMPL
 #define ENABLE_EV2_IMPL 0
@@ -377,6 +378,7 @@
     {
       svn_revnum_t changed_rev = status->changed_rev;
       const char *suffix;
+      const char *repos;
       const char *url = svn_path_url_add_component2(status->repos_root_url,
                                                     status->repos_relpath,
                                                     scratch_pool);
@@ -395,10 +397,13 @@
           suffix = "";
         }
 
-      SVN_ERR(svn_subst_build_keywords2
+      SVN_ERR(svn_wc__node_get_repos_info(&repos, NULL, wc_ctx,
+             eib->origin_abspath /* XXX: ?? from_abspath */,
+             scratch_pool, scratch_pool));
+      SVN_ERR(svn_subst_build_keywords3
               (&kw, keywords->data,
                apr_psprintf(scratch_pool, "%ld%s", changed_rev, suffix),
-               url, tm, author, scratch_pool));
+               url, repos, tm, author, scratch_pool));
     }
 
   /* For atomicity, we translate to a tmp file and then rename the tmp file
@@ -544,6 +549,7 @@
   /* Any keyword vals to be substituted */
   const char *revision;
   const char *url;
+  const char *repos;
   const char *author;
   apr_time_t date;
 
@@ -665,6 +671,7 @@
   fb->edit_baton = eb;
   fb->path = full_path;
   fb->url = full_url;
+  fb->repos = eb->root_url;
   fb->pool = pool;
 
   *baton = fb;
@@ -830,8 +837,8 @@
         }
 
       if (fb->keywords_val)
-        SVN_ERR(svn_subst_build_keywords2(&final_kw, fb->keywords_val->data,
-                                          fb->revision, fb->url, fb->date,
+        SVN_ERR(svn_subst_build_keywords3(&final_kw, fb->keywords_val->data,
+                                          fb->revision, fb->url, fb->repos, 
fb->date,
                                           fb->author, pool));
 
       SVN_ERR(svn_subst_copy_and_translate4(fb->tmppath, fb->path,
Index: subversion/libsvn_client/import.c
===================================================================
--- subversion/libsvn_client/import.c   (revision 1441445)
+++ subversion/libsvn_client/import.c   (working copy)
@@ -49,6 +49,7 @@
 #include "private/svn_subr_private.h"
 #include "private/svn_ra_private.h"
 #include "private/svn_magic.h"
+#include "private/svn_subst_private.h"
 
 #include "svn_private_config.h"
 
@@ -133,9 +134,9 @@
     }
 
   if (keywords_val)
-    SVN_ERR(svn_subst_build_keywords2(&keywords, keywords_val->data,
+    SVN_ERR(svn_subst_build_keywords3(&keywords, keywords_val->data,
                                       APR_STRINGIFY(SVN_INVALID_REVNUM),
-                                      "", 0, "", pool));
+                                      "", "", 0, "", pool));
   else
     keywords = NULL;
 
Index: subversion/libsvn_subr/subst.c
===================================================================
--- subversion/libsvn_subr/subst.c      (revision 1441445)
+++ subversion/libsvn_subr/subst.c      (working copy)
@@ -49,6 +49,7 @@
 #include "svn_private_config.h"
 
 #include "private/svn_string_private.h"
+#include "private/svn_subst_private.h"
 
 /**
  * The textual elements of a detranslated special file.  One of these
@@ -135,8 +136,11 @@
  * %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 path relative to root of repos
  * %r number of this revision
+ * %R root url of repository
  * %u URL of this file
+ * %_ a space
  * %% a literal %
  *
  * All memory is allocated out of @a pool.
@@ -145,12 +149,14 @@
 keyword_printf(const char *fmt,
                const char *rev,
                const char *url,
+               const char *repos,
                apr_time_t date,
                const char *author,
                apr_pool_t *pool)
 {
   svn_stringbuf_t *value = svn_stringbuf_ncreate("", 0, pool);
   const char *cur;
+  const char *relative;
   size_t n;
 
   for (;;)
@@ -203,6 +209,23 @@
             svn_stringbuf_appendcstr(value,
                                      svn_time_to_human_cstring(date, pool));
           break;
+        case 'P': /* relative path of this file */
+         relative = url;
+          if (relative && repos)
+            {
+             int len = strlen(repos);
+
+             if (strncmp(repos, relative, len) == 0
+                 && relative[len] == '/')
+               relative += len + 1;
+           }
+         if (relative)
+            svn_stringbuf_appendcstr(value, relative);
+          break;
+        case 'R': /* root of repos */
+         if (repos)
+           svn_stringbuf_appendcstr(value, repos);
+         break;
         case 'r': /* number of this revision */
           if (rev)
             svn_stringbuf_appendcstr(value, rev);
@@ -211,6 +234,9 @@
           if (url)
             svn_stringbuf_appendcstr(value, url);
           break;
+        case '_': /* '%_' => a space */
+          svn_stringbuf_appendbytes(value, " ", 1);
+          break;
         case '%': /* '%%' => a literal % */
           svn_stringbuf_appendbyte(value, *cur);
           break;
@@ -246,8 +272,8 @@
   apr_hash_t *kwhash;
   const svn_string_t *val;
 
-  SVN_ERR(svn_subst_build_keywords2(&kwhash, keywords_val, rev,
-                                    url, date, author, pool));
+  SVN_ERR(svn_subst_build_keywords3(&kwhash, keywords_val, rev,
+                                    url, "", date, author, pool));
 
   /* The behaviour of pre-1.3 svn_subst_build_keywords, which we are
    * replicating here, is to write to a slot in the svn_subst_keywords_t
@@ -286,6 +312,21 @@
                           const char *author,
                           apr_pool_t *pool)
 {
+  SVN_ERR(svn_subst_build_keywords3(kw, keywords_val, rev,
+                                    url, "", date, author, pool));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_subst_build_keywords3(apr_hash_t **kw,
+                          const char *keywords_val,
+                          const char *rev,
+                          const char *url,
+                          const char *repos,
+                          apr_time_t date,
+                          const char *author,
+                          apr_pool_t *pool)
+{
   apr_array_header_t *keyword_tokens;
   int i;
   *kw = apr_hash_make(pool);
@@ -296,14 +337,32 @@
   for (i = 0; i < keyword_tokens->nelts; ++i)
     {
       const char *keyword = APR_ARRAY_IDX(keyword_tokens, i, const char *);
+      apr_array_header_t *keyword_tokens2;
 
+      keyword_tokens2 = svn_cstring_split(keyword, "=", TRUE /* chop */, pool);
+      if (keyword_tokens2->nelts == 2)
+        {
+          svn_string_t *custom_val;
+          const char *custom_expand;
+
+          keyword = APR_ARRAY_IDX(keyword_tokens2, 0, const char*);
+          custom_expand = APR_ARRAY_IDX(keyword_tokens2, 1, const char*);
+          if (! strcmp(custom_expand, "%H"))
+           custom_expand = "%P %r %d %a";
+         else if (! strcmp(custom_expand, "%I"))
+           custom_expand = "%b %r %d %a";
+          custom_val = keyword_printf(custom_expand, rev, url, repos, date, 
author, pool);
+          apr_hash_set(*kw, keyword, APR_HASH_KEY_STRING, custom_val);
+          return SVN_NO_ERROR;
+        }
+
       if ((! strcmp(keyword, SVN_KEYWORD_REVISION_LONG))
           || (! strcmp(keyword, SVN_KEYWORD_REVISION_MEDIUM))
           || (! svn_cstring_casecmp(keyword, SVN_KEYWORD_REVISION_SHORT)))
         {
           svn_string_t *revision_val;
 
-          revision_val = keyword_printf("%r", rev, url, date, author, pool);
+          revision_val = keyword_printf("%r", rev, url, repos, date, author, 
pool);
           apr_hash_set(*kw, SVN_KEYWORD_REVISION_LONG,
                        APR_HASH_KEY_STRING, revision_val);
           apr_hash_set(*kw, SVN_KEYWORD_REVISION_MEDIUM,
@@ -316,7 +375,7 @@
         {
           svn_string_t *date_val;
 
-          date_val = keyword_printf("%D", rev, url, date, author, pool);
+          date_val = keyword_printf("%D", rev, url, repos, date, author, pool);
           apr_hash_set(*kw, SVN_KEYWORD_DATE_LONG,
                        APR_HASH_KEY_STRING, date_val);
           apr_hash_set(*kw, SVN_KEYWORD_DATE_SHORT,
@@ -327,7 +386,7 @@
         {
           svn_string_t *author_val;
 
-          author_val = keyword_printf("%a", rev, url, date, author, pool);
+          author_val = keyword_printf("%a", rev, url, repos, date, author, 
pool);
           apr_hash_set(*kw, SVN_KEYWORD_AUTHOR_LONG,
                        APR_HASH_KEY_STRING, author_val);
           apr_hash_set(*kw, SVN_KEYWORD_AUTHOR_SHORT,
@@ -338,7 +397,7 @@
         {
           svn_string_t *url_val;
 
-          url_val = keyword_printf("%u", rev, url, date, author, pool);
+          url_val = keyword_printf("%u", rev, url, repos, date, author, pool);
           apr_hash_set(*kw, SVN_KEYWORD_URL_LONG,
                        APR_HASH_KEY_STRING, url_val);
           apr_hash_set(*kw, SVN_KEYWORD_URL_SHORT,
@@ -348,7 +407,7 @@
         {
           svn_string_t *id_val;
 
-          id_val = keyword_printf("%b %r %d %a", rev, url, date, author,
+          id_val = keyword_printf("%b %r %d %a", rev, url, repos, date, author,
                                   pool);
           apr_hash_set(*kw, SVN_KEYWORD_ID,
                        APR_HASH_KEY_STRING, id_val);
@@ -357,7 +416,7 @@
         {
           svn_string_t *header_val;
 
-          header_val = keyword_printf("%u %r %d %a", rev, url, date, author,
+          header_val = keyword_printf("%u %r %d %a", rev, url, repos, date, 
author,
                                       pool);
           apr_hash_set(*kw, SVN_KEYWORD_HEADER,
                        APR_HASH_KEY_STRING, header_val);
Index: subversion/libsvn_wc/translate.c
===================================================================
--- subversion/libsvn_wc/translate.c    (revision 1441445)
+++ subversion/libsvn_wc/translate.c    (working copy)
@@ -46,6 +46,7 @@
 
 #include "svn_private_config.h"
 #include "private/svn_wc_private.h"
+#include "private/svn_subst_private.h"
 
 
 
@@ -313,10 +314,10 @@
   apr_time_t changed_date;
   const char *changed_author;
   const char *url;
+  const char *repos_root_url;
 
   if (! for_normalization)
     {
-      const char *repos_root_url;
       const char *repos_relpath;
 
       SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, &repos_relpath,
@@ -341,13 +342,23 @@
       changed_rev = SVN_INVALID_REVNUM;
       changed_date = 0;
       changed_author = "";
+
+      SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL,
+                                   &repos_root_url, NULL, NULL,
+                                   NULL, NULL, NULL,
+                                   NULL, NULL, NULL, NULL, NULL, NULL,
+                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                                   NULL, NULL, NULL, NULL,
+                                   db, local_abspath,
+                                   scratch_pool, scratch_pool));
     }
 
-  SVN_ERR(svn_subst_build_keywords2(keywords,
+  SVN_ERR(svn_subst_build_keywords3(keywords,
                                     keyword_list,
                                     apr_psprintf(scratch_pool, "%ld",
                                                  changed_rev),
                                     url,
+                                    repos_root_url,
                                     changed_date,
                                     changed_author,
                                     result_pool));

Reply via email to