📄 questions.c
字号:
/* * questions.c: routines for asking questions about working copies * * ==================================================================== * Copyright (c) 2000-2004, 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_file_io.h>#include <apr_time.h>#include "svn_pools.h"#include "svn_types.h"#include "svn_string.h"#include "svn_error.h"#include "svn_path.h"#include "svn_time.h"#include "svn_wc.h"#include "svn_io.h"#include "svn_props.h"#include "wc.h"#include "adm_files.h"#include "questions.h"#include "entries.h"#include "translate.h"#include "svn_md5.h"#include <apr_md5.h>#include "svn_private_config.h"/* ### todo: make this compare repository too? Or do so in parallel code. See also adm_files.c:check_adm_exists(), which should probably be merged with this. */svn_error_t *svn_wc_check_wc(const char *path, int *wc_format, apr_pool_t *pool){ svn_error_t *err = SVN_NO_ERROR; const char *format_file_path = svn_wc__adm_path(path, FALSE, pool, SVN_WC__ADM_ENTRIES, NULL); /* First try to read the format number from the entries file. */ err = svn_io_read_version_file(wc_format, format_file_path, pool); /* If that didn't work and the first line of the entries file contains something other than a number, then it is probably in XML format. */ if (err && err->apr_err == SVN_ERR_BAD_VERSION_FILE_FORMAT) { svn_error_clear(err); /* Fall back on reading the format file instead. Note that the format file might not exist in newer working copies (format 7 and higher), but in that case, the entries file should have contained the format number. */ format_file_path = svn_wc__adm_path(path, FALSE, pool, SVN_WC__ADM_FORMAT, NULL); err = svn_io_read_version_file(wc_format, format_file_path, pool); } if (err && (APR_STATUS_IS_ENOENT(err->apr_err) || APR_STATUS_IS_ENOTDIR(err->apr_err))) { svn_node_kind_t kind; svn_error_clear(err); /* Check path itself exists. */ SVN_ERR(svn_io_check_path(path, &kind, pool)); if (kind == svn_node_none) { return svn_error_createf (APR_ENOENT, NULL, _("'%s' does not exist"), svn_path_local_style(path, pool)); } /* If the format file does not exist or path not directory, then for our purposes this is not a working copy, so return 0. */ *wc_format = 0; } else if (err) return err; else { /* If we managed to read the format file we assume that we are dealing with a real wc so we can return a nice error. */ SVN_ERR(svn_wc__check_format(*wc_format, path, pool)); } return SVN_NO_ERROR;}svn_error_t *svn_wc__check_format(int wc_format, const char *path, apr_pool_t *pool){ if (wc_format < 2) { return svn_error_createf (SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL, _("Working copy format of '%s' is too old (%d); " "please check out your working copy again"), svn_path_local_style(path, pool), wc_format); } else if (wc_format > SVN_WC__VERSION) { return svn_error_createf (SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL, _("This client is too old to work with working copy '%s'; " "please get a newer Subversion client"), svn_path_local_style(path, pool)); } return SVN_NO_ERROR;}/*** svn_wc_text_modified_p ***//* svn_wc_text_modified_p answers the question: "Are the contents of F different than the contents of .svn/text-base/F.svn-base?" In other words, we're looking to see if a user has made local modifications to a file since the last update or commit. Note: Assuming that F lives in a directory D at revision V, please notice that we are *NOT* answering the question, "are the contents of F different than revision V of F?" While F may be at a different revision number than its parent directory, but we're only looking for local edits on F, not for consistent directory revisions. TODO: the logic of the routines on this page might change in the future, as they bear some relation to the user interface. For example, if a file is removed -- without telling subversion about it -- how should subversion react? Should it copy the file back out of text-base? Should it ask whether one meant to officially mark it for removal?*//* Is PATH's timestamp the same as the one recorded in our `entries' file? Return the answer in EQUAL_P. TIMESTAMP_KIND should be one of the enumerated type above. */svn_error_t *svn_wc__timestamps_equal_p(svn_boolean_t *equal_p, const char *path, svn_wc_adm_access_t *adm_access, enum svn_wc__timestamp_kind timestamp_kind, apr_pool_t *pool){ apr_time_t wfile_time, entrytime = 0; const svn_wc_entry_t *entry; /* Get the timestamp from the entries file */ SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool)); /* Can't compare timestamps for an unversioned file. */ if (entry == NULL) return svn_error_createf (SVN_ERR_ENTRY_NOT_FOUND, NULL, _("'%s' is not under version control"), svn_path_local_style(path, pool)); /* Get the timestamp from the working file and the entry */ if (timestamp_kind == svn_wc__text_time) { SVN_ERR(svn_io_file_affected_time(&wfile_time, path, pool)); entrytime = entry->text_time; } else if (timestamp_kind == svn_wc__prop_time) { const char *prop_path; SVN_ERR(svn_wc__prop_path(&prop_path, path, entry->kind, FALSE, pool)); SVN_ERR(svn_io_file_affected_time(&wfile_time, prop_path, pool)); entrytime = entry->prop_time; } if (! entrytime) { /* TODO: If either timestamp is inaccessible, the test cannot return an answer. Assume that the timestamps are different. */ *equal_p = FALSE; return SVN_NO_ERROR; } { /* Put the disk timestamp through a string conversion, so it's at the same resolution as entry timestamps. */ /* This string conversion here may be goodness, but it does nothing currently _and_ it is somewhat expensive _and_ it eats memory _and_ it is tested for in the regression tests. But I will only comment it out because I do not possess the guts to remove it altogether. */ /* const char *tstr = svn_time_to_cstring (wfile_time, pool); SVN_ERR (svn_time_from_cstring (&wfile_time, tstr, pool)); */ } if (wfile_time == entrytime) *equal_p = TRUE; else *equal_p = FALSE; return SVN_NO_ERROR;}/* Set *MODIFIED_P to TRUE if (after translation) VERSIONED_FILE * differs from BASE_FILE, else to FALSE if not. Also verify that * BASE_FILE matches the entry checksum for VERSIONED_FILE, if * verify_checksum is TRUE. If checksum does not match, return the error * SVN_ERR_WC_CORRUPT_TEXT_BASE. * * ADM_ACCESS is an access baton for VERSIONED_FILE. Use POOL for * temporary allocation. */static svn_error_t *compare_and_verify(svn_boolean_t *modified_p, const char *versioned_file, svn_wc_adm_access_t *adm_access, const char *base_file, svn_boolean_t compare_textbases, svn_boolean_t verify_checksum, apr_pool_t *pool){ svn_boolean_t same; svn_subst_eol_style_t eol_style; const char *eol_str; apr_hash_t *keywords; svn_boolean_t special; svn_boolean_t need_translation; SVN_ERR(svn_wc__get_eol_style(&eol_style, &eol_str, versioned_file, adm_access, pool)); SVN_ERR(svn_wc__get_keywords(&keywords, versioned_file, adm_access, NULL, pool)); SVN_ERR(svn_wc__get_special(&special, versioned_file, adm_access, pool)); need_translation = svn_subst_translation_required(eol_style, eol_str, keywords, special, TRUE); if (verify_checksum || need_translation) { /* Reading files is necessary. */ const unsigned char *digest; /* "v_" means versioned_file, "b_" means base_file. */ apr_file_t *v_file_h, *b_file_h; svn_stream_t *v_stream, *b_stream; const svn_wc_entry_t *entry; SVN_ERR(svn_io_file_open(&b_file_h, base_file, APR_READ, APR_OS_DEFAULT, pool)); b_stream = svn_stream_from_aprfile2(b_file_h, FALSE, pool);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -