> Use SVN_ERR_ASSERT instead.
I fixed this in the attached patch.
> The apr_time_now call looks odd. Do we need to change the file's
> timestamp in this case?
Do you think the file's fimestamp should be preserved afer removing the
property?
> You also need to update the help text for 'svn ps' to describe the new
> property, see subversion/svn/svn.c.
I fixed this in the attached patch.
> and "if (" not "if(".
I fixed this in the attached patch.
> svn diff -x-p
> , please? That makes review easier.
I fixed this in the attached patch.
> Inheriting could be a later patch. Another issue in the current patch
> is the use of apr_time_now when the property is removed; changing that
> affects the regression test.
I added a test in update_with_use_commit_times() at
subversion/tests/cmdline/update_tests.py.
Regards.
--
Masaru Tsuchiyama<m.tma...@gmail.com>
Index: subversion/include/svn_props.h
===================================================================
--- subversion/include/svn_props.h (revision 1509957)
+++ subversion/include/svn_props.h (working copy)
@@ -412,6 +412,14 @@ svn_prop_name_is_valid(const char *prop_name);
*/
#define SVN_PROP_SPECIAL_VALUE SVN_PROP_BOOLEAN_TRUE
+/** The value to force the executable property to when set.
+ *
+ * @deprecated Provided for backward compatibility with the 1.4 API.
+ * Use @c SVN_PROP_BOOLEAN_TRUE instead.
+ * @since New in 1.9.
+ */
+#define SVN_PROP_USE_COMMIT_TIMES_VALUE SVN_PROP_BOOLEAN_TRUE
+
/** Describes external items to check out into this directory.
*
* The format is a series of lines, each in the following format:
@@ -449,6 +457,12 @@ svn_prop_name_is_valid(const char *prop_name);
/** Property used to record inheritable configuration ignores. */
#define SVN_PROP_INHERITABLE_IGNORES SVN_PROP_PREFIX "global-ignores"
+/**
+ * Property used to control whether timestamp of a file is modified to the
commit time * @since New in 1.9.
+ * @since New in 1.9.
+ */
+#define SVN_PROP_USE_COMMIT_TIMES SVN_PROP_PREFIX "use-commit-times"
+
/** Meta-data properties.
*
* The following properties are used for storing meta-data about
@@ -509,7 +523,8 @@ svn_prop_name_is_valid(const char *prop_name);
SVN_PROP_TEXT_TIME, \
SVN_PROP_OWNER, \
SVN_PROP_GROUP, \
- SVN_PROP_UNIX_MODE,
+ SVN_PROP_UNIX_MODE, \
+ SVN_PROP_USE_COMMIT_TIMES,
/** @} */
Index: subversion/libsvn_subr/properties.c
===================================================================
--- subversion/libsvn_subr/properties.c (revision 1509957)
+++ subversion/libsvn_subr/properties.c (working copy)
@@ -446,7 +446,8 @@ svn_prop_is_boolean(const char *prop_name)
make any speed difference. */
if (strcmp(prop_name, SVN_PROP_EXECUTABLE) == 0
|| strcmp(prop_name, SVN_PROP_NEEDS_LOCK) == 0
- || strcmp(prop_name, SVN_PROP_SPECIAL) == 0)
+ || strcmp(prop_name, SVN_PROP_SPECIAL) == 0
+ || strcmp(prop_name, SVN_PROP_USE_COMMIT_TIMES) == 0)
return TRUE;
return FALSE;
}
Index: subversion/libsvn_wc/props.c
===================================================================
--- subversion/libsvn_wc/props.c (revision 1509957)
+++ subversion/libsvn_wc/props.c (working copy)
@@ -2152,7 +2152,7 @@ svn_wc_canonicalize_svn_prop(const svn_string_t **
}
else if (svn_prop_is_boolean(propname))
{
- /* SVN_PROP_EXECUTABLE, SVN_PROP_NEEDS_LOCK, SVN_PROP_SPECIAL */
+ /* SVN_PROP_EXECUTABLE, SVN_PROP_NEEDS_LOCK, SVN_PROP_SPECIAL,
SVN_PROP_USE_COMMIT_TIMES */
propval = &boolean_value;
}
else if (strcmp(propname, SVN_PROP_MERGEINFO) == 0)
Index: subversion/libsvn_wc/update_editor.c
===================================================================
--- subversion/libsvn_wc/update_editor.c (revision 1509957)
+++ subversion/libsvn_wc/update_editor.c (working copy)
@@ -751,6 +751,12 @@ struct file_baton
/* The tree conflict to install once the node is really edited */
svn_skel_t *edit_conflict;
+
+ /* use-commit-times */
+ svn_boolean_t use_commit_times;
+
+ /* remove use-commit-times */
+ svn_boolean_t remove_use_commit_times;
};
@@ -3830,6 +3836,17 @@ change_file_prop(void *file_baton,
fb->already_notified = TRUE;
}
}
+ if (strcmp(name, SVN_PROP_USE_COMMIT_TIMES) == 0)
+ {
+ if (propchange->value)
+ {
+ fb->use_commit_times = TRUE;
+ }
+ else
+ {
+ fb->remove_use_commit_times = TRUE;
+ }
+ }
return SVN_NO_ERROR;
}
@@ -4636,6 +4653,24 @@ close_file(void *file_baton,
eb->notify_func(eb->notify_baton, notify, scratch_pool);
}
+ /* use_commit_times and remove_use_commit_times are mutably exclusive */
+ SVN_ERR_ASSERT( (fb->use_commit_times & fb->remove_use_commit_times) == 0 );
+ if ( !fb->adding_file )
+ {
+ if ( fb->use_commit_times && fb->changed_date )
+ {
+ SVN_ERR(svn_io_set_file_affected_time(fb->changed_date,
+ fb->local_abspath,
+ scratch_pool));
+ }
+ else if ( fb->remove_use_commit_times )
+ {
+ SVN_ERR(svn_io_set_file_affected_time(apr_time_now(),
+ fb->local_abspath,
+ scratch_pool));
+ }
+ }
+
svn_pool_destroy(fb->pool); /* Destroy scratch_pool */
/* We have one less referrer to the directory */
Index: subversion/libsvn_wc/workqueue.c
===================================================================
--- subversion/libsvn_wc/workqueue.c (revision 1509957)
+++ subversion/libsvn_wc/workqueue.c (working copy)
@@ -638,6 +638,9 @@ run_file_install(work_item_baton_t *wqb,
SVN_ERR(svn_io_set_file_read_only(local_abspath, FALSE, scratch_pool));
}
+ if (props && svn_hash_gets(props, SVN_PROP_USE_COMMIT_TIMES))
+ use_commit_times = TRUE;
+
if (use_commit_times)
{
if (changed_date)
Index: subversion/svn/svn.c
===================================================================
--- subversion/svn/svn.c (revision 1509957)
+++ subversion/svn/svn.c (working copy)
@@ -1340,6 +1340,8 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table
" before it is modified. Makes the working copy file read-only\n"
" when it is not locked. Use 'svn propdel svn:needs-lock PATH...'\n"
" to clear.\n"
+ " svn:use-commit-times - If present, make the timestamp of the file\n"
+ " to commit time. Use 'svn propdel svn:use-commit-times PATH...' to
clear.\n"
"\n"
" Subversion recognizes the following special versioned properties on
a\n"
" directory:\n"
Index: subversion/tests/cmdline/checkout_tests.py
===================================================================
--- subversion/tests/cmdline/checkout_tests.py (revision 1509957)
+++ subversion/tests/cmdline/checkout_tests.py (working copy)
@@ -1102,7 +1102,61 @@ def checkout_wc_from_drive(sbox):
subprocess.call(['subst', '/D', drive +':'])
#----------------------------------------------------------------------
+# Test checking out with svn:use-commit-times
+def checkout_with_use_commit_times(sbox):
+ "checkout with svn:use-commit-times"
+ sbox.build()
+
+ # Create the revprop-change hook for this test
+ svntest.actions.enable_revprop_changes(sbox.repo_dir)
+
+ wc_dir = sbox.wc_dir
+ iota_path = sbox.ospath('iota')
+
+ svntest.actions.set_prop('svn:use-commit-times', '*', iota_path)
+
+ # Create expected output tree.
+ expected_output = svntest.wc.State(wc_dir, {
+ 'iota' : Item(verb='Sending'),
+ })
+
+ # Commit the one file.
+ svntest.actions.run_and_verify_commit(wc_dir,
+ expected_output,
+ None,
+ None,
+ iota_path)
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'propset', '--revprop', '-r2',
+ 'svn:date', '2001-01-01T00:00:00.000000Z',
+ sbox.wc_dir)
+
+ # now checkout the repo in another folder
+ checkout_target = sbox.add_wc_path('checkout')
+ os.mkdir(checkout_target)
+
+ expected_output = svntest.main.greek_state.copy()
+ expected_output.wc_dir = checkout_target
+ expected_output.tweak(status='A ', contents=None)
+ expected_wc = svntest.main.greek_state.copy()
+
+ svntest.actions.run_and_verify_checkout(sbox.repo_url,
+ checkout_target,
+ expected_output,
+ expected_wc)
+ secs_svn_date = time.mktime( (2001, 1, 1, 0, 0, 0, 0, 0, 0) )
+ secs_svn_date -= time.timezone
+ new_iota = os.path.join(checkout_target, 'iota')
+ mtime = os.path.getmtime(new_iota)
+
+ # check whether the timestamp of the file is expected value
+ if secs_svn_date != mtime:
+ raise svntest.Failure
+
+#----------------------------------------------------------------------
+
# list all tests here, starting with None:
test_list = [ None,
checkout_with_obstructions,
@@ -1118,7 +1172,8 @@ test_list = [ None,
checkout_peg_rev,
checkout_peg_rev_date,
co_with_obstructing_local_adds,
- checkout_wc_from_drive
+ checkout_wc_from_drive,
+ checkout_with_use_commit_times
]
if __name__ == "__main__":
Index: subversion/tests/cmdline/export_tests.py
===================================================================
--- subversion/tests/cmdline/export_tests.py (revision 1509957)
+++ subversion/tests/cmdline/export_tests.py (working copy)
@@ -27,6 +27,7 @@
# General modules
import os
import tempfile
+import time
# Our testing module
import svntest
@@ -964,6 +965,63 @@ def export_custom_keywords(sbox):
if open(export_file).read() != ''.join(alpha_content):
raise svntest.Failure("wrong keyword expansion")
+
+#----------------------------------------------------------------------
+# Test exporting out with svn:use-commit-times
+def export_with_use_commit_times(sbox):
+ "export with svn:use-commit-times"
+
+ sbox.build()
+
+ # Create the revprop-change hook for this test
+ svntest.actions.enable_revprop_changes(sbox.repo_dir)
+
+ wc_dir = sbox.wc_dir
+ iota_path = sbox.ospath('iota')
+
+ svntest.actions.set_prop('svn:use-commit-times', '*', iota_path)
+
+ # Create expected output tree.
+ expected_output = svntest.wc.State(wc_dir, {
+ 'iota' : Item(verb='Sending'),
+ })
+
+ # Commit the one file.
+ svntest.actions.run_and_verify_commit(wc_dir,
+ expected_output,
+ None,
+ None,
+ iota_path)
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'propset', '--revprop', '-r2',
+ 'svn:date', '2001-01-01T00:00:00.000000Z',
+ sbox.wc_dir)
+
+ # now export the repo in another folder
+ export_target = sbox.add_wc_path('export')
+ expected_disk = svntest.main.greek_state.copy()
+ export_target = sbox.add_wc_path('export')
+
+ expected_output = svntest.main.greek_state.copy()
+ expected_output.wc_dir = export_target
+ expected_output.desc[''] = Item()
+ expected_output.tweak(contents=None, status='A ')
+
+ svntest.actions.run_and_verify_export(sbox.repo_url,
+ export_target,
+ expected_output,
+ expected_disk)
+
+ secs_svn_date = time.mktime( (2001, 1, 1, 0, 0, 0, 0, 0, 0) )
+ secs_svn_date -= time.timezone
+ new_iota = os.path.join(export_target, 'iota')
+ mtime = os.path.getmtime(new_iota)
+
+ # check whether the timestamp of the file is expected value
+ if secs_svn_date != mtime:
+ raise svntest.Failure
+
########################################################################
# Run the tests
@@ -998,6 +1056,7 @@ test_list = [ None,
export_to_current_dir,
export_file_overwrite_with_force,
export_custom_keywords,
+ export_with_use_commit_times,
]
if __name__ == '__main__':
Index: subversion/tests/cmdline/prop_tests.py
===================================================================
--- subversion/tests/cmdline/prop_tests.py (revision 1509957)
+++ subversion/tests/cmdline/prop_tests.py (working copy)
@@ -901,6 +901,13 @@ def prop_value_conversions(sbox):
svntest.actions.set_prop('svn:executable', pval, mu_path,
"svn: warning: W125005.*use 'svn propdel'")
+ # svn:use-commit-times value should be forced to a '*'
+ svntest.actions.set_prop('svn:use-commit-times', 'foo', iota_path)
+ svntest.actions.set_prop('svn:use-commit-times', '*', lambda_path)
+ for pval in (' ', '', 'no', 'off', 'false'):
+ svntest.actions.set_prop('svn:use-commit-times', pval, mu_path,
+ "svn: warning: W125005.*use 'svn propdel'")
+
# Anything else should be untouched
svntest.actions.set_prop('svn:some-prop', 'bar', lambda_path, force=True)
svntest.actions.set_prop('svn:some-prop', ' bar baz', mu_path, force=True)
@@ -945,6 +952,11 @@ def prop_value_conversions(sbox):
svntest.actions.check_prop('svn:executable', lambda_path, ['*'])
svntest.actions.check_prop('svn:executable', mu_path, ['*'])
+ # Check svn:use-commit-times
+ svntest.actions.check_prop('svn:use-commit-times', iota_path, ['*'])
+ svntest.actions.check_prop('svn:use-commit-times', lambda_path, ['*'])
+ svntest.actions.check_prop('svn:use-commit-times', mu_path, ['*'])
+
# Check other props
svntest.actions.check_prop('svn:some-prop', lambda_path, ['bar'])
svntest.actions.check_prop('svn:some-prop', mu_path, [' bar baz'])
Index: subversion/tests/cmdline/update_tests.py
===================================================================
--- subversion/tests/cmdline/update_tests.py (revision 1509957)
+++ subversion/tests/cmdline/update_tests.py (working copy)
@@ -6779,6 +6779,111 @@ def update_child_below_add(sbox):
sbox.ospath('A/B/E'))
+#----------------------------------------------------------------------
+# Test updating out with svn:use-commit-times
+def update_with_use_commit_times(sbox):
+ "update with svn:use-commit-times"
+
+ sbox.build()
+
+ # Create the revprop-change hook for this test
+ svntest.actions.enable_revprop_changes(sbox.repo_dir)
+
+ wc_dir = sbox.wc_dir
+ iota_path = sbox.ospath('iota')
+
+ # checkout the repo before setting 'svn:use-commit-times'
+ checkout_target = sbox.add_wc_path('checkout')
+ os.mkdir(checkout_target)
+
+ expected_output = svntest.main.greek_state.copy()
+ expected_output.wc_dir = checkout_target
+ expected_output.tweak(status='A ', contents=None)
+ expected_wc = svntest.main.greek_state.copy()
+
+ # checkout for updating before setting 'svn:use-commit-times'
+ svntest.actions.run_and_verify_checkout(sbox.repo_url,
+ checkout_target,
+ expected_output,
+ expected_wc)
+
+ # set 'svn:use-commit-times' to wc
+ svntest.actions.set_prop('svn:use-commit-times', '*', iota_path)
+
+ # Create expected output tree.
+ expected_output = svntest.wc.State(wc_dir, {
+ 'iota' : Item(verb='Sending'),
+ })
+
+ # Commit the one file.
+ svntest.actions.run_and_verify_commit(wc_dir,
+ expected_output,
+ None,
+ None,
+ iota_path)
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'propset', '--revprop', '-r1',
+ 'svn:date', '2001-01-01T00:00:00.000000Z',
+ sbox.wc_dir)
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'propset', '--revprop', '-r2',
+ 'svn:date', '2001-01-01T00:00:00.000000Z',
+ sbox.wc_dir)
+
+ # Update
+ expected_output = svntest.wc.State(checkout_target, {
+ 'iota' : Item(status=' U'),
+ })
+ expected_output.wc_dir = checkout_target
+
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.wc_dir = checkout_target
+
+ expected_status = svntest.actions.get_virginal_state(checkout_target, 1)
+ expected_status.tweak('iota', wc_rev=2)
+
+ svntest.actions.run_and_verify_update(checkout_target,
+ None,
+ None,
+ None,
+ None, None, None, None, None, 0 )
+
+ secs_svn_date = time.mktime( (2001, 1, 1, 0, 0, 0, 0, 0, 0) )
+ secs_svn_date -= time.timezone
+ new_iota = os.path.join(checkout_target, 'iota')
+ mtime = os.path.getmtime(new_iota)
+
+ # check whether the timestamp of the file is expected value
+ if secs_svn_date != mtime:
+ raise svntest.Failure
+
+ # remove 'svn:use-commit-times' property test
+ svntest.main.run_svn(None, 'propdel', 'svn:use-commit-times', iota_path)
+ svntest.actions.run_and_verify_commit(wc_dir,
+ None,
+ None,
+ None,
+ iota_path)
+ # get current time before update
+ time_before_update = time.time()
+
+ # update
+ svntest.actions.run_and_verify_update(checkout_target,
+ None,
+ None,
+ None,
+ None, None, None, None, None, 0 )
+ # get current time after update
+ time_before_after = time.time()
+
+ mtime = os.path.getmtime(new_iota)
+
+ # check whether the timestamp of the file is between 'before update' and
'after update'
+ if time_before_update > mtime or mtime > time_before_after:
+ raise svntest.Failure
+
#######################################################################
# Run the tests
@@ -6865,6 +6970,7 @@ test_list = [ None,
update_moved_away,
bump_below_tree_conflict,
update_child_below_add,
+ update_with_use_commit_times,
]
if __name__ == '__main__':