You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by cm...@apache.org on 2012/06/21 19:17:02 UTC
svn commit: r1352627 - in /subversion/trunk/subversion/libsvn_ra_serf:
property.c update.c
Author: cmpilato
Date: Thu Jun 21 17:17:01 2012
New Revision: 1352627
URL: http://svn.apache.org/viewvc?rev=1352627&view=rev
Log:
Give ra_serf the power to properly recognize non-existent properties
explicitly requested.
* subversion/libsvn_ra_serf/property.c
(prop_state_e): Add STATUS state.
(parse_status_code): New helper function.
(propfind_ttable): Add record for STATUS state, and flip the bit
that lets us handle the "propstat" closure with our custom
callback.
(propfind_opened): Now store the 'ns' and 'name' values on the
PROPSTAT state, not the PROPVAL.
(propfind_closed): Handle the STATUS closure, parsing the status
code and leaving a note if it indicates that the property value
isn't worthy of remembrance. Also handle the PROPSTAT closure,
where we can finally consult that status note and remove the
property value we just stored.
* subversion/libsvn_ra_serf/update.c
(try_get_wc_contents): Let empty-string checksums return to raising
red flags.
Modified:
subversion/trunk/subversion/libsvn_ra_serf/property.c
subversion/trunk/subversion/libsvn_ra_serf/update.c
Modified: subversion/trunk/subversion/libsvn_ra_serf/property.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/property.c?rev=1352627&r1=1352626&r2=1352627&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/property.c Thu Jun 21 17:17:01 2012
@@ -46,6 +46,7 @@ typedef enum prop_state_e {
RESPONSE,
HREF,
PROPSTAT,
+ STATUS,
PROP,
PROPVAL,
COLLECTION,
@@ -107,7 +108,10 @@ static const svn_ra_serf__xml_transition
TRUE, { NULL }, TRUE },
{ RESPONSE, D_, "propstat", PROPSTAT,
- FALSE, { NULL }, FALSE },
+ FALSE, { NULL }, TRUE },
+
+ { PROPSTAT, D_, "status", STATUS,
+ TRUE, { NULL }, TRUE },
{ PROPSTAT, D_, "prop", PROP,
FALSE, { NULL }, FALSE },
@@ -125,6 +129,29 @@ static const svn_ra_serf__xml_transition
};
+/* Return the HTTP status code contained in STATUS_LINE, or 0 if
+ there's a problem parsing it. */
+static int parse_status_code(const char *status_line)
+{
+ /* STATUS_LINE should be of form: "HTTP/1.1 200 OK" */
+ if (status_line[0] == 'H' &&
+ status_line[1] == 'T' &&
+ status_line[2] == 'T' &&
+ status_line[3] == 'P' &&
+ status_line[4] == '/' &&
+ (status_line[5] >= '0' && status_line[5] <= '9') &&
+ status_line[6] == '.' &&
+ (status_line[7] >= '0' && status_line[7] <= '9') &&
+ status_line[8] == ' ')
+ {
+ char *reason;
+
+ return apr_strtoi64(status_line + 8, &reason, 10);
+ }
+ return 0;
+}
+
+
/* Conforms to svn_ra_serf__xml_opened_t */
static svn_error_t *
propfind_opened(svn_ra_serf__xml_estate_t *xes,
@@ -135,8 +162,8 @@ propfind_opened(svn_ra_serf__xml_estate_
{
if (entered_state == PROPVAL)
{
- svn_ra_serf__xml_note(xes, PROPVAL, "ns", tag->namespace);
- svn_ra_serf__xml_note(xes, PROPVAL, "name", tag->name);
+ svn_ra_serf__xml_note(xes, PROPSTAT, "ns", tag->namespace);
+ svn_ra_serf__xml_note(xes, PROPSTAT, "name", tag->name);
}
return SVN_NO_ERROR;
@@ -193,7 +220,17 @@ propfind_closed(svn_ra_serf__xml_estate_
{
svn_ra_serf__xml_note(xes, PROPVAL, "altvalue", cdata->data);
}
- else
+ else if (leaving_state == STATUS)
+ {
+ /* Parse the status field, and remember if this is a property
+ that we wish to ignore. (Typically, if it's not a 200, the
+ status will be 404 to indicate that a property we
+ specifically requested from the server doesn't exist.) */
+ int status = parse_status_code(cdata->data);
+ if (status != 200)
+ svn_ra_serf__xml_note(xes, PROPSTAT, "ignore-prop", "*");
+ }
+ else if (leaving_state == PROPVAL)
{
const char *encoding = apr_hash_get(attrs, "V:encoding",
APR_HASH_KEY_STRING);
@@ -204,8 +241,6 @@ propfind_closed(svn_ra_serf__xml_estate_
const char *name;
const char *altvalue;
- SVN_ERR_ASSERT(leaving_state == PROPVAL);
-
if (encoding)
{
if (strcmp(encoding, "base64") != 0)
@@ -225,7 +260,16 @@ propfind_closed(svn_ra_serf__xml_estate_
/* The current path sits on the RESPONSE state. Gather up all the
state from this PROPVAL to the (grandparent) RESPONSE state,
- and grab the path from there. */
+ and grab the path from there.
+
+ Now, it would be nice if we could, at this point, know that
+ the status code for this property indicated a problem -- then
+ we could simply bail out here and ignore the property.
+ Sadly, though, we might get the status code *after* we get
+ the property value. So we'll carry on with our processing
+ here, setting the property and value as expected. But later,
+ we might turn around and delete this property upon learning
+ that its status code was not a 200. */
gathered = svn_ra_serf__xml_gather_since(xes, RESPONSE);
/* These will be dup'd into CTX->POOL, as necessary. */
@@ -233,9 +277,9 @@ propfind_closed(svn_ra_serf__xml_estate_
if (path == NULL)
path = ctx->path;
- ns = apr_hash_get(attrs, "ns", APR_HASH_KEY_STRING);
+ ns = apr_hash_get(gathered, "ns", APR_HASH_KEY_STRING);
name = apr_pstrdup(ctx->pool,
- apr_hash_get(attrs, "name", APR_HASH_KEY_STRING));
+ apr_hash_get(gathered, "name", APR_HASH_KEY_STRING));
altvalue = apr_hash_get(attrs, "altvalue", APR_HASH_KEY_STRING);
if (altvalue != NULL)
@@ -245,6 +289,32 @@ propfind_closed(svn_ra_serf__xml_estate_
path, ctx->rev, ns, name, val_str,
ctx->pool);
}
+ else
+ {
+ apr_hash_t *gathered;
+
+ SVN_ERR_ASSERT(leaving_state == PROPSTAT);
+
+ /* If we've squirreled away a note that says we want to ignore
+ this property, then we'll ignore this property.
+ Unfortunately, we might have gotten this note after we
+ already set the property, so we have to turn right around and
+ delete it. */
+ gathered = svn_ra_serf__xml_gather_since(xes, RESPONSE);
+ if (apr_hash_get(gathered, "ignore-prop", APR_HASH_KEY_STRING))
+ {
+ const char *path = apr_hash_get(gathered, "path",
+ APR_HASH_KEY_STRING);
+ if (path == NULL)
+ path = ctx->path;
+ svn_ra_serf__set_ver_prop(ctx->ret_props, path, ctx->rev,
+ apr_hash_get(gathered, "ns",
+ APR_HASH_KEY_STRING),
+ apr_hash_get(gathered, "name",
+ APR_HASH_KEY_STRING),
+ NULL, ctx->pool);
+ }
+ }
return SVN_NO_ERROR;
}
Modified: subversion/trunk/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/update.c?rev=1352627&r1=1352626&r2=1352627&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/update.c Thu Jun 21 17:17:01 2012
@@ -2858,34 +2858,17 @@ try_get_wc_contents(svn_boolean_t *found
return SVN_NO_ERROR;
}
-
svn_props = apr_hash_get(props, SVN_DAV_PROP_NS_DAV, APR_HASH_KEY_STRING);
if (!svn_props)
{
- /* No checksum property in response. */
+ /* No properties -- therefore no checksum property -- in response. */
return SVN_NO_ERROR;
}
- /* If we are talking to an old server, then the sha1-checksum property
- will not exist. In our property parsing code, we don't bother to
- check the <status> element which would indicate a 404. That section
- needs to name the 404'd property, so our parsing code only sees:
-
- <g0:sha1-checksum/>
-
- That is parsed as an empty string value for the property.
-
- When checking the property, if it is missing (NULL), or the above
- empty string, then we know the property doesn't exist.
-
- Strictly speaking, we could start parsing <status> and omit any
- properties that were 404'd. But the 404 only happens when we ask
- for a specific property, and it is easier to just check for the
- empty string. Since it isn't a legal value in this case, we won't
- get confused with a truly existent property. */
sha1_checksum_prop = svn_prop_get_value(svn_props, "sha1-checksum");
- if (sha1_checksum_prop == NULL || *sha1_checksum_prop == '\0')
+ if (sha1_checksum_prop == NULL)
{
+ /* No checksum property in response. */
return SVN_NO_ERROR;
}