📄 fs_skels.c
字号:
/* fs_skels.c --- conversion between fs native types and skeletons
*
* ====================================================================
* 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 "svn_error.h"
#include "svn_string.h"
#include "fs_skels.h"
#include "skel.h"
#include "../id.h"
static svn_error_t *
skel_err (const char *skel_type)
{
return svn_error_createf (SVN_ERR_FS_MALFORMED_SKEL, NULL,
"Malformed%s%s skeleton",
skel_type ? " " : "",
skel_type ? skel_type : "");
}
/*** Validity Checking ***/
static svn_boolean_t
is_valid_checksum_skel (skel_t *skel)
{
if (svn_fs_base__list_length (skel) != 2)
return FALSE;
if (svn_fs_base__matches_atom (skel->children, "md5")
&& skel->children->next->is_atom)
return TRUE;
return FALSE;
}
static svn_boolean_t
is_valid_proplist_skel (skel_t *skel)
{
int len = svn_fs_base__list_length (skel);
if ((len >= 0) && (len & 1) == 0)
{
skel_t *elt;
for (elt = skel->children; elt; elt = elt->next)
if (! elt->is_atom)
return FALSE;
return TRUE;
}
return FALSE;
}
static svn_boolean_t
is_valid_revision_skel (skel_t *skel)
{
int len = svn_fs_base__list_length (skel);
if ((len == 2)
&& svn_fs_base__matches_atom (skel->children, "revision")
&& skel->children->next->is_atom)
return TRUE;
return FALSE;
}
static svn_boolean_t
is_valid_transaction_skel (skel_t *skel, transaction_kind_t *kind)
{
int len = svn_fs_base__list_length (skel);
if (len != 5)
return FALSE;
/* Determine (and verify) the kind. */
if (svn_fs_base__matches_atom (skel->children, "transaction"))
*kind = transaction_kind_normal;
else if (svn_fs_base__matches_atom (skel->children, "committed"))
*kind = transaction_kind_committed;
else if (svn_fs_base__matches_atom (skel->children, "dead"))
*kind = transaction_kind_dead;
else
return FALSE;
if (skel->children->next->is_atom
&& skel->children->next->next->is_atom
&& (! skel->children->next->next->next->is_atom)
&& (! skel->children->next->next->next->next->is_atom))
return TRUE;
return FALSE;
}
static svn_boolean_t
is_valid_rep_delta_chunk_skel (skel_t *skel)
{
int len;
skel_t *window;
skel_t *diff;
/* check the delta skel. */
if ((svn_fs_base__list_length (skel) != 2)
|| (! skel->children->is_atom))
return FALSE;
/* check the window. */
window = skel->children->next;
len = svn_fs_base__list_length (window);
if ((len < 3) || (len > 4))
return FALSE;
if (! ((! window->children->is_atom)
&& (window->children->next->is_atom)
&& (window->children->next->next->is_atom)))
return FALSE;
if ((len == 5)
&& (! window->children->next->next->next->is_atom))
return FALSE;
/* check the diff. ### currently we support only svndiff version
0 delta data. */
diff = window->children;
if ((svn_fs_base__list_length (diff) == 3)
&& (svn_fs_base__matches_atom (diff->children, "svndiff"))
&& (svn_fs_base__matches_atom (diff->children->next, "0"))
&& (diff->children->next->next->is_atom))
return TRUE;
return FALSE;
}
static svn_boolean_t
is_valid_representation_skel (skel_t *skel)
{
int len = svn_fs_base__list_length (skel);
skel_t *header;
int header_len;
/* the rep has at least two items in it, a HEADER list, and at least
one piece of kind-specific data. */
if (len < 2)
return FALSE;
/* check the header. it must have KIND and TXN atoms, and
optionally a CHECKSUM (which is a list form). */
header = skel->children;
header_len = svn_fs_base__list_length (header);
if (! (((header_len == 2) /* 2 means old repository, checksum absent */
&& (header->children->is_atom)
&& (header->children->next->is_atom))
|| ((header_len == 3) /* 3 means checksum present */
&& (header->children->is_atom)
&& (header->children->next->is_atom)
&& (is_valid_checksum_skel (header->children->next->next)))))
return FALSE;
/* check for fulltext rep. */
if ((len == 2)
&& (svn_fs_base__matches_atom (header->children, "fulltext")))
return TRUE;
/* check for delta rep. */
if ((len >= 2)
&& (svn_fs_base__matches_atom (header->children, "delta")))
{
/* it's a delta rep. check the validity. */
skel_t *chunk = skel->children->next;
/* loop over chunks, checking each one. */
while (chunk)
{
if (! is_valid_rep_delta_chunk_skel (chunk))
return FALSE;
chunk = chunk->next;
}
/* all good on this delta rep. */
return TRUE;
}
return FALSE;
}
static svn_boolean_t
is_valid_node_revision_header_skel (skel_t *skel, skel_t **kind_p)
{
int len = svn_fs_base__list_length (skel);
if (len < 2)
return FALSE;
/* set the *KIND_P pointer. */
*kind_p = skel->children;
/* without predecessor... */
if ((len == 2)
&& skel->children->is_atom
&& skel->children->next->is_atom
&& (skel->children->next->data[0] == '/'))
return TRUE;
/* or with predecessor... */
if ((len == 3)
&& skel->children->is_atom
&& skel->children->next->is_atom
&& (skel->children->next->data[0] == '/')
&& skel->children->next->next->is_atom)
return TRUE;
/* or with predecessor and predecessor count... */
if ((len == 4)
&& skel->children->is_atom
&& skel->children->next->is_atom
&& (skel->children->next->data[0] == '/')
&& skel->children->next->next->is_atom
&& skel->children->next->next->next->is_atom)
return TRUE;
return FALSE;
}
static svn_boolean_t
is_valid_node_revision_skel (skel_t *skel)
{
int len = svn_fs_base__list_length (skel);
if (len >= 1)
{
skel_t *header = skel->children;
skel_t *kind;
if (is_valid_node_revision_header_skel (header, &kind))
{
if (svn_fs_base__matches_atom (kind, "dir")
&& len == 3
&& header->next->is_atom
&& header->next->next->is_atom)
return TRUE;
if (svn_fs_base__matches_atom (kind, "file")
&& ((len == 3) || (len == 4))
&& header->next->is_atom
&& header->next->next->is_atom)
{
if ((len == 4) && (! header->next->next->next->is_atom))
return FALSE;
return TRUE;
}
}
}
return FALSE;
}
static svn_boolean_t
is_valid_copy_skel (skel_t *skel)
{
return (((svn_fs_base__list_length (skel) == 4)
&& (svn_fs_base__matches_atom (skel->children, "copy")
|| svn_fs_base__matches_atom (skel->children, "soft-copy"))
&& skel->children->next->is_atom
&& skel->children->next->next->is_atom
&& skel->children->next->next->next->is_atom) ? TRUE : FALSE);
}
static svn_boolean_t
is_valid_change_skel (skel_t *skel, svn_fs_path_change_kind_t *kind)
{
if ((svn_fs_base__list_length (skel) == 6)
&& svn_fs_base__matches_atom (skel->children, "change")
&& skel->children->next->is_atom
&& skel->children->next->next->is_atom
&& skel->children->next->next->next->is_atom
&& skel->children->next->next->next->next->is_atom
&& skel->children->next->next->next->next->next->is_atom)
{
skel_t *kind_skel = skel->children->next->next->next;
/* check the kind (and return it) */
if (svn_fs_base__matches_atom (kind_skel, "reset"))
{
if (kind)
*kind = svn_fs_path_change_reset;
return TRUE;
}
if (svn_fs_base__matches_atom (kind_skel, "add"))
{
if (kind)
*kind = svn_fs_path_change_add;
return TRUE;
}
if (svn_fs_base__matches_atom (kind_skel, "delete"))
{
if (kind)
*kind = svn_fs_path_change_delete;
return TRUE;
}
if (svn_fs_base__matches_atom (kind_skel, "replace"))
{
if (kind)
*kind = svn_fs_path_change_replace;
return TRUE;
}
if (svn_fs_base__matches_atom (kind_skel, "modify"))
{
if (kind)
*kind = svn_fs_path_change_modify;
return TRUE;
}
}
return FALSE;
}
/*** Parsing (conversion from skeleton to native FS type) ***/
svn_error_t *
svn_fs_base__parse_proplist_skel (apr_hash_t **proplist_p,
skel_t *skel,
apr_pool_t *pool)
{
apr_hash_t *proplist = NULL;
skel_t *elt;
/* Validate the skel. */
if (! is_valid_proplist_skel (skel))
return skel_err ("proplist");
/* Create the returned structure */
if (skel->children)
proplist = apr_hash_make (pool);
for (elt = skel->children; elt; elt = elt->next->next)
{
svn_string_t *value = svn_string_ncreate (elt->next->data,
elt->next->len, pool);
apr_hash_set (proplist,
apr_pstrmemdup (pool, elt->data, elt->len),
elt->len,
value);
}
/* Return the structure. */
*proplist_p = proplist;
return SVN_NO_ERROR;
}
svn_error_t *
svn_fs_base__parse_revision_skel (revision_t **revision_p,
skel_t *skel,
apr_pool_t *pool)
{
revision_t *revision;
/* Validate the skel. */
if (! is_valid_revision_skel (skel))
return skel_err ("revision");
/* Create the returned structure */
revision = apr_pcalloc (pool, sizeof (*revision));
revision->txn_id = apr_pstrmemdup (pool, skel->children->next->data,
skel->children->next->len);
/* Return the structure. */
*revision_p = revision;
return SVN_NO_ERROR;
}
svn_error_t *
svn_fs_base__parse_transaction_skel (transaction_t **transaction_p,
skel_t *skel,
apr_pool_t *pool)
{
transaction_t *transaction;
transaction_kind_t kind;
skel_t *root_id, *base_id_or_rev, *proplist, *copies;
int len;
/* Validate the skel. */
if (! is_valid_transaction_skel (skel, &kind))
return skel_err ("transaction");
root_id = skel->children->next;
base_id_or_rev = skel->children->next->next;
proplist = skel->children->next->next->next;
copies = skel->children->next->next->next->next;
/* Create the returned structure */
transaction = apr_pcalloc (pool, sizeof (*transaction));
/* KIND */
transaction->kind = kind;
/* REVISION or BASE-ID */
if (kind == transaction_kind_committed)
{
/* Committed transactions have a revision number... */
transaction->base_id = NULL;
transaction->revision = atoi (apr_pstrmemdup (pool, base_id_or_rev->data,
base_id_or_rev->len));
if (! SVN_IS_VALID_REVNUM (transaction->revision))
return skel_err ("tranaction");
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -