⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs_skels.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 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 + -