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

📄 reporter.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
        SVN_ERR (b->editor->add_file (e_path, dir_baton, NULL,
                                      SVN_INVALID_REVNUM, pool, &new_baton));
      SVN_ERR (delta_files (b, new_baton, s_rev, s_path, t_path, pool));
      SVN_ERR (svn_fs_file_md5_checksum (digest, b->t_root, t_path, pool));
      hex_digest = svn_md5_digest_to_cstring (digest, pool);
      return b->editor->close_file (new_baton, hex_digest, pool);
    }
}


/* Emit edits within directory DIR_BATON (with corresponding path
   E_PATH) with the changes from the directory S_REV/S_PATH to the
   directory B->t_rev/T_PATH.  S_PATH may be NULL if the entry does
   not exist in the source. */
static svn_error_t *
delta_dirs (report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
            const char *t_path, void *dir_baton, const char *e_path,
            svn_boolean_t start_empty, apr_pool_t *pool)
{
  svn_fs_root_t *s_root;
  apr_hash_t *s_entries = NULL, *t_entries;
  apr_hash_index_t *hi;
  apr_pool_t *subpool;
  const svn_fs_dirent_t *s_entry, *t_entry;
  void *val;
  const char *name, *s_fullpath, *t_fullpath, *e_fullpath;
  path_info_t *info;

  /* Compare the property lists.  If we're starting empty, pass a NULL
     source path so that we add all the properties. */
  SVN_ERR (delta_proplists (b, s_rev, start_empty ? NULL : s_path, t_path,
                            change_dir_prop, dir_baton, pool));

  /* Get the list of entries in each of source and target. */
  if (s_path && !start_empty)
    {
      SVN_ERR (get_source_root (b, &s_root, s_rev));
      SVN_ERR (svn_fs_dir_entries (&s_entries, s_root, s_path, pool));
    }
  SVN_ERR (svn_fs_dir_entries (&t_entries, b->t_root, t_path, pool));

  /* Iterate over the report information for this directory. */
  subpool = svn_pool_create (pool);

  while (1)
    {
      svn_pool_clear (subpool);
      SVN_ERR (fetch_path_info (b, &name, &info, e_path, subpool));
      if (!name)
        break;
      e_fullpath = svn_path_join (e_path, name, subpool);
      t_fullpath = svn_path_join (t_path, name, subpool);
      t_entry = apr_hash_get (t_entries, name, APR_HASH_KEY_STRING);
      s_fullpath = s_path ? svn_path_join (s_path, name, subpool) : NULL;
      s_entry = s_entries ?
        apr_hash_get (s_entries, name, APR_HASH_KEY_STRING) : NULL;

      SVN_ERR (update_entry (b, s_rev, s_fullpath, s_entry, t_fullpath,
                             t_entry, dir_baton, e_fullpath, info,
                             b->recurse, subpool));

      /* Don't revisit this name in the target or source entries. */
      apr_hash_set (t_entries, name, APR_HASH_KEY_STRING, NULL);
      if (s_entries)
        apr_hash_set (s_entries, name, APR_HASH_KEY_STRING, NULL);

      /* pathinfo entries live in their own subpools due to lookahead,
         so we need to clear each one out as we finish with it. */
      if (info)
        svn_pool_destroy (info->pool);
    }

  /* Loop over the remaining dirents in the target. */
  for (hi = apr_hash_first (pool, t_entries); hi; hi = apr_hash_next (hi))
    {
      svn_pool_clear (subpool);
      apr_hash_this (hi, NULL, NULL, &val);
      t_entry = val;

      /* Compose the report, editor, and target paths for this entry. */
      e_fullpath = svn_path_join (e_path, t_entry->name, subpool);
      t_fullpath = svn_path_join (t_path, t_entry->name, subpool);

      /* Look for an entry with the same name in the source dirents. */
      s_entry = s_entries ?
        apr_hash_get (s_entries, t_entry->name, APR_HASH_KEY_STRING) : NULL;
      s_fullpath = s_entry ? svn_path_join (s_path, t_entry->name, subpool)
        : NULL;

      SVN_ERR (update_entry (b, s_rev, s_fullpath, s_entry, t_fullpath,
                             t_entry, dir_baton, e_fullpath, NULL,
                             b->recurse, subpool));

      /* Don't revisit this name in the source entries. */
      if (s_entries)
        apr_hash_set (s_entries, t_entry->name, APR_HASH_KEY_STRING, NULL);
    }

  /* Loop over the remaining dirents in the source. */
  if (s_entries)
    {
      for (hi = apr_hash_first (pool, s_entries); hi; hi = apr_hash_next (hi))
        {
          svn_pool_clear (subpool);
          apr_hash_this (hi, NULL, NULL, &val);
          s_entry = val;

          /* We know there is no corresponding target entry, so just delete. */
          e_fullpath = svn_path_join (e_path, s_entry->name, subpool);
          if (b->recurse || s_entry->kind != svn_node_dir)
            SVN_ERR (b->editor->delete_entry (e_fullpath, SVN_INVALID_REVNUM,
                                              dir_baton, subpool));
        }
    }

  /* Destroy iteration subpool. */
  svn_pool_destroy (subpool);

  return SVN_NO_ERROR;
}

static svn_error_t *
drive (report_baton_t *b, svn_revnum_t s_rev, path_info_t *info,
       apr_pool_t *pool)
{
  const char *t_anchor, *s_fullpath;
  svn_boolean_t allowed, info_is_set_path;
  svn_fs_root_t *s_root;
  const svn_fs_dirent_t *s_entry, *t_entry;
  void *root_baton;

  /* Compute the target path corresponding to the working copy anchor,
     and check its authorization. */
  t_anchor = *b->s_operand ? svn_path_dirname (b->t_path, pool) : b->t_path;
  SVN_ERR (check_auth (b, &allowed, t_anchor, pool));
  if (!allowed)
    return svn_error_create (SVN_ERR_AUTHZ_ROOT_UNREADABLE, NULL,
                             "Not authorized to open root of edit operation.");

  SVN_ERR (b->editor->set_target_revision (b->edit_baton, b->t_rev, pool));

  /* Collect information about the source and target nodes. */
  s_fullpath = svn_path_join (b->fs_base, b->s_operand, pool);
  SVN_ERR (get_source_root (b, &s_root, s_rev));
  SVN_ERR (fake_dirent (&s_entry, s_root, s_fullpath, pool));
  SVN_ERR (fake_dirent (&t_entry, b->t_root, b->t_path, pool));

  /* If the operand is a locally added file or directory, it won't
     exist in the source, so accept that. */
  info_is_set_path = (SVN_IS_VALID_REVNUM (info->rev) && !info->link_path);
  if (info_is_set_path && !s_entry)
    s_fullpath = NULL;

  /* If the anchor is the operand, the source and target must be dirs.
     Check this before opening the root to avoid modifying the wc. */
  if (!*b->s_operand && (!s_entry || s_entry->kind != svn_node_dir
                         || !t_entry || t_entry->kind != svn_node_dir))
    return svn_error_create (SVN_ERR_FS_PATH_SYNTAX, NULL,
                             "Cannot replace a directory from within");

  SVN_ERR (b->editor->open_root (b->edit_baton, s_rev, pool, &root_baton));

  /* If the anchor is the operand, diff the two directories; otherwise
     update the operand within the anchor directory. */
  if (!*b->s_operand)
    SVN_ERR (delta_dirs (b, s_rev, s_fullpath, b->t_path, root_baton,
                         "", info->start_empty, pool));
  else
    SVN_ERR (update_entry (b, s_rev, s_fullpath, s_entry, b->t_path,
                           t_entry, root_baton, b->s_operand, info,
                           TRUE, pool));

  SVN_ERR (b->editor->close_directory (root_baton, pool));
  SVN_ERR (b->editor->close_edit (b->edit_baton, pool));
  return SVN_NO_ERROR;
}

/* Initialize the baton fields for editor-driving, and drive the editor. */
static svn_error_t *
finish_report (report_baton_t *b, apr_pool_t *pool)
{
  apr_off_t offset;
  path_info_t *info;
  apr_pool_t *subpool;
  svn_revnum_t s_rev;
  int i;

  /* Save our pool to manage the lookahead and fs_root cache with. */
  b->pool = pool;

  /* Add an end marker and rewind the temporary file. */
  SVN_ERR (svn_io_file_write_full (b->tempfile, "-", 1, NULL, pool));
  offset = 0;
  SVN_ERR (svn_io_file_seek (b->tempfile, APR_SET, &offset, pool));

  /* Read the first pathinfo from the report and verify that it is a top-level
     set_path entry. */
  SVN_ERR (read_path_info (&info, b->tempfile, pool));
  if (!info || strcmp (info->path, b->s_operand) != 0
      || info->link_path || !SVN_IS_VALID_REVNUM(info->rev))
    return svn_error_create (SVN_ERR_REPOS_BAD_REVISION_REPORT, NULL,
                             "Invalid report for top level of working copy");
  s_rev = info->rev;

  /* Initialize the lookahead pathinfo. */
  subpool = svn_pool_create (pool);
  SVN_ERR (read_path_info (&b->lookahead, b->tempfile, subpool));

  if (b->lookahead && strcmp(b->lookahead->path, b->s_operand) == 0)
    {
      /* If the operand of the wc operation is switched or deleted,
         then info above is just a place-holder, and the only thing we
         have to do is pass the revision it contains to open_root.
         The next pathinfo actually describes the target. */
      if (!*b->s_operand)
        return svn_error_create (SVN_ERR_REPOS_BAD_REVISION_REPORT, NULL,
                                 "Two top-level reports with no target");
      info = b->lookahead;
      SVN_ERR (read_path_info (&b->lookahead, b->tempfile, subpool));
    }

  /* Open the target root and initialize the source root cache. */
  SVN_ERR (svn_fs_revision_root (&b->t_root, b->repos->fs, b->t_rev, pool));
  for (i = 0; i < NUM_CACHED_SOURCE_ROOTS; i++)
    b->s_roots[i] = NULL;

  return drive (b, s_rev, info, pool);
}

/* --- COLLECTING THE REPORT INFORMATION --- */

/* Record a report operation into the temporary file. */
static svn_error_t *
write_path_info (report_baton_t *b, const char *path, const char *lpath,
                 svn_revnum_t rev, svn_boolean_t start_empty, apr_pool_t *pool)
{
  const char *lrep, *rrep, *rep;

  /* Munge the path to be anchor-relative, so that we can use edit paths
     as report paths. */
  path = svn_path_join (b->s_operand, path, pool);

  lrep = lpath ? apr_psprintf (pool, "+%" APR_SIZE_T_FMT ":%s",
                               strlen(lpath), lpath) : "-";
  rrep = (SVN_IS_VALID_REVNUM (rev)) ?
    apr_psprintf (pool, "+%ld:", rev) : "-";
  rep = apr_psprintf (pool, "+%" APR_SIZE_T_FMT ":%s%s%s%c",
                      strlen(path), path, lrep, rrep, start_empty ? '+' : '-');
  return svn_io_file_write_full (b->tempfile, rep, strlen(rep), NULL, pool);
}

svn_error_t *
svn_repos_set_path (void *baton, const char *path, svn_revnum_t rev,
                    svn_boolean_t start_empty, apr_pool_t *pool)
{
  return write_path_info (baton, path, NULL, rev, start_empty, pool);
}

svn_error_t *
svn_repos_link_path (void *baton, const char *path, const char *link_path,
                     svn_revnum_t rev, svn_boolean_t start_empty,
                     apr_pool_t *pool)
{
  return write_path_info (baton, path, link_path, rev, start_empty, pool);
}

svn_error_t *
svn_repos_delete_path (void *baton, const char *path, apr_pool_t *pool)
{
  return write_path_info (baton, path, NULL, SVN_INVALID_REVNUM, FALSE, pool);
}

svn_error_t *
svn_repos_finish_report (void *baton, apr_pool_t *pool)
{
  report_baton_t *b = baton;
  svn_error_t *finish_err, *close_err;

  finish_err = finish_report (b, pool);
  close_err = svn_io_file_close (b->tempfile, pool);
  if (finish_err)
    svn_error_clear (close_err);
  return finish_err ? finish_err : close_err;
}

svn_error_t *
svn_repos_abort_report (void *baton, apr_pool_t *pool)
{
  report_baton_t *b = baton;

  return svn_io_file_close (b->tempfile, pool);
}

/* --- BEGINNING THE REPORT --- */

svn_error_t *
svn_repos_begin_report (void **report_baton,
                        svn_revnum_t revnum,
                        const char *username,
                        svn_repos_t *repos,
                        const char *fs_base,
                        const char *s_operand,
                        const char *switch_path,
                        svn_boolean_t text_deltas,
                        svn_boolean_t recurse,
                        svn_boolean_t ignore_ancestry,
                        const svn_delta_editor_t *editor,
                        void *edit_baton,
                        svn_repos_authz_func_t authz_read_func,
                        void *authz_read_baton,
                        apr_pool_t *pool)
{
  report_baton_t *b;
  const char *tempdir, *dummy;

  /* Build a reporter baton.  Copy strings in case the caller doesn't
     keep track of them. */
  b = apr_palloc (pool, sizeof (*b));
  b->repos = repos;
  b->fs_base = apr_pstrdup (pool, fs_base);
  b->s_operand = apr_pstrdup (pool, s_operand);
  b->t_rev = revnum;
  b->t_path = switch_path ? switch_path
    : svn_path_join (fs_base, s_operand, pool);
  b->text_deltas = text_deltas;
  b->recurse = recurse;
  b->ignore_ancestry = ignore_ancestry;
  b->is_switch = (switch_path != NULL);
  b->editor = editor;
  b->edit_baton = edit_baton;
  b->authz_read_func = authz_read_func;
  b->authz_read_baton = authz_read_baton;

  SVN_ERR (svn_io_temp_dir (&tempdir, pool));
  SVN_ERR (svn_io_open_unique_file (&b->tempfile, &dummy,
                                    apr_psprintf (pool, "%s/report", tempdir),
                                    ".tmp", TRUE, pool));

  /* Hand reporter back to client. */
  *report_baton = b;
  return SVN_NO_ERROR;
}

⌨️ 快捷键说明

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