Alien-SVN

 view release on metacpan or  search on metacpan

src/subversion/subversion/bindings/cxxhl/src/exception.cpp  view on Meta::CPAN

{
  const bool throw_cancelled = (err->apr_err == SVN_ERR_CANCELLED);
  detail::error_description* description = NULL;
  try
    {
      // Be very careful when creating the error descriptions, so that
      // the exception unwinder can free them if an allocation fails.
      // The private constructor does not increment the refcount
      // precisely for this reason.

      shared_ptr nested;
      shared_ptr* current = &nested;

      for (svn_error_t* next = err->child; next; next = next->child)
        {
          description = detail::error_description::create(
              next->message, next->file, next->line,
              svn_error__is_tracing_link(next));
          description->reference();
          current->reset(new error(next->apr_err, description));
          description = NULL;
          current = &(*current)->m_nested;
        }

      const int apr_err = err->apr_err;
      description = detail::error_description::create(
          err->message, err->file, err->line,
          svn_error__is_tracing_link(err));
      description->reference();
      svn_error_clear(err);
      if (throw_cancelled)
        {
          cancelled converted = cancelled(apr_err, description);
          description = NULL;
          converted.m_nested = nested;
          throw converted;
        }
      else
        {
          error converted = error(apr_err, description);
          description = NULL;
          converted.m_nested = nested;
          throw converted;
        }
    }
  catch (...)
    {
      description->dereference();
      throw;
    }
}


namespace {
void handle_one_error(error::message_list& ml, bool show_traces,
                      int error_code, detail::error_description* descr,
                      apr_pool_t* pool)
{
  if (show_traces && descr->file())
    {
      const char* file_utf8 = NULL;
      svn_error_t* err =
        svn_utf_cstring_to_utf8(&file_utf8, descr->file(), pool);
      if (err)
        {
          svn_error_clear(err);
          file_utf8 = NULL;
        }
      std::ostringstream buffer;
      if (file_utf8)
        buffer << file_utf8 << ':' << descr->line();
      else
        buffer << "svn:<undefined>";
      buffer << ": (apr_err=" << error_code << ')';
      ml.push_back(error::message(0, buffer.str()));
    }

  if (descr->trace())
    return;

  const char *description = descr->what();
  if (!description)
    {
      char errorbuf[512];

      // Is this a Subversion-specific error code?
      if (error_code > APR_OS_START_USEERR
          && error_code <= APR_OS_START_CANONERR)
        description = svn_strerror(error_code, errorbuf, sizeof(errorbuf));
      // Otherwise, this must be an APR error code.
      else
        {
          svn_error_t* err = svn_utf_cstring_to_utf8(
              &description,
              apr_strerror(error_code, errorbuf, sizeof(errorbuf)),
              pool);
          if (err)
            {
              svn_error_clear(err);
              description = _("Can't recode error string from APR");
            }
        }
    }
  ml.push_back(error::message(error_code, std::string(description)));
}
} // anonymous namespace

error::message_list error::compile_messages(bool show_traces) const
{
  // Determine the maximum size of the returned list
  message_list::size_type max_length = 0;
  for (const error* err = this; err; err = err->m_nested.get())
    {
      if (show_traces && m_description->file())
        ++max_length;                   // We will display an error location
      if (!m_description->trace())
        ++max_length;                   // Traces do not emit a message line
    }
  message_list ml;
  ml.reserve(max_length);

  // This vector holds a list of all error codes that we've printed
  // the generic description for.  See svn_handle_error2 for details.
  std::vector<int> empties;
  empties.reserve(max_length);

  apr_pool_t* pool = NULL;
  apr_pool_create(&pool, NULL);
  try
    {
      for (const error* err = this; err; err = err->m_nested.get())
        {
          if (!err->m_description->what())
            {
              // Non-specific messages are printed only once.
              std::vector<int>::iterator it = std::find(
                  empties.begin(), empties.end(), err->m_errno);
              if (it != empties.end())
                continue;
              empties.push_back(err->m_errno);
            }
          handle_one_error(ml, show_traces,
                           err->m_errno, err->m_description,
                           pool);
        }
    }
  catch (...)
    {
      apr_pool_destroy(pool);
      throw;
    }

  apr_pool_destroy(pool);



( run in 0.562 second using v1.01-cache-2.11-cpan-5b529ec07f3 )