📄 log.c
字号:
/* * log.c: handle the adm area's log file. * * ==================================================================== * 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_strings.h>#include "svn_wc.h"#include "svn_error.h"#include "svn_string.h"#include "svn_xml.h"#include "svn_pools.h"#include "svn_io.h"#include "svn_path.h"#include "svn_time.h"#include "wc.h"#include "log.h"#include "props.h"#include "adm_files.h"#include "entries.h"#include "lock.h"#include "translate.h"#include "questions.h"#include "svn_private_config.h"/*** Constant definitions for xml generation/parsing ***//* Note: every entry in the logfile is either idempotent or atomic. * This allows us to remove the entire logfile when every entry in it * has been completed -- if you crash in the middle of running a * logfile, and then later are running over it again as part of the * recovery, a given entry is "safe" in the sense that you can either * tell it has already been done (in which case, ignore it) or you can * do it again without ill effect. * * All log commands are self-closing tags with attributes. *//** Log actions. **//* Set some attributes on SVN_WC__LOG_ATTR_NAME's entry. Unmentioned attributes are unaffected. */#define SVN_WC__LOG_MODIFY_ENTRY "modify-entry"/* Delete lock related fields from the entry SVN_WC__LOG_ATTR_NAME. */#define SVN_WC__LOG_DELETE_LOCK "delete-lock"/* Delete the entry SVN_WC__LOG_ATTR_NAME. */#define SVN_WC__LOG_DELETE_ENTRY "delete-entry"/* Move file SVN_WC__LOG_ATTR_NAME to SVN_WC__LOG_ATTR_DEST. */#define SVN_WC__LOG_MV "mv"/* Copy file SVN_WC__LOG_ATTR_NAME to SVN_WC__LOG_ATTR_DEST. */#define SVN_WC__LOG_CP "cp"/* Copy file SVN_WC__LOG_ATTR_NAME to SVN_WC__LOG_ATTR_DEST, but expand any keywords and use any eol-style defined by properties of the DEST. */#define SVN_WC__LOG_CP_AND_TRANSLATE "cp-and-translate"/* Copy file SVN_WC__LOG_ATTR_NAME to SVN_WC__LOG_ATTR_DEST, but contract any keywords and convert to LF eol, according to properties of NAME. */#define SVN_WC__LOG_CP_AND_DETRANSLATE "cp-and-detranslate"/* Remove file SVN_WC__LOG_ATTR_NAME. */#define SVN_WC__LOG_RM "rm"/* Append file from SVN_WC__LOG_ATTR_NAME to SVN_WC__LOG_ATTR_DEST. */#define SVN_WC__LOG_APPEND "append"/* Make file SVN_WC__LOG_ATTR_NAME readonly */#define SVN_WC__LOG_READONLY "readonly"/* Make file SVN_WC__LOG_ATTR_NAME readonly if needs-lock property is set and there is no lock token for the file in the working copy. */#define SVN_WC__LOG_MAYBE_READONLY "maybe-readonly"/* Make file SVN_WC__LOG_ATTR_NAME executable if the executable property is set. */#define SVN_WC__LOG_MAYBE_EXECUTABLE "maybe-executable"/* Set SVN_WC__LOG_ATTR_NAME to have timestamp SVN_WC__LOG_ATTR_TIMESTAMP. */#define SVN_WC__LOG_SET_TIMESTAMP "set-timestamp"/* Handle closure after a commit completes successfully: * * If SVN/tmp/text-base/SVN_WC__LOG_ATTR_NAME exists, then * compare SVN/tmp/text-base/SVN_WC__LOG_ATTR_NAME with working file * if they're the same, use working file's timestamp * else use SVN/tmp/text-base/SVN_WC__LOG_ATTR_NAME's timestamp * set SVN_WC__LOG_ATTR_NAME's revision to N */#define SVN_WC__LOG_COMMITTED "committed"/* On target SVN_WC__LOG_ATTR_NAME, set wc property SVN_WC__LOG_ATTR_PROPNAME to value SVN_WC__LOG_ATTR_PROPVAL. If SVN_WC__LOG_ATTR_PROPVAL is absent, then remove the property. */#define SVN_WC__LOG_MODIFY_WCPROP "modify-wcprop"/* A log command which runs svn_wc_merge2(). See its documentation for details. Here is a map of entry-attributes to svn_wc_merge arguments: SVN_WC__LOG_NAME : MERGE_TARGET SVN_WC__LOG_ATTR_ARG_1 : LEFT SVN_WC__LOG_ATTR_ARG_2 : RIGHT SVN_WC__LOG_ATTR_ARG_3 : LEFT_LABEL SVN_WC__LOG_ATTR_ARG_4 : RIGHT_LABEL SVN_WC__LOG_ATTR_ARG_5 : TARGET_LABEL Of course, the three paths should be *relative* to the directory in which the log is running, as with all other log commands. (Usually they're just basenames within loggy->path.) */#define SVN_WC__LOG_MERGE "merge"/* Upgrade the WC format, both .svn/format and the format number in the entries file to SVN_WC__LOG_ATTR_FORMAT. */#define SVN_WC__LOG_UPGRADE_FORMAT "upgrade-format"/** Log attributes. See the documentation above for log actions for how these are used. **/#define SVN_WC__LOG_ATTR_NAME "name"#define SVN_WC__LOG_ATTR_DEST "dest"#define SVN_WC__LOG_ATTR_REVISION "revision"#define SVN_WC__LOG_ATTR_TIMESTAMP "timestamp"#define SVN_WC__LOG_ATTR_PROPNAME "propname"#define SVN_WC__LOG_ATTR_PROPVAL "propval"/* This one is for SVN_WC__LOG_MERGE and optionally SVN_WC__LOG_CP_AND_(DE)TRANSLATE to indicate special-only */#define SVN_WC__LOG_ATTR_ARG_1 "arg1"/* This one is for SVN_WC__LOG_MERGE and optionally SVN_WC__LOG_CP_AND_(DE)TRANSLATE to indicate a versioned path to take its translation properties from */#define SVN_WC__LOG_ATTR_ARG_2 "arg2"/* The rest are for SVN_WC__LOG_MERGE. Extend as necessary. */#define SVN_WC__LOG_ATTR_ARG_3 "arg3"#define SVN_WC__LOG_ATTR_ARG_4 "arg4"#define SVN_WC__LOG_ATTR_ARG_5 "arg5"/* For upgrade-format. */#define SVN_WC__LOG_ATTR_FORMAT "format"/*** Userdata for the callbacks. ***/struct log_runner{ apr_pool_t *pool; svn_xml_parser_t *parser; svn_boolean_t entries_modified; svn_boolean_t wcprops_modified; svn_boolean_t rerun; svn_wc_adm_access_t *adm_access; /* the dir in which all this happens */ const char *diff3_cmd; /* external diff3 cmd, or null if none */ /* Which top-level log element we're on for this logfile. Some callers care whether a failure happened on the first element or on some later element (e.g., 'svn cleanup'). This is initialized to 0 when the log_runner is created, and incremented every time start_handler() is called. */ int count;};/*** Forward declarations ***//* log runner forward declaration used in log_do_merge */static svn_error_t *run_log_from_memory(svn_wc_adm_access_t *adm_access, const char *buf, apr_size_t buf_len, svn_boolean_t rerun, const char *diff3_cmd, apr_pool_t *pool);/*** The XML handlers. ***//* Used by file_xfer_under_path(). */enum svn_wc__xfer_action { svn_wc__xfer_cp, svn_wc__xfer_mv, svn_wc__xfer_append, svn_wc__xfer_cp_and_translate, svn_wc__xfer_cp_and_detranslate};/* Perform some sort of copy-related ACTION on NAME and DEST: svn_wc__xfer_cp: just do a copy of NAME to DEST. svn_wc__xfer_mv: do a copy, then remove NAME. svn_wc__xfer_append: append contents of NAME to DEST svn_wc__xfer_cp_and_translate: copy NAME to DEST, doing any eol and keyword expansion according to the current property vals of VERSIONED or, if that's NULL, those of DEST. svn_wc__xfer_cp_and_detranslate: copy NAME to DEST, converting to LF and contracting keywords according to the current property vals of VERSIONED or, if that's NULL, those of NAME. When SPECIAL_ONLY is TRUE, only translate special, not keywords and eol-style.*/static svn_error_t *file_xfer_under_path(svn_wc_adm_access_t *adm_access, const char *name, const char *dest, const char *versioned, enum svn_wc__xfer_action action, svn_boolean_t special_only, svn_boolean_t rerun, apr_pool_t *pool){ svn_error_t *err; const char *full_from_path, *full_dest_path, *full_versioned_path; full_from_path = svn_path_join(svn_wc_adm_access_path(adm_access), name, pool); full_dest_path = svn_path_join(svn_wc_adm_access_path(adm_access), dest, pool); if (versioned) full_versioned_path = svn_path_join(svn_wc_adm_access_path(adm_access), versioned, pool); else full_versioned_path = NULL; /* Silence GCC uninitialised warning */ switch (action) { case svn_wc__xfer_append: err = svn_io_append_file(full_from_path, full_dest_path, pool); if (err) { if (! rerun || ! APR_STATUS_IS_ENOENT(err->apr_err)) return err; svn_error_clear(err); } break; case svn_wc__xfer_cp: return svn_io_copy_file(full_from_path, full_dest_path, FALSE, pool); case svn_wc__xfer_cp_and_translate: { const char *tmp_file; err = svn_wc_translated_file2 (&tmp_file, full_from_path, versioned ? full_versioned_path : full_dest_path, adm_access, SVN_WC_TRANSLATE_FROM_NF | SVN_WC_TRANSLATE_FORCE_COPY, pool); if (err) { if (! rerun || ! APR_STATUS_IS_ENOENT(err->apr_err)) return err; svn_error_clear(err); } else SVN_ERR(svn_io_file_rename(tmp_file, full_dest_path, pool)); SVN_ERR(svn_wc__maybe_set_read_only(NULL, full_dest_path, adm_access, pool)); SVN_ERR(svn_wc__maybe_set_executable(NULL, full_dest_path, adm_access, pool)); return SVN_NO_ERROR; } case svn_wc__xfer_cp_and_detranslate: { const char *tmp_file; SVN_ERR(svn_wc_translated_file2 (&tmp_file, full_from_path, versioned ? full_versioned_path : full_from_path, adm_access, SVN_WC_TRANSLATE_TO_NF | SVN_WC_TRANSLATE_FORCE_COPY, pool)); SVN_ERR(svn_io_file_rename(tmp_file, full_dest_path, pool)); return SVN_NO_ERROR; } case svn_wc__xfer_mv: err = svn_io_file_rename(full_from_path, full_dest_path, pool); /* If we got an ENOENT, that's ok; the move has probably already completed in an earlier run of this log. */ if (err) { if (! rerun || ! APR_STATUS_IS_ENOENT(err->apr_err)) return svn_error_quick_wrap(err, _("Can't move source to dest")); svn_error_clear(err); } } return SVN_NO_ERROR;}/* If new text was committed, then replace the text base for * newly-committed file NAME in directory PATH with the new * post-commit text base, which is waiting in the adm tmp area in * detranslated form. * * If eol and/or keyword translation would cause the working file to * change, then overwrite the working file with a translated copy of * the new text base (but only if the translated copy differs from the * current working file -- if they are the same, do nothing, to avoid * clobbering timestamps unnecessarily). * * If the executable property is set, the set working file's * executable. * * If the working file was re-translated or had executability set, * then set OVERWROTE_WORKING to TRUE. If the working file isn't * touched at all, then set to FALSE. * * Use POOL for any temporary allocation. */static svn_error_t *install_committed_file(svn_boolean_t *overwrote_working, svn_wc_adm_access_t *adm_access,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -