Follow-up to r29036: Now that the "mergeinfo" transaction file is no
[svn.git] / tools / examples / testwrite.c
blob017d0c18551dffc3a352d74e80b4a6d7a269a57b
1 /*
2 * testwrite.c : test whether a user has commit access.
4 * ====================================================================
5 * Copyright (c) 2000-2005 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 * To compile on unix against Subversion and APR libraries, try
19 * something like:
21 * cc testwrite.c -o testwrite \
22 * -I/usr/local/include/subversion-1 -I/usr/local/apache2/include \
23 * -L/usr/local/apache2/lib -L/usr/local/lib \
24 * -lsvn_client-1 -lsvn_ra-1 -lsvn_subr-1 -lsvn-fs-1 -lapr-0 -laprutil-0
28 #include "svn_client.h"
29 #include "svn_pools.h"
30 #include "svn_config.h"
31 #include "svn_fs.h"
32 #include "svn_cmdline.h"
33 #include "svn_path.h"
34 #include "svn_time.h"
37 /* Display a prompt and read a one-line response into the provided buffer,
38 removing a trailing newline if present. */
39 static svn_error_t *
40 prompt_and_read_line(const char *prompt,
41 char *buffer,
42 size_t max)
44 int len;
45 printf("%s: ", prompt);
46 if (fgets(buffer, max, stdin) == NULL)
47 return svn_error_create(0, NULL, "error reading stdin");
48 len = strlen(buffer);
49 if (len > 0 && buffer[len-1] == '\n')
50 buffer[len-1] = 0;
51 return SVN_NO_ERROR;
54 /* A tiny callback function of type 'svn_auth_simple_prompt_func_t'. For
55 a much better example, see svn_cl__auth_simple_prompt in the official
56 svn cmdline client. */
57 static svn_error_t *
58 my_simple_prompt_callback (svn_auth_cred_simple_t **cred,
59 void *baton,
60 const char *realm,
61 const char *username,
62 svn_boolean_t may_save,
63 apr_pool_t *pool)
65 svn_auth_cred_simple_t *ret = apr_pcalloc (pool, sizeof (*ret));
66 char answerbuf[100];
68 if (realm)
70 printf ("Authentication realm: %s\n", realm);
73 if (username)
74 ret->username = apr_pstrdup (pool, username);
75 else
77 SVN_ERR (prompt_and_read_line("Username", answerbuf, sizeof(answerbuf)));
78 ret->username = apr_pstrdup (pool, answerbuf);
81 SVN_ERR (prompt_and_read_line("Password", answerbuf, sizeof(answerbuf)));
82 ret->password = apr_pstrdup (pool, answerbuf);
84 *cred = ret;
85 return SVN_NO_ERROR;
89 /* A tiny callback function of type 'svn_auth_username_prompt_func_t'. For
90 a much better example, see svn_cl__auth_username_prompt in the official
91 svn cmdline client. */
92 static svn_error_t *
93 my_username_prompt_callback (svn_auth_cred_username_t **cred,
94 void *baton,
95 const char *realm,
96 svn_boolean_t may_save,
97 apr_pool_t *pool)
99 svn_auth_cred_username_t *ret = apr_pcalloc (pool, sizeof (*ret));
100 char answerbuf[100];
102 if (realm)
104 printf ("Authentication realm: %s\n", realm);
107 SVN_ERR (prompt_and_read_line("Username", answerbuf, sizeof(answerbuf)));
108 ret->username = apr_pstrdup (pool, answerbuf);
110 *cred = ret;
111 return SVN_NO_ERROR;
114 /* A callback function used when the RA layer needs a handle to a
115 temporary file. This is a reduced version of the callback used in
116 the official svn cmdline client. */
117 static svn_error_t *
118 open_tmp_file (apr_file_t **fp,
119 void *callback_baton,
120 apr_pool_t *pool)
122 const char *path;
123 const char *ignored_filename;
125 SVN_ERR (svn_io_temp_dir (&path, pool));
126 path = svn_path_join (path, "tempfile", pool);
128 /* Open a unique file, with delete-on-close set. */
129 SVN_ERR (svn_io_open_unique_file2 (fp, &ignored_filename,
130 path, ".tmp",
131 svn_io_file_del_on_close, pool));
133 return SVN_NO_ERROR;
137 /* Called when a commit is successful. */
138 static svn_error_t *
139 my_commit_callback (svn_revnum_t new_revision,
140 const char *date,
141 const char *author,
142 void *baton)
144 printf ("Upload complete. Committed revision %ld.\n", new_revision);
145 return SVN_NO_ERROR;
151 main (int argc, const char **argv)
153 apr_pool_t *pool;
154 svn_error_t *err;
155 apr_hash_t *dirents;
156 const char *upload_file, *URL;
157 const char *parent_URL, *basename;
158 svn_ra_plugin_t *ra_lib;
159 void *session, *ra_baton;
160 svn_revnum_t rev;
161 const svn_delta_editor_t *editor;
162 void *edit_baton;
163 svn_dirent_t *dirent;
164 svn_ra_callbacks_t *cbtable;
165 apr_hash_t *cfg_hash;
166 svn_auth_baton_t *auth_baton;
168 if (argc <= 1)
170 printf ("Usage: %s URL\n", argv[0]);
171 printf (" Tries to create an svn commit-transaction at URL.\n");
172 return EXIT_FAILURE;
174 URL = argv[1];
176 /* Initialize the app. Send all error messages to 'stderr'. */
177 if (svn_cmdline_init ("minimal_client", stderr) != EXIT_SUCCESS)
178 return EXIT_FAILURE;
180 /* Create top-level memory pool. Be sure to read the HACKING file to
181 understand how to properly use/free subpools. */
182 pool = svn_pool_create (NULL);
184 /* Initialize the FS library. */
185 err = svn_fs_initialize (pool);
186 if (err) goto hit_error;
188 /* Make sure the ~/.subversion run-time config files exist, and load. */
189 err = svn_config_ensure (NULL, pool);
190 if (err) goto hit_error;
192 err = svn_config_get_config (&cfg_hash, NULL, pool);
193 if (err) goto hit_error;
195 /* Build an authentication baton. */
197 /* There are many different kinds of authentication back-end
198 "providers". See svn_auth.h for a full overview. */
199 svn_auth_provider_object_t *provider;
200 apr_array_header_t *providers
201 = apr_array_make (pool, 4, sizeof (svn_auth_provider_object_t *));
203 svn_client_get_simple_prompt_provider (&provider,
204 my_simple_prompt_callback,
205 NULL, /* baton */
206 2, /* retry limit */ pool);
207 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider;
209 svn_client_get_username_prompt_provider (&provider,
210 my_username_prompt_callback,
211 NULL, /* baton */
212 2, /* retry limit */ pool);
213 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider;
215 /* Register the auth-providers into the context's auth_baton. */
216 svn_auth_open (&auth_baton, providers, pool);
219 /* Create a table of callbacks for the RA session, mostly nonexistent. */
220 cbtable = apr_pcalloc (pool, sizeof(*cbtable));
221 cbtable->auth_baton = auth_baton;
222 cbtable->open_tmp_file = open_tmp_file;
224 /* Now do the real work. */
226 /* Open an RA session to the parent URL, fetch current HEAD rev and
227 "lock" onto that revnum for the remainder of the session. */
228 svn_path_split (URL, &parent_URL, &basename, pool);
230 err = svn_ra_init_ra_libs (&ra_baton, pool);
231 if (err) goto hit_error;
233 err = svn_ra_get_ra_library (&ra_lib, ra_baton, parent_URL, pool);
234 if (err) goto hit_error;
236 err = ra_lib->open (&session, parent_URL, cbtable, NULL, cfg_hash, pool);
237 if (err) goto hit_error;
239 /* Fetch a commit editor (it's anchored on the parent URL, because
240 the session is too.) */
241 /* ### someday add an option for a user-written commit message? */
242 err = ra_lib->get_commit_editor (session, &editor, &edit_baton,
243 "File upload from 'svnput' program.",
244 my_commit_callback, NULL, pool);
245 if (err) goto hit_error;
247 /* Drive the editor */
249 void *root_baton, *file_baton, *handler_baton;
250 svn_txdelta_window_handler_t handler;
251 svn_stream_t *contents;
252 apr_file_t *f = NULL;
254 err = editor->open_root (edit_baton, rev, pool, &root_baton);
255 if (err) goto hit_error;
257 err = editor->abort_edit (edit_baton, pool);
258 if (err) goto hit_error;
261 printf ("No problems creating commit transaction.\n");
262 return EXIT_SUCCESS;
264 hit_error:
266 printf("Could not open a commit transaction.\n");
267 svn_handle_error2 (err, stderr, FALSE, "testwrite: ");
268 return EXIT_FAILURE;