2 * minimal_client.c - a minimal Subversion client application ("hello world")
4 * ====================================================================
5 * Copyright (c) 2000-2004 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
18 * This app demonstrates how to use the svn_client.h API.
20 * It reads a directory URL from the commandline, runs
21 * svn_client_list() and prints the list of directory-entries. It
22 * also knows how to deal with basic username/password authentication
25 * For a much more complex example, the svn cmdline client might be
26 * considered the 'reference implementation'.
28 * From a Linux system, a typical commandline compile might look like:
30 * cc minimal_client.c -o minimal_client \
31 * -I/usr/local/include/subversion-1 -I/usr/local/apache2/include \
32 * -L/usr/local/apache2/lib -L/usr/local/lib \
33 * -lsvn_client-1 -lapr-0 -laprutil-0
38 #include "svn_client.h"
39 #include "svn_cmdline.h"
40 #include "svn_pools.h"
41 #include "svn_config.h"
45 /* Display a prompt and read a one-line response into the provided buffer,
46 removing a trailing newline if present. */
48 prompt_and_read_line(const char *prompt
,
53 printf("%s: ", prompt
);
54 if (fgets(buffer
, max
, stdin
) == NULL
)
55 return svn_error_create(0, NULL
, "error reading stdin");
57 if (len
> 0 && buffer
[len
-1] == '\n')
62 /* A tiny callback function of type 'svn_auth_simple_prompt_func_t'. For
63 a much better example, see svn_cl__auth_simple_prompt in the official
64 svn cmdline client. */
66 my_simple_prompt_callback (svn_auth_cred_simple_t
**cred
,
70 svn_boolean_t may_save
,
73 svn_auth_cred_simple_t
*ret
= apr_pcalloc (pool
, sizeof (*ret
));
78 printf ("Authentication realm: %s\n", realm
);
82 ret
->username
= apr_pstrdup (pool
, username
);
85 SVN_ERR (prompt_and_read_line("Username", answerbuf
, sizeof(answerbuf
)));
86 ret
->username
= apr_pstrdup (pool
, answerbuf
);
89 SVN_ERR (prompt_and_read_line("Password", answerbuf
, sizeof(answerbuf
)));
90 ret
->password
= apr_pstrdup (pool
, answerbuf
);
97 /* A tiny callback function of type 'svn_auth_username_prompt_func_t'. For
98 a much better example, see svn_cl__auth_username_prompt in the official
99 svn cmdline client. */
101 my_username_prompt_callback (svn_auth_cred_username_t
**cred
,
104 svn_boolean_t may_save
,
107 svn_auth_cred_username_t
*ret
= apr_pcalloc (pool
, sizeof (*ret
));
112 printf ("Authentication realm: %s\n", realm
);
115 SVN_ERR (prompt_and_read_line("Username", answerbuf
, sizeof(answerbuf
)));
116 ret
->username
= apr_pstrdup (pool
, answerbuf
);
125 main (int argc
, const char **argv
)
129 svn_opt_revision_t revision
;
131 apr_hash_index_t
*hi
;
132 svn_client_ctx_t
*ctx
;
137 printf ("Usage: %s URL\n", argv
[0]);
143 /* Initialize the app. Send all error messages to 'stderr'. */
144 if (svn_cmdline_init ("minimal_client", stderr
) != EXIT_SUCCESS
)
147 /* Create top-level memory pool. Be sure to read the HACKING file to
148 understand how to properly use/free subpools. */
149 pool
= svn_pool_create (NULL
);
151 /* Initialize the FS library. */
152 err
= svn_fs_initialize (pool
);
155 /* For functions deeper in the stack, we usually use the
156 SVN_ERR() exception-throwing macro (see svn_error.h). At the
157 top level, we catch & print the error with svn_handle_error2(). */
158 svn_handle_error2 (err
, stderr
, FALSE
, "minimal_client: ");
162 /* Make sure the ~/.subversion run-time config files exist */
163 err
= svn_config_ensure (NULL
, pool
);
166 svn_handle_error2 (err
, stderr
, FALSE
, "minimal_client: ");
170 /* All clients need to fill out a client_ctx object. */
172 /* Initialize and allocate the client_ctx object. */
173 if ((err
= svn_client_create_context (&ctx
, pool
)))
175 svn_handle_error2 (err
, stderr
, FALSE
, "minimal_client: ");
179 /* Load the run-time config file into a hash */
180 if ((err
= svn_config_get_config (&(ctx
->config
), NULL
, pool
)))
182 svn_handle_error2 (err
, stderr
, FALSE
, "minimal_client: ");
187 /* Set the working copy administrative directory name. */
188 if (getenv ("SVN_ASP_DOT_NET_HACK"))
190 err
= svn_wc_set_adm_dir ("_svn", pool
);
193 svn_handle_error2 (err
, stderr
, FALSE
, "minimal_client: ");
199 /* Depending on what your client does, you'll want to read about
200 (and implement) the various callback function types below. */
202 /* A func (& context) which receives event signals during
203 checkouts, updates, commits, etc. */
204 /* ctx->notify_func = my_notification_func;
205 ctx->notify_baton = NULL; */
207 /* A func (& context) which can receive log messages */
208 /* ctx->log_msg_func = my_log_msg_receiver_func;
209 ctx->log_msg_baton = NULL; */
211 /* A func (& context) which checks whether the user cancelled */
212 /* ctx->cancel_func = my_cancel_checking_func;
213 ctx->cancel_baton = NULL; */
215 /* Make the client_ctx capable of authenticating users */
217 /* There are many different kinds of authentication back-end
218 "providers". See svn_auth.h for a full overview.
220 If you want to get the auth behavior of the 'svn' program,
221 you can use svn_cmdline_setup_auth_baton, which will give
222 you the exact set of auth providers it uses. This program
223 doesn't use it because it's only appropriate for a command
224 line program, and this is supposed to be a general purpose
227 svn_auth_provider_object_t
*provider
;
228 apr_array_header_t
*providers
229 = apr_array_make (pool
, 4, sizeof (svn_auth_provider_object_t
*));
231 svn_auth_get_simple_prompt_provider (&provider
,
232 my_simple_prompt_callback
,
234 2, /* retry limit */ pool
);
235 APR_ARRAY_PUSH (providers
, svn_auth_provider_object_t
*) = provider
;
237 svn_auth_get_username_prompt_provider (&provider
,
238 my_username_prompt_callback
,
240 2, /* retry limit */ pool
);
241 APR_ARRAY_PUSH (providers
, svn_auth_provider_object_t
*) = provider
;
243 /* Register the auth-providers into the context's auth_baton. */
244 svn_auth_open (&ctx
->auth_baton
, providers
, pool
);
246 } /* end of client_ctx setup */
249 /* Now do the real work. */
251 /* Set revision to always be the HEAD revision. It could, however,
252 be set to a specific revision number, date, or other values. */
253 revision
.kind
= svn_opt_revision_head
;
255 /* Main call into libsvn_client does all the work. */
256 err
= svn_client_ls (&dirents
,
258 FALSE
, /* no recursion */
262 svn_handle_error2 (err
, stderr
, FALSE
, "minimal_client: ");
266 /* Print the dir entries in the hash. */
267 for (hi
= apr_hash_first (pool
, dirents
); hi
; hi
= apr_hash_next (hi
))
269 const char *entryname
;
272 apr_hash_this (hi
, (void *) &entryname
, NULL
, (void *) &val
);
273 printf (" %s\n", entryname
);
275 /* 'val' is actually an svn_dirent_t structure; a more complex
276 program would mine it for extra printable information. */