1 /*
2 * headrev.c : print out the HEAD revision of a repository.
3 *
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
20 * under the License.
21 * ====================================================================
22 *
23 * To compile on unix against Subversion and APR libraries, try
24 * something like:
25 *
26 * cc headrev.c -o headrev \
27 * -I/usr/local/include/subversion-1 -I/usr/local/apache2/include \
28 * -L/usr/local/apache2/lib -L/usr/local/lib \
29 * -lsvn_client-1 -lsvn_ra-1 -lsvn_subr-1 -lapr-0 -laprutil-0
30 *
31 */
32
33 #include "svn_client.h"
34 #include "svn_pools.h"
35 #include "svn_config.h"
36 #include "svn_fs.h"
37 #include "svn_path.h"
38 #include "svn_cmdline.h"
39
40
41 /* Display a prompt and read a one-line response into the provided buffer,
42 removing a trailing newline if present. */
43 static svn_error_t *
prompt_and_read_line(const char * prompt,char * buffer,size_t max)44 prompt_and_read_line(const char *prompt,
45 char *buffer,
46 size_t max)
47 {
48 int len;
49 printf("%s: ", prompt);
50 if (fgets(buffer, max, stdin) == NULL)
51 return svn_error_create(0, NULL, "error reading stdin");
52 len = strlen(buffer);
53 if (len > 0 && buffer[len-1] == '\n')
54 buffer[len-1] = 0;
55 return SVN_NO_ERROR;
56 }
57
58 /* A tiny callback function of type 'svn_auth_simple_prompt_func_t'. For
59 a much better example, see svn_cl__auth_simple_prompt in the official
60 svn cmdline client. */
61 static svn_error_t *
my_simple_prompt_callback(svn_auth_cred_simple_t ** cred,void * baton,const char * realm,const char * username,svn_boolean_t may_save,apr_pool_t * pool)62 my_simple_prompt_callback (svn_auth_cred_simple_t **cred,
63 void *baton,
64 const char *realm,
65 const char *username,
66 svn_boolean_t may_save,
67 apr_pool_t *pool)
68 {
69 svn_auth_cred_simple_t *ret = apr_pcalloc (pool, sizeof (*ret));
70 char answerbuf[100];
71
72 if (realm)
73 {
74 printf ("Authentication realm: %s\n", realm);
75 }
76
77 if (username)
78 ret->username = apr_pstrdup (pool, username);
79 else
80 {
81 SVN_ERR (prompt_and_read_line("Username", answerbuf, sizeof(answerbuf)));
82 ret->username = apr_pstrdup (pool, answerbuf);
83 }
84
85 SVN_ERR (prompt_and_read_line("Password", answerbuf, sizeof(answerbuf)));
86 ret->password = apr_pstrdup (pool, answerbuf);
87
88 *cred = ret;
89 return SVN_NO_ERROR;
90 }
91
92
93 /* A tiny callback function of type 'svn_auth_username_prompt_func_t'. For
94 a much better example, see svn_cl__auth_username_prompt in the official
95 svn cmdline client. */
96 static svn_error_t *
my_username_prompt_callback(svn_auth_cred_username_t ** cred,void * baton,const char * realm,svn_boolean_t may_save,apr_pool_t * pool)97 my_username_prompt_callback (svn_auth_cred_username_t **cred,
98 void *baton,
99 const char *realm,
100 svn_boolean_t may_save,
101 apr_pool_t *pool)
102 {
103 svn_auth_cred_username_t *ret = apr_pcalloc (pool, sizeof (*ret));
104 char answerbuf[100];
105
106 if (realm)
107 {
108 printf ("Authentication realm: %s\n", realm);
109 }
110
111 SVN_ERR (prompt_and_read_line("Username", answerbuf, sizeof(answerbuf)));
112 ret->username = apr_pstrdup (pool, answerbuf);
113
114 *cred = ret;
115 return SVN_NO_ERROR;
116 }
117
118
119 /* A callback function used when the RA layer needs a handle to a
120 temporary file. This is a reduced version of the callback used in
121 the official svn cmdline client. */
122 static svn_error_t *
open_tmp_file(apr_file_t ** fp,void * callback_baton,apr_pool_t * pool)123 open_tmp_file (apr_file_t **fp,
124 void *callback_baton,
125 apr_pool_t *pool)
126 {
127 const char *path;
128 const char *ignored_filename;
129
130 SVN_ERR (svn_io_temp_dir (&path, pool));
131 path = svn_path_join (path, "tempfile", pool);
132
133 /* Open a unique file, with delete-on-close set. */
134 SVN_ERR (svn_io_open_unique_file2 (fp, &ignored_filename,
135 path, ".tmp",
136 svn_io_file_del_on_close, pool));
137
138 return SVN_NO_ERROR;
139 }
140
141
142 int
main(int argc,const char ** argv)143 main (int argc, const char **argv)
144 {
145 apr_pool_t *pool;
146 svn_error_t *err;
147 const char *URL;
148 svn_ra_session_t *session;
149 svn_ra_callbacks2_t *cbtable;
150 svn_revnum_t rev;
151 apr_hash_t *cfg_hash;
152 svn_auth_baton_t *auth_baton;
153
154 if (argc <= 1)
155 {
156 printf ("Usage: %s URL\n", argv[0]);
157 printf (" Print HEAD revision of URL's repository.\n");
158 return EXIT_FAILURE;
159 }
160 else
161 URL = argv[1];
162
163 /* Initialize the app. Send all error messages to 'stderr'. */
164 if (svn_cmdline_init ("headrev", stderr) != EXIT_SUCCESS)
165 return EXIT_FAILURE;
166
167 /* Create top-level memory pool. Be sure to read the HACKING file to
168 understand how to properly use/free subpools. */
169 pool = svn_pool_create (NULL);
170
171 /* Initialize the FS library. */
172 err = svn_fs_initialize (pool);
173 if (err) goto hit_error;
174
175 /* Make sure the ~/.subversion run-time config files exist, and load. */
176 err = svn_config_ensure (NULL, pool);
177 if (err) goto hit_error;
178
179 err = svn_config_get_config (&cfg_hash, NULL, pool);
180 if (err) goto hit_error;
181
182 /* Build an authentication baton. */
183 {
184 /* There are many different kinds of authentication back-end
185 "providers". See svn_auth.h for a full overview. */
186 svn_auth_provider_object_t *provider;
187 apr_array_header_t *providers
188 = apr_array_make (pool, 4, sizeof (svn_auth_provider_object_t *));
189
190 svn_client_get_simple_prompt_provider (&provider,
191 my_simple_prompt_callback,
192 NULL, /* baton */
193 2, /* retry limit */ pool);
194 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider;
195
196 svn_client_get_username_prompt_provider (&provider,
197 my_username_prompt_callback,
198 NULL, /* baton */
199 2, /* retry limit */ pool);
200 APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider;
201
202 /* Register the auth-providers into the context's auth_baton. */
203 svn_auth_open (&auth_baton, providers, pool);
204 }
205
206 /* Create a table of callbacks for the RA session, mostly nonexistent. */
207 cbtable = apr_pcalloc (pool, sizeof(*cbtable));
208 cbtable->auth_baton = auth_baton;
209 cbtable->open_tmp_file = open_tmp_file;
210
211 /* Now do the real work. */
212
213 err = svn_ra_open2(&session, URL, cbtable, NULL, cfg_hash, pool);
214 if (err) goto hit_error;
215
216 err = svn_ra_get_latest_revnum(session, &rev, pool);
217 if (err) goto hit_error;
218
219 printf ("The latest revision is %ld.\n", rev);
220
221 return EXIT_SUCCESS;
222
223 hit_error:
224 svn_handle_error2 (err, stderr, FALSE, "headrev: ");
225 return EXIT_FAILURE;
226 }
227