=== subversion/include/private/svn_fs_private.h
==================================================================
--- subversion/include/private/svn_fs_private.h (revision 32554)
+++ subversion/include/private/svn_fs_private.h (local)
@@ -20,6 +20,8 @@
#ifndef SVN_FS_PRIVATE_H
#define SVN_FS_PRIVATE_H
+#include "svn_fs.h"
+
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -38,6 +40,20 @@
*/
#define SVN_FS__TXN_MAX_LEN 220
+/** Retrieve the lock-tokens associated in the context @a access_ctx.
+ * The tokens are in a hash keyed with const char * tokens,
+ * and with const char * values for the paths associated.
+ *
+ * You should always use svn_fs_access_add_lock_token2() if you intend
+ * to use this function. The result of the function is not guaranteed
+ * if you use it with the deprecated svn_fs_access_add_lock_token()
+ * API.
+ *
+ * @since New in 1.6. */
+
+apr_hash_t *
+svn_fs__access_get_lock_tokens(svn_fs_access_t *access_ctx);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
=== subversion/include/svn_fs.h
==================================================================
--- subversion/include/svn_fs.h (revision 32554)
+++ subversion/include/svn_fs.h (local)
@@ -471,12 +471,25 @@
svn_fs_access_t *access_ctx);
-/** Push a lock-token @a token into the context @a access_ctx. The
- * context remembers all tokens it receives, and makes them available
- * to fs functions. The token is not duplicated into @a access_ctx's
- * pool; make sure the token's lifetime is at least as long as @a
- * access_ctx. */
+/** Push a lock-token @a token associated with path @path into the
+ * context @a access_ctx. The context remembers all tokens it
+ * receives, and makes them available to fs functions. The token and
+ * path are not duplicated into @a access_ctx's pool; make sure the
+ * token's lifetime is at least as long as @a access_ctx.
+ *
+ * @since New in 1.6. */
+
svn_error_t *
+svn_fs_access_add_lock_token2(svn_fs_access_t *access_ctx,
+ const char *path,
+ const char *token);
+/**
+ * Same as svn_fs_access_add_lock_token2(), but with @a path set to value 1.
+ *
+ * @deprecated Provided for backward compatibility with the 1.1 API.
+ */
+
+svn_error_t *
svn_fs_access_add_lock_token(svn_fs_access_t *access_ctx,
const char *token);
@@ -1811,7 +1824,8 @@
* string by the client), and is required to make further use of the
* lock (including removal of the lock.) A lock-token can also be
* queried to return a svn_lock_t structure that describes the details
- * of the lock.
+ * of the lock. lock-tokens must not contain any newline character,
+ * mainly due to the serialization for tokens for pre-commit hook.
*
* Locks are not secret; anyone can view existing locks in a
* filesystem. Locks are not omnipotent: they can broken and stolen
=== subversion/libsvn_fs/access.c
==================================================================
--- subversion/libsvn_fs/access.c (revision 32554)
+++ subversion/libsvn_fs/access.c (local)
@@ -77,11 +77,23 @@
svn_error_t *
+svn_fs_access_add_lock_token2(svn_fs_access_t *access_ctx,
+ const char *path,
+ const char *token)
+{
+ apr_hash_set(access_ctx->lock_tokens,
+ token, APR_HASH_KEY_STRING, (void *) path);
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_fs_access_add_lock_token(svn_fs_access_t *access_ctx,
const char *token)
{
- apr_hash_set(access_ctx->lock_tokens,
- token, APR_HASH_KEY_STRING, (void *) 1);
+ return svn_fs_access_add_lock_token2(access_ctx, (const char *) 1, token);
+}
- return SVN_NO_ERROR;
+apr_hash_t *
+svn_fs__access_get_lock_tokens(svn_fs_access_t *access_ctx) {
+ return access_ctx->lock_tokens;
}
=== subversion/libsvn_ra_local/ra_plugin.c
==================================================================
--- subversion/libsvn_ra_local/ra_plugin.c (revision 32554)
+++ subversion/libsvn_ra_local/ra_plugin.c (local)
@@ -649,11 +649,14 @@
hi = apr_hash_next(hi))
{
void *val;
- const char *token;
+ const char *path, *token;
+ const void *key;
- apr_hash_this(hi, NULL, NULL, &val);
+ apr_hash_this(hi, &key, NULL, &val);
+ path = svn_path_join(sess->fs_path->data, (const char *)key,
+ pool);
token = val;
- SVN_ERR(svn_fs_access_add_lock_token(fs_access, token));
+ SVN_ERR(svn_fs_access_add_lock_token2(fs_access, path, token));
}
}
}
=== subversion/libsvn_repos/hooks.c
==================================================================
--- subversion/libsvn_repos/hooks.c (revision 32554)
+++ subversion/libsvn_repos/hooks.c (local)
@@ -28,6 +28,7 @@
#include "svn_utf.h"
#include "repos.h"
#include "svn_private_config.h"
+#include "private/svn_fs_private.h"
@@ -367,7 +368,41 @@
return SVN_NO_ERROR;
}
+/* Turns the LOCK_TOKENS hash into the file handle HANDLE in the
+ format documented in the pre-commit template, using POOL for
+ temporary allocations. */
+static svn_error_t *
+lock_token_content(apr_file_t **handle, apr_hash_t *lock_tokens,
+ apr_pool_t *pool)
+{
+ svn_stringbuf_t *lock_str = svn_stringbuf_create("LOCK-TOKENS:\n", pool);
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(pool, lock_tokens); hi;
+ hi = apr_hash_next(hi))
+ {
+ void *val;
+ const char *path, *token;
+
+ apr_hash_this(hi, (void *)&token, NULL, &val);
+ path = val;
+ svn_stringbuf_appendstr(lock_str,
+ svn_stringbuf_createf(pool, "%s|%s\n",
+ svn_path_uri_autoescape(path, pool),
+ token));
+ }
+
+ svn_stringbuf_appendcstr(lock_str, "\n");
+ SVN_ERR(create_temp_file(handle,
+ svn_string_create_from_buf(lock_str, pool),
+ pool));
+
+ return SVN_NO_ERROR;
+}
+
+
+
svn_error_t *
svn_repos__hooks_pre_commit(svn_repos_t *repos,
const char *txn_name,
@@ -383,14 +418,29 @@
else if (hook)
{
const char *args[4];
+ svn_fs_access_t *access_ctx;
+ apr_file_t *stdin_handle = NULL;
args[0] = hook;
args[1] = svn_path_local_style(svn_repos_path(repos, pool), pool);
args[2] = txn_name;
args[3] = NULL;
- SVN_ERR(run_hook_cmd(SVN_REPOS__HOOK_PRE_COMMIT, hook, args, NULL,
- pool));
+ SVN_ERR(svn_fs_get_access(&access_ctx, repos->fs));
+ if (access_ctx)
+ {
+ apr_hash_t *lock_tokens = svn_fs__access_get_lock_tokens(access_ctx);
+ if (apr_hash_count(lock_tokens)) {
+ SVN_ERR(lock_token_content(&stdin_handle, lock_tokens, pool));
+ }
+ }
+
+ if (!stdin_handle)
+ SVN_ERR(svn_io_file_open(&stdin_handle, SVN_NULL_DEVICE_NAME,
+ APR_READ, APR_OS_DEFAULT, pool));
+
+ SVN_ERR(run_hook_cmd(SVN_REPOS__HOOK_PRE_COMMIT, hook, args,
+ stdin_handle, pool));
}
return SVN_NO_ERROR;
=== subversion/libsvn_repos/repos.c
==================================================================
--- subversion/libsvn_repos/repos.c (revision 32554)
+++ subversion/libsvn_repos/repos.c (local)
@@ -381,6 +381,16 @@
"# [1] REPOS-PATH (the path to this repository)" NL
"# [2] TXN-NAME (the name of the txn about to be committed)" NL
"#" NL
+"# [STDIN] LOCK-TOKENS ** the lock tokens are passed via STDIN." NL
+"#" NL
+"# If the STDIN contains a line matching \"LOCK-TOKENS:\\n\", (here" NL
+"# \"\\n\" denotes a single newline)" NL
+"# the lines following it are used as the lock tokens for this commit," NL
+"# until it reaches a line containing only a newline character." NL
+"#" NL
+"# Each line of lock token is of the format: URI-escaped path, a '|'" NL
+"# character, the lock token string, and a new line character." NL
+"#" NL
"# The default working directory for the invocation is undefined, so" NL
"# the program should set one explicitly if it cares." NL
"#" NL
=== subversion/mod_dav_svn/repos.c
==================================================================
--- subversion/mod_dav_svn/repos.c (revision 32554)
+++ subversion/mod_dav_svn/repos.c (local)
@@ -1783,8 +1783,14 @@
}
do {
- serr = svn_fs_access_add_lock_token(access_ctx,
- list->locktoken->uuid_str);
+ /* Note the path/lock pairs are only for lock token checking
+ in access, and the relative path is not actually accurate
+ as it contains the !svn bits. However, we're using only
+ the tokens anyway (for access control). */
+
+ serr = svn_fs_access_add_lock_token2(access_ctx, relative,
+ list->locktoken->uuid_str);
+
if (serr)
return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
"Error pushing token into filesystem.",
=== subversion/mod_dav_svn/version.c
==================================================================
--- subversion/mod_dav_svn/version.c (revision 32554)
+++ subversion/mod_dav_svn/version.c (local)
@@ -1181,12 +1181,13 @@
for (hi = apr_hash_first(pool, locks); hi; hi = apr_hash_next(hi))
{
- const char *token;
+ const char *path, *token;
+ const void *key;
void *val;
- apr_hash_this(hi, NULL, NULL, &val);
- token = val;
+ apr_hash_this(hi, &key, NULL, &val);
+ path = key, token = val;
- serr = svn_fs_access_add_lock_token(fsaccess, token);
+ serr = svn_fs_access_add_lock_token2(fsaccess, path, token);
if (serr)
return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
"Error pushing token into filesystem.",
=== subversion/svnserve/serve.c
==================================================================
--- subversion/svnserve/serve.c (revision 32554)
+++ subversion/svnserve/serve.c (local)
@@ -1125,7 +1125,7 @@
sb, conn, pool);
token = token_item->u.string->data;
- SVN_ERR(svn_fs_access_add_lock_token(fs_access, token));
+ SVN_ERR(svn_fs_access_add_lock_token2(fs_access, path, token));
}
return SVN_NO_ERROR;