Hi!
Here's my new patch.
On Tue, Mar 09, 2010 at 12:52:23AM +0100, Bert Huijben wrote:
> > Several points:
> > * use svn_wc__internal_text_modified_p(); then you won't need wc_ctx
> > (just the db)
Done!
> > * read_info can return NULL for the repos_* values
I'm checking that the values are null before setting using them for
svn_uri_join().
> > * typo in analyze_status docstring (the typename)
Fixed!
> > * status_deleted nodes have no revision info; you may simply want to
> > test for SVN_INVALID_REVNUM, since read_info() will return that when
> > it is "not interesting". IOW, it does the proper work for you
I'm checking that revision is not SVN_INVALID_REVNUM. As I've understood
it, that happens when we have something in WORKING, it has been deleted
or added and in that case there's no revision info for us to use. Right?
> > * do you need wc_root? how about just using
> > svn_wc__internal_path_switched() ?
I first tried to use the child_disjoint.*() func of libsvn_wc/lock.c but
it felt strange to use that code when we already have
svn_wc__check_wc_root() that checks if a node is switched. I can
separate the switch part into a separate func in a follow up and
replace the call to svn_wc__check_wc_root() with that one then. But I'm
so terribly slow at getting my patches finished that I thought it was
best to use _check_wc_root() as is for now.
> * You could optimize the checking for modifications to stop checking when
> you find the first change. (You are not reporting specific changes)
Done that!
I've removed the comments in the end about sparse_checkout not detecting
all cases. The walker reaches all nodes beneath local_abspath and if we
check for absent too I can't come up with any more cases where we won't
detect sparse_checkouts. Is that assumption correct?
I'm catching the _WC_PATH_NOT_FOUND error. Before my changes the code
didn't return that error. BUT, is that the _right_ thing to do? Are we
counting on the svn_wc_.* functions to always return _WC_PATH_NOT_FOUND
error for unversioned resources and such? Since it's a new revision I
could just as well return it, right?
[[[
As part of WC-NG, remove some uses of svn_wc_entry_t.
* subversion/libsvn_wc/revision_status.c
(status_baton): Rename this...
(walk_baton): .. to this.
(analyze_status): Change this to implement svn_wc__node_func_t and use
WC-NG funcs instead of information in svn_wc_entry_t.
(svn_wc_revision_status2): Use svn_wc__node_walk_children() instead of
svn_wc_walk_status() to spare us from the overhead of invoking an
editor.
]]]
Daniel
Index: subversion/libsvn_wc/revision_status.c
===================================================================
--- subversion/libsvn_wc/revision_status.c (revision 921239)
+++ subversion/libsvn_wc/revision_status.c (arbetskopia)
@@ -23,65 +23,109 @@
#include "svn_wc.h"
#include "svn_dirent_uri.h"
+#include "wc_db.h"
+#include "wc.h"
+#include "props.h"
#include "private/svn_wc_private.h"
#include "svn_private_config.h"
/* A baton for analyze_status(). */
-struct status_baton
+struct walk_baton
{
svn_wc_revision_status_t *result; /* where to put the result */
svn_boolean_t committed; /* examine last committed revisions */
const char *local_abspath; /* path whose URL we're looking for */
const char *wc_url; /* URL for the path whose URL we're looking for */
+ svn_wc__db_t *db;
apr_pool_t *pool; /* pool in which to store alloc-needy things */
};
-/* An svn_wc_status_func4_t callback function for analyzing status
- structures. */
+/* An svn_wc__node_found_func_t callback function for analyzing the status
+ * of nodes */
static svn_error_t *
-analyze_status(void *baton,
- const char *local_abspath,
- const svn_wc_status2_t *status,
- apr_pool_t *pool)
+analyze_status(const char *local_abspath,
+ void *baton,
+ apr_pool_t *scratch_pool)
{
- struct status_baton *sb = baton;
+ struct walk_baton *wb = baton;
+ svn_revnum_t changed_rev;
+ svn_revnum_t revision;
+ svn_depth_t depth;
+ svn_wc__db_status_t status;
+ const char *repos_root;
+ const char *repos_relpath;
+ svn_boolean_t wc_root;
+ svn_boolean_t switched;
- if (! status->entry)
+ SVN_ERR(svn_wc__db_read_info(&status, NULL, &revision, &repos_relpath,
+ &repos_root, NULL, &changed_rev,
+ NULL, NULL, NULL, &depth, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, wb->db,
+ local_abspath, scratch_pool, scratch_pool));
+
+ /* We need the excluded and absent paths when checking for sparse
+ * checkouts. But only for that. To collect those we're walking all the
+ * hidden nodes. */
+ if (status == svn_wc__db_status_excluded
+ || status == svn_wc__db_status_absent)
+ {
+ wb->result->sparse_checkout |= TRUE;
+ return SVN_NO_ERROR;
+ }
+
+ if (status == svn_wc__db_status_not_present)
return SVN_NO_ERROR;
+ SVN_ERR(svn_wc__check_wc_root(&wc_root, NULL, &switched, wb->db,
+ local_abspath, scratch_pool));
+
+ wb->result->switched |= switched;
+
/* Added files have a revision of no interest */
- if (status->text_status != svn_wc_status_added)
+ if (revision != SVN_INVALID_REVNUM)
{
- svn_revnum_t item_rev = (sb->committed
- ? status->entry->cmt_rev
- : status->entry->revision);
+ svn_revnum_t item_rev = (wb->committed
+ ? changed_rev
+ : revision);
- if (sb->result->min_rev == SVN_INVALID_REVNUM
- || item_rev < sb->result->min_rev)
- sb->result->min_rev = item_rev;
+ if (wb->result->min_rev == SVN_INVALID_REVNUM
+ || item_rev < wb->result->min_rev)
+ wb->result->min_rev = item_rev;
- if (sb->result->max_rev == SVN_INVALID_REVNUM
- || item_rev > sb->result->max_rev)
- sb->result->max_rev = item_rev;
+ if (wb->result->max_rev == SVN_INVALID_REVNUM
+ || item_rev > wb->result->max_rev)
+ wb->result->max_rev = item_rev;
}
- if (status->entry->depth != svn_depth_exclude)
+ if (! wb->result->modified)
{
- sb->result->switched |= status->switched;
- sb->result->modified |= (status->text_status != svn_wc_status_normal);
- sb->result->modified |= (status->prop_status != svn_wc_status_normal
- && status->prop_status != svn_wc_status_none);
+ svn_boolean_t text_mod;
+ svn_boolean_t props_mod;
+
+ SVN_ERR(svn_wc__props_modified(&props_mod, wb->db, local_abspath,
+ scratch_pool));
+
+ SVN_ERR(svn_wc__internal_text_modified_p(&text_mod, wb->db,
+ local_abspath,
+ FALSE,
+ TRUE,
+ scratch_pool));
+ wb->result->modified |= (text_mod || props_mod);
}
- sb->result->sparse_checkout |= (status->entry->depth != svn_depth_infinity);
- if (sb->local_abspath
- && (! sb->wc_url)
- && (strcmp(local_abspath, sb->local_abspath) == 0)
- && (status->entry))
- sb->wc_url = apr_pstrdup(sb->pool, status->entry->url);
+ wb->result->sparse_checkout |= ((depth != svn_depth_infinity
+ && depth != svn_depth_unknown));
+ if (wb->local_abspath
+ && repos_root
+ && repos_relpath
+ && (! wb->wc_url)
+ && (strcmp(local_abspath, wb->local_abspath) == 0))
+ wb->wc_url = svn_uri_join(repos_root, repos_relpath, wb->pool);
+
return SVN_NO_ERROR;
}
@@ -96,7 +140,9 @@
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- struct status_baton sb;
+ struct walk_baton wb;
+ svn_wc__db_kind_t kind;
+ svn_error_t *err;
svn_wc_revision_status_t *result = apr_palloc(result_pool, sizeof(*result));
*result_p = result;
@@ -109,24 +155,36 @@
result->modified = FALSE;
result->sparse_checkout = FALSE;
+ /* Rule out the possibility of local_abspath not beeing a versioned path
+ */
+ err = svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath, FALSE,
+ scratch_pool);
+
+ if (err)
+ {
+ if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ svn_error_clear(err);
+ return SVN_NO_ERROR;
+ }
+ else
+ SVN_ERR(err);
+
/* initialize walking baton */
- sb.result = result;
- sb.committed = committed;
- sb.local_abspath = local_abspath;
- sb.wc_url = NULL;
- sb.pool = scratch_pool;
+ wb.result = result;
+ wb.committed = committed;
+ wb.local_abspath = local_abspath;
+ wb.wc_url = NULL;
+ wb.db = wc_ctx->db;
+ wb.pool = scratch_pool;
- SVN_ERR(svn_wc_walk_status(wc_ctx,
- local_abspath,
- svn_depth_infinity,
- TRUE /* get_all */,
- FALSE /* no_ignore */,
- TRUE, /* get_excluded */
- NULL /* ignore_patterns */,
- analyze_status, &sb,
- NULL, NULL,
- cancel_func, cancel_baton,
- scratch_pool));
+ SVN_ERR(svn_wc__node_walk_children(wc_ctx,
+ local_abspath,
+ TRUE /* show_hidden */,
+ analyze_status, &wb,
+ svn_depth_infinity,
+ cancel_func, cancel_baton,
+ scratch_pool));
if ((! result->switched) && (trail_url != NULL))
@@ -134,26 +192,18 @@
/* If the trailing part of the URL of the working copy directory
does not match the given trailing URL then the whole working
copy is switched. */
- if (! sb.wc_url)
+ if (! wb.wc_url)
{
result->switched = TRUE;
}
else
{
apr_size_t len1 = strlen(trail_url);
- apr_size_t len2 = strlen(sb.wc_url);
- if ((len1 > len2) || strcmp(sb.wc_url + len2 - len1, trail_url))
+ apr_size_t len2 = strlen(wb.wc_url);
+ if ((len1 > len2) || strcmp(wb.wc_url + len2 - len1, trail_url))
result->switched = TRUE;
}
}
- /* ### 1.6+: If result->sparse_checkout is FALSE the answer is not final
- We can still have excluded nodes!
-
- ### TODO: Check every node below local_abspath for excluded
-
- ### BH: What about absent? You don't know if you have a complete tree
- without checking for absent too */
-
return SVN_NO_ERROR;
}