1289177Speter/*
2289177Speter * list-cmd.c -- list a URL
3289177Speter *
4289177Speter * ====================================================================
5289177Speter *    Licensed to the Apache Software Foundation (ASF) under one
6289177Speter *    or more contributor license agreements.  See the NOTICE file
7289177Speter *    distributed with this work for additional information
8289177Speter *    regarding copyright ownership.  The ASF licenses this file
9289177Speter *    to you under the Apache License, Version 2.0 (the
10289177Speter *    "License"); you may not use this file except in compliance
11289177Speter *    with the License.  You may obtain a copy of the License at
12289177Speter *
13289177Speter *      http://www.apache.org/licenses/LICENSE-2.0
14289177Speter *
15289177Speter *    Unless required by applicable law or agreed to in writing,
16289177Speter *    software distributed under the License is distributed on an
17289177Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18289177Speter *    KIND, either express or implied.  See the License for the
19289177Speter *    specific language governing permissions and limitations
20289177Speter *    under the License.
21289177Speter * ====================================================================
22289177Speter */
23289177Speter
24289177Speter#include "svn_cmdline.h"
25289177Speter#include "svn_client.h"
26289177Speter#include "svn_error.h"
27289177Speter#include "svn_pools.h"
28289177Speter#include "svn_time.h"
29289177Speter#include "svn_xml.h"
30289177Speter#include "svn_dirent_uri.h"
31289177Speter#include "svn_path.h"
32289177Speter#include "svn_utf.h"
33289177Speter#include "svn_opt.h"
34289177Speter
35289177Speter#include "cl.h"
36289177Speter
37289177Speter#include "svn_private_config.h"
38289177Speter#include "private/svn_string_private.h"
39289177Speter
40289177Speter
41289177Speter
42289177Speter/* Baton used when printing directory entries. */
43289177Speterstruct print_baton {
44289177Speter  svn_boolean_t verbose;
45289177Speter  apr_int64_t directories;
46289177Speter  apr_int64_t files;
47289177Speter  apr_int64_t locks;
48289177Speter  svn_client_ctx_t *ctx;
49289177Speter};
50289177Speter
51289177Speter/* This implements the svn_client_list_func2_t API, printing a single
52289177Speter   directory entry in text format. */
53289177Speterstatic svn_error_t *
54289177Speterprint_dirent(void *baton,
55289177Speter             const char *path,
56289177Speter             const svn_dirent_t *dirent,
57289177Speter             const svn_lock_t *lock,
58289177Speter             const char *abs_path,
59289177Speter             const char *external_parent_url,
60289177Speter             const char *external_target,
61289177Speter             apr_pool_t *pool)
62289177Speter{
63289177Speter  struct print_baton *pb = baton;
64289177Speter
65289177Speter  if (pb->ctx->cancel_func)
66289177Speter    SVN_ERR(pb->ctx->cancel_func(pb->ctx->cancel_baton));
67289177Speter
68289177Speter  if (dirent->kind == svn_node_dir)
69289177Speter    pb->directories++;
70289177Speter  if (dirent->kind == svn_node_file)
71289177Speter    pb->files++;
72289177Speter  if (lock)
73289177Speter    pb->locks++;
74289177Speter
75289177Speter  return SVN_NO_ERROR;
76289177Speter}
77289177Speter
78289177Speter
79289177Speter/* This implements the `svn_opt_subcommand_t' interface. */
80289177Spetersvn_error_t *
81289177Spetersvn_cl__null_list(apr_getopt_t *os,
82289177Speter                  void *baton,
83289177Speter                  apr_pool_t *pool)
84289177Speter{
85289177Speter  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
86289177Speter  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
87289177Speter  apr_array_header_t *targets;
88289177Speter  int i;
89289177Speter  apr_pool_t *subpool = svn_pool_create(pool);
90289177Speter  apr_uint32_t dirent_fields;
91289177Speter  struct print_baton pb = { FALSE };
92289177Speter  svn_boolean_t seen_nonexistent_target = FALSE;
93289177Speter  svn_error_t *err;
94289177Speter
95289177Speter  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
96289177Speter                                                      opt_state->targets,
97289177Speter                                                      ctx, FALSE, pool));
98289177Speter
99289177Speter  /* Add "." if user passed 0 arguments */
100289177Speter  svn_opt_push_implicit_dot_target(targets, pool);
101289177Speter
102289177Speter  if (opt_state->verbose)
103289177Speter    dirent_fields = SVN_DIRENT_ALL;
104289177Speter  else
105289177Speter    dirent_fields = SVN_DIRENT_KIND; /* the only thing we actually need... */
106289177Speter
107289177Speter  pb.ctx = ctx;
108289177Speter  pb.verbose = opt_state->verbose;
109289177Speter
110289177Speter  if (opt_state->depth == svn_depth_unknown)
111289177Speter    opt_state->depth = svn_depth_immediates;
112289177Speter
113289177Speter  /* For each target, try to list it. */
114289177Speter  for (i = 0; i < targets->nelts; i++)
115289177Speter    {
116289177Speter      const char *target = APR_ARRAY_IDX(targets, i, const char *);
117289177Speter      const char *truepath;
118289177Speter      svn_opt_revision_t peg_revision;
119289177Speter
120289177Speter      svn_pool_clear(subpool);
121289177Speter
122289177Speter      SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
123289177Speter
124289177Speter      /* Get peg revisions. */
125289177Speter      SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
126289177Speter                                 subpool));
127289177Speter
128289177Speter      err = svn_client_list3(truepath, &peg_revision,
129289177Speter                             &(opt_state->start_revision),
130289177Speter                             opt_state->depth,
131289177Speter                             dirent_fields,
132289177Speter                             opt_state->verbose,
133289177Speter                             FALSE, /* include externals */
134289177Speter                             print_dirent,
135289177Speter                             &pb, ctx, subpool);
136289177Speter
137289177Speter      if (err)
138289177Speter        {
139289177Speter          /* If one of the targets is a non-existent URL or wc-entry,
140289177Speter             don't bail out.  Just warn and move on to the next target. */
141289177Speter          if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND ||
142289177Speter              err->apr_err == SVN_ERR_FS_NOT_FOUND)
143289177Speter              svn_handle_warning2(stderr, err, "svnbench: ");
144289177Speter          else
145289177Speter              return svn_error_trace(err);
146289177Speter
147289177Speter          svn_error_clear(err);
148289177Speter          err = NULL;
149289177Speter          seen_nonexistent_target = TRUE;
150289177Speter        }
151289177Speter      else if (!opt_state->quiet)
152289177Speter        SVN_ERR(svn_cmdline_printf(pool,
153289177Speter                                   _("%15s directories\n"
154289177Speter                                     "%15s files\n"
155289177Speter                                     "%15s locks\n"),
156289177Speter                                   svn__ui64toa_sep(pb.directories, ',', pool),
157289177Speter                                   svn__ui64toa_sep(pb.files, ',', pool),
158289177Speter                                   svn__ui64toa_sep(pb.locks, ',', pool)));
159289177Speter    }
160289177Speter
161289177Speter  svn_pool_destroy(subpool);
162289177Speter
163289177Speter  if (seen_nonexistent_target)
164289177Speter    return svn_error_create(
165289177Speter      SVN_ERR_ILLEGAL_TARGET, NULL,
166289177Speter      _("Could not list all targets because some targets don't exist"));
167289177Speter  else
168289177Speter    return SVN_NO_ERROR;
169289177Speter}
170