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

📄 rev_hunt.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 2 页
字号:
  svn_fs_root_t *root;
  svn_fs_history_t *history;
  const char *path;
  svn_revnum_t revision;
  apr_pool_t *lastpool, *currpool;

  lastpool = svn_pool_create (pool);
  currpool = svn_pool_create (pool);

  SVN_ERR (svn_fs_revision_root (&root, fs, future_revision, pool));

  SVN_ERR (svn_fs_node_history (&history, root, fs_path, lastpool));

  /* Since paths that are different according to strcmp may still be
     equivalent (due to number of consecutive slashes and the fact that
     "" is the same as "/"), we get the "canonical" path in the first
     iteration below so that the comparison after the loop will work
     correctly. */
  fs_path = NULL;

  while (1)
    {
      apr_pool_t *tmppool;

      SVN_ERR (svn_fs_history_prev (&history, history, TRUE, currpool));

      if (!history)
        break;

      SVN_ERR (svn_fs_history_location (&path, &revision, history, currpool));

      if (!fs_path)
        fs_path = apr_pstrdup (pool, path);

      if (revision <= peg_revision)
        break;

      /* Clear old pool and flip. */
      svn_pool_clear (lastpool);
      tmppool = lastpool;
      lastpool = currpool;
      currpool = tmppool;
    }

  /* We must have had at least one iteration above where we
     reassigned fs_path. Else, the path wouldn't have existed at
     future_revision and svn_fs_history would have thrown. */
  assert (fs_path != NULL);
     
  *is_ancestor = (history && strcmp (path, fs_path) == 0);

  return SVN_NO_ERROR;
}


svn_error_t *
svn_repos_trace_node_locations (svn_fs_t *fs,
                                apr_hash_t **locations,
                                const char *fs_path,
                                svn_revnum_t peg_revision,
                                apr_array_header_t *location_revisions_orig,
                                svn_repos_authz_func_t authz_read_func,
                                void *authz_read_baton,
                                apr_pool_t *pool)
{
  apr_array_header_t *location_revisions;
  svn_revnum_t *revision_ptr, *revision_ptr_end;
  svn_fs_root_t *root;
  svn_fs_history_t *history;
  const char *path;
  svn_revnum_t revision;
  svn_boolean_t is_ancestor;
  apr_pool_t *lastpool, *currpool;

  /* Sanity check. */
  assert (location_revisions_orig->elt_size == sizeof(svn_revnum_t));

  /* Another sanity check. */
  if (authz_read_func)
    {
      svn_fs_root_t *peg_root;
      SVN_ERR (svn_fs_revision_root (&peg_root, fs, peg_revision, pool));
      SVN_ERR (check_readability (peg_root, fs_path,
                                  authz_read_func, authz_read_baton, pool));
    }

  *locations = apr_hash_make (pool);

  /* We flip between two pools in the second loop below. */
  lastpool = svn_pool_create (pool);
  currpool = svn_pool_create (pool);

  /* First - let's sort the array of the revisions from the greatest revision
   * downward, so it will be easier to search on. */
  location_revisions = apr_array_copy (pool, location_revisions_orig);
  qsort (location_revisions->elts, location_revisions->nelts,
         sizeof (*revision_ptr), svn_sort_compare_revisions);

  revision_ptr = (svn_revnum_t *)location_revisions->elts;
  revision_ptr_end = revision_ptr + location_revisions->nelts;

  /* Ignore revisions R that are younger than the peg_revisions where
     path@peg_revision is not an ancestor of path@R. */
  is_ancestor = FALSE;
  while (revision_ptr < revision_ptr_end && *revision_ptr > peg_revision)
    {
      svn_pool_clear (currpool);
      SVN_ERR (check_ancestry_of_peg_path (&is_ancestor, fs, fs_path,
                                           peg_revision, *revision_ptr,
                                           currpool));
      if (is_ancestor)
        break;
      ++revision_ptr;
    }

  SVN_ERR (svn_fs_revision_root (&root, fs,
                                 (is_ancestor ?
                                  (*revision_ptr) :
                                  peg_revision), pool));
  if (authz_read_func)
    SVN_ERR (check_readability (root, fs_path, authz_read_func,
                                authz_read_baton, pool));

  SVN_ERR (svn_fs_node_history (&history, root, fs_path, lastpool));

  while (revision_ptr < revision_ptr_end)
    {
      apr_pool_t *tmppool;

      SVN_ERR (svn_fs_history_prev (&history, history, TRUE, currpool));
      if (!history)
        break;

      SVN_ERR (svn_fs_history_location (&path, &revision, history, currpool));

      if (authz_read_func)
        {
          svn_boolean_t readable;
          svn_fs_root_t *tmp_root;

          SVN_ERR (svn_fs_revision_root (&tmp_root, fs, revision, currpool));
          SVN_ERR (authz_read_func (&readable, tmp_root, path,
                                    authz_read_baton, currpool));
          if (! readable)
            {
              return SVN_NO_ERROR;
            }
        }

      /* Assign the current path to all younger revisions until we reach
         the current one. */
      while ((revision_ptr < revision_ptr_end) && (*revision_ptr >= revision))
        {
          /* *revision_ptr is allocated out of pool, so we can point
             to in the hash table. */
          apr_hash_set (*locations, revision_ptr, sizeof (*revision_ptr),
                        apr_pstrdup (pool, path));
          revision_ptr++;
        }

      /* Clear last pool and switch. */
      svn_pool_clear (lastpool);
      tmppool = lastpool;
      lastpool = currpool;
      currpool = tmppool;
    }

  svn_pool_destroy (lastpool);
  svn_pool_destroy (currpool);

  return SVN_NO_ERROR;
}

svn_error_t *
svn_repos_get_file_revs (svn_repos_t *repos,
                         const char *path,
                         svn_revnum_t start,
                         svn_revnum_t end,
                         svn_repos_authz_func_t authz_read_func,
                         void *authz_read_baton,
                         svn_repos_file_rev_handler_t handler,
                         void *handler_baton,
                         apr_pool_t *pool)
{
  apr_pool_t *iter_pool, *last_pool;
  svn_fs_history_t *history;
  apr_array_header_t *revnums = apr_array_make (pool, 0,
                                                sizeof (svn_revnum_t));
  apr_array_header_t *paths = apr_array_make (pool, 0, sizeof (char *));
  apr_hash_t *last_props;
  svn_fs_root_t *root, *last_root;
  const char *last_path;
  int i;

  /* We switch betwwen two pools while looping, since we need information from
     the last iteration to be available. */
  iter_pool = svn_pool_create (pool);
  last_pool = svn_pool_create (pool);

  /* Open revision root for path@end. */
  /* ### Can we use last_pool for this? How long does the history
     object need the root? */
  SVN_ERR (svn_fs_revision_root (&root, repos->fs, end, pool));

  /* Open a history object. */
  SVN_ERR (svn_fs_node_history (&history, root, path, last_pool));
  
  /* Get the revisions we are interested in. */
  while (1)
    {
      const char* rev_path;
      svn_revnum_t rev;
      apr_pool_t *tmp_pool;

      svn_pool_clear (iter_pool);

      SVN_ERR (svn_fs_history_prev (&history, history, TRUE, iter_pool));
      if (!history)
        break;
      SVN_ERR (svn_fs_history_location (&rev_path, &rev, history, iter_pool));
      if (authz_read_func)
        {
          svn_boolean_t readable;
          svn_fs_root_t *tmp_root;

          SVN_ERR (svn_fs_revision_root (&tmp_root, repos->fs, rev, iter_pool));
          SVN_ERR (authz_read_func (&readable, tmp_root, rev_path,
                                    authz_read_baton, iter_pool));
          if (! readable)
            {
              break;
            }
        }
      *(svn_revnum_t*) apr_array_push (revnums) = rev;
      *(char **) apr_array_push (paths) = apr_pstrdup (pool, rev_path);
      if (rev <= start)
        break;

      /* Swap pools. */
      tmp_pool = iter_pool;
      iter_pool = last_pool;
      last_pool = tmp_pool;
    }

  /* We must have at least one revision to get. */
  assert (revnums->nelts > 0);

  /* We want the first txdelta to be against the empty file. */
  last_root = NULL;
  last_path = NULL;

  /* Create an empty hash table for the first property diff. */
  last_props = apr_hash_make (last_pool);

  /* Walk through the revisions in chronological order. */
  for (i = revnums->nelts; i > 0; --i)
    {
      svn_revnum_t rev = APR_ARRAY_IDX (revnums, i - 1, svn_revnum_t);
      const char *rev_path = APR_ARRAY_IDX (paths, i - 1, const char *);
      apr_hash_t *rev_props;
      apr_hash_t *props;
      apr_array_header_t *prop_diffs;
      svn_txdelta_stream_t *delta_stream;
      svn_txdelta_window_handler_t delta_handler = NULL;
      void *delta_baton = NULL;
      apr_pool_t *tmp_pool;  /* For swapping */
      svn_boolean_t contents_changed;

      svn_pool_clear (iter_pool);

      /* Get the revision properties. */
      SVN_ERR (svn_fs_revision_proplist (&rev_props, repos->fs,
                                         rev, iter_pool));

      /* Open the revision root. */
      SVN_ERR (svn_fs_revision_root (&root, repos->fs, rev, iter_pool));

      /* Get the file's properties for this revision and compute the diffs. */
      SVN_ERR (svn_fs_node_proplist (&props, root, rev_path, iter_pool));
      SVN_ERR (svn_prop_diffs (&prop_diffs, props, last_props, pool));

      /* Check if the contents changed. */
      /* Special case: In the first revision, we always provide a delta. */
      if (last_root)
        SVN_ERR (svn_fs_contents_changed (&contents_changed,
                                          last_root, last_path,
                                          root, rev_path, iter_pool));
      else
        contents_changed = TRUE;

      /* We have all we need, give to the handler. */
      SVN_ERR (handler (handler_baton, rev_path, rev, rev_props,
                        contents_changed ? &delta_handler : NULL,
                        contents_changed ? &delta_baton : NULL,
                        prop_diffs, iter_pool));

      /* Compute and send delta if client asked for it.
         Note that this was initialized to NULL, so if !contents_changed,
         no deltas will be computed. */
      if (delta_handler)
        {
          /* Get the content delta. */
          SVN_ERR (svn_fs_get_file_delta_stream (&delta_stream,
                                                 last_root, last_path,
                                                 root, rev_path,
                                                 iter_pool));
          /* And send. */
          SVN_ERR (svn_txdelta_send_txstream (delta_stream,
                                              delta_handler, delta_baton,
                                              iter_pool));
        }

      /* Remember root, path and props for next iteration. */
      last_root = root;
      last_path = rev_path;
      last_props = props;

      /* Swap the pools. */
      tmp_pool = iter_pool;
      iter_pool = last_pool;
      last_pool = tmp_pool;
    }

  svn_pool_destroy (last_pool);
  svn_pool_destroy (iter_pool);

  return SVN_NO_ERROR;
}

⌨️ 快捷键说明

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