You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/11/07 15:30:36 UTC
svn commit: r1032285 [3/4] - in /subversion/branches/performance: ./ build/
build/ac-macros/ subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/bindings/javahl/src/org/apache/subversion/javahl/cal...
Modified: subversion/branches/performance/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/wc_db.c?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/wc_db.c Sun Nov 7 14:30:34 2010
@@ -710,6 +710,84 @@ blank_ibb(insert_base_baton_t *pibb)
}
+/* Extend any delete of the parent of LOCAL_RELPATH to LOCAL_RELPATH.
+
+ Given a wc:
+
+ 0 1 2 3 4
+ normal
+ A normal
+ A/B normal normal
+ A/B/C not-pres normal
+ A/B/C/D normal
+
+ That is checkout, delete A/B, copy a replacement A/B, delete copied
+ child A/B/C, add replacement A/B/C, add A/B/C/D.
+
+ Now an update that adds base nodes for A/B/C, A/B/C/D and A/B/C/D/E
+ must extend the A/B deletion:
+
+ 0 1 2 3 4
+ normal
+ A normal
+ A/B normal normal
+ A/B/C normal not-pres normal
+ A/B/C/D normal base-del normal
+ A/B/C/D/E normal base-del
+
+ When adding a base node if the parent has a working node then the
+ parent base is deleted and this must be extended to cover new base
+ node.
+
+ In the example above A/B/C/D and A/B/C/D/E are the nodes that get
+ the extended delete, A/B/C is already deleted.
+ */
+static svn_error_t *
+extend_parent_delete(svn_sqlite__db_t *sdb,
+ apr_int64_t wc_id,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t have_row;
+ svn_sqlite__stmt_t *stmt;
+ apr_int64_t parent_op_depth;
+ const char *parent_relpath = svn_relpath_dirname(local_relpath, scratch_pool);
+
+ SVN_ERR_ASSERT(local_relpath[0]);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_SELECT_LOWEST_WORKING_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, parent_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ parent_op_depth = svn_sqlite__column_int64(stmt, 0);
+ SVN_ERR(svn_sqlite__reset(stmt));
+ if (have_row)
+ {
+ apr_int64_t op_depth;
+
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ op_depth = svn_sqlite__column_int64(stmt, 0);
+ SVN_ERR(svn_sqlite__reset(stmt));
+ if (!have_row || parent_op_depth < op_depth)
+ {
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_INSERT_WORKING_NODE_FROM_BASE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isit", wc_id,
+ local_relpath, parent_op_depth,
+ presence_map,
+ svn_wc__db_status_base_deleted));
+ SVN_ERR(svn_sqlite__update(NULL, stmt));
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+
/* */
static svn_error_t *
insert_base_node(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
@@ -773,6 +851,10 @@ insert_base_node(void *baton, svn_sqlite
0 /* BASE */,
scratch_pool));
+ if (parent_relpath)
+ SVN_ERR(extend_parent_delete(sdb, pibb->wc_id, pibb->local_relpath,
+ scratch_pool));
+
SVN_ERR(add_work_items(sdb, pibb->work_items, scratch_pool));
return SVN_NO_ERROR;
@@ -791,49 +873,6 @@ blank_iwb(insert_working_baton_t *piwb)
}
-/* Copy the row specified by BATON->(wc_id,local_relpath) from BASE to
- * WORKING, changing its 'presence' and 'op_depth' to the values in BATON. */
-static svn_error_t *
-copy_working_from_base(void *baton,
- svn_sqlite__db_t *sdb,
- apr_pool_t *scratch_pool)
-{
- const insert_working_baton_t *piwb = baton;
- svn_sqlite__stmt_t *stmt;
-#ifdef SVN_WC__OP_DEPTH
- const char *like_arg;
-#endif
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_INSERT_WORKING_NODE_FROM_BASE));
- SVN_ERR(svn_sqlite__bindf(stmt, "isit", piwb->wc_id,
- piwb->local_relpath,
- piwb->op_depth,
- presence_map, piwb->presence));
- SVN_ERR(svn_sqlite__insert(NULL, stmt));
-
-#ifdef SVN_WC__OP_DEPTH
- /* Need to update the op_depth of all deleted child trees -- this
- relies on the recursion having already deleted the trees so
- that they are all at op_depth+1.
-
- ### Rewriting the op_depth means that the number of queries is
- ### O(depth^2). Fix it by implementing svn_wc__db_op_delete so
- ### that the recursion gets moved from adm_ops.c to wc_db.c and
- ### one transaction does the whole tree and thus each op_depth
- ### only gets written once. */
- like_arg = construct_like_arg(piwb->local_relpath, scratch_pool);
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_UPDATE_OP_DEPTH_RECURSIVE));
- SVN_ERR(svn_sqlite__bindf(stmt, "isi",
- piwb->wc_id, like_arg, piwb->op_depth));
- SVN_ERR(svn_sqlite__update(NULL, stmt));
-#endif
-
- return SVN_NO_ERROR;
-}
-
-
/* Insert a row in NODES for each (const char *) child name in CHILDREN,
whose parent directory is LOCAL_RELPATH, at op_depth=OP_DEPTH. Set each
child's presence to 'incomplete', kind to 'unknown', repos_id to REPOS_ID,
@@ -1814,40 +1853,31 @@ svn_wc__db_base_remove(svn_wc__db_t *db,
}
-svn_error_t *
-svn_wc__db_base_get_info(svn_wc__db_status_t *status,
- svn_wc__db_kind_t *kind,
- svn_revnum_t *revision,
- const char **repos_relpath,
- const char **repos_root_url,
- const char **repos_uuid,
- svn_revnum_t *changed_rev,
- apr_time_t *changed_date,
- const char **changed_author,
- apr_time_t *last_mod_time,
- svn_depth_t *depth,
- const svn_checksum_t **checksum,
- svn_filesize_t *translated_size,
- const char **target,
- svn_wc__db_lock_t **lock,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+static svn_error_t *
+base_get_info(svn_wc__db_status_t *status,
+ svn_wc__db_kind_t *kind,
+ svn_revnum_t *revision,
+ const char **repos_relpath,
+ const char **repos_root_url,
+ const char **repos_uuid,
+ svn_revnum_t *changed_rev,
+ apr_time_t *changed_date,
+ const char **changed_author,
+ apr_time_t *last_mod_time,
+ svn_depth_t *depth,
+ const svn_checksum_t **checksum,
+ svn_filesize_t *translated_size,
+ const char **target,
+ svn_wc__db_lock_t **lock,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- svn_wc__db_pdh_t *pdh;
- const char *local_relpath;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
svn_error_t *err = SVN_NO_ERROR;
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
- SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
- local_abspath, svn_sqlite__mode_readonly,
- scratch_pool, scratch_pool));
- VERIFY_USABLE_PDH(pdh);
-
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
lock ? STMT_SELECT_BASE_NODE_WITH_LOCK
: STMT_SELECT_BASE_NODE));
@@ -1924,7 +1954,8 @@ svn_wc__db_base_get_info(svn_wc__db_stat
err = svn_error_createf(
err->apr_err, err,
_("The node '%s' has a corrupt checksum value."),
- svn_dirent_local_style(local_abspath, scratch_pool));
+ path_for_error_message(pdh->wcroot, local_relpath,
+ scratch_pool));
}
}
if (translated_size)
@@ -1943,7 +1974,7 @@ svn_wc__db_base_get_info(svn_wc__db_stat
{
err = svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
_("The node '%s' was not found."),
- svn_dirent_local_style(local_abspath,
+ path_for_error_message(pdh->wcroot, local_relpath,
scratch_pool));
}
@@ -1953,6 +1984,45 @@ svn_wc__db_base_get_info(svn_wc__db_stat
svn_error_t *
+svn_wc__db_base_get_info(svn_wc__db_status_t *status,
+ svn_wc__db_kind_t *kind,
+ svn_revnum_t *revision,
+ const char **repos_relpath,
+ const char **repos_root_url,
+ const char **repos_uuid,
+ svn_revnum_t *changed_rev,
+ apr_time_t *changed_date,
+ const char **changed_author,
+ apr_time_t *last_mod_time,
+ svn_depth_t *depth,
+ const svn_checksum_t **checksum,
+ svn_filesize_t *translated_size,
+ const char **target,
+ svn_wc__db_lock_t **lock,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_pdh_t *pdh;
+ const char *local_relpath;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+ local_abspath, svn_sqlite__mode_readonly,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(pdh);
+
+ SVN_ERR(base_get_info(status, kind, revision, repos_relpath, repos_root_url,
+ repos_uuid, changed_rev, changed_date, changed_author,
+ last_mod_time, depth, checksum, translated_size,
+ target, lock,
+ pdh, local_relpath, result_pool, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_wc__db_base_get_prop(const svn_string_t **propval,
svn_wc__db_t *db,
const char *local_abspath,
@@ -3174,8 +3244,8 @@ copy_actual_rows(svn_wc__db_pdh_t *src_p
src_pdh->wcroot->wc_id, src_relpath,
construct_like_arg(src_relpath, scratch_pool),
dst_relpath, dst_parent_relpath,
- strlen(src_relpath) + 1,
- strlen(src_parent_relpath) + 1));
+ (apr_int64_t)(strlen(src_relpath) + 1),
+ (apr_int64_t)(strlen(src_parent_relpath) + 1)));
SVN_ERR(svn_sqlite__step_done(stmt));
return SVN_NO_ERROR;
@@ -4425,7 +4495,7 @@ svn_wc__db_temp_op_remove_working(svn_wc
SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
- STMT_DELETE_WORKING_NODES));
+ STMT_DELETE_WORKING_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
@@ -4526,57 +4596,67 @@ delete_not_present_children(svn_wc__db_p
/* Update the working node for LOCAL_ABSPATH setting presence=STATUS */
static svn_error_t *
db_working_update_presence(svn_wc__db_status_t status,
- svn_wc__db_t *db,
- const char *local_abspath,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
apr_pool_t *scratch_pool)
{
- svn_wc__db_pdh_t *pdh;
- const char *local_relpath;
svn_sqlite__stmt_t *stmt;
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
- local_abspath, svn_sqlite__mode_readwrite,
- scratch_pool, scratch_pool));
- VERIFY_USABLE_PDH(pdh);
-
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
STMT_UPDATE_NODE_WORKING_PRESENCE));
SVN_ERR(svn_sqlite__bindf(stmt, "ist", pdh->wcroot->wc_id, local_relpath,
presence_map, status));
SVN_ERR(svn_sqlite__step_done(stmt));
- /* Switching to base-deleted is undoing an add/copy. If this was a
- copy then any children of the copy will now be not-present and
- should be removed. By this stage an add will have no children. */
if (status == svn_wc__db_status_base_deleted)
- SVN_ERR(delete_not_present_children(pdh, local_relpath, scratch_pool));
+ {
+ /* Switching to base-deleted is undoing an add/copy. If this
+ was a copy then any children of the copy will now be
+ not-present and should be removed. By this stage an add will
+ have no children. */
+ SVN_ERR(delete_not_present_children(pdh, local_relpath, scratch_pool));
+
+ /* Reset the copyfrom in case this was a copy.
+ ### What else should be reset? Properties? Or copy the node again? */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_UPDATE_COPYFROM_TO_INHERIT));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+ }
+
+ /* ### Should the switch to not-present remove an ACTUAL row? */
return SVN_NO_ERROR;
}
/* Delete working and actual nodes for LOCAL_ABSPATH. When called any
- remain working child sub-trees should be presence=not-present and will
- be deleted. */
+ remaining working child sub-trees should be presence=not-present
+ and will be deleted. */
static svn_error_t *
-db_working_actual_remove(svn_wc__db_t *db,
- const char *local_abspath,
+db_working_actual_remove(svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
apr_pool_t *scratch_pool)
{
- svn_wc__db_pdh_t *pdh;
- const char *local_relpath;
svn_sqlite__stmt_t *stmt;
+ apr_int64_t op_depth;
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
- local_abspath, svn_sqlite__mode_readwrite,
- scratch_pool, scratch_pool));
+ /* Precondition: There is a working row in NODES.
+ * Record its op_depth, which is needed for postcondition checking. */
+ {
+ svn_boolean_t have_row;
- VERIFY_USABLE_PDH(pdh);
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_SELECT_WORKING_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ SVN_ERR_ASSERT(have_row);
+ op_depth = svn_sqlite__column_int64(stmt, 0);
+ SVN_ERR(svn_sqlite__reset(stmt));
+ }
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
- STMT_DELETE_WORKING_NODES));
+ STMT_DELETE_WORKING_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
@@ -4587,7 +4667,32 @@ db_working_actual_remove(svn_wc__db_t *d
SVN_ERR(delete_not_present_children(pdh, local_relpath, scratch_pool));
- SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
+ /* Postcondition: There are no NODES rows in this subtree, at same or
+ * greater op_depth. */
+ {
+ svn_boolean_t have_row;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_SELECT_NODES_GE_OP_DEPTH_RECURSIVE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "issi", pdh->wcroot->wc_id, local_relpath,
+ construct_like_arg(local_relpath, scratch_pool),
+ op_depth));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ SVN_ERR_ASSERT(! have_row);
+ SVN_ERR(svn_sqlite__reset(stmt));
+ }
+ /* Postcondition: There are no ACTUAL_NODE rows in this subtree. */
+ {
+ svn_boolean_t have_row;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_SELECT_ACTUAL_NODE_RECURSIVE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "iss", pdh->wcroot->wc_id, local_relpath,
+ construct_like_arg(local_relpath, scratch_pool)));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ SVN_ERR_ASSERT(! have_row);
+ SVN_ERR(svn_sqlite__reset(stmt));
+ }
return SVN_NO_ERROR;
}
@@ -4598,38 +4703,40 @@ db_working_actual_remove(svn_wc__db_t *d
/* Insert a working node for LOCAL_ABSPATH with presence=STATUS. */
static svn_error_t *
db_working_insert(svn_wc__db_status_t status,
- svn_wc__db_t *db,
- const char *local_abspath,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
apr_pool_t *scratch_pool)
{
- svn_wc__db_pdh_t *pdh;
- const char *local_relpath;
- insert_working_baton_t iwb;
-
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
- local_abspath, svn_sqlite__mode_readwrite,
- scratch_pool, scratch_pool));
- VERIFY_USABLE_PDH(pdh);
-
- /* Update WORKING_NODE and NODE_DATA transactionally */
- blank_iwb(&iwb);
-
- iwb.wc_id = pdh->wcroot->wc_id;
- iwb.local_relpath = local_relpath;
- iwb.presence = status;
+ svn_sqlite__stmt_t *stmt;
#ifdef SVN_WC__OP_DEPTH
- iwb.op_depth = relpath_depth(local_relpath);
+ const char *like_arg = construct_like_arg(local_relpath, scratch_pool);
+ apr_int64_t op_depth = relpath_depth(local_relpath);
#else
- iwb.op_depth = 2; /* ### temporary op_depth */
+ apr_int64_t op_depth = 2; /* ### temporary op_depth */
#endif
- SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
- copy_working_from_base, &iwb,
- scratch_pool));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_INSERT_WORKING_NODE_FROM_BASE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isit", pdh->wcroot->wc_id,
+ local_relpath, op_depth, presence_map, status));
+ SVN_ERR(svn_sqlite__insert(NULL, stmt));
+#ifdef SVN_WC__OP_DEPTH
+ /* Need to update the op_depth of all deleted child trees -- this
+ relies on the recursion having already deleted the trees so
+ that they are all at op_depth+1.
- SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
+ ### Rewriting the op_depth means that the number of queries is
+ ### O(depth^2). Fix it by implementing svn_wc__db_op_delete so
+ ### that the recursion gets moved from adm_ops.c to wc_db.c and
+ ### one transaction does the whole tree and thus each op_depth
+ ### only gets written once. */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_UPDATE_OP_DEPTH_RECURSIVE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isi",
+ pdh->wcroot->wc_id, like_arg, op_depth));
+ SVN_ERR(svn_sqlite__update(NULL, stmt));
+#endif
return SVN_NO_ERROR;
}
@@ -4707,138 +4814,224 @@ is_add_or_root_of_copy(svn_boolean_t *ad
return SVN_NO_ERROR;
}
-
-/* Delete LOCAL_ABSPATH. Implements the delete transition from
- notes/wc-ng/transitions. */
-svn_error_t *
-svn_wc__db_temp_op_delete(svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool)
+/* Convert STATUS, the raw status obtained from the presence map, to
+ the status appropriate for a working (op_depth > 0) node and return
+ it in *WORKING_STATUS. */
+static svn_error_t *
+convert_to_working_status(svn_wc__db_status_t *working_status,
+ svn_wc__db_status_t status)
{
- svn_wc__db_pdh_t *pdh;
- const char *local_relpath;
- svn_wc__db_status_t base_status, working_status, new_working_status;
- svn_boolean_t have_base, have_work, new_have_work;
+ svn_wc__db_status_t work_status = status;
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+ SVN_ERR_ASSERT(work_status == svn_wc__db_status_normal
+ || work_status == svn_wc__db_status_not_present
+ || work_status == svn_wc__db_status_base_deleted
+ || work_status == svn_wc__db_status_incomplete
+ || work_status == svn_wc__db_status_excluded);
- SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
- local_abspath, svn_sqlite__mode_readonly,
- scratch_pool, scratch_pool));
- VERIFY_USABLE_PDH(pdh);
+ if (work_status == svn_wc__db_status_incomplete)
+ {
+ *working_status = svn_wc__db_status_incomplete;
+ }
+ else if (work_status == svn_wc__db_status_excluded)
+ {
+ *working_status = svn_wc__db_status_excluded;
+ }
+ else if (work_status == svn_wc__db_status_not_present
+ || work_status == svn_wc__db_status_base_deleted)
+ {
+ /* The caller should scan upwards to detect whether this
+ deletion has occurred because this node has been moved
+ away, or it is a regular deletion. Also note that the
+ deletion could be of the BASE tree, or a child of
+ something that has been copied/moved here. */
- SVN_ERR(read_info(&working_status, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, &have_base, &have_work, NULL, NULL,
- pdh, local_relpath,
- scratch_pool, scratch_pool));
- if (working_status == svn_wc__db_status_deleted)
+ *working_status = svn_wc__db_status_deleted;
+ }
+ else /* normal */
{
- /* The node is already deleted. */
- /* ### return an error? callers should know better. */
- return SVN_NO_ERROR;
+ /* The caller should scan upwards to detect whether this
+ addition has occurred because of a simple addition,
+ a copy, or is the destination of a move. */
+ *working_status = svn_wc__db_status_added;
}
- if (have_base)
- SVN_ERR(svn_wc__db_base_get_info(&base_status,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- db, local_abspath,
- scratch_pool, scratch_pool));
+ return SVN_NO_ERROR;
+}
- if (have_base && (base_status == svn_wc__db_status_absent
- || base_status == svn_wc__db_status_excluded))
- return SVN_NO_ERROR; /* ### should return an error.... WHICH ONE? */
+/* Return the status of the node, if any, below the "working" node.
+ Set *HAVE_BASE or *HAVE_WORK to indicate if a base node or lower
+ working node is present, and *STATUS to the status of the node.
- new_have_work = have_work;
- new_working_status = working_status;
+ This is an experimental interface. It appears that delete only
+ needs to know whether the below node is base or not (if it is a
+ base the status is available via base_get_info). It's possible
+ this function should be removed and read_info modified to return
+ the "lower is base". I'll leave it for now because delete may turn
+ out to need more info. */
+static svn_error_t *
+info_below_working(svn_boolean_t *have_base,
+ svn_boolean_t *have_work,
+ svn_wc__db_status_t *status,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
- if (working_status == svn_wc__db_status_normal
- || working_status == svn_wc__db_status_not_present)
- {
- /* No structural changes (ie. no WORKING node). Mark the BASE node
- as deleted. */
+ *have_base = *have_work = FALSE;
- SVN_ERR_ASSERT(!have_work);
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_SELECT_NODE_INFO));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is",
+ pdh->wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ {
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ {
+ apr_int64_t op_depth = svn_sqlite__column_int64(stmt, 0);
- new_have_work = TRUE;
- new_working_status = svn_wc__db_status_base_deleted;
+ if (op_depth > 0)
+ *have_work = TRUE;
+ else
+ *have_base = TRUE;
+
+ *status = svn_sqlite__column_token(stmt, 3, presence_map);
+ if (op_depth > 0)
+ SVN_ERR(convert_to_working_status(status, *status));
+ }
}
- /* ### remaining states: added, absent, excluded, incomplete
- ### the last three have debatable schedule-delete semantics,
- ### and this code may need to change further, but I'm not
- ### going to worry about it now
- */
- else if (!have_work)
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ return SVN_NO_ERROR;
+}
+
+struct temp_op_delete_baton {
+ svn_wc__db_pdh_t *pdh;
+ const char *local_relpath;
+
+ /* The following two are only needed for svn_wc__db_temp_forget_directory */
+ svn_wc__db_t *db;
+ const char *local_abspath;
+};
+
+/* Deletes BATON->LOCAL_RELPATH using BATON->PDH. */
+static svn_error_t *
+temp_op_delete_txn(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
+{
+ struct temp_op_delete_baton *b = baton;
+ svn_wc__db_status_t status, new_working_status;
+ svn_boolean_t have_work, new_have_work;
+
+ SVN_ERR(read_info(&status,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ &have_work,
+ NULL, NULL,
+ b->pdh, b->local_relpath,
+ scratch_pool, scratch_pool));
+
+ new_have_work = have_work;
+ new_working_status = status;
+
+ if (!have_work)
{
/* No structural changes */
- if (base_status == svn_wc__db_status_normal
- || base_status == svn_wc__db_status_incomplete
- || base_status == svn_wc__db_status_excluded)
+ if (status == svn_wc__db_status_normal
+ || status == svn_wc__db_status_incomplete)
{
new_have_work = TRUE;
new_working_status = svn_wc__db_status_base_deleted;
}
}
- /* ### BH: have_base is not a safe check, because a node can
- ### still be a child of an added node even though it replaces
- ### a base node. */
- else if (working_status == svn_wc__db_status_added
- && (!have_base || base_status == svn_wc__db_status_not_present))
+ else if (status == svn_wc__db_status_added)
{
- /* ADD/COPY-HERE/MOVE-HERE. There is "no BASE node". */
-
+ /* ADD/COPY-HERE/MOVE-HERE */
svn_boolean_t add_or_root_of_copy;
SVN_ERR(is_add_or_root_of_copy(&add_or_root_of_copy,
- pdh, local_relpath, scratch_pool));
- if (add_or_root_of_copy)
- new_have_work = FALSE;
- else
- new_working_status = svn_wc__db_status_not_present;
- }
- else if (working_status == svn_wc__db_status_added)
- {
- /* DELETE + ADD */
- svn_boolean_t add_or_root_of_copy;
- SVN_ERR(is_add_or_root_of_copy(&add_or_root_of_copy,
- pdh, local_relpath, scratch_pool));
+ b->pdh, b->local_relpath, scratch_pool));
if (add_or_root_of_copy)
- new_working_status = svn_wc__db_status_base_deleted;
+ {
+ svn_boolean_t below_base, below_work;
+ svn_wc__db_status_t below_status;
+
+ SVN_ERR(info_below_working(&below_base, &below_work, &below_status,
+ b->pdh, b->local_relpath, scratch_pool));
+
+ if (below_base && below_status != svn_wc__db_status_not_present)
+ new_working_status = svn_wc__db_status_base_deleted;
+ else
+ new_have_work = FALSE;
+ }
else
new_working_status = svn_wc__db_status_not_present;
}
- else if (working_status == svn_wc__db_status_incomplete)
+ else if (status == svn_wc__db_status_incomplete)
{
svn_boolean_t add_or_root_of_copy;
SVN_ERR(is_add_or_root_of_copy(&add_or_root_of_copy,
- pdh, local_relpath, scratch_pool));
+ b->pdh, b->local_relpath, scratch_pool));
if (add_or_root_of_copy)
new_have_work = FALSE;
}
if (!new_have_work && have_work)
{
- SVN_ERR(db_working_actual_remove(db, local_abspath, scratch_pool));
- /* ### Search the cached directories in db for directories below
- local_abspath and close their handles to allow deleting
- them from the working copy */
- SVN_ERR(svn_wc__db_temp_forget_directory(db, local_abspath,
+ SVN_ERR(db_working_actual_remove(b->pdh, b->local_relpath, scratch_pool));
+
+ /* This is needed for access batons? */
+ SVN_ERR(svn_wc__db_temp_forget_directory(b->db, b->local_abspath,
scratch_pool));
}
else if (new_have_work && !have_work)
- SVN_ERR(db_working_insert(new_working_status,
- db, local_abspath, scratch_pool));
+ {
+ SVN_ERR(db_working_insert(new_working_status, b->pdh, b->local_relpath,
+ scratch_pool));
+ }
else if (new_have_work && have_work
- && new_working_status != working_status)
- SVN_ERR(db_working_update_presence(new_working_status,
- db, local_abspath, scratch_pool));
- /* ### else nothing to do, return an error? */
+ && new_working_status != status)
+ {
+ SVN_ERR(db_working_update_presence(new_working_status, b->pdh,
+ b->local_relpath, scratch_pool));
+ }
+ else
+ {
+ /* Already deleted, or absent or excluded. */
+ /* ### Nothing to do, return an error? Which one? */
+ }
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc__db_temp_op_delete(svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool)
+{
+ struct temp_op_delete_baton b;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&b.pdh, &b.local_relpath, db,
+ local_abspath, svn_sqlite__mode_readwrite,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(b.pdh);
+
+ /* These two for svn_wc__db_temp_forget_directory */
+ b.db = db;
+ b.local_abspath = local_abspath;
+
+ SVN_ERR(svn_sqlite__with_transaction(b.pdh->wcroot->sdb, temp_op_delete_txn,
+ &b, scratch_pool));
+
+ SVN_ERR(flush_entries(db, b.pdh, local_abspath, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
/* Like svn_wc__db_read_info(), but with PDH+LOCAL_RELPATH instead of
* DB+LOCAL_ABSPATH.*/
@@ -4914,43 +5107,7 @@ read_info(svn_wc__db_status_t *status,
*status = svn_sqlite__column_token(stmt_info, 3, presence_map);
if (op_depth != 0) /* WORKING */
- {
- svn_wc__db_status_t work_status;
-
- work_status = *status;
- SVN_ERR_ASSERT(work_status == svn_wc__db_status_normal
- || work_status == svn_wc__db_status_not_present
- || work_status == svn_wc__db_status_base_deleted
- || work_status == svn_wc__db_status_incomplete
- || work_status == svn_wc__db_status_excluded);
-
- if (work_status == svn_wc__db_status_incomplete)
- {
- *status = svn_wc__db_status_incomplete;
- }
- else if (work_status == svn_wc__db_status_excluded)
- {
- *status = svn_wc__db_status_excluded;
- }
- else if (work_status == svn_wc__db_status_not_present
- || work_status == svn_wc__db_status_base_deleted)
- {
- /* The caller should scan upwards to detect whether this
- deletion has occurred because this node has been moved
- away, or it is a regular deletion. Also note that the
- deletion could be of the BASE tree, or a child of
- something that has been copied/moved here. */
-
- *status = svn_wc__db_status_deleted;
- }
- else /* normal */
- {
- /* The caller should scan upwards to detect whether this
- addition has occurred because of a simple addition,
- a copy, or is the destination of a move. */
- *status = svn_wc__db_status_added;
- }
- }
+ SVN_ERR(convert_to_working_status(status, *status));
}
if (kind)
{
@@ -5286,13 +5443,7 @@ svn_wc__db_read_children_info(apr_hash_t
child->status = svn_sqlite__column_token(stmt, 3, presence_map);
if (*op_depth != 0)
- {
- if (child->status == svn_wc__db_status_not_present
- || child->status == svn_wc__db_status_base_deleted)
- child->status = svn_wc__db_status_deleted;
- else if (child->status == svn_wc__db_status_normal)
- child->status = svn_wc__db_status_added;
- }
+ SVN_ERR(convert_to_working_status(&child->status, child->status));
if (*op_depth != 0)
child->revnum = SVN_INVALID_REVNUM;
@@ -5992,8 +6143,10 @@ commit_node(void *baton, svn_sqlite__db_
if (have_work)
{
+ /* This removes all op_depth > 0 and so does both layers of a
+ two-layer replace. */
SVN_ERR(svn_sqlite__get_statement(&stmt, cb->pdh->wcroot->sdb,
- STMT_DELETE_WORKING_NODES));
+ STMT_DELETE_ALL_WORKING_NODES));
SVN_ERR(svn_sqlite__bindf(stmt, "is",
cb->pdh->wcroot->wc_id, cb->local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
@@ -7934,24 +8087,46 @@ svn_wc__db_read_kind(svn_wc__db_kind_t *
svn_boolean_t allow_missing,
apr_pool_t *scratch_pool)
{
- svn_error_t *err;
+ svn_wc__db_pdh_t *pdh;
+ const char *local_relpath;
+ svn_sqlite__stmt_t *stmt_info;
+ svn_boolean_t have_info;
- err = svn_wc__db_read_info(NULL, kind, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL,
- db, local_abspath, scratch_pool, scratch_pool);
- if (!err)
- return SVN_NO_ERROR;
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- if (allow_missing && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+ local_abspath, svn_sqlite__mode_readonly,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(pdh);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt_info, pdh->wcroot->sdb,
+ STMT_SELECT_NODE_INFO));
+ SVN_ERR(svn_sqlite__bindf(stmt_info, "is",
+ pdh->wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_info, stmt_info));
+
+ if (!have_info)
{
- svn_error_clear(err);
- *kind = svn_wc__db_kind_unknown;
- return SVN_NO_ERROR;
+ if (allow_missing)
+ {
+ *kind = svn_wc__db_kind_unknown;
+ SVN_ERR(svn_sqlite__reset(stmt_info));
+ return SVN_NO_ERROR;
+ }
+ else
+ {
+ SVN_ERR(svn_sqlite__reset(stmt_info));
+ return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("The node '%s' was not found."),
+ path_for_error_message(pdh->wcroot,
+ local_relpath,
+ scratch_pool));
+ }
}
- return svn_error_return(err);
+ *kind = svn_sqlite__column_token(stmt_info, 4, kind_map);
+
+ return svn_error_return(svn_sqlite__reset(stmt_info));
}
@@ -7998,10 +8173,10 @@ svn_wc__db_node_hidden(svn_boolean_t *hi
SVN_ERR(svn_sqlite__reset(stmt));
/* Now check the BASE node's status. */
- SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, db, local_abspath,
- scratch_pool, scratch_pool));
+ SVN_ERR(base_get_info(&base_status,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ pdh, local_relpath, scratch_pool, scratch_pool));
*hidden = (base_status == svn_wc__db_status_absent
|| base_status == svn_wc__db_status_not_present
@@ -8564,11 +8739,11 @@ start_directory_update_txn(void *baton,
&stmt, db,
STMT_UPDATE_BASE_NODE_PRESENCE_REVNUM_AND_REPOS_PATH));
- SVN_ERR(svn_sqlite__bindf(stmt, "istis",
+ SVN_ERR(svn_sqlite__bindf(stmt, "istrs",
du->wc_id,
du->local_relpath,
presence_map, svn_wc__db_status_incomplete,
- (apr_int64_t)du->new_rev,
+ du->new_rev,
du->new_repos_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
@@ -8736,7 +8911,7 @@ make_copy_txn(void *baton,
if (remove_working)
{
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_DELETE_WORKING_NODES));
+ STMT_DELETE_WORKING_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "is",
mcb->pdh->wcroot->wc_id,
mcb->local_relpath));
@@ -9273,9 +9448,9 @@ set_rev_relpath_txn(void *baton,
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_UPDATE_BASE_REVISION));
- SVN_ERR(svn_sqlite__bindf(stmt, "isi", rrb->pdh->wcroot->wc_id,
+ SVN_ERR(svn_sqlite__bindf(stmt, "isr", rrb->pdh->wcroot->wc_id,
rrb->local_relpath,
- (apr_int64_t)rrb->rev));
+ rrb->rev));
SVN_ERR(svn_sqlite__step_done(stmt));
}
@@ -9364,14 +9539,6 @@ set_new_dir_to_incomplete_txn(void *bato
SVN_ERR(create_repos_id(&repos_id, dtb->repos_root_url, dtb->repos_uuid,
sdb, scratch_pool));
- /* Delete the base and working node data */
- SVN_ERR(svn_sqlite__get_statement(&stmt, dtb->pdh->wcroot->sdb,
- STMT_DELETE_NODES));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", dtb->pdh->wcroot->wc_id,
- dtb->local_relpath));
- SVN_ERR(svn_sqlite__step_done(stmt));
-
- /* Insert the incomplete base node */
SVN_ERR(svn_sqlite__get_statement(&stmt, dtb->pdh->wcroot->sdb,
STMT_INSERT_NODE));
@@ -9393,6 +9560,10 @@ set_new_dir_to_incomplete_txn(void *bato
SVN_ERR(svn_sqlite__step_done(stmt));
+ if (parent_relpath)
+ SVN_ERR(extend_parent_delete(dtb->pdh->wcroot->sdb, dtb->pdh->wcroot->wc_id,
+ dtb->local_relpath, scratch_pool));
+
return SVN_NO_ERROR;
}
Modified: subversion/branches/performance/subversion/mod_authz_svn/INSTALL
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/mod_authz_svn/INSTALL?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/mod_authz_svn/INSTALL (original)
+++ subversion/branches/performance/subversion/mod_authz_svn/INSTALL Sun Nov 7 14:30:34 2010
@@ -79,6 +79,26 @@ II. Configuration
though AuthzSVNAnonymous was set to 'No'. The AuthzSVNAnonymous
directive prevents the anonymous access check from being run.
+ D. Example 4: Per-repository access file
+
+ This configuration allows to use SVNParentPath but have
+ different authz files per repository.
+
+ <Location /svn>
+ DAV svn
+ SVNParentPath /path/to/reposparent
+
+ AuthType Basic
+ AuthName "Subversion repository"
+ AuthUserFile /path/to/htpasswd/file
+
+ AuthzSVNReposRelativeAccessFile filename
+
+ Require valid-user
+ </Location>
+
+ NOTE: AuthzSVNReposRelativeAccessFile filename causes the authz file
+ to be read from <repo path>/conf/<filename>
2. Specifying permissions
Modified: subversion/branches/performance/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/mod_authz_svn/mod_authz_svn.c?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/branches/performance/subversion/mod_authz_svn/mod_authz_svn.c Sun Nov 7 14:30:34 2010
@@ -52,6 +52,7 @@ typedef struct {
int no_auth_when_anon_ok;
const char *base_path;
const char *access_file;
+ const char *repo_relative_access_file;
const char *force_username_case;
} authz_svn_config_rec;
@@ -76,6 +77,37 @@ create_authz_svn_dir_config(apr_pool_t *
return conf;
}
+static const char *
+AuthzSVNAccessFile_cmd(cmd_parms *cmd, void *config, const char *arg1)
+{
+ authz_svn_config_rec *conf = config;
+
+ if (conf->repo_relative_access_file != NULL)
+ return "AuthzSVNAccessFile cannot be defined at "
+ "same time as AuthzSVNReposRelativeAccessFile.";
+
+ conf->access_file = ap_server_root_relative(cmd->pool, arg1);
+
+ return NULL;
+}
+
+
+static const char *
+AuthzSVNReposRelativeAccessFile_cmd(cmd_parms *cmd,
+ void *config,
+ const char *arg1)
+{
+ authz_svn_config_rec *conf = config;
+
+ if (conf->access_file != NULL)
+ return "AuthzSVNReposRelativeAccessFile cannot be defined at "
+ "same time as AuthzSVNAccessFile.";
+
+ conf->repo_relative_access_file = arg1;
+
+ return NULL;
+}
+
/* Implements the #cmds member of Apache's #module vtable. */
static const command_rec authz_svn_cmds[] =
{
@@ -84,10 +116,17 @@ static const command_rec authz_svn_cmds[
OR_AUTHCFG,
"Set to 'Off' to allow access control to be passed along to "
"lower modules. (default is On.)"),
- AP_INIT_TAKE1("AuthzSVNAccessFile", ap_set_file_slot,
- (void *)APR_OFFSETOF(authz_svn_config_rec, access_file),
+ AP_INIT_TAKE1("AuthzSVNAccessFile", AuthzSVNAccessFile_cmd,
+ NULL,
+ OR_AUTHCFG,
+ "Path to text file containing permissions of repository "
+ "paths."),
+ AP_INIT_TAKE1("AuthzSVNReposRelativeAccessFile",
+ AuthzSVNReposRelativeAccessFile_cmd,
+ NULL,
OR_AUTHCFG,
- "Text file containing permissions of repository paths."),
+ "Path (relative to repository 'conf' directory) to text "
+ "file containing permissions of repository paths. "),
AP_INIT_FLAG("AuthzSVNAnonymous", ap_set_flag_slot,
(void *)APR_OFFSETOF(authz_svn_config_rec, anonymous),
OR_AUTHCFG,
@@ -119,18 +158,40 @@ static svn_authz_t *
get_access_conf(request_rec *r, authz_svn_config_rec *conf)
{
const char *cache_key = NULL;
+ const char *access_file;
+ const char *repos_path;
void *user_data = NULL;
svn_authz_t *access_conf = NULL;
svn_error_t *svn_err;
+ dav_error *dav_err;
char errbuf[256];
+ if (conf->repo_relative_access_file)
+ {
+ dav_err = dav_svn_get_repos_path(r, conf->base_path, &repos_path);
+ if (dav_err) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, dav_err->desc);
+ return NULL;
+ }
+ access_file = svn_dirent_join_many(r->pool, repos_path, "conf",
+ conf->repo_relative_access_file,
+ NULL);
+ }
+ else
+ {
+ access_file = conf->access_file;
+ }
+
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Path to authz file is %s", access_file);
+
cache_key = apr_pstrcat(r->pool, "mod_authz_svn:",
- conf->access_file, (char *)NULL);
+ access_file, (char *)NULL);
apr_pool_userdata_get(&user_data, cache_key, r->connection->pool);
access_conf = user_data;
if (access_conf == NULL)
{
- svn_err = svn_repos_authz_read(&access_conf, conf->access_file,
+ svn_err = svn_repos_authz_read(&access_conf, access_file,
TRUE, r->connection->pool);
if (svn_err)
{
@@ -516,7 +577,8 @@ subreq_bypass(request_rec *r,
username_to_authorize = get_username_to_authorize(r, conf);
/* If configured properly, this should never be true, but just in case. */
- if (!conf->anonymous || !conf->access_file)
+ if (!conf->anonymous || !conf->access_file
+ || !conf->repo_relative_access_file)
{
log_access_verdict(APLOG_MARK, r, 0, repos_path, NULL);
return HTTP_FORBIDDEN;
@@ -580,7 +642,8 @@ access_checker(request_rec *r)
int status;
/* We are not configured to run */
- if (!conf->anonymous || !conf->access_file)
+ if (!conf->anonymous
+ || (!conf->access_file && !conf->repo_relative_access_file))
return DECLINED;
if (ap_some_auth_required(r))
@@ -638,7 +701,8 @@ check_user_id(request_rec *r)
/* We are not configured to run, or, an earlier module has already
* authenticated this request. */
- if (!conf->access_file || !conf->no_auth_when_anon_ok || r->user)
+ if ((!conf->access_file && !conf->repo_relative_access_file)
+ || !conf->no_auth_when_anon_ok || r->user)
return DECLINED;
/* If anon access is allowed, return OK, preventing later modules
@@ -665,7 +729,7 @@ auth_checker(request_rec *r)
int status;
/* We are not configured to run */
- if (!conf->access_file)
+ if (!conf->access_file && !conf->repo_relative_access_file)
return DECLINED;
/* Previous hook (check_user_id) already did all the work,
Modified: subversion/branches/performance/subversion/svn/export-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svn/export-cmd.c?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svn/export-cmd.c (original)
+++ subversion/branches/performance/subversion/svn/export-cmd.c Sun Nov 7 14:30:34 2010
@@ -79,10 +79,7 @@ svn_cl__export(apr_getopt_t *os,
{
to = APR_ARRAY_IDX(targets, 1, const char *);
- /* If given the cwd, pretend we weren't given anything. */
- if (strcmp("", to) == 0)
- to = svn_path_uri_decode(svn_uri_basename(truefrom, pool), pool);
- else
+ if (strcmp("", to) != 0)
/* svn_cl__eat_peg_revisions() but only on one target */
SVN_ERR(svn_opt__split_arg_at_peg_revision(&to, NULL, to, pool));
}
Modified: subversion/branches/performance/subversion/svn/info-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svn/info-cmd.c?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svn/info-cmd.c (original)
+++ subversion/branches/performance/subversion/svn/info-cmd.c Sun Nov 7 14:30:34 2010
@@ -126,6 +126,11 @@ print_info_xml(void *baton,
/* "<wc-info>" */
svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "wc-info", NULL);
+ /* "<wcroot-abspath> xx </wcroot-abspath>" */
+ if (info->wcroot_abspath)
+ svn_cl__xml_tagged_cdata(&sb, pool, "wcroot-abspath",
+ info->wcroot_abspath);
+
/* "<schedule> xx </schedule>" */
svn_cl__xml_tagged_cdata(&sb, pool, "schedule",
schedule_str(info->schedule));
@@ -256,6 +261,11 @@ print_info(void *baton,
SVN_ERR(svn_cmdline_printf(pool, _("Name: %s\n"),
svn_dirent_basename(target, pool)));
+ if (info->wcroot_abspath)
+ SVN_ERR(svn_cmdline_printf(pool, _("Working Copy Root Path: %s\n"),
+ svn_dirent_local_style(info->wcroot_abspath,
+ pool)));
+
if (info->URL)
SVN_ERR(svn_cmdline_printf(pool, _("URL: %s\n"), info->URL));
@@ -539,13 +549,19 @@ svn_cl__info(apr_getopt_t *os,
SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target, subpool));
/* If no peg-rev was attached to a URL target, then assume HEAD. */
- if (svn_path_is_url(target))
+ if (svn_path_is_url(truepath))
{
+ truepath = svn_uri_canonicalize(truepath, subpool);
+
if (peg_revision.kind == svn_opt_revision_unspecified)
peg_revision.kind = svn_opt_revision_head;
}
else
- SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, subpool));
+ {
+ truepath = svn_dirent_canonicalize(truepath, subpool);
+
+ SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, subpool));
+ }
err = svn_client_info3(truepath,
&peg_revision, &(opt_state->start_revision),
Modified: subversion/branches/performance/subversion/svn/lock-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svn/lock-cmd.c?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svn/lock-cmd.c (original)
+++ subversion/branches/performance/subversion/svn/lock-cmd.c Sun Nov 7 14:30:34 2010
@@ -89,6 +89,8 @@ svn_cl__lock(apr_getopt_t *os,
svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
apr_array_header_t *targets;
const char *comment;
+ svn_boolean_t wc_present = FALSE, url_present = FALSE;
+ int i;
SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
opt_state->targets,
@@ -98,6 +100,22 @@ svn_cl__lock(apr_getopt_t *os,
if (! targets->nelts)
return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
+ /* Check to see if at least one of our paths is a working copy
+ * path or a repository url. */
+ for (i = 0; i < targets->nelts; ++i)
+ {
+ const char *target = APR_ARRAY_IDX(targets, i, const char *);
+ if (! svn_path_is_url(target))
+ wc_present = TRUE;
+ else
+ url_present = TRUE;
+ }
+
+ if (url_present && wc_present)
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Cannot mix repository and working copy "
+ "targets"));
+
/* Get comment. */
SVN_ERR(get_comment(&comment, ctx, opt_state, pool));
Modified: subversion/branches/performance/subversion/svn/resolve-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svn/resolve-cmd.c?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svn/resolve-cmd.c (original)
+++ subversion/branches/performance/subversion/svn/resolve-cmd.c Sun Nov 7 14:30:34 2010
@@ -29,6 +29,7 @@
#define APR_WANT_STDIO
#include <apr_want.h>
+#include "svn_path.h"
#include "svn_client.h"
#include "svn_error.h"
#include "svn_pools.h"
@@ -93,6 +94,19 @@ svn_cl__resolve(apr_getopt_t *os,
SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
+ /* Don't even attempt to modify the working copy if any of the
+ * targets look like URLs. URLs are invalid input. */
+ for (i = 0; i < targets->nelts; i++)
+ {
+ const char *target = APR_ARRAY_IDX(targets, i, const char *);
+
+ if (svn_path_is_url(target))
+ return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
+ NULL,
+ _("'%s' is not a local path"),
+ target));
+ }
+
iterpool = svn_pool_create(scratch_pool);
for (i = 0; i < targets->nelts; i++)
{
Modified: subversion/branches/performance/subversion/svn/resolved-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svn/resolved-cmd.c?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svn/resolved-cmd.c (original)
+++ subversion/branches/performance/subversion/svn/resolved-cmd.c Sun Nov 7 14:30:34 2010
@@ -29,6 +29,7 @@
#define APR_WANT_STDIO
#include <apr_want.h>
+#include "svn_path.h"
#include "svn_client.h"
#include "svn_error.h"
#include "svn_pools.h"
@@ -64,6 +65,18 @@ svn_cl__resolved(apr_getopt_t *os,
SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
+ /* URLs are invalid input. */
+ for (i = 0; i < targets->nelts; i++)
+ {
+ const char *target = APR_ARRAY_IDX(targets, i, const char *);
+
+ if (svn_path_is_url(target))
+ return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
+ NULL,
+ _("'%s' is not a local path"),
+ target));
+ }
+
iterpool = svn_pool_create(scratch_pool);
for (i = 0; i < targets->nelts; i++)
{
Modified: subversion/branches/performance/subversion/svn/revert-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svn/revert-cmd.c?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svn/revert-cmd.c (original)
+++ subversion/branches/performance/subversion/svn/revert-cmd.c Sun Nov 7 14:30:34 2010
@@ -27,6 +27,7 @@
/*** Includes. ***/
+#include "svn_path.h"
#include "svn_client.h"
#include "svn_error_codes.h"
#include "svn_error.h"
@@ -47,6 +48,7 @@ svn_cl__revert(apr_getopt_t *os,
svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
apr_array_header_t *targets = NULL;
svn_error_t *err;
+ int i;
SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
opt_state->targets,
@@ -63,9 +65,21 @@ svn_cl__revert(apr_getopt_t *os,
SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
+ /* Don't even attempt to modify the working copy if any of the
+ * targets look like URLs. URLs are invalid input. */
+ for (i = 0; i < targets->nelts; i++)
+ {
+ const char *target = APR_ARRAY_IDX(targets, i, const char *);
+
+ if (svn_path_is_url(target))
+ return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
+ NULL,
+ _("'%s' is not a local path"),
+ target));
+ }
+
err = svn_client_revert2(targets, opt_state->depth,
opt_state->changelists, ctx, scratch_pool);
-
if (err
&& (err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH)
&& (! SVN_DEPTH_IS_RECURSIVE(opt_state->depth)))
Modified: subversion/branches/performance/subversion/svn/schema/info.rnc
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svn/schema/info.rnc?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svn/schema/info.rnc (original)
+++ subversion/branches/performance/subversion/svn/schema/info.rnc Sun Nov 7 14:30:34 2010
@@ -53,6 +53,7 @@ uuid = element uuid { uuid.type }
## Info in the working copy entry.
wc-info =
element wc-info {
+ wcroot-abspath?,
schedule?,
changelist?,
copy-from-url?,
@@ -63,6 +64,8 @@ wc-info =
checksum?
}
+wcroot-abspath = element wcroot-abspath { string }
+
schedule =
element schedule { "normal" | "add" | "delete" | "replace" | "none" }
Modified: subversion/branches/performance/subversion/svn/status-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svn/status-cmd.c?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svn/status-cmd.c (original)
+++ subversion/branches/performance/subversion/svn/status-cmd.c Sun Nov 7 14:30:34 2010
@@ -249,6 +249,18 @@ svn_cl__status(apr_getopt_t *os,
/* Add "." if user passed 0 arguments */
svn_opt_push_implicit_dot_target(targets, scratch_pool);
+ /* URLs are invalid input. */
+ for (i = 0; i < targets->nelts; i++)
+ {
+ const char *target = APR_ARRAY_IDX(targets, i, const char *);
+
+ if (svn_path_is_url(target))
+ return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
+ NULL,
+ _("'%s' is not a local path"),
+ target));
+ }
+
/* We want our -u statuses to be against HEAD. */
rev.kind = svn_opt_revision_head;
Modified: subversion/branches/performance/subversion/svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svn/util.c?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svn/util.c (original)
+++ subversion/branches/performance/subversion/svn/util.c Sun Nov 7 14:30:34 2010
@@ -826,14 +826,14 @@ svn_cl__get_log_message(const char **log
white space as we will consider white space only as empty */
apr_size_t len;
- for (len = message->len - 1; len >= 0; len--)
+ for (len = 0; len < message->len; len++)
{
/* FIXME: should really use an UTF-8 whitespace test
rather than svn_ctype_isspace, which is ASCII only */
if (! svn_ctype_isspace(message->data[len]))
break;
}
- if (len < 0)
+ if (len == message->len)
message = NULL;
}
Modified: subversion/branches/performance/subversion/tests/cmdline/atomic-ra-revprop-change.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/atomic-ra-revprop-change.c?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/atomic-ra-revprop-change.c (original)
+++ subversion/branches/performance/subversion/tests/cmdline/atomic-ra-revprop-change.c Sun Nov 7 14:30:34 2010
@@ -261,6 +261,5 @@ main(int argc, const char *argv[])
svn_pool_destroy(pool);
apr_terminate();
- exit(exit_code);
return exit_code;
}
Modified: subversion/branches/performance/subversion/tests/cmdline/basic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/basic_tests.py?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/basic_tests.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/basic_tests.py Sun Nov 7 14:30:34 2010
@@ -2500,9 +2500,9 @@ def delete_from_url_with_spaces(sbox):
"delete a directory with ' ' using its url"
sbox.build()
- sbox.simple_mkdir(os.path.join(sbox.wc_dir, 'Dir With Spaces'))
- sbox.simple_mkdir(os.path.join(sbox.wc_dir, 'Dir With'))
- sbox.simple_mkdir(os.path.join(sbox.wc_dir, 'Dir With/Spaces'))
+ sbox.simple_mkdir('Dir With Spaces')
+ sbox.simple_mkdir('Dir With')
+ sbox.simple_mkdir('Dir With/Spaces')
svntest.actions.run_and_verify_svn(None, None, [],
'ci', sbox.wc_dir, '-m', 'Added dir')
@@ -2647,6 +2647,29 @@ def basic_relocate(sbox):
### TODO: When testing ra_dav or ra_svn, do relocations between
### those and ra_local URLs.
+#----------------------------------------------------------------------
+
+def delete_urls_with_spaces(sbox):
+ "delete multiple targets with spaces"
+ sbox.build(create_wc = False)
+
+ # Create three directories with a space in their name
+ svntest.actions.run_and_verify_svn(None, None, [], 'mkdir',
+ sbox.repo_url + '/A spaced',
+ sbox.repo_url + '/B spaced',
+ sbox.repo_url + '/C spaced',
+ '-m', 'Created dirs')
+
+ # Try to delete the first
+ svntest.actions.run_and_verify_svn(None, None, [], 'rm',
+ sbox.repo_url + '/A spaced',
+ '-m', 'Deleted A')
+
+ # And then two at once
+ svntest.actions.run_and_verify_svn(None, None, [], 'rm',
+ sbox.repo_url + '/B spaced',
+ sbox.repo_url + '/C spaced',
+ '-m', 'Deleted B and C')
########################################################################
# Run the tests
@@ -2708,6 +2731,7 @@ test_list = [ None,
delete_and_add_same_file,
delete_child_parent_update,
basic_relocate,
+ delete_urls_with_spaces,
]
if __name__ == '__main__':
Modified: subversion/branches/performance/subversion/tests/cmdline/blame_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/blame_tests.py?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/blame_tests.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/blame_tests.py Sun Nov 7 14:30:34 2010
@@ -462,10 +462,10 @@ def blame_merge_info(sbox):
wc_dir = sbox.wc_dir
iota_path = os.path.join(wc_dir, 'trunk', 'iota')
+ mu_path = os.path.join(wc_dir, 'trunk', 'A', 'mu')
exit_code, output, error = svntest.actions.run_and_verify_svn(
- None, None, [],
- 'blame', '-g', iota_path)
+ None, None, [], 'blame', '-g', iota_path)
expected_blame = [
{ 'revision' : 2,
@@ -481,6 +481,45 @@ def blame_merge_info(sbox):
]
parse_and_verify_blame(output, expected_blame, 1)
+ exit_code, output, error = svntest.actions.run_and_verify_svn(
+ None, None, [], 'blame', '-g', '-r10:11', iota_path)
+
+ expected_blame = [
+ { 'revision' : None,
+ 'author' : None,
+ 'text' : "This is the file 'iota'.\n",
+ 'merged' : 0,
+ },
+ { 'revision' : None,
+ 'author' : None,
+ 'text' : "'A' has changed a bit.\n",
+ 'merged' : 0,
+ },
+ ]
+ parse_and_verify_blame(output, expected_blame, 1)
+
+ exit_code, output, error = svntest.actions.run_and_verify_svn(
+ None, None, [], 'blame', '-g', '-r16:17', mu_path)
+
+ expected_blame = [
+ { 'revision' : None,
+ 'author' : None,
+ 'text' : "This is the file 'mu'.\n",
+ 'merged' : 0,
+ },
+ { 'revision' : 16,
+ 'author' : 'jrandom',
+ 'text' : "Don't forget to look at 'upsilon', as well.\n",
+ 'merged' : 1,
+ },
+ { 'revision' : 16,
+ 'author' : 'jrandom',
+ 'text' : "This is yet more content in 'mu'.\n",
+ 'merged' : 1,
+ },
+ ]
+ parse_and_verify_blame(output, expected_blame, 1)
+
def blame_merge_out_of_range(sbox):
"don't look for merged files out of range"
Modified: subversion/branches/performance/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/copy_tests.py?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/copy_tests.py Sun Nov 7 14:30:34 2010
@@ -4588,7 +4588,7 @@ def changed_data_should_match_checkout(s
svntest.actions.run_and_verify_svn(None, None, [], 'copy', A_B_E, E_new)
- sbox.simple_commit(wc_dir)
+ sbox.simple_commit()
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
@@ -4618,7 +4618,7 @@ def changed_dir_data_should_match_checko
svntest.actions.run_and_verify_svn(None, None, [], 'copy', A_B, B_new)
- sbox.simple_commit(wc_dir)
+ sbox.simple_commit()
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
@@ -4835,6 +4835,92 @@ def delete_replace_delete(sbox):
# Currently fails because pi, rho, tau get left behind
svntest.actions.run_and_verify_status(wc_dir, expected_status)
+A_B_children = ['A/B/lambda', 'A/B/F', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/E']
+A_D_children = ['A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
+ 'A/D/H', 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega']
+
+def copy_repos_over_deleted_same_kind(sbox):
+ "copy repos node over deleted node, same kind"
+ sbox.build(read_only = True)
+ expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+
+ # Set up some deleted paths
+ sbox.simple_rm('iota', 'A/B')
+ for path in ['iota', 'A/B'] + A_B_children:
+ expected_status.tweak(path, status='D ')
+
+ # Test copying
+ main.run_svn(None, 'cp', sbox.repo_url + '/A/mu', sbox.ospath('iota'))
+ expected_status.tweak('iota', status='R ', wc_rev='-', copied='+')
+ main.run_svn(None, 'cp', sbox.repo_url + '/A/D', sbox.ospath('A/B'))
+ expected_status.tweak('A/B', status='R ', wc_rev='-', copied='+')
+ for child in A_D_children:
+ expected_status.add({ child.replace('A/D', 'A/B'):
+ Item(status=' ', wc_rev='-', copied='+')})
+ svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
+
+def copy_repos_over_deleted_other_kind(sbox):
+ "copy repos node over deleted node, other kind"
+ sbox.build(read_only = True)
+ expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+
+ # Set up some deleted paths
+ sbox.simple_rm('iota', 'A/B')
+ for path in ['iota', 'A/B'] + A_B_children:
+ expected_status.tweak(path, status='D ')
+
+ # Test copying
+ main.run_svn(None, 'cp', sbox.repo_url + '/iota', sbox.ospath('A/B'))
+ expected_status.tweak('A/B', status='R ', wc_rev='-', copied='+')
+ expected_status.remove(*A_B_children)
+ main.run_svn(None, 'cp', sbox.repo_url + '/A/B', sbox.ospath('iota'))
+ expected_status.tweak('iota', status='R ', wc_rev='-', copied='+')
+ for child in A_B_children:
+ expected_status.add({ child.replace('A/B', 'iota'):
+ Item(status=' ', wc_rev='-', copied='+')})
+ svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
+
+def copy_wc_over_deleted_same_kind(sbox):
+ "copy WC node over a deleted node, same kind"
+ sbox.build(read_only = True)
+ expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+
+ # Set up some deleted paths
+ sbox.simple_rm('iota', 'A/B')
+ for path in ['iota', 'A/B'] + A_B_children:
+ expected_status.tweak(path, status='D ')
+
+ # Test copying
+ main.run_svn(None, 'cp', sbox.ospath('A/mu'), sbox.ospath('iota'))
+ expected_status.tweak('iota', status='R ', wc_rev='-', copied='+')
+ main.run_svn(None, 'cp', sbox.ospath('A/D'), sbox.ospath('A/B'))
+ expected_status.tweak('A/B', status='R ', wc_rev='-', copied='+')
+ for child in A_D_children:
+ expected_status.add({ child.replace('A/D', 'A/B'):
+ Item(status=' ', wc_rev='-', copied='+')})
+ svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
+
+def copy_wc_over_deleted_other_kind(sbox):
+ "copy WC node over deleted node, other kind"
+ sbox.build(read_only = True)
+ expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+
+ # Set up some deleted paths
+ sbox.simple_rm('iota', 'A/B')
+ for path in ['iota', 'A/B'] + A_B_children:
+ expected_status.tweak(path, status='D ')
+
+ # Test copying
+ main.run_svn(None, 'cp', sbox.ospath('A/mu'), sbox.ospath('A/B'))
+ expected_status.tweak('A/B', status='R ', wc_rev='-', copied='+')
+ expected_status.remove(*A_B_children)
+ main.run_svn(None, 'cp', sbox.ospath('A/D'), sbox.ospath('iota'))
+ expected_status.tweak('iota', status='R ', wc_rev='-', copied='+')
+ for child in A_D_children:
+ expected_status.add({ child.replace('A/D', 'iota'):
+ Item(status=' ', wc_rev='-', copied='+')})
+ svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
+
########################################################################
# Run the tests
@@ -4934,6 +5020,10 @@ test_list = [ None,
copy_delete_delete,
XFail(copy_delete_revert),
delete_replace_delete,
+ copy_repos_over_deleted_same_kind,
+ copy_repos_over_deleted_other_kind,
+ copy_wc_over_deleted_same_kind,
+ copy_wc_over_deleted_other_kind,
]
if __name__ == '__main__':
Modified: subversion/branches/performance/subversion/tests/cmdline/diff_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/diff_tests.py?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/diff_tests.py Sun Nov 7 14:30:34 2010
@@ -2585,9 +2585,9 @@ def basic_diff_summarize(sbox):
# Add props to some items that will be deleted, and commit.
sbox.simple_propset('prop', 'val',
- p('A/C'),
- p('A/D/gamma'),
- p('A/D/H/chi'))
+ 'A/C',
+ 'A/D/gamma',
+ 'A/D/H/chi')
sbox.simple_commit() # r2
sbox.simple_update()
@@ -2595,37 +2595,37 @@ def basic_diff_summarize(sbox):
svntest.main.file_append(p('A/mu'), 'new text\n')
# Prop modification.
- sbox.simple_propset('prop', 'val', p('iota'))
+ sbox.simple_propset('prop', 'val', 'iota')
# Both content and prop mods.
svntest.main.file_append(p('A/D/G/tau'), 'new text\n')
- sbox.simple_propset('prop', 'val', p('A/D/G/tau'))
+ sbox.simple_propset('prop', 'val', 'A/D/G/tau')
# File addition.
svntest.main.file_append(p('newfile'), 'new text\n')
svntest.main.file_append(p('newfile2'), 'new text\n')
- sbox.simple_add(p('newfile'),
- p('newfile2'))
- sbox.simple_propset('prop', 'val', p('newfile'))
+ sbox.simple_add('newfile',
+ 'newfile2')
+ sbox.simple_propset('prop', 'val', 'newfile')
# File deletion.
- sbox.simple_rm(p('A/B/lambda'),
- p('A/D/gamma'))
-
+ sbox.simple_rm('A/B/lambda',
+ 'A/D/gamma')
+
# Directory addition.
os.makedirs(p('P'))
os.makedirs(p('Q/R'))
svntest.main.file_append(p('Q/newfile'), 'new text\n')
svntest.main.file_append(p('Q/R/newfile'), 'new text\n')
- sbox.simple_add(p('P'),
- p('Q'))
+ sbox.simple_add('P',
+ 'Q')
sbox.simple_propset('prop', 'val',
- p('P'),
- p('Q/newfile'))
+ 'P',
+ 'Q/newfile')
# Directory deletion.
- sbox.simple_rm(p('A/D/H'),
- p('A/C'))
+ sbox.simple_rm('A/D/H',
+ 'A/C')
# Commit, because diff-summarize handles repos-repos only.
#svntest.main.run_svn(False, 'st', wc_dir)
Modified: subversion/branches/performance/subversion/tests/cmdline/export_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/export_tests.py?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/export_tests.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/export_tests.py Sun Nov 7 14:30:34 2010
@@ -680,7 +680,7 @@ test_list = [ None,
export_with_url_unsafe_characters,
XFail(export_working_copy_with_depths),
export_externals_with_native_eol,
- XFail(export_to_current_dir),
+ export_to_current_dir,
]
if __name__ == '__main__':
Modified: subversion/branches/performance/subversion/tests/cmdline/info_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/info_tests.py?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/info_tests.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/info_tests.py Sun Nov 7 14:30:34 2010
@@ -285,6 +285,39 @@ def info_on_mkdir(sbox):
('depth', {}, 'infinity'),
('schedule', {}, 'add')])
+def info_wcroot_abspaths(sbox):
+ """wc root paths in 'svn info' output"""
+
+ def check_wcroot_paths(lines, wcroot_abspath):
+ "check that paths found on input lines beginning 'Path: ' are as expected"
+ path = None
+ target = None
+ for line in lines:
+ if line.startswith('Path: '):
+ target = line[6:].rstrip()
+ if line.startswith('Working Copy Root Path: '):
+ path = line[24:].rstrip()
+ if target is not None and path is not None:
+ break
+
+ if target is None:
+ target = "(UNKNOWN)"
+
+ if path is None:
+ print "No WC root path for '%s'" % (target)
+ raise svntest.Failure
+
+ if path != wcroot_abspath:
+ print("For target '%s'..." % (target))
+ print(" Reported WC root path: %s" % (path))
+ print(" Expected WC root path: %s" % (wcroot_abspath))
+ raise svntest.Failure
+
+ sbox.build(read_only=True)
+ exit_code, output, errput = svntest.main.run_svn(None, 'info', '-R', sbox.wc_dir)
+ check_wcroot_paths(output, os.path.abspath(sbox.wc_dir))
+
+
########################################################################
# Run the tests
@@ -293,6 +326,7 @@ test_list = [ None,
info_with_tree_conflicts,
info_on_added_file,
info_on_mkdir,
+ info_wcroot_abspaths,
]
if __name__ == '__main__':
Modified: subversion/branches/performance/subversion/tests/cmdline/input_validation_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/input_validation_tests.py?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/input_validation_tests.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/input_validation_tests.py Sun Nov 7 14:30:34 2010
@@ -173,6 +173,40 @@ def invalid_wcpath_upgrade(sbox):
run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'upgrade',
target, target)
+def invalid_resolve_targets(sbox):
+ "non-working copy paths for 'resolve'"
+ sbox.build(read_only=True)
+ for target in _invalid_wc_path_targets:
+ run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'resolve',
+ '--accept', 'base', target)
+
+def invalid_resolved_targets(sbox):
+ "non-working copy paths for 'resolved'"
+ sbox.build(read_only=True)
+ for target in _invalid_wc_path_targets:
+ run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'resolved',
+ target)
+
+def invalid_revert_targets(sbox):
+ "non-working copy paths for 'revert'"
+ sbox.build(read_only=True)
+ for target in _invalid_wc_path_targets:
+ run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'revert',
+ target)
+
+def invalid_lock_targets(sbox):
+ "wc paths and repo URL target mixture for 'lock'"
+ sbox.build(read_only=True)
+ for (target1, target2) in [("iota", "^/"), ("file://", "iota")]:
+ run_and_verify_svn_in_wc(sbox, "svn: Cannot mix repository and working "
+ "copy targets", 'lock', target1, target2)
+
+def invalid_status_targets(sbox):
+ "non-working copy paths for 'status'"
+ sbox.build(read_only=True)
+ for target in _invalid_wc_path_targets:
+ run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'status',
+ target)
########################################################################
# Run the tests
@@ -192,6 +226,11 @@ test_list = [ None,
invalid_log_targets,
invalid_merge_args,
invalid_wcpath_upgrade,
+ invalid_resolve_targets,
+ invalid_resolved_targets,
+ invalid_revert_targets,
+ invalid_lock_targets,
+ invalid_status_targets,
]
if __name__ == '__main__':
Modified: subversion/branches/performance/subversion/tests/cmdline/lock_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/lock_tests.py?rev=1032285&r1=1032284&r2=1032285&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/lock_tests.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/lock_tests.py Sun Nov 7 14:30:34 2010
@@ -1606,16 +1606,16 @@ def cp_isnt_ro(sbox):
open(kappa_path, 'w').write("This is the file 'kappa'.\n")
## added file
- sbox.simple_add(kappa_path)
+ sbox.simple_add('kappa')
svntest.actions.set_prop('svn:needs-lock', 'yes', kappa_path)
is_writable(kappa_path)
- sbox.simple_commit(kappa_path)
+ sbox.simple_commit('kappa')
is_readonly(kappa_path)
## versioned file
svntest.actions.set_prop('svn:needs-lock', 'yes', mu_path)
is_writable(mu_path)
- sbox.simple_commit(mu_path)
+ sbox.simple_commit('A/mu')
is_readonly(mu_path)
# At this point, mu has 'svn:needs-lock' set
@@ -1623,13 +1623,13 @@ def cp_isnt_ro(sbox):
## wc->wc copied file
svntest.main.run_svn(None, 'copy', mu_path, mu2_path)
is_writable(mu2_path)
- sbox.simple_commit(mu2_path)
+ sbox.simple_commit('A/mu2')
is_readonly(mu2_path)
## URL->wc copied file
svntest.main.run_svn(None, 'copy', mu_URL, mu3_path)
is_writable(mu3_path)
- sbox.simple_commit(mu3_path)
+ sbox.simple_commit('A/mu3')
is_readonly(mu3_path)