📄 entries.c
字号:
/*
* entries.c : manipulating the administrative `entries' file.
*
* ====================================================================
* 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 <string.h>
#include <assert.h>
#include <apr_strings.h>
#include "svn_xml.h"
#include "svn_error.h"
#include "svn_types.h"
#include "svn_time.h"
#include "svn_pools.h"
#include "svn_path.h"
#include "wc.h"
#include "adm_files.h"
#include "adm_ops.h"
#include "entries.h"
#include "svn_private_config.h"
/** Overview **/
/* The administrative `entries' file tracks information about files
and subdirs within a particular directory.
See the section on the `entries' file in libsvn_wc/README, for
concrete information about the XML format.
*/
/*--------------------------------------------------------------- */
/*** Initialization of the entries file. ***/
svn_error_t *
svn_wc__entries_init (const char *path,
const char *uuid,
const char *url,
svn_revnum_t initial_rev,
apr_pool_t *pool)
{
apr_file_t *f = NULL;
svn_stringbuf_t *accum = NULL;
apr_hash_t *atts = apr_hash_make (pool);
char *initial_revstr = apr_psprintf (pool, "%ld",
initial_rev);
/* Create the entries file, which must not exist prior to this. */
SVN_ERR (svn_wc__open_adm_file (&f, path, SVN_WC__ADM_ENTRIES,
(APR_WRITE | APR_CREATE | APR_EXCL), pool));
/* Make a the XML standard header, to satisfy bureacracy. */
svn_xml_make_header (&accum, pool);
/* Open the file's top-level form. */
svn_xml_make_open_tag (&accum,
pool,
svn_xml_normal,
SVN_WC__ENTRIES_TOPLEVEL,
"xmlns",
SVN_XML_NAMESPACE,
NULL);
/* Add an entry for the dir itself. The directory has no name. It
might have a UUID, but otherwise only the revision and default
ancestry are present as XML attributes, and possibly an
'incomplete' flag if the revnum is > 0. */
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_KIND,
sizeof (SVN_WC__ENTRY_ATTR_KIND) - 1,
SVN_WC__ENTRIES_ATTR_DIR_STR);
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_URL,
sizeof (SVN_WC__ENTRY_ATTR_URL) - 1,
url);
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_REVISION,
sizeof (SVN_WC__ENTRY_ATTR_REVISION) - 1,
initial_revstr);
if (uuid)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_UUID,
sizeof (SVN_WC__ENTRY_ATTR_UUID) - 1,
uuid);
if (initial_rev > 0)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_INCOMPLETE,
sizeof (SVN_WC__ENTRY_ATTR_INCOMPLETE) - 1,
"true");
svn_xml_make_open_tag_hash (&accum, pool, svn_xml_self_closing,
SVN_WC__ENTRIES_ENTRY, atts);
/* Close the top-level form. */
svn_xml_make_close_tag (&accum,
pool,
SVN_WC__ENTRIES_TOPLEVEL);
SVN_ERR_W (svn_io_file_write_full (f, accum->data, accum->len, NULL, pool),
apr_psprintf (pool,
_("Error writing entries file for '%s'"), path));
/* Now we have a `entries' file with exactly one entry, an entry
for this dir. Close the file and sync it up. */
SVN_ERR (svn_wc__close_adm_file (f, path, SVN_WC__ADM_ENTRIES, 1, pool));
return SVN_NO_ERROR;
}
/*--------------------------------------------------------------- */
/*** reading and writing the entries file ***/
struct entries_accumulator
{
/* Keys are entry names, vals are (struct svn_wc_entry_t *)'s. */
apr_hash_t *entries;
/* The parser that's parsing it, for signal_expat_bailout(). */
svn_xml_parser_t *parser;
/* Should we include 'deleted' entries in the hash? */
svn_boolean_t show_hidden;
/* Don't leave home without one. */
apr_pool_t *pool;
};
static svn_wc_entry_t *
alloc_entry (apr_pool_t *pool)
{
svn_wc_entry_t *entry = apr_pcalloc (pool, sizeof (*entry));
entry->revision = SVN_INVALID_REVNUM;
entry->copyfrom_rev = SVN_INVALID_REVNUM;
entry->cmt_rev = SVN_INVALID_REVNUM;
entry->kind = svn_node_none;
return entry;
}
svn_error_t *
svn_wc__atts_to_entry (svn_wc_entry_t **new_entry,
apr_uint32_t *modify_flags,
apr_hash_t *atts,
apr_pool_t *pool)
{
svn_wc_entry_t *entry = alloc_entry (pool);
const char *name;
*modify_flags = 0;
/* Find the name and set up the entry under that name. */
name = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_NAME, APR_HASH_KEY_STRING);
/* XXX Replace the obsolete "svn:this_dir".
XXX This code should go away by 1.0 */
{
if (name && strcmp (name, "svn:this_dir") == 0)
name = SVN_WC_ENTRY_THIS_DIR;
}
entry->name = name ? name : SVN_WC_ENTRY_THIS_DIR;
/* Attempt to set revision (resolve_to_defaults may do it later, too) */
{
const char *revision_str
= apr_hash_get (atts, SVN_WC__ENTRY_ATTR_REVISION, APR_HASH_KEY_STRING);
if (revision_str)
{
entry->revision = SVN_STR_TO_REV (revision_str);
*modify_flags |= SVN_WC__ENTRY_MODIFY_REVISION;
}
else
entry->revision = SVN_INVALID_REVNUM;
}
/* Attempt to set up url path (again, see resolve_to_defaults). */
{
entry->url
= apr_hash_get (atts, SVN_WC__ENTRY_ATTR_URL, APR_HASH_KEY_STRING);
if (entry->url)
*modify_flags |= SVN_WC__ENTRY_MODIFY_URL;
}
/* Set up kind. */
{
const char *kindstr
= apr_hash_get (atts, SVN_WC__ENTRY_ATTR_KIND, APR_HASH_KEY_STRING);
entry->kind = svn_node_none;
if (kindstr)
{
if (! strcmp (kindstr, SVN_WC__ENTRIES_ATTR_FILE_STR))
entry->kind = svn_node_file;
else if (! strcmp (kindstr, SVN_WC__ENTRIES_ATTR_DIR_STR))
entry->kind = svn_node_dir;
else
return svn_error_createf
(SVN_ERR_NODE_UNKNOWN_KIND, NULL,
_("Entry '%s' has invalid node kind"),
(name ? name : SVN_WC_ENTRY_THIS_DIR));
*modify_flags |= SVN_WC__ENTRY_MODIFY_KIND;
}
}
/* Look for a schedule attribute on this entry. */
{
const char *schedulestr
= apr_hash_get (atts, SVN_WC__ENTRY_ATTR_SCHEDULE, APR_HASH_KEY_STRING);
entry->schedule = svn_wc_schedule_normal;
if (schedulestr)
{
if (! strcmp (schedulestr, SVN_WC__ENTRY_VALUE_ADD))
entry->schedule = svn_wc_schedule_add;
else if (! strcmp (schedulestr, SVN_WC__ENTRY_VALUE_DELETE))
entry->schedule = svn_wc_schedule_delete;
else if (! strcmp (schedulestr, SVN_WC__ENTRY_VALUE_REPLACE))
entry->schedule = svn_wc_schedule_replace;
else if (! strcmp (schedulestr, ""))
entry->schedule = svn_wc_schedule_normal;
else
return svn_error_createf
(SVN_ERR_ENTRY_ATTRIBUTE_INVALID, NULL,
_("Entry '%s' has invalid '%s' value"),
(name ? name : SVN_WC_ENTRY_THIS_DIR),
SVN_WC__ENTRY_ATTR_SCHEDULE);
*modify_flags |= SVN_WC__ENTRY_MODIFY_SCHEDULE;
}
}
/* Is this entry in a state of mental torment (conflict)? */
{
if ((entry->prejfile
= apr_hash_get (atts, SVN_WC__ENTRY_ATTR_PREJFILE,
APR_HASH_KEY_STRING)))
*modify_flags |= SVN_WC__ENTRY_MODIFY_PREJFILE;
if ((entry->conflict_old
= apr_hash_get (atts, SVN_WC__ENTRY_ATTR_CONFLICT_OLD,
APR_HASH_KEY_STRING)))
*modify_flags |= SVN_WC__ENTRY_MODIFY_CONFLICT_OLD;
if ((entry->conflict_new
= apr_hash_get (atts, SVN_WC__ENTRY_ATTR_CONFLICT_NEW,
APR_HASH_KEY_STRING)))
*modify_flags |= SVN_WC__ENTRY_MODIFY_CONFLICT_NEW;
if ((entry->conflict_wrk
= apr_hash_get (atts, SVN_WC__ENTRY_ATTR_CONFLICT_WRK,
APR_HASH_KEY_STRING)))
*modify_flags |= SVN_WC__ENTRY_MODIFY_CONFLICT_WRK;
}
/* Is this entry copied? */
{
const char *copiedstr, *revstr;
copiedstr = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_COPIED,
APR_HASH_KEY_STRING);
entry->copied = FALSE;
if (copiedstr)
{
if (! strcmp (copiedstr, "true"))
entry->copied = TRUE;
else if (! strcmp (copiedstr, "false"))
entry->copied = FALSE;
else if (! strcmp (copiedstr, ""))
entry->copied = FALSE;
else
return svn_error_createf
(SVN_ERR_ENTRY_ATTRIBUTE_INVALID, NULL,
_("Entry '%s' has invalid '%s' value"),
(name ? name : SVN_WC_ENTRY_THIS_DIR),
SVN_WC__ENTRY_ATTR_COPIED);
*modify_flags |= SVN_WC__ENTRY_MODIFY_COPIED;
}
entry->copyfrom_url = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_COPYFROM_URL,
APR_HASH_KEY_STRING);
if (entry->copyfrom_url)
*modify_flags |= SVN_WC__ENTRY_MODIFY_COPYFROM_URL;
revstr = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_COPYFROM_REV,
APR_HASH_KEY_STRING);
if (revstr)
{
entry->copyfrom_rev = SVN_STR_TO_REV (revstr);
*modify_flags |= SVN_WC__ENTRY_MODIFY_COPYFROM_REV;
}
}
/* Is this entry deleted? */
{
const char *deletedstr;
deletedstr = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_DELETED,
APR_HASH_KEY_STRING);
entry->deleted = FALSE;
if (deletedstr)
{
if (! strcmp (deletedstr, "true"))
entry->deleted = TRUE;
else if (! strcmp (deletedstr, "false"))
entry->deleted = FALSE;
else if (! strcmp (deletedstr, ""))
entry->deleted = FALSE;
else
return svn_error_createf
(SVN_ERR_ENTRY_ATTRIBUTE_INVALID, NULL,
_("Entry '%s' has invalid '%s' value"),
(name ? name : SVN_WC_ENTRY_THIS_DIR),
SVN_WC__ENTRY_ATTR_DELETED);
*modify_flags |= SVN_WC__ENTRY_MODIFY_DELETED;
}
}
/* Is this entry absent? */
{
const char *absentstr;
absentstr = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_ABSENT,
APR_HASH_KEY_STRING);
entry->absent = FALSE;
if (absentstr)
{
if (! strcmp (absentstr, "true"))
entry->absent = TRUE;
else if (! strcmp (absentstr, "false"))
entry->absent = FALSE;
else if (! strcmp (absentstr, ""))
entry->absent = FALSE;
else
return svn_error_createf
(SVN_ERR_ENTRY_ATTRIBUTE_INVALID, NULL,
_("Entry '%s' has invalid '%s' value"),
(name ? name : SVN_WC_ENTRY_THIS_DIR),
SVN_WC__ENTRY_ATTR_ABSENT);
*modify_flags |= SVN_WC__ENTRY_MODIFY_ABSENT;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -