Reorganize the output to "svnserve --help".
[svn.git] / subversion / libsvn_wc / util.c
blobf473d442691f5229d146c0c00cfb37c4ab990bb9
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.
7 * ====================================================================
8 * Copyright (c) 2000-2007 CollabNet. All rights reserved.
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.
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 * ====================================================================
24 #include <assert.h>
25 #include <apr_pools.h>
26 #include <apr_file_io.h>
27 #include "svn_io.h"
28 #include "svn_types.h"
29 #include "svn_error.h"
30 #include "svn_path.h"
31 #include "wc.h" /* just for prototypes of things in this .c file */
32 #include "private/svn_wc_private.h"
34 #include "svn_private_config.h"
37 svn_error_t *
38 svn_wc__ensure_directory(const char *path,
39 apr_pool_t *pool)
41 svn_node_kind_t kind;
42 svn_error_t *err = svn_io_check_path(path, &kind, pool);
44 if (err)
45 return err;
47 if (kind != svn_node_none && kind != svn_node_dir)
49 /* If got an error other than dir non-existence, then we can't
50 ensure this directory's existence, so just return the error.
51 Might happen if there's a file in the way, for example. */
52 return svn_error_createf(APR_ENOTDIR, NULL,
53 _("'%s' is not a directory"),
54 svn_path_local_style(path, pool));
56 else if (kind == svn_node_none)
58 /* The dir doesn't exist, and it's our job to change that. */
60 err = svn_io_dir_make(path, APR_OS_DEFAULT, pool);
62 if (err && !APR_STATUS_IS_ENOENT(err->apr_err))
64 /* Tried to create the dir, and encountered some problem
65 other than non-existence of intermediate dirs. We can't
66 ensure the desired directory's existence, so just return
67 the error. */
68 return err;
70 else if (err && APR_STATUS_IS_ENOENT(err->apr_err))
71 /* (redundant conditional and comment) */
73 /* Okay, so the problem is a missing intermediate
74 directory. We don't know which one, so we recursively
75 back up one level and try again. */
76 const char *shorter = svn_path_dirname(path, pool);
78 /* Clear the error. */
79 svn_error_clear(err);
81 if (shorter[0] == '\0')
83 /* A weird and probably rare situation. */
84 return svn_error_create(0, NULL,
85 _("Unable to make any directories"));
87 else /* We have a valid path, so recursively ensure it. */
89 err = svn_wc__ensure_directory(shorter, pool);
91 if (err)
92 return (err);
93 else
94 return svn_wc__ensure_directory(path, pool);
98 if (err)
99 return err;
101 else /* No problem, the dir already existed, so just leave. */
102 assert(kind == svn_node_dir);
104 return SVN_NO_ERROR;
107 /* Return the library version number. */
108 const svn_version_t *
109 svn_wc_version(void)
111 SVN_VERSION_BODY;
114 svn_wc_notify_t *
115 svn_wc_create_notify(const char *path,
116 svn_wc_notify_action_t action,
117 apr_pool_t *pool)
119 svn_wc_notify_t *ret = apr_palloc(pool, sizeof(*ret));
120 ret->path = path;
121 ret->action = action;
122 ret->kind = svn_node_unknown;
123 ret->mime_type = NULL;
124 ret->lock = NULL;
125 ret->err = SVN_NO_ERROR;
126 ret->content_state = ret->prop_state = svn_wc_notify_state_unknown;
127 ret->lock_state = svn_wc_notify_lock_state_unknown;
128 ret->revision = SVN_INVALID_REVNUM;
129 ret->changelist_name = NULL;
130 ret->merge_range = NULL;
132 return ret;
135 /* Pool cleanup function to clear an svn_error_t *. */
136 static apr_status_t err_cleanup(void *data)
138 svn_error_clear(data);
140 return APR_SUCCESS;
143 svn_wc_notify_t *
144 svn_wc_dup_notify(const svn_wc_notify_t *notify,
145 apr_pool_t *pool)
147 svn_wc_notify_t *ret = apr_palloc(pool, sizeof(*ret));
149 *ret = *notify;
151 if (ret->path)
152 ret->path = apr_pstrdup(pool, ret->path);
153 if (ret->mime_type)
154 ret->mime_type = apr_pstrdup(pool, ret->mime_type);
155 if (ret->lock)
156 ret->lock = svn_lock_dup(ret->lock, pool);
157 if (ret->err)
159 ret->err = svn_error_dup(ret->err);
160 apr_pool_cleanup_register(pool, ret->err, err_cleanup,
161 apr_pool_cleanup_null);
163 if (ret->changelist_name)
164 ret->changelist_name = apr_pstrdup(pool, ret->changelist_name);
165 if (ret->merge_range)
166 ret->merge_range = svn_merge_range_dup(ret->merge_range, pool);
168 return ret;
171 svn_error_t *
172 svn_wc_external_item_create(const svn_wc_external_item2_t **item,
173 apr_pool_t *pool)
175 *item = apr_pcalloc(pool, sizeof(svn_wc_external_item2_t));
176 return SVN_NO_ERROR;
179 svn_wc_external_item_t *
180 svn_wc_external_item_dup(const svn_wc_external_item_t *item,
181 apr_pool_t *pool)
183 svn_wc_external_item_t *new_item = apr_palloc(pool, sizeof(*new_item));
185 *new_item = *item;
187 if (new_item->target_dir)
188 new_item->target_dir = apr_pstrdup(pool, new_item->target_dir);
190 if (new_item->url)
191 new_item->url = apr_pstrdup(pool, new_item->url);
193 return new_item;
196 svn_wc_external_item2_t *
197 svn_wc_external_item2_dup(const svn_wc_external_item2_t *item,
198 apr_pool_t *pool)
200 svn_wc_external_item2_t *new_item = apr_palloc(pool, sizeof(*new_item));
202 *new_item = *item;
204 if (new_item->target_dir)
205 new_item->target_dir = apr_pstrdup(pool, new_item->target_dir);
207 if (new_item->url)
208 new_item->url = apr_pstrdup(pool, new_item->url);
210 return new_item;
213 void svn_wc__compat_call_notify_func(void *baton,
214 const svn_wc_notify_t *n,
215 apr_pool_t *pool)
217 svn_wc__compat_notify_baton_t *nb = baton;
219 if (nb->func)
220 (*nb->func)(nb->baton, n->path, n->action, n->kind, n->mime_type,
221 n->content_state, n->prop_state, n->revision);
224 svn_boolean_t
225 svn_wc_match_ignore_list(const char *str, apr_array_header_t *list,
226 apr_pool_t *pool)
228 /* For now, we simply forward to svn_cstring_match_glob_list. In the
229 future, if we support more complex ignore patterns, we would iterate
230 over 'list' ourselves, and decide for each pattern how to handle
231 it. */
233 return svn_cstring_match_glob_list(str, list);
236 svn_error_t *
237 svn_wc__path_switched(const char *wc_path,
238 svn_boolean_t *switched,
239 const svn_wc_entry_t *entry,
240 apr_pool_t *pool)
242 const char *wc_parent_path, *parent_child_url;
243 const svn_wc_entry_t *parent_entry;
244 svn_wc_adm_access_t *parent_adm_access;
245 svn_error_t *err;
247 SVN_ERR(svn_path_get_absolute(&wc_path, wc_path, pool));
249 if (svn_dirent_is_root(wc_path, strlen(wc_path)))
251 *switched = FALSE;
252 return SVN_NO_ERROR;
255 wc_parent_path = svn_path_dirname(wc_path, pool);
256 err = svn_wc_adm_open3(&parent_adm_access, NULL, wc_parent_path, FALSE, 0,
257 NULL, NULL, pool);
259 if (err)
261 if (err->apr_err == SVN_ERR_WC_NOT_DIRECTORY)
263 svn_error_clear(err);
264 err = SVN_NO_ERROR;
265 *switched = FALSE;
268 return err;
271 SVN_ERR(svn_wc__entry_versioned(&parent_entry, wc_parent_path,
272 parent_adm_access, FALSE, pool));
273 SVN_ERR(svn_wc_adm_close(parent_adm_access));
275 /* Without complete entries (and URLs) for WC_PATH and it's parent
276 we return SVN_ERR_ENTRY_MISSING_URL. */
277 if (!parent_entry->url || !entry->url)
279 const char *no_url_path = parent_entry->url ? wc_path : wc_parent_path;
280 return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
281 _("Cannot find a URL for '%s'"),
282 svn_path_local_style(no_url_path, pool));
285 parent_child_url
286 = svn_path_url_add_component(parent_entry->url,
287 svn_path_basename(wc_path, pool), pool);
288 *switched = strcmp(parent_child_url, entry->url) != 0;
290 return SVN_NO_ERROR;