Modified: subversion/branches/ev2-export/subversion/libsvn_repos/rev_hunt.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/rev_hunt.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_repos/rev_hunt.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_repos/rev_hunt.c Sat Feb 23 01:25:38 2013 @@ -532,7 +532,7 @@ check_ancestry_of_peg_path(svn_boolean_t { svn_fs_root_t *root; svn_fs_history_t *history; - const char *path; + const char *path = NULL; svn_revnum_t revision; apr_pool_t *lastpool, *currpool; @@ -1252,17 +1252,18 @@ find_merged_revisions(apr_array_header_t apr_hash_t *duplicate_path_revs, svn_repos_authz_func_t authz_read_func, void *authz_read_baton, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { const apr_array_header_t *old; apr_array_header_t *new_merged_path_revs; apr_pool_t *iterpool, *last_pool; apr_array_header_t *merged_path_revisions = - apr_array_make(pool, 0, sizeof(struct path_revision *)); + apr_array_make(scratch_pool, 0, sizeof(struct path_revision *)); old = mainline_path_revisions; - iterpool = svn_pool_create(pool); - last_pool = svn_pool_create(pool); + iterpool = svn_pool_create(scratch_pool); + last_pool = svn_pool_create(scratch_pool); do { @@ -1325,8 +1326,8 @@ find_merged_revisions(apr_array_header_t TRUE, TRUE, duplicate_path_revs, authz_read_func, - authz_read_baton, pool, - iterpool3)); + authz_read_baton, + result_pool, iterpool3)); } svn_pool_destroy(iterpool3); } @@ -1350,7 +1351,8 @@ find_merged_revisions(apr_array_header_t sizeof(struct path_revision *), compare_path_revisions); /* Copy to the output array. */ - *merged_path_revisions_out = apr_array_copy(pool, merged_path_revisions); + *merged_path_revisions_out = apr_array_copy(result_pool, + merged_path_revisions); svn_pool_destroy(iterpool); svn_pool_destroy(last_pool); @@ -1447,6 +1449,114 @@ send_path_revision(struct path_revision return SVN_NO_ERROR; } +/* Similar to svn_repos_get_file_revs2() but returns paths while walking + history instead of after collecting all history. + + This allows implementing clients to immediately start processing and + stop when they got the information they need. (E.g. all or a specific set + of lines were modified) */ +static svn_error_t * +get_file_revs_backwards(svn_repos_t *repos, + const char *path, + svn_revnum_t start, + svn_revnum_t end, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + svn_file_rev_handler_t handler, + void *handler_baton, + apr_pool_t *scratch_pool) +{ + apr_pool_t *iterpool, *last_pool; + svn_fs_history_t *history; + svn_fs_root_t *root; + svn_node_kind_t kind; + struct send_baton sb; + + /* We switch between two pools while looping and so does the path-rev + handler for actually reported revisions. We do this as we + need just information from last iteration to be available. */ + + iterpool = svn_pool_create(scratch_pool); + last_pool = svn_pool_create(scratch_pool); + sb.iterpool = svn_pool_create(scratch_pool); + sb.last_pool = svn_pool_create(scratch_pool); + + /* We want the first txdelta to be against the empty file. */ + sb.last_root = NULL; + sb.last_path = NULL; + + /* Create an empty hash table for the first property diff. */ + sb.last_props = apr_hash_make(sb.last_pool); + + /* The path had better be a file in this revision. */ + SVN_ERR(svn_fs_revision_root(&root, repos->fs, end, scratch_pool)); + SVN_ERR(svn_fs_check_path(&kind, root, path, scratch_pool)); + if (kind != svn_node_file) + return svn_error_createf(SVN_ERR_FS_NOT_FILE, + NULL, _("'%s' is not a file in revision %ld"), + path, end); + + /* Open a history object. */ + SVN_ERR(svn_fs_node_history(&history, root, path, scratch_pool)); + while (1) + { + struct path_revision *path_rev; + svn_revnum_t tmp_revnum; + const char *tmp_path; + + svn_pool_clear(iterpool); + + /* Fetch the history object to walk through. */ + SVN_ERR(svn_fs_history_prev(&history, history, TRUE, iterpool)); + if (!history) + break; + SVN_ERR(svn_fs_history_location(&tmp_path, &tmp_revnum, + history, iterpool)); + + /* Check authorization. */ + if (authz_read_func) + { + svn_boolean_t readable; + svn_fs_root_t *tmp_root; + + SVN_ERR(svn_fs_revision_root(&tmp_root, repos->fs, tmp_revnum, + iterpool)); + SVN_ERR(authz_read_func(&readable, tmp_root, tmp_path, + authz_read_baton, iterpool)); + if (! readable) + break; + } + + /* We didn't break, so we must really want this path-rev. */ + path_rev = apr_palloc(iterpool, sizeof(*path_rev)); + path_rev->path = tmp_path; + path_rev->revnum = tmp_revnum; + path_rev->merged = FALSE; + + SVN_ERR(send_path_revision(path_rev, repos, &sb, + handler, handler_baton)); + + if (path_rev->revnum <= start) + break; + + /* Swap pools. */ + { + apr_pool_t *tmp_pool = iterpool; + iterpool = last_pool; + last_pool = tmp_pool; + } + } + + svn_pool_destroy(iterpool); + svn_pool_destroy(last_pool); + svn_pool_destroy(sb.last_pool); + svn_pool_destroy(sb.iterpool); + + return SVN_NO_ERROR; + +} + + /* We don't yet support sending revisions in reverse order; the caller wait * until we've traced back through the entire history, and then accept * them from oldest to youngest. Someday this may change, but in the meantime, @@ -1463,6 +1573,10 @@ send_path_revision(struct path_revision * oldest to youngest, interleaving as appropriate. This is implemented * similar to an insertion sort, but instead of inserting into another * array, we just call the appropriate handler. + * + * 2013-02: Added a very simple reverse for mainline only changes. Before this, + * this would return an error (path not found) or just the first + * revision before end. */ svn_error_t * svn_repos_get_file_revs2(svn_repos_t *repos, @@ -1474,48 +1588,65 @@ svn_repos_get_file_revs2(svn_repos_t *re void *authz_read_baton, svn_file_rev_handler_t handler, void *handler_baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { apr_array_header_t *mainline_path_revisions, *merged_path_revisions; apr_hash_t *duplicate_path_revs; struct send_baton sb; int mainline_pos, merged_pos; + if (end < start) + { + if (include_merged_revisions) + return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL); + + return svn_error_trace( + get_file_revs_backwards(repos, path, + end, start, + authz_read_func, + authz_read_baton, + handler, + handler_baton, + scratch_pool)); + } + + /* We switch between two pools while looping, since we need information from + the last iteration to be available. */ + sb.iterpool = svn_pool_create(scratch_pool); + sb.last_pool = svn_pool_create(scratch_pool); + + /* We want the first txdelta to be against the empty file. */ + sb.last_root = NULL; + sb.last_path = NULL; + + /* Create an empty hash table for the first property diff. */ + sb.last_props = apr_hash_make(sb.last_pool); + + /* Get the revisions we are interested in. */ - duplicate_path_revs = apr_hash_make(pool); - mainline_path_revisions = apr_array_make(pool, 0, + duplicate_path_revs = apr_hash_make(scratch_pool); + mainline_path_revisions = apr_array_make(scratch_pool, 100, sizeof(struct path_revision *)); SVN_ERR(find_interesting_revisions(mainline_path_revisions, repos, path, start, end, include_merged_revisions, FALSE, duplicate_path_revs, - authz_read_func, authz_read_baton, pool, - pool)); + authz_read_func, authz_read_baton, + scratch_pool, sb.iterpool)); /* If we are including merged revisions, go get those, too. */ if (include_merged_revisions) SVN_ERR(find_merged_revisions(&merged_path_revisions, start, mainline_path_revisions, repos, duplicate_path_revs, authz_read_func, - authz_read_baton, pool)); + authz_read_baton, + scratch_pool, sb.iterpool)); else - merged_path_revisions = apr_array_make(pool, 0, + merged_path_revisions = apr_array_make(scratch_pool, 0, sizeof(struct path_revision *)); /* We must have at least one revision to get. */ SVN_ERR_ASSERT(mainline_path_revisions->nelts > 0); - /* We switch betwwen two pools while looping, since we need information from - the last iteration to be available. */ - sb.iterpool = svn_pool_create(pool); - sb.last_pool = svn_pool_create(pool); - - /* We want the first txdelta to be against the empty file. */ - sb.last_root = NULL; - sb.last_path = NULL; - - /* Create an empty hash table for the first property diff. */ - sb.last_props = apr_hash_make(sb.last_pool); - /* Walk through both mainline and merged revisions, and send them in reverse chronological order, interleaving as appropriate. */ mainline_pos = mainline_path_revisions->nelts - 1;
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/auth.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/auth.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_subr/auth.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_subr/auth.c Sat Feb 23 01:25:38 2013 @@ -35,6 +35,8 @@ #include "svn_dso.h" #include "svn_version.h" +#include "auth.h" + /* AN OVERVIEW =========== @@ -619,3 +621,20 @@ svn_auth_get_platform_specific_client_pr return SVN_NO_ERROR; } + +svn_error_t * +svn_auth_cleanup_walk(svn_auth_baton_t *baton, + svn_auth_cleanup_callback cleanup, + void *cleanup_baton, + apr_pool_t *scratch_pool) +{ + + if (apr_hash_get(baton->tables, SVN_AUTH_CRED_SIMPLE, APR_HASH_KEY_STRING)) + { + SVN_ERR(svn_auth__simple_cleanup_walk(baton, cleanup, cleanup_baton, + baton->creds_cache, scratch_pool)); + } + /* ### Maybe add support for other providers? */ + + return SVN_NO_ERROR; +} Modified: subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c Sat Feb 23 01:25:38 2013 @@ -1372,7 +1372,7 @@ membuffer_cache_set_internal(svn_membuff /* if there is an old version of that entry and the new data fits into * the old spot, just re-use that space. */ - if (buffer && entry && entry->size >= size) + if (entry && ALIGN_VALUE(entry->size) >= size && buffer) { cache->data_used += size - entry->size; entry->size = size; @@ -1430,7 +1430,10 @@ membuffer_cache_set_internal(svn_membuff else { /* if there is already an entry for this key, drop it. + * Since ensure_data_insertable may have removed entries from + * ENTRY's group, re-do the lookup. */ + entry = find_entry(cache, group_index, to_find, FALSE); if (entry) drop_entry(cache, entry); } @@ -1967,16 +1970,6 @@ svn_membuffer_cache_get(void **value_p, DEBUG_CACHE_MEMBUFFER_TAG result_pool)); - /* We don't need more the key anymore. - * But since we allocate only small amounts of data per get() call and - * apr_pool_clear is somewhat expensive, we clear it only now and then. - */ - if (++cache->alloc_counter > ALLOCATIONS_PER_POOL_CLEAR) - { - svn_pool_clear(cache->pool); - cache->alloc_counter = 0; - } - /* return result */ *found = *value_p != NULL; return SVN_NO_ERROR; @@ -2060,12 +2053,6 @@ svn_membuffer_cache_get_partial(void **v return SVN_NO_ERROR; } - if (++cache->alloc_counter > ALLOCATIONS_PER_POOL_CLEAR) - { - svn_pool_clear(cache->pool); - cache->alloc_counter = 0; - } - combine_key(cache, key, cache->key_len); SVN_ERR(membuffer_cache_get_partial(cache->membuffer, cache->combined_key, Modified: subversion/branches/ev2-export/subversion/libsvn_subr/config_auth.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/config_auth.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_subr/config_auth.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_subr/config_auth.c Sat Feb 23 01:25:38 2013 @@ -29,18 +29,20 @@ #include "config_impl.h" +#include "auth.h" + #include "svn_private_config.h" /* Helper for svn_config_{read|write}_auth_data. Return a path to a file within ~/.subversion/auth/ that holds CRED_KIND credentials within REALMSTRING. If no path is available *PATH will be set to NULL. */ -static svn_error_t * -auth_file_path(const char **path, - const char *cred_kind, - const char *realmstring, - const char *config_dir, - apr_pool_t *pool) +svn_error_t * +svn_auth__file_path(const char **path, + const char *cred_kind, + const char *realmstring, + const char *config_dir, + apr_pool_t *pool) { const char *authdir_path, *hexname; svn_checksum_t *checksum; @@ -81,8 +83,8 @@ svn_config_read_auth_data(apr_hash_t **h *hash = NULL; - SVN_ERR(auth_file_path(&auth_path, cred_kind, realmstring, config_dir, - pool)); + SVN_ERR(svn_auth__file_path(&auth_path, cred_kind, realmstring, config_dir, + pool)); if (! auth_path) return SVN_NO_ERROR; @@ -118,8 +120,8 @@ svn_config_write_auth_data(apr_hash_t *h svn_stream_t *stream; const char *auth_path; - SVN_ERR(auth_file_path(&auth_path, cred_kind, realmstring, config_dir, - pool)); + SVN_ERR(svn_auth__file_path(&auth_path, cred_kind, realmstring, config_dir, + pool)); if (! auth_path) return svn_error_create(SVN_ERR_NO_AUTH_FILE_PATH, NULL, _("Unable to locate auth file")); Modified: subversion/branches/ev2-export/subversion/libsvn_subr/config_file.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/config_file.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_subr/config_file.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_subr/config_file.c Sat Feb 23 01:25:38 2013 @@ -1175,8 +1175,18 @@ svn_config_ensure(const char *config_dir "" NL "### Section for configuring working copies." NL "[working-copy]" NL - "### Set to true to enable exclusive SQLite locking. Some clients" NL - "### may not support exclusive locking." NL + "### Set to a list of the names of specific clients that should use" NL + "### exclusive SQLite locking of working copies. This increases the"NL + "### performance of the client but prevents concurrent access by" NL + "### other clients." NL + "### Possible values:" NL + "### svn (the command line client)" NL + "### Third-party clients may also support this option." NL + "# exclusive-locking-clients =" NL + "### Set to true to enable exclusive SQLite locking of working" NL + "### copies by all clients. Enabling this may cause some clients" NL + "### to fail to work properly. This does not have to be set for" NL + "### exclusive-locking-clients to work." NL "# exclusive-locking = false" NL; err = svn_io_file_open(&f, path, Modified: subversion/branches/ev2-export/subversion/libsvn_subr/mergeinfo.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/mergeinfo.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_subr/mergeinfo.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_subr/mergeinfo.c Sat Feb 23 01:25:38 2013 @@ -1201,26 +1201,15 @@ range_swap_endpoints(svn_merge_range_t * svn_error_t * svn_rangelist_reverse(svn_rangelist_t *rangelist, apr_pool_t *pool) { - int i, swap_index; - svn_merge_range_t range; - for (i = 0; i < rangelist->nelts / 2; i++) - { - swap_index = rangelist->nelts - i - 1; - range = *APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *); - *APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *) = - *APR_ARRAY_IDX(rangelist, swap_index, svn_merge_range_t *); - *APR_ARRAY_IDX(rangelist, swap_index, svn_merge_range_t *) = range; - range_swap_endpoints(APR_ARRAY_IDX(rangelist, swap_index, - svn_merge_range_t *)); + int i; + + svn_sort__array_reverse(rangelist, pool); + + for (i = 0; i < rangelist->nelts; i++) + { range_swap_endpoints(APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *)); } - /* If there's an odd number of elements, we still need to swap the - end points of the remaining range. */ - if (rangelist->nelts % 2 == 1) - range_swap_endpoints(APR_ARRAY_IDX(rangelist, rangelist->nelts / 2, - svn_merge_range_t *)); - return SVN_NO_ERROR; } Modified: subversion/branches/ev2-export/subversion/libsvn_subr/prompt.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/prompt.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_subr/prompt.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_subr/prompt.c Sat Feb 23 01:25:38 2013 @@ -29,6 +29,7 @@ #include <apr_lib.h> #include <apr_poll.h> +#include <apr_portable.h> #include "svn_cmdline.h" #include "svn_string.h" @@ -39,41 +40,385 @@ #include "private/svn_cmdline_private.h" #include "svn_private_config.h" +#ifdef WIN32 +#include <conio.h> +#elif defined(HAVE_TERMIOS_H) +#include <termios.h> +#endif + -/* Wait for input on @a *f. Doing all allocations - * in @a pool. This functions is based on apr_wait_for_io_or_timeout(). - * Note that this will return an EINTR on a signal. - * - * ### FIX: When APR gives us a better way of doing this use it. */ -static apr_status_t wait_for_input(apr_file_t *f, - apr_pool_t *pool) +/* Descriptor of an open terminal */ +typedef struct terminal_handle_t terminal_handle_t; +struct terminal_handle_t +{ + apr_file_t *infd; /* input file handle */ + apr_file_t *outfd; /* output file handle */ + svn_boolean_t noecho; /* terminal echo was turned off */ + svn_boolean_t close_handles; /* close handles when closing the terminal */ + apr_pool_t *pool; /* pool associated with the file handles */ + +#ifdef HAVE_TERMIOS_H + svn_boolean_t restore_state; /* terminal state was changed */ + apr_os_file_t osinfd; /* OS-specific handle for infd */ + struct termios attr; /* saved terminal attributes */ +#endif +}; + +/* Initialize safe state of terminal_handle_t. */ +static void +terminal_handle_init(terminal_handle_t *terminal, + apr_file_t *infd, apr_file_t *outfd, + svn_boolean_t noecho, svn_boolean_t close_handles, + apr_pool_t *pool) +{ + memset(terminal, 0, sizeof(*terminal)); + terminal->infd = infd; + terminal->outfd = outfd; + terminal->noecho = noecho; + terminal->close_handles = close_handles; + terminal->pool = pool; +} + +/* + * Common pool cleanup handler for terminal_handle_t. Closes TERMINAL. + * If CLOSE_HANDLES is TRUE, close the terminal file handles. + * If RESTORE_STATE is TRUE, restores the TERMIOS flags of the terminal. + */ +static apr_status_t +terminal_cleanup_handler(terminal_handle_t *terminal, + svn_boolean_t close_handles, + svn_boolean_t restore_state) +{ + apr_status_t status = APR_SUCCESS; + +#ifdef HAVE_TERMIOS_H + /* Restore terminal state flags. */ + if (restore_state && terminal->restore_state) + tcsetattr(terminal->osinfd, TCSANOW, &terminal->attr); +#endif + + /* Close terminal handles. */ + if (close_handles && terminal->close_handles) + { + apr_file_t *const infd = terminal->infd; + apr_file_t *const outfd = terminal->outfd; + + if (infd) + { + terminal->infd = NULL; + status = apr_file_close(infd); + } + + if (!status && outfd && outfd != infd) + { + terminal->outfd = NULL; + status = apr_file_close(terminal->outfd); + } + } + return status; +} + +/* Normal pool cleanup for a terminal. */ +static apr_status_t terminal_plain_cleanup(void *baton) { -#ifndef WIN32 - apr_pollfd_t pollset; - int srv, n; + return terminal_cleanup_handler(baton, FALSE, TRUE); +} + +/* Child pool cleanup for a terminal -- does not restore echo state. */ +static apr_status_t terminal_child_cleanup(void *baton) +{ + return terminal_cleanup_handler(baton, FALSE, FALSE); +} + +/* Explicitly close the terminal, removing its cleanup handlers. */ +static svn_error_t * +terminal_close(terminal_handle_t *terminal) +{ + apr_status_t status; + + /* apr_pool_cleanup_kill() removes both normal and child cleanup */ + apr_pool_cleanup_kill(terminal->pool, terminal, terminal_plain_cleanup); + + status = terminal_cleanup_handler(terminal, TRUE, TRUE); + if (status) + return svn_error_create(status, NULL, _("Can't close terminal")); + return SVN_NO_ERROR; +} + +/* Allocate and open *TERMINAL. If NOECHO is TRUE, try to turn off + terminal echo. Use POOL for all allocations.*/ +static svn_error_t * +terminal_open(terminal_handle_t **terminal, svn_boolean_t noecho, + apr_pool_t *pool) +{ + apr_status_t status; - pollset.desc_type = APR_POLL_FILE; - pollset.desc.f = f; - pollset.p = pool; - pollset.reqevents = APR_POLLIN; - - srv = apr_poll(&pollset, 1, &n, -1); - - if (n == 1 && pollset.rtnevents & APR_POLLIN) - return APR_SUCCESS; - - return srv; -#else - /* APR specs say things that are unimplemented are supposed to return - * APR_ENOTIMPL. But when trying to use APR_POLL_FILE with apr_poll - * on Windows it returns APR_EBADF instead. So just return APR_ENOTIMPL - * ourselves here. - */ - return APR_ENOTIMPL; +#ifdef WIN32 + /* On Windows, we'll use the console API directly if the process has + a console attached; otherwise we'll just use stdin and stderr. */ + const HANDLE conin = CreateFileW(L"CONIN$", GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + *terminal = apr_palloc(pool, sizeof(terminal_handle_t)); + if (conin != INVALID_HANDLE_VALUE) + { + /* The process has a console. */ + CloseHandle(conin); + terminal_handle_init(*terminal, NULL, NULL, noecho, FALSE, NULL); + return SVN_NO_ERROR; + } +#else /* !WIN32 */ + /* Without evidence to the contrary, we'll assume this is *nix and + try to open /dev/tty. If that fails, we'll use stdin for input + and stderr for prompting. */ + apr_file_t *tmpfd; + status = apr_file_open(&tmpfd, "/dev/tty", + APR_FOPEN_READ | APR_FOPEN_WRITE, + APR_OS_DEFAULT, pool); + *terminal = apr_palloc(pool, sizeof(terminal_handle_t)); + if (!status) + { + /* We have a terminal handle that we can use for input and output. */ + terminal_handle_init(*terminal, tmpfd, tmpfd, FALSE, TRUE, pool); + } +#endif /* !WIN32 */ + else + { + /* There is no terminal. Sigh. */ + apr_file_t *infd; + apr_file_t *outfd; + + status = apr_file_open_stdin(&infd, pool); + if (status) + return svn_error_wrap_apr(status, _("Can't open stdin")); + status = apr_file_open_stderr(&outfd, pool); + if (status) + return svn_error_wrap_apr(status, _("Can't open stderr")); + terminal_handle_init(*terminal, infd, outfd, FALSE, FALSE, pool); + } + +#ifdef HAVE_TERMIOS_H + /* Set terminal state */ + if (0 == apr_os_file_get(&(*terminal)->osinfd, (*terminal)->infd)) + { + if (0 == tcgetattr((*terminal)->osinfd, &(*terminal)->attr)) + { + struct termios attr = (*terminal)->attr; + /* Turn off signal handling and canonical input mode */ + attr.c_lflag &= ~(ISIG | ICANON); + attr.c_cc[VMIN] = 1; /* Read one byte at a time */ + attr.c_cc[VTIME] = 0; /* No timeout, wait indefinitely */ + if (noecho) + attr.c_lflag &= ~(ECHO); /* Turn off echo */ + if (0 == tcsetattr((*terminal)->osinfd, TCSAFLUSH, &attr)) + { + (*terminal)->noecho = noecho; + (*terminal)->restore_state = TRUE; + } + } + } +#endif /* HAVE_TERMIOS_H */ + + /* Register pool cleanup to close handles and restore echo state. */ + apr_pool_cleanup_register((*terminal)->pool, *terminal, + terminal_plain_cleanup, + terminal_child_cleanup); + return SVN_NO_ERROR; +} + +/* Write a null-terminated STRING to TERMINAL. + Use POOL for allocations related to converting STRING from UTF-8. */ +static svn_error_t * +terminal_puts(const char *string, terminal_handle_t *terminal, + apr_pool_t *pool) +{ + svn_error_t *err; + apr_status_t status; + const char *converted; + + err = svn_cmdline_cstring_from_utf8(&converted, string, pool); + if (err) + { + svn_error_clear(err); + converted = svn_cmdline_cstring_from_utf8_fuzzy(string, pool); + } + +#ifdef WIN32 + if (!terminal->outfd) + { + /* See terminal_open; we're using Console I/O. */ + _cputs(converted); + return SVN_NO_ERROR; + } #endif + + status = apr_file_write_full(terminal->outfd, converted, + strlen(converted), NULL); + if (!status) + status = apr_file_flush(terminal->outfd); + if (status) + return svn_error_wrap_apr(status, _("Can't write to terminal")); + return SVN_NO_ERROR; } +/* These codes can be returned from terminal_getc instead of a character. */ +#define TERMINAL_NONE 0x80000 /* no character read, retry */ +#define TERMINAL_DEL (TERMINAL_NONE + 1) /* the input was a deleteion */ +#define TERMINAL_EOL (TERMINAL_NONE + 2) /* end of input/end of line */ +#define TERMINAL_EOF (TERMINAL_NONE + 3) /* end of file during input */ + +/* Read one character or control code from TERMINAL, returning it in CODE. + if CAN_ERASE and the input was a deletion, emit codes to erase the + last character displayed on the terminal. + Use POOL for all allocations. */ +static svn_error_t * +terminal_getc(int *code, terminal_handle_t *terminal, + svn_boolean_t can_erase, apr_pool_t *pool) +{ + apr_status_t status = APR_SUCCESS; + char ch; + +#ifdef WIN32 + if (!terminal->infd) + { + /* See terminal_open; we're using Console I/O. */ + const svn_boolean_t echo = !terminal->noecho; + + /* The following was hoisted from APR's getpass for Windows. */ + int concode = _getch(); + switch (concode) + { + case '\r': /* end-of-line */ + *code = TERMINAL_EOL; + if (echo) + _cputs("\r\n"); + break; + + case EOF: /* end-of-file */ + case 26: /* Ctrl+Z */ + *code = TERMINAL_EOF; + if (echo) + _cputs((concode == EOF ? "[EOF]\r\n" : "^Z\r\n")); + break; + + case 3: /* Ctrl+C, Ctrl+Break */ + /* _getch() bypasses Ctrl+C but not Ctrl+Break detection! */ + if (echo) + _cputs("^C\r\n"); + return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL); + + case 0: /* Function code prefix */ + case 0xE0: + concode = (concode << 4) | _getch(); + /* Catch {DELETE}, {<--}, Num{DEL} and Num{<--} */ + if (concode == 0xE53 || concode == 0xE4B + || concode == 0x053 || concode == 0x04B) + { + *code = TERMINAL_DEL; + if (can_erase) + _cputs("\b \b"); + } + else + { + *code = TERMINAL_NONE; + _putch('\a'); + } + break; + + case '\b': /* BS */ + case 127: /* DEL */ + *code = TERMINAL_DEL; + if (can_erase) + _cputs("\b \b"); + break; + + default: + if (!apr_iscntrl(concode)) + { + *code = (int)(unsigned char)concode; + _putch(echo ? concode : '*'); + } + else + { + *code = TERMINAL_NONE; + _putch('\a'); + } + } + return SVN_NO_ERROR; + } +#elif defined(HAVE_TERMIOS_H) + if (terminal->restore_state) + { + /* We're using a bytewise-immediate termios input */ + const struct termios *const attr = &terminal->attr; + + status = apr_file_getc(&ch, terminal->infd); + if (status) + return svn_error_wrap_apr(status, _("Can't read from terminal")); + + if (ch == attr->c_cc[VINTR] || ch == attr->c_cc[VQUIT]) + return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL); + else if (ch == '\r' || ch == '\n' || ch == attr->c_cc[VEOL]) + *code = TERMINAL_EOL; + else if (ch == '\b' + || ch == attr->c_cc[VERASE] || ch == attr->c_cc[VKILL]) + *code = TERMINAL_DEL; + else if (ch == attr->c_cc[VEOF]) + *code = TERMINAL_EOF; + else if (!apr_iscntrl(ch)) + *code = (int)(unsigned char)ch; + else + { + *code = TERMINAL_NONE; + apr_file_putc('\a', terminal->outfd); + } + return SVN_NO_ERROR; + } +#endif /* HAVE_TERMIOS_H */ + + /* Fall back to plain stream-based I/O. */ +#ifndef WIN32 + /* Wait for input on termin. This code is based on + apr_wait_for_io_or_timeout(). + Note that this will return an EINTR on a signal. */ + { + apr_pollfd_t pollset; + int n; + + pollset.desc_type = APR_POLL_FILE; + pollset.desc.f = terminal->infd; + pollset.p = pool; + pollset.reqevents = APR_POLLIN; + + status = apr_poll(&pollset, 1, &n, -1); + + if (n == 1 && pollset.rtnevents & APR_POLLIN) + status = APR_SUCCESS; + } +#endif /* !WIN32 */ + + if (!status) + status = apr_file_getc(&ch, terminal->infd); + if (APR_STATUS_IS_EINTR(status)) + { + *code = TERMINAL_NONE; + return SVN_NO_ERROR; + } + else if (APR_STATUS_IS_EOF(status)) + { + *code = TERMINAL_EOF; + return SVN_NO_ERROR; + } + else if (status) + return svn_error_wrap_apr(status, _("Can't read from terminal")); + + *code = (int)(unsigned char)ch; + return SVN_NO_ERROR; +} + + /* Set @a *result to the result of prompting the user with @a * prompt_msg. Use @ *pb to get the cancel_func and cancel_baton. * Do not call the cancel_func if @a *pb is NULL. @@ -91,77 +436,91 @@ prompt(const char **result, /* XXX: If this functions ever starts using members of *pb * which were not included in svn_cmdline_prompt_baton_t, * we need to update svn_cmdline_prompt_user2 and its callers. */ - apr_status_t status; - apr_file_t *fp; - char c; + svn_boolean_t saw_first_half_of_eol = FALSE; svn_stringbuf_t *strbuf = svn_stringbuf_create_empty(pool); + terminal_handle_t *terminal; + int code; + char c; - status = apr_file_open_stdin(&fp, pool); - if (status) - return svn_error_wrap_apr(status, _("Can't open stdin")); + SVN_ERR(terminal_open(&terminal, hide, pool)); + SVN_ERR(terminal_puts(prompt_msg, terminal, pool)); - if (! hide) + while (1) { - svn_boolean_t saw_first_half_of_eol = FALSE; - SVN_ERR(svn_cmdline_fputs(prompt_msg, stderr, pool)); - fflush(stderr); - - while (1) - { - /* Hack to allow us to not block for io on the prompt, so - * we can cancel. */ - if (pb) - SVN_ERR(pb->cancel_func(pb->cancel_baton)); - status = wait_for_input(fp, pool); - if (APR_STATUS_IS_EINTR(status)) - continue; - else if (status && status != APR_ENOTIMPL) - return svn_error_wrap_apr(status, _("Can't read stdin")); - - status = apr_file_getc(&c, fp); - if (status) - return svn_error_wrap_apr(status, _("Can't read stdin")); + SVN_ERR(terminal_getc(&code, terminal, (strbuf->len > 0), pool)); - if (saw_first_half_of_eol) - { - if (c == APR_EOL_STR[1]) - break; - else - saw_first_half_of_eol = FALSE; - } - else if (c == APR_EOL_STR[0]) + /* Check for cancellation after a character has been read, some + input processing modes may eat ^C and we'll only notice a + cancellation signal after characters have been read -- + sometimes even after a newline. */ + if (pb) + SVN_ERR(pb->cancel_func(pb->cancel_baton)); + + switch (code) + { + case TERMINAL_NONE: + /* Nothing useful happened; retry. */ + continue; + + case TERMINAL_DEL: + /* Delete the last input character. terminal_getc takes care + of erasing the feedback from the terminal, if applicable. */ + svn_stringbuf_chop(strbuf, 1); + continue; + + case TERMINAL_EOL: + /* End-of-line means end of input. Trick the EOL-detection code + below to stop reading. */ + saw_first_half_of_eol = TRUE; + c = APR_EOL_STR[1]; /* Could be \0 but still stops reading. */ + break; + + case TERMINAL_EOF: + return svn_error_create( + APR_EOF, + terminal_close(terminal), + _("End of file while reading from terminal")); + + default: + /* Convert the returned code back to the character. */ + c = (char)code; + } + + if (saw_first_half_of_eol) + { + if (c == APR_EOL_STR[1]) + break; + else + saw_first_half_of_eol = FALSE; + } + else if (c == APR_EOL_STR[0]) + { + /* GCC might complain here: "warning: will never be executed" + * That's fine. This is a compile-time check for "\r\n\0" */ + if (sizeof(APR_EOL_STR) == 3) { - /* GCC might complain here: "warning: will never be executed" - * That's fine. This is a compile-time check for "\r\n\0" */ - if (sizeof(APR_EOL_STR) == 3) - { - saw_first_half_of_eol = TRUE; - continue; - } - else if (sizeof(APR_EOL_STR) == 2) - break; - else - /* ### APR_EOL_STR holds more than two chars? Who - ever heard of such a thing? */ - SVN_ERR_MALFUNCTION(); + saw_first_half_of_eol = TRUE; + continue; } - - svn_stringbuf_appendbyte(strbuf, c); + else if (sizeof(APR_EOL_STR) == 2) + break; + else + /* ### APR_EOL_STR holds more than two chars? Who + ever heard of such a thing? */ + SVN_ERR_MALFUNCTION(); } + + svn_stringbuf_appendbyte(strbuf, c); } - else - { - const char *prompt_stdout; - size_t bufsize = 300; - SVN_ERR(svn_cmdline_cstring_from_utf8(&prompt_stdout, prompt_msg, - pool)); - svn_stringbuf_ensure(strbuf, bufsize); - status = apr_password_get(prompt_stdout, strbuf->data, &bufsize); - if (status) - return svn_error_wrap_apr(status, _("Can't get password")); + if (terminal->noecho) + { + /* If terminal echo was turned off, make sure future output + to the terminal starts on a new line, as expected. */ + terminal_puts(APR_EOL_STR, terminal, pool); } + SVN_ERR(terminal_close(terminal)); return svn_cmdline_cstring_to_utf8(result, strbuf->data, pool); } @@ -179,9 +538,13 @@ maybe_print_realm(const char *realm, apr { if (realm) { - SVN_ERR(svn_cmdline_fprintf(stderr, pool, - _("Authentication realm: %s\n"), realm)); - fflush(stderr); + terminal_handle_t *terminal; + SVN_ERR(terminal_open(&terminal, FALSE, pool)); + SVN_ERR(terminal_puts( + apr_psprintf(pool, + _("Authentication realm: %s\n"), realm), + terminal, pool)); + SVN_ERR(terminal_close(terminal)); } return SVN_NO_ERROR; @@ -396,13 +759,17 @@ plaintext_prompt_helper(svn_boolean_t *m svn_boolean_t answered = FALSE; svn_cmdline_prompt_baton2_t *pb = baton; const char *config_path = NULL; + terminal_handle_t *terminal; if (pb) SVN_ERR(svn_config_get_user_config_path(&config_path, pb->config_dir, SVN_CONFIG_CATEGORY_SERVERS, pool)); - SVN_ERR(svn_cmdline_fprintf(stderr, pool, prompt_text, realmstring, - config_path)); + SVN_ERR(terminal_open(&terminal, FALSE, pool)); + SVN_ERR(terminal_puts(apr_psprintf(pool, prompt_text, + realmstring, config_path), + terminal, pool)); + SVN_ERR(terminal_close(terminal)); do { Modified: subversion/branches/ev2-export/subversion/libsvn_subr/simple_providers.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/simple_providers.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_subr/simple_providers.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_subr/simple_providers.c Sat Feb 23 01:25:38 2013 @@ -29,6 +29,9 @@ #include <apr_pools.h> #include "svn_auth.h" +#include "svn_dirent_uri.h" +#include "svn_hash.h" +#include "svn_pools.h" #include "svn_error.h" #include "svn_utf.h" #include "svn_config.h" @@ -37,6 +40,8 @@ #include "private/svn_auth_private.h" #include "svn_private_config.h" + +#include "auth.h" /*-----------------------------------------------------------------------*/ /* File provider */ @@ -372,8 +377,9 @@ svn_auth__simple_creds_cache_set(svn_boo simple_provider_baton_t *b = (simple_provider_baton_t *)provider_baton; - if (svn_cstring_casecmp(store_plaintext_passwords, - SVN_CONFIG_ASK) == 0) + if (store_plaintext_passwords + && svn_cstring_casecmp(store_plaintext_passwords, + SVN_CONFIG_ASK) == 0) { if (non_interactive) /* In non-interactive mode, the default behaviour is @@ -438,13 +444,15 @@ svn_auth__simple_creds_cache_set(svn_boo may_save_password = TRUE; } } - else if (svn_cstring_casecmp(store_plaintext_passwords, - SVN_CONFIG_FALSE) == 0) + else if (store_plaintext_passwords + && svn_cstring_casecmp(store_plaintext_passwords, + SVN_CONFIG_FALSE) == 0) { may_save_password = FALSE; } - else if (svn_cstring_casecmp(store_plaintext_passwords, - SVN_CONFIG_TRUE) == 0) + else if (!store_plaintext_passwords + || svn_cstring_casecmp(store_plaintext_passwords, + SVN_CONFIG_TRUE) == 0) { may_save_password = TRUE; } @@ -517,6 +525,133 @@ simple_save_creds(svn_boolean_t *saved, pool); } +svn_error_t * +svn_auth__simple_cleanup_walk(svn_auth_baton_t *baton, + svn_auth_cleanup_callback cleanup, + void *cleanup_baton, + apr_hash_t *creds_cache, + apr_pool_t *scratch_pool) +{ + const char *config_dir; + svn_boolean_t no_auth_cache; + int i; + apr_pool_t *iterpool; + + const char *cred_kinds[] = + { + SVN_AUTH_CRED_SIMPLE, + SVN_AUTH_CRED_USERNAME, + SVN_AUTH_CRED_SSL_CLIENT_CERT, + SVN_AUTH_CRED_SSL_CLIENT_CERT_PW, + SVN_AUTH_CRED_SSL_SERVER_TRUST, + NULL + }; + + config_dir = svn_auth_get_parameter(baton, SVN_AUTH_PARAM_CONFIG_DIR); + no_auth_cache = (svn_auth_get_parameter(baton, SVN_AUTH_PARAM_NO_AUTH_CACHE) + != NULL); + + if ((! config_dir) || no_auth_cache) + { + /* Can't locate the cache to clear */ + return SVN_NO_ERROR; + } + + iterpool = svn_pool_create(scratch_pool); + for (i = 0; cred_kinds[i]; i++) + { + const char *item_path; + const char *dir_path; + apr_hash_t *nodes; + svn_error_t *err; + apr_pool_t *itempool; + apr_hash_index_t *hi; + + svn_pool_clear(iterpool); + + SVN_ERR(svn_auth__file_path(&item_path, cred_kinds[i], "!", config_dir, + iterpool)); + + dir_path = svn_dirent_dirname(item_path, iterpool); + + err = svn_io_get_dirents3(&nodes, dir_path, TRUE, iterpool, iterpool); + + if (err) + { + if (!APR_STATUS_IS_ENOENT(err->apr_err) + && !SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)) + return svn_error_trace(err); + + svn_error_clear(err); + continue; + } + + itempool = svn_pool_create(iterpool); + for (hi = apr_hash_first(iterpool, nodes); hi; hi = apr_hash_next(hi)) + { + svn_io_dirent2_t *dirent = svn__apr_hash_index_val(hi); + svn_stream_t *stream; + apr_hash_t *file_data; + + if (dirent->kind != svn_node_file) + continue; + + svn_pool_clear(itempool); + + item_path = svn_dirent_join(dir_path, svn__apr_hash_index_key(hi), + itempool); + + err = svn_stream_open_readonly(&stream, item_path, itempool, itempool); + if (err) + { + /* Ignore this file. There are no credentials in it anyway */ + svn_error_clear(err); + continue; + } + + file_data = apr_hash_make(itempool); + err = svn_hash_read2(file_data, stream, SVN_HASH_TERMINATOR, itempool); + err = svn_error_compose_create(err, svn_stream_close(stream)); + if (err) + { + /* Ignore this file. There are no credentials in it anyway */ + svn_error_clear(err); + continue; + } + + { + const svn_string_t *realm = svn_hash_gets(file_data, SVN_CONFIG_REALMSTRING_KEY); + svn_boolean_t delete_file = FALSE; + + if (! realm) + continue; /* Not an auth file */ + + SVN_ERR(cleanup(&delete_file, cleanup_baton, cred_kinds[i], realm->data, + SVN_AUTH_CRED_SIMPLE, itempool)); + + if (delete_file) + { + /* Delete from the credential hash */ + const char *cache_key = apr_pstrcat(itempool, + cred_kinds[0], + ":", + realm->data, + (char *)NULL); + + svn_hash_sets(creds_cache, cache_key, NULL); + + /* And the file on disk */ + SVN_ERR(svn_io_remove_file2(item_path, TRUE, itempool)); + } + } + } + } + + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; +} + + static const svn_auth_provider_t simple_provider = { SVN_AUTH_CRED_SIMPLE, simple_first_creds, @@ -718,7 +853,6 @@ simple_prompt_next_creds(void **credenti ! no_auth_cache, pool); } - static const svn_auth_provider_t simple_prompt_provider = { SVN_AUTH_CRED_SIMPLE, simple_prompt_first_creds, Modified: subversion/branches/ev2-export/subversion/libsvn_subr/sorts.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/sorts.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_subr/sorts.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_subr/sorts.c Sat Feb 23 01:25:38 2013 @@ -270,3 +270,39 @@ svn_sort__array_delete(apr_array_header_ arr->nelts -= elements_to_delete; } } + +void +svn_sort__array_reverse(apr_array_header_t *array, + apr_pool_t *scratch_pool) +{ + int i; + + if (array->elt_size == sizeof(void *)) + { + for (i = 0; i < array->nelts / 2; i++) + { + int swap_index = array->nelts - i - 1; + void *tmp = APR_ARRAY_IDX(array, i, void *); + + APR_ARRAY_IDX(array, i, void *) = + APR_ARRAY_IDX(array, swap_index, void *); + APR_ARRAY_IDX(array, swap_index, void *) = tmp; + } + } + else + { + apr_size_t sz = array->elt_size; + char *tmp = apr_palloc(scratch_pool, sz); + + for (i = 0; i < array->nelts / 2; i++) + { + int swap_index = array->nelts - i - 1; + char *x = array->elts + (sz * i); + char *y = array->elts + (sz * swap_index); + + memcpy(tmp, x, sz); + memcpy(x, y, sz); + memcpy(y, tmp, sz); + } + } +} Modified: subversion/branches/ev2-export/subversion/libsvn_subr/sqlite.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/sqlite.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_subr/sqlite.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_subr/sqlite.c Sat Feb 23 01:25:38 2013 @@ -140,8 +140,9 @@ struct svn_sqlite__value_t int sqlite_err__temp = (x); \ if (sqlite_err__temp != SQLITE_OK) \ return svn_error_createf(SQLITE_ERROR_CODE(sqlite_err__temp), \ - NULL, "sqlite: %s", \ - sqlite3_errmsg((db)->db3)); \ + NULL, "sqlite: %s (%d)", \ + sqlite3_errmsg((db)->db3), \ + sqlite_err__temp); \ } while (0) #define SQLITE_ERR_MSG(x, msg) do \ @@ -149,7 +150,8 @@ struct svn_sqlite__value_t int sqlite_err__temp = (x); \ if (sqlite_err__temp != SQLITE_OK) \ return svn_error_createf(SQLITE_ERROR_CODE(sqlite_err__temp), \ - NULL, "sqlite: %s", (msg)); \ + NULL, "sqlite: %s (%d)", (msg), \ + sqlite_err__temp); \ } while (0) @@ -171,8 +173,9 @@ exec_sql2(svn_sqlite__db_t *db, const ch if (sqlite_err != SQLITE_OK && sqlite_err != ignored_err) { svn_error_t *err = svn_error_createf(SQLITE_ERROR_CODE(sqlite_err), NULL, - _("sqlite: %s, executing statement '%s'"), - err_msg, sql); + _("sqlite: %s (%d)," + " executing statement '%s'"), + err_msg, sqlite_err, sql); sqlite3_free(err_msg); return err; } @@ -289,7 +292,8 @@ svn_sqlite__step(svn_boolean_t *got_row, svn_error_t *err1, *err2; err1 = svn_error_createf(SQLITE_ERROR_CODE(sqlite_result), NULL, - "sqlite: %s", sqlite3_errmsg(stmt->db->db3)); + "sqlite: %s (%d)", + sqlite3_errmsg(stmt->db->db3), sqlite_result); err2 = svn_sqlite__reset(stmt); return svn_error_compose_create(err1, err2); } @@ -739,8 +743,8 @@ init_sqlite(void *baton, apr_pool_t *poo { int err = sqlite3_config(SQLITE_CONFIG_MULTITHREAD); if (err != SQLITE_OK && err != SQLITE_MISUSE) - return svn_error_create(SQLITE_ERROR_CODE(err), NULL, - _("Could not configure SQLite")); + return svn_error_createf(SQLITE_ERROR_CODE(err), NULL, + _("Could not configure SQLite (%d)"), err); } SQLITE_ERR_MSG(sqlite3_initialize(), _("Could not initialize SQLite")); @@ -793,7 +797,8 @@ internal_open(sqlite3 **db3, const char sqlite3_close(*db3); return svn_error_createf(SQLITE_ERROR_CODE(err_code), NULL, - "sqlite: %s: '%s'", msg, path); + "sqlite: %s (%d): '%s'", + msg, err_code, path); } } } @@ -863,7 +868,7 @@ close_apr(void *data) } if (result != SQLITE_OK) - return SQLITE_ERROR_CODE(result); + return SQLITE_ERROR_CODE(result); /* ### lossy */ db->db3 = NULL; Modified: subversion/branches/ev2-export/subversion/libsvn_wc/adm_crawler.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/adm_crawler.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_wc/adm_crawler.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_wc/adm_crawler.c Sat Feb 23 01:25:38 2013 @@ -58,8 +58,8 @@ last-commit-time. Either way, set entry-timestamp to match that of the working file when all is finished. - If REMOVE_TEXT_CONFLICT is TRUE, remove an existing text conflict - from LOCAL_ABSPATH. + If MARK_RESOLVED_TEXT_CONFLICT is TRUE, mark as resolved any existing + text conflict on LOCAL_ABSPATH. Not that a valid access baton with a write lock to the directory of LOCAL_ABSPATH must be available in DB.*/ @@ -67,7 +67,7 @@ static svn_error_t * restore_file(svn_wc__db_t *db, const char *local_abspath, svn_boolean_t use_commit_times, - svn_boolean_t remove_text_conflicts, + svn_boolean_t mark_resolved_text_conflict, apr_pool_t *scratch_pool) { svn_skel_t *work_item; @@ -89,8 +89,8 @@ restore_file(svn_wc__db_t *db, scratch_pool)); /* Remove any text conflict */ - if (remove_text_conflicts) - SVN_ERR(svn_wc__resolve_text_conflict(db, local_abspath, scratch_pool)); + if (mark_resolved_text_conflict) + SVN_ERR(svn_wc__mark_resolved_text_conflict(db, local_abspath, scratch_pool)); return SVN_NO_ERROR; } @@ -135,7 +135,8 @@ svn_wc_restore(svn_wc_context_t *wc_ctx, } if (kind == svn_kind_file || kind == svn_kind_symlink) - SVN_ERR(restore_file(wc_ctx->db, local_abspath, use_commit_times, FALSE, + SVN_ERR(restore_file(wc_ctx->db, local_abspath, use_commit_times, + FALSE /*mark_resolved_text_conflict*/, scratch_pool)); else SVN_ERR(svn_io_dir_make(local_abspath, APR_OS_DEFAULT, scratch_pool)); @@ -161,8 +162,9 @@ restore_node(svn_wc__db_t *db, { if (kind == svn_kind_file || kind == svn_kind_symlink) { - /* Recreate file from text-base */ - SVN_ERR(restore_file(db, local_abspath, use_commit_times, TRUE, + /* Recreate file from text-base; mark any text conflict as resolved */ + SVN_ERR(restore_file(db, local_abspath, use_commit_times, + TRUE /*mark_resolved_text_conflict*/, scratch_pool)); } else if (kind == svn_kind_dir) Modified: subversion/branches/ev2-export/subversion/libsvn_wc/adm_files.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/adm_files.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_wc/adm_files.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_wc/adm_files.c Sat Feb 23 01:25:38 2013 @@ -570,40 +570,6 @@ svn_wc__adm_cleanup_tmp_area(svn_wc__db_ } - -svn_error_t * -svn_wc_create_tmp_file2(apr_file_t **fp, - const char **new_name, - const char *path, - svn_io_file_del_t delete_when, - apr_pool_t *pool) -{ - svn_wc__db_t *db; - const char *local_abspath; - const char *temp_dir; - svn_error_t *err; - - SVN_ERR_ASSERT(fp || new_name); - - SVN_ERR(svn_wc__db_open(&db, - NULL /* config */, - FALSE /* auto_upgrade */, - TRUE /* enforce_empty_wq */, - pool, pool)); - - SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool)); - err = svn_wc__db_temp_wcroot_tempdir(&temp_dir, db, local_abspath, - pool, pool); - err = svn_error_compose_create(err, svn_wc__db_close(db)); - if (err) - return svn_error_trace(err); - - SVN_ERR(svn_io_open_unique_file3(fp, new_name, temp_dir, - delete_when, pool, pool)); - - return SVN_NO_ERROR; -} - svn_error_t * svn_wc__get_tmpdir(const char **tmpdir_abspath, svn_wc_context_t *wc_ctx, Modified: subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c?rev=1449262&r1=1449261&r2=1449262&view=diff ============================================================================== --- subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c (original) +++ subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c Sat Feb 23 01:25:38 2013 @@ -1249,9 +1249,19 @@ svn_wc_remove_lock2(svn_wc_context_t *wc } /* if svn:needs-lock is present, then make the file read-only. */ - SVN_ERR(svn_wc__internal_propget(&needs_lock, wc_ctx->db, local_abspath, - SVN_PROP_NEEDS_LOCK, scratch_pool, - scratch_pool)); + err = svn_wc__internal_propget(&needs_lock, wc_ctx->db, local_abspath, + SVN_PROP_NEEDS_LOCK, scratch_pool, + scratch_pool); + if (err) + { + if (err->apr_err != SVN_ERR_WC_PATH_UNEXPECTED_STATUS) + return svn_error_trace(err); + + svn_error_clear(err); + return SVN_NO_ERROR; /* Node is shadowed and/or deleted, + so we shouldn't apply its lock */ + } + if (needs_lock) SVN_ERR(svn_io_set_file_read_only(local_abspath, FALSE, scratch_pool));
