| /* |
| * repos_diff_summarize.c -- The diff callbacks for summarizing |
| * the differences of two repository 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_dirent_uri.h" |
| #include "svn_hash.h" |
| #include "svn_path.h" |
| #include "svn_props.h" |
| #include "svn_pools.h" |
| |
| #include "private/svn_wc_private.h" |
| |
| #include "client.h" |
| |
| |
| /* Diff callbacks baton. */ |
| struct summarize_baton_t { |
| /* The summarize callback passed down from the API */ |
| svn_client_diff_summarize_func_t summarize_func; |
| |
| /* The summarize callback baton */ |
| void *summarize_func_baton; |
| }; |
| |
| /* Call B->summarize_func with B->summarize_func_baton, passing it a |
| * summary object composed from PATH, SUMMARIZE_KIND, PROP_CHANGED (or |
| * FALSE if the action is an add or delete) and NODE_KIND. */ |
| static svn_error_t * |
| send_summary(struct summarize_baton_t *b, |
| const char *path, |
| svn_client_diff_summarize_kind_t summarize_kind, |
| svn_boolean_t prop_changed, |
| svn_node_kind_t node_kind, |
| apr_pool_t *scratch_pool) |
| { |
| svn_client_diff_summarize_t *sum = apr_pcalloc(scratch_pool, sizeof(*sum)); |
| |
| SVN_ERR_ASSERT(summarize_kind != svn_client_diff_summarize_kind_normal |
| || prop_changed); |
| |
| sum->path = path; |
| sum->summarize_kind = summarize_kind; |
| if (summarize_kind == svn_client_diff_summarize_kind_modified |
| || summarize_kind == svn_client_diff_summarize_kind_normal) |
| sum->prop_changed = prop_changed; |
| sum->node_kind = node_kind; |
| |
| SVN_ERR(b->summarize_func(sum, b->summarize_func_baton, scratch_pool)); |
| return SVN_NO_ERROR; |
| } |
| |
| /* Are there any changes to relevant (normal) props in PROPS? */ |
| static svn_boolean_t |
| props_changed_hash(apr_hash_t *props, |
| apr_pool_t *scratch_pool) |
| { |
| apr_hash_index_t *hi; |
| |
| if (!props) |
| return FALSE; |
| |
| for (hi = apr_hash_first(scratch_pool, props); hi; hi = apr_hash_next(hi)) |
| { |
| const char *name = apr_hash_this_key(hi); |
| |
| if (svn_property_kind2(name) == svn_prop_regular_kind) |
| { |
| return TRUE; |
| } |
| } |
| |
| return FALSE; |
| } |
| |
| /* Are there any changes to relevant (normal) props in PROPCHANGES? */ |
| static svn_boolean_t |
| props_changed(const apr_array_header_t *propchanges, |
| apr_pool_t *scratch_pool) |
| { |
| apr_array_header_t *props; |
| |
| svn_error_clear(svn_categorize_props(propchanges, NULL, NULL, &props, |
| scratch_pool)); |
| return (props->nelts != 0); |
| } |
| |
| /* svn_diff_tree_processor_t callback */ |
| static svn_error_t * |
| diff_dir_opened(void **new_dir_baton, |
| svn_boolean_t *skip, |
| svn_boolean_t *skip_children, |
| const char *relpath, |
| const svn_diff_source_t *left_source, |
| const svn_diff_source_t *right_source, |
| const svn_diff_source_t *copyfrom_source, |
| void *parent_dir_baton, |
| const struct svn_diff_tree_processor_t *processor, |
| apr_pool_t *result_pool, |
| apr_pool_t *scratch_pool) |
| { |
| /* struct summarize_baton_t *b = processor->baton; */ |
| |
| /* ### Send here instead of from dir_added() ? */ |
| /*if (!left_source) |
| { |
| SVN_ERR(send_summary(b, relpath, svn_client_diff_summarize_kind_added, |
| FALSE, svn_node_dir, scratch_pool)); |
| }*/ |
| |
| return SVN_NO_ERROR; |
| } |
| |
| /* svn_diff_tree_processor_t callback */ |
| static svn_error_t * |
| diff_dir_changed(const char *relpath, |
| const svn_diff_source_t *left_source, |
| const svn_diff_source_t *right_source, |
| /*const*/ apr_hash_t *left_props, |
| /*const*/ apr_hash_t *right_props, |
| const apr_array_header_t *prop_changes, |
| void *dir_baton, |
| const struct svn_diff_tree_processor_t *processor, |
| apr_pool_t *scratch_pool) |
| { |
| struct summarize_baton_t *b = processor->baton; |
| |
| SVN_ERR(send_summary(b, relpath, svn_client_diff_summarize_kind_normal, |
| TRUE, svn_node_dir, scratch_pool)); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| /* svn_diff_tree_processor_t callback */ |
| static svn_error_t * |
| diff_dir_added(const char *relpath, |
| const svn_diff_source_t *copyfrom_source, |
| const svn_diff_source_t *right_source, |
| /*const*/ apr_hash_t *copyfrom_props, |
| /*const*/ apr_hash_t *right_props, |
| void *dir_baton, |
| const struct svn_diff_tree_processor_t *processor, |
| apr_pool_t *scratch_pool) |
| { |
| struct summarize_baton_t *b = processor->baton; |
| |
| /* ### Send from dir_opened without prop info? */ |
| SVN_ERR(send_summary(b, relpath, svn_client_diff_summarize_kind_added, |
| props_changed_hash(right_props, scratch_pool), |
| svn_node_dir, scratch_pool)); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| /* svn_diff_tree_processor_t callback */ |
| static svn_error_t * |
| diff_dir_deleted(const char *relpath, |
| const svn_diff_source_t *left_source, |
| /*const*/ apr_hash_t *left_props, |
| void *dir_baton, |
| const struct svn_diff_tree_processor_t *processor, |
| apr_pool_t *scratch_pool) |
| { |
| struct summarize_baton_t *b = processor->baton; |
| |
| SVN_ERR(send_summary(b, relpath, svn_client_diff_summarize_kind_deleted, |
| FALSE, svn_node_dir, scratch_pool)); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| /* svn_diff_tree_processor_t callback */ |
| static svn_error_t * |
| diff_file_added(const char *relpath, |
| const svn_diff_source_t *copyfrom_source, |
| const svn_diff_source_t *right_source, |
| const char *copyfrom_file, |
| const char *right_file, |
| /*const*/ apr_hash_t *copyfrom_props, |
| /*const*/ apr_hash_t *right_props, |
| void *file_baton, |
| const struct svn_diff_tree_processor_t *processor, |
| apr_pool_t *scratch_pool) |
| { |
| struct summarize_baton_t *b = processor->baton; |
| |
| SVN_ERR(send_summary(b, relpath, svn_client_diff_summarize_kind_added, |
| props_changed_hash(right_props, scratch_pool), |
| svn_node_file, scratch_pool)); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| /* svn_diff_tree_processor_t callback */ |
| static svn_error_t * |
| diff_file_changed(const char *relpath, |
| const svn_diff_source_t *left_source, |
| const svn_diff_source_t *right_source, |
| const char *left_file, |
| const char *right_file, |
| /*const*/ apr_hash_t *left_props, |
| /*const*/ apr_hash_t *right_props, |
| svn_boolean_t file_modified, |
| const apr_array_header_t *prop_changes, |
| void *file_baton, |
| const struct svn_diff_tree_processor_t *processor, |
| apr_pool_t *scratch_pool) |
| { |
| struct summarize_baton_t *b = processor->baton; |
| |
| SVN_ERR(send_summary(b, relpath, |
| file_modified ? svn_client_diff_summarize_kind_modified |
| : svn_client_diff_summarize_kind_normal, |
| props_changed(prop_changes, scratch_pool), |
| svn_node_file, scratch_pool)); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| /* svn_diff_tree_processor_t callback */ |
| static svn_error_t * |
| diff_file_deleted(const char *relpath, |
| const svn_diff_source_t *left_source, |
| const char *left_file, |
| /*const*/ apr_hash_t *left_props, |
| void *file_baton, |
| const struct svn_diff_tree_processor_t *processor, |
| apr_pool_t *scratch_pool) |
| { |
| struct summarize_baton_t *b = processor->baton; |
| |
| SVN_ERR(send_summary(b, relpath, svn_client_diff_summarize_kind_deleted, |
| FALSE, svn_node_file, scratch_pool)); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| svn_error_t * |
| svn_client__get_diff_summarize_callbacks( |
| svn_diff_tree_processor_t **diff_processor, |
| svn_client_diff_summarize_func_t summarize_func, |
| void *summarize_baton, |
| apr_pool_t *result_pool, |
| apr_pool_t *scratch_pool) |
| { |
| svn_diff_tree_processor_t *dp; |
| struct summarize_baton_t *b = apr_pcalloc(result_pool, sizeof(*b)); |
| |
| b->summarize_func = summarize_func; |
| b->summarize_func_baton = summarize_baton; |
| |
| dp = svn_diff__tree_processor_create(b, result_pool); |
| |
| /*dp->file_opened = diff_file_opened;*/ |
| dp->file_added = diff_file_added; |
| dp->file_deleted = diff_file_deleted; |
| dp->file_changed = diff_file_changed; |
| |
| dp->dir_opened = diff_dir_opened; |
| dp->dir_changed = diff_dir_changed; |
| dp->dir_deleted = diff_dir_deleted; |
| dp->dir_added = diff_dir_added; |
| |
| *diff_processor = dp; |
| |
| return SVN_NO_ERROR; |
| } |
| |
| svn_client_diff_summarize_t * |
| svn_client_diff_summarize_dup(const svn_client_diff_summarize_t *diff, |
| apr_pool_t *pool) |
| { |
| svn_client_diff_summarize_t *dup_diff = apr_palloc(pool, sizeof(*dup_diff)); |
| |
| *dup_diff = *diff; |
| |
| if (diff->path) |
| dup_diff->path = apr_pstrdup(pool, diff->path); |
| |
| return dup_diff; |
| } |