/* An editor function. */ static svn_error_t * delete_entry(const char *path, svn_revnum_t base_revision, void *parent_baton, apr_pool_t *pool) { struct item_baton *ib = parent_baton; struct edit_baton *eb = ib->edit_baton; svn_client_diff_summarize_t *sum; svn_node_kind_t kind; /* We need to know if this is a directory or a file */ SVN_ERR(svn_ra_check_path(eb->ra_session, path, eb->revision, &kind, pool)); sum = apr_pcalloc(pool, sizeof(*sum)); sum->summarize_kind = svn_client_diff_summarize_kind_deleted; sum->path = path; sum->node_kind = kind; SVN_ERR(eb->summarize_func(sum, eb->summarize_func_baton, pool)); if (kind == svn_node_dir) SVN_ERR(diff_deleted_dir(path, eb->revision, eb->ra_session, eb, eb->cancel_func, eb->cancel_baton, pool)); return SVN_NO_ERROR; }
/* An svn_delta_editor_t function. */ static svn_error_t * delete_entry(const char *path, svn_revnum_t base_revision, void *parent_baton, apr_pool_t *pool) { struct dir_baton *pb = parent_baton; struct edit_baton *eb = pb->edit_baton; svn_node_kind_t kind; svn_wc_notify_state_t state = svn_wc_notify_state_inapplicable; svn_wc_notify_action_t action = svn_wc_notify_skip; svn_boolean_t tree_conflicted = FALSE; apr_pool_t *scratch_pool; /* Skip *everything* within a newly tree-conflicted directory, * and directories the children of which should be skipped. */ if (pb->skip || pb->tree_conflicted || pb->skip_children) return SVN_NO_ERROR; scratch_pool = svn_pool_create(eb->pool); /* We need to know if this is a directory or a file */ SVN_ERR(svn_ra_check_path(eb->ra_session, path, eb->revision, &kind, scratch_pool)); switch (kind) { case svn_node_file: { SVN_ERR(diff_deleted_file(&state, &tree_conflicted, path, eb, scratch_pool)); break; } case svn_node_dir: { SVN_ERR(diff_deleted_dir(&state, &tree_conflicted, path, eb, scratch_pool)); break; } default: break; } if ((state != svn_wc_notify_state_missing) && (state != svn_wc_notify_state_obstructed) && !tree_conflicted) { action = svn_wc_notify_update_delete; } if (eb->notify_func) { const char *deleted_path = apr_pstrdup(eb->pool, path); deleted_path_notify_t *dpn = apr_pcalloc(eb->pool, sizeof(*dpn)); dpn->kind = kind; dpn->action = tree_conflicted ? svn_wc_notify_tree_conflict : action; dpn->state = state; dpn->tree_conflicted = tree_conflicted; apr_hash_set(eb->deleted_paths, deleted_path, APR_HASH_KEY_STRING, dpn); } svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; }
/* ### TODO: Handle depth. */ static svn_error_t * diff_deleted_dir(const char *dir, svn_revnum_t revision, svn_ra_session_t *ra_session, void *edit_baton, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) { struct edit_baton *eb = edit_baton; apr_hash_t *dirents; apr_pool_t *iterpool = svn_pool_create(pool); apr_hash_index_t *hi; if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); SVN_ERR(svn_ra_get_dir2(ra_session, &dirents, NULL, NULL, dir, revision, SVN_DIRENT_KIND, pool)); for (hi = apr_hash_first(pool, dirents); hi; hi = apr_hash_next(hi)) { const char *path; const char *name = svn__apr_hash_index_key(hi); svn_dirent_t *dirent = svn__apr_hash_index_val(hi); svn_node_kind_t kind; svn_client_diff_summarize_t *sum; svn_pool_clear(iterpool); path = svn_relpath_join(dir, name, iterpool); SVN_ERR(svn_ra_check_path(eb->ra_session, path, eb->revision, &kind, iterpool)); sum = apr_pcalloc(iterpool, sizeof(*sum)); sum->summarize_kind = svn_client_diff_summarize_kind_deleted; sum->path = path; sum->node_kind = kind; SVN_ERR(eb->summarize_func(sum, eb->summarize_func_baton, iterpool)); if (dirent->kind == svn_node_dir) SVN_ERR(diff_deleted_dir(path, revision, ra_session, eb, cancel_func, cancel_baton, iterpool)); } svn_pool_destroy(iterpool); return SVN_NO_ERROR; }
/* ### TODO: Handle depth. */ static svn_error_t * diff_deleted_dir(svn_wc_notify_state_t *state_p, svn_boolean_t *tree_conflicted_p, const char *dir, struct edit_baton *eb, apr_pool_t *pool) { apr_hash_t *dirents; apr_pool_t *iterpool = svn_pool_create(pool); apr_hash_index_t *hi; SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(eb->revision)); if (eb->cancel_func) SVN_ERR(eb->cancel_func(eb->cancel_baton)); SVN_ERR(eb->diff_callbacks->dir_deleted( state_p, tree_conflicted_p, dir, eb->diff_cmd_baton, pool)); /* The "old" dir will be skipped by the repository report. If required, * crawl it recursively, diffing each file against the empty file. This * is a workaround for issue 2333 "'svn diff URL1 URL2' not reverse of * 'svn diff URL2 URL1'". */ if (! eb->walk_deleted_repos_dirs) { svn_pool_destroy(iterpool); return SVN_NO_ERROR; } SVN_ERR(svn_ra_get_dir2(eb->ra_session, &dirents, NULL, NULL, dir, eb->revision, SVN_DIRENT_KIND, pool)); for (hi = apr_hash_first(pool, dirents); hi; hi = apr_hash_next(hi)) { const char *path; const char *name = svn__apr_hash_index_key(hi); svn_dirent_t *dirent = svn__apr_hash_index_val(hi); svn_pool_clear(iterpool); path = svn_relpath_join(dir, name, iterpool); if (dirent->kind == svn_node_file) { SVN_ERR(diff_deleted_file(NULL, NULL, path, eb, iterpool)); } if (dirent->kind == svn_node_dir) { SVN_ERR(diff_deleted_dir(NULL, NULL, path, eb, iterpool)); } } svn_pool_destroy(iterpool); return SVN_NO_ERROR; }