/*************************************************************************** * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // wait not longer than 10 seconds for a thread #define MAX_THREAD_WAITTIME 10000 class SvnActionsData:public svn::ref_count { typedef svn::SharedPointer 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::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 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 m_PropertiesCache; /// \todo as persistent cache (sqlite?) helpers::itemCache m_InfoCache; TQMap m_tempfilelist; TQMap m_tempdirlist; TQTimer m_ThreadCheckTimer; TQTimer m_UpdateCheckTimer; TQTime m_UpdateCheckTick; TQGuardedPtr m_DiffBrowserPtr; TQGuardedPtr m_DiffDialog; TQGuardedPtr m_LogDialog; TQMap 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,TQ_SIGNAL(sendNotify(const TQString&)),this,TQ_SLOT(slotNotifyMessage(const TQString&))); connect(&(m_Data->m_ThreadCheckTimer),TQ_SIGNAL(timeout()),this,TQ_SLOT(checkModthread())); connect(&(m_Data->m_UpdateCheckTimer),TQ_SIGNAL(timeout()),this,TQ_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 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?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 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 logs = new svn::LogEntriesMap; if (!m_Data->m_CurrentContext) return 0; bool follow = Kdesvnsettings::log_follows_nodes(); kdDebug()<<"Get logs for "<< which<m_SvnContextListener,(parent?parent:m_Data->m_ParentList->realWidget()),0,"Logs", i18n("Getting logs - hit cancel for abort")); connect(this,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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 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()<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: "<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 "<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,TQ_SIGNAL(makeNorecDiff(const TQString&,const svn::Revision&,const TQString&,const svn::Revision&,TQWidget*)), this,TQ_SLOT(makeNorecDiff(const TQString&,const svn::Revision&,const TQString&,const svn::Revision&,TQWidget*)) ); connect( disp,TQ_SIGNAL(makeRecDiff(const TQString&,const svn::Revision&,const TQString&,const svn::Revision&,TQWidget*)), this,TQ_SLOT(makeDiff(const TQString&,const svn::Revision&,const TQString&,const svn::Revision&,TQWidget*)) ); connect(disp,TQ_SIGNAL(makeCat(const svn::Revision&, const TQString&,const TQString&,const svn::Revision&,TQWidget*)), this,TQ_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..."< logs = getLog(start,end,peg,which,list_files,limit); if (!logs) return; bool need_modal = m_Data->runblocked||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,TQ_SIGNAL(makeDiff(const TQString&,const svn::Revision&,const TQString&,const svn::Revision&,TQWidget*)), this,TQ_SLOT(makeDiff(const TQString&,const svn::Revision&,const TQString&,const svn::Revision&,TQWidget*))); connect(m_Data->m_LogDialog,TQ_SIGNAL(makeCat(const svn::Revision&, const TQString&,const TQString&,const svn::Revision&,TQWidget*)), this,TQ_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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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 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+="

"+item->fullName()+"

"; 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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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 = ""; static TQString re = "\n"; static TQString cs = ":"; unsigned int val = 0; for (it=entries.begin();it!=entries.end();++it) { if (val>0) { text+=""; } text+="

"; text+=""; 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 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+="

\n"; } return text; } void SvnActions::makeInfo(TQPtrList lst,const svn::Revision&rev,const svn::Revision&peg,bool recursive) { TQStringList l; TQString res = ""; SvnItem*item; for (item=lst.first();item;item=lst.next()) { TQString text = getInfo(item->fullName(),rev,peg,recursive,true); if (!text.isEmpty()) { res+="

"+item->fullName()+"

"; res+=text; } } res+=""; 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+="

"+lst[i]+"

"; text+=res; } } text = ""+text+""; 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,TQ_SIGNAL(clientException(const TQString&)),m_Data->m_ParentList->realWidget(),TQ_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 delList; dlg.changedItems(setList,delList); changeProperties(setList,delList,k->fullName()); k->refreshStatus(); EMIT_FINISHED; } bool SvnActions::changeProperties(const svn::PropertiesMap&setList,const TQValueList&delList,const TQString&path) { try { StopDlg sdlg(m_Data->m_SvnContextListener,m_Data->m_ParentList->realWidget(),0,"Applying properties","
Applying
hit cancel for abort
"); connect(this,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_SLOT(slotExtraMessage(const TQString&))); unsigned int pos; for (pos = 0; posm_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 which; m_Data->m_ParentList->SelectionList(&which); SvnItem*cur; TQPtrListIterator 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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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)"<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::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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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"<isExternalDiff()) { kdDebug()<<"External diff..."<m_ParentList->realWidget(),i18n("Both entries seems to be the same, can not diff.")); return; } kdDebug()<<"Diff: "<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..."<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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_SLOT(slotExtraMessage(const TQString&))); if (p1==p2 && (r1.isRemote()||r2.isRemote())) { kdDebug()<<"Pegged diff"<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"<m_SvnContextListener,_p?_p:m_Data->m_ParentList->realWidget(),0,"Diffing","Diffing - hit cancel for abort"); connect(this,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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<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||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,TQ_SIGNAL(TextCodecChanged(const TQString&)), ptr,TQ_SLOT(slotTextCodecChanged(const TQString&))); } TQObject::connect(dlg,TQ_SIGNAL(user1Clicked()),ptr,TQ_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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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 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 items; SvnItemListIterator liter(lst); SvnItem*cur; while ((cur=liter.current())!=0){ ++liter; if (cur->isVersioned()) { KMessageBox::error(m_Data->m_ParentList->realWidget(),i18n("
The entry
%1
is versioned - break.
") .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(cur->parent())); } #else emit sigRefreshCurrent(0); #endif } bool SvnActions::addItems(const TQStringList&w,svn::Depth depth) { TQValueList items; for (unsigned int i = 0; i &items,svn::Depth depth) { TQString ex; try { TQValueList::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; im_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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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 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("
The entry
%1
is not versioned - break.
") .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 items; for (unsigned j = 0; jm_SvnContextListener,m_Data->m_ParentList->realWidget(),0,i18n("Revert"),i18n("Reverting items")); connect(this,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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; jm_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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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 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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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: "<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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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<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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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 targets; for (unsigned int i = 0; im_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 targets; if (!m_Data->m_CurrentContext) return; for (unsigned int i = 0; im_Svnclient->unlock(svn::Targets(targets),breakit); } catch (const svn::Exception&e) { emit clientException(e.msg()); return; } for (unsigned int i = 0; im_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,TQ_SIGNAL(sigExtraLogMsg(const TQString&)),&sdlg,TQ_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; iisVersioned()) { 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; jsetOn(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"<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"<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&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 d; return m_Data->m_UpdateCache.findSingleValid(path,d); } bool SvnActions::getUpdated(const TQString&path,svn::SharedPointer&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 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 "<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 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? "<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()<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::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"