You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by cm...@apache.org on 2012/10/16 17:59:43 UTC

svn commit: r1398863 - in /subversion/trunk/subversion: include/private/svn_subr_private.h include/svn_error_codes.h libsvn_subr/version.c tests/libsvn_subr/compat-test.c

Author: cmpilato
Date: Tue Oct 16 15:59:42 2012
New Revision: 1398863

URL: http://svn.apache.org/viewvc?rev=1398863&view=rev
Log:
Add private APIs for parsing Subversion release version strings and
testing that they meet some minimum required version number.  This is
intended for use with a new SVNMasterVersion httpd.conf directive (to
replace the plethora of per-feature toggles required to make
version-mismatched proxy servers happy).

That said, we might consider making these public and exposing them to
hook authors who wish to use the ephemeral txnprops in start-commit
and pre-commit to test and deny/allow commits based on client version
pedigree.  Just a thought.

* subversion/include/svn_error_codes.h
  (SVN_ERR_MALFORMED_VERSION_STRING): New error code.

* subversion/include/private/svn_subr_private.h,
* subversion/libsvn_subr/version.c
  (svn_version__parse_version_string, svn_version__at_least): New functions.

* subversion/tests/libsvn_subr/compat-test.c
  (test_version_parsing, test_version_at_least): New tests.
  (test_funcs): Add reference to new tests.

Modified:
    subversion/trunk/subversion/include/private/svn_subr_private.h
    subversion/trunk/subversion/include/svn_error_codes.h
    subversion/trunk/subversion/libsvn_subr/version.c
    subversion/trunk/subversion/tests/libsvn_subr/compat-test.c

Modified: subversion/trunk/subversion/include/private/svn_subr_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_subr_private.h?rev=1398863&r1=1398862&r2=1398863&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_subr_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_subr_private.h Tue Oct 16 15:59:42 2012
@@ -295,6 +295,36 @@ svn_hash__make(apr_pool_t *pool);
 
 /** @} */
 
+/**
+ * @defgroup svn_version Version number dotted triplet parsing
+ * @{
+ */
+
+/* Set @a *version to a version structure parsed from the version
+ * string representation in @a version_string.  Return 
+ * @c SVN_ERR_MALFORMED_VERSION_STRING if the string fails to parse
+ * cleanly.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_version__parse_version_string(svn_version_t **version,
+                                  const char *version_string,
+                                  apr_pool_t *result_pool);
+
+/* Return true iff @a version represents a version number of at least
+ * the level represented by @a major, @a minor, and @a patch.
+ *
+ * @since New in 1.8.
+ */
+svn_boolean_t
+svn_version__at_least(svn_version_t *version,
+                      int major,
+                      int minor,
+                      int patch);
+
+/** @} */
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/trunk/subversion/include/svn_error_codes.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_error_codes.h?rev=1398863&r1=1398862&r2=1398863&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_error_codes.h (original)
+++ subversion/trunk/subversion/include/svn_error_codes.h Tue Oct 16 15:59:42 2012
@@ -1415,6 +1415,11 @@ SVN_ERROR_START
              SVN_ERR_MISC_CATEGORY_START + 36,
              "too many memcached servers configured")
 
+  /** @since New in 1.8. */
+  SVN_ERRDEF(SVN_ERR_MALFORMED_VERSION_STRING,
+             SVN_ERR_MISC_CATEGORY_START + 37,
+             "too many memcached servers configured")
+
   /* command-line client errors */
 
   SVN_ERRDEF(SVN_ERR_CL_ARG_PARSING_ERROR,

Modified: subversion/trunk/subversion/libsvn_subr/version.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/version.c?rev=1398863&r1=1398862&r2=1398863&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/version.c (original)
+++ subversion/trunk/subversion/libsvn_subr/version.c Tue Oct 16 15:59:42 2012
@@ -28,6 +28,7 @@
 
 #include "sysinfo.h"
 #include "svn_private_config.h"
+#include "private/svn_subr_private.h"
 
 const svn_version_t *
 svn_subr_version(void)
@@ -193,3 +194,85 @@ svn_version_ext_loaded_libs(const svn_ve
 {
   return ext_info->loaded_libs;
 }
+
+svn_error_t *
+svn_version__parse_version_string(svn_version_t **version_p,
+                                  const char *version_string,
+                                  apr_pool_t *result_pool)
+{
+  svn_error_t *err;
+  svn_version_t *version;
+  apr_array_header_t *pieces = 
+    svn_cstring_split(version_string, ".", FALSE, result_pool);
+
+  if ((pieces->nelts < 2) || (pieces->nelts > 3))
+    return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING, NULL, NULL);
+
+  version = apr_pcalloc(result_pool, sizeof(*version));
+  version->tag = "";
+
+  /* Parse the major and minor integers strictly. */
+  err = svn_cstring_atoi(&(version->major),
+                         APR_ARRAY_IDX(pieces, 0, const char *));
+  if (err)
+    return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING, err, NULL);
+  err = svn_cstring_atoi(&(version->minor),
+                         APR_ARRAY_IDX(pieces, 1, const char *));
+  if (err)
+    return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING, err, NULL);
+
+  /* If there's a third component, we'll parse it, too.  But we don't
+     require that it be present. */
+  if (pieces->nelts == 3)
+    {
+      const char *piece = APR_ARRAY_IDX(pieces, 2, const char *);
+      char *hyphen = strchr(piece, '-');
+      if (hyphen)
+        {
+          version->tag = apr_pstrdup(result_pool, hyphen + 1);
+          *hyphen = '\0';
+        }
+      err = svn_cstring_atoi(&(version->patch), piece);
+      if (err)
+        return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING,
+                                err, NULL);
+    }
+
+  *version_p = version;
+  return SVN_NO_ERROR;
+}
+
+
+svn_boolean_t
+svn_version__at_least(svn_version_t *version,
+                      int major,
+                      int minor,
+                      int patch)
+{
+  /* Compare major versions. */
+  if (version->major < major)
+    return FALSE;
+  if (version->major > major)
+    return TRUE;
+
+  /* Major versions are the same.  Compare minor versions. */
+  if (version->minor < minor)
+    return FALSE;
+  if (version->minor > minor)
+    return TRUE;
+
+  /* Major and minor versions are the same.  Compare patch
+     versions. */
+  if (version->patch < patch)
+    return FALSE;
+  if (version->patch > patch)
+    return TRUE;
+
+  /* Major, minor, and patch versions are identical matches.  But tags
+     in our schema are always used for versions not yet quite at the
+     given patch level. */
+  if (version->tag && version->tag[0])
+    return FALSE;
+
+  return TRUE;
+}

Modified: subversion/trunk/subversion/tests/libsvn_subr/compat-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_subr/compat-test.c?rev=1398863&r1=1398862&r2=1398863&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_subr/compat-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_subr/compat-test.c Tue Oct 16 15:59:42 2012
@@ -24,10 +24,12 @@
 #include <apr_pools.h>
 
 #include "svn_error.h"
+#include "svn_pools.h"
 #include "svn_version.h"
 
 #include "../svn_test.h"
 #include "svn_private_config.h"
+#include "private/svn_subr_private.h"
 
 #ifndef SVN_DISABLE_FULL_VERSION_MATCH
 #define FALSE_IF_FULL FALSE
@@ -100,11 +102,121 @@ test_version_compatibility(apr_pool_t *p
   return SVN_NO_ERROR;
 }
 
+
+static svn_error_t *
+test_version_parsing(apr_pool_t *pool)
+{
+  unsigned int i;
+  apr_pool_t *iterpool;
+
+  struct version_pair {
+    const char *str;
+    svn_boolean_t malformed;
+    svn_version_t version;
+  } versions[] = {
+    /*  str          malformed        version   */
+    { "1.8",           FALSE,     { 1,  8,  0, ""} },
+    { "1.8-dev",        TRUE,     { 0,  0,  0, ""} },
+    { "1.1.0",         FALSE,     { 1,  1,  0, ""} },
+    { "1.1.3",         FALSE,     { 1,  1,  3, ""} },
+    { "2.10.0",        FALSE,     { 2, 10,  0, ""} },
+    { "1.8.0-dev",     FALSE,     { 1,  8,  0, "dev"} },
+    { "1.7.0-beta1",   FALSE,     { 1,  7,  0, "beta1"} },
+    { "1a.8.0",         TRUE,     { 0,  0,  0, ""} },
+    { "1a.8.0",         TRUE,     { 0,  0,  0, ""} },
+    { "1.a8.0",         TRUE,     { 0,  0,  0, ""} },
+    { "1.8.0a",         TRUE,     { 0,  0,  0, ""} },
+    { "1.8.0.1",        TRUE,     { 0,  0,  0, ""} },
+  };
+
+  iterpool = svn_pool_create(pool);
+  for (i = 0; i < sizeof(versions)/sizeof(versions[0]); ++i)
+    {
+      svn_version_t *version;
+      svn_error_t *err;
+
+      svn_pool_clear(iterpool);
+
+      err = svn_version__parse_version_string(&version, versions[i].str,
+                                              iterpool);
+      if (err && (err->apr_err != SVN_ERR_MALFORMED_VERSION_STRING))
+        return svn_error_create(SVN_ERR_TEST_FAILED, err,
+                                "Unexpected error code");
+      if (err)
+        {
+          if (! versions[i].malformed)
+            return svn_error_create(SVN_ERR_TEST_FAILED, err,
+                                    "Unexpected parsing error returned");
+          else
+            svn_error_clear(err);
+        }
+      else
+        {
+          if (versions[i].malformed)
+            return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
+                                    "Parsing error expected; none returned");
+          if (! svn_ver_equal(version, &(versions[i].version)))
+            return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                                     "Parsed version of '%s' doesn't match "
+                                     "expected", versions[i].str);
+        }
+    }
+  svn_pool_destroy(iterpool);
+  
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_version_at_least(apr_pool_t *pool)
+{
+  unsigned int i;
+
+  struct version_pair {
+    svn_version_t version;
+    int major;
+    int minor;
+    int patch;
+    svn_boolean_t at_least;
+  } versions[] = {
+    /* maj  min  pat     version   at_least */
+    { { 1, 3, 3, ""},    1, 3, 3,    TRUE },
+    { { 1, 3, 3, ""},    1, 3, 4,    FALSE },
+    { { 1, 3, 3, ""},    1, 4, 3,    FALSE },
+    { { 1, 3, 3, ""},    0, 4, 3,    TRUE },
+    { { 1, 3, 3, ""},    2, 0, 0,    FALSE },
+    { { 1, 3, 3, ""},    1, 3, 2,    TRUE },
+    { { 1, 3, 3, ""},    1, 2, 4,    TRUE },
+    { { 1, 3, 3, "dev"}, 1, 3, 2,    TRUE },
+    { { 1, 3, 3, "dev"}, 1, 3, 3,    FALSE },
+    { { 1, 3, 3, ""},    0, 4, 3,    TRUE },
+  };
+
+  for (i = 0; i < sizeof(versions)/sizeof(versions[0]); ++i)
+    {
+      svn_boolean_t at_least = svn_version__at_least(&(versions[i].version),
+                                                     versions[i].major,
+                                                     versions[i].minor,
+                                                     versions[i].patch);
+      if (at_least && (! versions[i].at_least))
+        return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
+                                "Expected at-least to be FALSE; got TRUE");
+      if ((! at_least) && versions[i].at_least)
+        return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
+                                "Expected at-least to be TRUE; got FALSE");
+    }
+  
+  return SVN_NO_ERROR;
+}
+
 /* An array of all test functions */
 struct svn_test_descriptor_t test_funcs[] =
   {
     SVN_TEST_NULL,
     SVN_TEST_PASS2(test_version_compatibility,
                    "svn_ver_compatible"),
+    SVN_TEST_PASS2(test_version_parsing,
+                   "svn_version__parse_version_string"),
+    SVN_TEST_PASS2(test_version_at_least,
+                   "svn_version__at_least"),
     SVN_TEST_NULL
   };



RE: svn commit: r1398863 - in /subversion/trunk/subversion: include/private/svn_subr_private.h include/svn_error_codes.h libsvn_subr/version.c tests/libsvn_subr/compat-test.c

Posted by Bert Huijben <be...@qqmail.nl>.

> -----Original Message-----
> From: C. Michael Pilato [mailto:cmpilato@collab.net]
> Sent: dinsdag 16 oktober 2012 20:11
> To: Bert Huijben
> Cc: dev@subversion.apache.org
> Subject: Re: svn commit: r1398863 - in /subversion/trunk/subversion:
> include/private/svn_subr_private.h include/svn_error_codes.h
> libsvn_subr/version.c tests/libsvn_subr/compat-test.c
> 
> On 10/16/2012 12:47 PM, Bert Huijben wrote:
> >> Add private APIs for parsing Subversion release version strings and
> >> testing that they meet some minimum required version number.  This is
> >> intended for use with a new SVNMasterVersion httpd.conf directive (to
> >> replace the plethora of per-feature toggles required to make
> >> version-mismatched proxy servers happy).
> >>
> >> That said, we might consider making these public and exposing them to
> >> hook authors who wish to use the ephemeral txnprops in start-commit
> and
> >> pre-commit to test and deny/allow commits based on client version
> >> pedigree.  Just a thought.
> >
> > Can we also use this for a more future proof svnadmin create
> > --pre-1.6-compatible variant?
> >
> > There is currently no way I can always create a Subversion 1.7 repository
> > with either a 1.7 or a future client. (1.7 doesn't accept a pre-1.8
> > compatible version argument, etc.)
> 
> So, you're thinking something along the lines of:
> 
>    $ svnadmin create --compat-version=MAJOR.MINOR

Something like that.

I really dislike the existing pattern here, of just adding a new argument on new versions for making the repository compatible with an old version. This only makes us compatible one version after breaking compatibility.

	Bert



Re: svn commit: r1398863 - in /subversion/trunk/subversion: include/private/svn_subr_private.h include/svn_error_codes.h libsvn_subr/version.c tests/libsvn_subr/compat-test.c

Posted by "C. Michael Pilato" <cm...@collab.net>.
On 10/16/2012 12:47 PM, Bert Huijben wrote:
>> Add private APIs for parsing Subversion release version strings and 
>> testing that they meet some minimum required version number.  This is 
>> intended for use with a new SVNMasterVersion httpd.conf directive (to 
>> replace the plethora of per-feature toggles required to make 
>> version-mismatched proxy servers happy).
>> 
>> That said, we might consider making these public and exposing them to 
>> hook authors who wish to use the ephemeral txnprops in start-commit and
>> pre-commit to test and deny/allow commits based on client version 
>> pedigree.  Just a thought.
> 
> Can we also use this for a more future proof svnadmin create
> --pre-1.6-compatible variant?
> 
> There is currently no way I can always create a Subversion 1.7 repository
> with either a 1.7 or a future client. (1.7 doesn't accept a pre-1.8
> compatible version argument, etc.)

So, you're thinking something along the lines of:

   $ svnadmin create --compat-version=MAJOR.MINOR

?

-- 
C. Michael Pilato <cm...@collab.net>
CollabNet   <>   www.collab.net   <>   Enterprise Cloud Development


RE: svn commit: r1398863 - in /subversion/trunk/subversion: include/private/svn_subr_private.h include/svn_error_codes.h libsvn_subr/version.c tests/libsvn_subr/compat-test.c

Posted by Bert Huijben <be...@qqmail.nl>.

> -----Original Message-----
> From: cmpilato@apache.org [mailto:cmpilato@apache.org]
> Sent: dinsdag 16 oktober 2012 18:00
> To: commits@subversion.apache.org
> Subject: svn commit: r1398863 - in /subversion/trunk/subversion:
> include/private/svn_subr_private.h include/svn_error_codes.h
> libsvn_subr/version.c tests/libsvn_subr/compat-test.c
> 
> Author: cmpilato
> Date: Tue Oct 16 15:59:42 2012
> New Revision: 1398863
> 
> URL: http://svn.apache.org/viewvc?rev=1398863&view=rev
> Log:
> Add private APIs for parsing Subversion release version strings and
> testing that they meet some minimum required version number.  This is
> intended for use with a new SVNMasterVersion httpd.conf directive (to
> replace the plethora of per-feature toggles required to make
> version-mismatched proxy servers happy).
> 
> That said, we might consider making these public and exposing them to
> hook authors who wish to use the ephemeral txnprops in start-commit
> and pre-commit to test and deny/allow commits based on client version
> pedigree.  Just a thought.

Can we also use this for a more future proof svnadmin create --pre-1.6-compatible variant?

There is currently no way I can always create a Subversion 1.7 repository with either a 1.7 or a future client. (1.7 doesn't accept a pre-1.8 compatible version argument, etc.)

	Bert 



RE: svn commit: r1398863 - in /subversion/trunk/subversion: include/private/svn_subr_private.h include/svn_error_codes.h libsvn_subr/version.c tests/libsvn_subr/compat-test.c

Posted by Bert Huijben <be...@qqmail.nl>.

> -----Original Message-----
> From: cmpilato@apache.org [mailto:cmpilato@apache.org]
> Sent: dinsdag 16 oktober 2012 18:00
> To: commits@subversion.apache.org
> Subject: svn commit: r1398863 - in /subversion/trunk/subversion:
> include/private/svn_subr_private.h include/svn_error_codes.h
> libsvn_subr/version.c tests/libsvn_subr/compat-test.c
> 
> Author: cmpilato
> Date: Tue Oct 16 15:59:42 2012
> New Revision: 1398863
> 
> URL: http://svn.apache.org/viewvc?rev=1398863&view=rev
> Log:
> Add private APIs for parsing Subversion release version strings and
> testing that they meet some minimum required version number.  This is
> intended for use with a new SVNMasterVersion httpd.conf directive (to
> replace the plethora of per-feature toggles required to make
> version-mismatched proxy servers happy).
> 
> That said, we might consider making these public and exposing them to
> hook authors who wish to use the ephemeral txnprops in start-commit
> and pre-commit to test and deny/allow commits based on client version
> pedigree.  Just a thought.

Can we also use this for a more future proof svnadmin create --pre-1.6-compatible variant?

There is currently no way I can always create a Subversion 1.7 repository with either a 1.7 or a future client. (1.7 doesn't accept a pre-1.8 compatible version argument, etc.)

	Bert