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; }
int main (int argc, const char **argv) { apr_pool_t *pool; svn_error_t *err; svn_opt_revision_t revision; apr_hash_t *dirents; apr_hash_index_t *hi; svn_client_ctx_t *ctx; const char *URL; if (argc <= 1) { printf ("Usage: %s URL\n", argv[0]); return EXIT_FAILURE; } else URL = argv[1]; /* Initialize the app. Send all error messages to 'stderr'. */ if (svn_cmdline_init ("minimal_client", stderr) != EXIT_SUCCESS) return EXIT_FAILURE; /* Create top-level memory pool. Be sure to read the HACKING file to understand how to properly use/free subpools. */ pool = svn_pool_create (NULL); /* Initialize the FS library. */ err = svn_fs_initialize (pool); if (err) { /* For functions deeper in the stack, we usually use the SVN_ERR() exception-throwing macro (see svn_error.h). At the top level, we catch & print the error with svn_handle_error2(). */ svn_handle_error2 (err, stderr, FALSE, "minimal_client: "); return EXIT_FAILURE; } /* Make sure the ~/.subversion run-time config files exist */ err = svn_config_ensure (NULL, pool); if (err) { svn_handle_error2 (err, stderr, FALSE, "minimal_client: "); return EXIT_FAILURE; } /* All clients need to fill out a client_ctx object. */ { /* Initialize and allocate the client_ctx object. */ if ((err = svn_client_create_context (&ctx, pool))) { svn_handle_error2 (err, stderr, FALSE, "minimal_client: "); return EXIT_FAILURE; } /* Load the run-time config file into a hash */ if ((err = svn_config_get_config (&(ctx->config), NULL, pool))) { svn_handle_error2 (err, stderr, FALSE, "minimal_client: "); return EXIT_FAILURE; } #ifdef WIN32 /* Set the working copy administrative directory name. */ if (getenv ("SVN_ASP_DOT_NET_HACK")) { err = svn_wc_set_adm_dir ("_svn", pool); if (err) { svn_handle_error2 (err, stderr, FALSE, "minimal_client: "); return EXIT_FAILURE; } } #endif /* Depending on what your client does, you'll want to read about (and implement) the various callback function types below. */ /* A func (& context) which receives event signals during checkouts, updates, commits, etc. */ /* ctx->notify_func = my_notification_func; ctx->notify_baton = NULL; */ /* A func (& context) which can receive log messages */ /* ctx->log_msg_func = my_log_msg_receiver_func; ctx->log_msg_baton = NULL; */ /* A func (& context) which checks whether the user cancelled */ /* ctx->cancel_func = my_cancel_checking_func; ctx->cancel_baton = NULL; */ /* Make the client_ctx capable of authenticating users */ { /* There are many different kinds of authentication back-end "providers". See svn_auth.h for a full overview. If you want to get the auth behavior of the 'svn' program, you can use svn_cmdline_setup_auth_baton, which will give you the exact set of auth providers it uses. This program doesn't use it because it's only appropriate for a command line program, and this is supposed to be a general purpose example. */ svn_auth_provider_object_t *provider; apr_array_header_t *providers = apr_array_make (pool, 4, sizeof (svn_auth_provider_object_t *)); svn_auth_get_simple_prompt_provider (&provider, my_simple_prompt_callback, NULL, /* baton */ 2, /* retry limit */ pool); APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; svn_auth_get_username_prompt_provider (&provider, my_username_prompt_callback, NULL, /* baton */ 2, /* retry limit */ pool); APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider; /* Register the auth-providers into the context's auth_baton. */ svn_auth_open (&ctx->auth_baton, providers, pool); } } /* end of client_ctx setup */ /* Now do the real work. */ /* Set revision to always be the HEAD revision. It could, however, be set to a specific revision number, date, or other values. */ revision.kind = svn_opt_revision_head; /* Main call into libsvn_client does all the work. */ err = svn_client_ls (&dirents, URL, &revision, FALSE, /* no recursion */ ctx, pool); if (err) { svn_handle_error2 (err, stderr, FALSE, "minimal_client: "); return EXIT_FAILURE; } /* Print the dir entries in the hash. */ for (hi = apr_hash_first (pool, dirents); hi; hi = apr_hash_next (hi)) { const char *entryname; svn_dirent_t *val; apr_hash_this (hi, (void *) &entryname, NULL, (void *) &val); printf (" %s\n", entryname); /* 'val' is actually an svn_dirent_t structure; a more complex program would mine it for extra printable information. */ } return EXIT_SUCCESS; }