📄 repos_diff.c
字号:
return SVN_NO_ERROR;
}
/* Get the props attached to a directory in the repository. */
static svn_error_t *
get_dirprops_from_ra (struct dir_baton *b)
{
SVN_ERR (b->edit_baton->ra_lib->get_dir (b->edit_baton->ra_session,
b->path,
b->edit_baton->revision,
NULL, NULL,
&(b->pristine_props),
b->pool));
return SVN_NO_ERROR;
}
/* Create an empty file, the path to the file is returned in EMPTY_FILE.
* If HAVE_WRITE_LOCK is true, create the file in the working directory,
* otherwise use a system temp dir.
*/
static svn_error_t *
create_empty_file (const char **empty_file,
svn_boolean_t have_write_lock,
apr_pool_t *pool)
{
apr_file_t *file;
const char *temp_path;
if (have_write_lock)
{
temp_path = "tmp";
}
else
{
const char *temp_dir;
SVN_ERR (svn_io_temp_dir (&temp_dir, pool));
temp_path = svn_path_join (temp_dir, "tmp", pool);
}
SVN_ERR (svn_io_open_unique_file (&file, empty_file, temp_path,
"", FALSE, pool));
SVN_ERR (svn_io_file_close (file, pool));
return SVN_NO_ERROR;
}
/* Return in *PATH_ACCESS the access baton for the directory PATH by
searching the access baton set of ADM_ACCESS. If ADM_ACCESS is NULL
then *PATH_ACCESS will be NULL. If LENIENT is TRUE then failure to find
an access baton will not return an error but will set *PATH_ACCESS to
NULL instead. */
static svn_error_t *
get_path_access (svn_wc_adm_access_t **path_access,
svn_wc_adm_access_t *adm_access,
const char *path,
svn_boolean_t lenient,
apr_pool_t *pool)
{
if (! adm_access)
*path_access = NULL;
else
{
svn_error_t *err = svn_wc_adm_retrieve (path_access, adm_access, path,
pool);
if (err)
{
if (! lenient)
return err;
svn_error_clear (err);
*path_access = NULL;
}
}
return SVN_NO_ERROR;
}
/* Like get_path_access except the returned access baton, in
*PARENT_ACCESS, is for the parent of PATH rather than for PATH
itself. */
static svn_error_t *
get_parent_access (svn_wc_adm_access_t **parent_access,
svn_wc_adm_access_t *adm_access,
const char *path,
svn_boolean_t lenient,
apr_pool_t *pool)
{
if (! adm_access)
*parent_access = NULL; /* Avoid messing around with paths */
else
{
const char *parent_path = svn_path_dirname (path, pool);
SVN_ERR (get_path_access (parent_access, adm_access, parent_path,
lenient, pool));
}
return SVN_NO_ERROR;
}
/* Get the empty file associated with the edit baton. This is cached so
* that it can be reused, all empty files are the same.
*/
static svn_error_t *
get_empty_file (struct edit_baton *b,
const char **empty_file)
{
/* Create the file if it does not exist */
if (!b->empty_file)
{
svn_boolean_t have_lock;
have_lock = (b->adm_access && svn_wc_adm_locked (b->adm_access));
SVN_ERR (create_empty_file (&(b->empty_file), have_lock, b->pool));
/* Install a pool cleanup handler to delete the file */
SVN_ERR (temp_file_cleanup_register (b->empty_file, b->pool));
}
*empty_file = b->empty_file;
return SVN_NO_ERROR;
}
/* An editor function. The root of the comparison hierarchy */
static svn_error_t *
set_target_revision (void *edit_baton,
svn_revnum_t target_revision,
apr_pool_t *pool)
{
struct edit_baton *eb = edit_baton;
eb->target_revision = target_revision;
return SVN_NO_ERROR;
}
/* 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 edit_baton *eb = edit_baton;
struct dir_baton *dir_baton = apr_pcalloc (pool, sizeof (*dir_baton));
dir_baton->dir_baton = NULL;
dir_baton->edit_baton = eb;
dir_baton->added = FALSE;
dir_baton->pool = pool;
dir_baton->path = "";
dir_baton->wcpath = eb->target ? apr_pstrdup (pool, eb->target) : "";
dir_baton->propchanges = apr_array_make (pool, 1, sizeof (svn_prop_t));
*root_baton = dir_baton;
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 dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
svn_node_kind_t kind;
svn_wc_adm_access_t *adm_access;
svn_wc_notify_state_t state = svn_wc_notify_state_inapplicable;
svn_wc_notify_action_t action = svn_wc_notify_skip;
/* We need to know if this is a directory or a file */
SVN_ERR (pb->edit_baton->ra_lib->check_path (pb->edit_baton->ra_session,
path,
pb->edit_baton->revision,
&kind,
pool));
SVN_ERR (get_path_access (&adm_access, eb->adm_access, pb->wcpath,
TRUE, pool));
if ((! eb->adm_access) || adm_access)
{
switch (kind)
{
case svn_node_file:
{
const char *mimetype1, *mimetype2;
struct file_baton *b;
/* Compare a file being deleted against an empty file */
b = make_file_baton (path, FALSE, pb->edit_baton, pool);
SVN_ERR (get_file_from_ra (b));
SVN_ERR (get_empty_file(b->edit_baton, &(b->path_end_revision)));
get_file_mime_types (&mimetype1, &mimetype2, b);
SVN_ERR (pb->edit_baton->diff_callbacks->file_deleted
(adm_access, &state, b->wcpath,
b->path_start_revision,
b->path_end_revision,
mimetype1, mimetype2,
b->edit_baton->diff_cmd_baton));
break;
}
case svn_node_dir:
{
SVN_ERR (pb->edit_baton->diff_callbacks->dir_deleted
(adm_access, &state,
svn_path_join (eb->target, path, pool),
pb->edit_baton->diff_cmd_baton));
break;
}
default:
break;
}
if ((state != svn_wc_notify_state_missing)
&& (state != svn_wc_notify_state_obstructed))
action = svn_wc_notify_update_delete;
}
if (pb->edit_baton->notify_func)
(*pb->edit_baton->notify_func) (pb->edit_baton->notify_baton,
svn_path_join (eb->target, path, pool),
action,
kind,
NULL,
state, state,
SVN_INVALID_REVNUM);
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_revision,
apr_pool_t *pool,
void **child_baton)
{
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
struct dir_baton *b;
svn_wc_adm_access_t *adm_access;
svn_wc_notify_state_t state;
svn_wc_notify_action_t action;
/* ### TODO: support copyfrom? */
b = make_dir_baton (path, pb, TRUE, pool);
*child_baton = b;
SVN_ERR (get_path_access (&adm_access,
pb->edit_baton->adm_access, pb->wcpath,
pb->edit_baton->dry_run, pool));
SVN_ERR (pb->edit_baton->diff_callbacks->dir_added
(adm_access, &state, b->wcpath, eb->target_revision,
pb->edit_baton->diff_cmd_baton));
if ((state == svn_wc_notify_state_missing)
|| (state == svn_wc_notify_state_obstructed))
action = svn_wc_notify_skip;
else
action = svn_wc_notify_update_add;
if (pb->edit_baton->notify_func)
(*pb->edit_baton->notify_func) (pb->edit_baton->notify_baton,
b->wcpath,
action,
svn_node_dir,
NULL,
svn_wc_notify_state_unknown,
svn_wc_notify_state_unknown,
SVN_INVALID_REVNUM);
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 dir_baton *pb = parent_baton;
struct dir_baton *b;
b = make_dir_baton (path, pb, FALSE, pool);
*child_baton = b;
SVN_ERR (get_dirprops_from_ra (b));
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_revision,
apr_pool_t *pool,
void **file_baton)
{
struct dir_baton *pb = parent_baton;
struct file_baton *b;
/* ### TODO: support copyfrom? */
b = make_file_baton (path, TRUE, pb->edit_baton, pool);
*file_baton = b;
SVN_ERR (get_empty_file (b->edit_baton, &(b->path_start_revision)));
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 dir_baton *pb = parent_baton;
struct file_baton *b;
b = make_file_baton (path, FALSE, pb->edit_baton, pool);
*file_baton = b;
SVN_ERR (get_file_from_ra (b));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -