Woo Hoo! This open source thing is pretty neat, even if it is hard!
Thanks for your help.
Troy
On Tue, Apr 22, 2008 at 10:22 AM, Julian Foad
<julianfoad_at_btopenworld.com> wrote:
> Troy,
>
> I have reviewed and tested this patch now. The structure is great: thanks
> for moving things into libsvn_client while maintaining backward
> compatibility. It works fine. I tweaked a little bit: mainly a doc-string or
> two, and added localisation macros around the error message strings.
>
> Committed in r30753.
>
> Thanks very much for doing this.
>
> - Julian
>
>
> Troy Curtis Jr wrote:
>
> >
> >
> >
> > Here is my first shot at implementing the command-line repository root
> > relative url support in libsvn_client. Note to Julian: I chose not to
> return
> > a structure because after looking into it I found that it was a much
> larger
> > job than I wanted to do for relative url support...it was definetly not a
> > "gimme". I also found that it did not really gain me (or this patch) much
> > benefit.
> >
> > [[[
> > Implement repository root relative url support for the svn command-line
> > client. This allows the user to use '^/' in front of any target to
> > mean the repository root url. The repository root url is determined by
> > checking the other arguments' root urls (if they exist) and using that
> common
> > url. If none is found the root url of the current directory is used. If
> no
> > common repository root url can be found, an error is generated.
> >
> > * subversion/include/private/svn_opt_private.h
> > New file to hold inter-library svn_opt functions.
> > (svn_opt__arg_canonicalize_url): New function prototype.
> > (svn_opt__arg_canonicalize_path): New function prototype.
> >
> > * subversion/include/svn_opt.h
> > (svn_opt_args_to_target_array3): Change doc string to reflect deprecated
> > status.
> >
> > * subversion/libsvn_subr/opt.c
> > (svn_opt__arg_canonicalize_url): New function to canonicalize user input
> > urls.
> > (svn_opt__arg_canonicalize_path): New function to canonicalize user input
> > paths.
> > (svn_opt_args_to_target_array3): Replace the inline canonicalization code
> > with calls to the new svn_opt__arg_canonicalize_* functions.
> >
> > * subversion/include/svn_client.h
> > (svn_client_args_to_target_array): New function prototype.
> >
> > * subversion/libsvn_client/cmdline.c
> > New file for client library commandline processing functionality.
> > (arg_is_repos_relative_url,
> > resolve_repos_relative_url,
> > check_root_url_of_target): New functions to support
> > svn_client_args_to_target_array.
> > (svn_client_args_to_target_array): New client function to parse user
> > arguments into a target array. Replaces use of
> > svn_opt_args_to_target_array3()
> >
> > * subversion/tests/libsvn_client/client-test.c
> > (test_args_to_target_array): New test function.
> > (test_funcs): Run new test function.
> >
> > * subversion/tests/cmdline/special_tests.py
> > (warn_on_reserved_name): Modify test to work right with
> > svn_client_args_to_target_array.
> >
> > * subversion/tests/cmdline/basic_tests.py
> > (basic_relative_url_multi_repo,
> > basic_relative_url_using_other_targets,
> > basic_relative_url_using_current_dir): New test functions.
> > (test_list): Run new test functions.
> >
> > * subversion/svn/cl.h
> > (svn_cl__args_to_target_array_print_reserved): Add client context
> parameter.
> >
> > * subversion/svn/util.c
> > (svn_cl__args_to_target_array_print_reserved): Replace call to
> > svn_opt_args_to_target_array3() with svn_client_args_to_target_array().
> >
> > * subversion/svn/update-cmd.c
> > (svn_cl__update): Replace svn_opt_args_to_target_array3() with
> > svn_cl__args_to_target_array_print_reserved() for consistency with the
> other
> > command line functions.
> >
> > * subversion/svn/diff-cmd.c
> > (svn_cl__diff): Create a client context variable and use it in the
> > svn_cl__args_to_target_array_print_reserved() function along with every
> > else it is needed.
> >
> > * subversion/svn/merge-cmd.c,
> > subversion/svn/propdel-cmd.c,
> > subversion/svn/checkout-cmd.c,
> > subversion/svn/move-cmd.c,
> > subversion/svn/mkdir-cmd.c,
> > subversion/svn/cat-cmd.c,
> > subversion/svn/revert-cmd.c,
> > subversion/svn/copy-cmd.c,
> > subversion/svn/mergeinfo-cmd.c,
> > subversion/svn/list-cmd.c,
> > subversion/svn/blame-cmd.c,
> > subversion/svn/propget-cmd.c,
> > subversion/svn/changelist-cmd.c,
> > subversion/svn/log-cmd.c,
> > subversion/svn/resolved-cmd.c,
> > subversion/svn/cleanup-cmd.c,
> > subversion/svn/commit-cmd.c,
> > subversion/svn/add-cmd.c,
> > subversion/svn/propset-cmd.c,
> > subversion/svn/switch-cmd.c,
> > subversion/svn/delete-cmd.c,
> > subversion/svn/import-cmd.c,
> > subversion/svn/proplist-cmd.c,
> > subversion/svn/export-cmd.c,
> > subversion/svn/status-cmd.c,
> > subversion/svn/propedit-cmd.c,
> > subversion/svn/lock-cmd.c,
> > subversion/svn/info-cmd.c,
> > subversion/svn/unlock-cmd.c
> > Add client context variable to all the calls to
> > svn_cl__args_to_target_array_print_reserved().
> > ]]]
> >
> > Troy
> >
> >
> > ------------------------------------------------------------------------
> >
> > Index: subversion/include/svn_client.h
> > ===================================================================
> > --- subversion/include/svn_client.h (revision 29840)
> > +++ subversion/include/svn_client.h (working copy)
> > @@ -889,6 +889,44 @@ typedef struct svn_client_ctx_t
> > #define SVN_CLIENT_AUTH_PASSWORD "password"
> > /** @} group end: Authentication information file names */
> > +/** Client argument processing + *
> > + * @defgroup clnt_cmdline Client command-line processing
> > + *
> > + * @{
> > + */
> > +
> > +/**
> > + * Pull remaining target argument from @a os into @a *targets_p,
> > + * converting them to UTF-8, followed by targets from @a known_targets +
> * (which might come from, for example, the "--targets" command line option).
> > + *
> > + * On each URL target, do some IRI-to-URI encoding and some
> auto-escaping. + * On each local path, canonicalize case and path
> separators.
> > + *
> > + * Allocate @a *targets_p and its elements in @a pool.
> > + *
> > + * @ctx is required for possible repository authentication.
> > + *
> > + * If a path has the same name as a Subversion working copy
> > + * administrative directory, return SVN_ERR_RESERVED_FILENAME_SPECIFIED;
> > + * if multiple reserved paths are encountered, return a chain of
> > + * errors, all of which are SVN_ERR_RESERVED_FILENAME_SPECIFIED. Do
> > + * not return this type of error in a chain with any other type of
> > + * error, and if this is the only type of error encountered, complete
> > + * the operation before returning the error(s).
> > + *
> > + * @since New in 1.6
> > + */
> > +svn_error_t *
> > +svn_client_args_to_target_array(apr_array_header_t **targets_p,
> > + apr_getopt_t *os,
> > + apr_array_header_t *known_targets,
> > + svn_client_ctx_t *ctx,
> > + apr_pool_t *pool);
> > +
> > +/** @} group end: Client command-line processing */
> > +
> > /** @} */
> > /**
> > Index: subversion/include/private/svn_opt_private.h
> > ===================================================================
> > --- subversion/include/private/svn_opt_private.h (revision 0)
> > +++ subversion/include/private/svn_opt_private.h (revision 0)
> > @@ -0,0 +1,65 @@
> > +/**
> > + * @copyright
> > + * ====================================================================
> > + * Copyright (c) 2008 CollabNet. All rights reserved.
> > + *
> > + * This software is licensed as described in the file COPYING, which
> > + * you should have received as part of this distribution. The terms
> > + * are also available at http://subversion.tigris.org/license-1.html.
> > + * If newer versions of this license are posted there, you may use a
> > + * newer version instead, at your option.
> > + *
> > + * This software consists of voluntary contributions made by many
> > + * individuals. For exact contribution history, see the revision
> > + * history and logs, available at http://subversion.tigris.org/.
> > + * ====================================================================
> > + * @endcopyright
> > + *
> > + * @file svn_opt_private.h
> > + * @brief Subversion-internal option parsing APIs.
> > + */
> > +
> > +#ifndef SVN_OPT_PRIVATE_H
> > +#define SVN_OPT_PRIVATE_H
> > +
> > +#include <apr_pools.h>
> > +
> > +#ifdef __cplusplus
> > +extern "C" {
> > +#endif /* __cplusplus */
> > +
> > +/* Attempt to transform URL_IN, which is a URL-like user input, into a
> > + * valid URL:
> > + * - escape IRI characters and some other non-URI characters
> > + * - check that only valid URI characters remain
> > + * - check that no back-path ("..") components are present
> > + * - canonicalize the separator ("/") characters
> > + * URL_IN is in UTF-8 encoding and has no peg revision specifier.
> > + * Set *URL_OUT to the result, allocated from POOL.
> > + */
> > +svn_error_t *
> > +svn_opt__arg_canonicalize_url(const char **url_out, +
> const char *url_in,
> > + apr_pool_t *pool);
> > +
> > +/*
> > + * Attempt to transform PATH_IN, which is a local path-like user input,
> into a
> > + * valid local path:
> > + * - Attempt to get the correct capitialization by trying to actually
> find + * the path specified. + * - If the path does not exist (which
> is valid) the given capitialization + * is used.
> > + * - canonicalize the separator ("/") characters
> > + * PATH_IN is in UTF-8 encoding and has no peg revision specifier.
> > + * Set *PATH_OUT to the result, allocated from POOL.
> > + */
> > +svn_error_t *
> > +svn_opt__arg_canonicalize_path(const char **path_out, +
> const char *path_in,
> > + apr_pool_t *pool);
> > +
> > +#ifdef __cplusplus
> > +}
> > +#endif /* __cplusplus */
> > +
> > +#endif /* SVN_OPT_PRIVATE_H */
> > Index: subversion/include/svn_opt.h
> > ===================================================================
> > --- subversion/include/svn_opt.h (revision 29840)
> > +++ subversion/include/svn_opt.h (working copy)
> > @@ -489,7 +489,7 @@ svn_opt_resolve_revisions(svn_opt_revision_t *peg_
> > * error, and if this is the only type of error encountered, complete
> > * the operation before returning the error(s).
> > *
> > - * @since New in 1.5.
> > + * @deprecated Provided for backward compatibility with the 1.5 API.
> > */
> > svn_error_t *
> > svn_opt_args_to_target_array3(apr_array_header_t **targets_p,
> > Index: subversion/libsvn_subr/opt.c
> > ===================================================================
> > --- subversion/libsvn_subr/opt.c (revision 29840)
> > +++ subversion/libsvn_subr/opt.c (working copy)
> > @@ -37,6 +37,8 @@
> > #include "svn_utf.h"
> > #include "svn_time.h"
> > +#include "private/svn_opt_private.h"
> > +
> > #include "svn_private_config.h"
> > @@ -965,59 +967,14 @@ svn_opt_args_to_target_array3(apr_array_header_t
> *
> > /* URLs and wc-paths get treated differently. */
> > if (svn_path_is_url(utf8_target))
> > {
> > - /* No need to canonicalize a URL's case or path separators. */
> > -
> > - /* Convert to URI. */
> > - target = svn_path_uri_from_iri(utf8_target, pool);
> > - /* Auto-escape some ASCII characters. */
> > - target = svn_path_uri_autoescape(target, pool);
> > -
> > - /* The above doesn't guarantee a valid URI. */
> > - if (! svn_path_is_uri_safe(target))
> > - return svn_error_createf(SVN_ERR_BAD_URL, 0,
> > - _("URL '%s' is not properly
> URI-encoded"),
> > - utf8_target);
> > -
> > - /* Verify that no backpaths are present in the URL. */
> > - if (svn_path_is_backpath_present(target))
> > - return svn_error_createf(SVN_ERR_BAD_URL, 0,
> > - _("URL '%s' contains a '..'
> element"),
> > - utf8_target);
> > -
> > - /* strip any trailing '/' */
> > - target = svn_path_canonicalize(target, pool);
> > + SVN_ERR(svn_opt__arg_canonicalize_url(&target, utf8_target,
> pool));
> > }
> > else /* not a url, so treat as a path */
> > {
> > - const char *apr_target;
> > const char *base_name;
> > - char *truenamed_target; /* APR-encoded */
> > - apr_status_t apr_err;
> > - /* canonicalize case, and change all separators to '/'. */
> > - SVN_ERR(svn_path_cstring_from_utf8(&apr_target, utf8_target,
> > - pool));
> > - apr_err = apr_filepath_merge(&truenamed_target, "", apr_target,
> > - APR_FILEPATH_TRUENAME, pool);
> > + SVN_ERR(svn_opt__arg_canonicalize_path(&target, utf8_target,
> pool));
> > - if (!apr_err)
> > - /* We have a canonicalized APR-encoded target now. */
> > - apr_target = truenamed_target;
> > - else if (APR_STATUS_IS_ENOENT(apr_err))
> > - /* It's okay for the file to not exist, that just means we
> > - have to accept the case given to the client. We'll use
> > - the original APR-encoded target. */
> > - ;
> > - else
> > - return svn_error_createf(apr_err, NULL,
> > - _("Error resolving case of '%s'"),
> > - svn_path_local_style(utf8_target,
> > - pool));
> > -
> > - /* convert back to UTF-8. */
> > - SVN_ERR(svn_path_cstring_to_utf8(&target, apr_target, pool));
> > - target = svn_path_canonicalize(target, pool);
> > -
> > /* If the target has the same name as a Subversion
> > working copy administrative dir, skip it. */
> > base_name = svn_path_basename(target, pool);
> > @@ -1141,7 +1098,69 @@ svn_opt_parse_revprop(apr_hash_t **revprop_table_p
> > return SVN_NO_ERROR;
> > }
> > +svn_error_t *
> > +svn_opt__arg_canonicalize_url(const char **url_out, const char *url_in,
> > + apr_pool_t *pool)
> > +{
> > + const char *target;
> > + /* Convert to URI. */
> > + target = svn_path_uri_from_iri(url_in, pool);
> > + /* Auto-escape some ASCII characters. */
> > + target = svn_path_uri_autoescape(target, pool);
> > +
> > + /* The above doesn't guarantee a valid URI. */
> > + if (! svn_path_is_uri_safe(target))
> > + return svn_error_createf(SVN_ERR_BAD_URL, 0,
> > + _("URL '%s' is not properly URI-encoded"),
> > + target);
> > +
> > + /* Verify that no backpaths are present in the URL. */
> > + if (svn_path_is_backpath_present(target))
> > + return svn_error_createf(SVN_ERR_BAD_URL, 0,
> > + _("URL '%s' contains a '..' element"),
> > + target);
> > +
> > + /* strip any trailing '/' and collapse other redundant elements */
> > + target = svn_path_canonicalize(target, pool);
> > +
> > + *url_out = target;
> > + return SVN_NO_ERROR;
> > +}
> > +
> > +svn_error_t *
> > +svn_opt__arg_canonicalize_path(const char **path_out, const char
> *path_in,
> > + apr_pool_t *pool)
> > +{
> > + const char *apr_target;
> > + char *truenamed_target; /* APR-encoded */
> > + apr_status_t apr_err;
> > +
> > + /* canonicalize case, and change all separators to '/'. */
> > + SVN_ERR(svn_path_cstring_from_utf8(&apr_target, path_in, pool));
> > + apr_err = apr_filepath_merge(&truenamed_target, "", apr_target,
> > + APR_FILEPATH_TRUENAME, pool);
> > +
> > + if (!apr_err)
> > + /* We have a canonicalized APR-encoded target now. */
> > + apr_target = truenamed_target;
> > + else if (APR_STATUS_IS_ENOENT(apr_err))
> > + /* It's okay for the file to not exist, that just means we
> > + have to accept the case given to the client. We'll use
> > + the original APR-encoded target. */
> > + ;
> > + else
> > + return svn_error_createf(apr_err, NULL,
> > + _("Error resolving case of '%s'"),
> > + svn_path_local_style(path_in, pool));
> > +
> > + /* convert back to UTF-8. */
> > + SVN_ERR(svn_path_cstring_to_utf8(path_out, apr_target, pool));
> > + *path_out = svn_path_canonicalize(*path_out, pool);
> > +
> > + return SVN_NO_ERROR;
> > +}
> > +
> > /* Print version info for PGM_NAME. If QUIET is true, print in
> > * brief. Else if QUIET is not true, print the version more
> > * verbosely, and if FOOTER is non-null, print it following the
> > Index: subversion/libsvn_client/cmdline.c
> > ===================================================================
> > --- subversion/libsvn_client/cmdline.c (revision 0)
> > +++ subversion/libsvn_client/cmdline.c (revision 0)
> > @@ -0,0 +1,307 @@
> > +/*
> > + * cmdline.c: command-line processing + *
> > + * ====================================================================
> > + * Copyright (c) 2000-2007 CollabNet. All rights reserved.
> > + *
> > + * This software is licensed as described in the file COPYING, which
> > + * you should have received as part of this distribution. The terms
> > + * are also available at http://subversion.tigris.org/license-1.html.
> > + * If newer versions of this license are posted there, you may use a
> > + * newer version instead, at your option.
> > + *
> > + * This software consists of voluntary contributions made by many
> > + * individuals. For exact contribution history, see the revision
> > + * history and logs, available at http://subversion.tigris.org/.
> > + * ====================================================================
> > + */
> > +
> > +/* ====================================================================
> */
> > +
> > + +/*** Includes. ***/
> > +#include "svn_client.h"
> > +#include "svn_error.h"
> > +#include "svn_path.h"
> > +#include "svn_opt.h"
> > +#include "svn_utf.h"
> > +
> > +#include "client.h"
> > +
> > +#include "private/svn_opt_private.h"
> > +
> > + +/*** Code. ***/
> > +
> > +#define DEFAULT_ARRAY_SIZE 5
> > +
> > +/* Return true iff ARG is a repository-relative URL: specifically that
> > + * it starts with the characters "^/".
> > + * ARG is in UTF-8 encoding.
> > + * Do not check whether ARG is properly URI-encoded, canonical, or valid
> > + * in any other way. */
> > +static svn_boolean_t
> > +arg_is_repos_relative_url(const char *arg)
> > +{
> > + return (0 == strncmp("^/", arg, 2));
> > +}
> > +
> > +/* Set *ABSOLUTE_URL to the absolute URL represented by RELATIVE_URL
> > + * relative to REPOS_ROOT_URL.
> > + * *ABSOLUTE_URL will end with a peg revision specifier if RELATIVE_URL
> did.
> > + * RELATIVE_URL is in repository-relative syntax: + *
> "^/[REL-URL][@PEG]", + * REPOS_ROOT_URL is the absolute URL of the
> repository root.
> > + * All strings are in UTF-8 encoding.
> > + * Allocate *ABSOLUTE_URL in POOL.
> > + */
> > +static svn_error_t *
> > +resolve_repos_relative_url(const char **absolute_url,
> > + const char *relative_url,
> > + const char *repos_root_url,
> > + apr_pool_t *pool)
> > +{
> > + if (! arg_is_repos_relative_url(relative_url))
> > + return svn_error_createf(SVN_ERR_BAD_URL, NULL,
> > + "Improper relative URL '%s'",
> > + relative_url);
> > +
> > + *absolute_url = svn_path_join(repos_root_url, relative_url + 2, pool);
> > +
> > + return SVN_NO_ERROR;
> > +}
> > +
> > +
> > +/* Attempt to find the root url for TARGET possibly using CTX for
> > + * authentication. If one is found and *ROOT_URL is
> > + * not NULL, then the root url for TARGET must match the value given in
> > + * *ROOT_URL. If *ROOT_URL is NULL then set it with the root url
> allocated
> > + * from POOL as determined from TARGET. + *
> > + * TARGET is a UTF-8 encoded string that is fully canonicalized and
> escaped.
> > + *
> > + * If a root url is not found for TARGET because it does not exist in the
> > + * repository, then return with no error.
> > + */ +static svn_error_t *
> > +check_root_url_of_target(const char **root_url,
> > + const char *target,
> > + svn_client_ctx_t *ctx,
> > + apr_pool_t *pool)
> > +{
> > + svn_error_t *error;
> > + const char *tmp_root_url;
> > + const char *truepath;
> > + svn_opt_revision_t opt_rev;
> > +
> > + SVN_ERR(svn_opt_parse_path(&opt_rev, &truepath, target, pool));
> > +
> > + if ((error = svn_client__get_repos_root(&tmp_root_url,
> > + truepath,
> > + &opt_rev, +
> NULL, ctx, pool)))
> > + {
> > + /* It is OK if the given target does not exist, it just means +
> * we will not be able to determine the root url from this particular
> > + * argument.
> > + */
> > + if ( (error->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
> > + || (error->apr_err == SVN_ERR_WC_NOT_DIRECTORY))
> > + {
> > + svn_error_clear(error);
> > + return SVN_NO_ERROR;
> > + }
> > + else
> > + return error;
> > + }
> > + else if ( (*root_url != NULL)
> > + && (strcmp(*root_url, tmp_root_url) != 0))
> > + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
> > + "All non-relative targets must have the same root
> url.");
> > + else
> > + *root_url = tmp_root_url;
> > +
> > + return SVN_NO_ERROR;
> > +}
> > +
> > +svn_error_t *
> > +svn_client_args_to_target_array(apr_array_header_t **targets_p,
> > + apr_getopt_t *os,
> > + apr_array_header_t *known_targets,
> > + svn_client_ctx_t *ctx,
> > + apr_pool_t *pool)
> > +{
> > + int i;
> > + svn_boolean_t rel_url_found = FALSE;
> > + const char *root_url = NULL;
> > + svn_error_t *err = SVN_NO_ERROR;
> > + apr_array_header_t *input_targets =
> > + apr_array_make(pool, DEFAULT_ARRAY_SIZE, sizeof(const char *));
> > + apr_array_header_t *output_targets =
> > + apr_array_make(pool, DEFAULT_ARRAY_SIZE, sizeof(const char *));
> > +
> > + /* Step 1: create a master array of targets that are in UTF-8
> > + encoding, and come from concatenating the targets left by
> apr_getopt,
> > + plus any extra targets (e.g., from the --targets switch.) + If
> any of the targets are relative urls, then set the rel_url_found +
> flag.*/
> > +
> > + for (; os->ind < os->argc; os->ind++)
> > + {
> > + /* The apr_getopt targets are still in native encoding. */
> > + const char *raw_target = os->argv[os->ind];
> > + const char *utf8_target;
> > +
> > + SVN_ERR(svn_utf_cstring_to_utf8(&utf8_target,
> > + raw_target, pool));
> > +
> > + if (arg_is_repos_relative_url(utf8_target))
> > + rel_url_found = TRUE;
> > +
> > + APR_ARRAY_PUSH(input_targets, const char *) = utf8_target;
> > + }
> > +
> > + if (known_targets)
> > + {
> > + for (i = 0; i < known_targets->nelts; i++)
> > + {
> > + /* The --targets array have already been converted to UTF-8,
> > + because we needed to split up the list with
> svn_cstring_split. */
> > + const char *utf8_target = APR_ARRAY_IDX(known_targets,
> > + i, const char *);
> > +
> > + if (arg_is_repos_relative_url(utf8_target))
> > + rel_url_found = TRUE;
> > +
> > + APR_ARRAY_PUSH(input_targets, const char *) = utf8_target;
> > + }
> > + }
> > +
> > + /* Step 2: process each target. */
> > +
> > + for (i = 0; i < input_targets->nelts; i++)
> > + {
> > + const char *utf8_target = APR_ARRAY_IDX(input_targets, i, const
> char *);
> > + const char *peg_start = NULL; /* pointer to the peg revision, if
> any */
> > + const char *target;
> > + int j;
> > +
> > + /* Remove a peg revision, if any, in the target so that it can
> > + be properly canonicalized, otherwise the canonicalization
> > + does not treat a "._at_BASE" as a "." with a BASE peg revision,
> > + and it is not canonicalized to "@BASE". If any peg revision
> > + exists, it is appended to the final canonicalized path or
> > + URL. Do not use svn_opt_parse_path() because the resulting
> > + peg revision is a structure that would have to be converted
> > + back into a string. Converting from a string date to the
> > + apr_time_t field in the svn_opt_revision_value_t and back to
> > + a string would not necessarily preserve the exact bytes of
> > + the input date, so its easier just to keep it in string
> > + form. */
> > + for (j = (strlen(utf8_target) - 1); j >= 0; --j)
> > + {
> > + /* If we hit a path separator, stop looking. This is OK
> > + only because our revision specifiers can't contain
> > + '/'. */
> > + if (utf8_target[j] == '/')
> > + break;
> > + if (utf8_target[j] == '@')
> > + {
> > + peg_start = utf8_target + j;
> > + break;
> > + }
> > + }
> > + if (peg_start)
> > + utf8_target = apr_pstrmemdup(pool,
> > + utf8_target,
> > + peg_start - utf8_target);
> > +
> > + /* Relative urls will be canonicallized when they are resolved
> later in + * the function + */
> > + if (arg_is_repos_relative_url(utf8_target))
> > + {
> > + APR_ARRAY_PUSH(output_targets, const char *) = utf8_target;
> > + }
> > + else
> > + {
> > + /* URLs and wc-paths get treated differently. */
> > + if (svn_path_is_url(utf8_target))
> > + {
> > + SVN_ERR(svn_opt__arg_canonicalize_url(&target, +
> utf8_target, pool));
> > + }
> > + else /* not a url, so treat as a path */
> > + {
> > + const char *base_name;
> > +
> > + SVN_ERR(svn_opt__arg_canonicalize_path(&target, +
> utf8_target, pool));
> > +
> > + /* If the target has the same name as a Subversion
> > + working copy administrative dir, skip it. */
> > + base_name = svn_path_basename(target, pool);
> > +
> > + if (svn_wc_is_adm_dir(base_name, pool))
> > + {
> > + err =
> svn_error_createf(SVN_ERR_RESERVED_FILENAME_SPECIFIED,
> > + err, +
> "'%s' ends in a reserved name",
> > + target);
> > + continue;
> > + }
> > + }
> > +
> > + /* Append the peg revision back to the canonicalized target if
> > + there was a peg revision. */
> > + if (peg_start)
> > + target = apr_pstrcat(pool, target, peg_start, NULL);
> > +
> > + if (rel_url_found)
> > + {
> > + SVN_ERR(check_root_url_of_target(&root_url, target, +
> ctx, pool));
> > + }
> > +
> > + APR_ARRAY_PUSH(output_targets, const char *) = target;
> > + }
> > + }
> > +
> > + /* Only resolve relative urls if there were some actually found
> earlier. */
> > + if (rel_url_found)
> > + {
> > + /*
> > + * Use the current directory's root url if one wasn't found using
> the
> > + * arguments.
> > + */
> > + if (root_url == NULL)
> > + SVN_ERR(svn_client_root_url_from_path(&root_url, +
> svn_path_canonicalize(".", pool),
> > + ctx, pool));
> > +
> > + *targets_p = apr_array_make(pool, output_targets->nelts,
> sizeof(const char *));
> > +
> > + for (i = 0; i < output_targets->nelts; i++)
> > + {
> > + const char *target = APR_ARRAY_IDX(output_targets, i, +
> const char *);
> > +
> > + if (arg_is_repos_relative_url(target))
> > + {
> > + const char *abs_target;
> > +
> > + SVN_ERR(resolve_repos_relative_url(&abs_target, target, +
> root_url, pool));
> > +
> > + SVN_ERR(svn_opt__arg_canonicalize_url(&target, abs_target,
> + pool));
> > + }
> > +
> > + APR_ARRAY_PUSH(*targets_p, const char *) = target;
> > + }
> > + }
> > + else
> > + *targets_p = output_targets;
> > +
> > + return err;
> > +}
> > Index: subversion/tests/libsvn_client/client-test.c
> > ===================================================================
> > --- subversion/tests/libsvn_client/client-test.c (revision 29840)
> > +++ subversion/tests/libsvn_client/client-test.c (working copy)
> > @@ -20,6 +20,7 @@
> > #include "svn_mergeinfo.h"
> > #include "../../libsvn_client/mergeinfo.h"
> > #include "svn_pools.h"
> > +#include "svn_client.h"
> > #include "../svn_test.h"
> > @@ -98,11 +99,117 @@ test_elide_mergeinfo_catalog(const char **msg,
> > return SVN_NO_ERROR; }
> > +static svn_error_t *
> > +test_args_to_target_array(const char **msg,
> > + svn_boolean_t msg_only,
> > + svn_test_opts_t *opts,
> > + apr_pool_t *pool)
> > +{
> > + apr_size_t i;
> > + apr_pool_t *iterpool; + svn_client_ctx_t *ctx;
> > + static struct {
> > + const char *input;
> > + const char *output; /* NULL means an error is expected. */
> > + } const tests[] = {
> > + { ".", "" },
> > + { "._at_BASE", "@BASE" },
> > + { "foo///bar", "foo/bar" },
> > + { "foo///bar_at_13", "foo/bar_at_13" },
> > + { "foo///bar_at_HEAD", "foo/bar_at_HEAD" },
> > + { "foo///bar@{1999-12-31}", "foo/bar@{1999-12-31}" },
> > + { "http://a//b////", "http://a/b" },
> > + { "http://a///b@27", "http://a/b@27" },
> > + { "http://a/b//@COMMITTED", "http://a/b@COMMITTED" },
> > + { "foo///bar_at_1:2", "foo/bar_at_1:2" },
> > + { "foo///bar_at_baz", "foo/bar_at_baz" },
> > + { "foo///bar@", "foo/bar@" },
> > + { "foo///bar///@13", "foo/bar_at_13" },
> > + { "foo///bar@@13", "foo/bar@@13" },
> > + { "foo///@bar_at_HEAD", "foo/@bar_at_HEAD" },
> > + { "foo@///bar", "foo@/bar" },
> > + { "foo_at_HEAD///bar", "foo_at_HEAD/bar" },
> > + };
> > +
> > + *msg = "test svn_client_args_to_target_array";
> > + if (msg_only)
> > + return SVN_NO_ERROR;
> > +
> > + SVN_ERR(svn_client_create_context(&ctx, pool));
> > +
> > + iterpool = svn_pool_create(pool);
> > +
> > + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
> > + {
> > + const char *input = tests[i].input;
> > + const char *expected_output = tests[i].output;
> > + apr_array_header_t *targets;
> > + apr_getopt_t *os;
> > + const int argc = 2;
> > + const char *argv[] = { "opt-test", input, NULL };
> > + apr_status_t apr_err;
> > + svn_error_t *err;
> > +
> > + apr_err = apr_getopt_init(&os, iterpool, argc, argv);
> > + if (apr_err)
> > + return svn_error_wrap_apr(apr_err,
> > + "Error initializing command line
> arguments");
> > +
> > + err = svn_client_args_to_target_array(&targets, os, NULL, ctx,
> iterpool);
> > +
> > + if (expected_output)
> > + {
> > + const char *actual_output;
> > +
> > + if (err)
> > + return err;
> > + if (argc - 1 != targets->nelts)
> > + return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
> > + "Passed %d target(s) to "
> > + "svn_client_args_to_target_array()
> but "
> > + "got %d back.",
> > + argc - 1,
> > + targets->nelts);
> > +
> > + actual_output = APR_ARRAY_IDX(targets, 0, const char *);
> > +
> > + if (! svn_path_is_canonical(actual_output, iterpool))
> > + return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
> > + "Input '%s' to "
> > + "svn_client_args_to_target_array()
> should "
> > + "have returned a canonical path but
> "
> > + "'%s' is not.",
> > + input,
> > + actual_output);
> > + + if (strcmp(expected_output, actual_output) != 0)
> > + return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
> > + "Input '%s' to "
> > + "svn_client_args_to_target_array()
> should "
> > + "have returned '%s' but returned
> '%s'.",
> > + input,
> > + expected_output,
> > + actual_output);
> > + }
> > + else
> > + {
> > + if (! err)
> > + return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
> > + "Unexpected success in passing '%s'
> "
> > + "to
> svn_client_args_to_target_array().",
> > + input);
> > + }
> > + }
> > +
> > + return SVN_NO_ERROR;
> > +}
> > +
> > /*
> ==========================================================================
> */
> > struct svn_test_descriptor_t test_funcs[] =
> > {
> > SVN_TEST_NULL,
> > SVN_TEST_PASS(test_elide_mergeinfo_catalog),
> > + SVN_TEST_PASS(test_args_to_target_array),
> > SVN_TEST_NULL
> > };
> > Index: subversion/tests/cmdline/special_tests.py
> > ===================================================================
> > --- subversion/tests/cmdline/special_tests.py (revision 29840)
> > +++ subversion/tests/cmdline/special_tests.py (working copy)
> > @@ -613,18 +613,18 @@ def warn_on_reserved_name(sbox):
> > sbox.build()
> > wc_dir = sbox.wc_dir
> > if os.path.exists(os.path.join(wc_dir, ".svn")):
> > + reserved_path = os.path.join(wc_dir, ".svn")
> > + elif os.path.exists(os.path.join(wc_dir, "_svn")):
> > reserved_path = os.path.join(wc_dir, "_svn")
> > - elif os.path.exists(os.path.join(wc_dir, "_svn")):
> > - reserved_path = os.path.join(wc_dir, ".svn")
> > else:
> > # We don't know how to test this, but have no reason to believe
> > # it would fail. (TODO: any way to return 'Skip', though?)
> > return
> > - svntest.main.file_append(reserved_path, 'expecting rejection')
> > svntest.actions.run_and_verify_svn(
> > - "Adding a file with a reserved name failed to result in an error",
> > - None, ".*Skipping argument: '.+' ends in a reserved name.*",
> > - 'add', reserved_path)
> > + "Locking a file with a reserved name failed to result in an error",
> > + None, + ".*Skipping argument: '.+' ends in a reserved name.*",
> > + 'lock', reserved_path)
> >
> ########################################################################
> > Index: subversion/tests/cmdline/basic_tests.py
> > ===================================================================
> > --- subversion/tests/cmdline/basic_tests.py (revision 29840)
> > +++ subversion/tests/cmdline/basic_tests.py (working copy)
> > @@ -2162,7 +2162,93 @@ def info_nonexisting_file(sbox):
> > #----------------------------------------------------------------------
> > +# Relative urls
> > +#
> > +# Use blame to test three specific cases for relative url support. +def
> basic_relative_url_using_current_dir(sbox):
> > + "basic relative url target using current dir"
> > + # We'll use blame to test relative url parsing
> > + sbox.build()
> > +
> > + # First, make a new revision of iota.
> > + iota = os.path.join(sbox.wc_dir, 'iota')
> > + svntest.main.file_append(iota, "New contents for iota\n")
> > + svntest.main.run_svn(None, 'ci',
> > + '-m', '', iota)
> > +
> > + expected_output = [
> > + " 1 jrandom This is the file 'iota'.\n",
> > + " 2 jrandom New contents for iota\n",
> > + ]
> > +
> > + orig_dir = os.getcwd()
> > + os.chdir(sbox.wc_dir)
> > +
> > + exit_code, output, error = svntest.actions.run_and_verify_svn(None,
> > + expected_output, [],
> > + 'blame', '^/iota')
> > +
> > + os.chdir(orig_dir)
> > +
> > +def basic_relative_url_using_other_targets(sbox):
> > + "basic relative url target using other targets"
> > +
> > + sbox.build()
> > +
> > + # First, make a new revision of iota.
> > + iota = os.path.join(sbox.wc_dir, 'iota')
> > + svntest.main.file_append(iota, "New contents for iota\n")
> > + svntest.main.run_svn(None, 'ci',
> > + '-m', '', iota)
> > +
> > + # Now, make a new revision of A/mu .
> > + mu = os.path.join(sbox.wc_dir, 'A', 'mu')
> > + mu_url = sbox.repo_url + '/A/mu'
> > +
> > + svntest.main.file_append(mu, "New contents for mu\n")
> > + svntest.main.run_svn(None, 'ci',
> > + '-m', '', mu)
> > +
> > +
> > + expected_output = [
> > + " 1 jrandom This is the file 'iota'.\n",
> > + " 2 jrandom New contents for iota\n",
> > + " 1 jrandom This is the file 'mu'.\n",
> > + " 3 jrandom New contents for mu\n",
> > + ]
> > +
> > + exit_code, output, error = svntest.actions.run_and_verify_svn(None,
> > + expected_output, [], 'blame', +
> '^/iota', mu_url)
> > +
> > +def basic_relative_url_multi_repo(sbox):
> > + "basic relative url target with multiple repos"
> > +
> > + sbox.build()
> > + repo_url1 = sbox.repo_url
> > + repo_dir1 = sbox.repo_dir
> > + wc_dir1 = sbox.wc_dir
> > +
> > + repo_dir2, repo_url2 = sbox.add_repo_path("other")
> > + svntest.main.copy_repos(repo_dir1, repo_dir2, 1, 1)
> > + wc_dir2 = sbox.add_wc_path("other")
> > + svntest.actions.run_and_verify_svn("Unexpected error during co",
> > + svntest.verify.AnyOutput, [], "co",
> > + repo_url2,
> > + wc_dir2)
> > +
> > + # Don't bother with making new revisions, the command should not work.
> > + iota_url_repo1 = repo_url1 + '/iota'
> > + iota_url_repo2 = repo_url2 + '/iota'
> > +
> > + exit_code, output, error = svntest.actions.run_and_verify_svn(None, [],
> + svntest.verify.AnyOutput, 'blame', +
> '^/A/mu', iota_url_repo1, iota_url_repo2)
> > +
> > +
> > +#----------------------------------------------------------------------
> > +
> > ########################################################################
> > # Run the tests
> > @@ -2208,6 +2294,9 @@ test_list = [ None,
> > XFail(basic_rm_urls_multi_repos),
> > automatic_conflict_resolution,
> > info_nonexisting_file,
> > + basic_relative_url_using_current_dir,
> > + basic_relative_url_using_other_targets,
> > + basic_relative_url_multi_repo,
> > ]
> > if __name__ == '__main__':
> > Index: subversion/svn/merge-cmd.c
> > ===================================================================
> > --- subversion/svn/merge-cmd.c (revision 29840)
> > +++ subversion/svn/merge-cmd.c (working copy)
> > @@ -52,7 +52,7 @@ svn_cl__merge(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Parse at least one, and possible two, sources. */
> > if (targets->nelts >= 1)
> > Index: subversion/svn/cl.h
> > ===================================================================
> > --- subversion/svn/cl.h (revision 29840)
> > +++ subversion/svn/cl.h (working copy)
> > @@ -581,6 +581,7 @@ svn_error_t *
> > svn_cl__args_to_target_array_print_reserved(apr_array_header_t
> **targets_p,
> > apr_getopt_t *os,
> > apr_array_header_t
> *known_targets,
> > + svn_client_ctx_t *ctx,
> > apr_pool_t *pool);
> > #ifdef __cplusplus
> > Index: subversion/svn/propdel-cmd.c
> > ===================================================================
> > --- subversion/svn/propdel-cmd.c (revision 29840)
> > +++ subversion/svn/propdel-cmd.c (working copy)
> > @@ -58,7 +58,7 @@ svn_cl__propdel(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Add "." if user passed 0 file arguments */
> > Index: subversion/svn/checkout-cmd.c
> > ===================================================================
> > --- subversion/svn/checkout-cmd.c (revision 29840)
> > +++ subversion/svn/checkout-cmd.c (working copy)
> > @@ -72,7 +72,7 @@ svn_cl__checkout(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > if (! targets->nelts)
> > return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
> > Index: subversion/svn/move-cmd.c
> > ===================================================================
> > --- subversion/svn/move-cmd.c (revision 29840)
> > +++ subversion/svn/move-cmd.c (working copy)
> > @@ -48,7 +48,7 @@ svn_cl__move(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > if (targets->nelts < 2)
> > return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
> > Index: subversion/svn/mkdir-cmd.c
> > ===================================================================
> > --- subversion/svn/mkdir-cmd.c (revision 29840)
> > +++ subversion/svn/mkdir-cmd.c (working copy)
> > @@ -47,7 +47,7 @@ svn_cl__mkdir(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > if (! targets->nelts)
> > return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
> > Index: subversion/svn/cat-cmd.c
> > ===================================================================
> > --- subversion/svn/cat-cmd.c (revision 29840)
> > +++ subversion/svn/cat-cmd.c (working copy)
> > @@ -45,7 +45,7 @@ svn_cl__cat(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Cat cannot operate on an implicit '.' so a filename is required */
> > if (! targets->nelts)
> > Index: subversion/svn/revert-cmd.c
> > ===================================================================
> > --- subversion/svn/revert-cmd.c (revision 29840)
> > +++ subversion/svn/revert-cmd.c (working copy)
> > @@ -45,7 +45,7 @@ svn_cl__revert(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Revert has no implicit dot-target `.', so don't you put that code
> here! */
> > if (! targets->nelts)
> > Index: subversion/svn/diff-cmd.c
> > ===================================================================
> > --- subversion/svn/diff-cmd.c (revision 29840)
> > +++ subversion/svn/diff-cmd.c (working copy)
> > @@ -147,6 +147,7 @@ svn_cl__diff(apr_getopt_t *os,
> > apr_pool_t *pool)
> > {
> > svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *)
> baton)->opt_state;
> > + svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
> > apr_array_header_t *options;
> > apr_array_header_t *targets;
> > apr_file_t *outfile, *errfile;
> > @@ -190,7 +191,7 @@ svn_cl__diff(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > if (! opt_state->old_target && ! opt_state->new_target
> > && (targets->nelts == 2)
> > @@ -230,7 +231,7 @@ svn_cl__diff(apr_getopt_t *os,
> > const char *));
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&tmp2, os,
> tmp, - pool));
> > + ctx, pool));
> > SVN_ERR(svn_opt_parse_path(&old_rev, &old_target,
> > APR_ARRAY_IDX(tmp2, 0, const char *),
> > pool));
> > @@ -328,8 +329,7 @@ svn_cl__diff(apr_getopt_t *os,
> > opt_state->changelists,
> > summarize_func,
> > (void *) target1,
> > - ((svn_cl__cmd_baton_t *)baton)->ctx,
> > - iterpool));
> > + ctx, iterpool));
> > else
> > SVN_ERR(svn_client_diff4
> > (options,
> > @@ -346,8 +346,7 @@ svn_cl__diff(apr_getopt_t *os,
> > outfile,
> > errfile,
> > opt_state->changelists,
> > - ((svn_cl__cmd_baton_t *)baton)->ctx,
> > - iterpool));
> > + ctx, iterpool));
> > }
> > else
> > {
> > @@ -374,8 +373,7 @@ svn_cl__diff(apr_getopt_t *os,
> > opt_state->changelists,
> > summarize_func,
> > (void *) truepath,
> > - ((svn_cl__cmd_baton_t *)baton)->ctx,
> > - iterpool));
> > + ctx, iterpool));
> > else
> > SVN_ERR(svn_client_diff_peg4
> > (options,
> > @@ -392,8 +390,7 @@ svn_cl__diff(apr_getopt_t *os,
> > outfile,
> > errfile,
> > opt_state->changelists,
> > - ((svn_cl__cmd_baton_t *)baton)->ctx,
> > - iterpool));
> > + ctx, iterpool));
> > }
> > }
> > Index: subversion/svn/copy-cmd.c
> > ===================================================================
> > --- subversion/svn/copy-cmd.c (revision 29840)
> > +++ subversion/svn/copy-cmd.c (working copy)
> > @@ -49,7 +49,7 @@ svn_cl__copy(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > if (targets->nelts < 2)
> > return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
> > Index: subversion/svn/mergeinfo-cmd.c
> > ===================================================================
> > --- subversion/svn/mergeinfo-cmd.c (revision 29840)
> > +++ subversion/svn/mergeinfo-cmd.c (working copy)
> > @@ -133,7 +133,7 @@ svn_cl__mergeinfo(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Add "." if user passed 0 arguments. */
> > svn_opt_push_implicit_dot_target(targets, pool);
> > Index: subversion/svn/list-cmd.c
> > ===================================================================
> > --- subversion/svn/list-cmd.c (revision 29840)
> > +++ subversion/svn/list-cmd.c (working copy)
> > @@ -220,7 +220,7 @@ svn_cl__list(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Add "." if user passed 0 arguments */
> > svn_opt_push_implicit_dot_target(targets, pool);
> > Index: subversion/svn/util.c
> > ===================================================================
> > --- subversion/svn/util.c (revision 29840)
> > +++ subversion/svn/util.c (working copy)
> > @@ -1014,10 +1014,12 @@ svn_error_t *
> > svn_cl__args_to_target_array_print_reserved(apr_array_header_t **targets,
> > apr_getopt_t *os,
> > apr_array_header_t
> *known_targets,
> > + svn_client_ctx_t *ctx,
> > apr_pool_t *pool)
> > {
> > - svn_error_t *error = svn_opt_args_to_target_array3(targets, os,
> > - known_targets,
> pool);
> > + svn_error_t *error = svn_client_args_to_target_array(targets, os,
> > + known_targets, +
> ctx, pool);
> > if (error)
> > {
> > if (error->apr_err == SVN_ERR_RESERVED_FILENAME_SPECIFIED)
> > Index: subversion/svn/blame-cmd.c
> > ===================================================================
> > --- subversion/svn/blame-cmd.c (revision 29840)
> > +++ subversion/svn/blame-cmd.c (working copy)
> > @@ -204,7 +204,7 @@ svn_cl__blame(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Blame needs a file on which to operate. */
> > if (! targets->nelts)
> > Index: subversion/svn/propget-cmd.c
> > ===================================================================
> > --- subversion/svn/propget-cmd.c (revision 29840)
> > +++ subversion/svn/propget-cmd.c (working copy)
> > @@ -182,7 +182,7 @@ svn_cl__propget(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Add "." if user passed 0 file arguments */
> > svn_opt_push_implicit_dot_target(targets, pool);
> > Index: subversion/svn/changelist-cmd.c
> > ===================================================================
> > --- subversion/svn/changelist-cmd.c (revision 29840)
> > +++ subversion/svn/changelist-cmd.c (working copy)
> > @@ -60,7 +60,7 @@ svn_cl__changelist(apr_getopt_t *os,
> > /* Parse the remaining arguments as paths. */
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> opt_state->targets, -
> pool));
> > + ctx, pool));
> > /* Changelist has no implicit dot-target `.', so don't you put that
> > code here! */
> > Index: subversion/svn/log-cmd.c
> > ===================================================================
> > --- subversion/svn/log-cmd.c (revision 29840)
> > +++ subversion/svn/log-cmd.c (working copy)
> > @@ -468,7 +468,7 @@ svn_cl__log(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Add "." if user passed 0 arguments */
> > svn_opt_push_implicit_dot_target(targets, pool);
> > Index: subversion/svn/update-cmd.c
> > ===================================================================
> > --- subversion/svn/update-cmd.c (revision 29840)
> > +++ subversion/svn/update-cmd.c (working copy)
> > @@ -46,8 +46,9 @@ svn_cl__update(apr_getopt_t *os,
> > svn_depth_t depth;
> > svn_boolean_t depth_is_sticky;
> > - SVN_ERR(svn_opt_args_to_target_array3(&targets, os,
> > - opt_state->targets, pool));
> > + SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > + opt_state->targets,
> + ctx, pool));
> > /* Add "." if user passed 0 arguments */
> > svn_opt_push_implicit_dot_target(targets, pool);
> > Index: subversion/svn/resolved-cmd.c
> > ===================================================================
> > --- subversion/svn/resolved-cmd.c (revision 29840)
> > +++ subversion/svn/resolved-cmd.c (working copy)
> > @@ -76,7 +76,7 @@ svn_cl__resolved(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > if (! targets->nelts)
> > return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
> > Index: subversion/svn/cleanup-cmd.c
> > ===================================================================
> > --- subversion/svn/cleanup-cmd.c (revision 29840)
> > +++ subversion/svn/cleanup-cmd.c (working copy)
> > @@ -45,7 +45,7 @@ svn_cl__cleanup(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Add "." if user passed 0 arguments */
> > svn_opt_push_implicit_dot_target(targets, pool);
> > Index: subversion/svn/commit-cmd.c
> > ===================================================================
> > --- subversion/svn/commit-cmd.c (revision 29840)
> > +++ subversion/svn/commit-cmd.c (working copy)
> > @@ -53,7 +53,7 @@ svn_cl__commit(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Add "." if user passed 0 arguments. */
> > svn_opt_push_implicit_dot_target(targets, pool);
> > Index: subversion/svn/add-cmd.c
> > ===================================================================
> > --- subversion/svn/add-cmd.c (revision 29840)
> > +++ subversion/svn/add-cmd.c (working copy)
> > @@ -47,7 +47,7 @@ svn_cl__add(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > if (! targets->nelts)
> > return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
> > Index: subversion/svn/propset-cmd.c
> > ===================================================================
> > --- subversion/svn/propset-cmd.c (revision 29840)
> > +++ subversion/svn/propset-cmd.c (working copy)
> > @@ -93,7 +93,7 @@ svn_cl__propset(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Implicit "." is okay for revision properties; it just helps
> > us find the right repository. */
> > Index: subversion/svn/switch-cmd.c
> > ===================================================================
> > --- subversion/svn/switch-cmd.c (revision 29840)
> > +++ subversion/svn/switch-cmd.c (working copy)
> > @@ -101,7 +101,7 @@ svn_cl__switch(apr_getopt_t *os,
> > switch to ("switch_url"). */
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* handle only-rewrite case specially */
> > if (opt_state->relocate)
> > Index: subversion/svn/delete-cmd.c
> > ===================================================================
> > --- subversion/svn/delete-cmd.c (revision 29840)
> > +++ subversion/svn/delete-cmd.c (working copy)
> > @@ -46,7 +46,7 @@ svn_cl__delete(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > if (! targets->nelts)
> > return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
> > Index: subversion/svn/import-cmd.c
> > ===================================================================
> > --- subversion/svn/import-cmd.c (revision 29840)
> > +++ subversion/svn/import-cmd.c (working copy)
> > @@ -75,7 +75,7 @@ svn_cl__import(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > if (targets->nelts < 1)
> > return svn_error_create
> > Index: subversion/svn/proplist-cmd.c
> > ===================================================================
> > --- subversion/svn/proplist-cmd.c (revision 29840)
> > +++ subversion/svn/proplist-cmd.c (working copy)
> > @@ -114,7 +114,7 @@ svn_cl__proplist(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Add "." if user passed 0 file arguments */
> > svn_opt_push_implicit_dot_target(targets, pool);
> > Index: subversion/svn/export-cmd.c
> > ===================================================================
> > --- subversion/svn/export-cmd.c (revision 29840)
> > +++ subversion/svn/export-cmd.c (working copy)
> > @@ -48,7 +48,7 @@ svn_cl__export(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* We want exactly 1 or 2 targets for this subcommand. */
> > if (targets->nelts < 1)
> > Index: subversion/svn/status-cmd.c
> > ===================================================================
> > --- subversion/svn/status-cmd.c (revision 29840)
> > +++ subversion/svn/status-cmd.c (working copy)
> > @@ -218,7 +218,7 @@ svn_cl__status(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > /* Add "." if user passed 0 arguments */
> > svn_opt_push_implicit_dot_target(targets, pool);
> > Index: subversion/svn/propedit-cmd.c
> > ===================================================================
> > --- subversion/svn/propedit-cmd.c (revision 29840)
> > +++ subversion/svn/propedit-cmd.c (working copy)
> > @@ -68,7 +68,7 @@ svn_cl__propedit(apr_getopt_t *os,
> > /* Suck up all the remaining arguments into a targets array */
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> > opt_state->targets,
> - pool));
> > + ctx, pool));
> > if (opt_state->revprop) /* operate on a revprop */
> > {
> > Index: subversion/svn/lock-cmd.c
> > ===================================================================
> > --- subversion/svn/lock-cmd.c (revision 29840)
> > +++ subversion/svn/lock-cmd.c (working copy)
> > @@ -87,7 +87,7 @@ svn_cl__lock(apr_getopt_t *os,
> > SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
> opt_state->targets, -
> pool));
> > +
> ...
>
> [Message clipped]
--
"Beware of spyware. If you can, use the Firefox browser." - USA Today
Download now at http://getfirefox.com
Registered Linux User #354814 ( http://counter.li.org/)
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe_at_subversion.tigris.org
For additional commands, e-mail: dev-help_at_subversion.tigris.org
Received on 2008-04-23 04:01:06 CEST