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 * ====================================================================
25 #include <apr_pools.h>
26 #include <apr_file_io.h>
28 #include "svn_types.h"
29 #include "svn_error.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"
38 svn_wc__ensure_directory(const char *path
,
42 svn_error_t
*err
= svn_io_check_path(path
, &kind
, pool
);
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
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. */
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
);
94 return svn_wc__ensure_directory(path
, pool
);
101 else /* No problem, the dir already existed, so just leave. */
102 assert(kind
== svn_node_dir
);
107 /* Return the library version number. */
108 const svn_version_t
*
115 svn_wc_create_notify(const char *path
,
116 svn_wc_notify_action_t action
,
119 svn_wc_notify_t
*ret
= apr_palloc(pool
, sizeof(*ret
));
121 ret
->action
= action
;
122 ret
->kind
= svn_node_unknown
;
123 ret
->mime_type
= 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
;
135 /* Pool cleanup function to clear an svn_error_t *. */
136 static apr_status_t
err_cleanup(void *data
)
138 svn_error_clear(data
);
144 svn_wc_dup_notify(const svn_wc_notify_t
*notify
,
147 svn_wc_notify_t
*ret
= apr_palloc(pool
, sizeof(*ret
));
152 ret
->path
= apr_pstrdup(pool
, ret
->path
);
154 ret
->mime_type
= apr_pstrdup(pool
, ret
->mime_type
);
156 ret
->lock
= svn_lock_dup(ret
->lock
, pool
);
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
);
172 svn_wc_external_item_create(const svn_wc_external_item2_t
**item
,
175 *item
= apr_pcalloc(pool
, sizeof(svn_wc_external_item2_t
));
179 svn_wc_external_item_t
*
180 svn_wc_external_item_dup(const svn_wc_external_item_t
*item
,
183 svn_wc_external_item_t
*new_item
= apr_palloc(pool
, sizeof(*new_item
));
187 if (new_item
->target_dir
)
188 new_item
->target_dir
= apr_pstrdup(pool
, new_item
->target_dir
);
191 new_item
->url
= apr_pstrdup(pool
, new_item
->url
);
196 svn_wc_external_item2_t
*
197 svn_wc_external_item2_dup(const svn_wc_external_item2_t
*item
,
200 svn_wc_external_item2_t
*new_item
= apr_palloc(pool
, sizeof(*new_item
));
204 if (new_item
->target_dir
)
205 new_item
->target_dir
= apr_pstrdup(pool
, new_item
->target_dir
);
208 new_item
->url
= apr_pstrdup(pool
, new_item
->url
);
213 void svn_wc__compat_call_notify_func(void *baton
,
214 const svn_wc_notify_t
*n
,
217 svn_wc__compat_notify_baton_t
*nb
= baton
;
220 (*nb
->func
)(nb
->baton
, n
->path
, n
->action
, n
->kind
, n
->mime_type
,
221 n
->content_state
, n
->prop_state
, n
->revision
);
225 svn_wc_match_ignore_list(const char *str
, apr_array_header_t
*list
,
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
233 return svn_cstring_match_glob_list(str
, list
);
237 svn_wc__path_switched(const char *wc_path
,
238 svn_boolean_t
*switched
,
239 const svn_wc_entry_t
*entry
,
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
;
247 SVN_ERR(svn_path_get_absolute(&wc_path
, wc_path
, pool
));
249 if (svn_dirent_is_root(wc_path
, strlen(wc_path
)))
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,
261 if (err
->apr_err
== SVN_ERR_WC_NOT_DIRECTORY
)
263 svn_error_clear(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
));
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;