/*
* repos_diff_summarize.c -- The diff summarize editor for summarizing
* the differences of two repository versions
*
* ====================================================================
* Copyright (c) 2005-2006 CollabNet. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://subversion.tigris.org/license-1.html.
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
*
* This software consists of voluntary contributions made by many
* individuals. For exact contribution history, see the revision
* history and logs, available at http://subversion.tigris.org/.
* ====================================================================
*/
#include "svn_props.h"
#include "svn_pools.h"
#include "client.h"
/* Overall crawler editor baton. */
struct edit_baton {
/* The summarize callback passed down from the API */
svn_client_diff_summarize_func_t summarize_func;
/* The summarize callback baton */
void *summarize_func_baton;
/* An RA session used to check the kind of deleted paths */
svn_ra_session_t *ra_session;
/* The start revision for the comparison */
svn_revnum_t revision;
};
/* Item baton. */
struct item_baton {
/* The overall crawler editor baton */
struct edit_baton *edit_baton;
/* The summarize filled by the editor calls, NULL if this item hasn't
been modified (yet) */
svn_client_diff_summarize_t *summarize;
/* The path of the file or directory within the repository */
const char *path;
/* The kind of this item */
svn_node_kind_t node_kind;
/* The file/directory pool */
apr_pool_t *item_pool;
};
/* Create an item baton, with the fields initialized to EDIT_BATON, PATH,
* NODE_KIND and POOL, respectively. Allocate the returned structure in POOL.
*/
static struct item_baton *
create_item_baton(struct edit_baton *edit_baton,
const char *path,
svn_node_kind_t node_kind,
apr_pool_t *pool)
{
struct item_baton *b = apr_pcalloc(pool, sizeof(*b));
b->edit_baton = edit_baton;
b->path = apr_pstrdup(pool, path);
b->node_kind = node_kind;
b->item_pool = pool;
return b;
}
/* Make sure that this item baton contains a summarize struct.
* If it doesn't before this call, allocate a new struct in the item's pool,
* initializing the diff kind to normal.
* All other fields are also initialized from IB to to NULL/invalid values. */
static void
ensure_summarize(struct item_baton *ib)
{
svn_client_diff_summarize_t *sum;
if (ib->summarize)
return;
sum = apr_pcalloc(ib->item_pool, sizeof(*sum));
sum->node_kind = ib->node_kind;
sum->summarize_kind = svn_client_diff_summarize_kind_normal;
sum->path = ib->path;
ib->summarize = sum;
}
/* An editor function. The root of the comparison hierarchy */
static svn_error_t *
open_root(void *edit_baton,
svn_revnum_t base_revision,
apr_pool_t *pool,
void **root_baton)
{
struct item_baton *ib = create_item_baton(edit_baton, "",
svn_node_dir, pool);;
*root_baton = ib;
return SVN_NO_ERROR;
}
/* 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));
return SVN_NO_ERROR;
}
/* An editor function. */
static svn_error_t *
add_directory(const char *path,
void *parent_baton,
const char *copyfrom_path,
svn_revnum_t copyfrom_rev,
apr_pool_t *pool,
void **child_baton)
{
struct item_baton *pb = parent_baton;
struct item_baton *cb;
cb = create_item_baton(pb->edit_baton, path, svn_node_dir, pool);
ensure_summarize(cb);
cb->summarize->summarize_kind = svn_client_diff_summarize_kind_added;
*child_baton = cb;
return SVN_NO_ERROR;
}
/* An editor function. */
static svn_error_t *
open_directory(const char *path,
void *parent_baton,
svn_revnum_t base_revision,
apr_pool_t *pool,
void **child_baton)
{
struct item_baton *pb = parent_baton;
struct item_baton *cb;
cb = create_item_baton(pb->edit_baton, path, svn_node_dir, pool);
*child_baton = cb;
return SVN_NO_ERROR;
}
/* An editor function. */
static svn_error_t *
close_directory(void *dir_baton,
apr_pool_t *pool)
{
struct item_baton *ib = dir_baton;
struct edit_baton *eb = ib->edit_baton;
if (ib->summarize)
SVN_ERR(eb->summarize_func(ib->summarize, eb->summarize_func_baton,
pool));
return SVN_NO_ERROR;
}
/* An editor function. */
static svn_error_t *
add_file(const char *path,
void *parent_baton,
const char *copyfrom_path,
svn_revnum_t copyfrom_rev,
apr_pool_t *pool,
void **file_baton)
{
struct item_baton *pb = parent_baton;
struct item_baton *cb;
cb = create_item_baton(pb->edit_baton, path, svn_node_file, pool);
ensure_summarize(cb);
cb->summarize->summarize_kind = svn_client_diff_summarize_kind_added;
*file_baton = cb;
return SVN_NO_ERROR;
}
/* An editor function. */
static svn_error_t *
open_file(const char *path,
void *parent_baton,
svn_revnum_t base_revision,
apr_pool_t *pool,
void **file_baton)
{
struct item_baton *pb = parent_baton;
struct item_baton *cb;
cb = create_item_baton(pb->edit_baton, path, svn_node_file, pool);
*file_baton = cb;
return SVN_NO_ERROR;
}
/* An editor function. */
static svn_error_t *
apply_textdelta(void *file_baton,
const char *base_checksum,
apr_pool_t *pool,
svn_txdelta_window_handler_t *handler,
void **handler_baton)
{
struct item_baton *ib = file_baton;
ensure_summarize(ib);
if (ib->summarize->summarize_kind == svn_client_diff_summarize_kind_normal)
ib->summarize->summarize_kind = svn_client_diff_summarize_kind_modified;
*handler = svn_delta_noop_window_handler;
*handler_baton = NULL;
return SVN_NO_ERROR;
}
/* An editor function. */
static svn_error_t *
close_file(void *file_baton,
const char *text_checksum,
apr_pool_t *pool)
{
struct item_baton *fb = file_baton;
struct edit_baton *eb = fb->edit_baton;
if (fb->summarize)
SVN_ERR(eb->summarize_func(fb->summarize, eb->summarize_func_baton,
pool));
return SVN_NO_ERROR;
}
/* An editor function, implementing both change_file_prop and
* change_dir_prop. */
static svn_error_t *
change_prop(void *entry_baton,
const char *name,
const svn_string_t *value,
apr_pool_t *pool)
{
struct item_baton *ib = entry_baton;
if (svn_property_kind(NULL, name) == svn_prop_regular_kind)
{
ensure_summarize(ib);
ib->summarize->prop_changed = TRUE;
}
return SVN_NO_ERROR;
}
/* Create a repository diff summarize editor and baton. */
svn_error_t *
svn_client__get_diff_summarize_editor(const char *target,
svn_client_diff_summarize_func_t
summarize_func,
void *item_baton,
svn_ra_session_t *ra_session,
svn_revnum_t revision,
svn_cancel_func_t cancel_func,
void *cancel_baton,
const svn_delta_editor_t **editor,
void **edit_baton,
apr_pool_t *pool)
{
svn_delta_editor_t *tree_editor = svn_delta_default_editor(pool);
struct edit_baton *eb = apr_palloc(pool, sizeof(*eb));
eb->summarize_func = summarize_func;
eb->summarize_func_baton = item_baton;
eb->ra_session = ra_session;
eb->revision = revision;
tree_editor->open_root = open_root;
tree_editor->delete_entry = delete_entry;
tree_editor->add_directory = add_directory;
tree_editor->open_directory = open_directory;
tree_editor->change_dir_prop = change_prop;
tree_editor->close_directory = close_directory;
tree_editor->add_file = add_file;
tree_editor->open_file = open_file;
tree_editor->apply_textdelta = apply_textdelta;
tree_editor->change_file_prop = change_prop;
tree_editor->close_file = close_file;
SVN_ERR(svn_delta_get_cancellation_editor
(cancel_func, cancel_baton, tree_editor, eb, editor, edit_baton,
pool));
return SVN_NO_ERROR;
}
syntax highlighted by Code2HTML, v. 0.9.1