~svn/ubuntu/raring/subversion/ppa

« back to all changes in this revision

Viewing changes to subversion/libsvn_client/switch.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-12-05 01:26:14 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051205012614-qom4xfypgtsqc2xq
Tags: 1.2.3dfsg1-3ubuntu1
Merge with the final Debian release of 1.2.3dfsg1-3, bringing in
fixes to the clean target, better documentation of the libdb4.3
upgrade and build fixes to work with swig1.3_1.3.27.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * switch.c:  implement 'switch' feature via WC & RA interfaces.
 
3
 *
 
4
 * ====================================================================
 
5
 * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
 
6
 *
 
7
 * This software is licensed as described in the file COPYING, which
 
8
 * you should have received as part of this distribution.  The terms
 
9
 * are also available at http://subversion.tigris.org/license-1.html.
 
10
 * If newer versions of this license are posted there, you may use a
 
11
 * newer version instead, at your option.
 
12
 *
 
13
 * This software consists of voluntary contributions made by many
 
14
 * individuals.  For exact contribution history, see the revision
 
15
 * history and logs, available at http://subversion.tigris.org/.
 
16
 * ====================================================================
 
17
 */
 
18
 
 
19
/* ==================================================================== */
 
20
 
 
21
 
 
22
 
 
23
/*** Includes. ***/
 
24
 
 
25
#include <assert.h>
 
26
 
 
27
#include "svn_wc.h"
 
28
#include "svn_client.h"
 
29
#include "svn_error.h"
 
30
#include "svn_time.h"
 
31
#include "svn_path.h"
 
32
#include "svn_config.h"
 
33
#include "client.h"
 
34
 
 
35
#include "svn_private_config.h"
 
36
 
 
37
 
 
38
/*** Code. ***/
 
39
 
 
40
/* This feature is essentially identical to 'svn update' (see
 
41
   ./update.c), but with two differences:
 
42
 
 
43
     - the reporter->finish_report() routine needs to make the server
 
44
       run delta_dirs() on two *different* paths, rather than on two
 
45
       identical paths.
 
46
 
 
47
     - after the update runs, we need to more than just
 
48
       ensure_uniform_revision;  we need to rewrite all the entries'
 
49
       URL attributes.
 
50
*/
 
51
 
 
52
 
 
53
svn_error_t *
 
54
svn_client_switch (svn_revnum_t *result_rev,
 
55
                   const char *path,
 
56
                   const char *switch_url,
 
57
                   const svn_opt_revision_t *revision,
 
58
                   svn_boolean_t recurse,
 
59
                   svn_client_ctx_t *ctx,
 
60
                   apr_pool_t *pool)
 
61
{
 
62
  const svn_ra_reporter2_t *reporter;
 
63
  void *report_baton;
 
64
  const svn_wc_entry_t *entry;
 
65
  const char *URL, *anchor, *target;
 
66
  svn_ra_session_t *ra_session;
 
67
  svn_revnum_t revnum;
 
68
  svn_error_t *err = SVN_NO_ERROR;
 
69
  svn_wc_adm_access_t *adm_access, *dir_access;
 
70
  const char *diff3_cmd;
 
71
  svn_boolean_t timestamp_sleep = FALSE;  
 
72
  svn_boolean_t use_commit_times;
 
73
  const svn_delta_editor_t *switch_editor;
 
74
  void *switch_edit_baton;
 
75
  svn_wc_traversal_info_t *traversal_info = svn_wc_init_traversal_info (pool);
 
76
  svn_config_t *cfg = ctx->config ? apr_hash_get (ctx->config, 
 
77
                                                  SVN_CONFIG_CATEGORY_CONFIG,  
 
78
                                                  APR_HASH_KEY_STRING)
 
79
                                  : NULL;
 
80
  
 
81
  /* Get the external diff3, if any. */
 
82
  svn_config_get (cfg, &diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
 
83
                  SVN_CONFIG_OPTION_DIFF3_CMD, NULL);
 
84
 
 
85
  /* See if the user wants last-commit timestamps instead of current ones. */
 
86
  SVN_ERR (svn_config_get_bool (cfg, &use_commit_times,
 
87
                                SVN_CONFIG_SECTION_MISCELLANY,
 
88
                                SVN_CONFIG_OPTION_USE_COMMIT_TIMES, FALSE));
 
89
 
 
90
  /* Sanity check.  Without these, the switch is meaningless. */
 
91
  assert (path);
 
92
  assert (switch_url && (switch_url[0] != '\0'));
 
93
 
 
94
  /* ### Need to lock the whole target tree to invalidate wcprops. Does
 
95
     non-recursive switch really need to invalidate the whole tree? */
 
96
  SVN_ERR (svn_wc_adm_open_anchor (&adm_access, &dir_access, &target, path,
 
97
                                   TRUE, -1, ctx->cancel_func,
 
98
                                   ctx->cancel_baton, pool));
 
99
  anchor = svn_wc_adm_access_path (adm_access);
 
100
 
 
101
  SVN_ERR (svn_wc_entry (&entry, anchor, adm_access, FALSE, pool));
 
102
  if (! entry)
 
103
    return svn_error_createf (SVN_ERR_UNVERSIONED_RESOURCE, NULL, 
 
104
                              _("'%s' is not under version control"),
 
105
                              svn_path_local_style (anchor, pool));
 
106
  if (! entry->url)
 
107
    return svn_error_createf (SVN_ERR_ENTRY_MISSING_URL, NULL,
 
108
                              _("Directory '%s' has no URL"),
 
109
                              svn_path_local_style (anchor, pool));
 
110
 
 
111
  URL = apr_pstrdup (pool, entry->url);
 
112
 
 
113
  /* Get revnum set to something meaningful, so we can fetch the
 
114
     switch editor. */
 
115
  if (revision->kind == svn_opt_revision_number)
 
116
    revnum = revision->value.number; /* do the trivial conversion manually */
 
117
  else
 
118
    revnum = SVN_INVALID_REVNUM; /* no matter, do real conversion later */
 
119
 
 
120
  /* Open an RA session to 'source' URL */
 
121
  SVN_ERR (svn_client__open_ra_session (&ra_session, URL, anchor, 
 
122
                                        adm_access, NULL, TRUE, FALSE, 
 
123
                                        ctx, pool));
 
124
  SVN_ERR (svn_client__get_revision_number
 
125
           (&revnum, ra_session, revision, path, pool));
 
126
 
 
127
  /* Fetch the switch (update) editor.  If REVISION is invalid, that's
 
128
     okay; the RA driver will call editor->set_target_revision() later on. */
 
129
  SVN_ERR (svn_wc_get_switch_editor2 (&revnum, adm_access, target,
 
130
                                      switch_url, use_commit_times, recurse,
 
131
                                      ctx->notify_func2, ctx->notify_baton2,
 
132
                                      ctx->cancel_func, ctx->cancel_baton,
 
133
                                      diff3_cmd,
 
134
                                      &switch_editor, &switch_edit_baton,
 
135
                                      traversal_info, pool));
 
136
 
 
137
  /* Tell RA to do an update of URL+TARGET to REVISION; if we pass an
 
138
     invalid revnum, that means RA will use the latest revision. */
 
139
  SVN_ERR (svn_ra_do_switch (ra_session, &reporter, &report_baton, revnum,
 
140
                             target, recurse, switch_url,
 
141
                             switch_editor, switch_edit_baton, pool));
 
142
 
 
143
  /* Drive the reporter structure, describing the revisions within
 
144
     PATH.  When we call reporter->finish_report, the update_editor
 
145
     will be driven by svn_repos_dir_delta.
 
146
 
 
147
     We pass NULL for traversal_info because this is a switch, not an
 
148
     update, and therefore we don't want to handle any externals
 
149
     except the ones directly affected by the switch. */ 
 
150
  err = svn_wc_crawl_revisions2 (path, dir_access, reporter, report_baton,
 
151
                                 TRUE, recurse, use_commit_times,
 
152
                                 ctx->notify_func2, ctx->notify_baton2,
 
153
                                 NULL, /* no traversal info */
 
154
                                 pool);
 
155
    
 
156
  /* We handle externals after the switch is complete, so that
 
157
     handling external items (and any errors therefrom) doesn't delay
 
158
     the primary operation.  We ignore the timestamp_sleep value since
 
159
     there is an unconditional sleep later on. */
 
160
  if (! err)
 
161
    err = svn_client__handle_externals (traversal_info, FALSE,
 
162
                                        &timestamp_sleep, ctx, pool);
 
163
 
 
164
  /* Sleep to ensure timestamp integrity (we do this regardless of
 
165
     errors in the actual switch operation(s)). */
 
166
  svn_sleep_for_timestamps ();
 
167
 
 
168
  /* Return errors we might have sustained. */
 
169
  if (err)
 
170
    return err;
 
171
 
 
172
  SVN_ERR (svn_wc_adm_close (adm_access));
 
173
 
 
174
  /* Let everyone know we're finished here. */
 
175
  if (ctx->notify_func2)
 
176
    {
 
177
      svn_wc_notify_t *notify
 
178
        = svn_wc_create_notify (anchor, svn_wc_notify_update_completed, pool);
 
179
      notify->kind = svn_node_none;
 
180
      notify->content_state = notify->prop_state
 
181
        = svn_wc_notify_state_inapplicable;
 
182
      notify->lock_state = svn_wc_notify_lock_state_inapplicable;
 
183
      notify->revision = revnum;
 
184
      (*ctx->notify_func2) (ctx->notify_baton2, notify, pool);
 
185
    }
 
186
 
 
187
  /* If the caller wants the result revision, give it to them. */
 
188
  if (result_rev)
 
189
    *result_rev = revnum;
 
190
  
 
191
  return SVN_NO_ERROR;
 
192
}