[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH] Phase 3 of Keywords as Hash - Properties as Keywords

From: John Peacock <jpeacock_at_rowman.com>
Date: 2004-04-23 20:34:38 CEST

Finally, the addition of a new feature: Properties as Keywords. Permits user
defined keywords, allowing properties to be embedded in source code files.
While not as useful as it might be with inherited properties, it is still of
some use, if only as a proof of concept for the keywords as hash rewrite. I'm
not sure that this is a 1.1.0 candidate.

Patch attached and log entry inline.

John

==================================================================
Custom user-defined keywords using properties

* subversion/libsvn_subr/subst.c
   (svn_subst_build_keywords2): Add stanza to use properties as keywords

* subversion/tests/clients/cmdline/prop_tests.py
   (keyword_props): new tests to exercise properties as keywords feature

-- 
John Peacock
Director of Information Research and Technology
Rowman & Littlefield Publishing Group
4501 Forbes Boulevard
Suite H
Lanham, MD  20706
301-459-3366 x.5010
fax 301-429-5748

Index: subversion/libsvn_subr/subst.c
==================================================================
--- subversion/libsvn_subr/subst.c (revision 8737)
+++ subversion/libsvn_subr/subst.c (local)
@@ -429,6 +429,64 @@
        * placed here to check and see if one of the repository-defined
        * keywords matches
        */
+ else /* a keyword that doesn't match (may be a property) */
+ {
+ if (props)
+ {
+ svn_string_t *prop_val =
+ apr_hash_get(props, keyword, strlen(keyword));
+
+ /* do no harm if they didn't set that property */
+ if (prop_val)
+ {
+ char *found_nl;
+ svn_error_t *warn = NULL;
+ svn_stringbuf_t *prop_buf =
+ svn_stringbuf_create_from_string (prop_val, pool);
+ apr_size_t last_char = prop_buf->len;
+
+ /* make sure the property is only a single line */
+ if ((found_nl = strchr (prop_buf->data, '\n')) != NULL)
+ {
+ warn = svn_error_createf (SVN_ERR_BAD_PROP_KIND, NULL,
+ "Property used as keyword "
+ "contains newline: '%s'\n",
+ keyword);
+
+ /* shorten the string to the newline character */
+ last_char = (apr_size_t)(found_nl - prop_buf->data);
+ }
+
+ /* cannot have more than SVN_KEYWORD_MAX_LEN characters
+ * in a keyword value
+ */
+ if ( last_char > SVN_KEYWORD_MAX_LEN )
+ {
+ warn = svn_error_createf (SVN_ERR_BAD_PROP_KIND, NULL,
+ "Property used as keyword "
+ "contains too many characters:"
+ "'%s'\n", keyword);
+
+ last_char = SVN_KEYWORD_MAX_LEN;
+ }
+
+ /* emit a warning if one has been created */
+ if (warn)
+ {
+ svn_handle_warning (stderr, warn);
+ }
+
+ /* chop any extra characters off */
+ if (last_char < prop_buf->len)
+ svn_stringbuf_chop (prop_buf,
+ (prop_buf->len - last_char));
+
+ apr_hash_set (kw, keyword,
+ APR_HASH_KEY_STRING,
+ svn_string_create_from_buf(prop_buf,pool));
+ }
+ }
+ }
     }

   return SVN_NO_ERROR;
Index: subversion/tests/clients/cmdline/prop_tests.py
==================================================================
--- subversion/tests/clients/cmdline/prop_tests.py (revision 8737)
+++ subversion/tests/clients/cmdline/prop_tests.py (local)
@@ -1072,7 +1072,171 @@
   verify_output([ prop1 + ' : ' + propval1, prop2 + ' : ' + propval2,
                   'Properties on ' ], output, errput)

+#----------------------------------------------------------------------
+
+def keyword_props(sbox):
+ "keyword substitution from properties"
+
+ # Bootstrap
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ prop1 = 'prop1'
+ propval1 = 'propval1'
+ newpropval1 = 'newpropval1'
+ multilineprop = 'line one\nline two\nline three'
+ longprop = '12345' * 100
+ keywords = 'svn:keywords'
+
+ mu_path = os.path.join(sbox.wc_dir, 'A', 'mu')
+ svntest.main.file_append (mu_path, '\n$prop1$\n')
+
+ # Enable the keyword on that property, but don't set the property yet
+ svntest.main.run_svn(None, 'propset', keywords, prop1, mu_path)
+
+ # Create expected output tree.
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/mu' : Item(verb='Sending'),
+ })
+
+ # Created expected status tree.
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak(repos_rev=2)
+ expected_status.tweak('A/mu', wc_rev=2, status=' ')
+
+ # Commit the one file.
+ svntest.actions.run_and_verify_commit (wc_dir,
+ expected_output,
+ expected_status,
+ None,
+ None, None,
+ None, None,
+ wc_dir)
+
+ # Inspect mu, make sure it's right.
+ mu_text = svntest.tree.get_text(mu_path)
+ if mu_text != "This is the file 'mu'.\n$prop1$\n":
+ print "Unexpected text in keyword expanded '" + mu_path + "'"
+ raise svntest.Failure
+
+ # Now set the property and make sure that it actually expands
+ svntest.main.run_svn(None, 'propset', prop1, propval1, mu_path)
+
+ # Created expected status tree.
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak(repos_rev=3)
+ expected_status.tweak('A/mu', wc_rev=3, status=' ')
+
+ # Commit the file again
+ svntest.actions.run_and_verify_commit (wc_dir,
+ expected_output,
+ expected_status,
+ None,
+ None, None,
+ None, None,
+ wc_dir)
+
+ # Inspect mu, make sure it's still right.
+ mu_text = svntest.tree.get_text(mu_path)
+ if mu_text != "This is the file 'mu'.\n$prop1: propval1 $\n":
+ print "Unexpected text in keyword expanded '" + mu_path + "'"
+ raise svntest.Failure

+ # Change the property
+ svntest.main.run_svn(None, 'propset', prop1, newpropval1, mu_path)
+
+ # Created expected status tree.
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak(repos_rev=4)
+ expected_status.tweak('A/mu', wc_rev=4, status=' ')
+
+ # Commit the file again
+ svntest.actions.run_and_verify_commit (wc_dir,
+ expected_output,
+ expected_status,
+ None,
+ None, None,
+ None, None,
+ wc_dir)
+
+ # Inspect mu, make sure it's still right.
+ mu_text = svntest.tree.get_text(mu_path)
+ if mu_text != "This is the file 'mu'.\n$prop1: newpropval1 $\n":
+ print "Unexpected text in keyword expanded '" + mu_path + "'"
+ raise svntest.Failure
+
+ # Delete the property, but not the keyword
+ svntest.main.run_svn(None, 'propdel', prop1, mu_path)
+
+ # Created expected status tree.
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak(repos_rev=5)
+ expected_status.tweak('A/mu', wc_rev=5, status=' ')
+
+ # Commit the file again
+ svntest.actions.run_and_verify_commit (wc_dir,
+ expected_output,
+ expected_status,
+ None,
+ None, None,
+ None, None,
+ wc_dir)
+
+ # Inspect mu, make sure it's still right.
+ mu_text = svntest.tree.get_text(mu_path)
+ if mu_text != "This is the file 'mu'.\n$prop1: newpropval1 $\n":
+ print "Unexpected text in keyword expanded '" + mu_path + "'"
+ raise svntest.Failure
+
+ # Re-add the property but with a multiline one
+ svntest.main.run_svn(None, 'propset', prop1, multilineprop, mu_path)
+
+ # Created expected status tree.
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak(repos_rev=6)
+ expected_status.tweak('A/mu', wc_rev=6, status=' ')
+
+ # Commit the file again
+ # output, errput = svntest.actions.run_and_verify_svn(
+ # None, None, SVNAnyOutput,
+ # 'log', 'file:///nonexistent_path')
+ svntest.actions.run_and_verify_commit (wc_dir,
+ expected_output,
+ expected_status,
+ '.*keyword contains newline.*',
+ None, None,
+ None, None,
+ wc_dir)
+
+ # Inspect mu, make sure it's still right.
+ mu_text = svntest.tree.get_text(mu_path)
+ if mu_text != "This is the file 'mu'.\n$prop1: line one $\n":
+ print "Unexpected text in keyword expanded '" + mu_path + "'"
+ raise svntest.Failure
+
+ # Add a property with too many characters
+ svntest.main.run_svn(None, 'propset', prop1, longprop, mu_path)
+
+ # Created expected status tree.
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak(repos_rev=7)
+ expected_status.tweak('A/mu', wc_rev=7, status=' ')
+
+ # Commit the file again
+ svntest.actions.run_and_verify_commit (wc_dir,
+ expected_output,
+ expected_status,
+ '.*contains too many characters.*',
+ None, None,
+ None, None,
+ wc_dir)
+
+ # Inspect mu, make sure it's still right.
+ mu_text = svntest.tree.get_text(mu_path)
+ if mu_text.count('12345') != 50 :
+ print "Unexpected text in keyword expanded '" + mu_path + "'"
+ raise svntest.Failure
+
 ########################################################################
 # Run the tests
 
@@ -1096,6 +1260,7 @@
               binary_props,
               recursive_base_wc_ops,
               url_props_ops,
+ keyword_props,
              ]
 
 if __name__ == '__main__':

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri Apr 23 20:34:38 2004

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.