📄 entries.c
字号:
/* Run a simple validity check on the ENTRIES (the list of entries
associated with the directory PATH). */
static svn_error_t *
check_entries (apr_hash_t *entries,
const char *path,
apr_pool_t *pool)
{
svn_wc_entry_t *default_entry;
apr_hash_index_t *hi;
default_entry = apr_hash_get (entries,
SVN_WC_ENTRY_THIS_DIR,
APR_HASH_KEY_STRING);
if (! default_entry)
return svn_error_createf
(SVN_ERR_WC_CORRUPT, NULL,
_("Corrupt working copy: '%s' has no default entry"), path);
/* Validate DEFAULT_ENTRY's current schedule. */
switch (default_entry->schedule)
{
case svn_wc_schedule_normal:
case svn_wc_schedule_add:
case svn_wc_schedule_delete:
case svn_wc_schedule_replace:
/* These are all valid states */
break;
default:
/* This is an invalid state */
return svn_error_createf
(SVN_ERR_WC_CORRUPT, NULL,
_("Corrupt working copy: directory '%s' has an invalid schedule"),
path);
}
for (hi = apr_hash_first (pool, entries); hi; hi = apr_hash_next (hi))
{
const void *key;
const char *name;
void *val;
svn_wc_entry_t *this_entry;
/* Get the entry */
apr_hash_this (hi, &key, NULL, &val);
this_entry = val;
name = key;
/* We've already checked the "this dir" entry */
if (! strcmp (name, SVN_WC_ENTRY_THIS_DIR ))
continue;
/* Validate THIS_ENTRY's current schedule. */
switch (this_entry->schedule)
{
case svn_wc_schedule_normal:
case svn_wc_schedule_add:
case svn_wc_schedule_delete:
case svn_wc_schedule_replace:
/* These are all valid states */
break;
default:
/* This is an invalid state */
return svn_error_createf
(SVN_ERR_WC_CORRUPT, NULL,
_("Corrupt working copy: "
"'%s' in directory '%s' has an invalid schedule"),
name, path);
}
if ((default_entry->schedule == svn_wc_schedule_add)
&& (this_entry->schedule != svn_wc_schedule_add))
return svn_error_createf
(SVN_ERR_WC_CORRUPT, NULL,
_("Corrupt working copy: '%s' in directory '%s' (which is "
"scheduled for addition) is not itself scheduled for addition"),
name, path);
if ((default_entry->schedule == svn_wc_schedule_delete)
&& (this_entry->schedule != svn_wc_schedule_delete))
return svn_error_createf
(SVN_ERR_WC_CORRUPT, NULL,
_("Corrupt working copy: '%s' in directory '%s' (which is "
"scheduled for deletion) is not itself scheduled for deletion"),
name, path);
if ((default_entry->schedule == svn_wc_schedule_replace)
&& (this_entry->schedule == svn_wc_schedule_normal))
return svn_error_createf
(SVN_ERR_WC_CORRUPT, NULL,
_("Corrupt working copy: '%s' in directory '%s' (which is "
"scheduled for replacement) has an invalid schedule"),
name, path);
}
return SVN_NO_ERROR;
}
#endif /* 0 */
svn_error_t *
svn_wc_entries_read (apr_hash_t **entries,
svn_wc_adm_access_t *adm_access,
svn_boolean_t show_hidden,
apr_pool_t *pool)
{
apr_hash_t *new_entries;
new_entries = svn_wc__adm_access_entries (adm_access, show_hidden, pool);
if (! new_entries)
{
SVN_ERR (read_entries (adm_access, show_hidden, pool));
new_entries = svn_wc__adm_access_entries (adm_access, show_hidden, pool);
}
*entries = new_entries;
return SVN_NO_ERROR;
}
/* Append a single entry THIS_ENTRY to the string OUTPUT, using the
entry for "this dir" THIS_DIR for comparison/optimization.
Allocations are done in POOL. */
static svn_error_t *
write_entry (svn_stringbuf_t **output,
svn_wc_entry_t *entry,
const char *name,
svn_wc_entry_t *this_dir,
apr_pool_t *pool)
{
apr_hash_t *atts = apr_hash_make (pool);
const char *valuestr;
/*** Create a hash that represents an entry. ***/
assert (name);
/* Name */
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_NAME, APR_HASH_KEY_STRING,
entry->name);
/* Revision */
if (SVN_IS_VALID_REVNUM (entry->revision))
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_REVISION, APR_HASH_KEY_STRING,
apr_psprintf (pool, "%ld", entry->revision));
/* URL */
if (entry->url)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_URL, APR_HASH_KEY_STRING,
entry->url);
/* Kind */
switch (entry->kind)
{
case svn_node_dir:
valuestr = SVN_WC__ENTRIES_ATTR_DIR_STR;
break;
case svn_node_none:
valuestr = NULL;
break;
case svn_node_file:
case svn_node_unknown:
default:
valuestr = SVN_WC__ENTRIES_ATTR_FILE_STR;
break;
}
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_KIND, APR_HASH_KEY_STRING, valuestr);
/* Schedule */
switch (entry->schedule)
{
case svn_wc_schedule_add:
valuestr = SVN_WC__ENTRY_VALUE_ADD;
break;
case svn_wc_schedule_delete:
valuestr = SVN_WC__ENTRY_VALUE_DELETE;
break;
case svn_wc_schedule_replace:
valuestr = SVN_WC__ENTRY_VALUE_REPLACE;
break;
case svn_wc_schedule_normal:
default:
valuestr = NULL;
break;
}
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_SCHEDULE, APR_HASH_KEY_STRING,
valuestr);
/* Conflicts */
if (entry->conflict_old)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_CONFLICT_OLD, APR_HASH_KEY_STRING,
entry->conflict_old);
if (entry->conflict_new)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_CONFLICT_NEW, APR_HASH_KEY_STRING,
entry->conflict_new);
if (entry->conflict_wrk)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_CONFLICT_WRK, APR_HASH_KEY_STRING,
entry->conflict_wrk);
if (entry->prejfile)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_PREJFILE, APR_HASH_KEY_STRING,
entry->prejfile);
/* Copy-related Stuff */
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_COPIED, APR_HASH_KEY_STRING,
(entry->copied ? "true" : NULL));
if (SVN_IS_VALID_REVNUM (entry->copyfrom_rev))
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_COPYFROM_REV, APR_HASH_KEY_STRING,
apr_psprintf (pool, "%ld",
entry->copyfrom_rev));
if (entry->copyfrom_url)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_COPYFROM_URL, APR_HASH_KEY_STRING,
entry->copyfrom_url);
/* Deleted state */
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_DELETED, APR_HASH_KEY_STRING,
(entry->deleted ? "true" : NULL));
/* Absent state */
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_ABSENT, APR_HASH_KEY_STRING,
(entry->absent ? "true" : NULL));
/* Incomplete state */
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_INCOMPLETE, APR_HASH_KEY_STRING,
(entry->incomplete ? "true" : NULL));
/* Timestamps */
if (entry->text_time)
{
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_TEXT_TIME, APR_HASH_KEY_STRING,
svn_time_to_cstring (entry->text_time, pool));
}
if (entry->prop_time)
{
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_PROP_TIME, APR_HASH_KEY_STRING,
svn_time_to_cstring (entry->prop_time, pool));
}
/* Checksum */
if (entry->checksum)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_CHECKSUM, APR_HASH_KEY_STRING,
entry->checksum);
/* Last-commit Stuff */
if (SVN_IS_VALID_REVNUM (entry->cmt_rev))
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_CMT_REV, APR_HASH_KEY_STRING,
apr_psprintf (pool, "%ld", entry->cmt_rev));
if (entry->cmt_author)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_CMT_AUTHOR, APR_HASH_KEY_STRING,
entry->cmt_author);
if (entry->uuid)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_UUID, APR_HASH_KEY_STRING,
entry->uuid);
if (entry->cmt_date)
{
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_CMT_DATE, APR_HASH_KEY_STRING,
svn_time_to_cstring (entry->cmt_date, pool));
}
/*** Now, remove stuff that can be derived through inheritance rules. ***/
/* We only want to write out 'revision' and 'url' for the
following things:
1. the current directory's "this dir" entry.
2. non-directory entries:
a. which are marked for addition (and consequently should
have an invalid revnum)
b. whose revision or url is valid and different than
that of the "this dir" entry.
*/
if (strcmp (name, SVN_WC_ENTRY_THIS_DIR))
{
/* This is NOT the "this dir" entry */
if (! strcmp (name, "."))
{
/* By golly, if this isn't recognized as the "this dir"
entry, and it looks like '.', we're just asking for an
infinite recursion to happen. Abort! */
abort();
}
if (entry->kind == svn_node_dir)
{
/* We don't write url, revision, or uuid for subdir
entries. */
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_REVISION, APR_HASH_KEY_STRING,
NULL);
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_URL, APR_HASH_KEY_STRING,
NULL);
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_UUID, APR_HASH_KEY_STRING,
NULL);
}
else
{
/* If this is not the "this dir" entry, and the revision is
the same as that of the "this dir" entry, don't write out
the revision. */
if (entry->revision == this_dir->revision)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_REVISION,
APR_HASH_KEY_STRING, NULL);
/* If this is not the "this dir" entry, and the uuid is
the same as that of the "this dir" entry, don't write out
the uuid. */
if (entry->uuid && this_dir->uuid)
{
if (strcmp(entry->uuid, this_dir->uuid) == 0)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_UUID,
APR_HASH_KEY_STRING, NULL);
}
/* If this is not the "this dir" entry, and the url is
trivially calculable from that of the "this dir" entry,
don't write out the url */
if (entry->url)
{
if (strcmp (entry->url,
svn_path_url_add_component (this_dir->url,
name, pool)) == 0)
apr_hash_set (atts, SVN_WC__ENTRY_ATTR_URL,
APR_HASH_KEY_STRING, NULL);
}
}
}
/* Append the entry onto the accumulating string. */
svn_xml_make_open_tag_hash (output,
pool,
svn_xml_self_closing,
SVN_WC__ENTRIES_ENTRY,
atts);
return SVN_NO_ERROR;
}
svn_error_t *
svn_wc__entries_write (apr_hash_t *entries,
svn_wc_adm_access_t *adm_access,
apr_pool_t *pool)
{
svn_error_t *err = SVN_NO_ERROR;
svn_stringbuf_t *bigstr = NULL;
apr_file_t *outfile = NULL;
apr_hash_index_t *hi;
svn_wc_entry_t *this_dir;
apr_pool_t *subpool = svn_pool_create (pool);
SVN_ERR (svn_wc__adm_write_check (adm_access));
/* Get a copy of the "this dir" entry for comparison purposes. */
this_dir = apr_hash_get (entries, SVN_WC_ENTRY_THIS_DIR,
APR_HASH_KEY_STRING);
/* If there is no "this dir" entry, something is wrong. */
if (! this_dir)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -