/*
* ====================================================================
* Copyright (c) 2002-2005 The RapidSvn Group. All rights reserved.
*
* This software is licensed as described in the file LICENSE.txt,
* which you should have received as part of this distribution.
*
* 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/.
* ====================================================================
*/
#if defined( _MSC_VER) && _MSC_VER <= 1200
#pragma warning( disable: 4786 )// debug symbol truncated
#endif
// Subversion api
#include "svn_client.h"
#include "svn_sorts.h"
//#include "svn_utf.h"
// subcpp
#include "client.hpp"
#include "dirent.hpp"
#include "exception.hpp"
#include "pool.hpp"
#include "status.hpp"
#include "targets.hpp"
#include "url.hpp"
namespace svn
{
svn_error_t* StatusEntriesFunc( void* baton, const char* path, const svn_client_status_t* status, apr_pool_t* )
{
StatusEntries* statusEntries = reinterpret_cast< StatusEntries* >( baton );
WCStatus& wcStatus = (*statusEntries)[ path ];
wcStatus.m_status = svn_client_status_dup( status, wcStatus.m_pool );
return SVN_NO_ERROR;
}
StatusEntries Client::Status( const char* path,
svn_depth_t depth,
const bool get_all,
const bool update,
const Revision & revision,
const bool no_ignore,
const bool ignore_externals,
const bool depth_as_sticky )
{
svn_error_t* error;
svn_revnum_t revnum;
Pool pool;
StatusEntries entries;
error = svn_client_status5(
&revnum,
*m_context,
path,
revision.revision(),
depth,
get_all,
update,
no_ignore,
ignore_externals,
depth_as_sticky,
0,
StatusEntriesFunc,
&entries,
pool );
if ( error != NULL )
{
throw ClientException( error );
}
return entries;
}
svn_error_t* LogReceiver( void* baton, svn_log_entry_t* svnLogEntry, apr_pool_t* /*pool*/ )
{
try
{
LogEntryListener* listener = reinterpret_cast< LogEntryListener* >( baton );
bool shouldCancel = false;
listener->OnLogEntry( LogEntry( svnLogEntry ), shouldCancel );
if ( shouldCancel )
{
return svn_error_create( SVN_ERR_CANCELLED, NULL, "cancelled by user" );
}
else
{
return SVN_NO_ERROR;
}
}
catch ( std::exception& ex )
{
return svn_error_create( SVN_ERR_CANCELLED, NULL, ex.what() );
}
}
void Client::Log( const Targets& targets,
LogEntryListener& listener,
const svn::Revision& peg /*= Revision()*/,
const std::vector< std::pair< Revision, Revision > >& revisionRanges /* = std::vector< std::pair< Revision, Revision > >( 1, std::pair< Revision, Revision >( 0, svn::Revision::HEAD ) )*/,
int limit /*= 0*/,
bool discoverChangedPaths /*= false*/,
bool strictNodeHistory /*= true*/,
bool includeMergedRevisions /*= false*/,
bool retrieveAllRevisionProperties /*= false*/,
const std::vector< std::string >& revisionProperties /*= std::vector< std::string >*/
)
{
Pool pool;
apr_array_header_t* aprRevisionRanges = apr_array_make( pool.pool(), static_cast< int >( revisionRanges.size() ), static_cast< int >( sizeof( svn_opt_revision_range_t* ) ) );
std::vector< svn_opt_revision_range_t > svnRevisionRanges;
for ( std::vector< std::pair< Revision, Revision > >::const_iterator range = revisionRanges.begin(), end = revisionRanges.end(); range != end; ++range )
{
svn_opt_revision_range_t tempRange = { *range->first.revision(), *range->second.revision() };
svnRevisionRanges.push_back( tempRange );
*static_cast< svn_opt_revision_range_t** >( apr_array_push( aprRevisionRanges ) ) = &svnRevisionRanges.back();
}
apr_array_header_t* aprRevisionProperties = NULL;
if ( !retrieveAllRevisionProperties )
{
aprRevisionProperties = apr_array_make( pool.pool(), static_cast< int >( revisionProperties.size() ), sizeof( const char* ) );
for ( std::vector< std::string >::const_iterator revprop = revisionProperties.begin(), end = revisionProperties.end(); revprop != end; ++revprop )
{
const char* aprRevProp = apr_pstrdup( pool.pool(), revprop->c_str() );
*static_cast< const char ** >( apr_array_push( aprRevisionProperties ) ) = aprRevProp;
}
}
svn_error_t* error = svn_client_log5( targets.array( pool ),
peg.revision(),
aprRevisionRanges,
limit,
discoverChangedPaths ? 1 : 0,
strictNodeHistory ? 1 : 0,
includeMergedRevisions ? 1 : 0,
aprRevisionProperties,
LogReceiver,
&listener,
*m_context, // client ctx
pool );
if ( error != NULL )
{
throw ClientException( error );
}
}
WCEntry Client::WorkingCopyInfo( const char *path )
{
Pool pool;
svn_wc_adm_access_t *adm_access;
svn_error_t *error
= svn_wc_adm_probe_open( &adm_access, NULL, path, FALSE,
FALSE, pool );
if ( error != NULL )
throw ClientException( error );
const svn_wc_entry_t *entry;
error = svn_wc_entry( &entry, path, adm_access, FALSE, pool );
if ( error != NULL )
throw ClientException( error );
// entry may be NULL
return WCEntry( entry );
}
svn_error_t* SingleInfoReceiver( void* baton, const char*, const svn_info_t* info, apr_pool_t* )
{
Info* cppReceiver = reinterpret_cast< Info* >( baton );
*cppReceiver = Info( info );
return SVN_NO_ERROR;
}
svn::Info Client::Info( const Path& path,
const svn::Revision& peg /*= Revision( Revision::HEAD )*/,
const svn::Revision& revision /*= Revision( Revision::HEAD )*/ )
{
Pool pool;
svn::Info info;
svn_error_t* error = svn_client_info2( path.c_str(),
peg.revision(),
revision.revision(),
SingleInfoReceiver,
&info,
svn_depth_empty,
NULL, /* TODO: Support Changelists */
*m_context,
pool );
if( error != NULL )
{
throw ClientException( error );
}
return info;
}
};