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.
tdesvn/src/svnfrontend/svnactions.cpp

2892 lines
96 KiB

/***************************************************************************
* Copyright (C) 2005-2007 by Rajko Albrecht *
* ral@alwins-world.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "svnactions.h"
#include "checkoutinfo_impl.h"
#include "itemdisplay.h"
#include "svnitem.h"
#include "rangeinput_impl.h"
#include "propertiesdlg.h"
#include "ccontextlistener.h"
#include "tcontextlistener.h"
#include "modifiedthread.h"
#include "fillcachethread.h"
#include "svnlogdlgimp.h"
#include "stopdlg.h"
#include "blamedisplay_impl.h"
#include "logmsg_impl.h"
#include "diffbrowser.h"
#include "encodingselector_impl.h"
#include "revertform_impl.h"
#include "revisiontree.h"
#include "tdesvnsettings.h"
#include "tdesvn_events.h"
#include "client.h"
#include "annotate_line.h"
#include "context_listener.h"
#include "dirent.h"
#include "targets.h"
#include "url.h"
#include "wc.h"
#include "svnqt_defines.h"
#include "LogCache.h"
#include "ReposLog.h"
#include "url.h"
#include "helpers/sub2qt.h"
#include "fronthelpers/cursorstack.h"
#include "cacheentry.h"
#include <kdialog.h>
#include <ktextbrowser.h>
#include <tdelocale.h>
#include <tdeglobalsettings.h>
#include <tdemessagebox.h>
#include <kinputdialog.h>
#include <kprocess.h>
#include <ktempdir.h>
#include <tdetempfile.h>
#include <kdialogbase.h>
#include <tdeapplication.h>
#include <tdeio/jobclasses.h>
#include <tdeio/job.h>
#include <kdebug.h>
#include <tdeconfig.h>
#include <tdelistview.h>
#include <tdeio/netaccess.h>
#include <kstandarddirs.h>
#include <ktrader.h>
#include <krun.h>
#include <kstdguiitem.h>
#include <tqstring.h>
#include <tqmap.h>
#include <tqpushbutton.h>
#include <tqlayout.h>
#include <tqvaluelist.h>
#include <tqvbox.h>
#include <tqstylesheet.h>
#include <tqregexp.h>
#include <tqimage.h>
#include <tqthread.h>
#include <tqtimer.h>
#include <tqlistview.h>
#include <tqfileinfo.h>
#include <sys/time.h>
#include <unistd.h>
#include <tqguardedptr.h>
// wait not longer than 10 seconds for a thread
#define MAX_THREAD_WAITTIME 10000
class SvnActionsData:public svn::ref_count
{
typedef svn::SharedPointer<svn::PathPropertiesMapList> sPPlist;
public:
SvnActionsData():ref_count()
{
m_Svnclient = svn::Client::getobject(0,0);
m_CurrentContext = 0;
}
virtual ~SvnActionsData()
{
if (m_DiffDialog) {
m_DiffDialog->saveDialogSize(*(Kdesvnsettings::self()->config()),"diff_display",false);
delete m_DiffDialog;
}
if (m_LogDialog) {
m_LogDialog->saveSize();
delete m_LogDialog;
}
TQMap<TDEProcess*,TQStringList>::iterator it;
for (it=m_tempfilelist.begin();it!=m_tempfilelist.end();++it) {
for (TQStringList::iterator it2 = (*it).begin();
it2 != (*it).end();++it2) {
::unlink((*it2).ascii());
}
}
for (it=m_tempdirlist.begin();it!=m_tempdirlist.end();++it) {
for (TQStringList::iterator it2 = (*it).begin();
it2 != (*it).end();++it2) {
TDEIO::NetAccess::del((*it2),0);
}
}
delete m_Svnclient;
m_Svnclient = 0L;
}
bool isExternalDiff()
{
if (Kdesvnsettings::use_external_diff()) {
TQString edisp = Kdesvnsettings::external_diff_display();
TQStringList wlist = TQStringList::split(" ",edisp);
if (wlist.count()>=3 && edisp.find("%1")!=-1 && edisp.find("%2")!=-1) {
return true;
}
}
return false;
}
void clearCaches()
{
m_PropertiesCache.clear();
m_contextData.clear();
m_InfoCache.clear();
}
void cleanDialogs()
{
if (m_DiffDialog) {
m_DiffDialog->saveDialogSize(*(Kdesvnsettings::self()->config()),"diff_display",false);
delete m_DiffDialog;
m_DiffDialog=0;
}
if (m_LogDialog) {
m_LogDialog->saveSize();
delete m_LogDialog;
m_LogDialog=0;
}
}
ItemDisplay* m_ParentList;
svn::smart_pointer<CContextListener> m_SvnContextListener;
svn::ContextP m_CurrentContext;
svn::Client*m_Svnclient;
helpers::statusCache m_UpdateCache;
helpers::statusCache m_Cache;
helpers::statusCache m_conflictCache;
helpers::statusCache m_repoLockCache;
helpers::itemCache<svn::PathPropertiesMapListPtr> m_PropertiesCache;
/// \todo as persistent cache (sqlite?)
helpers::itemCache<svn::InfoEntry> m_InfoCache;
TQMap<TDEProcess*,TQStringList> m_tempfilelist;
TQMap<TDEProcess*,TQStringList> m_tempdirlist;
TQTimer m_ThreadCheckTimer;
TQTimer m_UpdateCheckTimer;
TQTime m_UpdateCheckTick;
TQGuardedPtr<DiffBrowser> m_DiffBrowserPtr;
TQGuardedPtr<KDialogBase> m_DiffDialog;
TQGuardedPtr<SvnLogDlgImp> m_LogDialog;
TQMap<TQString,TQString> m_contextData;
bool runblocked;
};
#define EMIT_FINISHED emit sendNotify(i18n("Finished"))
#define EMIT_REFRESH emit sigRefreshAll()
#define DIALOGS_SIZES "display_dialogs_sizes"
SvnActions::SvnActions(ItemDisplay *parent, const char *name,bool processes_blocked)
: TQObject(parent?parent->realWidget():0, name),SimpleLogCb()
{
m_CThread = 0;
m_UThread = 0;
m_FCThread = 0;
m_Data = new SvnActionsData();
m_Data->m_ParentList = parent;
m_Data->m_SvnContextListener = new CContextListener(this);
m_Data->runblocked = processes_blocked;
connect(m_Data->m_SvnContextListener,TQT_SIGNAL(sendNotify(const TQString&)),this,TQT_SLOT(slotNotifyMessage(const TQString&)));
connect(&(m_Data->m_ThreadCheckTimer),TQT_SIGNAL(timeout()),this,TQT_SLOT(checkModthread()));
connect(&(m_Data->m_UpdateCheckTimer),TQT_SIGNAL(timeout()),this,TQT_SLOT(checkUpdateThread()));
}
svn::Client* SvnActions::svnclient()
{
return m_Data->m_Svnclient;
}
SvnActions::~SvnActions()
{
killallThreads();
}
void SvnActions::slotNotifyMessage(const TQString&aMsg)
{
emit sendNotify(aMsg);
}
void SvnActions::reInitClient()
{
m_Data->clearCaches();
m_Data->cleanDialogs();
if (m_Data->m_CurrentContext) m_Data->m_CurrentContext->setListener(0L);
m_Data->m_CurrentContext = new svn::Context();
m_Data->m_CurrentContext->setListener(m_Data->m_SvnContextListener);
m_Data->m_Svnclient->setContext(m_Data->m_CurrentContext);
}
template<class T> KDialogBase* SvnActions::createDialog(T**ptr,const TQString&_head,bool OkCancel,const char*name,bool showHelp,bool modal,const KGuiItem&u1)
{
int buttons = KDialogBase::Ok;
if (OkCancel) {
buttons = buttons|KDialogBase::Cancel;
}
if (showHelp) {
buttons = buttons|KDialogBase::Help;
}
if (!u1.text().isEmpty()) {
buttons = buttons|KDialogBase::User1;
}
KDialogBase * dlg = new KDialogBase(
modal?TQT_TQWIDGET(TQT_TQWIDGET(TDEApplication::activeModalWidget())):0, // parent
name, // name
modal, // modal
_head, // caption
buttons, // buttonmask
KDialogBase::Ok, // defaultButton
false , // separator
(u1.text().isEmpty()?KGuiItem():u1) //user1
);
if (!dlg) return dlg;
TQWidget* Dialog1Layout = dlg->makeVBoxMainWidget();
*ptr = new T(Dialog1Layout);
dlg->resize(dlg->configDialogSize(*(Kdesvnsettings::self()->config()),name?name:DIALOGS_SIZES));
return dlg;
}
/*!
\fn SvnActions::makeLog(svn::Revision start,svn::Revision end,FileListViewItem*k)
*/
void SvnActions::makeLog(const svn::Revision&start,const svn::Revision&end,const svn::Revision&peg,SvnItem*k,bool list_files,int limit)
{
if (k) {
makeLog(start,end,peg,k->fullName(),list_files,limit);
}
}
svn::SharedPointer<svn::LogEntriesMap> SvnActions::getLog(const svn::Revision&start,const svn::Revision&end,const svn::Revision&peg,const TQString&which,bool list_files,
int limit,TQWidget*parent)
{
svn::SharedPointer<svn::LogEntriesMap> logs = new svn::LogEntriesMap;
if (!m_Data->m_CurrentContext) return 0;
bool follow = Kdesvnsettings::log_follows_nodes();
kdDebug()<<"Get logs for "<< which<<endl;
try {
StopDlg sdlg(m_Data->m_SvnContextListener,(parent?parent:m_Data->m_ParentList->realWidget()),0,"Logs",
i18n("Getting logs - hit cancel for abort"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
if (doNetworking()) {
m_Data->m_Svnclient->log(which,start,end,*logs,peg,list_files,!follow,limit);
} else {
svn::InfoEntry e;
if (!singleInfo(m_Data->m_ParentList->baseUri(),svn::Revision::BASE,e)) {
return 0;
}
if (svn::Url::isLocal(e.reposRoot())) {
m_Data->m_Svnclient->log(which,start,end,*logs,peg,list_files,!follow,limit);
} else {
svn::cache::ReposLog rl(m_Data->m_Svnclient,e.reposRoot());
TQString s1,s2,what;
s1=e.url().mid(e.reposRoot().length());
if (which==".") {
what=s1;
} else {
s2=which.mid(m_Data->m_ParentList->baseUri().length());
what=s1+"/"+s2;
}
rl.log(what,start,end,peg,*logs,!follow,limit);
}
}
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return 0;
}
if (!logs) {
emit clientException(i18n("Got no logs"));
return 0;
}
return logs;
}
bool SvnActions::getSingleLog(svn::LogEntry&t,const svn::Revision&r,const TQString&what,const svn::Revision&peg,TQString&root)
{
bool res = false;
if (what.isEmpty()) {
return res;
}
if (root.isEmpty()) {
svn::InfoEntry inf;
if (!singleInfo(what,peg,inf))
{
return res;
}
root = inf.reposRoot();
}
if (!svn::Url::isLocal(root)) {
svn::LogEntriesMap _m;
try {
svn::cache::ReposLog rl(m_Data->m_Svnclient ,root);
if (rl.isValid() && rl.simpleLog(_m,r,r,true) && _m.find(r.revnum())!=_m.end() ) {
t = _m[r.revnum()];
res = true;
}
} catch (const svn::Exception&e) {
emit clientException(e.msg());
}
}
if (!res) {
svn::SharedPointer<svn::LogEntriesMap> log = getLog(r,r,peg,root,true,1);
if (log) {
if (log->find(r.revnum())!=log->end()) {
t = (*log)[r.revnum()];
res = true;
}
}
}
return res;
}
bool SvnActions::singleInfo(const TQString&what,const svn::Revision&_rev,svn::InfoEntry&target,const svn::Revision&_peg)
{
TQString url;
TQString ex;
TQString cacheKey;
TQTime d; d.start();
svn::Revision rev = _rev;
svn::Revision peg = _peg;
if (!m_Data->m_CurrentContext) return false;
if (!svn::Url::isValid(what)) {
// working copy
// url = svn::Wc::getUrl(what);
url = what;
if (url.find("@")!=-1) {
url+="@BASE";
}
peg = svn::Revision::UNDEFINED;
cacheKey=url;
} else {
KURL _uri = what;
TQString prot = svn::Url::transformProtokoll(_uri.protocol());
_uri.setProtocol(prot);
url = _uri.prettyURL();
if (peg==svn::Revision::UNDEFINED)
{
peg = _rev;
}
if (peg==svn::Revision::UNDEFINED)
{
peg=svn::Revision::HEAD;
}
cacheKey=_rev.toString()+"/"+url;
}
svn::InfoEntries e;
if (cacheKey.isEmpty() || !m_Data->m_InfoCache.findSingleValid(cacheKey,target)) {
try {
e = (m_Data->m_Svnclient->info(url,svn::DepthEmpty,_rev,peg));
} catch (const svn::Exception&ce) {
kdDebug()<<"Singleinfo: "<<_rev.toString()<<endl;
kdDebug()<<"Singleinfo: "<<ce.msg() << endl;
emit clientException(ce.msg());
return false;
}
if (e.count()<1||e[0].reposRoot().isEmpty()) {
emit clientException(i18n("Got no info."));
return false;
}
target = e[0];
if (!cacheKey.isEmpty()) {
m_Data->m_InfoCache.insertKey(e[0],cacheKey);
if (peg != svn::Revision::UNDEFINED && peg.kind()!= svn::Revision::NUMBER && peg.kind()!= svn::Revision::DATE ) {
// for persistent storage, store head into persistent cache makes no sense.
cacheKey=e[0].revision().toString()+"/"+url;
kdDebug()<<"Extra: "<<cacheKey<<endl;
m_Data->m_InfoCache.insertKey(e[0],cacheKey);
}
}
}
return true;
}
void SvnActions::makeTree(const TQString&what,const svn::Revision&_rev,const svn::Revision&startr,const svn::Revision&endr)
{
svn::InfoEntry info;
if (!singleInfo(what,_rev,info)) {
return;
}
TQString reposRoot = info.reposRoot();
bool restartCache = (m_FCThread && m_FCThread->running());
if (restartCache) {
stopFillCache();
}
kdDebug()<<"Logs for "<<reposRoot<<endl;
TQWidget*disp;
KDialogBase dlg(m_Data->m_ParentList->realWidget(),"historylist",true,i18n("History of %1").arg(info.url().mid(reposRoot.length())),
KDialogBase::Ok,
KDialogBase::Ok,true);
TQWidget* Dialog1Layout = dlg.makeVBoxMainWidget();
RevisionTree rt(m_Data->m_Svnclient,m_Data->m_SvnContextListener,reposRoot,
startr,endr,
info.prettyUrl().mid(reposRoot.length()),_rev,Dialog1Layout,m_Data->m_ParentList->realWidget());
if (rt.isValid()) {
disp = rt.getView();
if (disp) {
connect(
disp,TQT_SIGNAL(makeNorecDiff(const TQString&,const svn::Revision&,const TQString&,const svn::Revision&,TQWidget*)),
this,TQT_SLOT(makeNorecDiff(const TQString&,const svn::Revision&,const TQString&,const svn::Revision&,TQWidget*))
);
connect(
disp,TQT_SIGNAL(makeRecDiff(const TQString&,const svn::Revision&,const TQString&,const svn::Revision&,TQWidget*)),
this,TQT_SLOT(makeDiff(const TQString&,const svn::Revision&,const TQString&,const svn::Revision&,TQWidget*))
);
connect(disp,TQT_SIGNAL(makeCat(const svn::Revision&, const TQString&,const TQString&,const svn::Revision&,TQWidget*)),
this,TQT_SLOT(slotMakeCat(const svn::Revision&,const TQString&,const TQString&,const svn::Revision&,TQWidget*)));
dlg.resize(dlg.configDialogSize(*(Kdesvnsettings::self()->config()),"revisiontree_dlg"));
dlg.exec();
dlg.saveDialogSize(*(Kdesvnsettings::self()->config()),"revisiontree_dlg",false);
}
}
if (restartCache) {
startFillCache(reposRoot);
}
}
void SvnActions::makeLog(const svn::Revision&start,const svn::Revision&end,const svn::Revision&peg,const TQString&which,bool list_files,int limit)
{
svn::InfoEntry info;
if (!singleInfo(which,start,info)) {
return;
}
TQString reposRoot = info.reposRoot();
kdDebug()<<"getting logs..."<<endl;
svn::SharedPointer<svn::LogEntriesMap> logs = getLog(start,end,peg,which,list_files,limit);
if (!logs) return;
bool need_modal = m_Data->runblocked||TQT_TQWIDGET(TDEApplication::activeModalWidget())!=0;
if (need_modal||!m_Data->m_LogDialog) {
m_Data->m_LogDialog=new SvnLogDlgImp(this,0,"logdialog",need_modal);
connect(m_Data->m_LogDialog,TQT_SIGNAL(makeDiff(const TQString&,const svn::Revision&,const TQString&,const svn::Revision&,TQWidget*)),
this,TQT_SLOT(makeDiff(const TQString&,const svn::Revision&,const TQString&,const svn::Revision&,TQWidget*)));
connect(m_Data->m_LogDialog,TQT_SIGNAL(makeCat(const svn::Revision&, const TQString&,const TQString&,const svn::Revision&,TQWidget*)),
this,TQT_SLOT(slotMakeCat(const svn::Revision&,const TQString&,const TQString&,const svn::Revision&,TQWidget*)));
}
if (m_Data->m_LogDialog) {
m_Data->m_LogDialog->dispLog(logs,info.url().mid(reposRoot.length()),reposRoot,
(
peg==svn::Revision::UNDEFINED?
(svn::Url::isValid(which)?svn::Revision::HEAD:svn::Revision::UNDEFINED):
peg
),which);
if (need_modal) {
m_Data->m_LogDialog->exec();
m_Data->m_LogDialog->saveSize();
delete m_Data->m_LogDialog;
} else {
m_Data->m_LogDialog->show();
m_Data->m_LogDialog->raise();
}
}
EMIT_FINISHED;
}
void SvnActions::makeBlame(const svn::Revision&start, const svn::Revision&end, SvnItem*k)
{
if (k) makeBlame(start,end,k->fullName(),m_Data->m_ParentList->realWidget());
}
void SvnActions::makeBlame(const svn::Revision&start, const svn::Revision&end,const TQString&k,TQWidget*_p,const svn::Revision&_peg,SimpleLogCb*_acb)
{
if (!m_Data->m_CurrentContext) return;
svn::AnnotatedFile blame;
TQString ex;
svn::Path p(k);
TQWidget*_parent = _p?_p:m_Data->m_ParentList->realWidget();
svn::Revision peg = _peg==svn::Revision::UNDEFINED?end:_peg;
try {
CursorStack a(TQt::BusyCursor);
StopDlg sdlg(m_Data->m_SvnContextListener,_parent,0,"Annotate",i18n("Annotate lines - hit cancel for abort"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
m_Data->m_Svnclient->annotate(blame,p,start,end,peg);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return;
}
if (blame.count()==0) {
ex = i18n("Got no annotate");
emit clientException(ex);
return;
}
EMIT_FINISHED;
BlameDisplay_impl::displayBlame(_acb?_acb:this,k,blame,_p,"blame_dlg");
}
bool SvnActions::makeGet(const svn::Revision&start, const TQString&what, const TQString&target,
const svn::Revision&peg,TQWidget*_dlgparent)
{
if (!m_Data->m_CurrentContext) return false;
CursorStack a(TQt::BusyCursor);
TQWidget*dlgp=_dlgparent?_dlgparent:m_Data->m_ParentList->realWidget();
TQString ex;
svn::Path p(what);
try {
StopDlg sdlg(m_Data->m_SvnContextListener,dlgp,
0,"Content get",i18n("Getting content - hit cancel for abort"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
m_Data->m_Svnclient->get(p,target,start,peg);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
} catch (...) {
ex = i18n("Error getting content");
emit clientException(ex);
return false;
}
return true;
}
void SvnActions::slotMakeCat(const svn::Revision&start, const TQString&what, const TQString&disp,const svn::Revision&peg,TQWidget*_dlgparent)
{
KTempFile content;
content.setAutoDelete(true);
if (!makeGet(start,what,content.name(),peg,_dlgparent)) {
return;
}
EMIT_FINISHED;
KMimeType::Ptr mptr;
mptr = KMimeType::findByFileContent(content.name());
TDETrader::OfferList offers = TDETrader::self()->query(mptr->name(), "Type == 'Application' or (exist Exec)");
if (offers.count()==0 || offers.first()->exec().isEmpty()) {
offers = TDETrader::self()->query(mptr->name(), "Type == 'Application'");
}
TDETrader::OfferList::ConstIterator it = offers.begin();
for( ; it != offers.end(); ++it ) {
if ((*it)->noDisplay())
continue;
break;
}
if (it!=offers.end()) {
content.setAutoDelete(false);
KRun::run(**it,KURL(content.name()),true);
return;
}
KTextBrowser*ptr;
TQFile file(content.name());
file.open( IO_ReadOnly );
TQByteArray co = file.readAll();
if (co.size()) {
KDialogBase*dlg = createDialog(&ptr,TQString(i18n("Content of %1")).arg(disp),false,"cat_display_dlg");
if (dlg) {
ptr->setFont(TDEGlobalSettings::fixedFont());
ptr->setWordWrap(TQTextEdit::NoWrap);
ptr->setText(TQString::FROMUTF8(co,co.size()));
dlg->exec();
dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"cat_display_dlg",false);
delete dlg;
}
} else {
KMessageBox::information(_dlgparent?_dlgparent:m_Data->m_ParentList->realWidget(),
i18n("Got no content."));
}
}
bool SvnActions::makeMkdir(const TQStringList&which,const TQString&logMessage)
{
if (!m_Data->m_CurrentContext||which.count()<1) return false;
svn::Targets targets(which);
try {
m_Data->m_Svnclient->mkdir(targets,logMessage);
}catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
return true;
}
TQString SvnActions::makeMkdir(const TQString&parentDir)
{
if (!m_Data->m_CurrentContext) return TQString();
TQString ex;
bool isOk=false;
ex = KInputDialog::getText(i18n("New folder"),i18n("Enter folder name:"),TQString(),&isOk);
if (!isOk) {
return TQString();
}
svn::Path target(parentDir);
target.addComponent(ex);
ex = "";
TQString logMessage=TQString();
try {
m_Data->m_Svnclient->mkdir(target,logMessage);
}catch (const svn::Exception&e) {
emit clientException(e.msg());
return TQString();
}
ex = target.path();
return ex;
}
TQString SvnActions::getInfo(TQPtrList<SvnItem> lst,const svn::Revision&rev,const svn::Revision&peg,bool recursive,bool all)
{
TQStringList l;
TQString res = "";
SvnItem*item;
for (item=lst.first();item;item=lst.next()) {
if (all) res+="<h4 align=\"center\">"+item->fullName()+"</h4>";
res += getInfo(item->fullName(),rev,peg,recursive,all);
}
return res;
}
TQString SvnActions::getInfo(const TQString& _what,const svn::Revision&rev,const svn::Revision&peg,bool recursive,bool all)
{
if (!m_Data->m_CurrentContext) return TQString();
TQString ex;
svn::InfoEntries entries;
if (recursive) {
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,"Details",
i18n("Retrieving infos - hit cancel for abort"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
svn::InfoEntries e;
entries = (m_Data->m_Svnclient->info(_what+
(_what.find("@")>-1&&!svn::Url::isValid(_what)?"@BASE":""),recursive?svn::DepthInfinity:svn::DepthEmpty,rev,peg));
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return TQString();
}
} else {
svn::InfoEntry info;
if (!singleInfo(_what,rev,info,peg)) {
return TQString();
}
entries.append(info);
}
//if (!all) EMIT_FINISHED;
TQString text = "";
svn::InfoEntries::const_iterator it;
static TQString rb = "<tr><td><nobr><font color=\"black\">";
static TQString re = "</font></nobr></td></tr>\n";
static TQString cs = "</font></nobr>:</td><td><nobr><font color=\"black\">";
unsigned int val = 0;
for (it=entries.begin();it!=entries.end();++it) {
if (val>0) {
text+="<hline>";
}
text+="<p align=\"center\">";
text+="<table cellspacing=0 cellpadding=0>";
if ((*it).Name().length()) {
text+=rb+i18n("Name")+cs+((*it).Name())+re;
}
if (all) {
text+=rb+i18n("URL")+cs+((*it).url())+re;
if ((*it).reposRoot().length()) {
text+=rb+i18n("Canonical repository url")+cs+((*it).reposRoot())+re;
}
if ((*it).checksum().length()) {
text+=rb+i18n("Checksum")+cs+((*it).checksum())+re;
}
}
text+=rb+i18n("Type")+cs;
switch ((*it).kind()) {
case svn_node_none:
text+=i18n("Absent");
break;
case svn_node_file:
text+=i18n("File");
break;
case svn_node_dir:
text+=i18n("Folder");
break;
case svn_node_unknown:
default:
text+=i18n("Unknown");
break;
}
text+=re;
if (all) {
text+=rb+i18n("Schedule")+cs;
switch ((*it).Schedule()) {
case svn_wc_schedule_normal:
text+=i18n("Normal");
break;
case svn_wc_schedule_add:
text+=i18n("Addition");
break;
case svn_wc_schedule_delete:
text+=i18n("Deletion");
break;
case svn_wc_schedule_replace:
text+=i18n("Replace");
break;
default:
text+=i18n("Unknown");
break;
}
text+=re;
text+=rb+i18n("UUID")+cs+((*it).uuid())+re;
}
text+=rb+i18n("Last author")+cs+((*it).cmtAuthor())+re;
if ((*it).cmtDate()>0) {
text+=rb+i18n("Last committed")+cs+helpers::sub2qt::DateTime2qtString((*it).cmtDate())+re;
}
text+=rb+i18n("Last revision")+cs+(*it).cmtRev().toString()+re;
if ((*it).textTime()>0) {
text+=rb+i18n("Content last changed")+cs+helpers::sub2qt::DateTime2qtString((*it).textTime())+re;
}
if (all) {
if ((*it).propTime()>0) {
text+=rb+i18n("Property last changed")+cs+helpers::sub2qt::DateTime2qtString((*it).propTime())+re;
}
if ((*it).conflictNew().length()) {
text+=rb+i18n("New version of conflicted file")+cs+((*it).conflictNew())+re;
}
if ((*it).conflictOld().length()) {
text+=rb+i18n("Old version of conflicted file")+cs+((*it).conflictOld())+re;
}
if ((*it).conflictWrk().length()) {
text+=rb+i18n("Working version of conflicted file")+
cs+((*it).conflictWrk())+re;
}
if ((*it).prejfile().length()) {
text+=rb+i18n("Property reject file")+
cs+((*it).prejfile())+re;
}
if ((*it).copyfromUrl().length()) {
text+=rb+i18n("Copy from URL")+cs+((*it).copyfromUrl())+re;
}
if ((*it).lockEntry().Locked()) {
text+=rb+i18n("Lock token")+cs+((*it).lockEntry().Token())+re;
text+=rb+i18n("Owner")+cs+((*it).lockEntry().Owner())+re;
text+=rb+i18n("Locked on")+cs+
helpers::sub2qt::DateTime2qtString((*it).lockEntry().Date())+
re;
text+=rb+i18n("Lock comment")+cs+
(*it).lockEntry().Comment()+re;
} else {
svn::SharedPointer<svn::Status> d;
if (checkReposLockCache(_what,d)&& d && d->lockEntry().Locked()) {
text+=rb+i18n("Lock token")+cs+(d->lockEntry().Token())+re;
text+=rb+i18n("Owner")+cs+(d->lockEntry().Owner())+re;
text+=rb+i18n("Locked on")+cs+
helpers::sub2qt::DateTime2qtString(d->lockEntry().Date())+
re;
text+=rb+i18n("Lock comment")+cs+
d->lockEntry().Comment()+re;
}
}
}
text+="</table></p>\n";
}
return text;
}
void SvnActions::makeInfo(TQPtrList<SvnItem> lst,const svn::Revision&rev,const svn::Revision&peg,bool recursive)
{
TQStringList l;
TQString res = "<html><head></head><body>";
SvnItem*item;
for (item=lst.first();item;item=lst.next()) {
TQString text = getInfo(item->fullName(),rev,peg,recursive,true);
if (!text.isEmpty()) {
res+="<h4 align=\"center\">"+item->fullName()+"</h4>";
res+=text;
}
}
res+="</body></html>";
KTextBrowser*ptr;
KDialogBase*dlg = createDialog(&ptr,TQString(i18n("Infolist")),false,"info_dialog");
if (dlg) {
ptr->setText(res);
dlg->exec();
dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"info_dialog",false);
delete dlg;
}
}
void SvnActions::makeInfo(const TQStringList&lst,const svn::Revision&rev,const svn::Revision&peg,bool recursive)
{
TQString text = "";
for (unsigned int i=0; i < lst.count();++i) {
TQString res = getInfo(lst[i],rev,peg,recursive,true);
if (!res.isEmpty()) {
text+="<h4 align=\"center\">"+lst[i]+"</h4>";
text+=res;
}
}
text = "<html><head></head><body>"+text+"</body></html>";
KTextBrowser*ptr;
KDialogBase*dlg = createDialog(&ptr,TQString(i18n("Infolist")),false,"info_dialog");
if (dlg) {
ptr->setText(text);
dlg->exec();
dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"info_dialog",false);
delete dlg;
}
}
/*!
\fn SvnActions::slotProperties()
*/
void SvnActions::slotProperties()
{
/// @todo remove reference to parentlist
if (!m_Data->m_CurrentContext) return;
if (!m_Data->m_ParentList) return;
SvnItem*k = m_Data->m_ParentList->Selected();
if (!k) return;
PropertiesDlg dlg(k,svnclient(),
m_Data->m_ParentList->isWorkingCopy()?svn::Revision::WORKING:svn::Revision::HEAD);
connect(&dlg,TQT_SIGNAL(clientException(const TQString&)),m_Data->m_ParentList->realWidget(),TQT_SLOT(slotClientException(const TQString&)));
dlg.resize(dlg.configDialogSize(*(Kdesvnsettings::self()->config()), "properties_dlg"));
if (dlg.exec()!=TQDialog::Accepted) {
return;
}
dlg.saveDialogSize(*(Kdesvnsettings::self()->config()),"properties_dlg",false);
TQString ex;
svn::PropertiesMap setList;
TQValueList<TQString> delList;
dlg.changedItems(setList,delList);
changeProperties(setList,delList,k->fullName());
k->refreshStatus();
EMIT_FINISHED;
}
bool SvnActions::changeProperties(const svn::PropertiesMap&setList,const TQValueList<TQString>&delList,const TQString&path)
{
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,"Applying properties","<center>Applying<br>hit cancel for abort</center>");
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
unsigned int pos;
for (pos = 0; pos<delList.size();++pos) {
m_Data->m_Svnclient->propdel(delList[pos],svn::Path(path));
}
svn::PropertiesMap::ConstIterator it;
for (it=setList.begin(); it!=setList.end();++it) {
m_Data->m_Svnclient->propset(it.key(),it.data(),svn::Path(path));
}
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
return true;
}
/*!
\fn SvnActions::slotCommit()
*/
void SvnActions::slotCommit()
{
if (!m_Data->m_CurrentContext||!m_Data->m_ParentList->isWorkingCopy()) {
return;
}
TQPtrList<SvnItem> which;
m_Data->m_ParentList->SelectionList(&which);
SvnItem*cur;
TQPtrListIterator<SvnItem> liter(which);
svn::Pathes targets;
if (which.count()==0) {
targets.push_back(svn::Path("."));
} else {
while ( (cur=liter.current())!=0) {
++liter;
targets.push_back(svn::Path(
m_Data->m_ParentList->relativePath(cur)
));
}
}
if (m_Data->m_ParentList->baseUri().length()>0) {
chdir(m_Data->m_ParentList->baseUri().local8Bit());
}
if (makeCommit(targets) && Kdesvnsettings::log_cache_on_open()) {
startFillCache(m_Data->m_ParentList->baseUri());
}
}
bool SvnActions::makeCommit(const svn::Targets&targets)
{
bool ok,keeplocks;
svn::Depth depth;
svn::Revision nnum;
svn::Targets _targets;
svn::Pathes _deldir;
bool review = Kdesvnsettings::review_commit();
TQString msg,_p;
if (!doNetworking()) {
emit clientException(i18n("Not commiting because networking is disabled"));
return false;
}
stopFillCache();
if (!review) {
msg = Logmsg_impl::getLogmessage(&ok,&depth,&keeplocks,
m_Data->m_ParentList->realWidget(),"logmsg_impl");
if (!ok) {
return false;
}
_targets = targets;
} else {
Logmsg_impl::logActionEntries _check,_uncheck,_result;
svn::StatusEntries _Cache;
depth=svn::DepthEmpty;
/// @todo filter out double entries
for (unsigned j = 0; j < targets.size(); ++j) {
svn::Revision where = svn::Revision::HEAD;
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Status / List"),i18n("Creating list / check status"));
_Cache = m_Data->m_Svnclient->status(targets.target(j).path(),svn::DepthInfinity,false,false,false,where);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
for (unsigned int i = 0; i < _Cache.count();++i) {
_p = _Cache[i]->path();
if (_Cache[i]->isRealVersioned()&& (
_Cache[i]->textStatus()==svn_wc_status_modified||
_Cache[i]->textStatus()==svn_wc_status_added||
_Cache[i]->textStatus()==svn_wc_status_replaced||
_Cache[i]->textStatus()==svn_wc_status_deleted||
_Cache[i]->propStatus()==svn_wc_status_modified
) ) {
if (_Cache[i]->textStatus()==svn_wc_status_deleted) {
_check.append(Logmsg_impl::logActionEntry(_p,i18n("Delete"),Logmsg_impl::logActionEntry::DELETE));
} else {
_check.append(Logmsg_impl::logActionEntry(_p,i18n("Commit"),Logmsg_impl::logActionEntry::COMMIT));
}
} else if (_Cache[i]->textStatus()==svn_wc_status_missing) {
_uncheck.append(Logmsg_impl::logActionEntry(_p,i18n("Delete and Commit"),Logmsg_impl::logActionEntry::MISSING_DELETE));
} else if (!_Cache[i]->isVersioned()) {
_uncheck.append(Logmsg_impl::logActionEntry(_p,i18n("Add and Commit"),Logmsg_impl::logActionEntry::ADD_COMMIT));
}
}
}
msg = Logmsg_impl::getLogmessage(_check,_uncheck,this,_result,&ok,&keeplocks,
m_Data->m_ParentList->realWidget(),"logmsg_impl");
if (!ok||_result.count()==0) {
return false;
}
svn::Pathes _add,_commit,_delete;
for (unsigned int i=0; i < _result.count();++i) {
if (_result[i]._kind==Logmsg_impl::logActionEntry::DELETE) {
TQFileInfo fi(_result[i]._name);
if (fi.isDir()) {
depth = svn::DepthInfinity;
}
}
_commit.append(_result[i]._name);
if (_result[i]._kind==Logmsg_impl::logActionEntry::ADD_COMMIT) {
_add.append(_result[i]._name);
} else if (_result[i]._kind==Logmsg_impl::logActionEntry::MISSING_DELETE) {
_delete.append(_result[i]._name);
}
}
if (_add.count()>0) {
if (!addItems(_add,svn::DepthEmpty)) {
return false;
}
}
if (_delete.count()>0) {
makeDelete(_delete);
}
_targets = svn::Targets(_commit);
}
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Commiting"),
i18n("Commiting - hit cancel for abort"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
nnum = m_Data->m_Svnclient->commit(_targets,msg,depth,keeplocks);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
EMIT_REFRESH;
emit sendNotify(i18n("Committed revision %1.").arg(nnum.toString()));
return true;
}
/*!
\fn SvnActions::wroteStdin(TDEProcess*)
*/
void SvnActions::wroteStdin(TDEProcess*proc)
{
if (!proc) return;
kdDebug()<<"void SvnActions::wroteStdin(TDEProcess*proc)"<<endl;
proc->closeStdin();
}
void SvnActions::receivedStderr(TDEProcess*proc,char*buff,int len)
{
if (!proc || !buff || len == 0) {
return;
}
TQString msg(TQCString(buff,len));
emit sendNotify(msg);
}
void SvnActions::procClosed(TDEProcess*proc)
{
if (!proc) return;
TQMap<TDEProcess*,TQStringList>::iterator it;
if ( (it=m_Data->m_tempfilelist.find(proc))!=m_Data->m_tempfilelist.end()) {
for (TQStringList::iterator it2 = (*it).begin();
it2 != (*it).end();++it2) {
::unlink((*it2).ascii());
}
m_Data->m_tempfilelist.erase(it);
}
if ( (it=m_Data->m_tempdirlist.find(proc))!=m_Data->m_tempdirlist.end()) {
for (TQStringList::iterator it2 = (*it).begin();
it2 != (*it).end();++it2) {
TDEIO::NetAccess::del((*it2),0);
}
m_Data->m_tempdirlist.erase(it);
}
delete proc;
}
bool SvnActions::get(const TQString&what,const TQString& to,const svn::Revision&rev,const svn::Revision&peg,TQWidget*p)
{
svn::Revision _peg = peg;
if (_peg == svn::Revision::UNDEFINED) {
_peg = rev;
}
try {
StopDlg sdlg(m_Data->m_SvnContextListener,p?p:m_Data->m_ParentList->realWidget(),0,"Downloading",
i18n("Download - hit cancel for abort"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
m_Data->m_Svnclient->get(svn::Path(what),
to,rev,_peg);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
return true;
}
/*!
\fn SvnActions::makeDiff(const TQString&,const svn::Revision&start,const svn::Revision&end)
*/
void SvnActions::makeDiff(const TQString&what,const svn::Revision&start,const svn::Revision&end,const svn::Revision&_peg,bool isDir)
{
makeDiff(what,start,what,end,_peg,isDir,m_Data->m_ParentList->realWidget());
}
void SvnActions::makeDiff(const TQString&p1,const svn::Revision&start,const TQString&p2,const svn::Revision&end)
{
makeDiff(p1,start,p2,end,(TQWidget*)0);
}
void SvnActions::makeDiff(const TQString&p1,const svn::Revision&start,const TQString&p2,const svn::Revision&end,TQWidget*p)
{
if (!doNetworking()&&start!=svn::Revision::BASE && end!=svn::Revision::WORKING) {
emit sendNotify(i18n("Can not do this diff because networking is disabled."));
kdDebug()<<"No diff 'cause no network"<<endl;
return;
}
if (m_Data->isExternalDiff()) {
kdDebug()<<"External diff..."<<endl;
svn::InfoEntry info;
if (singleInfo(p1,start,info)) {
makeDiff(p1,start,p2,end,end,info.isDir(),p);
}
return;
}
makeDiffinternal(p1,start,p2,end,p);
}
void SvnActions::makeDiffExternal(const TQString&p1,const svn::Revision&start,const TQString&p2,const svn::Revision&end,const svn::Revision&_peg,
bool isDir,TQWidget*p,bool rec)
{
TQString edisp = Kdesvnsettings::external_diff_display();
TQStringList wlist = TQStringList::split(" ",edisp);
TQFileInfo f1(p1);
TQFileInfo f2(p2);
KTempFile tfile(TQString(),f1.fileName()+"-"+start.toString()),tfile2(TQString(),f2.fileName()+"-"+end.toString());
TQString s1 = f1.fileName()+"-"+start.toString();
TQString s2 = f2.fileName()+"-"+end.toString();
KTempDir tdir1;
tdir1.setAutoDelete(true);
tfile.setAutoDelete(true);
tfile2.setAutoDelete(true);
TQString first,second;
svn::Revision peg = _peg;
if (start != svn::Revision::WORKING) {
first = isDir?tdir1.name()+"/"+s1:tfile.name();
} else {
first = p1;
}
if (end!=svn::Revision::WORKING) {
second = isDir?tdir1.name()+"/"+s2:tfile2.name();
} else {
second = p2;
}
if (second == first) {
KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("Both entries seems to be the same, can not diff."));
return;
}
kdDebug()<<"Diff: "<<peg.toString()<<endl;
if (start != svn::Revision::WORKING) {
if (!isDir) {
if (!get(p1,tfile.name(),start,peg,p)) {
return;
}
} else {
if (!makeCheckout(p1,first,start,peg,
rec?svn::DepthInfinity:svn::DepthFiles,true,false,false,false,p)) {
return;
}
}
}
if (end!=svn::Revision::WORKING) {
if (!isDir) {
if (!get(p2,tfile2.name(),end,peg,p)) {
return;
}
} else {
if (!makeCheckout(p2,second,end,peg,
rec?svn::DepthInfinity:svn::DepthFiles,true,false,false,false,p)) {
return;
}
}
}
TDEProcess*proc = new TDEProcess();
for ( TQStringList::Iterator it = wlist.begin();it!=wlist.end();++it) {
if (*it=="%1") {
*proc<<first;
} else if (*it=="%2") {
*proc<<second;
} else {
*proc << *it;
}
}
connect(proc,TQT_SIGNAL(processExited(TDEProcess*)),this,TQT_SLOT(procClosed(TDEProcess*)));
connect(proc,TQT_SIGNAL(receivedStderr(TDEProcess*,char*,int)),this,TQT_SLOT(receivedStderr(TDEProcess*,char*,int)));
connect(proc,TQT_SIGNAL(receivedStdout(TDEProcess*,char*,int)),this,TQT_SLOT(receivedStderr(TDEProcess*,char*,int)));
if (proc->start(m_Data->runblocked?TDEProcess::Block:TDEProcess::NotifyOnExit,TDEProcess::All)) {
if (!m_Data->runblocked) {
if (!isDir) {
tfile2.setAutoDelete(false);
tfile.setAutoDelete(false);
m_Data->m_tempfilelist[proc].append(tfile.name());
m_Data->m_tempfilelist[proc].append(tfile2.name());
} else {
tdir1.setAutoDelete(false);
m_Data->m_tempdirlist[proc].append(tdir1.name());
}
}
return;
} else {
emit sendNotify(i18n("Diff-process could not started, check command."));
}
delete proc;
return;
}
void SvnActions::makeDiff(const TQString&p1,const svn::Revision&start,const TQString&p2,const svn::Revision&end,const svn::Revision&_peg,bool isDir,TQWidget*p)
{
if (m_Data->isExternalDiff()) {
kdDebug()<<"External diff 2..."<<endl;
makeDiffExternal(p1,start,p2,end,_peg,isDir,p);
} else {
makeDiffinternal(p1,start,p2,end,p,_peg);
}
}
void SvnActions::makeDiffinternal(const TQString&p1,const svn::Revision&r1,const TQString&p2,const svn::Revision&r2,TQWidget*p,const svn::Revision&_peg)
{
if (!m_Data->m_CurrentContext) return;
TQByteArray ex;
KTempDir tdir;
tdir.setAutoDelete(true);
TQString tn = TQString("%1/%2").arg(tdir.name()).arg("/svndiff");
bool ignore_content = Kdesvnsettings::diff_ignore_content();
TQWidget*parent = p?p:m_Data->m_ParentList->realWidget();
TQStringList extraOptions;
if (Kdesvnsettings::diff_ignore_spaces())
{
extraOptions.append("-b");
}
if (Kdesvnsettings::diff_ignore_all_white_spaces())
{
extraOptions.append("-w");
}
svn::Revision peg = _peg==svn::Revision::UNDEFINED?r2:_peg;
try {
StopDlg sdlg(m_Data->m_SvnContextListener,parent,0,"Diffing",
i18n("Diffing - hit cancel for abort"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
if (p1==p2 && (r1.isRemote()||r2.isRemote())) {
kdDebug()<<"Pegged diff"<<endl;
ex = m_Data->m_Svnclient->diff_peg(svn::Path(tn),
svn::Path(p1),svn::Path(),r1, r2,peg,
svn::DepthInfinity,false,false,ignore_content,extraOptions,svn::StringArray());
} else {
ex = m_Data->m_Svnclient->diff(svn::Path(tn),
svn::Path(p1),svn::Path(p2),svn::Path(),
r1, r2,
svn::DepthInfinity,false,false,ignore_content,extraOptions,svn::StringArray());
}
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return;
}
EMIT_FINISHED;
if (ex.isEmpty()) {
emit clientException(i18n("No difference to display"));
return;
}
dispDiff(ex);
}
void SvnActions::makeNorecDiff(const TQString&p1,const svn::Revision&r1,const TQString&p2,const svn::Revision&r2,TQWidget*_p)
{
if (!m_Data->m_CurrentContext) return;
if (m_Data->isExternalDiff()) {
svn::InfoEntry info;
if (singleInfo(p1,r1,info)) {
makeDiffExternal(p1,r1,p2,r2,r2,info.isDir(),_p,false);
}
return;
}
TQStringList extraOptions;
if (Kdesvnsettings::diff_ignore_spaces())
{
extraOptions.append("-b");
}
if (Kdesvnsettings::diff_ignore_all_white_spaces())
{
extraOptions.append("-w");
}
TQByteArray ex;
KTempDir tdir;
tdir.setAutoDelete(true);
kdDebug()<<"Non recourse diff"<<endl;
TQString tn = TQString("%1/%2").arg(tdir.name()).arg("/svndiff");
bool ignore_content = Kdesvnsettings::diff_ignore_content();
try {
StopDlg sdlg(m_Data->m_SvnContextListener,_p?_p:m_Data->m_ParentList->realWidget(),0,"Diffing","Diffing - hit cancel for abort");
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
ex = m_Data->m_Svnclient->diff(svn::Path(tn),
svn::Path(p1),svn::Path(p2),svn::Path(),
r1, r2,
svn::DepthEmpty,false,false,ignore_content,extraOptions,svn::StringArray());
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return;
}
EMIT_FINISHED;
if (ex.isEmpty()) {
emit clientException(i18n("No difference to display"));
return;
}
dispDiff(ex);
}
void SvnActions::dispDiff(const TQByteArray&ex)
{
TQString what = Kdesvnsettings::external_diff_display();
int r = TDEProcess::Stdin|TDEProcess::Stderr;
if (Kdesvnsettings::use_external_diff() && (what.find("%1")==-1 || what.find("%2")==-1)) {
TQStringList wlist = TQStringList::split(" ",what);
TDEProcess*proc = new TDEProcess();
bool fname_used = false;
KTempFile tfile;
tfile.setAutoDelete(false);
for ( TQStringList::Iterator it = wlist.begin();it!=wlist.end();++it) {
if (*it=="%f") {
fname_used = true;
TQDataStream*ds = tfile.dataStream();
ds->writeRawBytes(ex,ex.size());
tfile.close();
*proc<<tfile.name();
} else {
*proc << *it;
}
}
connect(proc,TQT_SIGNAL(processExited(TDEProcess*)),this,TQT_SLOT(procClosed(TDEProcess*)));
connect(proc,TQT_SIGNAL(receivedStderr(TDEProcess*,char*,int)),this,TQT_SLOT(receivedStderr(TDEProcess*,char*,int)));
if (!fname_used) {
connect(proc,TQT_SIGNAL(wroteStdin(TDEProcess*)),this,TQT_SLOT(wroteStdin(TDEProcess*)));
}
if (proc->start(TDEProcess::NotifyOnExit,fname_used?TDEProcess::Stderr:(TDEProcess::Communication)r)) {
if (!fname_used) proc->writeStdin(ex,ex.size());
else m_Data->m_tempfilelist[proc].append(tfile.name());
return;
} else {
emit sendNotify(i18n("Display-process could not started, check command."));
}
delete proc;
}
bool need_modal = m_Data->runblocked||TQT_TQWIDGET(TDEApplication::activeModalWidget())!=0;
if (need_modal||!m_Data->m_DiffBrowserPtr||!m_Data->m_DiffDialog) {
DiffBrowser*ptr;
if (!need_modal && m_Data->m_DiffBrowserPtr) {
delete m_Data->m_DiffBrowserPtr;
}
KDialogBase*dlg = createDialog(&ptr,TQString(i18n("Diff display")),false,
"diff_display",false,need_modal,
KStdGuiItem::saveAs());
if (dlg) {
TQWidget*wd = dlg->mainWidget();
if (wd) {
EncodingSelector_impl * ls = new EncodingSelector_impl("",wd);
TQObject::connect(ls,TQT_SIGNAL(TextCodecChanged(const TQString&)),
ptr,TQT_SLOT(slotTextCodecChanged(const TQString&)));
}
TQObject::connect(dlg,TQT_SIGNAL(user1Clicked()),ptr,TQT_SLOT(saveDiff()));
ptr->setText(ex);
if (need_modal) {
ptr->setFocus();
dlg->exec();
dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"diff_display",false);
delete dlg;
return;
} else {
m_Data->m_DiffBrowserPtr=ptr;
m_Data->m_DiffDialog=dlg;
}
}
} else {
m_Data->m_DiffBrowserPtr->setText(ex);
m_Data->m_DiffBrowserPtr->setFocus();
}
if (m_Data->m_DiffDialog) {
m_Data->m_DiffDialog->show();
m_Data->m_DiffDialog->raise();
}
}
/*!
\fn SvnActions::makeUpdate(const TQString&what,const svn::Revision&rev,bool recurse)
*/
void SvnActions::makeUpdate(const TQStringList&what,const svn::Revision&rev,bool recurse)
{
if (!m_Data->m_CurrentContext) return;
TQString ex;
svn::Revisions ret;
stopCheckUpdateThread();
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,"Making update",
i18n("Making update - hit cancel for abort"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
svn::Targets pathes(what);
ret = m_Data->m_Svnclient->update(pathes,rev, recurse?svn::DepthInfinity:svn::DepthFiles,false,false,true);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return;
}
removeFromUpdateCache(what,!recurse);
EMIT_REFRESH;
EMIT_FINISHED;
}
/*!
\fn SvnActions::slotUpdateHeadRec()
*/
void SvnActions::slotUpdateHeadRec()
{
prepareUpdate(false);
}
/*!
\fn SvnActions::prepareUpdate(bool ask)
*/
void SvnActions::prepareUpdate(bool ask)
{
if (!m_Data->m_ParentList||!m_Data->m_ParentList->isWorkingCopy()) return;
SvnItemList k;
m_Data->m_ParentList->SelectionList(&k);
TQStringList what;
if (k.count()==0) {
what.append(m_Data->m_ParentList->baseUri());
} else {
SvnItemListIterator liter(k);
SvnItem*cur;
while ((cur=liter.current())!=0){
++liter;
what.append(cur->fullName());
}
}
svn::Revision r(svn::Revision::HEAD);
if (ask) {
Rangeinput_impl*rdlg;
KDialog*dlg = createDialog(&rdlg,TQString(i18n("Revisions")),true);
if (!dlg) {
return;
}
rdlg->setStartOnly(true);
/* just here cause layout has changed meanwhile */
dlg->resize( TQSize(120,60).expandedTo(dlg->minimumSizeHint()) );
int result;
if ((result=dlg->exec())==TQDialog::Accepted) {
Rangeinput_impl::revision_range range = rdlg->getRange();
r=range.first;
}
delete dlg;
if (result!=TQDialog::Accepted) return;
}
makeUpdate(what,r,true);
}
/*!
\fn SvnActions::slotUpdateTo()
*/
void SvnActions::slotUpdateTo()
{
prepareUpdate(true);
}
/*!
\fn SvnActions::slotAdd()
*/
void SvnActions::slotAdd()
{
makeAdd(false);
}
void SvnActions::slotAddRec()
{
makeAdd(true);
}
void SvnActions::makeAdd(bool rec)
{
if (!m_Data->m_CurrentContext) return;
if (!m_Data->m_ParentList) return;
TQPtrList<SvnItem> lst;
m_Data->m_ParentList->SelectionList(&lst);
if (lst.count()==0) {
KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("Which files or directories should I add?"));
return;
}
TQValueList<svn::Path> items;
SvnItemListIterator liter(lst);
SvnItem*cur;
while ((cur=liter.current())!=0){
++liter;
if (cur->isVersioned()) {
KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("<center>The entry<br>%1<br>is versioned - break.</center>")
.arg(cur->fullName()));
return;
}
items.push_back(svn::Path(cur->fullName()));
}
addItems(items,rec?svn::DepthInfinity:svn::DepthEmpty);
liter.toFirst();
#if 0
while ((cur=liter.current())!=0){
++liter;
//cur->refreshStatus();
//emit sigRefreshCurrent(static_cast<FileListViewItem*>(cur->parent()));
}
#else
emit sigRefreshCurrent(0);
#endif
}
bool SvnActions::addItems(const TQStringList&w,svn::Depth depth)
{
TQValueList<svn::Path> items;
for (unsigned int i = 0; i<w.count();++i) {
items.push_back(w[i]);
}
return addItems(items,depth);
}
bool SvnActions::addItems(const TQValueList<svn::Path> &items,svn::Depth depth)
{
TQString ex;
try {
TQValueList<svn::Path>::const_iterator piter;
for (piter=items.begin();piter!=items.end();++piter) {
m_Data->m_Svnclient->add((*piter),depth);
}
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
return true;
}
bool SvnActions::makeDelete(const TQStringList&w)
{
int answer = KMessageBox::questionYesNoList(0,i18n("Really delete these entries?"),w,i18n("Delete from repository"));
if (answer!=KMessageBox::Yes) {
return false;
}
svn::Pathes items;
for (unsigned int i = 0; i<w.count();++i) {
items.push_back(w[i]);
}
return makeDelete(items);
}
/*!
\fn SvnActions::makeDelete()
*/
bool SvnActions::makeDelete(const svn::Pathes&items)
{
if (!m_Data->m_CurrentContext) return false;
TQString ex;
try {
svn::Targets target(items);
m_Data->m_Svnclient->remove(target,false);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
EMIT_FINISHED;
return true;
}
void SvnActions::slotCheckout()
{
CheckoutExport(false);
}
void SvnActions::slotExport()
{
CheckoutExport(true);
}
void SvnActions::slotCheckoutCurrent()
{
CheckoutExportCurrent(false);
}
void SvnActions::slotExportCurrent()
{
CheckoutExportCurrent(true);
}
void SvnActions::CheckoutExport(bool _exp)
{
CheckoutInfo_impl*ptr;
KDialogBase * dlg = createDialog(&ptr,(_exp?i18n("Export repository"):i18n("Checkout a repository")),true,"checkout_export_dialog");
if (dlg) {
if (dlg->exec()==TQDialog::Accepted) {
svn::Revision r = ptr->toRevision();
bool openit = ptr->openAfterJob();
bool ignoreExternal=ptr->ignoreExternals();
makeCheckout(ptr->reposURL(),ptr->targetDir(),r,r,
ptr->getDepth(),
_exp,
openit,
ignoreExternal,
ptr->overwrite(),0);
}
dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"checkout_export_dialog",false);
delete dlg;
}
}
void SvnActions::CheckoutExport(const TQString&what,bool _exp,bool urlisTarget)
{
CheckoutInfo_impl*ptr;
KDialog * dlg = createDialog(&ptr,_exp?i18n("Export a repository"):i18n("Checkout a repository"),true);
if (dlg) {
if (!urlisTarget) {
ptr->setStartUrl(what);
} else {
ptr->setTargetUrl(what);
}
if (dlg->exec()==TQDialog::Accepted) {
svn::Revision r = ptr->toRevision();
bool openIt = ptr->openAfterJob();
bool ignoreExternal = ptr->ignoreExternals();
makeCheckout(ptr->reposURL(),ptr->targetDir(),r,r,ptr->getDepth(),_exp,openIt,ignoreExternal,ptr->overwrite(),0);
}
delete dlg;
}
}
void SvnActions::CheckoutExportCurrent(bool _exp)
{
if ( !m_Data->m_ParentList || (!_exp&&m_Data->m_ParentList->isWorkingCopy()) ) return;
SvnItem*k = m_Data->m_ParentList->Selected();
if (k && !k->isDir()) {
KMessageBox::error(m_Data->m_ParentList->realWidget(),_exp?i18n("Exporting a file?"):i18n("Checking out a file?"));
return;
}
TQString what;
if (!k) {
what = m_Data->m_ParentList->baseUri();
} else {
what = k->fullName();
}
CheckoutExport(what,_exp);
}
bool SvnActions::makeCheckout(const TQString&rUrl,const TQString&tPath,const svn::Revision&r,const svn::Revision&_peg,
svn::Depth depth,
// kind of operation
bool _exp,
// open after job
bool openIt,
// ignore externals
bool ignoreExternal,
// overwrite/force not versioned items
bool overwrite,
TQWidget*_p
)
{
TQString fUrl = rUrl;
TQString ex;
while (fUrl.endsWith("/")) {
fUrl.truncate(fUrl.length()-1);
}
svn::Path p(tPath);
svn::Revision peg = _peg;
if (r!=svn::Revision::BASE && r!=svn::Revision::WORKING && _peg==svn::Revision::UNDEFINED) {
peg = r;
}
if (!_exp||!m_Data->m_CurrentContext) reInitClient();
try {
StopDlg sdlg(m_Data->m_SvnContextListener,_p?_p:m_Data->m_ParentList->realWidget(),0,_exp?i18n("Export"):i18n("Checkout"),_exp?i18n("Exporting"):i18n("Checking out"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
if (_exp) {
/// @todo setup parameter for export operation
m_Data->m_Svnclient->doExport(svn::Path(fUrl),p,r,peg,overwrite,TQString(),ignoreExternal,depth);
} else {
m_Data->m_Svnclient->checkout(fUrl,p,r,peg,depth,ignoreExternal,overwrite);
}
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
if (openIt) {
if (!_exp) emit sigGotourl(tPath);
else kapp->invokeBrowser(tPath);
}
EMIT_FINISHED;
return true;
}
void SvnActions::slotRevert()
{
if (!m_Data->m_ParentList||!m_Data->m_ParentList->isWorkingCopy()) return;
TQPtrList<SvnItem> lst;
m_Data->m_ParentList->SelectionList(&lst);
TQStringList displist;
SvnItemListIterator liter(lst);
SvnItem*cur;
if (lst.count()>0) {
while ((cur=liter.current())!=0){
if (!cur->isVersioned()) {
KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("<center>The entry<br>%1<br>is not versioned - break.</center>")
.arg(cur->fullName()));
return;
}
displist.append(cur->fullName());
++liter;
}
} else {
displist.push_back(m_Data->m_ParentList->baseUri());
}
slotRevertItems(displist);
EMIT_REFRESH;
}
void SvnActions::slotRevertItems(const TQStringList&displist)
{
if (!m_Data->m_CurrentContext) return;
if (displist.count()==0) {
return;
}
svn::Depth depth;
RevertFormImpl*ptr;
KDialog * dlg = createDialog(&ptr,i18n("Revert entries"),true);
if (!dlg) {
return;
}
ptr->setDispList(displist);
if (dlg->exec()!=TQDialog::Accepted) {
delete dlg;
return;
}
depth = ptr->getDepth();
TQValueList<svn::Path> items;
for (unsigned j = 0; j<displist.count();++j) {
items.push_back(svn::Path((*(displist.at(j)))));
}
TQString ex;
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Revert"),i18n("Reverting items"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
svn::Targets target(items);
m_Data->m_Svnclient->revert(target,depth);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return;
}
// remove them from cache
for (unsigned int j = 0; j<items.count();++j) {
m_Data->m_Cache.deleteKey(items[j].path(),depth!=svn::DepthInfinity);
// m_Data->m_Cache.dump_tree();
}
EMIT_FINISHED;
}
bool SvnActions::makeSwitch(const TQString&rUrl,const TQString&tPath,const svn::Revision&r,svn::Depth depth,const svn::Revision&peg,bool stickydepth,bool ignore_externals,bool allow_unversioned)
{
if (!m_Data->m_CurrentContext) return false;
TQString fUrl = rUrl;
TQString ex;
while (fUrl.endsWith("/")) {
fUrl.truncate(fUrl.length()-1);
}
svn::Path p(tPath);
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Switch url"),i18n("Switching url"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
m_Data->m_Svnclient->doSwitch(p,fUrl,r,depth,peg,stickydepth,ignore_externals,allow_unversioned);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
EMIT_FINISHED;
return true;
}
bool SvnActions::makeRelocate(const TQString&fUrl,const TQString&tUrl,const TQString&path,bool rec)
{
if (!m_Data->m_CurrentContext) return false;
TQString _f = fUrl;
TQString _t = tUrl;
TQString ex;
while (_f.endsWith("/")) {
_f.truncate(_f.length()-1);
}
while (_t.endsWith("/")) {
_t.truncate(_t.length()-1);
}
svn::Path p(path);
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Relocate url"),i18n("Relocate repository to new URL"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
m_Data->m_Svnclient->relocate(p,_f,_t,rec);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
EMIT_FINISHED;
return true;
}
void SvnActions::slotSwitch()
{
if (!m_Data->m_CurrentContext) return;
if (!m_Data->m_ParentList||!m_Data->m_ParentList->isWorkingCopy()) return;
TQPtrList<SvnItem> lst;
m_Data->m_ParentList->SelectionList(&lst);
if (lst.count()>1) {
KMessageBox::error(0,i18n("Can only switch one item at time"));
return;
}
SvnItem*k;
k = m_Data->m_ParentList->SelectedOrMain();
if (!k) {
KMessageBox::error(0,i18n("Error getting entry to switch"));
return;
}
TQString path,what;
path = k->fullName();
what = k->Url();
if (makeSwitch(path,what)) {
emit reinitItem(k);
}
}
bool SvnActions::makeSwitch(const TQString&path,const TQString&what)
{
CheckoutInfo_impl*ptr;
KDialogBase * dlg = createDialog(&ptr,i18n("Switch url"),true,"switch_url_dlg");
bool done = false;
if (dlg) {
ptr->setStartUrl(what);
ptr->disableAppend(true);
ptr->disableTargetDir(true);
ptr->disableOpen(true);
if (dlg->exec()==TQDialog::Accepted) {
svn::Revision r = ptr->toRevision();
done = makeSwitch(ptr->reposURL(),path,r,ptr->getDepth(),r,true,ptr->ignoreExternals(),ptr->overwrite());
}
dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"switch_url_dlg",false);
delete dlg;
}
return done;
}
bool SvnActions::makeCleanup(const TQString&path)
{
if (!m_Data->m_CurrentContext) return false;
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Cleanup"),i18n("Cleaning up folder"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
m_Data->m_Svnclient->cleanup(svn::Path(path));
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
return true;
}
void SvnActions::slotResolved(const TQString&path)
{
if (!m_Data->m_CurrentContext) return;
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Resolve"),i18n("Marking resolved"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
m_Data->m_Svnclient->resolve(svn::Path(path),svn::DepthEmpty);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return;
}
m_Data->m_conflictCache.deleteKey(path,false);
}
void SvnActions::slotResolve(const TQString&p)
{
if (!m_Data->m_CurrentContext) return;
TQString eresolv = Kdesvnsettings::conflict_resolver();
TQStringList wlist = TQStringList::split(" ",eresolv);
if (wlist.size()==0) {
return;
}
kdDebug()<<"Resolve: "<<p<<endl;
svn::InfoEntry i1;
if (!singleInfo(p,svn::Revision::UNDEFINED,i1)) {
return;
}
TQFileInfo fi(p);
TQString base = fi.dirPath(true);
kdDebug()<<i1.conflictNew()<<" "
<<i1.conflictOld()<<" "
<<i1.conflictWrk()<<" "
<<endl;
if (!i1.conflictNew().length()||
!i1.conflictOld().length()||
!i1.conflictWrk().length() ) {
emit sendNotify(i18n("Could not retrieve conflict information - giving up."));
return;
}
TDEProcess*proc = new TDEProcess();
for ( TQStringList::Iterator it = wlist.begin();it!=wlist.end();++it) {
if (*it=="%o"||*it=="%l") {
*proc<<(base+"/"+i1.conflictOld());
} else if (*it=="%m" || *it=="%w") {
*proc<<(base+"/"+i1.conflictWrk());
} else if (*it=="%n"||*it=="%r") {
*proc<<(base+"/"+i1.conflictNew());
} else if (*it=="%t") {
*proc<<p;
} else {
*proc << *it;
}
}
connect(proc,TQT_SIGNAL(processExited(TDEProcess*)),this,TQT_SLOT(procClosed(TDEProcess*)));
connect(proc,TQT_SIGNAL(receivedStderr(TDEProcess*,char*,int)),this,TQT_SLOT(receivedStderr(TDEProcess*,char*,int)));
connect(proc,TQT_SIGNAL(receivedStdout(TDEProcess*,char*,int)),this,TQT_SLOT(receivedStderr(TDEProcess*,char*,int)));
if (proc->start(m_Data->runblocked?TDEProcess::Block:TDEProcess::NotifyOnExit,TDEProcess::All)) {
return;
} else {
emit sendNotify(i18n("Resolve-process could not started, check command."));
}
delete proc;
return;
}
void SvnActions::slotImport(const TQString&path,const TQString&target,const TQString&message,svn::Depth depth,
bool noIgnore,bool noUnknown)
{
if (!m_Data->m_CurrentContext) return;
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Import"),i18n("Importing items"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
m_Data->m_Svnclient->import(svn::Path(path),target,message,depth,noIgnore,noUnknown);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return;
}
}
void SvnActions::slotMergeExternal(const TQString&_src1,const TQString&_src2, const TQString&_target,
const svn::Revision&rev1,const svn::Revision&rev2,const svn::Revision&_peg,bool rec)
{
KTempDir tdir1;
tdir1.setAutoDelete(true);
TQString src1 = _src1;
TQString src2 = _src2;
TQString target = _target;
bool singleMerge = false;
if (rev1 == rev2 && (src2.isEmpty() || src1==src2) ) {
singleMerge = true;
}
if (src1.isEmpty()) {
emit clientException(i18n("Nothing to merge."));
return;
}
if (target.isEmpty()) {
emit clientException(i18n("No destination to merge."));
return;
}
KURL url(target);
if (!url.isLocalFile()) {
emit clientException(i18n("Target for merge must be local!"));
return;
}
TQFileInfo f1(src1);
TQFileInfo f2(src2);
bool isDir = true;
svn::InfoEntry i1,i2;
if (!singleInfo(src1,rev1,i1)) {
return;
}
isDir = i1.isDir();
if (!singleMerge && src1 != src2) {
if (!singleInfo(src2,rev2,i2)) {
return;
}
if (i2.isDir()!=isDir) {
emit clientException(i18n("Both sources must be same type!"));
return;
}
}
TQFileInfo ti(target);
if (ti.isDir()!=isDir) {
emit clientException(i18n("Target for merge must same type like sources!"));
return;
}
TQString s1 = f1.fileName()+"-"+rev1.toString();
TQString s2 = f2.fileName()+"-"+rev2.toString();
TQString first,second,out;
if (rev1 != svn::Revision::WORKING) {
first = tdir1.name()+"/"+s1;
} else {
first = src1;
}
if (!singleMerge) {
if (rev2!=svn::Revision::WORKING) {
second = tdir1.name()+"/"+s2;
} else {
second = src2;
}
} else {
// only two-way merge
second = TQString();
}
if (second == first) {
KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("Both entries seems to be the same, won't do a merge."));
return;
}
if (rev1 != svn::Revision::WORKING) {
if (isDir) {
if (!makeCheckout(src1,first,rev1,svn::Revision::UNDEFINED,
rec?svn::DepthInfinity:svn::DepthFiles,
true,
false,
false,
false,0)) {
return;
}
} else {
if (!get(src1,first,rev1,svn::Revision::UNDEFINED,m_Data->m_ParentList->realWidget())) {
return;
}
}
}
if (!singleMerge) {
if (rev2!=svn::Revision::WORKING) {
if (isDir) {
if (!makeCheckout(src2,second,rev2,svn::Revision::UNDEFINED,
rec?svn::DepthInfinity:svn::DepthFiles,
true,false,false,false,0)) {
return;
}
} else {
if (!get(src2,second,rev2,svn::Revision::UNDEFINED,m_Data->m_ParentList->realWidget())) {
return;
}
}
}
}
TQString edisp = Kdesvnsettings::external_merge_program();
TQStringList wlist = TQStringList::split(" ",edisp);
TDEProcess*proc = new TDEProcess();
for ( TQStringList::Iterator it = wlist.begin();it!=wlist.end();++it) {
if (*it=="%s1") {
*proc<<first;
} else if (*it=="%s2") {
if (!second.isEmpty()) *proc<<second;
} else if (*it=="%t") {
*proc<<target;
} else {
*proc << *it;
}
}
connect(proc,TQT_SIGNAL(processExited(TDEProcess*)),this,TQT_SLOT(procClosed(TDEProcess*)));
connect(proc,TQT_SIGNAL(receivedStderr(TDEProcess*,char*,int)),this,TQT_SLOT(receivedStderr(TDEProcess*,char*,int)));
if (proc->start(m_Data->runblocked?TDEProcess::Block:TDEProcess::NotifyOnExit,TDEProcess::Stderr)) {
if (!m_Data->runblocked) {
tdir1.setAutoDelete(false);
m_Data->m_tempdirlist[proc].append(tdir1.name());
}
return;
} else {
emit sendNotify(i18n("Merge-process could not started, check command."));
}
delete proc;
}
void SvnActions::slotMergeWcRevisions(const TQString&_entry,const svn::Revision&rev1,
const svn::Revision&rev2,
bool rec,bool ancestry,bool forceIt,bool dry)
{
slotMerge(_entry,_entry,_entry,rev1,rev2,svn::Revision::UNDEFINED,rec,ancestry,forceIt,dry);
}
void SvnActions::slotMerge(const TQString&src1,const TQString&src2, const TQString&target,
const svn::Revision&rev1,const svn::Revision&rev2,const svn::Revision&_peg,
bool rec,bool ancestry,bool forceIt,bool dry)
{
if (!m_Data->m_CurrentContext) return;
TQString s2;
svn::Revision peg = svn::Revision::HEAD;
svn::Revision tpeg;
svn::RevisionRanges ranges;
svn::Path p1;
try {
svn::Path::parsePeg(src1,p1,tpeg);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return;
}
if (tpeg!=svn::Revision::UNDEFINED) {
peg=tpeg;
}
svn::Path p2(src2);
bool pegged_merge=false;
if(!p2.isset() || src1==src2) {
// pegged merge
pegged_merge=true;
ranges.append(svn::RevisionRange(rev1,rev2));
if (peg==svn::Revision::UNDEFINED) {
if (p1.isUrl()) {
peg = rev2;
} else {
peg=svn::Revision::WORKING;
}
}
}
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Merge"),i18n("Merging items"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
if (pegged_merge) {
m_Data->m_Svnclient->merge_peg(p1,ranges,svn::Revision::HEAD,svn::Path(target),rec?svn::DepthUnknown:svn::DepthFiles,
ancestry,dry,forceIt,false);
} else {
m_Data->m_Svnclient->merge(p1,rev1,p2,rev2,
svn::Path(target),
forceIt,rec?svn::DepthUnknown:svn::DepthFiles,ancestry,dry);
}
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return;
}
}
/*!
\fn SvnActions::slotCopyMove(bool,const TQString&,const TQString&)
*/
bool SvnActions::makeMove(const TQString&Old,const TQString&New,bool force)
{
if (!m_Data->m_CurrentContext) return false;
svn::Revision nnum;
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Move"),i18n("Moving/Rename item "));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
nnum = m_Data->m_Svnclient->move(svn::Path(Old),svn::Path(New),force);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
if (nnum != svn::Revision::UNDEFINED) {
emit sendNotify(i18n("Committed revision %1.").arg(nnum.toString()));
}
EMIT_REFRESH;
return true;
}
bool SvnActions::makeMove(const KURL::List&Old,const TQString&New,bool force)
{
svn::Revision nnum;
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Move"),i18n("Moving entries"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
KURL::List::ConstIterator it = Old.begin();
bool local = false;
if ((*it).protocol().isEmpty()) {
local = true;
}
it = Old.begin();
svn::Pathes p;
for (;it!=Old.end();++it) {
p.append((local?(*it).path():(*it).url()));
}
svn::Targets t(p);
svn::Path NPath(New);
m_Data->m_Svnclient->move(t,NPath,force,true,false);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
return true;
}
bool SvnActions::makeCopy(const TQString&Old,const TQString&New,const svn::Revision&rev)
{
if (!m_Data->m_CurrentContext) return false;
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Copy / Move"),i18n("Copy or Moving entries"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
m_Data->m_Svnclient->copy(svn::Path(Old),rev,svn::Path(New));
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
EMIT_REFRESH;
return true;
}
bool SvnActions::makeCopy(const KURL::List&Old,const TQString&New,const svn::Revision&rev)
{
KURL::List::ConstIterator it = Old.begin();
svn::Pathes p;
bool local = false;
if ((*it).protocol().isEmpty()) {
local = true;
}
for (;it!=Old.end();++it) {
p.append((local?(*it).path():(*it).url()));
}
svn::Targets t(p);
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Copy / Move"),i18n("Copy or Moving entries"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
KURL::List::ConstIterator it = Old.begin();
m_Data->m_Svnclient->copy(t,rev,rev,svn::Path(New),true);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
return true;
}
/*!
\fn SvnActions::makeLock(const TQStringList&)
*/
void SvnActions::makeLock(const TQStringList&what,const TQString&_msg,bool breakit)
{
TQValueList<svn::Path> targets;
for (unsigned int i = 0; i<what.count();++i) {
targets.push_back(svn::Path((*(what.at(i)))));
}
if (!m_Data->m_CurrentContext) return;
try {
m_Data->m_Svnclient->lock(svn::Targets(targets),_msg,breakit);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return;
}
}
/*!
\fn SvnActions::makeUnlock(const TQStringList&)
*/
void SvnActions::makeUnlock(const TQStringList&what,bool breakit)
{
TQValueList<svn::Path> targets;
if (!m_Data->m_CurrentContext) return;
for (unsigned int i = 0; i<what.count();++i) {
targets.push_back(svn::Path((*(what.at(i)))));
}
try {
m_Data->m_Svnclient->unlock(svn::Targets(targets),breakit);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return;
}
for (unsigned int i = 0; i<what.count();++i) {
m_Data->m_repoLockCache.deleteKey(*(what.at(i)),true);
}
// m_Data->m_repoLockCache.dump_tree();
}
/*!
\fn SvnActions::makeStatus(const TQString&what, svn::StatusEntries&dlist)
*/
bool SvnActions::makeStatus(const TQString&what, svn::StatusEntries&dlist, svn::Revision&where,bool rec,bool all)
{
bool display_ignores = Kdesvnsettings::display_ignored_files();
return makeStatus(what,dlist,where,rec,all,display_ignores);
}
bool SvnActions::makeStatus(const TQString&what, svn::StatusEntries&dlist, svn::Revision&where,bool rec,bool all,bool display_ignores,bool updates)
{
bool disp_remote_details = Kdesvnsettings::details_on_remote_listing();
TQString ex;
svn::Depth _d=rec?svn::DepthInfinity:svn::DepthImmediates;
try {
StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Status / List"),i18n("Creating list / check status"));
connect(this,TQT_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQT_SLOT(slotExtraMessage(const TQString&)));
// rec all up noign
dlist = m_Data->m_Svnclient->status(what,_d,all,updates,display_ignores,where,disp_remote_details,false);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
return true;
}
void SvnActions::checkAddItems(const TQString&path,bool print_error_box)
{
svn::StatusEntries dlist;
svn::StatusEntries rlist;
TQStringList displist;
svn::Revision where = svn::Revision::HEAD;
if (!makeStatus(path,dlist,where,true,true,false,false)) {
return;
}
for (unsigned int i = 0; i<dlist.size();++i) {
if (!dlist[i]->isVersioned()) {
rlist.append(dlist[i]);
displist.append(dlist[i]->path());
}
}
if (rlist.size()==0) {
if (print_error_box) KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("No unversioned items found."));
} else {
TDEListView*ptr;
KDialogBase * dlg = createDialog(&ptr,i18n("Add unversioned items"),true,"add_items_dlg");
ptr->addColumn("Item");
for (unsigned j = 0; j<displist.size();++j) {
TQCheckListItem * n = new TQCheckListItem(ptr,displist[j],TQCheckListItem::CheckBox);
n->setOn(true);
}
if (dlg->exec()==TQDialog::Accepted) {
TQListViewItemIterator it(ptr);
displist.clear();
while(it.current()) {
TQCheckListItem*t = (TQCheckListItem*)it.current();
if (t->isOn()) {
displist.append(t->text());
}
++it;
}
if (displist.count()>0) {
addItems(displist,svn::DepthEmpty);
}
}
dlg->saveDialogSize(*(Kdesvnsettings::self()->config()),"add_items_dlg",false);
delete dlg;
}
}
void SvnActions::stopCheckModThread()
{
m_Data->m_ThreadCheckTimer.stop();
if (m_CThread) {
m_CThread->cancelMe();
if (!m_CThread->wait(MAX_THREAD_WAITTIME)) {
m_CThread->terminate();
m_CThread->wait(MAX_THREAD_WAITTIME);
}
delete m_CThread;
m_CThread=0;
}
}
void SvnActions::stopCheckUpdateThread()
{
m_Data->m_UpdateCheckTimer.stop();
if (m_UThread) {
m_UThread->cancelMe();
if (!m_UThread->wait(MAX_THREAD_WAITTIME)) {
m_UThread->terminate();
m_UThread->wait(MAX_THREAD_WAITTIME);
}
delete m_UThread;
m_UThread=0;
}
}
void SvnActions::stopFillCache()
{
if (m_FCThread) {
m_FCThread->cancelMe();
if (!m_FCThread->wait(MAX_THREAD_WAITTIME)) {
m_FCThread->terminate();
m_FCThread->wait(MAX_THREAD_WAITTIME);
}
delete m_FCThread;
m_FCThread = 0;
emit sigCacheStatus(-1,-1);
}
}
void SvnActions::stopMain()
{
if (m_Data->m_CurrentContext) {
m_Data->m_SvnContextListener->setCanceled(true);
sleep(1);
m_Data->m_SvnContextListener->contextCancel();
}
}
void SvnActions::killallThreads()
{
stopMain();
stopCheckModThread();
stopCheckUpdateThread();
stopFillCache();
}
bool SvnActions::createModifiedCache(const TQString&what)
{
stopCheckModThread();
m_Data->m_Cache.clear();
m_Data->m_conflictCache.clear();
kdDebug()<<"Create cache for " << what << endl;
m_CThread = new CheckModifiedThread(this,what);
m_CThread->start();
m_Data->m_ThreadCheckTimer.start(100,true);
return true;
}
void SvnActions::checkModthread()
{
if (!m_CThread)return;
if (m_CThread->running()) {
m_Data->m_ThreadCheckTimer.start(100,true);
return;
}
kdDebug()<<"ModifiedThread seems stopped"<<endl;
for (unsigned int i = 0; i < m_CThread->getList().count();++i) {
svn::StatusPtr ptr = m_CThread->getList()[i];
if (m_CThread->getList()[i]->isRealVersioned()&& (
m_CThread->getList()[i]->textStatus()==svn_wc_status_modified||
m_CThread->getList()[i]->textStatus()==svn_wc_status_added||
m_CThread->getList()[i]->textStatus()==svn_wc_status_deleted||
m_CThread->getList()[i]->textStatus()==svn_wc_status_replaced||
m_CThread->getList()[i]->propStatus()==svn_wc_status_modified
) ) {
m_Data->m_Cache.insertKey(ptr,ptr->path());
} else if (m_CThread->getList()[i]->textStatus()==svn_wc_status_conflicted) {
m_Data->m_conflictCache.insertKey(ptr,ptr->path());
}
}
delete m_CThread;
m_CThread = 0;
emit sigRefreshIcons(false);
}
void SvnActions::checkUpdateThread()
{
if (!m_UThread)return;
if (m_UThread->running()) {
if (m_Data->m_UpdateCheckTick.elapsed()>2500) {
m_Data->m_UpdateCheckTick.restart();
emit sendNotify(i18n("Still checking for updates"));
}
m_Data->m_UpdateCheckTimer.start(100,true);
return;
}
kdDebug()<<"Updates Thread seems stopped"<<endl;
bool newer=false;
for (unsigned int i = 0; i < m_UThread->getList().count();++i) {
svn::StatusPtr ptr = m_UThread->getList()[i];
if (ptr->validReposStatus()) {
m_Data->m_UpdateCache.insertKey(ptr,ptr->path());
ptr->textStatus();
ptr->propStatus();
if (!(ptr->validLocalStatus())) {
newer = true;
}
}
if (ptr->isLocked() &&
!(ptr->entry().lockEntry().Locked())) {
m_Data->m_repoLockCache.insertKey(ptr,ptr->path());
}
}
emit sigRefreshIcons(newer);
emit sendNotify(i18n("Checking for updates finished"));
if (newer) {
emit sendNotify(i18n("There are new items in repository"));
}
delete m_UThread;
m_UThread = 0;
}
void SvnActions::getaddedItems(const TQString&path,svn::StatusEntries&target)
{
helpers::ValidRemoteOnly vro;
m_Data->m_UpdateCache.listsubs_if(path,vro);
target=vro.liste();
}
bool SvnActions::checkUpdatesRunning()
{
return m_UThread && m_UThread->running();
}
void SvnActions::addModifiedCache(const svn::StatusPtr&what)
{
if (what->textStatus()==svn_wc_status_conflicted) {
m_Data->m_conflictCache.insertKey(what,what->path());
} else {
m_Data->m_Cache.insertKey(what,what->path());
// m_Data->m_Cache.dump_tree();
}
}
void SvnActions::deleteFromModifiedCache(const TQString&what)
{
m_Data->m_Cache.deleteKey(what,true);
m_Data->m_conflictCache.deleteKey(what,true);
//m_Data->m_Cache.dump_tree();
}
bool SvnActions::checkModifiedCache(const TQString&path)
{
return m_Data->m_Cache.find(path);
}
bool SvnActions::checkReposLockCache(const TQString&path)
{
return m_Data->m_repoLockCache.findSingleValid(path,false);
}
bool SvnActions::checkReposLockCache(const TQString&path,svn::SharedPointer<svn::Status>&t)
{
/// @todo create a method where svn::Status* will be a parameter so no copy is needed but just reading content
return m_Data->m_repoLockCache.findSingleValid(path,t);
}
bool SvnActions::checkConflictedCache(const TQString&path)
{
return m_Data->m_conflictCache.find(path);
}
void SvnActions::startFillCache(const TQString&path)
{
stopFillCache();
svn::InfoEntry e;
if (!doNetworking()) {
emit sendNotify(i18n("Not filling logcache because networking is disabled"));
return;
}
if (!singleInfo(path,svn::Revision::UNDEFINED,e)) {
return;
}
if (svn::Url::isLocal(e.reposRoot())) {
return;
}
m_FCThread=new FillCacheThread(this,e.reposRoot());
m_FCThread->start();
emit sendNotify(i18n("Filling log cache in background"));
}
bool SvnActions::doNetworking()
{
// if networking is allowd we don't need extra checks, second is just for avoiding segfaults
if (Kdesvnsettings::network_on()||!m_Data->m_ParentList) {
return true;
}
bool is_url=false;
if (m_Data->m_ParentList->isNetworked()) {
// if called http:// etc.pp.
is_url=true;
} else if (m_Data->m_ParentList->baseUri().startsWith("/")){
// if opened a working copy we must check if it points to a networking repository
svn::InfoEntry e;
if (!singleInfo(m_Data->m_ParentList->baseUri(),svn::Revision::UNDEFINED,e)) {
return false;
}
is_url = !e.reposRoot().startsWith("file:/");
}
return !is_url;
}
void SvnActions::customEvent(TQCustomEvent * e)
{
if (e->type()==EVENT_LOGCACHE_FINISHED) {
emit sendNotify(i18n("Filling log cache in background finished."));
stopFillCache();
emit sigThreadsChanged();
return;
} else if (e&&e->type()==EVENT_LOGCACHE_STATUS && m_FCThread && m_FCThread->running()) {
FillCacheStatusEvent*fev=(FillCacheStatusEvent*)e;
emit sigCacheStatus(fev->current(),fev->max());
}
}
/*!
\fn SvnActions::createUpdateCache(const TQString&what)
*/
bool SvnActions::createUpdateCache(const TQString&what)
{
clearUpdateCache();
m_Data->m_repoLockCache.clear();
stopCheckUpdateThread();
if (!doNetworking()) {
emit sendNotify(i18n("Not checking for updates because networking is disabled"));
return false;
}
m_UThread = new CheckModifiedThread(this,what,true);
m_UThread->start();
m_Data->m_UpdateCheckTimer.start(100,true);
emit sendNotify(i18n("Checking for updates started in background"));
m_Data->m_UpdateCheckTick.start();
return true;
}
bool SvnActions::checkUpdateCache(const TQString&path)const
{
return m_Data->m_UpdateCache.find(path);
}
void SvnActions::removeFromUpdateCache(const TQStringList&what,bool exact_only)
{
for (unsigned int i = 0; i < what.count(); ++i) {
m_Data->m_UpdateCache.deleteKey(what[i],exact_only);
}
}
bool SvnActions::isUpdated(const TQString&path)const
{
svn::SharedPointer<svn::Status> d;
return m_Data->m_UpdateCache.findSingleValid(path,d);
}
bool SvnActions::getUpdated(const TQString&path,svn::SharedPointer<svn::Status>&d)const
{
return m_Data->m_UpdateCache.findSingleValid(path,d);
}
void SvnActions::clearUpdateCache()
{
m_Data->m_UpdateCache.clear();
}
/*!
\fn SvnActions::makeIgnoreEntry(const TQString&which)
*/
bool SvnActions::makeIgnoreEntry(SvnItem*which,bool unignore)
{
if (!which) return false;
TQString parentName = which->getParentDir();
if (parentName.isEmpty()) return false;
TQString name = which->shortName();
TQString ex;
svn::Path p(parentName);
svn::Revision r(svn_opt_revision_unspecified);
TQPair<TQLONG,svn::PathPropertiesMapList> pmp;
try {
pmp = m_Data->m_Svnclient->propget("svn:ignore",p,r,r);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
svn::PathPropertiesMapList pm = pmp.second;
TQString data = "";
if (pm.size()>0) {
svn::PropertiesMap&mp = pm[0].second;
data = mp["svn:ignore"];
}
bool result = false;
TQStringList lst = TQStringList::split("\n",data);
TQStringList::iterator it = lst.find(name);
if (it != lst.end()) {
if (unignore) {
lst.erase(it);
result = true;
}
} else {
if (!unignore) {
lst.append(name);
result = true;
}
}
if (result) {
data = lst.join("\n");
try {
m_Data->m_Svnclient->propset("svn:ignore",data,p);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
}
return result;
}
svn::PathPropertiesMapListPtr SvnActions::propList(const TQString&which,const svn::Revision&where,bool cacheOnly)
{
svn::PathPropertiesMapListPtr pm;
if (!which.isEmpty()) {
TQString fk=where.toString()+"/"+which;
TQString ex;
svn::Path p(which);
if (where != svn::Revision::WORKING)
{
m_Data->m_PropertiesCache.findSingleValid(fk,pm);
}
if (!pm && !cacheOnly)
{
try {
pm = m_Data->m_Svnclient->proplist(p,where,where);
} catch (const svn::Exception&e) {
/* no messagebox needed */
if (e.apr_err()!=SVN_ERR_WC_NOT_DIRECTORY) {
sendNotify(e.msg());
}
}
if (where != svn::Revision::WORKING && pm) {
kdDebug()<<"Put into cache "<<endl;
m_Data->m_PropertiesCache.insertKey(pm,fk);
}
}
}
return pm;
}
bool SvnActions::isLockNeeded(SvnItem*which,const svn::Revision&where)
{
if (!which) return false;
TQString ex;
svn::Path p(which->fullName());
TQPair<TQLONG,svn::PathPropertiesMapList> pmp;
try {
pmp = m_Data->m_Svnclient->propget("svn:needs-lock",p,where,where);
} catch (const svn::Exception&e) {
/* no messagebox needed */
//emit clientException(e.msg());
return false;
}
svn::PathPropertiesMapList pm = pmp.second;
if (pm.size()>0) {
svn::PropertiesMap&mp = pm[0].second;
if (mp.find("svn:needs-lock")!=mp.end()) {
return true;
}
}
return false;
}
TQString SvnActions::searchProperty(TQString&Store, const TQString&property, const TQString&start,const svn::Revision&where,bool up)
{
svn::Path pa(start);
kdDebug()<<"Url? "<<pa.isUrl()<<endl;
svn::InfoEntry inf;
if (!singleInfo(start,where,inf)) {
return TQString();
}
while(pa.length()>0) {
svn::PathPropertiesMapListPtr pm = propList(pa,where,false);
if (!pm) {
return TQString();
}
if (pm->size()>0) {
svn::PropertiesMap&mp = (*pm)[0].second;
if (mp.find(property)!=mp.end()) {
Store=mp[property];
return pa;
}
}
if (up) {
pa.removeLast();
kdDebug()<<"Going up to " << pa.path() << endl;
if (pa.isUrl() && inf.reposRoot().length()>pa.path().length()) {
kdDebug()<<pa.path()<<" is not in repository" << endl;
break;
}
} else {
break;
}
}
return TQString();
}
bool SvnActions::makeList(const TQString&url,svn::DirEntries&dlist,svn::Revision&where,bool rec)
{
if (!m_Data->m_CurrentContext) return false;
TQString ex;
try {
dlist = m_Data->m_Svnclient->list(url,where,where,rec?svn::DepthInfinity:svn::DepthEmpty,false);
} catch (const svn::Exception&e) {
emit clientException(e.msg());
return false;
}
return true;
}
/*!
\fn SvnActions::isLocalWorkingCopy(const KURL&url)
*/
bool SvnActions::isLocalWorkingCopy(const KURL&url,TQString&_baseUri)
{
if (url.isEmpty()||!url.isLocalFile()) return false;
TQString cleanpath = url.path();
while (cleanpath.endsWith("/")) {
cleanpath.truncate(cleanpath.length()-1);
}
_baseUri="";
svn::Revision peg(svn_opt_revision_unspecified);
svn::Revision rev(svn_opt_revision_unspecified);
svn::InfoEntries e;
try {
e = m_Data->m_Svnclient->info(cleanpath,svn::DepthEmpty,rev,peg);
} catch (const svn::Exception&e) {
kdDebug()<< e.msg()<< " " << endl;
if (SVN_ERR_WC_NOT_DIRECTORY==e.apr_err())
{
return false;
}
return true;
}
_baseUri=e[0].url();
return true;
}
void SvnActions::slotExtraLogMsg(const TQString&msg)
{
emit sigExtraLogMsg(msg);
}
void SvnActions::slotCancel(bool how)
{
if (!m_Data->m_CurrentContext) return;
m_Data->m_SvnContextListener->setCanceled(how);
}
void SvnActions::setContextData(const TQString&aKey,const TQString&aValue)
{
if (aValue.isNull()) {
TQMap<TQString,TQString>::iterator it = m_Data->m_contextData.find(aKey);
if (it!=m_Data->m_contextData.end()) {
m_Data->m_contextData.remove(it);
}
} else {
m_Data->m_contextData[aKey]=aValue;
}
}
void SvnActions::clearContextData()
{
m_Data->m_contextData.clear();
}
TQString SvnActions::getContextData(const TQString&aKey)const
{
if (m_Data->m_contextData.find(aKey)!=m_Data->m_contextData.end()) {
return m_Data->m_contextData[aKey];
}
return TQString();
}
bool SvnActions::threadRunning(ThreadType which)
{
switch(which) {
case checkupdatethread:
return (m_UThread && m_UThread->running());
break;
case fillcachethread:
return (m_FCThread && m_FCThread->running());
break;
case checkmodifiedthread:
return (m_CThread && m_CThread->running());
break;
}
return false;
}
#include "svnactions.moc"