📄 repos_diff.c
字号:
return SVN_NO_ERROR;
}
/* An editor function. Do the work of applying the text delta. */
static svn_error_t *
window_handler (svn_txdelta_window_t *window,
void *window_baton)
{
struct file_baton *b = window_baton;
SVN_ERR (b->apply_handler (window, b->apply_baton));
if (!window)
{
SVN_ERR (svn_io_file_close (b->file_start_revision, b->pool));
SVN_ERR (svn_io_file_close (b->file_end_revision, b->pool));
}
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 file_baton *b = file_baton;
svn_boolean_t have_lock;
/* Open the file to be used as the base for second revision */
SVN_ERR (svn_io_file_open (&(b->file_start_revision),
b->path_start_revision,
APR_READ, APR_OS_DEFAULT, b->pool));
/* Open the file that will become the second revision after applying the
text delta, it starts empty */
have_lock = (b->edit_baton->adm_access
&& svn_wc_adm_locked (b->edit_baton->adm_access));
SVN_ERR (create_empty_file (&(b->path_end_revision), have_lock, b->pool));
SVN_ERR (temp_file_cleanup_register (b->path_end_revision, b->pool));
SVN_ERR (svn_io_file_open (&(b->file_end_revision), b->path_end_revision,
APR_WRITE, APR_OS_DEFAULT, b->pool));
svn_txdelta_apply (svn_stream_from_aprfile (b->file_start_revision, b->pool),
svn_stream_from_aprfile (b->file_end_revision, b->pool),
NULL,
b->path,
b->pool,
&(b->apply_handler), &(b->apply_baton));
*handler = window_handler;
*handler_baton = file_baton;
return SVN_NO_ERROR;
}
/* An editor function. When the file is closed we have a temporary
* file containing a pristine version of the repository file. This can
* be compared against the working copy.
*
* ### Ignore TEXT_CHECKSUM for now. Someday we can use it to verify
* ### the integrity of the file being diffed. Done efficiently, this
* ### would probably involve calculating the checksum as the data is
* ### received, storing the final checksum in the file_baton, and
* ### comparing against it here.
*/
static svn_error_t *
close_file (void *file_baton,
const char *text_checksum,
apr_pool_t *pool)
{
struct file_baton *b = file_baton;
struct edit_baton *eb = b->edit_baton;
svn_wc_adm_access_t *adm_access;
svn_error_t *err;
svn_wc_notify_action_t action;
svn_wc_notify_state_t
content_state = svn_wc_notify_state_unknown,
prop_state = svn_wc_notify_state_unknown;
err = get_parent_access (&adm_access, eb->adm_access,
b->wcpath, eb->dry_run, b->pool);
if (err && err->apr_err == SVN_ERR_WC_NOT_LOCKED)
{
/* ### maybe try to stat the local b->wcpath? */
/* If the file path doesn't exist, then send a 'skipped' notification. */
if (eb->notify_func)
(*eb->notify_func) (eb->notify_baton, b->wcpath,
svn_wc_notify_skip, svn_node_file, NULL,
svn_wc_notify_state_missing, prop_state,
SVN_INVALID_REVNUM);
svn_error_clear (err);
return SVN_NO_ERROR;
}
else if (err)
return err;
if (b->path_end_revision)
{
const char *mimetype1, *mimetype2;
get_file_mime_types (&mimetype1, &mimetype2, b);
if (b->added)
SVN_ERR (eb->diff_callbacks->file_added
(adm_access, &content_state,
b->wcpath,
b->path_start_revision,
b->path_end_revision,
0,
b->edit_baton->target_revision,
mimetype1, mimetype2,
b->edit_baton->diff_cmd_baton));
else
SVN_ERR (eb->diff_callbacks->file_changed
(adm_access, &content_state,
b->wcpath,
b->path_start_revision,
b->path_end_revision,
b->edit_baton->revision,
b->edit_baton->target_revision,
mimetype1, mimetype2,
b->edit_baton->diff_cmd_baton));
}
/* Don't do the props_changed stuff if this is a dry_run and we don't
have an access baton, since in that case the file will already have
been recognised as added, in which case they cannot conflict. A
similar argument applies to directories in close_directory. */
if (b->propchanges->nelts > 0 && (! (eb->dry_run && b->added)))
{
SVN_ERR (eb->diff_callbacks->props_changed
(adm_access, &prop_state,
b->wcpath,
b->propchanges, b->pristine_props,
b->edit_baton->diff_cmd_baton));
}
/* ### Is b->path the repos path? Probably. This doesn't really
matter while issue #748 (svn merge only happens in ".") is
outstanding. But when we take a wc_path as an argument to
merge, then we'll need to pass around a wc path somehow. */
if ((content_state == svn_wc_notify_state_missing)
|| (content_state == svn_wc_notify_state_obstructed))
action = svn_wc_notify_skip;
else if (b->added)
action = svn_wc_notify_update_add;
else
action = svn_wc_notify_update_update;
if (eb->notify_func)
(*eb->notify_func)
(eb->notify_baton,
b->wcpath,
action,
svn_node_file,
NULL,
content_state,
prop_state,
SVN_INVALID_REVNUM);
return SVN_NO_ERROR;
}
/* An editor function. */
static svn_error_t *
close_directory (void *dir_baton,
apr_pool_t *pool)
{
struct dir_baton *b = dir_baton;
struct edit_baton *eb = b->edit_baton;
svn_wc_notify_state_t prop_state = svn_wc_notify_state_unknown;
svn_error_t *err;
if (b->propchanges->nelts > 0)
{
svn_wc_adm_access_t *adm_access;
err = get_path_access (&adm_access, eb->adm_access, b->wcpath,
eb->dry_run, b->pool);
if (err && err->apr_err == SVN_ERR_WC_NOT_LOCKED)
{
/* ### maybe try to stat the local b->wcpath? */
/* If the path doesn't exist, then send a 'skipped' notification. */
if (eb->notify_func)
(*eb->notify_func) (eb->notify_baton, b->wcpath,
svn_wc_notify_skip, svn_node_dir, NULL,
svn_wc_notify_state_missing,
svn_wc_notify_state_missing,
SVN_INVALID_REVNUM);
svn_error_clear (err);
return SVN_NO_ERROR;
}
else if (err)
return err;
/* As for close_file, whether we do this depends on whether it's a
dry-run */
if (! eb->dry_run || adm_access)
SVN_ERR (eb->diff_callbacks->props_changed
(adm_access, &prop_state,
b->wcpath,
b->propchanges, b->pristine_props,
b->edit_baton->diff_cmd_baton));
}
if (eb->notify_func)
(*eb->notify_func) (eb->notify_baton,
b->wcpath,
svn_wc_notify_update_update,
svn_node_dir,
NULL,
svn_wc_notify_state_inapplicable,
prop_state,
SVN_INVALID_REVNUM);
return SVN_NO_ERROR;
}
/* An editor function. */
static svn_error_t *
change_file_prop (void *file_baton,
const char *name,
const svn_string_t *value,
apr_pool_t *pool)
{
struct file_baton *b = file_baton;
svn_prop_t *propchange;
propchange = apr_array_push (b->propchanges);
propchange->name = apr_pstrdup (b->pool, name);
propchange->value = value ? svn_string_dup (value, b->pool) : NULL;
return SVN_NO_ERROR;
}
/* An editor function. */
static svn_error_t *
change_dir_prop (void *dir_baton,
const char *name,
const svn_string_t *value,
apr_pool_t *pool)
{
struct dir_baton *db = dir_baton;
svn_prop_t *propchange;
propchange = apr_array_push (db->propchanges);
propchange->name = apr_pstrdup (db->pool, name);
propchange->value = value ? svn_string_dup (value, db->pool) : NULL;
return SVN_NO_ERROR;
}
/* An editor function. */
static svn_error_t *
close_edit (void *edit_baton,
apr_pool_t *pool)
{
struct edit_baton *eb = edit_baton;
svn_pool_destroy (eb->pool);
return SVN_NO_ERROR;
}
/* Create a repository diff editor and baton. */
svn_error_t *
svn_client__get_diff_editor (const char *target,
svn_wc_adm_access_t *adm_access,
const svn_wc_diff_callbacks_t *diff_callbacks,
void *diff_cmd_baton,
svn_boolean_t recurse,
svn_boolean_t dry_run,
svn_ra_plugin_t *ra_lib,
void *ra_session,
svn_revnum_t revision,
svn_wc_notify_func_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
const svn_delta_editor_t **editor,
void **edit_baton,
apr_pool_t *pool)
{
apr_pool_t *subpool = svn_pool_create (pool);
svn_delta_editor_t *tree_editor = svn_delta_default_editor (subpool);
struct edit_baton *eb = apr_palloc (subpool, sizeof (*eb));
eb->target = target;
eb->adm_access = adm_access;
eb->diff_callbacks = diff_callbacks;
eb->diff_cmd_baton = diff_cmd_baton;
eb->recurse = recurse;
eb->dry_run = dry_run;
eb->ra_lib = ra_lib;
eb->ra_session = ra_session;
eb->revision = revision;
eb->empty_file = NULL;
eb->pool = subpool;
eb->notify_func = notify_func;
eb->notify_baton = notify_baton;
tree_editor->set_target_revision = set_target_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->add_file = add_file;
tree_editor->open_file = open_file;
tree_editor->apply_textdelta = apply_textdelta;
tree_editor->close_file = close_file;
tree_editor->close_directory = close_directory;
tree_editor->change_file_prop = change_file_prop;
tree_editor->change_dir_prop = change_dir_prop;
tree_editor->close_edit = close_edit;
SVN_ERR (svn_delta_get_cancellation_editor (cancel_func,
cancel_baton,
tree_editor,
eb,
editor,
edit_baton,
pool));
return SVN_NO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -