1/* 2 * list-cmd.c -- list a URL 3 * 4 * ==================================================================== 5 * Licensed to the Apache Software Foundation (ASF) under one 6 * or more contributor license agreements. See the NOTICE file 7 * distributed with this work for additional information 8 * regarding copyright ownership. The ASF licenses this file 9 * to you under the Apache License, Version 2.0 (the 10 * "License"); you may not use this file except in compliance 11 * with the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, 16 * software distributed under the License is distributed on an 17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 * KIND, either express or implied. See the License for the 19 * specific language governing permissions and limitations 20 * under the License. 21 * ==================================================================== 22 */ 23 24#include "svn_cmdline.h" 25#include "svn_client.h" 26#include "svn_error.h" 27#include "svn_pools.h" 28#include "svn_time.h" 29#include "svn_xml.h" 30#include "svn_dirent_uri.h" 31#include "svn_path.h" 32#include "svn_utf.h" 33#include "svn_opt.h" 34 35#include "cl.h" 36 37#include "svn_private_config.h" 38#include "private/svn_string_private.h" 39 40 41 42/* Baton used when printing directory entries. */ 43struct print_baton { 44 svn_boolean_t verbose; 45 apr_int64_t directories; 46 apr_int64_t files; 47 apr_int64_t locks; 48 svn_client_ctx_t *ctx; 49}; 50 51/* This implements the svn_client_list_func2_t API, printing a single 52 directory entry in text format. */ 53static svn_error_t * 54print_dirent(void *baton, 55 const char *path, 56 const svn_dirent_t *dirent, 57 const svn_lock_t *lock, 58 const char *abs_path, 59 const char *external_parent_url, 60 const char *external_target, 61 apr_pool_t *pool) 62{ 63 struct print_baton *pb = baton; 64 65 if (pb->ctx->cancel_func) 66 SVN_ERR(pb->ctx->cancel_func(pb->ctx->cancel_baton)); 67 68 if (dirent->kind == svn_node_dir) 69 pb->directories++; 70 if (dirent->kind == svn_node_file) 71 pb->files++; 72 if (lock) 73 pb->locks++; 74 75 return SVN_NO_ERROR; 76} 77 78 79/* This implements the `svn_opt_subcommand_t' interface. */ 80svn_error_t * 81svn_cl__null_list(apr_getopt_t *os, 82 void *baton, 83 apr_pool_t *pool) 84{ 85 svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; 86 svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; 87 apr_array_header_t *targets; 88 int i; 89 apr_pool_t *subpool = svn_pool_create(pool); 90 apr_uint32_t dirent_fields; 91 struct print_baton pb = { FALSE }; 92 svn_boolean_t seen_nonexistent_target = FALSE; 93 svn_error_t *err; 94 95 SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, 96 opt_state->targets, 97 ctx, FALSE, pool)); 98 99 /* Add "." if user passed 0 arguments */ 100 svn_opt_push_implicit_dot_target(targets, pool); 101 102 if (opt_state->verbose) 103 dirent_fields = SVN_DIRENT_ALL; 104 else 105 dirent_fields = SVN_DIRENT_KIND; /* the only thing we actually need... */ 106 107 pb.ctx = ctx; 108 pb.verbose = opt_state->verbose; 109 110 if (opt_state->depth == svn_depth_unknown) 111 opt_state->depth = svn_depth_immediates; 112 113 /* For each target, try to list it. */ 114 for (i = 0; i < targets->nelts; i++) 115 { 116 const char *target = APR_ARRAY_IDX(targets, i, const char *); 117 const char *truepath; 118 svn_opt_revision_t peg_revision; 119 120 svn_pool_clear(subpool); 121 122 SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton)); 123 124 /* Get peg revisions. */ 125 SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target, 126 subpool)); 127 128 err = svn_client_list3(truepath, &peg_revision, 129 &(opt_state->start_revision), 130 opt_state->depth, 131 dirent_fields, 132 opt_state->verbose, 133 FALSE, /* include externals */ 134 print_dirent, 135 &pb, ctx, subpool); 136 137 if (err) 138 { 139 /* If one of the targets is a non-existent URL or wc-entry, 140 don't bail out. Just warn and move on to the next target. */ 141 if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND || 142 err->apr_err == SVN_ERR_FS_NOT_FOUND) 143 svn_handle_warning2(stderr, err, "svnbench: "); 144 else 145 return svn_error_trace(err); 146 147 svn_error_clear(err); 148 err = NULL; 149 seen_nonexistent_target = TRUE; 150 } 151 else if (!opt_state->quiet) 152 SVN_ERR(svn_cmdline_printf(pool, 153 _("%15s directories\n" 154 "%15s files\n" 155 "%15s locks\n"), 156 svn__ui64toa_sep(pb.directories, ',', pool), 157 svn__ui64toa_sep(pb.files, ',', pool), 158 svn__ui64toa_sep(pb.locks, ',', pool))); 159 } 160 161 svn_pool_destroy(subpool); 162 163 if (seen_nonexistent_target) 164 return svn_error_create( 165 SVN_ERR_ILLEGAL_TARGET, NULL, 166 _("Could not list all targets because some targets don't exist")); 167 else 168 return SVN_NO_ERROR; 169} 170