FreeBSD/contrib/subversion/subversion/libsvn_fs_fs/transaction.c
/* Merge the internal-use-only CHANGE into a hash of public-FS
   svn_fs_path_change2_t CHANGED_PATHS, collapsing multiple changes into a
   single summarical (is that real word?) change per path.  DELETIONS is
   also a path->svn_fs_path_change2_t hash and contains all the deletions
   that got turned into a replacement. */
Merge the internal-use-only CHANGE into a hash of public-FS
svn_fs_path_change2_t CHANGED_PATHS, collapsing multiple changes into a
single summarical (is that real word?) change per path.  DELETIONS is
also a path->svn_fs_path_change2_t hash and contains all the deletions
that got turned into a replacement.
Merge the internal - use - only CHANGE into a hash of public - FS svn_fs_path_change2_t CHANGED_PATHS collapsing multiple changes into a single summarical ( is that real word? ) change per path . DELETIONS is also a path - > svn_fs_path_change2_t hash and contains all the deletions that got turned into a replacement .
static svn_error_t *
fold_change(apr_hash_t *changed_paths,
            apr_hash_t *deletions,
            const change_t *change)
{
  apr_pool_t *pool = apr_hash_pool_get(changed_paths);
  svn_fs_path_change2_t *old_change, *new_change;
  const svn_string_t *path = &change->path;
  const svn_fs_path_change2_t *info = &change->info;
  if ((old_change = apr_hash_get(changed_paths, path->data, path->len)))
    {
      if ((! info->node_rev_id)
           && (info->change_kind != svn_fs_path_change_reset))
        return svn_error_create
          (SVN_ERR_FS_CORRUPT, NULL,
           _("Missing required node revision ID"));
      if (info->node_rev_id
          && (! svn_fs_fs__id_eq(old_change->node_rev_id, info->node_rev_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"));
      if ((old_change->change_kind == svn_fs_path_change_delete)
          && (! ((info->change_kind == svn_fs_path_change_replace)
                 || (info->change_kind == svn_fs_path_change_reset)
                 || (info->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"));
      if ((info->change_kind == svn_fs_path_change_add)
          && (old_change->change_kind != svn_fs_path_change_delete)
          && (old_change->change_kind != svn_fs_path_change_reset))
        return svn_error_create
          (SVN_ERR_FS_CORRUPT, NULL,
           _("Invalid change ordering: add change on preexisting path"));
      switch (info->change_kind)
        {
        case svn_fs_path_change_reset:
          apr_hash_set(changed_paths, path->data, path->len, NULL);
          break;
        case svn_fs_path_change_delete:
          if (old_change->change_kind == svn_fs_path_change_add)
            {
              apr_hash_set(changed_paths, path->data, path->len, NULL);
            }
          else if (old_change->change_kind == svn_fs_path_change_replace)
            {
              new_change = apr_hash_get(deletions, path->data, path->len);
              SVN_ERR_ASSERT(new_change);
              apr_hash_set(changed_paths, path->data, path->len, new_change);
            }
          else
            {
              new_change = path_change_dup(info, pool);
              apr_hash_set(changed_paths, path->data, path->len, new_change);
            }
          break;
        case svn_fs_path_change_add:
        case svn_fs_path_change_replace:
          new_change = path_change_dup(info, pool);
          new_change->change_kind = svn_fs_path_change_replace;
          apr_hash_set(changed_paths, path->data, path->len, new_change);
          apr_hash_set(deletions,
                       apr_pstrmemdup(apr_hash_pool_get(deletions),
                                      path->data, path->len),
                       path->len, old_change);
          break;
        case svn_fs_path_change_modify:
        default:
          if (info->text_mod)
            old_change->text_mod = TRUE;
          if (info->prop_mod)
            old_change->prop_mod = TRUE;
          if (info->mergeinfo_mod == svn_tristate_true)
            old_change->mergeinfo_mod = svn_tristate_true;
          break;
        }
    }
  else
    {
      apr_hash_set(changed_paths,
                   apr_pstrmemdup(pool, path->data, path->len), path->len,
                   path_change_dup(info, pool));
    }
  return SVN_NO_ERROR;
}
static svn_error_t * fold_change ( apr_hash_t * changed_paths , apr_hash_t * deletions , const change_t * change ) { apr_pool_t * pool = apr_hash_pool_get ( changed_paths ) ; svn_fs_path_change2_t * old_change , * new_change ; const svn_string_t * path = & change -> path ; const svn_fs_path_change2_t * info = & change -> info ; if ( ( old_change = apr_hash_get ( changed_paths , path -> data , path -> len ) ) ) { if ( ( ! info -> node_rev_id ) && ( info -> change_kind != svn_fs_path_change_reset ) ) return svn_error_create ( SVN_ERR_FS_CORRUPT , NULL , _ ( " " ) ) ; if ( info -> node_rev_id && ( ! svn_fs_fs__id_eq ( old_change -> node_rev_id , info -> node_rev_id ) ) && ( old_change -> change_kind != svn_fs_path_change_delete ) ) return svn_error_create ( SVN_ERR_FS_CORRUPT , NULL , _ ( " " " " ) ) ; if ( ( old_change -> change_kind == svn_fs_path_change_delete ) && ( ! ( ( info -> change_kind == svn_fs_path_change_replace ) || ( info -> change_kind == svn_fs_path_change_reset ) || ( info -> change_kind == svn_fs_path_change_add ) ) ) ) return svn_error_create ( SVN_ERR_FS_CORRUPT , NULL , _ ( " " ) ) ; if ( ( info -> change_kind == svn_fs_path_change_add ) && ( old_change -> change_kind != svn_fs_path_change_delete ) && ( old_change -> change_kind != svn_fs_path_change_reset ) ) return svn_error_create ( SVN_ERR_FS_CORRUPT , NULL , _ ( " " ) ) ; switch ( info -> change_kind ) { case svn_fs_path_change_reset : apr_hash_set ( changed_paths , path -> data , path -> len , NULL ) ; break ; case svn_fs_path_change_delete : if ( old_change -> change_kind == svn_fs_path_change_add ) { apr_hash_set ( changed_paths , path -> data , path -> len , NULL ) ; } else if ( old_change -> change_kind == svn_fs_path_change_replace ) { new_change = apr_hash_get ( deletions , path -> data , path -> len ) ; SVN_ERR_ASSERT ( new_change ) ; apr_hash_set ( changed_paths , path -> data , path -> len , new_change ) ; } else { new_change = path_change_dup ( info , pool ) ; apr_hash_set ( changed_paths , path -> data , path -> len , new_change ) ; } break ; case svn_fs_path_change_add : case svn_fs_path_change_replace : new_change = path_change_dup ( info , pool ) ; new_change -> change_kind = svn_fs_path_change_replace ; apr_hash_set ( changed_paths , path -> data , path -> len , new_change ) ; apr_hash_set ( deletions , apr_pstrmemdup ( apr_hash_pool_get ( deletions ) , path -> data , path -> len ) , path -> len , old_change ) ; break ; case svn_fs_path_change_modify : default : if ( info -> text_mod ) old_change -> text_mod = TRUE ; if ( info -> prop_mod ) old_change -> prop_mod = TRUE ; if ( info -> mergeinfo_mod == svn_tristate_true ) old_change -> mergeinfo_mod = svn_tristate_true ; break ; } } else { apr_hash_set ( changed_paths , apr_pstrmemdup ( pool , path -> data , path -> len ) , path -> len , path_change_dup ( info , pool ) ) ; } return SVN_NO_ERROR ; }
Merge the internal-use-only CHANGE into a hash of public-FS
svn_fs_path_change2_t CHANGED_PATHS, collapsing multiple changes into a
single summarical (is that real word?)
Merge the internal - use - only CHANGE into a hash of public - FS svn_fs_path_change2_t CHANGED_PATHS collapsing multiple changes into a single summarical ( is that real word? )
/* This path already exists in the hash, so we have to merge
         this change into the already existing one. */ /* Sanity check:  only allow NULL node revision ID in the
         `reset' case. */ /* Sanity check: we should be talking about the same node
         revision ID as our last change except where the last change
         was a deletion. */ /* Sanity check: an add, replacement, or reset must be the first
         thing to follow a deletion. */ /* Sanity check: an add can't follow anything except
         a delete or reset.  */ /* Now, merge that change in. */ /* A reset here will simply remove the path change from the
             hash. */ /* If the path was introduced in this transaction via an
                 add, and we are deleting it, just remove the path
                 altogether.  (The caller will delete any child paths.) */ /* A deleting a 'replace' restore the original deletion. */ /* A deletion overrules a previous change (modify). */ /* An add at this point must be following a previous delete,
             so treat it just like a replace.  Remember the original
             deletion such that we are able to delete this path again
             (the replacement may have changed node kind and id). */ /* Remember the original change.
           * Make sure to allocate the hash key in a durable pool. */ /* If the new change modifies some attribute of the node, set
             the corresponding flag, whether it already was set or not.
             Note: We do not reset a flag to FALSE if a change is undone. */ /* Add this path.  The API makes no guarantees that this (new) key
         will not be retained.  Thus, we copy the key into the target pool
         to ensure a proper lifetime.  */