You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2012/08/16 12:18:03 UTC
svn commit: r1373783 [6/50] - in /subversion/branches/compressed-pristines:
./ build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/client-side/emacs/ contrib/client-side/svn-push/
contrib/client-side/svnmerge/ contr...
Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/client.h?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/client.h (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/client.h Thu Aug 16 10:17:48 2012
@@ -87,16 +87,18 @@ svn_client__get_revision_number(svn_revn
const svn_opt_revision_t *revision,
apr_pool_t *scratch_pool);
-/* Set *COPYFROM_PATH and *COPYFROM_REV to the path (without initial '/')
- and revision that served as the source of the copy from which PATH_OR_URL
- at REVISION was created, or NULL and SVN_INVALID_REVNUM (respectively) if
- PATH_OR_URL at REVISION was not the result of a copy operation. */
-svn_error_t *svn_client__get_copy_source(const char *path_or_url,
- const svn_opt_revision_t *revision,
- const char **copyfrom_path,
- svn_revnum_t *copyfrom_rev,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool);
+/* Set *ORIGINAL_REPOS_RELPATH and *ORIGINAL_REVISION to the original location
+ that served as the source of the copy from which PATH_OR_URL at REVISION was
+ created, or NULL and SVN_INVALID_REVNUM (respectively) if PATH_OR_URL at
+ REVISION was not the result of a copy operation. */
+svn_error_t *
+svn_client__get_copy_source(const char **original_repos_relpath,
+ svn_revnum_t *original_revision,
+ const char *path_or_url,
+ const svn_opt_revision_t *revision,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Set *START_URL and *START_REVISION (and maybe *END_URL
and *END_REVISION) to the revisions and repository URLs of one
@@ -198,6 +200,9 @@ svn_client__repos_location_segments(apr_
LOC1 and LOC2. If the locations have no common ancestor (including if
they don't have the same repository root URL), set *ANCESTOR_P to NULL.
+ If SESSION is not NULL, use it for retrieving the common ancestor instead
+ of creating a new session.
+
Use the authentication baton cached in CTX to authenticate against
the repository. Use POOL for all allocations.
@@ -207,6 +212,7 @@ svn_error_t *
svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
const svn_client__pathrev_t *loc1,
const svn_client__pathrev_t *loc2,
+ svn_ra_session_t *session,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
@@ -227,29 +233,15 @@ svn_client__get_youngest_common_ancestor
for a URL or 'working' for a WC path. If REVISION->kind is
'unspecified', the operative revision is the peg revision.
- Store the resulting ra_session in *RA_SESSION_P. Store the actual
- revision number of the object in *REV_P, and the final resulting
- URL in *URL_P. REV_P and/or URL_P may be NULL if not wanted.
+ Store the resulting ra_session in *RA_SESSION_P. Store the final
+ resolved location of the object in *RESOLVED_LOC_P. RESOLVED_LOC_P
+ may be NULL if not wanted.
Use authentication baton cached in CTX to authenticate against the
repository.
Use POOL for all allocations. */
svn_error_t *
-svn_client__ra_session_from_path(svn_ra_session_t **ra_session_p,
- svn_revnum_t *rev_p,
- const char **url_p,
- const char *path_or_url,
- const char *base_dir_abspath,
- const svn_opt_revision_t *peg_revision,
- const svn_opt_revision_t *revision,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool);
-
-/* Like svn_client__ra_session_from_path() but returning a path-rev
- * instead of separate URL and rev outputs. RESOLVED_LOC_P may be NULL
- * if not wanted. */
-svn_error_t *
svn_client__ra_session_from_path2(svn_ra_session_t **ra_session_p,
svn_client__pathrev_t **resolved_loc_p,
const char *path_or_url,
@@ -286,40 +278,6 @@ svn_client__ensure_ra_session_url(const
const char *session_url,
apr_pool_t *pool);
-/* Return the path of ABSPATH_OR_URL relative to the repository root
- in REL_PATH (URI-decoded), allocated in RESULT_POOL.
- If INCLUDE_LEADING_SLASH is set, the returned result will have a leading
- slash; otherwise, it will not.
-
- REPOS_ROOT and RA_SESSION may be NULL if ABSPATH_OR_URL is a WC path,
- otherwise at least one of them must be non-null.
-
- CAUTION: While having a leading slash on a so-called relative path
- might work out well for functionality that interacts with
- mergeinfo, it results in a relative path that cannot be naively
- svn_path_join()'d with a repository root URL to provide a full URL.
-
- Use SCRATCH_POOL for temporary allocations.
-*/
-svn_error_t *
-svn_client__path_relative_to_root(const char **rel_path,
- svn_wc_context_t *wc_ctx,
- const char *abspath_or_url,
- const char *repos_root,
- svn_boolean_t include_leading_slash,
- svn_ra_session_t *ra_session,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool);
-
-/* A default error handler for use with svn_wc_walk_entries3(). Returns
- ERR in all cases. */
-svn_error_t *
-svn_client__default_walker_error_handler(const char *path,
- svn_error_t *err,
- void *walk_baton,
- apr_pool_t *pool);
-
-
/* ---------------------------------------------------------------- */
/*** RA callbacks ***/
@@ -367,20 +325,36 @@ svn_client__open_ra_session_internal(svn
apr_pool_t *pool);
+svn_error_t *
+svn_client__ra_provide_base(svn_stream_t **contents,
+ svn_revnum_t *revision,
+ void *baton,
+ const char *repos_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
-/* ---------------------------------------------------------------- */
-
-/*** Status ***/
-/* Verify that the path can be deleted without losing stuff,
- i.e. ensure that there are no modified or unversioned resources
- under PATH. This is similar to checking the output of the status
- command. CTX is used for the client's config options. POOL is
- used for all temporary allocations. */
-svn_error_t * svn_client__can_delete(const char *path,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool);
+svn_error_t *
+svn_client__ra_provide_props(apr_hash_t **props,
+ svn_revnum_t *revision,
+ void *baton,
+ const char *repos_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+svn_error_t *
+svn_client__ra_get_copysrc_kind(svn_kind_t *kind,
+ void *baton,
+ const char *repos_relpath,
+ svn_revnum_t src_revision,
+ apr_pool_t *scratch_pool);
+
+
+void *
+svn_client__ra_make_cb_baton(svn_wc_context_t *wc_ctx,
+ apr_hash_t *relpath_map,
+ apr_pool_t *result_pool);
/* ---------------------------------------------------------------- */
@@ -879,10 +853,10 @@ svn_client__condense_commit_items(const
NOTIFY_PATH_PREFIX will be passed to CTX->notify_func2() as the
common absolute path prefix of the committed paths. It can be NULL.
- If MD5_CHECKSUMS is not NULL, set *MD5_CHECKSUMS to a hash containing,
+ If SHA1_CHECKSUMS is not NULL, set *SHA1_CHECKSUMS to a hash containing,
for each file transmitted, a mapping from the commit-item's (const
- char *) path to the (const svn_checksum_t *) MD5 checksum of its new text
- base. Similarly for SHA1_CHECKSUMS.
+ char *) path to the (const svn_checksum_t *) SHA1 checksum of its new text
+ base.
Use RESULT_POOL for all allocating the resulting hashes and SCRATCH_POOL
for temporary allocations.
@@ -893,7 +867,6 @@ svn_client__do_commit(const char *base_u
const svn_delta_editor_t *editor,
void *edit_baton,
const char *notify_path_prefix,
- apr_hash_t **md5_checksums,
apr_hash_t **sha1_checksums,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
@@ -976,11 +949,12 @@ svn_client__export_externals(apr_hash_t
apr_pool_t *pool);
-/* Perform status operations on each external in TRAVERSAL_INFO. All
- other options are the same as those passed to svn_client_status(). */
+/* Perform status operations on each external in EXTERNAL_MAP, a const char *
+ local_abspath of all externals mapping to the const char* defining_abspath.
+ All other options are the same as those passed to svn_client_status(). */
svn_error_t *
svn_client__do_external_status(svn_client_ctx_t *ctx,
- apr_hash_t *external_defs,
+ apr_hash_t *external_map,
svn_depth_t depth,
svn_boolean_t get_all,
svn_boolean_t update,
@@ -989,32 +963,6 @@ svn_client__do_external_status(svn_clien
void *status_baton,
apr_pool_t *pool);
-/* Baton type for svn_wc__external_info_gatherer(). */
-typedef struct svn_client__external_func_baton_t
-{
- apr_hash_t *externals_old; /* Hash of old externals property values,
- or NULL if the caller doesn't care. */
- apr_hash_t *externals_new; /* Hash of new externals property values,
- or NULL if the caller doesn't care. */
- apr_hash_t *ambient_depths; /* Hash of ambient depth values, or NULL
- if the caller doesn't care. */
- apr_pool_t *result_pool; /* Pool to use for all stored values. */
-
-} svn_client__external_func_baton_t;
-
-
-/* This function gets invoked whenever external changes are encountered.
- This implements the `svn_wc_external_update_t' interface, and can
- be used with an svn_client__external_func_baton_t BATON to gather
- information about changes to externals definitions. */
-svn_error_t *
-svn_client__external_info_gatherer(void *baton,
- const char *local_abspath,
- const svn_string_t *old_val,
- const svn_string_t *new_val,
- svn_depth_t depth,
- apr_pool_t *scratch_pool);
-
/* Baton for svn_client__dirent_fetcher */
struct svn_client__dirent_fetcher_baton_t
{
@@ -1082,7 +1030,7 @@ svn_client__get_normalized_stream(svn_st
/* Return a set of callbacks to use with the Ev2 shims. */
svn_delta_shim_callbacks_t *
svn_client__get_shim_callbacks(svn_wc_context_t *wc_ctx,
- const char *anchor_abspath,
+ apr_hash_t *relpath_map,
apr_pool_t *result_pool);
/* Return true if KIND is a revision kind that is dependent on the working
Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/commit.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/commit.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/commit.c Thu Aug 16 10:17:48 2012
@@ -49,6 +49,7 @@
#include "client.h"
#include "private/svn_wc_private.h"
+#include "private/svn_subr_private.h"
#include "private/svn_ra_private.h"
#include "private/svn_magic.h"
@@ -269,75 +270,48 @@ import_file(const svn_delta_editor_t *ed
/* Finally, close the file. */
text_checksum =
- svn_checksum_to_cstring(svn_checksum__from_digest(digest, svn_checksum_md5,
- pool), pool);
+ svn_checksum_to_cstring(svn_checksum__from_digest_md5(digest, pool), pool);
return editor->close_file(file_baton, text_checksum, pool);
}
-/* Import directory LOCAL_ABSPATH into the repository directory indicated by
- * DIR_BATON in EDITOR. EDIT_PATH is the path imported as the root
- * directory, so all edits are relative to that.
- *
- * DEPTH is the depth at this point in the descent (it may be changed
- * for recursive calls).
- *
- * Accumulate file paths and their batons in FILES, which must be
- * non-null. (These are used to send postfix textdeltas later).
- *
- * EXCLUDES is a hash whose keys are absolute paths to exclude from
- * the import (values are unused).
- *
- * If NO_IGNORE is FALSE, don't import files or directories that match
- * ignore patterns.
- *
- * If FILTER_CALLBACK is not NULL, call it with FILTER_BATON on each to be
- * imported node below LOCAL_ABSPATH to allow filtering nodes.
- *
- * If CTX->NOTIFY_FUNC is non-null, invoke it with CTX->NOTIFY_BATON for each
- * directory.
+/* Return in CHILDREN a mapping of basenames to dirents for the importable
+ * children of DIR_ABSPATH. EXCLUDES is a hash of absolute paths to filter
+ * out. IGNORES, if non-NULL, is a list of basenames to filter out.
+ * FILTER_CALLBACK and FILTER_BATON will be called for each absolute path,
+ * allowing users to further filter the list of returned entries.
*
- * Use POOL for any temporary allocation. */
+ * Results are returned in RESULT_POOL; use SCRATCH_POOL for temporary data.*/
static svn_error_t *
-import_dir(const svn_delta_editor_t *editor,
- void *dir_baton,
- const char *local_abspath,
- const char *edit_path,
- svn_depth_t depth,
- apr_hash_t *excludes,
- svn_boolean_t no_ignore,
- svn_boolean_t ignore_unknown_node_types,
- svn_client_import_filter_func_t filter_callback,
- void *filter_baton,
- import_ctx_t *import_ctx,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+get_filtered_children(apr_hash_t **children,
+ const char *dir_abspath,
+ apr_hash_t *excludes,
+ apr_array_header_t *ignores,
+ svn_client_import_filter_func_t filter_callback,
+ void *filter_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- apr_pool_t *subpool = svn_pool_create(pool); /* iteration pool */
apr_hash_t *dirents;
apr_hash_index_t *hi;
- apr_array_header_t *ignores;
-
- SVN_ERR(svn_path_check_valid(local_abspath, pool));
-
- if (!no_ignore)
- SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, pool));
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- SVN_ERR(svn_io_get_dirents3(&dirents, local_abspath, TRUE, pool, pool));
+ SVN_ERR(svn_io_get_dirents3(&dirents, dir_abspath, TRUE, result_pool,
+ scratch_pool));
- for (hi = apr_hash_first(pool, dirents); hi; hi = apr_hash_next(hi))
+ for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi))
{
- const char *this_abspath, *this_edit_path;
- const char *filename = svn__apr_hash_index_key(hi);
+ const char *base_name = svn__apr_hash_index_key(hi);
const svn_io_dirent2_t *dirent = svn__apr_hash_index_val(hi);
+ const char *local_abspath;
- svn_pool_clear(subpool);
+ svn_pool_clear(iterpool);
- if (ctx->cancel_func)
- SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+ local_abspath = svn_dirent_join(dir_abspath, base_name, iterpool);
- if (svn_wc_is_adm_dir(filename, subpool))
+ if (svn_wc_is_adm_dir(base_name, iterpool))
{
/* If someone's trying to import a directory named the same
as our administrative directories, that's probably not
@@ -348,95 +322,130 @@ import_dir(const svn_delta_editor_t *edi
if (ctx->notify_func2)
{
svn_wc_notify_t *notify
- = svn_wc_create_notify(svn_dirent_join(local_abspath, filename,
- subpool),
- svn_wc_notify_skip, subpool);
+ = svn_wc_create_notify(svn_dirent_join(local_abspath, base_name,
+ iterpool),
+ svn_wc_notify_skip, iterpool);
notify->kind = svn_node_dir;
notify->content_state = notify->prop_state
= svn_wc_notify_state_inapplicable;
notify->lock_state = svn_wc_notify_lock_state_inapplicable;
- (*ctx->notify_func2)(ctx->notify_baton2, notify, subpool);
+ (*ctx->notify_func2)(ctx->notify_baton2, notify, iterpool);
}
+
+ apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL);
+ continue;
+ }
+ /* If this is an excluded path, exclude it. */
+ if (apr_hash_get(excludes, local_abspath, APR_HASH_KEY_STRING))
+ {
+ apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL);
continue;
}
- /* Typically, we started importing from ".", in which case
- edit_path is "". So below, this_path might become "./blah",
- and this_edit_path might become "blah", for example. */
- this_abspath = svn_dirent_join(local_abspath, filename, subpool);
- this_edit_path = svn_relpath_join(edit_path, filename, subpool);
-
- /* If this is an excluded path, exclude it. */
- if (apr_hash_get(excludes, this_abspath, APR_HASH_KEY_STRING))
- continue;
-
- if ((!no_ignore) && svn_wc_match_ignore_list(filename, ignores,
- subpool))
- continue;
+ if (ignores && svn_wc_match_ignore_list(base_name, ignores, iterpool))
+ {
+ apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL);
+ continue;
+ }
- if (filter_callback != NULL)
+ if (filter_callback)
{
svn_boolean_t filter = FALSE;
- SVN_ERR(filter_callback(filter_baton, &filter, this_abspath,
- dirent, subpool));
+ SVN_ERR(filter_callback(filter_baton, &filter, local_abspath,
+ dirent, iterpool));
if (filter)
- continue;
+ {
+ apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL);
+ continue;
+ }
}
+ }
+ svn_pool_destroy(iterpool);
- if (dirent->kind == svn_node_dir && depth >= svn_depth_immediates)
- {
- void *this_dir_baton;
+ *children = dirents;
+ return SVN_NO_ERROR;
+}
- /* Add the new subdirectory, getting a descent baton from
- the editor. */
- SVN_ERR(editor->add_directory(this_edit_path, dir_baton,
- NULL, SVN_INVALID_REVNUM, subpool,
- &this_dir_baton));
+static svn_error_t *
+import_dir(const svn_delta_editor_t *editor,
+ void *dir_baton,
+ const char *local_abspath,
+ const char *edit_path,
+ svn_depth_t depth,
+ apr_hash_t *excludes,
+ svn_boolean_t no_ignore,
+ svn_boolean_t ignore_unknown_node_types,
+ svn_client_import_filter_func_t filter_callback,
+ void *filter_baton,
+ import_ctx_t *import_ctx,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool);
- /* Remember that the repository was modified */
- import_ctx->repos_changed = TRUE;
- /* By notifying before the recursive call below, we display
- a directory add before displaying adds underneath the
- directory. To do it the other way around, just move this
- after the recursive call. */
- if (ctx->notify_func2)
- {
- svn_wc_notify_t *notify
- = svn_wc_create_notify(this_abspath,
- svn_wc_notify_commit_added,
- subpool);
- notify->kind = svn_node_dir;
- notify->content_state = notify->prop_state
- = svn_wc_notify_state_inapplicable;
- notify->lock_state = svn_wc_notify_lock_state_inapplicable;
- (*ctx->notify_func2)(ctx->notify_baton2, notify, subpool);
- }
+/* Import the children of DIR_ABSPATH, with other arguments similar to
+ * import_dir(). */
+static svn_error_t *
+import_children(const char *dir_abspath,
+ const char *edit_path,
+ apr_hash_t *dirents,
+ const svn_delta_editor_t *editor,
+ void *dir_baton,
+ svn_depth_t depth,
+ apr_hash_t *excludes,
+ svn_boolean_t no_ignore,
+ svn_boolean_t ignore_unknown_node_types,
+ svn_client_import_filter_func_t filter_callback,
+ void *filter_baton,
+ import_ctx_t *import_ctx,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ apr_array_header_t *sorted_dirents;
+ int i;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- /* Recurse. */
- {
- svn_depth_t depth_below_here = depth;
- if (depth == svn_depth_immediates)
- depth_below_here = svn_depth_empty;
-
- SVN_ERR(import_dir(editor, this_dir_baton, this_abspath,
- this_edit_path, depth_below_here, excludes,
- no_ignore, ignore_unknown_node_types,
- filter_callback, filter_baton,
- import_ctx, ctx,
- subpool));
- }
+ sorted_dirents = svn_sort__hash(dirents, svn_sort_compare_items_lexically,
+ scratch_pool);
+ for (i = 0; i < sorted_dirents->nelts; i++)
+ {
+ const char *this_abspath, *this_edit_path;
+ svn_sort__item_t item = APR_ARRAY_IDX(sorted_dirents, i,
+ svn_sort__item_t);
+ const char *filename = item.key;
+ const svn_io_dirent2_t *dirent = item.value;
+
+ svn_pool_clear(iterpool);
- /* Finally, close the sub-directory. */
- SVN_ERR(editor->close_directory(this_dir_baton, subpool));
+ if (ctx->cancel_func)
+ SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+
+ /* Typically, we started importing from ".", in which case
+ edit_path is "". So below, this_path might become "./blah",
+ and this_edit_path might become "blah", for example. */
+ this_abspath = svn_dirent_join(dir_abspath, filename, iterpool);
+ this_edit_path = svn_relpath_join(edit_path, filename, iterpool);
+
+ if (dirent->kind == svn_node_dir && depth >= svn_depth_immediates)
+ {
+ /* Recurse. */
+ svn_depth_t depth_below_here = depth;
+ if (depth == svn_depth_immediates)
+ depth_below_here = svn_depth_empty;
+
+ SVN_ERR(import_dir(editor, dir_baton, this_abspath,
+ this_edit_path, depth_below_here, excludes,
+ no_ignore, ignore_unknown_node_types,
+ filter_callback, filter_baton,
+ import_ctx, ctx,
+ iterpool));
}
else if (dirent->kind == svn_node_file && depth >= svn_depth_files)
{
SVN_ERR(import_file(editor, dir_baton, this_abspath,
this_edit_path, dirent,
- import_ctx, ctx, subpool));
+ import_ctx, ctx, iterpool));
}
else if (dirent->kind != svn_node_dir && dirent->kind != svn_node_file)
{
@@ -447,23 +456,114 @@ import_dir(const svn_delta_editor_t *edi
{
svn_wc_notify_t *notify
= svn_wc_create_notify(this_abspath,
- svn_wc_notify_skip, subpool);
+ svn_wc_notify_skip, iterpool);
notify->kind = svn_node_dir;
notify->content_state = notify->prop_state
= svn_wc_notify_state_inapplicable;
notify->lock_state = svn_wc_notify_lock_state_inapplicable;
- (*ctx->notify_func2)(ctx->notify_baton2, notify, subpool);
+ (*ctx->notify_func2)(ctx->notify_baton2, notify, iterpool);
}
}
else
return svn_error_createf
(SVN_ERR_NODE_UNKNOWN_KIND, NULL,
_("Unknown or unversionable type for '%s'"),
- svn_dirent_local_style(this_abspath, subpool));
+ svn_dirent_local_style(this_abspath, iterpool));
}
}
- svn_pool_destroy(subpool);
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+}
+
+
+/* Import directory LOCAL_ABSPATH into the repository directory indicated by
+ * DIR_BATON in EDITOR. EDIT_PATH is the path imported as the root
+ * directory, so all edits are relative to that.
+ *
+ * DEPTH is the depth at this point in the descent (it may be changed
+ * for recursive calls).
+ *
+ * Accumulate file paths and their batons in FILES, which must be
+ * non-null. (These are used to send postfix textdeltas later).
+ *
+ * EXCLUDES is a hash whose keys are absolute paths to exclude from
+ * the import (values are unused).
+ *
+ * If NO_IGNORE is FALSE, don't import files or directories that match
+ * ignore patterns.
+ *
+ * If FILTER_CALLBACK is not NULL, call it with FILTER_BATON on each to be
+ * imported node below LOCAL_ABSPATH to allow filtering nodes.
+ *
+ * If CTX->NOTIFY_FUNC is non-null, invoke it with CTX->NOTIFY_BATON for each
+ * directory.
+ *
+ * Use POOL for any temporary allocation. */
+static svn_error_t *
+import_dir(const svn_delta_editor_t *editor,
+ void *dir_baton,
+ const char *local_abspath,
+ const char *edit_path,
+ svn_depth_t depth,
+ apr_hash_t *excludes,
+ svn_boolean_t no_ignore,
+ svn_boolean_t ignore_unknown_node_types,
+ svn_client_import_filter_func_t filter_callback,
+ void *filter_baton,
+ import_ctx_t *import_ctx,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ apr_hash_t *dirents;
+ apr_array_header_t *ignores = NULL;
+ void *this_dir_baton;
+
+ SVN_ERR(svn_path_check_valid(local_abspath, pool));
+
+ if (!no_ignore)
+ SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, pool));
+
+ SVN_ERR(get_filtered_children(&dirents, local_abspath, excludes, ignores,
+ filter_callback, filter_baton, ctx,
+ pool, pool));
+
+ /* Import this directory, but not yet its children. */
+ {
+ /* Add the new subdirectory, getting a descent baton from the editor. */
+ SVN_ERR(editor->add_directory(edit_path, dir_baton, NULL,
+ SVN_INVALID_REVNUM, pool, &this_dir_baton));
+
+ /* Remember that the repository was modified */
+ import_ctx->repos_changed = TRUE;
+
+ /* By notifying before the recursive call below, we display
+ a directory add before displaying adds underneath the
+ directory. To do it the other way around, just move this
+ after the recursive call. */
+ if (ctx->notify_func2)
+ {
+ svn_wc_notify_t *notify
+ = svn_wc_create_notify(local_abspath, svn_wc_notify_commit_added,
+ pool);
+ notify->kind = svn_node_dir;
+ notify->content_state = notify->prop_state
+ = svn_wc_notify_state_inapplicable;
+ notify->lock_state = svn_wc_notify_lock_state_inapplicable;
+ (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
+ }
+ }
+
+ /* Now import the children recursively. */
+ SVN_ERR(import_children(local_abspath, edit_path, dirents, editor,
+ this_dir_baton, depth, excludes, no_ignore,
+ ignore_unknown_node_types,
+ filter_callback, filter_baton,
+ import_ctx, ctx, pool));
+
+ /* Finally, close the sub-directory. */
+ SVN_ERR(editor->close_directory(this_dir_baton, pool));
+
return SVN_NO_ERROR;
}
@@ -518,7 +618,7 @@ import(const char *local_abspath,
apr_pool_t *pool)
{
void *root_baton;
- apr_array_header_t *ignores;
+ apr_array_header_t *ignores = NULL;
apr_array_header_t *batons = NULL;
const char *edit_path = "";
import_ctx_t *import_ctx = apr_pcalloc(pool, sizeof(*import_ctx));
@@ -596,11 +696,20 @@ import(const char *local_abspath,
}
else if (dirent->kind == svn_node_dir)
{
- SVN_ERR(import_dir(editor, root_baton, local_abspath, edit_path,
- depth, excludes, no_ignore,
- ignore_unknown_node_types,
- filter_callback, filter_baton,
- import_ctx, ctx, pool));
+ apr_hash_t *dirents;
+
+ if (!no_ignore)
+ SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, pool));
+
+ SVN_ERR(get_filtered_children(&dirents, local_abspath, excludes, ignores,
+ filter_callback, filter_baton, ctx,
+ pool, pool));
+
+ SVN_ERR(import_children(local_abspath, edit_path, dirents, editor,
+ root_baton, depth, excludes, no_ignore,
+ ignore_unknown_node_types,
+ filter_callback, filter_baton,
+ import_ctx, ctx, pool));
}
else if (dirent->kind == svn_node_none
@@ -655,16 +764,13 @@ capture_commit_info(const svn_commit_inf
static svn_error_t *
-get_ra_editor(svn_ra_session_t **ra_session,
- const svn_delta_editor_t **editor,
+get_ra_editor(const svn_delta_editor_t **editor,
void **edit_baton,
+ svn_ra_session_t *ra_session,
svn_client_ctx_t *ctx,
- const char *base_url,
- const char *base_dir_abspath,
const char *log_msg,
const apr_array_header_t *commit_items,
const apr_hash_t *revprop_table,
- svn_boolean_t is_commit,
apr_hash_t *lock_tokens,
svn_boolean_t keep_locks,
svn_commit_callback2_t commit_callback,
@@ -672,54 +778,43 @@ get_ra_editor(svn_ra_session_t **ra_sess
apr_pool_t *pool)
{
apr_hash_t *commit_revprops;
- const char *anchor_abspath;
-
- /* Open an RA session to URL. */
- SVN_ERR(svn_client__open_ra_session_internal(ra_session, NULL, base_url,
- base_dir_abspath, commit_items,
- is_commit, !is_commit,
- ctx, pool));
-
- /* If this is an import (aka, not a commit), we need to verify that
- our repository URL exists. */
- if (! is_commit)
- {
- svn_node_kind_t kind;
-
- SVN_ERR(svn_ra_check_path(*ra_session, "", SVN_INVALID_REVNUM,
- &kind, pool));
- if (kind == svn_node_none)
- return svn_error_createf(SVN_ERR_FS_NO_SUCH_ENTRY, NULL,
- _("Path '%s' does not exist"),
- base_url);
- }
+ apr_hash_t *relpath_map = NULL;
SVN_ERR(svn_client__ensure_revprop_table(&commit_revprops, revprop_table,
log_msg, ctx, pool));
#ifdef ENABLE_EV2_SHIMS
- /* We need this for the shims. */
- if (base_dir_abspath)
+ if (commit_items)
{
- const char *relpath;
- const char *wcroot_abspath;
+ int i;
+ apr_pool_t *iterpool = svn_pool_create(pool);
- SVN_ERR(svn_wc__get_wc_root(&wcroot_abspath, ctx->wc_ctx,
- base_dir_abspath, pool, pool));
+ relpath_map = apr_hash_make(pool);
+ for (i = 0; i < commit_items->nelts; i++)
+ {
+ svn_client_commit_item3_t *item = APR_ARRAY_IDX(commit_items, i,
+ svn_client_commit_item3_t *);
+ const char *relpath;
+
+ if (!item->path)
+ continue;
- SVN_ERR(svn_ra_get_path_relative_to_root(*ra_session, &relpath, base_url,
- pool));
- anchor_abspath = svn_dirent_join(wcroot_abspath, relpath, pool);
+ svn_pool_clear(iterpool);
+ SVN_ERR(svn_wc__node_get_origin(NULL, NULL, &relpath, NULL, NULL, NULL,
+ ctx->wc_ctx, item->path, FALSE, pool,
+ iterpool));
+ if (relpath)
+ apr_hash_set(relpath_map, relpath, APR_HASH_KEY_STRING, item->path);
+ }
+ svn_pool_destroy(iterpool);
}
- else
#endif
- anchor_abspath = NULL;
/* Fetch RA commit editor. */
- SVN_ERR(svn_ra__register_editor_shim_callbacks(*ra_session,
+ SVN_ERR(svn_ra__register_editor_shim_callbacks(ra_session,
svn_client__get_shim_callbacks(ctx->wc_ctx,
- anchor_abspath, pool)));
- SVN_ERR(svn_ra_get_commit_editor3(*ra_session, editor, edit_baton,
+ relpath_map, pool)));
+ SVN_ERR(svn_ra_get_commit_editor3(ra_session, editor, edit_baton,
commit_revprops, commit_callback,
commit_baton, lock_tokens, keep_locks,
pool));
@@ -756,7 +851,8 @@ svn_client_import5(const char *path,
sizeof(const char *));
const char *temp;
const char *dir;
- apr_pool_t *subpool;
+ apr_hash_t *commit_revprops;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
if (svn_path_is_url(path))
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
@@ -794,37 +890,34 @@ svn_client_import5(const char *path,
SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
+ SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, url, NULL,
+ NULL, FALSE, TRUE, ctx,
+ scratch_pool));
+
/* Figure out all the path components we need to create just to have
a place to stick our imported tree. */
- subpool = svn_pool_create(scratch_pool);
- do
- {
- svn_pool_clear(subpool);
+ SVN_ERR(svn_ra_check_path(ra_session, "", SVN_INVALID_REVNUM, &kind,
+ iterpool));
- /* See if the user is interested in cancelling this operation. */
- if (ctx->cancel_func)
- SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+ /* We can import into directories, but if a file already exists, that's
+ an error. */
+ if (kind == svn_node_file)
+ return svn_error_createf
+ (SVN_ERR_ENTRY_EXISTS, NULL,
+ _("Path '%s' already exists"), url);
- if (err)
- {
- /* If get_ra_editor below failed we either tried to open
- an invalid url, or else some other kind of error. In case
- the url was bad we back up a directory and try again. */
+ while (kind == svn_node_none)
+ {
+ svn_pool_clear(iterpool);
- if (err->apr_err != SVN_ERR_FS_NO_SUCH_ENTRY)
- return err;
- else
- svn_error_clear(err);
+ svn_uri_split(&temp, &dir, url, scratch_pool);
+ APR_ARRAY_PUSH(new_entries, const char *) = dir;
+ url = temp;
+ SVN_ERR(svn_ra_reparent(ra_session, url, iterpool));
- svn_uri_split(&temp, &dir, url, scratch_pool);
- APR_ARRAY_PUSH(new_entries, const char *) = dir;
- url = temp;
- }
+ SVN_ERR(svn_ra_check_path(ra_session, "", SVN_INVALID_REVNUM, &kind,
+ iterpool));
}
- while ((err = get_ra_editor(&ra_session,
- &editor, &edit_baton, ctx, url, NULL,
- log_msg, NULL, revprop_table, FALSE, NULL, TRUE,
- commit_callback, commit_baton, subpool)));
/* Reverse the order of the components we added to our NEW_ENTRIES array. */
if (new_entries->nelts)
@@ -843,14 +936,6 @@ svn_client_import5(const char *path,
}
}
- /* An empty NEW_ENTRIES list the first call to get_ra_editor() above
- succeeded. That means that URL corresponds to an already
- existing filesystem entity. */
- if (kind == svn_node_file && (! new_entries->nelts))
- return svn_error_createf
- (SVN_ERR_ENTRY_EXISTS, NULL,
- _("Path '%s' already exists"), url);
-
/* The repository doesn't know about the reserved administrative
directory. */
if (new_entries->nelts
@@ -867,6 +952,17 @@ svn_client_import5(const char *path,
_("'%s' is a reserved name and cannot be imported"),
svn_dirent_local_style(temp, scratch_pool));
+ SVN_ERR(svn_client__ensure_revprop_table(&commit_revprops, revprop_table,
+ log_msg, ctx, scratch_pool));
+
+ /* Fetch RA commit editor. */
+ SVN_ERR(svn_ra__register_editor_shim_callbacks(ra_session,
+ svn_client__get_shim_callbacks(ctx->wc_ctx,
+ NULL, scratch_pool)));
+ SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
+ commit_revprops, commit_callback,
+ commit_baton, NULL, TRUE,
+ scratch_pool));
/* If an error occurred during the commit, abort the edit and return
the error. We don't even care if the abort itself fails. */
@@ -874,13 +970,13 @@ svn_client_import5(const char *path,
depth, excludes, no_ignore,
ignore_unknown_node_types,
filter_callback, filter_baton,
- ctx, subpool)))
+ ctx, iterpool)))
{
- svn_error_clear(editor->abort_edit(edit_baton, subpool));
+ svn_error_clear(editor->abort_edit(edit_baton, iterpool));
return svn_error_trace(err);
}
- svn_pool_destroy(subpool);
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -1238,7 +1334,10 @@ append_externals_as_explicit_targets(apr
{
int rel_targets_nelts_fixed;
int i;
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_pool_t *iterpool;
+
+ if (! (include_file_externals || include_dir_externals))
+ return SVN_NO_ERROR;
/* Easy part of applying DEPTH to externals. */
if (depth == svn_depth_empty)
@@ -1266,12 +1365,11 @@ append_externals_as_explicit_targets(apr
* ### not at all. No other effect. So not doing that for now. */
}
- if (! (include_file_externals || include_dir_externals))
- return SVN_NO_ERROR;
-
/* Iterate *and* grow REL_TARGETS at the same time. */
rel_targets_nelts_fixed = rel_targets->nelts;
+ iterpool = svn_pool_create(scratch_pool);
+
for (i = 0; i < rel_targets_nelts_fixed; i++)
{
int j;
@@ -1673,11 +1771,18 @@ svn_client_commit6(const apr_array_heade
cb.pool = pool;
cmt_err = svn_error_trace(
- get_ra_editor(&ra_session, &editor, &edit_baton, ctx,
- base_url, base_abspath, log_msg,
- commit_items, revprop_table, TRUE, lock_tokens,
- keep_locks, capture_commit_info,
- &cb, pool));
+ svn_client__open_ra_session_internal(&ra_session, NULL, base_url,
+ base_abspath, commit_items,
+ TRUE, FALSE, ctx, pool));
+
+ if (cmt_err)
+ goto cleanup;
+
+ cmt_err = svn_error_trace(
+ get_ra_editor(&editor, &edit_baton, ra_session, ctx,
+ log_msg, commit_items, revprop_table,
+ lock_tokens, keep_locks, capture_commit_info,
+ &cb, pool));
if (cmt_err)
goto cleanup;
@@ -1687,9 +1792,9 @@ svn_client_commit6(const apr_array_heade
/* Perform the commit. */
cmt_err = svn_error_trace(
- svn_client__do_commit(base_url, commit_items, editor, edit_baton,
- notify_prefix, NULL,
- &sha1_checksums, ctx, pool, iterpool));
+ svn_client__do_commit(base_url, commit_items, editor, edit_baton,
+ notify_prefix, &sha1_checksums, ctx, pool,
+ iterpool));
/* Handle a successful commit. */
if ((! cmt_err)