Thanks Julian!
As for the DTDs I think they would be useful at both place, in book and
as separate files.
Laszlo Kishalmi
Julian Foad wrote:
> It's time to submit this for review.
>
> Log message:
> [[[
> Implement an XML output option for "svn list", similar to that for "svn
> log".
>
> * doc/book/book/ch09.xml
> Document the new options for "svn list".
>
> * subversion/clients/cmdline/ls-cmd.c
> (kind_str): New helper function.
> (print_dirents_xml): New.
> (svn_cl__ls): Output XML if requested.
>
> * subversion/clients/cmdline/main.c
> (svn_cl__cmd_table):
> Add "--incremental" and "--xml" options to "list" command.
>
> * tools/client-side/bash_completion
> (_svn): Add "--incremental" and "--xml" options to "list" command.
> ]]]
>
>
> An XML DTD gives a concise description of the output format. I have
> just written this, to cover "svn log" and "svn list". Should I include
> this in the book and/or in a separate .dtd file?
>
> [[[
> <!-- XML DTD for Subversion command-line client output. -->
>
> <!-- Common attributes and elements -->
> <!-- revision number: integer -->
> <!ENTITY % revision-attr "revision CDATA #REQUIRED">
> <!ELEMENT author (#PCDATA)> <!-- user name -->
> <!ELEMENT date (#PCDATA)> <!-- date as "yyyy-mm-ddThh:mm:ss.ssssssZ" -->
>
> <!-- For "svn log" -->
> <!ELEMENT log (logentry*)>
> <!ELEMENT logentry (author, date, paths?, msg?)>
> <!ATTLIST logentry %revision-attr;>
> <!ELEMENT paths (path*)>
> <!ELEMENT path (#PCDATA)> <!-- path within repository -->
> <!ATTLIST path action CDATA #REQUIRED> <!-- action code: one character -->
> <!ELEMENT msg (#PCDATA)> <!-- log message -->
>
> <!-- For "svn list" -->
> <!ELEMENT lists (list+)>
> <!ELEMENT list (entry*)>
> <!ATTLIST list path CDATA #REQUIRED> <!-- local path or URL -->
> <!ELEMENT entry (name, size?, commit)>
> <!ATTLIST entry kind (dir | file) #REQUIRED>
> <!ELEMENT name (#PCDATA)> <!-- name of file or directory -->
> <!ELEMENT size (#PCDATA)> <!-- file size in bytes: integer -->
> <!ELEMENT commit (author, date)>
> <!ATTLIST commit %revision-attr;>
> ]]]
>
>
> - Julian
>
>
> ------------------------------------------------------------------------
>
> Implement an XML output option for "svn list", similar to that for "svn log".
>
> * doc/book/book/ch09.xml
> Document the new options for "svn list".
>
> * subversion/clients/cmdline/ls-cmd.c
> (kind_str): New helper function.
> (print_dirents_xml): New.
> (svn_cl__ls): Output XML if requested.
>
> * subversion/clients/cmdline/main.c
> (svn_cl__cmd_table):
> Add "--incremental" and "--xml" options to "list" command.
>
> * tools/client-side/bash_completion
> (_svn): Add "--incremental" and "--xml" options to "list" command.
>
> Index: tools/client-side/bash_completion
> ===================================================================
> --- tools/client-side/bash_completion (revision 12757)
> +++ tools/client-side/bash_completion (working copy)
> @@ -100,7 +100,8 @@ _svn()
> cmdOpts="--targets -R --recursive"
> ;;
> list|ls)
> - cmdOpts="$rOpts -v --verbose -R --recursive $pOpts"
> + cmdOpts="$rOpts -v --verbose -R --recursive $pOpts \
> + --incremental --xml"
> ;;
> log)
> cmdOpts="$rOpts -v --verbose --targets $pOpts --stop-on-copy \
> Index: doc/book/book/ch09.xml
> ===================================================================
> --- doc/book/book/ch09.xml (revision 12757)
> +++ doc/book/book/ch09.xml (working copy)
> @@ -1951,6 +1951,12 @@ Last Changed Date: 2003-01-16 23:21:19 -
> bytes)</para></listitem> <listitem><para>Date and time of
> the last commit</para></listitem>
> </itemizedlist>
> +
> + <para>With <option>--xml</option>, output is in XML format (with
> + a header and an enclosing document element unless
> + <option>--incremental</option> is also specified). All of the
> + information is present; the <option>--verbose</option> option
> + is not accepted.</para>
> </refsect1>
>
> <refsect1>
> @@ -1975,6 +1981,8 @@ Last Changed Date: 2003-01-16 23:21:19 -
> --revision (-r) REV
> --verbose (-v)
> --recursive (-R)
> +--incremental
> +--xml
> --username USER
> --password PASS
> --no-auth-cache
> Index: subversion/clients/cmdline/ls-cmd.c
> ===================================================================
> --- subversion/clients/cmdline/ls-cmd.c (revision 12757)
> +++ subversion/clients/cmdline/ls-cmd.c (working copy)
> @@ -28,8 +28,10 @@
> #include "svn_sorts.h"
> #include "svn_pools.h"
> #include "svn_time.h"
> +#include "svn_xml.h"
> #include "cl.h"
>
> +#include "svn_private_config.h"
>
> /*** Code. ***/
>
> @@ -114,6 +116,109 @@
> }
>
>
> +static const char *
> +kind_str (svn_node_kind_t kind)
> +{
> + switch (kind)
> + {
> + case svn_node_dir:
> + return "dir";
> + case svn_node_file:
> + return "file";
> + default:
> + return "";
> + }
> +}
> +
> +
> +static svn_error_t *
> +print_dirents_xml (apr_hash_t *dirents,
> + const char *path,
> + svn_client_ctx_t *ctx,
> + apr_pool_t *pool)
> +{
> + /* Collate whole list into sb before printing. */
> + svn_stringbuf_t *sb = svn_stringbuf_create ("", pool);
> +
> + apr_array_header_t *array;
> + int i;
> +
> + array = svn_sort__hash (dirents, svn_sort_compare_items_as_paths, pool);
> +
> + /* "<list path=...>" */
> + svn_xml_make_open_tag (&sb, pool, svn_xml_normal, "list",
> + "path", path,
> + NULL);
> +
> + for (i = 0; i < array->nelts; ++i)
> + {
> + const char *utf8_entryname;
> + svn_dirent_t *dirent;
> + svn_sort__item_t *item;
> +
> + if (ctx->cancel_func)
> + SVN_ERR (ctx->cancel_func (ctx->cancel_baton));
> +
> + item = &APR_ARRAY_IDX (array, i, svn_sort__item_t);
> +
> + utf8_entryname = item->key;
> +
> + dirent = apr_hash_get (dirents, utf8_entryname, item->klen);
> +
> + /* "<entry ...>" */
> + svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata, "entry",
> + "kind", kind_str (dirent->kind),
> + NULL);
> +
> + /* "<name>xxx</name> */
> + svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata, "name", NULL);
> + svn_xml_escape_cdata_cstring (&sb, utf8_entryname, pool);
> + svn_xml_make_close_tag (&sb, pool, "name");
> +
> + /* "<size>xxx</size>" */
> + if (dirent->kind == svn_node_file)
> + {
> + svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata, "size",
> + NULL);
> + svn_xml_escape_cdata_cstring
> + (&sb, apr_psprintf (pool, "%" SVN_FILESIZE_T_FMT, dirent->size),
> + pool);
> + svn_xml_make_close_tag (&sb, pool, "size");
> + }
> +
> + /* "<commit revision=...>" */
> + svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata, "commit",
> + "revision",
> + apr_psprintf (pool, "%" SVN_REVNUM_T_FMT,
> + dirent->created_rev),
> + NULL);
> + if (dirent->last_author)
> + {
> + /* "<author>xxx</author>" */
> + svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata, "author",
> + NULL);
> + svn_xml_escape_cdata_cstring (&sb, dirent->last_author, pool);
> + svn_xml_make_close_tag (&sb, pool, "author");
> + }
> + /* "<date>xxx</date>" */
> + svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata, "date", NULL);
> + svn_xml_escape_cdata_cstring
> + (&sb, svn_time_to_cstring (dirent->time, pool), pool);
> + svn_xml_make_close_tag (&sb, pool, "date");
> + /* "</commit>" */
> + svn_xml_make_close_tag (&sb, pool, "commit");
> +
> + /* "</entry>" */
> + svn_xml_make_close_tag (&sb, pool, "entry");
> + }
> +
> + /* "</list>" */
> + svn_xml_make_close_tag (&sb, pool, "list");
> +
> + return svn_cmdline_printf (pool, "%s", sb->data);
> +}
> +
> +
> /* This implements the `svn_opt_subcommand_t' interface. */
> svn_error_t *
> svn_cl__ls (apr_getopt_t *os,
> @@ -132,6 +237,38 @@
> /* Add "." if user passed 0 arguments */
> svn_opt_push_implicit_dot_target (targets, pool);
>
> + if (opt_state->xml)
> + {
> + /* The XML output contains all the information, so "--verbose"
> + does not apply. */
> + if (opt_state->verbose)
> + return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
> + _("'verbose' option invalid in XML mode"));
> +
> + /* If output is not incremental, output the XML header and wrap
> + everything in a top-level element. This makes the output in
> + its entirety a well-formed XML document. */
> + if (! opt_state->incremental)
> + {
> + svn_stringbuf_t *sb = svn_stringbuf_create ("", pool);
> +
> + /* <?xml version="1.0" encoding="utf-8"?> */
> + svn_xml_make_header (&sb, pool);
> +
> + /* "<lists>" */
> + svn_xml_make_open_tag (&sb, pool, svn_xml_normal, "lists", NULL);
> +
> + SVN_ERR (svn_cmdline_printf (pool, "%s", sb->data));
> + }
> + }
> + else
> + {
> + if (opt_state->incremental)
> + return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
> + _("'incremental' option only valid in XML "
> + "mode"));
> + }
> +
> /* For each target, try to list it. */
> for (i = 0; i < targets->nelts; i++)
> {
> @@ -149,9 +286,24 @@
> &(opt_state->start_revision),
> opt_state->recursive, ctx, subpool));
>
> - SVN_ERR (print_dirents (dirents, opt_state->verbose, ctx, subpool));
> + if (opt_state->xml)
> + SVN_ERR (print_dirents_xml (dirents, truepath, ctx, subpool));
> + else
> + SVN_ERR (print_dirents (dirents, opt_state->verbose, ctx, subpool));
> +
> svn_pool_clear (subpool);
> }
>
> + if (opt_state->xml)
> + {
> + if (! opt_state->incremental)
> + {
> + svn_stringbuf_t *sb = svn_stringbuf_create ("", pool);
> + /* "</lists>" */
> + svn_xml_make_close_tag (&sb, pool, "lists");
> + SVN_ERR (svn_cmdline_printf (pool, "%s", sb->data));
> + }
> + }
> +
> return SVN_NO_ERROR;
> }
> Index: subversion/clients/cmdline/main.c
> ===================================================================
> --- subversion/clients/cmdline/main.c (revision 12757)
> +++ subversion/clients/cmdline/main.c (working copy)
> @@ -369,7 +369,8 @@
> " Author of the last commit\n"
> " Size (in bytes)\n"
> " Date and time of the last commit\n"),
> - {'r', 'v', 'R', SVN_CL__AUTH_OPTIONS, svn_cl__config_dir_opt} },
> + {'r', 'v', 'R', svn_cl__incremental_opt, svn_cl__xml_opt,
> + SVN_CL__AUTH_OPTIONS, svn_cl__config_dir_opt} },
>
> { "log", svn_cl__log, {0},
> N_("Show the log messages for a set of revision(s) and/or file(s).\n"
>
>
> ------------------------------------------------------------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
> For additional commands, e-mail: dev-help@subversion.tigris.org
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue Jan 18 10:40:32 2005