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.
tdesdk/cervisia/cvsservice/cvsservice.cpp

1009 lines
26 KiB

/*
* Copyright (c) 2002-2004 Christian Loose <christian.loose@kdemail.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#include "cvsservice.h"
#include <tqintdict.h>
#include <tqstring.h>
#include <dcopref.h>
#include <dcopclient.h>
#include <kapplication.h>
#include <kconfig.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kprocess.h>
#include "cvsjob.h"
#include "cvsloginjob.h"
#include "cvsserviceutils.h"
#include "repository.h"
#include "sshagent.h"
static const char SINGLE_JOB_ID[] = "NonConcurrentJob";
static const char REDIRECT_STDERR[] = "2>&1";
enum WatchEvents { None=0, All=1, Commits=2, Edits=4, Unedits=8 };
struct CvsService::Private
{
Private() : singleCvsJob(0), lastJobId(0), repository(0) {}
~Private()
{
delete repository;
delete singleCvsJob;
}
CvsJob* singleCvsJob; // non-concurrent cvs job, like update or commit
DCOPRef singleJobRef; // DCOP reference to non-concurrent cvs job
TQIntDict<CvsJob> cvsJobs; // concurrent cvs jobs, like diff or annotate
TQIntDict<CvsLoginJob> loginJobs;
unsigned lastJobId;
TQCString appId; // cache the DCOP clients app id
Repository* repository;
CvsJob* createCvsJob();
DCOPRef setupNonConcurrentJob(Repository* repo = 0);
bool hasWorkingCopy();
bool hasRunningJob();
};
CvsService::CvsService()
: DCOPObject("CvsService")
, d(new Private)
{
d->appId = kapp->dcopClient()->appId();
// create non-concurrent cvs job
d->singleCvsJob = new CvsJob(SINGLE_JOB_ID);
d->singleJobRef.setRef(d->appId, d->singleCvsJob->objId());
// create repository manager
d->repository = new Repository();
d->cvsJobs.setAutoDelete(true);
d->loginJobs.setAutoDelete(true);
KConfig* config = kapp->config();
KConfigGroupSaver cs(config, "General");
if( config->readBoolEntry("UseSshAgent", false) )
{
// use the existing or start a new ssh-agent
SshAgent ssh;
// TODO CL do we need the return value?
//bool res = ssh.querySshAgent();
ssh.querySshAgent();
}
}
CvsService::~CvsService()
{
// kill the ssh-agent (when we started it)
SshAgent ssh;
ssh.killSshAgent();
d->cvsJobs.clear();
d->loginJobs.clear();
delete d;
}
DCOPRef CvsService::add(const TQStringList& files, bool isBinary)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs add [-kb] [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "add";
if( isBinary )
*d->singleCvsJob << "-kb";
*d->singleCvsJob << CvsServiceUtils::joinFileList(files) << REDIRECT_STDERR;
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::addWatch(const TQStringList& files, int events)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "watch add";
if( events != All )
{
if( events & Commits )
*d->singleCvsJob << "-a commit";
if( events & Edits )
*d->singleCvsJob << "-a edit";
if( events & Unedits )
*d->singleCvsJob << "-a unedit";
}
*d->singleCvsJob << CvsServiceUtils::joinFileList(files);
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::annotate(const TQString& fileName, const TQString& revision)
{
if( !d->hasWorkingCopy() )
return DCOPRef();
// create a cvs job
CvsJob* job = d->createCvsJob();
// assemble the command line
// (cvs log [FILE] && cvs annotate [-r rev] [FILE])
TQString quotedName = KProcess::quote(fileName);
TQString cvsClient = d->repository->cvsClient();
*job << "(" << cvsClient << "log" << quotedName << "&&"
<< cvsClient << "annotate";
if( !revision.isEmpty() )
*job << "-r" << revision;
// *Hack*
// because the string "Annotations for blabla" is
// printed to stderr even with option -Q.
*job << quotedName << ")" << REDIRECT_STDERR;
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::checkout(const TQString& workingDir, const TQString& repository,
const TQString& module, const TQString& tag,
bool pruneDirs)
{
if( d->hasRunningJob() )
return DCOPRef();
Repository repo(repository);
// assemble the command line
// cd [DIRECTORY] && cvs -d [REPOSITORY] checkout [-r tag] [-P] [MODULE]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << "cd" << KProcess::quote(workingDir) << "&&"
<< repo.cvsClient()
<< "-d" << repository
<< "checkout";
if( !tag.isEmpty() )
*d->singleCvsJob << "-r" << tag;
if( pruneDirs )
*d->singleCvsJob << "-P";
*d->singleCvsJob << module;
return d->setupNonConcurrentJob(&repo);
}
DCOPRef CvsService::checkout(const TQString& workingDir, const TQString& repository,
const TQString& module, const TQString& tag,
bool pruneDirs, const TQString& alias, bool exportOnly)
{
if( d->hasRunningJob() )
return DCOPRef();
Repository repo(repository);
// assemble the command line
// cd [DIRECTORY] && cvs -d [REPOSITORY] co [-r tag] [-P] [-d alias] [MODULE]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << "cd" << KProcess::quote(workingDir) << "&&"
<< repo.cvsClient()
<< "-d" << repository;
if( exportOnly)
*d->singleCvsJob << "export";
else
*d->singleCvsJob << "checkout";
if( !tag.isEmpty() )
*d->singleCvsJob << "-r" << tag;
if( pruneDirs && !exportOnly )
*d->singleCvsJob << "-P";
if( !alias.isEmpty() )
*d->singleCvsJob << "-d" << alias;
*d->singleCvsJob << module;
return d->setupNonConcurrentJob(&repo);
}
DCOPRef CvsService::checkout(const TQString& workingDir, const TQString& repository,
const TQString& module, const TQString& tag,
bool pruneDirs, const TQString& alias, bool exportOnly,
bool recursive)
{
if( d->hasRunningJob() )
return DCOPRef();
Repository repo(repository);
// assemble the command line
// cd [DIRECTORY] && cvs -d [REPOSITORY] co [-r tag] [-P] [-d alias] [MODULE]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << "cd" << KProcess::quote(workingDir) << "&&"
<< repo.cvsClient()
<< "-d" << repository;
if( exportOnly)
*d->singleCvsJob << "export";
else
*d->singleCvsJob << "checkout";
if( !tag.isEmpty() )
*d->singleCvsJob << "-r" << tag;
if( pruneDirs && !exportOnly )
*d->singleCvsJob << "-P";
if( !alias.isEmpty() )
*d->singleCvsJob << "-d" << alias;
if( ! recursive )
*d->singleCvsJob << "-l";
*d->singleCvsJob << module;
return d->setupNonConcurrentJob(&repo);
}
DCOPRef CvsService::commit(const TQStringList& files, const TQString& commitMessage,
bool recursive)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs commit [-l] [-m MESSAGE] [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "commit";
if( !recursive )
*d->singleCvsJob << "-l";
*d->singleCvsJob << "-m" << KProcess::quote(commitMessage)
<< CvsServiceUtils::joinFileList(files) << REDIRECT_STDERR;
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::createRepository(const TQString& repository)
{
if( d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs -d [REPOSITORY] init
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << "mkdir -p" << KProcess::quote(repository) << "&&"
<< d->repository->cvsClient()
<< "-d" << KProcess::quote(repository)
<< "init";
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::createTag(const TQStringList& files, const TQString& tag,
bool branch, bool force)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs tag [-b] [-F] [TAG] [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "tag";
if( branch )
*d->singleCvsJob << "-b";
if( force )
*d->singleCvsJob << "-F";
*d->singleCvsJob << KProcess::quote(tag)
<< CvsServiceUtils::joinFileList(files);
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::deleteTag(const TQStringList& files, const TQString& tag,
bool branch, bool force)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs tag -d [-b] [-F] [TAG] [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "tag" << "-d";
if( branch )
*d->singleCvsJob << "-b";
if( force )
*d->singleCvsJob << "-F";
*d->singleCvsJob << KProcess::quote(tag)
<< CvsServiceUtils::joinFileList(files);
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::downloadCvsIgnoreFile(const TQString& repository,
const TQString& outputFile)
{
Repository repo(repository);
// create a cvs job
CvsJob* job = d->createCvsJob();
// assemble the command line
// cvs -d [REPOSITORY] -q checkout -p CVSROOT/cvsignore > [OUTPUTFILE]
*job << repo.cvsClient() << "-d" << repository
<< "-q checkout -p CVSROOT/cvsignore >"
<< KProcess::quote(outputFile);
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::downloadRevision(const TQString& fileName,
const TQString& revision,
const TQString& outputFile)
{
if( !d->hasWorkingCopy() )
return DCOPRef();
// create a cvs job
CvsJob* job = d->createCvsJob();
// assemble the command line
// cvs update -p -r [REV] [FILE] > [OUTPUTFILE]
*job << d->repository->cvsClient() << "update -p";
if( !revision.isEmpty() )
*job << "-r" << KProcess::quote(revision);
*job << KProcess::quote(fileName) << ">" << KProcess::quote(outputFile);
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::downloadRevision(const TQString& fileName,
const TQString& revA,
const TQString& outputFileA,
const TQString& revB,
const TQString& outputFileB)
{
if( !d->hasWorkingCopy() )
return DCOPRef();
// create a cvs job
CvsJob* job = d->createCvsJob();
// assemble the command line
// cvs update -p -r [REVA] [FILE] > [OUTPUTFILEA] ;
// cvs update -p -r [REVB] [FILE] > [OUTPUTFILEB]
*job << d->repository->cvsClient() << "update -p"
<< "-r" << KProcess::quote(revA)
<< KProcess::quote(fileName) << ">" << KProcess::quote(outputFileA)
<< ";" << d->repository->cvsClient() << "update -p"
<< "-r" << KProcess::quote(revB)
<< KProcess::quote(fileName) << ">" << KProcess::quote(outputFileB);
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::diff(const TQString& fileName, const TQString& revA,
const TQString& revB, const TQString& diffOptions,
unsigned contextLines)
{
// cvs diff [DIFFOPTIONS] -U CONTEXTLINES [-r REVA] {-r REVB] [FILE]
TQString format = "-U" + TQString::number(contextLines);
return diff(fileName, revA, revB, diffOptions, format);
}
DCOPRef CvsService::diff(const TQString& fileName, const TQString& revA,
const TQString& revB, const TQString& diffOptions,
const TQString& format)
{
if( !d->hasWorkingCopy() )
return DCOPRef();
// create a cvs job
CvsJob* job = d->createCvsJob();
// assemble the command line
// cvs diff [DIFFOPTIONS] [FORMAT] [-r REVA] {-r REVB] [FILE]
*job << d->repository->cvsClient() << "diff" << diffOptions
<< format;
if( !revA.isEmpty() )
*job << "-r" << KProcess::quote(revA);
if( !revB.isEmpty() )
*job << "-r" << KProcess::quote(revB);
*job << KProcess::quote(fileName);
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::edit(const TQStringList& files)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs edit [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "edit"
<< CvsServiceUtils::joinFileList(files);
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::editors(const TQStringList& files)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs editors [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "editors"
<< CvsServiceUtils::joinFileList(files);
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::history()
{
if( !d->hasWorkingCopy() )
return DCOPRef();
// create a cvs job
CvsJob* job = d->createCvsJob();
// assemble the command line
// cvs history -e -a
*job << d->repository->cvsClient() << "history -e -a";
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::import(const TQString& workingDir, const TQString& repository,
const TQString& module, const TQString& ignoreList,
const TQString& comment, const TQString& vendorTag,
const TQString& releaseTag, bool importAsBinary)
{
if( d->hasRunningJob() )
return DCOPRef();
Repository repo(repository);
// assemble the command line
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << "cd" << KProcess::quote(workingDir) << "&&"
<< repo.cvsClient()
<< "-d" << repository
<< "import";
if( importAsBinary )
*d->singleCvsJob << "-kb";
const TQString ignore = ignoreList.stripWhiteSpace();
if( !ignore.isEmpty() )
*d->singleCvsJob << "-I" << KProcess::quote(ignore);
TQString logMessage = comment.stripWhiteSpace();
logMessage.prepend("\"");
logMessage.append("\"");
*d->singleCvsJob << "-m" << logMessage;
*d->singleCvsJob << module << vendorTag << releaseTag;
return d->setupNonConcurrentJob(&repo);
}
DCOPRef CvsService::import(const TQString& workingDir, const TQString& repository,
const TQString& module, const TQString& ignoreList,
const TQString& comment, const TQString& vendorTag,
const TQString& releaseTag, bool importAsBinary,
bool useModificationTime)
{
if( d->hasRunningJob() )
return DCOPRef();
Repository repo(repository);
// assemble the command line
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << "cd" << KProcess::quote(workingDir) << "&&"
<< repo.cvsClient()
<< "-d" << repository
<< "import";
if( importAsBinary )
*d->singleCvsJob << "-kb";
if( useModificationTime )
*d->singleCvsJob << "-d";
const TQString ignore = ignoreList.stripWhiteSpace();
if( !ignore.isEmpty() )
*d->singleCvsJob << "-I" << KProcess::quote(ignore);
TQString logMessage = comment.stripWhiteSpace();
logMessage.prepend("\"");
logMessage.append("\"");
*d->singleCvsJob << "-m" << logMessage;
*d->singleCvsJob << module << vendorTag << releaseTag;
return d->setupNonConcurrentJob(&repo);
}
DCOPRef CvsService::lock(const TQStringList& files)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs admin -l [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "admin -l"
<< CvsServiceUtils::joinFileList(files);
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::log(const TQString& fileName)
{
if( !d->hasWorkingCopy() )
return DCOPRef();
// create a cvs job
CvsJob* job = d->createCvsJob();
// assemble the command line
// cvs log [FILE]
*job << d->repository->cvsClient() << "log" << KProcess::quote(fileName);
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::login(const TQString& repository)
{
if( repository.isEmpty() )
return DCOPRef();
Repository repo(repository);
// create a cvs job
++(d->lastJobId);
CvsLoginJob* job = new CvsLoginJob(d->lastJobId);
d->loginJobs.insert(d->lastJobId, job);
// TODO: CVS_SERVER doesn't work ATM
// job->setServer(repo.server());
// assemble the command line
// cvs -d [REPOSITORY] login
job->setCvsClient(repo.clientOnly().local8Bit());
job->setRepository(repository.local8Bit());
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::logout(const TQString& repository)
{
if( repository.isEmpty() )
return DCOPRef();
Repository repo(repository);
// create a cvs job
++(d->lastJobId);
CvsJob* job = new CvsJob(d->lastJobId);
d->cvsJobs.insert(d->lastJobId, job);
job->setRSH(repo.rsh());
job->setServer(repo.server());
job->setDirectory(repo.workingCopy());
// assemble the command line
// cvs -d [REPOSITORY] logout
*job << repo.cvsClient() << "-d" << repository << "logout";
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::makePatch()
{
return makePatch("", "-u");
}
DCOPRef CvsService::makePatch(const TQString& diffOptions, const TQString& format)
{
if( !d->hasWorkingCopy() )
return DCOPRef();
// create a cvs job
CvsJob* job = d->createCvsJob();
// assemble the command line
// cvs diff [DIFFOPTIONS] [FORMAT] -R 2>/dev/null
*job << d->repository->cvsClient() << "diff" << diffOptions << format << "-R"
<< "2>/dev/null";
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::moduleList(const TQString& repository)
{
Repository repo(repository);
// create a cvs job
++(d->lastJobId);
CvsJob* job = new CvsJob(d->lastJobId);
d->cvsJobs.insert(d->lastJobId, job);
job->setRSH(repo.rsh());
job->setServer(repo.server());
job->setDirectory(repo.workingCopy());
// assemble the command line
// cvs -d [REPOSITORY] checkout -c
*job << repo.cvsClient() << "-d" << repository << "checkout -c";
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::remove(const TQStringList& files, bool recursive)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs remove -f [-l] [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "remove -f";
if( !recursive )
*d->singleCvsJob << "-l";
*d->singleCvsJob << CvsServiceUtils::joinFileList(files) << REDIRECT_STDERR;
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::removeWatch(const TQStringList& files, int events)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "watch remove";
if( events != All )
{
if( events & Commits )
*d->singleCvsJob << "-a commit";
if( events & Edits )
*d->singleCvsJob << "-a edit";
if( events & Unedits )
*d->singleCvsJob << "-a unedit";
}
*d->singleCvsJob << CvsServiceUtils::joinFileList(files);
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::rlog(const TQString& repository, const TQString& module,
bool recursive)
{
Repository repo(repository);
// create a cvs job
++(d->lastJobId);
CvsJob* job = new CvsJob(d->lastJobId);
d->cvsJobs.insert(d->lastJobId, job);
job->setRSH(repo.rsh());
job->setServer(repo.server());
// assemble the command line
// cvs -d [REPOSITORY] rlog [-l] [MODULE]
*job << repo.cvsClient() << "-d" << repository << "rlog";
if( !recursive )
*job << "-l";
*job << module;
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::simulateUpdate(const TQStringList& files, bool recursive,
bool createDirs, bool pruneDirs)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs -n update [-l] [-d] [-P] [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "-n -q update";
if( !recursive )
*d->singleCvsJob << "-l";
if( createDirs )
*d->singleCvsJob << "-d";
if( pruneDirs )
*d->singleCvsJob << "-P";
*d->singleCvsJob << CvsServiceUtils::joinFileList(files) << REDIRECT_STDERR;
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::status(const TQStringList& files, bool recursive, bool tagInfo)
{
if( !d->hasWorkingCopy() )
return DCOPRef();
// create a cvs job
CvsJob* job = d->createCvsJob();
// assemble the command line
// cvs status [-l] [-v] [FILES]
*job << d->repository->cvsClient() << "status";
if( !recursive )
*job << "-l";
if( tagInfo )
*job << "-v";
*job << CvsServiceUtils::joinFileList(files);
// return a DCOP reference to the cvs job
return DCOPRef(d->appId, job->objId());
}
DCOPRef CvsService::unedit(const TQStringList& files)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// echo y | cvs unedit [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << "echo y |"
<< d->repository->cvsClient() << "unedit"
<< CvsServiceUtils::joinFileList(files);
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::unlock(const TQStringList& files)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs admin -u [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "admin -u"
<< CvsServiceUtils::joinFileList(files);
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::update(const TQStringList& files, bool recursive,
bool createDirs, bool pruneDirs, const TQString& extraOpt)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs update [-l] [-d] [-P] [EXTRAOPTIONS] [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "-q update";
if( !recursive )
*d->singleCvsJob << "-l";
if( createDirs )
*d->singleCvsJob << "-d";
if( pruneDirs )
*d->singleCvsJob << "-P";
*d->singleCvsJob << extraOpt << CvsServiceUtils::joinFileList(files)
<< REDIRECT_STDERR;
return d->setupNonConcurrentJob();
}
DCOPRef CvsService::watchers(const TQStringList& files)
{
if( !d->hasWorkingCopy() || d->hasRunningJob() )
return DCOPRef();
// assemble the command line
// cvs watchers [FILES]
d->singleCvsJob->clearCvsCommand();
*d->singleCvsJob << d->repository->cvsClient() << "watchers"
<< CvsServiceUtils::joinFileList(files);
return d->setupNonConcurrentJob();
}
void CvsService::quit()
{
kapp->quit();
}
CvsJob* CvsService::Private::createCvsJob()
{
++lastJobId;
// create a cvs job
CvsJob* job = new CvsJob(lastJobId);
cvsJobs.insert(lastJobId, job);
job->setRSH(repository->rsh());
job->setServer(repository->server());
job->setDirectory(repository->workingCopy());
return job;
}
DCOPRef CvsService::Private::setupNonConcurrentJob(Repository* repo)
{
// no explicit repository provided?
if( !repo )
repo = repository;
singleCvsJob->setRSH(repo->rsh());
singleCvsJob->setServer(repo->server());
singleCvsJob->setDirectory(repo->workingCopy());
return singleJobRef;
}
bool CvsService::Private::hasWorkingCopy()
{
if( repository->workingCopy().isEmpty() )
{
KMessageBox::sorry(0, i18n("You have to set a local working copy "
"directory before you can use this function!"));
return false;
}
return true;
}
bool CvsService::Private::hasRunningJob()
{
bool result = singleCvsJob->isRunning();
if( result )
KMessageBox::sorry(0, i18n("There is already a job running"));
return result;
}