You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by mi...@apache.org on 2015/03/02 20:55:12 UTC

svn commit: r1663412 - in /subversion/branches/mod-dav-svn-expressions: CHANGES subversion/mod_dav_svn/mod_dav_svn.c

Author: minfrin
Date: Mon Mar  2 19:55:11 2015
New Revision: 1663412

URL: http://svn.apache.org/r1663412
Log:
mod_dav_svn: add expression support for templates in SVNPath and
SVNParentPath.

Modified:
    subversion/branches/mod-dav-svn-expressions/CHANGES
    subversion/branches/mod-dav-svn-expressions/subversion/mod_dav_svn/mod_dav_svn.c

Modified: subversion/branches/mod-dav-svn-expressions/CHANGES
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/CHANGES?rev=1663412&r1=1663411&r2=1663412&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/CHANGES (original)
+++ subversion/branches/mod-dav-svn-expressions/CHANGES Mon Mar  2 19:55:11 2015
@@ -21,6 +21,8 @@ http://svn.apache.org/repos/asf/subversi
     * fsfs: new format 7 with more efficient logical addressing (r1547045 et al)
 
   - Minor new features and improvements:
+    * mod_dav_svn: add expression support for templates in SVNPath and
+      SVNParentPath.
     * new 'diff-ignore-content-type' runtime configuration option.
     * new option for 'svnadmin verify': --check-normalization.
     * new option for 'svnadmin verify': --keep-going.

Modified: subversion/branches/mod-dav-svn-expressions/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/mod_dav_svn/mod_dav_svn.c?rev=1663412&r1=1663411&r2=1663412&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/mod_dav_svn/mod_dav_svn.c Mon Mar  2 19:55:11 2015
@@ -48,6 +48,9 @@
 #include "dav_svn.h"
 #include "mod_authz_svn.h"
 
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+#include <ap_expr.h>
+#endif
 
 /* This is the default "special uri" used for SVN's special resources
    (e.g. working resources, activities) */
@@ -70,6 +73,14 @@ typedef struct server_conf_t {
 } server_conf_t;
 
 
+/* combination of path and expression */
+typedef struct path_expr_t {
+    const char *base;                /* base path */
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+    const ap_expr_info_t *expr;      /* expression suffix added to the base */
+#endif
+} path_expr_t;
+
 /* A tri-state enum used for per directory on/off flags.  Note that
    it's important that CONF_FLAG_DEFAULT is 0 to make
    merge_dir_config in mod_dav_svn do the right thing. */
@@ -89,10 +100,10 @@ enum path_authz_conf {
 
 /* per-dir configuration */
 typedef struct dir_conf_t {
-  const char *fs_path;               /* path to the SVN FS */
+  path_expr_t *fs_path;              /* path to the SVN FS */
   const char *repo_name;             /* repository name */
   const char *xslt_uri;              /* XSL transform URI */
-  const char *fs_parent_path;        /* path to parent of SVN FS'es  */
+  path_expr_t *fs_parent_path;       /* path to parent of SVN FS'es  */
   enum conf_flag autoversioning;     /* whether autoversioning is active */
   dav_svn__bulk_upd_conf bulk_updates; /* whether bulk updates are allowed */
   enum conf_flag v2_protocol;        /* whether HTTP v2 is advertised */
@@ -107,6 +118,9 @@ typedef struct dir_conf_t {
   enum conf_flag revprop_cache;      /* whether to enable revprop caching */
   enum conf_flag block_read;         /* whether to enable block read mode */
   const char *hooks_env;             /* path to hook script env config file */
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+  const ap_expr_info_t *root_expr;   /* expression for our top-level directory */
+#endif
 } dir_conf_t;
 
 
@@ -235,7 +249,7 @@ create_dir_config(apr_pool_t *p, char *d
   /* In subversion context dir is always considered to be coming from
      <Location /blah> directive. So we treat it as a urlpath. */
   if (dir)
-    conf->root_dir = svn_urlpath__canonicalize(dir, p);
+    conf->root_dir = dir;
   conf->bulk_updates = CONF_BULKUPD_DEFAULT;
   conf->v2_protocol = CONF_FLAG_DEFAULT;
   conf->hooks_env = NULL;
@@ -273,6 +287,9 @@ merge_dir_config(apr_pool_t *p, void *ba
   newconf->block_read = INHERIT_VALUE(parent, child, block_read);
   newconf->root_dir = INHERIT_VALUE(parent, child, root_dir);
   newconf->hooks_env = INHERIT_VALUE(parent, child, hooks_env);
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+  newconf->root_expr = INHERIT_VALUE(parent, child, root_expr);
+#endif
 
   if (parent->fs_path)
     ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
@@ -469,28 +486,98 @@ SVNListParentPath_cmd(cmd_parms *cmd, vo
 
 
 static const char *
-SVNPath_cmd(cmd_parms *cmd, void *config, const char *arg1)
+SVNPath_cmd(cmd_parms *cmd, void *config, const char *arg1, const char *arg2)
 {
   dir_conf_t *conf = config;
 
   if (conf->fs_parent_path != NULL)
     return "SVNPath cannot be defined at same time as SVNParentPath.";
 
-  conf->fs_path = svn_dirent_internal_style(arg1, cmd->pool);
+  conf->fs_path = apr_pcalloc(cmd->pool, sizeof(path_expr_t));
+  conf->fs_path->base = svn_dirent_internal_style(arg1, cmd->pool);
+
+  if (arg2)
+    {
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+      const char *expr_err = NULL;
+
+      conf->fs_path->expr = ap_expr_parse_cmd(cmd, arg2, AP_EXPR_FLAG_STRING_RESULT,
+              &expr_err, NULL);
+      if (expr_err)
+        {
+          return apr_pstrcat(cmd->temp_pool,
+                  "Cannot parse expression '", arg2, "' in SVNPath: ",
+                  expr_err, NULL);
+        }
+#else
+      return "Expressions require httpd v2.4.0 or higher"
+#endif
+    }
+
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+  if (!conf->root_expr)
+    {
+      const char *expr_err = NULL;
+
+      conf->root_expr = ap_expr_parse_cmd(cmd, conf->root_dir, AP_EXPR_FLAG_STRING_RESULT,
+              &expr_err, NULL);
+      if (expr_err)
+        {
+          return apr_pstrcat(cmd->temp_pool,
+                  "Cannot parse Location expression '", conf->root_dir, "': ",
+                  expr_err, NULL);
+        }
+    }
+#endif
 
   return NULL;
 }
 
 
 static const char *
-SVNParentPath_cmd(cmd_parms *cmd, void *config, const char *arg1)
+SVNParentPath_cmd(cmd_parms *cmd, void *config, const char *arg1, const char *arg2)
 {
   dir_conf_t *conf = config;
 
   if (conf->fs_path != NULL)
     return "SVNParentPath cannot be defined at same time as SVNPath.";
 
-  conf->fs_parent_path = svn_dirent_internal_style(arg1, cmd->pool);
+  conf->fs_parent_path = apr_pcalloc(cmd->pool, sizeof(path_expr_t));
+  conf->fs_parent_path->base = svn_dirent_internal_style(arg1, cmd->pool);
+
+  if (arg2)
+    {
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+      const char *expr_err = NULL;
+
+      conf->fs_parent_path->expr = ap_expr_parse_cmd(cmd, arg2, AP_EXPR_FLAG_STRING_RESULT,
+              &expr_err, NULL);
+      if (expr_err)
+        {
+          return apr_pstrcat(cmd->temp_pool,
+                  "Cannot parse expression '", arg2, "'in SVNParentPath: ",
+                      expr_err, NULL);
+        }
+#else
+      return "Expressions require httpd v2.4.0 or higher"
+#endif
+    }
+
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+  if (!conf->root_expr)
+    {
+      const char *expr_err = NULL;
+
+      conf->root_expr = ap_expr_parse_cmd(cmd, conf->root_dir, AP_EXPR_FLAG_STRING_RESULT,
+              &expr_err, NULL);
+      if (expr_err)
+        {
+          return apr_pstrcat(cmd->temp_pool,
+                  "Cannot parse Location expression '", conf->root_dir, "': ",
+                  expr_err, NULL);
+        }
+    }
+#endif
 
   return NULL;
 }
@@ -668,7 +755,61 @@ dav_svn__get_fs_path(request_rec *r)
   dir_conf_t *conf;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
-  return conf->fs_path;
+
+  if (conf->fs_path)
+    {
+
+  #if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+      if (conf->fs_path->expr)
+        {
+          svn_error_t *serr;
+          svn_boolean_t under_root;
+          const char *err = NULL, *suffix;
+
+          suffix = ap_expr_str_exec(r, conf->fs_path->expr, &err);
+          if (!err)
+            {
+              serr = svn_dirent_is_under_root(&under_root,
+                      &suffix, conf->fs_path->base, suffix, r->pool);
+              if (!serr && under_root)
+                {
+                  return svn_dirent_join(conf->fs_path->base,
+                          svn_dirent_internal_style(suffix, r->pool), r->pool);
+                }
+              else if (serr)
+                {
+                  ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err, r,
+                          "mod_dav_svn: SVNPath: '%s' not under '%s': '%s'",
+                          suffix, conf->fs_path->base,
+                          serr->message ? serr->message : "(no more info)");
+                  return NULL;
+                }
+              else
+                {
+                  ap_log_rerror(
+                          APLOG_MARK, APLOG_ERR, 0, r,
+                          "mod_dav_svn: SVNPath: '%s' not under '%s'",
+                          suffix, conf->fs_path->base);
+                  return NULL;
+                }
+            }
+          else
+            {
+              ap_log_rerror(
+                      APLOG_MARK, APLOG_ERR, 0, r, "mod_dav_svn: SVNPath: can't "
+                      "evaluate expression: %s", err);
+              return NULL;
+            }
+
+        }
+  #endif
+
+      return conf->fs_path->base;
+    }
+  else
+    {
+      return NULL;
+    }
 }
 
 
@@ -678,7 +819,61 @@ dav_svn__get_fs_parent_path(request_rec
   dir_conf_t *conf;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
-  return conf->fs_parent_path;
+
+  if (conf->fs_parent_path)
+    {
+
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+      if (conf->fs_parent_path->expr)
+        {
+          svn_error_t *serr;
+          svn_boolean_t under_root;
+          const char *err = NULL, *suffix;
+
+          suffix = ap_expr_str_exec(r, conf->fs_parent_path->expr, &err);
+          if (!err)
+            {
+              serr = svn_dirent_is_under_root(&under_root,
+                      &suffix, conf->fs_parent_path->base, suffix, r->pool);
+              if (!serr && under_root)
+                {
+                  return svn_dirent_join(conf->fs_parent_path->base,
+                          svn_dirent_internal_style(suffix, r->pool), r->pool);
+                }
+              else if (serr)
+                {
+                  ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err, r,
+                          "mod_dav_svn: SVNParentPath: '%s' not under '%s': '%s'",
+                          suffix, conf->fs_parent_path->base,
+                          serr->message ? serr->message : "(no more info)");
+                  return NULL;
+                }
+              else
+                {
+                  ap_log_rerror(
+                          APLOG_MARK, APLOG_ERR, 0, r,
+                          "mod_dav_svn: SVNParentPath: '%s' not under '%s'",
+                          suffix, conf->fs_parent_path->base);
+                  return NULL;
+                }
+            }
+          else
+            {
+              ap_log_rerror(
+                      APLOG_MARK, APLOG_ERR, 0, r, "mod_dav_svn: SVNParentPath: can't "
+                      "evaluate expression: %s", err);
+              return NULL;
+            }
+
+        }
+#endif
+
+      return conf->fs_parent_path->base;
+    }
+  else
+    {
+      return NULL;
+    }
 }
 
 
@@ -751,7 +946,29 @@ dav_svn__get_root_dir(request_rec *r)
   dir_conf_t *conf;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
-  return conf->root_dir;
+
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+  if (conf->root_expr)
+    {
+      const char *err = NULL, *root_dir;
+
+      root_dir = ap_expr_str_exec(r, conf->root_expr, &err);
+      if (!err)
+        {
+          return svn_urlpath__canonicalize(root_dir, r->pool);
+        }
+      else
+        {
+          ap_log_rerror(
+                  APLOG_MARK, APLOG_ERR, 0, r, "mod_dav_svn: can't "
+                  "evaluate root directory expression: %s", err);
+        }
+
+    }
+  return NULL;
+#else
+  return svn_urlpath__canonicalize(conf->root_dir, r->pool);
+#endif
 }
 
 
@@ -1192,7 +1409,7 @@ static int dav_svn__translate_name(reque
   else
     {
       /* Retrieve path to repo and within repo for the request */
-      dav_error *err = dav_svn_split_uri(r, r->uri, conf->root_dir,
+      dav_error *err = dav_svn_split_uri(r, r->uri, dav_svn__get_root_dir(r),
                                          &ignore_cleaned_uri,
                                          &ignore_had_slash, &repos_basename,
                                          &ignore_relative_path, &repos_path);
@@ -1205,12 +1422,18 @@ static int dav_svn__translate_name(reque
 
   if (conf->fs_parent_path)
     {
-      fs_path = svn_dirent_join(conf->fs_parent_path, repos_basename,
-                                r->pool);
+      fs_path = dav_svn__get_fs_parent_path(r);
+      if (!fs_path)
+          return HTTP_INTERNAL_SERVER_ERROR;
+
+      fs_path = svn_dirent_join(fs_path, repos_basename,
+              r->pool);
     }
   else
     {
-      fs_path = conf->fs_path;
+      fs_path = dav_svn__get_fs_path(r);
+      if (!fs_path)
+          return HTTP_INTERNAL_SERVER_ERROR;
     }
 
   /* Avoid a trailing slash on the bogus path when repos_path is just "/" */
@@ -1254,9 +1477,10 @@ static int dav_svn__map_to_storage(reque
 static const command_rec cmds[] =
 {
   /* per directory/location */
-  AP_INIT_TAKE1("SVNPath", SVNPath_cmd, NULL, ACCESS_CONF,
+  AP_INIT_TAKE12("SVNPath", SVNPath_cmd, NULL, ACCESS_CONF,
                 "specifies the location in the filesystem for a Subversion "
-                "repository's files."),
+                "repository's files. Add an optional suffix expression as"
+                "a second argument."),
 
   /* per server */
   AP_INIT_TAKE1("SVNSpecialURI", SVNSpecialURI_cmd, NULL, RSRC_CONF,
@@ -1273,9 +1497,11 @@ static const command_rec cmds[] =
                 "directory indexes"),
 
   /* per directory/location */
-  AP_INIT_TAKE1("SVNParentPath", SVNParentPath_cmd, NULL, ACCESS_CONF,
+  AP_INIT_TAKE12("SVNParentPath", SVNParentPath_cmd, NULL, ACCESS_CONF,
                 "specifies the location in the filesystem whose "
-                "subdirectories are assumed to be Subversion repositories."),
+                "subdirectories are assumed to be Subversion "
+                "repositories. Add an optional suffix expression as"
+                "a second argument."),
 
   /* per directory/location */
   AP_INIT_FLAG("SVNAutoversioning", SVNAutoversioning_cmd, NULL,



Re: svn commit: r1663412 - in /subversion/branches/mod-dav-svn-expressions: CHANGES subversion/mod_dav_svn/mod_dav_svn.c

Posted by Branko Čibej <br...@wandisco.com>.
On 02.03.2015 20:55, minfrin@apache.org wrote:
> Author: minfrin
> Date: Mon Mar  2 19:55:11 2015
> New Revision: 1663412
>
> URL: http://svn.apache.org/r1663412
> Log:
> mod_dav_svn: add expression support for templates in SVNPath and
> SVNParentPath.

Hi Graham,

Thanks!

FYI, we have a bit of a tradition about code style and writing log
messages; see

http://subversion.apache.org/docs/community-guide/conventions.html
http://subversion.apache.org/docs/community-guide/

and also (on that branch)

    $ svn log -c1663861,1663863,1663865

where I tweaked the code to match our formatting guidelines.

You can update the log message with this command:

    $ svn propedit --revprop svn:log -r1663412


-- Brane