Py::Object pysvn_client::cmd_export( const Py::Tuple &a_args, const Py::Dict &a_kws )
{
    static argument_description args_desc[] =
    {
    { true,  name_src_url_or_path },
    { true,  name_dest_path },
    { false, name_force },
    { false, name_revision },
#if defined( PYSVN_HAS_CLIENT_EXPORT2 )
    { false, name_native_eol },
#endif
#if defined( PYSVN_HAS_CLIENT_EXPORT3 )
    { false, name_ignore_externals },
    { false, name_recurse },
    { false, name_peg_revision },
#endif
#if defined( PYSVN_HAS_CLIENT_EXPORT4 )
    { false, name_depth },
#endif
    { false, NULL }
    };
    FunctionArguments args( "export", args_desc, a_args, a_kws );
    args.check();

    std::string src_path( args.getUtf8String( name_src_url_or_path ) );
    std::string dest_path( args.getUtf8String( name_dest_path ) );
    bool is_url = is_svn_url( src_path );

    bool force = args.getBoolean( name_force, false );
    svn_opt_revision_t revision;
    if( is_url )
         revision = args.getRevision( name_revision, svn_opt_revision_head );
    else
         revision = args.getRevision( name_revision, svn_opt_revision_working );

#if defined( PYSVN_HAS_CLIENT_EXPORT2 )
    const char *native_eol = NULL;
    if( args.hasArg( name_native_eol ) )
    {
        Py::Object native_eol_obj = args.getArg( name_native_eol );
        if( native_eol_obj != Py::None() )
        {
            Py::String eol_py_str( native_eol_obj );
            std::string eol_str = eol_py_str.as_std_string( g_utf_8 );
            if( eol_str == "CR" )
                native_eol = "CR";
            else if( eol_str == "CRLF" )
                native_eol = "CRLF";
            else if( eol_str == "LF" )
                native_eol = "LF";
            else
                throw Py::ValueError( "native_eol must be one of None, \"LF\", \"CRLF\" or \"CR\"" );
        }
    }
#endif
#if defined( PYSVN_HAS_CLIENT_EXPORT3 )
#if defined( PYSVN_HAS_CLIENT_EXPORT4 )
    svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_infinity, svn_depth_infinity, svn_depth_files );
#else
    bool recurse = args.getBoolean( name_recurse, true );
#endif
    bool ignore_externals = args.getBoolean( name_ignore_externals, false );
    svn_opt_revision_t peg_revision = args.getRevision( name_peg_revision, revision );

    revisionKindCompatibleCheck( is_url, peg_revision, name_peg_revision, name_url_or_path );
#endif

    revisionKindCompatibleCheck( is_url, revision, name_revision, name_url_or_path );

    svn_revnum_t revnum = 0;

    SvnPool pool( m_context );

    try
    {
        std::string norm_src_path( svnNormalisedIfPath( src_path, pool ) );

        checkThreadPermission();

        PythonAllowThreads permission( m_context );

#if defined( PYSVN_HAS_CLIENT_EXPORT4 )
        svn_error_t * error = svn_client_export4
            (
            &revnum,
            norm_src_path.c_str(),
            dest_path.c_str(),
            &peg_revision,
            &revision,
            force,
            ignore_externals,
            depth,
            native_eol,
            m_context,
            pool
            );
#elif defined( PYSVN_HAS_CLIENT_EXPORT3 )
        svn_error_t * error = svn_client_export3
            (
            &revnum,
            norm_src_path.c_str(),
            dest_path.c_str(),
            &peg_revision,
            &revision,
            force,
            ignore_externals,
            recurse,
            native_eol,
            m_context,
            pool
            );
#elif defined( PYSVN_HAS_CLIENT_EXPORT2 )
        svn_error_t * error = svn_client_export2
            (
            &revnum,
            norm_src_path.c_str(),
            dest_path.c_str(),
            &revision,
            force,
            native_eol,
            m_context,
            pool
            );
#else
        svn_error_t * error = svn_client_export
            (
            &revnum,
            norm_src_path.c_str(),
            dest_path.c_str(),
            &revision,
            force,
            m_context,
            pool
            );
#endif
        permission.allowThisThread();
        if( error != NULL )
            throw SvnException( error );
    }
    catch( SvnException &e )
    {
        // use callback error over ClientException
        m_context.checkForError( m_module.client_error );

        throw_client_error( e );
    }

    return Py::asObject( new pysvn_revision( svn_opt_revision_number, 0, revnum ) );
}
Example #2
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__export(apr_getopt_t *os,
               void *baton,
               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;
  const char *from, *to;
  apr_array_header_t *targets;
  svn_error_t *err;
  svn_opt_revision_t peg_revision;
  const char *truefrom;

  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                      opt_state->targets,
                                                      ctx, pool));

  /* We want exactly 1 or 2 targets for this subcommand. */
  if (targets->nelts < 1)
    return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
  if (targets->nelts > 2)
    return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL);

  /* The first target is the `from' path. */
  from = APR_ARRAY_IDX(targets, 0, const char *);

  /* Get the peg revision if present. */
  SVN_ERR(svn_opt_parse_path(&peg_revision, &truefrom, from, pool));

  /* If only one target was given, split off the basename to use as
     the `to' path.  Else, a `to' path was supplied. */
  if (targets->nelts == 1)
    to = svn_path_uri_decode(svn_path_basename(truefrom, pool), pool);
  else
    to = APR_ARRAY_IDX(targets, 1, const char *);

  SVN_ERR(svn_opt__split_arg_at_peg_revision(&to, NULL, to, pool));

  if (! opt_state->quiet)
    svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE, TRUE,
                         FALSE, pool);

  if (opt_state->depth == svn_depth_unknown)
    opt_state->depth = svn_depth_infinity;

  /* Decode the partially encoded URL and escape all URL unsafe characters. */
  if (svn_path_is_url(truefrom))
    truefrom = svn_path_uri_encode(svn_path_uri_decode(truefrom, pool), pool);

  /* Do the export. */
  err = svn_client_export4(NULL, truefrom, to, &peg_revision,
                           &(opt_state->start_revision),
                           opt_state->force, opt_state->ignore_externals,
                           opt_state->depth,
                           opt_state->native_eol, ctx,
                           pool);
  if (err && err->apr_err == SVN_ERR_WC_OBSTRUCTED_UPDATE && !opt_state->force)
    SVN_ERR_W(err,
              _("Destination directory exists; please remove "
                "the directory or use --force to overwrite"));

  return err;
}