blob: ef52b41b43dc3f0f0648a0af8acf585cfad87f22 [file] [log] [blame]
/*
* dump_editor.c: The svn_delta_editor_t editor used by svnrdump to
* dump revisions.
*
* ====================================================================
* 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 "svn_types.h"
#include "svn_props.h"
#include "svn_ra.h"
#include "svn_io.h"
#include "svn_delta.h"
#include "private/svn_repos_private.h"
#include "private/svn_editor.h"
#include "svnrdump.h"
#include <assert.h>
/* The baton used by the dump editor. */
struct dump_edit_baton {
/* A backdoor ra session to fetch additional information during the edit. */
svn_ra_session_t *ra_session;
/* The revision we're currently dumping. */
svn_revnum_t current_revision;
};
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 dump_edit_baton *eb = baton;
svn_stream_t *fstream;
svn_error_t *err;
if (path[0] == '/')
path += 1;
if (! SVN_IS_VALID_REVNUM(base_revision))
base_revision = eb->current_revision - 1;
SVN_ERR(svn_stream_open_unique(&fstream, filename, NULL,
svn_io_file_del_on_pool_cleanup,
result_pool, scratch_pool));
err = svn_ra_get_file(eb->ra_session, path, base_revision,
fstream, NULL, NULL, scratch_pool);
if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
{
svn_error_clear(err);
SVN_ERR(svn_stream_close(fstream));
*filename = NULL;
return SVN_NO_ERROR;
}
else if (err)
return svn_error_trace(err);
SVN_ERR(svn_stream_close(fstream));
return SVN_NO_ERROR;
}
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 dump_edit_baton *eb = baton;
svn_node_kind_t node_kind;
if (path[0] == '/')
path += 1;
if (! SVN_IS_VALID_REVNUM(base_revision))
base_revision = eb->current_revision - 1;
SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, &node_kind,
scratch_pool));
if (node_kind == svn_node_file)
{
SVN_ERR(svn_ra_get_file(eb->ra_session, path, base_revision,
NULL, NULL, props, result_pool));
}
else if (node_kind == svn_node_dir)
{
apr_array_header_t *tmp_props;
SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, props, path,
base_revision, 0 /* Dirent fields */,
result_pool));
tmp_props = svn_prop_hash_to_array(*props, result_pool);
SVN_ERR(svn_categorize_props(tmp_props, NULL, NULL, &tmp_props,
result_pool));
*props = svn_prop_array_to_hash(tmp_props, result_pool);
}
else
{
*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 dump_edit_baton *eb = baton;
if (path[0] == '/')
path += 1;
if (! SVN_IS_VALID_REVNUM(base_revision))
base_revision = eb->current_revision - 1;
SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, kind,
scratch_pool));
return SVN_NO_ERROR;
}
svn_error_t *
svn_rdump__get_dump_editor(const svn_delta_editor_t **editor,
void **edit_baton,
svn_revnum_t revision,
svn_stream_t *stream,
svn_ra_session_t *ra_session,
const char *update_anchor_relpath,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool)
{
struct dump_edit_baton *eb;
svn_delta_shim_callbacks_t *shim_callbacks =
svn_delta_shim_callbacks_default(pool);
eb = apr_pcalloc(pool, sizeof(struct dump_edit_baton));
eb->ra_session = ra_session;
eb->current_revision = revision;
SVN_ERR(svn_repos__get_dump_editor(editor, edit_baton,
stream, update_anchor_relpath, pool));
/* Wrap this editor in a cancellation editor. */
SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
*editor, *edit_baton,
editor, edit_baton,
pool));
shim_callbacks->fetch_base_func = fetch_base_func;
shim_callbacks->fetch_props_func = fetch_props_func;
shim_callbacks->fetch_kind_func = fetch_kind_func;
shim_callbacks->fetch_baton = eb;
SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
NULL, NULL, shim_callbacks, pool, pool));
return SVN_NO_ERROR;
}