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

📄 fs_fs.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 5 页
字号:
        }
      else if (strcmp (str, KIND_DIR) == 0)
        {
          dirent->kind = svn_node_dir;
        }
      else
        {
          return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
                                   _("Directory entry corrupt"));
        }

      str = apr_strtok (NULL, " ", &last_str);
      if (str == NULL)
        return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
                                 _("Directory entry corrupt"));
      
      dirent->id = svn_fs_fs__id_parse (str, strlen (str),
                                        ffd->dir_cache_pool);

      apr_hash_set (ffd->dir_cache, dirent->name, APR_HASH_KEY_STRING, dirent);
    }

  /* Mark which directory we've cached and return it. */
  ffd->dir_cache_id = svn_fs_fs__id_copy (noderev->id, ffd->dir_cache_pool);
  *entries_p = ffd->dir_cache;
  return SVN_NO_ERROR;
}

apr_hash_t *
svn_fs_fs__copy_dir_entries (apr_hash_t *entries,
                             apr_pool_t *pool)
{
  apr_hash_t *new_entries = apr_hash_make (pool);
  apr_hash_index_t *hi;

  for (hi = apr_hash_first (pool, entries); hi; hi = apr_hash_next (hi))
    {
      void *val;
      svn_fs_dirent_t *dirent, *new_dirent;

      apr_hash_this (hi, NULL, NULL, &val);
      dirent = val;
      new_dirent = apr_palloc (pool, sizeof (*new_dirent));
      new_dirent->name = apr_pstrdup (pool, dirent->name);
      new_dirent->kind = dirent->kind;
      new_dirent->id = svn_fs_fs__id_copy (dirent->id, pool);
      apr_hash_set (new_entries, new_dirent->name, APR_HASH_KEY_STRING,
                    new_dirent);
    }
  return new_entries;
}

svn_error_t *
svn_fs_fs__get_proplist (apr_hash_t **proplist_p,
                         svn_fs_t *fs,
                         node_revision_t *noderev,
                         apr_pool_t *pool)
{
  apr_hash_t *proplist;
  svn_stream_t *stream;

  proplist = apr_hash_make (pool);

  if (noderev->prop_rep && noderev->prop_rep->txn_id)
    {
      apr_file_t *props_file;
      const char *filename = path_txn_node_props (fs, noderev->id, pool);

      SVN_ERR (svn_io_file_open (&props_file, filename,
                                 APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
                                 pool));
      stream = svn_stream_from_aprfile (props_file, pool);
      SVN_ERR (svn_hash_read2 (proplist, stream, SVN_HASH_TERMINATOR, pool));
      SVN_ERR (svn_io_file_close (props_file, pool));
    }
  else if (noderev->prop_rep)
    {
      SVN_ERR (read_representation (&stream, fs, noderev->prop_rep, pool));
      SVN_ERR (svn_hash_read2 (proplist, stream, SVN_HASH_TERMINATOR, pool));
      SVN_ERR (svn_stream_close (stream));
    }

  *proplist_p = proplist;

  return SVN_NO_ERROR;
}

svn_error_t *
svn_fs_fs__file_length (svn_filesize_t *length,
                        node_revision_t *noderev,
                        apr_pool_t *pool)
{
  if (noderev->data_rep)
    *length = noderev->data_rep->expanded_size;
  else
    *length = 0;

  return SVN_NO_ERROR;
}

svn_boolean_t
svn_fs_fs__noderev_same_rep_key (representation_t *a,
                                 representation_t *b)
{
  if (a == b)
    return TRUE;

  if (a && (! b))
    return FALSE;

  if (b && (! a))
    return FALSE;

  if (a->offset != b->offset)
    return FALSE;

  if (a->revision != b->revision)
    return FALSE;
  
  return TRUE;
}

svn_error_t *
svn_fs_fs__file_checksum (unsigned char digest[],
                          node_revision_t *noderev,
                          apr_pool_t *pool)
{
  if (noderev->data_rep)
    memcpy (digest, noderev->data_rep->checksum, APR_MD5_DIGESTSIZE);
  else
    memset (digest, 0, APR_MD5_DIGESTSIZE);

  return SVN_NO_ERROR;
}

representation_t *
svn_fs_fs__rep_copy (representation_t *rep,
                     apr_pool_t *pool)
{
  representation_t *rep_new;
  
  if (rep == NULL)
    return NULL;
    
  rep_new = apr_pcalloc (pool, sizeof (*rep_new));
  
  memcpy (rep_new, rep, sizeof (*rep_new));
  
  return rep_new;
}

/* Merge the internal-use-only CHANGE into a hash of public-FS
   svn_fs_path_change_t CHANGES, collapsing multiple changes into a
   single summarical (is that real word?) change per path.  Also keep
   the COPYFROM_HASH up to date with new adds and replaces.  */
static svn_error_t *
fold_change (apr_hash_t *changes,
             const change_t *change,
             apr_hash_t *copyfrom_hash)
{
  apr_pool_t *pool = apr_hash_pool_get (changes);
  apr_pool_t *copyfrom_pool = apr_hash_pool_get (copyfrom_hash);
  svn_fs_path_change_t *old_change, *new_change;
  const char *path, *copyfrom_string, *copyfrom_path = NULL;

  if ((old_change = apr_hash_get (changes, change->path, APR_HASH_KEY_STRING)))
    {
      /* This path already exists in the hash, so we have to merge
         this change into the already existing one. */

      /* Get the existing copyfrom entry for this path. */
      copyfrom_string = apr_hash_get (copyfrom_hash, change->path,
                                      APR_HASH_KEY_STRING);

      /* If this entry existed in the copyfrom hash, we don't need to
         copy it. */
      if (copyfrom_string)
        copyfrom_path = change->path;

      /* Since the path already exists in the hash, we don't have to
         dup the allocation for the path itself. */
      path = change->path;
      /* Sanity check:  only allow NULL node revision ID in the
         `reset' case. */
      if ((! change->noderev_id) && (change->kind != svn_fs_path_change_reset))
        return svn_error_create
          (SVN_ERR_FS_CORRUPT, NULL,
           _("Missing required node revision ID"));

      /* Sanity check: we should be talking about the same node
         revision ID as our last change except where the last change
         was a deletion. */
      if (change->noderev_id
          && (! svn_fs_fs__id_eq (old_change->node_rev_id, change->noderev_id))
          && (old_change->change_kind != svn_fs_path_change_delete))
        return svn_error_create
          (SVN_ERR_FS_CORRUPT, NULL,
           _("Invalid change ordering: new node revision ID "
             "without delete"));

      /* Sanity check: an add, replacement, or reset must be the first
         thing to follow a deletion. */
      if ((old_change->change_kind == svn_fs_path_change_delete)
          && (! ((change->kind == svn_fs_path_change_replace)
                 || (change->kind == svn_fs_path_change_reset)
                 || (change->kind == svn_fs_path_change_add))))
        return svn_error_create
          (SVN_ERR_FS_CORRUPT, NULL,
           _("Invalid change ordering: non-add change on deleted path"));

      /* Now, merge that change in. */
      switch (change->kind)
        {
        case svn_fs_path_change_reset:
          /* A reset here will simply remove the path change from the
             hash. */
          old_change = NULL;
          copyfrom_string = NULL;
          break;

        case svn_fs_path_change_delete:
          if (old_change->change_kind == svn_fs_path_change_add)
            {
              /* If the path was introduced in this transaction via an
                 add, and we are deleting it, just remove the path
                 altogether. */
              old_change = NULL;
            }
          else
            {
              /* A deletion overrules all previous changes. */
              old_change->change_kind = svn_fs_path_change_delete;
              old_change->text_mod = change->text_mod;
              old_change->prop_mod = change->prop_mod;
            }
          copyfrom_string = NULL;
          break;

        case svn_fs_path_change_add:
        case svn_fs_path_change_replace:
          /* An add at this point must be following a previous delete,
             so treat it just like a replace. */
          old_change->change_kind = svn_fs_path_change_replace;
          old_change->node_rev_id = svn_fs_fs__id_copy (change->noderev_id,
                                                        pool);
          old_change->text_mod = change->text_mod;
          old_change->prop_mod = change->prop_mod;
          if (change->copyfrom_rev == SVN_INVALID_REVNUM)
            {
              copyfrom_string = apr_pstrdup (copyfrom_pool, "");
            }
          else
            {
              copyfrom_string = apr_psprintf (copyfrom_pool,
                                              "%ld %s",
                                              change->copyfrom_rev,
                                              change->copyfrom_path);
            }
          break;

        case svn_fs_path_change_modify:
        default:
          if (change->text_mod)
            old_change->text_mod = TRUE;
          if (change->prop_mod)
            old_change->prop_mod = TRUE;
          break;
        }

      /* Point our new_change to our (possibly modified) old_change. */
      new_change = old_change;
    }
  else
    {
      /* This change is new to the hash, so make a new public change
         structure from the internal one (in the hash's pool), and dup
         the path into the hash's pool, too. */
      new_change = apr_pcalloc (pool, sizeof (*new_change));
      new_change->node_rev_id = svn_fs_fs__id_copy (change->noderev_id, pool);
      new_change->change_kind = change->kind;
      new_change->text_mod = change->text_mod;
      new_change->prop_mod = change->prop_mod;
      if (change->copyfrom_rev != SVN_INVALID_REVNUM)
        {
          copyfrom_string = apr_psprintf (copyfrom_pool, "%ld %s",
                                          change->copyfrom_rev,
                                          change->copyfrom_path);
        }
      else
        {
          copyfrom_string = apr_pstrdup (copyfrom_pool, "");
        }
      path = apr_pstrdup (pool, change->path);
    }

  /* Add (or update) this path. */
  apr_hash_set (changes, path, APR_HASH_KEY_STRING, new_change);

  /* If we don't yet have a path string allocated in the copyfrom_hash
     get something to use.  If we are adding an entry, allocate
     something new, otherwise we just need a key and the one allocated
     for the changes hash will work. */
  if (! copyfrom_path)
    {
      copyfrom_path = copyfrom_string ? apr_pstrdup (copyfrom_pool, path)
        : path;
    }
  
  apr_hash_set (copyfrom_hash, copyfrom_path, APR_HASH_KEY_STRING,
                copyfrom_string);

  return SVN_NO_ERROR;
}


/* Read the next entry in the changes record from file FILE and store
   the resulting change in *CHANGE_P.  If there is no next record,
   store NULL there.  Perform all allocations from POOL. */
static svn_error_t *
read_change (change_t **change_p,
             apr_file_t *file,
             apr_pool_t *pool)
{
  char buf[4096];
  apr_size_t len = sizeof (buf);
  change_t *change;
  char *str, *last_str;
  svn_error_t *err;

  /* Default return value. */
  *change_p = NULL;

  err = svn_io_read_length_line (file, buf, &len, pool);

  /* Check for a blank line. */
  if (err || (len == 0))
    {
      if (err && APR_STATUS_IS_EOF (err->apr_err))
        {
          svn_error_clear (err);
          return SVN_NO_ERROR;
        }
      if ((len == 0) && (! err))
        return SVN_NO_ERROR;
      return err;
    }

  change = apr_pcalloc (pool, sizeof (*change));

  /* Get the node-id of the change. */
  str = apr_strtok (buf, " ", &last_str);
  if (str == NULL)
    return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
                             _("Invalid changes line in rev-file"));

  change->noderev_id = svn_fs_fs__id_parse (str, strlen (str), pool);

  /* Get the change type. */
  str = apr_strtok (NULL, " ", &last_str);
  if (str == NULL)
    return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
                             _("Invalid changes line in rev-file"));

  if (strcmp (str, ACTION_MODIFY) == 0)
    {
      change->kind = svn_fs_path_change_modify;
    }
  else if (strcmp (str, ACTION_ADD) == 0)
    {
      change->kind = svn_fs_path_change_add;
    }
  else if (strcmp (str, ACTION_DELETE) == 0)
    {
      change->kind = svn_fs_path_change_delete;
    }
  else if (strcmp (str, ACTION_REPLACE) == 0)
    {
      change->kind = svn_fs_path_change_replace;
    }
  else if (strcmp (str, ACTION_RESET) == 0)
    {
      change->kind = svn_fs_path_change_reset;
    }
  else
    {
      return svn_error_create (SVN_ERR_FS_CORRUPT, NULL,
                               _("Invalid change kind in rev file"));
    }

  /* Get the text-mod flag. */
  str = apr_strtok (NULL, " ", &last_str);
  if (str == NULL)
    return svn_error_create (SVN_ERR_FS_CO

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -