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 * ====================================================================
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"
30 #include "svn_error.h"
31 #include "svn_subst.h"
33 #include "svn_props.h"
36 #include "adm_files.h"
37 #include "translate.h"
40 #include "svn_private_config.h"
41 #include "private/svn_wc_private.h"
46 read_handler_unsupported(void *baton
, char *buffer
, apr_size_t
*len
)
53 write_handler_unsupported(void *baton
, const char *buffer
, apr_size_t
*len
)
60 svn_wc_translated_stream(svn_stream_t
**stream
,
62 const char *versioned_file
,
63 svn_wc_adm_access_t
*adm_access
,
67 svn_subst_eol_style_t style
;
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
,
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
));
80 SVN_ERR(svn_subst_stream_from_specialfile(stream
, path
, pool
));
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
))
96 SVN_ERR(svn_subst_stream_translated_to_normal_form
97 (stream
, *stream
, style
, eol
, repair_forced
,
100 *stream
= svn_subst_stream_translated
101 (*stream
, eol
, TRUE
, keywords
, TRUE
, pool
);
105 /* Enfore our contract, because a specialfile stream won't */
107 svn_stream_set_write(*stream
, write_handler_unsupported
);
109 svn_stream_set_read(*stream
, read_handler_unsupported
);
116 svn_wc_translated_file2(const char **xlated_path
,
118 const char *versioned_file
,
119 svn_wc_adm_access_t
*adm_access
,
123 svn_subst_eol_style_t style
;
125 apr_hash_t
*keywords
;
126 svn_boolean_t special
;
128 SVN_ERR(svn_wc__get_eol_style(&style
, &eol
, versioned_file
,
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. */
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
);
154 tmp_vfile
= svn_wc__adm_path(tmp_dir
, 1, pool
, tmp_vfile
, NULL
);
156 SVN_ERR(svn_io_open_unique_file2
160 (flags
& SVN_WC_TRANSLATE_NO_OUTPUT_CLEANUP
)
161 ? svn_io_file_del_none
: svn_io_file_del_on_pool_cleanup
,
164 if (flags
& SVN_WC_TRANSLATE_TO_NF
)
166 SVN_ERR(svn_subst_translate_to_normal_form
167 (src
, tmp_vfile
, style
, eol
,
169 keywords
, special
, pool
));
170 else /* from normal form */
171 SVN_ERR(svn_subst_copy_and_translate3
178 *xlated_path
= tmp_vfile
;
186 svn_wc_translated_file(const char **xlated_p
,
188 svn_wc_adm_access_t
*adm_access
,
189 svn_boolean_t force_repair
,
192 return svn_wc_translated_file2(xlated_p
, vfile
, vfile
, adm_access
,
193 SVN_WC_TRANSLATE_TO_NF
195 SVN_WC_TRANSLATE_FORCE_EOL_REPAIR
: 0),
201 svn_wc__get_eol_style(svn_subst_eol_style_t
*style
,
204 svn_wc_adm_access_t
*adm_access
,
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
,
214 svn_subst_eol_style_from_value(style
, eol
, propval
? propval
->data
: NULL
);
221 svn_wc__eol_value_from_string(const char **value
, const char *eol
)
225 else if (! strcmp("\n", eol
))
227 else if (! strcmp("\r", eol
))
229 else if (! strcmp("\r\n", eol
))
237 svn_wc__get_keywords(apr_hash_t
**keywords
,
239 svn_wc_adm_access_t
*adm_access
,
240 const char *force_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
,
255 list
= propval
? propval
->data
: NULL
;
260 /* The easy answer. */
267 SVN_ERR(svn_wc__entry_versioned(&entry
, path
, adm_access
, FALSE
, pool
));
269 SVN_ERR(svn_subst_build_keywords2(keywords
,
271 apr_psprintf(pool
, "%ld",
278 if (apr_hash_count(*keywords
) == 0)
286 svn_wc__get_special(svn_boolean_t
*special
,
288 svn_wc_adm_access_t
*adm_access
,
291 const svn_string_t
*propval
;
293 /* Get the property value. */
294 SVN_ERR(svn_wc_prop_get(&propval
, SVN_PROP_SPECIAL
, path
,
296 *special
= propval
!= NULL
;
303 svn_wc__maybe_set_executable(svn_boolean_t
*did_set
,
305 svn_wc_adm_access_t
*adm_access
,
308 const svn_string_t
*propval
;
309 SVN_ERR(svn_wc_prop_get(&propval
, SVN_PROP_EXECUTABLE
, path
, adm_access
,
314 SVN_ERR(svn_io_set_file_executable(path
, TRUE
, FALSE
, pool
));
326 svn_wc__maybe_set_read_only(svn_boolean_t
*did_set
,
328 svn_wc_adm_access_t
*adm_access
,
331 const svn_string_t
*needs_lock
;
332 const svn_wc_entry_t
* entry
;
337 SVN_ERR(svn_wc_entry(&entry
, path
, adm_access
, FALSE
, pool
));
338 if (entry
&& entry
->lock_token
)
341 SVN_ERR(svn_wc_prop_get(&needs_lock
, SVN_PROP_NEEDS_LOCK
, path
,
344 if (needs_lock
!= NULL
)
346 SVN_ERR(svn_io_set_file_read_only(path
, FALSE
, pool
));