In message <1047303679.3e6c95ff2183b@www.xbc.nu>
brane@xbc.nu wrote:
> Quoting Alex Waugh <alex@alexwaugh.com>:
>
>
> > - SVN_ERR (svn_io_set_file_executable (path, TRUE, TRUE, pool));
> > + {
> > + /* Since we only check if the property exists or not, force the
> > + property value to a specific value */
> > + new_value = svn_stringbuf_create_from_string (value, pool);
> > + svn_stringbuf_set (new_value, SVN_PROP_EXECUTABLE_VALUE);
> > + SVN_ERR (svn_io_set_file_executable (path, TRUE, TRUE, pool));
> > + }
>
> How about just:
>
> value = SVN_PROP_EXECUTABLE_VALUE;
>
> You don't have to create a stringbuf just to change the prop value to a fixed
> string, right? :-)
You still need to create a svn_string though, as value is a const. I
suppose you could have a third non-const value variable instead.
> I'll make that change and commit later today.
I've updated the tests in the patch below, and thought I might as well
make the other two changes at the same time. Don't worry if you've
already done them though.
Alex
* subversion/libsvn_wc/props.c
(svn_wc_prop_set): Force svn:executable to a specific value, Strip all
leading and trailing whitespace for svn:mime-type, svn:eol-style and
svn:keywords. Make sure that the last line in the prop value ends in a
newline for svn:ignore and svn:externals.
* subversion/include/svn_props.h
(SVN_PROP_EXECUTABLE_VALUE): New value to force svn:executable to.
* subversion/tests/clients/cmdline/prop_tests.py
(copy_should_use_copied_executable_and_mime_type_values): Take account of
svn:executable being forced to "*".
(strip_or_add_whitespace): New test for whitespace stripping.
* subversion/tests/clients/cmdline/schedule_tests.py
(add_executable): Take account of svn:executable being forced to "*".
* doc/book/book/ch06.xml: Mention new behaviour of svn:executable.
Index: subversion/include/svn_props.h
===================================================================
--- subversion/include/svn_props.h (revision 5249)
+++ subversion/include/svn_props.h (working copy)
@@ -165,6 +165,9 @@
/** Set to either TRUE or FALSE if we want a file to be executable or not. */
#define SVN_PROP_EXECUTABLE SVN_PROP_PREFIX "executable"
+/** The value to force the executable property to when set */
+#define SVN_PROP_EXECUTABLE_VALUE "*"
+
/** Describes external items to check out into this directory.
*
* Describes external items to check out into this directory.
Index: subversion/libsvn_wc/props.c
===================================================================
--- subversion/libsvn_wc/props.c (revision 5249)
+++ subversion/libsvn_wc/props.c (working copy)
@@ -1103,6 +1103,7 @@
apr_hash_t *prophash;
apr_file_t *fp = NULL;
svn_subst_keywords_t *old_keywords;
+ svn_stringbuf_t *new_value = NULL;
svn_node_kind_t kind;
enum svn_prop_kind prop_kind = svn_property_kind (NULL, name);
@@ -1124,7 +1125,30 @@
{
SVN_ERR (validate_prop_against_node_kind (name, path, kind, pool));
if (strcmp (name, SVN_PROP_EOL_STYLE) == 0)
- SVN_ERR (validate_eol_prop_against_file (path, adm_access, pool));
+ {
+ new_value = svn_stringbuf_create_from_string (value, pool);
+ svn_stringbuf_strip_whitespace (new_value);
+ SVN_ERR (validate_eol_prop_against_file (path, adm_access, pool));
+ }
+ else if (strcmp (name, SVN_PROP_MIME_TYPE) == 0)
+ {
+ new_value = svn_stringbuf_create_from_string (value, pool);
+ svn_stringbuf_strip_whitespace (new_value);
+ SVN_ERR (svn_mime_type_validate (new_value->data, pool));
+ }
+ else if (strcmp (name, SVN_PROP_IGNORE) == 0
+ || strcmp (name, SVN_PROP_EXTERNALS) == 0)
+ {
+ new_value = svn_stringbuf_create_from_string (value, pool);
+ /* Make sure that the last line ends in a newline */
+ if (new_value->data[new_value->len - 1] != '\n')
+ svn_stringbuf_appendbytes (new_value, "\n", sizeof ("\n") - 1);
+ }
+ else if (strcmp (name, SVN_PROP_KEYWORDS) == 0)
+ {
+ new_value = svn_stringbuf_create_from_string (value, pool);
+ svn_stringbuf_strip_whitespace (new_value);
+ }
}
if (kind == svn_node_file && strcmp (name, SVN_PROP_EXECUTABLE) == 0)
@@ -1133,14 +1157,17 @@
If the svn:executable property was deleted (NULL value passed
in), then chmod -x. */
if (value == NULL)
- SVN_ERR (svn_io_set_file_executable (path, FALSE, TRUE, pool));
+ {
+ SVN_ERR (svn_io_set_file_executable (path, FALSE, TRUE, pool));
+ }
else
- SVN_ERR (svn_io_set_file_executable (path, TRUE, TRUE, pool));
+ {
+ /* Since we only check if the property exists or not, force the
+ property value to a specific value */
+ value = svn_string_create (SVN_PROP_EXECUTABLE_VALUE, pool);
+ SVN_ERR (svn_io_set_file_executable (path, TRUE, TRUE, pool));
+ }
}
- else if ((strcmp (name, SVN_PROP_MIME_TYPE) == 0) && value)
- {
- SVN_ERR (svn_mime_type_validate (value->data, pool));
- }
err = svn_wc_prop_list (&prophash, path, adm_access, pool);
if (err)
@@ -1162,6 +1189,8 @@
/* Now we have all the properties in our hash. Simply merge the new
property into it. */
+ if (new_value)
+ value = svn_string_create_from_buf (new_value, pool);
apr_hash_set (prophash, name, APR_HASH_KEY_STRING, value);
/* Open the propfile for writing. */
Index: subversion/tests/clients/cmdline/prop_tests.py
===================================================================
--- subversion/tests/clients/cmdline/prop_tests.py (revision 5249)
+++ subversion/tests/clients/cmdline/prop_tests.py (working copy)
@@ -699,12 +699,13 @@
status = 1
# Check the svn:executable value.
+ # The value of the svn:executable property is now always forced to '*'
if os.name == 'posix':
actual_stdout, actual_stderr = svntest.main.run_svn(None,
'pg',
'svn:executable',
new_path2)
- expected_stdout = ['on\n']
+ expected_stdout = ['*\n']
if actual_stdout != expected_stdout:
print "svn pg svn:executable output does not match expected."
print "Expected standard output: ", expected_stdout, "\n"
@@ -737,7 +738,247 @@
return 0
+#----------------------------------------------------------------------
+def strip_or_add_whitespace(sbox):
+ "some svn: properties should have whitespace stripped or added"
+
+ # Bootstrap
+ if sbox.build():
+ return 1
+
+ wc_dir = sbox.wc_dir
+ A_path = os.path.join(wc_dir, 'A')
+ B_path = os.path.join(wc_dir, 'A', 'B')
+ iota_path = os.path.join(wc_dir, 'iota')
+ lambda_path = os.path.join(wc_dir, 'A', 'B', 'lambda')
+ mu_path = os.path.join(wc_dir, 'A', 'mu')
+
+ # Leading and trailing whitespace should be stripped
+ svntest.main.run_svn(None, 'propset', 'svn:mime-type', ' text/html\n\n',
+ iota_path)
+ svntest.main.run_svn(None, 'propset', 'svn:mime-type', 'text/html',
+ mu_path)
+
+ # Leading and trailing whitespace should be stripped
+ svntest.main.run_svn(None, 'propset', 'svn:eol-style', '\nnative\n',
+ iota_path)
+ svntest.main.run_svn(None, 'propset', 'svn:eol-style', 'native', mu_path)
+
+ # A trailing newline should be added if it doesn't already exist
+ svntest.main.run_svn(None, 'propset', 'svn:ignore', '*.o\nfoo.c', A_path)
+ svntest.main.run_svn(None, 'propset', 'svn:ignore', '*.o\nfoo.c\n', B_path)
+
+ # A trailing newline should be added if it doesn't already exist
+ svntest.main.run_svn(None, 'propset', 'svn:externals',
+ 'foo http://foo.com/repos', A_path)
+ svntest.main.run_svn(None, 'propset', 'svn:externals',
+ 'foo http://foo.com/repos\n', B_path)
+
+ # Leading and trailing whitespace should be stripped, but not internal
+ # whitespace
+ svntest.main.run_svn(None, 'propset', 'svn:keywords', ' Rev Date \n',
+ iota_path)
+ svntest.main.run_svn(None, 'propset', 'svn:keywords', 'Rev Date', mu_path)
+
+ # svn:executable value should be forced to a '*'
+ svntest.main.run_svn(None, 'propset', 'svn:executable', 'foo', iota_path)
+ svntest.main.run_svn(None, 'propset', 'svn:executable', '', lambda_path)
+ svntest.main.run_svn(None, 'propset', 'svn:executable', ' ', mu_path)
+
+ # Anything else should be untouched
+ svntest.main.run_svn(None, 'propset', 'svn:foo', 'bar', lambda_path)
+ svntest.main.run_svn(None, 'propset', 'svn:foo', ' bar baz', mu_path)
+ svntest.main.run_svn(None, 'propset', 'svn:foo', 'bar\n', iota_path)
+
+
+ # Check svn:mime-type
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:mime-type',
+ iota_path)
+ expected_stdout = ['text/html\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:mime-type output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:mime-type',
+ mu_path)
+ expected_stdout = ['text/html\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:mime-type output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ # Check svn:eol-style
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:eol-style',
+ iota_path)
+ expected_stdout = ['native\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:eol-style output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:eol-style',
+ mu_path)
+ expected_stdout = ['native\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:eol-style output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ # Check svn:ignore
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:ignore',
+ A_path)
+ expected_stdout = ['*.o\n', 'foo.c\n', '\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:ignore output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:ignore',
+ B_path)
+ expected_stdout = ['*.o\n', 'foo.c\n', '\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:ignore output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ # Check svn:externals
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:externals',
+ A_path)
+ expected_stdout = ['foo http://foo.com/repos\n', '\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:externals output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:externals',
+ B_path)
+ expected_stdout = ['foo http://foo.com/repos\n', '\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:externals output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ # Check svn:keywords
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:keywords',
+ iota_path)
+ expected_stdout = ['Rev Date\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:keywords output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:keywords',
+ mu_path)
+ expected_stdout = ['Rev Date\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:keywords output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ # Check svn:executable
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:executable',
+ iota_path)
+ expected_stdout = ['*\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:keywords output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:executable',
+ lambda_path)
+ expected_stdout = ['*\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:keywords output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:executable',
+ mu_path)
+ expected_stdout = ['*\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:keywords output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ # Check other props
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:foo',
+ lambda_path)
+ expected_stdout = ['bar\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:keywords output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:foo',
+ mu_path)
+ expected_stdout = [' bar baz\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:keywords output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ actual_stdout, actual_stderr = svntest.main.run_svn(None,
+ 'pg',
+ 'svn:foo',
+ iota_path)
+ expected_stdout = ['bar\n', '\n']
+ if actual_stdout != expected_stdout:
+ print "svn pg svn:keywords output does not match expected."
+ print "Expected standard output: ", expected_stdout, "\n"
+ print "Actual standard output: ", actual_stdout, "\n"
+ return 1
+
+ return 0
+
+
+
########################################################################
# Run the tests
@@ -757,6 +998,7 @@
# If we learn how to write a pre-revprop-change hook for
# non-Posix platforms, we won't have to skip here:
Skip(revprop_change, (os.name != 'posix')),
+ strip_or_add_whitespace,
]
if __name__ == '__main__':
Index: subversion/tests/clients/cmdline/schedule_tests.py
===================================================================
--- subversion/tests/clients/cmdline/schedule_tests.py (revision 5249)
+++ subversion/tests/clients/cmdline/schedule_tests.py (working copy)
@@ -177,7 +177,7 @@
def runTest(wc_dir, fileName, perm, executable):
fileName = os.path.join(wc_dir, fileName)
if executable:
- expected = (["\n"], [])
+ expected = (["*\n"], [])
else:
expected = ([], [])
f = open(fileName,"w")
Index: doc/book/book/ch06.xml
===================================================================
--- doc/book/book/ch06.xml (revision 5249)
+++ doc/book/book/ch06.xml (working copy)
@@ -931,16 +931,10 @@
<literal>.COM</literal>) to denote executable
files.</para>
</footnote>
- Also, while it has no defined values, some people choose as
- a convention a value (such as <literal>on</literal>) to use
- when setting this property. Subversion doesn't
- care—it won't even read the property value. But be
- careful when choosing such conventions—inexperienced
- users might mistakenly believe that the way to disable this
- functionality is to change the property value to its
- idiomatic <!-- is that the right word? --> opposite (in this
- case, <literal>off</literal>). Finally, this property is
- valid only on files, not on directories.</para>
+ Also, although it has no defined values, Subversion will force
+ its value to <literal>*</literal> when setting this property.
+ Finally, this property is valid only on files, not on
+ directories.</para>
</sect3>
--
Alex Waugh alex@alexwaugh.com
RISC OS Software from http://www.alexwaugh.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue Mar 11 00:23:54 2003