Le 12/4/2005 said:
I'll give it a whirl, see what happens.
From the INSTALL file:
E.1 Prerequisites
[snip requirements]
Please tell me that I don't need to do all of that just to generate
the SWIG bindings for Windows... (mumble, grumble, why can't this be
automated more easily?)
Hey, it is not that bad. See the snippet at the end that
I wrote for a 'native' extension. The code is not all that
great (I was mainly trying to get it to just work) but
that Apache Portable Runtime is some truly horrible stuff.
I was looking through the pickaxe book and I saw that rubygems seems
to make allowance for precompiled gems... Can I make use of this?
Ultimately, what I'd like to create is a simple ruby-svn gem that can
be installed anywhere with zero hassle. If it's possible, I'd like to
just include the external libraries for svn for each of the possible
platforms inside the gem or something like that. I don't want to rely
on the library's user actually having all of the required build tools
(especially for the windows platform). Is this possible? If so, how
hard is it, and what do I have to watch out for as far as pitfalls?
I'd prefer not to have to make seperate gems for each platform, is
that possible, given what I want to do?
For that matter, how hard would it be to make a pure-ruby svn client
that conversed with svn only via http/apache? How bad of an idea is
this?
Be aware, I've never tried to make a gem before. (Heck, I'm only just
getting started with ruby, so...)
Someone is already working on a SVN extension to go with the RSCM
project... I would suggest taking a look if you can help there
instead?
E
//////////////////////
// rsvn.c
//-- rsvn_client_ls / Method --//
/* -- Lists the contents of a repo directory.
*/
VALUE rsvn_client_ls(VALUE self,
VALUE path_or_url,
VALUE revision,
VALUE recurse)
{
rsvn_client_rep* clt; // The raw client info
const char* encoded_uri; // URI-encoded path/URL
svn_opt_revision_t revision_data; // SVN revision information
apr_pool_t* pool; // Memory pool for this operation
apr_pool_t* subpool; // Temporary pool for looping
apr_hash_t* directory; // Hash for the file/dir names
apr_hash_index_t* element; // A single element in the directory
has
const void* filename; // Hashed file/directory name
void* file_entry; // File information
svn_error_t* error; // Any received errors
VALUE directory; // The directory structure
// Initializations
// Get the raw data for the client
Data_Get_Struct(self, rsvn_client_rep, clt);
// Extract the revision information from the Ruby object
_rsvn_revision_get_svn_revision(revision, &revision_data);
// Subpool for safe looping
pool = svn_pool_create(clt->memory_pool);
subpool = svn_pool_create(pool);
// Generate an encoded URI (spaces replaced etc.)
// TODO: Can't seem to be able to access local reps on a Windows
// machine.
encoded_uri = svn_path_uri_encode(STR2CSTR(path_or_url), pool);
// Implementation
// Propagate to SVN
error = svn_client_ls(&directory, // Directory entries
encoded_uri, // Path to list
&revision_data, // Revision to retrieve
0, // Recursion
clt->context, // Context
pool);
if (error != 0)
{
// Throw an error <fix>Only prints the topmost error</fix>
rb_raise(rsvn_eSVNError,
"Ruby-SVN::rsvn_new_client (%s:%d): %s\n", error->file,
error->line,
error->message);
}
// Sort the retrieved file names
// TODO: Remove completely?
//files = svn_sort__hash(directory_hash,
svn_sort_compare_items_as_paths,
pool);
// Create a directory to fill
directory = rb_class_new_instance(0, 0, rsvn_cDirectory);
// Fill it
for (element = apr_hash_first(pool, directory);
element != 0; element = apr_hash_next(element))
{
// Extract the key (filename) and value (file info)
// from the hash, ignore key length
apr_hash_this(element, &filename, 0, &file_entry);
// Add the file to the directory
_rsvn_directory_add(directory, filename, file_entry);
}
// Release both pools
svn_pool_destroy(pool);
// The user will receive the directory
return directory;
}
// ...
//-- _rsvn_client_on_username_prompt / Callback --//
/* -- Invoked if the authenticator needs to get
the username interactively.
*/
svn_error_t*
_rsvn_client_on_username_prompt(svn_auth_cred_username_t** credentials,
void* client,
const char* realm_string,
svn_boolean_t may_save,
apr_pool_t * pool)
{
VALUE self; // Calling Client object
VALUE listener; // Event listener for this Client
VALUE retval; // The retrieved values in a hash
svn_auth_cred_username_t* cred = 0; // Collected credential data
// Extract the variables, propagate error out if there's a problem
SVN_TRY(_rsvn_client_get_listener(client, &self, &listener),
"Ruby-SVN::rsvn_client_on_username_prompt: ");
// Query the Listener for a username (may_save should be 0 or 1)
retval = rb_funcall(listener,
ID_PROMPT_USERNAME,
2,
rb_str_new2(realm_string),
INT2FIX(may_save));
// Verify the query succeeded
if (retval == Qnil)
{
// Error and cancel
return svn_error_createf(SVN_ERR_CANCELLED,
0,
"Ruby-SVN::rsvn_client_on_username_prompt: No username from
Listener.");
}
cred = apr_palloc(pool, sizeof(svn_auth_cred_username_t));
// Collect the data <todo>UTF conversion unnecessary?</todo>
SVN_TRY(svn_utf_cstring_to_utf8(&cred->username,
STR2CSTR(rb_funcall(retval,
ID_GET_INDEX,
1,
rb_str_new2("username"))),
pool),
"Ruby-SVN::rsvn_client_on_username_prompt: ");
cred->may_save = FIX2INT(rb_funcall(retval,
ID_GET_INDEX,
1,
rb_str_new2("cache")));
// No errors, we're done
*credentials = cred;
return SVN_NO_ERROR;
}
// End