Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/serf.c URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/serf.c?rev=1558485&r1=1558484&r2=1558485&view=diff ============================================================================== --- subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/serf.c (original) +++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/serf.c Wed Jan 15 17:47:23 2014 @@ -857,7 +857,8 @@ serf__rev_proplist(svn_ra_session_t *ra_ svn_revnum_t rev, const svn_ra_serf__dav_props_t *fetch_props, apr_hash_t **ret_props, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_ra_serf__session_t *session = ra_session->priv; apr_hash_t *props; @@ -865,7 +866,8 @@ serf__rev_proplist(svn_ra_session_t *ra_ if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session)) { - propfind_path = apr_psprintf(pool, "%s/%ld", session->rev_stub, rev); + propfind_path = apr_psprintf(scratch_pool, "%s/%ld", session->rev_stub, + rev); /* svn_ra_serf__retrieve_props() wants to added the revision as a Label to the PROPFIND, which isn't really necessary when @@ -876,16 +878,17 @@ serf__rev_proplist(svn_ra_session_t *ra_ else { /* Use the VCC as the propfind target path. */ - SVN_ERR(svn_ra_serf__discover_vcc(&propfind_path, session, NULL, pool)); + SVN_ERR(svn_ra_serf__discover_vcc(&propfind_path, session, NULL, + scratch_pool)); } /* ### fix: fetch hash of *just* the PATH@REV props. no nested hash. */ SVN_ERR(svn_ra_serf__retrieve_props(&props, session, session->conns[0], propfind_path, rev, "0", fetch_props, - pool, pool)); + result_pool, scratch_pool)); SVN_ERR(svn_ra_serf__select_revprops(ret_props, propfind_path, rev, props, - pool, pool)); + result_pool, scratch_pool)); return SVN_NO_ERROR; } @@ -895,11 +898,16 @@ static svn_error_t * svn_ra_serf__rev_proplist(svn_ra_session_t *ra_session, svn_revnum_t rev, apr_hash_t **ret_props, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_error_trace( - serf__rev_proplist(ra_session, rev, all_props, - ret_props, pool)); + apr_pool_t *scratch_pool = svn_pool_create(result_pool); + svn_error_t *err; + + err = serf__rev_proplist(ra_session, rev, all_props, ret_props, + result_pool, scratch_pool); + + svn_pool_destroy(scratch_pool); + return svn_error_trace(err); } @@ -909,8 +917,9 @@ svn_ra_serf__rev_prop(svn_ra_session_t * svn_revnum_t rev, const char *name, svn_string_t **value, - apr_pool_t *pool) + apr_pool_t *result_pool) { + apr_pool_t *scratch_pool = svn_pool_create(result_pool); apr_hash_t *props; svn_ra_serf__dav_props_t specific_props[2]; const svn_ra_serf__dav_props_t *fetch_props = all_props; @@ -930,483 +939,12 @@ svn_ra_serf__rev_prop(svn_ra_session_t * fetch_props = specific_props; } - SVN_ERR(serf__rev_proplist(session, rev, fetch_props, &props, pool)); + SVN_ERR(serf__rev_proplist(session, rev, fetch_props, &props, + result_pool, scratch_pool)); *value = svn_hash_gets(props, name); - return SVN_NO_ERROR; -} - -static svn_error_t * -fetch_path_props(apr_hash_t **props, - svn_ra_serf__session_t *session, - const char *session_relpath, - svn_revnum_t revision, - const svn_ra_serf__dav_props_t *desired_props, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - const char *url; - - url = session->session_url.path; - - /* If we have a relative path, append it. */ - if (session_relpath) - url = svn_path_url_add_component2(url, session_relpath, scratch_pool); - - /* If we were given a specific revision, get a URL that refers to that - specific revision (rather than floating with HEAD). */ - if (SVN_IS_VALID_REVNUM(revision)) - { - SVN_ERR(svn_ra_serf__get_stable_url(&url, NULL /* latest_revnum */, - session, NULL /* conn */, - url, revision, - scratch_pool, scratch_pool)); - } - - /* URL is stable, so we use SVN_INVALID_REVNUM since it is now irrelevant. - Or we started with SVN_INVALID_REVNUM and URL may be floating. */ - SVN_ERR(svn_ra_serf__fetch_node_props(props, session->conns[0], - url, SVN_INVALID_REVNUM, - desired_props, - result_pool, scratch_pool)); - - return SVN_NO_ERROR; -} - -/* Implements svn_ra__vtable_t.check_path(). */ -static svn_error_t * -svn_ra_serf__check_path(svn_ra_session_t *ra_session, - const char *rel_path, - svn_revnum_t revision, - svn_node_kind_t *kind, - apr_pool_t *pool) -{ - svn_ra_serf__session_t *session = ra_session->priv; - apr_hash_t *props; - - svn_error_t *err = fetch_path_props(&props, session, rel_path, - revision, check_path_props, - pool, pool); - - if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND) - { - svn_error_clear(err); - *kind = svn_node_none; - } - else - { - /* Any other error, raise to caller. */ - if (err) - return svn_error_trace(err); - - SVN_ERR(svn_ra_serf__get_resource_type(kind, props)); - } - - return SVN_NO_ERROR; -} - - -struct dirent_walker_baton_t { - /* Update the fields in this entry. */ - svn_dirent_t *entry; - - svn_tristate_t *supports_deadprop_count; - - /* If allocations are necessary, then use this pool. */ - apr_pool_t *result_pool; -}; - -static svn_error_t * -dirent_walker(void *baton, - const char *ns, - const char *name, - const svn_string_t *val, - apr_pool_t *scratch_pool) -{ - struct dirent_walker_baton_t *dwb = baton; - - if (strcmp(ns, SVN_DAV_PROP_NS_CUSTOM) == 0) - { - dwb->entry->has_props = TRUE; - } - else if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0) - { - dwb->entry->has_props = TRUE; - } - else if (strcmp(ns, SVN_DAV_PROP_NS_DAV) == 0) - { - if(strcmp(name, "deadprop-count") == 0) - { - if (*val->data) - { - apr_int64_t deadprop_count; - SVN_ERR(svn_cstring_atoi64(&deadprop_count, val->data)); - dwb->entry->has_props = deadprop_count > 0; - if (dwb->supports_deadprop_count) - *dwb->supports_deadprop_count = svn_tristate_true; - } - else if (dwb->supports_deadprop_count) - *dwb->supports_deadprop_count = svn_tristate_false; - } - } - else if (strcmp(ns, "DAV:") == 0) - { - if (strcmp(name, SVN_DAV__VERSION_NAME) == 0) - { - dwb->entry->created_rev = SVN_STR_TO_REV(val->data); - } - else if (strcmp(name, "creator-displayname") == 0) - { - dwb->entry->last_author = val->data; - } - else if (strcmp(name, SVN_DAV__CREATIONDATE) == 0) - { - SVN_ERR(svn_time_from_cstring(&dwb->entry->time, - val->data, - dwb->result_pool)); - } - else if (strcmp(name, "getcontentlength") == 0) - { - /* 'getcontentlength' property is empty for directories. */ - if (val->len) - { - SVN_ERR(svn_cstring_atoi64(&dwb->entry->size, val->data)); - } - } - else if (strcmp(name, "resourcetype") == 0) - { - if (strcmp(val->data, "collection") == 0) - { - dwb->entry->kind = svn_node_dir; - } - else - { - dwb->entry->kind = svn_node_file; - } - } - } - - return SVN_NO_ERROR; -} - -struct path_dirent_visitor_t { - apr_hash_t *full_paths; - apr_hash_t *base_paths; - const char *orig_path; - svn_tristate_t supports_deadprop_count; - apr_pool_t *result_pool; -}; - -static svn_error_t * -path_dirent_walker(void *baton, - const char *path, apr_ssize_t path_len, - const char *ns, apr_ssize_t ns_len, - const char *name, apr_ssize_t name_len, - const svn_string_t *val, - apr_pool_t *pool) -{ - struct path_dirent_visitor_t *dirents = baton; - struct dirent_walker_baton_t dwb; - svn_dirent_t *entry; - - /* Skip our original path. */ - if (strcmp(path, dirents->orig_path) == 0) - { - return SVN_NO_ERROR; - } - - entry = apr_hash_get(dirents->full_paths, path, path_len); - - if (!entry) - { - const char *base_name; - - entry = svn_dirent_create(pool); - - apr_hash_set(dirents->full_paths, path, path_len, entry); - - base_name = svn_path_uri_decode(svn_urlpath__basename(path, pool), - pool); - - svn_hash_sets(dirents->base_paths, base_name, entry); - } - - dwb.entry = entry; - dwb.supports_deadprop_count = &dirents->supports_deadprop_count; - dwb.result_pool = dirents->result_pool; - return svn_error_trace(dirent_walker(&dwb, ns, name, val, pool)); -} - -static const svn_ra_serf__dav_props_t * -get_dirent_props(apr_uint32_t dirent_fields, - svn_ra_serf__session_t *session, - apr_pool_t *pool) -{ - svn_ra_serf__dav_props_t *prop; - apr_array_header_t *props = apr_array_make - (pool, 7, sizeof(svn_ra_serf__dav_props_t)); - - if (session->supports_deadprop_count != svn_tristate_false - || ! (dirent_fields & SVN_DIRENT_HAS_PROPS)) - { - if (dirent_fields & SVN_DIRENT_KIND) - { - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = "resourcetype"; - } - - if (dirent_fields & SVN_DIRENT_SIZE) - { - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = "getcontentlength"; - } - - if (dirent_fields & SVN_DIRENT_HAS_PROPS) - { - prop = apr_array_push(props); - prop->xmlns = SVN_DAV_PROP_NS_DAV; - prop->name = "deadprop-count"; - } - - if (dirent_fields & SVN_DIRENT_CREATED_REV) - { - svn_ra_serf__dav_props_t *p = apr_array_push(props); - p->xmlns = "DAV:"; - p->name = SVN_DAV__VERSION_NAME; - } - - if (dirent_fields & SVN_DIRENT_TIME) - { - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = SVN_DAV__CREATIONDATE; - } - - if (dirent_fields & SVN_DIRENT_LAST_AUTHOR) - { - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = "creator-displayname"; - } - } - else - { - /* We found an old subversion server that can't handle - the deadprop-count property in the way we expect. - - The neon behavior is to retrieve all properties in this case */ - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = "allprop"; - } - - prop = apr_array_push(props); - prop->xmlns = NULL; - prop->name = NULL; - - return (svn_ra_serf__dav_props_t *) props->elts; -} - -/* Implements svn_ra__vtable_t.stat(). */ -static svn_error_t * -svn_ra_serf__stat(svn_ra_session_t *ra_session, - const char *rel_path, - svn_revnum_t revision, - svn_dirent_t **dirent, - apr_pool_t *pool) -{ - svn_ra_serf__session_t *session = ra_session->priv; - apr_hash_t *props; - svn_error_t *err; - struct dirent_walker_baton_t dwb; - svn_tristate_t deadprop_count = svn_tristate_unknown; - - err = fetch_path_props(&props, - session, rel_path, revision, - get_dirent_props(SVN_DIRENT_ALL, session, pool), - pool, pool); - if (err) - { - if (err->apr_err == SVN_ERR_FS_NOT_FOUND) - { - svn_error_clear(err); - *dirent = NULL; - return SVN_NO_ERROR; - } - else - return svn_error_trace(err); - } - - dwb.entry = svn_dirent_create(pool); - dwb.supports_deadprop_count = &deadprop_count; - dwb.result_pool = pool; - SVN_ERR(svn_ra_serf__walk_node_props(props, dirent_walker, &dwb, pool)); - - if (deadprop_count == svn_tristate_false - && session->supports_deadprop_count == svn_tristate_unknown - && !dwb.entry->has_props) - { - /* We have to requery as the server didn't give us the right - information */ - session->supports_deadprop_count = svn_tristate_false; - - SVN_ERR(fetch_path_props(&props, - session, rel_path, SVN_INVALID_REVNUM, - get_dirent_props(SVN_DIRENT_ALL, session, pool), - pool, pool)); - - SVN_ERR(svn_ra_serf__walk_node_props(props, dirent_walker, &dwb, pool)); - } - - if (deadprop_count != svn_tristate_unknown) - session->supports_deadprop_count = deadprop_count; - - *dirent = dwb.entry; - - return SVN_NO_ERROR; -} - -/* Reads the 'resourcetype' property from the list PROPS and checks if the - * resource at PATH@REVISION really is a directory. Returns - * SVN_ERR_FS_NOT_DIRECTORY if not. - */ -static svn_error_t * -resource_is_directory(apr_hash_t *props) -{ - svn_node_kind_t kind; - - SVN_ERR(svn_ra_serf__get_resource_type(&kind, props)); - - if (kind != svn_node_dir) - { - return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL, - _("Can't get entries of non-directory")); - } - - return SVN_NO_ERROR; -} - -/* Implements svn_ra__vtable_t.get_dir(). */ -static svn_error_t * -svn_ra_serf__get_dir(svn_ra_session_t *ra_session, - apr_hash_t **dirents, - svn_revnum_t *fetched_rev, - apr_hash_t **ret_props, - const char *rel_path, - svn_revnum_t revision, - apr_uint32_t dirent_fields, - apr_pool_t *pool) -{ - svn_ra_serf__session_t *session = ra_session->priv; - const char *path; - - path = session->session_url.path; - - /* If we have a relative path, URI encode and append it. */ - if (rel_path) - { - path = svn_path_url_add_component2(path, rel_path, pool); - } - - /* If the user specified a peg revision other than HEAD, we have to fetch - the baseline collection url for that revision. If not, we can use the - public url. */ - if (SVN_IS_VALID_REVNUM(revision) || fetched_rev) - { - SVN_ERR(svn_ra_serf__get_stable_url(&path, fetched_rev, - session, NULL /* conn */, - path, revision, - pool, pool)); - revision = SVN_INVALID_REVNUM; - } - /* REVISION is always SVN_INVALID_REVNUM */ - SVN_ERR_ASSERT(!SVN_IS_VALID_REVNUM(revision)); - - /* If we're asked for children, fetch them now. */ - if (dirents) - { - struct path_dirent_visitor_t dirent_walk; - apr_hash_t *props; - const char *rtype; - - /* Always request node kind to check that path is really a - * directory. - */ - dirent_fields |= SVN_DIRENT_KIND; - SVN_ERR(svn_ra_serf__retrieve_props(&props, session, session->conns[0], - path, SVN_INVALID_REVNUM, "1", - get_dirent_props(dirent_fields, - session, pool), - pool, pool)); - - /* Check if the path is really a directory. */ - rtype = svn_ra_serf__get_prop(props, path, "DAV:", "resourcetype"); - if (rtype == NULL || strcmp(rtype, "collection") != 0) - return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL, - _("Can't get entries of non-directory")); - - /* We're going to create two hashes to help the walker along. - * We're going to return the 2nd one back to the caller as it - * will have the basenames it expects. - */ - dirent_walk.full_paths = apr_hash_make(pool); - dirent_walk.base_paths = apr_hash_make(pool); - dirent_walk.orig_path = svn_urlpath__canonicalize(path, pool); - dirent_walk.supports_deadprop_count = svn_tristate_unknown; - dirent_walk.result_pool = pool; - - SVN_ERR(svn_ra_serf__walk_all_paths(props, SVN_INVALID_REVNUM, - path_dirent_walker, &dirent_walk, - pool)); - - if (dirent_walk.supports_deadprop_count == svn_tristate_false - && session->supports_deadprop_count == svn_tristate_unknown - && dirent_fields & SVN_DIRENT_HAS_PROPS) - { - /* We have to requery as the server didn't give us the right - information */ - session->supports_deadprop_count = svn_tristate_false; - SVN_ERR(svn_ra_serf__retrieve_props(&props, session, - session->conns[0], - path, SVN_INVALID_REVNUM, "1", - get_dirent_props(dirent_fields, - session, pool), - pool, pool)); - - apr_hash_clear(dirent_walk.full_paths); - apr_hash_clear(dirent_walk.base_paths); - - SVN_ERR(svn_ra_serf__walk_all_paths(props, SVN_INVALID_REVNUM, - path_dirent_walker, - &dirent_walk, pool)); - } - - *dirents = dirent_walk.base_paths; - - if (dirent_walk.supports_deadprop_count != svn_tristate_unknown) - session->supports_deadprop_count = dirent_walk.supports_deadprop_count; - } - - /* If we're asked for the directory properties, fetch them too. */ - if (ret_props) - { - apr_hash_t *props; - - SVN_ERR(svn_ra_serf__fetch_node_props(&props, session->conns[0], - path, SVN_INVALID_REVNUM, - all_props, - pool, pool)); - - /* Check if the path is really a directory. */ - SVN_ERR(resource_is_directory(props)); - - /* ### flatten_props() does not copy PROPVALUE, but fetch_node_props() - ### put them into POOL, so we're okay. */ - SVN_ERR(svn_ra_serf__flatten_props(ret_props, props, pool, pool)); - } + svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; }
