blob: fe31124ff00be431e36b00b53cf78a006f972cfe [file] [log] [blame]
/*
* compat.c: compatibility shims to adapt between different API versions.
*
* ====================================================================
* 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_repos.h"
#include "svn_compat.h"
#include "svn_hash.h"
#include "svn_props.h"
#include "svn_pools.h"
#include "svn_private_config.h"
#include "repos.h"
#include "private/svn_repos_private.h"
#include "private/svn_subr_private.h"
/*** log4 -> log5 ***/
/* Baton type to be used with both log4 compatibility callbacks.
* For each revision, we collect the CHANGES and then pass them
* on to INNER. */
typedef struct log_entry_receiver_baton_t
{
/* Pool to use to allocate CHANGES and its entries.
* Gets cleared after each revision. */
apr_pool_t *changes_pool;
/* Path changes reported so far for the current revision.
* Will be NULL before the first item gets added and will be reset
* to NULL after the INNER callback has returned. */
apr_hash_t *changes;
/* User-provided callback to send the log entry to. */
svn_log_entry_receiver_t inner;
void *inner_baton;
} log_entry_receiver_baton_t;
/* Return the action character (see svn_log_changed_path2_t) for KIND.
* Returns 0 for invalid KINDs. */
static char
path_change_kind_to_char(svn_fs_path_change_kind_t kind)
{
const char symbol[] = "MADR";
if (kind < svn_fs_path_change_modify || kind > svn_fs_path_change_replace)
return 0;
return symbol[kind];
}
/* Implement svn_repos_path_change_receiver_t.
* Convert CHANGE and add it to the CHANGES list in *BATON. */
static svn_error_t *
log4_path_change_receiver(void *baton,
svn_repos_path_change_t *change,
apr_pool_t *scratch_pool)
{
log_entry_receiver_baton_t *b = baton;
svn_log_changed_path2_t *change_copy;
const char *path = apr_pstrmemdup(b->changes_pool, change->path.data,
change->path.len);
/* Create a deep copy of the temporary CHANGE struct. */
change_copy = svn_log_changed_path2_create(b->changes_pool);
change_copy->action = path_change_kind_to_char(change->change_kind);
if (change->copyfrom_path)
change_copy->copyfrom_path = apr_pstrdup(b->changes_pool,
change->copyfrom_path);
change_copy->copyfrom_rev = change->copyfrom_rev;
change_copy->node_kind = change->node_kind;
change_copy->text_modified = change->text_mod ? svn_tristate_true
: svn_tristate_false;
change_copy->props_modified = change->prop_mod ? svn_tristate_true
: svn_tristate_false;
/* Auto-create the CHANGES container (happens for each first change
* in any revision. */
if (b->changes == NULL)
b->changes = svn_hash__make(b->changes_pool);
/* Add change to per-revision collection. */
apr_hash_set(b->changes, path, change->path.len, change_copy);
return SVN_NO_ERROR;
}
/* Implement svn_log_entry_receiver_t.
* Combine the data gathered in BATON for this revision and send it
* to the user-provided log4-compatible callback. */
static svn_error_t *
log4_entry_receiver(void *baton,
svn_repos_log_entry_t *log_entry,
apr_pool_t *scratch_pool)
{
log_entry_receiver_baton_t *b = baton;
svn_log_entry_t *entry = svn_log_entry_create(scratch_pool);
/* Complete the ENTRY. */
entry->changed_paths = b->changes;
entry->revision = log_entry->revision;
entry->revprops = log_entry->revprops;
entry->has_children = log_entry->has_children;
entry->changed_paths2 = b->changes;
entry->non_inheritable = log_entry->non_inheritable;
entry->subtractive_merge = log_entry->subtractive_merge;
/* Invoke the log4-compatible callback. */
SVN_ERR(b->inner(b->inner_baton, entry, scratch_pool));
/* Release per-revision data. */
svn_pool_clear(b->changes_pool);
b->changes = NULL;
return SVN_NO_ERROR;
}
svn_error_t *
svn_repos__get_logs_compat(svn_repos_t *repos,
const apr_array_header_t *paths,
svn_revnum_t start,
svn_revnum_t end,
int limit,
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_boolean_t include_merged_revisions,
const apr_array_header_t *revprops,
svn_repos_authz_func_t authz_read_func,
void *authz_read_baton,
svn_log_entry_receiver_t receiver,
void *receiver_baton,
apr_pool_t *pool)
{
apr_pool_t *changes_pool = svn_pool_create(pool);
log_entry_receiver_baton_t baton;
baton.changes_pool = changes_pool;
baton.changes = NULL;
baton.inner = receiver;
baton.inner_baton = receiver_baton;
SVN_ERR(svn_repos_get_logs5(repos, paths, start, end, limit,
strict_node_history,
include_merged_revisions,
revprops,
authz_read_func, authz_read_baton,
discover_changed_paths
? log4_path_change_receiver
: NULL,
&baton,
log4_entry_receiver, &baton,
pool));
svn_pool_destroy(changes_pool);
return SVN_NO_ERROR;
}