📄 adm_files.c
字号:
else return close_adm_file (fp, parent_dir, 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) return sync_adm_file(parent_dir, NULL, pool, SVN_WC__ADM_DIR_PROP_BASE, NULL); else return sync_adm_file(parent_dir, SVN_WC__BASE_EXT, pool, SVN_WC__ADM_PROP_BASE, base_name, NULL); } else if (wcprops) { if (kind == svn_node_dir) return sync_adm_file(parent_dir, NULL, pool, SVN_WC__ADM_DIR_WCPROPS, NULL); else return sync_adm_file(parent_dir, SVN_WC__BASE_EXT, pool, SVN_WC__ADM_WCPROPS, base_name, NULL); } else /* plain old property file */ { if (kind == svn_node_dir) return sync_adm_file(parent_dir, NULL, pool, SVN_WC__ADM_DIR_PROPS, NULL); else return sync_adm_file(parent_dir, SVN_WC__WORK_EXT, pool, SVN_WC__ADM_PROPS, base_name, NULL); }}/*** Checking for and creating administrative subdirs. ***//* Set *EXISTS to true iff there's an adm area for PATH, and it matches URL * and REVISION. If there's no adm area, set *EXISTS to false; if * there's an adm area but it doesn't match URL and REVISION, then * return error and don't touch *EXISTS. * * ### These semantics are totally bizarre. One wonders what the * ### callers' real needs are. In the long term, this function * ### should probably be unified with svn_wc_check_wc. */static svn_error_t *check_adm_exists(svn_boolean_t *exists, const char *path, const char *url, svn_revnum_t revision, apr_pool_t *pool){ svn_error_t *err = SVN_NO_ERROR; svn_node_kind_t kind; svn_boolean_t dir_exists = FALSE, wc_exists = FALSE; const char *tmp_path; /** Step 1: check that the directory exists. **/ tmp_path = extend_with_adm_name(path, NULL, 0, pool, NULL); SVN_ERR(svn_io_check_path(tmp_path, &kind, pool)); if (kind != svn_node_none && kind != svn_node_dir) { /* If got an error other than dir non-existence, then something's weird and we should return a genuine error. */ return svn_error_createf(APR_ENOTDIR, NULL, _("'%s' is not a directory"), svn_path_local_style(tmp_path, pool)); } else if (kind == svn_node_none) { dir_exists = FALSE; } else /* must be a dir. */ { assert(kind == svn_node_dir); dir_exists = TRUE; } /** Step 1. If no adm directory, then we're done. */ if (! dir_exists) { *exists = FALSE; return SVN_NO_ERROR; } /** The directory exists, but is it a valid working copy yet? Try step 2: checking that we can read the format number. */ { int wc_format; err = svn_io_read_version_file (&wc_format, svn_path_join(tmp_path, SVN_WC__ADM_ENTRIES, pool), pool); /* Fall back on the format file for WCs before format 7. */ if (err) { svn_error_clear(err); err = svn_io_read_version_file (&wc_format, svn_path_join(tmp_path, SVN_WC__ADM_FORMAT, pool), pool); } if (err) { svn_error_clear(err); wc_exists = FALSE; } else wc_exists = TRUE; } /** Step 3: now check that repos and ancestry are correct **/ if (wc_exists) { /* This is a bit odd. We have to open an access baton, which relies on this being a working copy, in order to determine if this is a working copy! */ svn_wc_adm_access_t *adm_access; const svn_wc_entry_t *entry; SVN_ERR(svn_wc_adm_open3(&adm_access, NULL, path, FALSE, 0, NULL, NULL, pool)); SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool)); SVN_ERR(svn_wc_adm_close(adm_access)); if (!entry) return svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL, _("No entry for '%s'"), svn_path_local_style(path, pool)); /* When the directory exists and is scheduled for deletion do not * check the revision or the URL. The revision can be any * arbitrary revision and the URL may differ if the add is * being driven from a merge which will have a different URL. */ if (entry->schedule != svn_wc_schedule_delete) { if (entry->revision != revision) return svn_error_createf (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL, _("Revision %ld doesn't match existing revision %ld in '%s'"), revision, entry->revision, path); /** ### comparing URLs, should they be canonicalized first? */ if (strcmp(entry->url, url) != 0) return svn_error_createf (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL, _("URL '%s' doesn't match existing URL '%s' in '%s'"), url, entry->url, path); } } *exists = wc_exists; return SVN_NO_ERROR;}static svn_error_t *make_empty_adm(const char *path, apr_pool_t *pool){ path = extend_with_adm_name(path, NULL, 0, pool, NULL); SVN_ERR(svn_io_dir_make_hidden(path, APR_OS_DEFAULT, pool)); return SVN_NO_ERROR;}static svn_error_t *init_adm_tmp_area(svn_wc_adm_access_t *adm_access, apr_pool_t *pool){ /* Default perms */ apr_fileperms_t perms = APR_OS_DEFAULT; /* SVN_WC__ADM_TMP */ SVN_ERR(svn_wc__make_adm_thing(adm_access, SVN_WC__ADM_TMP, svn_node_dir, perms, 0, pool)); /* SVN_WC__ADM_TMP/SVN_WC__ADM_TEXT_BASE */ SVN_ERR(svn_wc__make_adm_thing(adm_access, SVN_WC__ADM_TEXT_BASE, svn_node_dir, perms, 1, pool)); /* SVN_WC__ADM_TMP/SVN_WC__ADM_PROP_BASE */ SVN_ERR(svn_wc__make_adm_thing(adm_access, SVN_WC__ADM_PROP_BASE, svn_node_dir, perms, 1, pool)); /* SVN_WC__ADM_TMP/SVN_WC__ADM_PROPS */ SVN_ERR(svn_wc__make_adm_thing(adm_access, SVN_WC__ADM_PROPS, svn_node_dir, perms, 1, pool)); return SVN_NO_ERROR;}/* Set up a new adm area for PATH, with URL as the ancestor url, and INITIAL_REV as the starting revision. The entries file starts out marked as 'incomplete. The adm area starts out locked; remember to unlock it when done. */static svn_error_t *init_adm(const char *path, const char *uuid, const char *url, const char *repos, svn_revnum_t initial_rev, apr_pool_t *pool){ svn_wc_adm_access_t *adm_access; /* Default perms */ apr_fileperms_t perms = APR_OS_DEFAULT; /* First, make an empty administrative area. */ SVN_ERR(make_empty_adm(path, pool)); /* Lock it immediately. Theoretically, no compliant wc library would ever consider this an adm area until a README file were present... but locking it is still appropriately paranoid. */ SVN_ERR(svn_wc__adm_pre_open(&adm_access, path, pool)); /** Make subdirectories. ***/ /* SVN_WC__ADM_TEXT_BASE */ SVN_ERR(svn_wc__make_adm_thing(adm_access, SVN_WC__ADM_TEXT_BASE, svn_node_dir, perms, 0, pool)); /* SVN_WC__ADM_PROP_BASE */ SVN_ERR(svn_wc__make_adm_thing(adm_access, SVN_WC__ADM_PROP_BASE, svn_node_dir, perms, 0, pool)); /* SVN_WC__ADM_PROPS */ SVN_ERR(svn_wc__make_adm_thing(adm_access, SVN_WC__ADM_PROPS, svn_node_dir, perms, 0, pool)); /** Init the tmp area. ***/ SVN_ERR(init_adm_tmp_area(adm_access, pool)); /** Initialize each administrative file. */ /* SVN_WC__ADM_ENTRIES */ /* THIS FILE MUST BE CREATED LAST: After this exists, the dir is considered complete. */ SVN_ERR(svn_wc__entries_init(path, uuid, url, repos, initial_rev, pool)); /* We provide this for backwards compatibilty. Clients that don't understand format version 7 or higher will display a nicer error message if this file exists. ### Consider removing this in svn 1.5 or 1.6. */ SVN_ERR(svn_io_write_version_file (extend_with_adm_name(path, NULL, FALSE, pool, SVN_WC__ADM_FORMAT, NULL), SVN_WC__VERSION, pool)); /* Now unlock it. It's now a valid working copy directory, that just happens to be at revision 0. */ SVN_ERR(svn_wc_adm_close(adm_access)); /* Else no problems, we're outta here. */ return SVN_NO_ERROR;}svn_error_t *svn_wc_ensure_adm2(const char *path, const char *uuid, const char *url, const char *repos, svn_revnum_t revision, apr_pool_t *pool){ svn_boolean_t exists_already; SVN_ERR(check_adm_exists(&exists_already, path, url, revision, pool)); return (exists_already ? SVN_NO_ERROR : init_adm(path, uuid, url, repos, revision, pool));}svn_error_t *svn_wc_ensure_adm(const char *path, const char *uuid, const char *url, svn_revnum_t revision, apr_pool_t *pool){ return svn_wc_ensure_adm2(path, uuid, url, NULL, revision, pool);}svn_error_t *svn_wc__adm_destroy(svn_wc_adm_access_t *adm_access, apr_pool_t *pool){ const char *path; SVN_ERR(svn_wc__adm_write_check(adm_access)); /* Well, the coast is clear for blowing away the administrative directory, which also removes the lock file */ path = extend_with_adm_name(svn_wc_adm_access_path(adm_access), NULL, FALSE, pool, NULL); SVN_ERR(svn_io_remove_dir(path, pool)); SVN_ERR(svn_wc_adm_close(adm_access)); return SVN_NO_ERROR;}svn_error_t *svn_wc__adm_cleanup_tmp_area(svn_wc_adm_access_t *adm_access, apr_pool_t *pool){ const char *tmp_path; SVN_ERR(svn_wc__adm_write_check(adm_access)); /* Get the path to the tmp area, and blow it away. */ tmp_path = extend_with_adm_name(svn_wc_adm_access_path(adm_access), NULL, 0, pool, SVN_WC__ADM_TMP, NULL); SVN_ERR(svn_io_remove_dir(tmp_path, pool)); /* Now, rebuild the tmp area. */ SVN_ERR(init_adm_tmp_area(adm_access, pool)); return SVN_NO_ERROR;}svn_error_t *svn_wc_create_tmp_file2(apr_file_t **fp, const char **new_name, const char *path, svn_io_file_del_t delete_when, apr_pool_t *pool){ apr_file_t *file; assert(fp || new_name); /* Use a self-explanatory name for the file :-) . */ path = svn_wc__adm_path(path, TRUE, pool, "tempfile", NULL); /* Open a unique file; use APR_DELONCLOSE. */ SVN_ERR(svn_io_open_unique_file2(&file, new_name, path, ".tmp", delete_when, pool)); if (fp) *fp = file; else SVN_ERR(svn_io_file_close(file, pool)); return SVN_NO_ERROR;}svn_error_t *svn_wc_create_tmp_file(apr_file_t **fp, const char *path, svn_boolean_t delete_on_close, apr_pool_t *pool){ return svn_wc_create_tmp_file2(fp, NULL, path, delete_on_close ? svn_io_file_del_on_close : svn_io_file_del_none, pool);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -