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

Re: [Patch] Issue #2291 - 'svn ls -v' should return locking information - V5

From: Ben Collins-Sussman <sussman_at_collab.net>
Date: 2005-07-26 00:40:10 CEST

On Jul 25, 2005, at 4:14 PM, Alexander Thomas wrote:

>
> Fix issue #2291: 'svn ls -v' should return locking information.
>
> * subversion/include/svn_types.h
> (svn_dirent2_t): New struct.
> (svn_dirent_t): Deprecated and moved to group it with new struct.
>
> * subversion/libsvn_client/ls.c
> (svn_client_ls2): Gets lock information.
>
> * subversion/clients/cmdline/ls-cmd.c
> (print_dirents): Print lock information.
> (print_dirents_xml): Print lock information in xml.
>
> * subversion/clients/cmdline/main.c
> Mention locking information in the help text for 'svn ls'.
>
> * subversion/clients/cmdline/dtd/list.dtd
> Updated DTD file.
>

Log message looks good. I wouldn't exactly call this a "fix",
though. It's an enhancement, not a bug. :-)

> Index: subversion/include/svn_types.h
> ===================================================================
> --- subversion/include/svn_types.h (revision 15421)
> +++ subversion/include/svn_types.h (working copy)
> @@ -188,31 +188,6 @@
> svn_recursive
> };
>
> -
> -/** A general subversion directory entry. */
> -typedef struct svn_dirent_t
> -{
> - /** node kind */
> - svn_node_kind_t kind;
> -
> - /** length of file text, or 0 for directories */
> - svn_filesize_t size;
> -
> - /** does the node have props? */
> - svn_boolean_t has_props;
> -
> - /** last rev in which this node changed */
> - svn_revnum_t created_rev;
> -
> - /** time of created_rev (mod-time) */
> - apr_time_t time;
> -
> - /** author of created_rev */
> - const char *last_author;
> -
> -} svn_dirent_t;
> -
> -
>
>
> /** Keyword substitution.
> @@ -458,6 +433,67 @@
> svn_lock_t *
> svn_lock_dup (const svn_lock_t *lock, apr_pool_t *pool);
>
> +
> +/**
> + * A general subversion directory entry with lock information.
> + *
> + * @since New in 1.3.
> + */
> +typedef struct svn_dirent2_t
> +{
> + /** node kind */
> + svn_node_kind_t kind;
> +
> + /** length of file text, or 0 for directories */
> + svn_filesize_t size;
> +
> + /** does the node have props? */
> + svn_boolean_t has_props;
> +
> + /** last rev in which this node changed */
> + svn_revnum_t created_rev;
> +
> + /** time of created_rev (mod-time) */
> + apr_time_t time;
> +
> + /** author of created_rev */
> + const char *last_author;
> +
> + /** repository lock details, if present or NULL */
>

I might word this differently, perhaps something like "if not NULL,
the details of existing repository lock".

> + svn_lock_t *lock;
> +
> +} svn_dirent2_t;
> +
> +
> +/**
> + * Similar to @c svn_dirent2_t except that @svn_dirent_t give only
> + * subversion directory entry.
>

I can see that you imagine

    svn_dirent2_t == svn_dirent_t + svn_lock_t

and therefore

    svn_dirent2_t - svn_lock_t = svn_dirent_t

...but most people reading the code will have no idea about these
formulas and categorizations. It's not obvious that if you subtract
"only a directory entry" from a dirent2_t that a lock_t is left
behind: people think of the lock_t as part of the dirent, not some
extra thing.

So the simpler wording is just:

   "Like a @c svn_dirent2_t, but without the @c svn_lock_t field."

> + *
> + * @deprecated Provided for backward compatibility with the 1.2 API.
> + */
> +typedef struct svn_dirent_t
> +{
> + /** node kind */
> + svn_node_kind_t kind;
> +
> + /** length of file text, or 0 for directories */
> + svn_filesize_t size;
> +
> + /** does the node have props? */
> + svn_boolean_t has_props;
> +
> + /** last rev in which this node changed */
> + svn_revnum_t created_rev;
> +
> + /** time of created_rev (mod-time) */
> + apr_time_t time;
> +
> + /** author of created_rev */
> + const char *last_author;
> +
> +} svn_dirent_t;
> +
> +
> #ifdef __cplusplus
> }
> #endif /* __cplusplus */
> Index: subversion/libsvn_client/ls.c
> ===================================================================
> --- subversion/libsvn_client/ls.c (revision 15421)
> +++ subversion/libsvn_client/ls.c (working copy)
> @@ -75,7 +75,7 @@
> const char *path_or_url,
> const svn_opt_revision_t *peg_revision,
> const svn_opt_revision_t *revision,
> - svn_boolean_t recurse,
> + svn_boolean_t recurse,
>

Spurious whitespace change here?

> svn_client_ctx_t *ctx,
> apr_pool_t *pool)
> {
> @@ -83,14 +83,18 @@
> svn_revnum_t rev;
> svn_node_kind_t url_kind;
> const char *url;
> + apr_hash_t *locks;
> + apr_hash_index_t *hi;
> + apr_hash_index_t *hl;
>

Can you use variables here whose names are less similar? I actually
had to squint for a minute, before realizing that the two hash
indices had different names! Or, better yet, maybe the variables
names could be more descriptive.

>
> +
> /* Get an RA plugin for this filesystem object. */
> SVN_ERR (svn_client__ra_session_from_path (&ra_session, &rev,
> &url, path_or_url,
> peg_revision,
> revision, ctx, pool));
>
> /* Decide if the URL is a file or directory. */
> - SVN_ERR (svn_ra_check_path (ra_session, "", rev, &url_kind, pool));
> + svn_ra_check_path (ra_session, "", rev, &url_kind, pool);
>
>

Why are you deliberately ignoring the error here?

>
> if (url_kind == svn_node_dir)
> {
> @@ -135,6 +139,48 @@
> _("URL '%s' non-existent in that
> revision"),
> url);
>
> + /* Get Lock entries in to the hash. */
> + svn_ra_get_locks (ra_session, &locks, "", pool);
> +
> + for (hi = apr_hash_first (pool, *dirents); hi; hi =
> apr_hash_next (hi))
> + {
> + const void *key;
> + void *val;
> + const char *bname;
> + svn_dirent_t *entry;
> + svn_dirent2_t *newent;
> +
> + apr_hash_this (hi, &key, NULL, &val);
> + bname = key;
> + entry = val;
> +
> + newent = apr_pcalloc (pool, sizeof(*newent));
> + memcpy (newent, entry, sizeof (*entry));
> +
> + /* Traverse through locks hash. */
> + for (hl = apr_hash_first (pool, locks); hl; hl =
> apr_hash_next (hl))
> + {
> + const void *kkey;
> + void *vval;
> + const char *lockon;
> +
> + apr_hash_this (hl, &kkey, NULL, &vval);
> + lockon = kkey;
> +
> + if (strlen (bname) >= strlen(lockon))
> + continue;
> +
> + if (strcasecmp (&lockon[strlen(lockon)-strlen(bname)],
> bname) == 0)
> + {
> + newent->lock = vval;
> + break;
> + }
> +
> + }
>

Yikes! This is a hash! Instead of looping through the hash keys,
perhaps you should be looking up things using apr_hash_get() instead??

(By the way, strcasecmp is incorrect anyway... you're comparing
repository paths with repository paths, and repository paths are
always case-sensitive.)

So let me step back a second, and suggest we take a slightly
different route here. kfogel, lundblad and I had a conversation, and
we think that this patch puts us in a bad "halfway" place. This
patch deprecates svn_dirent_t, but not fully. It's still being used
in other places. We think that we should either do it all the way,
or not do it.

Option 1: *Fully* deprecate svn_dirent_t. That means stop using it
everywhere. It means having to rev all the public libsvn_client and
libsvn_ra APIs that make use of it. Quite a lot of work.

Option 2: Just don't bother to create svn_dirent2_t. Instead, just
rev svn_client_ls() could return a new "svn_client_dirent_t"
structure which contains the lock_t. (Or return the hash of locks to
the caller.)

We need to discuss these options, because there are problems with both.

Alexander: many apologies for bouncing the strategy of your patch
back and forth. You are a man of infinite patience. :-) Let's
discuss a bit more before you write another iteration of this patch.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue Jul 26 00:41:09 2005

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