Modified: subversion/branches/multi-wc-format/subversion/libsvn_client/shelf.c URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/shelf.c?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/libsvn_client/shelf.c (original) +++ subversion/branches/multi-wc-format/subversion/libsvn_client/shelf.c Fri Jan 14 14:01:45 2022 @@ -38,6 +38,7 @@ #include "svn_props.h" #include "client.h" +#include "private/svn_client_shelf.h" #include "private/svn_client_private.h" #include "private/svn_wc_private.h" #include "private/svn_sorts_private.h" @@ -100,7 +101,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 +115,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 +151,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 +177,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 +359,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 +384,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 +448,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 +466,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 +493,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 +501,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 +545,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 +561,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 +658,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 +667,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 +684,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 +692,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 +713,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 +980,106 @@ 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*/, + NULL, /* default WC format */ + 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 +1092,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 +1177,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/multi-wc-format/subversion/libsvn_client/status.c URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/status.c?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/libsvn_client/status.c (original) +++ subversion/branches/multi-wc-format/subversion/libsvn_client/status.c Fri Jan 14 14:01:45 2022 @@ -44,6 +44,7 @@ #include "svn_error.h" #include "svn_hash.h" +#include "private/svn_client_shelf.h" #include "private/svn_client_private.h" #include "private/svn_sorts_private.h" #include "private/svn_wc_private.h" Modified: subversion/branches/multi-wc-format/subversion/libsvn_client/switch.c URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/switch.c?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/libsvn_client/switch.c (original) +++ subversion/branches/multi-wc-format/subversion/libsvn_client/switch.c Fri Jan 14 14:01:45 2022 @@ -216,7 +216,7 @@ switch_internal(svn_revnum_t *result_rev anchor_url, switch_loc->repos_root_url); /* If we're not ignoring ancestry, then error out if the switch - source and target don't have a common ancestory. + source and target don't have a common ancestry. ### We're acting on the anchor here, not the target. Is that ### okay? */ @@ -279,7 +279,7 @@ switch_internal(svn_revnum_t *result_rev /* If LOCAL_ABSPATH will be unswitched relative to its parent, then it doesn't need an iprop cache. Note: It doesn't matter if - LOCAL_ABSPATH is withing a switched subtree, only if it's the + LOCAL_ABSPATH is within a switched subtree, only if it's the *root* of a switched subtree.*/ if (strcmp(unswitched_url, switch_loc->url) == 0) needs_iprop_cache = FALSE; Modified: subversion/branches/multi-wc-format/subversion/libsvn_client/update.c URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/update.c?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/libsvn_client/update.c (original) +++ subversion/branches/multi-wc-format/subversion/libsvn_client/update.c Fri Jan 14 14:01:45 2022 @@ -96,7 +96,7 @@ svn_client__dirent_fetcher(void *baton, folder. ANCHOR_ABSPATH is the w/c root and LOCAL_ABSPATH will still be considered empty, if it is equal to ANCHOR_ABSPATH and only contains the admin sub-folder. - If the w/c folder already exists but cannot be openend, we return + If the w/c folder already exists but cannot be opened, we return "unclean" - just in case. Most likely, the caller will have to bail out later due to the same error we got here. */ Modified: subversion/branches/multi-wc-format/subversion/libsvn_client/upgrade.c URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/upgrade.c?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/libsvn_client/upgrade.c (original) +++ subversion/branches/multi-wc-format/subversion/libsvn_client/upgrade.c Fri Jan 14 14:01:45 2022 @@ -337,7 +337,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}}; @@ -351,7 +351,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)) @@ -385,14 +385,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 = @@ -410,25 +408,30 @@ 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, wc_format, 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; @@ -440,8 +443,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/multi-wc-format/subversion/libsvn_client/util.c URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_client/util.c?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/libsvn_client/util.c (original) +++ subversion/branches/multi-wc-format/subversion/libsvn_client/util.c Fri Jan 14 14:01:45 2022 @@ -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; } Modified: subversion/branches/multi-wc-format/subversion/libsvn_delta/branch.c URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_delta/branch.c?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/libsvn_delta/branch.c (original) +++ subversion/branches/multi-wc-format/subversion/libsvn_delta/branch.c Fri Jan 14 14:01:45 2022 @@ -157,7 +157,7 @@ branch_txn_delete_branch(svn_branch__txn if (strcmp(b->bid, bid) == 0) { - svn_sort__array_delete(txn->priv->branches, i, 1); + SVN_ERR(svn_sort__array_delete2(txn->priv->branches, i, 1)); break; } } Modified: subversion/branches/multi-wc-format/subversion/libsvn_delta/branch_compat.c URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/libsvn_delta/branch_compat.c?rev=1897034&r1=1897033&r2=1897034&view=diff ============================================================================== --- subversion/branches/multi-wc-format/subversion/libsvn_delta/branch_compat.c (original) +++ subversion/branches/multi-wc-format/subversion/libsvn_delta/branch_compat.c Fri Jan 14 14:01:45 2022 @@ -875,6 +875,8 @@ drive_ev1_props(const char *repos_relpat */ static svn_error_t * apply_change(void **dir_baton, + const svn_delta_editor_t *editor, + void *edit_baton, void *parent_baton, void *callback_baton, const char *ev1_relpath, @@ -905,7 +907,7 @@ apply_change(void **dir_baton, /* Only property edits are allowed on the root. */ SVN_ERR_ASSERT(change->action == RESTRUCTURE_NONE); SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props, - eb->deditor, *dir_baton, scratch_pool)); + editor, *dir_baton, scratch_pool)); /* No further action possible for the root. */ return SVN_NO_ERROR; @@ -913,10 +915,10 @@ apply_change(void **dir_baton, if (change->action == RESTRUCTURE_DELETE) { - SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting_rev, - parent_baton, scratch_pool)); + SVN_ERR(editor->delete_entry(ev1_relpath, change->deleting_rev, + parent_baton, scratch_pool)); - /* No futher action possible for this node. */ + /* No further action possible for this node. */ return SVN_NO_ERROR; } @@ -927,11 +929,11 @@ apply_change(void **dir_baton, if (change->action == RESTRUCTURE_ADD_ABSENT) { if (change->kind == svn_node_dir) - SVN_ERR(eb->deditor->absent_directory(ev1_relpath, parent_baton, - scratch_pool)); - else if (change->kind == svn_node_file) - SVN_ERR(eb->deditor->absent_file(ev1_relpath, parent_baton, + SVN_ERR(editor->absent_directory(ev1_relpath, parent_baton, scratch_pool)); + else if (change->kind == svn_node_file) + SVN_ERR(editor->absent_file(ev1_relpath, parent_baton, + scratch_pool)); else SVN_ERR_MALFUNCTION(); @@ -948,8 +950,8 @@ apply_change(void **dir_baton, /* Do we have an old node to delete first? If so, delete it. */ if (change->deleting) - SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting_rev, - parent_baton, scratch_pool)); + SVN_ERR(editor->delete_entry(ev1_relpath, change->deleting_rev, + parent_baton, scratch_pool)); /* If it's a copy, determine the copy source location. */ if (change->copyfrom_path) @@ -974,13 +976,13 @@ apply_change(void **dir_baton, } if (change->kind == svn_node_dir) - SVN_ERR(eb->deditor->add_directory(ev1_relpath, parent_baton, - copyfrom_url, copyfrom_rev, - result_pool, dir_baton)); - else if (change->kind == svn_node_file) - SVN_ERR(eb->deditor->add_file(ev1_relpath, parent_baton, + SVN_ERR(editor->add_directory(ev1_relpath, parent_baton, copyfrom_url, copyfrom_rev, - result_pool, &file_baton)); + result_pool, dir_baton)); + else if (change->kind == svn_node_file) + SVN_ERR(editor->add_file(ev1_relpath, parent_baton, + copyfrom_url, copyfrom_rev, + result_pool, &file_baton)); else SVN_ERR_MALFUNCTION(); } @@ -993,13 +995,13 @@ apply_change(void **dir_baton, when we fetch the base properties.) */ if (change->kind == svn_node_dir) - SVN_ERR(eb->deditor->open_directory(ev1_relpath, parent_baton, - change->changing_rev, - result_pool, dir_baton)); - else if (change->kind == svn_node_file) - SVN_ERR(eb->deditor->open_file(ev1_relpath, parent_baton, + SVN_ERR(editor->open_directory(ev1_relpath, parent_baton, change->changing_rev, - result_pool, &file_baton)); + result_pool, dir_baton)); + else if (change->kind == svn_node_file) + SVN_ERR(editor->open_file(ev1_relpath, parent_baton, + change->changing_rev, + result_pool, &file_baton)); else SVN_ERR_MALFUNCTION(); } @@ -1007,10 +1009,10 @@ apply_change(void **dir_baton, /* Apply any properties in CHANGE to the node. */ if (change->kind == svn_node_dir) SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props, - eb->deditor, *dir_baton, scratch_pool)); + editor, *dir_baton, scratch_pool)); else SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props, - eb->deditor, file_baton, scratch_pool)); + editor, file_baton, scratch_pool)); /* Send the text content delta, if new text content is provided. */ if (change->contents_text) @@ -1023,7 +1025,7 @@ apply_change(void **dir_baton, scratch_pool); /* ### would be nice to have a BASE_CHECKSUM, but hey: this is the ### shim code... */ - SVN_ERR(eb->deditor->apply_textdelta(file_baton, NULL, scratch_pool, + SVN_ERR(editor->apply_textdelta(file_baton, NULL, scratch_pool, &handler, &handler_baton)); /* ### it would be nice to send a true txdelta here, but whatever. */ SVN_ERR(svn_txdelta_send_stream(read_stream, handler, handler_baton, @@ -1033,7 +1035,7 @@ apply_change(void **dir_baton, if (file_baton) { - SVN_ERR(eb->deditor->close_file(file_baton, NULL, scratch_pool)); + SVN_ERR(editor->close_file(file_baton, NULL, scratch_pool)); } return SVN_NO_ERROR; @@ -1740,7 +1742,7 @@ drive_changes(svn_branch__txn_priv_t *eb /* Apply the appropriate Ev1 change to each Ev1-relative path. */ paths = get_unsorted_paths(eb->changes, scratch_pool); - SVN_ERR(svn_delta_path_driver2(eb->deditor, eb->dedit_baton, + SVN_ERR(svn_delta_path_driver3(eb->deditor, eb->dedit_baton, paths, TRUE /*sort*/, apply_change, (void *)eb, scratch_pool));
