You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2013/01/27 01:01:59 UTC
svn commit: r1438999 [3/7] - in /subversion/branches/windows-build-update:
./ build/generator/ subversion/include/ subversion/include/private/
subversion/libsvn_client/ subversion/libsvn_diff/
subversion/libsvn_ra_serf/ subversion/libsvn_repos/ subvers...
Modified: subversion/branches/windows-build-update/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/windows-build-update/subversion/libsvn_client/repos_diff.c?rev=1438999&r1=1438998&r2=1438999&view=diff
==============================================================================
--- subversion/branches/windows-build-update/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/windows-build-update/subversion/libsvn_client/repos_diff.c Sun Jan 27 00:01:57 2013
@@ -56,10 +56,8 @@ struct edit_baton {
/* The passed depth */
svn_depth_t depth;
- /* The callback and calback argument that implement the file comparison
- function */
- const svn_wc_diff_callbacks4_t *diff_callbacks;
- void *diff_cmd_baton;
+ /* The result processor */
+ svn_diff_tree_processor_t *processor;
/* RA_SESSION is the open session for making requests to the RA layer */
svn_ra_session_t *ra_session;
@@ -79,15 +77,6 @@ struct edit_baton {
/* Empty hash used for adds. */
apr_hash_t *empty_hash;
- /* Hash used to check replaced paths. Key is path relative CWD,
- * Value is *deleted_path_notify_t.
- * All allocations are from edit_baton's pool. */
- apr_hash_t *deleted_paths;
-
- /* If the func is non-null, send notifications of actions. */
- svn_wc_notify_func2_t notify_func;
- void *notify_baton;
-
/* TRUE if the operation needs to walk deleted dirs on the "old" side.
FALSE otherwise. */
svn_boolean_t walk_deleted_repos_dirs;
@@ -147,6 +136,11 @@ struct dir_baton {
/* Boolean indicating whether a node property was changed */
svn_boolean_t has_propchange;
+ /* Baton for svn_diff_tree_processor_t */
+ void *pdb;
+ svn_diff_source_t *left_source;
+ svn_diff_source_t *right_source;
+
/* The pool passed in by add_dir, open_dir, or open_root.
Also, the pool this dir baton is allocated in. */
apr_pool_t *pool;
@@ -206,6 +200,11 @@ struct file_baton {
/* Boolean indicating whether a node property was changed */
svn_boolean_t has_propchange;
+ /* Baton for svn_diff_tree_processor_t */
+ void *pfb;
+ svn_diff_source_t *left_source;
+ svn_diff_source_t *right_source;
+
/* The pool passed in by add_file or open_file.
Also, the pool this file_baton is allocated in. */
apr_pool_t *pool;
@@ -269,49 +268,6 @@ make_file_baton(const char *path,
return file_baton;
}
-/* Helper function: return up to two svn:mime-type values buried
- * within a file baton. Set *MIMETYPE1 to the value within the file's
- * pristine properties, or NULL if not available. Set *MIMETYPE2 to
- * the value within the "new" file's propchanges, or NULL if not
- * available.
- */
-static void
-get_file_mime_types(const char **mimetype1,
- const char **mimetype2,
- struct file_baton *fb)
-{
- /* Defaults */
- *mimetype1 = NULL;
- *mimetype2 = NULL;
-
- if (fb->pristine_props)
- {
- svn_string_t *pristine_val;
- pristine_val = apr_hash_get(fb->pristine_props, SVN_PROP_MIME_TYPE,
- strlen(SVN_PROP_MIME_TYPE));
- if (pristine_val)
- *mimetype2 = *mimetype1 = pristine_val->data;
- }
-
- if (fb->propchanges)
- {
- int i;
- svn_prop_t *propchange;
-
- for (i = 0; i < fb->propchanges->nelts; i++)
- {
- propchange = &APR_ARRAY_IDX(fb->propchanges, i, svn_prop_t);
- if (strcmp(propchange->name, SVN_PROP_MIME_TYPE) == 0)
- {
- if (propchange->value)
- *mimetype2 = propchange->value->data;
- break;
- }
- }
- }
-}
-
-
/* Get revision FB->base_revision of the file described by FB from the
* repository, through FB->edit_baton->ra_session.
*
@@ -427,7 +383,6 @@ remove_non_prop_changes(apr_hash_t *pris
}
}
-
/* Get the empty file associated with the edit baton. This is cached so
* that it can be reused, all empty files are the same.
*/
@@ -471,6 +426,9 @@ open_root(void *edit_baton,
struct dir_baton *db = make_dir_baton("", NULL, eb, FALSE, base_revision,
pool);
+ db->left_source = svn_diff__source_create(eb->revision, db->pool);
+ db->right_source = svn_diff__source_create(eb->target_revision, db->pool);
+
*root_baton = db;
return SVN_NO_ERROR;
}
@@ -478,34 +436,43 @@ open_root(void *edit_baton,
/* Compare a file being deleted against an empty file.
*/
static svn_error_t *
-diff_deleted_file(svn_wc_notify_state_t *state_p,
- svn_boolean_t *tree_conflicted_p,
- const char *path,
+diff_deleted_file(const char *path,
+ void *ppdb,
struct edit_baton *eb,
apr_pool_t *scratch_pool)
{
struct file_baton *fb = make_file_baton(path, FALSE, eb, scratch_pool);
-/* struct edit_baton *eb = fb->edit_baton;*/
- const char *mimetype1, *mimetype2;
+ svn_boolean_t skip = FALSE;
+ svn_diff_source_t *left_source = svn_diff__source_create(eb->revision,
+ scratch_pool);
if (eb->cancel_func)
SVN_ERR(eb->cancel_func(eb->cancel_baton));
- if (eb->text_deltas)
- SVN_ERR(get_file_from_ra(fb, FALSE, scratch_pool));
- else
- SVN_ERR(get_empty_file(eb, &fb->path_start_revision));
- SVN_ERR(get_empty_file(eb, &fb->path_end_revision));
- get_file_mime_types(&mimetype1, &mimetype2, fb);
-
- SVN_ERR(eb->diff_callbacks->file_deleted(state_p, tree_conflicted_p,
- fb->path,
- fb->path_start_revision,
- fb->path_end_revision,
- mimetype1, mimetype2,
- fb->pristine_props,
- eb->diff_cmd_baton,
- scratch_pool));
+ SVN_ERR(eb->processor->file_opened(&fb->pfb, &skip, path,
+ left_source,
+ NULL /* right_source */,
+ NULL /* copyfrom_source */,
+ ppdb,
+ eb->processor,
+ scratch_pool, scratch_pool));
+
+ if (eb->cancel_func)
+ SVN_ERR(eb->cancel_func(eb->cancel_baton));
+
+ if (skip)
+ return SVN_NO_ERROR;
+
+ SVN_ERR(get_file_from_ra(fb, ! eb->text_deltas, scratch_pool));
+
+ SVN_ERR(eb->processor->file_deleted(fb->path,
+ left_source,
+ fb->path_start_revision,
+ fb->pristine_props,
+ fb->pfb,
+ eb->processor,
+ scratch_pool));
+
return SVN_NO_ERROR;
}
@@ -519,63 +486,82 @@ diff_deleted_file(svn_wc_notify_state_t
*/
/* ### 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,
+diff_deleted_dir(const char *path,
+ void *ppdb,
struct edit_baton *eb,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
- apr_hash_t *dirents;
- apr_pool_t *iterpool = svn_pool_create(pool);
- apr_hash_index_t *hi;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ svn_boolean_t skip = FALSE;
+ svn_boolean_t skip_children = FALSE;
+ apr_hash_t *dirents = NULL;
+ apr_hash_t *left_props = NULL;
+ svn_diff_source_t *left_source = svn_diff__source_create(eb->revision,
+ scratch_pool);
+ void *pdb;
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));
+ SVN_ERR(eb->processor->dir_opened(&pdb, &skip, &skip_children,
+ path,
+ left_source,
+ NULL /* right_source */,
+ NULL /* copyfrom_source */,
+ ppdb,
+ eb->processor,
+ scratch_pool, iterpool));
+
+ if (!skip || !skip_children)
+ SVN_ERR(svn_ra_get_dir2(eb->ra_session,
+ skip_children ? NULL : &dirents,
+ NULL,
+ skip ? NULL : &left_props,
+ path,
+ eb->revision,
+ SVN_DIRENT_KIND,
+ scratch_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)
+ if (! skip_children && 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));
+ apr_hash_index_t *hi;
- 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);
+ for (hi = apr_hash_first(scratch_pool, dirents); hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *child_path;
+ const char *name = svn__apr_hash_index_key(hi);
+ svn_dirent_t *dirent = svn__apr_hash_index_val(hi);
- svn_pool_clear(iterpool);
+ svn_pool_clear(iterpool);
- path = svn_relpath_join(dir, name, iterpool);
+ child_path = svn_relpath_join(path, name, iterpool);
- if (dirent->kind == svn_node_file)
- {
- SVN_ERR(diff_deleted_file(NULL, NULL, path, eb, iterpool));
+ if (dirent->kind == svn_node_file)
+ {
+ SVN_ERR(diff_deleted_file(child_path, pdb, eb, iterpool));
+ }
+ else if (dirent->kind == svn_node_dir)
+ {
+ SVN_ERR(diff_deleted_dir(child_path, pdb, eb, iterpool));
+ }
}
+ }
- if (dirent->kind == svn_node_dir)
- {
- SVN_ERR(diff_deleted_dir(NULL, NULL, path, eb, iterpool));
- }
+ if (! skip)
+ {
+ SVN_ERR(eb->processor->dir_deleted(path,
+ left_source,
+ left_props,
+ pdb,
+ eb->processor,
+ scratch_pool));
}
svn_pool_destroy(iterpool);
@@ -592,9 +578,6 @@ delete_entry(const char *path,
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;
/* Process skips. */
@@ -611,39 +594,18 @@ delete_entry(const char *path,
{
case svn_node_file:
{
- SVN_ERR(diff_deleted_file(&state, &tree_conflicted, path, eb,
- scratch_pool));
+ SVN_ERR(diff_deleted_file(path, pb->pdb, eb, scratch_pool));
break;
}
case svn_node_dir:
{
- SVN_ERR(diff_deleted_dir(&state, &tree_conflicted, path, eb,
- scratch_pool));
+ SVN_ERR(diff_deleted_dir(path, pb->pdb, 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;
@@ -661,7 +623,6 @@ add_directory(const char *path,
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
struct dir_baton *db;
- svn_wc_notify_state_t state;
/* ### TODO: support copyfrom? */
@@ -677,64 +638,19 @@ add_directory(const char *path,
return SVN_NO_ERROR;
}
+ db->right_source = svn_diff__source_create(eb->target_revision,
+ db->pool);
- SVN_ERR(eb->diff_callbacks->dir_added(
- &state, &db->tree_conflicted,
- &db->skip, &db->skip_children, db->path,
- eb->target_revision, copyfrom_path, copyfrom_revision,
- eb->diff_cmd_baton, pool));
-
- /* Notifications for directories are done at close_directory time.
- * But for paths at which the editor drive adds directories, we make an
- * exception to this rule, so that the path appears in the output before
- * any children of the newly added directory. Since a deletion at this path
- * must have happened before this addition, we can safely notify about
- * replaced directories here, too. */
- if (eb->notify_func)
- {
- deleted_path_notify_t *dpn;
- svn_wc_notify_t *notify;
- svn_wc_notify_action_t action;
- svn_node_kind_t kind = svn_node_dir;
-
- /* Find out if a pending delete notification for this path is
- * still around. */
- dpn = apr_hash_get(eb->deleted_paths, db->path, APR_HASH_KEY_STRING);
- if (dpn)
- {
- /* If any was found, we will handle the pending 'deleted path
- * notification' (DPN) here. Remove it from the list. */
- apr_hash_set(eb->deleted_paths, db->path,
- APR_HASH_KEY_STRING, NULL);
-
- /* the pending delete might be on a different node kind. */
- kind = dpn->kind;
- state = dpn->state;
- }
-
- /* Determine what the notification (ACTION) should be.
- * In case of a pending 'delete', this might become a 'replace'. */
- if (db->tree_conflicted)
- action = svn_wc_notify_tree_conflict;
- else if (dpn)
- {
- if (dpn->action == svn_wc_notify_update_delete)
- action = svn_wc_notify_update_replace;
- else
- /* Note: dpn->action might be svn_wc_notify_tree_conflict */
- action = dpn->action;
- }
- else 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;
-
- notify = svn_wc_create_notify(db->path, action, pool);
- notify->kind = kind;
- notify->content_state = notify->prop_state = state;
- (*eb->notify_func)(eb->notify_baton, notify, pool);
- }
+ SVN_ERR(eb->processor->dir_opened(&db->pdb,
+ &db->skip,
+ &db->skip_children,
+ db->path,
+ NULL,
+ db->right_source,
+ NULL /* copyfrom_source */,
+ pb->pdb,
+ eb->processor,
+ db->pool, db->pool));
return SVN_NO_ERROR;
}
@@ -763,10 +679,18 @@ open_directory(const char *path,
return SVN_NO_ERROR;
}
- SVN_ERR(eb->diff_callbacks->dir_opened(
- &db->tree_conflicted, &db->skip,
- &db->skip_children, db->path, base_revision,
- eb->diff_cmd_baton, pool));
+ db->left_source = svn_diff__source_create(eb->revision, db->pool);
+ db->right_source = svn_diff__source_create(eb->target_revision, db->pool);
+
+ SVN_ERR(eb->processor->dir_opened(&db->pdb,
+ &db->skip, &db->skip_children,
+ path,
+ db->left_source,
+ db->right_source,
+ NULL /* copyfrom */,
+ pb ? pb->pdb : NULL,
+ eb->processor,
+ db->pool, db->pool));
return SVN_NO_ERROR;
}
@@ -782,6 +706,7 @@ add_file(const char *path,
void **file_baton)
{
struct dir_baton *pb = parent_baton;
+ struct edit_baton *eb = pb->edit_baton;
struct file_baton *fb;
/* ### TODO: support copyfrom? */
@@ -798,6 +723,18 @@ add_file(const char *path,
fb->pristine_props = pb->edit_baton->empty_hash;
+ fb->right_source = svn_diff__source_create(eb->target_revision, fb->pool);
+
+ SVN_ERR(eb->processor->file_opened(&fb->pfb,
+ &fb->skip,
+ path,
+ NULL,
+ fb->right_source,
+ NULL /* copy source */,
+ pb->pdb,
+ eb->processor,
+ fb->pool, fb->pool));
+
return SVN_NO_ERROR;
}
@@ -824,9 +761,18 @@ open_file(const char *path,
fb->base_revision = base_revision;
- SVN_ERR(eb->diff_callbacks->file_opened(
- &fb->tree_conflicted, &fb->skip,
- fb->path, base_revision, eb->diff_cmd_baton, pool));
+ fb->left_source = svn_diff__source_create(eb->revision, fb->pool);
+ fb->right_source = svn_diff__source_create(eb->target_revision, fb->pool);
+
+ SVN_ERR(eb->processor->file_opened(&fb->pfb,
+ &fb->skip,
+ path,
+ fb->left_source,
+ fb->right_source,
+ NULL /* copy source */,
+ pb->pdb,
+ eb->processor,
+ fb->pool, fb->pool));
return SVN_NO_ERROR;
}
@@ -947,8 +893,6 @@ close_file(void *file_baton,
{
struct file_baton *fb = file_baton;
struct edit_baton *eb = fb->edit_baton;
- svn_wc_notify_state_t content_state = svn_wc_notify_state_unknown;
- svn_wc_notify_state_t prop_state = svn_wc_notify_state_unknown;
apr_pool_t *scratch_pool;
/* Skip *everything* within a newly tree-conflicted directory. */
@@ -976,9 +920,9 @@ close_file(void *file_baton,
fb->path));
}
- if (fb->path_end_revision || fb->has_propchange)
+ if (fb->added || fb->path_end_revision || fb->has_propchange)
{
- const char *mimetype1, *mimetype2;
+ apr_hash_t *right_props;
if (!fb->added && !fb->pristine_props)
{
@@ -990,85 +934,35 @@ close_file(void *file_baton,
if (fb->pristine_props)
remove_non_prop_changes(fb->pristine_props, fb->propchanges);
- get_file_mime_types(&mimetype1, &mimetype2, fb);
-
+ right_props = svn_prop__patch(fb->pristine_props, fb->propchanges,
+ fb->pool);
if (fb->added)
- SVN_ERR(eb->diff_callbacks->file_added(
- &content_state, &prop_state, &fb->tree_conflicted,
- fb->path,
- fb->path_end_revision ? fb->path_start_revision : NULL,
- fb->path_end_revision,
- 0,
- eb->target_revision,
- mimetype1, mimetype2,
- NULL, SVN_INVALID_REVNUM,
- fb->propchanges, fb->pristine_props,
- eb->diff_cmd_baton,
- scratch_pool));
- else
- SVN_ERR(eb->diff_callbacks->file_changed(
- &content_state, &prop_state,
- &fb->tree_conflicted, fb->path,
- fb->path_end_revision ? fb->path_start_revision : NULL,
- fb->path_end_revision,
- eb->revision,
- eb->target_revision,
- mimetype1, mimetype2,
- fb->propchanges, fb->pristine_props,
- eb->diff_cmd_baton,
- scratch_pool));
- }
-
-
- if (eb->notify_func)
- {
- deleted_path_notify_t *dpn;
- svn_wc_notify_t *notify;
- svn_wc_notify_action_t action;
- svn_node_kind_t kind = svn_node_file;
-
- /* Find out if a pending delete notification for this path is
- * still around. */
- dpn = apr_hash_get(eb->deleted_paths, fb->path, APR_HASH_KEY_STRING);
- if (dpn)
- {
- /* If any was found, we will handle the pending 'deleted path
- * notification' (DPN) here. Remove it from the list. */
- apr_hash_set(eb->deleted_paths, fb->path,
- APR_HASH_KEY_STRING, NULL);
-
- /* the pending delete might be on a different node kind. */
- kind = dpn->kind;
- content_state = prop_state = dpn->state;
- }
-
- /* Determine what the notification (ACTION) should be.
- * In case of a pending 'delete', this might become a 'replace'. */
- if (fb->tree_conflicted)
- action = svn_wc_notify_tree_conflict;
- else if (dpn)
- {
- if (dpn->action == svn_wc_notify_update_delete
- && fb->added)
- action = svn_wc_notify_update_replace;
- else
- /* Note: dpn->action might be svn_wc_notify_tree_conflict */
- action = dpn->action;
- }
- else if ((content_state == svn_wc_notify_state_missing)
- || (content_state == svn_wc_notify_state_obstructed))
- action = svn_wc_notify_skip;
- else if (fb->added)
- action = svn_wc_notify_update_add;
+ SVN_ERR(eb->processor->file_added(fb->path,
+ NULL /* copyfrom_src */,
+ fb->right_source,
+ NULL /* copyfrom_file */,
+ fb->path_end_revision,
+ NULL /* copyfrom_props */,
+ right_props,
+ fb->pfb,
+ eb->processor,
+ fb->pool));
else
- action = svn_wc_notify_update_update;
-
- notify = svn_wc_create_notify(fb->path, action, scratch_pool);
- notify->kind = kind;
- notify->content_state = content_state;
- notify->prop_state = prop_state;
- (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
+ SVN_ERR(eb->processor->file_changed(fb->path,
+ fb->left_source,
+ fb->right_source,
+ fb->path_end_revision
+ ? fb->path_start_revision
+ : NULL,
+ fb->path_end_revision,
+ fb->pristine_props,
+ right_props,
+ (fb->path_end_revision != NULL),
+ fb->propchanges,
+ fb->pfb,
+ eb->processor,
+ fb->pool));
}
svn_pool_destroy(fb->pool); /* Destroy file and scratch pool */
@@ -1089,15 +983,13 @@ close_directory(void *dir_baton,
{
struct dir_baton *db = dir_baton;
struct edit_baton *eb = db->edit_baton;
- svn_wc_notify_state_t content_state = svn_wc_notify_state_unknown;
- svn_wc_notify_state_t prop_state = svn_wc_notify_state_unknown;
- svn_boolean_t skipped = FALSE;
apr_pool_t *scratch_pool;
apr_hash_t *pristine_props;
+ svn_boolean_t send_changed = FALSE;
scratch_pool = db->pool;
- if (db->has_propchange && !db->skip)
+ if ((db->has_propchange || db->added) && !db->skip)
{
if (db->added)
{
@@ -1114,86 +1006,49 @@ close_directory(void *dir_baton,
remove_non_prop_changes(pristine_props, db->propchanges);
}
- if (db->propchanges->nelts > 0)
+ if (db->propchanges->nelts > 0 || db->added)
{
- svn_boolean_t tree_conflicted = FALSE;
- SVN_ERR(eb->diff_callbacks->dir_props_changed(
- &prop_state, &tree_conflicted,
- db->path, db->added,
- db->propchanges, pristine_props,
- eb->diff_cmd_baton, scratch_pool));
- if (tree_conflicted)
- db->tree_conflicted = TRUE;
+ apr_hash_t *right_props;
+
+ right_props = svn_prop__patch(pristine_props, db->propchanges,
+ scratch_pool);
- if (prop_state == svn_wc_notify_state_obstructed
- || prop_state == svn_wc_notify_state_missing)
+ if (db->added)
{
- content_state = prop_state;
- skipped = TRUE;
+ SVN_ERR(eb->processor->dir_added(db->path,
+ NULL /* copyfrom */,
+ db->right_source,
+ NULL /* copyfrom props */,
+ right_props,
+ db->pdb,
+ eb->processor,
+ db->pool));
+ }
+ else
+ {
+ SVN_ERR(eb->processor->dir_changed(db->path,
+ db->left_source,
+ db->right_source,
+ pristine_props,
+ right_props,
+ db->propchanges,
+ db->pdb,
+ eb->processor,
+ db->pool));
}
- }
- }
-
- SVN_ERR(eb->diff_callbacks->dir_closed(NULL, NULL, NULL,
- db->path, db->added,
- eb->diff_cmd_baton,
- scratch_pool));
-
- /* Notify about any deleted paths within this directory that have not
- * already been notified. */
- if (!skipped && !db->added && eb->notify_func)
- {
- apr_hash_index_t *hi;
- for (hi = apr_hash_first(pool, eb->deleted_paths); hi;
- hi = apr_hash_next(hi))
- {
- svn_wc_notify_t *notify;
- const char *deleted_path = svn__apr_hash_index_key(hi);
- deleted_path_notify_t *dpn = svn__apr_hash_index_val(hi);
-
- /* Ignore paths which are not children of bb->path. (There
- should be none due to editor ordering constraints, but
- ra_serf drops the ball here -- see issue #3802 for
- details.) */
- if (! svn_relpath_skip_ancestor(db->path, deleted_path))
- continue;
-
- notify = svn_wc_create_notify(deleted_path, dpn->action, pool);
- notify->kind = dpn->kind;
- notify->content_state = notify->prop_state = dpn->state;
- notify->lock_state = svn_wc_notify_lock_state_inapplicable;
- (*eb->notify_func)(eb->notify_baton, notify, pool);
- apr_hash_set(eb->deleted_paths, deleted_path,
- APR_HASH_KEY_STRING, NULL);
+ send_changed = TRUE; /* Skip dir_closed */
}
}
- /* Notify about this directory itself (unless it was added, in which
- * case the notification was done at that time). */
- if (!db->added && eb->notify_func && !db->skip)
+ if (! db->skip && !send_changed)
{
- svn_wc_notify_t *notify;
- svn_wc_notify_action_t action;
-
- if (db->tree_conflicted)
- action = svn_wc_notify_tree_conflict;
- else if (skipped)
- action = svn_wc_notify_skip;
- else
- action = svn_wc_notify_update_update;
-
- notify = svn_wc_create_notify(db->path, action, pool);
- notify->kind = svn_node_dir;
-
- /* In case of a tree conflict during merge, the diff callback
- * sets content_state appropriately. So copy the state into the
- * notify_t to make sure conflicts get displayed. */
- notify->content_state = content_state;
-
- notify->prop_state = prop_state;
- notify->lock_state = svn_wc_notify_lock_state_inapplicable;
- (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
+ SVN_ERR(eb->processor->dir_closed(db->path,
+ db->left_source,
+ db->right_source,
+ db->pdb,
+ eb->processor,
+ db->pool));
}
svn_pool_destroy(db->pool); /* Destroy baton and scratch_pool */
@@ -1285,18 +1140,7 @@ absent_directory(const char *path,
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
- /* ### TODO: Raise a tree-conflict?? I sure hope not.*/
-
- if (eb->notify_func)
- {
- svn_wc_notify_t *notify
- = svn_wc_create_notify(path, svn_wc_notify_skip, pool);
-
- notify->kind = svn_node_dir;
- notify->content_state = notify->prop_state
- = svn_wc_notify_state_missing;
- (*eb->notify_func)(eb->notify_baton, notify, pool);
- }
+ SVN_ERR(eb->processor->node_absent(path, pb->pdb, eb->processor, pool));
return SVN_NO_ERROR;
}
@@ -1312,18 +1156,7 @@ absent_file(const char *path,
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
- /* ### TODO: Raise a tree-conflict?? I sure hope not.*/
-
- if (eb->notify_func)
- {
- svn_wc_notify_t *notify
- = svn_wc_create_notify(path, svn_wc_notify_skip, pool);
-
- notify->kind = svn_node_file;
- notify->content_state = notify->prop_state
- = svn_wc_notify_state_missing;
- (*eb->notify_func)(eb->notify_baton, notify, pool);
- }
+ SVN_ERR(eb->processor->node_absent(path, pb->pdb, eb->processor, pool));
return SVN_NO_ERROR;
}
@@ -1427,6 +1260,244 @@ fetch_base_func(const char **filename,
return SVN_NO_ERROR;
}
+/* Baton for diff_state_* functions */
+struct diff_notify_baton_t
+{
+ /* Hash used to check replaced paths. Key is path relative CWD,
+ * Value is *deleted_path_notify_t.
+ * All allocations are from edit_baton's pool. */
+ apr_hash_t *deleted_paths;
+
+ /* If the func is non-null, send notifications of actions. */
+ svn_wc_notify_func2_t notify_func;
+ void *notify_baton;
+
+ /* If not NULL collects the absent paths */
+ apr_hash_t *absent_relpaths;
+
+ apr_pool_t *pool;
+};
+
+/** Callback for the svn_diff_tree_processor_t wrapper, to allow handling
+ * notifications like how the repos diff in libsvn_client does.
+ *
+ * Probably only necessary while transitioning to svn_diff_tree_processor_t
+ */
+static svn_error_t *
+diff_state_handle(svn_boolean_t tree_conflicted,
+ svn_wc_notify_state_t *state,
+ svn_wc_notify_state_t *prop_state,
+ const char *relpath,
+ svn_kind_t kind,
+ svn_boolean_t before_operation,
+ svn_boolean_t for_add,
+ svn_boolean_t for_delete,
+ void *state_baton,
+ apr_pool_t *scratch_pool)
+{
+ struct diff_notify_baton_t *dnb = state_baton;
+ svn_wc_notify_state_t notify_content_state = svn_wc_notify_state_inapplicable;
+ svn_wc_notify_state_t notify_prop_state = svn_wc_notify_state_inapplicable;
+
+ if (! dnb->notify_func)
+ return SVN_NO_ERROR;
+
+ if ((for_delete && before_operation && !tree_conflicted)
+ || (for_add && kind == svn_kind_dir && !before_operation))
+ return SVN_NO_ERROR;
+
+ if (for_delete)
+ {
+ const char *deleted_path;
+ deleted_path_notify_t *dpn;
+ svn_wc_notify_action_t action;
+
+ deleted_path = apr_pstrdup(dnb->pool, relpath);
+ dpn = apr_pcalloc(dnb->pool, sizeof(*dpn));
+
+ if (!tree_conflicted
+ && state
+ && (*state != svn_wc_notify_state_missing)
+ && (*state != svn_wc_notify_state_obstructed))
+ {
+ action = svn_wc_notify_update_delete;
+ }
+ else
+ action = svn_wc_notify_skip;
+
+ dpn->kind = (kind == svn_kind_dir) ? svn_node_dir : svn_node_file;
+ dpn->action = tree_conflicted ? svn_wc_notify_tree_conflict : action;
+ dpn->state = state ? *state : svn_wc_notify_state_inapplicable;
+ dpn->tree_conflicted = tree_conflicted;
+ apr_hash_set(dnb->deleted_paths, deleted_path, APR_HASH_KEY_STRING, dpn);
+
+ return SVN_NO_ERROR;
+ }
+
+ if (tree_conflicted)
+ {
+ svn_wc_notify_t *notify;
+ deleted_path_notify_t *dpn;
+ svn_node_kind_t notify_kind;
+
+ apr_hash_set(dnb->deleted_paths, relpath,
+ APR_HASH_KEY_STRING, NULL);
+
+ notify = svn_wc_create_notify(relpath, svn_wc_notify_tree_conflict,
+ scratch_pool);
+
+ dpn = apr_hash_get(dnb->deleted_paths, relpath, APR_HASH_KEY_STRING);
+ if (dpn)
+ {
+ /* If any was found, we will handle the pending 'deleted path
+ * notification' (DPN) here. Remove it from the list. */
+ apr_hash_set(dnb->deleted_paths, relpath,
+ APR_HASH_KEY_STRING, NULL);
+
+ /* the pending delete might be on a different node kind. */
+ notify_kind = dpn->kind;
+ }
+
+ notify->kind = notify_kind;
+ (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
+ return SVN_NO_ERROR;
+ }
+
+ if (state)
+ notify_content_state = *state;
+ if (prop_state)
+ notify_prop_state = *prop_state;
+
+ /* These states apply to properties (dirs) and content (files) at the same
+ time, so handle them as the same whatever way we got them. */
+ if (notify_prop_state == svn_wc_notify_state_obstructed
+ || notify_prop_state == svn_wc_notify_state_missing)
+ {
+ notify_content_state = notify_prop_state;
+ }
+
+ if (notify_content_state == svn_wc_notify_state_obstructed
+ || notify_content_state == svn_wc_notify_state_missing)
+ {
+ svn_wc_notify_t *notify;
+
+ notify = svn_wc_create_notify(relpath, svn_wc_notify_skip,
+ scratch_pool);
+
+ notify->kind = (kind == svn_kind_dir) ? svn_node_dir : svn_node_file;
+ notify->content_state = notify_content_state;
+ notify->prop_state = notify_prop_state;
+ (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
+ return SVN_NO_ERROR;
+ }
+
+ /* This code is only used from the merge api, and should really be
+ integrated there. */
+
+ {
+ deleted_path_notify_t *dpn;
+ svn_wc_notify_t *notify;
+ svn_wc_notify_action_t action;
+ svn_node_kind_t notify_kind = (kind == svn_kind_dir) ? svn_node_dir
+ : svn_node_file;
+
+ if (for_add)
+ action = svn_wc_notify_update_add;
+ else
+ action = svn_wc_notify_update_update;
+
+ /* Find out if a pending delete notification for this path is
+ * still around. */
+ dpn = apr_hash_get(dnb->deleted_paths, relpath, APR_HASH_KEY_STRING);
+ if (dpn)
+ {
+ /* If any was found, we will handle the pending 'deleted path
+ * notification' (DPN) here. Remove it from the list. */
+ apr_hash_set(dnb->deleted_paths, relpath,
+ APR_HASH_KEY_STRING, NULL);
+
+ /* the pending delete might be on a different node kind. */
+ notify_kind = dpn->kind;
+ notify_content_state = notify_prop_state = dpn->state;
+
+ if (for_add && dpn->action == svn_wc_notify_update_delete)
+ action = svn_wc_notify_update_replace;
+ }
+
+ notify = svn_wc_create_notify(relpath, action, scratch_pool);
+ notify->kind = notify_kind;
+ notify->content_state = notify_content_state;
+ notify->prop_state = notify_prop_state;
+ (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+diff_state_close(const char *relpath,
+ svn_kind_t kind,
+ void *state_baton,
+ apr_pool_t *scratch_pool)
+{
+ struct diff_notify_baton_t *dnb = state_baton;
+ apr_hash_index_t *hi;
+
+ if (! dnb->notify_func)
+ return SVN_NO_ERROR;
+
+ for (hi = apr_hash_first(scratch_pool, dnb->deleted_paths); hi;
+ hi = apr_hash_next(hi))
+ {
+ svn_wc_notify_t *notify;
+ const char *deleted_path = svn__apr_hash_index_key(hi);
+ deleted_path_notify_t *dpn = svn__apr_hash_index_val(hi);
+
+ /* Ignore paths which are not children of bb->path. (There
+ should be none due to editor ordering constraints, but
+ ra_serf drops the ball here -- see issue #3802 for
+ details.) */
+ if (! svn_relpath_skip_ancestor(relpath, deleted_path))
+ continue;
+
+ notify = svn_wc_create_notify(deleted_path, dpn->action, scratch_pool);
+ notify->kind = dpn->kind;
+ notify->content_state = notify->prop_state = dpn->state;
+ notify->lock_state = svn_wc_notify_lock_state_inapplicable;
+ (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
+ apr_hash_set(dnb->deleted_paths, deleted_path,
+ APR_HASH_KEY_STRING, NULL);
+ }
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+diff_state_absent(const char *relpath,
+ void *state_baton,
+ apr_pool_t *scratch_pool)
+{
+ struct diff_notify_baton_t *dnb = state_baton;
+
+ if (dnb->notify_func)
+ {
+ svn_wc_notify_t *notify
+ = svn_wc_create_notify(relpath, svn_wc_notify_skip, scratch_pool);
+
+ notify->kind = svn_node_unknown;
+ notify->content_state = notify->prop_state
+ = svn_wc_notify_state_missing;
+ (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
+ }
+
+ if (dnb->absent_relpaths)
+ apr_hash_set(dnb->absent_relpaths,
+ apr_pstrdup(apr_hash_pool_get(dnb->absent_relpaths), relpath),
+ APR_HASH_KEY_STRING,
+ "");
+
+ return SVN_NO_ERROR;
+}
+
/* Create a repository diff editor and baton. */
svn_error_t *
svn_client__get_diff_editor(const svn_delta_editor_t **editor,
@@ -1436,6 +1507,7 @@ svn_client__get_diff_editor(const svn_de
svn_revnum_t revision,
svn_boolean_t walk_deleted_dirs,
svn_boolean_t text_deltas,
+ apr_hash_t *absent_relpaths,
const svn_wc_diff_callbacks4_t *diff_callbacks,
void *diff_cmd_baton,
svn_cancel_func_t cancel_func,
@@ -1447,21 +1519,32 @@ svn_client__get_diff_editor(const svn_de
apr_pool_t *editor_pool = svn_pool_create(result_pool);
svn_delta_editor_t *tree_editor = svn_delta_default_editor(editor_pool);
struct edit_baton *eb = apr_pcalloc(editor_pool, sizeof(*eb));
+ struct diff_notify_baton_t *dnb = apr_pcalloc(editor_pool, sizeof(*eb));
svn_delta_shim_callbacks_t *shim_callbacks =
svn_delta_shim_callbacks_default(editor_pool);
eb->pool = editor_pool;
eb->depth = depth;
- eb->diff_callbacks = diff_callbacks;
- eb->diff_cmd_baton = diff_cmd_baton;
+
+ dnb->pool = editor_pool;
+ dnb->deleted_paths = apr_hash_make(eb->pool);
+ dnb->notify_func = notify_func;
+ dnb->notify_baton = notify_baton;
+ dnb->absent_relpaths = absent_relpaths;
+
+ SVN_ERR(svn_wc__wrap_diff_callbacks(&eb->processor,
+ diff_callbacks, diff_cmd_baton,
+ diff_state_handle,
+ diff_state_close,
+ diff_state_absent,
+ dnb,
+ result_pool, result_pool));
+
eb->ra_session = ra_session;
eb->revision = revision;
eb->empty_file = NULL;
eb->empty_hash = apr_hash_make(eb->pool);
- eb->deleted_paths = apr_hash_make(eb->pool);
- eb->notify_func = notify_func;
- eb->notify_baton = notify_baton;
eb->walk_deleted_repos_dirs = walk_deleted_dirs;
eb->text_deltas = text_deltas;
eb->cancel_func = cancel_func;
Modified: subversion/branches/windows-build-update/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/windows-build-update/subversion/libsvn_diff/diff_file.c?rev=1438999&r1=1438998&r2=1438999&view=diff
==============================================================================
--- subversion/branches/windows-build-update/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/windows-build-update/subversion/libsvn_diff/diff_file.c Sun Jan 27 00:01:57 2013
@@ -762,7 +762,9 @@ datasources_open(void *baton,
struct file_info files[4];
apr_finfo_t finfo[4];
apr_off_t length[4];
+#ifndef SVN_DISABLE_PREFIX_SUFFIX_SCANNING
svn_boolean_t reached_one_eof;
+#endif
apr_size_t i;
/* Make sure prefix_lines and suffix_lines are set correctly, even if we
@@ -1566,12 +1568,26 @@ output_unified_line(svn_diff__file_outpu
return SVN_NO_ERROR;
}
+static APR_INLINE svn_error_t *
+output_unified_diff_range(svn_diff__file_output_baton_t *output_baton,
+ int source,
+ svn_diff__file_output_unified_type_e type,
+ apr_off_t until)
+{
+ while (output_baton->current_line[source] < until)
+ {
+ SVN_ERR(output_unified_line(output_baton, type, source));
+ }
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *
output_unified_flush_hunk(svn_diff__file_output_baton_t *baton)
{
apr_off_t target_line;
apr_size_t hunk_len;
- int i;
+ apr_off_t old_start;
+ apr_off_t new_start;
if (svn_stringbuf_isempty(baton->hunk))
{
@@ -1583,25 +1599,25 @@ output_unified_flush_hunk(svn_diff__file
+ SVN_DIFF__UNIFIED_CONTEXT_SIZE;
/* Add trailing context to the hunk */
- while (baton->current_line[0] < target_line)
- {
- SVN_ERR(output_unified_line
- (baton, svn_diff__file_output_unified_context, 0));
- }
+ SVN_ERR(output_unified_diff_range(baton, 0 /* original */,
+ svn_diff__file_output_unified_context,
+ target_line));
+
+ old_start = baton->hunk_start[0];
+ new_start = baton->hunk_start[1];
/* If the file is non-empty, convert the line indexes from
zero based to one based */
- for (i = 0; i < 2; i++)
- {
- if (baton->hunk_length[i] > 0)
- baton->hunk_start[i]++;
- }
+ if (baton->hunk_length[0])
+ old_start++;
+ if (baton->hunk_length[1])
+ new_start++;
/* Write the hunk header */
SVN_ERR(svn_diff__unified_write_hunk_header(
baton->output_stream, baton->header_encoding, "@@",
- baton->hunk_start[0], baton->hunk_length[0],
- baton->hunk_start[1], baton->hunk_length[1],
+ old_start, baton->hunk_length[0],
+ new_start, baton->hunk_length[1],
baton->hunk_extra_context,
baton->pool));
@@ -1613,6 +1629,8 @@ output_unified_flush_hunk(svn_diff__file
/* Prepare for the next hunk */
baton->hunk_length[0] = 0;
baton->hunk_length[1] = 0;
+ baton->hunk_start[0] = 0;
+ baton->hunk_start[1] = 0;
svn_stringbuf_setempty(baton->hunk);
return SVN_NO_ERROR;
@@ -1625,96 +1643,121 @@ output_unified_diff_modified(void *baton
apr_off_t latest_start, apr_off_t latest_length)
{
svn_diff__file_output_baton_t *output_baton = baton;
- apr_off_t target_line[2];
- int i;
+ apr_off_t context_prefix_length;
+ apr_off_t prev_context_end;
+ svn_boolean_t init_hunk = FALSE;
- target_line[0] = original_start >= SVN_DIFF__UNIFIED_CONTEXT_SIZE
- ? original_start - SVN_DIFF__UNIFIED_CONTEXT_SIZE : 0;
- target_line[1] = modified_start;
-
- /* If the changed ranges are far enough apart (no overlapping or connecting
- context), flush the current hunk, initialize the next hunk and skip the
- lines not in context. Also do this when this is the first hunk.
- */
- if (output_baton->current_line[0] < target_line[0]
- && (output_baton->hunk_start[0] + output_baton->hunk_length[0]
- + SVN_DIFF__UNIFIED_CONTEXT_SIZE < target_line[0]
- || output_baton->hunk_length[0] == 0))
- {
- SVN_ERR(output_unified_flush_hunk(output_baton));
-
- output_baton->hunk_start[0] = target_line[0];
- output_baton->hunk_start[1] = target_line[1] + target_line[0]
- - original_start;
-
- /* Skip lines until we are at the beginning of the context we want to
- display */
- while (output_baton->current_line[0] < target_line[0])
- {
- SVN_ERR(output_unified_line(output_baton,
- svn_diff__file_output_unified_skip, 0));
- }
-
- if (output_baton->show_c_function)
- {
- apr_size_t p;
- const char *invalid_character;
-
- /* Save the extra context for later use.
- * Note that the last byte of the hunk_extra_context array is never
- * touched after it is zero-initialized, so the array is always
- * 0-terminated. */
- strncpy(output_baton->hunk_extra_context,
- output_baton->extra_context->data,
- SVN_DIFF__EXTRA_CONTEXT_LENGTH);
- /* Trim whitespace at the end, most notably to get rid of any
- * newline characters. */
- p = strlen(output_baton->hunk_extra_context);
- while (p > 0
- && svn_ctype_isspace(output_baton->hunk_extra_context[p - 1]))
- {
- output_baton->hunk_extra_context[--p] = '\0';
- }
- invalid_character =
- svn_utf__last_valid(output_baton->hunk_extra_context,
- SVN_DIFF__EXTRA_CONTEXT_LENGTH);
- for (p = invalid_character - output_baton->hunk_extra_context;
- p < SVN_DIFF__EXTRA_CONTEXT_LENGTH; p++)
- {
- output_baton->hunk_extra_context[p] = '\0';
- }
- }
- }
+ if (original_start > SVN_DIFF__UNIFIED_CONTEXT_SIZE)
+ context_prefix_length = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+ else
+ context_prefix_length = original_start;
- /* Skip lines until we are at the start of the changed range */
- while (output_baton->current_line[1] < target_line[1])
+ /* Calculate where the previous hunk will end if we would write it now
+ (including the necessary context at the end) */
+ if (output_baton->hunk_length[0] > 0 || output_baton->hunk_length[1] > 0)
+ {
+ prev_context_end = output_baton->hunk_start[0]
+ + output_baton->hunk_length[0]
+ + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+ }
+ else
{
- SVN_ERR(output_unified_line(output_baton,
- svn_diff__file_output_unified_skip, 1));
+ prev_context_end = -1;
+
+ if (output_baton->hunk_start[0] == 0
+ && (original_length > 0 || modified_length > 0))
+ init_hunk = TRUE;
}
- /* Output the context preceding the changed range */
- while (output_baton->current_line[0] < original_start)
+ /* If the changed range is far enough from the previous range, flush the current
+ hunk. */
+ {
+ apr_off_t new_hunk_start = (original_start - context_prefix_length);
+
+ if (output_baton->current_line[0] < new_hunk_start
+ && prev_context_end <= new_hunk_start)
+ {
+ SVN_ERR(output_unified_flush_hunk(output_baton));
+ init_hunk = TRUE;
+ }
+ else if (output_baton->hunk_length[0] > 0
+ || output_baton->hunk_length[1] > 0)
+ {
+ /* We extend the current hunk */
+
+
+ /* Original: Output the context preceding the changed range */
+ SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */,
+ svn_diff__file_output_unified_context,
+ original_start));
+ }
+ }
+
+ /* Original: Skip lines until we are at the beginning of the context we want
+ to display */
+ SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */,
+ svn_diff__file_output_unified_skip,
+ original_start - context_prefix_length));
+
+ /* Note that the above skip stores data for the show_c_function support below */
+
+ if (init_hunk)
{
- SVN_ERR(output_unified_line(output_baton,
- svn_diff__file_output_unified_context, 0));
- }
+ SVN_ERR_ASSERT(output_baton->hunk_length[0] == 0
+ && output_baton->hunk_length[1] == 0);
- target_line[0] = original_start + original_length;
- target_line[1] = modified_start + modified_length;
+ output_baton->hunk_start[0] = original_start - context_prefix_length;
+ output_baton->hunk_start[1] = modified_start - context_prefix_length;
+ }
- /* Output the changed range */
- for (i = 0; i < 2; i++)
+ if (init_hunk && output_baton->show_c_function)
{
- while (output_baton->current_line[i] < target_line[i])
+ apr_size_t p;
+ const char *invalid_character;
+
+ /* Save the extra context for later use.
+ * Note that the last byte of the hunk_extra_context array is never
+ * touched after it is zero-initialized, so the array is always
+ * 0-terminated. */
+ strncpy(output_baton->hunk_extra_context,
+ output_baton->extra_context->data,
+ SVN_DIFF__EXTRA_CONTEXT_LENGTH);
+ /* Trim whitespace at the end, most notably to get rid of any
+ * newline characters. */
+ p = strlen(output_baton->hunk_extra_context);
+ while (p > 0
+ && svn_ctype_isspace(output_baton->hunk_extra_context[p - 1]))
+ {
+ output_baton->hunk_extra_context[--p] = '\0';
+ }
+ invalid_character =
+ svn_utf__last_valid(output_baton->hunk_extra_context,
+ SVN_DIFF__EXTRA_CONTEXT_LENGTH);
+ for (p = invalid_character - output_baton->hunk_extra_context;
+ p < SVN_DIFF__EXTRA_CONTEXT_LENGTH; p++)
{
- SVN_ERR(output_unified_line
- (output_baton,
- i == 0 ? svn_diff__file_output_unified_delete
- : svn_diff__file_output_unified_insert, i));
+ output_baton->hunk_extra_context[p] = '\0';
}
}
+ /* Modified: Skip lines until we are at the start of the changed range */
+ SVN_ERR(output_unified_diff_range(output_baton, 1 /* modified */,
+ svn_diff__file_output_unified_skip,
+ modified_start));
+
+ /* Original: Output the context preceding the changed range */
+ SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */,
+ svn_diff__file_output_unified_context,
+ original_start));
+
+ /* Both: Output the changed range */
+ SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */,
+ svn_diff__file_output_unified_delete,
+ original_start + original_length));
+ SVN_ERR(output_unified_diff_range(output_baton, 1 /* modified */,
+ svn_diff__file_output_unified_insert,
+ modified_start + modified_length));
+
return SVN_NO_ERROR;
}
@@ -1767,7 +1810,6 @@ svn_diff_file_output_unified3(svn_stream
if (svn_diff_contains_diffs(diff))
{
svn_diff__file_output_baton_t baton;
- const char **c;
int i;
memset(&baton, 0, sizeof(baton));
@@ -1779,14 +1821,15 @@ svn_diff_file_output_unified3(svn_stream
baton.hunk = svn_stringbuf_create_empty(pool);
baton.show_c_function = show_c_function;
baton.extra_context = svn_stringbuf_create_empty(pool);
- baton.extra_skip_match = apr_array_make(pool, 3, sizeof(char **));
- c = apr_array_push(baton.extra_skip_match);
- *c = "public:*";
- c = apr_array_push(baton.extra_skip_match);
- *c = "private:*";
- c = apr_array_push(baton.extra_skip_match);
- *c = "protected:*";
+ if (show_c_function)
+ {
+ baton.extra_skip_match = apr_array_make(pool, 3, sizeof(char **));
+
+ APR_ARRAY_PUSH(baton.extra_skip_match, const char *) = "public:*";
+ APR_ARRAY_PUSH(baton.extra_skip_match, const char *) = "private:*";
+ APR_ARRAY_PUSH(baton.extra_skip_match, const char *) = "protected:*";
+ }
SVN_ERR(svn_utf_cstring_from_utf8_ex2(&baton.context_str, " ",
header_encoding, pool));
@@ -1810,7 +1853,7 @@ svn_diff_file_output_unified3(svn_stream
else
return svn_error_createf(
SVN_ERR_BAD_RELATIVE_PATH, NULL,
- _("Path '%s' must be an immediate child of "
+ _("Path '%s' must be inside "
"the directory '%s'"),
svn_dirent_local_style(original_path, pool),
svn_dirent_local_style(relative_to_dir,
@@ -1826,7 +1869,7 @@ svn_diff_file_output_unified3(svn_stream
else
return svn_error_createf(
SVN_ERR_BAD_RELATIVE_PATH, NULL,
- _("Path '%s' must be an immediate child of "
+ _("Path '%s' must be inside "
"the directory '%s'"),
svn_dirent_local_style(modified_path, pool),
svn_dirent_local_style(relative_to_dir,
@@ -1842,19 +1885,19 @@ svn_diff_file_output_unified3(svn_stream
if (original_header == NULL)
{
- SVN_ERR(output_unified_default_hdr
- (&original_header, original_path, pool));
+ SVN_ERR(output_unified_default_hdr(&original_header, original_path,
+ pool));
}
if (modified_header == NULL)
{
- SVN_ERR(output_unified_default_hdr
- (&modified_header, modified_path, pool));
+ SVN_ERR(output_unified_default_hdr(&modified_header, modified_path,
+ pool));
}
- SVN_ERR(svn_diff__unidiff_write_header(
- output_stream, header_encoding,
- original_header, modified_header, pool));
+ SVN_ERR(svn_diff__unidiff_write_header(output_stream, header_encoding,
+ original_header, modified_header,
+ pool));
SVN_ERR(svn_diff_output(diff, &baton,
&svn_diff__file_output_unified_vtable));
Modified: subversion/branches/windows-build-update/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/windows-build-update/subversion/libsvn_diff/diff_memory.c?rev=1438999&r1=1438998&r2=1438999&view=diff
==============================================================================
--- subversion/branches/windows-build-update/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/windows-build-update/subversion/libsvn_diff/diff_memory.c Sun Jan 27 00:01:57 2013
@@ -27,6 +27,8 @@
#include <apr_want.h>
#include <apr_tables.h>
+#include <assert.h>
+
#include "svn_diff.h"
#include "svn_pools.h"
#include "svn_types.h"
@@ -342,7 +344,8 @@ typedef enum unified_output_e
{
unified_output_context = 0,
unified_output_delete,
- unified_output_insert
+ unified_output_insert,
+ unified_output_skip
} unified_output_e;
/* Baton for generating unified diffs */
@@ -351,7 +354,7 @@ typedef struct unified_output_baton_t
svn_stream_t *output_stream;
const char *header_encoding;
source_tokens_t sources[2]; /* 0 == original; 1 == modified */
- apr_off_t next_token; /* next token in original source */
+ apr_off_t current_token[2]; /* current token per source */
/* Cached markers, in header_encoding,
indexed using unified_output_e */
@@ -382,31 +385,28 @@ static svn_error_t *
output_unified_token_range(output_baton_t *btn,
int tokens,
unified_output_e type,
- apr_off_t first,
- apr_off_t past_last)
+ apr_off_t until)
{
source_tokens_t *source = &btn->sources[tokens];
- apr_off_t idx;
-
- past_last = (past_last > source->tokens->nelts)
- ? source->tokens->nelts : past_last;
- if (tokens == 0)
- /* We get context from the original source, don't expect
- to be asked to output a block which starts before
- what we already have written. */
- first = (first < btn->next_token) ? btn->next_token : first;
+ if (until > source->tokens->nelts)
+ until = source->tokens->nelts;
- if (first >= past_last)
+ if (until <= btn->current_token[tokens])
return SVN_NO_ERROR;
/* Do the loop with prefix and token */
- for (idx = first; idx < past_last; idx++)
+ while (TRUE)
{
- svn_string_t *token
- = APR_ARRAY_IDX(source->tokens, idx, svn_string_t *);
- svn_stringbuf_appendcstr(btn->hunk, btn->prefix_str[type]);
- svn_stringbuf_appendbytes(btn->hunk, token->data, token->len);
+ svn_string_t *token =
+ APR_ARRAY_IDX(source->tokens, btn->current_token[tokens],
+ svn_string_t *);
+
+ if (type != unified_output_skip)
+ {
+ svn_stringbuf_appendcstr(btn->hunk, btn->prefix_str[type]);
+ svn_stringbuf_appendbytes(btn->hunk, token->data, token->len);
+ }
if (type == unified_output_context)
{
@@ -415,11 +415,18 @@ output_unified_token_range(output_baton_
}
else if (type == unified_output_delete)
btn->hunk_length[0]++;
- else
+ else if (type == unified_output_insert)
btn->hunk_length[1]++;
+ /* ### TODO: Add skip processing for -p handling? */
+
+ btn->current_token[tokens]++;
+ if (btn->current_token[tokens] == until)
+ break;
}
- if (past_last == source->tokens->nelts && source->ends_without_eol)
+
+ if (btn->current_token[tokens] == source->tokens->nelts
+ && source->ends_without_eol)
{
const char *out_str;
@@ -429,8 +436,7 @@ output_unified_token_range(output_baton_
svn_stringbuf_appendcstr(btn->hunk, out_str);
}
- if (tokens == 0)
- btn->next_token = past_last;
+
return SVN_NO_ERROR;
}
@@ -445,6 +451,8 @@ output_unified_flush_hunk(output_baton_t
{
apr_off_t target_token;
apr_size_t hunk_len;
+ apr_off_t old_start;
+ apr_off_t new_start;
if (svn_stringbuf_isempty(baton->hunk))
return SVN_NO_ERROR;
@@ -453,24 +461,28 @@ output_unified_flush_hunk(output_baton_t
/* Write the trailing context */
target_token = baton->hunk_start[0] + baton->hunk_length[0]
- + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+ + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
SVN_ERR(output_unified_token_range(baton, 0 /*original*/,
unified_output_context,
- baton->next_token, target_token));
+ target_token));
if (hunk_delimiter == NULL)
hunk_delimiter = "@@";
- /* Convert our 0-based line numbers into unidiff 1-based numbers */
- if (baton->hunk_length[0] > 0)
- baton->hunk_start[0]++;
- if (baton->hunk_length[1] > 0)
- baton->hunk_start[1]++;
+ old_start = baton->hunk_start[0];
+ new_start = baton->hunk_start[1];
+
+ /* If the file is non-empty, convert the line indexes from
+ zero based to one based */
+ if (baton->hunk_length[0])
+ old_start++;
+ if (baton->hunk_length[1])
+ new_start++;
/* Write the hunk header */
SVN_ERR(svn_diff__unified_write_hunk_header(
baton->output_stream, baton->header_encoding, hunk_delimiter,
- baton->hunk_start[0], baton->hunk_length[0],
- baton->hunk_start[1], baton->hunk_length[1],
+ old_start, baton->hunk_length[0],
+ new_start, baton->hunk_length[1],
NULL /* hunk_extra_context */,
baton->pool));
@@ -478,7 +490,11 @@ output_unified_flush_hunk(output_baton_t
SVN_ERR(svn_stream_write(baton->output_stream,
baton->hunk->data, &hunk_len));
- baton->hunk_length[0] = baton->hunk_length[1] = 0;
+ /* Prepare for the next hunk */
+ baton->hunk_length[0] = 0;
+ baton->hunk_length[1] = 0;
+ baton->hunk_start[0] = 0;
+ baton->hunk_start[1] = 0;
svn_stringbuf_setempty(baton->hunk);
return SVN_NO_ERROR;
@@ -494,38 +510,91 @@ output_unified_diff_modified(void *baton
apr_off_t latest_start,
apr_off_t latest_length)
{
- output_baton_t *btn = baton;
- apr_off_t targ_orig, targ_mod;
+ output_baton_t *output_baton = baton;
+ apr_off_t context_prefix_length;
+ apr_off_t prev_context_end;
+ svn_boolean_t init_hunk = FALSE;
+
+ if (original_start > SVN_DIFF__UNIFIED_CONTEXT_SIZE)
+ context_prefix_length = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+ else
+ context_prefix_length = original_start;
- targ_orig = original_start - SVN_DIFF__UNIFIED_CONTEXT_SIZE;
- targ_orig = (targ_orig < 0) ? 0 : targ_orig;
- targ_mod = modified_start;
-
- /* If the changed ranges are far enough apart (no overlapping or
- * connecting context), flush the current hunk. */
- if (btn->next_token + SVN_DIFF__UNIFIED_CONTEXT_SIZE < targ_orig)
- SVN_ERR(output_unified_flush_hunk(btn, btn->hunk_delimiter));
- /* Adjust offset if it's not the first hunk. */
- else if (btn->hunk_length[0] != 0)
- targ_orig = btn->next_token;
+ /* Calculate where the previous hunk will end if we would write it now
+ (including the necessary context at the end) */
+ if (output_baton->hunk_length[0] > 0 || output_baton->hunk_length[1] > 0)
+ {
+ prev_context_end = output_baton->hunk_start[0]
+ + output_baton->hunk_length[0]
+ + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+ }
+ else
+ {
+ prev_context_end = -1;
+
+ if (output_baton->hunk_start[0] == 0
+ && (original_length > 0 || modified_length > 0))
+ init_hunk = TRUE;
+ }
- if (btn->hunk_length[0] == 0
- && btn->hunk_length[1] == 0)
+ /* If the changed range is far enough from the previous range, flush the current
+ hunk. */
+ {
+ apr_off_t new_hunk_start = (original_start - context_prefix_length);
+
+ if (output_baton->current_token[0] < new_hunk_start
+ && prev_context_end <= new_hunk_start)
+ {
+ SVN_ERR(output_unified_flush_hunk(output_baton,
+ output_baton->hunk_delimiter));
+ init_hunk = TRUE;
+ }
+ else if (output_baton->hunk_length[0] > 0
+ || output_baton->hunk_length[1] > 0)
+ {
+ /* We extend the current hunk */
+
+ /* Original: Output the context preceding the changed range */
+ SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
+ unified_output_context,
+ original_start));
+ }
+ }
+
+ /* Original: Skip lines until we are at the beginning of the context we want
+ to display */
+ SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
+ unified_output_skip,
+ original_start - context_prefix_length));
+
+ if (init_hunk)
{
- btn->hunk_start[0] = targ_orig;
- btn->hunk_start[1] = targ_mod + targ_orig - original_start;
+ SVN_ERR_ASSERT(output_baton->hunk_length[0] == 0
+ && output_baton->hunk_length[1] == 0);
+
+ output_baton->hunk_start[0] = original_start - context_prefix_length;
+ output_baton->hunk_start[1] = modified_start - context_prefix_length;
}
- SVN_ERR(output_unified_token_range(btn, 0/*original*/,
- unified_output_context,
- targ_orig, original_start));
- SVN_ERR(output_unified_token_range(btn, 0/*original*/,
+ /* Modified: Skip lines until we are at the start of the changed range */
+ SVN_ERR(output_unified_token_range(output_baton, 1 /* modified */,
+ unified_output_skip,
+ modified_start));
+
+ /* Original: Output the context preceding the changed range */
+ SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
+ unified_output_context,
+ original_start));
+
+ /* Both: Output the changed range */
+ SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
unified_output_delete,
- original_start,
original_start + original_length));
- return output_unified_token_range(btn, 1/*modified*/, unified_output_insert,
- modified_start,
- modified_start + modified_length);
+ SVN_ERR(output_unified_token_range(output_baton, 1 /* modified */,
+ unified_output_insert,
+ modified_start + modified_length));
+
+ return SVN_NO_ERROR;
}
static const svn_diff_output_fns_t mem_output_unified_vtable =
@@ -656,7 +725,7 @@ typedef struct merge_output_baton_t
/* Tokenized source text */
source_tokens_t sources[3];
- apr_off_t next_token;
+ apr_off_t next_token[3];
/* Markers for marking conflicted sections */
const char *markers[4]; /* 0 = original, 1 = modified,
Modified: subversion/branches/windows-build-update/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/windows-build-update/subversion/libsvn_ra_serf/update.c?rev=1438999&r1=1438998&r2=1438999&view=diff
==============================================================================
--- subversion/branches/windows-build-update/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/windows-build-update/subversion/libsvn_ra_serf/update.c Sun Jan 27 00:01:57 2013
@@ -2738,6 +2738,28 @@ create_update_report_body(serf_bucket_t
return SVN_NO_ERROR;
}
+/* Serf callback to setup update request headers. */
+static svn_error_t *
+setup_update_report_headers(serf_bucket_t *headers,
+ void *baton,
+ apr_pool_t *pool)
+{
+ report_context_t *report = baton;
+
+ if (report->sess->using_compression)
+ {
+ serf_bucket_headers_setn(headers, "Accept-Encoding",
+ "gzip;svndiff1;q=0.9,svndiff;q=0.8");
+ }
+ else
+ {
+ serf_bucket_headers_setn(headers, "Accept-Encoding",
+ "svndiff1;q=0.9,svndiff;q=0.8");
+ }
+
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *
finish_report(void *report_baton,
apr_pool_t *pool)
@@ -2783,6 +2805,9 @@ finish_report(void *report_baton,
handler->body_delegate = create_update_report_body;
handler->body_delegate_baton = report;
handler->body_type = "text/xml";
+ handler->custom_accept_encoding = TRUE;
+ handler->header_delegate = setup_update_report_headers;
+ handler->header_delegate_baton = report;
handler->conn = sess->conns[0];
handler->session = sess;
Modified: subversion/branches/windows-build-update/subversion/libsvn_repos/authz.c
URL: http://svn.apache.org/viewvc/subversion/branches/windows-build-update/subversion/libsvn_repos/authz.c?rev=1438999&r1=1438998&r2=1438999&view=diff
==============================================================================
--- subversion/branches/windows-build-update/subversion/libsvn_repos/authz.c (original)
+++ subversion/branches/windows-build-update/subversion/libsvn_repos/authz.c Sun Jan 27 00:01:57 2013
@@ -849,7 +849,7 @@ authz_retrieve_config_repo(svn_config_t
/* Add the URL to the error stack since the parser doesn't have it. */
if (err != SVN_NO_ERROR)
return svn_error_createf(err->apr_err, err,
- "Error parsing config file: '%s' in repo '%s':",
+ "Error while parsing config file: '%s' in repo '%s':",
fs_path, repos_root_dirent);
return SVN_NO_ERROR;
@@ -919,20 +919,81 @@ authz_retrieve_config(svn_config_t **cfg
return SVN_NO_ERROR;
}
+
+/* Callback to copy (name, value) group into the "groups" section
+ of another configuration. */
+static svn_boolean_t
+authz_copy_group(const char *name, const char *value,
+ void *baton, apr_pool_t *pool)
+{
+ svn_config_t *authz_cfg = baton;
+
+ svn_config_set(authz_cfg, SVN_CONFIG_SECTION_GROUPS, name, value);
+
+ return TRUE;
+}
+
+/* Copy group definitions from GROUPS_CFG to the resulting AUTHZ.
+ * If AUTHZ already contains any group definition, report an error.
+ * Use POOL for temporary allocations. */
+static svn_error_t *
+authz_copy_groups(svn_authz_t *authz, svn_config_t *groups_cfg,
+ apr_pool_t *pool)
+{
+ /* Easy out: we prohibit local groups in the authz file when global
+ groups are being used. */
+ if (svn_config_has_section(authz->cfg, SVN_CONFIG_SECTION_GROUPS))
+ {
+ return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+ "Authz file cannot contain any groups "
+ "when global groups are being used.");
+ }
+
+ svn_config_enumerate2(groups_cfg, SVN_CONFIG_SECTION_GROUPS,
+ authz_copy_group, authz->cfg, pool);
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_repos__authz_read(svn_authz_t **authz_p, const char *path,
- svn_boolean_t must_exist, svn_boolean_t accept_urls,
- const char *repos_root, apr_pool_t *pool)
+ const char *groups_path, svn_boolean_t must_exist,
+ svn_boolean_t accept_urls, const char *repos_root,
+ apr_pool_t *pool)
{
svn_authz_t *authz = apr_palloc(pool, sizeof(*authz));
- /* Load the rule file */
+ /* Load the authz file */
if (accept_urls)
SVN_ERR(authz_retrieve_config(&authz->cfg, path, must_exist, repos_root,
pool));
else
SVN_ERR(svn_config_read2(&authz->cfg, path, must_exist, TRUE, pool));
+ if (groups_path)
+ {
+ svn_config_t *groups_cfg;
+ svn_error_t *err;
+
+ /* Load the groups file */
+ if (accept_urls)
+ SVN_ERR(authz_retrieve_config(&groups_cfg, groups_path, must_exist,
+ repos_root, pool));
+ else
+ SVN_ERR(svn_config_read2(&groups_cfg, groups_path, must_exist,
+ TRUE, pool));
+
+ /* Copy the groups from groups_cfg into authz. */
+ err = authz_copy_groups(authz, groups_cfg, pool);
+
+ /* Add the paths to the error stack since the authz_copy_groups
+ routine knows nothing about them. */
+ if (err != SVN_NO_ERROR)
+ return svn_error_createf(err->apr_err, err,
+ "Error reading authz file '%s' with "
+ "groups file '%s':", path, groups_path);
+ }
+
/* Make sure there are no errors in the configuration. */
SVN_ERR(authz_validate(authz, pool));
@@ -946,23 +1007,33 @@ svn_repos__authz_read(svn_authz_t **auth
svn_error_t *
svn_repos_authz_read2(svn_authz_t **authz_p, const char *path,
- svn_boolean_t must_exist, const char *repos_root,
- apr_pool_t *pool)
+ const char *groups_path, svn_boolean_t must_exist,
+ const char *repos_root, apr_pool_t *pool)
{
- return svn_repos__authz_read(authz_p, path, must_exist, TRUE, repos_root,
- pool);
+ return svn_repos__authz_read(authz_p, path, groups_path, must_exist,
+ TRUE, repos_root, pool);
}
svn_error_t *
svn_repos_authz_parse(svn_authz_t **authz_p, svn_stream_t *stream,
- apr_pool_t *pool)
+ svn_stream_t *groups_stream, apr_pool_t *pool)
{
svn_authz_t *authz = apr_palloc(pool, sizeof(*authz));
- /* Parse the stream */
+ /* Parse the authz stream */
SVN_ERR(svn_config_parse(&authz->cfg, stream, TRUE, pool));
+ if (groups_stream)
+ {
+ svn_config_t *groups_cfg;
+
+ /* Parse the groups stream */
+ SVN_ERR(svn_config_parse(&groups_cfg, groups_stream, TRUE, pool));
+
+ SVN_ERR(authz_copy_groups(authz, groups_cfg, pool));
+ }
+
/* Make sure there are no errors in the configuration. */
SVN_ERR(authz_validate(authz, pool));
Modified: subversion/branches/windows-build-update/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/windows-build-update/subversion/libsvn_repos/deprecated.c?rev=1438999&r1=1438998&r2=1438999&view=diff
==============================================================================
--- subversion/branches/windows-build-update/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/windows-build-update/subversion/libsvn_repos/deprecated.c Sun Jan 27 00:01:57 2013
@@ -1013,5 +1013,6 @@ svn_error_t *
svn_repos_authz_read(svn_authz_t **authz_p, const char *file,
svn_boolean_t must_exist, apr_pool_t *pool)
{
- return svn_repos__authz_read(authz_p, file, must_exist, FALSE, NULL, pool);
+ return svn_repos__authz_read(authz_p, file, NULL, must_exist,
+ FALSE, NULL, pool);
}
Modified: subversion/branches/windows-build-update/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/windows-build-update/subversion/libsvn_repos/repos.c?rev=1438999&r1=1438998&r2=1438999&view=diff
==============================================================================
--- subversion/branches/windows-build-update/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/windows-build-update/subversion/libsvn_repos/repos.c Sun Jan 27 00:01:57 2013
@@ -1025,6 +1025,12 @@ create_conf(svn_repos_t *repos, apr_pool
"### no path-based access control is done." NL
"### Uncomment the line below to use the default authorization file." NL
"# authz-db = " SVN_REPOS__CONF_AUTHZ NL
+"### The groups-db option controls the location of the groups file." NL
+"### Unless you specify a path starting with a /, the file's location is" NL
+"### relative to the directory containing this file. The specified path" NL
+"### may be a repository relative URL (^/) or an absolute file:// URL to a" NL
+"### text file in a Subversion repository." NL
+"# groups-db = " SVN_REPOS__CONF_GROUPS NL
"### This option specifies the authentication realm of the repository." NL
"### If two repositories have the same authentication realm, they should" NL
"### have the same password database, and vice versa. The default realm" NL
Modified: subversion/branches/windows-build-update/subversion/libsvn_repos/repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/windows-build-update/subversion/libsvn_repos/repos.h?rev=1438999&r1=1438998&r2=1438999&view=diff
==============================================================================
--- subversion/branches/windows-build-update/subversion/libsvn_repos/repos.h (original)
+++ subversion/branches/windows-build-update/subversion/libsvn_repos/repos.h Sun Jan 27 00:01:57 2013
@@ -95,10 +95,11 @@ extern "C" {
#define SVN_REPOS__CONF_SVNSERVE_CONF "svnserve.conf"
/* In the svnserve default configuration, these are the suggested
- locations for the passwd and authz files (in the repository conf
- directory), and we put example templates there. */
+ locations for the passwd, authz and groups files (in the repository
+ conf directory), and we put example templates there. */
#define SVN_REPOS__CONF_PASSWD "passwd"
#define SVN_REPOS__CONF_AUTHZ "authz"
+#define SVN_REPOS__CONF_GROUPS "groups"
/* The Repository object, created by svn_repos_open2() and
svn_repos_create(). */
@@ -307,22 +308,24 @@ svn_repos__hooks_post_unlock(svn_repos_t
/*** Authz Functions ***/
/* Read authz configuration data from PATH into *AUTHZ_P, allocated
- in POOL.
-
- PATH may be a file or a registry path and iff ACCEPT_URLS is set
- it may also be a repos relative url or an absolute file url. When
+ in POOL. If GROUPS_PATH is set, use the global groups parsed from it.
+
+ PATH and GROUPS_PATH may be a file or a registry path and iff ACCEPT_URLS
+ is set it may also be a repos relative url or an absolute file url. When
ACCEPT_URLS is FALSE REPOS_ROOT can be NULL.
-
- If PATH is not a valid authz rule file, then return
+
+ If PATH or GROUPS_PATH is not a valid authz rule file, then return
SVN_AUTHZ_INVALID_CONFIG. The contents of *AUTHZ_P is then
- undefined. If MUST_EXIST is TRUE, a missing authz file is also
- an error.
-
+ undefined. If MUST_EXIST is TRUE, a missing authz or global groups file
+ is also an error.
+
If PATH is a repos relative URL then REPOS_ROOT must be set to
- the root of the repository the authz configuration will be used with. */
+ the root of the repository the authz configuration will be used with.
+ The same applies to GROUPS_PATH if it is being used. */
svn_error_t *
svn_repos__authz_read(svn_authz_t **authz_p,
const char *path,
+ const char *groups_path,
svn_boolean_t must_exist,
svn_boolean_t accept_urls,
const char *repos_root,
Modified: subversion/branches/windows-build-update/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/windows-build-update/subversion/libsvn_subr/io.c?rev=1438999&r1=1438998&r2=1438999&view=diff
==============================================================================
--- subversion/branches/windows-build-update/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/windows-build-update/subversion/libsvn_subr/io.c Sun Jan 27 00:01:57 2013
@@ -2506,7 +2506,7 @@ svn_io_stat_dirent2(const svn_io_dirent2
apr_int32_t wanted = APR_FINFO_TYPE | APR_FINFO_LINK
| APR_FINFO_SIZE | APR_FINFO_MTIME;
-#if defined(WIN32) || defined(__OS2__) || defined(DARWIN)
+#if defined(WIN32) || defined(__OS2__)
if (verify_truename)
wanted |= APR_FINFO_NAME;
#endif
@@ -2535,6 +2535,7 @@ svn_io_stat_dirent2(const svn_io_dirent2
{
/* No parent directory. No need to stat/verify */
}
+#if defined(WIN32) || defined(__OS2__)
else if (finfo.name)
{
const char *name_on_disk;
@@ -2555,8 +2556,9 @@ svn_io_stat_dirent2(const svn_io_dirent2
name_on_disk);
}
}
-#if defined(DARWIN)
- /* Currently apr doesn't set finfo.name on DARWIN.
+#elif defined(DARWIN)
+ /* Currently apr doesn't set finfo.name on DARWIN, returning
+ APR_INCOMPLETE.
### Can we optimize this in another way? */
else
{