~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/svnbench/null-blame-cmd.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2015-08-07 21:32:47 UTC
  • mfrom: (0.2.15) (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150807213247-ozyewtmgsr6tkewl
Tags: 1.9.0-1
* Upload to unstable
* New upstream release.
  + Security fixes
    - CVE-2015-3184: Mixed anonymous/authenticated path-based authz with
      httpd 2.4
    - CVE-2015-3187: svn_repos_trace_node_locations() reveals paths hidden
      by authz
* Add >= 2.7 requirement for python-all-dev Build-Depends, needed to run
  tests.
* Remove Build-Conflicts against ruby-test-unit.  (Closes: #791844)
* Remove patches/apache_module_dependency in favor of expressing the
  dependencies in authz_svn.load/dav_svn.load.
* Build-Depend on apache2-dev (>= 2.4.16) to ensure ap_some_authn_required()
  is available when building mod_authz_svn and Depend on apache2-bin (>=
  2.4.16) for runtime support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * null-blame-cmd.c -- Subversion export command
 
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
/* ==================================================================== */
 
25
 
 
26
 
 
27
 
 
28
/*** Includes. ***/
 
29
 
 
30
#include "svn_client.h"
 
31
#include "svn_cmdline.h"
 
32
#include "svn_error.h"
 
33
#include "svn_dirent_uri.h"
 
34
#include "svn_path.h"
 
35
#include "svn_pools.h"
 
36
#include "svn_sorts.h"
 
37
#include "cl.h"
 
38
 
 
39
#include "svn_private_config.h"
 
40
#include "private/svn_string_private.h"
 
41
#include "private/svn_client_private.h"
 
42
 
 
43
struct file_rev_baton {
 
44
  apr_int64_t byte_count;
 
45
  apr_int64_t delta_count;
 
46
  apr_int64_t rev_count;
 
47
};
 
48
 
 
49
/* Implements svn_txdelta_window_handler_t */
 
50
static svn_error_t *
 
51
delta_handler(svn_txdelta_window_t *window, void *baton)
 
52
{
 
53
  struct file_rev_baton *frb = baton;
 
54
 
 
55
  if (window != NULL)
 
56
    frb->byte_count += window->tview_len;
 
57
 
 
58
  return SVN_NO_ERROR;
 
59
}
 
60
 
 
61
/* Implementes svn_file_rev_handler_t */
 
62
static svn_error_t *
 
63
file_rev_handler(void *baton, const char *path, svn_revnum_t revnum,
 
64
                 apr_hash_t *rev_props,
 
65
                 svn_boolean_t merged_revision,
 
66
                 svn_txdelta_window_handler_t *content_delta_handler,
 
67
                 void **content_delta_baton,
 
68
                 apr_array_header_t *prop_diffs,
 
69
                 apr_pool_t *pool)
 
70
{
 
71
  struct file_rev_baton *frb = baton;
 
72
 
 
73
  frb->rev_count++;
 
74
 
 
75
  if (content_delta_handler)
 
76
    {
 
77
      *content_delta_handler = delta_handler;
 
78
      *content_delta_baton = baton;
 
79
      frb->delta_count++;
 
80
    }
 
81
 
 
82
  return SVN_NO_ERROR;
 
83
}
 
84
 
 
85
static svn_error_t *
 
86
bench_null_blame(const char *target,
 
87
                 const svn_opt_revision_t *peg_revision,
 
88
                 const svn_opt_revision_t *start,
 
89
                 const svn_opt_revision_t *end,
 
90
                 svn_boolean_t include_merged_revisions,
 
91
                 svn_boolean_t quiet,
 
92
                 svn_client_ctx_t *ctx,
 
93
                 apr_pool_t *pool)
 
94
{
 
95
  struct file_rev_baton frb = { 0, 0, 0};
 
96
  svn_ra_session_t *ra_session;
 
97
  svn_revnum_t start_revnum, end_revnum;
 
98
  svn_boolean_t backwards;
 
99
  const char *target_abspath_or_url;
 
100
 
 
101
  if (start->kind == svn_opt_revision_unspecified
 
102
      || end->kind == svn_opt_revision_unspecified)
 
103
    return svn_error_create
 
104
      (SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);
 
105
 
 
106
  if (svn_path_is_url(target))
 
107
    target_abspath_or_url = target;
 
108
  else
 
109
    SVN_ERR(svn_dirent_get_absolute(&target_abspath_or_url, target, pool));
 
110
 
 
111
 
 
112
  /* Get an RA plugin for this filesystem object. */
 
113
  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, NULL,
 
114
                                            target, NULL, peg_revision,
 
115
                                            peg_revision,
 
116
                                            ctx, pool));
 
117
 
 
118
  SVN_ERR(svn_client__get_revision_number(&start_revnum, NULL, ctx->wc_ctx,
 
119
                                          target_abspath_or_url, ra_session,
 
120
                                          start, pool));
 
121
 
 
122
  SVN_ERR(svn_client__get_revision_number(&end_revnum, NULL, ctx->wc_ctx,
 
123
                                          target_abspath_or_url, ra_session,
 
124
                                          end, pool));
 
125
 
 
126
  {
 
127
    svn_client__pathrev_t *loc;
 
128
    svn_opt_revision_t younger_end;
 
129
    younger_end.kind = svn_opt_revision_number;
 
130
    younger_end.value.number = MAX(start_revnum, end_revnum);
 
131
 
 
132
    SVN_ERR(svn_client__resolve_rev_and_url(&loc, ra_session,
 
133
                                            target, peg_revision,
 
134
                                            &younger_end,
 
135
                                            ctx, pool));
 
136
 
 
137
    /* Make the session point to the real URL. */
 
138
    SVN_ERR(svn_ra_reparent(ra_session, loc->url, pool));
 
139
  }
 
140
 
 
141
  backwards = (start_revnum > end_revnum);
 
142
 
 
143
  /* Collect all blame information.
 
144
     We need to ensure that we get one revision before the start_rev,
 
145
     if available so that we can know what was actually changed in the start
 
146
     revision. */
 
147
  SVN_ERR(svn_ra_get_file_revs2(ra_session, "",
 
148
                                backwards ? start_revnum
 
149
                                          : MAX(0, start_revnum-1),
 
150
                                end_revnum,
 
151
                                include_merged_revisions,
 
152
                                file_rev_handler, &frb, pool));
 
153
 
 
154
  if (!quiet)
 
155
    SVN_ERR(svn_cmdline_printf(pool,
 
156
                               _("%15s revisions\n"
 
157
                                 "%15s deltas\n"
 
158
                                 "%15s bytes in deltas\n"),
 
159
                               svn__ui64toa_sep(frb.rev_count, ',', pool),
 
160
                               svn__ui64toa_sep(frb.delta_count, ',', pool),
 
161
                               svn__ui64toa_sep(frb.byte_count, ',', pool)));
 
162
 
 
163
  return SVN_NO_ERROR;
 
164
}
 
165
 
 
166
 
 
167
/* This implements the `svn_opt_subcommand_t' interface. */
 
168
svn_error_t *
 
169
svn_cl__null_blame(apr_getopt_t *os,
 
170
                   void *baton,
 
171
                   apr_pool_t *pool)
 
172
{
 
173
  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
 
174
  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
 
175
  apr_pool_t *iterpool;
 
176
  apr_array_header_t *targets;
 
177
  int i;
 
178
  svn_boolean_t end_revision_unspecified = FALSE;
 
179
  svn_boolean_t seen_nonexistent_target = FALSE;
 
180
 
 
181
  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
 
182
                                                      opt_state->targets,
 
183
                                                      ctx, FALSE, pool));
 
184
 
 
185
  /* Blame needs a file on which to operate. */
 
186
  if (! targets->nelts)
 
187
    return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
 
188
 
 
189
  if (opt_state->end_revision.kind == svn_opt_revision_unspecified)
 
190
    {
 
191
      if (opt_state->start_revision.kind != svn_opt_revision_unspecified)
 
192
        {
 
193
          /* In the case that -rX was specified, we actually want to set the
 
194
             range to be -r1:X. */
 
195
 
 
196
          opt_state->end_revision = opt_state->start_revision;
 
197
          opt_state->start_revision.kind = svn_opt_revision_number;
 
198
          opt_state->start_revision.value.number = 1;
 
199
        }
 
200
      else
 
201
        end_revision_unspecified = TRUE;
 
202
    }
 
203
 
 
204
  if (opt_state->start_revision.kind == svn_opt_revision_unspecified)
 
205
    {
 
206
      opt_state->start_revision.kind = svn_opt_revision_number;
 
207
      opt_state->start_revision.value.number = 1;
 
208
    }
 
209
 
 
210
  /* The final conclusion from issue #2431 is that blame info
 
211
     is client output (unlike 'svn cat' which plainly cats the file),
 
212
     so the EOL style should be the platform local one.
 
213
  */
 
214
  iterpool = svn_pool_create(pool);
 
215
 
 
216
  for (i = 0; i < targets->nelts; i++)
 
217
    {
 
218
      svn_error_t *err;
 
219
      const char *target = APR_ARRAY_IDX(targets, i, const char *);
 
220
      const char *parsed_path;
 
221
      svn_opt_revision_t peg_revision;
 
222
 
 
223
      svn_pool_clear(iterpool);
 
224
      SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
 
225
 
 
226
      /* Check for a peg revision. */
 
227
      SVN_ERR(svn_opt_parse_path(&peg_revision, &parsed_path, target,
 
228
                                 iterpool));
 
229
 
 
230
      if (end_revision_unspecified)
 
231
        {
 
232
          if (peg_revision.kind != svn_opt_revision_unspecified)
 
233
            opt_state->end_revision = peg_revision;
 
234
          else if (svn_path_is_url(target))
 
235
            opt_state->end_revision.kind = svn_opt_revision_head;
 
236
          else
 
237
            opt_state->end_revision.kind = svn_opt_revision_working;
 
238
        }
 
239
 
 
240
      err = bench_null_blame(parsed_path,
 
241
                             &peg_revision,
 
242
                             &opt_state->start_revision,
 
243
                             &opt_state->end_revision,
 
244
                             opt_state->use_merge_history,
 
245
                             opt_state->quiet,
 
246
                             ctx,
 
247
                             iterpool);
 
248
 
 
249
      if (err)
 
250
        {
 
251
          if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND ||
 
252
                   err->apr_err == SVN_ERR_ENTRY_NOT_FOUND ||
 
253
                   err->apr_err == SVN_ERR_FS_NOT_FILE ||
 
254
                   err->apr_err == SVN_ERR_FS_NOT_FOUND)
 
255
            {
 
256
              svn_handle_warning2(stderr, err, "svn: ");
 
257
              svn_error_clear(err);
 
258
              err = NULL;
 
259
              seen_nonexistent_target = TRUE;
 
260
            }
 
261
          else
 
262
            {
 
263
              return svn_error_trace(err);
 
264
            }
 
265
        }
 
266
    }
 
267
  svn_pool_destroy(iterpool);
 
268
 
 
269
  if (seen_nonexistent_target)
 
270
    return svn_error_create(
 
271
      SVN_ERR_ILLEGAL_TARGET, NULL,
 
272
      _("Could not perform blame on all targets because some "
 
273
        "targets don't exist"));
 
274
  else
 
275
    return SVN_NO_ERROR;
 
276
}