On Thu, Apr 30, 2009 at 17:01, Hyrum K. Wright <hyrum_at_hyrumwright.org> wrote:
>...
> +++ trunk/subversion/libsvn_wc/upgrade.c     Thu Apr 30 08:01:58 2009     (r37513)
>...
> +/* Helper for converting wcprops from the one-file-per-file model.
> + Â This implements svn_io_walk_func_t(). */
> +static svn_error_t *
> +convert_props_walker(void *baton,
> + Â Â Â Â Â Â Â Â Â Â const char *path,
> + Â Â Â Â Â Â Â Â Â Â const apr_finfo_t *finfo,
> + Â Â Â Â Â Â Â Â Â Â apr_pool_t *pool)
> +{
> + Â svn_wc__db_t *db = baton;
> + Â apr_hash_t *proplist;
> + Â apr_file_t *file;
> + Â svn_stream_t *stream;
> + Â const char *local_abspath;
> + Â int len;
> +
> + Â /* Skip the directory. */
> + Â if (finfo->filetype == APR_DIR)
> + Â Â return SVN_NO_ERROR;
> +
> + Â proplist = apr_hash_make(pool);
> + Â SVN_ERR(svn_io_file_open(&file, path, APR_READ | APR_BUFFERED,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â APR_OS_DEFAULT, pool));
> + Â stream = svn_stream_from_aprfile2(file, FALSE, pool);
> + Â SVN_ERR(svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR, pool));
> + Â SVN_ERR(svn_stream_close(stream));
> +
> + Â /* The filename will be something like foo.c.svn-work. Â From it, determine
> + Â Â the local_abspath of the node. Â The magic number of 9 below is basically
> + Â Â strlen(".svn-work"). */
> + Â len = strlen(path);
> + Â local_abspath = apr_pstrndup(pool, local_abspath, len - 9);
This won't work. local_abspath is never set. And even then, you're
talking about a resulting abspath that looks like
"/some/path/.svn/foo.c" ... you really don't want the .svn in there.
Might I also suggest adding a test case for this to upgrade_tests.py?
>...
> +static svn_error_t *
> +convert_wcprops(svn_wc_adm_access_t *adm_access,
> + Â Â Â Â Â Â Â Â int old_format,
> + Â Â Â Â Â Â Â Â apr_pool_t *scratch_pool)
> +{
> + Â svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
> +
> + Â if (old_format <= SVN_WC__WCPROPS_MANY_FILES_VERSION)
> + Â Â {
> + Â Â Â svn_stream_t *stream;
> + Â Â Â svn_error_t *err;
> + Â Â Â const char *dir_abspath;
> + Â Â Â apr_hash_t *proplist;
> +
> + Â Â Â /* First, look at dir-wcprops. */
> + Â Â Â SVN_ERR(svn_dirent_get_absolute(&dir_abspath,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â svn_wc_adm_access_path(adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â scratch_pool));
dir_abspath = svn_wc__adm_access_abspath(adm_access);
> + Â Â Â err = svn_wc__open_adm_stream(&stream, dir_abspath,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SVN_WC__ADM_DIR_WCPROPS,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â scratch_pool, scratch_pool);
> + Â Â Â if (err)
> + Â Â Â Â {
> + Â Â Â Â Â /* If the file doesn't exist, it means no wcprops. */
> + Â Â Â Â Â if (APR_STATUS_IS_ENOENT(err->apr_err))
> + Â Â Â Â Â Â svn_error_clear(err);
> + Â Â Â Â Â else
> + Â Â Â Â Â Â return svn_error_return(err);
> + Â Â Â Â }
> + Â Â Â else
> + Â Â Â Â {
> + Â Â Â Â Â proplist = apr_hash_make(scratch_pool);
> + Â Â Â Â Â SVN_ERR(svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â scratch_pool));
> + Â Â Â Â Â SVN_ERR(svn_wc__db_base_set_dav_cache(db, dir_abspath, proplist,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â scratch_pool));
> + Â Â Â Â }
> +
> + Â Â Â /* Now walk the wcprops directory. */
> + Â Â Â SVN_ERR(svn_io_dir_walk(svn_wc__adm_child(svn_wc_adm_access_path(
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SVN_WC__ADM_WCPROPS,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â scratch_pool),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0 /* wanted */,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â convert_props_walker,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â db, scratch_pool));
I understand this was the original/old code, but why walk rather than
simply fetching the dirents?
> + Â Â }
> + Â else
> + Â Â {
> + Â Â Â apr_hash_t *allprops;
> + Â Â Â apr_hash_index_t *hi;
> + Â Â Â apr_pool_t *iterpool;
> +
> + Â Â Â /* Read the all-wcprops file. */
> + Â Â Â SVN_ERR(read_wcprops(&allprops, db, svn_wc_adm_access_path(adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â scratch_pool, scratch_pool));
> +
> + Â Â Â /* Iterate over all the wcprops, writing each one to the wc_db. */
> + Â Â Â iterpool = svn_pool_create(scratch_pool);
> + Â Â Â for (hi = apr_hash_first(scratch_pool, allprops); hi;
> + Â Â Â Â Â Â hi = apr_hash_next(hi))
> + Â Â Â Â {
> + Â Â Â Â Â const void *key;
> + Â Â Â Â Â void *val;
> + Â Â Â Â Â const char *name;
> + Â Â Â Â Â apr_hash_t *proplist;
> + Â Â Â Â Â const char *local_abspath;
> +
> + Â Â Â Â Â svn_pool_clear(iterpool);
> +
> + Â Â Â Â Â apr_hash_this(hi, &key, NULL, &val);
> + Â Â Â Â Â name = key;
> + Â Â Â Â Â proplist = val;
> +
> + Â Â Â Â Â SVN_ERR(svn_dirent_get_absolute(&local_abspath,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â svn_wc_adm_access_path(adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iterpool));
I'd call this dir_abspath, locate it outside the loop, and use
svn_wc__adm_access_abspath() to get it.
> + Â Â Â Â Â local_abspath = svn_dirent_join(local_abspath, name, iterpool);
> + Â Â Â Â Â SVN_ERR(svn_wc__db_base_set_dav_cache(db, local_abspath, proplist,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â iterpool));
> + Â Â Â Â }
> + Â Â Â svn_pool_destroy(iterpool);
> + Â Â }
> +
> + Â return SVN_NO_ERROR;
> +}
> +
> +
> +svn_error_t *
> +svn_wc__upgrade_format(svn_wc_adm_access_t *adm_access,
> + Â Â Â Â Â Â Â Â Â Â Â apr_pool_t *scratch_pool)
> +{
> + Â int wc_format;
> + Â svn_boolean_t cleanup_required;
> + Â svn_stringbuf_t *log_accum;
> + Â const svn_wc_entry_t *this_dir;
> +
> + Â SVN_ERR(svn_wc__adm_wc_format(&wc_format, adm_access, scratch_pool));
> +
> + Â if (wc_format > SVN_WC__VERSION)
> + Â Â {
> + Â Â Â return svn_error_createf
> + Â Â Â Â (SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
> + Â Â Â Â _("This client is too old to work with working copy '%s'. Â You need\n"
> + Â Â Â Â Â "to get a newer Subversion client, or to downgrade this working "
> + Â Â Â Â Â "copy.\n"
> + Â Â Â Â Â "See "
> + Â Â Â Â Â "http://subversion.tigris.org/faq.html#working-copy-format-change\n"
> + Â Â Â Â Â "for details."
> + Â Â Â Â Â ),
> + Â Â Â Â svn_path_local_style(svn_wc_adm_access_path(adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â scratch_pool));
> + Â Â }
> +
> + Â /* We can upgrade all formats that are accepted by check_format(). */
> + Â if (wc_format >= SVN_WC__VERSION)
> + Â Â return SVN_NO_ERROR;
This test makes no sense. You already checked for greater-than above.
Further, the comment *totally* doesn't describe what is going on here.
> +
> + Â /* Don't try to mess with the WC if there are old log files left. */
> + Â SVN_ERR(svn_wc__adm_is_cleanup_required(&cleanup_required,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â adm_access, scratch_pool));
> +
> + Â if (cleanup_required)
> + Â Â return svn_error_create(SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â _("Cannot upgrade with existing logs; please "
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â "run 'svn cleanup' with Subversion 1.6"));
> +
> + Â /* What's going on here?
> + Â *
> + Â * We're attempting to upgrade an older working copy to the new wc-ng format.
> + Â * The sematics and storage mechanisms between the two are vastly different,
> + Â * so it's going to be a bit painful. Â Here's a plan for the operation:
> + Â *
> + Â * 1) The 'entries' file needs to be moved to the new format. Â Ideally, we'd
> + Â * Â Â read it using svn_wc__entries_read_old(), and then translate the
> + Â * Â Â current state of the file into a series of wc_db commands to duplicate
> + Â * Â Â that state in WC-NG. Â We're not quite there yet, so we just use
> + Â * Â Â the same loggy process as we always have, relying on the lower layers
> + Â * Â Â to take care of the translation, and remembering to remove the old
> + Â * Â Â entries file when were're done. Â ### This isn't a long-term solution.
> + Â *
> + Â * 2) Convert wcprop to the wc-ng format
> + Â *
> + Â * ### (fill in other bits as they are implemented)
> + Â */
> +
> + Â /***** ENTRIES *****/
> + Â /* Create an empty sqlite database for this directory. */
> + Â SVN_ERR(svn_wc_entry(&this_dir, svn_wc_adm_access_path(adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â adm_access, FALSE, scratch_pool));
> + Â SVN_ERR(svn_wc__entries_init(svn_wc_adm_access_path(adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â this_dir->uuid, this_dir->url,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â this_dir->repos, this_dir->revision,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â this_dir->depth, scratch_pool));
> +
> + Â /* Migrate the entries over to the new database.
> + Â Â ### We need to thing about atomicity here. */
> + Â SVN_ERR(svn_wc__entries_upgrade(adm_access, SVN_WC__VERSION, scratch_pool));
> + Â svn_error_clear(svn_io_remove_file(svn_wc__adm_child(svn_wc_adm_access_path(
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SVN_WC__ADM_FORMAT,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â scratch_pool),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â scratch_pool));
> + Â SVN_ERR(svn_io_remove_file(svn_wc__adm_child(svn_wc_adm_access_path(
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SVN_WC__ADM_ENTRIES,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â scratch_pool),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â scratch_pool));
> +
> + Â /* ### Note that lots of this content is cribbed from the old format updater.
> + Â Â ### The following code will change as the wc-ng format changes and more
> + Â Â ### stuff gets migrated to the sqlite format. */
> +
> + Â log_accum = svn_stringbuf_create("", scratch_pool);
> +
> + Â /***** WC PROPS *****/
> + Â SVN_ERR(convert_wcprops(adm_access, wc_format, scratch_pool));
> +
> + Â SVN_ERR(svn_wc__write_log(adm_access, 0, log_accum, scratch_pool));
eh? what is this write_log doing here?
> +
> + Â if (wc_format <= SVN_WC__WCPROPS_MANY_FILES_VERSION)
> + Â Â {
> + Â Â Â /* Remove wcprops directory, dir-props, README.txt and empty-file
> + Â Â Â Â files.
> + Â Â Â Â We just silently ignore errors, because keeping these files is
> + Â Â Â Â not catastrophic. */
> +
> + Â Â Â svn_error_clear(svn_io_remove_dir2(
> + Â Â Â Â Â svn_wc__adm_child(svn_wc_adm_access_path(adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â SVN_WC__ADM_WCPROPS, scratch_pool),
> + Â Â Â Â Â FALSE, NULL, NULL, scratch_pool));
> + Â Â Â svn_error_clear(svn_io_remove_file(
> + Â Â Â Â Â svn_wc__adm_child(svn_wc_adm_access_path(adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â SVN_WC__ADM_DIR_WCPROPS, scratch_pool),
> + Â Â Â Â Â scratch_pool));
> + Â Â Â svn_error_clear(svn_io_remove_file(
> + Â Â Â Â Â svn_wc__adm_child(svn_wc_adm_access_path(adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â SVN_WC__ADM_EMPTY_FILE, scratch_pool),
> + Â Â Â Â Â scratch_pool));
> + Â Â Â svn_error_clear(svn_io_remove_file(
> + Â Â Â Â Â svn_wc__adm_child(svn_wc_adm_access_path(adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â SVN_WC__ADM_README, scratch_pool),
> + Â Â Â Â Â scratch_pool));
> + Â Â }
> + Â else
> + Â Â {
> + Â Â Â svn_error_clear(svn_io_remove_file(
> + Â Â Â Â Â svn_wc__adm_child(svn_wc_adm_access_path(adm_access),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â SVN_WC__ADM_ALL_WCPROPS, scratch_pool),
> + Â Â Â Â Â scratch_pool));
> + Â Â }
> +
> + Â return svn_wc__run_log(adm_access, NULL, scratch_pool);
and what is this? you didn't put anything into log_accum.
>...
Cheers,
-g
------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=462&dsMessageId=2070805
Received on 2009-05-05 18:41:41 CEST