static void *compile_merge_config(apr_pool_t *pool, void *config1, void *config2) { compile_config_t *base = (compile_config_t*) config1; compile_config_t *overrides = (compile_config_t*) config2; compile_config_t *config; config = (compile_config_t*) apr_pcalloc(pool, sizeof (compile_config_t)); COMPILE_MERGE_FLAG(enabled); COMPILE_MERGE_FLAG(use_path_info); if (base->extension_commands && overrides->extension_commands) { config->extension_commands = apr_hash_merge(pool, overrides->extension_commands, base->extension_commands, compile_overlay_extension_commands, NULL); } else { if (base->extension_commands == NULL) { config->extension_commands = overrides->extension_commands; } else { config->extension_commands = base->extension_commands; } if (config->extension_commands && overrides->removed_commands) { config->extension_commands = apr_hash_copy(pool, config->extension_commands); } } if (config->extension_commands) { if (overrides->removed_commands) { compile_remove_extension_commands(pool, overrides->removed_commands, config->extension_commands); } } config->removed_commands = NULL; return (void*) config; }
/* Produce a diff of depth DEPTH for the directory at LOCAL_ABSPATH, * using information from the arbitrary_diff_walker_baton B. * LOCAL_ABSPATH is the path being crawled and can be on either side * of the diff depending on baton->recursing_within_added_subtree. */ static svn_error_t * arbitrary_diff_this_dir(struct arbitrary_diff_walker_baton *b, const char *local_abspath, svn_depth_t depth, apr_pool_t *scratch_pool) { const char *local_abspath1; const char *local_abspath2; svn_node_kind_t kind1; svn_node_kind_t kind2; const char *child_relpath; apr_hash_t *dirents1; apr_hash_t *dirents2; apr_hash_t *merged_dirents; apr_array_header_t *sorted_dirents; int i; apr_pool_t *iterpool; if (b->recursing_within_adm_dir) { if (svn_dirent_skip_ancestor(b->adm_dir_abspath, local_abspath)) return SVN_NO_ERROR; else { b->recursing_within_adm_dir = FALSE; b->adm_dir_abspath = NULL; } } else if (svn_wc_is_adm_dir(svn_dirent_basename(local_abspath, NULL), scratch_pool)) { b->recursing_within_adm_dir = TRUE; b->adm_dir_abspath = apr_pstrdup(b->pool, local_abspath); return SVN_NO_ERROR; } if (b->recursing_within_added_subtree) child_relpath = svn_dirent_skip_ancestor(b->root2_abspath, local_abspath); else child_relpath = svn_dirent_skip_ancestor(b->root1_abspath, local_abspath); if (!child_relpath) return SVN_NO_ERROR; local_abspath1 = svn_dirent_join(b->root1_abspath, child_relpath, scratch_pool); SVN_ERR(svn_io_check_resolved_path(local_abspath1, &kind1, scratch_pool)); local_abspath2 = svn_dirent_join(b->root2_abspath, child_relpath, scratch_pool); SVN_ERR(svn_io_check_resolved_path(local_abspath2, &kind2, scratch_pool)); if (depth > svn_depth_empty) { if (kind1 == svn_node_dir) SVN_ERR(svn_io_get_dirents3(&dirents1, local_abspath1, TRUE, /* only_check_type */ scratch_pool, scratch_pool)); else dirents1 = apr_hash_make(scratch_pool); } if (kind2 == svn_node_dir) { apr_hash_t *original_props; apr_hash_t *modified_props; apr_array_header_t *prop_changes; /* Show any property changes for this directory. */ SVN_ERR(get_props(&original_props, local_abspath1, b->ctx->wc_ctx, scratch_pool, scratch_pool)); SVN_ERR(get_props(&modified_props, local_abspath2, b->ctx->wc_ctx, scratch_pool, scratch_pool)); SVN_ERR(svn_prop_diffs(&prop_changes, modified_props, original_props, scratch_pool)); if (prop_changes->nelts > 0) SVN_ERR(b->callbacks->dir_props_changed(NULL, NULL, child_relpath, FALSE /* was_added */, prop_changes, original_props, b->diff_baton, scratch_pool)); if (depth > svn_depth_empty) { /* Read directory entries. */ SVN_ERR(svn_io_get_dirents3(&dirents2, local_abspath2, TRUE, /* only_check_type */ scratch_pool, scratch_pool)); } } else if (depth > svn_depth_empty) dirents2 = apr_hash_make(scratch_pool); if (depth <= svn_depth_empty) return SVN_NO_ERROR; /* Compare dirents1 to dirents2 and show added/deleted/changed files. */ merged_dirents = apr_hash_merge(scratch_pool, dirents1, dirents2, NULL, NULL); sorted_dirents = svn_sort__hash(merged_dirents, svn_sort_compare_items_as_paths, scratch_pool); iterpool = svn_pool_create(scratch_pool); for (i = 0; i < sorted_dirents->nelts; i++) { svn_sort__item_t elt = APR_ARRAY_IDX(sorted_dirents, i, svn_sort__item_t); const char *name = elt.key; svn_io_dirent2_t *dirent1; svn_io_dirent2_t *dirent2; const char *child1_abspath; const char *child2_abspath; svn_pool_clear(iterpool); if (b->ctx->cancel_func) SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton)); if (strcmp(name, SVN_WC_ADM_DIR_NAME) == 0) continue; dirent1 = svn_hash_gets(dirents1, name); if (!dirent1) { dirent1 = svn_io_dirent2_create(iterpool); dirent1->kind = svn_node_none; } dirent2 = svn_hash_gets(dirents2, name); if (!dirent2) { dirent2 = svn_io_dirent2_create(iterpool); dirent2->kind = svn_node_none; } child1_abspath = svn_dirent_join(local_abspath1, name, iterpool); child2_abspath = svn_dirent_join(local_abspath2, name, iterpool); if (dirent1->special) SVN_ERR(svn_io_check_resolved_path(child1_abspath, &dirent1->kind, iterpool)); if (dirent2->special) SVN_ERR(svn_io_check_resolved_path(child1_abspath, &dirent2->kind, iterpool)); if (dirent1->kind == svn_node_dir && dirent2->kind == svn_node_dir) { if (depth == svn_depth_immediates) { /* Not using the walker, so show property diffs on these dirs. */ SVN_ERR(do_arbitrary_dirs_diff(child1_abspath, child2_abspath, b->root1_abspath, b->root2_abspath, svn_depth_empty, b->callbacks, b->diff_baton, b->ctx, iterpool)); } else { /* Either the walker will visit these directories (with * depth=infinity) and they will be processed as 'this dir' * later, or we're showing file children only (depth=files). */ continue; } } /* Files that exist only in dirents1. */ if (dirent1->kind == svn_node_file && (dirent2->kind == svn_node_dir || dirent2->kind == svn_node_none)) SVN_ERR(do_arbitrary_files_diff(child1_abspath, b->empty_file_abspath, svn_relpath_join(child_relpath, name, iterpool), FALSE, TRUE, NULL, b->callbacks, b->diff_baton, b->ctx, iterpool)); /* Files that exist only in dirents2. */ if (dirent2->kind == svn_node_file && (dirent1->kind == svn_node_dir || dirent1->kind == svn_node_none)) { apr_hash_t *original_props; SVN_ERR(get_props(&original_props, child1_abspath, b->ctx->wc_ctx, scratch_pool, scratch_pool)); SVN_ERR(do_arbitrary_files_diff(b->empty_file_abspath, child2_abspath, svn_relpath_join(child_relpath, name, iterpool), TRUE, FALSE, original_props, b->callbacks, b->diff_baton, b->ctx, iterpool)); } /* Files that exist in dirents1 and dirents2. */ if (dirent1->kind == svn_node_file && dirent2->kind == svn_node_file) SVN_ERR(do_arbitrary_files_diff(child1_abspath, child2_abspath, svn_relpath_join(child_relpath, name, iterpool), FALSE, FALSE, NULL, b->callbacks, b->diff_baton, b->ctx, scratch_pool)); /* Directories that only exist in dirents2. These aren't crawled * by this walker so we have to crawl them separately. */ if (depth > svn_depth_files && dirent2->kind == svn_node_dir && (dirent1->kind == svn_node_file || dirent1->kind == svn_node_none)) SVN_ERR(do_arbitrary_dirs_diff(child1_abspath, child2_abspath, b->root1_abspath, b->root2_abspath, depth <= svn_depth_immediates ? svn_depth_empty : svn_depth_infinity , b->callbacks, b->diff_baton, b->ctx, iterpool)); } svn_pool_destroy(iterpool); return SVN_NO_ERROR; }