Alien-SVN

 view release on metacpan or  search on metacpan

src/subversion/subversion/libsvn_client/commit_util.c  view on Meta::CPAN

                        const char *local_abspath,
                        const svn_wc_status3_t *status,
                        apr_pool_t *scratch_pool);

static svn_error_t *
harvest_committables(const char *local_abspath,
                     svn_client__committables_t *committables,
                     apr_hash_t *lock_tokens,
                     const char *copy_mode_relpath,
                     svn_depth_t depth,
                     svn_boolean_t just_locked,
                     apr_hash_t *changelists,
                     apr_hash_t *danglers,
                     svn_client__check_url_kind_t check_url_func,
                     void *check_url_baton,
                     svn_cancel_func_t cancel_func,
                     void *cancel_baton,
                     svn_wc_notify_func2_t notify_func,
                     void *notify_baton,
                     svn_wc_context_t *wc_ctx,
                     apr_pool_t *result_pool,
                     apr_pool_t *scratch_pool)
{
  struct harvest_baton baton;

  SVN_ERR_ASSERT((just_locked && lock_tokens) || !just_locked);

  baton.root_abspath = local_abspath;
  baton.committables = committables;
  baton.lock_tokens = lock_tokens;
  baton.commit_relpath = copy_mode_relpath;
  baton.depth = depth;
  baton.just_locked = just_locked;
  baton.changelists = changelists;
  baton.danglers = danglers;
  baton.check_url_func = check_url_func;
  baton.check_url_baton = check_url_baton;
  baton.notify_func = notify_func;
  baton.notify_baton = notify_baton;
  baton.wc_ctx = wc_ctx;
  baton.result_pool = result_pool;

  baton.skip_below_abspath = NULL;

  SVN_ERR(svn_wc_walk_status(wc_ctx,
                             local_abspath,
                             depth,
                             (copy_mode_relpath != NULL) /* get_all */,
                             FALSE /* no_ignore */,
                             FALSE /* ignore_text_mods */,
                             NULL /* ignore_patterns */,
                             harvest_status_callback,
                             &baton,
                             cancel_func, cancel_baton,
                             scratch_pool));

  return SVN_NO_ERROR;
}

static svn_error_t *
harvest_not_present_for_copy(svn_wc_context_t *wc_ctx,
                             const char *local_abspath,
                             svn_client__committables_t *committables,
                             const char *repos_root_url,
                             const char *commit_relpath,
                             svn_client__check_url_kind_t check_url_func,
                             void *check_url_baton,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool)
{
  const apr_array_header_t *children;
  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
  int i;

  /* A function to retrieve not present children would be nice to have */
  SVN_ERR(svn_wc__node_get_children_of_working_node(
                                    &children, wc_ctx, local_abspath, TRUE,
                                    scratch_pool, iterpool));

  for (i = 0; i < children->nelts; i++)
    {
      const char *this_abspath = APR_ARRAY_IDX(children, i, const char *);
      const char *name = svn_dirent_basename(this_abspath, NULL);
      const char *this_commit_relpath;
      svn_boolean_t not_present;
      svn_node_kind_t kind;

      svn_pool_clear(iterpool);

      SVN_ERR(svn_wc__node_is_not_present(&not_present, NULL, NULL, wc_ctx,
                                          this_abspath, FALSE, scratch_pool));

      if (!not_present)
        continue;

      if (commit_relpath == NULL)
        this_commit_relpath = NULL;
      else
        this_commit_relpath = svn_relpath_join(commit_relpath, name,
                                              iterpool);

      /* We should check if we should really add a delete operation */
      if (check_url_func)
        {
          svn_revnum_t parent_rev;
          const char *parent_repos_relpath;
          const char *parent_repos_root_url;
          const char *node_url;

          /* Determine from what parent we would be the deleted child */
          SVN_ERR(svn_wc__node_get_origin(
                              NULL, &parent_rev, &parent_repos_relpath,
                              &parent_repos_root_url, NULL, NULL,
                              wc_ctx,
                              svn_dirent_dirname(this_abspath,
                                                  scratch_pool),
                              FALSE, scratch_pool, scratch_pool));

          node_url = svn_path_url_add_component2(
                        svn_path_url_add_component2(parent_repos_root_url,
                                                    parent_repos_relpath,
                                                    scratch_pool),
                        svn_dirent_basename(this_abspath, NULL),
                        iterpool);

          SVN_ERR(check_url_func(check_url_baton, &kind,
                                 node_url, parent_rev, iterpool));

          if (kind == svn_node_none)
            continue; /* This node can't be deleted */
        }
      else
        SVN_ERR(svn_wc_read_kind2(&kind, wc_ctx, this_abspath,
                                  TRUE, TRUE, scratch_pool));

      SVN_ERR(add_committable(committables, this_abspath, kind,
                              repos_root_url,
                              this_commit_relpath,
                              SVN_INVALID_REVNUM,
                              NULL /* copyfrom_relpath */,
                              SVN_INVALID_REVNUM /* copyfrom_rev */,
                              NULL /* moved_from_abspath */,
                              SVN_CLIENT_COMMIT_ITEM_DELETE,
                              NULL, NULL,
                              result_pool, scratch_pool));
    }

  svn_pool_destroy(iterpool);
  return SVN_NO_ERROR;
}

/* Implements svn_wc_status_func4_t */
static svn_error_t *

src/subversion/subversion/libsvn_client/commit_util.c  view on Meta::CPAN

  */
  if (matches_changelists
      && (is_harvest_root || baton->changelists)
      && state_flags
      && (is_added || (is_deleted && is_op_root && status->copied))
      && baton->danglers)
    {
      /* If a node is added, its parent must exist in the repository at the
         time of committing */
      apr_hash_t *danglers = baton->danglers;
      svn_boolean_t parent_added;
      const char *parent_abspath = svn_dirent_dirname(local_abspath,
                                                      scratch_pool);

      /* First check if parent is already in the list of commits
         (Common case for GUI clients that provide a list of commit targets) */
      if (look_up_committable(committables, parent_abspath, scratch_pool))
        parent_added = FALSE; /* Skip all expensive checks */
      else
        SVN_ERR(svn_wc__node_is_added(&parent_added, wc_ctx, parent_abspath,
                                      scratch_pool));

      if (parent_added)
        {
          const char *copy_root_abspath;
          svn_boolean_t parent_is_copy;

          /* The parent is added, so either it is a copy, or a locally added
           * directory. In either case, we require the op-root of the parent
           * to be part of the commit. See issue #4059. */
          SVN_ERR(svn_wc__node_get_origin(&parent_is_copy, NULL, NULL, NULL,
                                          NULL, &copy_root_abspath,
                                          wc_ctx, parent_abspath,
                                          FALSE, scratch_pool, scratch_pool));

          if (parent_is_copy)
            parent_abspath = copy_root_abspath;

          if (!svn_hash_gets(danglers, parent_abspath))
            {
              svn_hash_sets(danglers, apr_pstrdup(result_pool, parent_abspath),
                            apr_pstrdup(result_pool, local_abspath));
            }
        }
    }

  if (is_deleted && !is_added)
    {
      /* Skip all descendants */
      if (status->kind == svn_node_dir)
        baton->skip_below_abspath = apr_pstrdup(baton->result_pool,
                                                local_abspath);
      return SVN_NO_ERROR;
    }

  /* Recursively handle each node according to depth, except when the
     node is only being deleted, or is in an added tree (as added trees
     use the normal commit handling). */
  if (copy_mode && !is_added && !is_deleted && status->kind == svn_node_dir)
    {
      SVN_ERR(harvest_not_present_for_copy(wc_ctx, local_abspath, committables,
                                           repos_root_url, commit_relpath,
                                           baton->check_url_func,
                                           baton->check_url_baton,
                                           result_pool, scratch_pool));
    }

  return SVN_NO_ERROR;
}

/* Baton for handle_descendants */
struct handle_descendants_baton
{
  svn_wc_context_t *wc_ctx;
  svn_cancel_func_t cancel_func;
  void *cancel_baton;
  svn_client__check_url_kind_t check_url_func;
  void *check_url_baton;
  svn_client__committables_t *committables;
};

/* Helper for the commit harvesters */
static svn_error_t *
handle_descendants(void *baton,
                   const void *key, apr_ssize_t klen, void *val,
                   apr_pool_t *pool)
{
  struct handle_descendants_baton *hdb = baton;
  apr_array_header_t *commit_items = val;
  apr_pool_t *iterpool = svn_pool_create(pool);
  const char *repos_root_url = key;
  int i;

  for (i = 0; i < commit_items->nelts; i++)
    {
      svn_client_commit_item3_t *item =
        APR_ARRAY_IDX(commit_items, i, svn_client_commit_item3_t *);
      const apr_array_header_t *absent_descendants;
      int j;

      /* Is this a copy operation? */
      if (!(item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD)
          || ! item->copyfrom_url)
        continue;

      if (hdb->cancel_func)
        SVN_ERR(hdb->cancel_func(hdb->cancel_baton));

      svn_pool_clear(iterpool);

      SVN_ERR(svn_wc__get_not_present_descendants(&absent_descendants,
                                                  hdb->wc_ctx, item->path,
                                                  iterpool, iterpool));

      for (j = 0; j < absent_descendants->nelts; j++)
        {
          svn_node_kind_t kind;
          svn_client_commit_item3_t *desc_item;
          const char *relpath = APR_ARRAY_IDX(absent_descendants, j,
                                              const char *);
          const char *local_abspath = svn_dirent_join(item->path, relpath,
                                                      iterpool);

          /* ### Need a sub-iterpool? */


          /* We found a 'not present' descendant during a copy (at op_depth>0),
             this is most commonly caused by copying some mixed revision tree.

             In this case not present can imply that the node does not exist
             in the parent revision, or that the node does. But we want to copy
             the working copy state in which it does not exist, but might be
             replaced. */

          desc_item = svn_hash_gets(hdb->committables->by_path, local_abspath);

          /* If the path has a commit operation (possibly at an higher
             op_depth, we might want to turn an add in a replace. */
          if (desc_item)
            {
              const char *dir;
              svn_boolean_t found_intermediate = FALSE;

              if (desc_item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
                continue; /* We already have a delete or replace */
              else if (!(desc_item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
                continue; /* Not a copy/add, just a modification */

              dir = svn_dirent_dirname(local_abspath, iterpool);

              while (strcmp(dir, item->path))
                {
                  svn_client_commit_item3_t *i_item;

                  i_item = svn_hash_gets(hdb->committables->by_path, dir);

                  if (i_item)
                    {
                      if ((i_item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
                          || (i_item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
                        {
                          found_intermediate = TRUE;
                          break;
                        }
                    }
                  dir = svn_dirent_dirname(dir, iterpool);
                }

              if (found_intermediate)
                continue; /* Some intermediate ancestor is an add or delete */



( run in 1.169 second using v1.01-cache-2.11-cpan-524268b4103 )