📄 adm_ops.c
字号:
/* * adm_ops.c: routines for affecting working copy administrative * information. NOTE: this code doesn't know where the adm * info is actually stored. Instead, generic handles to * adm data are requested via a reference to some PATH * (PATH being a regular, non-administrative directory or * file in the working copy). * * ==================================================================== * Copyright (c) 2000-2006 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#include <string.h>#include <apr_pools.h>#include <apr_hash.h>#include <apr_md5.h>#include <apr_file_io.h>#include <apr_time.h>#include "svn_types.h"#include "svn_pools.h"#include "svn_string.h"#include "svn_error.h"#include "svn_path.h"#include "svn_wc.h"#include "svn_io.h"#include "svn_md5.h"#include "svn_xml.h"#include "svn_time.h"#include "wc.h"#include "log.h"#include "adm_files.h"#include "adm_ops.h"#include "entries.h"#include "lock.h"#include "props.h"#include "translate.h"#include "svn_private_config.h"/*** Finishing updates and commits. ***//* The main body of svn_wc__do_update_cleanup. */static svn_error_t *tweak_entries(svn_wc_adm_access_t *dirpath, const char *base_url, const char *repos, svn_revnum_t new_rev, svn_wc_notify_func2_t notify_func, void *notify_baton, svn_boolean_t remove_missing_dirs, svn_boolean_t recurse, apr_pool_t *pool){ apr_hash_t *entries; apr_hash_index_t *hi; apr_pool_t *subpool = svn_pool_create(pool); svn_boolean_t write_required = FALSE; svn_wc_notify_t *notify; /* Read DIRPATH's entries. */ SVN_ERR(svn_wc_entries_read(&entries, dirpath, TRUE, pool)); /* Tweak "this_dir" */ SVN_ERR(svn_wc__tweak_entry(entries, SVN_WC_ENTRY_THIS_DIR, base_url, repos, new_rev, FALSE, &write_required, svn_wc_adm_access_pool(dirpath))); /* Recursively loop over all children. */ for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi)) { const void *key; void *val; const char *name; svn_wc_entry_t *current_entry; const char *child_url = NULL; svn_pool_clear(subpool); apr_hash_this(hi, &key, NULL, &val); name = key; current_entry = val; /* Ignore the "this dir" entry. */ if (! strcmp(name, SVN_WC_ENTRY_THIS_DIR)) continue; /* Derive the new URL for the current (child) entry */ if (base_url) child_url = svn_path_url_add_component(base_url, name, subpool); /* If a file, or deleted or absent dir in recursive mode, then tweak the entry but don't recurse. */ if ((current_entry->kind == svn_node_file) || (recurse && (current_entry->deleted || current_entry->absent))) { SVN_ERR(svn_wc__tweak_entry(entries, name, child_url, repos, new_rev, TRUE, &write_required, svn_wc_adm_access_pool(dirpath))); } /* If a directory and recursive... */ else if (recurse && (current_entry->kind == svn_node_dir)) { const char *child_path = svn_path_join(svn_wc_adm_access_path(dirpath), name, subpool); /* If the directory is 'missing', remove it. This is safe as long as this function is only called as a helper to svn_wc__do_update_cleanup, since the update will already have restored any missing items that it didn't want to delete. */ if (remove_missing_dirs && svn_wc__adm_missing(dirpath, child_path)) { if (current_entry->schedule != svn_wc_schedule_add) { svn_wc__entry_remove(entries, name); if (notify_func) { notify = svn_wc_create_notify(child_path, svn_wc_notify_delete, subpool); notify->kind = current_entry->kind; (* notify_func)(notify_baton, notify, subpool); } } /* Else if missing item is schedule-add, do nothing. */ } /* Not missing, deleted, or absent, so recurse. */ else { svn_wc_adm_access_t *child_access; SVN_ERR(svn_wc_adm_retrieve(&child_access, dirpath, child_path, subpool)); SVN_ERR(tweak_entries (child_access, child_url, repos, new_rev, notify_func, notify_baton, remove_missing_dirs, recurse, subpool)); } } } /* Write a shiny new entries file to disk. */ if (write_required) SVN_ERR(svn_wc__entries_write(entries, dirpath, subpool)); /* Cleanup */ svn_pool_destroy(subpool); return SVN_NO_ERROR;}/* Helper for svn_wc_process_committed2. */static svn_error_t *remove_revert_file(svn_stringbuf_t **logtags, svn_wc_adm_access_t *adm_access, const char *base_name, svn_boolean_t is_prop, apr_pool_t * pool){ const char * revert_file; const svn_wc_entry_t *entry; svn_node_kind_t kind; SVN_ERR(svn_wc_entry(&entry, base_name, adm_access, FALSE, pool)); /*### Maybe assert (entry); calling remove_revert_file for an unversioned file is bogus */ if (! entry) return SVN_NO_ERROR; if (is_prop) SVN_ERR(svn_wc__prop_revert_path(&revert_file, base_name, entry->kind, FALSE, pool)); else revert_file = svn_wc__text_revert_path(base_name, FALSE, pool); SVN_ERR(svn_io_check_path (svn_path_join(svn_wc_adm_access_path(adm_access), revert_file, pool), &kind, pool)); if (kind == svn_node_file) SVN_ERR(svn_wc__loggy_remove(logtags, adm_access, revert_file, pool)); return SVN_NO_ERROR;}svn_error_t *svn_wc__do_update_cleanup(const char *path, svn_wc_adm_access_t *adm_access, svn_boolean_t recursive, const char *base_url, const char *repos, svn_revnum_t new_revision, svn_wc_notify_func2_t notify_func, void *notify_baton, svn_boolean_t remove_missing_dirs, apr_pool_t *pool){ apr_hash_t *entries; const svn_wc_entry_t *entry; SVN_ERR(svn_wc_entry(&entry, path, adm_access, TRUE, pool)); if (entry == NULL) return SVN_NO_ERROR; if (entry->kind == svn_node_file || (entry->kind == svn_node_dir && (entry->deleted || entry->absent))) { const char *parent, *base_name; svn_wc_adm_access_t *dir_access; svn_boolean_t write_required = FALSE; svn_path_split(path, &parent, &base_name, pool); SVN_ERR(svn_wc_adm_retrieve(&dir_access, adm_access, parent, pool)); SVN_ERR(svn_wc_entries_read(&entries, dir_access, TRUE, pool)); SVN_ERR(svn_wc__tweak_entry(entries, base_name, base_url, repos, new_revision, FALSE, /* Parent not updated so don't remove PATH entry */ &write_required, svn_wc_adm_access_pool(dir_access))); if (write_required) SVN_ERR(svn_wc__entries_write(entries, dir_access, pool)); } else if (entry->kind == svn_node_dir) { svn_wc_adm_access_t *dir_access; SVN_ERR(svn_wc_adm_retrieve(&dir_access, adm_access, path, pool)); SVN_ERR(tweak_entries(dir_access, base_url, repos, new_revision, notify_func, notify_baton, remove_missing_dirs, recursive, pool)); } else return svn_error_createf(SVN_ERR_NODE_UNKNOWN_KIND, NULL, _("Unrecognized node kind: '%s'"), svn_path_local_style(path, pool)); return SVN_NO_ERROR;}svn_error_t *svn_wc_maybe_set_repos_root(svn_wc_adm_access_t *adm_access, const char *path, const char *repos, apr_pool_t *pool){ apr_hash_t *entries; svn_boolean_t write_required = FALSE; const svn_wc_entry_t *entry; const char *base_name; svn_wc_adm_access_t *dir_access; SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool)); if (! entry) return SVN_NO_ERROR; if (entry->kind == svn_node_file) { const char *parent; svn_path_split(path, &parent, &base_name, pool); SVN_ERR(svn_wc__adm_retrieve_internal(&dir_access, adm_access, parent, pool)); } else { base_name = SVN_WC_ENTRY_THIS_DIR; SVN_ERR(svn_wc__adm_retrieve_internal(&dir_access, adm_access, path, pool)); } if (! dir_access) return SVN_NO_ERROR; SVN_ERR(svn_wc_entries_read(&entries, dir_access, TRUE, pool)); SVN_ERR(svn_wc__tweak_entry(entries, base_name, NULL, repos, SVN_INVALID_REVNUM, FALSE, &write_required, svn_wc_adm_access_pool(dir_access))); if (write_required) SVN_ERR(svn_wc__entries_write(entries, dir_access, pool)); return SVN_NO_ERROR;}static svn_error_t *process_committed_leaf(int log_number, const char *path, svn_wc_adm_access_t *adm_access, svn_boolean_t *recurse, svn_revnum_t new_revnum, const char *rev_date, const char *rev_author, apr_array_header_t *wcprop_changes, svn_boolean_t remove_lock, const unsigned char *digest, apr_pool_t *pool){ const char *base_name; const char *hex_digest = NULL; svn_wc_entry_t tmp_entry; apr_uint32_t modify_flags = 0; svn_stringbuf_t *logtags = svn_stringbuf_create("", pool); SVN_ERR(svn_wc__adm_write_check(adm_access)); /* Set PATH's working revision to NEW_REVNUM; if REV_DATE and REV_AUTHOR are both non-NULL, then set the 'committed-rev', 'committed-date', and 'last-author' entry values; and set the checksum if a file. */ base_name = svn_path_is_child(svn_wc_adm_access_path(adm_access), path, pool); if (base_name) { /* PATH must be some sort of file */ const char *latest_base; svn_node_kind_t kind; /* If the props or text revert file exists it needs to be deleted when * the file is committed. */ SVN_ERR(remove_revert_file(&logtags, adm_access, base_name, FALSE, pool)); SVN_ERR(remove_revert_file(&logtags, adm_access, base_name, TRUE, pool)); if (digest) hex_digest = svn_md5_digest_to_cstring(digest, pool); else { /* There may be a new text base sitting in the adm tmp area by now, because the commit succeeded. A file that is copied, but not otherwise modified, doesn't have a new text base, so we use the unmodified text base.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -