/*
 * url.c:  converting paths to urls
 *
 * ====================================================================
 * Copyright (c) 2000-2007 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 */



#include <apr_pools.h>

#include "svn_pools.h"
#include "svn_error.h"
#include "svn_types.h"
#include "svn_opt.h"
#include "svn_wc.h"
#include "svn_client.h"
#include "svn_path.h"

#include "private/svn_wc_private.h"
#include "client.h"
#include "svn_private_config.h"



svn_error_t *
svn_client_url_from_path(const char **url,
                         const char *path_or_url,
                         apr_pool_t *pool)
{
  svn_opt_revision_t revision;
  revision.kind = svn_opt_revision_unspecified;
  return svn_client__derive_location(url, NULL, path_or_url, &revision,
                                     NULL, NULL, NULL, pool);
}


svn_error_t *
svn_client_root_url_from_path(const char **url,
                              const char *path_or_url,
                              svn_client_ctx_t *ctx,
                              apr_pool_t *pool)
{
  svn_opt_revision_t peg_revision;
  peg_revision.kind = svn_path_is_url(path_or_url) ? svn_opt_revision_head
                                                   : svn_opt_revision_base;
  return svn_client__get_repos_root(url, path_or_url, &peg_revision,
                                    NULL, ctx, pool);
}

svn_error_t *
svn_client__derive_location(const char **url,
                            svn_revnum_t *peg_revnum,
                            const char *path_or_url,
                            const svn_opt_revision_t *peg_revision,
                            const svn_ra_session_t *ra_session,
                            svn_wc_adm_access_t *adm_access,
                            svn_client_ctx_t *ctx,
                            apr_pool_t *pool)
{
  /* If PATH_OR_URL is a local path (not a URL), we need to transform
     it into a URL. */
  if (! svn_path_is_url(path_or_url))
    {
      const svn_wc_entry_t *entry;

      if (adm_access)
        {
          SVN_ERR(svn_wc__entry_versioned(&entry, path_or_url, adm_access,
                                          FALSE, pool));
        }
      else
        {
          svn_cancel_func_t cancel_func;
          void *cancel_baton;

          if (ctx)
            {
              cancel_func = ctx->cancel_func;
              cancel_baton = ctx->cancel_baton;
            }
 
          SVN_ERR(svn_wc_adm_probe_open3(&adm_access, NULL, path_or_url,
                                         FALSE, 0, cancel_func, cancel_baton,
                                         pool));
          SVN_ERR(svn_wc__entry_versioned(&entry, path_or_url, adm_access,
                                          FALSE, pool));
          SVN_ERR(svn_wc_adm_close(adm_access));
        }

      SVN_ERR(svn_client__entry_location(url, peg_revnum, path_or_url,
                                         peg_revision->kind, entry, pool));
    }
  else
    {
      *url = path_or_url;
      /* peg_revnum (if provided) will be set below. */
    }

  /* If we haven't resolved for ourselves a numeric peg revision, do so. */
  if (peg_revnum && !SVN_IS_VALID_REVNUM(*peg_revnum))
    {
      /* Use sesspool to assure that if we opened an RA session, we
         close it. */
      apr_pool_t *sesspool = NULL;
      svn_ra_session_t *session = (svn_ra_session_t *) ra_session;
      if (session == NULL)
        {
          sesspool = svn_pool_create(pool);
          SVN_ERR(svn_client__open_ra_session_internal(&session, *url, NULL,
                                                       NULL, NULL, FALSE,
                                                       TRUE, ctx, sesspool));
        }
      SVN_ERR(svn_client__get_revision_number(peg_revnum, NULL, session,
                                              peg_revision, NULL, pool));
      if (sesspool)
        svn_pool_destroy(sesspool);
    }

  return SVN_NO_ERROR;
}

svn_error_t *
svn_client__entry_location(const char **url, svn_revnum_t *revnum,
                           const char *wc_path,
                           enum svn_opt_revision_kind peg_rev_kind,
                           const svn_wc_entry_t *entry, apr_pool_t *pool)
{
  if (entry->copyfrom_url && peg_rev_kind == svn_opt_revision_working)
    {
      *url = entry->copyfrom_url;
      if (revnum)
        *revnum = entry->copyfrom_rev;
    }
  else if (entry->url)
    {
      *url = entry->url;
      if (revnum)
        *revnum = entry->revision;
    }
  else
    {
      return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
                               _("Entry for '%s' has no URL"),
                               svn_path_local_style(wc_path, pool));
    }

  return SVN_NO_ERROR;
}
