📄 subst.c
字号:
const char *eol_str,
svn_boolean_t repair,
const svn_subst_keywords_t *keywords,
svn_boolean_t expand,
apr_pool_t *pool)
{
return svn_subst_copy_and_translate2 (src, dst, eol_str, repair, keywords,
expand, FALSE, pool);
}
/* Given a special file at SRC, generate a textual representation of
it in a normal file at DST. Perform all allocations in POOL. */
static svn_error_t *
detranslate_special_file (const char *src,
const char *dst,
apr_pool_t *pool)
{
const char *dst_tmp;
svn_string_t *buf;
apr_file_t *s, *d;
svn_stream_t *src_stream, *dst_stream;
apr_finfo_t finfo;
/* First determine what type of special file we are
detranslating. */
SVN_ERR (svn_io_stat (&finfo, src, APR_FINFO_MIN | APR_FINFO_LINK, pool));
/* Open a temporary destination that we will eventually atomically
rename into place. */
SVN_ERR (svn_io_open_unique_file (&d, &dst_tmp, dst,
".tmp", FALSE, pool));
dst_stream = svn_stream_from_aprfile (d, pool);
switch (finfo.filetype) {
case APR_REG:
/* Nothing special to do here, just copy the original file's
contents. */
SVN_ERR (svn_io_file_open (&s, src, APR_READ | APR_BUFFERED,
APR_OS_DEFAULT, pool));
src_stream = svn_stream_from_aprfile (d, pool);
SVN_ERR (svn_stream_copy (src_stream, dst_stream, pool));
break;
case APR_LNK:
/* Determine the destination of the link. */
SVN_ERR (svn_io_read_link (&buf, src, pool));
SVN_ERR (svn_stream_printf (dst_stream, pool, "link %s",
buf->data));
break;
default:
abort ();
}
SVN_ERR (svn_io_file_close (d, pool));
/* Do the atomic rename from our temporary location. */
SVN_ERR (svn_io_file_rename (dst_tmp, dst, pool));
return SVN_NO_ERROR;
}
/* Given a file containing a repository representation of a special
file in SRC, create the appropriate special file at location DST.
Perform all allocations in POOL. */
static svn_error_t *
create_special_file (const char *src,
const char *dst,
apr_pool_t *pool)
{
svn_stringbuf_t *contents;
char *identifier, *remainder;
const char *dst_tmp, *src_tmp = NULL;
svn_error_t *err;
svn_node_kind_t kind;
svn_boolean_t is_special;
/* Check to see if we are being asked to create a special file from
a special file. If so, do a temporary detranslation and work
from there. */
SVN_ERR (svn_io_check_special_path (src, &kind, &is_special, pool));
if (is_special)
{
apr_file_t *fp;
SVN_ERR (svn_io_open_unique_file (&fp, &src_tmp, dst, ".tmp", FALSE,
pool));
SVN_ERR (svn_io_file_close (fp, pool));
SVN_ERR (detranslate_special_file (src, src_tmp, pool));
src = src_tmp;
}
/* Read in the detranslated file. */
SVN_ERR (svn_stringbuf_from_file (&contents, src, pool));
/* If there was just a temporary detranslation, remove it now. */
if (src_tmp)
SVN_ERR (svn_io_remove_file (src_tmp, pool));
/* Separate off the identifier. The first space character delimits
the identifier, after which any remaining characters are specific
to the actual special device being created. */
identifier = contents->data;
for (remainder = identifier; *remainder; remainder++)
{
if (*remainder == ' ')
{
*remainder = '\0';
remainder++;
break;
}
}
if (! strcmp (identifier, SVN_SUBST__SPECIAL_LINK_STR))
{
/* For symlinks, the type specific data is just a filesystem
path that the symlink should reference. */
err = svn_io_create_unique_link (&dst_tmp, dst, remainder,
".tmp", pool);
}
else
{
/* We should return a valid error here. */
return svn_error_createf (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
"Unsupported special file type '%s'",
identifier);
}
/* If we had an error, check to see if it was because this type of
special device is not supported. */
if (err)
{
if (err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)
{
apr_file_t *fp;
svn_error_clear (err);
/* Fall back to just copying the text-base. */
SVN_ERR (svn_io_open_unique_file (&fp, &dst_tmp, dst, ".tmp", FALSE,
pool));
SVN_ERR (svn_io_file_close (fp, pool));
SVN_ERR (svn_io_copy_file (src, dst_tmp, TRUE, pool));
}
else
return err;
}
/* Do the atomic rename from our temporary location. */
SVN_ERR (svn_io_file_rename (dst_tmp, dst, pool));
return SVN_NO_ERROR;
}
svn_error_t *
svn_subst_copy_and_translate2 (const char *src,
const char *dst,
const char *eol_str,
svn_boolean_t repair,
const svn_subst_keywords_t *keywords,
svn_boolean_t expand,
svn_boolean_t special,
apr_pool_t *pool)
{
const char *dst_tmp = NULL;
svn_stream_t *src_stream, *dst_stream;
apr_file_t *s = NULL, *d = NULL; /* init to null important for APR */
svn_error_t *err;
apr_pool_t *subpool;
svn_node_kind_t kind;
svn_boolean_t path_special;
SVN_ERR (svn_io_check_special_path (src, &kind, &path_special, pool));
/* If this is a 'special' file, we may need to create it or
detranslate it. */
if (special || path_special)
{
if (expand)
SVN_ERR (create_special_file (src, dst, pool));
else
SVN_ERR (detranslate_special_file (src, dst, pool));
return SVN_NO_ERROR;
}
/* The easy way out: no translation needed, just copy. */
if (! (eol_str || keywords))
return svn_io_copy_file (src, dst, FALSE, pool);
subpool = svn_pool_create (pool);
/* Open source file. */
err = svn_io_file_open (&s, src, APR_READ | APR_BUFFERED,
APR_OS_DEFAULT, subpool);
if (err)
goto error;
/* For atomicity, we translate to a tmp file and
then rename the tmp file over the real destination. */
err = svn_io_open_unique_file (&d, &dst_tmp, dst,
".tmp", FALSE, subpool);
/* Move the file name to a more permanent pool. */
if (dst_tmp)
dst_tmp = apr_pstrdup(pool, dst_tmp);
if (err)
goto error;
/* Now convert our two open files into streams. */
src_stream = svn_stream_from_aprfile (s, subpool);
dst_stream = svn_stream_from_aprfile (d, subpool);
/* Translate src stream into dst stream. */
err = svn_subst_translate_stream (src_stream, dst_stream,
eol_str, repair, keywords, expand);
if (err)
{
if (err->apr_err == SVN_ERR_IO_INCONSISTENT_EOL)
err = svn_error_createf
(SVN_ERR_IO_INCONSISTENT_EOL, err,
_("File '%s' has inconsistent newlines"), src);
goto error;
}
/* clean up nicely. */
err = svn_stream_close (src_stream);
if (err)
goto error;
err = svn_stream_close (dst_stream);
if (err)
goto error;
err = svn_io_file_close (s, subpool);
if (err)
goto error;
err = svn_io_file_close (d, subpool);
if (err)
goto error;
/* Now that dst_tmp contains the translated data, do the atomic rename. */
err = svn_io_file_rename (dst_tmp, dst, subpool);
if (err)
goto error;
svn_pool_destroy (subpool);
return SVN_NO_ERROR;
error:
svn_pool_destroy (subpool); /* Make sure all files are closed first. */
if (dst_tmp)
svn_error_clear (svn_io_remove_file (dst_tmp, pool));
return err;
}
svn_error_t *
svn_subst_translate_string (svn_string_t **new_value,
const svn_string_t *value,
const char *encoding,
apr_pool_t *pool)
{
const char *val_utf8;
const char *val_utf8_lf;
if (value == NULL)
{
*new_value = NULL;
return SVN_NO_ERROR;
}
if (encoding)
{
SVN_ERR (svn_utf_cstring_to_utf8_ex (&val_utf8, value->data,
encoding, NULL, pool));
}
else
{
SVN_ERR (svn_utf_cstring_to_utf8 (&val_utf8, value->data, pool));
}
SVN_ERR (svn_subst_translate_cstring (val_utf8,
&val_utf8_lf,
"\n", /* translate to LF */
FALSE, /* no repair */
NULL, /* no keywords */
FALSE, /* no expansion */
pool));
*new_value = svn_string_create (val_utf8_lf, pool);
return SVN_NO_ERROR;
}
svn_error_t *
svn_subst_detranslate_string (svn_string_t **new_value,
const svn_string_t *value,
svn_boolean_t for_output,
apr_pool_t *pool)
{
svn_error_t *err;
const char *val_neol;
const char *val_nlocale_neol;
if (value == NULL)
{
*new_value = NULL;
return SVN_NO_ERROR;
}
SVN_ERR (svn_subst_translate_cstring (value->data,
&val_neol,
APR_EOL_STR, /* 'native' eol */
FALSE, /* no repair */
NULL, /* no keywords */
FALSE, /* no expansion */
pool));
if (for_output)
{
err = svn_cmdline_cstring_from_utf8 (&val_nlocale_neol, val_neol, pool);
if (err && (APR_STATUS_IS_EINVAL (err->apr_err)))
{
val_nlocale_neol =
svn_cmdline_cstring_from_utf8_fuzzy (val_neol, pool);
svn_error_clear (err);
}
else if (err)
return err;
}
else
{
err = svn_utf_cstring_from_utf8 (&val_nlocale_neol, val_neol, pool);
if (err && (APR_STATUS_IS_EINVAL (err->apr_err)))
{
val_nlocale_neol = svn_utf_cstring_from_utf8_fuzzy (val_neol, pool);
svn_error_clear (err);
}
else if (err)
return err;
}
*new_value = svn_string_create (val_nlocale_neol, pool);
return SVN_NO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -