FreeBSD/contrib/subversion/subversion/libsvn_repos/replay.c
/* Recursively traverse EDIT_PATH (as it exists under SOURCE_ROOT) emitting
   the appropriate editor calls to add it and its children without any
   history.  This is meant to be used when either a subset of the tree
   has been ignored and we need to copy something from that subset to
   the part of the tree we do care about, or if a subset of the tree is
   unavailable because of authz and we need to use it as the source of
   a copy. */
Recursively traverse EDIT_PATH (as it exists under SOURCE_ROOT) emitting
the appropriate editor calls to add it and its children without any
history.  This is meant to be used when either a subset of the tree
has been ignored and we need to copy something from that subset to
the part of the tree we do care about, or if a subset of the tree is
unavailable because of authz and we need to use it as the source of
a copy.
Recursively traverse EDIT_PATH ( as it exists under SOURCE_ROOT ) emitting the appropriate editor calls to add it and its children without any history . This is meant to be used when either a subset of the tree has been ignored and we need to copy something from that subset to the part of the tree we do care about or if a subset of the tree is unavailable because of authz and we need to use it as the source of a copy .
static svn_error_t *
add_subdir(svn_fs_root_t *source_root,
           svn_fs_root_t *target_root,
           const svn_delta_editor_t *editor,
           void *edit_baton,
           const char *edit_path,
           void *parent_baton,
           const char *source_fspath,
           svn_repos_authz_func_t authz_read_func,
           void *authz_read_baton,
           apr_hash_t *changed_paths,
           apr_pool_t *pool,
           void **dir_baton)
{
  apr_pool_t *subpool = svn_pool_create(pool);
  apr_hash_index_t *hi, *phi;
  apr_hash_t *dirents;
  apr_hash_t *props;
  SVN_ERR(editor->add_directory(edit_path, parent_baton, NULL,
                                SVN_INVALID_REVNUM, pool, dir_baton));
  SVN_ERR(svn_fs_node_proplist(&props, target_root, edit_path, pool));
  for (phi = apr_hash_first(pool, props); phi; phi = apr_hash_next(phi))
    {
      const char *key = apr_hash_this_key(phi);
      svn_string_t *val = apr_hash_this_val(phi);
      svn_pool_clear(subpool);
      SVN_ERR(editor->change_dir_prop(*dir_baton, key, val, subpool));
    }
  SVN_ERR(svn_fs_dir_entries(&dirents, source_root, source_fspath, pool));
  for (hi = apr_hash_first(pool, dirents); hi; hi = apr_hash_next(hi))
    {
      svn_fs_path_change2_t *change;
      svn_boolean_t readable = TRUE;
      svn_fs_dirent_t *dent = apr_hash_this_val(hi);
      const char *copyfrom_path = NULL;
      svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
      const char *new_edit_path;
      svn_pool_clear(subpool);
      new_edit_path = svn_relpath_join(edit_path, dent->name, subpool);
      change = svn_hash_gets(changed_paths, new_edit_path);
      if (change)
        {
          svn_hash_sets(changed_paths, new_edit_path, NULL);
          if (change->change_kind == svn_fs_path_change_delete)
            continue;
          if (change->change_kind == svn_fs_path_change_replace)
            {
              if (! change->copyfrom_known)
                {
                  SVN_ERR(svn_fs_copied_from(&change->copyfrom_rev,
                                             &change->copyfrom_path,
                                             target_root, new_edit_path, pool));
                  change->copyfrom_known = TRUE;
                }
              copyfrom_path = change->copyfrom_path;
              copyfrom_rev = change->copyfrom_rev;
            }
        }
      if (authz_read_func)
        SVN_ERR(authz_read_func(&readable, target_root, new_edit_path,
                                authz_read_baton, pool));
      if (! readable)
        continue;
      if (dent->kind == svn_node_dir)
        {
          svn_fs_root_t *new_source_root;
          const char *new_source_fspath;
          void *new_dir_baton;
          if (copyfrom_path)
            {
              svn_fs_t *fs = svn_fs_root_fs(source_root);
              SVN_ERR(svn_fs_revision_root(&new_source_root, fs,
                                           copyfrom_rev, pool));
              new_source_fspath = copyfrom_path;
            }
          else
            {
              new_source_root = source_root;
              new_source_fspath = svn_fspath__join(source_fspath, dent->name,
                                                   subpool);
            }
          if (change && change->change_kind == svn_fs_path_change_replace
              && copyfrom_path == NULL)
            {
              SVN_ERR(editor->add_directory(new_edit_path, *dir_baton,
                                            NULL, SVN_INVALID_REVNUM,
                                            subpool, &new_dir_baton));
            }
          else
            {
              SVN_ERR(add_subdir(new_source_root, target_root,
                                 editor, edit_baton, new_edit_path,
                                 *dir_baton, new_source_fspath,
                                 authz_read_func, authz_read_baton,
                                 changed_paths, subpool, &new_dir_baton));
            }
          SVN_ERR(editor->close_directory(new_dir_baton, subpool));
        }
      else if (dent->kind == svn_node_file)
        {
          svn_txdelta_window_handler_t delta_handler;
          void *delta_handler_baton, *file_baton;
          svn_txdelta_stream_t *delta_stream;
          svn_checksum_t *checksum;
          SVN_ERR(editor->add_file(new_edit_path, *dir_baton, NULL,
                                   SVN_INVALID_REVNUM, pool, &file_baton));
          SVN_ERR(svn_fs_node_proplist(&props, target_root,
                                       new_edit_path, subpool));
          for (phi = apr_hash_first(pool, props); phi; phi = apr_hash_next(phi))
            {
              const char *key = apr_hash_this_key(phi);
              svn_string_t *val = apr_hash_this_val(phi);
              SVN_ERR(editor->change_file_prop(file_baton, key, val, subpool));
            }
          SVN_ERR(editor->apply_textdelta(file_baton, NULL, pool,
                                          &delta_handler,
                                          &delta_handler_baton));
          SVN_ERR(svn_fs_get_file_delta_stream(&delta_stream, NULL, NULL,
                                               target_root, new_edit_path,
                                               pool));
          SVN_ERR(svn_txdelta_send_txstream(delta_stream,
                                            delta_handler,
                                            delta_handler_baton,
                                            pool));
          SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5, target_root,
                                       new_edit_path, TRUE, pool));
          SVN_ERR(editor->close_file(file_baton,
                                     svn_checksum_to_cstring(checksum, pool),
                                     pool));
        }
      else
        SVN_ERR_MALFUNCTION();
    }
  svn_pool_destroy(subpool);
  return SVN_NO_ERROR;
}
static svn_error_t * add_subdir ( svn_fs_root_t * source_root , svn_fs_root_t * target_root , const svn_delta_editor_t * editor , void * edit_baton , const char * edit_path , void * parent_baton , const char * source_fspath , svn_repos_authz_func_t authz_read_func , void * authz_read_baton , apr_hash_t * changed_paths , apr_pool_t * pool , void * * dir_baton ) { apr_pool_t * subpool = svn_pool_create ( pool ) ; apr_hash_index_t * hi , * phi ; apr_hash_t * dirents ; apr_hash_t * props ; SVN_ERR ( editor -> add_directory ( edit_path , parent_baton , NULL , SVN_INVALID_REVNUM , pool , dir_baton ) ) ; SVN_ERR ( svn_fs_node_proplist ( & props , target_root , edit_path , pool ) ) ; for ( phi = apr_hash_first ( pool , props ) ; phi ; phi = apr_hash_next ( phi ) ) { const char * key = apr_hash_this_key ( phi ) ; svn_string_t * val = apr_hash_this_val ( phi ) ; svn_pool_clear ( subpool ) ; SVN_ERR ( editor -> change_dir_prop ( * dir_baton , key , val , subpool ) ) ; } SVN_ERR ( svn_fs_dir_entries ( & dirents , source_root , source_fspath , pool ) ) ; for ( hi = apr_hash_first ( pool , dirents ) ; hi ; hi = apr_hash_next ( hi ) ) { svn_fs_path_change2_t * change ; svn_boolean_t readable = TRUE ; svn_fs_dirent_t * dent = apr_hash_this_val ( hi ) ; const char * copyfrom_path = NULL ; svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM ; const char * new_edit_path ; svn_pool_clear ( subpool ) ; new_edit_path = svn_relpath_join ( edit_path , dent -> name , subpool ) ; change = svn_hash_gets ( changed_paths , new_edit_path ) ; if ( change ) { svn_hash_sets ( changed_paths , new_edit_path , NULL ) ; if ( change -> change_kind == svn_fs_path_change_delete ) continue ; if ( change -> change_kind == svn_fs_path_change_replace ) { if ( ! change -> copyfrom_known ) { SVN_ERR ( svn_fs_copied_from ( & change -> copyfrom_rev , & change -> copyfrom_path , target_root , new_edit_path , pool ) ) ; change -> copyfrom_known = TRUE ; } copyfrom_path = change -> copyfrom_path ; copyfrom_rev = change -> copyfrom_rev ; } } if ( authz_read_func ) SVN_ERR ( authz_read_func ( & readable , target_root , new_edit_path , authz_read_baton , pool ) ) ; if ( ! readable ) continue ; if ( dent -> kind == svn_node_dir ) { svn_fs_root_t * new_source_root ; const char * new_source_fspath ; void * new_dir_baton ; if ( copyfrom_path ) { svn_fs_t * fs = svn_fs_root_fs ( source_root ) ; SVN_ERR ( svn_fs_revision_root ( & new_source_root , fs , copyfrom_rev , pool ) ) ; new_source_fspath = copyfrom_path ; } else { new_source_root = source_root ; new_source_fspath = svn_fspath__join ( source_fspath , dent -> name , subpool ) ; } if ( change && change -> change_kind == svn_fs_path_change_replace && copyfrom_path == NULL ) { SVN_ERR ( editor -> add_directory ( new_edit_path , * dir_baton , NULL , SVN_INVALID_REVNUM , subpool , & new_dir_baton ) ) ; } else { SVN_ERR ( add_subdir ( new_source_root , target_root , editor , edit_baton , new_edit_path , * dir_baton , new_source_fspath , authz_read_func , authz_read_baton , changed_paths , subpool , & new_dir_baton ) ) ; } SVN_ERR ( editor -> close_directory ( new_dir_baton , subpool ) ) ; } else if ( dent -> kind == svn_node_file ) { svn_txdelta_window_handler_t delta_handler ; void * delta_handler_baton , * file_baton ; svn_txdelta_stream_t * delta_stream ; svn_checksum_t * checksum ; SVN_ERR ( editor -> add_file ( new_edit_path , * dir_baton , NULL , SVN_INVALID_REVNUM , pool , & file_baton ) ) ; SVN_ERR ( svn_fs_node_proplist ( & props , target_root , new_edit_path , subpool ) ) ; for ( phi = apr_hash_first ( pool , props ) ; phi ; phi = apr_hash_next ( phi ) ) { const char * key = apr_hash_this_key ( phi ) ; svn_string_t * val = apr_hash_this_val ( phi ) ; SVN_ERR ( editor -> change_file_prop ( file_baton , key , val , subpool ) ) ; } SVN_ERR ( editor -> apply_textdelta ( file_baton , NULL , pool , & delta_handler , & delta_handler_baton ) ) ; SVN_ERR ( svn_fs_get_file_delta_stream ( & delta_stream , NULL , NULL , target_root , new_edit_path , pool ) ) ; SVN_ERR ( svn_txdelta_send_txstream ( delta_stream , delta_handler , delta_handler_baton , pool ) ) ; SVN_ERR ( svn_fs_file_checksum ( & checksum , svn_checksum_md5 , target_root , new_edit_path , TRUE , pool ) ) ; SVN_ERR ( editor -> close_file ( file_baton , svn_checksum_to_cstring ( checksum , pool ) , pool ) ) ; } else SVN_ERR_MALFUNCTION ( ) ; } svn_pool_destroy ( subpool ) ; return SVN_NO_ERROR ; }
Recursively traverse EDIT_PATH (as it exists under SOURCE_ROOT) emitting
the appropriate editor calls to add it and its children without any
history.
Recursively traverse EDIT_PATH ( as it exists under SOURCE_ROOT ) emitting the appropriate editor calls to add it and its children without any history .
/* We have to get the dirents from the source path, not the target,
     because we want nested copies from *readable* paths to be handled by
     path_driver_cb_func, not add_subdir (in order to preserve history). */ /* If a file or subdirectory of the copied directory is listed as a
         changed path (because it was modified after the copy but before the
         commit), we remove it from the changed_paths hash so that future
         calls to path_driver_cb_func will ignore it. */ /* If it's a delete, skip this entry. */ /* If it's a replacement, check for copyfrom info (if we
             don't have it already. */ /* ### authz considerations?
           *
           * I think not; when path_driver_cb_func() calls add_subdir(), it
           * passes SOURCE_ROOT and SOURCE_FSPATH that are unreadable.
           */