[GME-commit] GMESRC/GME/XmlBackEnd/SVNCode Client.cpp, NONE, 1.1 Client.h, NONE, 1.1 ClientUtil.h, NONE, 1.1 CmdClient.cpp, NONE, 1.1 CmdClient.h, NONE, 1.1 HiClient.cpp, NONE, 1.1 HiClient.h, NONE, 1.1 Path.cpp, NONE, 1.1 Path.h, NONE, 1.1 Pool.cpp, NONE, 1.1 Pool.h, NONE, 1.1 Prompter.cpp, NONE, 1.1 Prompter.h, NONE, 1.1 Revision.cpp, NONE, 1.1 Revision.h, NONE, 1.1 Targets.cpp, NONE, 1.1 Targets.h, NONE, 1.1 ThreadData.cpp, NONE, 1.1 ThreadData.h, NONE, 1.1 Util.cpp, NONE, 1.1 Util.h, NONE, 1.1
Log messages of CVS commits
gme-commit at list.isis.vanderbilt.edu
Thu Feb 7 14:01:41 CST 2008
- Previous message: [GME-commit] GMESRC/GME/XmlBackEnd/SVNCode - New directory
- Next message: [GME-commit] GMESRC/GME/XmlBackEnd CoreXmlFile.cpp, 1.24, 1.25 SvnConfig.h, 1.1, 1.2 SvnExec.cpp, 1.1, 1.2 SvnExec.rgs, 1.1, 1.2 SvnTester.cpp, 1.1, 1.2 XmlBackEnd.vcproj, 1.4, 1.5
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /project/gme-repository/GMESRC/GME/XmlBackEnd/SVNCode
In directory escher:/tmp/cvs-serv27120
Added Files:
Client.cpp Client.h ClientUtil.h CmdClient.cpp CmdClient.h
HiClient.cpp HiClient.h Path.cpp Path.h Pool.cpp Pool.h
Prompter.cpp Prompter.h Revision.cpp Revision.h Targets.cpp
Targets.h ThreadData.cpp ThreadData.h Util.cpp Util.h
Log Message:
CmdLineClient and ApiClient files checked in.
CVS User: Zoltan Molnar, ISIS (zolmol)
--- NEW FILE: Path.cpp ---
/**
* @copyright
* ====================================================================
* Copyright (c) 2003-2006 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/.
* ====================================================================
* @endcopyright
*
* @file Path.cpp
* @brief Implementation of the class Path
*/
#include "StdAfx.h"
#if(USESVN)
#include "Path.h"
#include "svn_path.h"
#include "Util.h"
#include "Pool.h"
/**
* Constructor
*
* @see Path::Path (const std::string &)
* @param path Path string
*/
Path::Path (const char * pi_path)
{
init (pi_path);
}
/**
* Constructor that takes a string as parameter.
* The string is converted to subversion internal
* representation. The string is copied.
*
* @param path Path string
*/
Path::Path (const std::string & pi_path)
{
init (pi_path.c_str ());
}
/**
* Copy constructor
*
* @param path Path to be copied
*/
Path::Path (const Path & pi_path)
{
init (pi_path.c_str ());
}
/**
* initialize the class
*
* @param path Path string
*/
void
Path::init (const char * pi_path)
{
if(*pi_path == 0)
{
m_error_occured = NULL;
m_path = "";
}
else
{
m_error_occured = Util::preprocessPath(pi_path,
Util::getRequestPool()->pool() );
m_path = pi_path;
}
}
/**
* @return Path string
*/
const std::string &
Path::path () const
{
return m_path;
}
/**
* @return Path string as c string
*/
const char *
Path::c_str() const
{
return m_path.c_str ();
}
/**
* Assignment operator
*/
Path&
Path::operator=(const Path & pi_path)
{
init (pi_path.c_str ());
return *this;
}
svn_error_t *Path::error_occured() const
{
return m_error_occured;
}
bool Path::isValid(const char *p)
{
if (p == NULL)
{
return false;
}
Pool requestPool;
svn_error_t *err = svn_path_check_valid(p, requestPool.pool());
if (err == SVN_NO_ERROR)
{
return true;
}
else
{
svn_error_clear(err);
return false;
}
}
#endif
--- NEW FILE: Targets.h ---
/**
* @copyright
* ====================================================================
* Copyright (c) 2003-2004 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/.
* ====================================================================
* @endcopyright
*
* @file Targets.h
* @brief Interface of the class Targets
*/
#pragma once
struct apr_array_header_t;
struct svn_error_t;
class Pool;
#include "Path.h"
#include <vector>
class Targets
{
private:
std::vector<Path> m_targets;
svn_error_t * m_error_occured;
bool m_doesNotContainsPath;
public:
Targets(const char *path);
void add(const char *path);
~Targets();
const apr_array_header_t * array(const Pool & pool);
svn_error_t * error_occured();
void setDoesNotContainsPath();
};
--- NEW FILE: Prompter.cpp ---
/**
* @copyright
* ====================================================================
* Copyright (c) 2003 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/.
* ====================================================================
* @endcopyright
*
* @file Prompter.cpp
* @brief Implementation of the class Prompter
*/
#include "StdAfx.h"
#if(USESVN)
#include "Prompter.h"
#include "Pool.h"
#include "svn_client.h"
#include "conio.h"
#include "Util.h"
#include "..\\CredentialDlg.h"
#include "..\\CertificateDlg.h"
#include <iostream> // remove this later
extern std::string g_userName;
extern std::string g_passWord;
//static
void PromptImpl::scanfBlind( std::string& ret)
{
ASSERT(0);
int k = 0;
ret.clear();
// blind scanf like:
while( 13 != ( k = getch()) && 10 != k)
{
if( k != 8)
{
std::cout << "*";
ret += (char) k;
}
else
{
ret = ret.substr( 0, ret.length() - 1); // remove last one
std::cout << "Backspace, please continue typing " << std::endl << std::string( ret.length(), '*');
}
}
if( k == 13 || k == 10)
std::cout << std::endl;
}
GPromptImpl::GPromptImpl()
: m_pWord( "-")
, m_uName( "-")
, m_credsFilled( false)
{
}
GPromptImpl::~GPromptImpl()
{
}
std::string GPromptImpl::username()
{
// assumes that prompt() was called before,
// and the m_uName field was filled already
if( m_credsFilled && m_uName.size() > 0 && m_uName != "-") // the default value
return m_uName;
ASSERT(0);
CCredentialDlg dlg( true, m_uName);
if( dlg.DoModal() == IDOK)
{
m_uName = dlg.name();
m_pWord = dlg.word();
m_credsFilled = true;
}
return m_uName;
}
std::string GPromptImpl::password()
{
if( m_credsFilled && m_pWord.size() > 0 && m_pWord != "-")// && m_maySave) // if not the default value ("-") and only if allowed to be saved
return m_pWord;
ASSERT(0);
CCredentialDlg dlg( true, m_uName);
if( dlg.DoModal() == IDOK)
{
m_uName = dlg.name();
m_pWord = dlg.word();
m_credsFilled = true;
}
return m_pWord;
}
bool GPromptImpl::askYesNo(const char *realm, const char *question,
bool yesIsDefault)
{
std::string msg = "Realm: " + std::string( realm ? realm:"<norealm>") + "\nQuestion: " + std::string( question ? question :"<noquestion>");
int res = AfxMessageBox( msg.c_str(), MB_YESNO);
if( IDYES == res)
return true;
else if( IDNO == res)
return false;
else
return yesIsDefault;
}
std::string GPromptImpl::askQuestion(const char *realm, const char *question,
bool showAnswer, bool maySave)
{
std::string msg = "Realm: " + std::string( realm ? realm:"<norealm>") + "\nQuestion: " + std::string( question ? question :"<noquestion>");
if( IDYES == AfxMessageBox( msg.c_str(), MB_YESNO))
m_answer = "y";
else
m_answer = "n";
m_maySave = false;
msg = "May save the answer?";
if( IDYES == AfxMessageBox( msg.c_str(), MB_YESNO))
m_maySave = true;
return m_answer;
}
int GPromptImpl::askTrust(const char *question, bool maySave)
{
std::string q = question;
int offs = 0; // make it Windows multiline: \r\n instead of \n
while( (offs = q.find( '\n', offs + 1)) != -1)
{
q.insert( offs, "\r"); offs += 2;
}
//if(maySave)
//{
// q += "(R)eject, accept (t)emporarily or accept (p)ermanently?";
//}
//else
//{
// q += "(R)eject or accept (t)emporarily?";
//}
CCertificateDlg dlg( q, maySave, 0);
if( dlg.DoModal() == IDOK)
{
CCertificateDlg::Response rp = dlg.getResp();
if( rp == CCertificateDlg::Response::PermanentAccept)
return Prompter::PrompUserPass::AcceptPermanently;
else if( rp == CCertificateDlg::Response::TemoraryAccept)
return Prompter::PrompUserPass::AcceptTemporary;
else
return Prompter::PrompUserPass::Reject;
}
return Prompter::PrompUserPass::Reject;
}
bool GPromptImpl::prompt(const char *p_realm, const char *p_username, bool p_maySave)
{
std::string u_name( p_username?p_username: "<<nousername>>");
std::string msg = "Realm: " + std::string( p_realm?p_realm:"<<norealm>>") + "\n -Username-: '" + u_name + "'\nChange user credentials?";
if( IDYES == AfxMessageBox( msg.c_str(), MB_YESNO))
{
CCredentialDlg dlg( p_maySave, u_name);
if( dlg.DoModal() == IDOK)
{
m_uName = dlg.name();
m_pWord = dlg.word();
m_credsFilled = true;
if( p_maySave)
{
m_maySave = dlg.maySave();
if( m_maySave)
{
g_userName = m_uName;
g_passWord = m_pWord;
// todo: then save it by using the special set_password
//
}
}
else
m_maySave = false;
}
}
else
{
//m_uName = p_username;
//m_pWord = "-";
}
return true;
}
//#include "svn_private_config.h"
TextPromptImpl::TextPromptImpl()
: m_pWord( "-")
, m_uName( "-")
{
}
std::string TextPromptImpl::readcnf( const EntryType& p_type)
{
if( p_type == EntryType::UserName)
{
return "username";
}
else if( p_type == EntryType::Password)
{
return m_pWord.size() > 0 ? m_pWord : "<<no pw?>>";
}
return "";
}
TextPromptImpl::~TextPromptImpl()
{
}
std::string TextPromptImpl::username()
{
// assumes that prompt() was called before,
// and the m_uName field was filled already
if( m_uName.size() > 0 && m_uName != "-") // the default value
return m_uName;
return readcnf( EntryType::UserName);
}
std::string TextPromptImpl::password()
{
if( m_pWord.size() > 0 && m_pWord != "-" && m_maySave) // if not the default value ("-") and only if allowed to be saved
return m_pWord;
// require it
std::cout << "Password please : ";
std::string ret;
scanfBlind( ret);
//if( 1 == scanf( "%s", &buff)) // cin eliminates whitespaces
//ret = buff;
//ret = readcnf( EntryType::Password);
if( m_maySave)
{
m_pWord = ret;
}
return ret;
}
bool TextPromptImpl::askYesNo(const char *realm, const char *question,
bool yesIsDefault)
{
std::cout << "\nRealm: " << (realm?realm:"<<norealm>>") << "\nQuestion: " << question;
//int k = getch();
std::string res;
std::cin >> res;
int k = res.size() > 0 ? res[0]: ' ';
if( (char) k == 'n' || (char) k == 'N')
return false;
else if( (char) k == 'y' || (char) k == 'Y')
return true;
else // if yesIsDefault return true = Yes, if !yesisDefault return false = No
return yesIsDefault;
}
std::string TextPromptImpl::askQuestion(const char *realm, const char *question,
bool showAnswer, bool maySave)
{
std::cout << "\nRealm: " << (realm?realm:"<norealm>") << "\nQuestion: " << (question?question:"<noquestion>");
std::string ret;
std::cin >> ret;
m_answer = ret;
if(maySave)
m_maySave = askYesNo(realm, "May save the answer ?", true);
else
m_maySave = false;
return m_answer;
}
int TextPromptImpl::askTrust(const char *question, bool maySave)
{
std::string q = question;
if(maySave)
{
q += "(R)eject, accept (t)emporarily or accept (p)ermanently?";
}
else
{
q += "(R)eject or accept (t)emporarily?";
}
std::string s_answer = askQuestion( NULL, q.c_str(), true, false);
char answer = (s_answer.size() > 0)? s_answer[0]: ' ';
if( answer == 't' || answer == 'T')
{
return
Prompter::PrompUserPass::AcceptTemporary;
}
else if(maySave && (answer == 'p' || answer == 'P'))
{
return
Prompter::PrompUserPass::AcceptPermanently;
}
else
return Prompter::PrompUserPass::Reject;
}
bool TextPromptImpl::prompt(const char *p_realm, const char *p_username, bool p_maySave)
{
// aren't we too ambitious here
std::cout << "\nRealm: " << (p_realm?p_realm:"<<norealm>>") << std::endl << "-Username-: '" << (p_username?p_username: "<<zerousernameptr>>") << "'";
if( askYesNo( p_realm, "Change user name?", false))
{
std::cout << "Username please : ";
std::cin >> m_uName; // what about storing retv somewhere?
std::cout << "Password for '" << m_uName << "' please : ";
scanfBlind( m_pWord);
if( p_maySave)
{
m_maySave = askYesNo( p_realm, "May save the answer ?", true);
if( m_maySave)
{
g_userName = m_uName;
g_passWord = m_pWord;
// todo: then save it by using the special set_password
//
}
}
else
m_maySave = false;
return true;
}
else
m_uName = p_username;
return true;
}
//**************************************
//*************************************
Prompter::Prompter( PromptImpl* p_prompter)
{
m_impl = p_prompter;
}
Prompter::~Prompter()
{
if( m_impl)
{
delete m_impl;
}
}
Prompter* Prompter::makePrompter( PromptImpl* p_promptImpl)
{
return new Prompter( p_promptImpl);
}
svn_auth_provider_object_t* Prompter::getProviderSimple()
{
apr_pool_t *pool = Util::getRequestPool()->pool();
svn_auth_provider_object_t *provider;
svn_client_get_simple_prompt_provider (&provider,
CallbackHelpers::simple_prompt, /* prompt function */
m_impl, /* prompt baton */
2, /* retry limit */
pool);
return provider;
}
svn_auth_provider_object_t* Prompter::getProviderUsername()
{
apr_pool_t *pool = Util::getRequestPool()->pool();
svn_auth_provider_object_t *provider;
svn_client_get_username_prompt_provider (&provider,
CallbackHelpers::username_prompt, /* prompt function */
m_impl, /* prompt baton */
2, /* retry limit */
pool);
return provider;
}
svn_auth_provider_object_t* Prompter::getProviderServerSSLTrust()
{
apr_pool_t *pool = Util::getRequestPool()->pool();
svn_auth_provider_object_t *provider;
svn_client_get_ssl_server_trust_prompt_provider
(&provider, CallbackHelpers::ssl_server_trust_prompt, m_impl, pool);
return provider;
}
svn_auth_provider_object_t* Prompter::getProviderClientSSL()
{
apr_pool_t *pool = Util::getRequestPool()->pool();
svn_auth_provider_object_t *provider;
svn_client_get_ssl_client_cert_prompt_provider
(&provider, CallbackHelpers::ssl_client_cert_prompt, m_impl, 2, /* retry limit */pool);
return provider;
}
svn_auth_provider_object_t* Prompter::getProviderClientSSLPassword()
{
apr_pool_t *pool = Util::getRequestPool()->pool();
svn_auth_provider_object_t *provider;
svn_client_get_ssl_client_cert_pw_prompt_provider
(&provider, CallbackHelpers::ssl_client_cert_pw_prompt, m_impl, 2 /* retry limit */,
pool);
return provider;
}
// *********************************************************************************************
// *********************** C A L L B A C K H E L P E R M E T H O D S ***********************
// *********************************************************************************************
// static, callback
svn_error_t *Prompter::CallbackHelpers::simple_prompt(svn_auth_cred_simple_t **cred_p,
void *baton,
const char *realm, const char *username,
svn_boolean_t may_save,
apr_pool_t *pool)
{
// SVN_AUTH_CRED_SIMPLE [svn.simple] credentials ( svn_auth_cred_simple_t ) comprise of
// const char *username;
// const char *password;
// svn_boolean_t may_save;
// This latter indicates if the credentials may be saved (to disk).
// For example, a GUI prompt implementation with a remember password
// checkbox shall set may_save to TRUE if the checkbox is checked.
PromptImpl *that = (PromptImpl*)baton;
svn_auth_cred_simple_t *ret = (svn_auth_cred_simple_t*)apr_pcalloc(pool, sizeof(*ret));
// show dlg
if(!that->prompt( realm, username, may_save ? true : false))
return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog");
// retrieve uname
std::string user = that->username();
if(user == "")
return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog");
// duplicate uname into return variable
ret->username = apr_pstrdup( pool, user.c_str());
// retrieve passwrd
std::string pass = that->password();
if(pass == "")
return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog");
// duplicate password into return variable
ret->password = apr_pstrdup( pool, pass.c_str());
// retrieve may_save option
ret->may_save = that->m_maySave;
*cred_p = ret;
return SVN_NO_ERROR;
}
// static, callback
svn_error_t* Prompter::CallbackHelpers::username_prompt(svn_auth_cred_username_t **cred_p,
void *baton,
const char *realm,
svn_boolean_t may_save,
apr_pool_t *pool)
{
// SVN_AUTH_CRED_USERNAME [svn.username] credentials ( svn_auth_cred_username_t ) comprise of
// const char *username;
// svn_boolean_t may_save;
// This latter indicates if the credentials may be saved (to disk).
// For example, a GUI prompt implementation with a remember username
// checkbox shall set may_save to TRUE if the checkbox is checked.
PromptImpl *that = (PromptImpl*)baton;
svn_auth_cred_username_t *ret = (svn_auth_cred_username_t*)apr_pcalloc(pool, sizeof(*ret));
// show question
std::string user = that->askQuestion( realm, "[svn.username] Username: ", true, may_save ? true : false);
if(user == "")
return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog");
// duplicate uname into return variable
ret->username = apr_pstrdup(pool,user.c_str());
// retrieve may_save option
ret->may_save = that->m_maySave;
*cred_p = ret;
return SVN_NO_ERROR;
}
// static, callback
svn_error_t* Prompter::CallbackHelpers::ssl_server_trust_prompt(
svn_auth_cred_ssl_server_trust_t **cred_p,
void *baton,
const char *realm,
apr_uint32_t failures,
const svn_auth_ssl_server_cert_info_t *cert_info,
svn_boolean_t may_save,
apr_pool_t *pool)
{
PromptImpl *that = (PromptImpl*)baton;
svn_auth_cred_ssl_server_trust_t *ret = (svn_auth_cred_ssl_server_trust_t*)apr_pcalloc(pool, sizeof(*ret));
std::string question = "Error validating server certificate for ";
question += realm;
question += ":\n";
if(failures & SVN_AUTH_SSL_UNKNOWNCA)
{
question += " - Unknown certificate issuer\n";
question += " Fingerprint: ";
question += cert_info->fingerprint;
question += "\n";
question += " Distinguished name: ";
question += cert_info->issuer_dname;
question += "\n";
}
if(failures & SVN_AUTH_SSL_CNMISMATCH)
{
question += " - Hostname mismatch (";
question += cert_info->hostname;
question += ")\n";
}
if(failures & SVN_AUTH_SSL_NOTYETVALID)
{
question += " - Certificate is not yet valid\n";
question += " Valid from ";
question += cert_info->valid_from;
question += "\n";
}
if(failures & SVN_AUTH_SSL_EXPIRED)
{
question += " - Certificate is expired\n";
question += " Valid until ";
question += cert_info->valid_until;
question += "\n";
}
switch( that->askTrust( question.c_str(), may_save ? true : false))
{
case PrompUserPass::AcceptTemporary:
*cred_p = ret;
ret->may_save = FALSE;
break;
case PrompUserPass::AcceptPermanently:
*cred_p = ret;
ret->may_save = TRUE;
ret->accepted_failures = failures;
break;
default:
*cred_p = NULL;
}
return SVN_NO_ERROR;
}
// static, callback
svn_error_t* Prompter::CallbackHelpers::ssl_client_cert_prompt(
svn_auth_cred_ssl_client_cert_t **cred_p,
void *baton,
const char *realm,
svn_boolean_t may_save,
apr_pool_t *pool)
{
PromptImpl *that = (PromptImpl*)baton;
svn_auth_cred_ssl_client_cert_t *ret = (svn_auth_cred_ssl_client_cert_t*)apr_pcalloc(pool, sizeof(*ret));
std::string cert_file = that->askQuestion( realm, "client certificate filename: ", true, may_save ? true : false);
if(cert_file == "")
return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog");
ret->cert_file = apr_pstrdup(pool, cert_file.c_str());
ret->may_save = that->m_maySave;
*cred_p = ret;
return SVN_NO_ERROR;
}
// static, callback
svn_error_t* Prompter::CallbackHelpers::ssl_client_cert_pw_prompt(
svn_auth_cred_ssl_client_cert_pw_t **cred_p,
void *baton,
const char *realm,
svn_boolean_t may_save,
apr_pool_t *pool)
{
PromptImpl *that = (PromptImpl*)baton;
svn_auth_cred_ssl_client_cert_pw_t *ret = (svn_auth_cred_ssl_client_cert_pw_t*)apr_pcalloc(pool, sizeof(*ret));
std::string info = that->askQuestion( realm, "client certificate passphrase: ", false, may_save ? true : false);
if(info == "")
return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog");
ret->password = apr_pstrdup( pool, info.c_str());
ret->may_save = that->m_maySave;
*cred_p = ret;
return SVN_NO_ERROR;
}
// *********************************************************************************************
// E O F
// *********************************************************************************************
#endif
--- NEW FILE: Revision.h ---
/**
* @copyright
* ====================================================================
* Copyright (c) 2003-2004 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/.
* ====================================================================
* @endcopyright
*
* @file Revision.h
* @brief Interface of the class Revision
*/
#pragma once
#include "svn_opt.h"
class Revision
{
private:
svn_opt_revision_t m_revision;
public:
static const svn_opt_revision_kind START;
static const svn_opt_revision_kind HEAD;
Revision();
Revision( bool p_head /*= false*/, bool p_one /*= false*/);
Revision( const svn_opt_revision_kind p_kind);
~Revision();
const svn_opt_revision_t *revision() const;
};
--- NEW FILE: Path.h ---
/**
* @copyright
* ====================================================================
* Copyright (c) 2003-2006 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/.
* ====================================================================
* @endcopyright
*
* @file Path.h
* @brief Interface of the C++ class Path.
*/
#pragma once
#include <string>
struct svn_error_t;
/**
* Encapsulation for Subversion Path handling
*/
class Path
{
private:
// the path to be stored
std::string m_path;
svn_error_t *m_error_occured;
/**
* initialize the class
*
* @param pi_path Path string
*/
void init(const char * pi_path);
public:
/**
* Constructor that takes a string as parameter.
* The string is converted to subversion internal
* representation. The string is copied.
*
* @param pi_path Path string
*/
Path(const std::string & pi_path = "");
/**
* Constructor
*
* @see Path::Path (const std::string &)
* @param pi_path Path string
*/
Path(const char * pi_path);
/**
* Copy constructor
*
* @param pi_path Path to be copied
*/
Path(const Path & pi_path);
/**
* Assignment operator
*/
Path& operator=(const Path&);
/**
* @return Path string
*/
const std::string &
path() const;
/**
* @return Path string as c string
*/
const char *
c_str() const;
svn_error_t *
error_occured() const;
/**
* Returns whether @a path is non-NULL and passes the @c
* svn_path_check_valid() test.
*
* @since 1.4.0
*/
static bool isValid(const char *path);
};
--- NEW FILE: Client.h ---
#pragma once
#include "Revision.h"
#include "Targets.h"
#include "svn_client.h"
#include "Prompter.h"
#include "ClientUtil.h"
// class mimicing subversion/bindings/java/javahl/native/svnclient.cpp
class CommitMessage;
class Client
{
public:
//Client(void);
Client( const std::string& p_userName, const std::string& p_passWord);
virtual ~Client(void);
protected:
// not so public: signaled by the sub_ prefix
long sub_checkout(const char *moduleName, const char *destPath,
Revision &revision, Revision &pegRevision,
bool recurse, bool ignoreExternals);
typedef std::vector< long> UPDATE_RES;
bool sub_update(Targets &targets, Revision &revision, bool recurse,
bool ignoreExternals, UPDATE_RES& res);
long sub_commit(Targets &targets, const char *message, bool recurse,
bool noUnlock);
long sub_commit3(Targets &targets, const char *message, bool recurse,
bool noUnlock);
bool sub_cleanup( const char *path);
bool sub_resolved(const char *path, bool recurse);
bool sub_propertySet(const char *path, const char *name,
const char *value, bool recurse, bool force);
bool sub_lock(Targets &targets, const char *comment,
bool force);
bool sub_unlock(Targets &targets);
bool sub_info2( const char * p_path, Revision &revision, Revision &pegRevision, bool p_recurse, ClientUtil::InfoHelp::InfoVec& p_infoVect, bool p_suppressIllegalUrlErrorMsg);
bool info2Qck ( const char * p_path, bool p_recursive, ClientUtil::InfoHelp::InfoVec& p_infoVect, bool p_suppressErrorMsg = false);
int sub_add( const char *p_pathOrUrl, bool rec);
long sub_mkdir( Targets& targets, const char * p_msg);
long sub_mkdir2( Targets& targets, const char * p_msg);
svn_client_ctx_t * getContext(const char *p_message);
//void * getCommitMessageBaton(const char *message);
ClientUtil::NotifyHelp *m_notify2;
void notification2( ClientUtil::NotifyHelp *notify2);
Prompter *m_prompter;
void setPrompt(Prompter *prompter);
ClientUtil::CommitHelp::MsgBuilder * m_commitMessageBuilder;
void setCommitMessageHandler( ClientUtil::CommitHelp::MsgBuilder * p_commitMessageBuilder);
std::string m_userName;
std::string m_passWord;
std::string m_configDir;
void cancelOperation();
ClientUtil::StatusInfo sub_single_status(const char *path, bool onServer);
ClientUtil::StatusExtInfoVec sub_extended_status( const char * p_path, bool p_onServer);
public:
bool m_cancelOperation; // client can signal her patience is not endless
// accessed from batons as well
};
--- NEW FILE: HiClient.h ---
#pragma once
//#include "SvnConfig.h"
#if(USESVN)
#include "Client.h"
#endif
#if(USESVN)
class HiClient : protected Client // implementation inherited from Client
#else
class HiClient
#endif
{
bool m_logEnabled;
void log( const std::string& p_command, const std::string& p_parameter);
public:
HiClient( const std::string& p_userName, const std::string& p_passWord);
~HiClient(void);
void setLog( bool p_val);
// public :
bool isItUs ( const std::string& p_userName);
bool isLocked ( const std::string& p_path);
bool isLockedByUs ( const std::string& p_path);
bool isLockedByOthers ( const std::string& p_path);
bool isLockedByWhom ( const std::string& p_path, bool * p_us, bool * p_else);
//bool isLockedBy ( const char * p_path, char * p_res, int p_len);
bool isLockedByUser ( const std::string& p_path, std::string& p_holder);
bool isVersioned ( const std::string& p_path, bool p_isADir = false, bool p_suppressErrorMsg = false);
bool info ( const std::string& p_url, bool p_recursive, bool p_assembleInfoMsg, std::string& p_infoMsg, std::string& p_author, std::string& p_lockOwner);
bool status ( const std::string& p_path, bool p_assembleStatusMsg, std::string& p_statMsg);
bool cleanup ( const std::string& p_path);
bool resolve ( const std::string& p_path, bool p_recursive);
bool tryLock ( const std::string& p_path);
bool unLock ( const std::string& p_path);
bool lockableProp ( const std::string& p_path);
bool getLatest ( const std::string& p_path);
bool lightCheckOut ( const std::string& p_path, const std::string& p_localDir); // this is used as svn checkout (in contrast with lock+checkout as in other versioning systems)
bool commitAll ( const std::string& p_path, bool p_keepCheckedOut);
bool add ( const std::string& p_path, bool p_recursive);
bool mkDirOnServer ( const std::string& p_path);
};
--- NEW FILE: Pool.h ---
/**
* @copyright
* ====================================================================
* Copyright (c) 2003-2004 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/.
* ====================================================================
* @endcopyright
*
* @file Pool.h
* @brief Interface of the class Pool
*/
#pragma once
#include "apr.h"
struct apr_pool_t;
/**
* this class manages one apr pool. Objects of this class are allocated on
* the stack of the SVNClient & SVNAdmin methods as the request pool.
* Leaving the methods will destroy the pool.
*/
class Pool
{
public:
Pool();
~Pool();
apr_pool_t * pool() const;
private:
/**
* the apr pool request pool
*/
apr_pool_t * m_pool;
};
--- NEW FILE: Targets.cpp ---
/**
* @copyright
* ====================================================================
* Copyright (c) 2003 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/.
* ====================================================================
* @endcopyright
*
* @file Targets.cpp
* @brief Implementation of the class Targets
*/
#include "StdAfx.h"
#if(USESVN)
#include "Targets.h"
#include "Pool.h"
#include "Util.h"
#include <apr_tables.h>
#include <apr_strings.h>
#include <svn_path.h>
#include <iostream> // remove this later
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Targets::~Targets()
{
m_targets.clear();
}
Targets::Targets(const char *path)
{
m_targets.push_back (path);
m_error_occured = NULL;
m_doesNotContainsPath = false;
}
void Targets::add(const char *path)
{
m_targets.push_back (path);
}
const apr_array_header_t *Targets::array (const Pool & pool)
{
std::vector<Path>::const_iterator it;
apr_pool_t *apr_pool = pool.pool ();
apr_array_header_t *apr_targets =
apr_array_make (apr_pool,
m_targets.size(),
sizeof (const char *));
for (it = m_targets.begin (); it != m_targets.end (); it++)
{
const Path &path = *it;
const char * target =
apr_pstrdup (apr_pool, path.c_str());
(*((const char **) apr_array_push (apr_targets))) = target;
}
return apr_targets;
}
svn_error_t *Targets::error_occured()
{
return m_error_occured;
}
void Targets::setDoesNotContainsPath()
{
m_doesNotContainsPath = true;
}
#endif
--- NEW FILE: CmdClient.h ---
#pragma once
#include <string>
class CmdClient
{
bool m_logEnabled;
void log( const std::string& p_command, const std::string& p_parameter);
const char * m_stdo; // "stdo.tmp"
const char * m_stde; // "stde.tmp"
bool m_showCmdWindows;
bool m_redirectOutput;
static const char * m_cs_checkout;
static const char * m_cs_update;
static const char * m_cs_lock;
static const char * m_cs_unlock;
static const char * m_cs_mkdir;
static const char * m_cs_propset_needs_lock;
static const char * m_cs_add;
static const char * m_cs_commit;
static const char * m_cs_info;
static const char * m_cs_status;
static const char * m_cs_cleanup;
static const char * m_cs_resolved;
std::string m_svnPath;
public:
CmdClient( bool p_showCmdWindows, bool p_redirectOutput);
void setLog ( bool p_val);
void setSvnPath ( const std::string& p_svnPath);
//tobe void getCheckOutUserSVN ( XmlObject * obj, std::string& user, bool& newfile);
bool getLatest ( const std::string& p_dir);
bool isCheckedOutByElse ( const std::string& p_file);
bool isLockedByUser ( const std::string& p_path, std::string& p_holderUserName);
bool lightCheckOut ( const std::string& p_url, const std::string& p_localDestPath); // this is used as svn checkout (in contrast with lock+checkout as in other versioning systems)
bool isVersioned ( const std::string& p_file, bool p_isADir = false, bool p_suppressErrorMsg = false);
bool info ( const std::string& p_url, bool p_recursive, bool p_assembleInfoMsg, std::string& p_resultMsg, std::string& p_author, std::string& p_holder);
bool status ( const std::string& p_path, bool p_assembleStatMsg, std::string& p_resultMsg);
bool cleanup ( const std::string& p_path, bool p_assembleStatMsg, std::string& p_resultMsg);
bool resolve ( const std::string& p_path, bool p_recursive);
bool lockableProp ( const std::string& p_file);
bool applyLock ( const std::string& p_file); // obsolete
bool removeLock ( const std::string& p_file); // obsolete
bool tryLock ( const std::string& p_file);
bool unLock ( const std::string& p_file);
//bool mkdirWithUpdate ( const std::string& p_url, const std::string& p_path, const std::string& p_dir); // obsolete
bool mkdirOnServer ( const std::string& p_path);
bool add ( const std::string& p_file, bool p_recursive = false);
bool commit ( const std::string& p_dirOrFile, bool p_initialCommit = false, bool p_noUnlock = false);
bool update ( const std::string& p_dirOrFile);
protected:
int execute ( const char * p);
bool check ( long p_code, bool p_suppressNonversionedErrorMsg = false);
void redirect ( std::string& p_cmd);
void loadContents ( const char * p_fname, std::string& p_fileContent);
void dumpContents ( const char * p_fname, long p_type);
DWORD runSilent ( const char* p_strFunct, const char* p_strstrParams, bool p_silent = true);
std::string command ( const char * p_command, const char * p_par = 0);
std::string findLastChangeAuthor ( const std::string& p_out);
std::string findLockOwner ( const std::string& p_out);
};
--- NEW FILE: Pool.cpp ---
/**
* @copyright
* ====================================================================
* Copyright (c) 2003 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/.
* ====================================================================
* @endcopyright
*
* @file Pool.cpp
* @brief Implementation of the class Pool
*/
#include "StdAfx.h"
#if(USESVN)
#include "Pool.h"
#include "Util.h"
//#include "JNIMutex.h"
//#include "JNICriticalSection.h"
#include "svn_pools.h"
/**
* Constructor to create one apr pool as the subpool of the global pool
* store this pool as the request pool.
*/
Pool::Pool()
{
//JNICriticalSection criticalSection(*JNIUtil::getGlobalPoolMutex());
m_pool = svn_pool_create(Util::getPool());
// we need to store in the static
Util::setRequestPool( this);
//Util::setRequestPool(this);
}
/**
* Destructor to destroy the apr pool and to clear the request pool pointer
*/
Pool::~Pool()
{
//JNICriticalSection criticalSection(*JNIUtil::getGlobalPoolMutex());
Util::setRequestPool(NULL); // will nullify the ptr's value
if(m_pool)
{
svn_pool_destroy (m_pool);
}
}
/**
* Returns the apr pool.
* @return the apr pool
*/
apr_pool_t * Pool::pool () const
{
return m_pool;
}
#endif
--- NEW FILE: CmdClient.cpp ---
#include "StdAfx.h"
#include "CmdClient.h"
#include "CoreXmlFile.h"
#include "FileHelp.h"
#include "MsgConsole.h"
//#include <stdlib.h>
#include <direct.h>
#if(USESVN)
// statics
const char * CmdClient::m_cs_checkout = "co"; // a light checkout, with no consequences on locks!
const char * CmdClient::m_cs_update = "update";
const char * CmdClient::m_cs_lock = "lock";
const char * CmdClient::m_cs_unlock = "unlock";
const char * CmdClient::m_cs_mkdir = "mkdir";
const char * CmdClient::m_cs_propset_needs_lock = "propset svn:needs-lock 'na'";
const char * CmdClient::m_cs_add = "add";
const char * CmdClient::m_cs_commit = "commit";
const char * CmdClient::m_cs_info = "info";
const char * CmdClient::m_cs_status = "status";
const char * CmdClient::m_cs_cleanup = "cleanup";
const char * CmdClient::m_cs_resolved = "resolved";
CmdClient::CmdClient( bool p_showCmdWindows, bool p_redirectOutput)
: m_stdo( "stdo.tmp")
, m_stde( "stde.tmp")
, m_showCmdWindows( p_showCmdWindows)
, m_redirectOutput( p_redirectOutput)
, m_svnPath( "svn")
{
}
std::string CmdClient::command( const char * p_command, const char * p_par /*= 0*/)
{
return m_svnPath + " " + p_command + " " + (p_par? p_par : "") + " ";
}
void CmdClient::setSvnPath( const std::string& p_svnPath)
{
m_svnPath = p_svnPath;
}
//void CmdClient::getCheckOutUserSVN(XmlObject * obj, string& user, bool& newfile)
//{
// ASSERT( m_sourceControl == SC_SUBVERSION );
// ASSERT( obj->isContainer() );
// ASSERT( m_svnByAPI);
//
// if( m_svnByAPI)
// {
// std::string fname;
// getContainerFileName( obj, fname, true);
// //char buff[100];
// //bool ret = m_svn->isLockedBy( fname.c_str(), &buff[0], 100);
// //if( ret)
// // user = buff;
// bool ret = m_svn->isLockedByUser( fname, user);
// newfile = false; // todo
// }
//}
bool CmdClient::isCheckedOutByElse( const std::string& p_file)
{
//ASSERT( isVersionedInSVN( p_file));
if( !FileHelp::isFileReadOnly( p_file))
return false; // file is svnlocked by us
if( applyLock( p_file))
{
// success: was not checked out by somebody else
if( removeLock( p_file))
return false;
}
return true;
}
bool CmdClient::isLockedByUser( const std::string& p_path/*, std::string& p_lastAuthor*/, std::string& p_holderUserName)
{
// ret val is always true
// p_username !empty indicates whether is held or not
return info( p_path, false /*recursive*/, false /*assemble inf msg*/, std::string() /*msg*/, std::string() /*p_lastAuthor*/, p_holderUserName);
}
bool CmdClient::lightCheckOut( const std::string& p_url, const std::string& p_localDestPath)
{
std::string cmd = command( m_cs_checkout) + p_url + " " + p_localDestPath;
redirect( cmd);
int r;
r = execute( cmd.c_str());
return check( r);
}
bool CmdClient::getLatest( const std::string& p_dir)
{
int r0;
r0 = _chdir( p_dir.c_str());
check( r0 );
// what about a clean?, or what about the first time this is called: 'svn checkout' should be used
std::string cmd = command( m_cs_update) + " . ";
redirect( cmd);
int r;
r = execute( cmd.c_str());
return check( r);
}
// obsolete
bool CmdClient::applyLock( const std::string& p_file)
{
std::string cmd = command( m_cs_lock) + p_file;
redirect( cmd);
int r;
r = execute( cmd.c_str());
return check( r);
}
bool CmdClient::removeLock( const std::string& p_file)
{
std::string cmd = command( m_cs_unlock) + p_file;
redirect( cmd);
int r;
r = execute( cmd.c_str());
return check( r);
}
bool CmdClient::tryLock( const std::string& p_file)
{
// is locked already? // optimization, but might mislead
WIN32_FILE_ATTRIBUTE_DATA attr;
BOOL res = GetFileAttributesEx( p_file.c_str(), GetFileExInfoStandard, &attr );
if( (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY //non-dir
&& (attr.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY) //non-read-only
return true; // lock present
// process with lock command
std::string cmd = command( m_cs_lock) + p_file;
redirect( cmd);
int r;
r = execute( cmd.c_str());
return check( r);
}
bool CmdClient::unLock( const std::string& p_file)
{
// is unlocked already? // optimization, but might mislead
WIN32_FILE_ATTRIBUTE_DATA attr;
BOOL res = GetFileAttributesEx( p_file.c_str(), GetFileExInfoStandard, &attr );
if( (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY //non-dir
&& (attr.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) //read-only
return true; // presumably unlocked, that's why is read-only
// process with unlock command
std::string cmd = command( m_cs_unlock) + p_file;
redirect( cmd);
int r;
r = execute( cmd.c_str());
return check( r);
}
bool CmdClient::mkdirOnServer( const std::string& p_path)
{
// creates and commits the versioned directory on the server
std::string cmd = command( m_cs_mkdir) + p_path + " -m \"initial checkin\"";
redirect( cmd);
int r;
r = execute( cmd.c_str());
return check( r );
}
// obsolete
//bool CmdClient::mkdirWithUpdate( const std::string& p_url, const std::string& p_path, const std::string& p_dir)
//{
// // creates and commits the versioned directory on the server
// std::string cmd = command( m_cs_mkdir);
// cmd += p_url + "/" + p_dir + " -m \"initial checkin\"";
// redirect( cmd);
//
// int r = execute( cmd.c_str());
// bool err = check( r );
//
// // check out a working copy to local directory
// //r = _chdir( m_folderPath);
// //check( r );
//
// // svn checkout URL PATH form can be used also e.g.:
// // svn checkout svn://localhost/svn_02 f:\t\at\an\svn_02
// std::string cmd2 = command( m_cs_checkout);
// cmd2 += p_url + '/' + p_dir + ' ' + p_path;
// redirect( cmd2);
//
// r = execute( cmd2.c_str());
// bool err2 = check( r);
//
// // change into the newly created directory
// r = _chdir( p_path.c_str());
//
// return err && err2 && check( r);
//}
bool CmdClient::lockableProp( const std::string& p_file)
{
// svn propset svn:needs-lock 'anyvalue' <file>
std::string cmd = command( m_cs_propset_needs_lock) + p_file;
redirect( cmd);
int r;
r = execute( cmd.c_str());
return check( r);
}
bool CmdClient::add( const std::string& p_entity, bool p_recursive /* = false*/)
{
std::string cmd = command( m_cs_add) + (p_recursive?"": " -N ") + p_entity;
//std::string cmt_line( "svn commit ");
//cmt_line.append( p_entity);
redirect( cmd);
int r;
r = execute( cmd.c_str());
//r2 = execute( cmt_line.c_str());
return check( r);
}
bool CmdClient::commit( const std::string& p_dirOrFile, bool p_initialCommit /* = false*/, bool p_noUnlock /* = false*/)
{
if( !p_initialCommit && !p_noUnlock && FileHelp::isFile( p_dirOrFile) && !FileHelp::isFileReadOnly( p_dirOrFile))
removeLock( p_dirOrFile); // commit does not always remove lock, [at least when diff is empty]
std::string cmd = command( m_cs_commit) + " -m \"ok\" " + p_dirOrFile;
if( p_noUnlock)
cmd.append( " --no-unlock ");
redirect( cmd);
int r;
r = execute( cmd.c_str());
return check( r);
}
bool CmdClient::update( const std::string& p_dirOrFile)
{
std::string cmd = command( m_cs_update) + p_dirOrFile;
redirect( cmd);
int r;
r = execute( cmd.c_str());
return check( r);
}
bool CmdClient::isVersioned( const std::string& p_file, bool p_isADir /*= false*/, bool p_suppressErrorMsg /*=false*/)
{
if( p_isADir)
{
if( FileHelp::isFile( p_file))
{
ASSERT( 0); // it should be a directory
return false;
}
}
else
{
// may be redundant sometimes, but needed when called from makeSureFileExistsInVerSys
if( !FileHelp::fileExist( p_file)) // the file even not exists not even a file
return false;
}
//std::string status_line = "svn status " + p_file;
std::string cmd = command( m_cs_info) + p_file;
redirect( cmd);
// error given in case file not committed: <<filename>>.txt: (Not a versioned resource)
int r;
r = execute( cmd.c_str());
return check( r);
}
#if(0)
// this is like isVersioned, but expects an element not be versioned, thus
// won't dump any error message onto the console.
// In other words its default behaviour is a little different.
bool CmdClient::isNotVersioned( const std::string& p_fileUrl, bool p_isADir = false, bool p_suppressErrorMsg = false)
{
if( p_isADir)
{
if( FileHelp::isFile( p_file))
{
ASSERT( 0); // it should be a directory
return false;
}
}
else
{
// file doesn't exist, means that is not versioned either
if( !FileHelp::fileExist( p_file))
return true;
}
std::string cmd = command( m_cs_info) + p_file;
redirect( cmd);
// error given in case file not committed: <<filename>>.txt: (Not a versioned resource)
int r;
r = execute( cmd.c_str());
if( r != 0) // error executing it
return true;
if( p_suppressErrorMsg)
std::string error_msg;
loadContents( m_stde, error_msg); // std out file
if( !error_msg.empty())
return true; // if errors => not versioned
return false;
}
#endif
bool CmdClient::info( const std::string& p_url, bool p_recursive, bool p_assembleInfoMsg, std::string& p_resultMsg, std::string& p_author, std::string& p_holder)
{
std::string cmd = command( m_cs_info) + p_url;
redirect( cmd);
int r;
r = execute( cmd.c_str());
std::string fc;
loadContents( m_stdo, fc); // std out file
//p_author = m_vssUser; // fooling the author consistency check
p_author.clear(); // clear the in params
p_holder.clear();
p_author = findLastChangeAuthor( fc);
p_holder = findLockOwner( fc);
if( p_assembleInfoMsg)
{
p_resultMsg.append( "\nOutput:\n");
p_resultMsg.append( fc);
p_resultMsg.append( "\nError (if any):\n");
loadContents( m_stde, fc); // std error file
p_resultMsg.append( fc);
}
return true; // always true, since the stde is captured and shown
}
bool CmdClient::status( const std::string& p_path, bool p_assembleStatMsg, std::string& p_resultMsg)
{
std::string cmd = command( m_cs_status) + p_path;
redirect( cmd);
int r;
r = execute( cmd.c_str());
std::string fc;
loadContents( m_stdo, fc); // std out file
if( p_assembleStatMsg)
{
p_resultMsg.append( "\nOutput:\n");
p_resultMsg.append( fc);
p_resultMsg.append( "\nError (if any):\n");
loadContents( m_stde, fc); // std error file
p_resultMsg.append( fc);
}
return true; // always true, since the stde is captured and shown
}
bool CmdClient::cleanup( const std::string& p_path, bool p_assembleStatMsg, std::string& p_resultMsg)
{
std::string cmd = command( m_cs_cleanup) + p_path;
redirect( cmd);
int r;
r = execute( cmd.c_str());
std::string fc;
loadContents( m_stdo, fc); // std out file
if( p_assembleStatMsg)
{
p_resultMsg.append( "\nOutput:\n");
p_resultMsg.append( fc);
p_resultMsg.append( "\nError (if any):\n");
loadContents( m_stde, fc); // std error file
p_resultMsg.append( fc);
}
return true; // always true, since the stde is captured and shown
}
bool CmdClient::resolve( const std::string& p_path, bool p_recursive)
{
std::string cmd = command( m_cs_resolved) + (p_recursive?" -R ":"") + p_path;
redirect( cmd);
int r;
r = execute( cmd.c_str());
return check( r);
}
// static
DWORD CmdClient::runSilent(const char* p_strFunct, const char* p_strstrParams, bool p_silent /*= true*/)
{
STARTUPINFO startup_info;
PROCESS_INFORMATION process_info;
char *env_CMD = NULL;
char *default_CMD = "CMD.EXE";
char args[4096];
ULONG rc;
//static HANDLE hi, ho, he;
memset(&startup_info, 0, sizeof(startup_info)); // clear all members
startup_info.cb = sizeof(STARTUPINFO);
startup_info.dwFlags = STARTF_USESHOWWINDOW;
if( p_silent)
{
startup_info.wShowWindow = SW_HIDE;
//startup_info.dwFlags | = STARTF_USESTDHANDLES;
//startup_info.hStdError = he;
//startup_info.hStdInput = hi;
//startup_info.hStdOutput = ho;
}
else
{
startup_info.wShowWindow = SW_SHOW;
}
args[0] = 0;
env_CMD = getenv("COMSPEC");
if(env_CMD) strcpy(args, env_CMD);
else strcpy(args, default_CMD);
// "/c" option - Do the command then terminate the command window
//if( p_silent) strcat(args, " /c ");
strcat( args, " /c ");
//the application you would like to run from the command window
strcat(args, p_strFunct);
strcat(args, " ");
//the parameters passed to the application being run from the command window.
strcat(args, p_strstrParams);
if (!CreateProcess( NULL, args, NULL, NULL, FALSE,
CREATE_NEW_CONSOLE, NULL, NULL,
&startup_info, &process_info))
{
return GetLastError();
}
//if( p_silent)
{
WaitForSingleObject(process_info.hProcess, INFINITE);
if(!GetExitCodeProcess(process_info.hProcess, &rc))
rc = 0;
CloseHandle(process_info.hThread);
CloseHandle(process_info.hProcess);
}
//else
{
//GetStartupInfo()process_info.hProcess
}
return rc;
}
int CmdClient::execute( const char * p)
{
log( p, "");
return runSilent( "", p, !m_showCmdWindows);
// the alternative could be to use the system() call:
//return system( p); // this can set errno
}
bool CmdClient::check( long p_ret, bool p_suppressNonversionedErrorMsg /*= false*/)
{
bool no_error = true;
// svn related std output and std error handling
WIN32_FILE_ATTRIBUTE_DATA attre, attro;
BOOL res = GetFileAttributesEx( m_stde, GetFileExInfoStandard, &attre );
BOOL rep = GetFileAttributesEx( m_stdo, GetFileExInfoStandard, &attro );
if( res && attre.nFileSizeHigh == 0 && attre.nFileSizeLow == 0) { } // no problem
else if( res) {
no_error = false;
if( !p_suppressNonversionedErrorMsg)
dumpContents( m_stde, MSG_ERROR);
}
if( rep && attro.nFileSizeHigh == 0 && attro.nFileSizeLow == 0) { } // no problem
else if( rep) {
dumpContents( m_stdo, MSG_INFO);
}
// execution related problems
if( p_ret != 0)
{
no_error = false;
}
// if execute uses the system()
if( p_ret == -1)
{
no_error = false;
// errno global variable handling:
switch( errno)
{
case E2BIG:// The space required for the arguments and environment settings exceeds 32 K.
MsgConsole::ssendMsg( "Cmd.exe execution error: E2BIG", MSG_ERROR);
break;
case EACCES:// The specified file has a locking or sharing violation.
MsgConsole::ssendMsg( "Cmd.exe execution error: EACCES", MSG_ERROR);
break;
case EMFILE:// Too many files open (the specified file must be opened to determine whether it is executable).
MsgConsole::ssendMsg( "Cmd.exe execution error: EMFILE", MSG_ERROR);
break;
case ENOENT:// File or path not found.
MsgConsole::ssendMsg( "Cmd.exe execution error: ENOENT", MSG_ERROR);
break;
case ENOEXEC:// The specified file is not executable or has an invalid executable-file format.
MsgConsole::ssendMsg( "Cmd.exe execution error: ENOEXEC", MSG_ERROR);
break;
case ENOMEM:
MsgConsole::ssendMsg( "Cmd.exe execution error: ENOMEM", MSG_ERROR);
break;
default:
MsgConsole::ssendMsg( "Cmd.exe execution error: <<unkown>>", MSG_ERROR);
}
}
return no_error;
}
// static
void CmdClient::loadContents( const char * p_fname, std::string& p_fileContent)
{
p_fileContent.clear();
std::ifstream f;
f.open( p_fname, std::ios_base::in);
if( !f.is_open())
return;
char buffer[1024];
while( f)
{
if( !p_fileContent.empty()) p_fileContent += '\n';
f.getline( buffer, 1024);
p_fileContent.append( buffer);
}
f.close();
}
void CmdClient::dumpContents( const char * p_fname, long p_msgType)
{
//FILE * f = fopen( p_fname, "r");
//if( !f) sendMsg( std::string( "Could not open file: ") + p_fname, p_msgType);
//char buffer[1024];
//while( !feof( f))
//{
// fread( buffer, 1, 1024, f);
// sendMsg( buffer, p_msgType);
//}
//fclose( f);
std::ifstream f;
f.open( p_fname, std::ios_base::in);
if( !f.is_open())
{
MsgConsole::ssendMsg( std::string( "Could not open file: ") + p_fname, p_msgType);
return;
}
char buffer[1024];
while( f)
{
f.getline( buffer, 1024);
MsgConsole::ssendMsg( std::string( "SVN> ") + buffer, p_msgType);
}
f.close();
}
// static
void CmdClient::redirect( std::string& p_cmd)
{
if( m_redirectOutput)
p_cmd.append( std::string( " 1> ") + m_stdo + " 2>" + m_stde + " ");//p_cmd.append( " 1>stdo.tmp 2>stde.tmp ");
}
std::string CmdClient::findLastChangeAuthor( const std::string& p_out)
{
const char * lca_str = "\nLast Changed Author: ";
const int lca_len = strlen( lca_str);
int ps = p_out.find( lca_str);
int ps_end = p_out.find( "\n", ps + 1);
if( ps != std::string::npos && ps_end != std::string::npos)
{
return p_out.substr( ps + lca_len, ps_end - ps - lca_len);
}
return "";
}
std::string CmdClient::findLockOwner( const std::string& p_out)
{
const char * lca_str = "\nLock Owner: ";
const int lca_len = strlen( lca_str);
int ps = p_out.find( lca_str);
int ps_end = p_out.find( "\n", ps + 1);
if( ps != std::string::npos && ps_end != std::string::npos)
{
return p_out.substr( ps + lca_len, ps_end - ps - lca_len);
}
return "";
}
void CmdClient::log( const std::string& p_command, const std::string& p_par)
{
if( !m_logEnabled) return;
std::ofstream fs;
fs.open( "c:\\svnlog.txt", std::ios_base::ate | std::ios_base::app); // append
if( fs)
{
fs << p_command << " " << p_par << std::endl;
fs.close();
}
}
void CmdClient::setLog( bool p_val)
{
m_logEnabled = p_val;
}
#endif
--- NEW FILE: Util.cpp ---
#include "StdAfx.h"
#if(USESVN)
#include ".\util.h"
#include <iostream> // remove this later
#include <fstream>
#include <string>
#include "svn_path.h"
#include "svn_pools.h"
#include "ThreadData.h"
#include <locale.h> // for LC_ALL
//#define _
/*static*/ //Pool * Util::m_requestPool = 0;
/*static*/ apr_pool_t* Util::g_pool = 0;
/*static*/ bool Util::g_inInit = false;
/*static*/ bool Util::g_initException = false;
/*static*/ ThreadData Util::m_globalData;
/*static*/ char Util::g_initFormatBuffer[formatBufferSize];
/*static*/ std::ofstream Util::g_logStream;
/*static*/ int Util::g_logLevel = Util::noLog;
/**
* initialize the environment for all requests
* @param env the JNI environment for this request
*/
//void Util::globalInit()
//{
// if (apr_initialize() != APR_SUCCESS)
// {
// printf("apr_initialize() failed.\n");
// exit(1);
// }
//
// g_pool = svn_pool_create (NULL);
//}
/**
* initialize the environment for all requests
* @param env the JNI environment for this request
*/
bool Util::globalInit()
{
// this method has to be run only once during the run a
// programm
static bool run = false;
if(run) // already run
{
return true;
}
run = true;
// do not run this part more than one time.
// this leaves a small time window when two threads create their first
// SVNClient & SVNAdmin at the same time, but I do not see a better
// option without APR already initialized
if(g_inInit)
{
return false;
}
g_inInit = true;
//g_initEnv = env;
apr_status_t status;
/* C programs default to the "C" locale. But because svn is supposed
to be i18n-aware, it should inherit the default locale of its
environment. */
if (!setlocale(LC_ALL, ""))
{
if (stderr)
{
const char *env_vars[] = { "LC_ALL", "LC_CTYPE", "LANG", NULL };
const char **env_var = &env_vars[0], *env_val = NULL;
while (*env_var)
{
env_val = getenv(*env_var);
if (env_val && env_val[0])
break;
++env_var;
}
if (!*env_var)
{
/* Unlikely. Can setlocale fail if no env vars are set? */
--env_var;
env_val = "not set";
}
fprintf(stderr,
"%s: error: cannot set LC_ALL locale\n"
"%s: error: environment variable %s is %s\n"
"%s: error: please check that your locale name is correct\n",
"svnjavahl", "svnjavahl", *env_var, env_val, "svnjavahl");
}
return FALSE;
}
/* Initialize the APR subsystem, and register an atexit() function
to Uninitialize that subsystem at program exit. */
status = apr_initialize();
if (status)
{
if (stderr)
{
char buf[1024];
apr_strerror(status, buf, sizeof(buf) - 1);
fprintf(stderr,
"%s: error: cannot initialize APR: %s\n",
"svnjavahl", buf);
}
return FALSE;
}
if (0 > atexit(apr_terminate))
{
if (stderr)
fprintf(stderr,
"%s: error: atexit registration failed\n",
"svnjavahl");
return FALSE;
}
#ifdef ENABLE_NLS
#ifdef WIN32
{
WCHAR ucs2_path[MAX_PATH];
char* utf8_path;
const char* internal_path;
apr_pool_t* pool;
apr_status_t apr_err;
unsigned int inwords, outbytes, outlength;
apr_pool_create (&pool, 0);
/* get dll name - our locale info will be in '../share/locale' */
inwords = sizeof (ucs2_path) / sizeof(ucs2_path[0]);
HINSTANCE moduleHandle = GetModuleHandle("libsvnjavahl-1");
GetModuleFileNameW (moduleHandle, ucs2_path, inwords);
inwords = lstrlenW (ucs2_path);
outbytes = outlength = 3 * (inwords + 1);
utf8_path = (char *)apr_palloc (pool, outlength);
apr_err = apr_conv_ucs2_to_utf8 ((const apr_wchar_t *) ucs2_path,
&inwords, utf8_path, &outbytes);
if (!apr_err && (inwords > 0 || outbytes == 0))
apr_err = APR_INCOMPLETE;
if (apr_err)
{
if (stderr)
fprintf (stderr, "Can't convert module path to UTF-8");
return FALSE;
}
utf8_path[outlength - outbytes] = '\0';
internal_path = svn_path_internal_style (utf8_path, pool);
/* get base path name */
internal_path = svn_path_dirname (internal_path, pool);
internal_path = svn_path_join (internal_path, SVN_LOCALE_RELATIVE_PATH,
pool);
bindtextdomain (PACKAGE_NAME, internal_path);
apr_pool_destroy (pool);
}
#else
bindtextdomain(PACKAGE_NAME, SVN_LOCALE_DIR);
#endif
textdomain(PACKAGE_NAME);
#endif
/* Create our top-level pool. */
g_pool = svn_pool_create (NULL);
#if defined(WIN32) || defined(__CYGWIN__)
/* See http://svn.collab.net/repos/svn/trunk/notes/asp-dot-net-hack.txt */
/* ### This code really only needs to be invoked by consumers of
### the libsvn_wc library, which basically means SVNClient. */
if (getenv ("SVN_ASP_DOT_NET_HACK"))
{
svn_error_t *err = svn_wc_set_adm_dir("_svn", g_pool);
if (err)
{
if (stderr)
{
fprintf(stderr,
"%s: error: SVN_ASP_DOT_NET_HACK failed: %s\n",
"svnjavahl", err->message);
}
svn_error_clear(err);
return FALSE;
}
}
#endif
//// build all mutexes
//g_finalizedObjectsMutex = new JNIMutex(g_pool);
//if(isExceptionThrown())
//{
// return false;
//}
//g_logMutex = new JNIMutex(g_pool);
//if(isExceptionThrown())
//{
// return false;
//}
//g_globalPoolMutext = new JNIMutex(g_pool);
//if(isExceptionThrown())
//{
// return false;
//}
//// initialized the thread local storage
//if(!JNIThreadData::initThreadData())
//{
// return false;
//}
//setEnv(env);
//if(isExceptionThrown())
//{
// return false;
//}
//g_initEnv = NULL;
m_globalData.init();
g_inInit = false;
return true;
}
void Util::handleAPRError(int error, const char *op)
{
char *buffer = getFormatBuffer();
if(buffer == NULL)
{
return;
}
apr_snprintf(buffer, formatBufferSize,
"an error occurred in function %s with return value %d",
op, error);
throwError(buffer);
}
//static
bool Util::isOtherExceptionThrown()
{
return false;
}
//static
bool Util::isExceptionThrown()
{
if(g_inInit) // during init -> look in the global member
{
return g_initException;
}
// look in the thread local storage
//JNIThreadData *data = JNIThreadData::getThreadData();
//return data == NULL || data->m_exceptionThrown;
return m_globalData.m_exceptionThrown;
}
//static
void Util::setExceptionThrown()
{
if (g_inInit)
{
// During global initialization, store any errors that occur
// in in a global variable (since thread-local storage may not
// yet be available).
g_initException = true;
}
else
{
// When global initialization is complete, thread-local
// storage should be available, so store the error there.
//JNIThreadData *data = JNIThreadData::getThreadData();
//data->m_exceptionThrown = true;
m_globalData.m_exceptionThrown = true;
}
}
/*static*/ void Util::throwNullPointerException( const char * p_msg)
{
std::cout << "Exception " << p_msg << std::endl;
//if (getLogLevel() >= errorLog)
{
logMessage("NullPointerException thrown");
}
setExceptionThrown();
}
//static
void Util::throwError(const char *message)
{
//raiseThrowable(JAVA_PACKAGE"/JNIError", message);
throw std::string( message);
}
/**
* returns the global (not request specific) pool
* @return global pool
*/
/*static*/ apr_pool_t * Util::getPool()
{
return g_pool;
}
/**
* build the error message from the svn error into buffer. This method calls
* itselft recursivly for all the chained errors
*
* @param err the subversion error
* @param depth the depth of the call, used for formating
* @param parent_apr_err the apr of the previous level, used for formating
* @param buffer the buffer where the formated error message will
* be stored
*/
void Util::assembleErrorMessage(svn_error_t *err, int depth,
apr_status_t parent_apr_err,
std::string &buffer)
{
// buffer for a single error message
char errbuf[256];
/* Pretty-print the error */
/* Note: we can also log errors here someday. */
/* When we're recursing, don't repeat the top-level message if its
the same as before. */
if (depth == 0 || err->apr_err != parent_apr_err)
{
/* Is this a Subversion-specific error code? */
if ((err->apr_err > APR_OS_START_USEERR)
&& (err->apr_err <= APR_OS_START_CANONERR))
buffer.append(svn_strerror (err->apr_err, errbuf, sizeof (errbuf)));
/* Otherwise, this must be an APR error code. */
else
buffer.append(apr_strerror (err->apr_err, errbuf, sizeof (errbuf)));
buffer.append("\n");
}
if (err->message)
buffer.append( "svn: ").append(err->message).append("\n");
if (err->child)
assembleErrorMessage(err->child, depth + 1, err->apr_err, buffer);
}
//static
std::string Util::makeSVNErrorMessage(svn_error_t *err)
{
if(err == NULL)
return "";
std::string buffer;
assembleErrorMessage(err, 0, APR_SUCCESS, buffer);
return buffer;
}
/**
* process a svn error by wraping in into a ClientExpection
* and throwing that
* @param err the error to by handled
*/
/*static*/ void Util::handleSVNError( svn_error_t * p_err)
{
if( !p_err)
{
//std::cout << "handleSVNError: p_err is 0" << std::endl;
return;
}
//std::cout << "Error " << ( p_err->message?p_err->message:"<<nomsg>>") << std::endl;
if(isOtherExceptionThrown())
{
svn_error_clear( p_err);
AfxMessageBox( "Other exception thrown, Util::handleSVNError");
return;
}
std::string buffer;
assembleErrorMessage( p_err, 0, APR_SUCCESS, buffer);
AfxMessageBox( (std::string( "SVN Error details follow:\n") + buffer).c_str());
//std::cout << "Error " << buffer << std::endl;
//if( p_err->apr_err == SVN_ERR_RA_ILLEGAL_URL)
// std::cout << "Error SVN_ERR_RA_ILLEGAL_URL, [URL does not exist]. " << std::endl;
//if( p_err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)
// std::cout << "Error SVN_ERR_UNSUPPORTED_FEATURE, [URL refs to file instead of a directory]. " << std::endl;
//if( p_err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE)
// std::cout << "Error SVN_ERR_UNVERSIONED_RESOURCE " << ( p_err->file? p_err->file: "<<nofile>>") << " msg = " << ( p_err->message?p_err->message:"<<nomsg>>") << std::endl;
//if( p_err->apr_err == SVN_ERR_RA_ILLEGAL_URL)
// std::cout << "Error SVN_ERR_RA_ILLEGAL_URL " << ( p_err->file? p_err->file: "<<nofile>>") << " msg = " << ( p_err->message?p_err->message:"<<nomsg>>") << std::endl;
//if( p_err->apr_err == SVN_ERR_RA_DAV_SOCK_INIT)
// std::cout << "Error SVN_ERR_RA_DAV_SOCK_INIT " << (p_err->file?p_err->file:"") << " msg = " << ( p_err->message?p_err->message:"<<nomsg>>") << std::endl;
//if( p_err->child)
// handleSVNError( p_err->child);
}
/*static*/ svn_error_t * Util::preprocessPath(const char *&path, apr_pool_t * pool)
{
/* URLs and wc-paths get treated differently. */
if (svn_path_is_url (path))
{
/* No need to canonicalize a URL's case or path separators. */
/* Convert to URI. */
path = svn_path_uri_from_iri (path, pool);
/* Auto-escape some ASCII characters. */
path = svn_path_uri_autoescape (path, pool);
/* The above doesn't guarantee a valid URI. */
if (! svn_path_is_uri_safe (path))
return svn_error_createf (SVN_ERR_BAD_URL, 0,
"URL '%s' is not properly URI-encoded",
path);
/* Verify that no backpaths are present in the URL. */
if (svn_path_is_backpath_present (path))
return svn_error_createf (SVN_ERR_BAD_URL, 0,
"URL '%s' contains a '..' element",
path);
/* strip any trailing '/' */
path = svn_path_canonicalize (path, pool);
}
else /* not a url, so treat as a path */
{
const char *apr_target;
char *truenamed_target; /* APR-encoded */
apr_status_t apr_err;
/* canonicalize case, and change all separators to '/'. */
SVN_ERR (svn_path_cstring_from_utf8 (&apr_target, path,
pool));
apr_err = apr_filepath_merge (&truenamed_target, "", apr_target,
APR_FILEPATH_TRUENAME, pool);
if (!apr_err)
/* We have a canonicalized APR-encoded target now. */
apr_target = truenamed_target;
else if (APR_STATUS_IS_ENOENT (apr_err))
/* It's okay for the file to not exist, that just means we
have to accept the case given to the client. We'll use
the original APR-encoded target. */
;
else
return svn_error_createf (apr_err, NULL,
"Error resolving case of '%s'",
svn_path_local_style (path,
pool));
/* convert back to UTF-8. */
SVN_ERR (svn_path_cstring_to_utf8 (&path, apr_target, pool));
path = svn_path_canonicalize (path, pool);
}
return NULL;
}
/**
* Return the request pool. The request pool will be destroyed after each
* request (call)
* @return the pool to be used for this request
*/
/*static*/ Pool * Util::getRequestPool()
{
//return JNIThreadData::getThreadData()->m_requestPool;
return m_globalData.m_requestPool;
//return m_requestPool;
}
/**
* Set the request pool in thread local storage
* @param pool the request pool
*/
/*static*/ void Util::setRequestPool(Pool *pool)
{
//JNIThreadData::getThreadData()->m_requestPool = pool;
//m_requestPool = pool;
m_globalData.m_requestPool = pool;
}
char * Util::getFormatBuffer()
{
if(g_inInit) // during init -> use the global buffer
{
return g_initFormatBuffer;
}
// use the buffer in the thread local storage
//JNIThreadData *data = JNIThreadData::getThreadData();
//if(data == NULL) // if that does not exists -> use the global buffer
//{
// return g_initFormatBuffer;
//}
//return data->m_formatBuffer;
return m_globalData.m_formatBuffer;
}
/**
* initialite the log file
* @param level the log level
* @param the name of the log file
*/
void Util::initLogFile(int level, const std::string& path)
{
// lock this operation
//JNICriticalSection cs(*g_logMutex);
if(g_logLevel > noLog) // if the log file has been opened
{
g_logStream.close();
}
// remember the log level
g_logLevel = level;
//JNIStringHolder myPath(path);
const char * myPath = path.c_str();
if(g_logLevel > noLog) // if a new log file is needed
{
// open it
g_logStream.open(myPath, std::ios::app);
}
}
/**
* Returns the current log level
* @return the log level
*/
int Util::getLogLevel()
{
return g_logLevel;
}
/**
* write a message to the log file if needed
* @param the log message
*/
void Util::logMessage(const char *message)
{
// lock the log file
//JNICriticalSection cs(*g_logMutex);
g_logStream << message << std::endl;
}
#endif
--- NEW FILE: ThreadData.h ---
#pragma once
#include "svn_client.h"
#include "Pool.h"
#include "Util.h"
class ThreadData
{
public:
ThreadData(void);
~ThreadData(void);
void init();
/**
* flag that a java execption has been detected
*/
bool m_exceptionThrown;
/**
* a buffer used for formating messages
*/
char m_formatBuffer[Util::formatBufferSize];
/**
* the pool for the current request (call)
*/
Pool *m_requestPool;
};
--- NEW FILE: ThreadData.cpp ---
#include "StdAfx.h"
#if(USESVN)
#include ".\threaddata.h"
ThreadData::ThreadData(void)
{
}
ThreadData::~ThreadData(void)
{
}
void ThreadData::init()
{
m_exceptionThrown = false;
m_requestPool = 0;
}
#endif
--- NEW FILE: Util.h ---
/**
* @copyright
* ====================================================================
* Copyright (c) 2003-2004 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/.
* ====================================================================
* @endcopyright
*
* @file JNIUtil.h
* @brief Interface of the class JNIUtil
*/
#pragma once
#include "svn_client.h"
#include "Pool.h"
#include <string>
class ThreadData;
/**
* class to hold a number of JNI relate utility methods. No Objects of this
* class are ever created
*/
class Util
{
public:
enum { formatBufferSize = 2048 };
static char * getFormatBuffer();
static bool globalInit();
static svn_error_t * preprocessPath(const char *&path, apr_pool_t * pool);
static void logMessage(const char *message);
static int getLogLevel();
static void initLogFile(int level, const std::string& path);
static void handleAPRError(int error, const char *op);
static bool isOtherExceptionThrown();
static bool isExceptionThrown();
static void setExceptionThrown();
static void throwNullPointerException( const char *);
static void throwError(const char *message);
static Pool* getRequestPool();
static void setRequestPool(Pool *pool);
static void assembleErrorMessage(svn_error_t *err, int depth,
apr_status_t parent_apr_err,
std::string& buffer);
static std::string makeSVNErrorMessage(svn_error_t *err);
static void handleSVNError( svn_error_t *);
static apr_pool_t * getPool();
private:
//static Pool *m_requestPool; // was in a Thread Local Storage
/**
* global master pool. All other pool are subpools of this pool
*/
static apr_pool_t* g_pool;
/**
* flag, that one thread is in the init code. Cannot use mutex here since
* apr is not initialized yes
*/
static bool g_inInit;
/**
* flag, that an exception occured during our initialization
*/
static bool g_initException;
enum { noLog, errorLog, exceptionLog, entryLog } LogLevel;
/**
* the log level of this module
*/
static int g_logLevel;
/**
* the stream to write log messages to
*/
static std::ofstream g_logStream;
static char g_initFormatBuffer[formatBufferSize];
static ThreadData m_globalData;
};
--- NEW FILE: HiClient.cpp ---
#include "StdAfx.h"
#include "HiClient.h"
#include <fstream>
#if(USESVN)
//#include "Revision.h" // these should not be here at all
#include "Pool.h"
//#include "Util.h"
//#include "Prompter.h" // end
extern std::string g_userName;
extern std::string g_passWord;
HiClient::HiClient( const std::string& p_userName, const std::string& p_passWord)
: Client( p_userName, p_passWord)
, m_logEnabled( true)
{
}
HiClient::~HiClient(void)
{
}
bool HiClient::isItUs( const std::string& p_userName)
{
log( "isItUs", p_userName);
return m_userName == p_userName;//strcmp( m_userName.c_str(), ( p_userName?p_userName:"")) == 0; // equal means yes
}
bool HiClient::isLocked ( const std::string& p_path)
{
log( "isLocked", p_path);
return isLockedByUser( p_path, std::string());
}
bool HiClient::isLockedByUs ( const std::string& p_path)
{
bool lkd, l_us, l_else;
log( "isLockedByUs", p_path);
lkd = isLockedByWhom( p_path, &l_us, &l_else);
return lkd && l_us;
}
bool HiClient::isLockedByOthers ( const std::string& p_path)
{
bool lkd, l_us, l_else;
log( "isLockedByOthers", p_path);
lkd = isLockedByWhom( p_path, &l_us, &l_else);
return lkd && l_else;
}
bool HiClient::isLockedByWhom ( const std::string& p_path, bool * p_us, bool * p_else)
{
ASSERT( p_us);
ASSERT( p_else);
std::string uname;
bool lockd = false;
log( "isLockedByWhom", p_path);
lockd = isLockedByUser( p_path, uname);
*p_us = isItUs( uname);
*p_else = !*p_us;
return lockd;
}
bool HiClient::isLockedByUser ( const std::string& p_path, std::string& p_username)
{
Pool reqPool;
bool res = false;
ClientUtil::InfoHelp::InfoVec inf;
log( "isLockedByUser", p_path + p_username);
bool suc = info2Qck( p_path.c_str(), false, inf);
ASSERT( suc);
ASSERT( inf.size() == 1);
for( ClientUtil::InfoHelp::InfoVecConIter it = inf.begin(), en = inf.end(); suc && it != en; ++it)
{
if( it->m_info && it->m_info->lock)
{
// locked
res = true;
// by whom
ASSERT( it->m_info->lock->owner);
if( it->m_info->lock->owner)
p_username = it->m_info->lock->owner;
else
p_username = "";
}
}
return res;
}
bool HiClient::isVersioned ( const std::string& p_path, bool p_isADir /*= false*/, bool p_suppressErrorMsg /*= false*/)
{
Pool reqPool;
log( "isVersioned", p_path + (p_isADir?" dir ": " file "));
ClientUtil::InfoHelp::InfoVec inf;
bool res = info2Qck( p_path.c_str(), false, inf, p_suppressErrorMsg);
return res;
}
bool HiClient::info ( const std::string& p_path, bool p_recursive, bool p_assembleInfoMessage, std::string& p_resultMsg, std::string& p_lastChangingAuthor, std::string& p_lockOwner)
{
Pool reqPool;
bool rv = false;
std::string msg;
std::string aut;
std::string own;
log( "info", p_path);
ClientUtil::InfoHelp::InfoVec inf;
if( sub_info2( p_path.c_str(), Revision(), Revision(), p_recursive, inf, true)) // non-recursive info only
{
rv = true;
if( p_assembleInfoMessage)
{
msg = "After issuing 'svn info "; msg += ClientUtil::charstar2str( p_path.c_str(), "Url"); msg += "'";
for( ClientUtil::InfoHelp::InfoVecConIter it = inf.begin(), en = inf.end(); it != en; ++it)
{
msg.append( "\nI know about: '");
msg.append( ClientUtil::charstar2str( it->m_path, "Path"));
msg.append( "' the following:");
if( it->m_info)
{
if( !aut.empty()) aut.append( ", "); // if multiple entries in inf, then separate authors by ,
msg.append( "\n\tLast Changed Author: ");
aut.append( ClientUtil::charstar2str( it->m_info->last_changed_author, "Author"));
msg.append( ClientUtil::charstar2str( it->m_info->last_changed_author, "Author"));
msg.append( "\n\tVersioned as (URL): ");
msg.append( ClientUtil::charstar2str( it->m_info->URL, "Url"));
if( it->m_info->lock)
{
msg.append( "\n\tLocked by ");
if( !own.empty()) own.append( ", "); // if multiple entries in inf, then separate owners by ,
own.append( ClientUtil::charstar2str( it->m_info->lock->owner, "LockOwner"));
msg.append( ClientUtil::charstar2str( it->m_info->lock->owner, "LockOwner"));
}
else
msg.append( "\n\tNot Locked");
}
else
msg.append( "No detailed info present for item");
}
}
}
else
{
rv = false;
if( p_assembleInfoMessage)
{
msg.append( "svn info command failed");
}
}
if( p_assembleInfoMessage)
p_resultMsg = msg;
p_lastChangingAuthor = aut;
p_lockOwner = own;
return rv;
}
bool HiClient::tryLock ( const std::string& p_path)
{
log( "tryLock", p_path);
bool res = false;
if( isLockedByOthers( p_path)) return res;
Pool reqPool;
res = sub_lock( Targets( p_path.c_str()), /*comment =*/ "nc" , /*force =*/ false );
return res;
}
bool HiClient::unLock ( const std::string& p_path)
{
log( "unLock", p_path);
Pool reqPool;
return sub_unlock( Targets( p_path.c_str()));
}
bool HiClient::lockableProp ( const std::string& p_path)
{
log( "lockableProp", p_path);
Pool reqPool;
return sub_propertySet( p_path.c_str(), "svn:needs-lock", /*value =*/ "na", /*recurse =*/ false, /*force =*/ false );
}
bool HiClient::getLatest ( const std::string& p_path)
{
log( "getLatest", p_path);
Pool reqPool;
UPDATE_RES res;
bool succ = sub_update( Targets( p_path.c_str()), Revision(), /*recurse =*/ true, /*ignoreExt =*/ false, res);
return succ;
}
bool HiClient::lightCheckOut( const std::string& p_path, const std::string& p_localDir)
{
log( "checkOut", p_path);
Pool reqPool;
return 0 < sub_checkout( p_path.c_str(), p_localDir.c_str(), Revision(), Revision(), /*recurse =*/ true, /*ignoreExt =*/ false);
}
bool HiClient::commitAll ( const std::string& p_path, bool p_keepCheckedOut)
{
log( "commitAll", p_path);
Pool requestPool;
Targets tgt( p_path.c_str()); // commit might return -1 if there were no things to commit (diff was 0)
return 0 < sub_commit( tgt, "no message", /*recurse =*/ true, /*noUnlock =*/ p_keepCheckedOut);
}
bool HiClient::add ( const std::string& p_path, bool p_recursive)
{
log( "add", p_path);
Pool reqPool;
return 0 < sub_add( p_path.c_str(), p_recursive);
}
bool HiClient::mkDirOnServer ( const std::string& p_path)
{
log( "mkDirOnServer", p_path);
Pool reqPool;
return 0 < sub_mkdir2( Targets( p_path.c_str()), "nm");
}
bool HiClient::cleanup( const std::string& p_path)
{
log( "cleanup", p_path);
Pool reqPool;
return sub_cleanup( p_path.c_str());
}
bool HiClient::resolve( const std::string& p_path, bool p_recursive)
{
log( "resolve", p_path);
Pool reqPool;
return sub_resolved( p_path.c_str(), p_recursive);
}
bool HiClient::status( const std::string& p_path, bool p_assembleStatusMsg, std::string& p_statMsg)
{
log( "status", p_path);
Pool reqPool;
bool rv = false;
std::string msg;
ClientUtil::StatusExtInfoVec vec;
vec = sub_extended_status( p_path.c_str(), false /* on_server*/);
if( !vec.empty())
{
rv = true;
if( p_assembleStatusMsg)
{
msg = "Svn status " + p_path + " command resulted in:\n";
for( ClientUtil::StatusExtInfoVec::iterator it = vec.begin(); it != vec.end(); ++it)
{
//const char * m_path;
//svn_wc_status2_t * m_status;
if( !it->m_status)
msg.append( "Null status");
else
{
std::string st;
switch( it->m_status->text_status) {
//case items copied from enum svn_wc_status_kind, svn_wc.h
case svn_wc_status_none: st += "Not exists "; break; /** does not exist */
case svn_wc_status_unversioned: st += "Unversioned"; break; /** is not a versioned thing in this wc */
case svn_wc_status_normal: st += "Normal "; break; /** exists, but uninteresting */
case svn_wc_status_added: st += "Added "; break; /** is scheduled for addition */
case svn_wc_status_missing: st += "Missing "; break; /** under v.c., but is missing */
case svn_wc_status_deleted: st += "Deleted "; break; /** scheduled for deletion */
case svn_wc_status_replaced: st += "Replaced "; break; /** was deleted and then re-added */
case svn_wc_status_modified: st += "Modified "; break; /** text or props have been modified */
case svn_wc_status_merged: st += "Merged "; break; /** local mods received repos mods */
case svn_wc_status_conflicted: st += "Conflicted "; break; /** local mods received conflicting repos mods */
case svn_wc_status_ignored: st += "Ignored "; break; /** is unversioned but configured to be ignored */
case svn_wc_status_obstructed: st += "Obstructed "; break; /** an unversioned resource is in the way of the versioned resource */
case svn_wc_status_external: st += "External "; break; /** an unversioned path populated by an svn:externals property */
case svn_wc_status_incomplete: st += "Incomplete "; break; /** a directory doesn't contain a complete entries list */
default: st += "Unknown ";
};
msg.append( st);
}
msg.append( " ");
msg.append( ClientUtil::charstar2str( it->m_path, "Path"));
if( it->m_status && it->m_status->locked)
msg.append( " locked");
if( it->m_status && it->m_status->repos_lock)
msg.append( std::string( " by ") + ClientUtil::charstar2str( it->m_status->repos_lock->owner, "Owner"));
msg.append( "\n");
}
p_statMsg = msg;
}
}
else // vec.empty()
{
if( p_assembleStatusMsg)
p_statMsg = "svn status command failed";
}
return rv;
}
#if(0)
msg = "After issuing 'svn info "; msg += ClientUtil::charstar2str( p_path.c_str(), "Url"); msg += "'";
for( ClientUtil::InfoHelp::InfoVecConIter it = inf.begin(), en = inf.end(); it != en; ++it)
{
msg.append( "\nI know about: '");
msg.append( ClientUtil::charstar2str( it->m_path, "Path"));
msg.append( "' the following:");
if( it->m_info)
{
if( !aut.empty()) aut.append( ", "); // if multiple entries in inf, then separate authors by ,
msg.append( "\n\tLast Changed Author: ");
aut.append( ClientUtil::charstar2str( it->m_info->last_changed_author, "Author"));
msg.append( ClientUtil::charstar2str( it->m_info->last_changed_author, "Author"));
msg.append( "\n\tVersioned as (URL): ");
msg.append( ClientUtil::charstar2str( it->m_info->URL, "Url"));
if( it->m_info->lock)
{
msg.append( "\n\tLocked by ");
if( !own.empty()) own.append( ", "); // if multiple entries in inf, then separate owners by ,
own.append( ClientUtil::charstar2str( it->m_info->lock->owner, "LockOwner"));
msg.append( ClientUtil::charstar2str( it->m_info->lock->owner, "LockOwner"));
}
else
msg.append( "\n\tNot Locked");
}
else
msg.append( "No detailed info present for item");
}
#endif
void HiClient::log( const std::string& p_command, const std::string& p_par)
{
if( !m_logEnabled) return;
std::ofstream fs;
fs.open( "c:\\svnlog.txt", std::ios_base::ate | std::ios_base::app); // append
if( fs)
{
fs << p_command << " " << p_par << std::endl;
fs.close();
}
}
void HiClient::setLog( bool p_val)
{
m_logEnabled = p_val;
}
#endif
--- NEW FILE: Client.cpp ---
#include "StdAfx.h"
#if(USESVN)
#include ".\client.h"
#include <crtdbg.h> // for ASSERT
#include <iostream> // remove this later
#include "Pool.h"
#include "Util.h"
#include "svn_client.h"
#include "svn_config.h"
extern std::string g_userName;
extern std::string g_passWord;
//Client::Client(void)
// : m_notify2( 0)
// , m_prompter( 0)
// , m_commitMessageBuilder( 0)
[...1099 lines suppressed...]
return commit2_info->revision;
return -1;
}
//
// std::string.append( const char * ) crashes if parameter ptr is 0, that's why this function is useful
//
// static
std::string ClientUtil::charstar2str( const char* p_charStar, const std::string p_name)
{
if( p_charStar)
{
return std::string( p_charStar);
}
return std::string( "<no" + p_name + ">");
}
#endif
--- NEW FILE: ClientUtil.h ---
#pragma once
#include "Revision.h"
#include "Targets.h"
#include "svn_client.h"
#include "Prompter.h"
// class mimicing subversion/bindings/java/javahl/native/svnclient.cpp
class ClientUtil
{
public:
//
// ******** Info *********
//
struct InfoHelp
{
struct InfoEntry
{
const char *m_path;
svn_info_t *m_info;
};
typedef std::vector<InfoEntry> InfoVec;
typedef InfoVec::const_iterator InfoVecConIter;
struct InfoBaton
{
InfoVec m_infoVect;
apr_pool_t *m_pool;
};
// callback, which will fill an InfoBaton struct (got in void *baton)
static svn_error_t * infoReceiver(void *baton,
const char *path,
const svn_info_t *info,
apr_pool_t *pool);
};
//
// ******** Commit related helper *********
//
struct CommitHelp
{
class MsgBuilder // builds a proper commit message based on entries
{
void dealWithItem( std::string& res, svn_client_commit_item_t * item);
public:
std::string build( const apr_array_header_t *commit_items);
};
struct LogMsgBaton // log_msg_baton
{
const char * m_message;
MsgBuilder * m_messageHandler;
};
// creates the baton class given to the callback
static void* createLogMsgBaton( const char * p_strMessage, CommitHelp::MsgBuilder * p_msgComposer);
// callback, which is called by commit-y operations
static svn_error_t * logMsg(const char **log_msg,
const char **tmp_file,
const apr_array_header_t *commit_items,
void *baton,
apr_pool_t *pool);
};
//
// ******** Notify : a Commit and Checkout related helper *********
//
struct NotifyHelp
{
/**
* Handler for Subversion notifications.
*
* @param notify all the information about the event
* @param pool an apr pool to allocated memory
*/
void onNotify( const svn_wc_notify_t *notify, apr_pool_t *pool);
/**
* notification function passed as svn_wc_notify_func2_t
* @param baton notification instance is passed using this parameter
* @param notify all the information about the event
* @param pool an apr pool to allocated memory
*/
// callback, which is called during notification
static void notify2(void *baton,
const svn_wc_notify_t *notify,
apr_pool_t *pool);
};
// **************************************
// other callbacks
// **************************************
struct OtherHelp
{
static svn_error_t * checkCancel(void *cancelBaton);
};
//
// ******** Status related helper *********
//
struct StatusHelp
{
struct StatusEntry
{
const char * m_path;
svn_wc_status2_t * m_status;
};
struct StatusBaton
{
std::vector<StatusEntry> m_statusVect;
apr_pool_t * m_pool;
};
static void statusReceiver(void *baton, const char *path,
svn_wc_status2_t *status);
};
typedef std::pair<std::string, long> StatusInfo;
StatusInfo sub_single_status(const char *path, bool onServer);
typedef StatusHelp::StatusEntry StatusExtInfo;
typedef std::vector<StatusExtInfo> StatusExtInfoVec;
StatusExtInfoVec sub_extended_status( const char * p_path, bool p_onServer);
// statics
static std::string charstar2str( const char* p_charStar, const std::string p_name);
};
--- NEW FILE: Revision.cpp ---
/**
* @copyright
* ====================================================================
* Copyright (c) 2003 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/.
* ====================================================================
* @endcopyright
*
* @file Revision.cpp
* @brief Implementation of the class Revision
*/
#include "StdAfx.h"
#if(USESVN)
#include "Revision.h"
const svn_opt_revision_kind Revision::START = svn_opt_revision_unspecified;
const svn_opt_revision_kind Revision::HEAD = svn_opt_revision_head;
Revision::Revision()
{
m_revision.value.number = 0;
m_revision.kind = svn_opt_revision_head;
}
Revision::Revision( bool p_head /* = false */, bool p_one /* = false */)
{
m_revision.kind = svn_opt_revision_unspecified;
m_revision.value.number = 0;
if( p_head)
m_revision.kind = svn_opt_revision_head;
else if( p_one)
{
m_revision.kind = svn_opt_revision_number;
m_revision.value.number = 1;
}
}
Revision::Revision (const svn_opt_revision_kind p_kind)
{
m_revision.kind = p_kind;
m_revision.value.number = 0;
}
Revision::~Revision()
{
}
const svn_opt_revision_t *Revision::revision () const
{
return &m_revision;
}
#endif
--- NEW FILE: Prompter.h ---
/**
* @copyright
* ====================================================================
* Copyright (c) 2003-2004 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/.
* ====================================================================
* @endcopyright
*
* @file Prompter.h
* @brief Interface of the class Prompter
*/
#if !defined(AFX_PROMPTER_H__6833BB77_DDCC_4BF8_A995_5A5CBC48DF4C__INCLUDED_)
#define AFX_PROMPTER_H__6833BB77_DDCC_4BF8_A995_5A5CBC48DF4C__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "svn_auth.h"
#include <string>
/**
* An interface to be implemented by subclasses.
* Callback methods of Prompter::CallbackHelpers will call these methods if needed.
*/
class PromptImpl
{
public:
PromptImpl() : m_maySave( false) { }
virtual ~PromptImpl() { }
virtual bool prompt
(const char *realm, const char *pi_username, bool maySave) = 0;
virtual bool askYesNo
(const char *realm, const char *question, bool yesIsDefault) = 0;
virtual int askTrust
(const char *question, bool maySave) = 0;
virtual std::string askQuestion
( const char *realm, const char *question, bool showAnswer, bool maySave) = 0;
virtual std::string password() = 0;
virtual std::string username() = 0;
/**
* flag is the user allowed, that the last answer is stored in
* the configuration
*/
bool m_maySave;
static void scanfBlind( std::string& ret);
};
class TextPromptImpl : public PromptImpl
{
protected:
std::string m_uName;
std::string m_pWord;
enum EntryType
{
UserName
, Password
};
std::string readcnf( const EntryType& p_type);
std::string m_answer;
public:
TextPromptImpl();
virtual ~TextPromptImpl();
virtual bool prompt(const char *realm, const char *pi_username, bool maySave);
virtual bool askYesNo(const char *realm, const char *question, bool yesIsDefault);
virtual int askTrust(const char *question, bool maySave);
virtual std::string askQuestion(const char *realm, const char *question, bool showAnswer, bool maySave);
virtual std::string password();
virtual std::string username();
};
class GPromptImpl : public PromptImpl
{
protected:
std::string m_uName;
std::string m_pWord;
bool m_credsFilled;
std::string m_answer;
public:
GPromptImpl();
virtual ~GPromptImpl();
virtual bool prompt(const char *realm, const char *pi_username, bool maySave);
virtual bool askYesNo(const char *realm, const char *question, bool yesIsDefault);
virtual int askTrust(const char *question, bool maySave);
virtual std::string askQuestion(const char *realm, const char *question, bool showAnswer, bool maySave);
virtual std::string password();
virtual std::string username();
};
/**
* This class helps setting up the prompters and providers for authentication.
*/
class Prompter
{
PromptImpl * m_impl;
Prompter( PromptImpl* p_prompter);
public:
static Prompter *makePrompter( PromptImpl* p_prompter);
~Prompter();
svn_auth_provider_object_t *getProviderUsername();
svn_auth_provider_object_t *getProviderSimple();
svn_auth_provider_object_t *getProviderServerSSLTrust();
svn_auth_provider_object_t *getProviderClientSSL();
svn_auth_provider_object_t *getProviderClientSSLPassword();
enum PrompUserPass
{
AcceptPermanently
, AcceptTemporary
, Reject
};
class CallbackHelpers
{
public:
static svn_error_t* simple_prompt(
svn_auth_cred_simple_t **cred_p,
void *baton, const char *realm,
const char *username,
svn_boolean_t may_save,
apr_pool_t *pool);
static svn_error_t* username_prompt(
svn_auth_cred_username_t **cred_p,
void *baton,
const char *realm,
svn_boolean_t may_save,
apr_pool_t *pool);
static svn_error_t* ssl_server_trust_prompt(
svn_auth_cred_ssl_server_trust_t **cred_p,
void *baton,
const char *realm,
apr_uint32_t failures,
const svn_auth_ssl_server_cert_info_t *cert_info,
svn_boolean_t may_save,
apr_pool_t *pool);
static svn_error_t* ssl_client_cert_prompt(
svn_auth_cred_ssl_client_cert_t **cred_p,
void *baton,
const char *realm,
svn_boolean_t may_save,
apr_pool_t *pool);
static svn_error_t* ssl_client_cert_pw_prompt(
svn_auth_cred_ssl_client_cert_pw_t **cred_p,
void *baton,
const char *realm,
svn_boolean_t may_save,
apr_pool_t *pool);
};
};
#endif
// !defined(AFX_PROMPTER_H__6833BB77_DDCC_4BF8_A995_5A5CBC48DF4C__INCLUDED_)
- Previous message: [GME-commit] GMESRC/GME/XmlBackEnd/SVNCode - New directory
- Next message: [GME-commit] GMESRC/GME/XmlBackEnd CoreXmlFile.cpp, 1.24, 1.25 SvnConfig.h, 1.1, 1.2 SvnExec.cpp, 1.1, 1.2 SvnExec.rgs, 1.1, 1.2 SvnTester.cpp, 1.1, 1.2 XmlBackEnd.vcproj, 1.4, 1.5
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the GME-commit
mailing list