Reorganize the output to "svnserve --help".
[svn.git] / subversion / libsvn_wc / translate.c
blob2f8b91360858dc356af5cf9179c1bda385d95276
1 /*
2 * translate.c : wc-specific eol/keyword substitution
4 * ====================================================================
5 * Copyright (c) 2000-2007 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 * ====================================================================
21 #include <stdlib.h>
22 #include <string.h>
23 #include <assert.h>
24 #include <apr_pools.h>
25 #include <apr_file_io.h>
26 #include <apr_strings.h>
27 #include "svn_types.h"
28 #include "svn_string.h"
29 #include "svn_path.h"
30 #include "svn_error.h"
31 #include "svn_subst.h"
32 #include "svn_io.h"
33 #include "svn_props.h"
35 #include "wc.h"
36 #include "adm_files.h"
37 #include "translate.h"
38 #include "props.h"
40 #include "svn_private_config.h"
41 #include "private/svn_wc_private.h"
45 static svn_error_t *
46 read_handler_unsupported(void *baton, char *buffer, apr_size_t *len)
48 abort();
49 return SVN_NO_ERROR;
52 static svn_error_t *
53 write_handler_unsupported(void *baton, const char *buffer, apr_size_t *len)
55 abort();
56 return SVN_NO_ERROR;
59 svn_error_t *
60 svn_wc_translated_stream(svn_stream_t **stream,
61 const char *path,
62 const char *versioned_file,
63 svn_wc_adm_access_t *adm_access,
64 apr_uint32_t flags,
65 apr_pool_t *pool)
67 svn_subst_eol_style_t style;
68 const char *eol;
69 apr_hash_t *keywords;
70 svn_boolean_t special;
71 svn_boolean_t to_nf = flags & SVN_WC_TRANSLATE_TO_NF;
73 SVN_ERR(svn_wc__get_eol_style(&style, &eol, versioned_file,
74 adm_access, pool));
75 SVN_ERR(svn_wc__get_keywords(&keywords, versioned_file,
76 adm_access, NULL, pool));
77 SVN_ERR(svn_wc__get_special(&special, versioned_file, adm_access, pool));
79 if (special)
80 SVN_ERR(svn_subst_stream_from_specialfile(stream, path, pool));
81 else
83 apr_file_t *file;
84 svn_boolean_t repair_forced = flags & SVN_WC_TRANSLATE_FORCE_EOL_REPAIR;
86 SVN_ERR(svn_io_file_open(&file, path,
87 to_nf ? (APR_READ | APR_BUFFERED)
88 : (APR_CREATE | APR_WRITE | APR_BUFFERED),
89 APR_OS_DEFAULT, pool));
91 *stream = svn_stream_from_aprfile2(file, FALSE, pool);
93 if (svn_subst_translation_required(style, eol, keywords, special, TRUE))
95 if (to_nf)
96 SVN_ERR(svn_subst_stream_translated_to_normal_form
97 (stream, *stream, style, eol, repair_forced,
98 keywords, pool));
99 else
100 *stream = svn_subst_stream_translated
101 (*stream, eol, TRUE, keywords, TRUE, pool);
105 /* Enfore our contract, because a specialfile stream won't */
106 if (to_nf)
107 svn_stream_set_write(*stream, write_handler_unsupported);
108 else
109 svn_stream_set_read(*stream, read_handler_unsupported);
111 return SVN_NO_ERROR;
115 svn_error_t *
116 svn_wc_translated_file2(const char **xlated_path,
117 const char *src,
118 const char *versioned_file,
119 svn_wc_adm_access_t *adm_access,
120 apr_uint32_t flags,
121 apr_pool_t *pool)
123 svn_subst_eol_style_t style;
124 const char *eol;
125 apr_hash_t *keywords;
126 svn_boolean_t special;
128 SVN_ERR(svn_wc__get_eol_style(&style, &eol, versioned_file,
129 adm_access, pool));
130 SVN_ERR(svn_wc__get_keywords(&keywords, versioned_file,
131 adm_access, NULL, pool));
132 SVN_ERR(svn_wc__get_special(&special, versioned_file, adm_access, pool));
135 if (! svn_subst_translation_required(style, eol, keywords, special, TRUE)
136 && (! (flags & SVN_WC_TRANSLATE_FORCE_COPY)))
138 /* Translation would be a no-op, so return the original file. */
139 *xlated_path = src;
142 else /* some translation (or copying) is necessary */
144 const char *tmp_dir, *tmp_vfile;
145 svn_boolean_t repair_forced = flags & SVN_WC_TRANSLATE_FORCE_EOL_REPAIR;
147 svn_path_split(versioned_file, &tmp_dir, &tmp_vfile, pool);
148 if (flags & SVN_WC_TRANSLATE_USE_GLOBAL_TMP)
150 SVN_ERR(svn_io_temp_dir(&tmp_dir, pool));
151 tmp_vfile = svn_path_join(tmp_dir, "svndiff", pool);
153 else
154 tmp_vfile = svn_wc__adm_path(tmp_dir, 1, pool, tmp_vfile, NULL);
156 SVN_ERR(svn_io_open_unique_file2
157 (NULL, &tmp_vfile,
158 tmp_vfile,
159 SVN_WC__TMP_EXT,
160 (flags & SVN_WC_TRANSLATE_NO_OUTPUT_CLEANUP)
161 ? svn_io_file_del_none : svn_io_file_del_on_pool_cleanup,
162 pool));
164 if (flags & SVN_WC_TRANSLATE_TO_NF)
165 /* to normal form */
166 SVN_ERR(svn_subst_translate_to_normal_form
167 (src, tmp_vfile, style, eol,
168 repair_forced,
169 keywords, special, pool));
170 else /* from normal form */
171 SVN_ERR(svn_subst_copy_and_translate3
172 (src, tmp_vfile,
173 eol, TRUE,
174 keywords, TRUE,
175 special,
176 pool));
178 *xlated_path = tmp_vfile;
181 return SVN_NO_ERROR;
185 svn_error_t *
186 svn_wc_translated_file(const char **xlated_p,
187 const char *vfile,
188 svn_wc_adm_access_t *adm_access,
189 svn_boolean_t force_repair,
190 apr_pool_t *pool)
192 return svn_wc_translated_file2(xlated_p, vfile, vfile, adm_access,
193 SVN_WC_TRANSLATE_TO_NF
194 | (force_repair ?
195 SVN_WC_TRANSLATE_FORCE_EOL_REPAIR : 0),
196 pool);
200 svn_error_t *
201 svn_wc__get_eol_style(svn_subst_eol_style_t *style,
202 const char **eol,
203 const char *path,
204 svn_wc_adm_access_t *adm_access,
205 apr_pool_t *pool)
207 const svn_string_t *propval;
209 /* Get the property value. */
210 SVN_ERR(svn_wc_prop_get(&propval, SVN_PROP_EOL_STYLE, path, adm_access,
211 pool));
213 /* Convert it. */
214 svn_subst_eol_style_from_value(style, eol, propval ? propval->data : NULL);
216 return SVN_NO_ERROR;
220 void
221 svn_wc__eol_value_from_string(const char **value, const char *eol)
223 if (eol == NULL)
224 *value = NULL;
225 else if (! strcmp("\n", eol))
226 *value = "LF";
227 else if (! strcmp("\r", eol))
228 *value = "CR";
229 else if (! strcmp("\r\n", eol))
230 *value = "CRLF";
231 else
232 *value = NULL;
236 svn_error_t *
237 svn_wc__get_keywords(apr_hash_t **keywords,
238 const char *path,
239 svn_wc_adm_access_t *adm_access,
240 const char *force_list,
241 apr_pool_t *pool)
243 const char *list;
244 const svn_wc_entry_t *entry = NULL;
246 /* Choose a property list to parse: either the one that came into
247 this function, or the one attached to PATH. */
248 if (force_list == NULL)
250 const svn_string_t *propval;
252 SVN_ERR(svn_wc_prop_get(&propval, SVN_PROP_KEYWORDS, path, adm_access,
253 pool));
255 list = propval ? propval->data : NULL;
257 else
258 list = force_list;
260 /* The easy answer. */
261 if (list == NULL)
263 *keywords = NULL;
264 return SVN_NO_ERROR;
267 SVN_ERR(svn_wc__entry_versioned(&entry, path, adm_access, FALSE, pool));
269 SVN_ERR(svn_subst_build_keywords2(keywords,
270 list,
271 apr_psprintf(pool, "%ld",
272 entry->cmt_rev),
273 entry->url,
274 entry->cmt_date,
275 entry->cmt_author,
276 pool));
278 if (apr_hash_count(*keywords) == 0)
279 *keywords = NULL;
281 return SVN_NO_ERROR;
285 svn_error_t *
286 svn_wc__get_special(svn_boolean_t *special,
287 const char *path,
288 svn_wc_adm_access_t *adm_access,
289 apr_pool_t *pool)
291 const svn_string_t *propval;
293 /* Get the property value. */
294 SVN_ERR(svn_wc_prop_get(&propval, SVN_PROP_SPECIAL, path,
295 adm_access, pool));
296 *special = propval != NULL;
298 return SVN_NO_ERROR;
302 svn_error_t *
303 svn_wc__maybe_set_executable(svn_boolean_t *did_set,
304 const char *path,
305 svn_wc_adm_access_t *adm_access,
306 apr_pool_t *pool)
308 const svn_string_t *propval;
309 SVN_ERR(svn_wc_prop_get(&propval, SVN_PROP_EXECUTABLE, path, adm_access,
310 pool));
312 if (propval != NULL)
314 SVN_ERR(svn_io_set_file_executable(path, TRUE, FALSE, pool));
315 if (did_set)
316 *did_set = TRUE;
318 else if (did_set)
319 *did_set = FALSE;
321 return SVN_NO_ERROR;
325 svn_error_t *
326 svn_wc__maybe_set_read_only(svn_boolean_t *did_set,
327 const char *path,
328 svn_wc_adm_access_t *adm_access,
329 apr_pool_t *pool)
331 const svn_string_t *needs_lock;
332 const svn_wc_entry_t* entry;
334 if (did_set)
335 *did_set = FALSE;
337 SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool));
338 if (entry && entry->lock_token)
339 return SVN_NO_ERROR;
341 SVN_ERR(svn_wc_prop_get(&needs_lock, SVN_PROP_NEEDS_LOCK, path,
342 adm_access, pool));
344 if (needs_lock != NULL)
346 SVN_ERR(svn_io_set_file_read_only(path, FALSE, pool));
347 if (did_set)
348 *did_set = TRUE;
351 return SVN_NO_ERROR;