~svn/ubuntu/oneiric/subversion/ppa

« back to all changes in this revision

Viewing changes to subversion/libsvn_client/ra.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2006-12-13 17:57:16 UTC
  • mfrom: (1.1.6 upstream) (0.1.3 etch)
  • Revision ID: james.westby@ubuntu.com-20061213175716-2ysv6z4w5dpa2r2f
Tags: 1.4.2dfsg1-2ubuntu1
* Merge with Debian unstable; remaining changes:
  - Create pot file on build.

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
 
37
37
 
38
38
static svn_error_t *
39
 
open_admin_tmp_file (apr_file_t **fp,
40
 
                     void *callback_baton,
41
 
                     apr_pool_t *pool)
 
39
open_admin_tmp_file(apr_file_t **fp,
 
40
                    void *callback_baton,
 
41
                    apr_pool_t *pool)
42
42
{
43
43
  svn_client__callback_baton_t *cb = callback_baton;
44
 
  
45
 
  SVN_ERR (svn_wc_create_tmp_file (fp, cb->base_dir, TRUE, pool));
 
44
 
 
45
  SVN_ERR(svn_wc_create_tmp_file2(fp, NULL, cb->base_dir,
 
46
                                  svn_io_file_del_on_close, pool));
46
47
 
47
48
  return SVN_NO_ERROR;
48
49
}
49
50
 
50
51
 
51
52
static svn_error_t *
52
 
open_tmp_file (apr_file_t **fp,
53
 
               void *callback_baton,
54
 
               apr_pool_t *pool)
 
53
open_tmp_file(apr_file_t **fp,
 
54
              void *callback_baton,
 
55
              apr_pool_t *pool)
55
56
{
56
57
  svn_client__callback_baton_t *cb = callback_baton;
57
58
  const char *truepath;
58
 
  const char *ignored_filename;
59
59
 
60
 
  if (cb->base_dir)
61
 
    truepath = apr_pstrdup (pool, cb->base_dir);
 
60
  if (cb->base_dir && ! cb->read_only_wc)
 
61
    truepath = apr_pstrdup(pool, cb->base_dir);
62
62
  else
63
 
    SVN_ERR (svn_io_temp_dir (&truepath, pool));
 
63
    SVN_ERR(svn_io_temp_dir(&truepath, pool));
64
64
 
65
65
  /* Tack on a made-up filename. */
66
 
  truepath = svn_path_join (truepath, "tempfile", pool);
 
66
  truepath = svn_path_join(truepath, "tempfile", pool);
67
67
 
68
 
  /* Open a unique file;  use APR_DELONCLOSE. */  
69
 
  SVN_ERR (svn_io_open_unique_file (fp, &ignored_filename,
70
 
                                    truepath, ".tmp", TRUE, pool));
 
68
  /* Open a unique file;  use APR_DELONCLOSE. */
 
69
  SVN_ERR(svn_io_open_unique_file2(fp, NULL, truepath, ".tmp",
 
70
                                   svn_io_file_del_on_close, pool));
71
71
 
72
72
  return SVN_NO_ERROR;
73
73
}
75
75
 
76
76
/* This implements the 'svn_ra_get_wc_prop_func_t' interface. */
77
77
static svn_error_t *
78
 
get_wc_prop (void *baton,
79
 
             const char *relpath,
80
 
             const char *name,
81
 
             const svn_string_t **value,
82
 
             apr_pool_t *pool)
 
78
get_wc_prop(void *baton,
 
79
            const char *relpath,
 
80
            const char *name,
 
81
            const svn_string_t **value,
 
82
            apr_pool_t *pool)
83
83
{
84
84
  svn_client__callback_baton_t *cb = baton;
85
85
 
95
95
          svn_client_commit_item2_t *item
96
96
            = APR_ARRAY_IDX(cb->commit_items, i,
97
97
                            svn_client_commit_item2_t *);
98
 
          if (! strcmp (relpath, 
99
 
                        svn_path_uri_decode (item->url, pool)))
100
 
            return svn_wc_prop_get (value, name, item->path, cb->base_access,
101
 
                                    pool);
 
98
          if (! strcmp(relpath, 
 
99
                       svn_path_uri_decode(item->url, pool)))
 
100
            return svn_wc_prop_get(value, name, item->path, cb->base_access,
 
101
                                   pool);
102
102
        }
103
103
 
104
104
      return SVN_NO_ERROR;
108
108
  else if (cb->base_dir == NULL)
109
109
    return SVN_NO_ERROR;
110
110
 
111
 
  return svn_wc_prop_get (value, name,
112
 
                          svn_path_join (cb->base_dir, relpath, pool),
113
 
                          cb->base_access, pool);
 
111
  return svn_wc_prop_get(value, name,
 
112
                         svn_path_join(cb->base_dir, relpath, pool),
 
113
                         cb->base_access, pool);
114
114
}
115
115
 
116
116
/* This implements the 'svn_ra_push_wc_prop_func_t' interface. */
117
117
static svn_error_t *
118
 
push_wc_prop (void *baton,
119
 
              const char *relpath,
120
 
              const char *name,
121
 
              const svn_string_t *value,
122
 
              apr_pool_t *pool)
 
118
push_wc_prop(void *baton,
 
119
             const char *relpath,
 
120
             const char *name,
 
121
             const svn_string_t *value,
 
122
             apr_pool_t *pool)
123
123
{
124
124
  svn_client__callback_baton_t *cb = baton;
125
125
  int i;
130
130
    return svn_error_createf
131
131
      (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
132
132
       _("Attempt to set wc property '%s' on '%s' in a non-commit operation"),
133
 
       name, svn_path_local_style (relpath, pool));
 
133
       name, svn_path_local_style(relpath, pool));
134
134
 
135
135
  for (i = 0; i < cb->commit_items->nelts; i++)
136
136
    {
137
137
      svn_client_commit_item2_t *item
138
138
        = APR_ARRAY_IDX(cb->commit_items, i, svn_client_commit_item2_t *);
139
139
      
140
 
      if (strcmp (relpath, svn_path_uri_decode (item->url, pool)) == 0)
 
140
      if (strcmp(relpath, svn_path_uri_decode(item->url, pool)) == 0)
141
141
        {
142
142
          apr_pool_t *cpool = item->wcprop_changes->pool;
143
 
          svn_prop_t *prop = apr_palloc (cpool, sizeof (*prop));
 
143
          svn_prop_t *prop = apr_palloc(cpool, sizeof(*prop));
144
144
          
145
 
          prop->name = apr_pstrdup (cpool, name);
 
145
          prop->name = apr_pstrdup(cpool, name);
146
146
          if (value)
147
147
            {
148
148
              prop->value
149
 
                = svn_string_ncreate (value->data, value->len, cpool);
 
149
                = svn_string_ncreate(value->data, value->len, cpool);
150
150
            }
151
151
          else
152
152
            prop->value = NULL;
153
153
          
154
154
          /* Buffer the propchange to take effect during the
155
155
             post-commit process. */
156
 
          *((svn_prop_t **) apr_array_push (item->wcprop_changes)) = prop;
 
156
          *((svn_prop_t **) apr_array_push(item->wcprop_changes)) = prop;
157
157
          return SVN_NO_ERROR;
158
158
        }
159
159
    }
164
164
 
165
165
/* This implements the 'svn_ra_set_wc_prop_func_t' interface. */
166
166
static svn_error_t *
167
 
set_wc_prop (void *baton,
168
 
             const char *path,
169
 
             const char *name,
170
 
             const svn_string_t *value,
171
 
             apr_pool_t *pool)
 
167
set_wc_prop(void *baton,
 
168
            const char *path,
 
169
            const char *name,
 
170
            const svn_string_t *value,
 
171
            apr_pool_t *pool)
172
172
{
173
173
  svn_client__callback_baton_t *cb = baton;
174
174
  svn_wc_adm_access_t *adm_access;
175
175
  const svn_wc_entry_t *entry;
176
 
  const char *full_path = svn_path_join (cb->base_dir, path, pool);
 
176
  const char *full_path = svn_path_join(cb->base_dir, path, pool);
177
177
 
178
 
  SVN_ERR (svn_wc_entry (&entry, full_path, cb->base_access, FALSE, pool));
 
178
  SVN_ERR(svn_wc_entry(&entry, full_path, cb->base_access, FALSE, pool));
179
179
  if (! entry)
180
 
    return svn_error_createf (SVN_ERR_UNVERSIONED_RESOURCE, NULL,
181
 
                              _("'%s' is not under version control"),
182
 
                              svn_path_local_style (full_path, pool));
 
180
    return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL,
 
181
                             _("'%s' is not under version control"),
 
182
                             svn_path_local_style(full_path, pool));
183
183
 
184
 
  SVN_ERR (svn_wc_adm_retrieve (&adm_access, cb->base_access,
185
 
                                (entry->kind == svn_node_dir
186
 
                                 ? full_path
187
 
                                 : svn_path_dirname (full_path, pool)),
188
 
                                pool));
 
184
  SVN_ERR(svn_wc_adm_retrieve(&adm_access, cb->base_access,
 
185
                              (entry->kind == svn_node_dir
 
186
                               ? full_path
 
187
                               : svn_path_dirname(full_path, pool)),
 
188
                              pool));
189
189
    
190
190
  /* We pass 1 for the 'force' parameter here.  Since the property is
191
191
     coming from the repository, we definitely want to accept it.
195
195
     right, but the conflict would remind the user to make sure.
196
196
     Unfortunately, we don't have a clean mechanism for doing that
197
197
     here, so we just set the property and hope for the best. */
198
 
  return svn_wc_prop_set2 (name, value, full_path, adm_access, TRUE, pool);
 
198
  return svn_wc_prop_set2(name, value, full_path, adm_access, TRUE, pool);
199
199
}
200
200
 
201
201
 
212
212
/* This implements the `found_entry' prototype in
213
213
   `svn_wc_entry_callbacks_t'. */
214
214
static svn_error_t *
215
 
invalidate_wcprop_for_entry (const char *path,
216
 
                             const svn_wc_entry_t *entry,
217
 
                             void *walk_baton,
218
 
                             apr_pool_t *pool)
 
215
invalidate_wcprop_for_entry(const char *path,
 
216
                            const svn_wc_entry_t *entry,
 
217
                            void *walk_baton,
 
218
                            apr_pool_t *pool)
219
219
{
220
220
  struct invalidate_wcprop_walk_baton *wb = walk_baton;
221
221
  svn_wc_adm_access_t *entry_access;
222
222
 
223
 
  SVN_ERR (svn_wc_adm_retrieve (&entry_access, wb->base_access,
224
 
                                ((entry->kind == svn_node_dir)
225
 
                                 ? path
226
 
                                 : svn_path_dirname (path, pool)),
227
 
                                pool));
 
223
  SVN_ERR(svn_wc_adm_retrieve(&entry_access, wb->base_access,
 
224
                              ((entry->kind == svn_node_dir)
 
225
                               ? path
 
226
                               : svn_path_dirname(path, pool)),
 
227
                              pool));
228
228
  /* It doesn't matter if we pass 0 or 1 for force here, since
229
229
     property deletion is always permitted. */
230
 
  return svn_wc_prop_set2 (wb->prop_name, NULL, path, entry_access,
231
 
                           FALSE, pool);
 
230
  return svn_wc_prop_set2(wb->prop_name, NULL, path, entry_access,
 
231
                          FALSE, pool);
232
232
}
233
233
 
234
234
 
235
235
/* This implements the `svn_ra_invalidate_wc_props_func_t' interface. */
236
236
static svn_error_t *
237
 
invalidate_wc_props (void *baton,
238
 
                     const char *path,
239
 
                     const char *prop_name,
240
 
                     apr_pool_t *pool)
 
237
invalidate_wc_props(void *baton,
 
238
                    const char *path,
 
239
                    const char *prop_name,
 
240
                    apr_pool_t *pool)
241
241
{
242
242
  svn_client__callback_baton_t *cb = baton;
243
243
  svn_wc_entry_callbacks_t walk_callbacks;
248
248
  wb.prop_name = prop_name;
249
249
  walk_callbacks.found_entry = invalidate_wcprop_for_entry;
250
250
 
251
 
  path = svn_path_join (cb->base_dir, path, pool);
252
 
  SVN_ERR (svn_wc_adm_probe_retrieve (&adm_access, cb->base_access, path,
253
 
                                      pool));
254
 
  SVN_ERR (svn_wc_walk_entries2 (path, adm_access, &walk_callbacks, &wb,
255
 
                                 FALSE, cb->ctx->cancel_func,
256
 
                                 cb->ctx->cancel_baton, pool));
 
251
  path = svn_path_join(cb->base_dir, path, pool);
 
252
  SVN_ERR(svn_wc_adm_probe_retrieve(&adm_access, cb->base_access, path,
 
253
                                    pool));
 
254
  SVN_ERR(svn_wc_walk_entries2(path, adm_access, &walk_callbacks, &wb,
 
255
                               FALSE, cb->ctx->cancel_func,
 
256
                               cb->ctx->cancel_baton, pool));
257
257
 
258
258
  return SVN_NO_ERROR;
259
259
}
260
260
 
261
261
 
262
262
svn_error_t * 
263
 
svn_client__open_ra_session_internal (svn_ra_session_t **ra_session,
264
 
                                      const char *base_url,
265
 
                                      const char *base_dir,
266
 
                                      svn_wc_adm_access_t *base_access,
267
 
                                      apr_array_header_t *commit_items,
268
 
                                      svn_boolean_t use_admin,
269
 
                                      svn_boolean_t read_only_wc,
270
 
                                      svn_client_ctx_t *ctx,
271
 
                                      apr_pool_t *pool)
 
263
svn_client__open_ra_session_internal(svn_ra_session_t **ra_session,
 
264
                                     const char *base_url,
 
265
                                     const char *base_dir,
 
266
                                     svn_wc_adm_access_t *base_access,
 
267
                                     apr_array_header_t *commit_items,
 
268
                                     svn_boolean_t use_admin,
 
269
                                     svn_boolean_t read_only_wc,
 
270
                                     svn_client_ctx_t *ctx,
 
271
                                     apr_pool_t *pool)
272
272
{
273
 
  svn_ra_callbacks2_t *cbtable = apr_pcalloc (pool, sizeof(*cbtable));
274
 
  svn_client__callback_baton_t *cb = apr_pcalloc (pool, sizeof(*cb));
 
273
  svn_ra_callbacks2_t *cbtable = apr_pcalloc(pool, sizeof(*cbtable));
 
274
  svn_client__callback_baton_t *cb = apr_pcalloc(pool, sizeof(*cb));
275
275
  
276
276
  cbtable->open_tmp_file = use_admin ? open_admin_tmp_file : open_tmp_file;
277
277
  cbtable->get_wc_prop = use_admin ? get_wc_prop : NULL;
284
284
 
285
285
  cb->base_dir = base_dir;
286
286
  cb->base_access = base_access;
 
287
  cb->read_only_wc = read_only_wc;
287
288
  cb->pool = pool;
288
289
  cb->commit_items = commit_items;
289
290
  cb->ctx = ctx;
290
291
 
291
 
  SVN_ERR (svn_ra_open2 (ra_session, base_url, cbtable, cb,
292
 
                         ctx->config, pool));
 
292
  SVN_ERR(svn_ra_open2(ra_session, base_url, cbtable, cb,
 
293
                       ctx->config, pool));
293
294
 
294
295
  return SVN_NO_ERROR;
295
296
}
296
297
 
297
298
svn_error_t *
298
 
svn_client_open_ra_session (svn_ra_session_t **session,
299
 
                            const char *url,
300
 
                            svn_client_ctx_t *ctx,
301
 
                            apr_pool_t *pool)
 
299
svn_client_open_ra_session(svn_ra_session_t **session,
 
300
                           const char *url,
 
301
                           svn_client_ctx_t *ctx,
 
302
                           apr_pool_t *pool)
302
303
{
303
 
  return svn_client__open_ra_session_internal (session, url, NULL, NULL, NULL,
304
 
                                               FALSE, TRUE, ctx, pool);
 
304
  return svn_client__open_ra_session_internal(session, url, NULL, NULL, NULL,
 
305
                                              FALSE, TRUE, ctx, pool);
305
306
}
306
307
 
307
308
 
308
309
svn_error_t *
309
 
svn_client_uuid_from_url (const char **uuid,
310
 
                          const char *url,
311
 
                          svn_client_ctx_t *ctx,
312
 
                          apr_pool_t *pool)
 
310
svn_client_uuid_from_url(const char **uuid,
 
311
                         const char *url,
 
312
                         svn_client_ctx_t *ctx,
 
313
                         apr_pool_t *pool)
313
314
{
314
315
  svn_ra_session_t *ra_session;
315
 
  apr_pool_t *subpool = svn_pool_create (pool);
 
316
  apr_pool_t *subpool = svn_pool_create(pool);
316
317
 
317
318
  /* use subpool to create a temporary RA session */
318
 
  SVN_ERR (svn_client__open_ra_session_internal (&ra_session, url,
319
 
                                                 NULL, /* no base dir */
320
 
                                                 NULL, NULL, FALSE, TRUE, 
321
 
                                                 ctx, subpool));
 
319
  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, url,
 
320
                                               NULL, /* no base dir */
 
321
                                               NULL, NULL, FALSE, TRUE, 
 
322
                                               ctx, subpool));
322
323
 
323
 
  SVN_ERR (svn_ra_get_uuid (ra_session, uuid, subpool));
 
324
  SVN_ERR(svn_ra_get_uuid(ra_session, uuid, subpool));
324
325
 
325
326
  /* Copy the uuid in to the passed-in pool. */
326
 
  *uuid = apr_pstrdup (pool, *uuid);
 
327
  *uuid = apr_pstrdup(pool, *uuid);
327
328
 
328
329
  /* destroy the RA session */
329
 
  svn_pool_destroy (subpool);
 
330
  svn_pool_destroy(subpool);
330
331
 
331
332
  return SVN_NO_ERROR;
332
333
}
333
334
 
334
335
 
335
336
svn_error_t *
336
 
svn_client_uuid_from_path (const char **uuid,
337
 
                           const char *path,
338
 
                           svn_wc_adm_access_t *adm_access,
339
 
                           svn_client_ctx_t *ctx,
340
 
                           apr_pool_t *pool)
 
337
svn_client_uuid_from_path(const char **uuid,
 
338
                          const char *path,
 
339
                          svn_wc_adm_access_t *adm_access,
 
340
                          svn_client_ctx_t *ctx,
 
341
                          apr_pool_t *pool)
341
342
{
342
343
  const svn_wc_entry_t *entry;
343
344
 
344
 
  SVN_ERR (svn_wc_entry (&entry, path, adm_access,
345
 
                         TRUE,  /* show deleted */ pool));
 
345
  SVN_ERR(svn_wc_entry(&entry, path, adm_access,
 
346
                       TRUE,  /* show deleted */ pool));
346
347
 
347
348
  if (! entry)
348
 
    return svn_error_createf (SVN_ERR_ENTRY_NOT_FOUND, NULL,
349
 
                              _("Can't find entry for '%s'"),
350
 
                              svn_path_local_style (path, pool));
 
349
    return svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL,
 
350
                             _("Can't find entry for '%s'"),
 
351
                             svn_path_local_style(path, pool));
351
352
 
352
353
  if (entry->uuid)
353
354
    {
356
357
  else if (entry->url)
357
358
    {
358
359
      /* fallback to using the network. */
359
 
      SVN_ERR (svn_client_uuid_from_url (uuid, entry->url, ctx, pool));
 
360
      SVN_ERR(svn_client_uuid_from_url(uuid, entry->url, ctx, pool));
360
361
    }
361
362
  else
362
363
    {
366
367
         http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=101831
367
368
         Message-ID: <877jgjtkus.fsf@debian2.lan> */
368
369
      svn_boolean_t is_root;
369
 
      SVN_ERR (svn_wc_is_wc_root (&is_root, path, adm_access, pool));
 
370
      SVN_ERR(svn_wc_is_wc_root(&is_root, path, adm_access, pool));
370
371
      if (is_root)
371
 
        return svn_error_createf (SVN_ERR_ENTRY_MISSING_URL, NULL,
372
 
                                  _("'%s' has no URL"),
373
 
                                  svn_path_local_style (path, pool));
 
372
        return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
 
373
                                 _("'%s' has no URL"),
 
374
                                 svn_path_local_style(path, pool));
374
375
      else
375
 
        return svn_client_uuid_from_path (uuid, svn_path_dirname (path, pool),
376
 
                                          adm_access, ctx, pool);
 
376
        return svn_client_uuid_from_path(uuid, svn_path_dirname(path, pool),
 
377
                                         adm_access, ctx, pool);
377
378
    }
378
379
 
379
380
  return SVN_NO_ERROR;
381
382
 
382
383
 
383
384
svn_error_t *
384
 
svn_client__prev_log_path (const char **prev_path_p,
385
 
                           char *action_p,
386
 
                           svn_revnum_t *copyfrom_rev_p,
387
 
                           apr_hash_t *changed_paths,
388
 
                           const char *path,
389
 
                           svn_node_kind_t kind,
390
 
                           svn_revnum_t revision,
391
 
                           apr_pool_t *pool)
 
385
svn_client__prev_log_path(const char **prev_path_p,
 
386
                          char *action_p,
 
387
                          svn_revnum_t *copyfrom_rev_p,
 
388
                          apr_hash_t *changed_paths,
 
389
                          const char *path,
 
390
                          svn_node_kind_t kind,
 
391
                          svn_revnum_t revision,
 
392
                          apr_pool_t *pool)
392
393
{
393
394
  svn_log_changed_path_t *change;
394
395
  const char *prev_path = NULL;
404
405
    *copyfrom_rev_p = SVN_INVALID_REVNUM;
405
406
 
406
407
  /* See if PATH was explicitly changed in this revision. */
407
 
  change = apr_hash_get (changed_paths, path, APR_HASH_KEY_STRING);
 
408
  change = apr_hash_get(changed_paths, path, APR_HASH_KEY_STRING);
408
409
  if (change)
409
410
    {
410
411
      /* If PATH was not newly added in this revision, then it may or may
420
421
          /* PATH is new in this revision.  This means it cannot have been
421
422
             part of a copied subtree. */
422
423
          if (change->copyfrom_path)
423
 
            prev_path = apr_pstrdup (pool, change->copyfrom_path);
 
424
            prev_path = apr_pstrdup(pool, change->copyfrom_path);
424
425
          else
425
426
            prev_path = NULL;
426
427
          
433
434
        }
434
435
    }
435
436
  
436
 
  if (apr_hash_count (changed_paths))
 
437
  if (apr_hash_count(changed_paths))
437
438
    {
438
439
      /* The path was not explicitly changed in this revision.  The
439
440
         fact that we're hearing about this revision implies, then,
444
445
      apr_array_header_t *paths;
445
446
 
446
447
      /* Build a sorted list of the changed paths. */
447
 
      paths = svn_sort__hash (changed_paths,
448
 
                              svn_sort_compare_items_as_paths, pool);
 
448
      paths = svn_sort__hash(changed_paths,
 
449
                             svn_sort_compare_items_as_paths, pool);
449
450
 
450
451
      /* Now, walk the list of paths backwards, looking a parent of
451
452
         our path that has copyfrom information. */
452
453
      for (i = paths->nelts; i > 0; i--)
453
454
        {
454
 
          svn_sort__item_t item = APR_ARRAY_IDX (paths,
455
 
                                                 i - 1, svn_sort__item_t);
 
455
          svn_sort__item_t item = APR_ARRAY_IDX(paths,
 
456
                                                i - 1, svn_sort__item_t);
456
457
          const char *ch_path = item.key;
457
 
          int len = strlen (ch_path);
 
458
          int len = strlen(ch_path);
458
459
 
459
460
          /* See if our path is the child of this change path.  If
460
461
             not, keep looking.  */
461
 
          if (! ((strncmp (ch_path, path, len) == 0) && (path[len] == '/')))
 
462
          if (! ((strncmp(ch_path, path, len) == 0) && (path[len] == '/')))
462
463
            continue;
463
464
 
464
465
          /* Okay, our path *is* a child of this change path.  If
467
468
             path, to the change's copyfrom path.  Otherwise, this
468
469
             change isn't really interesting to us, and our search
469
470
             continues. */
470
 
          change = apr_hash_get (changed_paths, ch_path, len);
 
471
          change = apr_hash_get(changed_paths, ch_path, len);
471
472
          if (change->copyfrom_path)
472
473
            {
473
474
              if (action_p)
474
475
                *action_p = change->action;
475
476
              if (copyfrom_rev_p)
476
477
                *copyfrom_rev_p = change->copyfrom_rev;
477
 
              prev_path = svn_path_join (change->copyfrom_path, 
478
 
                                         path + len + 1, pool);
 
478
              prev_path = svn_path_join(change->copyfrom_path, 
 
479
                                        path + len + 1, pool);
479
480
              break;
480
481
            }
481
482
        }
487
488
  if (! prev_path)
488
489
    {
489
490
      if (kind == svn_node_dir)
490
 
        prev_path = apr_pstrdup (pool, path);
 
491
        prev_path = apr_pstrdup(pool, path);
491
492
      else
492
 
        return svn_error_createf (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
493
 
                                  _("Missing changed-path information for "
494
 
                                    "'%s' in revision %ld"),
495
 
                                  svn_path_local_style (path, pool), revision);
 
493
        return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
 
494
                                 _("Missing changed-path information for "
 
495
                                   "'%s' in revision %ld"),
 
496
                                 svn_path_local_style(path, pool), revision);
496
497
    }
497
498
  
498
499
  *prev_path_p = prev_path;
530
531
   (defined above) and attempts to "fill in" all three paths in the
531
532
   baton over the course of many iterations. */
532
533
static svn_error_t *
533
 
log_receiver (void *baton,
534
 
              apr_hash_t *changed_paths,
535
 
              svn_revnum_t revision,
536
 
              const char *author,
537
 
              const char *date,
538
 
              const char *message,
539
 
              apr_pool_t *pool)
 
534
log_receiver(void *baton,
 
535
             apr_hash_t *changed_paths,
 
536
             svn_revnum_t revision,
 
537
             const char *author,
 
538
             const char *date,
 
539
             const char *message,
 
540
             apr_pool_t *pool)
540
541
{
541
542
  struct log_receiver_baton *lrb = baton;
542
543
  const char *current_path = lrb->last_path;
544
545
 
545
546
  /* See if the user is fed up with this time-consuming process yet. */
546
547
  if (lrb->ctx->cancel_func)
547
 
    SVN_ERR (lrb->ctx->cancel_func (lrb->ctx->cancel_baton));
 
548
    SVN_ERR(lrb->ctx->cancel_func(lrb->ctx->cancel_baton));
548
549
 
549
550
  /* No paths were changed in this revision.  Nothing to do. */
550
551
  if (!changed_paths)
561
562
  /* Determine the paths for any of the revisions for which we haven't
562
563
     gotten paths already. */
563
564
  if ((! *lrb->start_path_p) && (revision <= lrb->start_revision))
564
 
    *lrb->start_path_p = apr_pstrdup (lrb->pool, current_path);
 
565
    *lrb->start_path_p = apr_pstrdup(lrb->pool, current_path);
565
566
  if ((! *lrb->end_path_p) && (revision <= lrb->end_revision))
566
 
    *lrb->end_path_p = apr_pstrdup (lrb->pool, current_path);
 
567
    *lrb->end_path_p = apr_pstrdup(lrb->pool, current_path);
567
568
  if ((! lrb->peg_path) && (revision <= lrb->peg_revision))
568
 
    lrb->peg_path = apr_pstrdup (lrb->pool, current_path);
 
569
    lrb->peg_path = apr_pstrdup(lrb->pool, current_path);
569
570
 
570
571
  /* Figure out at which repository path our object of interest lived
571
572
     in the previous revision. */
572
 
  SVN_ERR (svn_client__prev_log_path (&prev_path, NULL, NULL, changed_paths,
573
 
                                      current_path, lrb->kind, 
574
 
                                      revision, pool));
 
573
  SVN_ERR(svn_client__prev_log_path(&prev_path, NULL, NULL, changed_paths,
 
574
                                    current_path, lrb->kind, 
 
575
                                    revision, pool));
575
576
 
576
577
  /* Squirrel away our "next place to look" path (suffer the strcmp
577
578
     hit to save on allocations). */
578
579
  if (! prev_path)
579
580
    lrb->last_path = NULL;
580
 
  else if (strcmp (prev_path, current_path) != 0)
581
 
    lrb->last_path = apr_pstrdup (lrb->pool, prev_path);
 
581
  else if (strcmp(prev_path, current_path) != 0)
 
582
    lrb->last_path = apr_pstrdup(lrb->pool, prev_path);
582
583
 
583
584
  return SVN_NO_ERROR;
584
585
}
592
593
   ### This is needed for 1.0.x servers, which don't have the get_locations
593
594
   RA layer function. */
594
595
static svn_error_t *
595
 
slow_locations (const char **start_path, const char** end_path,
596
 
                const char *abs_path, svn_revnum_t peg_revnum,
597
 
                svn_revnum_t start_revnum, svn_revnum_t end_revnum,
598
 
                const char *orig_path,
599
 
                svn_ra_session_t *ra_session,
600
 
                svn_client_ctx_t *ctx,
601
 
                apr_pool_t *pool)
 
596
slow_locations(const char **start_path, const char** end_path,
 
597
               const char *abs_path, svn_revnum_t peg_revnum,
 
598
               svn_revnum_t start_revnum, svn_revnum_t end_revnum,
 
599
               const char *orig_path,
 
600
               svn_ra_session_t *ra_session,
 
601
               svn_client_ctx_t *ctx,
 
602
               apr_pool_t *pool)
602
603
{
603
604
  struct log_receiver_baton lrb = { 0 };
604
605
  apr_array_header_t *targets;
606
607
  svn_boolean_t pegrev_is_youngest = FALSE;
607
608
 
608
609
  /* Sanity check:  verify that the peg-object exists in repos. */
609
 
  SVN_ERR (svn_ra_check_path (ra_session, "", peg_revnum, &(lrb.kind), pool));
 
610
  SVN_ERR(svn_ra_check_path(ra_session, "", peg_revnum, &(lrb.kind), pool));
610
611
  if (lrb.kind == svn_node_none)
611
612
    return svn_error_createf
612
613
      (SVN_ERR_FS_NOT_FOUND, NULL,
632
633
  oldest = (end_revnum < oldest) ? end_revnum : oldest;
633
634
 
634
635
  /* Build a one-item TARGETS array, as input to ra->get_log() */
635
 
  targets = apr_array_make (pool, 1, sizeof (const char *));
636
 
  APR_ARRAY_PUSH (targets, const char *) = "";
 
636
  targets = apr_array_make(pool, 1, sizeof(const char *));
 
637
  APR_ARRAY_PUSH(targets, const char *) = "";
637
638
 
638
639
  /* Let the RA layer drive our log information handler, which will do
639
640
     the work of finding the actual locations for our resource.
640
641
     Notice that we always run on the youngest rev of the 3 inputs. */
641
 
  SVN_ERR (svn_ra_get_log (ra_session, targets, youngest, oldest, 0,
642
 
                           TRUE, FALSE, log_receiver, &lrb, pool));
 
642
  SVN_ERR(svn_ra_get_log(ra_session, targets, youngest, oldest, 0,
 
643
                         TRUE, FALSE, log_receiver, &lrb, pool));
643
644
 
644
645
  /* If the received log information did not cover any of the
645
646
     requested revisions, use the last known path.  (This normally
665
666
     the same as what we expected it to be. */
666
667
  if (! pegrev_is_youngest)
667
668
    {
668
 
      if (strcmp (abs_path, lrb.peg_path) != 0)
 
669
      if (strcmp(abs_path, lrb.peg_path) != 0)
669
670
        return svn_error_createf
670
671
          (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
671
672
           _("'%s' in revision %ld is an unrelated object"),
676
677
}
677
678
                
678
679
svn_error_t *
679
 
svn_client__repos_locations (const char **start_url,
680
 
                             svn_opt_revision_t **start_revision,
681
 
                             const char **end_url,
682
 
                             svn_opt_revision_t **end_revision,
683
 
                             const char *path,
684
 
                             const svn_opt_revision_t *revision,
685
 
                             const svn_opt_revision_t *start,
686
 
                             const svn_opt_revision_t *end,
687
 
                             svn_client_ctx_t *ctx,
688
 
                             apr_pool_t *pool)
 
680
svn_client__repos_locations(const char **start_url,
 
681
                            svn_opt_revision_t **start_revision,
 
682
                            const char **end_url,
 
683
                            svn_opt_revision_t **end_revision,
 
684
                            svn_ra_session_t *ra_session,
 
685
                            const char *path,
 
686
                            const svn_opt_revision_t *revision,
 
687
                            const svn_opt_revision_t *start,
 
688
                            const svn_opt_revision_t *end,
 
689
                            svn_client_ctx_t *ctx,
 
690
                            apr_pool_t *pool)
689
691
{
690
692
  const char *repos_url;
691
693
  const char *url;
695
697
  svn_revnum_t start_revnum, end_revnum;
696
698
  apr_array_header_t *revs;
697
699
  apr_hash_t *rev_locs;
698
 
  svn_ra_session_t *ra_session;
699
 
  apr_pool_t *subpool = svn_pool_create (pool);
 
700
  apr_pool_t *subpool = svn_pool_create(pool);
700
701
  svn_error_t *err;
701
702
 
702
703
  /* Ensure that we are given some real revision data to work with.
704
705
     set it to the same thing as START.)  */
705
706
  if (revision->kind == svn_opt_revision_unspecified
706
707
      || start->kind == svn_opt_revision_unspecified)
707
 
    return svn_error_create (SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);
 
708
    return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);
708
709
 
709
710
  /* Check to see if this is schedule add with history working copy
710
711
     path.  If it is, then we need to use the URL and peg revision of
711
712
     the copyfrom information. */
712
 
  if (! svn_path_is_url (path))
 
713
  if (! svn_path_is_url(path))
713
714
    {
714
715
      svn_wc_adm_access_t *adm_access;
715
716
      const svn_wc_entry_t *entry;
716
 
      SVN_ERR (svn_wc_adm_probe_open3 (&adm_access, NULL, path,
717
 
                                       FALSE, 0, ctx->cancel_func,
718
 
                                       ctx->cancel_baton, pool));
719
 
      SVN_ERR (svn_wc_entry (&entry, path, adm_access, FALSE, pool));
720
 
      SVN_ERR (svn_wc_adm_close (adm_access));
 
717
      SVN_ERR(svn_wc_adm_probe_open3(&adm_access, NULL, path,
 
718
                                     FALSE, 0, ctx->cancel_func,
 
719
                                     ctx->cancel_baton, pool));
 
720
      SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool));
 
721
      SVN_ERR(svn_wc_adm_close(adm_access));
721
722
      if (entry->copyfrom_url && revision->kind == svn_opt_revision_working)
722
723
        {
723
724
          url = entry->copyfrom_url;
724
725
          peg_revnum = entry->copyfrom_rev;
 
726
          if (!entry->url || strcmp(entry->url, entry->copyfrom_url) != 0)
 
727
            {
 
728
              /* We can't use the caller provided RA session in this case */
 
729
              ra_session = NULL;
 
730
            }
725
731
        }
726
732
      else if (entry->url)
727
733
        {
729
735
        }
730
736
      else
731
737
        {
732
 
          return svn_error_createf (SVN_ERR_ENTRY_MISSING_URL, NULL,
733
 
                                    _("'%s' has no URL"),
734
 
                                    svn_path_local_style (path, pool));
 
738
          return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
 
739
                                   _("'%s' has no URL"),
 
740
                                   svn_path_local_style(path, pool));
735
741
        }
736
742
    }
737
743
  else
743
749
     WORKING revisions, we should already have the correct URL:s, so we
744
750
     don't need to do anything more here in that case. */
745
751
 
746
 
  /* Open a RA session to this URL. */
747
 
  SVN_ERR (svn_client__open_ra_session_internal (&ra_session, url, NULL,
 
752
  /* Open a RA session to this URL if we don't have one already. */
 
753
  if (! ra_session)
 
754
    SVN_ERR(svn_client__open_ra_session_internal(&ra_session, url, NULL,
748
755
                                                 NULL, NULL, FALSE, TRUE,
749
756
                                                 ctx, subpool));
750
757
 
751
758
  /* Resolve the opt_revision_ts. */
752
759
  if (peg_revnum == SVN_INVALID_REVNUM)
753
 
    SVN_ERR (svn_client__get_revision_number (&peg_revnum,
754
 
                                              ra_session, revision, path,
755
 
                                              pool));
 
760
    SVN_ERR(svn_client__get_revision_number(&peg_revnum,
 
761
                                            ra_session, revision, path,
 
762
                                            pool));
756
763
  
757
 
  SVN_ERR (svn_client__get_revision_number (&start_revnum,
758
 
                                            ra_session, start, path, pool));
 
764
  SVN_ERR(svn_client__get_revision_number(&start_revnum,
 
765
                                          ra_session, start, path, pool));
759
766
  if (end->kind == svn_opt_revision_unspecified)
760
767
    end_revnum = start_revnum;
761
768
  else
762
 
    SVN_ERR (svn_client__get_revision_number (&end_revnum,
763
 
                                              ra_session, end, path, pool));
 
769
    SVN_ERR(svn_client__get_revision_number(&end_revnum,
 
770
                                            ra_session, end, path, pool));
764
771
 
765
772
  /* Set the output revision variables. */
766
 
  *start_revision = apr_pcalloc (pool, sizeof (**start_revision));
 
773
  *start_revision = apr_pcalloc(pool, sizeof(**start_revision));
767
774
  (*start_revision)->kind = svn_opt_revision_number;
768
775
  (*start_revision)->value.number = start_revnum;
769
776
  if (end->kind != svn_opt_revision_unspecified)
770
777
    {
771
 
      *end_revision = apr_pcalloc (pool, sizeof (**end_revision));
 
778
      *end_revision = apr_pcalloc(pool, sizeof(**end_revision));
772
779
      (*end_revision)->kind = svn_opt_revision_number;
773
780
      (*end_revision)->value.number = end_revnum;
774
781
    }
779
786
      *start_url = url;
780
787
      if (end->kind != svn_opt_revision_unspecified)
781
788
        *end_url = url;
782
 
      svn_pool_destroy (subpool);
 
789
      svn_pool_destroy(subpool);
783
790
      return SVN_NO_ERROR;
784
791
    }
785
792
  
786
 
  SVN_ERR (svn_ra_get_repos_root (ra_session, &repos_url, subpool));
 
793
  SVN_ERR(svn_ra_get_repos_root(ra_session, &repos_url, subpool));
787
794
 
788
 
  revs = apr_array_make (subpool, 2, sizeof (svn_revnum_t));
789
 
  APR_ARRAY_PUSH (revs, svn_revnum_t) = start_revnum;
 
795
  revs = apr_array_make(subpool, 2, sizeof(svn_revnum_t));
 
796
  APR_ARRAY_PUSH(revs, svn_revnum_t) = start_revnum;
790
797
  if (end_revnum != start_revnum)
791
 
    APR_ARRAY_PUSH (revs, svn_revnum_t) = end_revnum;
 
798
    APR_ARRAY_PUSH(revs, svn_revnum_t) = end_revnum;
792
799
 
793
 
  if (! (err = svn_ra_get_locations (ra_session, &rev_locs, "", peg_revnum,
794
 
                                     revs, subpool)))
 
800
  if (! (err = svn_ra_get_locations(ra_session, &rev_locs, "", peg_revnum,
 
801
                                    revs, subpool)))
795
802
    {
796
 
      start_path = apr_hash_get (rev_locs, &start_revnum,
797
 
                                 sizeof (svn_revnum_t));
798
 
      end_path = apr_hash_get (rev_locs, &end_revnum, sizeof (svn_revnum_t));
 
803
      start_path = apr_hash_get(rev_locs, &start_revnum,
 
804
                                sizeof(svn_revnum_t));
 
805
      end_path = apr_hash_get(rev_locs, &end_revnum, sizeof(svn_revnum_t));
799
806
    }
800
807
  else if (err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)
801
808
    {
802
 
      svn_error_clear (err);
 
809
      svn_error_clear(err);
803
810
      /* Do it the slow way for 1.0.x servers. */
804
 
      SVN_ERR (slow_locations (&start_path, &end_path,
805
 
                               svn_path_uri_decode (url + strlen (repos_url),
806
 
                                                    subpool),
807
 
                               peg_revnum, start_revnum, end_revnum,
808
 
                               path, ra_session, ctx, subpool));
 
811
      SVN_ERR(slow_locations(&start_path, &end_path,
 
812
                             svn_path_uri_decode(url + strlen(repos_url),
 
813
                                                 subpool),
 
814
                             peg_revnum, start_revnum, end_revnum,
 
815
                             path, ra_session, ctx, subpool));
809
816
    }
810
817
  else
811
818
    return err;
832
839
    end_path = end_path + 1;
833
840
 
834
841
  /* Set our return variables */
835
 
  *start_url = svn_path_join (repos_url, svn_path_uri_encode (start_path,
836
 
                                                              pool), pool);
 
842
  *start_url = svn_path_join(repos_url, svn_path_uri_encode(start_path,
 
843
                                                            pool), pool);
837
844
  if (end->kind != svn_opt_revision_unspecified)
838
 
    *end_url = svn_path_join (repos_url, svn_path_uri_encode (end_path,
839
 
                                                              pool), pool);
 
845
    *end_url = svn_path_join(repos_url, svn_path_uri_encode(end_path,
 
846
                                                            pool), pool);
840
847
  
841
 
  svn_pool_destroy (subpool);
 
848
  svn_pool_destroy(subpool);
842
849
  return SVN_NO_ERROR;
843
850
}
844
851
 
845
852
 
846
853
 
847
854
svn_error_t *
848
 
svn_client__ra_session_from_path (svn_ra_session_t **ra_session_p,
849
 
                                  svn_revnum_t *rev_p,
850
 
                                  const char **url_p,
851
 
                                  const char *path_or_url,
852
 
                                  const svn_opt_revision_t *peg_revision_p,
853
 
                                  const svn_opt_revision_t *revision,
854
 
                                  svn_client_ctx_t *ctx,
855
 
                                  apr_pool_t *pool)
 
855
svn_client__ra_session_from_path(svn_ra_session_t **ra_session_p,
 
856
                                 svn_revnum_t *rev_p,
 
857
                                 const char **url_p,
 
858
                                 const char *path_or_url,
 
859
                                 const svn_opt_revision_t *peg_revision_p,
 
860
                                 const svn_opt_revision_t *revision,
 
861
                                 svn_client_ctx_t *ctx,
 
862
                                 apr_pool_t *pool)
856
863
{
857
864
  svn_ra_session_t *ra_session;
858
865
  const char *initial_url, *url;
863
870
  svn_revnum_t rev;
864
871
  const char *ignored_url;
865
872
  
866
 
  SVN_ERR (svn_client_url_from_path (&initial_url, path_or_url, pool));
 
873
  SVN_ERR(svn_client_url_from_path(&initial_url, path_or_url, pool));
867
874
  if (! initial_url)
868
 
    return svn_error_createf (SVN_ERR_ENTRY_MISSING_URL, NULL,
869
 
                              _("'%s' has no URL"), path_or_url);
 
875
    return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
 
876
                             _("'%s' has no URL"), path_or_url);
870
877
 
871
878
  /* If a peg revision was specified, but a desired revision was not,
872
879
     assume it is the same as the peg revision. */
874
881
      peg_revision_p->kind != svn_opt_revision_unspecified)
875
882
    revision = peg_revision_p;
876
883
  
877
 
  if (svn_path_is_url (path_or_url))
 
884
  if (svn_path_is_url(path_or_url))
878
885
    {
879
886
      /* URLs get a default starting rev of HEAD. */
880
887
      if (revision->kind == svn_opt_revision_unspecified)
904
911
        peg_revision = *peg_revision_p;
905
912
    }
906
913
  
 
914
  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, initial_url,
 
915
                                               NULL, NULL, NULL,
 
916
                                               FALSE, FALSE, ctx, pool));
 
917
 
907
918
  dead_end_rev.kind = svn_opt_revision_unspecified;
908
919
  
909
920
  /* Run the history function to get the object's (possibly
910
921
     different) url in REVISION. */
911
 
  SVN_ERR (svn_client__repos_locations (&url, &new_rev,
912
 
                                        &ignored_url, &ignored_rev,
913
 
                                        path_or_url, &peg_revision,
914
 
                                        /* search range: */
915
 
                                        &start_rev, &dead_end_rev,
916
 
                                        ctx, pool));
 
922
  SVN_ERR(svn_client__repos_locations(&url, &new_rev,
 
923
                                      &ignored_url, &ignored_rev,
 
924
                                      ra_session,
 
925
                                      path_or_url, &peg_revision,
 
926
                                      /* search range: */
 
927
                                      &start_rev, &dead_end_rev,
 
928
                                      ctx, pool));
917
929
  good_rev = new_rev;
918
930
 
919
 
  SVN_ERR (svn_client__open_ra_session_internal (&ra_session, url,
920
 
                                                 NULL, NULL, NULL,
921
 
                                                 FALSE, FALSE, ctx, pool));
 
931
  /* Make the session point to the real URL. */
 
932
  SVN_ERR(svn_ra_reparent(ra_session, url, pool));
922
933
 
923
934
  /* Resolve good_rev into a real revnum. */
924
 
  SVN_ERR (svn_client__get_revision_number (&rev, ra_session,
925
 
                                            good_rev, url, pool));
926
 
  if (! SVN_IS_VALID_REVNUM (rev))
927
 
    SVN_ERR (svn_ra_get_latest_revnum (ra_session, &rev, pool));
 
935
  SVN_ERR(svn_client__get_revision_number(&rev, ra_session,
 
936
                                          good_rev, url, pool));
 
937
  if (! SVN_IS_VALID_REVNUM(rev))
 
938
    SVN_ERR(svn_ra_get_latest_revnum(ra_session, &rev, pool));
928
939
 
929
940
  *ra_session_p = ra_session;
930
941
  *rev_p = rev;