You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by fu...@apache.org on 2019/07/08 15:19:05 UTC
svn commit: r1862754 [5/9] - in /subversion/branches/swig-py3: ./
build/ac-macros/ build/generator/ doc/ doc/programmer/ notes/
notes/shelving/ subversion/bindings/cxx/ subversion/bindings/cxxhl/
subversion/bindings/javahl/native/ subversion/bindings/j...
Modified: subversion/branches/swig-py3/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_client/copy.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_client/copy.c Mon Jul 8 15:19:03 2019
@@ -1158,10 +1158,6 @@ typedef struct path_driver_info_t
or move operation. */
struct path_driver_cb_baton
{
- /* The editor (and its state) used to perform the operation. */
- const svn_delta_editor_t *editor;
- void *edit_baton;
-
/* A hash of path -> path_driver_info_t *'s. */
apr_hash_t *action_hash;
@@ -1171,6 +1167,8 @@ struct path_driver_cb_baton
static svn_error_t *
path_driver_cb_func(void **dir_baton,
+ const svn_delta_editor_t *editor,
+ void *edit_baton,
void *parent_baton,
void *callback_baton,
const char *path,
@@ -1191,9 +1189,9 @@ path_driver_cb_func(void **dir_baton,
/* Check to see if we need to add the path as a parent directory. */
if (path_info->dir_add)
{
- return cb_baton->editor->add_directory(path, parent_baton, NULL,
- SVN_INVALID_REVNUM, pool,
- dir_baton);
+ return editor->add_directory(path, parent_baton, NULL,
+ SVN_INVALID_REVNUM, pool,
+ dir_baton);
}
/* If this is a resurrection, we know the source and dest paths are
@@ -1225,8 +1223,8 @@ path_driver_cb_func(void **dir_baton,
if (do_delete)
{
- SVN_ERR(cb_baton->editor->delete_entry(path, SVN_INVALID_REVNUM,
- parent_baton, pool));
+ SVN_ERR(editor->delete_entry(path, SVN_INVALID_REVNUM,
+ parent_baton, pool));
}
if (do_add)
{
@@ -1235,40 +1233,40 @@ path_driver_cb_func(void **dir_baton,
if (path_info->src_kind == svn_node_file)
{
void *file_baton;
- SVN_ERR(cb_baton->editor->add_file(path, parent_baton,
- path_info->src_url,
- path_info->src_revnum,
- pool, &file_baton));
+ SVN_ERR(editor->add_file(path, parent_baton,
+ path_info->src_url,
+ path_info->src_revnum,
+ pool, &file_baton));
if (path_info->mergeinfo)
- SVN_ERR(cb_baton->editor->change_file_prop(file_baton,
- SVN_PROP_MERGEINFO,
- path_info->mergeinfo,
- pool));
- SVN_ERR(cb_baton->editor->close_file(file_baton, NULL, pool));
+ SVN_ERR(editor->change_file_prop(file_baton,
+ SVN_PROP_MERGEINFO,
+ path_info->mergeinfo,
+ pool));
+ SVN_ERR(editor->close_file(file_baton, NULL, pool));
}
else
{
- SVN_ERR(cb_baton->editor->add_directory(path, parent_baton,
- path_info->src_url,
- path_info->src_revnum,
- pool, dir_baton));
+ SVN_ERR(editor->add_directory(path, parent_baton,
+ path_info->src_url,
+ path_info->src_revnum,
+ pool, dir_baton));
if (path_info->mergeinfo)
- SVN_ERR(cb_baton->editor->change_dir_prop(*dir_baton,
- SVN_PROP_MERGEINFO,
- path_info->mergeinfo,
- pool));
+ SVN_ERR(editor->change_dir_prop(*dir_baton,
+ SVN_PROP_MERGEINFO,
+ path_info->mergeinfo,
+ pool));
}
}
if (path_info->externals)
{
if (*dir_baton == NULL)
- SVN_ERR(cb_baton->editor->open_directory(path, parent_baton,
- SVN_INVALID_REVNUM,
- pool, dir_baton));
+ SVN_ERR(editor->open_directory(path, parent_baton,
+ SVN_INVALID_REVNUM,
+ pool, dir_baton));
- SVN_ERR(cb_baton->editor->change_dir_prop(*dir_baton, SVN_PROP_EXTERNALS,
- path_info->externals, pool));
+ SVN_ERR(editor->change_dir_prop(*dir_baton, SVN_PROP_EXTERNALS,
+ path_info->externals, pool));
}
return SVN_NO_ERROR;
@@ -1852,13 +1850,11 @@ repos_to_repos_copy(const apr_array_head
pool));
/* Setup the callback baton. */
- cb_baton.editor = editor;
- cb_baton.edit_baton = edit_baton;
cb_baton.action_hash = action_hash;
cb_baton.is_move = is_move;
/* Call the path-based editor driver. */
- err = svn_delta_path_driver2(editor, edit_baton, paths, TRUE,
+ err = svn_delta_path_driver3(editor, edit_baton, paths, TRUE,
path_driver_cb_func, &cb_baton, pool);
if (err)
{
@@ -2388,6 +2384,7 @@ copy_foreign_dir(svn_ra_session_t *ra_se
dst_abspath,
TRUE /*root_dir_add*/,
TRUE /*ignore_mergeinfo_changes*/,
+ FALSE /*manage_wc_write_lock*/,
notify_func, notify_baton,
NULL /*ra_session*/,
ctx, scratch_pool));
@@ -2434,6 +2431,8 @@ svn_client__repos_to_wc_copy_dir(svn_boo
*timestamp_sleep = TRUE;
+ /* ### Reparenting "ra_session" can't be right, can it? As this is
+ a foreign repo, surely we need a new RA session? */
SVN_ERR(svn_client__pathrev_create_with_session(&location, ra_session,
src_revnum, src_url,
scratch_pool));
@@ -2599,9 +2598,13 @@ svn_client__repos_to_wc_copy_internal(sv
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
+ const char *old_session_url;
svn_boolean_t timestamp_sleep_ignored;
svn_boolean_t same_repositories;
+ SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
+ src_url, scratch_pool));
+
SVN_ERR(is_same_repository(&same_repositories,
ra_session, dst_abspath, ctx, scratch_pool));
@@ -2626,6 +2629,9 @@ svn_client__repos_to_wc_copy_internal(sv
ra_session,
ctx, scratch_pool));
}
+
+ /* Reparent the session back to the original URL. */
+ SVN_ERR(svn_ra_reparent(ra_session, old_session_url, scratch_pool));
return SVN_NO_ERROR;
}
@@ -2647,11 +2653,15 @@ svn_client__repos_to_wc_copy_by_editor(s
SVN_ERR(svn_ra_reparent(ra_session, src_anchor, scratch_pool));
- SVN_ERR(svn_client__wc_editor(&editor, &eb,
- svn_dirent_dirname(dst_abspath, scratch_pool),
- ctx->notify_func2, ctx->notify_baton2,
- ra_session,
- ctx, scratch_pool));
+ SVN_ERR(svn_client__wc_editor_internal(
+ &editor, &eb,
+ svn_dirent_dirname(dst_abspath, scratch_pool),
+ FALSE /*root_dir_add*/,
+ FALSE /*ignore_mergeinfo_changes*/,
+ FALSE /*manage_wc_write_lock*/,
+ ctx->notify_func2, ctx->notify_baton2,
+ ra_session,
+ ctx, scratch_pool));
SVN_ERR(editor->open_root(eb, SVN_INVALID_REVNUM, scratch_pool, &rb));
if (kind == svn_node_dir)
Modified: subversion/branches/swig-py3/subversion/libsvn_client/delete.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_client/delete.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_client/delete.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_client/delete.c Mon Jul 8 15:19:03 2019
@@ -181,12 +181,13 @@ can_delete_node(svn_boolean_t *target_mi
static svn_error_t *
path_driver_cb_func(void **dir_baton,
+ const svn_delta_editor_t *editor,
+ void *edit_baton,
void *parent_baton,
void *callback_baton,
const char *path,
apr_pool_t *pool)
{
- const svn_delta_editor_t *editor = callback_baton;
*dir_baton = NULL;
return editor->delete_entry(path, SVN_INVALID_REVNUM, parent_baton, pool);
}
@@ -248,8 +249,8 @@ single_repos_delete(svn_ra_session_t *ra
pool));
/* Call the path-based editor driver. */
- err = svn_delta_path_driver2(editor, edit_baton, relpaths, TRUE,
- path_driver_cb_func, (void *)editor, pool);
+ err = svn_delta_path_driver3(editor, edit_baton, relpaths, TRUE,
+ path_driver_cb_func, NULL, pool);
if (err)
{
Modified: subversion/branches/swig-py3/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_client/deprecated.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_client/deprecated.c Mon Jul 8 15:19:03 2019
@@ -166,6 +166,61 @@ svn_client_mkdir(svn_client_commit_info_
}
/*** From blame.c ***/
+struct blame_receiver_wrapper_baton3 {
+ void *baton;
+ svn_client_blame_receiver3_t receiver;
+ svn_revnum_t start_revnum;
+ svn_revnum_t end_revnum;
+};
+
+static svn_error_t *
+blame_wrapper_receiver3(void *baton,
+ apr_int64_t line_no,
+ svn_revnum_t revision,
+ apr_hash_t *rev_props,
+ svn_revnum_t merged_revision,
+ apr_hash_t *merged_rev_props,
+ const char *merged_path,
+ const svn_string_t *line,
+ svn_boolean_t local_change,
+ apr_pool_t *pool)
+{
+ struct blame_receiver_wrapper_baton3 *brwb = baton;
+
+ if (brwb->receiver)
+ return brwb->receiver(brwb->baton, brwb->start_revnum, brwb->end_revnum,
+ line_no,
+ revision, rev_props, merged_revision,
+ merged_rev_props, merged_path, line->data,
+ local_change, pool);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_blame5(const char *target,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *start,
+ const svn_opt_revision_t *end,
+ const svn_diff_file_options_t *diff_options,
+ svn_boolean_t ignore_mime_type,
+ svn_boolean_t include_merged_revisions,
+ svn_client_blame_receiver3_t receiver,
+ void *receiver_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ struct blame_receiver_wrapper_baton3 baton;
+
+ baton.receiver = receiver;
+ baton.baton = receiver_baton;
+
+ return svn_client_blame6(&baton.start_revnum, &baton.end_revnum,
+ target, peg_revision, start, end,
+ diff_options,
+ ignore_mime_type, include_merged_revisions,
+ blame_wrapper_receiver3, &baton, ctx, pool);
+}
struct blame_receiver_wrapper_baton2 {
void *baton;
Modified: subversion/branches/swig-py3/subversion/libsvn_client/shelf.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_client/shelf.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_client/shelf.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_client/shelf.c Mon Jul 8 15:19:03 2019
@@ -100,7 +100,7 @@ shelf_name_from_filename(char **name,
{
size_t len = strlen(filename);
static const char suffix[] = ".current";
- int suffix_len = sizeof(suffix) - 1;
+ size_t suffix_len = sizeof(suffix) - 1;
if (len > suffix_len && strcmp(filename + len - suffix_len, suffix) == 0)
{
@@ -114,6 +114,28 @@ shelf_name_from_filename(char **name,
return SVN_NO_ERROR;
}
+/* Set *DIR to the shelf storage directory inside the WC's administrative
+ * area. Ensure the directory exists. */
+static svn_error_t *
+get_shelves_dir(char **dir,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ char *experimental_abspath;
+
+ SVN_ERR(svn_wc__get_experimental_dir(&experimental_abspath,
+ wc_ctx, local_abspath,
+ scratch_pool, scratch_pool));
+ *dir = svn_dirent_join(experimental_abspath, "shelves/v3", result_pool);
+
+ /* Ensure the directory exists. (Other versions of svn don't create it.) */
+ SVN_ERR(svn_io_make_dir_recursively(*dir, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
/* Set *ABSPATH to the abspath of the file storage dir for SHELF
* version VERSION, no matter whether it exists.
*/
@@ -128,7 +150,7 @@ shelf_version_files_dir_abspath(const ch
char *filename;
SVN_ERR(shelf_name_encode(&codename, shelf->name, result_pool));
- filename = apr_psprintf(scratch_pool, "%s-%03d.d", codename, version);
+ filename = apr_psprintf(scratch_pool, "%s-%03d.wc", codename, version);
*abspath = svn_dirent_join(shelf->shelves_dir, filename, result_pool);
return SVN_NO_ERROR;
}
@@ -154,86 +176,6 @@ shelf_version_create(svn_client__shelf_v
return SVN_NO_ERROR;
}
-/* Set *ABSPATH to the abspath of the metadata file for SHELF_VERSION
- * node at RELPATH, no matter whether it exists.
- */
-static svn_error_t *
-get_metadata_abspath(char **abspath,
- svn_client__shelf_version_t *shelf_version,
- const char *wc_relpath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- wc_relpath = apr_psprintf(scratch_pool, "%s.meta", wc_relpath);
- *abspath = svn_dirent_join(shelf_version->files_dir_abspath, wc_relpath,
- result_pool);
- return SVN_NO_ERROR;
-}
-
-/* Set *ABSPATH to the abspath of the base text file for SHELF_VERSION
- * node at RELPATH, no matter whether it exists.
- */
-static svn_error_t *
-get_base_file_abspath(char **base_abspath,
- svn_client__shelf_version_t *shelf_version,
- const char *wc_relpath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- wc_relpath = apr_psprintf(scratch_pool, "%s.base", wc_relpath);
- *base_abspath = svn_dirent_join(shelf_version->files_dir_abspath, wc_relpath,
- result_pool);
- return SVN_NO_ERROR;
-}
-
-/* Set *ABSPATH to the abspath of the working text file for SHELF_VERSION
- * node at RELPATH, no matter whether it exists.
- */
-static svn_error_t *
-get_working_file_abspath(char **work_abspath,
- svn_client__shelf_version_t *shelf_version,
- const char *wc_relpath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- wc_relpath = apr_psprintf(scratch_pool, "%s.work", wc_relpath);
- *work_abspath = svn_dirent_join(shelf_version->files_dir_abspath, wc_relpath,
- result_pool);
- return SVN_NO_ERROR;
-}
-
-/* Set *ABSPATH to the abspath of the base props file for SHELF_VERSION
- * node at RELPATH, no matter whether it exists.
- */
-static svn_error_t *
-get_base_props_abspath(char **base_abspath,
- svn_client__shelf_version_t *shelf_version,
- const char *wc_relpath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- wc_relpath = apr_psprintf(scratch_pool, "%s.base-props", wc_relpath);
- *base_abspath = svn_dirent_join(shelf_version->files_dir_abspath, wc_relpath,
- result_pool);
- return SVN_NO_ERROR;
-}
-
-/* Set *ABSPATH to the abspath of the working props file for SHELF_VERSION
- * node at RELPATH, no matter whether it exists.
- */
-static svn_error_t *
-get_working_props_abspath(char **work_abspath,
- svn_client__shelf_version_t *shelf_version,
- const char *wc_relpath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- wc_relpath = apr_psprintf(scratch_pool, "%s.work-props", wc_relpath);
- *work_abspath = svn_dirent_join(shelf_version->files_dir_abspath, wc_relpath,
- result_pool);
- return SVN_NO_ERROR;
-}
-
/* Delete the storage for SHELF:VERSION. */
static svn_error_t *
shelf_version_delete(svn_client__shelf_t *shelf,
@@ -416,150 +358,19 @@ shelf_write_current(svn_client__shelf_t
/*-------------------------------------------------------------------------*/
/* Status Reporting */
-/* Create a status struct with all fields initialized to valid values
- * representing 'uninteresting' or 'unknown' status.
- */
-static svn_wc_status3_t *
-status_create(apr_pool_t *result_pool)
-{
- svn_wc_status3_t *s = apr_pcalloc(result_pool, sizeof(*s));
-
- s->filesize = SVN_INVALID_FILESIZE;
- s->versioned = TRUE;
- s->node_status = svn_wc_status_none;
- s->text_status = svn_wc_status_none;
- s->prop_status = svn_wc_status_none;
- s->revision = SVN_INVALID_REVNUM;
- s->changed_rev = SVN_INVALID_REVNUM;
- s->repos_node_status = svn_wc_status_none;
- s->repos_text_status = svn_wc_status_none;
- s->repos_prop_status = svn_wc_status_none;
- s->ood_changed_rev = SVN_INVALID_REVNUM;
- return s;
-}
-
-/* Convert from svn_node_kind_t to a single character representation. */
-static char
-kind_to_char(svn_node_kind_t kind)
-{
- return (kind == svn_node_dir ? 'd'
- : kind == svn_node_file ? 'f'
- : kind == svn_node_symlink ? 'l'
- : '?');
-}
-
-/* Convert to svn_node_kind_t from a single character representation. */
-static svn_node_kind_t
-char_to_kind(char kind)
-{
- return (kind == 'd' ? svn_node_dir
- : kind == 'f' ? svn_node_file
- : kind == 'l' ? svn_node_symlink
- : svn_node_unknown);
-}
-
-/* Return the single character representation of STATUS.
- * (Similar to subversion/svn/status.c:generate_status_code()
- * and subversion/tests/libsvn_client/client-test.c:status_to_char().) */
-static char
-status_to_char(enum svn_wc_status_kind status)
-{
- switch (status)
- {
- case svn_wc_status_none: return '.';
- case svn_wc_status_unversioned: return '?';
- case svn_wc_status_normal: return ' ';
- case svn_wc_status_added: return 'A';
- case svn_wc_status_missing: return '!';
- case svn_wc_status_deleted: return 'D';
- case svn_wc_status_replaced: return 'R';
- case svn_wc_status_modified: return 'M';
- case svn_wc_status_merged: return 'G';
- case svn_wc_status_conflicted: return 'C';
- case svn_wc_status_ignored: return 'I';
- case svn_wc_status_obstructed: return '~';
- case svn_wc_status_external: return 'X';
- case svn_wc_status_incomplete: return ':';
- default: return '*';
- }
-}
-
-static enum svn_wc_status_kind
-char_to_status(char status)
-{
- switch (status)
- {
- case '.': return svn_wc_status_none;
- case '?': return svn_wc_status_unversioned;
- case ' ': return svn_wc_status_normal;
- case 'A': return svn_wc_status_added;
- case '!': return svn_wc_status_missing;
- case 'D': return svn_wc_status_deleted;
- case 'R': return svn_wc_status_replaced;
- case 'M': return svn_wc_status_modified;
- case 'G': return svn_wc_status_merged;
- case 'C': return svn_wc_status_conflicted;
- case 'I': return svn_wc_status_ignored;
- case '~': return svn_wc_status_obstructed;
- case 'X': return svn_wc_status_external;
- case ':': return svn_wc_status_incomplete;
- default: return (enum svn_wc_status_kind)0;
- }
-}
-
-/* Write a serial representation of (some fields of) STATUS to STREAM.
+/* Adjust a status STATUS_IN obtained from the shelf storage WC, to add
+ * shelf-related metadata:
+ * - changelist: 'svn:shelf:SHELFNAME'
*/
static svn_error_t *
-wc_status_serialize(svn_stream_t *stream,
- const svn_wc_status3_t *status,
- apr_pool_t *scratch_pool)
-{
- SVN_ERR(svn_stream_printf(stream, scratch_pool, "%c %c%c%c %ld",
- kind_to_char(status->kind),
- status_to_char(status->node_status),
- status_to_char(status->text_status),
- status_to_char(status->prop_status),
- status->revision));
- return SVN_NO_ERROR;
-}
-
-/* Read a serial representation of (some fields of) STATUS from STREAM.
- */
-static svn_error_t *
-wc_status_unserialize(svn_wc_status3_t *status,
- svn_stream_t *stream,
- apr_pool_t *result_pool)
-{
- svn_stringbuf_t *sb;
- char *string;
-
- SVN_ERR(svn_stringbuf_from_stream(&sb, stream, 100, result_pool));
- string = sb->data;
- status->kind = char_to_kind(string[0]);
- status->node_status = char_to_status(string[2]);
- status->text_status = char_to_status(string[3]);
- status->prop_status = char_to_status(string[4]);
- sscanf(string + 6, "%ld", &status->revision);
- return SVN_NO_ERROR;
-}
-
-/* Write status to shelf storage.
- */
-static svn_error_t *
-status_write(svn_client__shelf_version_t *shelf_version,
- const char *relpath,
- const svn_wc_status3_t *status,
- apr_pool_t *scratch_pool)
-{
- char *file_abspath;
- svn_stream_t *stream;
-
- SVN_ERR(get_metadata_abspath(&file_abspath, shelf_version, relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_open_writable(&stream, file_abspath,
- scratch_pool, scratch_pool));
- SVN_ERR(wc_status_serialize(stream, status, scratch_pool));
- SVN_ERR(svn_stream_close(stream));
+status_augment(svn_wc_status3_t **status_p,
+ const svn_wc_status3_t *status_in,
+ svn_client__shelf_version_t *shelf_version,
+ apr_pool_t *result_pool)
+{
+ *status_p = svn_wc_dup_status3(status_in, result_pool);
+ (*status_p)->changelist = apr_psprintf(result_pool, "svn:shelf:%s",
+ shelf_version->shelf->name);
return SVN_NO_ERROR;
}
@@ -572,68 +383,57 @@ status_read(svn_wc_status3_t **status,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_wc_status3_t *s = status_create(result_pool);
- char *file_abspath;
- svn_stream_t *stream;
-
- SVN_ERR(get_metadata_abspath(&file_abspath, shelf_version, relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_open_readonly(&stream, file_abspath,
- scratch_pool, scratch_pool));
- SVN_ERR(wc_status_unserialize(s, stream, result_pool));
- SVN_ERR(svn_stream_close(stream));
-
- s->changelist = apr_psprintf(result_pool, "svn:shelf:%s",
- shelf_version->shelf->name);
- *status = s;
+ svn_client_ctx_t *ctx = shelf_version->shelf->ctx;
+ char *abspath
+ = svn_dirent_join(shelf_version->files_dir_abspath, relpath,
+ scratch_pool);
+
+ SVN_ERR(svn_wc_status3(status, ctx->wc_ctx, abspath,
+ result_pool, scratch_pool));
+ SVN_ERR(status_augment(status, *status, shelf_version, result_pool));
return SVN_NO_ERROR;
}
/* A visitor function type for use with shelf_status_walk().
* The same as svn_wc_status_func4_t except relpath instead of abspath.
- * Only some fields in STATUS are available.
*/
typedef svn_error_t *(*shelf_status_visitor_t)(void *baton,
const char *relpath,
- svn_wc_status3_t *status,
+ const svn_wc_status3_t *status,
apr_pool_t *scratch_pool);
/* Baton for shelved_files_walk_visitor(). */
struct shelf_status_baton_t
{
svn_client__shelf_version_t *shelf_version;
- const char *top_relpath;
- const char *walk_root_abspath;
shelf_status_visitor_t walk_func;
void *walk_baton;
};
-/* Call BATON->walk_func(BATON->walk_baton, relpath, ...) for the shelved
- * 'binary' file stored at ABSPATH.
- * Implements svn_io_walk_func_t. */
+/* Convert a svn_wc_status_func4_t callback invocation to call a
+ * shelf_status_visitor_t callback.
+ *
+ * Call BATON->walk_func(BATON->walk_baton, relpath, ...) for the shelved
+ * storage path ABSPATH, converting ABSPATH to a WC-relative path, and
+ * augmenting the STATUS.
+ *
+ * The opposite of wc_status_visitor().
+ *
+ * Implements svn_wc_status_func4_t. */
static svn_error_t *
shelf_status_visitor(void *baton,
const char *abspath,
- const apr_finfo_t *finfo,
+ const svn_wc_status3_t *status,
apr_pool_t *scratch_pool)
{
struct shelf_status_baton_t *b = baton;
const char *relpath;
+ svn_wc_status3_t *new_status;
- relpath = svn_dirent_skip_ancestor(b->walk_root_abspath, abspath);
- if (finfo->filetype == APR_REG
- && (strlen(relpath) >= 5 && strcmp(relpath+strlen(relpath)-5, ".meta") == 0))
- {
- svn_wc_status3_t *s;
-
- relpath = apr_pstrndup(scratch_pool, relpath, strlen(relpath) - 5);
- if (!svn_relpath_skip_ancestor(b->top_relpath, relpath))
- return SVN_NO_ERROR;
-
- SVN_ERR(status_read(&s, b->shelf_version, relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(b->walk_func(b->walk_baton, relpath, s, scratch_pool));
- }
+ relpath = svn_dirent_skip_ancestor(b->shelf_version->files_dir_abspath,
+ abspath);
+ SVN_ERR(status_augment(&new_status, status, b->shelf_version, scratch_pool));
+ SVN_ERR(b->walk_func(b->walk_baton, relpath, new_status, scratch_pool));
return SVN_NO_ERROR;
}
@@ -647,24 +447,16 @@ shelf_status_visit_path(svn_client__shel
void *walk_baton,
apr_pool_t *scratch_pool)
{
- struct shelf_status_baton_t baton;
- char *abspath;
- apr_finfo_t finfo;
+ svn_wc_status3_t *status;
- baton.shelf_version = shelf_version;
- baton.top_relpath = wc_relpath;
- baton.walk_root_abspath = shelf_version->files_dir_abspath;
- baton.walk_func = walk_func;
- baton.walk_baton = walk_baton;
- SVN_ERR(get_metadata_abspath(&abspath, shelf_version, wc_relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_io_stat(&finfo, abspath, APR_FINFO_TYPE, scratch_pool));
- SVN_ERR(shelf_status_visitor(&baton, abspath, &finfo, scratch_pool));
+ SVN_ERR(status_read(&status, shelf_version, wc_relpath,
+ scratch_pool, scratch_pool));
+ SVN_ERR(walk_func(walk_baton, wc_relpath, status, scratch_pool));
return SVN_NO_ERROR;
}
/* Report the shelved status of all the shelved paths in SHELF_VERSION
- * via WALK_FUNC(WALK_BATON, ...).
+ * at and under WC_RELPATH, via WALK_FUNC(WALK_BATON, ...).
*/
static svn_error_t *
shelf_status_walk(svn_client__shelf_version_t *shelf_version,
@@ -673,17 +465,25 @@ shelf_status_walk(svn_client__shelf_vers
void *walk_baton,
apr_pool_t *scratch_pool)
{
+ svn_client_ctx_t *ctx = shelf_version->shelf->ctx;
+ char *walk_root_abspath
+ = svn_dirent_join(shelf_version->files_dir_abspath, wc_relpath,
+ scratch_pool);
struct shelf_status_baton_t baton;
svn_error_t *err;
baton.shelf_version = shelf_version;
- baton.top_relpath = wc_relpath;
- baton.walk_root_abspath = shelf_version->files_dir_abspath;
baton.walk_func = walk_func;
baton.walk_baton = walk_baton;
- err = svn_io_dir_walk2(baton.walk_root_abspath, 0 /*wanted*/,
- shelf_status_visitor, &baton,
- scratch_pool);
+ err = svn_wc_walk_status(ctx->wc_ctx, walk_root_abspath,
+ svn_depth_infinity,
+ FALSE /*get_all*/,
+ TRUE /*no_ignore*/,
+ FALSE /*ignore_text_mods*/,
+ NULL /*ignore_patterns: use the defaults*/,
+ shelf_status_visitor, &baton,
+ NULL, NULL, /*cancellation*/
+ scratch_pool);
if (err && APR_STATUS_IS_ENOENT(err->apr_err))
svn_error_clear(err);
else
@@ -692,6 +492,7 @@ shelf_status_walk(svn_client__shelf_vers
return SVN_NO_ERROR;
}
+/* Baton for wc_status_visitor(). */
typedef struct wc_status_baton_t
{
svn_client__shelf_version_t *shelf_version;
@@ -699,11 +500,20 @@ typedef struct wc_status_baton_t
void *walk_baton;
} wc_status_baton_t;
+/* Convert a shelf_status_visitor_t callback invocation to call a
+ * svn_wc_status_func4_t callback.
+ *
+ * Call BATON->walk_func(BATON->walk_baton, abspath, ...) for the WC-
+ * relative path RELPATH, converting RELPATH to an abspath in the user's WC.
+ *
+ * The opposite of shelf_status_visitor().
+ *
+ * Implements shelf_status_visitor_t. */
static svn_error_t *
wc_status_visitor(void *baton,
- const char *relpath,
- svn_wc_status3_t *status,
- apr_pool_t *scratch_pool)
+ const char *relpath,
+ const svn_wc_status3_t *status,
+ apr_pool_t *scratch_pool)
{
struct wc_status_baton_t *b = baton;
svn_client__shelf_t *shelf = b->shelf_version->shelf;
@@ -734,431 +544,6 @@ svn_client__shelf_version_status_walk(sv
/*-------------------------------------------------------------------------*/
/* Shelf Storage */
-/* A baton for use with write_changes_visitor(). */
-typedef struct write_changes_baton_t {
- const char *wc_root_abspath;
- svn_client__shelf_version_t *shelf_version;
- svn_client_ctx_t *ctx;
- svn_boolean_t any_shelved; /* were any paths successfully shelved? */
- svn_client_status_func_t was_shelved_func;
- void *was_shelved_baton;
- svn_client_status_func_t was_not_shelved_func;
- void *was_not_shelved_baton;
- apr_pool_t *pool; /* pool for data in 'unshelvable', etc. */
-} write_changes_baton_t;
-
-/* */
-static svn_error_t *
-notify_shelved(write_changes_baton_t *wb,
- const char *wc_relpath,
- const char *local_abspath,
- const svn_wc_status3_t *wc_status,
- apr_pool_t *scratch_pool)
-{
- if (wb->was_shelved_func)
- {
- svn_client_status_t *cst;
-
- SVN_ERR(svn_client__create_status(&cst, wb->ctx->wc_ctx, local_abspath,
- wc_status,
- scratch_pool, scratch_pool));
- SVN_ERR(wb->was_shelved_func(wb->was_shelved_baton,
- wc_relpath, cst, scratch_pool));
- }
-
- wb->any_shelved = TRUE;
- return SVN_NO_ERROR;
-}
-
-/* */
-static svn_error_t *
-notify_not_shelved(write_changes_baton_t *wb,
- const char *wc_relpath,
- const char *local_abspath,
- const svn_wc_status3_t *wc_status,
- apr_pool_t *scratch_pool)
-{
- if (wb->was_not_shelved_func)
- {
- svn_client_status_t *cst;
-
- SVN_ERR(svn_client__create_status(&cst, wb->ctx->wc_ctx, local_abspath,
- wc_status,
- scratch_pool, scratch_pool));
- SVN_ERR(wb->was_not_shelved_func(wb->was_not_shelved_baton,
- wc_relpath, cst, scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Read BASE_PROPS and WORK_PROPS from the WC, setting each to null if
- * the node has no base or working version (respectively).
- */
-static svn_error_t *
-read_props_from_wc(apr_hash_t **base_props,
- apr_hash_t **work_props,
- enum svn_wc_status_kind node_status,
- const char *from_wc_abspath,
- svn_client_ctx_t *ctx,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- if (node_status != svn_wc_status_added)
- SVN_ERR(svn_wc_get_pristine_props(base_props, ctx->wc_ctx, from_wc_abspath,
- result_pool, scratch_pool));
- else
- *base_props = NULL;
- if (node_status != svn_wc_status_deleted)
- SVN_ERR(svn_wc_prop_list2(work_props, ctx->wc_ctx, from_wc_abspath,
- result_pool, scratch_pool));
- else
- *work_props = NULL;
- return SVN_NO_ERROR;
-}
-
-/* Write BASE_PROPS and WORK_PROPS to storage in SHELF_VERSION:WC_RELPATH.
- */
-static svn_error_t *
-write_props_to_shelf(svn_client__shelf_version_t *shelf_version,
- const char *wc_relpath,
- apr_hash_t *base_props,
- apr_hash_t *work_props,
- apr_pool_t *scratch_pool)
-{
- char *stored_props_abspath;
- svn_stream_t *stream;
-
- if (base_props)
- {
- SVN_ERR(get_base_props_abspath(&stored_props_abspath,
- shelf_version, wc_relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_open_writable(&stream, stored_props_abspath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_hash_write2(base_props, stream, NULL, scratch_pool));
- SVN_ERR(svn_stream_close(stream));
- }
-
- if (work_props)
- {
- SVN_ERR(get_working_props_abspath(&stored_props_abspath,
- shelf_version, wc_relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_open_writable(&stream, stored_props_abspath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_hash_write2(work_props, stream, NULL, scratch_pool));
- SVN_ERR(svn_stream_close(stream));
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Read BASE_PROPS and WORK_PROPS from storage in SHELF_VERSION:WC_RELPATH.
- */
-static svn_error_t *
-read_props_from_shelf(apr_hash_t **base_props,
- apr_hash_t **work_props,
- enum svn_wc_status_kind node_status,
- svn_client__shelf_version_t *shelf_version,
- const char *wc_relpath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- char *stored_props_abspath;
- svn_stream_t *stream;
-
- if (node_status != svn_wc_status_added)
- {
- *base_props = apr_hash_make(result_pool);
- SVN_ERR(get_base_props_abspath(&stored_props_abspath,
- shelf_version, wc_relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_open_readonly(&stream, stored_props_abspath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_hash_read2(*base_props, stream, NULL, scratch_pool));
- SVN_ERR(svn_stream_close(stream));
- }
- else
- *base_props = NULL;
-
- if (node_status != svn_wc_status_deleted)
- {
- *work_props = apr_hash_make(result_pool);
- SVN_ERR(get_working_props_abspath(&stored_props_abspath,
- shelf_version, wc_relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_open_readonly(&stream, stored_props_abspath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_hash_read2(*work_props, stream, NULL, scratch_pool));
- SVN_ERR(svn_stream_close(stream));
- }
- else
- *work_props = NULL;
-
- return SVN_NO_ERROR;
-}
-
-/* Store metadata for any node, and base and working files if it's a file.
- *
- * Copy the WC base and working files at FROM_WC_ABSPATH to the storage
- * area in SHELF_VERSION.
- */
-static svn_error_t *
-store_file(const char *from_wc_abspath,
- const char *wc_relpath,
- svn_client__shelf_version_t *shelf_version,
- const svn_wc_status3_t *status,
- svn_client_ctx_t *ctx,
- apr_pool_t *scratch_pool)
-{
- char *stored_abspath;
- apr_hash_t *base_props, *work_props;
-
- SVN_ERR(get_working_file_abspath(&stored_abspath,
- shelf_version, wc_relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_io_make_dir_recursively(svn_dirent_dirname(stored_abspath,
- scratch_pool),
- scratch_pool));
- SVN_ERR(status_write(shelf_version, wc_relpath,
- status, scratch_pool));
-
- /* properties */
- SVN_ERR(read_props_from_wc(&base_props, &work_props,
- status->node_status,
- from_wc_abspath, ctx,
- scratch_pool, scratch_pool));
- SVN_ERR(write_props_to_shelf(shelf_version, wc_relpath,
- base_props, work_props,
- scratch_pool));
-
- /* file text */
- if (status->kind == svn_node_file)
- {
- svn_stream_t *wc_base_stream;
- svn_node_kind_t work_kind;
-
- /* Copy the base file (copy-from base, if copied/moved), if present */
- SVN_ERR(svn_wc_get_pristine_contents2(&wc_base_stream,
- ctx->wc_ctx, from_wc_abspath,
- scratch_pool, scratch_pool));
- if (wc_base_stream)
- {
- char *stored_base_abspath;
- svn_stream_t *stored_base_stream;
-
- SVN_ERR(get_base_file_abspath(&stored_base_abspath,
- shelf_version, wc_relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_open_writable(&stored_base_stream,
- stored_base_abspath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_copy3(wc_base_stream, stored_base_stream,
- NULL, NULL, scratch_pool));
- }
-
- /* Copy the working file, if present */
- SVN_ERR(svn_io_check_path(from_wc_abspath, &work_kind, scratch_pool));
- if (work_kind == svn_node_file)
- {
- SVN_ERR(svn_io_copy_file(from_wc_abspath, stored_abspath,
- TRUE /*copy_perms*/, scratch_pool));
- }
- }
- return SVN_NO_ERROR;
-}
-
-/* An implementation of svn_wc_status_func4_t. */
-static svn_error_t *
-write_changes_visitor(void *baton,
- const char *local_abspath,
- const svn_wc_status3_t *status,
- apr_pool_t *scratch_pool)
-{
- write_changes_baton_t *wb = baton;
- const char *wc_relpath = svn_dirent_skip_ancestor(wb->wc_root_abspath,
- local_abspath);
-
- /* Catch any conflict, even a tree conflict on a path that has
- node-status 'unversioned'. */
- if (status->conflicted)
- {
- SVN_ERR(notify_not_shelved(wb, wc_relpath, local_abspath,
- status, scratch_pool));
- }
- else switch (status->node_status)
- {
- case svn_wc_status_deleted:
- case svn_wc_status_added:
- case svn_wc_status_replaced:
- if (status->kind != svn_node_file
- || status->copied)
- {
- SVN_ERR(notify_not_shelved(wb, wc_relpath, local_abspath,
- status, scratch_pool));
- break;
- }
- /* fall through */
- case svn_wc_status_modified:
- {
- /* Store metadata, and base and working versions if it's a file */
- SVN_ERR(store_file(local_abspath, wc_relpath, wb->shelf_version,
- status, wb->ctx, scratch_pool));
- SVN_ERR(notify_shelved(wb, wc_relpath, local_abspath,
- status, scratch_pool));
- break;
- }
-
- case svn_wc_status_incomplete:
- if ((status->text_status != svn_wc_status_normal
- && status->text_status != svn_wc_status_none)
- || (status->prop_status != svn_wc_status_normal
- && status->prop_status != svn_wc_status_none))
- {
- /* Incomplete, but local modifications */
- SVN_ERR(notify_not_shelved(wb, wc_relpath, local_abspath,
- status, scratch_pool));
- }
- break;
-
- case svn_wc_status_conflicted:
- case svn_wc_status_missing:
- case svn_wc_status_obstructed:
- SVN_ERR(notify_not_shelved(wb, wc_relpath, local_abspath,
- status, scratch_pool));
- break;
-
- case svn_wc_status_normal:
- case svn_wc_status_ignored:
- case svn_wc_status_none:
- case svn_wc_status_external:
- case svn_wc_status_unversioned:
- default:
- break;
- }
-
- return SVN_NO_ERROR;
-}
-
-/* A baton for use with changelist_filter_func(). */
-struct changelist_filter_baton_t {
- apr_hash_t *changelist_hash;
- svn_wc_status_func4_t status_func;
- void *status_baton;
-};
-
-/* Filter out paths that are not in the requested changelist(s).
- * Implements svn_wc_status_func4_t. */
-static svn_error_t *
-changelist_filter_func(void *baton,
- const char *local_abspath,
- const svn_wc_status3_t *status,
- apr_pool_t *scratch_pool)
-{
- struct changelist_filter_baton_t *b = baton;
-
- if (b->changelist_hash
- && (! status->changelist
- || ! svn_hash_gets(b->changelist_hash, status->changelist)))
- {
- return SVN_NO_ERROR;
- }
-
- SVN_ERR(b->status_func(b->status_baton, local_abspath, status,
- scratch_pool));
- return SVN_NO_ERROR;
-}
-
-/*
- * Walk the WC tree(s) rooted at PATHS, to depth DEPTH, omitting paths that
- * are not in one of the CHANGELISTS (if not null).
- *
- * Call STATUS_FUNC(STATUS_BATON, ...) for each visited path.
- *
- * PATHS are absolute, or relative to CWD.
- */
-static svn_error_t *
-wc_walk_status_multi(const apr_array_header_t *paths,
- svn_depth_t depth,
- const apr_array_header_t *changelists,
- svn_wc_status_func4_t status_func,
- void *status_baton,
- svn_client_ctx_t *ctx,
- apr_pool_t *scratch_pool)
-{
- struct changelist_filter_baton_t cb = {0};
- int i;
-
- if (changelists && changelists->nelts)
- SVN_ERR(svn_hash_from_cstring_keys(&cb.changelist_hash,
- changelists, scratch_pool));
- cb.status_func = status_func;
- cb.status_baton = status_baton;
-
- for (i = 0; i < paths->nelts; i++)
- {
- const char *path = APR_ARRAY_IDX(paths, i, const char *);
-
- if (svn_path_is_url(path))
- return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
- _("'%s' is not a local path"), path);
- SVN_ERR(svn_dirent_get_absolute(&path, path, scratch_pool));
-
- SVN_ERR(svn_wc_walk_status(ctx->wc_ctx, path, depth,
- FALSE /*get_all*/, FALSE /*no_ignore*/,
- FALSE /*ignore_text_mods*/,
- NULL /*ignore_patterns*/,
- changelist_filter_func, &cb,
- ctx->cancel_func, ctx->cancel_baton,
- scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-/** Write local changes to the shelf storage.
- *
- * @a paths, @a depth, @a changelists: The selection of local paths to diff.
- *
- * @a paths are relative to CWD (or absolute).
- */
-static svn_error_t *
-shelf_write_changes(svn_boolean_t *any_shelved,
- svn_client__shelf_version_t *shelf_version,
- const apr_array_header_t *paths,
- svn_depth_t depth,
- const apr_array_header_t *changelists,
- svn_client_status_func_t shelved_func,
- void *shelved_baton,
- svn_client_status_func_t not_shelved_func,
- void *not_shelved_baton,
- const char *wc_root_abspath,
- svn_client_ctx_t *ctx,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- write_changes_baton_t wb = { 0 };
-
- wb.wc_root_abspath = wc_root_abspath;
- wb.shelf_version = shelf_version;
- wb.ctx = ctx;
- wb.any_shelved = FALSE;
- wb.was_shelved_func = shelved_func;
- wb.was_shelved_baton = shelved_baton;
- wb.was_not_shelved_func = not_shelved_func;
- wb.was_not_shelved_baton = not_shelved_baton;
- wb.pool = result_pool;
-
- /* Walk the WC */
- SVN_ERR(wc_walk_status_multi(paths, depth, changelists,
- write_changes_visitor, &wb,
- ctx, scratch_pool));
-
- *any_shelved = wb.any_shelved;
- return SVN_NO_ERROR;
-}
-
/* Construct a shelf object representing an empty shelf: no versions,
* no revprops, no looking to see if such a shelf exists on disk.
*/
@@ -1175,9 +560,8 @@ shelf_construct(svn_client__shelf_t **sh
SVN_ERR(svn_client_get_wc_root(&shelf->wc_root_abspath,
local_abspath, ctx,
result_pool, result_pool));
- SVN_ERR(svn_wc__get_shelves_dir(&shelves_dir,
- ctx->wc_ctx, local_abspath,
- result_pool, result_pool));
+ SVN_ERR(get_shelves_dir(&shelves_dir, ctx->wc_ctx, local_abspath,
+ result_pool, result_pool));
shelf->shelves_dir = shelves_dir;
shelf->ctx = ctx;
shelf->pool = result_pool;
@@ -1273,7 +657,6 @@ svn_client__shelf_delete(const char *nam
struct paths_changed_walk_baton_t
{
apr_hash_t *paths_hash;
- svn_boolean_t as_abspath;
const char *wc_root_abspath;
apr_pool_t *pool;
};
@@ -1283,14 +666,12 @@ struct paths_changed_walk_baton_t
static svn_error_t *
paths_changed_visitor(void *baton,
const char *relpath,
- svn_wc_status3_t *s,
+ const svn_wc_status3_t *s,
apr_pool_t *scratch_pool)
{
struct paths_changed_walk_baton_t *b = baton;
- relpath = (b->as_abspath
- ? svn_dirent_join(b->wc_root_abspath, relpath, b->pool)
- : apr_pstrdup(b->pool, relpath));
+ relpath = apr_pstrdup(b->pool, relpath);
svn_hash_sets(b->paths_hash, relpath, relpath);
return SVN_NO_ERROR;
}
@@ -1302,7 +683,6 @@ static svn_error_t *
shelf_paths_changed(apr_hash_t **paths_hash_p,
apr_array_header_t **paths_array_p,
svn_client__shelf_version_t *shelf_version,
- svn_boolean_t as_abspath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -1311,7 +691,6 @@ shelf_paths_changed(apr_hash_t **paths_h
struct paths_changed_walk_baton_t baton;
baton.paths_hash = paths_hash;
- baton.as_abspath = as_abspath;
baton.wc_root_abspath = shelf->wc_root_abspath;
baton.pool = result_pool;
SVN_ERR(shelf_status_walk(shelf_version, "",
@@ -1333,546 +712,243 @@ svn_client__shelf_paths_changed(apr_hash
apr_pool_t *scratch_pool)
{
SVN_ERR(shelf_paths_changed(affected_paths, NULL, shelf_version,
- FALSE /*as_abspath*/,
result_pool, scratch_pool));
return SVN_NO_ERROR;
}
-/* Send a notification */
-static svn_error_t *
-send_notification(const char *local_abspath,
- svn_wc_notify_action_t action,
- svn_node_kind_t kind,
- svn_wc_notify_state_t content_state,
- svn_wc_notify_state_t prop_state,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_pool_t *scratch_pool)
-{
- if (notify_func)
- {
- svn_wc_notify_t *notify
- = svn_wc_create_notify(local_abspath, action, scratch_pool);
-
- notify->kind = kind;
- notify->content_state = content_state;
- notify->prop_state = prop_state;
- notify_func(notify_baton, notify, scratch_pool);
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Merge a shelved change into WC_ABSPATH.
- */
-static svn_error_t *
-wc_file_merge(const char *wc_abspath,
- const char *left_file,
- const char *right_file,
- /*const*/ apr_hash_t *left_props,
- /*const*/ apr_hash_t *right_props,
- svn_client_ctx_t *ctx,
- apr_pool_t *scratch_pool)
-{
- svn_wc_notify_state_t property_state;
- svn_boolean_t has_local_mods;
- enum svn_wc_merge_outcome_t content_outcome;
- const char *target_label, *left_label, *right_label;
- apr_array_header_t *prop_changes;
-
- /* xgettext: the '.working', '.merge-left' and '.merge-right' strings
- are used to tag onto a file name in case of a merge conflict */
- target_label = apr_psprintf(scratch_pool, _(".working"));
- left_label = apr_psprintf(scratch_pool, _(".merge-left"));
- right_label = apr_psprintf(scratch_pool, _(".merge-right"));
-
- SVN_ERR(svn_prop_diffs(&prop_changes, right_props, left_props, scratch_pool));
- SVN_ERR(svn_wc_text_modified_p2(&has_local_mods, ctx->wc_ctx,
- wc_abspath, FALSE, scratch_pool));
-
- /* Do property merge and text merge in one step so that keyword expansion
- takes into account the new property values. */
- SVN_WC__CALL_WITH_WRITE_LOCK(
- svn_wc_merge5(&content_outcome, &property_state, ctx->wc_ctx,
- left_file, right_file, wc_abspath,
- left_label, right_label, target_label,
- NULL, NULL, /*left, right conflict-versions*/
- FALSE /*dry_run*/, NULL /*diff3_cmd*/,
- NULL /*merge_options*/,
- left_props, prop_changes,
- NULL, NULL,
- ctx->cancel_func, ctx->cancel_baton,
- scratch_pool),
- ctx->wc_ctx, wc_abspath,
- FALSE /*lock_anchor*/, scratch_pool);
-
- return SVN_NO_ERROR;
-}
-
-/* Merge a shelved change (of properties) into the dir at WC_ABSPATH.
- */
-static svn_error_t *
-wc_dir_props_merge(const char *wc_abspath,
- /*const*/ apr_hash_t *left_props,
- /*const*/ apr_hash_t *right_props,
- svn_client_ctx_t *ctx,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- apr_array_header_t *prop_changes;
- svn_wc_notify_state_t property_state;
-
- SVN_ERR(svn_prop_diffs(&prop_changes, right_props, left_props, scratch_pool));
- SVN_WC__CALL_WITH_WRITE_LOCK(
- svn_wc_merge_props3(&property_state, ctx->wc_ctx,
- wc_abspath,
- NULL, NULL, /*left, right conflict-versions*/
- left_props, prop_changes,
- FALSE /*dry_run*/,
- NULL, NULL,
- ctx->cancel_func, ctx->cancel_baton,
- scratch_pool),
- ctx->wc_ctx, wc_abspath,
- FALSE /*lock_anchor*/, scratch_pool);
-
- return SVN_NO_ERROR;
-}
-
-/* Apply a shelved "delete" to TO_WC_ABSPATH.
- */
-static svn_error_t *
-wc_node_delete(const char *to_wc_abspath,
- svn_client_ctx_t *ctx,
- apr_pool_t *scratch_pool)
-{
- SVN_WC__CALL_WITH_WRITE_LOCK(
- svn_wc_delete4(ctx->wc_ctx,
- to_wc_abspath,
- FALSE /*keep_local*/,
- TRUE /*delete_unversioned_target*/,
- NULL, NULL, NULL, NULL, /*cancel, notify*/
- scratch_pool),
- ctx->wc_ctx, to_wc_abspath,
- TRUE /*lock_anchor*/, scratch_pool);
- return SVN_NO_ERROR;
-}
-
-/* Apply a shelved "add" to TO_WC_ABSPATH.
- * The node must already exist on disk, in a versioned parent dir.
- */
-static svn_error_t *
-wc_node_add(const char *to_wc_abspath,
- apr_hash_t *work_props,
- svn_client_ctx_t *ctx,
- apr_pool_t *scratch_pool)
+svn_error_t *
+svn_client__shelf_replay(svn_client__shelf_version_t *shelf_version,
+ const char *top_relpath,
+ const svn_delta_editor_t *editor,
+ void *edit_baton,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ apr_pool_t *scratch_pool)
{
- /* If it was not already versioned, schedule the node for addition.
- (Do not apply autoprops, because this isn't a user-facing "add" but
- restoring a previously saved state.) */
- SVN_WC__CALL_WITH_WRITE_LOCK(
- svn_wc_add_from_disk3(ctx->wc_ctx,
- to_wc_abspath, work_props,
- FALSE /* skip checks */,
- NULL, NULL, scratch_pool),
- ctx->wc_ctx, to_wc_abspath,
- TRUE /*lock_anchor*/, scratch_pool);
+ svn_client_ctx_t *ctx = shelf_version->shelf->ctx;
+ apr_array_header_t *src_targets = apr_array_make(scratch_pool, 1,
+ sizeof(char *));
+ const char *src_wc_abspath
+ = svn_dirent_join(shelf_version->files_dir_abspath, top_relpath, scratch_pool);
+
+ APR_ARRAY_PUSH(src_targets, const char *) = src_wc_abspath;
+ SVN_ERR(svn_client__wc_replay(src_wc_abspath,
+ src_targets, svn_depth_infinity, NULL,
+ editor, edit_baton,
+ notify_func, notify_baton,
+ ctx, scratch_pool));
return SVN_NO_ERROR;
}
-/* Baton for apply_file_visitor(). */
-struct apply_files_baton_t
+/* Baton for test_apply_file_visitor(). */
+struct test_apply_files_baton_t
{
svn_client__shelf_version_t *shelf_version;
- svn_boolean_t test_only; /* only check whether it would conflict */
svn_boolean_t conflict; /* would it conflict? */
svn_client_ctx_t *ctx;
};
-/* Copy the file RELPATH from shelf binary file storage to the WC.
- *
- * If it is not already versioned, schedule the file for addition.
- *
- * Make any missing parent directories.
- *
- * In test mode (BATON->test_only): set BATON->conflict if we can't apply
- * the change to WC at RELPATH without conflict. But in fact, just check
+/* Ideally, set BATON->conflict if we can't apply a change to WC
+ * at RELPATH without conflict. But in fact, just check
* if WC at RELPATH is locally modified.
*
* Implements shelved_files_walk_func_t. */
static svn_error_t *
-apply_file_visitor(void *baton,
- const char *relpath,
- svn_wc_status3_t *s,
- apr_pool_t *scratch_pool)
+test_apply_file_visitor(void *baton,
+ const char *relpath,
+ const svn_wc_status3_t *s,
+ apr_pool_t *scratch_pool)
{
- struct apply_files_baton_t *b = baton;
+ struct test_apply_files_baton_t *b = baton;
const char *wc_root_abspath = b->shelf_version->shelf->wc_root_abspath;
- char *stored_base_abspath, *stored_work_abspath;
- apr_hash_t *base_props, *work_props;
const char *to_wc_abspath = svn_dirent_join(wc_root_abspath, relpath,
scratch_pool);
- const char *to_dir_abspath = svn_dirent_dirname(to_wc_abspath, scratch_pool);
-
- SVN_ERR(get_base_file_abspath(&stored_base_abspath,
- b->shelf_version, relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(get_working_file_abspath(&stored_work_abspath,
- b->shelf_version, relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(read_props_from_shelf(&base_props, &work_props,
- s->node_status,
- b->shelf_version, relpath,
- scratch_pool, scratch_pool));
-
- if (b->test_only)
- {
- svn_wc_status3_t *status;
-
- SVN_ERR(svn_wc_status3(&status, b->ctx->wc_ctx, to_wc_abspath,
- scratch_pool, scratch_pool));
- switch (status->node_status)
- {
- case svn_wc_status_normal:
- case svn_wc_status_none:
- break;
- default:
- b->conflict = TRUE;
- }
-
- return SVN_NO_ERROR;
- }
-
- /* Handle 'delete' and the delete half of 'replace' */
- if (s->node_status == svn_wc_status_deleted
- || s->node_status == svn_wc_status_replaced)
- {
- SVN_ERR(wc_node_delete(to_wc_abspath, b->ctx, scratch_pool));
- if (s->node_status != svn_wc_status_replaced)
- {
- SVN_ERR(send_notification(to_wc_abspath, svn_wc_notify_update_delete,
- s->kind,
- svn_wc_notify_state_inapplicable,
- svn_wc_notify_state_inapplicable,
- b->ctx->notify_func2, b->ctx->notify_baton2,
- scratch_pool));
- }
- }
-
- /* If we can merge a file, do so. */
- if (s->node_status == svn_wc_status_modified)
- {
- if (s->kind == svn_node_dir)
- {
- SVN_ERR(wc_dir_props_merge(to_wc_abspath,
- base_props, work_props,
- b->ctx, scratch_pool, scratch_pool));
- }
- else if (s->kind == svn_node_file)
- {
- SVN_ERR(wc_file_merge(to_wc_abspath,
- stored_base_abspath, stored_work_abspath,
- base_props, work_props,
- b->ctx, scratch_pool));
- }
- SVN_ERR(send_notification(to_wc_abspath, svn_wc_notify_update_update,
- s->kind,
- (s->kind == svn_node_dir)
- ? svn_wc_notify_state_inapplicable
- : svn_wc_notify_state_merged,
- (s->kind == svn_node_dir)
- ? svn_wc_notify_state_merged
- : svn_wc_notify_state_unknown,
- b->ctx->notify_func2, b->ctx->notify_baton2,
- scratch_pool));
- }
-
- /* For an added file, copy it into the WC and ensure it's versioned. */
- if (s->node_status == svn_wc_status_added
- || s->node_status == svn_wc_status_replaced)
- {
- if (s->kind == svn_node_dir)
- {
- SVN_ERR(svn_io_make_dir_recursively(to_wc_abspath, scratch_pool));
- }
- else if (s->kind == svn_node_file)
- {
- SVN_ERR(svn_io_make_dir_recursively(to_dir_abspath, scratch_pool));
- SVN_ERR(svn_io_copy_file(stored_work_abspath, to_wc_abspath,
- TRUE /*copy_perms*/, scratch_pool));
- }
- SVN_ERR(wc_node_add(to_wc_abspath, work_props, b->ctx, scratch_pool));
- SVN_ERR(send_notification(to_wc_abspath,
- (s->node_status == svn_wc_status_replaced)
- ? svn_wc_notify_update_replace
- : svn_wc_notify_update_add,
- s->kind,
- svn_wc_notify_state_inapplicable,
- svn_wc_notify_state_inapplicable,
- b->ctx->notify_func2, b->ctx->notify_baton2,
- scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-/*-------------------------------------------------------------------------*/
-/* Diff */
-
-/* */
-static svn_error_t *
-file_changed(svn_client__shelf_version_t *shelf_version,
- const char *relpath,
- svn_wc_status3_t *s,
- const svn_diff_tree_processor_t *diff_processor,
- svn_diff_source_t *left_source,
- svn_diff_source_t *right_source,
- const char *left_stored_abspath,
- const char *right_stored_abspath,
- void *dir_baton,
- apr_pool_t *scratch_pool)
-{
- void *fb;
- svn_boolean_t skip = FALSE;
-
- SVN_ERR(diff_processor->file_opened(&fb, &skip, relpath,
- left_source, right_source,
- NULL /*copyfrom*/,
- dir_baton, diff_processor,
- scratch_pool, scratch_pool));
- if (!skip)
- {
- apr_hash_t *left_props, *right_props;
- apr_array_header_t *prop_changes;
+ svn_wc_status3_t *status;
- SVN_ERR(read_props_from_shelf(&left_props, &right_props,
- s->node_status, shelf_version, relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_prop_diffs(&prop_changes, right_props, left_props,
- scratch_pool));
- SVN_ERR(diff_processor->file_changed(
- relpath,
- left_source, right_source,
- left_stored_abspath, right_stored_abspath,
- left_props, right_props,
- TRUE /*file_modified*/, prop_changes,
- fb, diff_processor, scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-/* */
-static svn_error_t *
-file_deleted(svn_client__shelf_version_t *shelf_version,
- const char *relpath,
- svn_wc_status3_t *s,
- const svn_diff_tree_processor_t *diff_processor,
- svn_diff_source_t *left_source,
- const char *left_stored_abspath,
- void *dir_baton,
- apr_pool_t *scratch_pool)
-{
- void *fb;
- svn_boolean_t skip = FALSE;
-
- SVN_ERR(diff_processor->file_opened(&fb, &skip, relpath,
- left_source, NULL, NULL /*copyfrom*/,
- dir_baton, diff_processor,
- scratch_pool, scratch_pool));
- if (!skip)
- {
- apr_hash_t *left_props, *right_props;
-
- SVN_ERR(read_props_from_shelf(&left_props, &right_props,
- s->node_status, shelf_version, relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(diff_processor->file_deleted(relpath,
- left_source,
- left_stored_abspath,
- left_props,
- fb, diff_processor,
- scratch_pool));
+ SVN_ERR(svn_wc_status3(&status, b->ctx->wc_ctx, to_wc_abspath,
+ scratch_pool, scratch_pool));
+ switch (status->node_status)
+ {
+ case svn_wc_status_normal:
+ case svn_wc_status_none:
+ break;
+ default:
+ b->conflict = TRUE;
}
return SVN_NO_ERROR;
}
-/* */
-static svn_error_t *
-file_added(svn_client__shelf_version_t *shelf_version,
- const char *relpath,
- svn_wc_status3_t *s,
- const svn_diff_tree_processor_t *diff_processor,
- svn_diff_source_t *right_source,
- const char *right_stored_abspath,
- void *dir_baton,
- apr_pool_t *scratch_pool)
-{
- void *fb;
- svn_boolean_t skip = FALSE;
-
- SVN_ERR(diff_processor->file_opened(&fb, &skip, relpath,
- NULL, right_source, NULL /*copyfrom*/,
- dir_baton, diff_processor,
- scratch_pool, scratch_pool));
- if (!skip)
- {
- apr_hash_t *left_props, *right_props;
-
- SVN_ERR(read_props_from_shelf(&left_props, &right_props,
- s->node_status, shelf_version, relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(diff_processor->file_added(
- relpath,
- NULL /*copyfrom_source*/, right_source,
- NULL /*copyfrom_abspath*/, right_stored_abspath,
- NULL /*copyfrom_props*/, right_props,
- fb, diff_processor, scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Baton for diff_visitor(). */
-struct diff_baton_t
-{
- svn_client__shelf_version_t *shelf_version;
- const char *top_relpath; /* top of diff, relative to shelf */
- const char *walk_root_abspath;
- const svn_diff_tree_processor_t *diff_processor;
-};
-
-/* Drive BATON->diff_processor.
- * Implements svn_io_walk_func_t. */
-static svn_error_t *
-diff_visitor(void *baton,
- const char *abspath,
- const apr_finfo_t *finfo,
- apr_pool_t *scratch_pool)
-{
- struct diff_baton_t *b = baton;
- const char *relpath;
-
- relpath = svn_dirent_skip_ancestor(b->walk_root_abspath, abspath);
- if (finfo->filetype == APR_REG
- && (strlen(relpath) >= 5 && strcmp(relpath+strlen(relpath)-5, ".meta") == 0))
- {
- svn_wc_status3_t *s;
- void *db = NULL;
- svn_diff_source_t *left_source;
- svn_diff_source_t *right_source;
- char *left_stored_abspath, *right_stored_abspath;
-
- relpath = apr_pstrndup(scratch_pool, relpath, strlen(relpath) - 5);
- if (!svn_relpath_skip_ancestor(b->top_relpath, relpath))
- return SVN_NO_ERROR;
-
- SVN_ERR(status_read(&s, b->shelf_version, relpath,
- scratch_pool, scratch_pool));
-
- left_source = svn_diff__source_create(s->revision, scratch_pool);
- right_source = svn_diff__source_create(SVN_INVALID_REVNUM, scratch_pool);
- SVN_ERR(get_base_file_abspath(&left_stored_abspath,
- b->shelf_version, relpath,
- scratch_pool, scratch_pool));
- SVN_ERR(get_working_file_abspath(&right_stored_abspath,
- b->shelf_version, relpath,
- scratch_pool, scratch_pool));
-
- switch (s->node_status)
- {
- case svn_wc_status_modified:
- SVN_ERR(file_changed(b->shelf_version, relpath, s,
- b->diff_processor,
- left_source, right_source,
- left_stored_abspath, right_stored_abspath,
- db, scratch_pool));
- break;
- case svn_wc_status_added:
- SVN_ERR(file_added(b->shelf_version, relpath, s,
- b->diff_processor,
- right_source, right_stored_abspath,
- db, scratch_pool));
- break;
- case svn_wc_status_deleted:
- SVN_ERR(file_deleted(b->shelf_version, relpath, s,
- b->diff_processor,
- left_source, left_stored_abspath,
- db, scratch_pool));
- break;
- case svn_wc_status_replaced:
- SVN_ERR(file_deleted(b->shelf_version, relpath, s,
- b->diff_processor,
- left_source, left_stored_abspath,
- db, scratch_pool));
- SVN_ERR(file_added(b->shelf_version, relpath, s,
- b->diff_processor,
- right_source, right_stored_abspath,
- db, scratch_pool));
- default:
- break;
- }
- }
- return SVN_NO_ERROR;
-}
-
svn_error_t *
svn_client__shelf_test_apply_file(svn_boolean_t *conflict_p,
svn_client__shelf_version_t *shelf_version,
const char *file_relpath,
apr_pool_t *scratch_pool)
{
- struct apply_files_baton_t baton = {0};
+ struct test_apply_files_baton_t baton = {0};
baton.shelf_version = shelf_version;
- baton.test_only = TRUE;
baton.conflict = FALSE;
baton.ctx = shelf_version->shelf->ctx;
SVN_ERR(shelf_status_visit_path(shelf_version, file_relpath,
- apply_file_visitor, &baton,
+ test_apply_file_visitor, &baton,
scratch_pool));
*conflict_p = baton.conflict;
return SVN_NO_ERROR;
}
+static svn_error_t *
+wc_mods_editor(const svn_delta_editor_t **editor_p,
+ void **edit_baton_p,
+ const char *dst_wc_abspath,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_client__pathrev_t *base;
+ const char *dst_wc_url;
+ svn_ra_session_t *ra_session;
+
+ /* We'll need an RA session to obtain the base of any copies */
+ SVN_ERR(svn_client__wc_node_get_base(&base,
+ dst_wc_abspath, ctx->wc_ctx,
+ scratch_pool, scratch_pool));
+ dst_wc_url = base->url;
+ SVN_ERR(svn_client_open_ra_session2(&ra_session,
+ dst_wc_url, dst_wc_abspath,
+ ctx, result_pool, scratch_pool));
+ SVN_ERR(svn_client__wc_editor(editor_p, edit_baton_p,
+ dst_wc_abspath,
+ notify_func, notify_baton,
+ ra_session, ctx, result_pool));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client__shelf_mods_editor(const svn_delta_editor_t **editor_p,
+ void **edit_baton_p,
+ svn_client__shelf_version_t *shelf_version,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool)
+{
+ SVN_ERR(wc_mods_editor(editor_p, edit_baton_p,
+ shelf_version->files_dir_abspath,
+ notify_func, notify_baton,
+ ctx, result_pool, result_pool));
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_client__shelf_apply(svn_client__shelf_version_t *shelf_version,
svn_boolean_t dry_run,
apr_pool_t *scratch_pool)
{
- struct apply_files_baton_t baton = {0};
+ svn_client__shelf_t *shelf = shelf_version->shelf;
+ const svn_delta_editor_t *editor;
+ void *edit_baton;
- baton.shelf_version = shelf_version;
- baton.ctx = shelf_version->shelf->ctx;
- SVN_ERR(shelf_status_walk(shelf_version, "",
- apply_file_visitor, &baton,
- scratch_pool));
+ SVN_ERR(wc_mods_editor(&editor, &edit_baton,
+ shelf->wc_root_abspath,
+ NULL, NULL, /*notification*/
+ shelf->ctx, scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_client__shelf_replay(shelf_version, "",
+ editor, edit_baton,
+ shelf->ctx->notify_func2, shelf->ctx->notify_baton2,
+ scratch_pool));
- svn_io_sleep_for_timestamps(shelf_version->shelf->wc_root_abspath,
+ svn_io_sleep_for_timestamps(shelf->wc_root_abspath,
scratch_pool);
return SVN_NO_ERROR;
}
+/* Baton for paths_changed_visitor(). */
+struct unapply_walk_baton_t
+{
+ const char *wc_root_abspath;
+ svn_boolean_t dry_run;
+ svn_boolean_t use_commit_times;
+ svn_client_ctx_t *ctx;
+ apr_pool_t *pool;
+};
+
+/* Revert the change at RELPATH in the user's WC.
+ * Implements shelved_files_walk_func_t. */
+static svn_error_t *
+unapply_visitor(void *baton,
+ const char *relpath,
+ const svn_wc_status3_t *s,
+ apr_pool_t *scratch_pool)
+{
+ struct unapply_walk_baton_t *b = baton;
+ const char *abspath = svn_dirent_join(b->wc_root_abspath, relpath,
+ scratch_pool);
+
+ if (!b->dry_run)
+ {
+ apr_array_header_t *targets
+ = apr_array_make(scratch_pool, 1, sizeof(char *));
+ svn_depth_t depth;
+
+ APR_ARRAY_PUSH(targets, const char *) = abspath;
+
+ /* If the local modification is a "delete" then revert it all
+ (recursively). Otherwise we'd have to walk paths in
+ top-down order to revert a delete, whereas we need bottom-up
+ order to revert children of an added directory. */
+ if (s->node_status == svn_wc_status_deleted
+ || s->node_status == svn_wc_status_replaced
+ || s->node_status == svn_wc_status_added)
+ depth = svn_depth_infinity;
+ else
+ depth = svn_depth_empty;
+ SVN_ERR(svn_wc_revert6(b->ctx->wc_ctx,
+ abspath,
+ depth,
+ b->use_commit_times,
+ NULL /*changelists*/,
+ FALSE /*clear_changelists*/,
+ FALSE /*metadata_only*/,
+ FALSE /*added_keep_local*/,
+ b->ctx->cancel_func, b->ctx->cancel_baton,
+ NULL, NULL, /*notification*/
+ scratch_pool));
+ }
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_client__shelf_unapply(svn_client__shelf_version_t *shelf_version,
svn_boolean_t dry_run,
apr_pool_t *scratch_pool)
{
- apr_array_header_t *targets;
+ svn_client_ctx_t *ctx = shelf_version->shelf->ctx;
+ svn_client__shelf_t *shelf = shelf_version->shelf;
+ struct unapply_walk_baton_t baton;
+ svn_config_t *cfg;
- SVN_ERR(shelf_paths_changed(NULL, &targets, shelf_version,
- TRUE /*as_abspath*/,
- scratch_pool, scratch_pool));
- if (!dry_run)
- {
- SVN_ERR(svn_client_revert4(targets, svn_depth_empty,
- NULL /*changelists*/,
- FALSE /*clear_changelists*/,
- FALSE /*metadata_only*/,
- FALSE /*added_keep_local*/,
- shelf_version->shelf->ctx, scratch_pool));
- }
+ baton.wc_root_abspath = shelf->wc_root_abspath;
+ baton.dry_run = dry_run;
+ baton.ctx = ctx;
+ baton.pool = scratch_pool;
+
+ cfg = ctx->config ? svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG)
+ : NULL;
+ SVN_ERR(svn_config_get_bool(cfg, &baton.use_commit_times,
+ SVN_CONFIG_SECTION_MISCELLANY,
+ SVN_CONFIG_OPTION_USE_COMMIT_TIMES, FALSE));
+
+ SVN_WC__CALL_WITH_WRITE_LOCK(
+ shelf_status_walk(shelf_version, "",
+ unapply_visitor, &baton,
+ scratch_pool),
+ ctx->wc_ctx, shelf_version->shelf->wc_root_abspath,
+ FALSE /*lock_anchor*/, scratch_pool);
return SVN_NO_ERROR;
}
@@ -1903,22 +979,105 @@ svn_client__shelf_diff(svn_client__shelf
const svn_diff_tree_processor_t *diff_processor,
apr_pool_t *scratch_pool)
{
- struct diff_baton_t baton;
+ svn_client_ctx_t *ctx = shelf_version->shelf->ctx;
+ char *local_abspath
+ = svn_dirent_join(shelf_version->files_dir_abspath, shelf_relpath,
+ scratch_pool);
if (shelf_version->version_number == 0)
return SVN_NO_ERROR;
- baton.shelf_version = shelf_version;
- baton.top_relpath = shelf_relpath;
- baton.walk_root_abspath = shelf_version->files_dir_abspath;
- baton.diff_processor = diff_processor;
- SVN_ERR(svn_io_dir_walk2(baton.walk_root_abspath, 0 /*wanted*/,
- diff_visitor, &baton,
- scratch_pool));
+ SVN_ERR(svn_wc__diff7(FALSE /*anchor_at_given_paths*/,
+ ctx->wc_ctx, local_abspath,
+ depth,
+ ignore_ancestry,
+ NULL /*changelists*/,
+ diff_processor,
+ NULL, NULL, /*cancellation*/
+ scratch_pool, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+/* Populate the storage a new shelf-version object NEW_SHELF_VERSION,
+ * by creating a shelf storage WC with its base state copied from the
+ * 'real' WC.
+ */
+static svn_error_t *
+shelf_copy_base(svn_client__shelf_version_t *new_shelf_version,
+ apr_pool_t *scratch_pool)
+{
+ svn_client_ctx_t *ctx = new_shelf_version->shelf->ctx;
+ const char *users_wc_abspath = new_shelf_version->shelf->wc_root_abspath;
+ svn_client__pathrev_t *users_wc_root_base;
+ svn_opt_revision_t users_wc_root_rev;
+ svn_ra_session_t *ra_session = NULL;
+ svn_boolean_t sleep_here = FALSE;
+
+ SVN_ERR(svn_client__wc_node_get_base(&users_wc_root_base,
+ users_wc_abspath, ctx->wc_ctx,
+ scratch_pool, scratch_pool));
+ /* ### We need to read and recreate the mixed-rev, switched-URL,
+ mixed-depth WC state; but for a rough start we'll just use
+ HEAD, unswitched, depth-infinity. */
+ users_wc_root_rev.kind = svn_opt_revision_head;
+
+ /* ### TODO: Create an RA session that reads from the user's WC.
+ For a rough start, we'll just let 'checkout' read from the repo. */
+
+ SVN_ERR(svn_client__checkout_internal(NULL /*result_rev*/, &sleep_here,
+ users_wc_root_base->url,
+ new_shelf_version->files_dir_abspath,
+ &users_wc_root_rev, &users_wc_root_rev,
+ svn_depth_infinity,
+ TRUE /*ignore_externals*/,
+ FALSE /*allow_unver_obstructions*/,
+ ra_session,
+ ctx, scratch_pool));
+ /* ### hopefully we won't eventually need to sleep_here... */
+ if (sleep_here)
+ svn_io_sleep_for_timestamps(new_shelf_version->files_dir_abspath,
+ scratch_pool);
return SVN_NO_ERROR;
}
+/* */
+struct shelf_save_notifer_baton_t
+{
+ svn_client__shelf_version_t *shelf_version;
+ svn_wc_notify_func2_t notify_func;
+ void *notify_baton;
+ svn_client_status_func_t shelved_func;
+ void *shelved_baton;
+ svn_boolean_t any_shelved;
+};
+
+/* */
+static void
+shelf_save_notifier(void *baton,
+ const svn_wc_notify_t *notify,
+ apr_pool_t *pool)
+{
+ struct shelf_save_notifer_baton_t *nb = baton;
+ const char *wc_relpath
+ = svn_dirent_skip_ancestor(nb->shelf_version->shelf->wc_root_abspath,
+ notify->path);
+ svn_client_status_t *cst = NULL;
+#if 0
+ svn_wc_status3_t *wc_status;
+
+ svn_error_clear(status_read(&wc_status, nb->shelf_version, wc_relpath,
+ pool, pool));
+ svn_error_clear(svn_client__create_status(
+ &cst, nb->shelf_version->shelf->ctx->wc_ctx,
+ notify->path, wc_status, pool, pool));
+#endif
+ svn_error_clear(nb->shelved_func(nb->shelved_baton, wc_relpath, cst, pool));
+ nb->any_shelved = TRUE;
+
+ nb->notify_func(nb->notify_baton, notify, pool);
+}
+
svn_error_t *
svn_client__shelf_save_new_version3(svn_client__shelf_version_t **new_version_p,
svn_client__shelf_t *shelf,
@@ -1931,28 +1090,41 @@ svn_client__shelf_save_new_version3(svn_
void *not_shelved_baton,
apr_pool_t *scratch_pool)
{
+ svn_client_ctx_t *ctx = shelf->ctx;
int next_version = shelf->max_version + 1;
svn_client__shelf_version_t *new_shelf_version;
- svn_boolean_t any_shelved;
+ struct shelf_save_notifer_baton_t nb;
+ const svn_delta_editor_t *editor;
+ void *edit_baton;
SVN_ERR(shelf_version_create(&new_shelf_version,
shelf, next_version, scratch_pool));
- SVN_ERR(shelf_write_changes(&any_shelved,
- new_shelf_version,
- paths, depth, changelists,
- shelved_func, shelved_baton,
- not_shelved_func, not_shelved_baton,
- shelf->wc_root_abspath,
- shelf->ctx, scratch_pool, scratch_pool));
+ SVN_ERR(shelf_copy_base(new_shelf_version, scratch_pool));
+
+ nb.shelf_version = new_shelf_version;
+ nb.notify_func = ctx->notify_func2;
+ nb.notify_baton = ctx->notify_baton2;
+ nb.shelved_func = shelved_func;
+ nb.shelved_baton = shelved_baton;
+ nb.any_shelved = FALSE;
+ SVN_ERR(svn_client__shelf_mods_editor(&editor, &edit_baton,
+ new_shelf_version,
+ NULL, NULL, /*notification*/
+ ctx, scratch_pool));
+ SVN_ERR(svn_client__wc_replay(shelf->wc_root_abspath,
+ paths, depth, changelists,
+ editor, edit_baton,
+ shelf_save_notifier, &nb,
+ ctx, scratch_pool));
- if (any_shelved)
+ if (nb.any_shelved)
{
shelf->max_version = next_version;
SVN_ERR(shelf_write_current(shelf, scratch_pool));
if (new_version_p)
SVN_ERR(svn_client__shelf_version_open(new_version_p, shelf, next_version,
- scratch_pool, scratch_pool));
+ scratch_pool, scratch_pool));
}
else
{
@@ -2003,8 +1175,8 @@ svn_client__shelf_list(apr_hash_t **shel
SVN_ERR(svn_wc__get_wcroot(&wc_root_abspath, ctx->wc_ctx, local_abspath,
scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__get_shelves_dir(&shelves_dir, ctx->wc_ctx, local_abspath,
- scratch_pool, scratch_pool));
+ SVN_ERR(get_shelves_dir(&shelves_dir, ctx->wc_ctx, local_abspath,
+ scratch_pool, scratch_pool));
SVN_ERR(svn_io_get_dirents3(&dirents, shelves_dir, FALSE /*only_check_type*/,
result_pool, scratch_pool));
Modified: subversion/branches/swig-py3/subversion/libsvn_client/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_client/upgrade.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_client/upgrade.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_client/upgrade.c Mon Jul 8 15:19:03 2019
@@ -303,7 +303,7 @@ upgrade_externals_from_properties(svn_cl
{
apr_hash_index_t *hi;
apr_pool_t *iterpool;
- apr_pool_t *iterpool2;
+ apr_pool_t *inner_iterpool;
apr_hash_t *externals;
svn_opt_revision_t rev = {svn_opt_revision_unspecified, {0}};
@@ -317,7 +317,7 @@ upgrade_externals_from_properties(svn_cl
scratch_pool, scratch_pool));
iterpool = svn_pool_create(scratch_pool);
- iterpool2 = svn_pool_create(scratch_pool);
+ inner_iterpool = svn_pool_create(scratch_pool);
for (hi = apr_hash_first(scratch_pool, externals); hi;
hi = apr_hash_next(hi))
@@ -351,14 +351,12 @@ upgrade_externals_from_properties(svn_cl
iterpool, iterpool);
if (!err)
- externals_parent_url = svn_path_url_add_component2(
- externals_parent_repos_root_url,
- externals_parent_repos_relpath,
- iterpool);
- if (!err)
- err = svn_wc_parse_externals_description3(
- &externals_p, svn_dirent_dirname(local_abspath, iterpool),
- external_desc->data, FALSE, iterpool);
+ {
+ err = svn_wc_parse_externals_description3(
+ &externals_p, svn_dirent_dirname(local_abspath, iterpool),
+ external_desc->data, FALSE, iterpool);
+ }
+
if (err)
{
svn_wc_notify_t *notify =
@@ -376,24 +374,29 @@ upgrade_externals_from_properties(svn_cl
continue;
}
+ externals_parent_url = svn_path_url_add_component2(
+ externals_parent_repos_root_url,
+ externals_parent_repos_relpath,
+ iterpool);
+
for (i = 0; i < externals_p->nelts; i++)
{
svn_wc_external_item2_t *item;
item = APR_ARRAY_IDX(externals_p, i, svn_wc_external_item2_t*);
- svn_pool_clear(iterpool2);
+ svn_pool_clear(inner_iterpool);
err = upgrade_external_item(ctx, externals_parent_abspath,
externals_parent_url,
externals_parent_repos_root_url,
- item, info_baton, iterpool2);
+ item, info_baton, inner_iterpool);
if (err)
{
svn_wc_notify_t *notify =
svn_wc_create_notify(svn_dirent_join(externals_parent_abspath,
item->target_dir,
- iterpool2),
+ inner_iterpool),
svn_wc_notify_failed_external,
scratch_pool);
notify->err = err;
@@ -405,8 +408,8 @@ upgrade_externals_from_properties(svn_cl
}
}
+ svn_pool_destroy(inner_iterpool);
svn_pool_destroy(iterpool);
- svn_pool_destroy(iterpool2);
return SVN_NO_ERROR;
}
Modified: subversion/branches/swig-py3/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_client/util.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_client/util.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_client/util.c Mon Jul 8 15:19:03 2019
@@ -93,6 +93,7 @@ svn_client__pathrev_create_with_session(
pathrev->rev = rev;
pathrev->url = apr_pstrdup(result_pool, url);
*pathrev_p = pathrev;
+ SVN_ERR_ASSERT(svn_uri__is_ancestor(pathrev->repos_root_url, url));
return SVN_NO_ERROR;
}