Index: subversion/include/svn_client.h
===================================================================
--- subversion/include/svn_client.h (revision 15448)
+++ subversion/include/svn_client.h (working copy)
@@ -1799,7 +1799,7 @@
/**
- * Set @a *dirents to a newly allocated hash of entries for @a
+ * Set @a *dirents and *locks to a newly allocated hash of entries for @a
* path_or_url at @a revision. The actual node revision selected is
* determined by the path as it exists in @a peg_revision. If @a
* peg_revision is @c svn_opt_revision_unspecified, then it defaults
@@ -1810,18 +1810,36 @@
* @a path_or_url is a file, return only the dirent for the file. If @a
* path_or_url is non-existent, return @c SVN_ERR_FS_NOT_FOUND.
*
- * The hash maps entry names (const char *) to @c svn_dirent_t *'s.
- * Do all allocation in @a pool.
+ * The dirents hash maps entry names (const char *) to
+ * @c svn_dirent_t *'s. Do all allocation in @a pool.
*
+ * The locks hash maps entry names (const char *) to
+ * @c svn_lock_t *'s. Do all allocation in @a pool.
+ *
* Use authentication baton cached in @a ctx to authenticate against the
* repository.
*
* If @a recurse is true (and @a path_or_url is a directory) this will
* be a recursive operation.
*
- * @since New in 1.2.
+ * @since New in 1.3.
*/
svn_error_t *
+svn_client_ls3 (apr_hash_t **dirents,
+ apr_hash_t **locks,
+ const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_boolean_t recurse,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool);
+
+/**
+ * Similar to svn_client_ls3(), return only dirent's in the form hash.
+ *
+ * @deprecated Provided for backward compatibility with the 1.2 API.
+ */
+svn_error_t *
svn_client_ls2 (apr_hash_t **dirents,
const char *path_or_url,
const svn_opt_revision_t *peg_revision,
Index: subversion/libsvn_client/ls.c
===================================================================
--- subversion/libsvn_client/ls.c (revision 15448)
+++ subversion/libsvn_client/ls.c (working copy)
@@ -71,6 +71,79 @@
}
svn_error_t *
+svn_client_ls3 (apr_hash_t **dirents,
+ apr_hash_t **locks,
+ const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_boolean_t recurse,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ svn_ra_session_t *ra_session;
+ const char *url;
+ const char *repos_root;
+ svn_revnum_t rev;
+ apr_hash_index_t *hi;
+ const char *rel_path;
+ svn_node_kind_t kind;
+ apr_hash_t *new_locks;
+ apr_pool_t *subpool;
+
+ SVN_ERR (svn_client_ls2 (dirents, path_or_url, peg_revision,
+ revision, recurse, ctx, pool));
+
+ if (locks == NULL)
+ return SVN_NO_ERROR;
+
+ /* Getting repository root. */
+ SVN_ERR (svn_client_url_from_path (&repos_root, "", pool));
+
+ /* 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));
+
+ rel_path = svn_path_is_child (repos_root, url, pool);
+ if (rel_path == NULL)
+ rel_path = "/";
+ else
+ {
+ svn_ra_check_path (ra_session, "", rev, &kind, pool);
+ if (kind == svn_node_file)
+ svn_path_split (rel_path, &rel_path, NULL, pool);
+
+ rel_path = apr_psprintf (pool, "/%s/", rel_path);
+ }
+
+ /* Get lock. */
+ apr_pool_create (&subpool, pool);
+ SVN_ERR (svn_ra_get_locks (ra_session, locks, "",
+ subpool));
+
+ new_locks = apr_hash_make (pool);
+ for (hi = apr_hash_first (subpool, *locks);
+ hi;
+ hi = apr_hash_next (hi))
+ {
+ const void *key;
+ void *val;
+
+ apr_hash_this (hi, &key, NULL, &val);
+ apr_hash_set (new_locks, svn_path_is_child (
+ svn_path_canonicalize (rel_path, pool),
+ svn_path_canonicalize (key, pool), pool),
+ APR_HASH_KEY_STRING, val);
+ }
+ apr_pool_destroy (subpool);
+
+ *locks = new_locks;
+
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
svn_client_ls2 (apr_hash_t **dirents,
const char *path_or_url,
const svn_opt_revision_t *peg_revision,
Index: subversion/clients/cmdline/ls-cmd.c
===================================================================
--- subversion/clients/cmdline/ls-cmd.c (revision 15448)
+++ subversion/clients/cmdline/ls-cmd.c (working copy)
@@ -37,6 +37,7 @@
static svn_error_t *
print_dirents (apr_hash_t *dirents,
+ apr_hash_t *locks,
svn_boolean_t verbose,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
@@ -51,6 +52,7 @@
{
const char *utf8_entryname;
svn_dirent_t *dirent;
+ svn_lock_t *lock;
svn_sort__item_t *item;
svn_pool_clear (subpool);
@@ -63,6 +65,7 @@
utf8_entryname = item->key;
dirent = apr_hash_get (dirents, utf8_entryname, item->klen);
+ lock = apr_hash_get (locks, utf8_entryname, APR_HASH_KEY_STRING);
if (verbose)
{
@@ -70,8 +73,8 @@
apr_time_exp_t exp_time;
apr_status_t apr_err;
apr_size_t size;
- char timestr[20];
- const char *sizestr, *utf8_timestr;
+ char timestr[20], lock_timestr[20];
+ const char *sizestr, *utf8_timestr, *utf8_lock_timestr;
/* svn_time_to_human_cstring gives us something *way* too long
to use for this, so we have to roll our own. We include
@@ -98,13 +101,42 @@
sizestr = apr_psprintf (subpool, "%" SVN_FILESIZE_T_FMT,
dirent->size);
+ if (lock)
+ {
+ apr_time_exp_lt (&exp_time, lock->creation_date);
+ if (apr_time_sec
+ (now - lock->creation_date) < (365 * 86400 / 2)
+ && apr_time_sec
+ (lock->creation_date - now) < (365 * 86400 / 2))
+ {
+ apr_err = apr_strftime (lock_timestr, &size,
+ sizeof (lock_timestr),
+ "%b %d %H:%M", &exp_time);
+ }
+ else
+ {
+ apr_err = apr_strftime (lock_timestr, &size,
+ sizeof (timestr),
+ "%b %d %Y", &exp_time);
+ }
+ /* if that failed, just zero out the string and print nothing */
+ if (apr_err)
+ lock_timestr[0] = '\0';
+
+ /* we need it in UTF-8. */
+ SVN_ERR (svn_utf_cstring_to_utf8
+ (&utf8_lock_timestr, lock_timestr, subpool));
+ }
+
SVN_ERR (svn_cmdline_printf
- (subpool, "%7ld %-8.8s %10s %12s %s%s\n",
+ (subpool, "%7ld %-12s %10s %12s %-12s %12s %s%s\n",
dirent->created_rev,
dirent->last_author ? dirent->last_author : " ? ",
(dirent->kind == svn_node_file) ? sizestr : "",
utf8_timestr,
+ lock ? lock->owner : "",
+ lock ? utf8_lock_timestr : "",
utf8_entryname,
(dirent->kind == svn_node_dir) ? "/" : ""));
}
@@ -154,6 +186,7 @@
static svn_error_t *
print_dirents_xml (apr_hash_t *dirents,
+ apr_hash_t *locks,
const char *path,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
@@ -179,6 +212,7 @@
const char *utf8_entryname;
svn_dirent_t *dirent;
svn_sort__item_t *item;
+ svn_lock_t *lock;
svn_pool_clear (subpool);
@@ -190,6 +224,7 @@
utf8_entryname = item->key;
dirent = apr_hash_get (dirents, utf8_entryname, item->klen);
+ lock = apr_hash_get (locks, utf8_entryname, APR_HASH_KEY_STRING);
sb = svn_stringbuf_create ("", subpool);
@@ -238,6 +273,49 @@
/* "" */
svn_xml_make_close_tag (&sb, subpool, "commit");
+ /* "" */
+ if (lock)
+ {
+ svn_xml_make_open_tag (&sb, pool, svn_xml_normal, "lock", NULL);
+
+ svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+ "token", NULL);
+ svn_xml_escape_cdata_cstring (&sb, lock->token, pool);
+ svn_xml_make_close_tag (&sb, pool, "token");
+
+ svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+ "owner", NULL);
+ svn_xml_escape_cdata_cstring (&sb, lock->owner, pool);
+ svn_xml_make_close_tag (&sb, pool, "owner");
+
+ if (lock->comment)
+ {
+ svn_xml_make_open_tag (&sb, pool, svn_xml_normal,
+ "comment", NULL);
+ svn_xml_escape_cdata_cstring (&sb, lock->comment, pool);
+ svn_xml_make_close_tag (&sb, pool, "comment");
+ }
+
+ svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+ "created", NULL);
+ svn_xml_escape_cdata_cstring (&sb, svn_time_to_cstring
+ (lock->creation_date, pool),
+ pool);
+ svn_xml_make_close_tag (&sb, pool, "created");
+
+ if (lock->expiration_date != 0)
+ {
+ svn_xml_make_open_tag (&sb, pool, svn_xml_protect_pcdata,
+ "expires", NULL);
+ svn_xml_escape_cdata_cstring (&sb, svn_time_to_cstring
+ (lock->expiration_date, pool),
+ pool);
+ svn_xml_make_close_tag (&sb, pool, "expires");
+ }
+
+ /* "" */
+ svn_xml_make_close_tag (&sb, subpool, "lock");
+ }
/* "" */
svn_xml_make_close_tag (&sb, subpool, "entry");
@@ -311,6 +389,7 @@
for (i = 0; i < targets->nelts; i++)
{
apr_hash_t *dirents;
+ apr_hash_t *locks;
const char *target = ((const char **) (targets->elts))[i];
const char *truepath;
svn_opt_revision_t peg_revision;
@@ -322,14 +401,15 @@
/* Get peg revisions. */
SVN_ERR (svn_opt_parse_path (&peg_revision, &truepath, target,
subpool));
- SVN_ERR (svn_client_ls2 (&dirents, truepath, &peg_revision,
+
+ SVN_ERR (svn_client_ls3 (&dirents, &locks, truepath, &peg_revision,
&(opt_state->start_revision),
opt_state->recursive, ctx, subpool));
if (opt_state->xml)
- SVN_ERR (print_dirents_xml (dirents, truepath, ctx, subpool));
+ SVN_ERR (print_dirents_xml (dirents, locks, truepath, ctx, subpool));
else
- SVN_ERR (print_dirents (dirents, opt_state->verbose, ctx, subpool));
+ SVN_ERR (print_dirents (dirents, locks, opt_state->verbose, ctx, subpool));
}
svn_pool_destroy (subpool);
Index: subversion/clients/cmdline/main.c
===================================================================
--- subversion/clients/cmdline/main.c (revision 15448)
+++ subversion/clients/cmdline/main.c (working copy)
@@ -389,12 +389,14 @@
"current\n"
" working directory.\n"
"\n"
- " With --verbose, the following fields show the status of the item:\n"
+ " With --verbose, the following fields will be shown for each item:\n"
"\n"
" Revision number of the last commit\n"
" Author of the last commit\n"
" Size (in bytes)\n"
- " Date and time of the last commit\n"),
+ " Date and time of the last commit\n"
+ " Date and time of the lock creation\n"
+ " Owner of the lock\n"),
{'r', 'v', 'R', svn_cl__incremental_opt, svn_cl__xml_opt,
SVN_CL__AUTH_OPTIONS, svn_cl__config_dir_opt} },
Index: subversion/clients/cmdline/dtd/list.dtd
===================================================================
--- subversion/clients/cmdline/dtd/list.dtd (revision 15448)
+++ subversion/clients/cmdline/dtd/list.dtd (working copy)
@@ -8,9 +8,16 @@
-
+
+
+
+
+
+
+
+