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

Re: [PATCH] Add an info command to svnsync

From: Ben Collins-Sussman <sussman_at_red-bean.com>
Date: Sat, 3 Jan 2009 09:25:18 -0600

To play devil's advocate, why is 'svn proplist -v --revprop -r0 URL'
more convenient than 'svnsync info URL'? Just fewer flags to type?

I have two worries about this:

  * Historically, we've tried to keep the number of subcommands small.
 It takes a *really* strong argument to add a new subcommand.

  * This begins a precedent of 'hiding the implementation details' of
svnsync, and I'm not sure we want that. It's never been our goal to
hide the fact that svnsync tracks work via r0 revprops. In fact, I'd
argue that we *want* users to know how svnsync works, so that they can
modify revprops when necessary (e.g. fixing a stuck sync by removing
an orphaned svn:sync-lock property.)

On Fri, Jan 2, 2009 at 3:17 AM, Chris Foote <cafoote_at_yahoo.com> wrote:
> The following patch adds an 'info' subcommand to svnsync that prints out the
> syncronisation information of a repo. This is more convient than using an
> svn proplist command.
>
> Regards
> Chris
>
> -----------------------
> [LOG]
> Add an info subcommand to svnsync to print the syncronization information and
> also add two tests for it.
>
> * subversion/svnsync/main.c
> (svnsync_cmd_table): Add the info subcommand.
> (info_cmd): New. Add the info subcommand handler.
>
> * subversion/tests/cmdline/svnsync_tests.py
> (run_info): New. Run the svnsync info subcommand.
> (info_syncronized): New. Test the info subcommand on a syncronized repo.
> (info_not_syncronized): New. Test the info subcommand on an un-syncronized
> repo.
> (test_list): Add the info_syncronized and info_not_syncronized tests.
>
> -----------------------
>
> Index: subversion/svnsync/main.c
> ===================================================================
> --- subversion/svnsync/main.c (revision 35003)
> +++ subversion/svnsync/main.c (working copy)
> @@ -35,6 +35,7 @@
> static svn_opt_subcommand_t initialize_cmd,
> synchronize_cmd,
> copy_revprops_cmd,
> + info_cmd,
> help_cmd;
>
> enum {
> @@ -105,6 +106,11 @@
> "to the destination. You may use \"HEAD\" for either revision to\n"
> "mean \"the last revision transferred\".\n"),
> { SVNSYNC_OPTS_DEFAULT } },
> + { "info", info_cmd, { 0 },
> + N_("usage: svnsync info URL\n"
> + "\n"
> + "Print syncronization information about the repository at URL.\n"),
> + { SVNSYNC_OPTS_DEFAULT } },
> { "help", help_cmd, { "?", "h" },
> N_("usage: svnsync help [SUBCOMMAND...]\n"
> "\n"
> @@ -1796,6 +1802,71 @@
>
>
>
> +/*** `svnsync info' ***/
> +
> +
> +/* SUBCOMMAND: info */
> +static svn_error_t *
> +info_cmd(apr_getopt_t *os, void *b, apr_pool_t * pool)
> +{
> + svn_ra_session_t *to_session;
> + opt_baton_t *opt_baton = b;
> + apr_array_header_t *targets;
> + subcommand_baton_t *baton;
> + const char *to_url;
> + svn_string_t *from_url;
> + svn_string_t *from_uuid;
> + svn_string_t *last_merged_rev;
> +
> + SVN_ERR(svn_opt__args_to_target_array(&targets, os,
> + apr_array_make(pool, 0,
> + sizeof(const char *)),
> + pool));
> + if (targets->nelts < 1)
> + return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
> + if (targets->nelts > 1)
> + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL);
> +
> + to_url = APR_ARRAY_IDX(targets, 0, const char *);
> +
> + if (! svn_path_is_url(to_url))
> + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
> + _("Path '%s' is not a URL"), to_url);
> +
> + baton = make_subcommand_baton(opt_baton, to_url, NULL, 0, 0, pool);
> + SVN_ERR(svn_ra_open3(&to_session, baton->to_url, NULL,
> + &(baton->sync_callbacks), baton, baton->config, pool));
> + SVN_ERR(check_if_session_is_at_repos_root(to_session, baton->to_url, pool));
> +
> + /* First, check that the repos has been initialized for syncronization. */
> +
> + SVN_ERR(svn_ra_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_URL,
> + &from_url, pool));
> + if (!from_url)
> + return svn_error_createf(SVN_ERR_BAD_URL, NULL,
> + _("the repository at '%s' is not syncronized."),
> + to_url);
> +
> + SVN_ERR(svn_ra_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_UUID,
> + &from_uuid, pool));
> + SVN_ERR(svn_ra_rev_prop(to_session, 0, SVNSYNC_PROP_LAST_MERGED_REV,
> + &last_merged_rev, pool));
> +
> + SVN_ERR(svn_cmdline_printf(pool, _("From URL: %s\n"), from_url->data));
> +
> + if (from_uuid)
> + SVN_ERR(svn_cmdline_printf(pool, _("From UUID: %s\n"),
> + from_uuid->data));
> +
> + if (last_merged_rev)
> + SVN_ERR(svn_cmdline_printf(pool, _("Last Merged Revision: %s\n"),
> + last_merged_rev->data));
> +
> + return SVN_NO_ERROR;
> +}
> +
> +
> +
> /*** `svnsync help' ***/
>
>
> Index: subversion/tests/cmdline/svnsync_tests.py
> ===================================================================
> --- subversion/tests/cmdline/svnsync_tests.py (revision 35003)
> +++ subversion/tests/cmdline/svnsync_tests.py (working copy)
> @@ -99,7 +99,29 @@
> if output != ['Copied properties for revision 0.\n']:
> raise SVNUnexpectedStdout(output)
>
> +def run_info(url, expected_error=None):
> + "Print synchronization information of the repository"
> + exit_code, output, errput = svntest.main.run_svnsync(
> + "info", url,
> + "--username", svntest.main.wc_author,
> + "--password", svntest.main.wc_passwd)
> + if errput:
> + if expected_error is None:
> + raise SVNUnexpectedStderr(errput)
> + else:
> + expected_error = svntest.verify.RegexOutput(expected_error,
> + match_all=False)
> + svntest.verify.compare_and_display_lines(None, "STDERR",
> + expected_error, errput)
> + elif expected_error is not None:
> + raise SVNExpectedStderr
> + if not output and not expected_error:
> + # should be: ['From URL: http://....\n',
> + # 'From UUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n',
> + # 'Last Merged Revision: XXX\n']
> + raise SVNUnexpectedStdout("Missing stdout")
>
> +
> def run_test(sbox, dump_file_name, subdir = None, exp_dump_file_name = None):
> """Load a dump file, sync repositories, and compare contents with the
> original
> or another dump file."""
> @@ -680,6 +702,47 @@
> "test move parent and modify child file in same rev"
> run_test(sbox, "svnsync-move-and-modify.dump")
>
> +def info_syncronized(sbox):
> + "test info cmd on a syncronized repo"
> +
> + sbox.build("svnsync-info-syncd", False)
> +
> + # Get the UUID of the source repository.
> + exit_code, output, errput = svntest.main.run_svnlook("uuid", sbox.repo_dir)
> + src_uuid = output[0].strip()
> +
> + dest_sbox = sbox.clone_dependent()
> + build_repos(dest_sbox)
> +
> + svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)
> + run_init(dest_sbox.repo_url, sbox.repo_url)
> + run_sync(dest_sbox.repo_url)
> +
> + exit_code, output, errput = svntest.main.run_svnsync(
> + "info", dest_sbox.repo_url,
> + "--username", svntest.main.wc_author,
> + "--password", svntest.main.wc_passwd)
> + if errput:
> + raise SVNUnexpectedStderr(errput)
> +
> + expected_out = ['From URL: %s\n' % sbox.repo_url,
> + 'From UUID: %s\n' % src_uuid,
> + 'Last Merged Revision: 1\n',
> + ]
> +
> + svntest.verify.compare_and_display_lines(None,
> + 'INFO',
> + expected_out,
> + output)
> +
> +def info_not_syncronized(sbox):
> + "test info cmd on an un-syncronized repo"
> +
> + sbox.build("svnsync-info-not-syncd", False)
> +
> + run_info(sbox.repo_url,
> + ".*the repository at '%s' is not syncronized.*" % sbox.repo_url)
> +
> ########################################################################
> # Run the tests
>
> @@ -713,6 +776,8 @@
> SkipUnless(only_trunk_A_with_changes,
> server_has_partial_replay),
> move_and_modify_in_the_same_revision,
> + info_syncronized,
> + info_not_syncronized,
> ]
>
> if __name__ == '__main__':
>
> ------------------------------------------------------
> http://subversion.tigris.org/ds/viewMessage.do?dsForumId=462&dsMessageId=999467
>

------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=462&dsMessageId=1000710
Received on 2009-01-03 16:25:40 CET

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.