blob: dfce5df05c215672ad7bb3525a12e55917cf2fc5 [file] [log] [blame]
/*
* minimal_client.c - a minimal Subversion client application ("hello world")
*
* ====================================================================
* Copyright (c) 2000-2003 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/.
* ====================================================================
*
* This app demonstrates how to use the svn_client.h API.
*
* It reads a directory URL from the commandline, runs
* svn_client_list() and prints the list of directory-entries. It
* also knows how to deal with basic username/password authentication
* challenges.
*
* For a much more complex example, the svn cmdline client might be
* considered the 'reference implementation'.
*/
#include "svn_client.h"
#include "svn_pools.h"
#include "svn_config.h"
/* Display a prmopt and read a one-line response into the provided buffer,
removing a trailing newline if present. */
static svn_error_t *
prompt_and_read_line(const char *prompt,
char *buffer,
size_t max)
{
int len;
printf("%s: ", prompt);
if (fgets(buffer, max, stdin) == NULL)
return svn_error_create(0, NULL, "error reading stdin");
len = strlen(buffer);
if (len > 0 && buffer[len-1] == '\n')
buffer[len-1] = 0;
return SVN_NO_ERROR;
}
/* A tiny callback function of type 'svn_auth_simple_prompt_func_t'. For
a much better example, see svn_cl__auth_simple_prompt in the official
svn cmdline client. */
static svn_error_t *
my_simple_prompt_callback (svn_auth_cred_simple_t **cred,
void *baton,
const char *realm,
const char *username,
apr_pool_t *pool)
{
svn_auth_cred_simple_t *ret = apr_pcalloc (pool, sizeof (*ret));
char answerbuf[100];
if (realm)
{
printf ("Authentication realm: %s\n", realm);
}
if (username)
ret->username = apr_pstrdup (pool, username);
else
{
SVN_ERR (prompt_and_read_line("Username", answerbuf, sizeof(answerbuf)));
ret->username = apr_pstrdup (pool, answerbuf);
}
SVN_ERR (prompt_and_read_line("Password", answerbuf, sizeof(answerbuf)));
ret->password = apr_pstrdup (pool, answerbuf);
*cred = ret;
return SVN_NO_ERROR;
}
/* A tiny callback function of type 'svn_auth_username_prompt_func_t'. For
a much better example, see svn_cl__auth_username_prompt in the official
svn cmdline client. */
static svn_error_t *
my_username_prompt_callback (svn_auth_cred_username_t **cred,
void *baton,
const char *realm,
apr_pool_t *pool)
{
svn_auth_cred_username_t *ret = apr_pcalloc (pool, sizeof (*ret));
char answerbuf[100];
if (realm)
{
printf ("Authentication realm: %s\n", realm);
}
SVN_ERR (prompt_and_read_line("Username", answerbuf, sizeof(answerbuf)));
ret->username = apr_pstrdup (pool, answerbuf);
*cred = ret;
return SVN_NO_ERROR;
}
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 = { 0 };
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);
/* Make sure the ~/.subversion run-time config files exist */
err = svn_config_ensure (NULL, 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_error(). */
svn_handle_error (err, stderr, 0);
return EXIT_FAILURE;
}
/* All clients need to fill out a client_ctx object. */
{
/* Load the run-time config file into a hash */
if ((err = svn_config_get_config (&(ctx.config), NULL, pool)))
{
svn_handle_error (err, stderr, 0);
return EXIT_FAILURE;
}
/* 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. */
svn_auth_provider_object_t *provider;
apr_array_header_t *providers
= apr_array_make (pool, 4, sizeof (svn_auth_provider_object_t *));
svn_client_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_client_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_error (err, stderr, 0);
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;
}