You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2207 lines
76 KiB
2207 lines
76 KiB
/* This file is part of the KDE project
|
|
Copyright (C) 2003 Mickael Marchand <marchand@kde.org>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <tqcstring.h>
|
|
#include <tqsocket.h>
|
|
#include <tqdatetime.h>
|
|
#include <tqbitarray.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <unistd.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <netdb.h>
|
|
|
|
#include <tdeapplication.h>
|
|
#include <kdebug.h>
|
|
#include <tdemessagebox.h>
|
|
#include <kinstance.h>
|
|
#include <tdeglobal.h>
|
|
#include <kstandarddirs.h>
|
|
#include <tdelocale.h>
|
|
#include <kurl.h>
|
|
#include <ksock.h>
|
|
#include <dcopclient.h>
|
|
#include <tqcstring.h>
|
|
|
|
#include <subversion-1/svn_sorts.h>
|
|
#include <subversion-1/svn_path.h>
|
|
#include <subversion-1/svn_utf.h>
|
|
#include <subversion-1/svn_ra.h>
|
|
#include <subversion-1/svn_time.h>
|
|
#include <subversion-1/svn_cmdline.h>
|
|
#include <subversion-1/svn_version.h>
|
|
|
|
#include <kmimetype.h>
|
|
#include <tqfile.h>
|
|
|
|
#include "svn_tdeio.h"
|
|
#include <apr_portable.h>
|
|
// #include "commitdlg.h"
|
|
#include <ktextedit.h>
|
|
|
|
using namespace TDEIO;
|
|
using namespace SvnGlobal;
|
|
|
|
typedef struct
|
|
{
|
|
/* Holds the directory that corresponds to the REPOS_URL at RA->open()
|
|
* time. When callbacks specify a relative path, they are joined with
|
|
* this base directory. */
|
|
const char *base_dir;
|
|
svn_wc_adm_access_t *base_access;
|
|
|
|
/* An array of svn_client_commit_item_t * structures, present only
|
|
* during working copy commits. */
|
|
apr_array_header_t *commit_items;
|
|
|
|
/* A hash of svn_config_t's, keyed off file name (i.e. the contents of
|
|
* ~/.subversion/config end up keyed off of 'config'). */
|
|
apr_hash_t *config;
|
|
|
|
/* The pool to use for session-related items. */
|
|
apr_pool_t *pool;
|
|
|
|
} svn_client__callback_baton_t;
|
|
|
|
static svn_error_t *
|
|
open_tmp_file (apr_file_t **fp,
|
|
void *callback_baton,
|
|
apr_pool_t *pool)
|
|
{
|
|
svn_client__callback_baton_t *cb = (svn_client__callback_baton_t *) callback_baton;
|
|
const char *truepath;
|
|
const char *ignored_filename;
|
|
|
|
if (cb->base_dir)
|
|
truepath = apr_pstrdup (pool, cb->base_dir);
|
|
else
|
|
truepath = "";
|
|
|
|
/* Tack on a made-up filename. */
|
|
truepath = svn_path_join (truepath, "tempfile", pool);
|
|
|
|
/* Open a unique file; use APR_DELONCLOSE. */
|
|
SVN_ERR (svn_io_open_unique_file (fp, &ignored_filename,
|
|
truepath, ".tmp", TRUE, pool));
|
|
|
|
return SVN_NO_ERROR;
|
|
}
|
|
|
|
static svn_error_t *write_to_string(void *baton, const char *data, apr_size_t *len) {
|
|
kbaton *tb = ( kbaton* )baton;
|
|
svn_stringbuf_appendbytes(tb->target_string, data, *len);
|
|
return SVN_NO_ERROR;
|
|
}
|
|
|
|
#if (SVN_VER_MAJOR == 1 && SVN_VER_MINOR <= 8)
|
|
typedef svn_sort__item_t svn_sort_item_type;
|
|
#else
|
|
// Taken from subversion 1.8.10 source code and modified where needed
|
|
|
|
// Same as svn_sort__item_t
|
|
typedef struct svn_sort_item_type {
|
|
const void *key; // pointer to the key
|
|
apr_ssize_t klen; // size of the key
|
|
void *value; // pointer to the value
|
|
} svn_sort_item_type;
|
|
|
|
apr_array_header_t* svn_sort__hash(apr_hash_t *ht,
|
|
int (*comparison_func)(const svn_sort__item_t*, const svn_sort__item_t*), apr_pool_t *pool)
|
|
{
|
|
apr_hash_index_t *hi;
|
|
apr_array_header_t *ary;
|
|
svn_boolean_t sorted;
|
|
svn_sort_item_type *prev_item;
|
|
|
|
/* allocate an array with enough elements to hold all the keys. */
|
|
ary = apr_array_make(pool, apr_hash_count(ht), sizeof(svn_sort_item_type));
|
|
|
|
/* loop over hash table and push all keys into the array */
|
|
sorted = TRUE;
|
|
prev_item = NULL;
|
|
for (hi = apr_hash_first(pool, ht); hi; hi = apr_hash_next(hi))
|
|
{
|
|
svn_sort_item_type *item = (svn_sort_item_type*)apr_array_push(ary);
|
|
apr_hash_this(hi, &item->key, &item->klen, &item->value);
|
|
|
|
if (prev_item == NULL)
|
|
{
|
|
prev_item = item;
|
|
continue;
|
|
}
|
|
|
|
if (sorted)
|
|
{
|
|
sorted = (comparison_func((svn_sort__item_t*)prev_item, (svn_sort__item_t*)item) < 0);
|
|
prev_item = item;
|
|
}
|
|
}
|
|
|
|
/* quicksort the array if it isn't already sorted. */
|
|
if (!sorted)
|
|
{
|
|
qsort(ary->elts, ary->nelts, ary->elt_size,
|
|
(int (*)(const void*, const void*))comparison_func);
|
|
}
|
|
|
|
return ary;
|
|
}
|
|
#endif
|
|
|
|
tdeio_svnProtocol::tdeio_svnProtocol(const TQCString &pool_socket, const TQCString &app_socket)
|
|
: SlaveBase("tdeio_svn", pool_socket, app_socket) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::tdeio_svnProtocol()" << endl;
|
|
|
|
m_counter = 0;
|
|
|
|
apr_initialize();
|
|
// Make sure to properly initialize svn client, besides other things, this sets up
|
|
// NLS support for environments that don't use UTF-8
|
|
svn_cmdline_init("kdevsvnd",NULL);
|
|
// CleanUP ctx preventing crash in svn_client_update and other
|
|
memset(&ctx, 0, sizeof(ctx));
|
|
pool = svn_pool_create (NULL);
|
|
|
|
svn_error_t *err = svn_client_create_context(&ctx, pool);
|
|
if ( err ) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::tdeio_svnProtocol() create_context ERROR" << endl;
|
|
error( TDEIO::ERR_SLAVE_DEFINED, err->message );
|
|
return;
|
|
}
|
|
|
|
err = svn_config_ensure (NULL,pool);
|
|
if ( err ) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::tdeio_svnProtocol() configensure ERROR" << endl;
|
|
error( TDEIO::ERR_SLAVE_DEFINED, err->message );
|
|
return;
|
|
}
|
|
svn_config_get_config (&ctx->config, NULL, pool);
|
|
|
|
ctx->log_msg_func = tdeio_svnProtocol::commitLogPrompt;
|
|
ctx->log_msg_baton = this; //pass this so that we can get a dcopClient from it
|
|
//TODO
|
|
ctx->cancel_func = NULL;
|
|
// progress notifications
|
|
ctx->progress_func = tdeio_svnProtocol::progressCallback;
|
|
ctx->progress_baton = this;
|
|
|
|
apr_array_header_t *providers = apr_array_make(pool, 15, sizeof(svn_auth_provider_object_t *));
|
|
|
|
svn_auth_provider_object_t *provider;
|
|
|
|
//disk cache
|
|
svn_client_get_simple_provider(&provider,pool);
|
|
APR_ARRAY_PUSH(providers, svn_auth_provider_object_t*) = provider;
|
|
svn_client_get_username_provider(&provider,pool);
|
|
APR_ARRAY_PUSH(providers, svn_auth_provider_object_t*) = provider;
|
|
|
|
//interactive prompt
|
|
svn_client_get_simple_prompt_provider (&provider,tdeio_svnProtocol::checkAuth,this,2,pool);
|
|
APR_ARRAY_PUSH(providers, svn_auth_provider_object_t*) = provider;
|
|
//we always ask user+pass, no need for a user only question
|
|
/* svn_client_get_username_prompt_provider
|
|
* (&provider,tdeio_svnProtocol::checkAuth,this,2,pool);
|
|
APR_ARRAY_PUSH(providers, svn_auth_provider_object_t*) = provider;*/
|
|
|
|
//SSL disk cache, keep that one, because it does nothing bad :)
|
|
svn_client_get_ssl_server_trust_file_provider (&provider, pool);
|
|
APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider;
|
|
svn_client_get_ssl_client_cert_file_provider (&provider, pool);
|
|
APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider;
|
|
svn_client_get_ssl_client_cert_pw_file_provider (&provider, pool);
|
|
APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider;
|
|
|
|
//SSL interactive prompt, where things get hard
|
|
svn_client_get_ssl_server_trust_prompt_provider (&provider, tdeio_svnProtocol::trustSSLPrompt, (void*)this, pool);
|
|
APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider;
|
|
svn_client_get_ssl_client_cert_prompt_provider (&provider, tdeio_svnProtocol::clientCertSSLPrompt, (void*)this, 2, pool);
|
|
APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider;
|
|
svn_client_get_ssl_client_cert_pw_prompt_provider (&provider, tdeio_svnProtocol::clientCertPasswdPrompt, (void*)this, 2, pool);
|
|
APR_ARRAY_PUSH (providers, svn_auth_provider_object_t *) = provider;
|
|
|
|
svn_auth_open(&ctx->auth_baton, providers, pool);
|
|
}
|
|
|
|
tdeio_svnProtocol::~tdeio_svnProtocol(){
|
|
kdDebug(9036) << "tdeio_svnProtocol::~tdeio_svnProtocol()" << endl;
|
|
svn_pool_destroy(pool);
|
|
apr_terminate();
|
|
}
|
|
|
|
void tdeio_svnProtocol::initNotifier(bool is_checkout, bool is_export, bool suppress_final_line, apr_pool_t *spool) {
|
|
m_counter=0;//reset counter
|
|
ctx->notify_func = tdeio_svnProtocol::notify;
|
|
struct notify_baton *nb = ( struct notify_baton* )apr_palloc(spool, sizeof( struct notify_baton ) );
|
|
nb->master = this;
|
|
nb->received_some_change = FALSE;
|
|
nb->sent_first_txdelta = FALSE;
|
|
nb->is_checkout = is_checkout;
|
|
nb->is_export = is_export;
|
|
nb->suppress_final_line = suppress_final_line;
|
|
nb->in_external = FALSE;
|
|
nb->had_print_error = FALSE;
|
|
nb->pool = svn_pool_create (spool);
|
|
|
|
ctx->notify_baton = nb;
|
|
}
|
|
|
|
svn_error_t* tdeio_svnProtocol::checkAuth(svn_auth_cred_simple_t **cred, void *baton, const char *realm, const char *username, svn_boolean_t may_save, apr_pool_t *pool) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::checkAuth() " << endl;
|
|
tdeio_svnProtocol *p = ( tdeio_svnProtocol* )baton;
|
|
svn_auth_cred_simple_t *ret = (svn_auth_cred_simple_t*)apr_pcalloc (pool, sizeof (*ret));
|
|
|
|
p->info.keepPassword = true;
|
|
p->info.verifyPath=true;
|
|
kdDebug(9036 ) << "auth current URL : " << p->myURL.url() << endl;
|
|
p->info.url = p->myURL;
|
|
p->info.username = username; //( const char* )svn_auth_get_parameter( p->ctx->auth_baton, SVN_AUTH_PARAM_DEFAULT_USERNAME );
|
|
if (realm) {
|
|
p->info.prompt = i18n("Username and Password for %1.").arg(realm);
|
|
}
|
|
|
|
// if ( !p->checkCachedAuthentication( p->info ) ){
|
|
p->openPassDlg( p->info );
|
|
// }
|
|
ret->username = apr_pstrdup(pool, p->info.username.utf8());
|
|
ret->password = apr_pstrdup(pool, p->info.password.utf8());
|
|
if (may_save) ret->may_save = p->info.keepPassword;
|
|
*cred = ret;
|
|
return SVN_NO_ERROR;
|
|
}
|
|
|
|
void tdeio_svnProtocol::recordCurrentURL(const KURL& url) {
|
|
myURL = url;
|
|
}
|
|
|
|
//don't implement mimeType() until we don't need to download the whole file
|
|
|
|
void tdeio_svnProtocol::get(const KURL& url ){
|
|
kdDebug(9036) << "tdeio_svn::get(const KURL& url)" << endl ;
|
|
|
|
TQString remoteServer = url.host();
|
|
infoMessage(i18n("Looking for %1...").arg( remoteServer ) );
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
kbaton *bt = (kbaton*)apr_pcalloc(subpool, sizeof(*bt));
|
|
bt->target_string = svn_stringbuf_create("", subpool);
|
|
bt->string_stream = svn_stream_create(bt,subpool);
|
|
svn_stream_set_write(bt->string_stream,write_to_string);
|
|
|
|
TQString target = makeSvnURL( url );
|
|
kdDebug(9036) << "SvnURL: " << target << endl;
|
|
recordCurrentURL( KURL( target ) );
|
|
|
|
//find the requested revision
|
|
svn_opt_revision_t rev;
|
|
svn_opt_revision_t endrev;
|
|
int idx = target.findRev( "?rev=" );
|
|
if ( idx != -1 ) {
|
|
TQString revstr = target.mid( idx+5 );
|
|
#if 0
|
|
kdDebug(9036) << "revision string found " << revstr << endl;
|
|
if ( revstr == "HEAD" ) {
|
|
rev.kind = svn_opt_revision_head;
|
|
kdDebug(9036) << "revision searched : HEAD" << endl;
|
|
} else {
|
|
rev.kind = svn_opt_revision_number;
|
|
rev.value.number = revstr.toLong();
|
|
kdDebug(9036) << "revision searched : " << rev.value.number << endl;
|
|
}
|
|
#endif
|
|
svn_opt_parse_revision( &rev, &endrev, revstr.utf8(), subpool );
|
|
target = target.left( idx );
|
|
kdDebug(9036) << "new target : " << target << endl;
|
|
} else {
|
|
kdDebug(9036) << "no revision given. searching HEAD " << endl;
|
|
rev.kind = svn_opt_revision_head;
|
|
}
|
|
initNotifier(false, false, false, subpool);
|
|
|
|
svn_error_t *err = svn_client_cat (bt->string_stream, svn_path_canonicalize( target.utf8(),subpool ),&rev,ctx, subpool);
|
|
if ( err ) {
|
|
error( TDEIO::ERR_SLAVE_DEFINED, err->message );
|
|
svn_pool_destroy( subpool );
|
|
return;
|
|
}
|
|
|
|
// Send the mimeType as soon as it is known
|
|
TQByteArray *cp = new TQByteArray();
|
|
cp->setRawData( bt->target_string->data, bt->target_string->len );
|
|
KMimeType::Ptr mt = KMimeType::findByContent(*cp);
|
|
kdDebug(9036) << "KMimeType returned : " << mt->name() << endl;
|
|
mimeType( mt->name() );
|
|
|
|
totalSize(bt->target_string->len);
|
|
|
|
//send data
|
|
data(*cp);
|
|
|
|
data(TQByteArray()); // empty array means we're done sending the data
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::stat(const KURL & url){
|
|
kdDebug(9036) << "tdeio_svn::stat(const KURL& url) : " << url.url() << endl ;
|
|
|
|
void *ra_baton, *session;
|
|
svn_ra_plugin_t *ra_lib;
|
|
svn_node_kind_t kind;
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
|
|
TQString target = makeSvnURL( url);
|
|
kdDebug(9036) << "SvnURL: " << target << endl;
|
|
recordCurrentURL( KURL( target ) );
|
|
|
|
//find the requested revision
|
|
svn_opt_revision_t rev;
|
|
svn_opt_revision_t endrev;
|
|
int idx = target.findRev( "?rev=" );
|
|
if ( idx != -1 ) {
|
|
TQString revstr = target.mid( idx+5 );
|
|
#if 0
|
|
kdDebug(9036) << "revision string found " << revstr << endl;
|
|
if ( revstr == "HEAD" ) {
|
|
rev.kind = svn_opt_revision_head;
|
|
kdDebug(9036) << "revision searched : HEAD" << endl;
|
|
} else {
|
|
rev.kind = svn_opt_revision_number;
|
|
rev.value.number = revstr.toLong();
|
|
kdDebug(9036) << "revision searched : " << rev.value.number << endl;
|
|
}
|
|
#endif
|
|
svn_opt_parse_revision( &rev, &endrev, revstr.utf8( ), subpool );
|
|
target = target.left( idx );
|
|
kdDebug(9036) << "new target : " << target << endl;
|
|
} else {
|
|
kdDebug(9036) << "no revision given. searching HEAD " << endl;
|
|
rev.kind = svn_opt_revision_head;
|
|
}
|
|
|
|
//init
|
|
svn_error_t *err = svn_ra_init_ra_libs(&ra_baton,subpool);
|
|
if ( err ) {
|
|
kdDebug(9036) << "init RA libs failed : " << err->message << endl;
|
|
return;
|
|
}
|
|
//find RA libs
|
|
err = svn_ra_get_ra_library(&ra_lib,ra_baton,svn_path_canonicalize( target.utf8(), subpool ),subpool);
|
|
if ( err ) {
|
|
kdDebug(9036) << "RA get libs failed : " << err->message << endl;
|
|
return;
|
|
}
|
|
kdDebug(9036) << "RA init completed" << endl;
|
|
|
|
//start session
|
|
svn_ra_callbacks_t *cbtable = (svn_ra_callbacks_t*)apr_pcalloc(subpool, sizeof(*cbtable));
|
|
tdeio_svn_callback_baton_t *callbackbt = (tdeio_svn_callback_baton_t*)apr_pcalloc(subpool, sizeof( *callbackbt ));
|
|
|
|
cbtable->open_tmp_file = open_tmp_file;
|
|
cbtable->get_wc_prop = NULL;
|
|
cbtable->set_wc_prop = NULL;
|
|
cbtable->push_wc_prop = NULL;
|
|
cbtable->auth_baton = ctx->auth_baton;
|
|
|
|
callbackbt->base_dir = target.utf8();
|
|
callbackbt->pool = subpool;
|
|
callbackbt->config = ctx->config;
|
|
|
|
err = ra_lib->open(&session,svn_path_canonicalize( target.utf8(), subpool ),cbtable,callbackbt,ctx->config,subpool);
|
|
if ( err ) {
|
|
kdDebug(9036)<< "Open session " << err->message << endl;
|
|
return;
|
|
}
|
|
kdDebug(9036) << "Session opened to " << target << endl;
|
|
//find number for HEAD
|
|
if (rev.kind == svn_opt_revision_head) {
|
|
err = ra_lib->get_latest_revnum(session,&rev.value.number,subpool);
|
|
if ( err ) {
|
|
kdDebug(9036)<< "Latest RevNum " << err->message << endl;
|
|
return;
|
|
}
|
|
kdDebug(9036) << "Got rev " << rev.value.number << endl;
|
|
}
|
|
|
|
//get it
|
|
ra_lib->check_path(session,"",rev.value.number,&kind,subpool);
|
|
kdDebug(9036) << "Checked Path" << endl;
|
|
UDSEntry entry;
|
|
switch ( kind ) {
|
|
case svn_node_file:
|
|
kdDebug(9036) << "::stat result : file" << endl;
|
|
createUDSEntry(url.filename(),"",0,false,0,entry);
|
|
statEntry( entry );
|
|
break;
|
|
case svn_node_dir:
|
|
kdDebug(9036) << "::stat result : directory" << endl;
|
|
createUDSEntry(url.filename(),"",0,true,0,entry);
|
|
statEntry( entry );
|
|
break;
|
|
case svn_node_unknown:
|
|
case svn_node_none:
|
|
//error XXX
|
|
default:
|
|
kdDebug(9036) << "::stat result : UNKNOWN ==> WOW :)" << endl;
|
|
;
|
|
}
|
|
finished();
|
|
svn_pool_destroy( subpool );
|
|
}
|
|
|
|
void tdeio_svnProtocol::listDir(const KURL& url){
|
|
kdDebug(9036) << "tdeio_svn::listDir(const KURL& url) : " << url.url() << endl ;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
apr_hash_t *dirents;
|
|
|
|
TQString target = makeSvnURL( url);
|
|
kdDebug(9036) << "SvnURL: " << target << endl;
|
|
recordCurrentURL( KURL( target ) );
|
|
|
|
//find the requested revision
|
|
svn_opt_revision_t rev;
|
|
svn_opt_revision_t endrev;
|
|
int idx = target.findRev( "?rev=" );
|
|
if ( idx != -1 ) {
|
|
TQString revstr = target.mid( idx+5 );
|
|
svn_opt_parse_revision( &rev, &endrev, revstr.utf8(), subpool );
|
|
#if 0
|
|
kdDebug(9036) << "revision string found " << revstr << endl;
|
|
if ( revstr == "HEAD" ) {
|
|
rev.kind = svn_opt_revision_head;
|
|
kdDebug(9036) << "revision searched : HEAD" << endl;
|
|
} else {
|
|
rev.kind = svn_opt_revision_number;
|
|
rev.value.number = revstr.toLong();
|
|
kdDebug(9036) << "revision searched : " << rev.value.number << endl;
|
|
}
|
|
#endif
|
|
target = target.left( idx );
|
|
kdDebug(9036) << "new target : " << target << endl;
|
|
} else {
|
|
kdDebug(9036) << "no revision given. searching HEAD " << endl;
|
|
rev.kind = svn_opt_revision_head;
|
|
}
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
svn_error_t *err = svn_client_ls (&dirents, svn_path_canonicalize( target.utf8(), subpool ), &rev, false, ctx, subpool);
|
|
if ( err ) {
|
|
error( TDEIO::ERR_SLAVE_DEFINED, err->message );
|
|
svn_pool_destroy( subpool );
|
|
return;
|
|
}
|
|
|
|
apr_array_header_t *array;
|
|
int i;
|
|
|
|
array = svn_sort__hash (dirents, svn_sort_compare_items_as_paths, subpool);
|
|
|
|
UDSEntry entry;
|
|
for (i = 0; i < array->nelts; ++i) {
|
|
entry.clear();
|
|
const char *utf8_entryname, *native_entryname;
|
|
svn_dirent_t *dirent;
|
|
svn_sort_item_type *item;
|
|
|
|
item = &APR_ARRAY_IDX (array, i, svn_sort_item_type);
|
|
|
|
utf8_entryname = (const char*)item->key;
|
|
|
|
dirent = (svn_dirent_t*)apr_hash_get (dirents, utf8_entryname, item->klen);
|
|
|
|
svn_utf_cstring_from_utf8 (&native_entryname, utf8_entryname, subpool);
|
|
const char *native_author = NULL;
|
|
|
|
//XXX BUGGY
|
|
/* apr_time_exp_t timexp;
|
|
apr_time_exp_lt(&timexp, dirent->time);
|
|
apr_os_exp_time_t *ostime;
|
|
apr_os_exp_time_get( &ostime, &timexp);
|
|
|
|
time_t mtime = mktime( ostime );*/
|
|
|
|
if (dirent->last_author)
|
|
svn_utf_cstring_from_utf8 (&native_author, dirent->last_author, subpool);
|
|
|
|
if ( createUDSEntry(TQString( native_entryname ), TQString( native_author ), dirent->size,
|
|
dirent->kind==svn_node_dir ? true : false, 0, entry) )
|
|
listEntry( entry, false );
|
|
}
|
|
listEntry( entry, true );
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
bool tdeio_svnProtocol::createUDSEntry( const TQString& filename, const TQString& user, long long int size, bool isdir, time_t mtime, UDSEntry& entry) {
|
|
kdDebug(9036) << "MTime : " << ( long )mtime << endl;
|
|
kdDebug(9036) << "UDS filename : " << filename << endl;
|
|
UDSAtom atom;
|
|
atom.m_uds = TDEIO::UDS_NAME;
|
|
atom.m_str = filename;
|
|
entry.append( atom );
|
|
|
|
atom.m_uds = TDEIO::UDS_FILE_TYPE;
|
|
atom.m_long = isdir ? S_IFDIR : S_IFREG;
|
|
entry.append( atom );
|
|
|
|
atom.m_uds = TDEIO::UDS_SIZE;
|
|
atom.m_long = size;
|
|
entry.append( atom );
|
|
|
|
atom.m_uds = TDEIO::UDS_MODIFICATION_TIME;
|
|
atom.m_long = mtime;
|
|
entry.append( atom );
|
|
|
|
atom.m_uds = TDEIO::UDS_USER;
|
|
atom.m_str = user;
|
|
entry.append( atom );
|
|
|
|
return true;
|
|
}
|
|
|
|
// not used, at least for KDevelop
|
|
// void tdeio_svnProtocol::copy(const KURL & src, const KURL& dest, int /*permissions*/, bool /*overwrite*/) {
|
|
// kdDebug(9036) << "tdeio_svnProtocol::copy() Source : " << src.url() << " Dest : " << dest.url() << endl;
|
|
//
|
|
// apr_pool_t *subpool = svn_pool_create (pool);
|
|
// svn_client_commit_info_t *commit_info = NULL;
|
|
//
|
|
// KURL nsrc = src;
|
|
// KURL ndest = dest;
|
|
// nsrc.setProtocol( chooseProtocol( src.protocol() ) );
|
|
// ndest.setProtocol( chooseProtocol( dest.protocol() ) );
|
|
// TQString srcsvn = nsrc.url();
|
|
// TQString destsvn = ndest.url();
|
|
//
|
|
// recordCurrentURL( nsrc );
|
|
//
|
|
// //find the requested revision
|
|
// svn_opt_revision_t rev;
|
|
// int idx = srcsvn.findRev( "?rev=" );
|
|
// if ( idx != -1 ) {
|
|
// TQString revstr = srcsvn.mid( idx+5 );
|
|
// kdDebug(9036) << "revision string found " << revstr << endl;
|
|
// if ( revstr == "HEAD" ) {
|
|
// rev.kind = svn_opt_revision_head;
|
|
// kdDebug(9036) << "revision searched : HEAD" << endl;
|
|
// } else {
|
|
// rev.kind = svn_opt_revision_number;
|
|
// rev.value.number = revstr.toLong();
|
|
// kdDebug(9036) << "revision searched : " << rev.value.number << endl;
|
|
// }
|
|
// srcsvn = srcsvn.left( idx );
|
|
// kdDebug(9036) << "new src : " << srcsvn << endl;
|
|
// } else {
|
|
// kdDebug(9036) << "no revision given. searching HEAD " << endl;
|
|
// rev.kind = svn_opt_revision_head;
|
|
// }
|
|
//
|
|
// initNotifier(false, false, false, subpool);
|
|
// svn_error_t *err = svn_client_copy(&commit_info, srcsvn.utf8(), &rev, destsvn.utf8(), ctx, subpool);
|
|
// if ( err ) {
|
|
// error( TDEIO::ERR_SLAVE_DEFINED, err->message );
|
|
// svn_pool_destroy (subpool);
|
|
// }
|
|
//
|
|
// finished();
|
|
// svn_pool_destroy (subpool);
|
|
// }
|
|
|
|
void tdeio_svnProtocol::mkdir( const KURL::List& list, int /*permissions*/ ) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::mkdir(LIST) : " << list << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
svn_client_commit_info_t *commit_info = NULL;
|
|
|
|
recordCurrentURL( list[ 0 ] );
|
|
|
|
apr_array_header_t *targets = apr_array_make(subpool, list.count()+1, sizeof(const char *));
|
|
|
|
KURL::List::const_iterator it = list.begin(), end = list.end();
|
|
for ( ; it != end; ++it ) {
|
|
TQString cur = makeSvnURL( *it );
|
|
kdDebug( 9036 ) << "tdeio_svnProtocol::mkdir raw url for subversion : " << cur << endl;
|
|
const char *_target = apr_pstrdup( subpool, svn_path_canonicalize( apr_pstrdup( subpool, cur.utf8() ), subpool ) );
|
|
(*(( const char ** )apr_array_push(( apr_array_header_t* )targets)) ) = _target;
|
|
}
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
svn_error_t *err = svn_client_mkdir(&commit_info,targets,ctx,subpool);
|
|
if ( err ) {
|
|
error( TDEIO::ERR_COULD_NOT_MKDIR, TQString::fromLocal8Bit(err->message) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::mkdir( const KURL& url, int /*permissions*/ ) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::mkdir() : " << url.url() << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
svn_client_commit_info_t *commit_info = NULL;
|
|
|
|
TQString target = makeSvnURL( url);
|
|
kdDebug(9036) << "SvnURL: " << target << endl;
|
|
recordCurrentURL( KURL( target ) );
|
|
|
|
apr_array_header_t *targets = apr_array_make(subpool, 2, sizeof(const char *));
|
|
(*(( const char ** )apr_array_push(( apr_array_header_t* )targets)) ) = apr_pstrdup( subpool, target.utf8() );
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
svn_error_t *err = svn_client_mkdir(&commit_info,targets,ctx,subpool);
|
|
if ( err ) {
|
|
error( TDEIO::ERR_COULD_NOT_MKDIR, err->message );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::del( const KURL& url, bool /*isfile*/ ) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::del() : " << url.url() << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
svn_client_commit_info_t *commit_info = NULL;
|
|
|
|
TQString target = makeSvnURL(url);
|
|
kdDebug(9036) << "SvnURL: " << target << endl;
|
|
recordCurrentURL( KURL( target ) );
|
|
|
|
apr_array_header_t *targets = apr_array_make(subpool, 2, sizeof(const char *));
|
|
(*(( const char ** )apr_array_push(( apr_array_header_t* )targets)) ) = apr_pstrdup( subpool, target.utf8() );
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
svn_error_t *err = svn_client_delete(&commit_info,targets,false/*force remove locally modified files in wc*/,ctx,subpool);
|
|
if ( err ) {
|
|
error( TDEIO::ERR_CANNOT_DELETE, err->message );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::rename(const KURL& src, const KURL& dest, bool /*overwrite*/) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::rename() Source : " << src.url() << " Dest : " << dest.url() << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
svn_client_commit_info_t *commit_info = NULL;
|
|
|
|
KURL nsrc = src;
|
|
KURL ndest = dest;
|
|
nsrc.setProtocol( chooseProtocol( src.protocol() ) );
|
|
ndest.setProtocol( chooseProtocol( dest.protocol() ) );
|
|
TQString srcsvn = nsrc.url();
|
|
TQString destsvn = ndest.url();
|
|
|
|
recordCurrentURL( nsrc );
|
|
|
|
//find the requested revision
|
|
svn_opt_revision_t rev;
|
|
int idx = srcsvn.findRev( "?rev=" );
|
|
if ( idx != -1 ) {
|
|
TQString revstr = srcsvn.mid( idx+5 );
|
|
kdDebug(9036) << "revision string found " << revstr << endl;
|
|
if ( revstr == "HEAD" ) {
|
|
rev.kind = svn_opt_revision_head;
|
|
kdDebug(9036) << "revision searched : HEAD" << endl;
|
|
} else {
|
|
rev.kind = svn_opt_revision_number;
|
|
rev.value.number = revstr.toLong();
|
|
kdDebug(9036) << "revision searched : " << rev.value.number << endl;
|
|
}
|
|
srcsvn = srcsvn.left( idx );
|
|
kdDebug(9036) << "new src : " << srcsvn << endl;
|
|
} else {
|
|
kdDebug(9036) << "no revision given. searching HEAD " << endl;
|
|
rev.kind = svn_opt_revision_head;
|
|
}
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
svn_error_t *err = svn_client_move(&commit_info, srcsvn.utf8(), &rev, destsvn.utf8(), false/*force remove locally modified files in wc*/, ctx, subpool);
|
|
if ( err ) {
|
|
error( TDEIO::ERR_CANNOT_RENAME, err->message );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::special( const TQByteArray& data ) {
|
|
// kdDebug(9036) << "tdeio_svnProtocol::special" << endl;
|
|
|
|
TQDataStream stream(data, IO_ReadOnly);
|
|
int tmp;
|
|
|
|
stream >> tmp;
|
|
kdDebug(9036) << "tdeio_svnProtocol::special " << tmp << endl;
|
|
|
|
switch ( tmp ) {
|
|
case SVN_CHECKOUT:
|
|
{
|
|
KURL repository, wc;
|
|
int revnumber;
|
|
TQString revkind;
|
|
stream >> repository;
|
|
stream >> wc;
|
|
stream >> revnumber;
|
|
stream >> revkind;
|
|
kdDebug(9036) << "tdeio_svnProtocol CHECKOUT from " << repository.url() << " to " << wc.url() << " at " << revnumber << " or " << revkind << endl;
|
|
checkout( repository, wc, revnumber, revkind );
|
|
break;
|
|
}
|
|
case SVN_UPDATE:
|
|
{
|
|
KURL::List list;
|
|
int revnumber;
|
|
TQString revkind;
|
|
stream >> list;
|
|
stream >> revnumber;
|
|
stream >> revkind;
|
|
kdDebug(9036) << "tdeio_svnProtocol UPDATE " << endl;
|
|
update( list, revnumber, revkind );
|
|
break;
|
|
}
|
|
case SVN_COMMIT:
|
|
{
|
|
KURL::List wclist;
|
|
while ( !stream.atEnd() ) {
|
|
KURL tmp;
|
|
stream >> tmp;
|
|
wclist << tmp;
|
|
}
|
|
kdDebug(9036) << "tdeio_svnProtocol COMMIT" << endl;
|
|
commit( wclist );
|
|
break;
|
|
}
|
|
case SVN_COMMIT_2:
|
|
{
|
|
bool recurse, keeplocks;
|
|
KURL::List wclist;
|
|
stream >> recurse;
|
|
stream >> keeplocks;
|
|
while ( !stream.atEnd() ) {
|
|
KURL tmp;
|
|
stream >> tmp;
|
|
wclist << tmp;
|
|
}
|
|
kdDebug(9036) << "tdeio_svnProtocol COMMIT2" << endl;
|
|
commit2( recurse, keeplocks, wclist );
|
|
break;
|
|
}
|
|
case SVN_LOG:
|
|
{
|
|
kdDebug(9036) << "tdeio_svnProtocol LOG" << endl;
|
|
int revstart, revend;
|
|
TQString revkindstart, revkindend;
|
|
bool discorverChangedPath, strictNodeHistory;
|
|
KURL::List targets;
|
|
|
|
stream >> revstart;
|
|
stream >> revkindstart;
|
|
stream >> revend;
|
|
stream >> revkindend;
|
|
stream >> discorverChangedPath;
|
|
stream >> strictNodeHistory;
|
|
while ( !stream.atEnd() ) {
|
|
KURL tmp;
|
|
stream >> tmp;
|
|
targets << tmp;
|
|
}
|
|
svn_log( revstart, revkindstart, revend, revkindend,
|
|
discorverChangedPath, strictNodeHistory, targets );
|
|
break;
|
|
}
|
|
case SVN_IMPORT:
|
|
{
|
|
KURL wc,repos;
|
|
stream >> repos;
|
|
stream >> wc;
|
|
kdDebug(9036) << "tdeio_svnProtocol IMPORT" << endl;
|
|
import(repos,wc);
|
|
break;
|
|
}
|
|
case SVN_ADD:
|
|
{
|
|
KURL::List wcList;
|
|
stream >> wcList;
|
|
kdDebug(9036) << "tdeio_svnProtocol ADD" << endl;
|
|
add(wcList);
|
|
break;
|
|
}
|
|
case SVN_DEL:
|
|
{
|
|
KURL::List wclist;
|
|
stream >> wclist;
|
|
kdDebug(9036) << "tdeio_svnProtocol DEL" << endl;
|
|
wc_delete(wclist);
|
|
break;
|
|
}
|
|
case SVN_REVERT:
|
|
{
|
|
KURL::List wclist;
|
|
stream >> wclist;
|
|
kdDebug(9036) << "tdeio_svnProtocol REVERT" << endl;
|
|
wc_revert(wclist);
|
|
break;
|
|
}
|
|
case SVN_STATUS:
|
|
{
|
|
KURL wc;
|
|
bool checkRepos=false;
|
|
bool fullRecurse=false;
|
|
stream >> wc;
|
|
stream >> checkRepos;
|
|
stream >> fullRecurse;
|
|
wc_status(wc,checkRepos,fullRecurse);
|
|
break;
|
|
}
|
|
case SVN_STATUS_2:
|
|
{
|
|
KURL wc;
|
|
TQString revkind;
|
|
int revnumber;
|
|
bool checkRepos, fullRecurse, getAll, noIgnore;
|
|
stream >> checkRepos;
|
|
stream >> fullRecurse;
|
|
stream >> getAll;
|
|
stream >> noIgnore;
|
|
stream >> revnumber;
|
|
stream >> revkind;
|
|
stream >> wc;
|
|
wc_status2(wc,checkRepos,fullRecurse, getAll, noIgnore, revnumber, revkind);
|
|
break;
|
|
}
|
|
case SVN_MKDIR:
|
|
{
|
|
KURL::List list;
|
|
stream >> list;
|
|
kdDebug(9036) << "tdeio_svnProtocol MKDIR" << endl;
|
|
mkdir(list,0);
|
|
break;
|
|
}
|
|
case SVN_RESOLVE:
|
|
{
|
|
KURL url;
|
|
bool recurse;
|
|
stream >> url;
|
|
stream >> recurse;
|
|
kdDebug(9036) << "tdeio_svnProtocol RESOLVE" << endl;
|
|
wc_resolve(url,recurse);
|
|
break;
|
|
}
|
|
case SVN_SWITCH:
|
|
{
|
|
KURL wc,url;
|
|
bool recurse;
|
|
int revnumber;
|
|
TQString revkind;
|
|
stream >> wc;
|
|
stream >> url;
|
|
stream >> recurse;
|
|
stream >> revnumber;
|
|
stream >> revkind;
|
|
kdDebug(9036) << "tdeio_svnProtocol SWITCH" << endl;
|
|
svn_switch(wc,url,revnumber,revkind,recurse);
|
|
break;
|
|
}
|
|
case SVN_SWITCH_RELOCATE:
|
|
{
|
|
KURL wc, origUrl, newUrl;
|
|
bool recurse;
|
|
stream >> wc;
|
|
stream >> origUrl;
|
|
stream >> newUrl;
|
|
stream >> recurse;
|
|
svn_switch_relocate( wc, origUrl, newUrl, recurse );
|
|
break;
|
|
}
|
|
case SVN_DIFF:
|
|
{
|
|
KURL url1,url2;
|
|
int rev1, rev2;
|
|
bool recurse, pegdiff;
|
|
TQString revkind1, revkind2;
|
|
stream >> url1;
|
|
stream >> url2;
|
|
stream >> rev1;
|
|
stream >> revkind1;
|
|
stream >> rev2;
|
|
stream >> revkind2;
|
|
stream >> recurse >> pegdiff;
|
|
kdDebug(9036) << "tdeio_svnProtocol DIFF" << endl;
|
|
svn_diff(url1,url2,rev1,rev2,revkind1,revkind2,recurse,pegdiff);
|
|
break;
|
|
}
|
|
case SVN_BLAME:
|
|
{
|
|
KURL url;
|
|
int urlMode;
|
|
int pegRev, startRev, endRev;
|
|
TQString pegRevKind, startRevKind, endRevKind;
|
|
stream >> url;
|
|
stream >> urlMode;
|
|
// stream >> pegRev;
|
|
// stream >> pegRevKind;
|
|
stream >> startRev;
|
|
stream >> startRevKind;
|
|
stream >> endRev;
|
|
stream >> endRevKind;
|
|
|
|
blame(url, (UrlMode)urlMode, startRev, startRevKind, endRev, endRevKind);
|
|
break;
|
|
}
|
|
case SVN_INFO:
|
|
{
|
|
KURL pathOrUrl;
|
|
int pegRev, rev;
|
|
TQString pegRevKind, revKind;
|
|
bool recurse = false;
|
|
stream >> pathOrUrl;
|
|
stream >> pegRev;
|
|
stream >> pegRevKind;
|
|
stream >> rev;
|
|
stream >> revKind;
|
|
stream >> recurse;
|
|
svn_info( pathOrUrl, pegRev, pegRevKind, rev, revKind, recurse );
|
|
break;
|
|
}
|
|
case SVN_COPY:
|
|
{
|
|
KURL src, dest;
|
|
int srcRev;
|
|
TQString srcRevKind;
|
|
stream >> src;
|
|
stream >> srcRev;
|
|
stream >> srcRevKind;
|
|
stream >> dest;
|
|
svn_copy( src, srcRev, srcRevKind, dest );
|
|
break;
|
|
}
|
|
case SVN_MERGE:
|
|
{
|
|
KURL src1, src2, wc_target;
|
|
int rev1, rev2;
|
|
TQString revKind1, revKind2;
|
|
bool recurse, ignore_ancestry, force, dry_run;
|
|
stream >> src1 >> rev1 >> revKind1;
|
|
stream >> src2 >> rev2 >> revKind2;
|
|
stream >> wc_target;
|
|
stream >> recurse >> ignore_ancestry >> force >> dry_run;
|
|
svn_merge( src1, rev1, revKind1, src2, rev2, revKind2, wc_target,
|
|
recurse, ignore_ancestry, force, dry_run );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
kdDebug(9036) << "tdeio_svnProtocol DEFAULT" << endl;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* not used anywhere, anymore
|
|
*/
|
|
void tdeio_svnProtocol::popupMessage( const TQString& message ) {
|
|
// TQByteArray params;
|
|
// TQDataStream stream(params, IO_WriteOnly);
|
|
// stream << message;
|
|
//
|
|
// if ( !dcopClient()->send( "kded","ksvnd","popupMessage(TQString)", params ) )
|
|
// kdWarning() << "Communication with KDED:KSvnd failed" << endl;
|
|
}
|
|
|
|
void tdeio_svnProtocol::blame( KURL url, UrlMode /*mode*/,/* int pegRev, TQString pegRevKind,*/ int startRev, TQString startRevKind, int endRev, TQString endRevKind )
|
|
{
|
|
kdDebug(9036) << " __TIME__ " << __TIME__ << endl;
|
|
// kdDebug(9036) << " PegRev " << pegRev << pegRevKind << endl;
|
|
kdDebug(9036) << " StartRev" << startRev << startRevKind << endl;
|
|
kdDebug(9036) << " EndRev" << endRev << endRevKind << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
const char* path_or_url = apr_pstrdup( subpool, url.pathOrURL().utf8() );;
|
|
|
|
svn_opt_revision_t rev1 = createRevision( startRev, startRevKind, subpool );
|
|
svn_opt_revision_t rev2 = createRevision( endRev, endRevKind, subpool );
|
|
// svn_opt_revision_t revPeg = createRevision( pegRev, pegRevKind, subpool );
|
|
|
|
//initNotifier(false, false, false, subpool);
|
|
svn_client_blame_receiver_t receiver = tdeio_svnProtocol::blameReceiver;
|
|
svn_error_t *err = svn_client_blame( path_or_url, &rev1, &rev2, receiver, (void*)this, ctx, subpool );
|
|
if ( err )
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit(err->message) );
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
|
|
}
|
|
|
|
svn_error_t* tdeio_svnProtocol::blameReceiver( void *baton, apr_int64_t line_no, svn_revnum_t rev, const char *author, const char *date, const char *line, apr_pool_t *pool )
|
|
{
|
|
tdeio_svnProtocol *p = (tdeio_svnProtocol*)baton;
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "LINE", TQString::number(line_no) );
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "REV", TQString::number(rev) );
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "AUTHOR", author );
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "DATE", date );
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "CONTENT", TQString::fromLocal8Bit(line) );
|
|
|
|
p->incCounter();
|
|
return SVN_NO_ERROR;
|
|
}
|
|
|
|
/**
|
|
KDevelop has no way to retrieve URL of working copy.
|
|
Thus retreiving URL from WC should be done here, using subversion native API.
|
|
Thus, svn_log should get another flag (bool repositHistory )specifying between file:/// or URL
|
|
*/
|
|
void tdeio_svnProtocol::svn_log( int revstart, const TQString& revkindstart, int revend, const TQString& revkindend,
|
|
bool discorverChangedPaths, bool strictNodeHistory,
|
|
const KURL::List& urls )
|
|
{
|
|
// kdDebug(9036) << " from revision " << revstart << " or " << revkindstart << " to " << " revision " << revend << " or " << revkindend << endl;
|
|
kdDebug(9036) << " __TIME__ " << __TIME__ << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
|
|
// TODO HEAD:1 was removed from SVN API 1.2, instead callers should specify HEAD:0
|
|
svn_opt_revision_t rev1 = createRevision( revstart, revkindstart, subpool );
|
|
svn_opt_revision_t rev2 = createRevision( revend, revkindend, subpool );
|
|
|
|
m_counter = 0;
|
|
apr_array_header_t *targets = apr_array_make(subpool, 1+urls.count(), sizeof(const char *));
|
|
|
|
for ( TQValueListConstIterator<KURL> it = urls.begin(); it != urls.end() ; ++it ) {
|
|
KURL nurl = *it;
|
|
const char *path =
|
|
apr_pstrdup( subpool, svn_path_canonicalize( nurl.pathOrURL().utf8(), subpool ) );
|
|
kdDebug(9036) << path << endl;
|
|
*(( const char ** )apr_array_push(( apr_array_header_t* )targets)) = path;
|
|
|
|
setMetaData(TQString::number( counter() ).rightJustify( 10,'0' )+ "requrl", nurl.pathOrURL() );
|
|
incCounter();
|
|
}
|
|
|
|
svn_log_message_receiver_t receiver = tdeio_svnProtocol::receiveLogMessage;
|
|
svn_error_t *err = svn_client_log2(targets, &rev1, &rev2, 0, discorverChangedPaths, strictNodeHistory, receiver, this, ctx, subpool);
|
|
if ( err ){
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit(err->message) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
// save for one revision
|
|
svn_error_t* tdeio_svnProtocol::receiveLogMessage(void *baton, apr_hash_t *changed_paths, svn_revnum_t revision,
|
|
const char *author, const char *date, const char *message, apr_pool_t *pool )
|
|
{
|
|
tdeio_svnProtocol *p = (tdeio_svnProtocol*)baton;
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "rev", TQString::number(revision) );
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "author", author );
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "date", date );
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "logmsg", TQString::fromLocal8Bit(message) );
|
|
if( changed_paths != NULL ){
|
|
TQString pathlist;
|
|
void *onePath;
|
|
const char *pathkey;
|
|
apr_hash_index_t *hi;
|
|
for (hi = apr_hash_first(pool, changed_paths); hi; hi = apr_hash_next(hi)) {
|
|
apr_hash_this(hi, (const void**) &pathkey, NULL, &onePath);
|
|
svn_log_changed_path_t *cp = (svn_log_changed_path_t*)onePath;
|
|
kdDebug(9036) << "OnePath: " << cp->copyfrom_path << " and key: " << pathkey << endl;
|
|
pathlist += cp->action;
|
|
pathlist += " ";
|
|
// pathlist += cp->copyfrom_path;
|
|
pathlist += pathkey;
|
|
pathlist += "\n";
|
|
}
|
|
kdDebug(9036) << "pathlist: " << pathlist <<endl;
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "pathlist", pathlist );
|
|
}
|
|
p->incCounter();
|
|
return SVN_NO_ERROR;
|
|
}
|
|
|
|
svn_opt_revision_t tdeio_svnProtocol::createRevision( int revision, const TQString& revkind, apr_pool_t *pool ) {
|
|
svn_opt_revision_t result;//,endrev;
|
|
// TODO support svn_opt_revision_date
|
|
if ( revision != -1 ) {
|
|
result.value.number = revision;
|
|
result.kind = svn_opt_revision_number;
|
|
} else if ( revkind == "WORKING" ) {
|
|
result.kind = svn_opt_revision_working;
|
|
} else if ( revkind == "BASE" ) {
|
|
result.kind = svn_opt_revision_base;
|
|
} else if ( revkind == "HEAD" ) {
|
|
result.kind = svn_opt_revision_head;
|
|
} else if ( revkind == "COMMITTED" ) {
|
|
result.kind = svn_opt_revision_committed;
|
|
} else if ( revkind == "PREV" ) {
|
|
result.kind = svn_opt_revision_previous;
|
|
}
|
|
// } else if ( !revkind.isNull() ) {
|
|
// svn_opt_parse_revision(&result,&endrev,revkind.utf8(),pool);
|
|
else if ( revkind == "UNSPECIFIED" ){
|
|
result.kind = svn_opt_revision_unspecified;
|
|
}
|
|
else {
|
|
result.kind = svn_opt_revision_unspecified;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void tdeio_svnProtocol::svn_diff(const KURL & url1, const KURL& url2,int rev1, int rev2,const TQString& revkind1,const TQString& revkind2,bool recurse, bool pegdiff )
|
|
{
|
|
kdDebug(9036) << "tdeio_svn::diff : " << url1.path() << " at revision " << rev1 << " or " << revkind1 << " with "
|
|
<< url2.path() << " at revision " << rev2 << " or " << revkind2
|
|
<< endl ;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
apr_array_header_t *options = svn_cstring_split( "", "\t\r\n", TRUE, subpool );
|
|
|
|
// KURL nurl1 = url1;
|
|
// KURL nurl2 = url2;
|
|
// nurl1.setProtocol( chooseProtocol( url1.protocol() ) ); //svn+https -> https for eg
|
|
// nurl2.setProtocol( chooseProtocol( url2.protocol() ) );
|
|
// recordCurrentURL( nurl1 );
|
|
// TQString source = makeSvnURL( nurl1 );
|
|
// TQString target = makeSvnURL( nurl2 );
|
|
|
|
// const char *path1 = svn_path_canonicalize( apr_pstrdup( subpool, source.utf8() ), subpool );
|
|
// const char *path2 = svn_path_canonicalize( apr_pstrdup( subpool, target.utf8() ), subpool );
|
|
|
|
//remove file:/// so we can diff for working copies, needs a better check (so we support URL for file:/// _repositories_ )
|
|
// if ( nurl1.protocol() == "file" ) {
|
|
// path1 = svn_path_canonicalize( apr_pstrdup( subpool, nurl1.path().utf8() ), subpool );
|
|
// }
|
|
// if ( nurl2.protocol() == "file" ) {
|
|
// path2 = svn_path_canonicalize( apr_pstrdup( subpool, nurl2.path().utf8() ), subpool );
|
|
// }
|
|
|
|
// all the commentted codes above are redundancy. url1/url2 is only file:// , svn:// or https://
|
|
// svn+https etc. are not handed out here.
|
|
const char *path1 = apr_pstrdup( subpool, url1.pathOrURL().utf8() );
|
|
const char *path2 = apr_pstrdup( subpool, url2.pathOrURL().utf8() );;
|
|
|
|
kdDebug( 9036 ) << "1 : " << path1 << " 2: " << path2 << endl;
|
|
|
|
svn_opt_revision_t revision1,revision2;
|
|
revision1 = createRevision(rev1, revkind1, subpool);
|
|
revision2 = createRevision(rev2, revkind2, subpool);
|
|
|
|
char *templ;
|
|
templ = apr_pstrdup ( subpool, "/tmp/tmpfile_XXXXXX" );
|
|
apr_file_t *outfile = NULL;
|
|
apr_file_mktemp( &outfile, templ , APR_READ|APR_WRITE|APR_CREATE|APR_TRUNCATE, subpool );
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
svn_error_t *err = 0;
|
|
if( pegdiff ){
|
|
svn_opt_revision_t peg_rev = createRevision(-1, "BASE", subpool );
|
|
err = svn_client_diff_peg( options, path1, &peg_rev, &revision1, &revision2,
|
|
recurse, false, false, outfile, NULL, ctx, subpool );
|
|
} else{
|
|
err = svn_client_diff( options, path1, &revision1, path2, &revision2, recurse,
|
|
false, false, outfile, NULL, ctx, subpool );
|
|
}
|
|
|
|
if ( err ){
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit(err->message) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
//read the content of the outfile now
|
|
TQStringList tmp;
|
|
apr_file_close(outfile);
|
|
TQFile file(templ);
|
|
if ( file.open( IO_ReadOnly ) ) {
|
|
TQTextStream stream( &file );
|
|
TQString line;
|
|
while ( !stream.atEnd() ) {
|
|
line = stream.readLine();
|
|
tmp << line;
|
|
}
|
|
file.close();
|
|
}
|
|
for ( TQStringList::Iterator itt = tmp.begin(); itt != tmp.end(); itt++ ) {
|
|
setMetaData(TQString::number( m_counter ).rightJustify( 10,'0' )+ "diffresult", ( *itt ) );
|
|
m_counter++;
|
|
}
|
|
//delete temp file
|
|
file.remove();
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::svn_switch( const KURL& wc, const KURL& repos, int revnumber, const TQString& revkind, bool recurse) {
|
|
kdDebug(9036) << "tdeio_svn::switch : " << wc.path() << " at revision " << revnumber << " or " << revkind << endl ;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
|
|
KURL nurl = repos;
|
|
KURL dest = wc;
|
|
nurl.setProtocol( chooseProtocol( repos.protocol() ) );
|
|
dest.setProtocol( "file" );
|
|
// recordCurrentURL( nurl );
|
|
// TQString source = dest.path();
|
|
// TQString target = makeSvnURL( repos );
|
|
|
|
const char *path = svn_path_canonicalize( apr_pstrdup( subpool, dest.path().utf8() ), subpool );
|
|
const char *url = svn_path_canonicalize( apr_pstrdup( subpool, nurl.url().utf8() ), subpool );
|
|
kdDebug(9036) << " WC path: " << path << " Repository URL: " << url << endl;
|
|
|
|
svn_opt_revision_t rev = createRevision( revnumber, revkind, subpool );
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
svn_error_t *err = svn_client_switch (NULL/*result revision*/, path, url, &rev, recurse, ctx, subpool);
|
|
if ( err ){
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit( err->message ) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::svn_switch_relocate( const KURL &wc, const KURL &origUrl, const KURL &newUrl,
|
|
bool recurse )
|
|
{
|
|
apr_pool_t *subpool = svn_pool_create( pool );
|
|
|
|
const char *wcPath = svn_path_canonicalize( apr_pstrdup( subpool, wc.path().utf8() ), subpool );
|
|
const char *fromUrl = apr_pstrdup( subpool, origUrl.url().utf8() );
|
|
const char *toUrl = apr_pstrdup( subpool, newUrl.url().utf8() );
|
|
kdDebug(9036) << " WC path: " << wcPath << " from: " << fromUrl << " to: " << toUrl << endl;
|
|
|
|
svn_error_t *err = svn_client_relocate( wcPath, fromUrl, toUrl, recurse, ctx, pool );
|
|
|
|
if ( err ){
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit( err->message ) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
m_counter = 0L;
|
|
setMetaData(TQString::number( counter() ).rightJustify( 10,'0' )+ "string",
|
|
TQString("switched to %1").arg( toUrl ) );
|
|
finished();
|
|
svn_pool_destroy( subpool );
|
|
}
|
|
|
|
void tdeio_svnProtocol::update( const KURL::List &list, int revnumber, const TQString& revkind ) {
|
|
kdDebug(9036) << "tdeio_svn::update : __TIME__" << __TIME__ << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
|
|
apr_array_header_t *targets = apr_array_make(subpool, 1+list.count(), sizeof(const char *));
|
|
svn_opt_revision_t rev = createRevision( revnumber, revkind, subpool );
|
|
|
|
for( TQValueList<KURL>::ConstIterator it = list.begin(); it != list.end(); ++it ){
|
|
KURL nurl = *it;
|
|
*( const char ** )apr_array_push(targets) = svn_path_canonicalize( nurl.path().utf8(), subpool );
|
|
}
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
svn_error_t *err = svn_client_update2( NULL, targets, &rev,
|
|
true/*recurse*/, false/*ignore_external*/,
|
|
ctx, subpool);
|
|
if ( err ){
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit(err->message) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::import( const KURL& repos, const KURL& wc ) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::import() : " << wc.url() << " into " << repos.url() << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
// svn_client_commit_info_t *commit_info =
|
|
// (svn_client_commit_info_t*) apr_palloc( subpool, sizeof(svn_client_commit_info_t) );
|
|
svn_commit_info_t *commit_info = svn_create_commit_info( subpool );
|
|
bool nonrecursive = false;
|
|
|
|
const char *path = apr_pstrdup( subpool, svn_path_canonicalize( wc.path().utf8(), subpool ) );
|
|
const char *url = apr_pstrdup( subpool, svn_path_canonicalize( repos.url().utf8(), subpool ) );
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
kdDebug(9036) << " Executing import: " << path << " to " << url << endl;
|
|
|
|
svn_error_t *err = svn_client_import2(&commit_info, path, url, nonrecursive, false, ctx, subpool);
|
|
if ( err ){
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit(err->message) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
svn_pool_destroy (subpool);
|
|
finished();
|
|
}
|
|
|
|
void tdeio_svnProtocol::checkout( const KURL& repos, const KURL& wc, int revnumber, const TQString& revkind ) {
|
|
kdDebug(9036) << "tdeio_svn::checkout : " << repos.url() << " into " << wc.path() << " at revision " << revnumber << " or " << revkind << endl ;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
KURL nurl = repos;
|
|
KURL dest = wc;
|
|
nurl.setProtocol( chooseProtocol( repos.protocol() ) );
|
|
dest.setProtocol( "file" );
|
|
TQString target = makeSvnURL( repos );
|
|
recordCurrentURL( nurl );
|
|
TQString dpath = dest.path();
|
|
|
|
//find the requested revision
|
|
svn_opt_revision_t rev = createRevision( revnumber, revkind, subpool );
|
|
|
|
initNotifier(true, false, false, subpool);
|
|
svn_error_t *err = svn_client_checkout (NULL/* rev actually checkedout */, svn_path_canonicalize( target.utf8(), subpool ), svn_path_canonicalize ( dpath.utf8(), subpool ), &rev, true, ctx, subpool);
|
|
if ( err ){
|
|
error( TDEIO::ERR_SLAVE_DEFINED, err->message );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::commit(const KURL::List& wc)
|
|
{
|
|
commit2(true, true, wc);
|
|
}
|
|
|
|
void tdeio_svnProtocol::commit2(bool recurse, bool keeplocks, const KURL::List& wc) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::commit2() : " << wc << endl;
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
svn_client_commit_info_t *commit_info = NULL;
|
|
|
|
apr_array_header_t *targets = apr_array_make(subpool, 1+wc.count(), sizeof(const char *));
|
|
|
|
for ( TQValueListConstIterator<KURL> it = wc.begin(); it != wc.end() ; ++it ) {
|
|
KURL nurl = *it;
|
|
nurl.setProtocol( "file" );
|
|
recordCurrentURL( nurl );
|
|
(*(( const char ** )apr_array_push(( apr_array_header_t* )targets)) ) = svn_path_canonicalize( nurl.path().utf8(), subpool );
|
|
}
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
kdDebug(9036) << "recurse: " << recurse << " keeplocks: " << keeplocks <<endl;
|
|
svn_error_t *err = svn_client_commit2(&commit_info,targets,recurse,keeplocks,ctx,subpool);
|
|
|
|
if ( err ){
|
|
char errbuf[512];
|
|
svn_strerror(err->apr_err, errbuf, 512);
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit(err->message) + "\n: " + TQString::fromLocal8Bit(errbuf) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
if ( commit_info ) {
|
|
for ( TQValueListConstIterator<KURL> it = wc.begin(); it != wc.end() ; ++it ) {
|
|
KURL nurl = *it;
|
|
nurl.setProtocol( "file" );
|
|
|
|
TQString userstring = i18n ( "Nothing to commit." );
|
|
if ( SVN_IS_VALID_REVNUM( commit_info->revision ) )
|
|
userstring = i18n( "Committed revision %1." ).arg(commit_info->revision);
|
|
setMetaData(TQString::number( m_counter ).rightJustify( 10,'0' )+ "path", nurl.path() );
|
|
setMetaData(TQString::number( m_counter ).rightJustify( 10,'0' )+ "action", "0" );
|
|
setMetaData(TQString::number( m_counter ).rightJustify( 10,'0' )+ "kind", "0" );
|
|
setMetaData(TQString::number( m_counter ).rightJustify( 10,'0' )+ "mime_t", "" );
|
|
setMetaData(TQString::number( m_counter ).rightJustify( 10,'0' )+ "content", "0" );
|
|
setMetaData(TQString::number( m_counter ).rightJustify( 10,'0' )+ "prop", "0" );
|
|
setMetaData(TQString::number( m_counter ).rightJustify( 10,'0' )+ "rev" , TQString::number( commit_info->revision ) );
|
|
setMetaData(TQString::number( m_counter ).rightJustify( 10,'0' )+ "string", userstring );
|
|
m_counter++;
|
|
}
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::add(const KURL::List& list) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::add() __TIME__" << __TIME__ << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
bool nonrecursive = false;
|
|
initNotifier(false, false, false, subpool);
|
|
|
|
svn_error_t *err = NULL;
|
|
for( TQValueList<KURL>::ConstIterator it = list.begin(); it != list.end(); ++it ){
|
|
|
|
KURL nurl = (*it);
|
|
nurl.setProtocol( "file" );
|
|
recordCurrentURL( nurl );
|
|
kdDebug(9036) << " Schedule to Add: " << nurl.path().utf8() << endl;
|
|
err = svn_client_add( svn_path_canonicalize( nurl.path().utf8(), subpool ),
|
|
nonrecursive, ctx, subpool);
|
|
if( err ) break;
|
|
}
|
|
if ( err ){
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit(err->message) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::wc_delete(const KURL::List& wc) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::wc_delete() : " << wc << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
svn_client_commit_info_t *commit_info = NULL;
|
|
bool force = false;
|
|
|
|
apr_array_header_t *targets = apr_array_make(subpool, 1+wc.count(), sizeof(const char *));
|
|
|
|
for ( TQValueListConstIterator<KURL> it = wc.begin(); it != wc.end() ; ++it ) {
|
|
KURL nurl = *it;
|
|
nurl.setProtocol( "file" );
|
|
recordCurrentURL( nurl );
|
|
(*(( const char ** )apr_array_push(( apr_array_header_t* )targets)) ) = svn_path_canonicalize( nurl.path().utf8(), subpool );
|
|
}
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
svn_error_t *err = svn_client_delete(&commit_info,targets,force,ctx,subpool);
|
|
|
|
if ( err )
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit(err->message) );
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::wc_revert(const KURL::List& wc) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::revert() : " << wc << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
bool nonrecursive = false;
|
|
|
|
apr_array_header_t *targets = apr_array_make(subpool, 1 + wc.count(), sizeof(const char *));
|
|
|
|
for ( TQValueListConstIterator<KURL> it = wc.begin(); it != wc.end() ; ++it ) {
|
|
KURL nurl = *it;
|
|
nurl.setProtocol( "file" );
|
|
recordCurrentURL( nurl );
|
|
(*(( const char ** )apr_array_push(( apr_array_header_t* )targets)) ) = svn_path_canonicalize( nurl.path().utf8(), subpool );
|
|
}
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
svn_error_t *err = svn_client_revert(targets,nonrecursive,ctx,subpool);
|
|
if ( err ){
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit( err->message ) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::wc_status(const KURL& wc, bool checkRepos, bool fullRecurse, bool getAll, int revnumber, const TQString& revkind) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::wc_status() : " << wc.url() << " checkRepos " << checkRepos << " fullRecurse " << fullRecurse << " getAll " << getAll << endl;
|
|
|
|
wc_status2( wc, checkRepos, fullRecurse, getAll, false, revnumber, revkind );
|
|
}
|
|
|
|
void tdeio_svnProtocol::wc_status2(const KURL& wc, bool checkRepos, bool fullRecurse, bool getAll, bool noIgnore, int revnumber, const TQString& revkind) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::wc_status2() : " << wc.url() << " checkRepos " << checkRepos << " fullRecurse " << fullRecurse << " getAll " << getAll << " noIgnore " << noIgnore << " revnumber " << revnumber << " revkind " << revkind << endl;
|
|
kdDebug(9036) << " __TIME__ " << __TIME__ << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
svn_revnum_t result_rev;
|
|
|
|
KURL nurl = wc;
|
|
nurl.setProtocol( "file" );
|
|
recordCurrentURL( nurl );
|
|
|
|
svn_opt_revision_t rev = createRevision( revnumber, revkind, subpool );
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
|
|
svn_error_t *err = svn_client_status(&result_rev, svn_path_canonicalize( nurl.path().utf8(), subpool ), &rev, tdeio_svnProtocol::status, this, fullRecurse, getAll, checkRepos, noIgnore, ctx, subpool);
|
|
|
|
if ( err ){
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit(err->message) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::svn_info( KURL pathOrUrl, int pegRev, TQString pegRevKind, int rev, TQString revKind, bool recurse )
|
|
{
|
|
kdDebug(9036) << " tdeio_svnProtocol::svn_info(): pegRev " << pegRev << " pegKind " << pegRevKind << " rev " << rev << " revKind " << revKind << " recurse " << recurse << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
svn_opt_revision_t peg_rev = createRevision( pegRev, pegRevKind, subpool );
|
|
svn_opt_revision_t revision = createRevision( rev, revKind, subpool );
|
|
|
|
svn_error_t *err = svn_client_info( pathOrUrl.pathOrURL().utf8(),
|
|
&peg_rev, &revision,
|
|
tdeio_svnProtocol::infoReceiver,
|
|
this,
|
|
recurse,
|
|
ctx, pool );
|
|
|
|
if ( err ){
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit(err->message) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
svn_pool_destroy( subpool );
|
|
finished();
|
|
}
|
|
|
|
svn_error_t* tdeio_svnProtocol::infoReceiver( void *baton, const char *path,
|
|
const svn_info_t *info, apr_pool_t *pool)
|
|
{
|
|
tdeio_svnProtocol *p= (tdeio_svnProtocol*)baton ;
|
|
if( !p )
|
|
return SVN_NO_ERROR;
|
|
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "PATH", TQString::fromUtf8( path ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "URL", TQString( info->URL ) );
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "REV", TQString::number( info->rev ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "KIND", TQString::number( info->kind ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "REPOS_ROOT_URL", TQString( info->repos_root_URL ) );
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "REPOS_UUID", TQString(info->repos_UUID) );
|
|
p->incCounter();
|
|
|
|
return SVN_NO_ERROR;
|
|
}
|
|
|
|
void tdeio_svnProtocol::svn_copy( const KURL &srcUrl, int srcRev, const TQString &srcRevKind,
|
|
const KURL &destUrl )
|
|
{
|
|
kdDebug(9036) << " tdeio: svn_copy src: " << srcUrl << " Dest Url: " << destUrl << " revnum: " << srcRev << " revKind: " << srcRevKind << endl;
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
svn_commit_info_t *commit_info = svn_create_commit_info( subpool );
|
|
|
|
svn_opt_revision_t rev = createRevision( srcRev, srcRevKind, subpool );
|
|
|
|
// TODO more elegant notification mechanism
|
|
initNotifier(false, false, false, subpool);
|
|
svn_error_t *err = svn_client_copy2( &commit_info,
|
|
srcUrl.pathOrURL().utf8(), &rev,
|
|
destUrl.pathOrURL().utf8(),
|
|
ctx, subpool);
|
|
|
|
if ( err ) {
|
|
apr_status_t errcode = err->apr_err;
|
|
char buf[512];
|
|
svn_strerror(errcode, buf, 512);
|
|
error( TDEIO::ERR_SLAVE_DEFINED, TQString::fromLocal8Bit(buf) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
if( commit_info ){
|
|
setMetaData(TQString::number( counter() ).rightJustify( 10,'0' )+ "string",
|
|
i18n("Copied Revision %1").arg( commit_info->revision) );
|
|
} else {
|
|
setMetaData(TQString::number( counter() ).rightJustify( 10,'0' )+ "string",
|
|
i18n("Copied") );
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
void tdeio_svnProtocol::svn_merge(const KURL &src1, int revNum1, TQString revKind1,
|
|
const KURL &src2, int revNum2, TQString revKind2,
|
|
const KURL &target_wc,
|
|
bool recurse, bool ignore_ancestry, bool force, bool dry_run )
|
|
{
|
|
kdDebug(9036) << " TDEIO::svn_merge src1 " << src1.pathOrURL().utf8() << " src2 " << src2.pathOrURL().utf8() << " target " << target_wc.pathOrURL().utf8() << endl;
|
|
apr_pool_t *subpool = svn_pool_create( pool );
|
|
|
|
svn_opt_revision_t rev1 = createRevision( revNum1, revKind1, subpool );
|
|
svn_opt_revision_t rev2 = createRevision( revNum2, revKind2, subpool );
|
|
|
|
initNotifier( false, false, false, subpool );
|
|
svn_error_t *err = svn_client_merge( src1.pathOrURL().utf8(), &rev1,
|
|
src2.pathOrURL().utf8(), &rev2,
|
|
target_wc.pathOrURL().utf8(),
|
|
recurse, ignore_ancestry, force, dry_run,
|
|
ctx, pool );
|
|
if ( err ) {
|
|
apr_status_t errcode = err->apr_err;
|
|
char buf[512];
|
|
svn_strerror(errcode, buf, 512);
|
|
error( TDEIO::ERR_SLAVE_DEFINED,
|
|
TQString::fromLocal8Bit(err->message) + "\n "+ TQString::fromLocal8Bit(buf) );
|
|
svn_pool_destroy (subpool);
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
svn_pool_destroy( subpool );
|
|
}
|
|
|
|
//change the proto and remove trailing /
|
|
//remove double / also
|
|
TQString tdeio_svnProtocol::makeSvnURL ( const KURL& url ) const {
|
|
TQString kproto = url.protocol();
|
|
KURL tpURL = url;
|
|
tpURL.cleanPath( true );
|
|
TQString svnUrl;
|
|
if ( kproto == "kdevsvn+http" ) {
|
|
kdDebug(9036) << "http:/ " << url.url() << endl;
|
|
tpURL.setProtocol("http");
|
|
svnUrl = tpURL.url(-1);
|
|
return svnUrl;
|
|
}
|
|
else if ( kproto == "kdevsvn+https" ) {
|
|
kdDebug(9036) << "https:/ " << url.url() << endl;
|
|
tpURL.setProtocol("https");
|
|
svnUrl = tpURL.url(-1);
|
|
return svnUrl;
|
|
}
|
|
else if ( kproto == "kdevsvn+ssh" ) {
|
|
kdDebug(9036) << "svn+ssh:/ " << url.url() << endl;
|
|
tpURL.setProtocol("svn+ssh");
|
|
svnUrl = tpURL.url(-1);
|
|
return svnUrl;
|
|
}
|
|
else if ( kproto == "kdevsvn+svn" ) {
|
|
kdDebug(9036) << "svn:/ " << url.url() << endl;
|
|
tpURL.setProtocol("svn");
|
|
svnUrl = tpURL.url(-1);
|
|
return svnUrl;
|
|
}
|
|
else if ( kproto == "kdevsvn+file" ) {
|
|
kdDebug(9036) << "file:/ " << url.url() << endl;
|
|
tpURL.setProtocol("file");
|
|
svnUrl = tpURL.url(-1);
|
|
//hack : add one more / after file:/
|
|
int idx = svnUrl.find("/");
|
|
svnUrl.insert( idx, "//" );
|
|
return svnUrl;
|
|
}
|
|
return tpURL.url(-1);
|
|
}
|
|
|
|
TQString tdeio_svnProtocol::chooseProtocol ( const TQString& kproto ) const {
|
|
if ( kproto == "svn+http" ) return TQString( "http" );
|
|
else if ( kproto == "svn+https" ) return TQString( "https" );
|
|
else if ( kproto == "svn+ssh" ) return TQString( "svn+ssh" );
|
|
else if ( kproto == "svn" ) return TQString( "svn" );
|
|
else if ( kproto == "svn+file" ) return TQString( "file" );
|
|
return kproto;
|
|
}
|
|
/** Certificate is not yet valid. */
|
|
#define SVN_AUTH_SSL_NOTYETVALID 0x00000001
|
|
/** Certificate has expired. */
|
|
#define SVN_AUTH_SSL_EXPIRED 0x00000002
|
|
/** Certificate's CN (hostname) does not match the remote hostname. */
|
|
#define SVN_AUTH_SSL_CNMISMATCH 0x00000004
|
|
/** @brief Certificate authority is unknown (i.e. not trusted) */
|
|
#define SVN_AUTH_SSL_UNKNOWNCA 0x00000008
|
|
/** @brief Other failure. This can happen if neon has introduced a new
|
|
* failure bit that we do not handle yet. */
|
|
#define SVN_AUTH_SSL_OTHER 0x40000000
|
|
svn_error_t *tdeio_svnProtocol::trustSSLPrompt(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 *ci, svn_boolean_t may_save, apr_pool_t *pool)
|
|
{
|
|
tdeio_svnProtocol *p = (tdeio_svnProtocol*)baton;
|
|
// prepare params.
|
|
TQByteArray params, replyData;
|
|
TQCString replyType;
|
|
TQDataStream arg(params, IO_WriteOnly);
|
|
|
|
arg << i18n( "The certificate from the server could not be trusted automatically. Do you want to trust this certificate? " );
|
|
arg << TQString::fromLocal8Bit(ci->hostname);
|
|
arg << TQString::fromLocal8Bit(ci->fingerprint);
|
|
arg << TQString::fromLocal8Bit(ci->valid_from) << TQString::fromLocal8Bit(ci->valid_until);
|
|
arg << TQString::fromLocal8Bit(ci->issuer_dname) << TQString::fromLocal8Bit(ci->ascii_cert) ;
|
|
// call dcop
|
|
int ret = p->dcopClient()->call( "kded", "kdevsvnd",
|
|
"sslServerTrustPrompt(TQString, TQString, TQString, TQString, TQString, TQString, TQString)",
|
|
params, replyType, replyData );
|
|
if (!ret){
|
|
kdWarning() << " failed to prompt SSL_Server_Trust_Prompt " << endl;
|
|
return SVN_NO_ERROR;
|
|
}
|
|
if (replyType != "int"){
|
|
kdWarning() << " abnormal reply type " << endl;
|
|
return SVN_NO_ERROR;
|
|
}
|
|
int resultCode;
|
|
TQDataStream replyStream( replyData, IO_ReadOnly );
|
|
replyStream >> resultCode;
|
|
|
|
if( resultCode == -1 ){
|
|
kdWarning() << " SSL server trust rejected " << endl;
|
|
*cred_p = 0L; //FIXME when rejected, maybe more elegant methods..
|
|
} else if( resultCode == 0 ){ //accept once
|
|
*cred_p = (svn_auth_cred_ssl_server_trust_t*)apr_pcalloc (pool, sizeof (svn_auth_cred_ssl_server_trust_t));
|
|
kdDebug(9036) << " accept once " << endl;
|
|
(*cred_p)->may_save = false;
|
|
(*cred_p)->accepted_failures = 0;
|
|
} else if( resultCode == 1 ){ //accept permanently
|
|
*cred_p = (svn_auth_cred_ssl_server_trust_t*)apr_pcalloc (pool, sizeof (svn_auth_cred_ssl_server_trust_t));
|
|
kdDebug(9036) << " accept permanently " << endl;
|
|
(*cred_p)->may_save = true;
|
|
(*cred_p)->accepted_failures = failures;
|
|
} else{
|
|
kdWarning() << " SSL server trust failed for some reason" << endl;
|
|
*cred_p = 0L;
|
|
}
|
|
|
|
return SVN_NO_ERROR;
|
|
}
|
|
/** TODO fully implemented, but there is no way to test this yet.*/
|
|
svn_error_t *tdeio_svnProtocol::clientCertSSLPrompt(
|
|
svn_auth_cred_ssl_client_cert_t **cred_p, void *baton, const char *realm, svn_boolean_t may_save, apr_pool_t *pool)
|
|
{
|
|
kdDebug(9036) << " clientCertSSLPrompt " << endl;
|
|
// tdeio_svnProtocol *p = (tdeio_svnProtocol*)baton;
|
|
// TQByteArray reply;
|
|
// TQByteArray params;
|
|
// TQCString replyType;
|
|
// call dcop
|
|
// if (!p->dcopClient()->call("kded","kdevsvnd", "sslCertFile()",params,replyType,reply)) {
|
|
// kdWarning()<<" Communication with dcop failed - fail to get certfile "<<endl;
|
|
// return SVN_NO_ERROR;
|
|
// }
|
|
// if (replyType != "TQString") {
|
|
// kdWarning()<<" unexpected reply type "<<endl;
|
|
// return SVN_NO_ERROR;
|
|
// }
|
|
// save reply data
|
|
// TQString fileName;
|
|
// TQDataStream replyStream( reply, IO_ReadOnly );
|
|
// replyStream >> fileName;
|
|
// allocate memory
|
|
// *cred_p = (svn_auth_cred_ssl_client_cert_t*) apr_palloc (pool, sizeof(svn_auth_cred_ssl_client_cert_t));
|
|
// (*cred_p)->cert_file = apr_pstrdup( pool, fileName.utf8() );
|
|
// (*cred_p)->may_save = may_save;
|
|
return SVN_NO_ERROR;
|
|
}
|
|
|
|
/** TODO fully implemented, but there is no way to test this yet.*/
|
|
svn_error_t *tdeio_svnProtocol::clientCertPasswdPrompt(
|
|
svn_auth_cred_ssl_client_cert_pw_t **cred_p, void *baton, const char *realm, svn_boolean_t may_save, apr_pool_t *pool)
|
|
{
|
|
kdDebug(9036) << " Password Prompt Callback " << endl;
|
|
kdDebug(9036) << " realm " << realm << " <--realm " << endl;
|
|
// tdeio_svnProtocol *p = ( tdeio_svnProtocol* )baton;
|
|
// // prepare dcop
|
|
// TQByteArray reply;
|
|
// TQByteArray params;
|
|
// TQCString replyType;
|
|
// TQDataStream arg( params, IO_WriteOnly );
|
|
// arg << i18n( "Enter password for subversion repository access" ) + "\n" + TQString(realm);
|
|
// // call dcop
|
|
// if (!p->dcopClient()->call("kded","kdevsvnd", "sslPasswdDlg(TQString)",params,replyType,reply)) {
|
|
// kdWarning()<<" Communication with dcop failed - fail to show passwd dlg"<<endl;
|
|
// return SVN_NO_ERROR;
|
|
// }
|
|
// if (replyType != "TQCString") {
|
|
// kdWarning()<<" unexpected reply type "<<endl;
|
|
// return SVN_NO_ERROR;
|
|
// }
|
|
// // save reply data
|
|
// TQCString retstr, passwd;
|
|
// TQDataStream replyStream( reply, IO_ReadOnly );
|
|
// replyStream >> retstr;
|
|
//
|
|
// if( retstr.left(1) == "-1" ){
|
|
// kdDebug(9036) << " Null string received for passwd " << endl;
|
|
// } else{
|
|
// passwd = retstr.right( retstr.length() - 1 );
|
|
// kdDebug(9036) << " PassWD : " << passwd << endl;
|
|
// }
|
|
//
|
|
// svn_auth_cred_ssl_client_cert_pw_t *newcred = (svn_auth_cred_ssl_client_cert_pw_t*) apr_palloc (pool, sizeof (svn_auth_cred_ssl_client_cert_pw_t ) );
|
|
//
|
|
// newcred->password = apr_pstrdup(pool, (const char*) passwd );
|
|
// newcred->may_save = false;
|
|
// *cred_p = newcred;
|
|
|
|
return SVN_NO_ERROR;
|
|
}
|
|
|
|
|
|
svn_error_t *tdeio_svnProtocol::commitLogPrompt( const char **log_msg, const char **file,
|
|
apr_array_header_t *commit_items, void *baton, apr_pool_t *pool )
|
|
{
|
|
*file = NULL; // if omitting this, it will segfault at import operation.
|
|
TQCString replyType;
|
|
TQByteArray params;
|
|
TQByteArray reply;
|
|
TQString result;// slist;
|
|
TQStringList slist;
|
|
tdeio_svnProtocol *p = ( tdeio_svnProtocol* )baton;
|
|
svn_stringbuf_t *message = NULL;
|
|
|
|
for (int i = 0; i < commit_items->nelts; i++) {
|
|
TQString list;
|
|
svn_client_commit_item_t *item = ((svn_client_commit_item_t **) commit_items->elts)[i];
|
|
const char *path = item->path;
|
|
char text_mod = '_', prop_mod = ' ';
|
|
|
|
if (! path)
|
|
path = item->url;
|
|
else if (! *path)
|
|
path = ".";
|
|
|
|
if (! path)
|
|
path = ".";
|
|
|
|
if ((item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE) && (item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
|
|
text_mod = 'R';
|
|
else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD)
|
|
text_mod = 'A';
|
|
else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
|
|
text_mod = 'D';
|
|
else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_TEXT_MODS)
|
|
text_mod = 'M';
|
|
if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_PROP_MODS)
|
|
prop_mod = 'M';
|
|
|
|
list += text_mod;
|
|
list += " ";
|
|
list += prop_mod;
|
|
list += " ";
|
|
list += path;
|
|
kdDebug(9036) << " Commiting items : " << list << endl;
|
|
slist << list;
|
|
// slist += list;
|
|
}
|
|
|
|
TQDataStream stream(params, IO_WriteOnly);
|
|
stream << slist.join("\n");
|
|
|
|
kdDebug(9036) << " __TIME__ " << __TIME__ << endl;
|
|
if ( !p->dcopClient()->call( "kded","kdevsvnd","commitDialog(TQString)", params, replyType, reply ) ) {
|
|
kdWarning() << "Communication with KDED:KDevSvnd failed" << endl;
|
|
svn_error_t *err = svn_error_create( SVN_ERR_EXTERNAL_PROGRAM, NULL,
|
|
apr_pstrdup( pool, "Fail to call kded_kdevsvnd via DCOP. If this is your first problem, try to restart KDE" ) );
|
|
return err;
|
|
}
|
|
|
|
if ( replyType != "TQString" ) {
|
|
kdWarning() << "Unexpected reply type" << endl;
|
|
svn_error_t *err = svn_error_create( SVN_ERR_EXTERNAL_PROGRAM, NULL,
|
|
apr_pstrdup( pool, "Fail to call kded_kdevsvnd via DCOP." ) );
|
|
return err;
|
|
}
|
|
|
|
TQDataStream stream2 ( reply, IO_ReadOnly );
|
|
stream2 >> result;
|
|
|
|
if ( result.isNull() ) { //cancelled
|
|
*log_msg = NULL;
|
|
svn_error_t *err = svn_error_create( SVN_ERR_CANCELLED, NULL,
|
|
apr_pstrdup( pool, "Commit interruppted" ) );
|
|
return err;
|
|
}
|
|
|
|
message = svn_stringbuf_create( result.utf8(), pool );
|
|
*log_msg = message->data;
|
|
|
|
return SVN_NO_ERROR;
|
|
}
|
|
|
|
void tdeio_svnProtocol::notify(void *baton, const char *path, svn_wc_notify_action_t action, svn_node_kind_t kind, const char *mime_type, svn_wc_notify_state_t content_state, svn_wc_notify_state_t prop_state, svn_revnum_t revision) {
|
|
kdDebug(9036) << "NOTIFY : " << path << " updated at revision " << revision << " action : " << action << ", kind : " << kind << " , content_state : " << content_state << ", prop_state : " << prop_state << endl;
|
|
|
|
TQString userstring;
|
|
struct notify_baton *nb = ( struct notify_baton* ) baton;
|
|
|
|
//// Convert notification to a user readable string
|
|
switch ( action ) {
|
|
case svn_wc_notify_add : //add
|
|
if (mime_type && (svn_mime_type_is_binary (mime_type)))
|
|
userstring = i18n( "A (bin) %1" ).arg( path );
|
|
else
|
|
userstring = i18n( "A %1" ).arg( path );
|
|
break;
|
|
case svn_wc_notify_copy: //copy
|
|
userstring = i18n( "Copied %1 " ).arg( path );
|
|
break;
|
|
case svn_wc_notify_delete: //delete
|
|
nb->received_some_change = TRUE;
|
|
userstring = i18n( "D %1" ).arg( path );
|
|
break;
|
|
case svn_wc_notify_restore : //restore
|
|
userstring=i18n( "Restored %1." ).arg( path );
|
|
break;
|
|
case svn_wc_notify_revert : //revert
|
|
userstring=i18n( "Reverted %1." ).arg( path );
|
|
break;
|
|
case svn_wc_notify_failed_revert: //failed revert
|
|
userstring=i18n( "Failed to revert %1.\nTry updating instead." ).arg( path );
|
|
break;
|
|
case svn_wc_notify_resolved: //resolved
|
|
userstring=i18n( "Resolved conflicted state of %1." ).arg( path );
|
|
break;
|
|
case svn_wc_notify_skip: //skip
|
|
if ( content_state == svn_wc_notify_state_missing )
|
|
userstring=i18n("Skipped missing target %1.").arg( path );
|
|
else
|
|
userstring=i18n("Skipped %1.").arg( path );
|
|
break;
|
|
case svn_wc_notify_update_delete: //update_delete
|
|
nb->received_some_change = TRUE;
|
|
userstring=i18n( "D %1" ).arg( path );
|
|
break;
|
|
case svn_wc_notify_update_add: //update_add
|
|
nb->received_some_change = TRUE;
|
|
userstring=i18n( "A %1" ).arg( path );
|
|
break;
|
|
case svn_wc_notify_update_update: //update_update
|
|
{
|
|
/* If this is an inoperative dir change, do no notification.
|
|
An inoperative dir change is when a directory gets closed
|
|
without any props having been changed. */
|
|
if (! ((kind == svn_node_dir)
|
|
&& ((prop_state == svn_wc_notify_state_inapplicable)
|
|
|| (prop_state == svn_wc_notify_state_unknown)
|
|
|| (prop_state == svn_wc_notify_state_unchanged)))) {
|
|
nb->received_some_change = TRUE;
|
|
|
|
if (kind == svn_node_file) {
|
|
if (content_state == svn_wc_notify_state_conflicted)
|
|
userstring = "C";
|
|
else if (content_state == svn_wc_notify_state_merged)
|
|
userstring = "G";
|
|
else if (content_state == svn_wc_notify_state_changed)
|
|
userstring = "U";
|
|
}
|
|
|
|
if (prop_state == svn_wc_notify_state_conflicted)
|
|
userstring += "C";
|
|
else if (prop_state == svn_wc_notify_state_merged)
|
|
userstring += "G";
|
|
else if (prop_state == svn_wc_notify_state_changed)
|
|
userstring += "U";
|
|
else
|
|
userstring += " ";
|
|
|
|
if (! ((content_state == svn_wc_notify_state_unchanged
|
|
|| content_state == svn_wc_notify_state_unknown)
|
|
&& (prop_state == svn_wc_notify_state_unchanged
|
|
|| prop_state == svn_wc_notify_state_unknown)))
|
|
userstring += TQString( " " ) + path;
|
|
}
|
|
break;
|
|
}
|
|
case svn_wc_notify_update_completed: //update_completed
|
|
{
|
|
if (! nb->suppress_final_line) {
|
|
if (SVN_IS_VALID_REVNUM (revision)) {
|
|
if (nb->is_export) {
|
|
if ( nb->in_external )
|
|
userstring = i18n("Exported external at revision %1.").arg( revision );
|
|
else
|
|
userstring = i18n("Exported revision %1.").arg( revision );
|
|
} else if (nb->is_checkout) {
|
|
if ( nb->in_external )
|
|
userstring = i18n("Checked out external at revision %1.").arg( revision );
|
|
else
|
|
userstring = i18n("Checked out revision %1.").arg( revision);
|
|
} else {
|
|
if (nb->received_some_change) {
|
|
if ( nb->in_external )
|
|
userstring=i18n("Updated external to revision %1.").arg( revision );
|
|
else
|
|
userstring = i18n("Updated to revision %1.").arg( revision);
|
|
} else {
|
|
if ( nb->in_external )
|
|
userstring = i18n("External at revision %1.").arg( revision );
|
|
else
|
|
userstring = i18n("At revision %1.").arg( revision);
|
|
}
|
|
}
|
|
} else /* no revision */ {
|
|
if (nb->is_export) {
|
|
if ( nb->in_external )
|
|
userstring = i18n("External export complete.");
|
|
else
|
|
userstring = i18n("Export complete.");
|
|
} else if (nb->is_checkout) {
|
|
if ( nb->in_external )
|
|
userstring = i18n("External checkout complete.");
|
|
else
|
|
userstring = i18n("Checkout complete.");
|
|
} else {
|
|
if ( nb->in_external )
|
|
userstring = i18n("External update complete.");
|
|
else
|
|
userstring = i18n("Update complete.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (nb->in_external)
|
|
nb->in_external = FALSE;
|
|
break;
|
|
case svn_wc_notify_update_external: //update_external
|
|
nb->in_external = TRUE;
|
|
userstring = i18n("Fetching external item into %1." ).arg( path );
|
|
break;
|
|
case svn_wc_notify_status_completed: //status_completed
|
|
if (SVN_IS_VALID_REVNUM (revision))
|
|
userstring = i18n( "Status against revision: %1.").arg( revision );
|
|
break;
|
|
case svn_wc_notify_status_external: //status_external
|
|
userstring = i18n("Performing status on external item at %1.").arg( path );
|
|
break;
|
|
case svn_wc_notify_commit_modified: //commit_modified
|
|
userstring = i18n( "Sending %1").arg( path );
|
|
break;
|
|
case svn_wc_notify_commit_added: //commit_added
|
|
if (mime_type && svn_mime_type_is_binary (mime_type)) {
|
|
userstring = i18n( "Adding (bin) %1.").arg( path );
|
|
} else {
|
|
userstring = i18n( "Adding %1.").arg( path );
|
|
}
|
|
break;
|
|
case svn_wc_notify_commit_deleted: //commit_deleted
|
|
userstring = i18n( "Deleting %1.").arg( path );
|
|
break;
|
|
case svn_wc_notify_commit_replaced: //commit_replaced
|
|
userstring = i18n( "Replacing %1.").arg( path );
|
|
break;
|
|
case svn_wc_notify_commit_postfix_txdelta: //commit_postfix_txdelta
|
|
if (! nb->sent_first_txdelta) {
|
|
nb->sent_first_txdelta = TRUE;
|
|
userstring=i18n("Transmitting file data ");
|
|
} else {
|
|
userstring=".";
|
|
}
|
|
break;
|
|
|
|
break;
|
|
case svn_wc_notify_blame_revision: //blame_revision
|
|
userstring = i18n("Blame %1.").arg(path);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
//// End convert
|
|
tdeio_svnProtocol *p = ( tdeio_svnProtocol* )nb->master;
|
|
if (!p) kdDebug(9036) << " Null Pointer at Line " << __LINE__ << endl;
|
|
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "path" , TQString::fromUtf8( path ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "action", TQString::number( action ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "kind", TQString::number( kind ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "mime_t", TQString::fromUtf8( mime_type ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "content", TQString::number( content_state ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "prop", TQString::number( prop_state ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "rev", TQString::number( revision ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "string", userstring );
|
|
kdDebug(9036) << " tdeio_svnProtocol::notify() userstring " << userstring << endl;
|
|
p->incCounter();
|
|
}
|
|
|
|
void tdeio_svnProtocol::status(void *baton, const char *path, svn_wc_status_t *status) {
|
|
kdDebug(9036) << "STATUS : " << path << ", wc text status : " << status->text_status
|
|
<< ", wc prop status : " << status->prop_status
|
|
<< ", repos text status : " << status->repos_text_status
|
|
<< ", repos prop status : " << status->repos_prop_status
|
|
<< endl;
|
|
|
|
TQByteArray params;
|
|
tdeio_svnProtocol *p = ( tdeio_svnProtocol* )baton;
|
|
|
|
TQDataStream stream(params, IO_WriteOnly);
|
|
long int rev = status->entry ? status->entry->revision : 0;
|
|
stream << TQString::fromUtf8( path ) << status->text_status << status->prop_status << status->repos_text_status << status->repos_prop_status << rev;
|
|
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "path", TQString::fromUtf8( path ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "text", TQString::number( status->text_status ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "prop", TQString::number( status->prop_status ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "reptxt", TQString::number( status->repos_text_status ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "repprop", TQString::number( status->repos_prop_status ));
|
|
p->setMetaData(TQString::number( p->counter() ).rightJustify( 10,'0' )+ "rev", TQString::number( rev ));
|
|
p->incCounter();
|
|
}
|
|
|
|
void tdeio_svnProtocol::progressCallback( apr_off_t processed, apr_off_t total, void *baton, apr_pool_t *pool)
|
|
{
|
|
tdeio_svnProtocol *p = (tdeio_svnProtocol*)baton;
|
|
if( total > -1 )
|
|
p->totalSize( total );
|
|
if( processed > -1 )
|
|
p->processedSize( processed );
|
|
}
|
|
|
|
void tdeio_svnProtocol::wc_resolve( const KURL& wc, bool recurse ) {
|
|
kdDebug(9036) << "tdeio_svnProtocol::wc_resolve() : " << wc.url() << endl;
|
|
|
|
apr_pool_t *subpool = svn_pool_create (pool);
|
|
|
|
KURL nurl = wc;
|
|
nurl.setProtocol( "file" );
|
|
recordCurrentURL( nurl );
|
|
|
|
initNotifier(false, false, false, subpool);
|
|
svn_error_t *err = svn_client_resolved(svn_path_canonicalize( nurl.path().utf8(), subpool ), recurse,ctx,subpool);
|
|
if ( err )
|
|
error( TDEIO::ERR_SLAVE_DEFINED, err->message );
|
|
|
|
finished();
|
|
svn_pool_destroy (subpool);
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
TDE_EXPORT int kdemain(int argc, char **argv) {
|
|
TDEInstance instance( "tdeio_kdevsvn" );
|
|
|
|
kdDebug(9036) << "*** Starting tdeio_kdevsvn " << endl;
|
|
|
|
if (argc != 4) {
|
|
kdDebug(9036) << "Usage: tdeio_kdevsvn protocol domain-socket1 domain-socket2" << endl;
|
|
exit(-1);
|
|
}
|
|
|
|
tdeio_svnProtocol slave(argv[2], argv[3]);
|
|
slave.dispatchLoop();
|
|
|
|
kdDebug(9036) << "*** tdeio_kdevsvn Done" << endl;
|
|
return 0;
|
|
}
|
|
}
|
|
|