Py::Object pysvn_client::cmd_revpropset( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_prop_name }, { true, name_prop_value }, { true, name_url }, { false, name_revision }, { false, name_force }, { false, NULL } }; FunctionArguments args( "revpropset", args_desc, a_args, a_kws ); args.check(); std::string propname( args.getUtf8String( name_prop_name ) ); std::string propval( args.getUtf8String( name_prop_value ) ); std::string path( args.getUtf8String( name_url ) ); svn_opt_revision_t revision = args.getRevision( name_revision, svn_opt_revision_head ); bool force = args.getBoolean( name_force, false ); SvnPool pool( m_context ); svn_revnum_t revnum = 0; try { std::string norm_path( svnNormalisedIfPath( path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); const svn_string_t *svn_propval = svn_string_ncreate( propval.c_str(), propval.size(), pool ); svn_error_t *error = svn_client_revprop_set ( propname.c_str(), svn_propval, norm_path.c_str(), &revision, &revnum, force, m_context, pool ); 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 ) ); }
Py::Object pysvn_client::cmd_lock( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_url_or_path }, { true, name_comment }, { false, name_force }, { false, NULL } }; FunctionArguments args( "lock", args_desc, a_args, a_kws ); args.check(); SvnPool pool( m_context ); apr_array_header_t *targets = targetsFromStringOrList( args.getArg( name_url_or_path ), pool ); std::string type_error_message; try { type_error_message = "expecting string for comment (arg 2)"; std::string comment( args.getUtf8String( name_comment ) ); type_error_message = "expecting boolean for force keyword arg"; bool force = args.getBoolean( name_force, false ); try { checkThreadPermission(); PythonAllowThreads permission( m_context ); svn_error_t *error = svn_client_lock ( targets, comment.c_str(), force, // non recursive m_context, pool ); 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 ); } } catch( Py::TypeError & ) { throw Py::TypeError( type_error_message ); } return Py::None(); }
Py::Object pysvn_client::cmd_info( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_path }, { false, NULL } }; FunctionArguments args( "info", args_desc, a_args, a_kws ); args.check(); std::string path( args.getUtf8String( name_path ) ); SvnPool pool( m_context ); const svn_wc_entry_t *entry = NULL; try { checkThreadPermission(); PythonAllowThreads permission( m_context ); svn_wc_adm_access_t *adm_access = NULL; #if defined( PYSVN_HAS_WC_ADM_PROBE_OPEN3 ) const char *c_norm_path = svn_dirent_internal_style( path.c_str(), pool ); std::string norm_path( c_norm_path ); svn_error_t *error = svn_wc_adm_probe_open3( &adm_access, NULL, norm_path.c_str(), false, 0, NULL, NULL, pool ); #else std::string norm_path( svnNormalisedPath( path, pool ) ); svn_error_t *error = svn_wc_adm_probe_open( &adm_access, NULL, norm_path.c_str(), false, false, pool ); #endif permission.allowThisThread(); if( error != NULL ) throw SvnException( error ); permission.allowOtherThreads(); error = svn_wc_entry( &entry, norm_path.c_str(), adm_access, false, pool ); 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::None(); // needed to remove warning about return value missing } if( entry == NULL ) return Py::None(); return toObject( *entry, pool, m_wrapper_entry ); }
Py::Object pysvn_client::cmd_revproplist( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_url }, { false, name_revision }, { false, NULL } }; FunctionArguments args( "revproplist", args_desc, a_args, a_kws ); args.check(); std::string path( args.getUtf8String( name_url ) ); svn_opt_revision_t revision = args.getRevision( name_revision, svn_opt_revision_head ); SvnPool pool( m_context ); apr_hash_t *props = NULL; svn_revnum_t revnum = 0; try { std::string norm_path( svnNormalisedIfPath( path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); svn_error_t *error = svn_client_revprop_list ( &props, norm_path.c_str(), &revision, &revnum, m_context, pool ); 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 ); } Py::Tuple result(2); result[0] = Py::asObject( new pysvn_revision( svn_opt_revision_number, 0, revnum ) ); result[1] = propsToObject( props, pool ); return result; }
Py::Object pysvn_client::cmd_propget( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_prop_name }, { true, name_url_or_path }, { false, name_revision }, { false, name_recurse }, #if defined( PYSVN_HAS_CLIENT_PROPGET2 ) { false, name_peg_revision }, #endif #if defined( PYSVN_HAS_CLIENT_PROPGET3 ) { false, name_depth }, { false, name_changelists }, #endif { false, NULL } }; FunctionArguments args( "propget", args_desc, a_args, a_kws ); args.check(); std::string propname( args.getUtf8String( name_prop_name ) ); std::string path( args.getUtf8String( name_url_or_path ) ); SvnPool pool( m_context ); #if defined( PYSVN_HAS_CLIENT_PROPGET3 ) apr_array_header_t *changelists = NULL; if( args.hasArg( name_changelists ) ) { changelists = arrayOfStringsFromListOfStrings( args.getArg( name_changelists ), pool ); } svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_files, svn_depth_empty ); #else bool recurse = args.getBoolean( name_recurse, false ); #endif svn_opt_revision_t revision; if( is_svn_url( path ) ) revision = args.getRevision( name_revision, svn_opt_revision_head ); else revision = args.getRevision( name_revision, svn_opt_revision_working ); #if defined( PYSVN_HAS_CLIENT_PROPGET2 ) svn_opt_revision_t peg_revision = args.getRevision( name_peg_revision, revision ); #endif bool is_url = is_svn_url( path ); #if defined( PYSVN_HAS_CLIENT_PROPGET2 ) revisionKindCompatibleCheck( is_url, peg_revision, name_peg_revision, name_url_or_path ); #endif revisionKindCompatibleCheck( is_url, revision, name_revision, name_url_or_path ); apr_hash_t *props = NULL; #if defined( PYSVN_HAS_CLIENT_PROPGET3 ) svn_revnum_t actual_revnum = 0; #endif try { std::string norm_path( svnNormalisedIfPath( path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); #if defined( PYSVN_HAS_CLIENT_PROPGET3 ) svn_error_t *error = svn_client_propget3 ( &props, propname.c_str(), norm_path.c_str(), &peg_revision, &revision, &actual_revnum, depth, changelists, m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_PROPGET2 ) svn_error_t *error = svn_client_propget2 ( &props, propname.c_str(), norm_path.c_str(), &peg_revision, &revision, recurse, m_context, pool ); #else svn_error_t *error = svn_client_propget ( &props, propname.c_str(), norm_path.c_str(), &revision, recurse, 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 propsToObject( props, pool ); }
Py::Object pysvn_client::cmd_proplist( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_url_or_path }, { false, name_revision }, { false, name_recurse }, #if defined( PYSVN_HAS_CLIENT_PROPLIST2 ) { false, name_peg_revision }, #endif #if defined( PYSVN_HAS_CLIENT_PROPLIST3 ) { false, name_depth }, { false, name_changelists }, #endif { false, NULL } }; FunctionArguments args( "proplist", args_desc, a_args, a_kws ); args.check(); Py::List path_list( toListOfStrings( args.getArg( name_url_or_path ) ) ); SvnPool pool( m_context ); #if defined( PYSVN_HAS_CLIENT_PROPLIST3 ) apr_array_header_t *changelists = NULL; if( args.hasArg( name_changelists ) ) { changelists = arrayOfStringsFromListOfStrings( args.getArg( name_changelists ), pool ); } svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_files, svn_depth_empty ); #else bool recurse = args.getBoolean( name_recurse, false ); #endif bool is_revision_setup = false; bool is_url = false; svn_opt_revision_t revision_url; svn_opt_revision_t revision_file; if( args.hasArg( name_revision ) ) { revision_url = args.getRevision( name_revision ); revision_file = revision_url; } else { revision_url.kind = svn_opt_revision_head; revision_file.kind = svn_opt_revision_working; } #if defined( PYSVN_HAS_CLIENT_PROPLIST2 ) svn_opt_revision_t peg_revision_url; svn_opt_revision_t peg_revision_file; if( args.hasArg( name_peg_revision ) ) { peg_revision_url = args.getRevision( name_peg_revision ); peg_revision_file = peg_revision_url; } else { peg_revision_url = revision_url; peg_revision_file = revision_file; } #endif Py::List list_of_proplists; for( Py::List::size_type i=0; i<path_list.length(); i++ ) { Py::String path_str( asUtf8String( path_list[i] ) ); std::string path( path_str.as_std_string() ); std::string norm_path( svnNormalisedIfPath( path, pool ) ); svn_opt_revision_t revision; svn_opt_revision_t peg_revision; if( !is_revision_setup ) if( is_svn_url( path ) ) { revision = revision_url; #if defined( PYSVN_HAS_CLIENT_PROPLIST2 ) peg_revision = peg_revision_url; #endif is_url = true; } else { revision = revision_file; #if defined( PYSVN_HAS_CLIENT_PROPLIST2 ) peg_revision = peg_revision_file; #endif } else if( is_svn_url( path ) && !is_url ) { throw Py::AttributeError( "cannot mix URL and PATH in name_path" ); } try { const char *norm_path_c_str= norm_path.c_str(); checkThreadPermission(); PythonAllowThreads permission( m_context ); #if defined( PYSVN_HAS_CLIENT_PROPLIST3 ) ProplistReceiveBaton proplist_baton( &permission, pool, list_of_proplists ); svn_error_t *error = svn_client_proplist3 ( norm_path_c_str, &peg_revision, &revision, depth, changelists, proplist_receiver_c, reinterpret_cast<void *>( &proplist_baton ), m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_PROPLIST2 ) apr_array_header_t *props = NULL; svn_error_t *error = svn_client_proplist2 ( &props, norm_path_c_str, &peg_revision, &revision, recurse, m_context, pool ); #else apr_array_header_t *props = NULL; svn_error_t *error = svn_client_proplist ( &props, norm_path_c_str, &revision, recurse, m_context, pool ); #endif permission.allowThisThread(); if( error != NULL ) throw SvnException( error ); #if !defined( PYSVN_HAS_CLIENT_PROPLIST3 ) proplistToObject( list_of_proplists, props, pool ); #endif } catch( SvnException &e ) { // use callback error over ClientException m_context.checkForError( m_module.client_error ); throw_client_error( e ); } } return list_of_proplists; }
Py::Object pysvn_client::cmd_add_to_changelist( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_path }, { true, name_changelist }, { false, name_depth }, { false, name_changelists }, { false, NULL } }; FunctionArguments args( "add_to_changelist", args_desc, a_args, a_kws ); args.check(); std::string type_error_message; SvnPool pool( m_context ); try { apr_array_header_t *targets = targetsFromStringOrList( args.getArg( name_path ), pool ); std::string changelist( args.getUtf8String( name_changelist ) ); apr_array_header_t *changelists = NULL; if( args.hasArg( name_changelists ) ) { changelists = arrayOfStringsFromListOfStrings( args.getArg( name_changelists ), pool ); } svn_depth_t depth = args.getDepth( name_depth, svn_depth_files ); try { checkThreadPermission(); PythonAllowThreads permission( m_context ); svn_error_t *error = svn_client_add_to_changelist ( targets, changelist.c_str(), depth, changelists, m_context, pool ); 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 ); } } catch( Py::TypeError & ) { throw Py::TypeError( type_error_message ); } return Py::None(); }
Py::Object pysvn_client::cmd_move2( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_sources }, { true, name_dest_url_or_path }, { false, name_force }, { false, name_move_as_child }, { false, name_make_parents }, { false, name_revprops }, { false, NULL } }; FunctionArguments args( "move2", args_desc, a_args, a_kws ); args.check(); SvnPool pool( m_context ); pysvn_commit_info_t *commit_info = NULL; std::string type_error_message; try { type_error_message = "expecting list for sources (arg 1)"; Py::List list_all_sources = args.getArg( name_sources ); apr_array_header_t *all_sources = apr_array_make( pool, list_all_sources.length(), sizeof(const char *) ); for( unsigned int index=0; index<list_all_sources.length(); index++ ) { type_error_message = "expecting string in sources list"; Py::String py_src_url_or_path( list_all_sources[ index ] ); std::string src_url_or_path; if( py_src_url_or_path.isUnicode() ) { Py::String utf8( py_src_url_or_path.encode( name_utf8 ) ); src_url_or_path = py_src_url_or_path.as_std_string(); } else { src_url_or_path = py_src_url_or_path.as_std_string(); } std::string norm_src_url_or_path( svnNormalisedIfPath( src_url_or_path, pool ) ); const char *src_path_copy = apr_pstrdup( pool, norm_src_url_or_path.c_str() ); APR_ARRAY_PUSH( all_sources, const char *) = src_path_copy; } type_error_message = "expecting string for dest_url_or_path"; Py::String dest_path( args.getUtf8String( name_dest_url_or_path ) ); type_error_message = "expecting boolean for keyword force"; bool force = args.getBoolean( name_force, false ); type_error_message = "expecting boolean for keyword move_as_child"; bool move_as_child = args.getBoolean( name_move_as_child, false ); type_error_message = "expecting boolean for keyword make_parents"; bool make_parents = args.getBoolean( name_make_parents, false ); apr_hash_t *revprops = NULL; if( args.hasArg( name_revprops ) ) { Py::Object py_revprop = args.getArg( name_revprops ); if( !py_revprop.isNone() ) { revprops = hashOfStringsFromDistOfStrings( py_revprop, pool ); } } try { std::string norm_dest_path( svnNormalisedIfPath( dest_path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); // behavior changed svn_error_t *error = svn_client_move5 ( &commit_info, all_sources, norm_dest_path.c_str(), force, move_as_child, make_parents, revprops, m_context, pool ); 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 ); } } catch( Py::TypeError & ) { throw Py::TypeError( type_error_message ); } return toObject( commit_info ); }
Py::Object pysvn_client::cmd_move( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_src_url_or_path }, { true, name_dest_url_or_path }, { false, name_force }, { false, NULL } }; FunctionArguments args( "move", args_desc, a_args, a_kws ); args.check(); SvnPool pool( m_context ); pysvn_commit_info_t *commit_info = NULL; std::string type_error_message; try { type_error_message = "expecting string for src_url_or_path (arg 1)"; Py::String src_path( args.getUtf8String( name_src_url_or_path ) ); type_error_message = "expecting string for dest_url_or_path (arg 2)"; Py::String dest_path( args.getUtf8String( name_dest_url_or_path ) ); #ifndef PYSVN_HAS_CLIENT_MOVE2 svn_opt_revision_t revision; revision.kind = svn_opt_revision_head; #endif type_error_message = "expecting boolean for keyword force"; bool force = args.getBoolean( name_force, false ); try { std::string norm_src_path( svnNormalisedIfPath( src_path, pool ) ); std::string norm_dest_path( svnNormalisedIfPath( dest_path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); #if defined( PYSVN_HAS_CLIENT_MOVE4 ) // behavior changed svn_error_t *error = svn_client_move4 ( &commit_info, norm_src_path.c_str(), norm_dest_path.c_str(), force, m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_MOVE3 ) svn_error_t *error = svn_client_move3 ( &commit_info, // changed type norm_src_path.c_str(), norm_dest_path.c_str(), force, m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_MOVE2 ) svn_error_t *error = svn_client_move2 ( &commit_info, norm_src_path.c_str(), norm_dest_path.c_str(), force, m_context, pool ); #else svn_error_t *error = svn_client_move ( &commit_info, norm_src_path.c_str(), &revision, norm_dest_path.c_str(), 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 ); } } catch( Py::TypeError & ) { throw Py::TypeError( type_error_message ); } return toObject( commit_info ); }
Py::Object pysvn_client::cmd_copy2( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_sources }, { true, name_dest_url_or_path }, { false, name_copy_as_child }, { false, name_make_parents }, { false, name_revprops }, { false, NULL } }; FunctionArguments args( "copy2", args_desc, a_args, a_kws ); args.check(); SvnPool pool( m_context ); pysvn_commit_info_t *commit_info = NULL; std::string type_error_message; try { type_error_message = "expecting list for sources (arg 1)"; Py::List list_all_sources = args.getArg( name_sources ); apr_array_header_t *all_sources = apr_array_make( pool, list_all_sources.length(), sizeof(svn_client_copy_source_t *) ); for( unsigned int index=0; index<list_all_sources.length(); index++ ) { Py::Tuple tuple_src_rev_pegrev( list_all_sources[ index ] ); std::string src_url_or_path; svn_opt_revision_t *revision = reinterpret_cast<svn_opt_revision_t *>( apr_palloc( pool, sizeof( svn_opt_revision_t ) ) ); svn_opt_revision_t *peg_revision = reinterpret_cast<svn_opt_revision_t *>( apr_palloc( pool, sizeof( svn_opt_revision_t ) ) ); if( tuple_src_rev_pegrev.length() > 3 ) { std::string msg = "copy2() expecting tuple with 2 or 3 values in sources list"; throw Py::AttributeError( msg ); } type_error_message = "expecting string for 1st tuple value in sources list"; Py::String py_src_url_or_path( tuple_src_rev_pegrev[0] ); if( py_src_url_or_path.isUnicode() ) { Py::String utf8( py_src_url_or_path.encode( name_utf8 ) ); src_url_or_path = py_src_url_or_path.as_std_string(); } else { src_url_or_path = py_src_url_or_path.as_std_string(); } std::string norm_src_url_or_path( svnNormalisedIfPath( src_url_or_path, pool ) ); bool is_url = is_svn_url( norm_src_url_or_path ); if( tuple_src_rev_pegrev.length() >= 2 ) { Py::Object obj( tuple_src_rev_pegrev[1] ); if( pysvn_revision::check( obj ) ) { pysvn_revision *rev = static_cast<pysvn_revision *>( obj.ptr() ); *revision = rev->getSvnRevision(); revisionKindCompatibleCheck( is_url, *revision, "sources list 2nd tuple value", "sources list 1st tuple value" ); } else { std::string msg = "copy2() expecting revision for 2nd tuple value in sources list"; throw Py::AttributeError( msg ); } } else { if( is_url ) { revision->kind = svn_opt_revision_head; } else { revision->kind = svn_opt_revision_working; } } if( tuple_src_rev_pegrev.length() >= 3 ) { Py::Object obj( tuple_src_rev_pegrev[2] ); if( pysvn_revision::check( obj ) ) { pysvn_revision *rev = static_cast<pysvn_revision *>( obj.ptr() ); *peg_revision = rev->getSvnRevision(); revisionKindCompatibleCheck( is_url, *peg_revision, "sources list 2nd tuple value", "sources list 1st tuple value" ); } else { std::string msg = "copy2() expecting revision for 3rd tuple value in sources list"; throw Py::AttributeError( msg ); } } else { *peg_revision = *revision; } svn_client_copy_source_t *source = reinterpret_cast<svn_client_copy_source_t *>( apr_palloc( pool, sizeof(*source) ) ); source->path = apr_pstrdup( pool, norm_src_url_or_path.c_str() ); source->revision = revision; source->peg_revision = peg_revision; APR_ARRAY_PUSH( all_sources, svn_client_copy_source_t *) = source; } type_error_message = "expecting string for dest_url_or_path"; Py::String dest_path( args.getUtf8String( name_dest_url_or_path ) ); type_error_message = "expecting boolean for keyword copy_as_child"; bool copy_as_child = args.getBoolean( name_copy_as_child, false ); type_error_message = "expecting boolean for keyword make_parents"; bool make_parents = args.getBoolean( name_make_parents, false ); apr_hash_t *revprops = NULL; if( args.hasArg( name_revprops ) ) { Py::Object py_revprop = args.getArg( name_revprops ); if( !py_revprop.isNone() ) { revprops = hashOfStringsFromDistOfStrings( py_revprop, pool ); } } try { std::string norm_dest_path( svnNormalisedIfPath( dest_path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); // behavior changed svn_error_t *error = svn_client_copy4 ( &commit_info, all_sources, norm_dest_path.c_str(), copy_as_child, make_parents, revprops, m_context, pool ); 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 ); } } catch( Py::TypeError & ) { throw Py::TypeError( type_error_message ); } return toObject( commit_info ); }
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 ) ); }
Py::Object pysvn_client::cmd_ls( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_url_or_path }, { false, name_revision }, { false, name_recurse }, #if defined( PYSVN_HAS_CLIENT_LS2 ) { false, name_peg_revision }, #endif { false, NULL } }; FunctionArguments args( "ls", args_desc, a_args, a_kws ); args.check(); std::string path( args.getUtf8String( name_url_or_path ) ); bool recurse = args.getBoolean( name_recurse, false ); svn_opt_revision_t revision = args.getRevision( name_revision, svn_opt_revision_head ); SvnPool pool( m_context ); apr_hash_t *hash = NULL; std::string norm_path( svnNormalisedIfPath( path, pool ) ); #if defined( PYSVN_HAS_CLIENT_LS2 ) svn_opt_revision_t peg_revision = args.getRevision( name_peg_revision, revision ); #endif bool is_url = is_svn_url( path ); #if defined( PYSVN_HAS_CLIENT_LS2 ) revisionKindCompatibleCheck( is_url, peg_revision, name_peg_revision, name_url_or_path ); #endif revisionKindCompatibleCheck( is_url, revision, name_revision, name_url_or_path ); try { checkThreadPermission(); PythonAllowThreads permission( m_context ); #if defined( PYSVN_HAS_CLIENT_LS2 ) svn_error_t *error = svn_client_ls2 ( &hash, norm_path.c_str(), &peg_revision, &revision, recurse, m_context, pool ); #else svn_error_t *error = svn_client_ls ( &hash, norm_path.c_str(), &revision, recurse, m_context, pool ); #endif permission.allowThisThread(); if( error != 0 ) throw SvnException( error ); } catch( SvnException &e ) { // use callback error over ClientException m_context.checkForError( m_module.client_error ); throw_client_error( e ); } apr_array_header_t *array = svn_sort__hash( hash, compare_items_as_paths, pool ); std::string base_path; if( !norm_path.empty() ) { base_path = norm_path; base_path += '/'; } // convert the entries into python objects Py::List entries_list; for( int i = 0; i < array->nelts; ++i ) { svn_sort__item_t *item = &APR_ARRAY_IDX( array, i, svn_sort__item_t ); const char *utf8_entryname = static_cast<const char *>( item->key ); svn_dirent_t *dirent = static_cast<svn_dirent_t *>( apr_hash_get( hash, utf8_entryname, item->klen ) ); std::string full_name( base_path ); full_name += utf8_entryname; Py::Dict entry_dict; entry_dict[ *py_name_name ] = Py::String( full_name, name_utf8 ); entry_dict[ *py_name_kind ] = toEnumValue( dirent->kind ); entry_dict[ *py_name_has_props ] = Py::Int( dirent->has_props ); entry_dict[ *py_name_size ] = Py::Long( Py::Float( double( static_cast<signed_int64>( dirent->size ) ) ) ); entry_dict[ *py_name_created_rev ] = Py::asObject( new pysvn_revision( svn_opt_revision_number, 0, dirent->created_rev ) ); entry_dict[ *py_name_time ] = toObject( dirent->time ); entry_dict[ *py_name_last_author ] = utf8_string_or_none( dirent->last_author ); entries_list.append( m_wrapper_dirent.wrapDict( entry_dict ) ); } return entries_list; }
Py::Object pysvn_client::cmd_propset( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_prop_name }, { true, name_prop_value }, { true, name_url_or_path }, { false, name_revision }, { false, name_recurse }, #if defined( PYSVN_HAS_CLIENT_PROPSET2 ) { false, name_skip_checks }, #endif #if defined( PYSVN_HAS_CLIENT_PROPSET3 ) { false, name_depth }, { false, name_base_revision_for_url }, { false, name_changelists }, { false, name_revprops }, #endif { false, NULL } }; FunctionArguments args( "propset", args_desc, a_args, a_kws ); args.check(); std::string propname( args.getUtf8String( name_prop_name ) ); std::string propval( args.getUtf8String( name_prop_value ) ); std::string path( args.getUtf8String( name_url_or_path ) ); svn_opt_revision_t revision; if( is_svn_url( path ) ) revision = args.getRevision( name_revision, svn_opt_revision_head ); else revision = args.getRevision( name_revision, svn_opt_revision_working ); SvnPool pool( m_context ); #if defined( PYSVN_HAS_CLIENT_PROPSET3 ) apr_array_header_t *changelists = NULL; if( args.hasArg( name_changelists ) ) { changelists = arrayOfStringsFromListOfStrings( args.getArg( name_changelists ), pool ); } svn_revnum_t base_revision_for_url = args.getInteger( name_base_revision_for_url, 0 ); svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_files, svn_depth_empty ); apr_hash_t *revprops = NULL; if( args.hasArg( name_revprops ) ) { Py::Object py_revprop = args.getArg( name_revprops ); if( !py_revprop.isNone() ) { revprops = hashOfStringsFromDistOfStrings( py_revprop, pool ); } } #else bool recurse = args.getBoolean( name_recurse, false ); #endif #if defined( PYSVN_HAS_CLIENT_PROPSET2 ) bool skip_checks = args.getBoolean( name_skip_checks, false ); #endif #if defined( PYSVN_HAS_CLIENT_PROPSET3 ) pysvn_commit_info_t *commit_info = NULL; #endif try { std::string norm_path( svnNormalisedIfPath( path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); const svn_string_t *svn_propval = svn_string_ncreate( propval.c_str(), propval.size(), pool ); #if defined( PYSVN_HAS_CLIENT_PROPSET3 ) svn_error_t *error = svn_client_propset3 ( &commit_info, propname.c_str(), svn_propval, norm_path.c_str(), depth, skip_checks, base_revision_for_url, changelists, revprops, m_context.ctx(), pool ); #elif defined( PYSVN_HAS_CLIENT_PROPSET2 ) svn_error_t *error = svn_client_propset2 ( propname.c_str(), svn_propval, norm_path.c_str(), recurse, skip_checks, m_context.ctx(), pool ); #else svn_error_t *error = svn_client_propset ( propname.c_str(), svn_propval, norm_path.c_str(), recurse, 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 ); } #if defined( PYSVN_HAS_CLIENT_PROPSET3 ) return toObject( commit_info ); #else return Py::None(); #endif }
Py::Object pysvn_client::cmd_annotate( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_url_or_path }, { false, name_revision_start }, { false, name_revision_end }, #if defined( PYSVN_HAS_CLIENT_ANNOTATE2 ) { false, name_peg_revision }, #endif #if defined( PYSVN_HAS_CLIENT_ANNOTATE3 ) { false, name_ignore_space }, { false, name_ignore_eol_style }, { false, name_ignore_mime_type }, #endif #if defined( PYSVN_HAS_CLIENT_ANNOTATE4 ) { false, name_include_merged_revisions }, #endif { false, NULL } }; FunctionArguments args( "annotate", args_desc, a_args, a_kws ); args.check(); std::string path( args.getUtf8String( name_url_or_path, empty_string ) ); svn_opt_revision_t revision_start = args.getRevision( name_revision_start, svn_opt_revision_number ); svn_opt_revision_t revision_end = args.getRevision( name_revision_end, svn_opt_revision_head ); #if defined( PYSVN_HAS_CLIENT_ANNOTATE2 ) svn_opt_revision_t peg_revision = args.getRevision( name_peg_revision, revision_end ); #endif #if defined( PYSVN_HAS_CLIENT_ANNOTATE3 ) svn_diff_file_ignore_space_t ignore_space = svn_diff_file_ignore_space_none; if( args.hasArg( name_ignore_space ) ) { Py::ExtensionObject< pysvn_enum_value<svn_diff_file_ignore_space_t> > py_ignore_space( args.getArg( name_ignore_space ) ); ignore_space = svn_diff_file_ignore_space_t( py_ignore_space.extensionObject()->m_value ); } svn_boolean_t ignore_eol_style = args.getBoolean( name_ignore_eol_style, false ); svn_boolean_t ignore_mime_type = args.getBoolean( name_ignore_mime_type, false ); #endif #if defined( PYSVN_HAS_CLIENT_ANNOTATE4 ) svn_boolean_t include_merged_revisions = args.getBoolean( name_include_merged_revisions, false ); #endif SvnPool pool( m_context ); #if defined( PYSVN_HAS_CLIENT_ANNOTATE3 ) svn_diff_file_options_t *diff_options = svn_diff_file_options_create( pool ); diff_options->ignore_space = ignore_space; diff_options->ignore_eol_style = ignore_eol_style; #endif bool is_url = is_svn_url( path ); #if defined( PYSVN_HAS_CLIENT_ANNOTATE2 ) revisionKindCompatibleCheck( is_url, peg_revision, name_peg_revision, name_url_or_path ); #endif revisionKindCompatibleCheck( is_url, revision_start, name_revision_start, name_url_or_path ); revisionKindCompatibleCheck( is_url, revision_end, name_revision_end, name_url_or_path ); std::list<AnnotatedLineInfo> all_entries; try { std::string norm_path( svnNormalisedIfPath( path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); #if defined( PYSVN_HAS_CLIENT_ANNOTATE4 ) svn_error_t *error = svn_client_blame4 ( norm_path.c_str(), &peg_revision, &revision_start, &revision_end, diff_options, ignore_mime_type, include_merged_revisions, annotate_receiver, &all_entries, m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_ANNOTATE3 ) svn_error_t *error = svn_client_blame3 ( norm_path.c_str(), &peg_revision, &revision_start, &revision_end, diff_options, ignore_mime_type, annotate_receiver, &all_entries, m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_ANNOTATE2 ) svn_error_t *error = svn_client_blame2 ( norm_path.c_str(), &peg_revision, &revision_start, &revision_end, annotate_receiver, &all_entries, m_context, pool ); #else svn_error_t *error = svn_client_blame ( norm_path.c_str(), &revision_start, &revision_end, annotate_receiver, &all_entries, 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 ); } // convert the entries into python objects Py::List entries_list; std::list<AnnotatedLineInfo>::const_iterator entry_it = all_entries.begin(); while( entry_it != all_entries.end() ) { const AnnotatedLineInfo &entry = *entry_it; ++entry_it; Py::Dict entry_dict; entry_dict[name_author] = Py::String( entry.m_author, name_utf8 ); entry_dict[name_date] = Py::String( entry.m_date ); entry_dict[name_line] = Py::String( entry.m_line ); entry_dict[name_number] = Py::Int( long( entry.m_line_no ) ); entry_dict[name_revision] = Py::asObject( new pysvn_revision( svn_opt_revision_number, 0, entry.m_revision ) ); entries_list.append( entry_dict ); } return entries_list; }
Py::Object pysvn_client::cmd_status( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_path }, { false, name_recurse }, { false, name_get_all }, { false, name_update }, { false, name_ignore }, #if defined( PYSVN_HAS_CLIENT_STATUS2 ) { false, name_ignore_externals }, #endif #if defined( PYSVN_HAS_CLIENT_STATUS3 ) { false, name_depth }, { false, name_changelists }, #endif { false, NULL } }; FunctionArguments args( "status", args_desc, a_args, a_kws ); args.check(); Py::String path( args.getUtf8String( name_path ) ); SvnPool pool( m_context ); #if defined( PYSVN_HAS_CLIENT_STATUS3 ) apr_array_header_t *changelists = NULL; if( args.hasArg( name_changelists ) ) { changelists = arrayOfStringsFromListOfStrings( args.getArg( name_changelists ), pool ); } svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_infinity, svn_depth_infinity, svn_depth_immediates ); #else bool recurse = args.getBoolean( name_recurse, true ); #endif bool get_all = args.getBoolean( name_get_all, true ); bool update = args.getBoolean( name_update, false ); bool ignore = args.getBoolean( name_ignore, false ); #if defined( PYSVN_HAS_CLIENT_STATUS2 ) bool ignore_externals = args.getBoolean( name_ignore_externals, false ); #endif apr_hash_t *status_hash = NULL; Py::List entries_list; try { std::string norm_path( svnNormalisedIfPath( path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); svn_revnum_t revnum; svn_opt_revision_t rev = { svn_opt_revision_head, {0} }; StatusEntriesBaton baton; status_hash = apr_hash_make( pool ); baton.hash = status_hash; baton.pool = pool; #if defined( PYSVN_HAS_CLIENT_STATUS4 ) svn_error_t *error = svn_client_status4 ( &revnum, // revnum norm_path.c_str(), // path &rev, StatusEntriesFunc, // status func &baton, // status baton depth, get_all, update, !ignore, ignore_externals, changelists, m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_STATUS3 ) svn_error_t *error = svn_client_status3 ( &revnum, // revnum norm_path.c_str(), // path &rev, StatusEntriesFunc, // status func &baton, // status baton depth, get_all, update, !ignore, ignore_externals, changelists, m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_STATUS2 ) svn_error_t *error = svn_client_status2 ( &revnum, // revnum norm_path.c_str(), // path &rev, StatusEntriesFunc, // status func &baton, // status baton recurse, get_all, update, !ignore, ignore_externals, m_context, pool ); #else svn_error_t *error = svn_client_status ( &revnum, // revnum norm_path.c_str(), // path &rev, StatusEntriesFunc, // status func &baton, // status baton recurse, get_all, update, !ignore, 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 ); } apr_array_header_t *statusarray = svn_sort__hash( status_hash, svn_sort_compare_items_as_paths, pool ); // Loop over array, printing each name/status-structure for (int i = statusarray->nelts-1; i >= 0; i--) { const svn_sort__item_t *item = &APR_ARRAY_IDX( statusarray, i, const svn_sort__item_t ); pysvn_wc_status_t *status = (pysvn_wc_status_t *)item->value; entries_list.append( toObject( Py::String( osNormalisedPath( (const char *)item->key, pool ), "UTF-8" ), *status, pool, m_wrapper_status, m_wrapper_entry, m_wrapper_lock ) ); } return entries_list; }
Py::Object pysvn_client::cmd_diff_summarize_peg( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_url_or_path }, { false, name_peg_revision }, { false, name_revision_start }, { false, name_revision_end }, { false, name_recurse }, { false, name_ignore_ancestry }, #if defined( PYSVN_HAS_CLIENT_DIFF_SUMMARIZE_PEG2 ) { false, name_depth }, { false, name_changelists }, #endif { false, NULL } }; FunctionArguments args( "diff_summarize_peg", args_desc, a_args, a_kws ); args.check(); std::string path( args.getUtf8String( name_url_or_path ) ); svn_opt_revision_t revision_start = args.getRevision( name_revision_start, svn_opt_revision_base ); svn_opt_revision_t revision_end = args.getRevision( name_revision_end, svn_opt_revision_working ); svn_opt_revision_t peg_revision = args.getRevision( name_peg_revision, revision_end ); SvnPool pool( m_context ); #if defined( PYSVN_HAS_CLIENT_DIFF_SUMMARIZE_PEG2 ) svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_infinity, svn_depth_infinity, svn_depth_files ); apr_array_header_t *changelists = NULL; if( args.hasArg( name_changelists ) ) { changelists = arrayOfStringsFromListOfStrings( args.getArg( name_changelists ), pool ); } #else bool recurse = args.getBoolean( name_recurse, true ); #endif bool ignore_ancestry = args.getBoolean( name_ignore_ancestry, true ); bool is_url = is_svn_url( path ); revisionKindCompatibleCheck( is_url, peg_revision, name_peg_revision, name_url_or_path ); revisionKindCompatibleCheck( is_url, revision_start, name_revision_start, name_url_or_path ); revisionKindCompatibleCheck( is_url, revision_end, name_revision_end, name_url_or_path ); Py::List diff_list; try { std::string norm_path( svnNormalisedIfPath( path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); DiffSummarizeBaton diff_baton( &permission, diff_list ); diff_baton.m_wrapper_diff_summary = &m_wrapper_diff_summary; #if defined( PYSVN_HAS_CLIENT_DIFF_SUMMARIZE_PEG2 ) svn_error_t *error = svn_client_diff_summarize_peg2 ( norm_path.c_str(), &peg_revision, &revision_start, &revision_end, depth, ignore_ancestry, changelists, diff_summarize_c, reinterpret_cast<void *>( &diff_baton ), m_context, pool ); #else svn_error_t *error = svn_client_diff_summarize_peg ( norm_path.c_str(), &peg_revision, &revision_start, &revision_end, recurse, ignore_ancestry, diff_summarize_c, reinterpret_cast<void *>( &diff_baton ), 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 ); } // cannot convert to Unicode as we have no idea of the encoding of the bytes return diff_list; }
Py::Object pysvn_client::cmd_diff_peg( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_tmp_path }, { true, name_url_or_path }, { false, name_peg_revision }, { false, name_revision_start }, { false, name_revision_end }, { false, name_recurse }, { false, name_ignore_ancestry }, { false, name_diff_deleted }, #if defined( PYSVN_HAS_CLIENT_DIFF_PEG2 ) { false, name_ignore_content_type }, #endif #if defined( PYSVN_HAS_CLIENT_DIFF_PEG3 ) { false, name_header_encoding }, { false, name_diff_options }, #endif #if defined( PYSVN_HAS_CLIENT_DIFF_PEG4 ) { false, name_depth }, { false, name_relative_to_dir }, { false, name_changelists }, #endif { false, NULL } }; FunctionArguments args( "diff_peg", args_desc, a_args, a_kws ); args.check(); std::string tmp_path( args.getUtf8String( name_tmp_path ) ); std::string path( args.getUtf8String( name_url_or_path ) ); svn_opt_revision_t revision_start = args.getRevision( name_revision_start, svn_opt_revision_base ); svn_opt_revision_t revision_end = args.getRevision( name_revision_end, svn_opt_revision_working ); svn_opt_revision_t peg_revision = args.getRevision( name_peg_revision, revision_end ); SvnPool pool( m_context ); #if defined( PYSVN_HAS_CLIENT_DIFF_PEG4 ) svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_infinity, svn_depth_infinity, svn_depth_files ); std::string std_relative_to_dir; const char *relative_to_dir = NULL; if( args.hasArg( name_relative_to_dir ) ) { std_relative_to_dir = args.getBytes( name_relative_to_dir ); relative_to_dir = std_relative_to_dir.c_str(); } apr_array_header_t *changelists = NULL; if( args.hasArg( name_changelists ) ) { changelists = arrayOfStringsFromListOfStrings( args.getArg( name_changelists ), pool ); } #else bool recurse = args.getBoolean( name_recurse, true ); #endif bool ignore_ancestry = args.getBoolean( name_ignore_ancestry, true ); bool diff_deleted = args.getBoolean( name_diff_deleted, true ); #if defined( PYSVN_HAS_CLIENT_DIFF_PEG2 ) bool ignore_content_type = args.getBoolean( name_ignore_content_type, false ); #endif #if defined( PYSVN_HAS_CLIENT_DIFF_PEG3 ) std::string header_encoding( args.getUtf8String( name_header_encoding, empty_string ) ); const char *header_encoding_ptr = APR_LOCALE_CHARSET; if( !header_encoding.empty() ) header_encoding_ptr = header_encoding.c_str(); apr_array_header_t *options = NULL; if( args.hasArg( name_diff_options ) ) { options = arrayOfStringsFromListOfStrings( args.getArg( name_diff_options ), pool ); } else { options = apr_array_make( pool, 0, sizeof( const char * ) ); } #else apr_array_header_t *options = apr_array_make( pool, 0, sizeof( const char * ) ); #endif bool is_url = is_svn_url( path ); revisionKindCompatibleCheck( is_url, peg_revision, name_peg_revision, name_url_or_path ); revisionKindCompatibleCheck( is_url, revision_start, name_revision_start, name_url_or_path ); revisionKindCompatibleCheck( is_url, revision_end, name_revision_end, name_url_or_path ); svn_stringbuf_t *stringbuf = NULL; try { std::string norm_tmp_path( svnNormalisedIfPath( tmp_path, pool ) ); std::string norm_path( svnNormalisedIfPath( path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); pysvn_apr_file output_file( pool ); pysvn_apr_file error_file( pool ); output_file.open_unique_file( norm_tmp_path ); error_file.open_unique_file( norm_tmp_path ); // std::cout << "peg_revision " << peg_revision.kind << " " << peg_revision.value.number << std::endl; // std::cout << "revision_start " << revision_start.kind << " " << revision_start.value.number << std::endl; // std::cout << "revision_end " << revision_end.kind << " " << revision_end.value.number << std::endl; #if defined( PYSVN_HAS_CLIENT_DIFF_PEG4 ) svn_error_t *error = svn_client_diff_peg4 ( options, norm_path.c_str(), &peg_revision, &revision_start, &revision_end, relative_to_dir, depth, ignore_ancestry, !diff_deleted, ignore_content_type, header_encoding_ptr, output_file.file(), error_file.file(), changelists, m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_DIFF_PEG3 ) svn_error_t *error = svn_client_diff_peg3 ( options, norm_path.c_str(), &peg_revision, &revision_start, &revision_end, recurse, ignore_ancestry, !diff_deleted, ignore_content_type, header_encoding_ptr, output_file.file(), error_file.file(), m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_DIFF_PEG2 ) svn_error_t *error = svn_client_diff_peg2 ( options, norm_path.c_str(), &peg_revision, &revision_start, &revision_end, recurse, ignore_ancestry, !diff_deleted, ignore_content_type, output_file.file(), error_file.file(), m_context, pool ); #else svn_error_t *error = svn_client_diff_peg ( options, norm_path.c_str(), &peg_revision, &revision_start, &revision_end, recurse, ignore_ancestry, !diff_deleted, output_file.file(), error_file.file(), m_context, pool ); #endif permission.allowThisThread(); if( error != NULL ) throw SvnException( error ); output_file.close(); output_file.open_tmp_file(); error = svn_stringbuf_from_aprfile( &stringbuf, output_file.file(), pool ); 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 ); } // cannot convert to Unicode as we have no idea of the encoding of the bytes return Py::String( stringbuf->data, (int)stringbuf->len ); }
Py::Object pysvn_client::cmd_import( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_path }, { true, name_url }, { true, name_log_message }, { false, name_recurse }, #if defined( PYSVN_HAS_CLIENT_IMPORT2 ) { false, name_ignore }, #endif #if defined( PYSVN_HAS_CLIENT_IMPORT3 ) { false, name_depth }, { false, name_ignore_unknown_node_types }, { false, name_revprops }, #endif { false, NULL } }; FunctionArguments args( "import_", args_desc, a_args, a_kws ); args.check(); std::string path( args.getUtf8String( name_path ) ); std::string url( args.getUtf8String( name_url ) ); std::string message( args.getUtf8String( name_log_message ) ); SvnPool pool( m_context ); #if defined( PYSVN_HAS_CLIENT_IMPORT3 ) svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_infinity, svn_depth_infinity, svn_depth_files ); bool ignore_unknown_node_types = args.getBoolean( name_ignore_unknown_node_types, false ); apr_hash_t *revprops = NULL; if( args.hasArg( name_revprops ) ) { Py::Object py_revprop = args.getArg( name_revprops ); if( !py_revprop.isNone() ) { revprops = hashOfStringsFromDistOfStrings( py_revprop, pool ); } } #else bool recurse = args.getBoolean( name_recurse, true ); #endif #if defined( PYSVN_HAS_CLIENT_IMPORT2 ) bool ignore = args.getBoolean( name_ignore, false ); #endif pysvn_commit_info_t *commit_info = NULL; try { std::string norm_path( svnNormalisedIfPath( path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); m_context.setLogMessage( message.c_str() ); #if defined( PYSVN_HAS_CLIENT_IMPORT3 ) svn_error_t *error = svn_client_import3 ( &commit_info, // changed type norm_path.c_str(), url.c_str(), depth, !ignore, ignore_unknown_node_types, revprops, m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_IMPORT2 ) svn_error_t *error = svn_client_import2 ( &commit_info, // changed type norm_path.c_str(), url.c_str(), !recurse, // non_recursive !ignore, m_context, pool ); #else svn_error_t *error = svn_client_import ( &commit_info, norm_path.c_str(), url.c_str(), !recurse, // non_recursive 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 toObject( commit_info, m_commit_info_style ); }
Py::Object pysvn_client::cmd_info2( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_url_or_path }, { false, name_revision }, { false, name_peg_revision}, { false, name_recurse }, #if defined( PYSVN_HAS_CLIENT_INFO2 ) { false, name_depth }, { false, name_changelists }, #endif { false, NULL } }; FunctionArguments args( "info2", args_desc, a_args, a_kws ); args.check(); std::string path( args.getUtf8String( name_url_or_path ) ); svn_opt_revision_kind kind = svn_opt_revision_unspecified; if( is_svn_url( path ) ) kind = svn_opt_revision_head; svn_opt_revision_t revision = args.getRevision( name_revision, kind ); svn_opt_revision_t peg_revision = args.getRevision( name_peg_revision, revision ); SvnPool pool( m_context ); #if defined( PYSVN_HAS_CLIENT_INFO2 ) apr_array_header_t *changelists = NULL; if( args.hasArg( name_changelists ) ) { changelists = arrayOfStringsFromListOfStrings( args.getArg( name_changelists ), pool ); } svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_infinity, svn_depth_infinity, svn_depth_empty ); #else bool recurse = args.getBoolean( name_recurse, true ); #endif bool is_url = is_svn_url( path ); revisionKindCompatibleCheck( is_url, peg_revision, name_peg_revision, name_url_or_path ); revisionKindCompatibleCheck( is_url, revision, name_revision, name_url_or_path ); Py::List info_list; try { std::string norm_path( svnNormalisedIfPath( path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); InfoReceiveBaton info_baton( &permission, info_list, m_wrapper_info, m_wrapper_lock, m_wrapper_wc_info ); #if defined( PYSVN_HAS_CLIENT_INFO2 ) svn_error_t *error = svn_client_info2 ( norm_path.c_str(), &peg_revision, &revision, info_receiver_c, reinterpret_cast<void *>( &info_baton ), depth, changelists, m_context, pool ); #else svn_error_t *error = svn_client_info ( norm_path.c_str(), &peg_revision, &revision, info_receiver_c, reinterpret_cast<void *>( &info_baton ), recurse, 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 info_list; }
Py::Object pysvn_client::cmd_list( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_url_or_path }, { false, name_peg_revision }, { false, name_revision }, { false, name_recurse }, { false, name_dirent_fields }, { false, name_fetch_locks }, #if defined( PYSVN_HAS_CLIENT_LIST2 ) { false, name_depth }, #endif { false, NULL } }; FunctionArguments args( "list", args_desc, a_args, a_kws ); args.check(); std::string path( args.getUtf8String( name_url_or_path ) ); svn_opt_revision_t peg_revision = args.getRevision( name_peg_revision, svn_opt_revision_unspecified ); bool is_url = is_svn_url( path ); 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_LIST2 ) svn_depth_t depth = args.getDepth( name_depth, name_recurse, svn_depth_immediates, svn_depth_infinity, svn_depth_immediates ); #else bool recurse = args.getBoolean( name_recurse, false ); #endif apr_uint32_t dirent_fields = args.getLong( name_dirent_fields, SVN_DIRENT_ALL ); bool fetch_locks = args.getBoolean( name_fetch_locks, false ); revisionKindCompatibleCheck( is_url, peg_revision, name_peg_revision, name_url_or_path ); revisionKindCompatibleCheck( is_url, revision, name_revision, name_url_or_path ); SvnPool pool( m_context ); std::string norm_path( svnNormalisedIfPath( path, pool ) ); Py::List list_list; try { checkThreadPermission(); PythonAllowThreads permission( m_context ); ListReceiveBaton list_baton( &permission, list_list ); list_baton.m_dirent_fields = dirent_fields; list_baton.m_is_url = is_url; list_baton.m_fetch_locks = fetch_locks; list_baton.m_url_or_path = norm_path; list_baton.m_wrapper_lock = &m_wrapper_lock; list_baton.m_wrapper_list = &m_wrapper_list; #if defined( PYSVN_HAS_CLIENT_LIST2 ) svn_error_t *error = svn_client_list2 ( norm_path.c_str(), &peg_revision, &revision, depth, dirent_fields, fetch_locks, list_receiver_c, reinterpret_cast<void *>( &list_baton ), m_context, pool ); #else svn_error_t *error = svn_client_list ( norm_path.c_str(), &peg_revision, &revision, recurse, dirent_fields, fetch_locks, list_receiver_c, reinterpret_cast<void *>( &list_baton ), m_context, pool ); #endif permission.allowThisThread(); if( error != 0 ) throw SvnException( error ); } catch( SvnException &e ) { // use callback error over ClientException m_context.checkForError( m_module.client_error ); throw_client_error( e ); } return list_list; }
// PYSVN_HAS_CLIENT_LOG4 version Py::Object pysvn_client::cmd_log( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_url_or_path }, { false, name_revision_start }, { false, name_revision_end }, { false, name_discover_changed_paths }, { false, name_strict_node_history }, { false, name_limit }, { false, name_peg_revision }, { false, name_include_merged_revisions }, { false, name_revprops }, { false, NULL } }; FunctionArguments args( "log", args_desc, a_args, a_kws ); args.check(); SvnPool pool( m_context ); svn_opt_revision_t revision_start = args.getRevision( name_revision_start, svn_opt_revision_head ); svn_opt_revision_t revision_end = args.getRevision( name_revision_end, svn_opt_revision_number ); bool discover_changed_paths = args.getBoolean( name_discover_changed_paths, false ); bool strict_node_history = args.getBoolean( name_strict_node_history, true ); int limit = args.getInteger( name_limit, 0 ); svn_opt_revision_t peg_revision = args.getRevision( name_peg_revision, svn_opt_revision_unspecified ); svn_boolean_t include_merged_revisions = args.getBoolean( name_include_merged_revisions, false ); apr_array_header_t *revprops = NULL; if( args.hasArg( name_revprops ) ) { Py::Object py_revprop = args.getArg( name_revprops ); if( !py_revprop.isNone() ) { revprops = arrayOfStringsFromListOfStrings( py_revprop, pool ); } } Py::Object url_or_path_obj = args.getArg( name_url_or_path ); Py::List url_or_path_list; if( url_or_path_obj.isList() ) { url_or_path_list = url_or_path_obj; } else { Py::List py_list; py_list.append( url_or_path_obj ); url_or_path_list = py_list; } for( size_t i=0; i<url_or_path_list.size(); i++ ) { Py::Bytes py_path( asUtf8Bytes( url_or_path_list[ i ] ) ); std::string path( py_path.as_std_string() ); bool is_url = is_svn_url( path ); revisionKindCompatibleCheck( is_url, peg_revision, name_peg_revision, name_url_or_path ); revisionKindCompatibleCheck( is_url, revision_start, name_revision_start, name_url_or_path ); revisionKindCompatibleCheck( is_url, revision_end, name_revision_end, name_url_or_path ); } apr_array_header_t *targets = targetsFromStringOrList( url_or_path_list, pool ); Py::List log_list; try { checkThreadPermission(); PythonAllowThreads permission( m_context ); Log4Baton baton( &permission, pool, log_list ); baton.m_wrapper_log = &m_wrapper_log; baton.m_wrapper_log_changed_path = &m_wrapper_log_changed_path; #if defined( PYSVN_HAS_CLIENT_LOG5 ) apr_array_header_t *revision_ranges = apr_array_make( pool, 0, sizeof(svn_opt_revision_range_t *) ); svn_opt_revision_range_t *range = reinterpret_cast<svn_opt_revision_range_t *>( apr_palloc( pool, sizeof(*range) ) ); range->start = revision_start; range->end = revision_end; APR_ARRAY_PUSH( revision_ranges, svn_opt_revision_range_t * ) = range; svn_error_t *error = svn_client_log5 ( targets, &peg_revision, revision_ranges, limit, discover_changed_paths, strict_node_history, include_merged_revisions, revprops, log4Receiver, reinterpret_cast<void *>( &baton ), m_context, pool ); #else svn_error_t *error = svn_client_log4 ( targets, &peg_revision, &revision_start, &revision_end, limit, discover_changed_paths, strict_node_history, include_merged_revisions, revprops, log4Receiver, reinterpret_cast<void *>( &baton ), 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 log_list; }
// PYSVN_HAS_CLIENT_LOG, PYSVN_HAS_CLIENT_LOG2, PYSVN_HAS_CLIENT_LOG3 version Py::Object pysvn_client::cmd_log( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_url_or_path }, { false, name_revision_start }, { false, name_revision_end }, { false, name_discover_changed_paths }, { false, name_strict_node_history }, #if defined( PYSVN_HAS_CLIENT_LOG2 ) || defined( PYSVN_HAS_CLIENT_LOG3 ) { false, name_limit }, #endif #if defined( PYSVN_HAS_CLIENT_LOG3 ) { false, name_peg_revision }, #endif #if defined( PYSVN_HAS_CLIENT_LOG4 ) { false, name_include_merged_revisions }, { false, name_revprops }, #endif { false, NULL } }; FunctionArguments args( "log", args_desc, a_args, a_kws ); args.check(); svn_opt_revision_t revision_start = args.getRevision( name_revision_start, svn_opt_revision_head ); svn_opt_revision_t revision_end = args.getRevision( name_revision_end, svn_opt_revision_number ); bool discover_changed_paths = args.getBoolean( name_discover_changed_paths, false ); bool strict_node_history = args.getBoolean( name_strict_node_history, true ); int limit = args.getInteger( name_limit, 0 ); #if defined( PYSVN_HAS_CLIENT_LOG3 ) svn_opt_revision_t peg_revision = args.getRevision( name_peg_revision, svn_opt_revision_unspecified ); #endif #if defined( PYSVN_HAS_CLIENT_LOG4 ) svn_boolean_t include_merged_revisions = args.getBoolean( name_include_merged_revisions, false ); apr_array_header_t *revprops = NULL; Py::Object py_revprop = args.getArg( name_revprops ); if( py_revprop is not None ) { revprops = arrayOfStringsFromListOfStrings( py_revprop. pool ); } #endif Py::Object url_or_path_obj = args.getArg( name_url_or_path ); Py::List url_or_path_list; if( url_or_path_obj.isList() ) { url_or_path_list = url_or_path_obj; } else { Py::List py_list; py_list.append( url_or_path_obj ); url_or_path_list = py_list; } for( size_t i=0; i<url_or_path_list.size(); i++ ) { Py::Bytes py_path( asUtf8Bytes( url_or_path_list[ i ] ) ); std::string path( py_path.as_std_string() ); bool is_url = is_svn_url( path ); // std::cout << "peg_revision " << peg_revision.kind << " " << peg_revision.value.number << std::endl; // std::cout << "revision_start " << revision_start.kind << " " << revision_start.value.number << std::endl; // std::cout << "revision_end " << revision_end.kind << " " << revision_end.value.number << std::endl; #if defined( PYSVN_HAS_CLIENT_LOG3 ) revisionKindCompatibleCheck( is_url, peg_revision, name_peg_revision, name_url_or_path ); #endif revisionKindCompatibleCheck( is_url, revision_start, name_revision_start, name_url_or_path ); revisionKindCompatibleCheck( is_url, revision_end, name_revision_end, name_url_or_path ); } SvnPool pool( m_context ); apr_array_header_t *targets = targetsFromStringOrList( url_or_path_list, pool ); #if defined( PYSVN_HAS_CLIENT_LOG4 ) Log4Baton baton( permission, pool ); #else std::list<LogEntryInfo> all_entries; #endif try { checkThreadPermission(); PythonAllowThreads permission( m_context ); #if defined( PYSVN_HAS_CLIENT_LOG4 ) svn_error_t *error = svn_client_log4 ( targets, &peg_revision, &revision_start, &revision_end, limit, discover_changed_paths, strict_node_history, include_merged_revisions, revprops, logReceiver, &all_entries, m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_LOG3 ) svn_error_t *error = svn_client_log3 ( targets, &peg_revision, &revision_start, &revision_end, limit, discover_changed_paths, strict_node_history, logReceiver, &all_entries, m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_LOG2 ) svn_error_t *error = svn_client_log2 ( targets, &revision_start, &revision_end, limit, discover_changed_paths, strict_node_history, logReceiver, &all_entries, m_context, pool ); #else svn_error_t *error = svn_client_log ( targets, &revision_start, &revision_end, discover_changed_paths, strict_node_history, logReceiver, &all_entries, 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 ); } apr_time_t now = apr_time_now(); // convert the entries into python objects Py::List entries_list; std::list<LogEntryInfo>::const_iterator entry_it = all_entries.begin(); while( entry_it != all_entries.end() ) { const LogEntryInfo &entry = *entry_it; ++entry_it; Py::Dict entry_dict; entry_dict[name_author] = Py::String( entry.m_author, name_utf8 ); entry_dict[name_date] = toObject( convertStringToTime( entry.m_date, now, pool ) ); entry_dict[name_message] = Py::String( entry.m_message, name_utf8 ); entry_dict[name_revision] = Py::asObject( new pysvn_revision( svn_opt_revision_number, 0, entry.m_revision ) ); Py::List changed_paths_list; std::list<LogChangePathInfo>::const_iterator changed_paths_it = entry.m_changed_paths.begin(); while( changed_paths_it != entry.m_changed_paths.end() ) { const LogChangePathInfo &change_entry = *changed_paths_it; ++changed_paths_it; Py::Dict changed_entry_dict; changed_entry_dict[name_path] = Py::String( change_entry.m_path, name_utf8 ); changed_entry_dict[name_action] = Py::String( &change_entry.m_action, 1 ); changed_entry_dict[name_copyfrom_path] = utf8_string_or_none( change_entry.m_copy_from_path ); if( SVN_IS_VALID_REVNUM( change_entry.m_copy_from_revision ) ) changed_entry_dict[name_copyfrom_revision] = Py::asObject( new pysvn_revision( svn_opt_revision_number, 0, change_entry.m_copy_from_revision ) ); else changed_entry_dict[name_copyfrom_revision] = Py::None(); changed_paths_list.append( m_wrapper_log_changed_path.wrapDict( changed_entry_dict ) ); } entry_dict[name_changed_paths] = changed_paths_list; entries_list.append( m_wrapper_log.wrapDict( entry_dict ) ); } return entries_list; }
Py::Object pysvn_client::cmd_get_changelist( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_path }, { false, name_depth }, { false, name_changelists }, { false, NULL } }; FunctionArguments args( "get_changelists", args_desc, a_args, a_kws ); args.check(); std::string type_error_message; SvnPool pool( m_context ); try { std::string path( args.getUtf8String( name_path ) ); std::string norm_path( svnNormalisedIfPath( path, pool ) ); apr_array_header_t *changelists = NULL; if( args.hasArg( name_changelists ) ) { changelists = arrayOfStringsFromListOfStrings( args.getArg( name_changelists ), pool ); //for (int j = 0; j < changelists->nelts; ++j) //{ // const char *name = ((const char **)changelists->elts)[j]; // std::cout << "QQQ: get changelist=" << name << std::endl; //} } svn_depth_t depth = args.getDepth( name_depth, svn_depth_files ); Py::List changelist_list; try { checkThreadPermission(); PythonAllowThreads permission( m_context ); ChangelistBaton baton( &permission, pool, changelist_list ); svn_error_t *error = svn_client_get_changelists ( norm_path.c_str(), changelists, depth, changelistReceiver, reinterpret_cast<void *>( &baton ), m_context, pool ); 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 changelist_list; } catch( Py::TypeError & ) { throw Py::TypeError( type_error_message ); } return Py::None(); }
Py::Object pysvn_client::cmd_revpropget( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_prop_name }, { true, name_url }, { false, name_revision }, { false, NULL } }; FunctionArguments args( "revpropget", args_desc, a_args, a_kws ); args.check(); std::string propname( args.getUtf8String( name_prop_name ) ); std::string path( args.getUtf8String( name_url ) ); svn_opt_revision_t revision = args.getRevision( name_revision, svn_opt_revision_head ); SvnPool pool( m_context ); svn_string_t *propval = NULL; svn_revnum_t revnum = 0; try { std::string norm_path( svnNormalisedIfPath( path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); svn_error_t * error = svn_client_revprop_get ( propname.c_str(), &propval, norm_path.c_str(), &revision, &revnum, m_context, pool ); 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 ); } Py::Tuple result(2); result[0] = Py::asObject( new pysvn_revision( svn_opt_revision_number, 0, revnum ) ); // prop_name that is not in this rev returns a NULL value if( propval == NULL ) { result[1] = Py::None(); } else { result[1] = Py::String( propval->data, propval->len, name_utf8 ); } return result; }
Py::Object pysvn_client::cmd_copy( const Py::Tuple &a_args, const Py::Dict &a_kws ) { static argument_description args_desc[] = { { true, name_src_url_or_path }, { true, name_dest_url_or_path }, { false, name_src_revision }, { false, NULL } }; FunctionArguments args( "copy", args_desc, a_args, a_kws ); args.check(); SvnPool pool( m_context ); pysvn_commit_info_t *commit_info = NULL; std::string type_error_message; try { type_error_message = "expecting string for src_path (arg 1)"; Py::String src_path( args.getUtf8String( name_src_url_or_path ) ); type_error_message = "expecting string for dest_path (arg 2)"; Py::String dest_path( args.getUtf8String( name_dest_url_or_path ) ); type_error_message = "expecting revision for keyword src_revision"; svn_opt_revision_t revision; if( is_svn_url( src_path ) ) revision = args.getRevision( name_src_revision, svn_opt_revision_head ); else revision = args.getRevision( name_src_revision, svn_opt_revision_working ); try { std::string norm_src_path( svnNormalisedIfPath( src_path, pool ) ); std::string norm_dest_path( svnNormalisedIfPath( dest_path, pool ) ); checkThreadPermission(); PythonAllowThreads permission( m_context ); #if defined( PYSVN_HAS_CLIENT_COPY3 ) // behavior changed svn_error_t *error = svn_client_copy3 ( &commit_info, norm_src_path.c_str(), &revision, norm_dest_path.c_str(), m_context, pool ); #elif defined( PYSVN_HAS_CLIENT_COPY2 ) svn_error_t *error = svn_client_copy2 ( &commit_info, // commit info type changed norm_src_path.c_str(), &revision, norm_dest_path.c_str(), m_context, pool ); #else svn_error_t *error = svn_client_copy ( &commit_info, norm_src_path.c_str(), &revision, norm_dest_path.c_str(), 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 ); } } catch( Py::TypeError & ) { throw Py::TypeError( type_error_message ); } return toObject( commit_info ); }