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 2013/04/09 16:27:47 UTC
svn commit: r1466055 - in /subversion/trunk/subversion/mod_dav_svn:
dav_svn.h repos.c
Author: cmpilato
Date: Tue Apr 9 14:27:47 2013
New Revision: 1466055
URL: http://svn.apache.org/r1466055
Log:
Accept "kw=1" parameter in mod_dav_svn GET query string as a flag
which means "perform keyword substitution on the returned file content
stream".
* subversion/mod_dav_svn/dav_svn.h
(struct dav_resource_private): add keyword_subst flag.
* subversion/mod_dav_svn/repos.c
(svn_subst.h): Add #include.
(parse_querystring): Set keyword_subst flag if query string contains
"kw" parameter with value "1", and preserve that flag's state when
redirecting.
(set_headers): Don't send "Content-length" header when doing keyword
substitution as we can't know the size of the resulting stream.
(deliver): Perform keyword substitution on the returned stream if
requested.
Patch by: jinfroster <jinfroster{_AT_}mail.ru>
(Tweaked by me.)
Modified:
subversion/trunk/subversion/mod_dav_svn/dav_svn.h
subversion/trunk/subversion/mod_dav_svn/repos.c
Modified: subversion/trunk/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/dav_svn.h?rev=1466055&r1=1466054&r2=1466055&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/trunk/subversion/mod_dav_svn/dav_svn.h Tue Apr 9 14:27:47 2013
@@ -284,11 +284,15 @@ struct dav_resource_private {
svn_boolean_t auto_checked_out;
/* was this resource fetched using our public peg-/working-rev CGI
- interface (ie: /path/to/item?p=PEGREV]? */
+ interface (ie: /path/to/item?p=PEGREV)? */
svn_boolean_t pegged;
/* Cache any revprop change error */
svn_error_t *revprop_error;
+
+ /* was keyword substitution requested using our public CGI interface
+ (ie: /path/to/item?kw=1)? */
+ svn_boolean_t keyword_subst;
};
Modified: subversion/trunk/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/repos.c?rev=1466055&r1=1466054&r2=1466055&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/repos.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/repos.c Tue Apr 9 14:27:47 2013
@@ -49,6 +49,7 @@
#include "svn_version.h"
#include "svn_props.h"
#include "svn_ctype.h"
+#include "svn_subst.h"
#include "mod_dav_svn.h"
#include "svn_ra.h" /* for SVN_RA_CAPABILITY_* */
#include "svn_dirent_uri.h"
@@ -1821,6 +1822,12 @@ parse_querystring(request_rec *r, const
apr_table_t *pairs = querystring_to_table(query, pool);
const char *prevstr = apr_table_get(pairs, "p");
const char *wrevstr;
+ const char *keyword_subst;
+
+ /* Will we be doing keyword substitution? */
+ keyword_subst = apr_table_get(pairs, "kw");
+ if (keyword_subst && (strcmp(keyword_subst, "1") == 0))
+ comb->priv.keyword_subst = TRUE;
if (prevstr)
{
@@ -1880,7 +1887,7 @@ parse_querystring(request_rec *r, const
}
else
{
- const char *newpath;
+ const char *newpath, *location;
apr_hash_t *locations;
apr_array_header_t *loc_revs = apr_array_make(pool, 1,
sizeof(svn_revnum_t));
@@ -1909,15 +1916,17 @@ parse_querystring(request_rec *r, const
/* Redirect folks to a canonical, peg-revision-only location.
If they used a peg revision in this request, we can use a
permanent redirect. If they didn't (peg-rev is HEAD), we can
- only use a temporary redirect. */
- apr_table_setn(r->headers_out, "Location",
- ap_construct_url(r->pool,
- apr_psprintf(r->pool, "%s%s?p=%ld",
+ only use a temporary redirect. In either case, preserve the
+ "keyword_subst" state in the redirected location, too. */
+ location = ap_construct_url(r->pool,
+ apr_psprintf(r->pool, "%s%s?p=%ld%s",
(comb->priv.repos->root_path[1]
? comb->priv.repos->root_path
: ""),
- newpath, working_rev),
- r));
+ newpath, working_rev,
+ keyword_subst ? "&kw=1" : ""),
+ r);
+ apr_table_setn(r->headers_out, "Location", location);
return dav_svn__new_error(r->pool,
prevstr ? HTTP_MOVED_PERMANENTLY
: HTTP_MOVED_TEMPORARILY,
@@ -3025,19 +3034,23 @@ set_headers(request_rec *r, const dav_re
mimetype = "text/plain";
- /* if we aren't sending a diff, then we know the length of the file,
- so set up the Content-Length header */
- serr = svn_fs_file_length(&length,
- resource->info->root.root,
- resource->info->repos_path,
- resource->pool);
- if (serr != NULL)
- {
- return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
- "could not fetch the resource length",
- resource->pool);
+ /* if we aren't sending a diff and aren't expanding keywords,
+ then we know the exact length of the file, so set up the
+ Content-Length header. */
+ if (! resource->info->keyword_subst)
+ {
+ serr = svn_fs_file_length(&length,
+ resource->info->root.root,
+ resource->info->repos_path,
+ resource->pool);
+ if (serr != NULL)
+ {
+ return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+ "could not fetch the resource length",
+ resource->pool);
+ }
+ ap_set_content_length(r, (apr_off_t) length);
}
- ap_set_content_length(r, (apr_off_t) length);
}
/* set the discovered MIME type */
@@ -3563,6 +3576,71 @@ deliver(const dav_resource *resource, ap
resource->pool);
}
+ /* Perform keywords substitution if requested by client */
+ if (resource->info->keyword_subst)
+ {
+ svn_string_t *keywords;
+
+ serr = svn_fs_node_prop(&keywords,
+ resource->info->root.root,
+ resource->info->repos_path,
+ SVN_PROP_KEYWORDS,
+ resource->pool);
+ if (serr != NULL)
+ return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+ "could not get fetch '"
+ SVN_PROP_KEYWORDS "' property for "
+ "for keywords substitution",
+ resource->pool);
+
+ if (keywords)
+ {
+ apr_hash_t *kw;
+ svn_revnum_t cmt_rev;
+ const char *str_cmt_rev, *str_uri;
+ const char *cmt_date, *cmt_author;
+ apr_time_t when = 0;
+
+ serr = svn_repos_get_committed_info(&cmt_rev,
+ &cmt_date,
+ &cmt_author,
+ resource->info->root.root,
+ resource->info->repos_path,
+ resource->pool);
+ if (serr != NULL)
+ return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+ "could not fetch committed info "
+ "for keywords substitution",
+ resource->pool);
+
+ serr = svn_time_from_cstring(&when, cmt_date, resource->pool);
+ if (serr != NULL)
+ return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+ "could not parse committed date "
+ "for keywords substitution",
+ resource->pool);
+ str_cmt_rev = apr_psprintf(resource->pool, "%ld", cmt_rev);
+ str_uri = apr_pstrcat(resource->pool,
+ resource->info->repos->base_url,
+ ap_escape_uri(resource->pool,
+ resource->info->r->uri),
+ NULL);
+ serr = svn_subst_build_keywords2(&kw, keywords->data,
+ str_cmt_rev, str_uri, when,
+ cmt_author, resource->pool);
+ if (serr != NULL)
+ return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+ "could not perform keywords "
+ "substitution", resource->pool);
+
+ /* Replace the raw file STREAM with a wrapper that
+ handles keyword translation. */
+ stream = svn_subst_stream_translated(
+ svn_stream_disown(stream, resource->pool),
+ NULL, FALSE, kw, TRUE, resource->pool);
+ }
+ }
+
/* ### one day in the future, we can create a custom bucket type
### which will read from the FS stream on demand */