blob: b084a7a1ee5d2a3f8c85bd59bd8174d30c33e073 [file] [log] [blame]
/*
* svn_tests_editor.c: a `dummy' editor implementation for testing
*
* ====================================================================
* Copyright (c) 2000-2002 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 <stdio.h>
#include <string.h>
#include "apr_pools.h"
#include "apr_file_io.h"
#include "svn_types.h"
#include "svn_test.h"
#include "svn_error.h"
#include "svn_path.h"
#include "svn_delta.h"
struct edit_baton
{
svn_stringbuf_t *root_path;
svn_stringbuf_t *editor_name;
svn_stream_t *out_stream;
apr_pool_t *pool;
int indentation;
svn_boolean_t verbose;
svn_stringbuf_t *newline;
};
struct dir_baton
{
int indent_level;
svn_stringbuf_t *path;
struct edit_baton *edit_baton;
};
struct file_baton
{
int indent_level;
svn_stringbuf_t *path;
struct dir_baton *dir_baton;
};
/* Initialize EB->newline if it hasn't already been initialized, then
print EB->newline to EB->outstream. */
static svn_error_t *
newline (struct edit_baton *eb)
{
apr_size_t len;
if (! eb->newline)
eb->newline = svn_stringbuf_create ("\n", eb->pool);
len = eb->newline->len;
return svn_stream_write (eb->out_stream, eb->newline->data, &len);
}
/* Print EB->indentation * LEVEL spaces, followed by STR,
to EB->out_stream. */
static svn_error_t *
print (struct edit_baton *eb, int level, svn_stringbuf_t *str)
{
apr_size_t len;
int i;
len = 1;
for (i = 0; i < (eb->indentation * level); i++)
SVN_ERR (svn_stream_write (eb->out_stream, " ", &len));
len = str->len;
SVN_ERR (svn_stream_write (eb->out_stream, str->data, &len));
return SVN_NO_ERROR;
}
/* A dummy routine designed to consume windows of vcdiff data, (of
type svn_text_delta_window_handler_t). This will be called by the
vcdiff parser everytime it has a window ready to go. */
static svn_error_t *
my_vcdiff_windoweater (svn_txdelta_window_t *window, void *baton)
{
int i;
struct file_baton *fb = (struct file_baton *) baton;
apr_pool_t *pool = fb->dir_baton->edit_baton->pool;
svn_stringbuf_t *str;
/* We're done if non-verbose */
if (! fb->dir_baton->edit_baton->verbose)
return SVN_NO_ERROR;
if (window)
str = svn_stringbuf_createf (pool,
"[%s] window_handler (%ld ops)\n",
fb->dir_baton->edit_baton->editor_name->data,
(long int) window->num_ops);
else
str = svn_stringbuf_createf (pool,
"[%s] window_handler (EOT)\n",
fb->dir_baton->edit_baton->editor_name->data);
SVN_ERR (print (fb->dir_baton->edit_baton, fb->indent_level + 2, str));
if (window)
{
/* Delve into the vcdiff window and print the data. */
for (i = 1; i <= window->num_ops; i++)
{
switch (window->ops[i].action_code)
{
case svn_txdelta_new:
{
str = svn_stringbuf_createf
(pool,
"(%ld) new text: length %ld\n",
(long int) i,
(long int) (window->ops[i].length));
SVN_ERR (print (fb->dir_baton->edit_baton,
fb->indent_level + 2,
str));
break;
}
case svn_txdelta_source:
{
str = svn_stringbuf_createf
(pool,
"(%ld) source text: offset %ld, length %ld\n",
(long int) i,
(long int) window->ops[i].offset,
(long int) window->ops[i].length);
SVN_ERR (print (fb->dir_baton->edit_baton,
fb->indent_level + 2,
str));
break;
}
case svn_txdelta_target:
{
str = svn_stringbuf_createf
(pool,
"(%ld) target text: offset %ld, length %ld\n",
(long int) i,
(long int) window->ops[i].offset,
(long int) window->ops[i].length);
SVN_ERR (print (fb->dir_baton->edit_baton,
fb->indent_level + 2,
str));
break;
}
default:
{
str = svn_stringbuf_createf
(pool,
"(%ld) unknown window type\n",
(long int) i);
SVN_ERR (print (fb->dir_baton->edit_baton,
fb->indent_level + 2,
str));
break;
}
}
}
}
SVN_ERR (newline (fb->dir_baton->edit_baton));
return SVN_NO_ERROR;
}
static svn_error_t *
test_delete_entry (svn_stringbuf_t *filename,
svn_revnum_t revision,
void *parent_baton)
{
struct dir_baton *d = (struct dir_baton *) parent_baton;
svn_stringbuf_t *path;
svn_stringbuf_t *str;
path = svn_stringbuf_dup (d->path, d->edit_baton->pool);
svn_path_add_component (path, filename);
str = svn_stringbuf_createf (d->edit_baton->pool,
"[%s] delete_entry (%s)\n",
d->edit_baton->editor_name->data,
path->data);
SVN_ERR (print (d->edit_baton, d->indent_level + 1, str));
if (d->edit_baton->verbose)
SVN_ERR (newline (d->edit_baton));
return SVN_NO_ERROR;
}
static svn_error_t *
test_set_target_revision (void *edit_baton,
svn_revnum_t target_revision)
{
struct edit_baton *eb = (struct edit_baton *) edit_baton;
svn_stringbuf_t *str;
str = svn_stringbuf_createf (eb->pool,
"[%s] set_target_revision (%ld)\n",
eb->editor_name->data,
(long int) target_revision);
SVN_ERR (print (eb, 0, str));
if (eb->verbose)
SVN_ERR (newline (eb));
return SVN_NO_ERROR;
}
static svn_error_t *
test_open_root (void *edit_baton,
svn_revnum_t base_revision,
void **root_baton)
{
struct edit_baton *eb = (struct edit_baton *) edit_baton;
struct dir_baton *d = apr_pcalloc (eb->pool, sizeof (*d));
svn_stringbuf_t *str;
d->path = (svn_stringbuf_t *) svn_stringbuf_dup (eb->root_path, eb->pool);
d->edit_baton = eb;
d->indent_level = 0;
*root_baton = d;
str = svn_stringbuf_createf (eb->pool,
"[%s] open_root (%s)\n",
eb->editor_name->data,
eb->root_path->data);
SVN_ERR (print (eb, d->indent_level, str));
/* We're done if non-verbose */
if (! eb->verbose)
return SVN_NO_ERROR;
str = svn_stringbuf_createf (eb->pool,
"base_revision: %ld\n",
(long int) base_revision);
SVN_ERR (print (eb, d->indent_level, str));
SVN_ERR (newline (eb));
return SVN_NO_ERROR;
}
static svn_error_t *
add_or_open_dir (svn_stringbuf_t *name,
void *parent_baton,
svn_stringbuf_t *base_path,
svn_revnum_t base_revision,
void **child_baton,
const char *pivot_string)
{
struct dir_baton *pd = (struct dir_baton *) parent_baton;
struct dir_baton *d = apr_pcalloc (pd->edit_baton->pool, sizeof (*d));
svn_stringbuf_t *str;
/* Set child_baton to a new dir baton. */
d->path = svn_stringbuf_dup (pd->path, pd->edit_baton->pool);
svn_path_add_component (d->path, name);
d->edit_baton = pd->edit_baton;
d->indent_level = (pd->indent_level + 1);
*child_baton = d;
str = svn_stringbuf_createf (pd->edit_baton->pool,
"[%s] %s_directory (%s)\n",
pd->edit_baton->editor_name->data,
pivot_string,
d->path->data);
SVN_ERR (print (d->edit_baton, d->indent_level, str));
/* We're done if non-verbose */
if (! pd->edit_baton->verbose)
return SVN_NO_ERROR;
str = svn_stringbuf_createf (pd->edit_baton->pool,
"parent: %s\n", pd->path->data);
SVN_ERR (print (d->edit_baton, d->indent_level, str));
if (strcmp (pivot_string, "add") == 0)
{
str = svn_stringbuf_createf (pd->edit_baton->pool,
"copyfrom_path: %s\n",
base_path ? base_path->data : "");
SVN_ERR (print (d->edit_baton, d->indent_level, str));
str = svn_stringbuf_createf (pd->edit_baton->pool,
"copyfrom_revision: %ld\n",
(long int) base_revision);
SVN_ERR (print (d->edit_baton, d->indent_level, str));
}
else
{
str = svn_stringbuf_createf (pd->edit_baton->pool,
"base_revision: %ld\n",
(long int) base_revision);
SVN_ERR (print (d->edit_baton, d->indent_level, str));
}
SVN_ERR (newline (d->edit_baton));
return SVN_NO_ERROR;
}
static svn_error_t *
test_add_directory (svn_stringbuf_t *name,
void *parent_baton,
svn_stringbuf_t *copyfrom_path,
svn_revnum_t copyfrom_revision,
void **child_baton)
{
return add_or_open_dir (name,
parent_baton,
copyfrom_path,
copyfrom_revision,
child_baton,
"add");
}
static svn_error_t *
test_open_directory (svn_stringbuf_t *name,
void *parent_baton,
svn_revnum_t base_revision,
void **child_baton)
{
return add_or_open_dir (name,
parent_baton,
NULL,
base_revision,
child_baton,
"open");
}
static svn_error_t *
test_close_directory (void *dir_baton)
{
struct dir_baton *d = (struct dir_baton *) dir_baton;
svn_stringbuf_t *str;
str = svn_stringbuf_createf (d->edit_baton->pool,
"[%s] close_directory (%s)\n",
d->edit_baton->editor_name->data,
d->path->data);
SVN_ERR (print (d->edit_baton, d->indent_level, str));
if (d->edit_baton->verbose)
SVN_ERR (newline (d->edit_baton));
return SVN_NO_ERROR;
}
static svn_error_t *
test_close_file (void *file_baton)
{
struct file_baton *fb = (struct file_baton *) file_baton;
svn_stringbuf_t *str;
str = svn_stringbuf_createf (fb->dir_baton->edit_baton->pool,
"[%s] close_file (%s)\n",
fb->dir_baton->edit_baton->editor_name->data,
fb->path->data);
SVN_ERR (print (fb->dir_baton->edit_baton, fb->indent_level, str));
if (fb->dir_baton->edit_baton->verbose)
SVN_ERR (newline (fb->dir_baton->edit_baton));
return SVN_NO_ERROR;
}
static svn_error_t *
test_close_edit (void *edit_baton)
{
struct edit_baton *eb = edit_baton;
svn_stringbuf_t *str;
str = svn_stringbuf_createf (eb->pool,
"[%s] close_edit\n",
eb->editor_name->data);
SVN_ERR (print (eb, 0, str));
if (eb->verbose)
SVN_ERR (newline (eb));
return SVN_NO_ERROR;
}
static svn_error_t *
test_apply_textdelta (void *file_baton,
svn_txdelta_window_handler_t *handler,
void **handler_baton)
{
struct file_baton *fb = (struct file_baton *) file_baton;
svn_stringbuf_t *str;
/* Set the value of HANDLER and HANDLER_BATON here */
*handler = my_vcdiff_windoweater;
*handler_baton = fb;
str = svn_stringbuf_createf (fb->dir_baton->edit_baton->pool,
"[%s] apply_textdelta (%s)\n",
fb->dir_baton->edit_baton->editor_name->data,
fb->path->data);
SVN_ERR (print (fb->dir_baton->edit_baton, fb->indent_level + 1, str));
if (fb->dir_baton->edit_baton->verbose)
SVN_ERR (newline (fb->dir_baton->edit_baton));
return SVN_NO_ERROR;
}
static svn_error_t *
add_or_open_file (svn_stringbuf_t *name,
void *parent_baton,
svn_stringbuf_t *base_path,
svn_revnum_t base_revision,
void **file_baton,
const char *pivot_string)
{
struct dir_baton *d = (struct dir_baton *) parent_baton;
struct file_baton *fb = apr_pcalloc (d->edit_baton->pool, sizeof (*fb));
svn_stringbuf_t *str;
/* Put the filename in file_baton */
fb->dir_baton = d;
fb->path = (svn_stringbuf_t *) svn_stringbuf_dup (d->path,
d->edit_baton->pool);
svn_path_add_component (fb->path, name);
fb->indent_level = (d->indent_level + 1);
*file_baton = fb;
str = svn_stringbuf_createf (d->edit_baton->pool,
"[%s] %s_file (%s)\n",
d->edit_baton->editor_name->data,
pivot_string,
fb->path->data);
SVN_ERR (print (fb->dir_baton->edit_baton, fb->indent_level, str));
/* We're done if non-verbose */
if (! d->edit_baton->verbose)
return SVN_NO_ERROR;
str = svn_stringbuf_createf (d->edit_baton->pool,
"parent: %s\n", d->path->data);
SVN_ERR (print (fb->dir_baton->edit_baton, fb->indent_level, str));
if (strcmp (pivot_string, "add") == 0)
{
str = svn_stringbuf_createf (d->edit_baton->pool,
"copyfrom_path: %s\n",
base_path ? base_path->data : "");
SVN_ERR (print (fb->dir_baton->edit_baton, fb->indent_level, str));
str = svn_stringbuf_createf (d->edit_baton->pool,
"copyfrom_revision: %ld\n",
(long int) base_revision);
SVN_ERR (print (fb->dir_baton->edit_baton, fb->indent_level, str));
}
else
{
str = svn_stringbuf_createf (d->edit_baton->pool,
"base_revision: %ld\n",
(long int) base_revision);
SVN_ERR (print (fb->dir_baton->edit_baton, fb->indent_level, str));
}
SVN_ERR (newline (fb->dir_baton->edit_baton));
return SVN_NO_ERROR;
}
static svn_error_t *
test_add_file (svn_stringbuf_t *name,
void *parent_baton,
svn_stringbuf_t *copyfrom_path,
svn_revnum_t copyfrom_revision,
void **file_baton)
{
return add_or_open_file (name,
parent_baton,
copyfrom_path,
copyfrom_revision,
file_baton,
"add");
}
static svn_error_t *
test_open_file (svn_stringbuf_t *name,
void *parent_baton,
svn_revnum_t base_revision,
void **file_baton)
{
return add_or_open_file (name,
parent_baton,
NULL,
base_revision,
file_baton,
"open");
}
static svn_error_t *
test_change_file_prop (void *file_baton,
svn_stringbuf_t *name, svn_stringbuf_t *value)
{
struct file_baton *fb = (struct file_baton *) file_baton;
svn_stringbuf_t *str;
str = svn_stringbuf_createf (fb->dir_baton->edit_baton->pool,
"[%s] change_file_prop (%s)\n",
fb->dir_baton->edit_baton->editor_name->data,
fb->path->data);
SVN_ERR (print (fb->dir_baton->edit_baton, fb->indent_level + 1, str));
/* We're done if non-verbose */
if (! fb->dir_baton->edit_baton->verbose)
return SVN_NO_ERROR;
str = svn_stringbuf_createf (fb->dir_baton->edit_baton->pool,
"name: %s\n",
name->data);
SVN_ERR (print (fb->dir_baton->edit_baton, fb->indent_level + 1, str));
str = svn_stringbuf_createf (fb->dir_baton->edit_baton->pool,
"value: %s\n",
value ? value->data : "(null)");
SVN_ERR (print (fb->dir_baton->edit_baton, fb->indent_level + 1, str));
SVN_ERR (newline (fb->dir_baton->edit_baton));
return SVN_NO_ERROR;
}
static svn_error_t *
test_change_dir_prop (void *parent_baton,
svn_stringbuf_t *name, svn_stringbuf_t *value)
{
struct dir_baton *d = (struct dir_baton *) parent_baton;
svn_stringbuf_t *str;
str = svn_stringbuf_createf (d->edit_baton->pool,
"[%s] change_dir_prop (%s)\n",
d->edit_baton->editor_name->data,
d->path->data);
SVN_ERR (print (d->edit_baton, d->indent_level + 1, str));
/* We're done if non-verbose */
if (! d->edit_baton->verbose)
return SVN_NO_ERROR;
str = svn_stringbuf_createf (d->edit_baton->pool,
"name: %s\n",
name->data);
SVN_ERR (print (d->edit_baton, d->indent_level + 1, str));
str = svn_stringbuf_createf (d->edit_baton->pool,
"value: %s\n",
value ? value->data : "(null)");
SVN_ERR (print (d->edit_baton, d->indent_level + 1, str));
SVN_ERR (newline (d->edit_baton));
return SVN_NO_ERROR;
}
/*---------------------------------------------------------------*/
/** Public interface: svn_test_get_editor() **/
svn_error_t *
svn_test_get_editor (const svn_delta_edit_fns_t **editor,
void **edit_baton,
svn_stringbuf_t *editor_name,
svn_stream_t *out_stream,
int indentation,
svn_boolean_t verbose,
svn_stringbuf_t *path,
apr_pool_t *pool)
{
svn_delta_edit_fns_t *my_editor;
struct edit_baton *my_edit_baton;
/* Set up the editor. */
my_editor = svn_delta_old_default_editor (pool);
my_editor->set_target_revision = test_set_target_revision;
my_editor->open_root = test_open_root;
my_editor->delete_entry = test_delete_entry;
my_editor->add_directory = test_add_directory;
my_editor->open_directory = test_open_directory;
my_editor->close_directory = test_close_directory;
my_editor->add_file = test_add_file;
my_editor->open_file = test_open_file;
my_editor->close_file = test_close_file;
my_editor->apply_textdelta = test_apply_textdelta;
my_editor->change_file_prop = test_change_file_prop;
my_editor->change_dir_prop = test_change_dir_prop;
my_editor->close_edit = test_close_edit;
/* Set up the edit baton. */
my_edit_baton = apr_pcalloc (pool, sizeof (*my_edit_baton));
my_edit_baton->root_path = svn_stringbuf_dup (path, pool);
my_edit_baton->editor_name = svn_stringbuf_dup (editor_name, pool);
my_edit_baton->pool = pool;
my_edit_baton->indentation = indentation;
my_edit_baton->verbose = verbose;
my_edit_baton->out_stream = out_stream;
my_edit_baton->newline = NULL; /* allocated when first needed */
*editor = my_editor;
*edit_baton = my_edit_baton;
return SVN_NO_ERROR;
}