1251881Speter/*
2251881Speter * propget-cmd.c -- Print properties and values of files/dirs
3251881Speter *
4251881Speter * ====================================================================
5251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
6251881Speter *    or more contributor license agreements.  See the NOTICE file
7251881Speter *    distributed with this work for additional information
8251881Speter *    regarding copyright ownership.  The ASF licenses this file
9251881Speter *    to you under the Apache License, Version 2.0 (the
10251881Speter *    "License"); you may not use this file except in compliance
11251881Speter *    with the License.  You may obtain a copy of the License at
12251881Speter *
13251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
14251881Speter *
15251881Speter *    Unless required by applicable law or agreed to in writing,
16251881Speter *    software distributed under the License is distributed on an
17251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18251881Speter *    KIND, either express or implied.  See the License for the
19251881Speter *    specific language governing permissions and limitations
20251881Speter *    under the License.
21251881Speter * ====================================================================
22251881Speter */
23251881Speter
24251881Speter/* ==================================================================== */
25251881Speter
26251881Speter
27251881Speter
28251881Speter/*** Includes. ***/
29251881Speter
30251881Speter#include "svn_hash.h"
31251881Speter#include "svn_cmdline.h"
32251881Speter#include "svn_pools.h"
33251881Speter#include "svn_client.h"
34251881Speter#include "svn_string.h"
35251881Speter#include "svn_error_codes.h"
36251881Speter#include "svn_error.h"
37251881Speter#include "svn_utf.h"
38251881Speter#include "svn_sorts.h"
39251881Speter#include "svn_subst.h"
40251881Speter#include "svn_dirent_uri.h"
41251881Speter#include "svn_path.h"
42251881Speter#include "svn_props.h"
43251881Speter#include "svn_xml.h"
44251881Speter#include "cl.h"
45251881Speter
46251881Speter#include "private/svn_cmdline_private.h"
47289180Speter#include "private/svn_opt_private.h"
48289180Speter#include "private/svn_sorts_private.h"
49251881Speter#include "svn_private_config.h"
50251881Speter
51251881Speter
52251881Speter/*** Code. ***/
53251881Speter
54251881Speterstatic svn_error_t *
55251881Speterstream_write(svn_stream_t *out,
56251881Speter             const char *data,
57251881Speter             apr_size_t len)
58251881Speter{
59251881Speter  apr_size_t write_len = len;
60251881Speter
61251881Speter  /* We're gonna bail on an incomplete write here only because we know
62251881Speter     that this stream is really stdout, which should never be blocking
63251881Speter     on us. */
64251881Speter  SVN_ERR(svn_stream_write(out, data, &write_len));
65251881Speter  if (write_len != len)
66251881Speter    return svn_error_create(SVN_ERR_STREAM_UNEXPECTED_EOF, NULL,
67251881Speter                            _("Error writing to stream"));
68251881Speter  return SVN_NO_ERROR;
69251881Speter}
70251881Speter
71251881Speter
72251881Speterstatic svn_error_t *
73251881Speterprint_properties_xml(const char *pname,
74251881Speter                     apr_hash_t *props,
75251881Speter                     apr_array_header_t *inherited_props,
76251881Speter                     apr_pool_t *pool)
77251881Speter{
78251881Speter  apr_array_header_t *sorted_props;
79251881Speter  int i;
80251881Speter  apr_pool_t *iterpool = NULL;
81251881Speter  svn_stringbuf_t *sb;
82251881Speter
83251881Speter  if (inherited_props && inherited_props->nelts)
84251881Speter    {
85251881Speter      iterpool = svn_pool_create(pool);
86251881Speter
87251881Speter      for (i = 0; i < inherited_props->nelts; i++)
88251881Speter        {
89251881Speter          const char *name_local;
90251881Speter          svn_prop_inherited_item_t *iprop =
91251881Speter           APR_ARRAY_IDX(inherited_props, i, svn_prop_inherited_item_t *);
92289180Speter          svn_string_t *propval = apr_hash_this_val(
93251881Speter            apr_hash_first(pool, iprop->prop_hash));
94251881Speter
95251881Speter          sb = NULL;
96251881Speter          svn_pool_clear(iterpool);
97251881Speter
98251881Speter          if (svn_path_is_url(iprop->path_or_url))
99251881Speter            name_local = iprop->path_or_url;
100251881Speter          else
101251881Speter            name_local = svn_dirent_local_style(iprop->path_or_url, iterpool);
102251881Speter
103251881Speter          svn_xml_make_open_tag(&sb, iterpool, svn_xml_normal, "target",
104289180Speter                            "path", name_local, SVN_VA_NULL);
105251881Speter
106251881Speter          svn_cmdline__print_xml_prop(&sb, pname, propval, TRUE, iterpool);
107251881Speter          svn_xml_make_close_tag(&sb, iterpool, "target");
108251881Speter
109251881Speter          SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
110251881Speter        }
111251881Speter    }
112251881Speter
113251881Speter  if (iterpool == NULL)
114251881Speter    iterpool = svn_pool_create(iterpool);
115251881Speter
116251881Speter  sorted_props = svn_sort__hash(props, svn_sort_compare_items_as_paths, pool);
117251881Speter  for (i = 0; i < sorted_props->nelts; i++)
118251881Speter    {
119251881Speter      svn_sort__item_t item = APR_ARRAY_IDX(sorted_props, i, svn_sort__item_t);
120251881Speter      const char *filename = item.key;
121251881Speter      svn_string_t *propval = item.value;
122251881Speter
123251881Speter      sb = NULL;
124251881Speter      svn_pool_clear(iterpool);
125251881Speter
126251881Speter      svn_xml_make_open_tag(&sb, iterpool, svn_xml_normal, "target",
127289180Speter                        "path", filename, SVN_VA_NULL);
128251881Speter      svn_cmdline__print_xml_prop(&sb, pname, propval, FALSE, iterpool);
129251881Speter      svn_xml_make_close_tag(&sb, iterpool, "target");
130251881Speter
131251881Speter      SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
132251881Speter    }
133251881Speter
134251881Speter  if (iterpool)
135251881Speter    svn_pool_destroy(iterpool);
136251881Speter
137251881Speter  return SVN_NO_ERROR;
138251881Speter}
139251881Speter
140362181Sdim/* Print the property PNAME with the value PROPVAL set on ABSPATH_OR_URL
141251881Speter   to the stream OUT.
142251881Speter
143251881Speter   If INHERITED_PROPERTY is true then the property described is inherited,
144251881Speter   otherwise it is explicit.
145251881Speter
146251881Speter   WC_PATH_PREFIX is the absolute path of the current working directory (and
147251881Speter   is ignored if ABSPATH_OR_URL is a URL).
148251881Speter
149251881Speter   All other arguments are as per print_properties. */
150251881Speterstatic svn_error_t *
151251881Speterprint_single_prop(svn_string_t *propval,
152251881Speter                  const char *target_abspath_or_url,
153251881Speter                  const char *abspath_or_URL,
154251881Speter                  const char *wc_path_prefix,
155251881Speter                  svn_stream_t *out,
156362181Sdim                  const char *pname,
157251881Speter                  svn_boolean_t print_filenames,
158251881Speter                  svn_boolean_t omit_newline,
159251881Speter                  svn_boolean_t like_proplist,
160251881Speter                  svn_boolean_t inherited_property,
161251881Speter                  apr_pool_t *scratch_pool)
162251881Speter{
163251881Speter  if (print_filenames)
164251881Speter    {
165251881Speter      const char *header;
166251881Speter
167251881Speter      /* Print the file name. */
168251881Speter
169251881Speter      if (! svn_path_is_url(abspath_or_URL))
170251881Speter        abspath_or_URL = svn_cl__local_style_skip_ancestor(wc_path_prefix,
171251881Speter                                                           abspath_or_URL,
172251881Speter                                                           scratch_pool);
173251881Speter
174251881Speter      /* In verbose mode, print exactly same as "proplist" does;
175251881Speter       * otherwise, print a brief header. */
176251881Speter      if (inherited_property)
177251881Speter        {
178251881Speter          if (like_proplist)
179251881Speter            {
180251881Speter              if (! svn_path_is_url(target_abspath_or_url))
181251881Speter                target_abspath_or_url =
182251881Speter                  svn_cl__local_style_skip_ancestor(wc_path_prefix,
183251881Speter                                                    target_abspath_or_url,
184251881Speter                                                    scratch_pool);
185251881Speter              header = apr_psprintf(
186251881Speter                scratch_pool,
187251881Speter                _("Inherited properties on '%s',\nfrom '%s':\n"),
188251881Speter                target_abspath_or_url, abspath_or_URL);
189251881Speter            }
190251881Speter          else
191251881Speter            {
192251881Speter              header = apr_psprintf(scratch_pool, "%s - ", abspath_or_URL);
193251881Speter            }
194251881Speter        }
195251881Speter      else
196251881Speter        header = apr_psprintf(scratch_pool, like_proplist
197251881Speter                              ? _("Properties on '%s':\n")
198251881Speter                              : "%s - ", abspath_or_URL);
199251881Speter      SVN_ERR(svn_cmdline_cstring_from_utf8(&header, header, scratch_pool));
200251881Speter      SVN_ERR(svn_subst_translate_cstring2(header, &header,
201251881Speter                                           APR_EOL_STR,  /* 'native' eol */
202251881Speter                                           FALSE, /* no repair */
203251881Speter                                           NULL,  /* no keywords */
204251881Speter                                           FALSE, /* no expansion */
205251881Speter                                           scratch_pool));
206251881Speter      SVN_ERR(stream_write(out, header, strlen(header)));
207251881Speter    }
208251881Speter
209251881Speter  if (like_proplist)
210251881Speter    {
211251881Speter      /* Print the property name and value just as "proplist -v" does */
212251881Speter      apr_hash_t *hash = apr_hash_make(scratch_pool);
213251881Speter
214362181Sdim      svn_hash_sets(hash, pname, propval);
215251881Speter      SVN_ERR(svn_cmdline__print_prop_hash(out, hash, FALSE, scratch_pool));
216251881Speter    }
217251881Speter  else
218251881Speter    {
219251881Speter      /* If this is a special Subversion property, it is stored as
220251881Speter         UTF8, so convert to the native format. */
221362181Sdim      if (svn_prop_needs_translation(pname))
222251881Speter        SVN_ERR(svn_subst_detranslate_string(&propval, propval,
223251881Speter                                             TRUE, scratch_pool));
224251881Speter
225251881Speter      SVN_ERR(stream_write(out, propval->data, propval->len));
226251881Speter
227251881Speter      if (! omit_newline)
228251881Speter        SVN_ERR(stream_write(out, APR_EOL_STR,
229251881Speter                             strlen(APR_EOL_STR)));
230251881Speter    }
231251881Speter  return SVN_NO_ERROR;
232251881Speter}
233251881Speter
234251881Speter/* Print the properties in PROPS and/or *INHERITED_PROPS to the stream OUT.
235251881Speter   PROPS is a hash mapping (const char *) path to (svn_string_t) property
236251881Speter   value.  INHERITED_PROPS is a depth-first ordered array of
237251881Speter   svn_prop_inherited_item_t * structures.
238251881Speter
239251881Speter   TARGET_ABSPATH_OR_URL is the path which inherits INHERITED_PROPS.
240251881Speter
241251881Speter   PROPS may be an empty hash, but is never null.  INHERITED_PROPS may be
242251881Speter   null.
243251881Speter
244251881Speter   If IS_URL is true, all paths in PROPS are URLs, else all paths are local
245251881Speter   paths.
246251881Speter
247362181Sdim   PNAME is the property name of all the properties.
248251881Speter
249251881Speter   If PRINT_FILENAMES is true, print the item's path before each property.
250251881Speter
251251881Speter   If OMIT_NEWLINE is true, don't add a newline at the end of each property.
252251881Speter
253251881Speter   If LIKE_PROPLIST is true, print everything in a more verbose format
254251881Speter   like "svn proplist -v" does. */
255251881Speterstatic svn_error_t *
256251881Speterprint_properties(svn_stream_t *out,
257251881Speter                 const char *target_abspath_or_url,
258362181Sdim                 const char *pname,
259251881Speter                 apr_hash_t *props,
260251881Speter                 apr_array_header_t *inherited_props,
261251881Speter                 svn_boolean_t print_filenames,
262251881Speter                 svn_boolean_t omit_newline,
263251881Speter                 svn_boolean_t like_proplist,
264251881Speter                 apr_pool_t *pool)
265251881Speter{
266251881Speter  apr_array_header_t *sorted_props;
267251881Speter  int i;
268251881Speter  apr_pool_t *iterpool = svn_pool_create(pool);
269251881Speter  const char *path_prefix;
270251881Speter
271251881Speter  SVN_ERR(svn_dirent_get_absolute(&path_prefix, "", pool));
272251881Speter
273251881Speter  if (inherited_props)
274251881Speter    {
275251881Speter      svn_pool_clear(iterpool);
276251881Speter
277251881Speter      for (i = 0; i < inherited_props->nelts; i++)
278251881Speter        {
279251881Speter          svn_prop_inherited_item_t *iprop =
280251881Speter            APR_ARRAY_IDX(inherited_props, i, svn_prop_inherited_item_t *);
281289180Speter          svn_string_t *propval = apr_hash_this_val(apr_hash_first(pool,
282251881Speter                                                          iprop->prop_hash));
283251881Speter          SVN_ERR(print_single_prop(propval, target_abspath_or_url,
284251881Speter                                    iprop->path_or_url,
285362181Sdim                                    path_prefix, out, pname,
286251881Speter                                    print_filenames, omit_newline,
287251881Speter                                    like_proplist, TRUE, iterpool));
288251881Speter        }
289251881Speter    }
290251881Speter
291251881Speter  sorted_props = svn_sort__hash(props, svn_sort_compare_items_as_paths, pool);
292251881Speter  for (i = 0; i < sorted_props->nelts; i++)
293251881Speter    {
294251881Speter      svn_sort__item_t item = APR_ARRAY_IDX(sorted_props, i, svn_sort__item_t);
295251881Speter      const char *filename = item.key;
296251881Speter      svn_string_t *propval = item.value;
297251881Speter
298251881Speter      svn_pool_clear(iterpool);
299251881Speter
300251881Speter      SVN_ERR(print_single_prop(propval, target_abspath_or_url, filename,
301362181Sdim                                path_prefix, out, pname, print_filenames,
302251881Speter                                omit_newline, like_proplist, FALSE,
303251881Speter                                iterpool));
304251881Speter    }
305251881Speter
306251881Speter  svn_pool_destroy(iterpool);
307251881Speter
308251881Speter  return SVN_NO_ERROR;
309251881Speter}
310251881Speter
311251881Speter
312251881Speter/* This implements the `svn_opt_subcommand_t' interface. */
313251881Spetersvn_error_t *
314251881Spetersvn_cl__propget(apr_getopt_t *os,
315251881Speter                void *baton,
316251881Speter                apr_pool_t *pool)
317251881Speter{
318251881Speter  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
319251881Speter  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
320362181Sdim  const char *pname;
321251881Speter  apr_array_header_t *args, *targets;
322251881Speter  svn_stream_t *out;
323289180Speter  svn_boolean_t warned = FALSE;
324251881Speter
325289180Speter  if (opt_state->verbose && (opt_state->revprop || opt_state->no_newline
326251881Speter                             || opt_state->xml))
327251881Speter    return svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
328251881Speter                            _("--verbose cannot be used with --revprop or "
329289180Speter                              "--no-newline or --xml"));
330251881Speter
331362181Sdim  /* PNAME is first argument */
332251881Speter  SVN_ERR(svn_opt_parse_num_args(&args, os, 1, pool));
333251881Speter  pname = APR_ARRAY_IDX(args, 0, const char *);
334362181Sdim  SVN_ERR(svn_utf_cstring_to_utf8(&pname, pname, pool));
335362181Sdim  if (! svn_prop_name_is_valid(pname))
336251881Speter    return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
337251881Speter                             _("'%s' is not a valid Subversion property name"),
338362181Sdim                             pname);
339251881Speter
340251881Speter  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
341251881Speter                                                      opt_state->targets,
342251881Speter                                                      ctx, FALSE, pool));
343251881Speter
344251881Speter  /* Add "." if user passed 0 file arguments */
345251881Speter  svn_opt_push_implicit_dot_target(targets, pool);
346251881Speter
347251881Speter  /* Open a stream to stdout. */
348251881Speter  SVN_ERR(svn_stream_for_stdout(&out, pool));
349251881Speter
350251881Speter  if (opt_state->revprop)  /* operate on a revprop */
351251881Speter    {
352251881Speter      svn_revnum_t rev;
353251881Speter      const char *URL;
354251881Speter      svn_string_t *propval;
355251881Speter
356251881Speter      if (opt_state->show_inherited_props)
357251881Speter        return svn_error_create(
358251881Speter          SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
359251881Speter          _("--show-inherited-props can't be used with --revprop"));
360251881Speter
361251881Speter      SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets,
362251881Speter                                      &URL, ctx, pool));
363251881Speter
364251881Speter      /* Let libsvn_client do the real work. */
365362181Sdim      SVN_ERR(svn_client_revprop_get(pname, &propval,
366251881Speter                                     URL, &(opt_state->start_revision),
367251881Speter                                     &rev, ctx, pool));
368251881Speter
369289180Speter      if (propval == NULL)
370251881Speter        {
371289180Speter          return svn_error_createf(SVN_ERR_PROPERTY_NOT_FOUND, NULL,
372289180Speter                                   _("Property '%s' not found on "
373289180Speter                                     "revision %s"),
374362181Sdim                                   pname,
375289180Speter                                   svn_opt__revision_to_string(
376289180Speter                                     &opt_state->start_revision,
377289180Speter                                     pool));
378289180Speter        }
379289180Speter      else
380289180Speter        {
381251881Speter          if (opt_state->xml)
382251881Speter            {
383251881Speter              svn_stringbuf_t *sb = NULL;
384251881Speter              char *revstr = apr_psprintf(pool, "%ld", rev);
385251881Speter
386251881Speter              SVN_ERR(svn_cl__xml_print_header("properties", pool));
387251881Speter
388251881Speter              svn_xml_make_open_tag(&sb, pool, svn_xml_normal,
389251881Speter                                    "revprops",
390289180Speter                                    "rev", revstr, SVN_VA_NULL);
391251881Speter
392362181Sdim              svn_cmdline__print_xml_prop(&sb, pname, propval, FALSE,
393251881Speter                                          pool);
394251881Speter
395251881Speter              svn_xml_make_close_tag(&sb, pool, "revprops");
396251881Speter
397251881Speter              SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
398251881Speter              SVN_ERR(svn_cl__xml_print_footer("properties", pool));
399251881Speter            }
400251881Speter          else
401251881Speter            {
402251881Speter              svn_string_t *printable_val = propval;
403251881Speter
404251881Speter              /* If this is a special Subversion property, it is stored as
405251881Speter                 UTF8 and LF, so convert to the native locale and eol-style. */
406251881Speter
407362181Sdim              if (svn_prop_needs_translation(pname))
408251881Speter                SVN_ERR(svn_subst_detranslate_string(&printable_val, propval,
409251881Speter                                                     TRUE, pool));
410251881Speter
411251881Speter              SVN_ERR(stream_write(out, printable_val->data,
412251881Speter                                   printable_val->len));
413289180Speter              if (! opt_state->no_newline)
414251881Speter                SVN_ERR(stream_write(out, APR_EOL_STR, strlen(APR_EOL_STR)));
415251881Speter            }
416251881Speter        }
417251881Speter    }
418251881Speter  else  /* operate on a normal, versioned property (not a revprop) */
419251881Speter    {
420251881Speter      apr_pool_t *subpool = svn_pool_create(pool);
421251881Speter      int i;
422251881Speter
423251881Speter      if (opt_state->xml)
424251881Speter        SVN_ERR(svn_cl__xml_print_header("properties", subpool));
425251881Speter
426251881Speter      if (opt_state->depth == svn_depth_unknown)
427251881Speter        opt_state->depth = svn_depth_empty;
428251881Speter
429289180Speter      /* No-newline mode only makes sense for a single target.  So make
430251881Speter         sure we have only a single target, and that we're not being
431251881Speter         asked to recurse on that target. */
432289180Speter      if (opt_state->no_newline
433289180Speter          && ((targets->nelts > 1) || (opt_state->depth != svn_depth_empty)
434289180Speter              || (opt_state->show_inherited_props)))
435251881Speter        return svn_error_create
436251881Speter          (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
437289180Speter           _("--no-newline is only available for single-target,"
438289180Speter             " non-recursive propget operations"));
439251881Speter
440251881Speter      for (i = 0; i < targets->nelts; i++)
441251881Speter        {
442251881Speter          const char *target = APR_ARRAY_IDX(targets, i, const char *);
443251881Speter          apr_hash_t *props;
444251881Speter          svn_boolean_t print_filenames;
445251881Speter          svn_boolean_t omit_newline;
446251881Speter          svn_boolean_t like_proplist;
447251881Speter          const char *truepath;
448251881Speter          svn_opt_revision_t peg_revision;
449251881Speter          apr_array_header_t *inherited_props;
450251881Speter
451251881Speter          svn_pool_clear(subpool);
452251881Speter          SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
453251881Speter
454251881Speter          /* Check for a peg revision. */
455251881Speter          SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
456251881Speter                                     subpool));
457251881Speter
458251881Speter          if (!svn_path_is_url(truepath))
459251881Speter            SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, subpool));
460251881Speter
461251881Speter          SVN_ERR(svn_client_propget5(
462251881Speter            &props,
463251881Speter            opt_state->show_inherited_props ? &inherited_props : NULL,
464362181Sdim            pname, truepath,
465251881Speter            &peg_revision,
466251881Speter            &(opt_state->start_revision),
467251881Speter            NULL, opt_state->depth,
468251881Speter            opt_state->changelists, ctx, subpool,
469251881Speter            subpool));
470251881Speter
471251881Speter          /* Any time there is more than one thing to print, or where
472251881Speter             the path associated with a printed thing is not obvious,
473251881Speter             we'll print filenames.  That is, unless we've been told
474289180Speter             not to do so with the --no-newline option. */
475251881Speter          print_filenames = ((opt_state->depth > svn_depth_empty
476251881Speter                              || targets->nelts > 1
477251881Speter                              || apr_hash_count(props) > 1
478251881Speter                              || opt_state->verbose
479251881Speter                              || opt_state->show_inherited_props)
480289180Speter                             && (! opt_state->no_newline));
481289180Speter          omit_newline = opt_state->no_newline;
482289180Speter          like_proplist = opt_state->verbose && !opt_state->no_newline;
483251881Speter
484289180Speter          /* If there are no properties, and exactly one node was queried,
485289180Speter             then warn. */
486289180Speter          if (opt_state->depth == svn_depth_empty
487289180Speter              && !opt_state->show_inherited_props
488289180Speter              && apr_hash_count(props) == 0)
489289180Speter            {
490289180Speter              svn_error_t *err;
491289180Speter              err = svn_error_createf(SVN_ERR_PROPERTY_NOT_FOUND, NULL,
492289180Speter                                      _("Property '%s' not found on '%s'"),
493362181Sdim                                      pname, target);
494289180Speter              svn_handle_warning2(stderr, err, "svn: ");
495289180Speter              svn_error_clear(err);
496289180Speter              warned = TRUE;
497289180Speter            }
498289180Speter
499251881Speter          if (opt_state->xml)
500251881Speter            SVN_ERR(print_properties_xml(
501362181Sdim              pname, props,
502251881Speter              opt_state->show_inherited_props ? inherited_props : NULL,
503251881Speter              subpool));
504251881Speter          else
505251881Speter            SVN_ERR(print_properties(
506362181Sdim              out, truepath, pname,
507251881Speter              props,
508251881Speter              opt_state->show_inherited_props ? inherited_props : NULL,
509251881Speter              print_filenames,
510251881Speter              omit_newline, like_proplist, subpool));
511251881Speter        }
512251881Speter
513251881Speter      if (opt_state->xml)
514251881Speter        SVN_ERR(svn_cl__xml_print_footer("properties", subpool));
515251881Speter
516251881Speter      svn_pool_destroy(subpool);
517251881Speter    }
518251881Speter
519289180Speter  if (warned)
520289180Speter    return svn_error_create(SVN_ERR_BASE, NULL, NULL);
521289180Speter
522251881Speter  return SVN_NO_ERROR;
523251881Speter}
524