mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-25 11:22:55 +00:00
406 lines
8.7 KiB
C++
406 lines
8.7 KiB
C++
/*
|
|
* ====================================================================
|
|
* Copyright (c) 2002-2009 The RapidSvn Group. All rights reserved.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program (in the file GPL.txt.
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* This software consists of voluntary contributions made by many
|
|
* individuals. For exact contribution history, see the revision
|
|
* history and logs, available at http://rapidsvn.tigris.org/.
|
|
* ====================================================================
|
|
*/
|
|
|
|
// subversion api
|
|
#include "svn_path.h"
|
|
#include "svn_dirent_uri.h"
|
|
|
|
// apr api
|
|
#include "apr_file_io.h"
|
|
|
|
// svncpp
|
|
#include "kdevsvncpp/path.hpp"
|
|
#include "kdevsvncpp/pool.hpp"
|
|
#include "kdevsvncpp/url.hpp"
|
|
|
|
namespace svn
|
|
{
|
|
const PathVector EmptyPathVector;
|
|
|
|
Path::Path(const char * path)
|
|
{
|
|
init(path);
|
|
}
|
|
|
|
Path::Path(const std::string & path)
|
|
{
|
|
init(path.c_str());
|
|
}
|
|
|
|
Path::Path(const Path & path)
|
|
{
|
|
init(path.c_str());
|
|
}
|
|
|
|
void
|
|
Path::init(const char * path)
|
|
{
|
|
Pool pool;
|
|
|
|
m_pathIsUrl = false;
|
|
|
|
if (path == 0)
|
|
m_path = "";
|
|
else
|
|
{
|
|
const char * int_path = svn_dirent_canonicalize(path, pool);
|
|
|
|
m_path = int_path;
|
|
|
|
if (svn::Url::isValid(int_path))
|
|
m_pathIsUrl = true;
|
|
}
|
|
}
|
|
|
|
const std::string &
|
|
Path::path() const
|
|
{
|
|
return m_path;
|
|
}
|
|
|
|
const char *
|
|
Path::c_str() const
|
|
{
|
|
return m_path.c_str();
|
|
}
|
|
|
|
Path&
|
|
Path::operator= (const Path & path)
|
|
{
|
|
if (this == &path)
|
|
return *this;
|
|
|
|
init(path.c_str());
|
|
|
|
return *this;
|
|
}
|
|
|
|
bool
|
|
Path::operator== (const Path& path) const
|
|
{
|
|
if (path.path() == this->path())
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
Path::isSet() const
|
|
{
|
|
return m_path.length() > 0;
|
|
}
|
|
|
|
bool
|
|
Path::isUrl() const
|
|
{
|
|
return m_pathIsUrl;
|
|
}
|
|
|
|
static bool
|
|
isAbsolute(const char * path)
|
|
{
|
|
if (0 == path)
|
|
return false;
|
|
|
|
std::string p(path);
|
|
|
|
if (0 == p.length())
|
|
return false;
|
|
|
|
// a path that begins with "/" is absolute
|
|
if ('/' == p [0])
|
|
return true;
|
|
|
|
// a path with a ":" like "http://xxx" or
|
|
// "c:/foo" is absolute too
|
|
if (p.find(":", 0) != std::string::npos)
|
|
return true;
|
|
|
|
// Well it's relative
|
|
return false;
|
|
}
|
|
|
|
void
|
|
Path::addComponent(const char * component)
|
|
{
|
|
Pool pool;
|
|
|
|
if (0 == component)
|
|
return;
|
|
|
|
// in case of an empty string, return
|
|
if (*component == 0)
|
|
return;
|
|
|
|
// if the @a component is absolute, simply
|
|
// use it
|
|
if (isAbsolute(component))
|
|
{
|
|
m_path = component;
|
|
return;
|
|
}
|
|
|
|
if (Url::isValid(m_path.c_str()))
|
|
{
|
|
const char * newPath =
|
|
svn_path_url_add_component(m_path.c_str(),
|
|
component,
|
|
pool);
|
|
m_path = newPath;
|
|
}
|
|
else
|
|
{
|
|
svn_stringbuf_t * pathStringbuf =
|
|
svn_stringbuf_create(m_path.c_str(), pool);
|
|
|
|
svn_path_add_component(pathStringbuf,
|
|
component);
|
|
|
|
m_path = pathStringbuf->data;
|
|
}
|
|
}
|
|
|
|
void
|
|
Path::addComponent(const std::string & component)
|
|
{
|
|
addComponent(component.c_str());
|
|
}
|
|
|
|
void
|
|
Path::split(std::string & dirpath, std::string & basename) const
|
|
{
|
|
Pool pool;
|
|
|
|
const char * cdirpath;
|
|
const char * cbasename;
|
|
|
|
svn_path_split(m_path.c_str(), &cdirpath, &cbasename, pool);
|
|
|
|
dirpath = cdirpath;
|
|
basename = cbasename;
|
|
}
|
|
|
|
void
|
|
Path::split(std::string & dir, std::string & filename, std::string & ext) const
|
|
{
|
|
std::string basename;
|
|
|
|
// first split path into dir and filename+ext
|
|
split(dir, basename);
|
|
|
|
// next search for last .
|
|
size_t pos = basename.find_last_of(".");
|
|
if (pos == std::string::npos)
|
|
{
|
|
filename = basename;
|
|
ext = "";
|
|
}
|
|
else
|
|
{
|
|
filename = basename.substr(0, pos);
|
|
ext = basename.substr(pos);
|
|
}
|
|
}
|
|
|
|
std::string
|
|
Path::basename() const
|
|
{
|
|
std::string dir;
|
|
std::string filename;
|
|
|
|
split(dir, filename);
|
|
|
|
return filename;
|
|
}
|
|
|
|
std::string
|
|
Path::dirpath() const
|
|
{
|
|
std::string dir;
|
|
std::string filename;
|
|
|
|
split(dir, filename);
|
|
|
|
return dir;
|
|
}
|
|
|
|
std::string
|
|
Path::substr(const size_t count) const
|
|
{
|
|
if (m_path.length() > count)
|
|
return m_path.substr(count);
|
|
else
|
|
return "";
|
|
}
|
|
|
|
std::string
|
|
Path::unescape() const
|
|
{
|
|
return svn::Url::unescape(m_path.c_str());
|
|
}
|
|
|
|
|
|
/* ===================================================================
|
|
* The next two Fixed_* functions are copies of the APR
|
|
* apr_temp_dir_get functionality with a fix applied.
|
|
* This should turn up in APR release 0.9.5 or 1.0, but
|
|
* for now is reproduced here.
|
|
*
|
|
* TODO: Remove this section!
|
|
*/
|
|
#include "apr_env.h"
|
|
|
|
#define test_tempdir Fixed_test_tempdir
|
|
#define apr_temp_dir_get Fixed_apr_temp_dir_get
|
|
|
|
static char global_temp_dir[APR_PATH_MAX+1] = { 0 };
|
|
|
|
/* Try to open a temporary file in the temporary dir, write to it,
|
|
and then close it. */
|
|
static int Fixed_test_tempdir(const char *temp_dir, apr_pool_t *p)
|
|
{
|
|
apr_file_t *dummy_file;
|
|
// This is the only actual fix - adding the ".XXXXXX"!
|
|
const char *path = apr_pstrcat(p, temp_dir, "/apr-tmp.XXXXXX", NULL);
|
|
|
|
if (apr_file_mktemp(&dummy_file, (char *)path, 0, p) == APR_SUCCESS) {
|
|
if (apr_file_putc('!', dummy_file) == APR_SUCCESS) {
|
|
if (apr_file_close(dummy_file) == APR_SUCCESS) {
|
|
apr_file_remove(path, p);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static apr_status_t Fixed_apr_temp_dir_get(const char **temp_dir, apr_pool_t *p)
|
|
{
|
|
apr_status_t apr_err;
|
|
const char *try_dirs[] = { "/tmp", "/usr/tmp", "/var/tmp" };
|
|
const char *try_envs[] = { "TMP", "TEMP", "TMPDIR" };
|
|
char *cwd;
|
|
size_t i;
|
|
|
|
/* Our goal is to find a temporary directory suitable for writing
|
|
into. We'll only pay the price once if we're successful -- we
|
|
cache our successful find. Here's the order in which we'll try
|
|
various paths:
|
|
|
|
$TMP
|
|
$TEMP
|
|
$TMPDIR
|
|
"/tmp"
|
|
"/var/tmp"
|
|
"/usr/tmp"
|
|
`pwd`
|
|
|
|
NOTE: This algorithm is basically the same one used by Python
|
|
2.2's tempfile.py module. */
|
|
|
|
/* Try the environment first. */
|
|
for (i = 0; i < (sizeof(try_envs) / sizeof(const char *)); i++) {
|
|
char *value;
|
|
apr_err = apr_env_get(&value, try_envs[i], p);
|
|
if ((apr_err == APR_SUCCESS) && value) {
|
|
apr_size_t len = strlen(value);
|
|
if (len && (len < APR_PATH_MAX) && test_tempdir(value, p)) {
|
|
memcpy(global_temp_dir, value, len + 1);
|
|
goto end;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Next, try a set of hard-coded paths. */
|
|
for (i = 0; i < (sizeof(try_dirs) / sizeof(const char *)); i++) {
|
|
if (test_tempdir(try_dirs[i], p)) {
|
|
memcpy(global_temp_dir, try_dirs[i], strlen(try_dirs[i]) + 1);
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
/* Finally, try the current working directory. */
|
|
if (APR_SUCCESS == apr_filepath_get(&cwd, APR_FILEPATH_NATIVE, p)) {
|
|
if (test_tempdir(cwd, p)) {
|
|
memcpy(global_temp_dir, cwd, strlen(cwd) + 1);
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
end:
|
|
if (global_temp_dir[0]) {
|
|
*temp_dir = apr_pstrdup(p, global_temp_dir);
|
|
return APR_SUCCESS;
|
|
}
|
|
return APR_EGENERAL;
|
|
}
|
|
/* ===================================================================
|
|
* End of inserted fixed APR code
|
|
*/
|
|
|
|
Path
|
|
Path::getTempDir()
|
|
{
|
|
const char * tempdir = NULL;
|
|
Pool pool;
|
|
|
|
if (apr_temp_dir_get(&tempdir, pool) != APR_SUCCESS)
|
|
{
|
|
tempdir = NULL;
|
|
}
|
|
|
|
return tempdir;
|
|
}
|
|
|
|
size_t
|
|
Path::length() const
|
|
{
|
|
return m_path.length();
|
|
}
|
|
|
|
std::string
|
|
Path::native() const
|
|
{
|
|
if (m_pathIsUrl)
|
|
{
|
|
// this converts something like
|
|
// http://foo/my%20location
|
|
// to
|
|
// http://foo/my location
|
|
return Url::unescape(m_path.c_str());
|
|
}
|
|
else
|
|
{
|
|
// On Windows, p://foo/bar will be converted to p:\foo\bar
|
|
Pool pool;
|
|
return svn_path_local_style(m_path.c_str(), pool);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* -----------------------------------------------------------------
|
|
* local variables:
|
|
* eval: (load-file "../../rapidsvn-dev.el")
|
|
* end:
|
|
*/
|