1/* 2 * compat.c: compatibility shims to adapt between different API versions. 3 * 4 * ==================================================================== 5 * Licensed to the Apache Software Foundation (ASF) under one 6 * or more contributor license agreements. See the NOTICE file 7 * distributed with this work for additional information 8 * regarding copyright ownership. The ASF licenses this file 9 * to you under the Apache License, Version 2.0 (the 10 * "License"); you may not use this file except in compliance 11 * with the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, 16 * software distributed under the License is distributed on an 17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 * KIND, either express or implied. See the License for the 19 * specific language governing permissions and limitations 20 * under the License. 21 * ==================================================================== 22 */ 23 24#include "svn_repos.h" 25#include "svn_compat.h" 26#include "svn_hash.h" 27#include "svn_props.h" 28#include "svn_pools.h" 29 30#include "svn_private_config.h" 31 32#include "repos.h" 33 34#include "private/svn_repos_private.h" 35#include "private/svn_subr_private.h" 36 37 38 39/*** log4 -> log5 ***/ 40 41/* Baton type to be used with both log4 compatibility callbacks. 42 * For each revision, we collect the CHANGES and then pass them 43 * on to INNER. */ 44typedef struct log_entry_receiver_baton_t 45{ 46 /* Pool to use to allocate CHANGES and its entries. 47 * Gets cleared after each revision. */ 48 apr_pool_t *changes_pool; 49 50 /* Path changes reported so far for the current revision. 51 * Will be NULL before the first item gets added and will be reset 52 * to NULL after the INNER callback has returned. */ 53 apr_hash_t *changes; 54 55 /* User-provided callback to send the log entry to. */ 56 svn_log_entry_receiver_t inner; 57 void *inner_baton; 58} log_entry_receiver_baton_t; 59 60/* Return the action character (see svn_log_changed_path2_t) for KIND. 61 * Returns 0 for invalid KINDs. */ 62static char 63path_change_kind_to_char(svn_fs_path_change_kind_t kind) 64{ 65 const char symbol[] = "MADR"; 66 67 if (kind < svn_fs_path_change_modify || kind > svn_fs_path_change_replace) 68 return 0; 69 70 return symbol[kind]; 71} 72 73/* Implement svn_repos_path_change_receiver_t. 74 * Convert CHANGE and add it to the CHANGES list in *BATON. */ 75static svn_error_t * 76log4_path_change_receiver(void *baton, 77 svn_repos_path_change_t *change, 78 apr_pool_t *scratch_pool) 79{ 80 log_entry_receiver_baton_t *b = baton; 81 svn_log_changed_path2_t *change_copy; 82 const char *path = apr_pstrmemdup(b->changes_pool, change->path.data, 83 change->path.len); 84 85 /* Create a deep copy of the temporary CHANGE struct. */ 86 change_copy = svn_log_changed_path2_create(b->changes_pool); 87 change_copy->action = path_change_kind_to_char(change->change_kind); 88 89 if (change->copyfrom_path) 90 change_copy->copyfrom_path = apr_pstrdup(b->changes_pool, 91 change->copyfrom_path); 92 93 change_copy->copyfrom_rev = change->copyfrom_rev; 94 change_copy->node_kind = change->node_kind; 95 change_copy->text_modified = change->text_mod ? svn_tristate_true 96 : svn_tristate_false; 97 change_copy->props_modified = change->prop_mod ? svn_tristate_true 98 : svn_tristate_false; 99 100 /* Auto-create the CHANGES container (happens for each first change 101 * in any revison. */ 102 if (b->changes == NULL) 103 b->changes = svn_hash__make(b->changes_pool); 104 105 /* Add change to per-revision collection. */ 106 apr_hash_set(b->changes, path, change->path.len, change_copy); 107 108 return SVN_NO_ERROR; 109} 110 111/* Implement svn_log_entry_receiver_t. 112 * Combine the data gathered in BATON for this revision and send it 113 * to the user-provided log4-compatible callback. */ 114static svn_error_t * 115log4_entry_receiver(void *baton, 116 svn_repos_log_entry_t *log_entry, 117 apr_pool_t *scratch_pool) 118{ 119 log_entry_receiver_baton_t *b = baton; 120 svn_log_entry_t *entry = svn_log_entry_create(scratch_pool); 121 122 /* Complete the ENTRY. */ 123 entry->changed_paths = b->changes; 124 entry->revision = log_entry->revision; 125 entry->revprops = log_entry->revprops; 126 entry->has_children = log_entry->has_children; 127 entry->changed_paths2 = b->changes; 128 entry->non_inheritable = log_entry->non_inheritable; 129 entry->subtractive_merge = log_entry->subtractive_merge; 130 131 /* Invoke the log4-compatible callback. */ 132 SVN_ERR(b->inner(b->inner_baton, entry, scratch_pool)); 133 134 /* Release per-revision data. */ 135 svn_pool_clear(b->changes_pool); 136 b->changes = NULL; 137 138 return SVN_NO_ERROR; 139} 140 141svn_error_t * 142svn_repos__get_logs_compat(svn_repos_t *repos, 143 const apr_array_header_t *paths, 144 svn_revnum_t start, 145 svn_revnum_t end, 146 int limit, 147 svn_boolean_t discover_changed_paths, 148 svn_boolean_t strict_node_history, 149 svn_boolean_t include_merged_revisions, 150 const apr_array_header_t *revprops, 151 svn_repos_authz_func_t authz_read_func, 152 void *authz_read_baton, 153 svn_log_entry_receiver_t receiver, 154 void *receiver_baton, 155 apr_pool_t *pool) 156{ 157 apr_pool_t *changes_pool = svn_pool_create(pool); 158 159 log_entry_receiver_baton_t baton; 160 baton.changes_pool = changes_pool; 161 baton.changes = NULL; 162 baton.inner = receiver; 163 baton.inner_baton = receiver_baton; 164 165 SVN_ERR(svn_repos_get_logs5(repos, paths, start, end, limit, 166 strict_node_history, 167 include_merged_revisions, 168 revprops, 169 authz_read_func, authz_read_baton, 170 discover_changed_paths 171 ? log4_path_change_receiver 172 : NULL, 173 &baton, 174 log4_entry_receiver, &baton, 175 pool)); 176 177 svn_pool_destroy(changes_pool); 178 return SVN_NO_ERROR; 179} 180