source: valtobtest/subversion-1.6.2/subversion/libsvn_wc/util.c @ 3

Last change on this file since 3 was 3, checked in by valtob, 15 years ago

subversion source 1.6.2 as test

File size: 13.6 KB
Line 
1/*
2 * util.c:  general routines defying categorization; eventually I
3 *          suspect they'll end up in libsvn_subr, but don't want to
4 *          pollute that right now.  Note that nothing in here is
5 *          specific to working copies.
6 *
7 * ====================================================================
8 * Copyright (c) 2000-2007 CollabNet.  All rights reserved.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution.  The terms
12 * are also available at http://subversion.tigris.org/license-1.html.
13 * If newer versions of this license are posted there, you may use a
14 * newer version instead, at your option.
15 *
16 * This software consists of voluntary contributions made by many
17 * individuals.  For exact contribution history, see the revision
18 * history and logs, available at http://subversion.tigris.org/.
19 * ====================================================================
20 */
21
22#include <apr_pools.h>
23#include <apr_file_io.h>
24
25#include "svn_io.h"
26#include "svn_types.h"
27#include "svn_error.h"
28#include "svn_dirent_uri.h"
29#include "svn_path.h"
30#include "svn_props.h"
31
32#include "wc.h"   /* just for prototypes of things in this .c file */
33#include "private/svn_wc_private.h"
34
35#include "svn_private_config.h"
36
37
38svn_error_t *
39svn_wc__ensure_directory(const char *path,
40                         apr_pool_t *pool)
41{
42  svn_node_kind_t kind;
43  svn_error_t *err = svn_io_check_path(path, &kind, pool);
44
45  if (err)
46    return err;
47
48  if (kind != svn_node_none && kind != svn_node_dir)
49    {
50      /* If got an error other than dir non-existence, then we can't
51         ensure this directory's existence, so just return the error.
52         Might happen if there's a file in the way, for example. */
53      return svn_error_createf(APR_ENOTDIR, NULL,
54                               _("'%s' is not a directory"),
55                               svn_path_local_style(path, pool));
56    }
57  else if (kind == svn_node_none)
58    {
59      /* The dir doesn't exist, and it's our job to change that. */
60
61      err = svn_io_dir_make(path, APR_OS_DEFAULT, pool);
62
63      if (err && !APR_STATUS_IS_ENOENT(err->apr_err))
64        {
65          /* Tried to create the dir, and encountered some problem
66             other than non-existence of intermediate dirs.  We can't
67             ensure the desired directory's existence, so just return
68             the error. */
69          return err;
70        }
71      else if (err && APR_STATUS_IS_ENOENT(err->apr_err))
72        /* (redundant conditional and comment) */
73        {
74          /* Okay, so the problem is a missing intermediate
75             directory.  We don't know which one, so we recursively
76             back up one level and try again. */
77          const char *shorter = svn_path_dirname(path, pool);
78
79          /* Clear the error. */
80          svn_error_clear(err);
81
82          if (shorter[0] == '\0')
83            {
84              /* A weird and probably rare situation. */
85              return svn_error_create(0, NULL,
86                                      _("Unable to make any directories"));
87            }
88          else  /* We have a valid path, so recursively ensure it. */
89            {
90              err = svn_wc__ensure_directory(shorter, pool);
91
92              if (err)
93                return (err);
94              else
95                return svn_wc__ensure_directory(path, pool);
96            }
97        }
98
99      if (err)
100        return err;
101    }
102  else  /* No problem, the dir already existed, so just leave. */
103    SVN_ERR_ASSERT(kind == svn_node_dir);
104
105  return SVN_NO_ERROR;
106}
107
108/* Return the library version number. */
109const svn_version_t *
110svn_wc_version(void)
111{
112  SVN_VERSION_BODY;
113}
114
115svn_wc_notify_t *
116svn_wc_create_notify(const char *path,
117                     svn_wc_notify_action_t action,
118                     apr_pool_t *pool)
119{
120  svn_wc_notify_t *ret = apr_pcalloc(pool, sizeof(*ret));
121  ret->path = path;
122  ret->action = action;
123  ret->kind = svn_node_unknown;
124  ret->content_state = ret->prop_state = svn_wc_notify_state_unknown;
125  ret->lock_state = svn_wc_notify_lock_state_unknown;
126  ret->revision = SVN_INVALID_REVNUM;
127
128  return ret;
129}
130
131svn_wc_notify_t *
132svn_wc_create_notify_url(const char *url,
133                         svn_wc_notify_action_t action,
134                         apr_pool_t *pool)
135{
136  svn_wc_notify_t *ret = svn_wc_create_notify(".", action, pool);
137  ret->url = url;
138
139  return ret;
140}
141
142/* Pool cleanup function to clear an svn_error_t *. */
143static apr_status_t err_cleanup(void *data)
144{
145  svn_error_clear(data);
146
147  return APR_SUCCESS;
148}
149
150svn_wc_notify_t *
151svn_wc_dup_notify(const svn_wc_notify_t *notify,
152                  apr_pool_t *pool)
153{
154  svn_wc_notify_t *ret = apr_palloc(pool, sizeof(*ret));
155
156  *ret = *notify;
157
158  if (ret->path)
159    ret->path = apr_pstrdup(pool, ret->path);
160  if (ret->mime_type)
161    ret->mime_type = apr_pstrdup(pool, ret->mime_type);
162  if (ret->lock)
163    ret->lock = svn_lock_dup(ret->lock, pool);
164  if (ret->err)
165    {
166      ret->err = svn_error_dup(ret->err);
167      apr_pool_cleanup_register(pool, ret->err, err_cleanup,
168                                apr_pool_cleanup_null);
169    }
170  if (ret->changelist_name)
171    ret->changelist_name = apr_pstrdup(pool, ret->changelist_name);
172  if (ret->merge_range)
173    ret->merge_range = svn_merge_range_dup(ret->merge_range, pool);
174  if (ret->url)
175    ret->url = apr_pstrdup(pool, ret->url);
176  if (ret->path_prefix)
177    ret->path_prefix = apr_pstrdup(pool, ret->path_prefix);
178  if (ret->prop_name)
179    ret->prop_name = apr_pstrdup(pool, ret->prop_name);
180  if (ret->rev_props)
181    ret->rev_props = svn_prop_hash_dup(ret->rev_props, pool);
182
183  return ret;
184}
185
186svn_error_t *
187svn_wc_external_item_create(const svn_wc_external_item2_t **item,
188                            apr_pool_t *pool)
189{
190  *item = apr_pcalloc(pool, sizeof(svn_wc_external_item2_t));
191  return SVN_NO_ERROR;
192}
193
194svn_wc_external_item_t *
195svn_wc_external_item_dup(const svn_wc_external_item_t *item,
196                         apr_pool_t *pool)
197{
198  svn_wc_external_item_t *new_item = apr_palloc(pool, sizeof(*new_item));
199
200  *new_item = *item;
201
202  if (new_item->target_dir)
203    new_item->target_dir = apr_pstrdup(pool, new_item->target_dir);
204
205  if (new_item->url)
206    new_item->url = apr_pstrdup(pool, new_item->url);
207
208  return new_item;
209}
210
211svn_wc_external_item2_t *
212svn_wc_external_item2_dup(const svn_wc_external_item2_t *item,
213                          apr_pool_t *pool)
214{
215  svn_wc_external_item2_t *new_item = apr_palloc(pool, sizeof(*new_item));
216
217  *new_item = *item;
218
219  if (new_item->target_dir)
220    new_item->target_dir = apr_pstrdup(pool, new_item->target_dir);
221
222  if (new_item->url)
223    new_item->url = apr_pstrdup(pool, new_item->url);
224
225  return new_item;
226}
227
228void svn_wc__compat_call_notify_func(void *baton,
229                                     const svn_wc_notify_t *n,
230                                     apr_pool_t *pool)
231{
232  svn_wc__compat_notify_baton_t *nb = baton;
233
234  if (nb->func)
235    (*nb->func)(nb->baton, n->path, n->action, n->kind, n->mime_type,
236                n->content_state, n->prop_state, n->revision);
237}
238
239svn_boolean_t
240svn_wc_match_ignore_list(const char *str, apr_array_header_t *list,
241                         apr_pool_t *pool)
242{
243  /* For now, we simply forward to svn_cstring_match_glob_list. In the
244     future, if we support more complex ignore patterns, we would iterate
245     over 'list' ourselves, and decide for each pattern how to handle
246     it. */
247
248  return svn_cstring_match_glob_list(str, list);
249}
250
251svn_error_t *
252svn_wc__path_switched(const char *wc_path,
253                      svn_boolean_t *switched,
254                      const svn_wc_entry_t *entry,
255                      apr_pool_t *pool)
256{
257  const char *wc_parent_path, *parent_child_url;
258  const svn_wc_entry_t *parent_entry;
259  svn_wc_adm_access_t *parent_adm_access;
260  svn_error_t *err;
261
262  SVN_ERR(svn_path_get_absolute(&wc_path, wc_path, pool));
263
264  if (svn_dirent_is_root(wc_path, strlen(wc_path)))
265    {
266      *switched = FALSE;
267      return SVN_NO_ERROR;
268    }
269
270  wc_parent_path = svn_path_dirname(wc_path, pool);
271  err = svn_wc_adm_open3(&parent_adm_access, NULL, wc_parent_path, FALSE, 0,
272                         NULL, NULL, pool);
273
274  if (err)
275    {
276      if (err->apr_err == SVN_ERR_WC_NOT_DIRECTORY)
277        {
278          svn_error_clear(err);
279          err = SVN_NO_ERROR;
280          *switched = FALSE;
281        }
282
283      return err;
284    }
285
286  SVN_ERR(svn_wc__entry_versioned(&parent_entry, wc_parent_path,
287                                  parent_adm_access, FALSE, pool));
288  SVN_ERR(svn_wc_adm_close2(parent_adm_access, pool));
289
290  /* Without complete entries (and URLs) for WC_PATH and it's parent
291     we return SVN_ERR_ENTRY_MISSING_URL. */
292  if (!parent_entry->url || !entry->url)
293    {
294      const char *no_url_path = parent_entry->url ? wc_path : wc_parent_path;
295      return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
296                               _("Cannot find a URL for '%s'"),
297                               svn_path_local_style(no_url_path, pool));
298    }
299
300  parent_child_url
301    = svn_path_url_add_component2(parent_entry->url,
302                                  svn_path_basename(wc_path, pool), pool);
303  *switched = strcmp(parent_child_url, entry->url) != 0;
304
305  return SVN_NO_ERROR;
306}
307
308svn_wc_conflict_description_t *
309svn_wc_conflict_description_create_text(const char *path,
310                                        svn_wc_adm_access_t *adm_access,
311                                        apr_pool_t *pool)
312{
313  svn_wc_conflict_description_t *conflict;
314
315  conflict = apr_pcalloc(pool, sizeof(*conflict));
316  conflict->path = path;
317  conflict->node_kind = svn_node_file;
318  conflict->kind = svn_wc_conflict_kind_text;
319  conflict->access = adm_access;
320  conflict->action = svn_wc_conflict_action_edit;
321  conflict->reason = svn_wc_conflict_reason_edited;
322  return conflict;
323}
324
325svn_wc_conflict_description_t *
326svn_wc_conflict_description_create_prop(const char *path,
327                                        svn_wc_adm_access_t *adm_access,
328                                        svn_node_kind_t node_kind,
329                                        const char *property_name,
330                                        apr_pool_t *pool)
331{
332  svn_wc_conflict_description_t *conflict;
333
334  conflict = apr_pcalloc(pool, sizeof(*conflict));
335  conflict->path = path;
336  conflict->node_kind = node_kind;
337  conflict->kind = svn_wc_conflict_kind_property;
338  conflict->access = adm_access;
339  conflict->property_name = property_name;
340  return conflict;
341}
342
343svn_wc_conflict_description_t *
344svn_wc_conflict_description_create_tree(
345                            const char *path,
346                            svn_wc_adm_access_t *adm_access,
347                            svn_node_kind_t node_kind,
348                            svn_wc_operation_t operation,
349                            svn_wc_conflict_version_t *src_left_version,
350                            svn_wc_conflict_version_t *src_right_version,
351                            apr_pool_t *pool)
352{
353  svn_wc_conflict_description_t *conflict;
354
355  conflict = apr_pcalloc(pool, sizeof(*conflict));
356  conflict->path = path;
357  conflict->node_kind = node_kind;
358  conflict->kind = svn_wc_conflict_kind_tree;
359  conflict->access = adm_access;
360  conflict->operation = operation;
361  conflict->src_left_version = src_left_version;
362  conflict->src_right_version = src_right_version;
363  return conflict;
364}
365
366svn_wc_conflict_description_t *
367svn_wc__conflict_description_dup(const svn_wc_conflict_description_t *conflict,
368                                 apr_pool_t *pool)
369{
370  svn_wc_conflict_description_t *new_conflict;
371
372  new_conflict = apr_pcalloc(pool, sizeof(*new_conflict));
373
374  /* Shallow copy all members. */
375  *new_conflict = *conflict;
376
377  if (conflict->path)
378    new_conflict->path = apr_pstrdup(pool, conflict->path);
379  if (conflict->property_name)
380    new_conflict->property_name = apr_pstrdup(pool, conflict->property_name);
381  if (conflict->mime_type)
382    new_conflict->mime_type = apr_pstrdup(pool, conflict->mime_type);
383  /* NOTE: We cannot make a deep copy of adm_access. */
384  if (conflict->base_file)
385    new_conflict->base_file = apr_pstrdup(pool, conflict->base_file);
386  if (conflict->their_file)
387    new_conflict->their_file = apr_pstrdup(pool, conflict->their_file);
388  if (conflict->my_file)
389    new_conflict->my_file = apr_pstrdup(pool, conflict->my_file);
390  if (conflict->merged_file)
391    new_conflict->merged_file = apr_pstrdup(pool, conflict->merged_file);
392  if (conflict->src_left_version)
393    new_conflict->src_left_version =
394      svn_wc_conflict_version_dup(conflict->src_left_version, pool);
395  if (conflict->src_right_version)
396    new_conflict->src_right_version =
397      svn_wc_conflict_version_dup(conflict->src_right_version, pool);
398
399  return new_conflict;
400}
401
402svn_wc_conflict_version_t *
403svn_wc_conflict_version_create(const char *repos_url,
404                               const char* path_in_repos,
405                               svn_revnum_t peg_rev,
406                               svn_node_kind_t node_kind,
407                               apr_pool_t *pool)
408{
409  svn_wc_conflict_version_t *version;
410
411  version = apr_pcalloc(pool, sizeof(*version));
412
413  version->repos_url = repos_url;
414  version->peg_rev = peg_rev;
415  version->path_in_repos = path_in_repos;
416  version->node_kind = node_kind;
417
418  return version;
419}
420
421
422svn_wc_conflict_version_t *
423svn_wc_conflict_version_dup(const svn_wc_conflict_version_t *version,
424                            apr_pool_t *pool)
425{
426
427  svn_wc_conflict_version_t *new_version;
428
429  new_version = apr_pcalloc(pool, sizeof(*new_version));
430
431  /* Shallow copy all members. */
432  *new_version = *version;
433
434  if (version->repos_url)
435    new_version->repos_url = apr_pstrdup(pool, version->repos_url);
436
437  if (version->path_in_repos)
438    new_version->path_in_repos = apr_pstrdup(pool, version->path_in_repos);
439
440  return new_version;
441}
442
Note: See TracBrowser for help on using the repository browser.