| /* |
| * atomic-ra-revprop-change.c : wrapper around svn_ra_change_rev_prop2() |
| * |
| * ==================================================================== |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * ==================================================================== |
| */ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| |
| #include <apr_pools.h> |
| #include <apr_general.h> |
| |
| #include "svn_types.h" |
| #include "svn_pools.h" |
| #include "svn_dirent_uri.h" |
| #include "svn_ra.h" |
| #include "svn_cmdline.h" |
| |
| #include "private/svn_skel.h" |
| |
| #include "svn_private_config.h" |
| |
| |
| #define KEY_OLD_PROPVAL "old_value_p" |
| #define KEY_NEW_PROPVAL "value" |
| |
| #define USAGE_MSG \ |
| "Usage: %s URL REVISION PROPNAME VALUES_SKEL WANT_ERROR CONFIG_DIR\n" \ |
| "\n" \ |
| "VALUES_SKEL is a proplist skel containing pseudo-properties '%s' \n" \ |
| "and '%s'. A pseudo-property missing from the skel is interpreted \n" \ |
| "as unset.\n" \ |
| "\n" \ |
| "WANT_ERROR is 1 if the propchange is expected to fail due to the atomicity,"\ |
| "and 0 if it is expected to succeed. If the expectation matches reality," \ |
| "the exit code shall be zero.\n" |
| |
| |
| static svn_error_t * |
| construct_auth_baton(svn_auth_baton_t **auth_baton_p, |
| const char *config_dir, |
| apr_pool_t *pool) |
| { |
| SVN_ERR(svn_cmdline_create_auth_baton2(auth_baton_p, |
| TRUE /* non_interactive */, |
| "jrandom", "rayjandom", |
| config_dir, |
| TRUE /* no_auth_cache */, |
| FALSE /* trust_server_cert */, |
| FALSE, FALSE, FALSE, FALSE, |
| NULL, NULL, NULL, pool)); |
| return SVN_NO_ERROR; |
| } |
| |
| static svn_error_t * |
| construct_config(apr_hash_t **config_p, |
| const char *config_dir, |
| apr_pool_t *pool) |
| { |
| SVN_ERR(svn_config_get_config(config_p, config_dir, pool)); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| static svn_error_t * |
| change_rev_prop(const char *url, |
| svn_revnum_t revision, |
| const char *propname, |
| const svn_string_t *propval, |
| const svn_string_t *old_value, |
| svn_boolean_t want_error, |
| const char *config_dir, |
| apr_pool_t *pool) |
| { |
| svn_ra_callbacks2_t *callbacks; |
| svn_ra_session_t *sess; |
| apr_hash_t *config; |
| svn_boolean_t capable; |
| svn_error_t *err; |
| |
| SVN_ERR(svn_ra_create_callbacks(&callbacks, pool)); |
| SVN_ERR(construct_auth_baton(&callbacks->auth_baton, config_dir, pool)); |
| SVN_ERR(construct_config(&config, config_dir, pool)); |
| |
| SVN_ERR(svn_ra_open4(&sess, NULL, url, NULL, callbacks, NULL /* baton */, |
| config, pool)); |
| |
| SVN_ERR(svn_ra_has_capability(sess, &capable, |
| SVN_RA_CAPABILITY_ATOMIC_REVPROPS, |
| pool)); |
| if (capable) |
| { |
| err = svn_ra_change_rev_prop2(sess, revision, propname, |
| &old_value, propval, pool); |
| |
| if (want_error && err |
| && svn_error_find_cause(err, SVN_ERR_FS_PROP_BASEVALUE_MISMATCH)) |
| { |
| /* Expectation was matched. Get out. */ |
| svn_error_clear(err); |
| return SVN_NO_ERROR; |
| } |
| else if (! want_error && ! err) |
| /* Expectation was matched. Get out. */ |
| return SVN_NO_ERROR; |
| else if (want_error && ! err) |
| return svn_error_create(SVN_ERR_TEST_FAILED, NULL, |
| "An error was expected but not seen"); |
| else |
| /* A real (non-SVN_ERR_FS_PROP_BASEVALUE_MISMATCH) error. */ |
| return svn_error_trace(err); |
| } |
| else |
| /* Running under --server-minor-version? */ |
| return svn_error_create(SVN_ERR_TEST_FAILED, NULL, |
| "Server doesn't advertise " |
| "SVN_RA_CAPABILITY_ATOMIC_REVPROPS"); |
| } |
| |
| /* Parse SKEL_CSTR according to the description in USAGE_MSG. */ |
| static svn_error_t * |
| extract_values_from_skel(svn_string_t **old_propval_p, |
| svn_string_t **propval_p, |
| const char *skel_cstr, |
| apr_pool_t *pool) |
| { |
| apr_hash_t *proplist; |
| svn_skel_t *skel; |
| |
| skel = svn_skel__parse(skel_cstr, strlen(skel_cstr), pool); |
| SVN_ERR(svn_skel__parse_proplist(&proplist, skel, pool)); |
| *old_propval_p = apr_hash_get(proplist, KEY_OLD_PROPVAL, APR_HASH_KEY_STRING); |
| *propval_p = apr_hash_get(proplist, KEY_NEW_PROPVAL, APR_HASH_KEY_STRING); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| int |
| main(int argc, const char *argv[]) |
| { |
| apr_pool_t *pool; |
| int exit_code = EXIT_SUCCESS; |
| svn_error_t *err; |
| const char *url; |
| svn_revnum_t revision; |
| const char *propname; |
| svn_string_t *propval; |
| svn_string_t *old_propval; |
| char *digits_end = NULL; |
| svn_boolean_t want_error; |
| const char *config_dir; |
| |
| if (argc != 7) |
| { |
| fprintf(stderr, USAGE_MSG, argv[0], KEY_OLD_PROPVAL, KEY_NEW_PROPVAL); |
| exit(1); |
| } |
| |
| if (apr_initialize() != APR_SUCCESS) |
| { |
| fprintf(stderr, "apr_initialize() failed.\n"); |
| exit(1); |
| } |
| |
| /* set up the global pool */ |
| pool = svn_pool_create(NULL); |
| |
| /* Parse argv. */ |
| url = svn_uri_canonicalize(argv[1], pool); |
| revision = strtol(argv[2], &digits_end, 10); |
| propname = argv[3]; |
| SVN_INT_ERR(extract_values_from_skel(&old_propval, &propval, argv[4], pool)); |
| want_error = !strcmp(argv[5], "1"); |
| config_dir = svn_dirent_canonicalize(argv[6], pool); |
| |
| |
| if ((! SVN_IS_VALID_REVNUM(revision)) || (! digits_end) || *digits_end) |
| SVN_INT_ERR(svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, |
| _("Invalid revision number supplied"))); |
| |
| /* Do something. */ |
| err = change_rev_prop(url, revision, propname, propval, old_propval, |
| want_error, config_dir, pool); |
| if (err) |
| { |
| svn_handle_error2(err, stderr, FALSE, "atomic-ra-revprop-change: "); |
| svn_error_clear(err); |
| exit_code = EXIT_FAILURE; |
| } |
| |
| /* Clean up, and get outta here */ |
| svn_pool_destroy(pool); |
| apr_terminate(); |
| |
| return exit_code; |
| } |