You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/12/21 01:23:41 UTC
svn commit: r1424772 [3/4] - in /subversion/branches/ev2-export: ./ build/
build/ac-macros/ build/win32/ subversion/bindings/cxxhl/include/
subversion/bindings/cxxhl/include/svncxxhl/
subversion/bindings/cxxhl/include/types/ subversion/bindings/cxxhl/s...
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c Fri Dec 21 00:23:39 2012
@@ -1422,29 +1422,21 @@ does_node_exist(svn_boolean_t *exists,
return svn_error_trace(svn_sqlite__reset(stmt));
}
-/* Baton for passing args to init_db(). */
-struct init_db_baton
-{
- /* output values */
- apr_int64_t wc_id;
- apr_int64_t repos_id;
- /* input values */
- const char *repos_root_url;
- const char *repos_uuid;
- const char *root_node_repos_relpath;
- svn_revnum_t root_node_revision;
- svn_depth_t root_node_depth;
-};
-
/* Helper for create_db(). Initializes our wc.db schema.
- *
- * Implements svn_sqlite__transaction_callback_t. */
+ */
static svn_error_t *
-init_db(void *baton,
+init_db(/* output values */
+ apr_int64_t *repos_id,
+ apr_int64_t *wc_id,
+ /* input values */
svn_sqlite__db_t *db,
+ const char *repos_root_url,
+ const char *repos_uuid,
+ const char *root_node_repos_relpath,
+ svn_revnum_t root_node_revision,
+ svn_depth_t root_node_depth,
apr_pool_t *scratch_pool)
{
- struct init_db_baton *idb = baton;
svn_sqlite__stmt_t *stmt;
/* Create the database's schema. */
@@ -1454,33 +1446,33 @@ init_db(void *baton,
SVN_ERR(svn_sqlite__exec_statements(db, STMT_CREATE_EXTERNALS));
/* Insert the repository. */
- SVN_ERR(create_repos_id(&idb->repos_id, idb->repos_root_url, idb->repos_uuid,
+ SVN_ERR(create_repos_id(repos_id, repos_root_url, repos_uuid,
db, scratch_pool));
/* Insert the wcroot. */
/* ### Right now, this just assumes wc metadata is being stored locally. */
SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_INSERT_WCROOT));
- SVN_ERR(svn_sqlite__insert(&idb->wc_id, stmt));
+ SVN_ERR(svn_sqlite__insert(wc_id, stmt));
- if (idb->root_node_repos_relpath)
+ if (root_node_repos_relpath)
{
svn_wc__db_status_t status = svn_wc__db_status_normal;
- if (idb->root_node_revision > 0)
+ if (root_node_revision > 0)
status = svn_wc__db_status_incomplete; /* Will be filled by update */
SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_INSERT_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "isdsisrtst",
- idb->wc_id, /* 1 */
+ *wc_id, /* 1 */
"", /* 2 */
0, /* op_depth is 0 for base */
NULL, /* 4 */
- idb->repos_id,
- idb->root_node_repos_relpath,
- idb->root_node_revision,
+ *repos_id,
+ root_node_repos_relpath,
+ root_node_revision,
presence_map, status, /* 8 */
svn_token__to_word(depth_map,
- idb->root_node_depth),
+ root_node_depth),
kind_map, svn_kind_dir /* 10 */));
SVN_ERR(svn_sqlite__insert(NULL, stmt));
@@ -1513,23 +1505,16 @@ create_db(svn_sqlite__db_t **sdb,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- struct init_db_baton idb;
-
SVN_ERR(svn_wc__db_util_open_db(sdb, dir_abspath, sdb_fname,
svn_sqlite__mode_rwcreate, exclusive,
NULL /* my_statements */,
result_pool, scratch_pool));
- idb.repos_root_url = repos_root_url;
- idb.repos_uuid = repos_uuid;
- idb.root_node_repos_relpath = root_node_repos_relpath;
- idb.root_node_revision = root_node_revision;
- idb.root_node_depth = root_node_depth;
-
- SVN_ERR(svn_sqlite__with_lock(*sdb, init_db, &idb, scratch_pool));
-
- *repos_id = idb.repos_id;
- *wc_id = idb.wc_id;
+ SVN_SQLITE__WITH_LOCK(init_db(repos_id, wc_id,
+ *sdb, repos_root_url, repos_uuid,
+ root_node_repos_relpath, root_node_revision,
+ root_node_depth, scratch_pool),
+ *sdb);
return SVN_NO_ERROR;
}
@@ -4925,6 +4910,7 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
svn_error_t *
svn_wc__db_op_add_directory(svn_wc__db_t *db,
const char *local_abspath,
+ const apr_hash_t *props,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
@@ -4948,6 +4934,11 @@ svn_wc__db_op_add_directory(svn_wc__db_t
iwb.presence = svn_wc__db_status_normal;
iwb.kind = svn_kind_dir;
iwb.op_depth = relpath_depth(local_relpath);
+ if (props && apr_hash_count((apr_hash_t *)props))
+ {
+ iwb.update_actual_props = TRUE;
+ iwb.new_actual_props = props;
+ }
iwb.work_items = work_items;
@@ -4965,6 +4956,7 @@ svn_wc__db_op_add_directory(svn_wc__db_t
svn_error_t *
svn_wc__db_op_add_file(svn_wc__db_t *db,
const char *local_abspath,
+ const apr_hash_t *props,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
@@ -4988,6 +4980,11 @@ svn_wc__db_op_add_file(svn_wc__db_t *db,
iwb.presence = svn_wc__db_status_normal;
iwb.kind = svn_kind_file;
iwb.op_depth = relpath_depth(local_relpath);
+ if (props && apr_hash_count((apr_hash_t *)props))
+ {
+ iwb.update_actual_props = TRUE;
+ iwb.new_actual_props = props;
+ }
iwb.work_items = work_items;
@@ -5003,6 +5000,7 @@ svn_error_t *
svn_wc__db_op_add_symlink(svn_wc__db_t *db,
const char *local_abspath,
const char *target,
+ const apr_hash_t *props,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
@@ -5029,6 +5027,11 @@ svn_wc__db_op_add_symlink(svn_wc__db_t *
iwb.presence = svn_wc__db_status_normal;
iwb.kind = svn_kind_symlink;
iwb.op_depth = relpath_depth(local_relpath);
+ if (props && apr_hash_count((apr_hash_t *)props))
+ {
+ iwb.update_actual_props = TRUE;
+ iwb.new_actual_props = props;
+ }
iwb.target = target;
@@ -9166,6 +9169,7 @@ struct read_inherited_props_baton_t
{
apr_array_header_t *iprops;
const char *propname;
+ const char *repos_root_url;
apr_pool_t *result_pool;
};
@@ -9288,7 +9292,15 @@ db_read_inherited_props(void *baton,
/* If we didn't filter everything then keep this iprop. */
if (apr_hash_count(cached_iprop->prop_hash))
- svn_sort__array_insert(&cached_iprop, ripb->iprops, 0);
+ {
+ /* Convert the repository relative path in the
+ cache to a full URL. */
+ cached_iprop->path_or_url =
+ svn_path_url_add_component2(ripb->repos_root_url,
+ cached_iprop->path_or_url,
+ result_pool);
+ svn_sort__array_insert(&cached_iprop, ripb->iprops, 0);
+ }
}
}
@@ -9307,9 +9319,14 @@ svn_wc__db_read_inherited_props(apr_arra
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
struct read_inherited_props_baton_t ripb;
+ const char *repos_root_url;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+ SVN_ERR(svn_wc__internal_get_repos_info(&repos_root_url, NULL, db,
+ local_abspath, scratch_pool,
+ scratch_pool));
+
SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
db, local_abspath,
scratch_pool, scratch_pool));
@@ -9317,6 +9334,7 @@ svn_wc__db_read_inherited_props(apr_arra
ripb.iprops = NULL;
ripb.propname = propname;
+ ripb.repos_root_url = repos_root_url;
ripb.result_pool = result_pool;
SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, db_read_inherited_props,
@@ -9501,9 +9519,9 @@ svn_wc__db_read_children_of_working_node
/* Baton for passing args to check_replace_txn(). */
struct check_replace_baton
{
- svn_boolean_t *is_replace_root;
- svn_boolean_t *base_replace;
- svn_boolean_t is_replace;
+ svn_boolean_t *is_replace_root_p;
+ svn_boolean_t *base_replace_p;
+ svn_boolean_t *is_replace_p;
};
/* Helper for svn_wc__db_node_check_replace().
@@ -9518,6 +9536,7 @@ check_replace_txn(void *baton,
struct check_replace_baton *crb = baton;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
+ svn_boolean_t is_replace = FALSE;
int replaced_op_depth;
svn_wc__db_status_t replaced_status;
@@ -9560,11 +9579,15 @@ check_replace_txn(void *baton,
&& replaced_status != svn_wc__db_status_excluded
&& replaced_status != svn_wc__db_status_server_excluded
&& replaced_status != svn_wc__db_status_base_deleted)
- crb->is_replace = TRUE;
+ {
+ is_replace = TRUE;
+ if (crb->is_replace_p)
+ *crb->is_replace_p = TRUE;
+ }
replaced_op_depth = svn_sqlite__column_int(stmt, 0);
- if (crb->base_replace)
+ if (crb->base_replace_p)
{
int op_depth = svn_sqlite__column_int(stmt, 0);
@@ -9582,13 +9605,13 @@ check_replace_txn(void *baton,
base_status = svn_sqlite__column_token(stmt, 3, presence_map);
- *crb->base_replace = (base_status != svn_wc__db_status_not_present);
+ *crb->base_replace_p = (base_status != svn_wc__db_status_not_present);
}
}
SVN_ERR(svn_sqlite__reset(stmt));
- if (!crb->is_replace_root || !crb->is_replace)
+ if (!crb->is_replace_root_p || !is_replace)
return SVN_NO_ERROR;
if (replaced_status != svn_wc__db_status_base_deleted)
@@ -9609,7 +9632,7 @@ check_replace_txn(void *baton,
{
/* Did we replace inside our directory? */
- *crb->is_replace_root = (parent_op_depth == replaced_op_depth);
+ *crb->is_replace_root_p = (parent_op_depth == replaced_op_depth);
SVN_ERR(svn_sqlite__reset(stmt));
return SVN_NO_ERROR;
}
@@ -9622,9 +9645,9 @@ check_replace_txn(void *baton,
SVN_ERR(svn_sqlite__reset(stmt));
if (!have_row)
- *crb->is_replace_root = TRUE; /* Parent is no replacement */
+ *crb->is_replace_root_p = TRUE; /* Parent is no replacement */
else if (parent_op_depth < replaced_op_depth)
- *crb->is_replace_root = TRUE; /* Parent replaces a lower layer */
+ *crb->is_replace_root_p = TRUE; /* Parent replaces a lower layer */
/*else // No replacement root */
}
@@ -9652,24 +9675,21 @@ svn_wc__db_node_check_replace(svn_boolea
if (is_replace_root)
*is_replace_root = FALSE;
- if (is_replace)
- *is_replace = FALSE;
if (base_replace)
*base_replace = FALSE;
+ if (is_replace)
+ *is_replace = FALSE;
if (local_relpath[0] == '\0')
return SVN_NO_ERROR; /* Working copy root can't be replaced */
- crb.is_replace_root = is_replace_root;
- crb.base_replace = base_replace;
- crb.is_replace = FALSE;
+ crb.is_replace_root_p = is_replace_root;
+ crb.base_replace_p = base_replace;
+ crb.is_replace_p = is_replace;
SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, check_replace_txn, &crb,
scratch_pool));
- if (is_replace)
- *is_replace = crb.is_replace;
-
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h Fri Dec 21 00:23:39 2012
@@ -1378,31 +1378,37 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
/* ### add a new versioned directory. a list of children is NOT passed
### since they are added in future, distinct calls to db_op_add_*.
- ### this is freshly added, so it has no properties. */
+ PROPS gives the properties; empty or NULL means none. */
/* ### do we need a CONFLICTS param? */
svn_error_t *
svn_wc__db_op_add_directory(svn_wc__db_t *db,
const char *local_abspath,
+ const apr_hash_t *props,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool);
-/* ### as a new file, there are no properties. this file has no "pristine"
+/* Add a file.
+ PROPS gives the properties; empty or NULL means none.
+ ### this file has no "pristine"
### contents, so a checksum [reference] is not required. */
/* ### do we need a CONFLICTS param? */
svn_error_t *
svn_wc__db_op_add_file(svn_wc__db_t *db,
const char *local_abspath,
+ const apr_hash_t *props,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool);
-/* ### newly added symlinks have no properties. */
+/* Add a symlink.
+ PROPS gives the properties; empty or NULL means none. */
/* ### do we need a CONFLICTS param? */
svn_error_t *
svn_wc__db_op_add_symlink(svn_wc__db_t *db,
const char *local_abspath,
const char *target,
+ const apr_hash_t *props,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool);
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_pristine.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_pristine.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_pristine.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_pristine.c Fri Dec 21 00:23:39 2012
@@ -288,20 +288,6 @@ svn_wc__db_pristine_get_tempdir(const ch
}
-/* Data for pristine_install_txn(). */
-typedef struct pristine_install_baton_t
-{
- /* The path to the source file that is to be moved into place. */
- const char *tempfile_abspath;
- /* The target path for the file (within the pristine store). */
- const char *pristine_abspath;
- /* The pristine text's SHA-1 checksum. */
- const svn_checksum_t *sha1_checksum;
- /* The pristine text's MD-5 checksum. */
- const svn_checksum_t *md5_checksum;
-} pristine_install_baton_t;
-
-
/* Install the pristine text described by BATON into the pristine store of
* SDB. If it is already stored then just delete the new file
* BATON->tempfile_abspath.
@@ -312,11 +298,17 @@ typedef struct pristine_install_baton_t
* Implements 'notes/wc-ng/pristine-store' section A-3(a).
* Implements svn_sqlite__transaction_callback_t. */
static svn_error_t *
-pristine_install_txn(void *baton,
- svn_sqlite__db_t *sdb,
+pristine_install_txn(svn_sqlite__db_t *sdb,
+ /* The path to the source file that is to be moved into place. */
+ const char *tempfile_abspath,
+ /* The target path for the file (within the pristine store). */
+ const char *pristine_abspath,
+ /* The pristine text's SHA-1 checksum. */
+ const svn_checksum_t *sha1_checksum,
+ /* The pristine text's MD-5 checksum. */
+ const svn_checksum_t *md5_checksum,
apr_pool_t *scratch_pool)
{
- pristine_install_baton_t *b = baton;
apr_finfo_t finfo;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
@@ -325,7 +317,7 @@ pristine_install_txn(void *baton,
/* If this pristine text is already present in the store, just keep it:
* delete the new one and return. */
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_PRISTINE));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, b->sha1_checksum, scratch_pool));
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
SVN_ERR(svn_sqlite__reset(stmt));
if (have_row)
@@ -335,30 +327,30 @@ pristine_install_txn(void *baton,
* ### We could check much more. */
{
apr_finfo_t finfo1, finfo2;
- SVN_ERR(svn_io_stat(&finfo1, b->tempfile_abspath, APR_FINFO_SIZE,
+ SVN_ERR(svn_io_stat(&finfo1, tempfile_abspath, APR_FINFO_SIZE,
scratch_pool));
- SVN_ERR(svn_io_stat(&finfo2, b->pristine_abspath, APR_FINFO_SIZE,
+ SVN_ERR(svn_io_stat(&finfo2, pristine_abspath, APR_FINFO_SIZE,
scratch_pool));
if (finfo1.size != finfo2.size)
{
return svn_error_createf(
SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
_("New pristine text '%s' has different size: %ld versus %ld"),
- svn_checksum_to_cstring_display(b->sha1_checksum, scratch_pool),
+ svn_checksum_to_cstring_display(sha1_checksum, scratch_pool),
(long int)finfo1.size, (long int)finfo2.size);
}
}
#endif
/* Remove the temp file: it's already there */
- SVN_ERR(svn_io_remove_file2(b->tempfile_abspath,
+ SVN_ERR(svn_io_remove_file2(tempfile_abspath,
FALSE /* ignore_enoent */, scratch_pool));
return SVN_NO_ERROR;
}
/* Move the file to its target location. (If it is already there, it is
* an orphan file and it doesn't matter if we overwrite it.) */
- err = svn_io_file_rename(b->tempfile_abspath, b->pristine_abspath,
+ err = svn_io_file_rename(tempfile_abspath, pristine_abspath,
scratch_pool);
/* Maybe the directory doesn't exist yet? */
@@ -366,7 +358,7 @@ pristine_install_txn(void *baton,
{
svn_error_t *err2;
- err2 = svn_io_dir_make(svn_dirent_dirname(b->pristine_abspath,
+ err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath,
scratch_pool),
APR_OS_DEFAULT, scratch_pool);
@@ -377,19 +369,19 @@ pristine_install_txn(void *baton,
/* We could create a directory: retry install */
svn_error_clear(err);
- SVN_ERR(svn_io_file_rename(b->tempfile_abspath, b->pristine_abspath,
+ SVN_ERR(svn_io_file_rename(tempfile_abspath, pristine_abspath,
scratch_pool));
}
else
SVN_ERR(err);
- SVN_ERR(svn_io_stat(&finfo, b->pristine_abspath, APR_FINFO_SIZE,
+ SVN_ERR(svn_io_stat(&finfo, pristine_abspath, APR_FINFO_SIZE,
scratch_pool));
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_INSERT_PRISTINE));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, b->sha1_checksum, scratch_pool));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, b->md5_checksum, scratch_pool));
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
SVN_ERR(svn_sqlite__bind_int64(stmt, 3, finfo.size));
SVN_ERR(svn_sqlite__insert(NULL, stmt));
@@ -407,7 +399,7 @@ svn_wc__db_pristine_install(svn_wc__db_t
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
const char *wri_abspath;
- struct pristine_install_baton_t b;
+ const char *pristine_abspath;
SVN_ERR_ASSERT(svn_dirent_is_absolute(tempfile_abspath));
SVN_ERR_ASSERT(sha1_checksum != NULL);
@@ -429,19 +421,18 @@ svn_wc__db_pristine_install(svn_wc__db_t
wri_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- b.tempfile_abspath = tempfile_abspath;
- b.sha1_checksum = sha1_checksum;
- b.md5_checksum = md5_checksum;
-
- SVN_ERR(get_pristine_fname(&b.pristine_abspath, wcroot->abspath,
+ SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
sha1_checksum,
scratch_pool, scratch_pool));
/* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
* at the disk, to ensure no concurrent pristine install/delete txn. */
- SVN_ERR(svn_sqlite__with_immediate_transaction(wcroot->sdb,
- pristine_install_txn, &b,
- scratch_pool));
+ SVN_SQLITE__WITH_IMMEDIATE_TXN(
+ pristine_install_txn(wcroot->sdb,
+ tempfile_abspath, pristine_abspath,
+ sha1_checksum, md5_checksum,
+ scratch_pool),
+ wcroot->sdb);
return SVN_NO_ERROR;
}
@@ -531,8 +522,15 @@ struct pristine_transfer_baton
svn_cancel_func_t cancel_func;
void * cancel_baton;
- /* pristine install baton, filled from pristine_transfer() */
- struct pristine_install_baton_t ib;
+ /* The following fields are filled in by pristine_transfer(). */
+ /* The path to the source file that is to be moved into place. */
+ const char *tempfile_abspath;
+ /* The target path for the file (within the pristine store). */
+ const char *pristine_abspath;
+ /* The pristine text's SHA-1 checksum. */
+ const svn_checksum_t *sha1_checksum;
+ /* The pristine text's MD-5 checksum. */
+ const svn_checksum_t *md5_checksum;
};
/* Transaction implementation of svn_wc__db_pristine_transfer().
@@ -555,8 +553,12 @@ pristine_transfer(void *baton, svn_wc__d
pristine_transfer, tb, scratch_pool));
/* And do the final install, while we still have the dst lock */
- if (tb->ib.tempfile_abspath)
- SVN_ERR(pristine_install_txn(&(tb->ib), tb->dst_wcroot->sdb,
+ if (tb->tempfile_abspath)
+ SVN_ERR(pristine_install_txn(tb->dst_wcroot->sdb,
+ tb->tempfile_abspath,
+ tb->pristine_abspath,
+ tb->sha1_checksum,
+ tb->md5_checksum,
scratch_pool));
return SVN_NO_ERROR;
}
@@ -564,7 +566,7 @@ pristine_transfer(void *baton, svn_wc__d
/* We have a lock on tb->dst_wcroot and tb->src_wcroot */
/* Get the right checksum if it wasn't passed */
- if (!tb->ib.sha1_checksum)
+ if (!tb->sha1_checksum)
{
SVN_ERR(svn_sqlite__get_statement(&stmt, tb->src_wcroot->sdb,
STMT_SELECT_NODE_INFO));
@@ -575,19 +577,19 @@ pristine_transfer(void *baton, svn_wc__d
SVN_ERR(svn_sqlite__step(&have_row, stmt));
if (have_row)
- SVN_ERR(svn_sqlite__column_checksum(&(tb->ib.sha1_checksum), stmt, 6,
+ SVN_ERR(svn_sqlite__column_checksum(&(tb->sha1_checksum), stmt, 6,
scratch_pool));
SVN_ERR(svn_sqlite__reset(stmt));
- if (!tb->ib.sha1_checksum)
+ if (!tb->sha1_checksum)
return SVN_NO_ERROR; /* Nothing to transfer */
}
/* Check if we have the pristine in the destination wcroot */
SVN_ERR(svn_sqlite__get_statement(&stmt, tb->dst_wcroot->sdb,
STMT_SELECT_PRISTINE));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, tb->ib.sha1_checksum,
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, tb->sha1_checksum,
scratch_pool));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
SVN_ERR(svn_sqlite__reset(stmt));
@@ -599,7 +601,7 @@ pristine_transfer(void *baton, svn_wc__d
/* Verify if the pristine actually exists and get the MD5 in one query */
SVN_ERR(svn_sqlite__get_statement(&stmt, tb->src_wcroot->sdb,
STMT_SELECT_PRISTINE));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, tb->ib.sha1_checksum,
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, tb->sha1_checksum,
scratch_pool));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -609,9 +611,9 @@ pristine_transfer(void *baton, svn_wc__d
_("The pristine text with checksum '%s' was "
"not found"),
svn_checksum_to_cstring_display(
- tb->ib.sha1_checksum, scratch_pool));
+ tb->sha1_checksum, scratch_pool));
}
- SVN_ERR(svn_sqlite__column_checksum(&(tb->ib.md5_checksum), stmt, 0,
+ SVN_ERR(svn_sqlite__column_checksum(&(tb->md5_checksum), stmt, 0,
scratch_pool));
SVN_ERR(svn_sqlite__reset(stmt));
@@ -631,7 +633,7 @@ pristine_transfer(void *baton, svn_wc__d
scratch_pool, scratch_pool));
SVN_ERR(get_pristine_fname(&src_abspath, tb->src_wcroot->abspath,
- tb->ib.sha1_checksum,
+ tb->sha1_checksum,
scratch_pool, scratch_pool));
SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath,
@@ -645,11 +647,11 @@ pristine_transfer(void *baton, svn_wc__d
/* And now set the right information to install once we leave the
src transaction */
- SVN_ERR(get_pristine_fname(&(tb->ib.pristine_abspath),
+ SVN_ERR(get_pristine_fname(&(tb->pristine_abspath),
tb->dst_wcroot->abspath,
- tb->ib.sha1_checksum,
+ tb->sha1_checksum,
scratch_pool, scratch_pool));
- tb->ib.tempfile_abspath = tmp_abspath;
+ tb->tempfile_abspath = tmp_abspath;
}
return SVN_NO_ERROR;
}
@@ -730,17 +732,8 @@ remove_file(const char *file_abspath,
return SVN_NO_ERROR;
}
-/* Data for pristine_remove_if_unreferenced_txn(). */
-typedef struct pristine_remove_baton_t
-{
- svn_wc__db_wcroot_t *wcroot;
- /* The pristine text's SHA-1 checksum. */
- const svn_checksum_t *sha1_checksum;
- /* The path to the pristine file (within the pristine store). */
- const char *pristine_abspath;
-} pristine_remove_baton_t;
-
-/* If the pristine text referenced by BATON in SDB has a reference count of
+/* If the pristine text referenced by SHA1_CHECKSUM in WCROOT/SDB, whose path
+ * within the pristine store is PRISTINE_ABSPATH, has a reference count of
* zero, delete it (both the database row and the disk file).
*
* This function expects to be executed inside a SQLite txn that has already
@@ -748,18 +741,19 @@ typedef struct pristine_remove_baton_t
*
* Implements svn_sqlite__transaction_callback_t. */
static svn_error_t *
-pristine_remove_if_unreferenced_txn(void *baton,
- svn_sqlite__db_t *sdb,
+pristine_remove_if_unreferenced_txn(svn_sqlite__db_t *sdb,
+ svn_wc__db_wcroot_t *wcroot,
+ const svn_checksum_t *sha1_checksum,
+ const char *pristine_abspath,
apr_pool_t *scratch_pool)
{
- pristine_remove_baton_t *b = baton;
svn_sqlite__stmt_t *stmt;
int affected_rows;
/* Remove the DB row, if refcount is 0. */
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_DELETE_PRISTINE_IF_UNREFERENCED));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, b->sha1_checksum, scratch_pool));
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
/* If we removed the DB row, then remove the file. */
@@ -774,7 +768,7 @@ pristine_remove_if_unreferenced_txn(void
svn_boolean_t ignore_enoent = TRUE;
#endif
- SVN_ERR(remove_file(b->pristine_abspath, b->wcroot, ignore_enoent,
+ SVN_ERR(remove_file(pristine_abspath, wcroot, ignore_enoent,
scratch_pool));
}
@@ -791,17 +785,17 @@ pristine_remove_if_unreferenced(svn_wc__
const svn_checksum_t *sha1_checksum,
apr_pool_t *scratch_pool)
{
- pristine_remove_baton_t b;
+ const char *pristine_abspath;
- b.wcroot = wcroot;
- b.sha1_checksum = sha1_checksum;
- SVN_ERR(get_pristine_fname(&b.pristine_abspath, wcroot->abspath,
+ SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
sha1_checksum, scratch_pool, scratch_pool));
/* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
* at the disk, to ensure no concurrent pristine install/delete txn. */
- SVN_ERR(svn_sqlite__with_immediate_transaction(
- wcroot->sdb, pristine_remove_if_unreferenced_txn, &b, scratch_pool));
+ SVN_SQLITE__WITH_IMMEDIATE_TXN(
+ pristine_remove_if_unreferenced_txn(
+ wcroot->sdb, wcroot, sha1_checksum, pristine_abspath, scratch_pool),
+ wcroot->sdb);
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c Fri Dec 21 00:23:39 2012
@@ -220,39 +220,81 @@ update_working_props(svn_wc_notify_state
}
-/* Check whether the node at LOCAL_RELPATH in the working copy at WCROOT
- * is shadowed by some node at a higher op depth than EXPECTED_OP_DEPTH. */
+/* If LOCAL_ABSPATH is shadowed then raise a tree-conflict on the root
+ of the obstruction if such a tree-conflict does not already exist. */
static svn_error_t *
-check_shadowed_node(svn_boolean_t *is_shadowed,
- int expected_op_depth,
+check_tree_conflict(svn_boolean_t *is_conflicted,
+ struct tc_editor_baton *b,
const char *local_relpath,
- svn_wc__db_wcroot_t *wcroot)
+ svn_node_kind_t kind,
+ apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
+ int dst_op_depth = relpath_depth(b->move_root_dst_relpath);
+ int op_depth;
+ const char *conflict_root_relpath = local_relpath;
+ const char *moved_to_relpath;
+ svn_skel_t *conflict;
+ svn_wc_conflict_version_t *version;
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+ STMT_SELECT_LOWEST_WORKING_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, local_relpath,
+ dst_op_depth));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ op_depth = svn_sqlite__column_int(stmt, 0);
+ SVN_ERR(svn_sqlite__reset(stmt));
- while (have_row)
+ if (!have_row)
{
- int op_depth = svn_sqlite__column_int(stmt, 0);
-
- if (op_depth > expected_op_depth)
- {
- *is_shadowed = TRUE;
- SVN_ERR(svn_sqlite__reset(stmt));
+ *is_conflicted = FALSE;
+ return SVN_NO_ERROR;
+ }
- return SVN_NO_ERROR;
- }
+ *is_conflicted = TRUE;
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- }
+ while (relpath_depth(conflict_root_relpath) > op_depth)
+ conflict_root_relpath = svn_relpath_dirname(conflict_root_relpath,
+ scratch_pool);
+
+ SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, b->wcroot,
+ conflict_root_relpath,
+ scratch_pool, scratch_pool));
+
+ if (conflict)
+ /* ### TODO: check this is the right sort of tree-conflict? */
+ return SVN_NO_ERROR;
+
+ SVN_ERR(svn_wc__db_scan_deletion_internal(NULL, &moved_to_relpath,
+ NULL, NULL,
+ b->wcroot, conflict_root_relpath,
+ scratch_pool, scratch_pool));
+
+ conflict = svn_wc__conflict_skel_create(scratch_pool);
+ SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
+ conflict, NULL,
+ svn_dirent_join(b->wcroot->abspath, conflict_root_relpath,
+ scratch_pool),
+ (moved_to_relpath
+ ? svn_wc_conflict_reason_moved_away
+ : svn_wc_conflict_reason_deleted),
+ svn_wc_conflict_action_edit,
+ scratch_pool,
+ scratch_pool));
+
+ version = svn_wc_conflict_version_create2(b->old_version->repos_url,
+ b->old_version->repos_uuid,
+ local_relpath,
+ b->old_version->peg_rev,
+ kind,
+ scratch_pool);
- *is_shadowed = FALSE;
- SVN_ERR(svn_sqlite__reset(stmt));
+ SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict, version,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, conflict_root_relpath,
+ conflict, scratch_pool));
return SVN_NO_ERROR;
}
@@ -272,9 +314,15 @@ tc_editor_alter_directory(void *baton,
svn_kind_t move_dst_kind;
working_node_version_t old_version, new_version;
svn_wc__db_status_t status;
+ svn_boolean_t is_conflicted;
SVN_ERR_ASSERT(expected_move_dst_revision == b->old_version->peg_rev);
+ SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath, svn_node_dir,
+ scratch_pool));
+ if (is_conflicted)
+ return SVN_NO_ERROR;
+
/* Get kind, revision, and checksum of the moved-here node. */
SVN_ERR(svn_wc__db_depth_get_info(&status, &move_dst_kind, &move_dst_revision,
&move_dst_repos_relpath, NULL, NULL, NULL,
@@ -294,59 +342,45 @@ tc_editor_alter_directory(void *baton,
if (new_props)
{
- svn_boolean_t is_shadowed;
+ const char *dst_abspath = svn_dirent_join(b->wcroot->abspath,
+ dst_relpath,
+ scratch_pool);
+ svn_wc_notify_state_t prop_state;
+ svn_skel_t *conflict_skel = NULL;
+ apr_hash_t *actual_props;
+ apr_array_header_t *propchanges;
+
+ SVN_ERR(update_working_props(&prop_state, &conflict_skel,
+ &propchanges, &actual_props,
+ b->db, dst_abspath,
+ &old_version, &new_version,
+ b->result_pool, scratch_pool));
- /* If the node is shadowed by a higher layer, we need to flag a
- * tree conflict and must not touch the working node. */
- SVN_ERR(check_shadowed_node(&is_shadowed,
- relpath_depth(b->move_root_dst_relpath),
- dst_relpath, b->wcroot));
- if (is_shadowed)
+ if (conflict_skel)
{
- /* ### TODO flag tree conflict */
+ SVN_ERR(create_conflict_markers(b->work_items, dst_abspath,
+ b->db, move_dst_repos_relpath,
+ conflict_skel,
+ &old_version, &new_version,
+ b->result_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, dst_relpath,
+ conflict_skel,
+ scratch_pool));
}
- else
- {
- const char *dst_abspath = svn_dirent_join(b->wcroot->abspath,
- dst_relpath,
- scratch_pool);
- svn_wc_notify_state_t prop_state;
- svn_skel_t *conflict_skel = NULL;
- apr_hash_t *actual_props;
- apr_array_header_t *propchanges;
-
- SVN_ERR(update_working_props(&prop_state, &conflict_skel,
- &propchanges, &actual_props,
- b->db, dst_abspath,
- &old_version, &new_version,
- b->result_pool, scratch_pool));
- if (conflict_skel)
- {
- SVN_ERR(create_conflict_markers(b->work_items, dst_abspath,
- b->db, move_dst_repos_relpath,
- conflict_skel,
- &old_version, &new_version,
- b->result_pool, scratch_pool));
- SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, dst_relpath,
- conflict_skel,
- scratch_pool));
- }
-
- if (b->notify_func)
- {
- svn_wc_notify_t *notify;
+ if (b->notify_func)
+ {
+ svn_wc_notify_t *notify;
- notify = svn_wc_create_notify(dst_abspath,
- svn_wc_notify_update_update,
- scratch_pool);
- notify->kind = svn_node_dir;
- notify->content_state = svn_wc_notify_state_inapplicable;
- notify->prop_state = prop_state;
- notify->old_revision = b->old_version->peg_rev;
- notify->revision = b->new_version->peg_rev;
- b->notify_func(b->notify_baton, notify, scratch_pool);
- }
+ notify = svn_wc_create_notify(dst_abspath,
+ svn_wc_notify_update_update,
+ scratch_pool);
+ notify->kind = svn_node_dir;
+ notify->content_state = svn_wc_notify_state_inapplicable;
+ notify->prop_state = prop_state;
+ notify->old_revision = b->old_version->peg_rev;
+ notify->revision = b->new_version->peg_rev;
+ b->notify_func(b->notify_baton, notify, scratch_pool);
}
}
@@ -503,6 +537,12 @@ tc_editor_alter_file(void *baton,
svn_revnum_t move_dst_revision;
svn_kind_t move_dst_kind;
working_node_version_t old_version, new_version;
+ svn_boolean_t is_conflicted;
+
+ SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath, svn_node_file,
+ scratch_pool));
+ if (is_conflicted)
+ return SVN_NO_ERROR;
/* Get kind, revision, and checksum of the moved-here node. */
SVN_ERR(svn_wc__db_depth_get_info(NULL, &move_dst_kind, &move_dst_revision,
@@ -528,30 +568,16 @@ tc_editor_alter_file(void *baton,
if (!svn_checksum_match(new_checksum, old_version.checksum)
/* ### || props have changed */)
{
- svn_boolean_t is_shadowed;
+ svn_skel_t *work_item;
- /* If the node is shadowed by a higher layer, we need to flag a
- * tree conflict and must not touch the working file. */
- SVN_ERR(check_shadowed_node(&is_shadowed,
- relpath_depth(b->move_root_dst_relpath),
- dst_relpath, b->wcroot));
- if (is_shadowed)
- {
- /* ### TODO flag tree conflict */
- }
- else
- {
- svn_skel_t *work_item;
-
- SVN_ERR(update_working_file(&work_item, dst_relpath,
- move_dst_repos_relpath,
- &old_version, &new_version,
- b->wcroot, b->db,
- b->notify_func, b->notify_baton,
- b->result_pool, scratch_pool));
- *b->work_items = svn_wc__wq_merge(*b->work_items, work_item,
- b->result_pool);
- }
+ SVN_ERR(update_working_file(&work_item, dst_relpath,
+ move_dst_repos_relpath,
+ &old_version, &new_version,
+ b->wcroot, b->db,
+ b->notify_func, b->notify_baton,
+ b->result_pool, scratch_pool));
+ *b->work_items = svn_wc__wq_merge(*b->work_items, work_item,
+ b->result_pool);
}
return SVN_NO_ERROR;
@@ -753,14 +779,55 @@ get_tc_info(svn_wc_operation_t *operatio
const char *repos_relpath;
svn_revnum_t revision;
svn_node_kind_t node_kind;
+ svn_wc__db_status_t status;
+
+ /* The scan dance: read_info then scan_delete then base_get
+ or scan_addition. Use the internal/relpath functions
+ here? */
+ SVN_ERR(svn_wc__db_read_info(&status, &kind, &revision,
+ &repos_relpath, &repos_root_url,
+ &repos_uuid, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ db, src_abspath, result_pool,
+ scratch_pool));
+ if (status == svn_wc__db_status_deleted)
+ {
+ const char *base_del_abspath, *work_del_abspath;
+ SVN_ERR(svn_wc__db_scan_deletion(&base_del_abspath, NULL,
+ &work_del_abspath,
+ NULL, db, src_abspath,
+ scratch_pool, scratch_pool));
+ SVN_ERR_ASSERT(base_del_abspath || work_del_abspath);
+ if (base_del_abspath)
+ {
+ SVN_ERR(svn_wc__db_base_get_info(NULL, &kind, &revision,
+ &repos_relpath,
+ &repos_root_url,
+ &repos_uuid,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ db, src_abspath, result_pool,
+ scratch_pool));
+ }
+ else if (work_del_abspath)
+ {
+ work_del_abspath = svn_dirent_dirname(work_del_abspath,
+ scratch_pool);
+ SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &repos_relpath,
+ &repos_root_url, &repos_uuid,
+ NULL, NULL, NULL,
+ &revision, NULL, NULL,
+ db, work_del_abspath,
+ scratch_pool, scratch_pool));
+ repos_relpath = svn_relpath_join(repos_relpath,
+ svn_dirent_skip_ancestor(work_del_abspath,
+ src_abspath),
+ scratch_pool);
+ }
+ }
- /* Construct new_version from BASE info. */
- SVN_ERR(svn_wc__db_base_get_info(NULL, &kind, &revision,
- &repos_relpath, &repos_root_url,
- &repos_uuid, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- db, src_abspath, result_pool,
- scratch_pool));
node_kind = svn__node_kind_from_kind(kind);
*new_version = svn_wc_conflict_version_create2(repos_root_url,
repos_uuid,
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_util.c Fri Dec 21 00:23:39 2012
@@ -153,8 +153,8 @@ svn_wc__db_util_open_db(svn_sqlite__db_t
/* Some helpful transaction helpers.
- Instead of directly using SQLite transactions, these wrappers take care of
- simple cases by allowing consumers to worry about wrapping the wcroot and
+ Instead of directly using SQLite transactions, these wrappers
+ relieve the consumer from the need to wrap the wcroot and
local_relpath, which are almost always used within the transaction.
This also means if we later want to implement some wc_db-specific txn
Modified: subversion/branches/ev2-export/subversion/svn/copy-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svn/copy-cmd.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svn/copy-cmd.c (original)
+++ subversion/branches/ev2-export/subversion/svn/copy-cmd.c Fri Dec 21 00:23:39 2012
@@ -68,7 +68,42 @@ svn_cl__copy(apr_getopt_t *os,
svn_opt_revision_t *peg_revision = apr_palloc(pool,
sizeof(*peg_revision));
- SVN_ERR(svn_opt_parse_path(peg_revision, &src, target, pool));
+ err = svn_opt_parse_path(peg_revision, &src, target, pool);
+
+ if (err)
+ {
+ /* Issue #3606: 'svn cp .@HEAD target' gives
+ svn: '@HEAD' is just a peg revision. Maybe try '@HEAD@' instead?
+
+ This is caused by a first round of canonicalization in
+ svn_cl__args_to_target_array_print_reserved(). Undo that in an
+ attempt to fix this issue without revving many apis.
+ */
+ if (*target == '@' && err->apr_err == SVN_ERR_BAD_FILENAME)
+ {
+ svn_error_t *err2;
+
+ err2 = svn_opt_parse_path(peg_revision, &src,
+ apr_pstrcat(pool, ".", target,
+ (const char *)NULL), pool);
+
+ if (err2)
+ {
+ /* Fix attempt failed; return original error */
+ svn_error_clear(err2);
+ }
+ else
+ {
+ /* Error resolved. Use path */
+ svn_error_clear(err);
+ err = NULL;
+ }
+ }
+
+ if (err)
+ return svn_error_trace(err);
+ }
+
source->path = src;
source->revision = &(opt_state->start_revision);
source->peg_revision = peg_revision;
Modified: subversion/branches/ev2-export/subversion/svn/help-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svn/help-cmd.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svn/help-cmd.c (original)
+++ subversion/branches/ev2-export/subversion/svn/help-cmd.c Fri Dec 21 00:23:39 2012
@@ -28,6 +28,7 @@
/*** Includes. ***/
#include "svn_string.h"
+#include "svn_config.h"
#include "svn_error.h"
#include "svn_version.h"
#include "cl.h"
@@ -43,7 +44,8 @@ svn_cl__help(apr_getopt_t *os,
void *baton,
apr_pool_t *pool)
{
- svn_cl__opt_state_t *opt_state;
+ svn_cl__opt_state_t *opt_state = NULL;
+ svn_stringbuf_t *version_footer = NULL;
/* xgettext: the %s is for SVN_VER_NUMBER. */
char help_header_template[] =
@@ -69,14 +71,72 @@ svn_cl__help(apr_getopt_t *os,
const char *ra_desc_start
= _("The following repository access (RA) modules are available:\n\n");
- svn_stringbuf_t *version_footer;
-
if (baton)
- opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
- else
- opt_state = NULL;
+ {
+ svn_cl__cmd_baton_t *const cmd_baton = baton;
+#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
+ /* Windows never actually stores plaintext passwords, it
+ encrypts the contents using CryptoAPI. ...
+
+ ... If CryptoAPI is available ... but it should be on all
+ versions of Windows that are even remotely interesting two
+ days before the scheduled end of the world, when this comment
+ is being written. */
+# ifndef WIN32
+ svn_boolean_t store_auth_creds =
+ SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS;
+ svn_boolean_t store_passwords =
+ SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS;
+ svn_boolean_t store_plaintext_passwords = FALSE;
+ svn_config_t *cfg;
+
+ if (cmd_baton->ctx->config)
+ {
+ cfg = apr_hash_get(cmd_baton->ctx->config,
+ SVN_CONFIG_CATEGORY_CONFIG,
+ APR_HASH_KEY_STRING);
+ if (cfg)
+ {
+ SVN_ERR(svn_config_get_bool(cfg, &store_auth_creds,
+ SVN_CONFIG_SECTION_AUTH,
+ SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
+ store_auth_creds));
+ SVN_ERR(svn_config_get_bool(cfg, &store_passwords,
+ SVN_CONFIG_SECTION_AUTH,
+ SVN_CONFIG_OPTION_STORE_PASSWORDS,
+ store_passwords));
+ }
+ cfg = apr_hash_get(cmd_baton->ctx->config,
+ SVN_CONFIG_CATEGORY_SERVERS,
+ APR_HASH_KEY_STRING);
+ if (cfg)
+ {
+ const char *value;
+ SVN_ERR(svn_config_get_yes_no_ask
+ (cfg, &value,
+ SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS,
+ SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS));
+ if (0 == svn_cstring_casecmp(value, SVN_CONFIG_TRUE))
+ store_plaintext_passwords = TRUE;
+ }
+ }
+
+ if (store_plaintext_passwords && store_auth_creds && store_passwords)
+ {
+ version_footer = svn_stringbuf_create(
+ _("WARNING: Plaintext password storage is enabled!\n\n"),
+ pool);
+ svn_stringbuf_appendcstr(version_footer, ra_desc_start);
+ }
+# endif /* !WIN32 */
+#endif /* !SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE */
+
+ opt_state = cmd_baton->opt_state;
+ }
- version_footer = svn_stringbuf_create(ra_desc_start, pool);
+ if (!version_footer)
+ version_footer = svn_stringbuf_create(ra_desc_start, pool);
SVN_ERR(svn_ra_print_modules(version_footer, pool));
return svn_opt_print_help4(os,
Modified: subversion/branches/ev2-export/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svn/svn.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svn/svn.c (original)
+++ subversion/branches/ev2-export/subversion/svn/svn.c Fri Dec 21 00:23:39 2012
@@ -101,6 +101,7 @@ typedef enum svn_cl__longopt_t {
opt_no_ignore,
opt_no_unlock,
opt_non_interactive,
+ opt_force_interactive,
opt_old_cmd,
opt_record_only,
opt_relocate,
@@ -229,7 +230,13 @@ const apr_getopt_option_t svn_cl__option
" "
"with '--non-interactive')") },
{"non-interactive", opt_non_interactive, 0,
- N_("do no interactive prompting")},
+ N_("do no interactive prompting (default is to prompt\n"
+ " "
+ "only if standard input is a terminal device)")},
+ {"force-interactive", opt_force_interactive, 0,
+ N_("do interactive prompting even if standard input\n"
+ " "
+ "is not a terminal device")},
{"dry-run", opt_dry_run, 0,
N_("try operation but make no changes")},
{"ignore-ancestry", opt_ignore_ancestry, 0,
@@ -401,7 +408,8 @@ const apr_getopt_option_t svn_cl__option
willy-nilly to every invocation of 'svn') . */
const int svn_cl__global_options[] =
{ opt_auth_username, opt_auth_password, opt_no_auth_cache, opt_non_interactive,
- opt_trust_server_cert, opt_config_dir, opt_config_options, 0
+ opt_force_interactive, opt_trust_server_cert, opt_config_dir,
+ opt_config_options, 0
};
/* Options for giving a log message. (Some of these also have other uses.)
@@ -730,7 +738,7 @@ const svn_opt_subcommand_desc2_t svn_cl_
" (the 'automatic' merge)\n"
" 2. merge [-c M[,N...] | -r N:M ...] SOURCE[@REV] [TARGET_WCPATH]\n"
" (the 'cherry-pick' merge)\n"
-" 3. merge SOURCE1[@N] SOURCE2[@M] [TARGET_WCPATH]\n"
+" 3. merge SOURCE1[@REV1] SOURCE2[@REV2] [TARGET_WCPATH]\n"
" (the '2-URL' merge)\n"
"\n"
" 1. This form, with one source path and no revision range, is called\n"
@@ -915,26 +923,27 @@ const svn_opt_subcommand_desc2_t svn_cl_
"\n"
" 3. This form is called a '2-URL merge':\n"
"\n"
-" svn merge SOURCE1[@N] SOURCE2[@M] [TARGET_WCPATH]\n"
-"\n"
-" Two source URLs are specified, together with two revisions N and M.\n"
-" The two sources are compared at the specified revisions, and the\n"
-" difference is applied to TARGET_WCPATH, which is a path to a working\n"
-" copy of another branch. The three branches involved can be completely\n"
-" unrelated.\n"
+" svn merge SOURCE1[@REV1] SOURCE2[@REV2] [TARGET_WCPATH]\n"
"\n"
" You should use this merge variant only if the other variants do not\n"
" apply to your situation, as this variant can be quite complex to\n"
" master.\n"
"\n"
+" Two source URLs are specified, identifying two trees on the same\n"
+" branch or on different branches. The trees are compared and the\n"
+" difference from SOURCE1@REV1 to SOURCE2@REV2 is applied to the\n"
+" working copy of the target branch at TARGET_WCPATH. The target\n"
+" branch may be the same as one or both sources, or different again.\n"
+" The three branches involved can be completely unrelated.\n"
+"\n"
" If TARGET_WCPATH is omitted, a default value of '.' is assumed.\n"
" However, in the special case where both sources refer to a file node\n"
-" with the same basename and a similarly named file is also found within\n"
-" '.', the differences will be applied to that local file. The source\n"
-" revisions default to HEAD if omitted.\n"
+" with the same name and a file with the same name is also found within\n"
+" '.', the differences will be applied to that local file. The source\n"
+" revisions REV1 and REV2 default to HEAD if omitted.\n"
"\n"
-" The sources can also be specified as working copy paths, in which case\n"
-" the URLs of the merge sources are derived from the working copies.\n"
+" SOURCE1 and/or SOURCE2 can also be specified as a working copy path,\n"
+" in which case the merge source URL is derived from the working copy.\n"
"\n"
" - 2-URL Merge Example -\n"
"\n"
@@ -1659,6 +1668,7 @@ sub_main(int argc, const char *argv[], a
svn_config_t *cfg_config;
svn_boolean_t descend = TRUE;
svn_boolean_t interactive_conflicts = FALSE;
+ svn_boolean_t force_interactive = FALSE;
svn_boolean_t use_notifier = TRUE;
apr_hash_t *changelists;
const char *sqlite_exclusive;
@@ -1982,6 +1992,9 @@ sub_main(int argc, const char *argv[], a
case opt_non_interactive:
opt_state.non_interactive = TRUE;
break;
+ case opt_force_interactive:
+ force_interactive = TRUE;
+ break;
case opt_trust_server_cert:
opt_state.trust_server_cert = TRUE;
break;
@@ -2191,6 +2204,20 @@ sub_main(int argc, const char *argv[], a
}
}
+ /* The --non-interactive and --force-interactive options are mutually
+ * exclusive. */
+ if (opt_state.non_interactive && force_interactive)
+ {
+ err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--non-interactive and --force-interactive "
+ "are mutually exclusive"));
+ return EXIT_ERROR(err);
+ }
+ else
+ opt_state.non_interactive = !svn_cmdline__be_interactive(
+ opt_state.non_interactive,
+ force_interactive);
+
/* Turn our hash of changelists into an array of unique ones. */
SVN_INT_ERR(svn_hash_keys(&(opt_state.changelists), changelists, pool));
Modified: subversion/branches/ev2-export/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svnrdump/dump_editor.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/ev2-export/subversion/svnrdump/dump_editor.c Fri Dec 21 00:23:39 2012
@@ -101,6 +101,14 @@ struct dump_edit_baton {
/* A backdoor ra session to fetch additional information during the edit. */
svn_ra_session_t *ra_session;
+ /* The repository relpath of the anchor of the editor when driven
+ via the RA update mechanism; NULL otherwise. (When the editor is
+ driven via the RA "replay" mechanism instead, the editor is
+ always anchored at the repository, we don't need to prepend an
+ anchor path to the dumped node paths, and open_root() doesn't
+ need to manufacture directory additions.) */
+ const char *update_anchor_relpath;
+
/* Pool for per-revision allocations */
apr_pool_t *pool;
@@ -308,14 +316,22 @@ dump_node(struct dump_edit_baton *eb,
svn_revnum_t copyfrom_rev,
apr_pool_t *pool)
{
+ const char *node_relpath = repos_relpath;
+
assert(svn_relpath_is_canonical(repos_relpath));
assert(!copyfrom_path || svn_relpath_is_canonical(copyfrom_path));
- /* Node-path: commons/STATUS */
+ /* Add the edit root relpath prefix if necessary. */
+ if (eb->update_anchor_relpath)
+ node_relpath = svn_relpath_join(eb->update_anchor_relpath,
+ node_relpath, pool);
+
+ /* Node-path: ... */
SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n", repos_relpath));
+ SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
+ node_relpath));
- /* Node-kind: file */
+ /* Node-kind: "file" | "dir" */
if (kind == svn_node_file)
SVN_ERR(svn_stream_printf(eb->stream, pool,
SVN_REPOS_DUMPFILE_NODE_KIND ": file\n"));
@@ -330,13 +346,24 @@ dump_node(struct dump_edit_baton *eb,
case svn_node_action_change:
/* We are here after a change_file_prop or change_dir_prop. They
set up whatever dump_props they needed to- nothing to
- do here but print node action information */
+ do here but print node action information.
+
+ Node-action: change. */
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION ": change\n"));
break;
case svn_node_action_replace:
- if (!is_copy)
+ if (is_copy)
+ {
+ /* Delete the original, and then re-add the replacement as a
+ copy using recursive calls into this function. */
+ SVN_ERR(dump_node(eb, repos_relpath, kind, svn_node_action_delete,
+ FALSE, NULL, SVN_INVALID_REVNUM, pool));
+ SVN_ERR(dump_node(eb, repos_relpath, kind, svn_node_action_add,
+ is_copy, copyfrom_path, copyfrom_rev, pool));
+ }
+ else
{
/* Node-action: replace */
SVN_ERR(svn_stream_puts(eb->stream,
@@ -346,24 +373,11 @@ dump_node(struct dump_edit_baton *eb,
/* Wait for a change_*_prop to be called before dumping
anything */
eb->dump_props = TRUE;
- break;
}
- /* More complex case: is_copy is true, and copyfrom_path/
- copyfrom_rev are present: delete the original, and then re-add
- it */
-
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n\n"));
-
- /* Recurse: Print an additional add-with-history record. */
- SVN_ERR(dump_node(eb, repos_relpath, kind, svn_node_action_add,
- is_copy, copyfrom_path, copyfrom_rev, pool));
-
- /* We can leave this routine quietly now, don't need to dump any
- content; that was already done in the second record. */
break;
case svn_node_action_delete:
+ /* Node-action: delete */
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n"));
@@ -371,44 +385,54 @@ dump_node(struct dump_edit_baton *eb,
print a couple of newlines because we're not dumping props or
text. */
SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
+
break;
case svn_node_action_add:
+ /* Node-action: add */
SVN_ERR(svn_stream_puts(eb->stream,
SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
- if (!is_copy)
+ if (is_copy)
{
- /* eb->dump_props for files is handled in close_file
- which is called immediately. However, directories are not
- closed until all the work inside them has been done;
- eb->dump_props for directories is handled in all the
- functions that can possibly be called after add_directory:
- add_directory, open_directory, delete_entry, close_directory,
- add_file, open_file. change_dir_prop is a special case. */
-
- /* Wait for a change_*_prop to be called before dumping
- anything */
- eb->dump_props = TRUE;
- break;
+ /* Node-copyfrom-rev / Node-copyfrom-path */
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV
+ ": %ld\n"
+ SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH
+ ": %s\n",
+ copyfrom_rev, copyfrom_path));
+
+ /* Ugly hack: If a directory was copied from a previous
+ revision, nothing like close_file() will be called to write two
+ blank lines. If change_dir_prop() is called, props are dumped
+ (along with the necessary PROPS-END\n\n and we're good. So
+ set DUMP_NEWLINES here to print the newlines unless
+ change_dir_prop() is called next otherwise the `svnadmin load`
+ parser will fail. */
+ if (kind == svn_node_dir)
+ eb->dump_newlines = TRUE;
}
+ else
+ {
+ /* eb->dump_props (for files) is handled in close_file()
+ which is called immediately.
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV
- ": %ld\n"
- SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH
- ": %s\n",
- copyfrom_rev, copyfrom_path));
+ However, directories are not closed until all the work
+ inside them has been done; eb->dump_props (for directories)
+ is handled (via dump_pending()) in all the functions that
+ can possibly be called after add_directory():
+
+ - add_directory()
+ - open_directory()
+ - delete_entry()
+ - close_directory()
+ - add_file()
+ - open_file()
- /* Ugly hack: If a directory was copied from a previous
- revision, nothing like close_file() will be called to write two
- blank lines. If change_dir_prop() is called, props are dumped
- (along with the necessary PROPS-END\n\n and we're good. So
- set DUMP_NEWLINES here to print the newlines unless
- change_dir_prop() is called next otherwise the `svnadmin load`
- parser will fail. */
- if (kind == svn_node_dir)
- eb->dump_newlines = TRUE;
+ change_dir_prop() is a special case. */
+ eb->dump_props = TRUE;
+ }
break;
}
@@ -416,23 +440,42 @@ dump_node(struct dump_edit_baton *eb,
}
static svn_error_t *
-open_root(void *edit_baton,
- svn_revnum_t base_revision,
- apr_pool_t *pool,
- void **root_baton)
+dump_mkdir(struct dump_edit_baton *eb,
+ const char *repos_relpath,
+ apr_pool_t *pool)
{
- struct dump_edit_baton *eb = edit_baton;
+ svn_stringbuf_t *prop_header, *prop_content;
+ apr_size_t len;
+ const char *buf;
- /* Clear the per-revision pool after each revision */
- svn_pool_clear(eb->pool);
+ /* Node-path: ... */
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
+ repos_relpath));
- eb->props = apr_hash_make(eb->pool);
- eb->deleted_props = apr_hash_make(eb->pool);
- eb->propstring = svn_stringbuf_create_empty(eb->pool);
+ /* Node-kind: dir */
+ SVN_ERR(svn_stream_printf(eb->stream, pool,
+ SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
- *root_baton = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
- edit_baton, NULL, FALSE, eb->pool);
- LDR_DBG(("open_root %p\n", *root_baton));
+ /* Node-action: add */
+ SVN_ERR(svn_stream_puts(eb->stream,
+ SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
+
+ /* Dump the (empty) property block. */
+ SVN_ERR(get_props_content(&prop_header, &prop_content,
+ apr_hash_make(pool), apr_hash_make(pool),
+ pool, pool));
+ len = prop_header->len;
+ SVN_ERR(svn_stream_write(eb->stream, prop_header->data, &len));
+ len = prop_content->len;
+ buf = apr_psprintf(pool, SVN_REPOS_DUMPFILE_CONTENT_LENGTH
+ ": %" APR_SIZE_T_FMT "\n", len);
+ SVN_ERR(svn_stream_puts(eb->stream, buf));
+ SVN_ERR(svn_stream_puts(eb->stream, "\n"));
+ SVN_ERR(svn_stream_write(eb->stream, prop_content->data, &len));
+
+ /* Newlines to tie it all off. */
+ SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
return SVN_NO_ERROR;
}
@@ -456,6 +499,77 @@ dump_pending(struct dir_baton *pb,
}
static svn_error_t *
+open_root(void *edit_baton,
+ svn_revnum_t base_revision,
+ apr_pool_t *pool,
+ void **root_baton)
+{
+ struct dump_edit_baton *eb = edit_baton;
+ struct dir_baton *new_db = NULL;
+
+ /* Clear the per-revision pool after each revision */
+ svn_pool_clear(eb->pool);
+
+ eb->props = apr_hash_make(eb->pool);
+ eb->deleted_props = apr_hash_make(eb->pool);
+ eb->propstring = svn_stringbuf_create_empty(eb->pool);
+
+ LDR_DBG(("open_root %p\n", *root_baton));
+
+ if (eb->update_anchor_relpath)
+ {
+ int i;
+ const char *parent_path = eb->update_anchor_relpath;
+ apr_array_header_t *dirs_to_add =
+ apr_array_make(pool, 4, sizeof(const char *));
+ apr_pool_t *iterpool = svn_pool_create(pool);
+
+ while (! svn_path_is_empty(parent_path))
+ {
+ APR_ARRAY_PUSH(dirs_to_add, const char *) = parent_path;
+ parent_path = svn_relpath_dirname(parent_path, pool);
+ }
+
+ for (i = dirs_to_add->nelts; i; --i)
+ {
+ const char *dir_to_add =
+ APR_ARRAY_IDX(dirs_to_add, i - 1, const char *);
+
+ svn_pool_clear(iterpool);
+
+ /* For parents of the source directory, we just manufacture
+ the adds ourselves. */
+ if (i > 1)
+ {
+ SVN_ERR(dump_mkdir(eb, dir_to_add, iterpool));
+ }
+ else
+ {
+ /* ... but for the source directory itself, we'll defer
+ to letting the typical plumbing handle this task. */
+ new_db = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
+ edit_baton, NULL, TRUE, pool);
+ SVN_ERR(dump_node(eb, new_db->repos_relpath, svn_node_dir,
+ svn_node_action_add, FALSE, NULL, SVN_INVALID_REVNUM,
+ pool));
+ new_db->written_out = TRUE;
+ }
+ }
+ svn_pool_destroy(iterpool);
+ }
+
+ if (! new_db)
+ {
+ new_db = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
+ edit_baton, NULL, FALSE, pool);
+ }
+
+ *root_baton = new_db;
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
delete_entry(const char *path,
svn_revnum_t revision,
void *parent_baton,
@@ -1014,6 +1128,7 @@ svn_rdump__get_dump_editor(const svn_del
svn_revnum_t revision,
svn_stream_t *stream,
svn_ra_session_t *ra_session,
+ const char *update_anchor_relpath,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool)
@@ -1026,6 +1141,7 @@ svn_rdump__get_dump_editor(const svn_del
eb = apr_pcalloc(pool, sizeof(struct dump_edit_baton));
eb->stream = stream;
eb->ra_session = ra_session;
+ eb->update_anchor_relpath = update_anchor_relpath;
eb->current_revision = revision;
/* Create a special per-revision pool */
Modified: subversion/branches/ev2-export/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svnrdump/load_editor.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/ev2-export/subversion/svnrdump/load_editor.c Fri Dec 21 00:23:39 2012
@@ -855,6 +855,8 @@ set_revision_property(void *baton,
{
struct revision_baton *rb = baton;
+ SVN_ERR(svn_rdump__normalize_prop(name, &value, rb->pool));
+
SVN_ERR(svn_repos__validate_prop(name, value, rb->pool));
if (rb->rev > 0)
@@ -934,6 +936,8 @@ set_node_property(void *baton,
}
}
+ SVN_ERR(svn_rdump__normalize_prop(name, &value, pool));
+
SVN_ERR(svn_repos__validate_prop(name, value, pool));
switch (nb->kind)
Modified: subversion/branches/ev2-export/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svnrdump/svnrdump.c?rev=1424772&r1=1424771&r2=1424772&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/ev2-export/subversion/svnrdump/svnrdump.c Fri Dec 21 00:23:39 2012
@@ -23,6 +23,7 @@
*/
#include <apr_signal.h>
+#include <apr_uri.h>
#include "svn_pools.h"
#include "svn_cmdline.h"
@@ -79,6 +80,7 @@ enum svn_svnrdump__longopt_t
opt_auth_password,
opt_auth_nocache,
opt_non_interactive,
+ opt_force_interactive,
opt_incremental,
opt_trust_server_cert,
opt_version
@@ -90,7 +92,8 @@ enum svn_svnrdump__longopt_t
opt_auth_password, \
opt_auth_nocache, \
opt_trust_server_cert, \
- opt_non_interactive
+ opt_non_interactive, \
+ opt_force_interactive
static const svn_opt_subcommand_desc2_t svnrdump__cmd_table[] =
{
@@ -126,7 +129,13 @@ static const apr_getopt_option_t svnrdum
{"password", opt_auth_password, 1,
N_("specify a password ARG")},
{"non-interactive", opt_non_interactive, 0,
- N_("do no interactive prompting")},
+ N_("do no interactive prompting (default is to prompt\n"
+ " "
+ "only if standard input is a terminal device)")},
+ {"force-interactive", opt_force_interactive, 0,
+ N_("do interactive prompting even if standard input\n"
+ " "
+ "is not a terminal device")},
{"no-auth-cache", opt_auth_nocache, 0,
N_("do not cache authentication tokens")},
{"help", 'h', 0,
@@ -223,7 +232,7 @@ replay_revstart(svn_revnum_t revision,
SVN_ERR(svn_rdump__get_dump_editor(editor, edit_baton, revision,
rb->stdout_stream, rb->extra_ra_session,
- check_cancel, NULL, pool));
+ NULL, check_cancel, NULL, pool));
return SVN_NO_ERROR;
}
@@ -298,7 +307,7 @@ replay_revstart_v2(svn_revnum_t revision
SVN_ERR(svn_rdump__get_dump_editor_v2(editor, revision,
rb->stdout_stream,
rb->extra_ra_session,
- check_cancel, NULL, pool, pool));
+ NULL, check_cancel, NULL, pool, pool));
return SVN_NO_ERROR;
}
@@ -328,6 +337,8 @@ replay_revend_v2(svn_revnum_t revision,
* allocated from POOL. Use CONFIG_DIR and pass USERNAME, PASSWORD,
* CONFIG_DIR and NO_AUTH_CACHE to initialize the authorization baton.
* CONFIG_OPTIONS (if not NULL) is a list of configuration overrides.
+ * REPOS_URL is used to fiddle with server-specific configuration
+ * options.
*/
static svn_error_t *
init_client_context(svn_client_ctx_t **ctx_p,
@@ -335,13 +346,14 @@ init_client_context(svn_client_ctx_t **c
const char *username,
const char *password,
const char *config_dir,
+ const char *repos_url,
svn_boolean_t no_auth_cache,
svn_boolean_t trust_server_cert,
apr_array_header_t *config_options,
apr_pool_t *pool)
{
svn_client_ctx_t *ctx = NULL;
- svn_config_t *cfg_config;
+ svn_config_t *cfg_config, *cfg_servers;
SVN_ERR(svn_ra_initialize(pool));
@@ -357,6 +369,47 @@ init_client_context(svn_client_ctx_t **c
cfg_config = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
APR_HASH_KEY_STRING);
+ /* ### FIXME: This is a hack to work around the fact that our dump
+ ### editor simply can't handle the way ra_serf violates the
+ ### editor v1 drive ordering requirements.
+ ###
+ ### We'll override both the global value and server-specific one
+ ### for the 'http-bulk-updates' and 'http-max-connections'
+ ### options in order to get ra_serf to try a bulk-update if the
+ ### server will allow it, or at least try to limit all its
+ ### auxiliary GETs/PROPFINDs to happening (well-ordered) on a
+ ### single server connection.
+ ###
+ ### See http://subversion.tigris.org/issues/show_bug.cgi?id=4116.
+ */
+ cfg_servers = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_SERVERS,
+ APR_HASH_KEY_STRING);
+ svn_config_set_bool(cfg_servers, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_HTTP_BULK_UPDATES, TRUE);
+ svn_config_set_int64(cfg_servers, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_HTTP_MAX_CONNECTIONS, 2);
+ if (cfg_servers)
+ {
+ apr_status_t status;
+ apr_uri_t parsed_url;
+
+ status = apr_uri_parse(pool, repos_url, &parsed_url);
+ if (! status)
+ {
+ const char *server_group;
+
+ server_group = svn_config_find_group(cfg_servers, parsed_url.hostname,
+ SVN_CONFIG_SECTION_GROUPS, pool);
+ if (server_group)
+ {
+ svn_config_set_bool(cfg_servers, server_group,
+ SVN_CONFIG_OPTION_HTTP_BULK_UPDATES, TRUE);
+ svn_config_set_int64(cfg_servers, server_group,
+ SVN_CONFIG_OPTION_HTTP_MAX_CONNECTIONS, 2);
+ }
+ }
+ }
+
/* Set up our cancellation support. */
ctx->cancel_func = check_cancel;
@@ -413,16 +466,68 @@ dump_revision_header(svn_ra_session_t *s
return SVN_NO_ERROR;
}
+static svn_error_t *
+dump_initial_full_revision(svn_ra_session_t *session,
+ svn_ra_session_t *extra_ra_session,
+ svn_stream_t *stdout_stream,
+ svn_revnum_t revision,
+ svn_boolean_t quiet,
+ apr_pool_t *pool)
+{
+ const svn_ra_reporter3_t *reporter;
+ void *report_baton;
+ const svn_delta_editor_t *dump_editor;
+ void *dump_baton;
+ const char *session_url, *source_relpath;
+
+ /* Determine whether we're dumping the repository root URL or some
+ child thereof. If we're dumping a subtree of the repository
+ rather than the root, we have to jump through some hoops to make
+ our update-driven dump generation work the way a replay-driven
+ one would.
+
+ See http://subversion.tigris.org/issues/show_bug.cgi?id=4101
+ */
+ SVN_ERR(svn_ra_get_session_url(session, &session_url, pool));
+ SVN_ERR(svn_ra_get_path_relative_to_root(session, &source_relpath,
+ session_url, pool));
+
+ /* Start with a revision record header. */
+ SVN_ERR(dump_revision_header(session, stdout_stream, revision, pool));
+
+ /* Then, we'll drive the dump editor with what would look like a
+ full checkout of the repository as it looked in START_REVISION.
+ We do this by manufacturing a basic 'report' to the update
+ reporter, telling it that we have nothing to start with. The
+ delta between nothing and everything-at-REV is, effectively, a
+ full dump of REV. */
+ SVN_ERR(svn_rdump__get_dump_editor(&dump_editor, &dump_baton, revision,
+ stdout_stream, extra_ra_session,
+ source_relpath, check_cancel, NULL, pool));
+ SVN_ERR(svn_ra_do_update2(session, &reporter, &report_baton, revision,
+ "", svn_depth_infinity, FALSE,
+ dump_editor, dump_baton, pool));
+ SVN_ERR(reporter->set_path(report_baton, "", revision,
+ svn_depth_infinity, TRUE, NULL, pool));
+ SVN_ERR(reporter->finish_report(report_baton, pool));
+
+ /* All finished with START_REVISION! */
+ if (! quiet)
+ SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
+ revision));
+
+ return SVN_NO_ERROR;
+}
+
/* Replay revisions START_REVISION thru END_REVISION (inclusive) of
- * the repository located at URL, using callbacks which generate
- * Subversion repository dumpstreams describing the changes made in
- * those revisions. If QUIET is set, don't generate progress
- * messages.
+ * the repository URL at which SESSION is rooted, using callbacks
+ * which generate Subversion repository dumpstreams describing the
+ * changes made in those revisions. If QUIET is set, don't generate
+ * progress messages.
*/
static svn_error_t *
replay_revisions(svn_ra_session_t *session,
svn_ra_session_t *extra_ra_session,
- const char *url,
svn_revnum_t start_revision,
svn_revnum_t end_revision,
svn_boolean_t quiet,
@@ -465,7 +570,18 @@ replay_revisions(svn_ra_session_t *sessi
incremental = TRUE;
}
- if (incremental)
+ /* If what remains to be dumped is not going to be dumped
+ incrementally, then dump the first revision in full. */
+ if (!incremental)
+ {
+ SVN_ERR(dump_initial_full_revision(session, extra_ra_session,
+ stdout_stream, start_revision,
+ quiet, pool));
+ start_revision++;
+ }
+
+ /* If there are still revisions left to be dumped, do so. */
+ if (start_revision <= end_revision)
{
#ifndef USE_EV2_IMPL
SVN_ERR(svn_ra_replay_range(session, start_revision, end_revision,
@@ -478,54 +594,6 @@ replay_revisions(svn_ra_session_t *sessi
NULL, NULL, NULL, NULL, pool));
#endif
}
- else
- {
- const svn_ra_reporter3_t *reporter;
- void *report_baton;
- const svn_delta_editor_t *dump_editor;
- void *dump_baton;
-
- /* First, we need to dump the start_revision in full. We'll
- start with a revision record header. */
- SVN_ERR(dump_revision_header(session, stdout_stream,
- start_revision, pool));
-
- /* Then, we'll drive the dump editor with what would look like a
- full checkout of the repository as it looked in
- START_REVISION. We do this by manufacturing a basic 'report'
- to the update reporter, telling it that we have nothing to
- start with. The delta between nothing and everything-at-REV
- is, effectively, a full dump of REV. */
- SVN_ERR(svn_rdump__get_dump_editor(&dump_editor, &dump_baton,
- start_revision,
- stdout_stream, extra_ra_session,
- check_cancel, NULL, pool));
- SVN_ERR(svn_ra_do_update2(session, &reporter, &report_baton,
- start_revision, "", svn_depth_infinity,
- FALSE, dump_editor, dump_baton, pool));
- SVN_ERR(reporter->set_path(report_baton, "", start_revision,
- svn_depth_infinity, TRUE, NULL, pool));
- SVN_ERR(reporter->finish_report(report_baton, pool));
-
- /* All finished with START_REVISION! */
- if (! quiet)
- SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
- start_revision));
- start_revision++;
-
- /* Now go pick up additional revisions in the range, if any. */
- if (start_revision <= end_revision)
-#ifndef USE_EV2_IMPL
- SVN_ERR(svn_ra_replay_range(session, start_revision, end_revision,
- 0, TRUE, replay_revstart, replay_revend,
- replay_baton, pool));
-#else
- SVN_ERR(svn_ra__replay_range_ev2(session, start_revision, end_revision,
- 0, TRUE, replay_revstart_v2,
- replay_revend_v2, replay_baton,
- NULL, NULL, NULL, NULL, pool));
-#endif
- }
SVN_ERR(svn_stream_close(stdout_stream));
return SVN_NO_ERROR;
@@ -635,7 +703,6 @@ dump_cmd(apr_getopt_t *os,
SVN_ERR(svn_ra_reparent(extra_ra_session, repos_root, pool));
return replay_revisions(opt_baton->session, extra_ra_session,
- opt_baton->url,
opt_baton->start_revision.value.number,
opt_baton->end_revision.value.number,
opt_baton->quiet, opt_baton->incremental, pool);
@@ -780,6 +847,7 @@ main(int argc, const char **argv)
svn_boolean_t no_auth_cache = FALSE;
svn_boolean_t trust_server_cert = FALSE;
svn_boolean_t non_interactive = FALSE;
+ svn_boolean_t force_interactive = FALSE;
apr_array_header_t *config_options = NULL;
apr_getopt_t *os;
const char *first_arg;
@@ -898,6 +966,9 @@ main(int argc, const char **argv)
case opt_non_interactive:
non_interactive = TRUE;
break;
+ case opt_force_interactive:
+ force_interactive = TRUE;
+ break;
case opt_incremental:
opt_baton->incremental = TRUE;
break;
@@ -916,6 +987,19 @@ main(int argc, const char **argv)
}
}
+ /* The --non-interactive and --force-interactive options are mutually
+ * exclusive. */
+ if (non_interactive && force_interactive)
+ {
+ err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--non-interactive and --force-interactive "
+ "are mutually exclusive"));
+ return svn_cmdline_handle_exit_error(err, pool, "svnrdump: ");
+ }
+ else
+ non_interactive = !svn_cmdline__be_interactive(non_interactive,
+ force_interactive);
+
if (opt_baton->help)
{
subcommand = svn_opt_get_canonical_subcommand2(svnrdump__cmd_table,
@@ -1050,6 +1134,7 @@ main(int argc, const char **argv)
username,
password,
config_dir,
+ opt_baton->url,
no_auth_cache,
trust_server_cert,
config_options,