📄 adm_files.c
字号:
const char *path,
const char *extension,
apr_fileperms_t protection,
apr_int32_t flags,
apr_pool_t *pool,
...)
{
svn_error_t *err = SVN_NO_ERROR;
va_list ap;
/* If we're writing, always do it to a tmp file. */
if (flags & APR_WRITE)
{
if (flags & APR_APPEND)
{
/* We don't handle append. To do so we would need to copy the
contents into the apr_file_t once it has been opened. */
return svn_error_create
(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
_("APR_APPEND not supported for adm files"));
}
/* Need to own the temporary file, so don't reuse an existing one. */
flags |= APR_EXCL | APR_CREATE;
/* Extend with tmp name. */
va_start (ap, pool);
path = v_extend_with_adm_name (path, extension, 1, pool, ap);
va_end (ap);
}
else
{
/* Extend with regular adm name. */
va_start (ap, pool);
path = v_extend_with_adm_name (path, extension, 0, pool, ap);
va_end (ap);
}
err = svn_io_file_open (handle, path, flags, protection, pool);
if ((flags & APR_WRITE) && err && APR_STATUS_IS_EEXIST(err->apr_err))
{
/* Exclusive open failed, delete and retry */
svn_error_clear (err);
SVN_ERR (svn_io_remove_file (path, pool));
err = svn_io_file_open (handle, path, flags, protection, pool);
}
if (err)
{
/* Oddly enough, APR will set *HANDLE even if the open failed.
You'll get a filehandle whose descriptor is -1. There must
be a reason this is useful... Anyway, we don't want the
handle. */
*handle = NULL;
/* If we receive a failure to open a file in our temporary directory,
* it may be because our temporary directories aren't created.
* Older SVN clients did not create these directories.
* 'svn cleanup' will fix this problem.
*/
if (APR_STATUS_IS_ENOENT(err->apr_err) && (flags & APR_WRITE))
{
err = svn_error_quick_wrap(err,
_("Your .svn/tmp directory may be missing or "
"corrupt; run 'svn cleanup' and try again"));
}
}
return err;
}
/* Close the file indicated by FP (PATH is passed to make error
* reporting better). If SYNC is non-zero, then the file will be
* sync'd from the adm tmp area to its permanent location, otherwise
* it will remain in the tmp area. See open_adm_file().
*/
static svn_error_t *
close_adm_file (apr_file_t *fp,
const char *path,
const char *extension,
svn_boolean_t sync,
apr_pool_t *pool,
...)
{
const char *tmp_path;
va_list ap;
/* Get the full name of the thing we're closing. */
va_start (ap, pool);
tmp_path = v_extend_with_adm_name (path, extension, sync, pool, ap);
va_end (ap);
SVN_ERR (svn_io_file_close (fp, pool));
/* If we're syncing a tmp file, it needs to be renamed after closing. */
if (sync)
{
/* Some code duplication with sync_adm_file() seems unavoidable,
given how C va_lists work. */
/* Obtain dest name. */
va_start (ap, pool);
path = v_extend_with_adm_name (path, extension, 0, pool, ap);
va_end (ap);
/* Rename. */
SVN_ERR (svn_wc__prep_file_for_replacement (path, TRUE, pool));
SVN_ERR (svn_io_file_rename (tmp_path, path, pool));
SVN_ERR (svn_io_set_file_read_only (path, FALSE, pool));
return SVN_NO_ERROR;
}
return SVN_NO_ERROR;
}
svn_error_t *
svn_wc__open_adm_file (apr_file_t **handle,
const char *path,
const char *fname,
apr_int32_t flags,
apr_pool_t *pool)
{
return open_adm_file (handle, path, NULL, APR_OS_DEFAULT, flags, pool,
fname, NULL);
}
svn_error_t *
svn_wc__close_adm_file (apr_file_t *fp,
const char *path,
const char *fname,
int sync,
apr_pool_t *pool)
{
return close_adm_file (fp, path, NULL, sync, pool, fname, NULL);
}
svn_error_t *
svn_wc__remove_adm_file (const char *path, apr_pool_t *pool, ...)
{
va_list ap;
va_start (ap, pool);
path = v_extend_with_adm_name (path, NULL, 0, pool, ap);
va_end (ap);
SVN_ERR(svn_io_remove_file (path, pool));
return SVN_NO_ERROR;
}
const char *
svn_wc__empty_file_path (const char *path,
apr_pool_t *pool)
{
const char *parent_path = svn_path_dirname (path, pool);
return extend_with_adm_name (parent_path, NULL, 0, pool,
SVN_WC__ADM_EMPTY_FILE, NULL);
}
svn_error_t *
svn_wc__open_empty_file (apr_file_t **handle,
const char *path,
apr_pool_t *pool)
{
const char *parent_path = svn_path_dirname (path, pool);
return open_adm_file (handle, parent_path, NULL, APR_OS_DEFAULT, APR_READ,
pool, SVN_WC__ADM_EMPTY_FILE, NULL);
}
svn_error_t *
svn_wc__close_empty_file (apr_file_t *fp,
const char *path,
apr_pool_t *pool)
{
const char *parent_path = svn_path_dirname (path, pool);
return close_adm_file (fp, parent_path, NULL, 0, pool,
SVN_WC__ADM_EMPTY_FILE, NULL);
}
svn_error_t *
svn_wc__open_text_base (apr_file_t **handle,
const char *path,
apr_int32_t flags,
apr_pool_t *pool)
{
const char *parent_path, *base_name;
svn_path_split (path, &parent_path, &base_name, pool);
return open_adm_file (handle, parent_path, SVN_WC__BASE_EXT, APR_OS_DEFAULT,
flags, pool, SVN_WC__ADM_TEXT_BASE, base_name, NULL);
}
svn_error_t *
svn_wc__close_text_base (apr_file_t *fp,
const char *path,
int write,
apr_pool_t *pool)
{
const char *parent_path, *base_name;
svn_path_split (path, &parent_path, &base_name, pool);
return close_adm_file (fp, parent_path, SVN_WC__BASE_EXT, write, pool,
SVN_WC__ADM_TEXT_BASE, base_name, NULL);
}
svn_error_t *
svn_wc__open_props (apr_file_t **handle,
const char *path,
apr_int32_t flags,
svn_boolean_t base,
svn_boolean_t wcprops,
apr_pool_t *pool)
{
const char *parent_dir, *base_name;
svn_node_kind_t kind;
int wc_format_version;
SVN_ERR (svn_io_check_path (path, &kind, pool));
if (kind == svn_node_dir)
parent_dir = path;
else
svn_path_split (path, &parent_dir, &base_name, pool);
/* At this point, we know we need to open a file in the admin area
of parent_dir. First check that parent_dir is a working copy: */
SVN_ERR (svn_wc_check_wc (parent_dir, &wc_format_version, pool));
if (wc_format_version == 0)
return svn_error_createf
(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
_("'%s' is not a working copy"), parent_dir);
/* Then examine the flags to know -which- kind of prop file to get. */
if (base && wcprops)
return svn_error_create (SVN_ERR_WC_PATH_NOT_FOUND, NULL,
_("No such thing as 'base' "
"working copy properties!"));
else if (base)
{
if (kind == svn_node_dir)
return open_adm_file (handle, parent_dir, NULL, APR_OS_DEFAULT, flags,
pool, SVN_WC__ADM_DIR_PROP_BASE, NULL);
else
return open_adm_file (handle, parent_dir, SVN_WC__BASE_EXT,
APR_OS_DEFAULT, flags, pool,
SVN_WC__ADM_PROP_BASE, base_name, NULL);
}
else if (wcprops)
{
if (kind == svn_node_dir)
return open_adm_file (handle, parent_dir, NULL, APR_OS_DEFAULT, flags,
pool, SVN_WC__ADM_DIR_WCPROPS, NULL);
else
{
return open_adm_file
(handle, parent_dir,
((wc_format_version <= SVN_WC__OLD_PROPNAMES_VERSION) ?
NULL : SVN_WC__WORK_EXT), APR_OS_DEFAULT,
flags, pool, SVN_WC__ADM_WCPROPS, base_name, NULL);
}
}
else /* plain old property file */
{
if (kind == svn_node_dir)
return open_adm_file (handle, parent_dir, NULL, APR_OS_DEFAULT, flags,
pool, SVN_WC__ADM_DIR_PROPS, NULL);
else
{
return open_adm_file
(handle, parent_dir,
((wc_format_version <= SVN_WC__OLD_PROPNAMES_VERSION) ?
NULL : SVN_WC__WORK_EXT), APR_OS_DEFAULT,
flags, pool, SVN_WC__ADM_PROPS, base_name, NULL);
}
}
}
svn_error_t *
svn_wc__close_props (apr_file_t *fp,
const char *path,
svn_boolean_t base,
svn_boolean_t wcprops,
int sync,
apr_pool_t *pool)
{
const char *parent_dir, *base_name;
svn_node_kind_t kind;
int wc_format_version;
SVN_ERR (svn_io_check_path (path, &kind, pool));
if (kind == svn_node_dir)
parent_dir = path;
else
svn_path_split (path, &parent_dir, &base_name, pool);
/* At this point, we know we need to open a file in the admin area
of parent_dir. First check that parent_dir is a working copy: */
SVN_ERR (svn_wc_check_wc (parent_dir, &wc_format_version, pool));
if (wc_format_version == 0)
return svn_error_createf
(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
_("'%s' is not a working copy"), parent_dir);
/* Then examine the flags to know -which- kind of prop file to get. */
if (base && wcprops)
return svn_error_create (SVN_ERR_WC_PATH_NOT_FOUND, NULL,
_("No such thing as 'base' "
"working copy properties!"));
else if (base)
{
if (kind == svn_node_dir)
return close_adm_file (fp, parent_dir, NULL, sync, pool,
SVN_WC__ADM_DIR_PROP_BASE, NULL);
else
return close_adm_file (fp, parent_dir, SVN_WC__BASE_EXT, sync, pool,
SVN_WC__ADM_PROP_BASE, base_name, NULL);
}
else if (wcprops)
{
if (kind == svn_node_dir)
return close_adm_file (fp, parent_dir, NULL, sync, pool,
SVN_WC__ADM_DIR_WCPROPS, NULL);
else
return close_adm_file
(fp, parent_dir,
((wc_format_version <= SVN_WC__OLD_PROPNAMES_VERSION) ?
NULL : SVN_WC__WORK_EXT),
sync, pool, SVN_WC__ADM_WCPROPS, base_name, NULL);
}
else /* plain old property file */
{
if (kind == svn_node_dir)
return close_adm_file (fp, parent_dir, NULL, sync, pool,
SVN_WC__ADM_DIR_PROPS, NULL);
else
return close_adm_file
(fp, parent_dir,
((wc_format_version <= SVN_WC__OLD_PROPNAMES_VERSION) ?
NULL : SVN_WC__WORK_EXT),
sync, pool, SVN_WC__ADM_PROPS, base_name, NULL);
}
}
svn_error_t *
svn_wc__sync_props (const char *path,
svn_boolean_t base,
svn_boolean_t wcprops,
apr_pool_t *pool)
{
const char *parent_dir, *base_name;
svn_node_kind_t kind;
/* Check if path is a file or a dir. */
SVN_ERR (svn_io_check_path (path, &kind, pool));
/* If file, split the path. */
if (kind == svn_node_file)
svn_path_split (path, &parent_dir, &base_name, pool);
else
parent_dir = path;
/* At this point, we know we need to open a file in the admin area
of parent_dir. Examine the flags to know -which- kind of prop
file to get -- there are three types! */
if (base && wcprops)
return svn_error_create (SVN_ERR_WC_PATH_NOT_FOUND, NULL,
_("No such thing as 'base' "
"working copy properties!"));
else if (base)
{
if (kind == svn_node_dir)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -