📄 status.c
字号:
/*
* status.c: construct a status structure from an entry structure
*
* ====================================================================
* Copyright (c) 2000-2004 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 <assert.h>
#include <string.h>
#include <apr_pools.h>
#include <apr_file_io.h>
#include <apr_hash.h>
#include <apr_time.h>
#include <apr_fnmatch.h>
#include "svn_pools.h"
#include "svn_types.h"
#include "svn_delta.h"
#include "svn_string.h"
#include "svn_error.h"
#include "svn_path.h"
#include "svn_io.h"
#include "svn_hash.h"
#include "svn_wc.h"
#include "svn_config.h"
#include "svn_private_config.h"
#include "wc.h"
#include "props.h"
#include "translate.h"
/*** Editor batons ***/
struct edit_baton
{
/* For status, the "destination" of the edit and whether to honor
any paths that are 'below'. */
const char *anchor;
const char *target;
svn_wc_adm_access_t *adm_access;
svn_boolean_t descend;
/* Do we want all statuses (instead of just the interesting ones) ? */
svn_boolean_t get_all;
/* Ignore the svn:ignores. */
svn_boolean_t no_ignore;
/* The comparison revision in the repository. This is a reference
because this editor returns this rev to the driver directly, as
well as in each statushash entry. */
svn_revnum_t *target_revision;
/* Subversion configuration hash. */
apr_hash_t *config;
/* Status function/baton. */
svn_wc_status_func_t status_func;
void *status_baton;
/* Cancellation function/baton. */
svn_cancel_func_t cancel_func;
void *cancel_baton;
/* The configured set of default ignores. */
apr_array_header_t *ignores;
/* Externals info harvested during the status run. */
svn_wc_traversal_info_t *traversal_info;
apr_hash_t *externals;
/* Status item for the path represented by the anchor of the edit. */
svn_wc_status_t *anchor_status;
/* Was open_root() called for this edit drive? */
svn_boolean_t root_opened;
/* The pool which the editor uses for the whole tree-walk.*/
apr_pool_t *pool;
};
struct dir_baton
{
/* The path to this directory. */
const char *path;
/* Basename of this directory. */
const char *name;
/* The global edit baton. */
struct edit_baton *edit_baton;
/* Baton for this directory's parent, or NULL if this is the root
directory. */
struct dir_baton *parent_baton;
/* 'svn status' shouldn't print status lines for things that are
added; we're only interest in asking if objects that the user
*already* has are up-to-date or not. Thus if this flag is set,
the next two will be ignored. :-) */
svn_boolean_t added;
/* Gets set iff there's a change to this directory's properties, to
guide us when syncing adm files later. */
svn_boolean_t prop_changed;
/* This means (in terms of 'svn status') that some child was deleted
or added to the directory */
svn_boolean_t text_changed;
/* Working copy status structures for children of this directory.
This hash maps const char * paths (relative to the root of the
edit) to svn_wc_status_t * status items. */
apr_hash_t *statii;
/* The pool in which this baton itself is allocated. */
apr_pool_t *pool;
};
struct file_baton
{
/* The global edit baton. */
struct edit_baton *edit_baton;
/* Baton for this file's parent directory. */
struct dir_baton *dir_baton;
/* Pool specific to this file_baton. */
apr_pool_t *pool;
/* Name of this file (its entry in the directory). */
const char *name;
/* Path to this file, either abs or relative to the change-root. */
const char *path;
/* 'svn status' shouldn't print status lines for things that are
added; we're only interest in asking if objects that the user
*already* has are up-to-date or not. Thus if this flag is set,
the next two will be ignored. :-) */
svn_boolean_t added;
/* This gets set if the file underwent a text change, which guides
the code that syncs up the adm dir and working copy. */
svn_boolean_t text_changed;
/* This gets set if the file underwent a prop change, which guides
the code that syncs up the adm dir and working copy. */
svn_boolean_t prop_changed;
};
/** Code **/
/* Fill in *STATUS for PATH, whose entry data is in ENTRY. Allocate
*STATUS in POOL.
ENTRY may be null, for non-versioned entities. In this case, we
will assemble a special status structure item which implies a
non-versioned thing.
Else, ENTRY's pool must not be shorter-lived than STATUS's, since
ENTRY will be stored directly, not copied.
PARENT_ENTRY is the entry for the parent directory of PATH, it may be
NULL if ENTRY is NULL or if PATH is a working copy root. The lifetime
of PARENT_ENTRY's pool is not important.
PATH_KIND is the node kind of PATH as determined by the caller.
NOTE: this may be svn_node_unknown if the caller has made no such
determination.
If GET_ALL is zero, and ENTRY is not locally modified, then *STATUS
will be set to NULL. If GET_ALL is non-zero, then *STATUS will be
allocated and returned no matter what.
If IS_IGNORED is non-zero and this is a non-versioned entity, set
the text_status to svn_wc_status_none. Otherwise set the
text_status to svn_wc_status_unversioned.
*/
static svn_error_t *
assemble_status (svn_wc_status_t **status,
const char *path,
svn_wc_adm_access_t *adm_access,
const svn_wc_entry_t *entry,
const svn_wc_entry_t *parent_entry,
svn_node_kind_t path_kind,
svn_boolean_t get_all,
svn_boolean_t is_ignored,
apr_pool_t *pool)
{
svn_wc_status_t *stat;
svn_boolean_t has_props;
svn_boolean_t text_modified_p = FALSE;
svn_boolean_t prop_modified_p = FALSE;
svn_boolean_t locked_p = FALSE;
svn_boolean_t switched_p = FALSE;
svn_boolean_t wc_special;
svn_boolean_t node_special;
svn_node_kind_t kind;
/* Defaults for two main variables. */
enum svn_wc_status_kind final_text_status = svn_wc_status_normal;
enum svn_wc_status_kind final_prop_status = svn_wc_status_none;
/* Check the path kind for PATH. */
if (path_kind == svn_node_unknown)
SVN_ERR (svn_io_check_path (path, &path_kind, pool));
SVN_ERR (svn_io_check_special_path (path, &kind, &node_special, pool));
if (! entry)
{
/* return a blank structure. */
stat = apr_pcalloc (pool, sizeof(*stat));
stat->entry = NULL;
stat->text_status = svn_wc_status_none;
stat->prop_status = svn_wc_status_none;
stat->repos_text_status = svn_wc_status_none;
stat->repos_prop_status = svn_wc_status_none;
stat->locked = FALSE;
stat->copied = FALSE;
stat->switched = FALSE;
/* If this path has no entry, but IS present on disk, it's
unversioned. If this file is being explicitly ignored (due
to matching an ignore-pattern), the text_status is set to
svn_wc_status_ignored. Otherwise the text_status is set to
svn_wc_status_unversioned. */
if (path_kind != svn_node_none)
{
if (is_ignored)
stat->text_status = svn_wc_status_ignored;
else
stat->text_status = svn_wc_status_unversioned;
}
*status = stat;
return SVN_NO_ERROR;
}
/* Someone either deleted the administrative directory in the versioned
subdir, or deleted the directory altogether and created a new one.
In any case, what is currently there is in the way.
*/
if (entry->kind == svn_node_dir)
{
if (path_kind == svn_node_dir)
{
if (svn_wc__adm_missing (adm_access, path))
final_text_status = svn_wc_status_obstructed;
}
else if (path_kind != svn_node_none)
final_text_status = svn_wc_status_obstructed;
}
/* Is this item switched? Well, to be switched it must have both an URL
and a parent with an URL, at the very least. */
if (entry->url && parent_entry && parent_entry->url)
{
/* An item is switched if its working copy basename differs from the
basename of its URL. */
if (strcmp (svn_path_uri_encode (svn_path_basename (path, pool), pool),
svn_path_basename (entry->url, pool)))
switched_p = TRUE;
/* An item is switched if its URL, without the basename, does not
equal its parent's URL. */
if (! switched_p
&& strcmp (svn_path_dirname (entry->url, pool),
parent_entry->url))
switched_p = TRUE;
}
if (final_text_status != svn_wc_status_obstructed)
{
/* Implement predecence rules: */
/* 1. Set the two main variables to "discovered" values first (M, C).
Together, these two stati are of lowest precedence, and C has
precedence over M. */
/* Does the entry have props? */
SVN_ERR (svn_wc__has_props (&has_props, path, adm_access, pool));
if (has_props)
final_prop_status = svn_wc_status_normal;
/* If the entry has a property file, see if it has local changes. */
SVN_ERR (svn_wc_props_modified_p (&prop_modified_p, path, adm_access,
pool));
SVN_ERR (svn_wc__get_special (&wc_special, path, adm_access, pool));
/* If the entry is a file, check for textual modifications */
if ((entry->kind == svn_node_file)
#ifdef HAVE_SYMLINK
&& (wc_special == node_special)
#endif /* HAVE_SYMLINK */
)
SVN_ERR (svn_wc_text_modified_p (&text_modified_p, path, FALSE,
adm_access, pool));
if (text_modified_p)
final_text_status = svn_wc_status_modified;
if (prop_modified_p)
final_prop_status = svn_wc_status_modified;
if (entry->prejfile || entry->conflict_old ||
entry->conflict_new || entry->conflict_wrk)
{
svn_boolean_t text_conflict_p, prop_conflict_p;
const char *parent_dir;
if (entry->kind == svn_node_dir)
parent_dir = path;
else /* non-directory, that's all we need to know */
parent_dir = svn_path_dirname (path, pool);
SVN_ERR (svn_wc_conflicted_p (&text_conflict_p, &prop_conflict_p,
parent_dir, entry, pool));
if (text_conflict_p)
final_text_status = svn_wc_status_conflicted;
if (prop_conflict_p)
final_prop_status = svn_wc_status_conflicted;
}
/* 2. Possibly overwrite the text_status variable with "scheduled"
states from the entry (A, D, R). As a group, these states are
of medium precedence. They also override any C or M that may
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -