2011-06-05 17:58:02 +03:00
/**************************************************************************
* *
2013-01-28 17:12:19 +01:00
* * Copyright ( c ) 2013 AudioCodes Ltd .
2011-06-05 17:58:02 +03:00
* * Author : Orgad Shaneh < orgad . shaneh @ audiocodes . com >
2012-10-02 09:12:39 +02:00
* * Contact : http : //www.qt-project.org/legal
2011-06-05 17:58:02 +03:00
* *
2012-10-02 09:12:39 +02:00
* * This file is part of Qt Creator .
2011-06-05 17:58:02 +03:00
* *
2012-10-02 09:12:39 +02:00
* * Commercial License Usage
* * Licensees holding valid commercial Qt licenses may use this file in
* * accordance with the commercial license agreement provided with the
* * Software or , alternatively , in accordance with the terms contained in
* * a written agreement between you and Digia . For licensing terms and
* * conditions see http : //qt.digia.com/licensing. For further information
* * use the contact form at http : //qt.digia.com/contact-us.
2011-06-05 17:58:02 +03:00
* *
* * GNU Lesser General Public License Usage
2012-10-02 09:12:39 +02:00
* * Alternatively , this file may be used under the terms of the GNU Lesser
* * General Public License version 2.1 as published by the Free Software
* * Foundation and appearing in the file LICENSE . LGPL included in the
* * packaging of this file . Please review the following information to
* * ensure the GNU Lesser General Public License version 2.1 requirements
* * will be met : http : //www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
* *
* * In addition , as a special exception , Digia gives you certain additional
* * rights . These rights are described in the Digia Qt LGPL Exception
2011-06-05 17:58:02 +03:00
* * version 1.1 , included in the file LGPL_EXCEPTION . txt in this package .
* *
2012-10-02 09:12:39 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-06-05 17:58:02 +03:00
2013-03-12 11:53:14 +01:00
# include "clearcaseplugin.h"
2011-06-05 17:58:02 +03:00
# include "activityselector.h"
# include "checkoutdialog.h"
# include "clearcaseconstants.h"
# include "clearcasecontrol.h"
# include "clearcaseeditor.h"
# include "clearcasesubmiteditor.h"
# include "clearcasesubmiteditorwidget.h"
2012-09-02 10:20:32 +03:00
# include "clearcasesync.h"
2011-06-05 17:58:02 +03:00
# include "settingspage.h"
# include "versionselector.h"
# include "ui_undocheckout.h"
# include <coreplugin/actionmanager/actioncontainer.h>
# include <coreplugin/actionmanager/actionmanager.h>
# include <coreplugin/actionmanager/command.h>
# include <coreplugin/coreconstants.h>
# include <coreplugin/documentmanager.h>
# include <coreplugin/editormanager/editormanager.h>
# include <coreplugin/icore.h>
# include <coreplugin/messagemanager.h>
# include <coreplugin/mimedatabase.h>
# include <coreplugin/progressmanager/progressmanager.h>
# include <locator/commandlocator.h>
# include <projectexplorer/projectexplorer.h>
# include <projectexplorer/project.h>
# include <projectexplorer/iprojectmanager.h>
# include <utils/synchronousprocess.h>
# include <utils/parameteraction.h>
# include <utils/fileutils.h>
2012-08-23 15:53:58 +02:00
# include <utils/hostosinfo.h>
2011-06-05 17:58:02 +03:00
# include <utils/qtcassert.h>
# include <utils/runextensions.h>
# include <vcsbase/basevcseditorfactory.h>
# include <vcsbase/basevcssubmiteditorfactory.h>
# include <vcsbase/vcsbaseeditor.h>
# include <vcsbase/vcsbaseeditorparameterwidget.h>
# include <vcsbase/vcsbaseoutputwindow.h>
# include <vcsbase/vcsbasesubmiteditor.h>
# include <QAction>
# include <QDebug>
# include <QDialog>
# include <QDialogButtonBox>
# include <QDir>
# include <QFileInfo>
# include <QFuture>
# include <QFutureInterface>
# include <QInputDialog>
# include <QList>
# include <QMainWindow>
# include <QMenu>
# include <QMessageBox>
2012-11-12 16:48:26 +02:00
# include <QMetaObject>
2011-06-05 17:58:02 +03:00
# include <QMutex>
# include <QProcess>
2012-09-24 11:39:34 +02:00
# include <QRegExp>
2011-06-05 17:58:02 +03:00
# include <QSharedPointer>
2012-09-24 11:39:34 +02:00
# include <QtConcurrentRun>
# include <QTemporaryFile>
# include <QTextCodec>
# include <QtPlugin>
2011-06-05 17:58:02 +03:00
# include <QUrl>
# include <QUuid>
# include <QVariant>
# include <QVBoxLayout>
# include <QXmlStreamReader>
2013-01-19 23:19:38 +02:00
# ifdef WITH_TESTS
# include <QTest>
# endif
2011-06-05 17:58:02 +03:00
2013-08-30 09:22:42 +02:00
using namespace Core ;
using namespace ProjectExplorer ;
2011-06-05 17:58:02 +03:00
namespace ClearCase {
namespace Internal {
static const char CMD_ID_CLEARCASE_MENU [ ] = " ClearCase.Menu " ;
static const char CMD_ID_CHECKOUT [ ] = " ClearCase.CheckOut " ;
static const char CMD_ID_CHECKIN [ ] = " ClearCase.CheckInCurrent " ;
static const char CMD_ID_UNDOCHECKOUT [ ] = " ClearCase.UndoCheckOut " ;
static const char CMD_ID_UNDOHIJACK [ ] = " ClearCase.UndoHijack " ;
static const char CMD_ID_DIFF_CURRENT [ ] = " ClearCase.DiffCurrent " ;
static const char CMD_ID_HISTORY_CURRENT [ ] = " ClearCase.HistoryCurrent " ;
static const char CMD_ID_ANNOTATE [ ] = " ClearCase.Annotate " ;
static const char CMD_ID_ADD_FILE [ ] = " ClearCase.AddFile " ;
static const char CMD_ID_DIFF_ACTIVITY [ ] = " ClearCase.DiffActivity " ;
static const char CMD_ID_CHECKIN_ACTIVITY [ ] = " ClearCase.CheckInActivity " ;
static const char CMD_ID_UPDATEINDEX [ ] = " ClearCase.UpdateIndex " ;
static const char CMD_ID_UPDATE_VIEW [ ] = " ClearCase.UpdateView " ;
static const char CMD_ID_CHECKIN_ALL [ ] = " ClearCase.CheckInAll " ;
static const char CMD_ID_STATUS [ ] = " ClearCase.Status " ;
static const VcsBase : : VcsBaseEditorParameters editorParameters [ ] = {
{
2013-05-22 21:03:37 +03:00
VcsBase : : LogOutput ,
2011-06-05 17:58:02 +03:00
" ClearCase File Log Editor " , // id
QT_TRANSLATE_NOOP ( " VCS " , " ClearCase File Log Editor " ) , // display_name
" ClearCase File Log Editor " , // context
2013-05-21 23:37:47 +03:00
" text/vnd.qtcreator.clearcase.log " } ,
2011-06-05 17:58:02 +03:00
{ VcsBase : : AnnotateOutput ,
" ClearCase Annotation Editor " , // id
QT_TRANSLATE_NOOP ( " VCS " , " ClearCase Annotation Editor " ) , // display_name
" ClearCase Annotation Editor " , // context
2013-05-21 23:37:47 +03:00
" text/vnd.qtcreator.clearcase.annotation " } ,
2011-06-05 17:58:02 +03:00
{ VcsBase : : DiffOutput ,
" ClearCase Diff Editor " , // id
QT_TRANSLATE_NOOP ( " VCS " , " ClearCase Diff Editor " ) , // display_name
" ClearCase Diff Editor " , // context
2013-05-21 20:54:26 +03:00
" text/x-patch " }
2011-06-05 17:58:02 +03:00
} ;
// Utility to find a parameter set by type
static inline const VcsBase : : VcsBaseEditorParameters * findType ( int ie )
{
const VcsBase : : EditorContentType et = static_cast < VcsBase : : EditorContentType > ( ie ) ;
return VcsBase : : VcsBaseEditorWidget : : findType ( editorParameters , sizeof ( editorParameters ) / sizeof ( VcsBase : : VcsBaseEditorParameters ) , et ) ;
}
static inline QString debugCodec ( const QTextCodec * c )
{
2012-09-21 13:54:38 +02:00
return c ? QString : : fromLatin1 ( c - > name ( ) ) : QString : : fromLatin1 ( " Null codec " ) ;
2011-06-05 17:58:02 +03:00
}
// ------------- ClearCasePlugin
ClearCasePlugin * ClearCasePlugin : : m_clearcasePluginInstance = 0 ;
2012-11-30 11:36:35 +02:00
ViewData : : ViewData ( ) :
isDynamic ( false ) ,
isUcm ( false )
{
}
2011-06-05 17:58:02 +03:00
ClearCasePlugin : : ClearCasePlugin ( ) :
m_commandLocator ( 0 ) ,
m_checkOutAction ( 0 ) ,
m_checkInCurrentAction ( 0 ) ,
m_undoCheckOutAction ( 0 ) ,
m_undoHijackAction ( 0 ) ,
m_diffCurrentAction ( 0 ) ,
m_historyCurrentAction ( 0 ) ,
m_annotateCurrentAction ( 0 ) ,
m_addFileAction ( 0 ) ,
m_diffActivityAction ( 0 ) ,
m_updateIndexAction ( 0 ) ,
m_updateViewAction ( 0 ) ,
m_checkInActivityAction ( 0 ) ,
m_checkInAllAction ( 0 ) ,
m_statusAction ( 0 ) ,
m_checkInSelectedAction ( 0 ) ,
m_checkInDiffAction ( 0 ) ,
m_submitUndoAction ( 0 ) ,
m_submitRedoAction ( 0 ) ,
m_menuAction ( 0 ) ,
2012-09-02 10:18:56 +03:00
m_submitActionTriggered ( false ) ,
2012-09-02 10:20:32 +03:00
m_activityMutex ( new QMutex ) ,
m_statusMap ( new StatusMap )
2013-11-20 11:59:34 +01:00
# ifdef WITH_TESTS
, m_fakeClearTool ( false )
# endif
2011-06-05 17:58:02 +03:00
{
2012-09-02 10:20:32 +03:00
qRegisterMetaType < ClearCase : : Internal : : FileStatus : : Status > ( " ClearCase::Internal::FileStatus::Status " ) ;
2011-06-05 17:58:02 +03:00
}
ClearCasePlugin : : ~ ClearCasePlugin ( )
{
cleanCheckInMessageFile ( ) ;
// wait for sync thread to finish reading activities
2012-09-02 10:18:56 +03:00
m_activityMutex - > lock ( ) ;
m_activityMutex - > unlock ( ) ;
delete m_activityMutex ;
2011-06-05 17:58:02 +03:00
}
void ClearCasePlugin : : cleanCheckInMessageFile ( )
{
if ( ! m_checkInMessageFileName . isEmpty ( ) ) {
QFile : : remove ( m_checkInMessageFileName ) ;
m_checkInMessageFileName . clear ( ) ;
2012-09-12 09:27:06 +03:00
m_checkInView . clear ( ) ;
2011-06-05 17:58:02 +03:00
}
}
bool ClearCasePlugin : : isCheckInEditorOpen ( ) const
{
return ! m_checkInMessageFileName . isEmpty ( ) ;
}
2013-04-18 22:25:23 +02:00
/// Files in this directories are under ClearCase control
QStringList ClearCasePlugin : : getVobList ( ) const
2013-02-03 23:30:22 +02:00
{
2013-04-18 22:25:23 +02:00
QStringList args ( QLatin1String ( " lsvob " ) ) ;
args < < QLatin1String ( " -s " ) ;
const ClearCaseResponse response =
runCleartool ( currentState ( ) . topLevel ( ) , args , m_settings . timeOutMS ( ) , SilentRun ) ;
return response . stdOut . split ( QLatin1Char ( ' \n ' ) , QString : : SkipEmptyParts ) ;
}
/// Get the drive letter of a path
/// Necessary since QDir(directory).rootPath() returns C:/ in all cases
QString ClearCasePlugin : : getDriveLetterOfPath ( const QString & directory )
{
// cdUp until we get just the drive letter
QDir dir ( directory ) ;
2013-12-03 08:15:44 +02:00
while ( ! dir . isRoot ( ) & & dir . cdUp ( ) )
2013-04-18 22:25:23 +02:00
{ }
return dir . path ( ) ;
}
2013-12-05 13:30:20 +01:00
void ClearCasePlugin : : updateStatusForFile ( const QString & absFile )
{
setStatus ( absFile , getFileStatus ( absFile ) , false ) ;
}
FileStatus : : Status ClearCasePlugin : : getFileStatus ( const QString & fileName ) const
{
QTC_CHECK ( ! fileName . isEmpty ( ) ) ;
const QDir viewRootDir = QFileInfo ( fileName ) . dir ( ) ;
const QString viewRoot = viewRootDir . path ( ) ;
QStringList args ( QLatin1String ( " ls " ) ) ;
args < < fileName ;
QString buffer = runCleartoolSync ( viewRoot , args ) ;
const int atatpos = buffer . indexOf ( QLatin1String ( " @@ " ) ) ;
2013-11-20 12:55:23 +01:00
if ( atatpos ! = - 1 ) { // probably a managed file
2013-12-05 13:30:20 +01:00
const QString absFile =
viewRootDir . absoluteFilePath (
QDir : : fromNativeSeparators ( buffer . left ( atatpos ) ) ) ;
QTC_CHECK ( QFile ( absFile ) . exists ( ) ) ;
QTC_CHECK ( ! absFile . isEmpty ( ) ) ;
2013-11-20 12:55:23 +01:00
// "cleartool ls" of a derived object looks like this:
// /path/to/file/export/MyFile.h@@--11-13T19:52.266580
const QChar c = buffer . at ( atatpos + 2 ) ;
const bool isDerivedObject = c ! = QLatin1Char ( ' / ' ) & & c ! = QLatin1Char ( ' \\ ' ) ;
if ( isDerivedObject )
return FileStatus : : Derived ;
// find first whitespace. anything before that is not interesting
const int wspos = buffer . indexOf ( QRegExp ( QLatin1String ( " \\ s " ) ) ) ;
2013-12-05 13:30:20 +01:00
if ( buffer . lastIndexOf ( QLatin1String ( " CHECKEDOUT " ) , wspos ) ! = - 1 )
return FileStatus : : CheckedOut ;
else
return FileStatus : : CheckedIn ;
} else {
QTC_CHECK ( QFile ( fileName ) . exists ( ) ) ;
QTC_CHECK ( ! fileName . isEmpty ( ) ) ;
return FileStatus : : NotManaged ;
}
}
2013-04-18 22:25:23 +02:00
///
/// Check if the directory is managed by ClearCase.
///
/// There are 6 cases to consider for accessing ClearCase views:
///
/// 1) Windows: dynamic view under M:\<view_tag> (working dir view)
/// 2) Windows: dynamic view under Z:\ (similar to unix "set view" by using "subst" or "net use")
/// 3) Windows: snapshot view
/// 4) Unix: dynamic view under /view/<view_tag> (working dir view)
/// 5) Unix: dynamic view which are set view (transparent access in a shell process)
/// 6) Unix: snapshot view
///
/// Note: the drive letters M: and Z: can be chosen by the user. /view is the "view-root"
/// directory and is not configurable, while VOB names and mount points are configurable
/// by the ClearCase admin.
///
/// Note: All cases except #5 have a root directory, i.e., all files reside under a directory.
/// For #5 files are "mounted" and access is transparent (e.g., under /vobs).
///
/// For a view named "myview" and a VOB named "vobA" topLevels would be:
/// 1) M:/myview/vobA
/// 2) Z:/vobA
/// 3) c:/snapshots/myview/vobA
/// 4) /view/myview/vobs/vobA
/// 5) /vobs/vobA/
/// 6) /home/<username>/snapshots/myview/vobs/vobA
///
/// Note: The VOB directory is used as toplevel although the directory one up could have been
/// used on cases execpt 5. For case 5 it would have been /, which we don't want.
///
/// "cleartool pwv" returns the values for "set view" and "working directory view", also for
/// snapshot views.
///
/// \returns The ClearCase topLevel/VOB directory for this directory
QString ClearCasePlugin : : ccManagesDirectory ( const QString & directory ) const
{
QStringList args ( QLatin1String ( " pwv " ) ) ;
const ClearCaseResponse response =
runCleartool ( directory , args , m_settings . timeOutMS ( ) , SilentRun ) ;
if ( response . error )
return QString ( ) ;
const QStringList result = response . stdOut . split ( QLatin1Char ( ' \n ' ) , QString : : SkipEmptyParts ) ;
if ( result . size ( ) ! = 2 )
return QString ( ) ;
const QByteArray workingDirPattern ( " Working directory view: " ) ;
if ( ! result [ 0 ] . startsWith ( QLatin1String ( workingDirPattern ) ) )
return QString ( ) ;
const QString workingDirectoryView = result [ 0 ] . mid ( workingDirPattern . size ( ) ) ;
const QByteArray setViewDirPattern ( " Set view: " ) ;
if ( ! result [ 1 ] . startsWith ( QLatin1String ( setViewDirPattern ) ) )
return QString ( ) ;
const QString setView = result [ 1 ] . mid ( setViewDirPattern . size ( ) ) ;
const QString none ( QLatin1String ( " ** NONE ** " ) ) ;
QString rootDir ;
if ( setView ! = none | | workingDirectoryView ! = none )
rootDir = ccViewRoot ( directory ) ;
else
return QString ( ) ;
// Check if the directory is inside one of the known VOBs.
static QStringList vobs ;
if ( vobs . empty ( ) )
vobs = getVobList ( ) ;
2013-02-03 23:30:22 +02:00
2013-04-18 22:25:23 +02:00
foreach ( const QString & relativeVobDir , vobs ) {
const QString vobPath = QDir : : cleanPath ( rootDir + QDir : : fromNativeSeparators ( relativeVobDir ) ) ;
const bool isManaged = Utils : : FileName : : fromString ( directory ) . isChildOf ( Utils : : FileName : : fromString ( vobPath ) ) ;
if ( isManaged )
return vobPath ;
}
2013-02-03 23:30:22 +02:00
return QString ( ) ;
}
2013-04-18 22:25:23 +02:00
/// Find the root path of a clearcase view. Precondition: This is a clearcase managed dir
QString ClearCasePlugin : : ccViewRoot ( const QString & directory ) const
{
QStringList args ( QLatin1String ( " pwv " ) ) ;
args < < QLatin1String ( " -root " ) ;
const ClearCaseResponse response =
runCleartool ( directory , args , m_settings . timeOutMS ( ) , SilentRun ) ;
QString root = response . stdOut . trimmed ( ) ;
if ( root . isEmpty ( ) ) {
if ( Utils : : HostOsInfo : : isWindowsHost ( ) )
root = getDriveLetterOfPath ( directory ) ;
else
root = QLatin1String ( " / " ) ;
}
return QDir : : fromNativeSeparators ( root ) ;
}
2012-09-20 19:41:35 +03:00
/*! Find top level for view that contains \a directory
*
2013-04-18 22:25:23 +02:00
* Handles both dynamic views and snapshot views .
2012-09-20 19:41:35 +03:00
*/
2011-06-05 17:58:02 +03:00
QString ClearCasePlugin : : findTopLevel ( const QString & directory ) const
{
2013-04-18 22:25:23 +02:00
// Do not check again if we've already tested that the dir is managed,
// or if it is a child of a managed dir (top level).
2012-10-03 18:03:53 +02:00
if ( ( directory = = m_topLevel ) | |
Utils : : FileName : : fromString ( directory ) . isChildOf ( Utils : : FileName : : fromString ( m_topLevel ) ) )
return m_topLevel ;
2013-04-18 22:25:23 +02:00
return ccManagesDirectory ( directory ) ;
2011-06-05 17:58:02 +03:00
}
static const VcsBase : : VcsBaseSubmitEditorParameters submitParameters = {
2013-09-03 15:38:13 +02:00
Constants : : CLEARCASE_SUBMIT_MIMETYPE ,
Constants : : CLEARCASECHECKINEDITOR_ID ,
Constants : : CLEARCASECHECKINEDITOR_DISPLAY_NAME ,
Constants : : CLEARCASECHECKINEDITOR ,
2013-01-11 10:45:00 +02:00
VcsBase : : VcsBaseSubmitEditorParameters : : DiffFiles
2011-06-05 17:58:02 +03:00
} ;
bool ClearCasePlugin : : initialize ( const QStringList & /*arguments */ , QString * errorMessage )
{
typedef VcsBase : : VcsSubmitEditorFactory < ClearCaseSubmitEditor > ClearCaseSubmitEditorFactory ;
typedef VcsBase : : VcsEditorFactory < ClearCaseEditor > ClearCaseEditorFactory ;
using namespace Constants ;
using namespace Core : : Constants ;
using namespace ExtensionSystem ;
initializeVcs ( new ClearCaseControl ( this ) ) ;
m_clearcasePluginInstance = this ;
2013-08-30 09:22:42 +02:00
connect ( ICore : : instance ( ) , SIGNAL ( coreAboutToClose ( ) ) , this , SLOT ( closing ( ) ) ) ;
2013-09-03 15:18:37 +02:00
connect ( ProgressManager : : instance ( ) , SIGNAL ( allTasksFinished ( Core : : Id ) ) ,
this , SLOT ( tasksFinished ( Core : : Id ) ) ) ;
2011-06-05 17:58:02 +03:00
2013-08-30 16:38:57 +02:00
if ( ! MimeDatabase : : addMimeTypes ( QLatin1String ( " :/clearcase/ClearCase.mimetypes.xml " ) , errorMessage ) )
2011-06-05 17:58:02 +03:00
return false ;
2013-08-30 09:22:42 +02:00
m_settings . fromSettings ( ICore : : settings ( ) ) ;
2011-06-05 17:58:02 +03:00
// update view name when changing active project
2013-08-30 09:22:42 +02:00
if ( ProjectExplorerPlugin * pe = ProjectExplorerPlugin : : instance ( ) )
2011-06-05 17:58:02 +03:00
connect ( pe , SIGNAL ( currentProjectChanged ( ProjectExplorer : : Project * ) ) ,
this , SLOT ( projectChanged ( ProjectExplorer : : Project * ) ) ) ;
addAutoReleasedObject ( new SettingsPage ) ;
addAutoReleasedObject ( new ClearCaseSubmitEditorFactory ( & submitParameters ) ) ;
// any editor responds to describe (when clicking a version)
static const char * describeSlot = SLOT ( describe ( QString , QString ) ) ;
const int editorCount = sizeof ( editorParameters ) / sizeof ( VcsBase : : VcsBaseEditorParameters ) ;
for ( int i = 0 ; i < editorCount ; i + + )
addAutoReleasedObject ( new ClearCaseEditorFactory ( editorParameters + i , this , describeSlot ) ) ;
const QString description = QLatin1String ( " ClearCase " ) ;
const QString prefix = QLatin1String ( " cc " ) ;
// register cc prefix in Locator
2013-01-18 11:35:38 +01:00
m_commandLocator = new Locator : : CommandLocator ( " cc " , description , prefix ) ;
2011-06-05 17:58:02 +03:00
addAutoReleasedObject ( m_commandLocator ) ;
//register actions
2013-08-30 09:22:42 +02:00
ActionContainer * toolsContainer = ActionManager : : actionContainer ( M_TOOLS ) ;
2011-06-05 17:58:02 +03:00
2013-08-30 09:22:42 +02:00
ActionContainer * clearcaseMenu = ActionManager : : createMenu ( CMD_ID_CLEARCASE_MENU ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > menu ( ) - > setTitle ( tr ( " C&learCase " ) ) ;
toolsContainer - > addMenu ( clearcaseMenu ) ;
m_menuAction = clearcaseMenu - > menu ( ) - > menuAction ( ) ;
2013-08-30 09:22:42 +02:00
Context globalcontext ( C_GLOBAL ) ;
Command * command ;
2011-06-05 17:58:02 +03:00
m_checkOutAction = new Utils : : ParameterAction ( tr ( " Check Out... " ) , tr ( " Check &Out \" %1 \" ... " ) , Utils : : ParameterAction : : AlwaysEnabled , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_checkOutAction , CMD_ID_CHECKOUT ,
2011-06-05 17:58:02 +03:00
globalcontext ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
command - > setDefaultKeySequence ( QKeySequence ( UseMacShortcuts ? tr ( " Meta+L,Meta+O " ) : tr ( " Alt+L,Alt+O " ) ) ) ;
2011-06-05 17:58:02 +03:00
connect ( m_checkOutAction , SIGNAL ( triggered ( ) ) , this , SLOT ( checkOutCurrentFile ( ) ) ) ;
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
m_checkInCurrentAction = new Utils : : ParameterAction ( tr ( " Check &In... " ) , tr ( " Check &In \" %1 \" ... " ) , Utils : : ParameterAction : : AlwaysEnabled , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_checkInCurrentAction , CMD_ID_CHECKIN , globalcontext ) ;
command - > setAttribute ( Command : : CA_UpdateText ) ;
command - > setDefaultKeySequence ( QKeySequence ( UseMacShortcuts ? tr ( " Meta+L,Meta+I " ) : tr ( " Alt+L,Alt+I " ) ) ) ;
2011-06-05 17:58:02 +03:00
connect ( m_checkInCurrentAction , SIGNAL ( triggered ( ) ) , this , SLOT ( startCheckInCurrentFile ( ) ) ) ;
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
m_undoCheckOutAction = new Utils : : ParameterAction ( tr ( " Undo Check Out " ) , tr ( " &Undo Check Out \" %1 \" " ) , Utils : : ParameterAction : : AlwaysEnabled , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_undoCheckOutAction , CMD_ID_UNDOCHECKOUT , globalcontext ) ;
command - > setAttribute ( Command : : CA_UpdateText ) ;
command - > setDefaultKeySequence ( QKeySequence ( UseMacShortcuts ? tr ( " Meta+L,Meta+U " ) : tr ( " Alt+L,Alt+U " ) ) ) ;
2011-06-05 17:58:02 +03:00
connect ( m_undoCheckOutAction , SIGNAL ( triggered ( ) ) , this , SLOT ( undoCheckOutCurrent ( ) ) ) ;
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
m_undoHijackAction = new Utils : : ParameterAction ( tr ( " Undo Hijack " ) , tr ( " Undo Hi&jack \" %1 \" " ) , Utils : : ParameterAction : : AlwaysEnabled , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_undoHijackAction , CMD_ID_UNDOHIJACK , globalcontext ) ;
command - > setAttribute ( Command : : CA_UpdateText ) ;
command - > setDefaultKeySequence ( QKeySequence ( UseMacShortcuts ? tr ( " Meta+L,Meta+R " ) : tr ( " Alt+L,Alt+R " ) ) ) ;
2011-06-05 17:58:02 +03:00
connect ( m_undoHijackAction , SIGNAL ( triggered ( ) ) , this , SLOT ( undoHijackCurrent ( ) ) ) ;
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
clearcaseMenu - > addSeparator ( globalcontext ) ;
m_diffCurrentAction = new Utils : : ParameterAction ( tr ( " Diff Current File " ) , tr ( " &Diff \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_diffCurrentAction ,
2011-06-05 17:58:02 +03:00
CMD_ID_DIFF_CURRENT , globalcontext ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
command - > setDefaultKeySequence ( QKeySequence ( UseMacShortcuts ? tr ( " Meta+L,Meta+D " ) : tr ( " Alt+L,Alt+D " ) ) ) ;
2011-06-05 17:58:02 +03:00
connect ( m_diffCurrentAction , SIGNAL ( triggered ( ) ) , this , SLOT ( diffCurrentFile ( ) ) ) ;
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
m_historyCurrentAction = new Utils : : ParameterAction ( tr ( " History Current File " ) , tr ( " &History \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_historyCurrentAction ,
2011-06-05 17:58:02 +03:00
CMD_ID_HISTORY_CURRENT , globalcontext ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
command - > setDefaultKeySequence ( QKeySequence ( UseMacShortcuts ? tr ( " Meta+L,Meta+H " ) : tr ( " Alt+L,Alt+H " ) ) ) ;
2011-06-05 17:58:02 +03:00
connect ( m_historyCurrentAction , SIGNAL ( triggered ( ) ) , this ,
SLOT ( historyCurrentFile ( ) ) ) ;
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
m_annotateCurrentAction = new Utils : : ParameterAction ( tr ( " Annotate Current File " ) , tr ( " &Annotate \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_annotateCurrentAction ,
2011-06-05 17:58:02 +03:00
CMD_ID_ANNOTATE , globalcontext ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
command - > setDefaultKeySequence ( QKeySequence ( UseMacShortcuts ? tr ( " Meta+L,Meta+A " ) : tr ( " Alt+L,Alt+A " ) ) ) ;
2011-06-05 17:58:02 +03:00
connect ( m_annotateCurrentAction , SIGNAL ( triggered ( ) ) , this ,
SLOT ( annotateCurrentFile ( ) ) ) ;
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
m_addFileAction = new Utils : : ParameterAction ( tr ( " Add File... " ) , tr ( " Add File \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_addFileAction , CMD_ID_ADD_FILE , globalcontext ) ;
command - > setAttribute ( Command : : CA_UpdateText ) ;
2011-06-05 17:58:02 +03:00
connect ( m_addFileAction , SIGNAL ( triggered ( ) ) , this , SLOT ( addCurrentFile ( ) ) ) ;
clearcaseMenu - > addAction ( command ) ;
clearcaseMenu - > addSeparator ( globalcontext ) ;
m_diffActivityAction = new QAction ( tr ( " Diff A&ctivity... " ) , this ) ;
2013-11-20 11:59:34 +01:00
m_diffActivityAction - > setEnabled ( false ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_diffActivityAction , CMD_ID_DIFF_ACTIVITY , globalcontext ) ;
2011-06-05 17:58:02 +03:00
connect ( m_diffActivityAction , SIGNAL ( triggered ( ) ) , this , SLOT ( diffActivity ( ) ) ) ;
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
m_checkInActivityAction = new Utils : : ParameterAction ( tr ( " Ch&eck In Activity " ) , tr ( " Chec&k In Activity \" %1 \" ... " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2013-11-20 11:59:34 +01:00
m_checkInActivityAction - > setEnabled ( false ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_checkInActivityAction , CMD_ID_CHECKIN_ACTIVITY , globalcontext ) ;
2011-06-05 17:58:02 +03:00
connect ( m_checkInActivityAction , SIGNAL ( triggered ( ) ) , this , SLOT ( startCheckInActivity ( ) ) ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
clearcaseMenu - > addSeparator ( globalcontext ) ;
m_updateIndexAction = new QAction ( tr ( " Update Index " ) , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_updateIndexAction , CMD_ID_UPDATEINDEX , globalcontext ) ;
2011-06-05 17:58:02 +03:00
connect ( m_updateIndexAction , SIGNAL ( triggered ( ) ) , this , SLOT ( updateIndex ( ) ) ) ;
clearcaseMenu - > addAction ( command ) ;
m_updateViewAction = new Utils : : ParameterAction ( tr ( " Update View " ) , tr ( " U&pdate View \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_updateViewAction , CMD_ID_UPDATE_VIEW , globalcontext ) ;
2011-06-05 17:58:02 +03:00
connect ( m_updateViewAction , SIGNAL ( triggered ( ) ) , this , SLOT ( updateView ( ) ) ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
clearcaseMenu - > addSeparator ( globalcontext ) ;
m_checkInAllAction = new QAction ( tr ( " Check In All &Files... " ) , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_checkInAllAction , CMD_ID_CHECKIN_ALL , globalcontext ) ;
command - > setDefaultKeySequence ( QKeySequence ( UseMacShortcuts ? tr ( " Meta+L,Meta+F " ) : tr ( " Alt+L,Alt+F " ) ) ) ;
2011-06-05 17:58:02 +03:00
connect ( m_checkInAllAction , SIGNAL ( triggered ( ) ) , this , SLOT ( startCheckInAll ( ) ) ) ;
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
m_statusAction = new QAction ( tr ( " View &Status " ) , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_statusAction , CMD_ID_STATUS , globalcontext ) ;
command - > setDefaultKeySequence ( QKeySequence ( UseMacShortcuts ? tr ( " Meta+L,Meta+S " ) : tr ( " Alt+L,Alt+S " ) ) ) ;
2011-06-05 17:58:02 +03:00
connect ( m_statusAction , SIGNAL ( triggered ( ) ) , this , SLOT ( viewStatus ( ) ) ) ;
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
// Actions of the submit editor
2013-08-30 09:22:42 +02:00
Context clearcasecheckincontext ( Constants : : CLEARCASECHECKINEDITOR ) ;
2011-06-05 17:58:02 +03:00
m_checkInSelectedAction = new QAction ( VcsBase : : VcsBaseSubmitEditor : : submitIcon ( ) , tr ( " Check In " ) , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_checkInSelectedAction , Constants : : CHECKIN_SELECTED , clearcasecheckincontext ) ;
command - > setAttribute ( Command : : CA_UpdateText ) ;
2011-06-05 17:58:02 +03:00
connect ( m_checkInSelectedAction , SIGNAL ( triggered ( ) ) , this , SLOT ( checkInSelected ( ) ) ) ;
m_checkInDiffAction = new QAction ( VcsBase : : VcsBaseSubmitEditor : : diffIcon ( ) , tr ( " Diff Selected Files " ) , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_checkInDiffAction , Constants : : DIFF_SELECTED , clearcasecheckincontext ) ;
2011-06-05 17:58:02 +03:00
m_submitUndoAction = new QAction ( tr ( " &Undo " ) , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_submitUndoAction , Core : : Constants : : UNDO , clearcasecheckincontext ) ;
2011-06-05 17:58:02 +03:00
m_submitRedoAction = new QAction ( tr ( " &Redo " ) , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_submitRedoAction , Core : : Constants : : REDO , clearcasecheckincontext ) ;
2011-06-05 17:58:02 +03:00
return true ;
}
// called before closing the submit editor
2013-04-18 12:06:43 +02:00
bool ClearCasePlugin : : submitEditorAboutToClose ( )
2011-06-05 17:58:02 +03:00
{
if ( ! isCheckInEditorOpen ( ) )
return true ;
2013-04-18 12:06:43 +02:00
ClearCaseSubmitEditor * editor = qobject_cast < ClearCaseSubmitEditor * > ( submitEditor ( ) ) ;
QTC_ASSERT ( editor , return true ) ;
2013-08-30 09:22:42 +02:00
IDocument * editorDocument = editor - > document ( ) ;
2013-04-18 12:06:43 +02:00
QTC_ASSERT ( editorDocument , return true ) ;
2011-06-05 17:58:02 +03:00
// Submit editor closing. Make it write out the check in message
// and retrieve files
2013-07-04 13:30:26 +02:00
const QFileInfo editorFile ( editorDocument - > filePath ( ) ) ;
2011-06-05 17:58:02 +03:00
const QFileInfo changeFile ( m_checkInMessageFileName ) ;
if ( editorFile . absoluteFilePath ( ) ! = changeFile . absoluteFilePath ( ) )
return true ; // Oops?!
// Prompt user. Force a prompt unless submit was actually invoked (that
// is, the editor was closed or shutdown).
bool prompt = m_settings . promptToCheckIn ;
const VcsBase : : VcsBaseSubmitEditor : : PromptSubmitResult answer =
editor - > promptSubmit ( tr ( " Closing ClearCase Editor " ) ,
tr ( " Do you want to check in the files? " ) ,
tr ( " The comment check failed. Do you want to check in the files? " ) ,
& prompt , ! m_submitActionTriggered ) ;
m_submitActionTriggered = false ;
switch ( answer ) {
case VcsBase : : VcsBaseSubmitEditor : : SubmitCanceled :
return false ; // Keep editing and change file
case VcsBase : : VcsBaseSubmitEditor : : SubmitDiscarded :
cleanCheckInMessageFile ( ) ;
return true ; // Cancel all
default :
break ;
}
// If user changed
if ( prompt ! = m_settings . promptToCheckIn ) {
m_settings . promptToCheckIn = prompt ;
2013-08-30 09:22:42 +02:00
m_settings . toSettings ( ICore : : settings ( ) ) ;
2011-06-05 17:58:02 +03:00
}
const QStringList fileList = editor - > checkedFiles ( ) ;
bool closeEditor = true ;
if ( ! fileList . empty ( ) ) {
// get message & check in
2013-08-30 09:22:42 +02:00
closeEditor = DocumentManager : : saveDocument ( editorDocument ) ;
2011-06-05 17:58:02 +03:00
if ( closeEditor ) {
ClearCaseSubmitEditorWidget * widget = editor - > submitEditorWidget ( ) ;
closeEditor = vcsCheckIn ( m_checkInMessageFileName , fileList , widget - > activity ( ) ,
widget - > isIdentical ( ) , widget - > isPreserve ( ) ,
widget - > activityChanged ( ) ) ;
}
}
// vcsCheckIn might fail if some of the files failed to check-in (though it does check-in
// those who didn't fail). Therefore, if more than one file was sent, consider it as success
// anyway (sync will be called from vcsCheckIn for next attempt)
closeEditor | = ( fileList . count ( ) > 1 ) ;
if ( closeEditor )
cleanCheckInMessageFile ( ) ;
return closeEditor ;
}
void ClearCasePlugin : : diffCheckInFiles ( const QStringList & files )
{
2012-09-12 09:27:06 +03:00
ccDiffWithPred ( m_checkInView , files ) ;
2011-06-05 17:58:02 +03:00
}
2013-10-06 20:52:09 +03:00
static inline void setWorkingDirectory ( IEditor * editor , const QString & wd )
2011-06-05 17:58:02 +03:00
{
if ( VcsBase : : VcsBaseEditorWidget * ve = qobject_cast < VcsBase : : VcsBaseEditorWidget * > ( editor - > widget ( ) ) )
2013-10-06 20:52:09 +03:00
ve - > setWorkingDirectory ( wd ) ;
2011-06-05 17:58:02 +03:00
}
//! retrieve full location of predecessor of \a version
QString ClearCasePlugin : : ccGetPredecessor ( const QString & version ) const
{
QStringList args ( QLatin1String ( " describe " ) ) ;
args < < QLatin1String ( " -fmt " ) < < QLatin1String ( " %En@@%PSn " ) < < version ;
const ClearCaseResponse response =
runCleartool ( currentState ( ) . topLevel ( ) , args , m_settings . timeOutMS ( ) , SilentRun ) ;
if ( response . error | | response . stdOut . endsWith ( QLatin1Char ( ' @ ' ) ) ) // <name-unknown>@@
return QString ( ) ;
else
return response . stdOut ;
}
2013-04-02 13:03:24 +02:00
//! Get a list of paths to active VOBs.
2013-04-18 22:25:23 +02:00
//! Paths are relative to viewRoot
2011-06-05 17:58:02 +03:00
QStringList ClearCasePlugin : : ccGetActiveVobs ( ) const
{
QStringList res ;
QStringList args ( QLatin1String ( " lsvob " ) ) ;
2013-04-18 22:25:23 +02:00
const QString theViewRoot = viewRoot ( ) ;
2011-06-05 17:58:02 +03:00
const ClearCaseResponse response =
2013-04-18 22:25:23 +02:00
runCleartool ( theViewRoot , args , m_settings . timeOutMS ( ) , SilentRun ) ;
2011-06-05 17:58:02 +03:00
if ( response . error )
return res ;
2013-04-02 13:03:24 +02:00
// format of output unix:
// * /path/to/vob /path/to/vob/storage.vbs <and some text omitted here>
// format of output windows:
// * \vob \\share\path\to\vob\storage.vbs <and some text omitted here>
2013-04-18 22:25:23 +02:00
QString prefix = theViewRoot ;
2013-04-02 13:03:24 +02:00
if ( ! prefix . endsWith ( QLatin1Char ( ' / ' ) ) )
prefix + = QLatin1Char ( ' / ' ) ;
2013-04-18 22:25:23 +02:00
const QDir theViewRootDir ( theViewRoot ) ;
2013-04-02 13:03:24 +02:00
foreach ( const QString & line , response . stdOut . split ( QLatin1Char ( ' \n ' ) , QString : : SkipEmptyParts ) ) {
const bool isActive = line . at ( 0 ) = = QLatin1Char ( ' * ' ) ;
if ( ! isActive )
continue ;
const QString dir =
QDir : : fromNativeSeparators ( line . mid ( 3 , line . indexOf ( QLatin1Char ( ' ' ) , 3 ) - 3 ) ) ;
2013-04-18 22:25:23 +02:00
const QString relativeDir = theViewRootDir . relativeFilePath ( dir ) ;
2013-04-02 13:03:24 +02:00
// Snapshot views does not necessarily have all active VOBs loaded, so we'll have to
// check if the dirs exists as well. Else the command will work, but the output will
// complain about the element not being loaded.
if ( QFile : : exists ( prefix + relativeDir ) )
res . append ( relativeDir ) ;
2011-06-05 17:58:02 +03:00
}
return res ;
}
2013-12-05 13:30:20 +01:00
void ClearCasePlugin : : checkAndReIndexUnknownFile ( const QString & file )
{
if ( isDynamic ( ) ) {
// reindex unknown files
if ( m_statusMap - > value ( file , FileStatus ( FileStatus : : Unknown ) ) . status = = FileStatus : : Unknown )
updateStatusForFile ( file ) ;
}
}
// file must be absolute, and using '/' path separator
2011-06-05 17:58:02 +03:00
FileStatus ClearCasePlugin : : vcsStatus ( const QString & file ) const
{
2012-09-02 10:20:32 +03:00
return m_statusMap - > value ( file , FileStatus ( FileStatus : : Unknown ) ) ;
2011-06-05 17:58:02 +03:00
}
QString ClearCasePlugin : : ccGetFileActivity ( const QString & workingDir , const QString & file )
{
QStringList args ( QLatin1String ( " lscheckout " ) ) ;
args < < QLatin1String ( " -fmt " ) < < QLatin1String ( " %[activity]p " ) ;
args < < file ;
const ClearCaseResponse response =
runCleartool ( workingDir , args , m_settings . timeOutMS ( ) , SilentRun ) ;
return response . stdOut ;
}
2012-09-24 11:39:34 +02:00
ClearCaseSubmitEditor * ClearCasePlugin : : openClearCaseSubmitEditor ( const QString & fileName , bool isUcm )
2011-06-05 17:58:02 +03:00
{
2013-08-30 09:22:42 +02:00
IEditor * editor =
EditorManager : : openEditor ( fileName , Constants : : CLEARCASECHECKINEDITOR_ID ) ;
2011-06-05 17:58:02 +03:00
ClearCaseSubmitEditor * submitEditor = qobject_cast < ClearCaseSubmitEditor * > ( editor ) ;
QTC_CHECK ( submitEditor ) ;
submitEditor - > registerActions ( m_submitUndoAction , m_submitRedoAction , m_checkInSelectedAction , m_checkInDiffAction ) ;
connect ( submitEditor , SIGNAL ( diffSelectedFiles ( QStringList ) ) , this , SLOT ( diffCheckInFiles ( QStringList ) ) ) ;
2012-09-12 09:27:06 +03:00
submitEditor - > setCheckScriptWorkingDirectory ( m_checkInView ) ;
2012-09-24 11:39:34 +02:00
submitEditor - > setIsUcm ( isUcm ) ;
2011-06-05 17:58:02 +03:00
return submitEditor ;
}
2013-10-07 15:57:05 +02:00
QString fileStatusToText ( FileStatus fileStatus )
{
switch ( fileStatus . status )
{
case FileStatus : : CheckedIn :
return QLatin1String ( " CheckedIn " ) ;
case FileStatus : : CheckedOut :
return QLatin1String ( " CheckedOut " ) ;
case FileStatus : : Hijacked :
return QLatin1String ( " Hijacked " ) ;
case FileStatus : : Missing :
return QLatin1String ( " Missing " ) ;
case FileStatus : : NotManaged :
return QLatin1String ( " ViewPrivate " ) ;
case FileStatus : : Unknown :
return QLatin1String ( " Unknown " ) ;
default :
return QLatin1String ( " default " ) ;
}
}
2011-06-05 17:58:02 +03:00
void ClearCasePlugin : : updateStatusActions ( )
{
2013-03-19 20:52:02 +01:00
FileStatus fileStatus = FileStatus : : Unknown ;
2011-06-05 17:58:02 +03:00
bool hasFile = currentState ( ) . hasFile ( ) ;
2013-03-19 20:52:02 +01:00
if ( hasFile ) {
2013-04-18 22:25:23 +02:00
QString absoluteFileName = currentState ( ) . currentFile ( ) ;
2013-12-05 13:30:20 +01:00
checkAndReIndexUnknownFile ( absoluteFileName ) ;
fileStatus = vcsStatus ( absoluteFileName ) ;
2012-09-24 11:39:34 +02:00
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2013-10-07 15:57:05 +02:00
qDebug ( ) < < Q_FUNC_INFO < < absoluteFileName < < " , status = "
< < fileStatusToText ( fileStatus . status ) < < " ( " < < fileStatus . status < < " ) " ;
2013-03-19 20:52:02 +01:00
}
2012-09-24 11:39:34 +02:00
2011-06-05 17:58:02 +03:00
m_checkOutAction - > setEnabled ( hasFile & & ( fileStatus . status & ( FileStatus : : CheckedIn | FileStatus : : Hijacked ) ) ) ;
m_undoCheckOutAction - > setEnabled ( hasFile & & ( fileStatus . status & FileStatus : : CheckedOut ) ) ;
2012-11-30 11:36:35 +02:00
m_undoHijackAction - > setEnabled ( ! m_viewData . isDynamic & & hasFile & & ( fileStatus . status & FileStatus : : Hijacked ) ) ;
2011-06-05 17:58:02 +03:00
m_checkInCurrentAction - > setEnabled ( hasFile & & ( fileStatus . status & FileStatus : : CheckedOut ) ) ;
m_addFileAction - > setEnabled ( hasFile & & ( fileStatus . status & FileStatus : : NotManaged ) ) ;
2013-10-07 12:48:25 +02:00
m_diffCurrentAction - > setEnabled ( hasFile & & ( fileStatus . status ! = FileStatus : : NotManaged ) ) ;
m_historyCurrentAction - > setEnabled ( hasFile & & ( fileStatus . status ! = FileStatus : : NotManaged ) ) ;
m_annotateCurrentAction - > setEnabled ( hasFile & & ( fileStatus . status ! = FileStatus : : NotManaged ) ) ;
2012-09-24 11:39:34 +02:00
2012-11-30 11:36:35 +02:00
m_checkInActivityAction - > setEnabled ( m_viewData . isUcm ) ;
m_diffActivityAction - > setEnabled ( m_viewData . isUcm ) ;
2011-06-05 17:58:02 +03:00
}
void ClearCasePlugin : : updateActions ( VcsBase : : VcsBasePlugin : : ActionState as )
{
if ( ! enableMenuAction ( as , m_menuAction ) ) {
m_commandLocator - > setEnabled ( false ) ;
return ;
}
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
const bool hasTopLevel = state . hasTopLevel ( ) ;
m_commandLocator - > setEnabled ( hasTopLevel ) ;
if ( hasTopLevel )
m_topLevel = state . topLevel ( ) ;
2012-11-30 11:36:35 +02:00
m_updateViewAction - > setParameter ( m_viewData . isDynamic ? QString ( ) : m_viewData . name ) ;
2011-06-05 17:58:02 +03:00
const QString fileName = state . currentFileName ( ) ;
m_checkOutAction - > setParameter ( fileName ) ;
m_undoCheckOutAction - > setParameter ( fileName ) ;
m_undoHijackAction - > setParameter ( fileName ) ;
m_diffCurrentAction - > setParameter ( fileName ) ;
m_checkInCurrentAction - > setParameter ( fileName ) ;
m_historyCurrentAction - > setParameter ( fileName ) ;
m_annotateCurrentAction - > setParameter ( fileName ) ;
m_addFileAction - > setParameter ( fileName ) ;
m_updateIndexAction - > setEnabled ( ! m_settings . disableIndexer ) ;
2013-12-05 13:30:20 +01:00
2011-06-05 17:58:02 +03:00
updateStatusActions ( ) ;
}
void ClearCasePlugin : : checkOutCurrentFile ( )
{
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return ) ;
vcsOpen ( state . currentFileTopLevel ( ) , state . relativeCurrentFile ( ) ) ;
}
void ClearCasePlugin : : addCurrentFile ( )
{
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return ) ;
vcsAdd ( state . currentFileTopLevel ( ) , state . relativeCurrentFile ( ) ) ;
}
2013-04-18 22:25:23 +02:00
// Set the FileStatus of file given in absolute path
2012-11-12 16:48:26 +02:00
void ClearCasePlugin : : setStatus ( const QString & file , FileStatus : : Status status , bool update )
2011-06-05 17:58:02 +03:00
{
2013-12-05 13:30:20 +01:00
QTC_CHECK ( ! file . isEmpty ( ) ) ;
2013-04-18 22:25:23 +02:00
m_statusMap - > insert ( file , FileStatus ( status , QFileInfo ( file ) . permissions ( ) ) ) ;
if ( update & & currentState ( ) . currentFile ( ) = = file )
2012-11-12 16:48:26 +02:00
QMetaObject : : invokeMethod ( this , " updateStatusActions " ) ;
2011-06-05 17:58:02 +03:00
}
void ClearCasePlugin : : undoCheckOutCurrent ( )
{
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return ) ;
QString file = state . relativeCurrentFile ( ) ;
const QString fileName = QDir : : toNativeSeparators ( file ) ;
QStringList args ( QLatin1String ( " diff " ) ) ;
args < < QLatin1String ( " -diff_format " ) < < QLatin1String ( " -predecessor " ) ;
args < < fileName ;
const ClearCaseResponse diffResponse =
runCleartool ( state . currentFileTopLevel ( ) , args , m_settings . timeOutMS ( ) , 0 ) ;
bool different = diffResponse . error ; // return value is 1 if there is any difference
bool keep = false ;
if ( different ) {
Ui : : UndoCheckOut uncoUi ;
QDialog uncoDlg ;
uncoUi . setupUi ( & uncoDlg ) ;
uncoUi . lblMessage - > setText ( tr ( " Do you want to undo the check out of '%1'? " ) . arg ( fileName ) ) ;
if ( uncoDlg . exec ( ) ! = QDialog : : Accepted )
return ;
keep = uncoUi . chkKeep - > isChecked ( ) ;
}
vcsUndoCheckOut ( state . topLevel ( ) , file , keep ) ;
}
bool ClearCasePlugin : : vcsUndoCheckOut ( const QString & workingDir , const QString & fileName , bool keep )
{
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2011-06-05 17:58:02 +03:00
qDebug ( ) < < Q_FUNC_INFO < < workingDir < < fileName < < keep ;
2013-08-30 09:22:42 +02:00
FileChangeBlocker fcb ( fileName ) ;
2011-06-05 17:58:02 +03:00
// revert
QStringList args ( QLatin1String ( " uncheckout " ) ) ;
args < < QLatin1String ( keep ? " -keep " : " -rm " ) ;
args < < QDir : : toNativeSeparators ( fileName ) ;
const ClearCaseResponse response =
runCleartool ( workingDir , args , m_settings . timeOutMS ( ) ,
ShowStdOutInLogWindow | FullySynchronously ) ;
if ( ! response . error ) {
2013-04-18 22:25:23 +02:00
const QString absPath = workingDir + QLatin1Char ( ' / ' ) + fileName ;
2011-06-05 17:58:02 +03:00
if ( ! m_settings . disableIndexer )
2013-04-18 22:25:23 +02:00
setStatus ( absPath , FileStatus : : CheckedIn ) ;
clearCaseControl ( ) - > emitFilesChanged ( QStringList ( absPath ) ) ;
2011-06-05 17:58:02 +03:00
}
return ! response . error ;
}
2012-09-20 19:41:35 +03:00
/*! Undo a hijacked file in a snapshot view
*
* Runs cleartool update - overwrite \ a fileName in \ a workingDir
* if \ a keep is true , renames hijacked files to < filename > . keep . Otherwise it is overwritten
*/
2011-06-05 17:58:02 +03:00
bool ClearCasePlugin : : vcsUndoHijack ( const QString & workingDir , const QString & fileName , bool keep )
{
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2011-06-05 17:58:02 +03:00
qDebug ( ) < < Q_FUNC_INFO < < workingDir < < fileName < < keep ;
QStringList args ( QLatin1String ( " update " ) ) ;
args < < QLatin1String ( keep ? " -rename " : " -overwrite " ) ;
args < < QLatin1String ( " -log " ) ;
2012-08-23 15:53:58 +02:00
if ( Utils : : HostOsInfo : : isWindowsHost ( ) )
args < < QLatin1String ( " NUL " ) ;
else
2011-06-05 17:58:02 +03:00
args < < QLatin1String ( " /dev/null " ) ;
args < < QDir : : toNativeSeparators ( fileName ) ;
const ClearCaseResponse response =
runCleartool ( workingDir , args , m_settings . timeOutMS ( ) ,
ShowStdOutInLogWindow | FullySynchronously ) ;
2013-04-18 22:25:23 +02:00
if ( ! response . error & & ! m_settings . disableIndexer ) {
const QString absPath = workingDir + QLatin1Char ( ' / ' ) + fileName ;
setStatus ( absPath , FileStatus : : CheckedIn ) ;
}
2011-06-05 17:58:02 +03:00
return ! response . error ;
}
void ClearCasePlugin : : undoHijackCurrent ( )
{
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return ) ;
const QString fileName = state . relativeCurrentFile ( ) ;
bool keep = false ;
2012-09-02 11:26:26 +03:00
bool askKeep = true ;
if ( m_settings . extDiffAvailable ) {
QString diffres = diffExternal ( ccGetFileVersion ( state . topLevel ( ) , fileName ) , fileName ) ;
if ( diffres . at ( 0 ) = = QLatin1Char ( ' F ' ) ) // Files are identical
askKeep = false ;
}
if ( askKeep ) {
2011-06-05 17:58:02 +03:00
Ui : : UndoCheckOut unhijackUi ;
QDialog unhijackDlg ;
unhijackUi . setupUi ( & unhijackDlg ) ;
2012-08-27 12:24:23 +02:00
unhijackDlg . setWindowTitle ( tr ( " Undo Hijack File " ) ) ;
2011-06-05 17:58:02 +03:00
unhijackUi . lblMessage - > setText ( tr ( " Do you want to undo hijack of '%1'? " )
. arg ( QDir : : toNativeSeparators ( fileName ) ) ) ;
if ( unhijackDlg . exec ( ) ! = QDialog : : Accepted )
return ;
keep = unhijackUi . chkKeep - > isChecked ( ) ;
}
2013-08-30 09:22:42 +02:00
FileChangeBlocker fcb ( state . currentFile ( ) ) ;
2011-06-05 17:58:02 +03:00
// revert
if ( vcsUndoHijack ( state . currentFileTopLevel ( ) , fileName , keep ) )
clearCaseControl ( ) - > emitFilesChanged ( QStringList ( state . currentFile ( ) ) ) ;
}
QString ClearCasePlugin : : ccGetFileVersion ( const QString & workingDir , const QString & file ) const
{
QStringList args ( QLatin1String ( " ls " ) ) ;
args < < QLatin1String ( " -short " ) < < file ;
return runCleartoolSync ( workingDir , args ) . trimmed ( ) ;
}
2012-09-12 09:27:06 +03:00
void ClearCasePlugin : : ccDiffWithPred ( const QString & workingDir , const QStringList & files )
2011-06-05 17:58:02 +03:00
{
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2011-06-05 17:58:02 +03:00
qDebug ( ) < < Q_FUNC_INFO < < files ;
2012-09-12 09:27:06 +03:00
const QString source = VcsBase : : VcsBaseEditorWidget : : getSource ( workingDir , files ) ;
2011-06-05 17:58:02 +03:00
QTextCodec * codec = source . isEmpty ( ) ? static_cast < QTextCodec * > ( 0 ) : VcsBase : : VcsBaseEditorWidget : : getCodec ( source ) ;
if ( ( m_settings . diffType = = GraphicalDiff ) & & ( files . count ( ) = = 1 ) ) {
2013-04-18 22:25:23 +02:00
const QString file = files . first ( ) ;
const QString absFilePath = workingDir + QLatin1Char ( ' / ' ) + file ;
2013-12-05 13:30:20 +01:00
if ( vcsStatus ( absFilePath ) . status = = FileStatus : : Hijacked )
2012-09-12 09:27:06 +03:00
diffGraphical ( ccGetFileVersion ( workingDir , file ) , file ) ;
2011-06-05 17:58:02 +03:00
else
diffGraphical ( file ) ;
return ; // done here, diff is opened in a new window
}
2012-09-02 11:26:26 +03:00
if ( ! m_settings . extDiffAvailable ) {
VcsBase : : VcsBaseOutputWindow : : instance ( ) - > appendError (
tr ( " External diff is required to compare multiple files. " ) ) ;
return ;
}
2011-06-05 17:58:02 +03:00
QString result ;
foreach ( const QString & file , files ) {
2013-04-18 22:25:23 +02:00
const QString absFilePath = workingDir + QLatin1Char ( ' / ' ) + file ;
2013-12-05 13:30:20 +01:00
if ( vcsStatus ( QDir : : fromNativeSeparators ( absFilePath ) ) . status = = FileStatus : : Hijacked )
2012-09-12 09:27:06 +03:00
result + = diffExternal ( ccGetFileVersion ( workingDir , file ) , file ) ;
2011-06-05 17:58:02 +03:00
else
result + = diffExternal ( file ) ;
}
QString diffname ;
// diff of a single file? re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
2012-09-12 09:27:06 +03:00
const QString tag = VcsBase : : VcsBaseEditorWidget : : editorTag ( VcsBase : : DiffOutput , workingDir , files ) ;
2011-06-05 17:58:02 +03:00
if ( files . count ( ) = = 1 ) {
// Show in the same editor if diff has been executed before
2013-08-30 09:22:42 +02:00
if ( IEditor * existingEditor = VcsBase : : VcsBaseEditorWidget : : locateEditorByTag ( tag ) ) {
2013-07-15 15:14:10 +02:00
existingEditor - > document ( ) - > setContents ( result . toUtf8 ( ) ) ;
2013-08-30 09:22:42 +02:00
EditorManager : : activateEditor ( existingEditor ) ;
2013-10-06 20:52:09 +03:00
setWorkingDirectory ( existingEditor , workingDir ) ;
2011-06-05 17:58:02 +03:00
return ;
}
diffname = QDir : : toNativeSeparators ( files . first ( ) ) ;
}
const QString title = QString : : fromLatin1 ( " cc diff %1 " ) . arg ( diffname ) ;
2013-08-30 09:22:42 +02:00
IEditor * editor = showOutputInEditor ( title , result , VcsBase : : DiffOutput , source , codec ) ;
2013-10-06 20:52:09 +03:00
setWorkingDirectory ( editor , workingDir ) ;
2011-06-05 17:58:02 +03:00
VcsBase : : VcsBaseEditorWidget : : tagEditor ( editor , tag ) ;
ClearCaseEditor * diffEditorWidget = qobject_cast < ClearCaseEditor * > ( editor - > widget ( ) ) ;
QTC_ASSERT ( diffEditorWidget , return ) ;
if ( files . count ( ) = = 1 )
editor - > setProperty ( " originalFileName " , diffname ) ;
}
QStringList ClearCasePlugin : : ccGetActivityVersions ( const QString & workingDir , const QString & activity )
{
QStringList args ( QLatin1String ( " lsactivity " ) ) ;
args < < QLatin1String ( " -fmt " ) < < QLatin1String ( " %[versions]Cp " ) < < activity ;
const ClearCaseResponse response =
runCleartool ( workingDir , args , m_settings . timeOutMS ( ) , SilentRun ) ;
if ( response . error )
return QStringList ( ) ;
QStringList versions = response . stdOut . split ( QLatin1String ( " , " ) ) ;
versions . sort ( ) ;
return versions ;
}
void ClearCasePlugin : : rmdir ( const QString & path )
{
QDir dir ( path ) ;
foreach ( QFileInfo fi , dir . entryInfoList ( QDir : : AllEntries | QDir : : NoDotAndDotDot ) ) {
if ( fi . isDir ( ) ) {
rmdir ( fi . canonicalFilePath ( ) ) ;
dir . rmdir ( fi . baseName ( ) ) ;
}
else
QFile : : remove ( fi . canonicalFilePath ( ) ) ;
}
}
void ClearCasePlugin : : diffActivity ( )
{
2013-03-08 09:53:02 +01:00
typedef QMap < QString , QStringPair > : : Iterator FileVerIt ;
2011-06-05 17:58:02 +03:00
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasTopLevel ( ) , return ) ;
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2011-06-05 17:58:02 +03:00
qDebug ( ) < < Q_FUNC_INFO ;
2012-09-02 11:26:26 +03:00
if ( ! m_settings . extDiffAvailable ) {
VcsBase : : VcsBaseOutputWindow : : instance ( ) - > appendError (
tr ( " External diff is required to compare multiple files. " ) ) ;
return ;
}
2011-06-05 17:58:02 +03:00
QString topLevel = state . topLevel ( ) ;
QString activity = QInputDialog : : getText ( 0 , tr ( " Enter Activity " ) , tr ( " Activity Name " ) , QLineEdit : : Normal , m_activity ) ;
if ( activity . isEmpty ( ) )
return ;
QStringList versions = ccGetActivityVersions ( topLevel , activity ) ;
QString result ;
// map from fileName to (first, latest) pair
QMap < QString , QStringPair > filever ;
int topLevelLen = topLevel . length ( ) ;
foreach ( const QString & version , versions ) {
QString shortver = version . mid ( topLevelLen + 1 ) ;
int atatpos = shortver . indexOf ( QLatin1String ( " @@ " ) ) ;
if ( atatpos ! = - 1 ) {
QString file = shortver . left ( atatpos ) ;
// latest version - updated each line
filever [ file ] . second = shortver ;
// pre-first version. only for the first occurence
if ( filever [ file ] . first . isEmpty ( ) ) {
int verpos = shortver . lastIndexOf ( QRegExp ( QLatin1String ( " [^0-9] " ) ) ) + 1 ;
int vernum = shortver . mid ( verpos ) . toInt ( ) ;
if ( vernum )
- - vernum ;
shortver . replace ( verpos , shortver . length ( ) - verpos , QString : : number ( vernum ) ) ;
// first version
filever [ file ] . first = shortver ;
}
}
}
if ( ( m_settings . diffType = = GraphicalDiff ) & & ( filever . count ( ) = = 1 ) ) {
QStringPair pair ( filever . values ( ) . at ( 0 ) ) ;
diffGraphical ( pair . first , pair . second ) ;
return ;
}
rmdir ( QDir : : tempPath ( ) + QLatin1String ( " /ccdiff/ " ) + activity ) ;
QDir ( QDir : : tempPath ( ) ) . rmpath ( QLatin1String ( " ccdiff/ " ) + activity ) ;
m_diffPrefix = activity ;
2013-03-08 09:53:02 +01:00
const FileVerIt fend = filever . end ( ) ;
for ( FileVerIt it = filever . begin ( ) ; it ! = fend ; + + it ) {
QStringPair & pair ( it . value ( ) ) ;
2011-06-05 17:58:02 +03:00
if ( pair . first . contains ( QLatin1String ( " CHECKEDOUT " ) ) )
pair . first = ccGetPredecessor ( pair . first . left ( pair . first . indexOf ( QLatin1String ( " @@ " ) ) ) ) ;
result + = diffExternal ( pair . first , pair . second , true ) ;
}
m_diffPrefix . clear ( ) ;
const QString title = QString : : fromLatin1 ( " %1.patch " ) . arg ( activity ) ;
2013-08-30 09:22:42 +02:00
IEditor * editor = showOutputInEditor ( title , result , VcsBase : : DiffOutput , activity , 0 ) ;
2013-10-06 20:52:09 +03:00
setWorkingDirectory ( editor , topLevel ) ;
2011-06-05 17:58:02 +03:00
}
void ClearCasePlugin : : diffCurrentFile ( )
{
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return ) ;
2012-09-12 09:27:06 +03:00
ccDiffWithPred ( state . topLevel ( ) , QStringList ( state . relativeCurrentFile ( ) ) ) ;
2011-06-05 17:58:02 +03:00
}
void ClearCasePlugin : : startCheckInCurrentFile ( )
{
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return ) ;
QString nativeFile = QDir : : toNativeSeparators ( state . relativeCurrentFile ( ) ) ;
startCheckIn ( state . currentFileTopLevel ( ) , QStringList ( nativeFile ) ) ;
}
void ClearCasePlugin : : startCheckInAll ( )
{
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasTopLevel ( ) , return ) ;
QString topLevel = state . topLevel ( ) ;
QStringList files ;
2012-09-02 10:20:32 +03:00
for ( StatusMap : : ConstIterator iterator = m_statusMap - > constBegin ( ) ;
iterator ! = m_statusMap - > constEnd ( ) ;
2011-06-05 17:58:02 +03:00
+ + iterator )
{
if ( iterator . value ( ) . status = = FileStatus : : CheckedOut )
files . append ( QDir : : toNativeSeparators ( iterator . key ( ) ) ) ;
}
2013-01-13 17:45:52 +02:00
files . sort ( ) ;
2011-06-05 17:58:02 +03:00
startCheckIn ( topLevel , files ) ;
}
void ClearCasePlugin : : startCheckInActivity ( )
{
2012-09-24 11:39:34 +02:00
QTC_ASSERT ( isUcm ( ) , return ) ;
2011-06-05 17:58:02 +03:00
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasProject ( ) , return ) ;
2012-09-24 11:39:34 +02:00
2011-06-05 17:58:02 +03:00
QDialog dlg ;
QVBoxLayout * layout = new QVBoxLayout ( & dlg ) ;
ActivitySelector * actSelector = new ActivitySelector ( & dlg ) ;
QDialogButtonBox * buttonBox = new QDialogButtonBox ( QDialogButtonBox : : Ok | QDialogButtonBox : : Cancel , Qt : : Horizontal , & dlg ) ;
connect ( buttonBox , SIGNAL ( accepted ( ) ) , & dlg , SLOT ( accept ( ) ) ) ;
connect ( buttonBox , SIGNAL ( rejected ( ) ) , & dlg , SLOT ( reject ( ) ) ) ;
layout - > addWidget ( actSelector ) ;
layout - > addWidget ( buttonBox ) ;
dlg . setWindowTitle ( tr ( " Check In Activity " ) ) ;
if ( ! dlg . exec ( ) )
return ;
2012-09-24 11:39:34 +02:00
2011-06-05 17:58:02 +03:00
QString topLevel = state . topLevel ( ) ;
int topLevelLen = topLevel . length ( ) ;
QStringList versions = ccGetActivityVersions ( topLevel , actSelector - > activity ( ) ) ;
QStringList files ;
QString last ;
foreach ( const QString & version , versions ) {
int atatpos = version . indexOf ( QLatin1String ( " @@ " ) ) ;
if ( ( atatpos ! = - 1 ) & & ( version . indexOf ( QLatin1String ( " CHECKEDOUT " ) , atatpos ) ! = - 1 ) ) {
QString file = version . left ( atatpos ) ;
if ( file ! = last )
files . append ( file . mid ( topLevelLen + 1 ) ) ;
last = file ;
}
}
2013-01-13 17:45:52 +02:00
files . sort ( ) ;
2012-11-15 13:45:48 +02:00
startCheckIn ( topLevel , files ) ;
2011-06-05 17:58:02 +03:00
}
/* Start check in of files of a single repository by displaying
* template and files in a submit editor . On closing , the real
* check in will start . */
void ClearCasePlugin : : startCheckIn ( const QString & workingDir , const QStringList & files )
{
2013-04-18 12:06:43 +02:00
if ( raiseSubmitEditor ( ) )
2011-06-05 17:58:02 +03:00
return ;
VcsBase : : VcsBaseOutputWindow * outputwindow = VcsBase : : VcsBaseOutputWindow : : instance ( ) ;
if ( isCheckInEditorOpen ( ) ) {
outputwindow - > appendWarning ( tr ( " Another check in is currently being executed. " ) ) ;
return ;
}
// Get list of added/modified/deleted files
if ( files . empty ( ) ) {
outputwindow - > appendWarning ( tr ( " There are no modified files. " ) ) ;
return ;
}
// Create a new submit change file containing the submit template
Utils : : TempFileSaver saver ;
saver . setAutoRemove ( false ) ;
// TODO: Retrieve submit template from
const QString submitTemplate ;
// Create a submit
saver . write ( submitTemplate . toUtf8 ( ) ) ;
if ( ! saver . finalize ( ) ) {
VcsBase : : VcsBaseOutputWindow : : instance ( ) - > appendError ( saver . errorString ( ) ) ;
return ;
}
m_checkInMessageFileName = saver . fileName ( ) ;
2012-09-12 09:27:06 +03:00
m_checkInView = workingDir ;
2011-06-05 17:58:02 +03:00
// Create a submit editor and set file list
2012-11-30 11:36:35 +02:00
ClearCaseSubmitEditor * editor = openClearCaseSubmitEditor ( m_checkInMessageFileName , m_viewData . isUcm ) ;
2013-04-18 12:06:43 +02:00
setSubmitEditor ( editor ) ;
2011-06-05 17:58:02 +03:00
editor - > setStatusList ( files ) ;
2012-09-24 11:39:34 +02:00
2012-11-30 11:36:35 +02:00
if ( m_viewData . isUcm & & ( files . size ( ) = = 1 ) ) {
2011-06-05 17:58:02 +03:00
QString activity = ccGetFileActivity ( workingDir , files . first ( ) ) ;
editor - > submitEditorWidget ( ) - > setActivity ( activity ) ;
}
}
void ClearCasePlugin : : historyCurrentFile ( )
{
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return ) ;
history ( state . currentFileTopLevel ( ) , QStringList ( state . relativeCurrentFile ( ) ) , true ) ;
}
void ClearCasePlugin : : updateView ( )
{
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasTopLevel ( ) , return ) ;
ccUpdate ( state . topLevel ( ) ) ;
}
void ClearCasePlugin : : history ( const QString & workingDir ,
const QStringList & files ,
bool enableAnnotationContextMenu )
{
QTextCodec * codec = VcsBase : : VcsBaseEditorWidget : : getCodec ( workingDir , files ) ;
// no need for temp file
QStringList args ( QLatin1String ( " lshistory " ) ) ;
if ( m_settings . historyCount > 0 )
args < < QLatin1String ( " -last " ) < < QString : : number ( m_settings . historyCount ) ;
if ( ! m_intStream . isEmpty ( ) )
args < < QLatin1String ( " -branch " ) < < m_intStream ;
foreach ( const QString & file , files )
args . append ( QDir : : toNativeSeparators ( file ) ) ;
const ClearCaseResponse response =
runCleartool ( workingDir , args , m_settings . timeOutMS ( ) ,
0 , codec ) ;
if ( response . error )
return ;
// Re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
const QString id = VcsBase : : VcsBaseEditorWidget : : getTitleId ( workingDir , files ) ;
const QString tag = VcsBase : : VcsBaseEditorWidget : : editorTag ( VcsBase : : LogOutput , workingDir , files ) ;
2013-08-30 09:22:42 +02:00
if ( IEditor * editor = VcsBase : : VcsBaseEditorWidget : : locateEditorByTag ( tag ) ) {
2013-07-15 15:14:10 +02:00
editor - > document ( ) - > setContents ( response . stdOut . toUtf8 ( ) ) ;
2013-08-30 09:22:42 +02:00
EditorManager : : activateEditor ( editor ) ;
2011-06-05 17:58:02 +03:00
} else {
const QString title = QString : : fromLatin1 ( " cc history %1 " ) . arg ( id ) ;
const QString source = VcsBase : : VcsBaseEditorWidget : : getSource ( workingDir , files ) ;
2013-08-30 09:22:42 +02:00
IEditor * newEditor = showOutputInEditor ( title , response . stdOut , VcsBase : : LogOutput , source , codec ) ;
2011-06-05 17:58:02 +03:00
VcsBase : : VcsBaseEditorWidget : : tagEditor ( newEditor , tag ) ;
if ( enableAnnotationContextMenu )
VcsBase : : VcsBaseEditorWidget : : getVcsBaseEditor ( newEditor ) - > setFileLogAnnotateEnabled ( true ) ;
}
}
void ClearCasePlugin : : viewStatus ( )
{
2012-11-30 11:36:35 +02:00
if ( m_viewData . name . isEmpty ( ) )
m_viewData = ccGetView ( m_topLevel ) ;
QTC_ASSERT ( ! m_viewData . name . isEmpty ( ) & & ! m_settings . disableIndexer , return ) ;
2011-06-05 17:58:02 +03:00
VcsBase : : VcsBaseOutputWindow * outputwindow = VcsBase : : VcsBaseOutputWindow : : instance ( ) ;
2013-12-05 13:30:20 +01:00
outputwindow - > appendCommand ( QLatin1String ( " Indexed files status (C=Checked Out, "
" H=Hijacked, ?=Missing) " ) ) ;
2011-06-05 17:58:02 +03:00
bool anymod = false ;
2012-09-02 10:20:32 +03:00
for ( StatusMap : : ConstIterator it = m_statusMap - > constBegin ( ) ;
it ! = m_statusMap - > constEnd ( ) ;
2011-06-05 17:58:02 +03:00
+ + it )
{
char cstat = 0 ;
switch ( it . value ( ) . status ) {
case FileStatus : : CheckedOut : cstat = ' C ' ; break ;
case FileStatus : : Hijacked : cstat = ' H ' ; break ;
case FileStatus : : Missing : cstat = ' ? ' ; break ;
default : break ;
}
if ( cstat ) {
outputwindow - > append ( QString : : fromLatin1 ( " %1 %2 \n " )
. arg ( cstat )
. arg ( QDir : : toNativeSeparators ( it . key ( ) ) ) ) ;
anymod = true ;
}
}
if ( ! anymod )
outputwindow - > appendWarning ( QLatin1String ( " No modified files found! " ) ) ;
}
void ClearCasePlugin : : ccUpdate ( const QString & workingDir , const QStringList & relativePaths )
{
QStringList args ( QLatin1String ( " update " ) ) ;
args < < QLatin1String ( " -noverwrite " ) ;
if ( ! relativePaths . isEmpty ( ) )
args . append ( relativePaths ) ;
const ClearCaseResponse response =
runCleartool ( workingDir , args , m_settings . longTimeOutMS ( ) , ShowStdOutInLogWindow ) ;
if ( ! response . error )
clearCaseControl ( ) - > emitRepositoryChanged ( workingDir ) ;
}
void ClearCasePlugin : : annotateCurrentFile ( )
{
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return ) ;
vcsAnnotate ( state . currentFileTopLevel ( ) , state . relativeCurrentFile ( ) ) ;
}
2013-10-06 20:47:29 +03:00
void ClearCasePlugin : : annotateVersion ( const QString & workingDirectory ,
const QString & file ,
const QString & revision ,
int lineNr )
2011-06-05 17:58:02 +03:00
{
2013-10-06 20:47:29 +03:00
vcsAnnotate ( workingDirectory , file , revision , lineNr ) ;
2011-06-05 17:58:02 +03:00
}
void ClearCasePlugin : : vcsAnnotate ( const QString & workingDir , const QString & file ,
const QString & revision /* = QString() */ ,
int lineNumber /* = -1 */ ) const
{
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2011-06-05 17:58:02 +03:00
qDebug ( ) < < Q_FUNC_INFO < < file ;
QTextCodec * codec = VcsBase : : VcsBaseEditorWidget : : getCodec ( file ) ;
// Determine id
QString id = file ;
if ( ! revision . isEmpty ( ) )
id + = QLatin1String ( " @@ " ) + revision ;
QStringList args ( QLatin1String ( " annotate " ) ) ;
args < < QLatin1String ( " -nco " ) < < QLatin1String ( " -f " ) ;
args < < QLatin1String ( " -fmt " ) < < QLatin1String ( " %-14.14Sd %-8.8u | " ) ;
args < < QLatin1String ( " -out " ) < < QLatin1String ( " - " ) ;
args . append ( QDir : : toNativeSeparators ( id ) ) ;
const ClearCaseResponse response =
runCleartool ( workingDir , args , m_settings . timeOutMS ( ) , 0 , codec ) ;
if ( response . error )
return ;
// Re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
const QString source = workingDir + QLatin1Char ( ' / ' ) + file ;
if ( lineNumber < = 0 )
lineNumber = VcsBase : : VcsBaseEditorWidget : : lineNumberOfCurrentEditor ( source ) ;
QString headerSep ( QLatin1String ( " ------------------------------------------------- " ) ) ;
int pos = qMax ( 0 , response . stdOut . indexOf ( headerSep ) ) ;
// there are 2 identical headerSep lines - skip them
int dataStart = response . stdOut . indexOf ( QLatin1Char ( ' \n ' ) , pos ) + 1 ;
dataStart = response . stdOut . indexOf ( QLatin1Char ( ' \n ' ) , dataStart ) + 1 ;
QString res ;
QTextStream stream ( & res , QIODevice : : WriteOnly | QIODevice : : Text ) ;
stream < < response . stdOut . mid ( dataStart ) < < headerSep < < QLatin1Char ( ' \n ' )
< < headerSep < < QLatin1Char ( ' \n ' ) < < response . stdOut . left ( pos ) ;
const QStringList files = QStringList ( file ) ;
const QString tag = VcsBase : : VcsBaseEditorWidget : : editorTag ( VcsBase : : AnnotateOutput , workingDir , files ) ;
2013-08-30 09:22:42 +02:00
if ( IEditor * editor = VcsBase : : VcsBaseEditorWidget : : locateEditorByTag ( tag ) ) {
2013-07-15 15:14:10 +02:00
editor - > document ( ) - > setContents ( res . toUtf8 ( ) ) ;
2011-06-05 17:58:02 +03:00
VcsBase : : VcsBaseEditorWidget : : gotoLineOfEditor ( editor , lineNumber ) ;
2013-08-30 09:22:42 +02:00
EditorManager : : activateEditor ( editor ) ;
2011-06-05 17:58:02 +03:00
} else {
const QString title = QString : : fromLatin1 ( " cc annotate %1 " ) . arg ( id ) ;
2013-08-30 09:22:42 +02:00
IEditor * newEditor = showOutputInEditor ( title , res , VcsBase : : AnnotateOutput , source , codec ) ;
2011-06-05 17:58:02 +03:00
VcsBase : : VcsBaseEditorWidget : : tagEditor ( newEditor , tag ) ;
VcsBase : : VcsBaseEditorWidget : : gotoLineOfEditor ( newEditor , lineNumber ) ;
}
}
void ClearCasePlugin : : describe ( const QString & source , const QString & changeNr )
{
const QFileInfo fi ( source ) ;
QString topLevel ;
const bool manages = managesDirectory ( fi . isDir ( ) ? source : fi . absolutePath ( ) , & topLevel ) ;
if ( ! manages | | topLevel . isEmpty ( ) )
return ;
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2011-06-05 17:58:02 +03:00
qDebug ( ) < < Q_FUNC_INFO < < source < < topLevel < < changeNr ;
QString description ;
QString relPath = QDir : : toNativeSeparators ( QDir ( topLevel ) . relativeFilePath ( source ) ) ;
QString id = QString : : fromLatin1 ( " %1@@%2 " ) . arg ( relPath ) . arg ( changeNr ) ;
QStringList args ( QLatin1String ( " describe " ) ) ;
args . push_back ( id ) ;
QTextCodec * codec = VcsBase : : VcsBaseEditorWidget : : getCodec ( source ) ;
const ClearCaseResponse response =
runCleartool ( topLevel , args , m_settings . timeOutMS ( ) , 0 , codec ) ;
description = response . stdOut ;
2012-09-02 11:26:26 +03:00
if ( m_settings . extDiffAvailable )
description + = diffExternal ( id ) ;
2011-06-05 17:58:02 +03:00
// Re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
const QString tag = VcsBase : : VcsBaseEditorWidget : : editorTag ( VcsBase : : DiffOutput , source , QStringList ( ) , changeNr ) ;
2013-08-30 09:22:42 +02:00
if ( IEditor * editor = VcsBase : : VcsBaseEditorWidget : : locateEditorByTag ( tag ) ) {
2013-07-15 15:14:10 +02:00
editor - > document ( ) - > setContents ( description . toUtf8 ( ) ) ;
2013-08-30 09:22:42 +02:00
EditorManager : : activateEditor ( editor ) ;
2011-06-05 17:58:02 +03:00
} else {
const QString title = QString : : fromLatin1 ( " cc describe %1 " ) . arg ( id ) ;
2013-08-30 09:22:42 +02:00
IEditor * newEditor = showOutputInEditor ( title , description , VcsBase : : DiffOutput , source , codec ) ;
2011-06-05 17:58:02 +03:00
VcsBase : : VcsBaseEditorWidget : : tagEditor ( newEditor , tag ) ;
}
}
void ClearCasePlugin : : checkInSelected ( )
{
m_submitActionTriggered = true ;
2013-08-30 09:22:42 +02:00
EditorManager : : closeEditor ( ) ;
2011-06-05 17:58:02 +03:00
}
QString ClearCasePlugin : : runCleartoolSync ( const QString & workingDir ,
const QStringList & arguments ) const
{
return runCleartool ( workingDir , arguments , m_settings . timeOutMS ( ) , SilentRun ) . stdOut ;
}
ClearCaseResponse
ClearCasePlugin : : runCleartool ( const QString & workingDir ,
const QStringList & arguments ,
int timeOut ,
unsigned flags ,
QTextCodec * outputCodec ) const
{
2012-08-21 10:06:05 +03:00
const QString executable = m_settings . ccBinaryPath ;
2011-06-05 17:58:02 +03:00
ClearCaseResponse response ;
if ( executable . isEmpty ( ) ) {
response . error = true ;
2012-08-27 12:24:23 +02:00
response . message = tr ( " No ClearCase executable specified. " ) ;
2011-06-05 17:58:02 +03:00
return response ;
}
const Utils : : SynchronousProcessResponse sp_resp =
VcsBase : : VcsBasePlugin : : runVcs ( workingDir , executable ,
2013-08-16 17:02:30 +03:00
arguments , timeOut ,
flags , outputCodec ) ;
2011-06-05 17:58:02 +03:00
response . error = sp_resp . result ! = Utils : : SynchronousProcessResponse : : Finished ;
if ( response . error )
response . message = sp_resp . exitMessage ( executable , timeOut ) ;
response . stdErr = sp_resp . stdErr ;
response . stdOut = sp_resp . stdOut ;
return response ;
}
2013-08-30 09:22:42 +02:00
IEditor * ClearCasePlugin : : showOutputInEditor ( const QString & title , const QString & output ,
2011-06-05 17:58:02 +03:00
int editorType , const QString & source ,
QTextCodec * codec ) const
{
const VcsBase : : VcsBaseEditorParameters * params = findType ( editorType ) ;
QTC_ASSERT ( params , return 0 ) ;
2013-08-30 09:22:42 +02:00
const Id id = params - > id ;
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2011-06-05 17:58:02 +03:00
qDebug ( ) < < " ClearCasePlugin::showOutputInEditor " < < title < < id . name ( )
< < " Size= " < < output . size ( ) < < " Type= " < < editorType < < debugCodec ( codec ) ;
QString s = title ;
2013-08-30 09:22:42 +02:00
IEditor * editor = EditorManager : : openEditorWithContents ( id , & s , output . toUtf8 ( ) ) ;
2013-10-06 20:47:29 +03:00
connect ( editor , SIGNAL ( annotateRevisionRequested ( QString , QString , QString , int ) ) ,
this , SLOT ( annotateVersion ( QString , QString , QString , int ) ) ) ;
2011-06-05 17:58:02 +03:00
ClearCaseEditor * e = qobject_cast < ClearCaseEditor * > ( editor - > widget ( ) ) ;
if ( ! e )
return 0 ;
e - > setForceReadOnly ( true ) ;
s . replace ( QLatin1Char ( ' ' ) , QLatin1Char ( ' _ ' ) ) ;
e - > setSuggestedFileName ( s ) ;
if ( ! source . isEmpty ( ) )
e - > setSource ( source ) ;
if ( codec )
e - > setCodec ( codec ) ;
2013-08-30 09:22:42 +02:00
IEditor * ie = e - > editor ( ) ;
EditorManager : : activateEditor ( ie ) ;
2011-06-05 17:58:02 +03:00
return ie ;
}
const ClearCaseSettings & ClearCasePlugin : : settings ( ) const
{
return m_settings ;
}
void ClearCasePlugin : : setSettings ( const ClearCaseSettings & s )
{
if ( s ! = m_settings ) {
m_settings = s ;
2013-08-30 09:22:42 +02:00
m_settings . toSettings ( ICore : : settings ( ) ) ;
2011-06-05 17:58:02 +03:00
clearCaseControl ( ) - > emitConfigurationChanged ( ) ;
}
}
ClearCasePlugin * ClearCasePlugin : : instance ( )
{
QTC_ASSERT ( m_clearcasePluginInstance , return m_clearcasePluginInstance ) ;
return m_clearcasePluginInstance ;
}
bool ClearCasePlugin : : vcsOpen ( const QString & workingDir , const QString & fileName )
{
QTC_ASSERT ( currentState ( ) . hasTopLevel ( ) , return false ) ;
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2011-06-05 17:58:02 +03:00
qDebug ( ) < < Q_FUNC_INFO < < workingDir < < fileName ;
QFileInfo fi ( workingDir , fileName ) ;
QString topLevel = currentState ( ) . topLevel ( ) ;
QString absPath = fi . absoluteFilePath ( ) ;
const QString relFile = QDir ( topLevel ) . relativeFilePath ( absPath ) ;
const QString file = QDir : : toNativeSeparators ( relFile ) ;
const QString title = QString : : fromLatin1 ( " Checkout %1 " ) . arg ( file ) ;
2012-11-30 11:36:35 +02:00
CheckOutDialog coDialog ( title , m_viewData . isUcm ) ;
2012-09-24 11:39:34 +02:00
2011-06-05 17:58:02 +03:00
if ( ! m_settings . disableIndexer & &
2013-12-05 13:30:20 +01:00
( fi . isWritable ( ) | | vcsStatus ( absPath ) . status = = FileStatus : : Unknown ) )
2013-04-18 22:25:23 +02:00
QtConcurrent : : run ( & sync , QStringList ( absPath ) ) . waitForFinished ( ) ;
2013-12-05 13:30:20 +01:00
if ( vcsStatus ( absPath ) . status = = FileStatus : : CheckedOut ) {
2012-08-27 12:24:23 +02:00
QMessageBox : : information ( 0 , tr ( " ClearCase Checkout " ) , tr ( " File is already checked out. " ) ) ;
2011-06-05 17:58:02 +03:00
return true ;
}
2012-09-17 22:53:51 +02:00
// Only snapshot views can have hijacked files
2013-12-05 13:30:20 +01:00
bool isHijacked = ( ! m_viewData . isDynamic & & ( vcsStatus ( absPath ) . status & FileStatus : : Hijacked ) ) ;
2011-06-05 17:58:02 +03:00
if ( ! isHijacked )
coDialog . hideHijack ( ) ;
if ( coDialog . exec ( ) = = QDialog : : Accepted ) {
2012-11-30 11:36:35 +02:00
if ( m_viewData . isUcm & & ! vcsSetActivity ( topLevel , title , coDialog . activity ( ) ) )
2011-06-05 17:58:02 +03:00
return false ;
2012-09-24 11:39:34 +02:00
2013-08-30 09:22:42 +02:00
FileChangeBlocker fcb ( absPath ) ;
2011-06-05 17:58:02 +03:00
QStringList args ( QLatin1String ( " checkout " ) ) ;
QString comment = coDialog . comment ( ) ;
if ( comment . isEmpty ( ) )
args < < QLatin1String ( " -nc " ) ;
else
args < < QLatin1String ( " -c " ) < < comment ;
args < < QLatin1String ( " -query " ) ;
if ( coDialog . isReserved ( ) )
args < < QLatin1String ( " -reserved " ) ;
if ( coDialog . isUnreserved ( ) )
args < < QLatin1String ( " -unreserved " ) ;
if ( coDialog . isPreserveTime ( ) )
args < < QLatin1String ( " -ptime " ) ;
if ( isHijacked ) {
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2012-09-17 22:53:51 +02:00
qDebug ( ) < < Q_FUNC_INFO < < file < < " seems to be hijacked " ;
// A hijacked files means that the file is modified but was
// not checked out. By checking it out now changes will
// be lost, unless handled. This can be done by renaming
// the hijacked file, undoing the hijack and updating the file
2011-06-05 17:58:02 +03:00
// -usehijack not supported in old cleartool versions...
// args << QLatin1String("-usehijack");
if ( coDialog . isUseHijacked ( ) )
QFile : : rename ( absPath , absPath + QLatin1String ( " .hijack " ) ) ;
vcsUndoHijack ( topLevel , relFile , false ) ; // don't keep, we've already kept a copy
}
args < < file ;
ClearCaseResponse response =
runCleartool ( topLevel , args , m_settings . timeOutMS ( ) , ShowStdOutInLogWindow |
SuppressStdErrInLogWindow | FullySynchronously ) ;
if ( response . error ) {
if ( response . stdErr . contains ( QLatin1String ( " Versions other than the selected version " ) ) ) {
VersionSelector selector ( file , response . stdErr ) ;
if ( selector . exec ( ) = = QDialog : : Accepted ) {
if ( selector . isUpdate ( ) )
ccUpdate ( workingDir , QStringList ( ) < < file ) ;
else
args . removeOne ( QLatin1String ( " -query " ) ) ;
response = runCleartool ( topLevel , args , m_settings . timeOutMS ( ) ,
ShowStdOutInLogWindow | FullySynchronously ) ;
}
} else {
VcsBase : : VcsBaseOutputWindow * outputWindow = VcsBase : : VcsBaseOutputWindow : : instance ( ) ;
outputWindow - > append ( response . stdOut ) ;
2013-08-11 22:35:49 +03:00
outputWindow - > appendError ( response . stdErr ) ;
2011-06-05 17:58:02 +03:00
}
}
if ( ! response . error & & isHijacked & & coDialog . isUseHijacked ( ) ) { // rename back
QFile : : remove ( absPath ) ;
QFile : : rename ( absPath + QLatin1String ( " .hijack " ) , absPath ) ;
}
2013-11-21 09:49:19 +01:00
if ( ( ! response . error | | response . stdErr . contains ( QLatin1String ( " already checked out " ) ) )
2013-04-18 22:25:23 +02:00
& & ! m_settings . disableIndexer ) {
setStatus ( absPath , FileStatus : : CheckedOut ) ;
}
2011-06-05 17:58:02 +03:00
return ! response . error ;
}
return true ;
}
bool ClearCasePlugin : : vcsSetActivity ( const QString & workingDir , const QString & title , const QString & activity )
{
QStringList args ;
args < < QLatin1String ( " setactivity " ) < < activity ;
const ClearCaseResponse actResponse =
runCleartool ( workingDir , args , m_settings . timeOutMS ( ) , ShowStdOutInLogWindow ) ;
if ( actResponse . error ) {
QMessageBox : : warning ( 0 , title , tr ( " Set current activity failed: %1 " ) . arg ( actResponse . message ) , QMessageBox : : Ok ) ;
return false ;
}
m_activity = activity ;
return true ;
}
// files are received using native separators
bool ClearCasePlugin : : vcsCheckIn ( const QString & messageFile , const QStringList & files , const QString & activity ,
bool isIdentical , bool isPreserve , bool replaceActivity )
{
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2011-06-05 17:58:02 +03:00
qDebug ( ) < < Q_FUNC_INFO < < messageFile < < files < < activity ;
if ( files . isEmpty ( ) )
return true ;
const QString title = QString : : fromLatin1 ( " Checkin %1 " ) . arg ( files . join ( QLatin1String ( " ; " ) ) ) ;
2013-08-30 09:22:42 +02:00
typedef QSharedPointer < FileChangeBlocker > FCBPointer ;
2011-06-05 17:58:02 +03:00
replaceActivity & = ( activity ! = QLatin1String ( Constants : : KEEP_ACTIVITY ) ) ;
2012-09-12 09:27:06 +03:00
if ( replaceActivity & & ! vcsSetActivity ( m_checkInView , title , activity ) )
2011-06-05 17:58:02 +03:00
return false ;
QFile msgFile ( messageFile ) ;
msgFile . open ( QFile : : ReadOnly | QFile : : Text ) ;
QString message = QString : : fromLocal8Bit ( msgFile . readAll ( ) . trimmed ( ) . constData ( ) ) ;
msgFile . close ( ) ;
QStringList args ;
args < < QLatin1String ( " checkin " ) ;
if ( message . isEmpty ( ) )
args < < QLatin1String ( " -nc " ) ;
else
args < < QLatin1String ( " -cfile " ) < < messageFile ;
if ( isIdentical )
args < < QLatin1String ( " -identical " ) ;
if ( isPreserve )
args < < QLatin1String ( " -ptime " ) ;
args < < files ;
QList < FCBPointer > blockers ;
2013-03-08 09:53:02 +01:00
foreach ( const QString & fileName , files ) {
2013-08-30 09:22:42 +02:00
FCBPointer fcb ( new FileChangeBlocker ( QFileInfo ( m_checkInView , fileName ) . canonicalFilePath ( ) ) ) ;
2011-06-05 17:58:02 +03:00
blockers . append ( fcb ) ;
}
const ClearCaseResponse response =
2012-09-12 09:27:06 +03:00
runCleartool ( m_checkInView , args , m_settings . longTimeOutMS ( ) , ShowStdOutInLogWindow ) ;
2011-06-05 17:58:02 +03:00
QRegExp checkedIn ( QLatin1String ( " Checked in \\ \" ([^ \" ]*) \ \ \ " " ) ) ;
bool anySucceeded = false ;
int offset = checkedIn . indexIn ( response . stdOut ) ;
while ( offset ! = - 1 ) {
QString file = checkedIn . cap ( 1 ) ;
2013-04-18 22:25:23 +02:00
QFileInfo fi ( m_checkInView , file ) ;
QString absPath = fi . absoluteFilePath ( ) ;
2011-06-05 17:58:02 +03:00
if ( ! m_settings . disableIndexer )
2013-04-18 22:25:23 +02:00
setStatus ( QDir : : fromNativeSeparators ( absPath ) , FileStatus : : CheckedIn ) ;
2011-06-05 17:58:02 +03:00
clearCaseControl ( ) - > emitFilesChanged ( files ) ;
anySucceeded = true ;
offset = checkedIn . indexIn ( response . stdOut , offset + 12 ) ;
}
return anySucceeded ;
}
bool ClearCasePlugin : : ccFileOp ( const QString & workingDir , const QString & title , const QStringList & opArgs ,
const QString & fileName , const QString & file2 )
{
const QString file = QDir : : toNativeSeparators ( fileName ) ;
bool noCheckout = false ;
QVBoxLayout * verticalLayout ;
2012-09-24 11:39:34 +02:00
ActivitySelector * actSelector = 0 ;
2011-06-05 17:58:02 +03:00
QLabel * commentLabel ;
QTextEdit * commentEdit ;
QDialogButtonBox * buttonBox ;
QDialog fileOpDlg ;
fileOpDlg . setWindowTitle ( title ) ;
verticalLayout = new QVBoxLayout ( & fileOpDlg ) ;
2012-11-30 11:36:35 +02:00
if ( m_viewData . isUcm ) {
2012-09-24 11:39:34 +02:00
actSelector = new ActivitySelector ;
verticalLayout - > addWidget ( actSelector ) ;
}
2011-06-05 17:58:02 +03:00
commentLabel = new QLabel ( tr ( " Enter &comment: " ) ) ;
verticalLayout - > addWidget ( commentLabel ) ;
commentEdit = new QTextEdit ;
verticalLayout - > addWidget ( commentEdit ) ;
buttonBox = new QDialogButtonBox ;
buttonBox - > setStandardButtons ( QDialogButtonBox : : Cancel | QDialogButtonBox : : Ok ) ;
verticalLayout - > addWidget ( buttonBox ) ;
# ifndef QT_NO_SHORTCUT
commentLabel - > setBuddy ( commentEdit ) ;
# endif // QT_NO_SHORTCUT
connect ( buttonBox , SIGNAL ( accepted ( ) ) , & fileOpDlg , SLOT ( accept ( ) ) ) ;
connect ( buttonBox , SIGNAL ( rejected ( ) ) , & fileOpDlg , SLOT ( reject ( ) ) ) ;
if ( ! fileOpDlg . exec ( ) )
2013-11-22 09:03:39 +01:00
return false ;
2012-09-24 11:39:34 +02:00
2011-06-05 17:58:02 +03:00
QString comment = commentEdit - > toPlainText ( ) ;
2012-11-30 11:36:35 +02:00
if ( m_viewData . isUcm & & actSelector - > changed ( ) )
2011-06-05 17:58:02 +03:00
vcsSetActivity ( workingDir , fileOpDlg . windowTitle ( ) , actSelector - > activity ( ) ) ;
2012-09-24 11:39:34 +02:00
2011-06-05 17:58:02 +03:00
QString dirName = QDir : : toNativeSeparators ( QFileInfo ( workingDir , fileName ) . absolutePath ( ) ) ;
QStringList commentArg ;
if ( comment . isEmpty ( ) )
commentArg < < QLatin1String ( " -nc " ) ;
else
commentArg < < QLatin1String ( " -c " ) < < comment ;
// check out directory
QStringList args ;
args < < QLatin1String ( " checkout " ) < < commentArg < < dirName ;
const ClearCaseResponse coResponse =
runCleartool ( workingDir , args , m_settings . timeOutMS ( ) ,
ShowStdOutInLogWindow | FullySynchronously ) ;
if ( coResponse . error ) {
2013-11-21 09:49:19 +01:00
if ( coResponse . stdErr . contains ( QLatin1String ( " already checked out " ) ) )
2011-06-05 17:58:02 +03:00
noCheckout = true ;
else
return false ;
}
// do the file operation
args . clear ( ) ;
args < < opArgs < < commentArg < < file ;
if ( ! file2 . isEmpty ( ) )
args < < QDir : : toNativeSeparators ( file2 ) ;
const ClearCaseResponse opResponse =
runCleartool ( workingDir , args , m_settings . timeOutMS ( ) ,
ShowStdOutInLogWindow | FullySynchronously ) ;
if ( opResponse . error ) {
// on failure - undo checkout for the directory
if ( ! noCheckout )
vcsUndoCheckOut ( workingDir , dirName , false ) ;
return false ;
}
if ( ! noCheckout ) {
// check in the directory
args . clear ( ) ;
args < < QLatin1String ( " checkin " ) < < commentArg < < dirName ;
const ClearCaseResponse ciResponse =
runCleartool ( workingDir , args , m_settings . timeOutMS ( ) ,
ShowStdOutInLogWindow | FullySynchronously ) ;
return ! ciResponse . error ;
}
return true ;
}
2012-09-17 22:26:23 +02:00
static QString baseName ( const QString & fileName )
{
return fileName . mid ( fileName . lastIndexOf ( QLatin1Char ( ' / ' ) ) + 1 ) ;
}
2011-06-05 17:58:02 +03:00
bool ClearCasePlugin : : vcsAdd ( const QString & workingDir , const QString & fileName )
{
2012-09-17 22:26:23 +02:00
return ccFileOp ( workingDir , tr ( " ClearCase Add File %1 " ) . arg ( baseName ( fileName ) ) ,
2011-06-05 17:58:02 +03:00
QStringList ( ) < < QLatin1String ( " mkelem " ) < < QLatin1String ( " -ci " ) , fileName ) ;
}
bool ClearCasePlugin : : vcsDelete ( const QString & workingDir , const QString & fileName )
{
2012-09-17 22:26:23 +02:00
const QString title ( tr ( " ClearCase Remove Element %1 " ) . arg ( baseName ( fileName ) ) ) ;
2012-08-27 12:24:23 +02:00
if ( QMessageBox : : warning ( 0 , title , tr ( " This operation is irreversible. Are you sure? " ) ,
2011-06-05 17:58:02 +03:00
QMessageBox : : Yes | QMessageBox : : No ) = = QMessageBox : : No )
return true ;
2012-09-17 22:26:23 +02:00
return ccFileOp ( workingDir , tr ( " ClearCase Remove File %1 " ) . arg ( baseName ( fileName ) ) ,
2011-06-05 17:58:02 +03:00
QStringList ( ) < < QLatin1String ( " rmname " ) < < QLatin1String ( " -force " ) , fileName ) ;
}
bool ClearCasePlugin : : vcsMove ( const QString & workingDir , const QString & from , const QString & to )
{
2012-09-17 22:26:23 +02:00
return ccFileOp ( workingDir , tr ( " ClearCase Rename File %1 -> %2 " )
. arg ( baseName ( from ) ) . arg ( baseName ( to ) ) ,
2011-06-05 17:58:02 +03:00
QStringList ( ) < < QLatin1String ( " move " ) , from , to ) ;
}
bool ClearCasePlugin : : vcsCheckout ( const QString & /*directory*/ , const QByteArray & /*url*/ )
{
return false ;
}
QString ClearCasePlugin : : vcsGetRepositoryURL ( const QString & /*directory*/ )
{
return currentState ( ) . topLevel ( ) ;
}
2013-04-18 22:25:23 +02:00
///
/// Check if the directory is managed under ClearCase control.
///
2011-06-05 17:58:02 +03:00
bool ClearCasePlugin : : managesDirectory ( const QString & directory , QString * topLevel /* = 0 */ ) const
{
2013-11-20 11:59:34 +01:00
# ifdef WITH_TESTS
// If running with tests and fake ClearTool is enabled, then pretend we manage every directory
QString topLevelFound = m_fakeClearTool ? directory : findTopLevel ( directory ) ;
# else
2011-06-05 17:58:02 +03:00
QString topLevelFound = findTopLevel ( directory ) ;
2013-11-20 11:59:34 +01:00
# endif
2011-06-05 17:58:02 +03:00
if ( topLevel )
* topLevel = topLevelFound ;
return ! topLevelFound . isEmpty ( ) ;
}
ClearCaseControl * ClearCasePlugin : : clearCaseControl ( ) const
{
return static_cast < ClearCaseControl * > ( versionControl ( ) ) ;
}
QString ClearCasePlugin : : ccGetCurrentActivity ( ) const
{
QStringList args ( QLatin1String ( " lsactivity " ) ) ;
args < < QLatin1String ( " -cact " ) ;
args < < QLatin1String ( " -fmt " ) < < QLatin1String ( " %n " ) ;
return runCleartoolSync ( currentState ( ) . topLevel ( ) , args ) ;
}
QList < QStringPair > ClearCasePlugin : : ccGetActivities ( ) const
{
QList < QStringPair > result ;
// Maintain latest deliver and rebase activities only
QStringPair rebaseAct ;
QStringPair deliverAct ;
// Retrieve all activities
2012-08-27 10:26:53 +03:00
QStringList args ( QLatin1String ( " lsactivity " ) ) ;
2011-06-05 17:58:02 +03:00
args < < QLatin1String ( " -fmt " ) < < QLatin1String ( " %n \\ t%[headline]p \\ n " ) ;
const QString response = runCleartoolSync ( currentState ( ) . topLevel ( ) , args ) ;
QStringList acts = response . split ( QLatin1Char ( ' \n ' ) , QString : : SkipEmptyParts ) ;
2013-03-08 09:53:02 +01:00
foreach ( const QString & activity , acts ) {
2011-06-05 17:58:02 +03:00
QStringList act = activity . split ( QLatin1Char ( ' \t ' ) ) ;
if ( act . size ( ) > = 2 )
{
QString actName = act . at ( 0 ) ;
2012-08-27 10:26:53 +03:00
// include only latest deliver/rebase activities. Activities are sorted
// by creation time
if ( actName . startsWith ( QLatin1String ( " rebase. " ) ) )
2011-06-05 17:58:02 +03:00
rebaseAct = QStringPair ( actName , act . at ( 1 ) ) ;
2012-08-27 10:26:53 +03:00
else if ( actName . startsWith ( QLatin1String ( " deliver. " ) ) )
2011-06-05 17:58:02 +03:00
deliverAct = QStringPair ( actName , act . at ( 1 ) ) ;
2012-08-27 10:26:53 +03:00
else
result . append ( QStringPair ( actName , act . at ( 1 ) . trimmed ( ) ) ) ;
2011-06-05 17:58:02 +03:00
}
}
2012-08-27 10:26:53 +03:00
qSort ( result ) ;
2011-06-05 17:58:02 +03:00
if ( ! rebaseAct . first . isEmpty ( ) )
result . append ( rebaseAct ) ;
if ( ! deliverAct . first . isEmpty ( ) )
result . append ( deliverAct ) ;
return result ;
}
void ClearCasePlugin : : refreshActivities ( )
{
2012-09-02 10:18:56 +03:00
QMutexLocker locker ( m_activityMutex ) ;
2011-06-05 17:58:02 +03:00
m_activity = ccGetCurrentActivity ( ) ;
m_activities = ccGetActivities ( ) ;
}
QList < QStringPair > ClearCasePlugin : : activities ( int * current ) const
{
QList < QStringPair > activitiesList ;
QString curActivity ;
const VcsBase : : VcsBasePluginState state = currentState ( ) ;
if ( state . topLevel ( ) = = state . currentProjectTopLevel ( ) ) {
2012-09-02 10:18:56 +03:00
QMutexLocker locker ( m_activityMutex ) ;
2011-06-05 17:58:02 +03:00
activitiesList = m_activities ;
curActivity = m_activity ;
} else {
activitiesList = ccGetActivities ( ) ;
curActivity = ccGetCurrentActivity ( ) ;
}
if ( current ) {
int nActivities = activitiesList . size ( ) ;
* current = - 1 ;
for ( int i = 0 ; i < nActivities & & ( * current = = - 1 ) ; + + i ) {
if ( activitiesList [ i ] . first = = curActivity )
* current = i ;
}
}
return activitiesList ;
}
bool ClearCasePlugin : : newActivity ( )
{
QString workingDir = currentState ( ) . topLevel ( ) ;
QStringList args ;
args < < QLatin1String ( " mkactivity " ) < < QLatin1String ( " -f " ) ;
if ( ! m_settings . autoAssignActivityName ) {
QString headline = QInputDialog : : getText ( 0 , tr ( " Activity Headline " ) , tr ( " Enter activity headline " ) ) ;
if ( headline . isEmpty ( ) )
return false ;
args < < QLatin1String ( " -headline " ) < < headline ;
}
const ClearCaseResponse response =
runCleartool ( workingDir , args , m_settings . timeOutMS ( ) , 0 ) ;
if ( ! response . error )
refreshActivities ( ) ;
return ( ! response . error ) ;
}
2012-09-24 11:39:34 +02:00
// check if the view is UCM
bool ClearCasePlugin : : ccCheckUcm ( const QString & viewname , const QString & workingDir ) const
{
QStringList catcsArgs ( QLatin1String ( " catcs " ) ) ;
catcsArgs < < QLatin1String ( " -tag " ) < < viewname ;
QString catcsData = runCleartoolSync ( workingDir , catcsArgs ) ;
// check output for the word "ucm"
return QRegExp ( QLatin1String ( " (^| \\ n) ucm \ \ n " )).indexIn(catcsData) != -1 ;
}
2013-10-02 00:18:39 +03:00
bool ClearCasePlugin : : managesFile ( const QString & workingDirectory , const QString & fileName ) const
{
2013-12-05 13:30:20 +01:00
QString absFile = QFileInfo ( QDir ( workingDirectory ) , fileName ) . absoluteFilePath ( ) ;
2013-11-20 12:55:23 +01:00
const FileStatus : : Status status = getFileStatus ( absFile ) ;
return status ! = FileStatus : : NotManaged & & status ! = FileStatus : : Derived ;
2013-10-02 00:18:39 +03:00
}
2012-11-30 11:36:35 +02:00
ViewData ClearCasePlugin : : ccGetView ( const QString & workingDir ) const
2011-06-05 17:58:02 +03:00
{
2012-11-29 22:41:18 +02:00
static QHash < QString , ViewData > viewCache ;
bool inCache = viewCache . contains ( workingDir ) ;
ViewData & res = viewCache [ workingDir ] ;
if ( ! inCache ) {
QStringList args ( QLatin1String ( " lsview " ) ) ;
args < < QLatin1String ( " -cview " ) ;
QString data = runCleartoolSync ( workingDir , args ) ;
res . isDynamic = ! data . isEmpty ( ) & & ( data . at ( 0 ) = = QLatin1Char ( ' * ' ) ) ;
res . name = data . mid ( 2 , data . indexOf ( QLatin1Char ( ' ' ) , 2 ) - 2 ) ;
res . isUcm = ccCheckUcm ( res . name , workingDir ) ;
2013-04-18 22:25:23 +02:00
res . root = ccViewRoot ( workingDir ) ;
2012-11-29 22:41:18 +02:00
}
2012-11-30 11:36:35 +02:00
return res ;
2011-06-05 17:58:02 +03:00
}
void ClearCasePlugin : : updateStreamAndView ( )
{
QStringList args ( QLatin1String ( " lsstream " ) ) ;
args < < QLatin1String ( " -fmt " ) < < QLatin1String ( " %n \\ t%[def_deliver_tgt]Xp " ) ;
const QString sresponse = runCleartoolSync ( m_topLevel , args ) ;
int tabPos = sresponse . indexOf ( QLatin1Char ( ' \t ' ) ) ;
m_stream = sresponse . left ( tabPos ) ;
QRegExp intStreamExp ( QLatin1String ( " stream:([^@]*) " )) ;
if ( intStreamExp . indexIn ( sresponse . mid ( tabPos + 1 ) ) ! = - 1 )
m_intStream = intStreamExp . cap ( 1 ) ;
2012-11-30 11:36:35 +02:00
m_viewData = ccGetView ( m_topLevel ) ;
m_updateViewAction - > setParameter ( m_viewData . isDynamic ? QString ( ) : m_viewData . name ) ;
2011-06-05 17:58:02 +03:00
}
2013-08-30 09:22:42 +02:00
void ClearCasePlugin : : projectChanged ( Project * project )
2011-06-05 17:58:02 +03:00
{
2012-11-30 11:36:35 +02:00
if ( m_viewData . name = = ccGetView ( m_topLevel ) . name ) // New project on same view as old project
2011-06-05 17:58:02 +03:00
return ;
2012-11-30 11:36:35 +02:00
m_viewData = ViewData ( ) ;
2011-06-05 17:58:02 +03:00
m_stream . clear ( ) ;
m_intStream . clear ( ) ;
2013-08-30 09:22:42 +02:00
disconnect ( ICore : : mainWindow ( ) , SIGNAL ( windowActivated ( ) ) , this , SLOT ( syncSlot ( ) ) ) ;
2013-09-03 15:18:37 +02:00
ProgressManager : : cancelTasks ( ClearCase : : Constants : : TASK_INDEX ) ;
2011-06-05 17:58:02 +03:00
if ( project ) {
QString projDir = project - > projectDirectory ( ) ;
QString topLevel = findTopLevel ( projDir ) ;
m_topLevel = topLevel ;
if ( topLevel . isEmpty ( ) )
return ;
2013-08-30 09:22:42 +02:00
connect ( ICore : : mainWindow ( ) , SIGNAL ( windowActivated ( ) ) , this , SLOT ( syncSlot ( ) ) ) ;
2011-06-05 17:58:02 +03:00
updateStreamAndView ( ) ;
2012-11-30 11:36:35 +02:00
if ( m_viewData . name . isEmpty ( ) )
2011-06-05 17:58:02 +03:00
return ;
updateIndex ( ) ;
}
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2012-11-30 11:36:35 +02:00
qDebug ( ) < < " stream: " < < m_stream < < " ; intStream: " < < m_intStream < < " view: " < < m_viewData . name ;
2011-06-05 17:58:02 +03:00
}
2013-09-03 15:18:37 +02:00
void ClearCasePlugin : : tasksFinished ( Core : : Id type )
2011-06-05 17:58:02 +03:00
{
2013-09-03 15:18:37 +02:00
if ( type = = ClearCase : : Constants : : TASK_INDEX )
2011-06-05 17:58:02 +03:00
m_checkInAllAction - > setEnabled ( true ) ;
}
void ClearCasePlugin : : updateIndex ( )
{
QTC_ASSERT ( currentState ( ) . hasTopLevel ( ) , return ) ;
2013-09-03 15:18:37 +02:00
ProgressManager : : cancelTasks ( ClearCase : : Constants : : TASK_INDEX ) ;
2013-08-30 09:22:42 +02:00
Project * project = ProjectExplorerPlugin : : currentProject ( ) ;
2011-06-05 17:58:02 +03:00
if ( ! project )
return ;
m_checkInAllAction - > setEnabled ( false ) ;
2012-09-02 10:20:32 +03:00
m_statusMap - > clear ( ) ;
2013-04-18 22:25:23 +02:00
QFuture < void > result = QtConcurrent : : run ( & sync ,
2013-08-30 09:22:42 +02:00
project - > files ( Project : : ExcludeGeneratedFiles ) ) ;
2011-06-05 17:58:02 +03:00
if ( ! m_settings . disableIndexer )
2013-09-03 15:18:37 +02:00
ProgressManager : : addTask ( result , tr ( " CC Indexing " ) , ClearCase : : Constants : : TASK_INDEX ) ;
2011-06-05 17:58:02 +03:00
}
/*! retrieve a \a file (usually of the form path\to\filename.cpp@@\main\ver)
* from cc and save it to a temporary location which is returned
*/
QString ClearCasePlugin : : getFile ( const QString & nativeFile , const QString & prefix )
{
QString tempFile ;
QDir tempDir = QDir : : temp ( ) ;
tempDir . mkdir ( QLatin1String ( " ccdiff " ) ) ;
tempDir . cd ( QLatin1String ( " ccdiff " ) ) ;
int atatpos = nativeFile . indexOf ( QLatin1String ( " @@ " ) ) ;
QString file = QDir : : fromNativeSeparators ( nativeFile . left ( atatpos ) ) ;
if ( prefix . isEmpty ( ) ) {
tempFile = tempDir . absoluteFilePath ( QString : : number ( QUuid : : createUuid ( ) . data1 , 16 ) ) ;
} else {
tempDir . mkpath ( prefix ) ;
tempDir . cd ( prefix ) ;
int slash = file . lastIndexOf ( QLatin1Char ( ' / ' ) ) ;
if ( slash ! = - 1 )
tempDir . mkpath ( file . left ( slash ) ) ;
tempFile = tempDir . absoluteFilePath ( file ) ;
}
2013-09-03 15:38:13 +02:00
if ( Constants : : debug )
2011-06-05 17:58:02 +03:00
qDebug ( ) < < Q_FUNC_INFO < < nativeFile ;
if ( ( atatpos ! = - 1 ) & & ( nativeFile . indexOf ( QLatin1String ( " CHECKEDOUT " ) , atatpos ) ! = - 1 ) ) {
bool res = QFile : : copy ( QDir ( m_topLevel ) . absoluteFilePath ( file ) , tempFile ) ;
return res ? tempFile : QString ( ) ;
}
QStringList args ( QLatin1String ( " get " ) ) ;
args < < QLatin1String ( " -to " ) < < tempFile < < nativeFile ;
const ClearCaseResponse response =
runCleartool ( m_topLevel , args , m_settings . timeOutMS ( ) , SilentRun ) ;
if ( response . error )
return QString ( ) ;
QFile : : setPermissions ( tempFile , QFile : : ReadOwner | QFile : : ReadUser |
QFile : : WriteOwner | QFile : : WriteUser ) ;
return tempFile ;
}
// runs external (GNU) diff, and returns the stdout result
QString ClearCasePlugin : : diffExternal ( QString file1 , QString file2 , bool keep )
{
QTextCodec * codec = VcsBase : : VcsBaseEditorWidget : : getCodec ( file1 ) ;
// if file2 is empty, we should compare to predecessor
if ( file2 . isEmpty ( ) ) {
QString predVer = ccGetPredecessor ( file1 ) ;
return ( predVer . isEmpty ( ) ? QString ( ) : diffExternal ( predVer , file1 , keep ) ) ;
}
file1 = QDir : : toNativeSeparators ( file1 ) ;
file2 = QDir : : toNativeSeparators ( file2 ) ;
QString tempFile1 , tempFile2 ;
QString prefix = m_diffPrefix ;
if ( ! prefix . isEmpty ( ) )
prefix . append ( QLatin1Char ( ' / ' ) ) ;
if ( file1 . contains ( QLatin1String ( " @@ " ) ) )
tempFile1 = getFile ( file1 , prefix + QLatin1String ( " old " ) ) ;
if ( file2 . contains ( QLatin1String ( " @@ " ) ) )
tempFile2 = getFile ( file2 , prefix + QLatin1String ( " new " ) ) ;
QStringList args ;
if ( ! tempFile1 . isEmpty ( ) ) {
args < < QLatin1String ( " -L " ) < < file1 ;
args < < tempFile1 ;
} else {
args < < file1 ;
}
if ( ! tempFile2 . isEmpty ( ) ) {
args < < QLatin1String ( " -L " ) < < file2 ;
args < < tempFile2 ;
} else {
args < < file2 ;
}
const QString diffResponse =
runExtDiff ( m_topLevel , args , m_settings . timeOutMS ( ) , codec ) ;
if ( ! keep & & ! tempFile1 . isEmpty ( ) ) {
QFile : : remove ( tempFile1 ) ;
QFileInfo ( tempFile1 ) . dir ( ) . rmpath ( QLatin1String ( " . " ) ) ;
}
if ( ! keep & & ! tempFile2 . isEmpty ( ) ) {
QFile : : remove ( tempFile2 ) ;
QFileInfo ( tempFile2 ) . dir ( ) . rmpath ( QLatin1String ( " . " ) ) ;
}
if ( diffResponse . isEmpty ( ) )
return QLatin1String ( " Files are identical " ) ;
QString header = QString : : fromLatin1 ( " diff %1 old/%2 new/%2 \n " )
. arg ( m_settings . diffArgs )
. arg ( QDir : : fromNativeSeparators ( file2 . left ( file2 . indexOf ( QLatin1String ( " @@ " ) ) ) ) ) ;
return header + diffResponse ;
}
// runs builtin diff (either graphical or diff_format)
void ClearCasePlugin : : diffGraphical ( const QString & file1 , const QString & file2 )
{
QStringList args ;
bool pred = file2 . isEmpty ( ) ;
args . push_back ( QLatin1String ( " diff " ) ) ;
if ( pred )
args . push_back ( QLatin1String ( " -predecessor " ) ) ;
args . push_back ( QLatin1String ( " -graphical " ) ) ;
args < < file1 ;
if ( ! pred )
args < < file2 ;
2012-08-21 10:06:05 +03:00
QProcess : : startDetached ( m_settings . ccBinaryPath , args , m_topLevel ) ;
2011-06-05 17:58:02 +03:00
}
QString ClearCasePlugin : : runExtDiff ( const QString & workingDir ,
const QStringList & arguments ,
int timeOut ,
QTextCodec * outputCodec )
{
const QString executable ( QLatin1String ( " diff " ) ) ;
QStringList args ( m_settings . diffArgs . split ( QLatin1Char ( ' ' ) , QString : : SkipEmptyParts ) ) ;
args < < arguments ;
QProcess process ;
process . setWorkingDirectory ( workingDir ) ;
process . start ( executable , args ) ;
if ( ! process . waitForFinished ( timeOut ) )
return QString ( ) ;
QByteArray ba = process . readAll ( ) ;
return outputCodec ? outputCodec - > toUnicode ( ba ) :
QString : : fromLocal8Bit ( ba . constData ( ) , ba . size ( ) ) ;
}
void ClearCasePlugin : : syncSlot ( )
{
VcsBase : : VcsBasePluginState state = currentState ( ) ;
if ( ! state . hasProject ( ) | | ! state . hasTopLevel ( ) )
return ;
QString topLevel = state . topLevel ( ) ;
if ( topLevel ! = state . currentProjectTopLevel ( ) )
return ;
2013-04-18 22:25:23 +02:00
QtConcurrent : : run ( & sync , QStringList ( ) ) ;
2011-06-05 17:58:02 +03:00
}
void ClearCasePlugin : : closing ( )
{
// prevent syncSlot from being called on shutdown
2013-09-03 15:18:37 +02:00
ProgressManager : : cancelTasks ( ClearCase : : Constants : : TASK_INDEX ) ;
2013-08-30 09:22:42 +02:00
disconnect ( ICore : : mainWindow ( ) , SIGNAL ( windowActivated ( ) ) , this , SLOT ( syncSlot ( ) ) ) ;
2011-06-05 17:58:02 +03:00
}
2013-04-18 22:25:23 +02:00
void ClearCasePlugin : : sync ( QFutureInterface < void > & future , QStringList files )
2011-06-05 17:58:02 +03:00
{
ClearCasePlugin * plugin = ClearCasePlugin : : instance ( ) ;
2012-09-02 10:20:32 +03:00
ClearCaseSync ccSync ( plugin , plugin - > m_statusMap ) ;
connect ( & ccSync , SIGNAL ( updateStreamAndView ( ) ) , plugin , SLOT ( updateStreamAndView ( ) ) ) ;
2013-04-18 22:25:23 +02:00
ccSync . run ( future , files ) ;
2011-06-05 17:58:02 +03:00
}
2013-01-19 23:19:38 +02:00
# ifdef WITH_TESTS
void ClearCasePlugin : : testDiffFileResolving_data ( )
{
QTest : : addColumn < QByteArray > ( " header " ) ;
QTest : : addColumn < QByteArray > ( " fileName " ) ;
QTest : : newRow ( " Modified " ) < < QByteArray (
" --- src/plugins/clearcase/clearcaseeditor.cpp@@/main/1 \t 2013-01-20 23:45:48.549615210 +0200 \n "
" +++ src/plugins/clearcase/clearcaseeditor.cpp@@/main/2 \t 2013-01-20 23:45:53.217604679 +0200 \n "
" @@ -58,6 +58,10 @@ \n \n " )
< < QByteArray ( " src/plugins/clearcase/clearcaseeditor.cpp " ) ;
}
void ClearCasePlugin : : testDiffFileResolving ( )
{
2013-05-27 18:34:02 +03:00
ClearCaseEditor editor ( editorParameters + 2 , 0 ) ;
2013-01-28 20:50:05 +02:00
editor . testDiffFileResolving ( ) ;
2013-01-19 23:19:38 +02:00
}
2013-01-28 22:02:35 +02:00
void ClearCasePlugin : : testLogResolving ( )
{
QByteArray data (
" 13-Sep.17:41 user1 create version \" src/plugins/clearcase/clearcaseeditor.h@@/main/branch1/branch2/9 \" (baseline1, baseline2, ...) \n "
" 22-Aug.14:13 user2 create version \" src/plugins/clearcase/clearcaseeditor.h@@/main/branch1/branch2/8 \" (baseline3, baseline4, ...) \n "
) ;
2013-05-27 18:34:02 +03:00
ClearCaseEditor editor ( editorParameters , 0 ) ;
2013-01-28 22:02:35 +02:00
editor . testLogResolving ( data ,
" src/plugins/clearcase/clearcaseeditor.h@@/main/branch1/branch2/9 " ,
" src/plugins/clearcase/clearcaseeditor.h@@/main/branch1/branch2/8 " ) ;
}
2013-11-20 11:59:34 +01:00
void ClearCasePlugin : : initTestCase ( )
{
m_tempFile = QDir : : currentPath ( ) + QLatin1String ( " /cc_file.cpp " ) ;
Utils : : FileSaver srcSaver ( m_tempFile ) ;
srcSaver . write ( QByteArray ( ) ) ;
srcSaver . finalize ( ) ;
}
void ClearCasePlugin : : cleanupTestCase ( )
{
QVERIFY ( QFile : : remove ( m_tempFile ) ) ;
}
void ClearCasePlugin : : testFileStatusParsing_data ( )
{
QTest : : addColumn < QString > ( " filename " ) ;
QTest : : addColumn < QString > ( " cleartoolLsLine " ) ;
QTest : : addColumn < int > ( " status " ) ;
QTest : : newRow ( " CheckedOut " )
< < m_tempFile
< < QString ( m_tempFile + QLatin1String ( " @@/main/branch1/CHECKEDOUT from /main/branch1/0 Rule: CHECKEDOUT " ) )
< < static_cast < int > ( FileStatus : : CheckedOut ) ;
QTest : : newRow ( " CheckedIn " )
< < m_tempFile
< < QString ( m_tempFile + QLatin1String ( " @@/main/9 Rule: MY_LABEL_1.6.4 [-mkbranch branch1] " ) )
< < static_cast < int > ( FileStatus : : CheckedIn ) ;
QTest : : newRow ( " Hijacked " )
< < m_tempFile
< < QString ( m_tempFile + QLatin1String ( " @@/main/9 [hijacked] Rule: MY_LABEL_1.5.33 [-mkbranch myview1] " ) )
< < static_cast < int > ( FileStatus : : Hijacked ) ;
QTest : : newRow ( " Missing " )
< < m_tempFile
< < QString ( m_tempFile + QLatin1String ( " @@/main/9 [loaded but missing] Rule: MY_LABEL_1.5.33 [-mkbranch myview1] " ) )
< < static_cast < int > ( FileStatus : : Missing ) ;
}
void ClearCasePlugin : : testFileStatusParsing ( )
{
ClearCasePlugin * plugin = ClearCasePlugin : : instance ( ) ;
plugin - > m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
QFETCH ( QString , filename ) ;
QFETCH ( QString , cleartoolLsLine ) ;
QFETCH ( int , status ) ;
ClearCaseSync ccSync ( plugin , plugin - > m_statusMap ) ;
ccSync . verifyParseStatus ( filename , cleartoolLsLine , static_cast < FileStatus : : Status > ( status ) ) ;
}
void ClearCasePlugin : : testFileNotManaged ( )
{
ClearCasePlugin * plugin = ClearCasePlugin : : instance ( ) ;
plugin - > m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
ClearCaseSync ccSync ( plugin , plugin - > m_statusMap ) ;
ccSync . verifyFileNotManaged ( ) ;
}
2013-12-05 13:30:20 +01:00
void ClearCasePlugin : : testFileCheckedOutDynamicView ( )
{
ClearCasePlugin * plugin = ClearCasePlugin : : instance ( ) ;
plugin - > m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
ClearCaseSync ccSync ( plugin , plugin - > m_statusMap ) ;
ccSync . verifyFileCheckedOutDynamicView ( ) ;
}
void ClearCasePlugin : : testFileCheckedInDynamicView ( )
{
ClearCasePlugin * plugin = ClearCasePlugin : : instance ( ) ;
plugin - > m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
ClearCaseSync ccSync ( plugin , plugin - > m_statusMap ) ;
ccSync . verifyFileCheckedInDynamicView ( ) ;
}
void ClearCasePlugin : : testFileNotManagedDynamicView ( )
{
ClearCasePlugin * plugin = ClearCasePlugin : : instance ( ) ;
plugin - > m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
ClearCaseSync ccSync ( plugin , plugin - > m_statusMap ) ;
ccSync . verifyFileNotManagedDynamicView ( ) ;
}
2013-11-20 11:59:34 +01:00
namespace {
/**
2013-12-05 13:30:20 +01:00
* @ brief Convenience class which also properly cleans up editors and temp files
2013-11-20 11:59:34 +01:00
*/
class TestCase
{
public :
TestCase ( const QString & fileName ) :
m_fileName ( fileName ) ,
m_editor ( 0 )
{
ClearCasePlugin : : instance ( ) - > setFakeCleartool ( true ) ;
Utils : : FileSaver srcSaver ( fileName ) ;
srcSaver . write ( QByteArray ( ) ) ;
srcSaver . finalize ( ) ;
m_editor = Core : : EditorManager : : openEditor ( fileName ) ;
QCoreApplication : : processEvents ( ) ; // process any pending events
}
ViewData dummyViewData ( ) const
{
ViewData viewData ;
viewData . name = QLatin1String ( " fake_view " ) ;
viewData . root = QDir : : currentPath ( ) ;
viewData . isUcm = false ;
return viewData ;
}
~ TestCase ( )
{
Core : : EditorManager : : closeEditor ( m_editor , false ) ;
QCoreApplication : : processEvents ( ) ; // process any pending events
2013-12-05 13:30:20 +01:00
QFile file ( m_fileName ) ;
if ( ! file . isWritable ( ) ) // Windows can't delete read only files
file . setPermissions ( file . permissions ( ) | QFile : : WriteUser ) ;
QVERIFY ( file . remove ( ) ) ;
2013-11-20 11:59:34 +01:00
ClearCasePlugin : : instance ( ) - > setFakeCleartool ( false ) ;
}
private :
QString m_fileName ;
Core : : IEditor * m_editor ;
} ;
}
void ClearCasePlugin : : testStatusActions_data ( )
{
QTest : : addColumn < int > ( " status " ) ;
QTest : : addColumn < bool > ( " checkOutAction " ) ;
QTest : : addColumn < bool > ( " undoCheckOutAction " ) ;
QTest : : addColumn < bool > ( " undoHijackAction " ) ;
QTest : : addColumn < bool > ( " checkInCurrentAction " ) ;
QTest : : addColumn < bool > ( " addFileAction " ) ;
QTest : : addColumn < bool > ( " checkInActivityAction " ) ;
QTest : : addColumn < bool > ( " diffActivityAction " ) ;
QTest : : newRow ( " Unknown " ) < < static_cast < int > ( FileStatus : : Unknown )
< < true < < true < < true < < true < < true < < false < < false ;
QTest : : newRow ( " CheckedOut " ) < < static_cast < int > ( FileStatus : : CheckedOut )
< < false < < true < < false < < true < < false < < false < < false ;
QTest : : newRow ( " CheckedIn " ) < < static_cast < int > ( FileStatus : : CheckedIn )
< < true < < false < < false < < false < < false < < false < < false ;
QTest : : newRow ( " NotManaged " ) < < static_cast < int > ( FileStatus : : NotManaged )
< < false < < false < < false < < false < < true < < false < < false ;
}
void ClearCasePlugin : : testStatusActions ( )
{
const QString fileName = QDir : : currentPath ( ) + QLatin1String ( " /clearcase_file.cpp " ) ;
TestCase testCase ( fileName ) ;
m_viewData = testCase . dummyViewData ( ) ;
QFETCH ( int , status ) ;
FileStatus : : Status tempStatus = static_cast < FileStatus : : Status > ( status ) ;
// special case: file should appear as "Unknown" since there is no entry in the index
// and we don't want to explicitly set the status for this test case
if ( tempStatus ! = FileStatus : : Unknown )
setStatus ( fileName , tempStatus , true ) ;
QFETCH ( bool , checkOutAction ) ;
QFETCH ( bool , undoCheckOutAction ) ;
QFETCH ( bool , undoHijackAction ) ;
QFETCH ( bool , checkInCurrentAction ) ;
QFETCH ( bool , addFileAction ) ;
QFETCH ( bool , checkInActivityAction ) ;
QFETCH ( bool , diffActivityAction ) ;
QCOMPARE ( m_checkOutAction - > isEnabled ( ) , checkOutAction ) ;
QCOMPARE ( m_undoCheckOutAction - > isEnabled ( ) , undoCheckOutAction ) ;
QCOMPARE ( m_undoHijackAction - > isEnabled ( ) , undoHijackAction ) ;
QCOMPARE ( m_checkInCurrentAction - > isEnabled ( ) , checkInCurrentAction ) ;
QCOMPARE ( m_addFileAction - > isEnabled ( ) , addFileAction ) ;
QCOMPARE ( m_checkInActivityAction - > isEnabled ( ) , checkInActivityAction ) ;
QCOMPARE ( m_diffActivityAction - > isEnabled ( ) , diffActivityAction ) ;
}
2013-12-05 13:30:20 +01:00
void ClearCasePlugin : : testVcsStatusDynamicReadonlyNotManaged ( )
{
// File is not in map, and is read-only
ClearCasePlugin : : instance ( ) ;
m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
const QString fileName = QDir : : currentPath ( ) + QLatin1String ( " /readonly_notmanaged_file.cpp " ) ;
m_viewData . isDynamic = true ;
TestCase testCase ( fileName ) ;
QFile : : setPermissions ( fileName , QFile : : ReadOwner |
QFile : : ReadUser |
QFile : : ReadGroup |
QFile : : ReadOther ) ;
m_viewData = testCase . dummyViewData ( ) ;
m_viewData . isDynamic = true ;
QCOMPARE ( vcsStatus ( fileName ) . status , FileStatus : : NotManaged ) ;
}
void ClearCasePlugin : : testVcsStatusDynamicNotManaged ( )
{
ClearCasePlugin : : instance ( ) ;
m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
const QString fileName = QDir : : currentPath ( ) + QLatin1String ( " /notmanaged_file.cpp " ) ;
m_viewData . isDynamic = true ;
TestCase testCase ( fileName ) ;
m_viewData = testCase . dummyViewData ( ) ;
m_viewData . isDynamic = true ;
QCOMPARE ( vcsStatus ( fileName ) . status , FileStatus : : NotManaged ) ;
}
2013-01-19 23:19:38 +02:00
# endif
2011-06-05 17:58:02 +03:00
} // namespace Internal
2012-09-02 10:18:56 +03:00
} // namespace ClearCase
2011-06-05 17:58:02 +03:00
Q_EXPORT_PLUGIN ( ClearCase : : Internal : : ClearCasePlugin )