diff options
author | peter <peter@FreeBSD.org> | 2013-06-18 02:07:41 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2013-06-18 02:07:41 +0000 |
commit | d25dac7fcc6acc838b71bbda8916fd9665c709ab (patch) | |
tree | 135691142dc0e75a5e5d97b5074d03436435b8e0 /subversion/libsvn_client/util.c | |
download | FreeBSD-src-d25dac7fcc6acc838b71bbda8916fd9665c709ab.zip FreeBSD-src-d25dac7fcc6acc838b71bbda8916fd9665c709ab.tar.gz |
Import trimmed svn-1.8.0-rc3
Diffstat (limited to 'subversion/libsvn_client/util.c')
-rw-r--r-- | subversion/libsvn_client/util.c | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/subversion/libsvn_client/util.c b/subversion/libsvn_client/util.c new file mode 100644 index 0000000..5ac0b8f --- /dev/null +++ b/subversion/libsvn_client/util.c @@ -0,0 +1,457 @@ +/* + * util.c : utility functions for the libsvn_client library + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include <apr_pools.h> +#include <apr_strings.h> + +#include "svn_hash.h" +#include "svn_pools.h" +#include "svn_error.h" +#include "svn_types.h" +#include "svn_opt.h" +#include "svn_props.h" +#include "svn_path.h" +#include "svn_wc.h" +#include "svn_client.h" + +#include "private/svn_client_private.h" +#include "private/svn_wc_private.h" +#include "private/svn_fspath.h" + +#include "client.h" + +#include "svn_private_config.h" + +svn_client__pathrev_t * +svn_client__pathrev_create(const char *repos_root_url, + const char *repos_uuid, + svn_revnum_t rev, + const char *url, + apr_pool_t *result_pool) +{ + svn_client__pathrev_t *loc = apr_palloc(result_pool, sizeof(*loc)); + + SVN_ERR_ASSERT_NO_RETURN(svn_path_is_url(repos_root_url)); + SVN_ERR_ASSERT_NO_RETURN(svn_path_is_url(url)); + + loc->repos_root_url = apr_pstrdup(result_pool, repos_root_url); + loc->repos_uuid = apr_pstrdup(result_pool, repos_uuid); + loc->rev = rev; + loc->url = apr_pstrdup(result_pool, url); + return loc; +} + +svn_client__pathrev_t * +svn_client__pathrev_create_with_relpath(const char *repos_root_url, + const char *repos_uuid, + svn_revnum_t rev, + const char *relpath, + apr_pool_t *result_pool) +{ + SVN_ERR_ASSERT_NO_RETURN(svn_relpath_is_canonical(relpath)); + + return svn_client__pathrev_create( + repos_root_url, repos_uuid, rev, + svn_path_url_add_component2(repos_root_url, relpath, result_pool), + result_pool); +} + +svn_error_t * +svn_client__pathrev_create_with_session(svn_client__pathrev_t **pathrev_p, + svn_ra_session_t *ra_session, + svn_revnum_t rev, + const char *url, + apr_pool_t *result_pool) +{ + svn_client__pathrev_t *pathrev = apr_palloc(result_pool, sizeof(*pathrev)); + + SVN_ERR_ASSERT(svn_path_is_url(url)); + + SVN_ERR(svn_ra_get_repos_root2(ra_session, &pathrev->repos_root_url, + result_pool)); + SVN_ERR(svn_ra_get_uuid2(ra_session, &pathrev->repos_uuid, result_pool)); + pathrev->rev = rev; + pathrev->url = apr_pstrdup(result_pool, url); + *pathrev_p = pathrev; + return SVN_NO_ERROR; +} + +svn_client__pathrev_t * +svn_client__pathrev_dup(const svn_client__pathrev_t *pathrev, + apr_pool_t *result_pool) +{ + return svn_client__pathrev_create( + pathrev->repos_root_url, pathrev->repos_uuid, + pathrev->rev, pathrev->url, result_pool); +} + +svn_client__pathrev_t * +svn_client__pathrev_join_relpath(const svn_client__pathrev_t *pathrev, + const char *relpath, + apr_pool_t *result_pool) +{ + return svn_client__pathrev_create( + pathrev->repos_root_url, pathrev->repos_uuid, pathrev->rev, + svn_path_url_add_component2(pathrev->url, relpath, result_pool), + result_pool); +} + +const char * +svn_client__pathrev_relpath(const svn_client__pathrev_t *pathrev, + apr_pool_t *result_pool) +{ + return svn_uri_skip_ancestor(pathrev->repos_root_url, pathrev->url, + result_pool); +} + +const char * +svn_client__pathrev_fspath(const svn_client__pathrev_t *pathrev, + apr_pool_t *result_pool) +{ + return svn_fspath__canonicalize(svn_uri_skip_ancestor( + pathrev->repos_root_url, pathrev->url, + result_pool), + result_pool); +} + + +svn_client_commit_item3_t * +svn_client_commit_item3_create(apr_pool_t *pool) +{ + return apr_pcalloc(pool, sizeof(svn_client_commit_item3_t)); +} + +svn_client_commit_item3_t * +svn_client_commit_item3_dup(const svn_client_commit_item3_t *item, + apr_pool_t *pool) +{ + svn_client_commit_item3_t *new_item = apr_palloc(pool, sizeof(*new_item)); + + *new_item = *item; + + if (new_item->path) + new_item->path = apr_pstrdup(pool, new_item->path); + + if (new_item->url) + new_item->url = apr_pstrdup(pool, new_item->url); + + if (new_item->copyfrom_url) + new_item->copyfrom_url = apr_pstrdup(pool, new_item->copyfrom_url); + + if (new_item->incoming_prop_changes) + new_item->incoming_prop_changes = + svn_prop_array_dup(new_item->incoming_prop_changes, pool); + + if (new_item->outgoing_prop_changes) + new_item->outgoing_prop_changes = + svn_prop_array_dup(new_item->outgoing_prop_changes, pool); + + return new_item; +} + +svn_error_t * +svn_client__wc_node_get_base(svn_client__pathrev_t **base_p, + const char *wc_abspath, + svn_wc_context_t *wc_ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *relpath; + + *base_p = apr_palloc(result_pool, sizeof(**base_p)); + + SVN_ERR(svn_wc__node_get_base(NULL, + &(*base_p)->rev, + &relpath, + &(*base_p)->repos_root_url, + &(*base_p)->repos_uuid, + NULL, + wc_ctx, wc_abspath, + TRUE /* ignore_enoent */, + TRUE /* show_hidden */, + result_pool, scratch_pool)); + if ((*base_p)->repos_root_url && relpath) + { + (*base_p)->url = svn_path_url_add_component2( + (*base_p)->repos_root_url, relpath, result_pool); + } + else + { + *base_p = NULL; + } + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client__wc_node_get_origin(svn_client__pathrev_t **origin_p, + const char *wc_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *relpath; + + *origin_p = apr_palloc(result_pool, sizeof(**origin_p)); + + SVN_ERR(svn_wc__node_get_origin(NULL /* is_copy */, + &(*origin_p)->rev, + &relpath, + &(*origin_p)->repos_root_url, + &(*origin_p)->repos_uuid, + NULL, ctx->wc_ctx, wc_abspath, + FALSE /* scan_deleted */, + result_pool, scratch_pool)); + if ((*origin_p)->repos_root_url && relpath) + { + (*origin_p)->url = svn_path_url_add_component2( + (*origin_p)->repos_root_url, relpath, result_pool); + } + else + { + *origin_p = NULL; + } + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_get_repos_root(const char **repos_root, + const char **repos_uuid, + const char *abspath_or_url, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_ra_session_t *ra_session; + + /* If PATH_OR_URL is a local path we can fetch the repos root locally. */ + if (!svn_path_is_url(abspath_or_url)) + { + svn_error_t *err; + err = svn_wc__node_get_repos_info(NULL, NULL, repos_root, repos_uuid, + ctx->wc_ctx, abspath_or_url, + result_pool, scratch_pool); + + if (err) + { + if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND + && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY) + return svn_error_trace(err); + + svn_error_clear(err); + if (repos_root) + *repos_root = NULL; + if (repos_uuid) + *repos_uuid = NULL; + } + return SVN_NO_ERROR; + } + + /* If PATH_OR_URL was a URL, we use the RA layer to look it up. */ + SVN_ERR(svn_client_open_ra_session2(&ra_session, abspath_or_url, NULL, + ctx, scratch_pool, scratch_pool)); + + if (repos_root) + SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, result_pool)); + if (repos_uuid) + SVN_ERR(svn_ra_get_uuid2(ra_session, repos_uuid, result_pool)); + + return SVN_NO_ERROR; +} + +const svn_opt_revision_t * +svn_cl__rev_default_to_head_or_base(const svn_opt_revision_t *revision, + const char *path_or_url) +{ + static svn_opt_revision_t head_rev = { svn_opt_revision_head, { 0 } }; + static svn_opt_revision_t base_rev = { svn_opt_revision_base, { 0 } }; + + if (revision->kind == svn_opt_revision_unspecified) + return svn_path_is_url(path_or_url) ? &head_rev : &base_rev; + return revision; +} + +const svn_opt_revision_t * +svn_cl__rev_default_to_head_or_working(const svn_opt_revision_t *revision, + const char *path_or_url) +{ + static svn_opt_revision_t head_rev = { svn_opt_revision_head, { 0 } }; + static svn_opt_revision_t work_rev = { svn_opt_revision_working, { 0 } }; + + if (revision->kind == svn_opt_revision_unspecified) + return svn_path_is_url(path_or_url) ? &head_rev : &work_rev; + return revision; +} + +const svn_opt_revision_t * +svn_cl__rev_default_to_peg(const svn_opt_revision_t *revision, + const svn_opt_revision_t *peg_revision) +{ + if (revision->kind == svn_opt_revision_unspecified) + return peg_revision; + return revision; +} + +svn_error_t * +svn_client__assert_homogeneous_target_type(const apr_array_header_t *targets) +{ + svn_boolean_t wc_present = FALSE, url_present = FALSE; + int i; + + for (i = 0; i < targets->nelts; ++i) + { + const char *target = APR_ARRAY_IDX(targets, i, const char *); + if (! svn_path_is_url(target)) + wc_present = TRUE; + else + url_present = TRUE; + if (url_present && wc_present) + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + _("Cannot mix repository and working copy " + "targets")); + } + + return SVN_NO_ERROR; +} + +struct shim_callbacks_baton +{ + svn_wc_context_t *wc_ctx; + apr_hash_t *relpath_map; +}; + +static svn_error_t * +fetch_props_func(apr_hash_t **props, + void *baton, + const char *path, + svn_revnum_t base_revision, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + struct shim_callbacks_baton *scb = baton; + const char *local_abspath; + + local_abspath = svn_hash_gets(scb->relpath_map, path); + if (!local_abspath) + { + *props = apr_hash_make(result_pool); + return SVN_NO_ERROR; + } + + /* Reads the pristine properties of WORKING, not those of BASE */ + SVN_ERR(svn_wc_get_pristine_props(props, scb->wc_ctx, local_abspath, + result_pool, scratch_pool)); + + if (!*props) + *props = apr_hash_make(result_pool); + + return SVN_NO_ERROR; +} + +static svn_error_t * +fetch_kind_func(svn_node_kind_t *kind, + void *baton, + const char *path, + svn_revnum_t base_revision, + apr_pool_t *scratch_pool) +{ + struct shim_callbacks_baton *scb = baton; + const char *local_abspath; + + local_abspath = svn_hash_gets(scb->relpath_map, path); + if (!local_abspath) + { + *kind = svn_node_unknown; + return SVN_NO_ERROR; + } + /* Reads the WORKING kind. Not the BASE kind */ + SVN_ERR(svn_wc_read_kind2(kind, scb->wc_ctx, local_abspath, + TRUE, FALSE, scratch_pool)); + + return SVN_NO_ERROR; +} + +static svn_error_t * +fetch_base_func(const char **filename, + void *baton, + const char *path, + svn_revnum_t base_revision, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + struct shim_callbacks_baton *scb = baton; + const char *local_abspath; + svn_stream_t *pristine_stream; + svn_stream_t *temp_stream; + svn_error_t *err; + + local_abspath = svn_hash_gets(scb->relpath_map, path); + if (!local_abspath) + { + *filename = NULL; + return SVN_NO_ERROR; + } + + /* Reads the pristine of WORKING, not of BASE */ + err = svn_wc_get_pristine_contents2(&pristine_stream, scb->wc_ctx, + local_abspath, scratch_pool, + scratch_pool); + if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) + { + svn_error_clear(err); + *filename = NULL; + return SVN_NO_ERROR; + } + else if (err) + return svn_error_trace(err); + + SVN_ERR(svn_stream_open_unique(&temp_stream, filename, NULL, + svn_io_file_del_on_pool_cleanup, + result_pool, scratch_pool)); + SVN_ERR(svn_stream_copy3(pristine_stream, temp_stream, NULL, NULL, + scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_delta_shim_callbacks_t * +svn_client__get_shim_callbacks(svn_wc_context_t *wc_ctx, + apr_hash_t *relpath_map, + apr_pool_t *result_pool) +{ + svn_delta_shim_callbacks_t *callbacks = + svn_delta_shim_callbacks_default(result_pool); + struct shim_callbacks_baton *scb = apr_pcalloc(result_pool, sizeof(*scb)); + + scb->wc_ctx = wc_ctx; + if (relpath_map) + scb->relpath_map = relpath_map; + else + scb->relpath_map = apr_hash_make(result_pool); + + callbacks->fetch_props_func = fetch_props_func; + callbacks->fetch_kind_func = fetch_kind_func; + callbacks->fetch_base_func = fetch_base_func; + callbacks->fetch_baton = scb; + + return callbacks; +} |