2022-08-19 15:59:36 +02:00
// Copyright (C) 2016 AudioCodes Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
2011-06-05 17:58:02 +03:00
2013-03-12 11:53:14 +01:00
# include "clearcaseplugin.h"
2022-08-03 06:55:06 +02:00
2011-06-05 17:58:02 +03:00
# include "activityselector.h"
# include "checkoutdialog.h"
# include "clearcaseconstants.h"
# include "clearcaseeditor.h"
2022-08-03 06:55:06 +02:00
# include "clearcasesettings.h"
2011-06-05 17:58:02 +03:00
# include "clearcasesubmiteditor.h"
# include "clearcasesubmiteditorwidget.h"
2012-09-02 10:20:32 +03:00
# include "clearcasesync.h"
2022-09-29 14:47:34 +02:00
# include "clearcasetr.h"
2011-06-05 17:58:02 +03:00
# include "settingspage.h"
# include "versionselector.h"
# include <coreplugin/actionmanager/actioncontainer.h>
# include <coreplugin/actionmanager/actionmanager.h>
# include <coreplugin/documentmanager.h>
2015-01-03 21:44:28 +02:00
# include <coreplugin/editormanager/documentmodel.h>
2011-06-05 17:58:02 +03:00
# include <coreplugin/editormanager/editormanager.h>
# include <coreplugin/icore.h>
2020-06-17 06:35:31 +02:00
# include <coreplugin/locator/commandlocator.h>
2011-06-05 17:58:02 +03:00
# include <coreplugin/progressmanager/progressmanager.h>
2020-06-17 06:35:31 +02:00
2015-02-26 13:22:35 +01:00
# include <texteditor/textdocument.h>
2020-06-17 06:35:31 +02:00
2011-06-05 17:58:02 +03:00
# include <projectexplorer/project.h>
2020-06-17 06:35:31 +02:00
# include <projectexplorer/session.h>
2014-06-16 18:25:52 +04:00
# include <utils/algorithm.h>
2012-08-23 15:53:58 +02:00
# include <utils/hostosinfo.h>
2020-06-17 12:23:44 +02:00
# include <utils/infobar.h>
2022-09-28 17:42:25 +02:00
# include <utils/layoutbuilder.h>
2020-06-17 06:35:31 +02:00
# include <utils/parameteraction.h>
2011-06-05 17:58:02 +03:00
# include <utils/qtcassert.h>
2021-05-05 18:21:22 +02:00
# include <utils/qtcprocess.h>
2011-06-05 17:58:02 +03:00
# include <utils/runextensions.h>
2020-06-17 06:35:31 +02:00
# include <utils/temporarydirectory.h>
2020-02-06 17:49:35 +01:00
2011-06-05 17:58:02 +03:00
# include <vcsbase/basevcseditorfactory.h>
# include <vcsbase/basevcssubmiteditorfactory.h>
# include <vcsbase/vcsbaseeditor.h>
2014-08-26 00:02:47 +02:00
# include <vcsbase/vcsoutputwindow.h>
2011-06-05 17:58:02 +03:00
# include <vcsbase/vcsbasesubmiteditor.h>
2020-02-06 17:49:35 +01:00
# include <vcsbase/vcsbaseplugin.h>
2022-08-01 10:49:13 +02:00
# include <vcsbase/vcscommand.h>
2011-06-05 17:58:02 +03:00
2022-09-28 17:42:25 +02:00
# include <QAbstractButton>
2011-06-05 17:58:02 +03:00
# include <QAction>
2022-09-28 17:42:25 +02:00
# include <QApplication>
# include <QCheckBox>
2011-06-05 17:58:02 +03:00
# include <QDebug>
# include <QDialog>
# include <QDialogButtonBox>
# include <QDir>
# include <QFileInfo>
# include <QFuture>
# include <QFutureInterface>
# include <QInputDialog>
2022-09-28 17:42:25 +02:00
# include <QLabel>
2011-06-05 17:58:02 +03:00
# include <QList>
# include <QMenu>
# include <QMessageBox>
2012-11-12 16:48:26 +02:00
# include <QMetaObject>
2011-06-05 17:58:02 +03:00
# include <QMutex>
2020-06-23 18:36:26 +02:00
# include <QRegularExpression>
2011-06-05 17:58:02 +03:00
# include <QSharedPointer>
2012-09-24 11:39:34 +02:00
# include <QTextCodec>
2011-06-05 17:58:02 +03:00
# include <QUuid>
# include <QVBoxLayout>
2022-09-28 17:42:25 +02:00
2013-01-19 23:19:38 +02:00
# ifdef WITH_TESTS
# include <QTest>
2014-08-25 13:18:41 +02:00
# include <coreplugin/vcsmanager.h>
2013-01-19 23:19:38 +02:00
# endif
2011-06-05 17:58:02 +03:00
2013-08-30 09:22:42 +02:00
using namespace Core ;
using namespace ProjectExplorer ;
2014-08-28 13:45:42 +02:00
using namespace VcsBase ;
2014-08-28 16:47:19 +02:00
using namespace Utils ;
2020-02-07 07:51:20 +01:00
using namespace std : : placeholders ;
2013-08-30 09:22:42 +02:00
2011-06-05 17:58:02 +03:00
namespace ClearCase {
namespace Internal {
2022-09-28 17:42:25 +02:00
const char CLEARCASE_CONTEXT [ ] = " ClearCase Context " ;
const char CMD_ID_CLEARCASE_MENU [ ] = " ClearCase.Menu " ;
const char CMD_ID_CHECKOUT [ ] = " ClearCase.CheckOut " ;
const char CMD_ID_CHECKIN [ ] = " ClearCase.CheckInCurrent " ;
const char CMD_ID_UNDOCHECKOUT [ ] = " ClearCase.UndoCheckOut " ;
const char CMD_ID_UNDOHIJACK [ ] = " ClearCase.UndoHijack " ;
const char CMD_ID_DIFF_CURRENT [ ] = " ClearCase.DiffCurrent " ;
const char CMD_ID_HISTORY_CURRENT [ ] = " ClearCase.HistoryCurrent " ;
const char CMD_ID_ANNOTATE [ ] = " ClearCase.Annotate " ;
const char CMD_ID_ADD_FILE [ ] = " ClearCase.AddFile " ;
const char CMD_ID_DIFF_ACTIVITY [ ] = " ClearCase.DiffActivity " ;
const char CMD_ID_CHECKIN_ACTIVITY [ ] = " ClearCase.CheckInActivity " ;
const char CMD_ID_UPDATEINDEX [ ] = " ClearCase.UpdateIndex " ;
const char CMD_ID_UPDATE_VIEW [ ] = " ClearCase.UpdateView " ;
const char CMD_ID_CHECKIN_ALL [ ] = " ClearCase.CheckInAll " ;
const char CMD_ID_STATUS [ ] = " ClearCase.Status " ;
2011-06-05 17:58:02 +03:00
2020-02-07 07:51:20 +01:00
const VcsBaseEditorParameters logEditorParameters {
2015-02-03 23:56:02 +02:00
LogOutput ,
2011-06-05 17:58:02 +03:00
" ClearCase File Log Editor " , // id
QT_TRANSLATE_NOOP ( " VCS " , " ClearCase File Log Editor " ) , // display_name
2020-02-07 07:51:20 +01:00
" text/vnd.qtcreator.clearcase.log "
} ;
const VcsBaseEditorParameters annotateEditorParameters {
AnnotateOutput ,
2011-06-05 17:58:02 +03:00
" ClearCase Annotation Editor " , // id
QT_TRANSLATE_NOOP ( " VCS " , " ClearCase Annotation Editor " ) , // display_name
2020-02-07 07:51:20 +01:00
" text/vnd.qtcreator.clearcase.annotation "
} ;
const VcsBaseEditorParameters diffEditorParameters {
DiffOutput ,
2011-06-05 17:58:02 +03:00
" ClearCase Diff Editor " , // id
QT_TRANSLATE_NOOP ( " VCS " , " ClearCase Diff Editor " ) , // display_name
2020-02-07 07:51:20 +01:00
" text/x-patch "
2011-06-05 17:58:02 +03:00
} ;
2020-02-07 07:51:20 +01:00
const VcsBaseSubmitEditorParameters submitParameters {
2020-02-06 18:51:46 +01:00
Constants : : CLEARCASE_SUBMIT_MIMETYPE ,
Constants : : CLEARCASECHECKINEDITOR_ID ,
Constants : : CLEARCASECHECKINEDITOR_DISPLAY_NAME ,
VcsBaseSubmitEditorParameters : : DiffFiles
} ;
2014-08-28 16:47:19 +02:00
static QString debugCodec ( const QTextCodec * c )
2011-06-05 17:58:02 +03:00
{
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
}
2020-02-06 17:49:35 +01:00
class ClearCasePluginPrivate final : public VcsBase : : VcsBasePluginPrivate
{
Q_OBJECT
public :
ClearCasePluginPrivate ( ) ;
~ ClearCasePluginPrivate ( ) final ;
// IVersionControl
QString displayName ( ) const final ;
2022-08-03 06:55:06 +02:00
Id id ( ) const final ;
2020-02-06 17:49:35 +01:00
2021-07-29 09:31:09 +02:00
bool isVcsFileOrDirectory ( const FilePath & filePath ) const final ;
2020-02-06 17:49:35 +01:00
2021-07-29 09:31:09 +02:00
bool managesDirectory ( const FilePath & directory , FilePath * topLevel ) const final ;
bool managesFile ( const FilePath & workingDirectory , const QString & fileName ) const final ;
2020-02-06 17:49:35 +01:00
bool isConfigured ( ) const final ;
bool supportsOperation ( Operation operation ) const final ;
2021-07-29 09:31:09 +02:00
OpenSupportMode openSupportMode ( const FilePath & filePath ) const final ;
bool vcsOpen ( const FilePath & filePath ) final ;
2020-02-06 17:49:35 +01:00
SettingsFlags settingsFlags ( ) const final ;
2021-07-29 09:31:09 +02:00
bool vcsAdd ( const FilePath & filePath ) final ;
bool vcsDelete ( const FilePath & filename ) final ;
bool vcsMove ( const FilePath & from , const FilePath & to ) final ;
bool vcsCreateRepository ( const FilePath & directory ) final ;
2020-02-06 17:49:35 +01:00
2021-07-29 09:31:09 +02:00
void vcsAnnotate ( const FilePath & file , int line ) final ;
void vcsDescribe ( const FilePath & source , const QString & changeNr ) final ;
2020-02-06 17:49:35 +01:00
QString vcsOpenText ( ) const final ;
QString vcsMakeWritableText ( ) const final ;
2021-07-29 09:31:09 +02:00
QString vcsTopic ( const FilePath & directory ) final ;
2020-02-06 17:49:35 +01:00
///
2021-07-30 16:46:27 +02:00
ClearCaseSubmitEditor * openClearCaseSubmitEditor ( const FilePath & filePath , bool isUcm ) ;
2020-02-06 17:49:35 +01:00
const ClearCaseSettings & settings ( ) const ;
void setSettings ( const ClearCaseSettings & s ) ;
// IVersionControl
2021-07-30 16:46:27 +02:00
bool vcsOpen ( const FilePath & workingDir , const QString & fileName ) ;
bool vcsAdd ( const FilePath & workingDir , const QString & fileName ) ;
bool vcsDelete ( const FilePath & workingDir , const QString & fileName ) ;
bool vcsCheckIn ( const FilePath & workingDir , const QStringList & files , const QString & activity ,
2020-02-06 17:49:35 +01:00
bool isIdentical , bool isPreserve , bool replaceActivity ) ;
2021-07-30 16:46:27 +02:00
bool vcsUndoCheckOut ( const FilePath & workingDir , const QString & fileName , bool keep ) ;
bool vcsUndoHijack ( const FilePath & workingDir , const QString & fileName , bool keep ) ;
bool vcsMove ( const FilePath & workingDir , const QString & from , const QString & to ) ;
bool vcsSetActivity ( const FilePath & workingDir , const QString & title , const QString & activity ) ;
2020-02-06 17:49:35 +01:00
static ClearCasePluginPrivate * instance ( ) ;
QString ccGetCurrentActivity ( ) const ;
2020-02-06 18:51:46 +01:00
QList < QStringPair > activities ( int * current = nullptr ) ;
2020-02-06 17:49:35 +01:00
QString ccGetPredecessor ( const QString & version ) const ;
QStringList ccGetActiveVobs ( ) const ;
2021-07-30 16:46:27 +02:00
ViewData ccGetView ( const FilePath & workingDir ) const ;
QString ccGetComment ( const FilePath & workingDir , const QString & fileName ) const ;
bool ccFileOp ( const FilePath & workingDir , const QString & title , const QStringList & args ,
const QString & fileName , const QString & file2 = { } ) ;
2020-02-06 17:49:35 +01:00
FileStatus vcsStatus ( const QString & file ) const ;
void checkAndReIndexUnknownFile ( const QString & file ) ;
QString currentView ( ) const { return m_viewData . name ; }
QString viewRoot ( ) const { return m_viewData . root ; }
void refreshActivities ( ) ;
inline bool isUcm ( ) const { return m_viewData . isUcm ; }
inline bool isDynamic ( ) const { return m_viewData . isDynamic ; }
void setStatus ( const QString & file , FileStatus : : Status status , bool update = true ) ;
2021-07-30 16:46:27 +02:00
bool ccCheckUcm ( const QString & viewname , const FilePath & workingDir ) const ;
2020-02-06 17:49:35 +01:00
# ifdef WITH_TESTS
inline void setFakeCleartool ( const bool b = true ) { m_fakeClearTool = b ; }
# endif
2021-07-30 16:46:27 +02:00
void vcsAnnotateHelper ( const FilePath & workingDir , const QString & file ,
const QString & revision = { } , int lineNumber = - 1 ) const ;
2020-02-06 17:49:35 +01:00
bool newActivity ( ) ;
void updateStreamAndView ( ) ;
protected :
void updateActions ( VcsBase : : VcsBasePluginPrivate : : ActionState ) override ;
bool submitEditorAboutToClose ( ) override ;
2021-07-30 16:46:27 +02:00
QString ccGet ( const FilePath & workingDir , const QString & file , const QString & prefix = { } ) ;
2020-02-06 17:49:35 +01:00
QList < QStringPair > ccGetActivities ( ) const ;
private :
void syncSlot ( ) ;
Q_INVOKABLE void updateStatusActions ( ) ;
QString commitDisplayName ( ) const final ;
void checkOutCurrentFile ( ) ;
void addCurrentFile ( ) ;
void undoCheckOutCurrent ( ) ;
void undoHijackCurrent ( ) ;
void diffActivity ( ) ;
void diffCurrentFile ( ) ;
void startCheckInAll ( ) ;
void startCheckInActivity ( ) ;
void startCheckInCurrentFile ( ) ;
void historyCurrentFile ( ) ;
void annotateCurrentFile ( ) ;
void viewStatus ( ) ;
void commitFromEditor ( ) override ;
void diffCheckInFiles ( const QStringList & ) ;
void updateIndex ( ) ;
void updateView ( ) ;
void projectChanged ( ProjectExplorer : : Project * project ) ;
2021-07-30 16:46:27 +02:00
void tasksFinished ( Id type ) ;
2020-02-06 17:49:35 +01:00
void closing ( ) ;
inline bool isCheckInEditorOpen ( ) const ;
QStringList getVobList ( ) const ;
2021-07-30 16:46:27 +02:00
QString ccManagesDirectory ( const FilePath & directory ) const ;
QString ccViewRoot ( const FilePath & directory ) const ;
QString findTopLevel ( const FilePath & directory ) const ;
2022-09-21 08:13:29 +02:00
IEditor * showOutputInEditor ( const QString & title , const QString & output , Id id ,
const QString & source , QTextCodec * codec ) const ;
2022-10-05 16:59:07 +02:00
CommandResult runCleartoolProc ( const FilePath & workingDir ,
const QStringList & arguments ) const ;
2022-09-21 08:13:29 +02:00
CommandResult runCleartool ( const FilePath & workingDir , const QStringList & arguments ,
2022-10-05 19:08:53 +02:00
VcsBase : : RunFlags flags = VcsBase : : RunFlags : : None ,
QTextCodec * codec = nullptr , int timeoutMultiplier = 1 ) const ;
2020-02-06 17:49:35 +01:00
static void sync ( QFutureInterface < void > & future , QStringList files ) ;
2021-07-30 16:46:27 +02:00
void history ( const FilePath & workingDir ,
const QStringList & file = { } ,
2020-02-06 17:49:35 +01:00
bool enableAnnotationContextMenu = false ) ;
2021-07-30 16:46:27 +02:00
QString ccGetFileVersion ( const FilePath & workingDir , const QString & file ) const ;
void ccUpdate ( const FilePath & workingDir , const QStringList & relativePaths = { } ) ;
void ccDiffWithPred ( const FilePath & workingDir , const QStringList & files ) ;
void startCheckIn ( const FilePath & workingDir , const QStringList & files = { } ) ;
2020-02-06 17:49:35 +01:00
void cleanCheckInMessageFile ( ) ;
2021-07-30 16:46:27 +02:00
QString ccGetFileActivity ( const FilePath & workingDir , const QString & file ) ;
QStringList ccGetActivityVersions ( const FilePath & workingDir , const QString & activity ) ;
2020-02-06 17:49:35 +01:00
void diffGraphical ( const QString & file1 , const QString & file2 = QString ( ) ) ;
QString diffExternal ( QString file1 , QString file2 = QString ( ) , bool keep = false ) ;
QString getFile ( const QString & nativeFile , const QString & prefix ) ;
static void rmdir ( const QString & path ) ;
2021-07-30 16:46:27 +02:00
QString runExtDiff ( const FilePath & workingDir , const QStringList & arguments , int timeOutS ,
2020-02-06 17:49:35 +01:00
QTextCodec * outputCodec = nullptr ) ;
static QString getDriveLetterOfPath ( const QString & directory ) ;
FileStatus : : Status getFileStatus ( const QString & fileName ) const ;
void updateStatusForFile ( const QString & absFile ) ;
void updateEditDerivedObjectWarning ( const QString & fileName , const FileStatus : : Status status ) ;
ClearCaseSettings m_settings ;
2021-07-30 16:46:27 +02:00
FilePath m_checkInMessageFilePath ;
FilePath m_checkInView ;
FilePath m_topLevel ;
2020-02-06 17:49:35 +01:00
QString m_stream ;
ViewData m_viewData ;
QString m_intStream ;
QString m_activity ;
QString m_diffPrefix ;
2022-08-03 06:55:06 +02:00
CommandLocator * m_commandLocator = nullptr ;
ParameterAction * m_checkOutAction = nullptr ;
ParameterAction * m_checkInCurrentAction = nullptr ;
ParameterAction * m_undoCheckOutAction = nullptr ;
ParameterAction * m_undoHijackAction = nullptr ;
ParameterAction * m_diffCurrentAction = nullptr ;
ParameterAction * m_historyCurrentAction = nullptr ;
ParameterAction * m_annotateCurrentAction = nullptr ;
ParameterAction * m_addFileAction = nullptr ;
2020-02-06 17:49:35 +01:00
QAction * m_diffActivityAction = nullptr ;
QAction * m_updateIndexAction = nullptr ;
2022-08-03 06:55:06 +02:00
ParameterAction * m_updateViewAction = nullptr ;
ParameterAction * m_checkInActivityAction = nullptr ;
2020-02-06 17:49:35 +01:00
QAction * m_checkInAllAction = nullptr ;
QAction * m_statusAction = nullptr ;
QAction * m_menuAction = nullptr ;
bool m_submitActionTriggered = false ;
2020-02-06 18:51:46 +01:00
QMutex m_activityMutex ;
2020-02-06 17:49:35 +01:00
QList < QStringPair > m_activities ;
QSharedPointer < StatusMap > m_statusMap ;
2020-02-06 18:51:46 +01:00
ClearCaseSettingsPage m_settingsPage ;
VcsSubmitEditorFactory m_submitEditorFactory {
submitParameters ,
[ ] { return new ClearCaseSubmitEditor ; } ,
this
} ;
2020-02-07 07:51:20 +01:00
VcsEditorFactory logEditorFactory {
& logEditorParameters ,
[ ] { return new ClearCaseEditorWidget ; } ,
2020-06-17 23:50:30 +03:00
std : : bind ( & ClearCasePluginPrivate : : vcsDescribe , this , _1 , _2 )
2020-02-07 07:51:20 +01:00
} ;
VcsEditorFactory annotateEditorFactory {
& annotateEditorParameters ,
[ ] { return new ClearCaseEditorWidget ; } ,
2020-06-17 23:50:30 +03:00
std : : bind ( & ClearCasePluginPrivate : : vcsDescribe , this , _1 , _2 )
2020-02-07 07:51:20 +01:00
} ;
VcsEditorFactory diffEditorFactory {
& diffEditorParameters ,
[ ] { return new ClearCaseEditorWidget ; } ,
2020-06-17 23:50:30 +03:00
std : : bind ( & ClearCasePluginPrivate : : vcsDescribe , this , _1 , _2 )
2020-02-07 07:51:20 +01:00
} ;
2020-02-06 17:49:35 +01:00
friend class ClearCasePlugin ;
# ifdef WITH_TESTS
bool m_fakeClearTool = false ;
QString m_tempFile ;
# endif
} ;
2011-06-05 17:58:02 +03:00
// ------------- ClearCasePlugin
2020-01-23 17:22:05 +01:00
static ClearCasePluginPrivate * dd = nullptr ;
2011-06-05 17:58:02 +03:00
2020-01-23 17:22:05 +01:00
ClearCasePluginPrivate : : ~ ClearCasePluginPrivate ( )
2011-06-05 17:58:02 +03:00
{
cleanCheckInMessageFile ( ) ;
// wait for sync thread to finish reading activities
2021-02-18 19:14:46 +01:00
QMutexLocker locker ( & m_activityMutex ) ;
2011-06-05 17:58:02 +03:00
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : cleanCheckInMessageFile ( )
2011-06-05 17:58:02 +03:00
{
2021-07-30 16:46:27 +02:00
if ( ! m_checkInMessageFilePath . isEmpty ( ) ) {
m_checkInMessageFilePath . removeFile ( ) ;
m_checkInMessageFilePath . clear ( ) ;
2012-09-12 09:27:06 +03:00
m_checkInView . clear ( ) ;
2011-06-05 17:58:02 +03:00
}
}
2020-01-23 17:22:05 +01:00
bool ClearCasePluginPrivate : : isCheckInEditorOpen ( ) const
2011-06-05 17:58:02 +03:00
{
2021-07-30 16:46:27 +02:00
return ! m_checkInMessageFilePath . isEmpty ( ) ;
2011-06-05 17:58:02 +03:00
}
2013-04-18 22:25:23 +02:00
/// Files in this directories are under ClearCase control
2020-01-23 17:22:05 +01:00
QStringList ClearCasePluginPrivate : : getVobList ( ) const
2013-02-03 23:30:22 +02:00
{
2022-10-05 16:59:07 +02:00
const CommandResult result = runCleartoolProc ( currentState ( ) . topLevel ( ) , { " lsvob " , " -s " } ) ;
2022-09-21 08:13:29 +02:00
return result . cleanedStdOut ( ) . split ( QLatin1Char ( ' \n ' ) , Qt : : SkipEmptyParts ) ;
2013-04-18 22:25:23 +02:00
}
/// Get the drive letter of a path
/// Necessary since QDir(directory).rootPath() returns C:/ in all cases
2020-01-23 17:22:05 +01:00
QString ClearCasePluginPrivate : : getDriveLetterOfPath ( const QString & directory )
2013-04-18 22:25:23 +02:00
{
// cdUp until we get just the drive letter
QDir dir ( directory ) ;
2013-12-03 08:15:44 +02:00
while ( ! dir . isRoot ( ) & & dir . cdUp ( ) )
2022-09-21 08:13:29 +02:00
;
2013-04-18 22:25:23 +02:00
return dir . path ( ) ;
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : updateStatusForFile ( const QString & absFile )
2013-12-05 13:30:20 +01:00
{
setStatus ( absFile , getFileStatus ( absFile ) , false ) ;
}
2013-12-03 17:45:26 +01:00
/// Give warning if a derived object is edited
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : updateEditDerivedObjectWarning ( const QString & fileName ,
2013-12-03 17:45:26 +01:00
const FileStatus : : Status status )
{
if ( ! isDynamic ( ) )
return ;
2014-08-28 16:47:19 +02:00
IDocument * curDocument = EditorManager : : currentDocument ( ) ;
2013-12-03 17:45:26 +01:00
if ( ! curDocument )
return ;
2014-08-28 16:47:19 +02:00
InfoBar * infoBar = curDocument - > infoBar ( ) ;
const Id derivedObjectWarning ( " ClearCase.DerivedObjectWarning " ) ;
2013-12-03 17:45:26 +01:00
if ( status = = FileStatus : : Derived ) {
if ( ! infoBar - > canInfoBeAdded ( derivedObjectWarning ) )
return ;
2014-08-28 16:47:19 +02:00
infoBar - > addInfo ( InfoBarEntry ( derivedObjectWarning ,
2022-09-29 14:47:34 +02:00
Tr : : tr ( " Editing Derived Object: %1 " ) . arg ( fileName ) ) ) ;
2013-12-03 17:45:26 +01:00
} else {
infoBar - > removeInfo ( derivedObjectWarning ) ;
}
}
2020-01-23 17:22:05 +01:00
FileStatus : : Status ClearCasePluginPrivate : : getFileStatus ( const QString & fileName ) const
2013-12-05 13:30:20 +01:00
{
QTC_CHECK ( ! fileName . isEmpty ( ) ) ;
const QDir viewRootDir = QFileInfo ( fileName ) . dir ( ) ;
2022-10-05 17:22:09 +02:00
const QString buffer = runCleartoolProc ( FilePath : : fromString ( viewRootDir . path ( ) ) ,
{ " ls " , fileName } ) . cleanedStdOut ( ) ;
2013-12-05 13:30:20 +01:00
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 ) ) ) ;
2017-04-13 16:26:38 +02:00
QTC_CHECK ( QFileInfo : : exists ( absFile ) ) ;
2013-12-05 13:30:20 +01:00
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
2020-06-23 18:36:26 +02:00
const int wspos = buffer . indexOf ( QRegularExpression ( " \\ s " ) ) ;
2013-12-05 13:30:20 +01:00
if ( buffer . lastIndexOf ( QLatin1String ( " CHECKEDOUT " ) , wspos ) ! = - 1 )
return FileStatus : : CheckedOut ;
else
return FileStatus : : CheckedIn ;
} else {
2017-04-13 16:26:38 +02:00
QTC_CHECK ( QFileInfo : : exists ( fileName ) ) ;
2013-12-05 13:30:20 +01:00
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
2021-07-30 16:46:27 +02:00
QString ClearCasePluginPrivate : : ccManagesDirectory ( const FilePath & directory ) const
2013-04-18 22:25:23 +02:00
{
2022-10-05 16:59:07 +02:00
const CommandResult result = runCleartoolProc ( directory , { " pwv " } ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) ! = ProcessResult : : FinishedWithSuccess )
return { } ;
2013-04-18 22:25:23 +02:00
2022-09-21 08:13:29 +02:00
const QStringList output = result . cleanedStdOut ( ) . split ( QLatin1Char ( ' \n ' ) , Qt : : SkipEmptyParts ) ;
if ( output . size ( ) ! = 2 )
return { } ;
2013-04-18 22:25:23 +02:00
const QByteArray workingDirPattern ( " Working directory view: " ) ;
2022-09-21 08:13:29 +02:00
if ( ! output [ 0 ] . startsWith ( QLatin1String ( workingDirPattern ) ) )
return { } ;
2013-04-18 22:25:23 +02:00
const QByteArray setViewDirPattern ( " Set view: " ) ;
2022-09-21 08:13:29 +02:00
if ( ! output [ 1 ] . startsWith ( QLatin1String ( setViewDirPattern ) ) )
return { } ;
2013-04-18 22:25:23 +02:00
2022-09-21 08:13:29 +02:00
const QString workingDirectoryView = output [ 0 ] . mid ( workingDirPattern . size ( ) ) ;
const QString setView = output [ 1 ] . mid ( setViewDirPattern . size ( ) ) ;
2013-04-18 22:25:23 +02:00
const QString none ( QLatin1String ( " ** NONE ** " ) ) ;
QString rootDir ;
if ( setView ! = none | | workingDirectoryView ! = none )
rootDir = ccViewRoot ( directory ) ;
else
2022-09-21 08:13:29 +02:00
return { } ;
2013-04-18 22:25:23 +02:00
// 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
2022-09-21 08:13:29 +02:00
for ( const QString & relativeVobDir : qAsConst ( vobs ) ) {
2013-04-18 22:25:23 +02:00
const QString vobPath = QDir : : cleanPath ( rootDir + QDir : : fromNativeSeparators ( relativeVobDir ) ) ;
2021-07-30 16:46:27 +02:00
const bool isManaged = ( vobPath = = directory . toString ( ) )
| | directory . isChildOf ( FilePath : : fromString ( vobPath ) ) ;
2013-04-18 22:25:23 +02:00
if ( isManaged )
return vobPath ;
}
2022-09-21 08:13:29 +02:00
return { } ;
2013-02-03 23:30:22 +02:00
}
2013-04-18 22:25:23 +02:00
/// Find the root path of a clearcase view. Precondition: This is a clearcase managed dir
2021-07-30 16:46:27 +02:00
QString ClearCasePluginPrivate : : ccViewRoot ( const FilePath & directory ) const
2013-04-18 22:25:23 +02:00
{
2022-10-05 16:59:07 +02:00
const CommandResult result = runCleartoolProc ( directory , { " pwv " , " -root " } ) ;
2022-09-21 08:13:29 +02:00
QString root = result . cleanedStdOut ( ) . trimmed ( ) ;
2013-04-18 22:25:23 +02:00
if ( root . isEmpty ( ) ) {
2014-08-28 16:47:19 +02:00
if ( HostOsInfo : : isWindowsHost ( ) )
2021-07-30 16:46:27 +02:00
root = getDriveLetterOfPath ( directory . toString ( ) ) ;
2013-04-18 22:25:23 +02:00
else
2014-08-29 14:00:18 +02:00
root = QLatin1Char ( ' / ' ) ;
2013-04-18 22:25:23 +02:00
}
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
*/
2021-07-30 16:46:27 +02:00
QString ClearCasePluginPrivate : : findTopLevel ( const FilePath & directory ) const
2011-06-05 17:58:02 +03:00
{
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).
2021-07-30 16:46:27 +02:00
if ( directory = = m_topLevel | | directory . isChildOf ( m_topLevel ) )
return m_topLevel . toString ( ) ;
2012-10-03 18:03:53 +02:00
2013-04-18 22:25:23 +02:00
return ccManagesDirectory ( directory ) ;
2011-06-05 17:58:02 +03:00
}
bool ClearCasePlugin : : initialize ( const QStringList & /*arguments */ , QString * errorMessage )
{
2015-02-04 09:32:46 +01:00
Q_UNUSED ( errorMessage )
2020-01-23 17:22:05 +01:00
dd = new ClearCasePluginPrivate ;
return true ;
}
void ClearCasePlugin : : extensionsInitialized ( )
{
dd - > extensionsInitialized ( ) ;
}
2020-01-30 12:31:47 +01:00
ClearCasePluginPrivate : : ClearCasePluginPrivate ( )
: VcsBase : : VcsBasePluginPrivate ( Context ( CLEARCASE_CONTEXT ) ) ,
m_statusMap ( new StatusMap )
2020-01-23 17:22:05 +01:00
{
dd = this ;
qRegisterMetaType < ClearCase : : Internal : : FileStatus : : Status > ( " ClearCase::Internal::FileStatus::Status " ) ;
connect ( qApp , & QApplication : : applicationStateChanged ,
this , [ this ] ( Qt : : ApplicationState state ) {
if ( state = = Qt : : ApplicationActive )
syncSlot ( ) ;
} ) ;
2011-06-05 17:58:02 +03:00
using namespace Constants ;
using namespace Core : : Constants ;
2014-11-16 12:05:34 +02:00
Context context ( CLEARCASE_CONTEXT ) ;
2020-01-23 17:22:05 +01:00
connect ( ICore : : instance ( ) , & ICore : : coreAboutToClose , this , & ClearCasePluginPrivate : : closing ) ;
2015-11-19 16:54:28 +01:00
connect ( ProgressManager : : instance ( ) , & ProgressManager : : allTasksFinished ,
2020-01-23 17:22:05 +01:00
this , & ClearCasePluginPrivate : : tasksFinished ) ;
2011-06-05 17:58:02 +03:00
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
2015-02-16 15:14:21 +01:00
connect ( SessionManager : : instance ( ) , & SessionManager : : startupProjectChanged ,
2020-01-23 17:22:05 +01:00
this , & ClearCasePluginPrivate : : projectChanged ) ;
2011-06-05 17:58:02 +03:00
const QString description = QLatin1String ( " ClearCase " ) ;
const QString prefix = QLatin1String ( " cc " ) ;
// register cc prefix in Locator
2018-02-02 10:08:21 +01:00
m_commandLocator = new CommandLocator ( " cc " , description , prefix , this ) ;
2022-09-29 14:47:34 +02:00
m_commandLocator - > setDescription ( Tr : : tr ( " Triggers a ClearCase version control operation. " ) ) ;
2011-06-05 17:58:02 +03:00
//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 ) ;
2022-09-29 14:47:34 +02:00
clearcaseMenu - > menu ( ) - > setTitle ( Tr : : tr ( " C&learCase " ) ) ;
2011-06-05 17:58:02 +03:00
toolsContainer - > addMenu ( clearcaseMenu ) ;
m_menuAction = clearcaseMenu - > menu ( ) - > menuAction ( ) ;
2013-08-30 09:22:42 +02:00
Command * command ;
2011-06-05 17:58:02 +03:00
2022-09-29 14:47:34 +02:00
m_checkOutAction = new ParameterAction ( Tr : : tr ( " Check Out... " ) , Tr : : tr ( " Check &Out \" %1 \" ... " ) , ParameterAction : : AlwaysEnabled , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_checkOutAction , CMD_ID_CHECKOUT ,
2014-11-16 12:05:34 +02:00
context ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
2022-09-29 14:47:34 +02:00
command - > setDefaultKeySequence ( QKeySequence ( useMacShortcuts ? Tr : : tr ( " Meta+L,Meta+O " ) : Tr : : tr ( " Alt+L,Alt+O " ) ) ) ;
2020-01-23 17:22:05 +01:00
connect ( m_checkOutAction , & QAction : : triggered , this , & ClearCasePluginPrivate : : checkOutCurrentFile ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
2022-09-29 14:47:34 +02:00
m_checkInCurrentAction = new ParameterAction ( Tr : : tr ( " Check &In... " ) , Tr : : tr ( " Check &In \" %1 \" ... " ) , ParameterAction : : AlwaysEnabled , this ) ;
2014-11-16 12:05:34 +02:00
command = ActionManager : : registerAction ( m_checkInCurrentAction , CMD_ID_CHECKIN , context ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
2022-09-29 14:47:34 +02:00
command - > setDefaultKeySequence ( QKeySequence ( useMacShortcuts ? Tr : : tr ( " Meta+L,Meta+I " ) : Tr : : tr ( " Alt+L,Alt+I " ) ) ) ;
2020-01-23 17:22:05 +01:00
connect ( m_checkInCurrentAction , & QAction : : triggered , this , & ClearCasePluginPrivate : : startCheckInCurrentFile ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
2022-09-29 14:47:34 +02:00
m_undoCheckOutAction = new ParameterAction ( Tr : : tr ( " Undo Check Out " ) , Tr : : tr ( " &Undo Check Out \" %1 \" " ) , ParameterAction : : AlwaysEnabled , this ) ;
2014-11-16 12:05:34 +02:00
command = ActionManager : : registerAction ( m_undoCheckOutAction , CMD_ID_UNDOCHECKOUT , context ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
2022-09-29 14:47:34 +02:00
command - > setDefaultKeySequence ( QKeySequence ( useMacShortcuts ? Tr : : tr ( " Meta+L,Meta+U " ) : Tr : : tr ( " Alt+L,Alt+U " ) ) ) ;
2020-01-23 17:22:05 +01:00
connect ( m_undoCheckOutAction , & QAction : : triggered , this , & ClearCasePluginPrivate : : undoCheckOutCurrent ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
2022-09-29 14:47:34 +02:00
m_undoHijackAction = new ParameterAction ( Tr : : tr ( " Undo Hijack " ) , Tr : : tr ( " Undo Hi&jack \" %1 \" " ) , ParameterAction : : AlwaysEnabled , this ) ;
2014-11-16 12:05:34 +02:00
command = ActionManager : : registerAction ( m_undoHijackAction , CMD_ID_UNDOHIJACK , context ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
2022-09-29 14:47:34 +02:00
command - > setDefaultKeySequence ( QKeySequence ( useMacShortcuts ? Tr : : tr ( " Meta+L,Meta+R " ) : Tr : : tr ( " Alt+L,Alt+R " ) ) ) ;
2020-01-23 17:22:05 +01:00
connect ( m_undoHijackAction , & QAction : : triggered , this , & ClearCasePluginPrivate : : undoHijackCurrent ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
2014-11-16 12:05:34 +02:00
clearcaseMenu - > addSeparator ( context ) ;
2011-06-05 17:58:02 +03:00
2022-09-29 14:47:34 +02:00
m_diffCurrentAction = new ParameterAction ( Tr : : tr ( " Diff Current File " ) , Tr : : tr ( " &Diff \" %1 \" " ) , ParameterAction : : EnabledWithParameter , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_diffCurrentAction ,
2014-11-16 12:05:34 +02:00
CMD_ID_DIFF_CURRENT , context ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
2022-09-29 14:47:34 +02:00
command - > setDefaultKeySequence ( QKeySequence ( useMacShortcuts ? Tr : : tr ( " Meta+L,Meta+D " ) : Tr : : tr ( " Alt+L,Alt+D " ) ) ) ;
2020-01-23 17:22:05 +01:00
connect ( m_diffCurrentAction , & QAction : : triggered , this , & ClearCasePluginPrivate : : diffCurrentFile ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
2022-09-29 14:47:34 +02:00
m_historyCurrentAction = new ParameterAction ( Tr : : tr ( " History Current File " ) , Tr : : tr ( " &History \" %1 \" " ) , ParameterAction : : EnabledWithParameter , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_historyCurrentAction ,
2014-11-16 12:05:34 +02:00
CMD_ID_HISTORY_CURRENT , context ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
2022-09-29 14:47:34 +02:00
command - > setDefaultKeySequence ( QKeySequence ( useMacShortcuts ? Tr : : tr ( " Meta+L,Meta+H " ) : Tr : : tr ( " Alt+L,Alt+H " ) ) ) ;
2015-11-19 16:54:28 +01:00
connect ( m_historyCurrentAction , & QAction : : triggered , this ,
2020-01-23 17:22:05 +01:00
& ClearCasePluginPrivate : : historyCurrentFile ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
2022-09-29 14:47:34 +02:00
m_annotateCurrentAction = new ParameterAction ( Tr : : tr ( " Annotate Current File " ) , Tr : : tr ( " &Annotate \" %1 \" " ) , ParameterAction : : EnabledWithParameter , this ) ;
2013-08-30 09:22:42 +02:00
command = ActionManager : : registerAction ( m_annotateCurrentAction ,
2014-11-16 12:05:34 +02:00
CMD_ID_ANNOTATE , context ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
2022-09-29 14:47:34 +02:00
command - > setDefaultKeySequence ( QKeySequence ( useMacShortcuts ? Tr : : tr ( " Meta+L,Meta+A " ) : Tr : : tr ( " Alt+L,Alt+A " ) ) ) ;
2015-11-19 16:54:28 +01:00
connect ( m_annotateCurrentAction , & QAction : : triggered , this ,
2020-01-23 17:22:05 +01:00
& ClearCasePluginPrivate : : annotateCurrentFile ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
2022-09-29 14:47:34 +02:00
m_addFileAction = new ParameterAction ( Tr : : tr ( " Add File... " ) , Tr : : tr ( " Add File \" %1 \" " ) , ParameterAction : : EnabledWithParameter , this ) ;
2014-11-16 12:05:34 +02:00
command = ActionManager : : registerAction ( m_addFileAction , CMD_ID_ADD_FILE , context ) ;
2013-08-30 09:22:42 +02:00
command - > setAttribute ( Command : : CA_UpdateText ) ;
2020-01-23 17:22:05 +01:00
connect ( m_addFileAction , & QAction : : triggered , this , & ClearCasePluginPrivate : : addCurrentFile ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
2014-11-16 12:05:34 +02:00
clearcaseMenu - > addSeparator ( context ) ;
2011-06-05 17:58:02 +03:00
2022-09-29 14:47:34 +02:00
m_diffActivityAction = new QAction ( Tr : : tr ( " Diff A&ctivity... " ) , this ) ;
2013-11-20 11:59:34 +01:00
m_diffActivityAction - > setEnabled ( false ) ;
2014-11-16 12:05:34 +02:00
command = ActionManager : : registerAction ( m_diffActivityAction , CMD_ID_DIFF_ACTIVITY , context ) ;
2020-01-23 17:22:05 +01:00
connect ( m_diffActivityAction , & QAction : : triggered , this , & ClearCasePluginPrivate : : diffActivity ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
2022-09-29 14:47:34 +02:00
m_checkInActivityAction = new ParameterAction ( Tr : : tr ( " Ch&eck In Activity " ) , Tr : : tr ( " Chec&k In Activity \" %1 \" ... " ) , ParameterAction : : EnabledWithParameter , this ) ;
2013-11-20 11:59:34 +01:00
m_checkInActivityAction - > setEnabled ( false ) ;
2014-11-16 12:05:34 +02:00
command = ActionManager : : registerAction ( m_checkInActivityAction , CMD_ID_CHECKIN_ACTIVITY , context ) ;
2020-01-23 17:22:05 +01:00
connect ( m_checkInActivityAction , & QAction : : triggered , this , & ClearCasePluginPrivate : : 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 ) ;
2014-11-16 12:05:34 +02:00
clearcaseMenu - > addSeparator ( context ) ;
2011-06-05 17:58:02 +03:00
2022-09-29 14:47:34 +02:00
m_updateIndexAction = new QAction ( Tr : : tr ( " Update Index " ) , this ) ;
2014-11-16 12:05:34 +02:00
command = ActionManager : : registerAction ( m_updateIndexAction , CMD_ID_UPDATEINDEX , context ) ;
2020-01-23 17:22:05 +01:00
connect ( m_updateIndexAction , & QAction : : triggered , this , & ClearCasePluginPrivate : : updateIndex ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
2022-09-29 14:47:34 +02:00
m_updateViewAction = new ParameterAction ( Tr : : tr ( " Update View " ) , Tr : : tr ( " U&pdate View \" %1 \" " ) , ParameterAction : : EnabledWithParameter , this ) ;
2014-11-16 12:05:34 +02:00
command = ActionManager : : registerAction ( m_updateViewAction , CMD_ID_UPDATE_VIEW , context ) ;
2020-01-23 17:22:05 +01:00
connect ( m_updateViewAction , & QAction : : triggered , this , & ClearCasePluginPrivate : : 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 ) ;
2014-11-16 12:05:34 +02:00
clearcaseMenu - > addSeparator ( context ) ;
2011-06-05 17:58:02 +03:00
2022-09-29 14:47:34 +02:00
m_checkInAllAction = new QAction ( Tr : : tr ( " Check In All &Files... " ) , this ) ;
2014-11-16 12:05:34 +02:00
command = ActionManager : : registerAction ( m_checkInAllAction , CMD_ID_CHECKIN_ALL , context ) ;
2022-09-29 14:47:34 +02:00
command - > setDefaultKeySequence ( QKeySequence ( useMacShortcuts ? Tr : : tr ( " Meta+L,Meta+F " ) : Tr : : tr ( " Alt+L,Alt+F " ) ) ) ;
2020-01-23 17:22:05 +01:00
connect ( m_checkInAllAction , & QAction : : triggered , this , & ClearCasePluginPrivate : : startCheckInAll ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
2022-09-29 14:47:34 +02:00
m_statusAction = new QAction ( Tr : : tr ( " View &Status " ) , this ) ;
2014-11-16 12:05:34 +02:00
command = ActionManager : : registerAction ( m_statusAction , CMD_ID_STATUS , context ) ;
2022-09-29 14:47:34 +02:00
command - > setDefaultKeySequence ( QKeySequence ( useMacShortcuts ? Tr : : tr ( " Meta+L,Meta+S " ) : Tr : : tr ( " Alt+L,Alt+S " ) ) ) ;
2020-01-23 17:22:05 +01:00
connect ( m_statusAction , & QAction : : triggered , this , & ClearCasePluginPrivate : : viewStatus ) ;
2011-06-05 17:58:02 +03:00
clearcaseMenu - > addAction ( command ) ;
m_commandLocator - > appendCommand ( command ) ;
}
// called before closing the submit editor
2020-01-23 17:22:05 +01:00
bool ClearCasePluginPrivate : : submitEditorAboutToClose ( )
2011-06-05 17:58:02 +03:00
{
if ( ! isCheckInEditorOpen ( ) )
return true ;
2018-09-20 00:56:28 +03:00
auto editor = qobject_cast < ClearCaseSubmitEditor * > ( submitEditor ( ) ) ;
2013-04-18 12:06:43 +02:00
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
2021-07-30 16:46:27 +02:00
const FilePath editorFile = editorDocument - > filePath ( ) ;
const FilePath changeFile = m_checkInMessageFilePath ;
2011-06-05 17:58:02 +03:00
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 ;
2014-08-28 16:47:19 +02:00
const VcsBaseSubmitEditor : : PromptSubmitResult answer =
2018-11-09 09:59:40 +02:00
editor - > promptSubmit ( this , & prompt , ! m_submitActionTriggered ) ;
2011-06-05 17:58:02 +03:00
m_submitActionTriggered = false ;
switch ( answer ) {
2014-08-28 16:47:19 +02:00
case VcsBaseSubmitEditor : : SubmitCanceled :
2011-06-05 17:58:02 +03:00
return false ; // Keep editing and change file
2014-08-28 16:47:19 +02:00
case VcsBaseSubmitEditor : : SubmitDiscarded :
2011-06-05 17:58:02 +03:00
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 ( ) ;
2021-07-30 16:46:27 +02:00
closeEditor = vcsCheckIn ( m_checkInMessageFilePath , fileList , widget - > activity ( ) ,
2011-06-05 17:58:02 +03:00
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 ;
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : diffCheckInFiles ( const QStringList & files )
2011-06-05 17:58:02 +03:00
{
2012-09-12 09:27:06 +03:00
ccDiffWithPred ( m_checkInView , files ) ;
2011-06-05 17:58:02 +03:00
}
2021-07-30 16:46:27 +02:00
static void setWorkingDirectory ( IEditor * editor , const FilePath & wd )
2011-06-05 17:58:02 +03:00
{
2018-09-20 00:56:28 +03:00
if ( auto ve = qobject_cast < 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
2020-01-23 17:22:05 +01:00
QString ClearCasePluginPrivate : : ccGetPredecessor ( const QString & version ) const
2011-06-05 17:58:02 +03:00
{
2022-10-05 16:59:07 +02:00
const CommandResult result = runCleartoolProc ( currentState ( ) . topLevel ( ) ,
{ " describe " , " -fmt " , " %En@@%PSn " , version } ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) ! = ProcessResult : : FinishedWithSuccess
| | result . cleanedStdOut ( ) . endsWith ( QLatin1Char ( ' @ ' ) ) ) { // <name-unknown>@@
return { } ;
}
return result . cleanedStdOut ( ) ;
2011-06-05 17:58:02 +03:00
}
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
2020-01-23 17:22:05 +01:00
QStringList ClearCasePluginPrivate : : ccGetActiveVobs ( ) const
2011-06-05 17:58:02 +03:00
{
2013-04-18 22:25:23 +02:00
const QString theViewRoot = viewRoot ( ) ;
2022-10-05 16:59:07 +02:00
const CommandResult result = runCleartoolProc ( FilePath : : fromString ( theViewRoot ) , { " lsvob " } ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) ! = ProcessResult : : FinishedWithSuccess )
return { } ;
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 ( ' / ' ) ;
2022-09-21 08:13:29 +02:00
QStringList res ;
2013-04-18 22:25:23 +02:00
const QDir theViewRootDir ( theViewRoot ) ;
2022-09-21 08:13:29 +02:00
const QStringList lines = result . cleanedStdOut ( ) . split ( QLatin1Char ( ' \n ' ) , Qt : : SkipEmptyParts ) ;
for ( const QString & line : lines ) {
2013-04-02 13:03:24 +02:00
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 ;
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : checkAndReIndexUnknownFile ( const QString & file )
2013-12-05 13:30:20 +01:00
{
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
2020-01-23 17:22:05 +01:00
FileStatus ClearCasePluginPrivate : : vcsStatus ( const QString & file ) const
2011-06-05 17:58:02 +03:00
{
2012-09-02 10:20:32 +03:00
return m_statusMap - > value ( file , FileStatus ( FileStatus : : Unknown ) ) ;
2011-06-05 17:58:02 +03:00
}
2021-07-30 16:46:27 +02:00
QString ClearCasePluginPrivate : : ccGetFileActivity ( const FilePath & workingDir , const QString & file )
2011-06-05 17:58:02 +03:00
{
2022-10-05 16:59:07 +02:00
return runCleartoolProc ( workingDir , { " lscheckout " , " -fmt " , " %[activity]p " , file } ) . cleanedStdOut ( ) ;
2011-06-05 17:58:02 +03:00
}
2021-07-30 16:46:27 +02:00
ClearCaseSubmitEditor * ClearCasePluginPrivate : : openClearCaseSubmitEditor ( const FilePath & filePath , bool isUcm )
2011-06-05 17:58:02 +03:00
{
2013-08-30 09:22:42 +02:00
IEditor * editor =
2021-07-30 16:46:27 +02:00
EditorManager : : openEditor ( filePath , Constants : : CLEARCASECHECKINEDITOR_ID ) ;
2018-09-20 00:56:28 +03:00
auto submitEditor = qobject_cast < ClearCaseSubmitEditor * > ( editor ) ;
QTC_ASSERT ( submitEditor , return nullptr ) ;
2015-03-04 14:56:56 +01:00
connect ( submitEditor , & VcsBaseSubmitEditor : : diffSelectedFiles ,
2020-01-23 17:22:05 +01:00
this , & ClearCasePluginPrivate : : diffCheckInFiles ) ;
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 " ) ;
}
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : updateStatusActions ( )
2011-06-05 17:58:02 +03:00
{
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-12-03 17:45:26 +01:00
updateEditDerivedObjectWarning ( absoluteFileName , fileStatus . status ) ;
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
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : updateActions ( VcsBasePluginPrivate : : ActionState as )
2011-06-05 17:58:02 +03:00
{
if ( ! enableMenuAction ( as , m_menuAction ) ) {
m_commandLocator - > setEnabled ( false ) ;
return ;
}
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
const bool hasTopLevel = state . hasTopLevel ( ) ;
m_commandLocator - > setEnabled ( hasTopLevel ) ;
2014-03-24 14:42:34 +02:00
if ( hasTopLevel ) {
2021-07-30 16:46:27 +02:00
const FilePath topLevel = state . topLevel ( ) ;
2014-03-24 14:42:34 +02:00
if ( m_topLevel ! = topLevel ) {
m_topLevel = topLevel ;
m_viewData = ccGetView ( topLevel ) ;
}
}
2011-06-05 17:58:02 +03:00
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 ( ) ;
}
2020-01-23 17:22:05 +01:00
QString ClearCasePluginPrivate : : commitDisplayName ( ) const
2017-09-08 12:52:35 +02:00
{
2022-09-29 14:47:34 +02:00
return Tr : : tr ( " Check In " ) ;
2017-09-08 12:52:35 +02:00
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : checkOutCurrentFile ( )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
QTC_ASSERT ( state . hasFile ( ) , return ) ;
vcsOpen ( state . currentFileTopLevel ( ) , state . relativeCurrentFile ( ) ) ;
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : addCurrentFile ( )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
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
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : 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 )
2020-11-11 16:34:39 +01:00
QMetaObject : : invokeMethod ( this , & ClearCasePluginPrivate : : updateStatusActions ) ;
2011-06-05 17:58:02 +03:00
}
2022-09-28 17:42:25 +02:00
class UndoCheckOutDialog : public QDialog
{
public :
UndoCheckOutDialog ( )
{
resize ( 323 , 105 ) ;
setSizePolicy ( QSizePolicy : : Expanding , QSizePolicy : : Preferred ) ;
2022-09-29 14:47:34 +02:00
setWindowTitle ( Tr : : tr ( " Dialog " ) ) ;
2022-09-28 17:42:25 +02:00
lblMessage = new QLabel ( this ) ;
QPalette palette ;
QBrush brush ( QColor ( 255 , 0 , 0 , 255 ) ) ;
brush . setStyle ( Qt : : SolidPattern ) ;
palette . setBrush ( QPalette : : Active , QPalette : : WindowText , brush ) ;
palette . setBrush ( QPalette : : Inactive , QPalette : : WindowText , brush ) ;
QBrush brush1 ( QColor ( 68 , 96 , 92 , 255 ) ) ;
brush1 . setStyle ( Qt : : SolidPattern ) ;
palette . setBrush ( QPalette : : Disabled , QPalette : : WindowText , brush1 ) ;
2022-09-29 14:47:34 +02:00
auto lblModified = new QLabel ( Tr : : tr ( " The file was changed. " ) ) ;
2022-09-28 17:42:25 +02:00
lblModified - > setPalette ( palette ) ;
2022-09-29 14:47:34 +02:00
chkKeep = new QCheckBox ( Tr : : tr ( " &Save copy of the file with a '.keep' extension " ) ) ;
2022-09-28 17:42:25 +02:00
chkKeep - > setChecked ( true ) ;
auto buttonBox = new QDialogButtonBox ( QDialogButtonBox : : No | QDialogButtonBox : : Yes ) ;
using namespace Layouting ;
Column {
lblMessage ,
lblModified ,
chkKeep ,
buttonBox
} . attachTo ( this ) ;
connect ( buttonBox , & QDialogButtonBox : : accepted , this , & QDialog : : accept ) ;
connect ( buttonBox , & QDialogButtonBox : : rejected , this , & QDialog : : reject ) ;
}
QLabel * lblMessage ;
QCheckBox * chkKeep ;
} ;
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : undoCheckOutCurrent ( )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
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 ;
2022-10-05 16:21:22 +02:00
const CommandResult result = runCleartool ( state . currentFileTopLevel ( ) , args ) ;
2011-06-05 17:58:02 +03:00
bool keep = false ;
2022-09-21 08:13:29 +02:00
if ( result . exitCode ( ) ) { // return value is 1 if there is any difference
2022-09-28 17:42:25 +02:00
UndoCheckOutDialog dialog ;
2022-09-29 14:47:34 +02:00
dialog . lblMessage - > setText ( Tr : : tr ( " Do you want to undo the check out of \" %1 \" ? " ) . arg ( fileName ) ) ;
2022-09-28 17:42:25 +02:00
dialog . chkKeep - > setChecked ( m_settings . keepFileUndoCheckout ) ;
if ( dialog . exec ( ) ! = QDialog : : Accepted )
2011-06-05 17:58:02 +03:00
return ;
2022-09-28 17:42:25 +02:00
keep = dialog . chkKeep - > isChecked ( ) ;
2015-01-02 16:15:20 +01:00
if ( keep ! = m_settings . keepFileUndoCheckout ) {
m_settings . keepFileUndoCheckout = keep ;
m_settings . toSettings ( ICore : : settings ( ) ) ;
}
2011-06-05 17:58:02 +03:00
}
vcsUndoCheckOut ( state . topLevel ( ) , file , keep ) ;
}
2021-07-30 16:46:27 +02:00
bool ClearCasePluginPrivate : : vcsUndoCheckOut ( const FilePath & workingDir , const QString & fileName , bool keep )
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 < < workingDir < < fileName < < keep ;
2021-06-09 09:59:37 +02:00
FileChangeBlocker fcb ( FilePath : : fromString ( fileName ) ) ;
2011-06-05 17:58:02 +03:00
// revert
QStringList args ( QLatin1String ( " uncheckout " ) ) ;
args < < QLatin1String ( keep ? " -keep " : " -rm " ) ;
args < < QDir : : toNativeSeparators ( fileName ) ;
2022-10-05 19:08:53 +02:00
const CommandResult result = runCleartool ( workingDir , args , RunFlags : : ShowStdOut ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) ! = ProcessResult : : FinishedWithSuccess )
return false ;
2013-04-18 22:25:23 +02:00
2022-09-21 08:13:29 +02:00
const QString absPath = workingDir . pathAppended ( fileName ) . toString ( ) ;
if ( ! m_settings . disableIndexer )
setStatus ( absPath , FileStatus : : CheckedIn ) ;
emit filesChanged ( QStringList ( absPath ) ) ;
return true ;
2011-06-05 17:58:02 +03:00
}
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
*/
2021-07-30 16:46:27 +02:00
bool ClearCasePluginPrivate : : vcsUndoHijack ( const FilePath & workingDir , const QString & fileName , bool keep )
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 < < workingDir < < fileName < < keep ;
QStringList args ( QLatin1String ( " update " ) ) ;
args < < QLatin1String ( keep ? " -rename " : " -overwrite " ) ;
args < < QLatin1String ( " -log " ) ;
2014-08-28 16:47:19 +02:00
if ( HostOsInfo : : isWindowsHost ( ) )
2012-08-23 15:53:58 +02:00
args < < QLatin1String ( " NUL " ) ;
else
2011-06-05 17:58:02 +03:00
args < < QLatin1String ( " /dev/null " ) ;
args < < QDir : : toNativeSeparators ( fileName ) ;
2022-10-05 19:08:53 +02:00
const CommandResult result = runCleartool ( workingDir , args , RunFlags : : ShowStdOut ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) = = ProcessResult : : FinishedWithSuccess )
return false ;
if ( m_settings . disableIndexer )
return true ;
const QString absPath = workingDir . pathAppended ( fileName ) . toString ( ) ;
setStatus ( absPath , FileStatus : : CheckedIn ) ;
return true ;
2011-06-05 17:58:02 +03:00
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : undoHijackCurrent ( )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
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 ) {
2022-10-05 17:22:09 +02:00
const QString result = diffExternal ( ccGetFileVersion ( state . topLevel ( ) , fileName ) , fileName ) ;
if ( ! result . isEmpty ( ) & & result . front ( ) = = QLatin1Char ( ' F ' ) ) // Files are identical
2012-09-02 11:26:26 +03:00
askKeep = false ;
}
if ( askKeep ) {
2022-09-28 17:42:25 +02:00
UndoCheckOutDialog unhijackDlg ;
2022-09-29 14:47:34 +02:00
unhijackDlg . setWindowTitle ( Tr : : tr ( " Undo Hijack File " ) ) ;
unhijackDlg . lblMessage - > setText ( Tr : : tr ( " Do you want to undo hijack of \" %1 \" ? " )
2011-06-05 17:58:02 +03:00
. arg ( QDir : : toNativeSeparators ( fileName ) ) ) ;
if ( unhijackDlg . exec ( ) ! = QDialog : : Accepted )
return ;
2022-09-28 17:42:25 +02:00
keep = unhijackDlg . chkKeep - > isChecked ( ) ;
2011-06-05 17:58:02 +03:00
}
2021-06-09 09:59:37 +02:00
FileChangeBlocker fcb ( FilePath : : fromString ( state . currentFile ( ) ) ) ;
2011-06-05 17:58:02 +03:00
// revert
if ( vcsUndoHijack ( state . currentFileTopLevel ( ) , fileName , keep ) )
2020-01-30 12:31:47 +01:00
emit filesChanged ( QStringList ( state . currentFile ( ) ) ) ;
2011-06-05 17:58:02 +03:00
}
2021-07-30 16:46:27 +02:00
QString ClearCasePluginPrivate : : ccGetFileVersion ( const FilePath & workingDir , const QString & file ) const
2011-06-05 17:58:02 +03:00
{
2022-10-05 17:22:09 +02:00
return runCleartoolProc ( workingDir , { " ls " , " -short " , file } ) . cleanedStdOut ( ) . trimmed ( ) ;
2011-06-05 17:58:02 +03:00
}
2021-07-30 16:46:27 +02:00
void ClearCasePluginPrivate : : ccDiffWithPred ( const FilePath & 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 ;
2014-08-28 16:47:19 +02:00
const QString source = VcsBaseEditor : : getSource ( workingDir , files ) ;
2018-09-20 00:56:28 +03:00
QTextCodec * codec = source . isEmpty ( ) ? static_cast < QTextCodec * > ( nullptr )
: VcsBaseEditor : : getCodec ( source ) ;
2011-06-05 17:58:02 +03:00
if ( ( m_settings . diffType = = GraphicalDiff ) & & ( files . count ( ) = = 1 ) ) {
2013-04-18 22:25:23 +02:00
const QString file = files . first ( ) ;
2021-07-30 16:46:27 +02:00
const QString absFilePath = workingDir . pathAppended ( file ) . toString ( ) ;
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 ) {
2022-09-29 14:47:34 +02:00
VcsOutputWindow : : appendError ( Tr : : tr ( " External diff is required to compare multiple files. " ) ) ;
2012-09-02 11:26:26 +03:00
return ;
}
2011-06-05 17:58:02 +03:00
QString result ;
2022-09-21 08:13:29 +02:00
for ( const QString & file : files ) {
2021-07-30 16:46:27 +02:00
const QString absFilePath = workingDir . pathAppended ( file ) . toString ( ) ;
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
2022-10-06 12:51:50 +02:00
const QString tag = VcsBaseEditor : : editorTag ( 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
2014-08-28 16:47:19 +02:00
if ( IEditor * existingEditor = VcsBaseEditor : : 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 ) ;
2020-02-07 07:51:20 +01:00
IEditor * editor = showOutputInEditor ( title , result , diffEditorParameters . id , source , codec ) ;
2013-10-06 20:52:09 +03:00
setWorkingDirectory ( editor , workingDir ) ;
2014-08-28 16:47:19 +02:00
VcsBaseEditor : : tagEditor ( editor , tag ) ;
2018-09-20 00:56:28 +03:00
auto diffEditorWidget = qobject_cast < ClearCaseEditorWidget * > ( editor - > widget ( ) ) ;
2011-06-05 17:58:02 +03:00
QTC_ASSERT ( diffEditorWidget , return ) ;
if ( files . count ( ) = = 1 )
editor - > setProperty ( " originalFileName " , diffname ) ;
}
2021-07-30 16:46:27 +02:00
QStringList ClearCasePluginPrivate : : ccGetActivityVersions ( const FilePath & workingDir , const QString & activity )
2011-06-05 17:58:02 +03:00
{
2022-10-05 16:59:07 +02:00
const CommandResult result = runCleartoolProc ( workingDir , { " lsactivity " , " -fmt " ,
" %[versions]Cp " , activity } ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) ! = ProcessResult : : FinishedWithSuccess )
return { } ;
QStringList versions = result . cleanedStdOut ( ) . split ( QLatin1String ( " , " ) ) ;
2011-06-05 17:58:02 +03:00
versions . sort ( ) ;
return versions ;
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : rmdir ( const QString & path )
2011-06-05 17:58:02 +03:00
{
QDir dir ( path ) ;
2022-09-21 08:13:29 +02:00
const auto fileInfoList = dir . entryInfoList ( QDir : : AllEntries | QDir : : NoDotAndDotDot ) ;
for ( QFileInfo fi : fileInfoList ) {
2011-06-05 17:58:02 +03:00
if ( fi . isDir ( ) ) {
rmdir ( fi . canonicalFilePath ( ) ) ;
dir . rmdir ( fi . baseName ( ) ) ;
2022-09-21 08:13:29 +02:00
} else {
2011-06-05 17:58:02 +03:00
QFile : : remove ( fi . canonicalFilePath ( ) ) ;
2022-09-21 08:13:29 +02:00
}
2011-06-05 17:58:02 +03:00
}
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : diffActivity ( )
2011-06-05 17:58:02 +03:00
{
2018-11-04 22:49:24 +01:00
using FileVerIt = QMap < QString , QStringPair > : : Iterator ;
2013-03-08 09:53:02 +01:00
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
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 ) {
2022-09-29 14:47:34 +02:00
VcsOutputWindow : : appendError ( Tr : : tr ( " External diff is required to compare multiple files. " ) ) ;
2012-09-02 11:26:26 +03:00
return ;
}
2021-07-30 16:46:27 +02:00
FilePath topLevel = state . topLevel ( ) ;
2022-09-29 14:47:34 +02:00
QString activity = QInputDialog : : getText ( ICore : : dialogParent ( ) , Tr : : tr ( " Enter Activity " ) ,
Tr : : tr ( " Activity Name " ) , QLineEdit : : Normal , m_activity ) ;
2011-06-05 17:58:02 +03:00
if ( activity . isEmpty ( ) )
return ;
2022-09-21 08:13:29 +02:00
const QStringList versions = ccGetActivityVersions ( topLevel , activity ) ;
2011-06-05 17:58:02 +03:00
QString result ;
// map from fileName to (first, latest) pair
QMap < QString , QStringPair > filever ;
2021-07-30 16:46:27 +02:00
int topLevelLen = topLevel . toString ( ) . length ( ) ;
2022-09-21 08:13:29 +02:00
for ( const QString & version : versions ) {
2011-06-05 17:58:02 +03:00
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 ;
2014-03-04 00:12:11 +01:00
// pre-first version. only for the first occurrence
2011-06-05 17:58:02 +03:00
if ( filever [ file ] . first . isEmpty ( ) ) {
2020-06-23 18:36:26 +02:00
int verpos = shortver . lastIndexOf ( QRegularExpression ( " [^0-9] " ) ) + 1 ;
2020-09-18 13:16:55 +02:00
int vernum = shortver . mid ( verpos ) . toInt ( ) ;
2011-06-05 17:58:02 +03:00
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 ) ) {
2020-12-08 15:41:46 +01:00
QStringPair pair ( filever . first ( ) ) ;
2011-06-05 17:58:02 +03:00
diffGraphical ( pair . first , pair . second ) ;
return ;
}
2022-08-03 06:55:06 +02:00
rmdir ( TemporaryDirectory : : masterDirectoryPath ( ) + QLatin1String ( " /ccdiff/ " ) + activity ) ;
QDir ( TemporaryDirectory : : masterDirectoryPath ( ) ) . rmpath ( QLatin1String ( " ccdiff/ " ) + activity ) ;
2011-06-05 17:58:02 +03:00
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 ) ;
2020-02-07 07:51:20 +01:00
IEditor * editor = showOutputInEditor ( title , result , diffEditorParameters . id , activity , nullptr ) ;
2013-10-06 20:52:09 +03:00
setWorkingDirectory ( editor , topLevel ) ;
2011-06-05 17:58:02 +03:00
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : diffCurrentFile ( )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
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
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : startCheckInCurrentFile ( )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
QTC_ASSERT ( state . hasFile ( ) , return ) ;
QString nativeFile = QDir : : toNativeSeparators ( state . relativeCurrentFile ( ) ) ;
startCheckIn ( state . currentFileTopLevel ( ) , QStringList ( nativeFile ) ) ;
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : startCheckInAll ( )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
QTC_ASSERT ( state . hasTopLevel ( ) , return ) ;
2021-07-30 16:46:27 +02:00
FilePath topLevel = state . topLevel ( ) ;
2011-06-05 17:58:02 +03:00
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 ) ;
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : startCheckInActivity ( )
2011-06-05 17:58:02 +03:00
{
2012-09-24 11:39:34 +02:00
QTC_ASSERT ( isUcm ( ) , return ) ;
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
QTC_ASSERT ( state . hasProject ( ) , return ) ;
2012-09-24 11:39:34 +02:00
2011-06-05 17:58:02 +03:00
QDialog dlg ;
2015-01-22 13:52:14 +01:00
auto layout = new QVBoxLayout ( & dlg ) ;
auto actSelector = new ActivitySelector ( & dlg ) ;
auto buttonBox = new QDialogButtonBox ( QDialogButtonBox : : Ok | QDialogButtonBox : : Cancel , Qt : : Horizontal , & dlg ) ;
connect ( buttonBox , & QDialogButtonBox : : accepted , & dlg , & QDialog : : accept ) ;
connect ( buttonBox , & QDialogButtonBox : : rejected , & dlg , & QDialog : : reject ) ;
2011-06-05 17:58:02 +03:00
layout - > addWidget ( actSelector ) ;
layout - > addWidget ( buttonBox ) ;
2022-09-29 14:47:34 +02:00
dlg . setWindowTitle ( Tr : : tr ( " Check In Activity " ) ) ;
2011-06-05 17:58:02 +03:00
if ( ! dlg . exec ( ) )
return ;
2012-09-24 11:39:34 +02:00
2021-07-30 16:46:27 +02:00
FilePath topLevel = state . topLevel ( ) ;
int topLevelLen = topLevel . toString ( ) . length ( ) ;
2022-09-21 08:13:29 +02:00
const QStringList versions = ccGetActivityVersions ( topLevel , actSelector - > activity ( ) ) ;
2011-06-05 17:58:02 +03:00
QStringList files ;
QString last ;
2022-09-21 08:13:29 +02:00
for ( const QString & version : versions ) {
2011-06-05 17:58:02 +03:00
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 . */
2021-07-30 16:46:27 +02:00
void ClearCasePluginPrivate : : startCheckIn ( const FilePath & workingDir , const QStringList & files )
2011-06-05 17:58:02 +03:00
{
2017-09-08 12:52:35 +02:00
if ( ! promptBeforeCommit ( ) )
return ;
2013-04-18 12:06:43 +02:00
if ( raiseSubmitEditor ( ) )
2011-06-05 17:58:02 +03:00
return ;
if ( isCheckInEditorOpen ( ) ) {
2022-09-29 14:47:34 +02:00
VcsOutputWindow : : appendWarning ( Tr : : tr ( " Another check in is currently being executed. " ) ) ;
2011-06-05 17:58:02 +03:00
return ;
}
// Get list of added/modified/deleted files
if ( files . empty ( ) ) {
2022-09-29 14:47:34 +02:00
VcsOutputWindow : : appendWarning ( Tr : : tr ( " There are no modified files. " ) ) ;
2011-06-05 17:58:02 +03:00
return ;
}
// Create a new submit change file containing the submit template
2014-08-28 16:47:19 +02:00
TempFileSaver saver ;
2011-06-05 17:58:02 +03:00
saver . setAutoRemove ( false ) ;
2014-09-15 13:06:13 +03:00
QString submitTemplate ;
if ( files . count ( ) = = 1 )
submitTemplate = ccGetComment ( workingDir , files . first ( ) ) ;
2011-06-05 17:58:02 +03:00
// Create a submit
saver . write ( submitTemplate . toUtf8 ( ) ) ;
if ( ! saver . finalize ( ) ) {
2014-08-26 00:02:47 +02:00
VcsOutputWindow : : appendError ( saver . errorString ( ) ) ;
2011-06-05 17:58:02 +03:00
return ;
}
2021-07-30 16:46:27 +02:00
m_checkInMessageFilePath = saver . filePath ( ) ;
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
2021-07-30 16:46:27 +02:00
ClearCaseSubmitEditor * editor = openClearCaseSubmitEditor ( m_checkInMessageFilePath , 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 ) ;
}
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : historyCurrentFile ( )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
QTC_ASSERT ( state . hasFile ( ) , return ) ;
history ( state . currentFileTopLevel ( ) , QStringList ( state . relativeCurrentFile ( ) ) , true ) ;
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : updateView ( )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
QTC_ASSERT ( state . hasTopLevel ( ) , return ) ;
ccUpdate ( state . topLevel ( ) ) ;
}
2021-07-30 16:46:27 +02:00
void ClearCasePluginPrivate : : history ( const FilePath & workingDir ,
const QStringList & files ,
bool enableAnnotationContextMenu )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
QTextCodec * codec = VcsBaseEditor : : getCodec ( workingDir , files ) ;
2011-06-05 17:58:02 +03:00
// 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 ;
2022-09-21 08:13:29 +02:00
for ( const QString & file : files )
2011-06-05 17:58:02 +03:00
args . append ( QDir : : toNativeSeparators ( file ) ) ;
2022-10-05 19:08:53 +02:00
const CommandResult result = runCleartool ( workingDir , args , RunFlags : : None , codec ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) ! = ProcessResult : : FinishedWithSuccess )
2011-06-05 17:58:02 +03:00
return ;
// Re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
2014-08-28 16:47:19 +02:00
const QString id = VcsBaseEditor : : getTitleId ( workingDir , files ) ;
2022-10-06 12:51:50 +02:00
const QString tag = VcsBaseEditor : : editorTag ( LogOutput , workingDir , files ) ;
2014-08-28 16:47:19 +02:00
if ( IEditor * editor = VcsBaseEditor : : locateEditorByTag ( tag ) ) {
2022-09-21 08:13:29 +02:00
editor - > document ( ) - > setContents ( result . cleanedStdOut ( ) . toUtf8 ( ) ) ;
2013-08-30 09:22:42 +02:00
EditorManager : : activateEditor ( editor ) ;
2022-09-21 08:13:29 +02:00
return ;
2011-06-05 17:58:02 +03:00
}
2022-09-21 08:13:29 +02:00
const QString title = QString : : fromLatin1 ( " cc history %1 " ) . arg ( id ) ;
const QString source = VcsBaseEditor : : getSource ( workingDir , files ) ;
IEditor * newEditor = showOutputInEditor ( title , result . cleanedStdOut ( ) ,
logEditorParameters . id , source , codec ) ;
VcsBaseEditor : : tagEditor ( newEditor , tag ) ;
if ( enableAnnotationContextMenu )
VcsBaseEditor : : getVcsBaseEditor ( newEditor ) - > setFileLogAnnotateEnabled ( true ) ;
2011-06-05 17:58:02 +03:00
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : viewStatus ( )
2011-06-05 17:58:02 +03:00
{
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 ) ;
2015-01-19 13:22:20 +01:00
VcsOutputWindow : : append ( QLatin1String ( " Indexed files status (C=Checked Out, "
" H=Hijacked, ?=Missing) " ) ,
VcsOutputWindow : : Command , true ) ;
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 ) {
2014-08-26 00:02:47 +02:00
VcsOutputWindow : : append ( QString : : fromLatin1 ( " %1 %2 \n " )
2011-06-05 17:58:02 +03:00
. arg ( cstat )
. arg ( QDir : : toNativeSeparators ( it . key ( ) ) ) ) ;
anymod = true ;
}
}
if ( ! anymod )
2014-08-26 00:02:47 +02:00
VcsOutputWindow : : appendWarning ( QLatin1String ( " No modified files found. " ) ) ;
2011-06-05 17:58:02 +03:00
}
2021-07-30 16:46:27 +02:00
void ClearCasePluginPrivate : : ccUpdate ( const FilePath & workingDir , const QStringList & relativePaths )
2011-06-05 17:58:02 +03:00
{
QStringList args ( QLatin1String ( " update " ) ) ;
args < < QLatin1String ( " -noverwrite " ) ;
if ( ! relativePaths . isEmpty ( ) )
args . append ( relativePaths ) ;
2022-10-05 19:08:53 +02:00
const CommandResult result = runCleartool ( workingDir , args , RunFlags : : ShowStdOut , nullptr , 10 ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) = = ProcessResult : : FinishedWithSuccess )
2020-01-30 12:31:47 +01:00
emit repositoryChanged ( workingDir ) ;
2011-06-05 17:58:02 +03:00
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : annotateCurrentFile ( )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
QTC_ASSERT ( state . hasFile ( ) , return ) ;
2020-01-30 12:31:47 +01:00
vcsAnnotateHelper ( state . currentFileTopLevel ( ) , state . relativeCurrentFile ( ) ) ;
2011-06-05 17:58:02 +03:00
}
2021-07-30 16:46:27 +02:00
void ClearCasePluginPrivate : : vcsAnnotateHelper ( const FilePath & workingDir , const QString & file ,
2020-01-30 12:31:47 +01:00
const QString & revision /* = QString() */ ,
int lineNumber /* = -1 */ ) const
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 < < file ;
2014-08-28 16:47:19 +02:00
QTextCodec * codec = VcsBaseEditor : : getCodec ( file ) ;
2011-06-05 17:58:02 +03:00
// 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 ) ) ;
2022-10-05 19:08:53 +02:00
const CommandResult result = runCleartool ( workingDir , args , RunFlags : : None , codec ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) ! = ProcessResult : : FinishedWithSuccess )
2011-06-05 17:58:02 +03:00
return ;
// Re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
2021-07-30 16:46:27 +02:00
const QString source = workingDir . pathAppended ( file ) . toString ( ) ;
2011-06-05 17:58:02 +03:00
if ( lineNumber < = 0 )
2014-08-28 16:47:19 +02:00
lineNumber = VcsBaseEditor : : lineNumberOfCurrentEditor ( source ) ;
2011-06-05 17:58:02 +03:00
QString headerSep ( QLatin1String ( " ------------------------------------------------- " ) ) ;
2022-09-21 08:13:29 +02:00
int pos = qMax ( 0 , result . cleanedStdOut ( ) . indexOf ( headerSep ) ) ;
2011-06-05 17:58:02 +03:00
// there are 2 identical headerSep lines - skip them
2022-09-21 08:13:29 +02:00
int dataStart = result . cleanedStdOut ( ) . indexOf ( QLatin1Char ( ' \n ' ) , pos ) + 1 ;
dataStart = result . cleanedStdOut ( ) . indexOf ( QLatin1Char ( ' \n ' ) , dataStart ) + 1 ;
2011-06-05 17:58:02 +03:00
QString res ;
QTextStream stream ( & res , QIODevice : : WriteOnly | QIODevice : : Text ) ;
2022-09-21 08:13:29 +02:00
stream < < result . cleanedStdOut ( ) . mid ( dataStart ) < < headerSep < < QLatin1Char ( ' \n ' )
< < headerSep < < QLatin1Char ( ' \n ' ) < < result . cleanedStdOut ( ) . left ( pos ) ;
2011-06-05 17:58:02 +03:00
const QStringList files = QStringList ( file ) ;
2022-10-06 12:51:50 +02:00
const QString tag = VcsBaseEditor : : editorTag ( AnnotateOutput , workingDir , files ) ;
2014-08-28 16:47:19 +02:00
if ( IEditor * editor = VcsBaseEditor : : locateEditorByTag ( tag ) ) {
2013-07-15 15:14:10 +02:00
editor - > document ( ) - > setContents ( res . toUtf8 ( ) ) ;
2014-08-28 16:47:19 +02:00
VcsBaseEditor : : 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 ) ;
2020-02-07 07:51:20 +01:00
IEditor * newEditor = showOutputInEditor ( title , res , annotateEditorParameters . id , source , codec ) ;
2014-08-28 16:47:19 +02:00
VcsBaseEditor : : tagEditor ( newEditor , tag ) ;
VcsBaseEditor : : gotoLineOfEditor ( newEditor , lineNumber ) ;
2011-06-05 17:58:02 +03:00
}
}
2021-07-29 09:31:09 +02:00
void ClearCasePluginPrivate : : vcsDescribe ( const FilePath & source , const QString & changeNr )
2011-06-05 17:58:02 +03:00
{
2021-07-29 09:31:09 +02:00
const QFileInfo fi = source . toFileInfo ( ) ;
FilePath topLevel ;
const bool manages = managesDirectory ( fi . isDir ( ) ? source : FilePath : : fromString ( fi . absolutePath ( ) ) , & topLevel ) ;
2011-06-05 17:58:02 +03:00
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 ;
2021-07-29 09:31:09 +02:00
QString relPath = QDir : : toNativeSeparators ( QDir ( topLevel . toString ( ) ) . relativeFilePath ( source . toString ( ) ) ) ;
2011-06-05 17:58:02 +03:00
QString id = QString : : fromLatin1 ( " %1@@%2 " ) . arg ( relPath ) . arg ( changeNr ) ;
QStringList args ( QLatin1String ( " describe " ) ) ;
args . push_back ( id ) ;
2021-07-29 09:31:09 +02:00
QTextCodec * codec = VcsBaseEditor : : getCodec ( source . toString ( ) ) ;
2022-10-05 19:08:53 +02:00
const CommandResult result = runCleartool ( topLevel , args , RunFlags : : None , codec ) ;
2022-09-21 08:13:29 +02:00
description = result . cleanedStdOut ( ) ;
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
2022-10-06 12:51:50 +02:00
const QString tag = VcsBaseEditor : : editorTag ( DiffOutput , source , { } , changeNr ) ;
2014-08-28 16:47:19 +02:00
if ( IEditor * editor = VcsBaseEditor : : 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 ) ;
2021-07-29 09:31:09 +02:00
IEditor * newEditor = showOutputInEditor ( title , description , diffEditorParameters . id , source . toString ( ) , codec ) ;
2014-08-28 16:47:19 +02:00
VcsBaseEditor : : tagEditor ( newEditor , tag ) ;
2011-06-05 17:58:02 +03:00
}
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : commitFromEditor ( )
2011-06-05 17:58:02 +03:00
{
m_submitActionTriggered = true ;
2014-08-19 16:15:57 +02:00
QTC_ASSERT ( submitEditor ( ) , return ) ;
2020-09-29 10:24:48 +02:00
EditorManager : : closeDocuments ( { submitEditor ( ) - > document ( ) } ) ;
2011-06-05 17:58:02 +03:00
}
2022-10-05 16:59:07 +02:00
CommandResult ClearCasePluginPrivate : : runCleartoolProc ( const FilePath & workingDir ,
const QStringList & arguments ) const
{
if ( m_settings . ccBinaryPath . isEmpty ( ) )
return CommandResult ( ProcessResult : : StartFailed , Tr : : tr ( " No ClearCase executable specified. " ) ) ;
QtcProcess process ;
Environment env = Environment : : systemEnvironment ( ) ;
VcsBase : : setProcessEnvironment ( & env ) ;
process . setEnvironment ( env ) ;
process . setCommand ( { m_settings . ccBinaryPath , arguments } ) ;
process . setWorkingDirectory ( workingDir ) ;
process . setTimeoutS ( m_settings . timeOutS ) ;
process . runBlocking ( ) ;
return CommandResult ( & process ) ;
2011-06-05 17:58:02 +03:00
}
2022-09-21 08:13:29 +02:00
CommandResult ClearCasePluginPrivate : : runCleartool ( const FilePath & workingDir ,
const QStringList & arguments ,
2022-10-05 19:08:53 +02:00
RunFlags flags ,
2022-10-05 16:21:22 +02:00
QTextCodec * codec ,
int timeoutMultiplier ) const
2011-06-05 17:58:02 +03:00
{
2022-09-21 08:13:29 +02:00
if ( m_settings . ccBinaryPath . isEmpty ( ) )
2022-09-29 14:47:34 +02:00
return CommandResult ( ProcessResult : : StartFailed , Tr : : tr ( " No ClearCase executable specified. " ) ) ;
2011-06-05 17:58:02 +03:00
2022-10-05 16:21:22 +02:00
const int timeoutS = m_settings . timeOutS * timeoutMultiplier ;
2022-10-05 12:38:09 +02:00
return VcsCommand : : runBlocking ( workingDir , Environment : : systemEnvironment ( ) ,
2022-10-05 16:21:22 +02:00
{ m_settings . ccBinaryPath , arguments } , flags , timeoutS , codec ) ;
2011-06-05 17:58:02 +03:00
}
2020-01-23 17:22:05 +01:00
IEditor * ClearCasePluginPrivate : : showOutputInEditor ( const QString & title , const QString & output ,
2022-08-03 06:55:06 +02:00
Id id , const QString & source ,
QTextCodec * codec ) const
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 ( ) < < " ClearCasePlugin::showOutputInEditor " < < title < < id . name ( )
2020-02-07 07:51:20 +01:00
< < " Size= " < < output . size ( ) < < debugCodec ( codec ) ;
2011-06-05 17:58:02 +03:00
QString s = title ;
2014-06-17 14:41:59 +02:00
IEditor * editor = EditorManager : : openEditorWithContents ( id , & s , output . toUtf8 ( ) ) ;
2018-09-20 00:56:28 +03:00
auto e = qobject_cast < ClearCaseEditorWidget * > ( editor - > widget ( ) ) ;
2011-06-05 17:58:02 +03:00
if ( ! e )
2018-09-20 00:56:28 +03:00
return nullptr ;
2020-01-30 12:31:47 +01:00
connect ( e , & VcsBaseEditorWidget : : annotateRevisionRequested ,
this , & ClearCasePluginPrivate : : vcsAnnotateHelper ) ;
2011-06-05 17:58:02 +03:00
e - > setForceReadOnly ( true ) ;
s . replace ( QLatin1Char ( ' ' ) , QLatin1Char ( ' _ ' ) ) ;
2016-01-14 14:45:01 +01:00
e - > textDocument ( ) - > setFallbackSaveAsFileName ( s ) ;
2011-06-05 17:58:02 +03:00
if ( ! source . isEmpty ( ) )
e - > setSource ( source ) ;
if ( codec )
e - > setCodec ( codec ) ;
2013-12-19 10:22:02 +01:00
return editor ;
2011-06-05 17:58:02 +03:00
}
2020-01-23 17:22:05 +01:00
const ClearCaseSettings & ClearCasePluginPrivate : : settings ( ) const
2011-06-05 17:58:02 +03:00
{
return m_settings ;
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : setSettings ( const ClearCaseSettings & s )
2011-06-05 17:58:02 +03:00
{
if ( s ! = m_settings ) {
m_settings = s ;
2013-08-30 09:22:42 +02:00
m_settings . toSettings ( ICore : : settings ( ) ) ;
2020-01-30 12:31:47 +01:00
emit configurationChanged ( ) ;
2011-06-05 17:58:02 +03:00
}
}
2020-01-23 17:22:05 +01:00
ClearCasePluginPrivate * ClearCasePluginPrivate : : instance ( )
2011-06-05 17:58:02 +03:00
{
2020-01-23 17:22:05 +01:00
QTC_ASSERT ( dd , return dd ) ;
return dd ;
2011-06-05 17:58:02 +03:00
}
2021-07-30 16:46:27 +02:00
bool ClearCasePluginPrivate : : vcsOpen ( const FilePath & workingDir , const QString & fileName )
2011-06-05 17:58:02 +03:00
{
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 ;
2021-07-30 16:46:27 +02:00
QFileInfo fi ( workingDir . toString ( ) , fileName ) ;
FilePath topLevel = currentState ( ) . topLevel ( ) ;
2011-06-05 17:58:02 +03:00
QString absPath = fi . absoluteFilePath ( ) ;
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 ) )
2022-08-03 06:55:06 +02:00
runAsync ( sync , QStringList ( absPath ) ) . waitForFinished ( ) ;
2013-12-05 13:30:20 +01:00
if ( vcsStatus ( absPath ) . status = = FileStatus : : CheckedOut ) {
2022-09-29 14:47:34 +02:00
QMessageBox : : information ( ICore : : dialogParent ( ) , Tr : : tr ( " ClearCase Checkout " ) ,
Tr : : tr ( " File is already checked out. " ) ) ;
2011-06-05 17:58:02 +03:00
return true ;
}
2014-09-08 11:07:09 +03:00
2021-07-30 16:46:27 +02:00
const QString relFile = QDir ( topLevel . toString ( ) ) . relativeFilePath ( absPath ) ;
2014-09-08 11:07:09 +03:00
const QString file = QDir : : toNativeSeparators ( relFile ) ;
const QString title = QString : : fromLatin1 ( " Checkout %1 " ) . arg ( file ) ;
2015-01-02 16:13:57 +01:00
CheckOutDialog coDialog ( title , m_viewData . isUcm , ! m_settings . noComment ) ;
2014-09-08 11:07:09 +03:00
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 ( ) ;
2022-09-21 08:13:29 +02:00
if ( coDialog . exec ( ) ! = QDialog : : Accepted )
return true ;
2012-09-24 11:39:34 +02:00
2022-09-21 08:13:29 +02:00
if ( m_viewData . isUcm & & ! vcsSetActivity ( topLevel , title , coDialog . activity ( ) ) )
return false ;
2015-01-02 16:13:57 +01:00
2022-09-21 08:13:29 +02:00
FileChangeBlocker fcb ( FilePath : : fromString ( absPath ) ) ;
QStringList args ( QLatin1String ( " checkout " ) ) ;
2011-06-05 17:58:02 +03:00
2022-09-21 08:13:29 +02:00
const QString comment = coDialog . comment ( ) ;
if ( m_settings . noComment | | comment . isEmpty ( ) )
args < < QLatin1String ( " -nc " ) ;
else
args < < QLatin1String ( " -c " ) < < comment ;
args < < QLatin1String ( " -query " ) ;
const bool reserved = coDialog . isReserved ( ) ;
const bool unreserved = ! reserved | | coDialog . isUnreserved ( ) ;
if ( reserved )
args < < QLatin1String ( " -reserved " ) ;
if ( unreserved )
args < < QLatin1String ( " -unreserved " ) ;
if ( coDialog . isPreserveTime ( ) )
args < < QLatin1String ( " -ptime " ) ;
if ( isHijacked ) {
if ( Constants : : debug )
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
2022-09-21 08:13:29 +02: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 ;
2022-10-05 16:21:22 +02:00
CommandResult result = runCleartool ( topLevel , args ,
2022-10-05 19:08:53 +02:00
RunFlags : : ShowStdOut | RunFlags : : SuppressStdErr ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) ! = ProcessResult : : FinishedWithSuccess ) {
if ( result . cleanedStdErr ( ) . contains ( QLatin1String ( " Versions other than the selected version " ) ) ) {
VersionSelector selector ( file , result . cleanedStdErr ( ) ) ;
if ( selector . exec ( ) = = QDialog : : Accepted ) {
if ( selector . isUpdate ( ) )
ccUpdate ( workingDir , QStringList ( file ) ) ;
else
args . removeOne ( QLatin1String ( " -query " ) ) ;
2022-10-05 19:08:53 +02:00
result = runCleartool ( topLevel , args , RunFlags : : ShowStdOut ) ;
2022-09-21 08:13:29 +02:00
}
} else {
VcsOutputWindow : : append ( result . cleanedStdOut ( ) ) ;
VcsOutputWindow : : appendError ( result . cleanedStdErr ( ) ) ;
2013-04-18 22:25:23 +02:00
}
2022-09-21 08:13:29 +02:00
}
2015-01-03 21:44:28 +02:00
2022-09-21 08:13:29 +02:00
const bool success = result . result ( ) = = ProcessResult : : FinishedWithSuccess ;
if ( success & & isHijacked & & coDialog . isUseHijacked ( ) ) { // rename back
QFile : : remove ( absPath ) ;
QFile : : rename ( absPath + QLatin1String ( " .hijack " ) , absPath ) ;
}
2015-01-03 21:44:28 +02:00
2022-09-21 08:13:29 +02:00
if ( ( success | | result . cleanedStdErr ( ) . contains ( QLatin1String ( " already checked out " ) ) )
& & ! m_settings . disableIndexer ) {
setStatus ( absPath , FileStatus : : CheckedOut ) ;
2011-06-05 17:58:02 +03:00
}
2022-09-21 08:13:29 +02:00
if ( DocumentModel : : Entry * e = DocumentModel : : entryForFilePath ( FilePath : : fromString ( absPath ) ) )
e - > document - > checkPermissions ( ) ;
return success ;
2011-06-05 17:58:02 +03:00
}
2021-07-30 16:46:27 +02:00
bool ClearCasePluginPrivate : : vcsSetActivity ( const FilePath & workingDir , const QString & title , const QString & activity )
2011-06-05 17:58:02 +03:00
{
QStringList args ;
args < < QLatin1String ( " setactivity " ) < < activity ;
2022-10-05 19:08:53 +02:00
const CommandResult result = runCleartool ( workingDir , args , RunFlags : : ShowStdOut ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) ! = ProcessResult : : FinishedWithSuccess ) {
2022-09-29 14:47:34 +02:00
QMessageBox : : warning ( ICore : : dialogParent ( ) , title , Tr : : tr ( " Set current activity failed: %1 " )
2022-09-21 08:13:29 +02:00
. arg ( result . exitMessage ( ) ) , QMessageBox : : Ok ) ;
2011-06-05 17:58:02 +03:00
return false ;
}
m_activity = activity ;
return true ;
}
// files are received using native separators
2021-07-30 16:46:27 +02:00
bool ClearCasePluginPrivate : : vcsCheckIn ( const FilePath & messageFile , const QStringList & files , const QString & activity ,
2011-06-05 17:58:02 +03:00
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 ( " ; " ) ) ) ;
2018-11-04 22:49:24 +01:00
using FCBPointer = QSharedPointer < FileChangeBlocker > ;
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 ;
2017-09-15 17:36:26 +02:00
QString message ;
2021-07-30 16:46:27 +02:00
QFile msgFile ( messageFile . toString ( ) ) ;
2017-09-15 17:36:26 +02:00
if ( msgFile . open ( QFile : : ReadOnly | QFile : : Text ) ) {
message = QString : : fromLocal8Bit ( msgFile . readAll ( ) . trimmed ( ) ) ;
msgFile . close ( ) ;
}
2011-06-05 17:58:02 +03:00
QStringList args ;
args < < QLatin1String ( " checkin " ) ;
if ( message . isEmpty ( ) )
args < < QLatin1String ( " -nc " ) ;
else
2021-07-30 16:46:27 +02:00
args < < QLatin1String ( " -cfile " ) < < messageFile . toString ( ) ;
2011-06-05 17:58:02 +03:00
if ( isIdentical )
args < < QLatin1String ( " -identical " ) ;
if ( isPreserve )
args < < QLatin1String ( " -ptime " ) ;
args < < files ;
QList < FCBPointer > blockers ;
2022-09-21 08:13:29 +02:00
for ( const QString & fileName : files ) {
2021-06-09 09:59:37 +02:00
FCBPointer fcb ( new FileChangeBlocker (
2021-07-30 16:46:27 +02:00
FilePath : : fromString ( QFileInfo ( m_checkInView . toString ( ) , fileName ) . canonicalFilePath ( ) ) ) ) ;
2011-06-05 17:58:02 +03:00
blockers . append ( fcb ) ;
}
2022-10-05 19:08:53 +02:00
const CommandResult result = runCleartool ( m_checkInView , args , RunFlags : : ShowStdOut , nullptr ,
2022-10-05 16:21:22 +02:00
10 ) ;
2020-06-23 18:36:26 +02:00
const QRegularExpression checkedIn ( " Checked in \\ \" ([^ \" ]*) \ \ \ " " ) ;
2022-09-21 08:13:29 +02:00
QRegularExpressionMatch match = checkedIn . match ( result . cleanedStdOut ( ) ) ;
2011-06-05 17:58:02 +03:00
bool anySucceeded = false ;
2020-06-23 18:36:26 +02:00
int offset = match . capturedStart ( ) ;
while ( match . hasMatch ( ) ) {
QString file = match . captured ( 1 ) ;
2021-07-30 16:46:27 +02:00
QFileInfo fi ( m_checkInView . toString ( ) , file ) ;
2013-04-18 22:25:23 +02:00
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 ) ;
2020-01-30 12:31:47 +01:00
emit filesChanged ( files ) ;
2011-06-05 17:58:02 +03:00
anySucceeded = true ;
2022-09-21 08:13:29 +02:00
match = checkedIn . match ( result . cleanedStdOut ( ) , offset + 12 ) ;
2020-06-23 18:36:26 +02:00
offset = match . capturedStart ( ) ;
2011-06-05 17:58:02 +03:00
}
return anySucceeded ;
}
2021-07-30 16:46:27 +02:00
bool ClearCasePluginPrivate : : ccFileOp ( const FilePath & workingDir , const QString & title , const QStringList & opArgs ,
2011-06-05 17:58:02 +03:00
const QString & fileName , const QString & file2 )
{
const QString file = QDir : : toNativeSeparators ( fileName ) ;
bool noCheckout = false ;
2018-09-20 00:56:28 +03:00
ActivitySelector * actSelector = nullptr ;
2011-06-05 17:58:02 +03:00
QDialog fileOpDlg ;
fileOpDlg . setWindowTitle ( title ) ;
2015-01-22 13:52:14 +01:00
auto 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
2022-09-29 14:47:34 +02:00
auto commentLabel = new QLabel ( Tr : : tr ( " Enter &comment: " ) ) ;
2011-06-05 17:58:02 +03:00
verticalLayout - > addWidget ( commentLabel ) ;
2015-01-22 13:52:14 +01:00
auto commentEdit = new QTextEdit ;
2011-06-05 17:58:02 +03:00
verticalLayout - > addWidget ( commentEdit ) ;
2015-01-22 13:52:14 +01:00
auto buttonBox = new QDialogButtonBox ;
2011-06-05 17:58:02 +03:00
buttonBox - > setStandardButtons ( QDialogButtonBox : : Cancel | QDialogButtonBox : : Ok ) ;
verticalLayout - > addWidget ( buttonBox ) ;
commentLabel - > setBuddy ( commentEdit ) ;
2015-11-19 16:54:28 +01:00
connect ( buttonBox , & QDialogButtonBox : : accepted , & fileOpDlg , & QDialog : : accept ) ;
connect ( buttonBox , & QDialogButtonBox : : rejected , & fileOpDlg , & QDialog : : reject ) ;
2011-06-05 17:58:02 +03:00
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
2021-07-30 16:46:27 +02:00
QString dirName = QDir : : toNativeSeparators ( QFileInfo ( workingDir . toString ( ) , fileName ) . absolutePath ( ) ) ;
2011-06-05 17:58:02 +03:00
QStringList commentArg ;
if ( comment . isEmpty ( ) )
commentArg < < QLatin1String ( " -nc " ) ;
else
commentArg < < QLatin1String ( " -c " ) < < comment ;
// check out directory
QStringList args ;
args < < QLatin1String ( " checkout " ) < < commentArg < < dirName ;
2022-10-05 19:08:53 +02:00
const CommandResult coResult = runCleartool ( workingDir , args , RunFlags : : ShowStdOut ) ;
2022-09-21 08:13:29 +02:00
if ( coResult . result ( ) ! = ProcessResult : : FinishedWithSuccess ) {
if ( coResult . cleanedStdErr ( ) . 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 ) ;
2022-10-05 19:08:53 +02:00
const CommandResult opResult = runCleartool ( workingDir , args , RunFlags : : ShowStdOut ) ;
2022-09-21 08:13:29 +02:00
if ( opResult . result ( ) ! = ProcessResult : : FinishedWithSuccess ) {
2011-06-05 17:58:02 +03:00
// on failure - undo checkout for the directory
if ( ! noCheckout )
vcsUndoCheckOut ( workingDir , dirName , false ) ;
return false ;
}
2022-09-21 08:13:29 +02:00
if ( noCheckout )
return true ;
// check in the directory
args . clear ( ) ;
args < < QLatin1String ( " checkin " ) < < commentArg < < dirName ;
2022-10-05 19:08:53 +02:00
const CommandResult ciResult = runCleartool ( workingDir , args , RunFlags : : ShowStdOut ) ;
2022-09-21 08:13:29 +02:00
return ciResult . result ( ) = = ProcessResult : : FinishedWithSuccess ;
2011-06-05 17:58:02 +03:00
}
2012-09-17 22:26:23 +02:00
static QString baseName ( const QString & fileName )
{
return fileName . mid ( fileName . lastIndexOf ( QLatin1Char ( ' / ' ) ) + 1 ) ;
}
2021-07-30 16:46:27 +02:00
bool ClearCasePluginPrivate : : vcsAdd ( const FilePath & workingDir , const QString & fileName )
2011-06-05 17:58:02 +03:00
{
2022-09-29 14:47:34 +02:00
return ccFileOp ( workingDir , Tr : : tr ( " ClearCase Add File %1 " ) . arg ( baseName ( fileName ) ) ,
2017-02-22 15:09:35 +01:00
QStringList ( { " mkelem " , " -ci " } ) , fileName ) ;
2011-06-05 17:58:02 +03:00
}
2021-07-30 16:46:27 +02:00
bool ClearCasePluginPrivate : : vcsDelete ( const FilePath & workingDir , const QString & fileName )
2011-06-05 17:58:02 +03:00
{
2022-09-29 14:47:34 +02:00
const QString title ( Tr : : tr ( " ClearCase Remove Element %1 " ) . arg ( baseName ( fileName ) ) ) ;
if ( QMessageBox : : warning ( ICore : : dialogParent ( ) , title , Tr : : tr ( " This operation is irreversible. Are you sure? " ) ,
2011-06-05 17:58:02 +03:00
QMessageBox : : Yes | QMessageBox : : No ) = = QMessageBox : : No )
return true ;
2022-09-29 14:47:34 +02:00
return ccFileOp ( workingDir , Tr : : tr ( " ClearCase Remove File %1 " ) . arg ( baseName ( fileName ) ) ,
2017-02-22 15:09:35 +01:00
QStringList ( { " rmname " , " -force " } ) , fileName ) ;
2011-06-05 17:58:02 +03:00
}
2021-07-30 16:46:27 +02:00
bool ClearCasePluginPrivate : : vcsMove ( const FilePath & workingDir , const QString & from , const QString & to )
2011-06-05 17:58:02 +03:00
{
2022-09-29 14:47:34 +02:00
return ccFileOp ( workingDir , Tr : : tr ( " ClearCase Rename File %1 -> %2 " )
2012-09-17 22:26:23 +02:00
. arg ( baseName ( from ) ) . arg ( baseName ( to ) ) ,
2017-02-07 16:59:21 +01:00
QStringList ( " move " ) , from , to ) ;
2011-06-05 17:58:02 +03:00
}
2013-04-18 22:25:23 +02:00
///
/// Check if the directory is managed under ClearCase control.
///
2021-07-29 09:31:09 +02:00
bool ClearCasePluginPrivate : : managesDirectory ( const FilePath & directory , FilePath * topLevel /* = 0 */ ) const
2011-06-05 17:58:02 +03:00
{
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
2021-07-30 16:46:27 +02:00
QString topLevelFound = m_fakeClearTool ? directory . toString ( ) : findTopLevel ( directory ) ;
2013-11-20 11:59:34 +01:00
# else
2021-07-30 16:46:27 +02:00
QString topLevelFound = findTopLevel ( directory ) ;
2013-11-20 11:59:34 +01:00
# endif
2011-06-05 17:58:02 +03:00
if ( topLevel )
2021-07-29 09:31:09 +02:00
* topLevel = FilePath : : fromString ( topLevelFound ) ;
2011-06-05 17:58:02 +03:00
return ! topLevelFound . isEmpty ( ) ;
}
2020-01-23 17:22:05 +01:00
QString ClearCasePluginPrivate : : ccGetCurrentActivity ( ) const
2011-06-05 17:58:02 +03:00
{
2022-10-05 17:22:09 +02:00
return runCleartoolProc ( currentState ( ) . topLevel ( ) , { " lsactivity " , " -cact " , " -fmt " , " %n " } )
. cleanedStdOut ( ) ;
2011-06-05 17:58:02 +03:00
}
2020-01-23 17:22:05 +01:00
QList < QStringPair > ClearCasePluginPrivate : : ccGetActivities ( ) const
2011-06-05 17:58:02 +03:00
{
QList < QStringPair > result ;
// Maintain latest deliver and rebase activities only
QStringPair rebaseAct ;
QStringPair deliverAct ;
// Retrieve all activities
2022-10-05 17:22:09 +02:00
const QString response = runCleartoolProc ( currentState ( ) . topLevel ( ) ,
{ " lsactivity " , " -fmt " , " %n \\ t%[headline]p \\ n " } ) . cleanedStdOut ( ) ;
2022-09-21 08:13:29 +02:00
const QStringList acts = response . split ( QLatin1Char ( ' \n ' ) , Qt : : SkipEmptyParts ) ;
for ( 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
}
}
2014-06-16 18:25:52 +04:00
Utils : : sort ( 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 ;
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : refreshActivities ( )
2011-06-05 17:58:02 +03:00
{
2020-02-06 18:51:46 +01:00
QMutexLocker locker ( & m_activityMutex ) ;
2011-06-05 17:58:02 +03:00
m_activity = ccGetCurrentActivity ( ) ;
m_activities = ccGetActivities ( ) ;
}
2020-02-06 18:51:46 +01:00
QList < QStringPair > ClearCasePluginPrivate : : activities ( int * current )
2011-06-05 17:58:02 +03:00
{
QList < QStringPair > activitiesList ;
QString curActivity ;
2014-08-28 16:47:19 +02:00
const VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
if ( state . topLevel ( ) = = state . currentProjectTopLevel ( ) ) {
2020-02-06 18:51:46 +01: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 ;
}
2020-01-23 17:22:05 +01:00
bool ClearCasePluginPrivate : : newActivity ( )
2011-06-05 17:58:02 +03:00
{
2021-07-30 16:46:27 +02:00
FilePath workingDir = currentState ( ) . topLevel ( ) ;
2011-06-05 17:58:02 +03:00
QStringList args ;
args < < QLatin1String ( " mkactivity " ) < < QLatin1String ( " -f " ) ;
if ( ! m_settings . autoAssignActivityName ) {
2022-09-29 14:47:34 +02:00
QString headline = QInputDialog : : getText ( ICore : : dialogParent ( ) , Tr : : tr ( " Activity Headline " ) ,
Tr : : tr ( " Enter activity headline " ) ) ;
2011-06-05 17:58:02 +03:00
if ( headline . isEmpty ( ) )
return false ;
args < < QLatin1String ( " -headline " ) < < headline ;
}
2022-10-05 16:21:22 +02:00
const CommandResult result = runCleartool ( workingDir , args ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) ! = ProcessResult : : FinishedWithSuccess )
return false ;
2011-06-05 17:58:02 +03:00
2022-09-21 08:13:29 +02:00
refreshActivities ( ) ;
return true ;
2011-06-05 17:58:02 +03:00
}
2012-09-24 11:39:34 +02:00
// check if the view is UCM
2021-07-30 16:46:27 +02:00
bool ClearCasePluginPrivate : : ccCheckUcm ( const QString & viewname , const FilePath & workingDir ) const
2012-09-24 11:39:34 +02:00
{
2022-10-05 17:22:09 +02:00
const QString catcsData = runCleartoolProc ( workingDir ,
{ " catcs " , " -tag " , viewname } ) . cleanedStdOut ( ) ;
2012-09-24 11:39:34 +02:00
// check output for the word "ucm"
2020-06-23 18:36:26 +02:00
return catcsData . indexOf ( QRegularExpression ( " (^| \\ n)ucm \\ n " ) ) ! = - 1 ;
2012-09-24 11:39:34 +02:00
}
2021-07-29 09:31:09 +02:00
bool ClearCasePluginPrivate : : managesFile ( const FilePath & workingDirectory , const QString & fileName ) const
2013-10-02 00:18:39 +03:00
{
2021-07-29 09:31:09 +02:00
QString absFile = QFileInfo ( QDir ( workingDirectory . toString ( ) ) , 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
}
2021-07-30 16:46:27 +02:00
ViewData ClearCasePluginPrivate : : ccGetView ( const FilePath & workingDir ) const
2011-06-05 17:58:02 +03:00
{
2021-07-30 16:46:27 +02:00
static QHash < FilePath , ViewData > viewCache ;
2012-11-29 22:41:18 +02:00
bool inCache = viewCache . contains ( workingDir ) ;
ViewData & res = viewCache [ workingDir ] ;
if ( ! inCache ) {
2022-10-05 17:22:09 +02:00
const QString data = runCleartoolProc ( workingDir , { " lsview " , " -cview " } ) . cleanedStdOut ( ) ;
2012-11-29 22:41:18 +02:00
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
}
2021-07-30 16:46:27 +02:00
QString ClearCasePluginPrivate : : ccGetComment ( const FilePath & workingDir , const QString & fileName ) const
2014-09-15 13:06:13 +03:00
{
2022-10-05 17:22:09 +02:00
return runCleartoolProc ( workingDir , { " describe " , " -fmt " , " %c " , fileName } ) . cleanedStdOut ( ) ;
2014-09-15 13:06:13 +03:00
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : updateStreamAndView ( )
2011-06-05 17:58:02 +03:00
{
2022-10-05 17:22:09 +02:00
const QString result = runCleartoolProc ( m_topLevel ,
{ " lsstream " , " -fmt " , " %n \\ t%[def_deliver_tgt]Xp " } ) . cleanedStdOut ( ) ;
const int tabPos = result . indexOf ( QLatin1Char ( ' \t ' ) ) ;
m_stream = result . left ( tabPos ) ;
2020-06-23 18:36:26 +02:00
const QRegularExpression intStreamExp ( " stream:([^@]*) " ) ;
2022-10-05 17:22:09 +02:00
const QRegularExpressionMatch match = intStreamExp . match ( result . mid ( tabPos + 1 ) ) ;
2020-06-23 18:36:26 +02:00
if ( match . hasMatch ( ) )
m_intStream = match . captured ( 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
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : 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-09-03 15:18:37 +02:00
ProgressManager : : cancelTasks ( ClearCase : : Constants : : TASK_INDEX ) ;
2011-06-05 17:58:02 +03:00
if ( project ) {
2021-07-30 16:46:27 +02:00
FilePath projDir = project - > projectDirectory ( ) ;
2011-06-05 17:58:02 +03:00
QString topLevel = findTopLevel ( projDir ) ;
2021-07-30 16:46:27 +02:00
m_topLevel = FilePath : : fromString ( topLevel ) ;
2011-06-05 17:58:02 +03:00
if ( topLevel . isEmpty ( ) )
return ;
2016-05-29 00:14:20 +03:00
connect ( qApp , & QApplication : : applicationStateChanged ,
this , [ this ] ( Qt : : ApplicationState state ) {
if ( state = = Qt : : ApplicationActive )
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
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : tasksFinished ( 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 ) ;
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : updateIndex ( )
2011-06-05 17:58:02 +03:00
{
QTC_ASSERT ( currentState ( ) . hasTopLevel ( ) , return ) ;
2013-09-03 15:18:37 +02:00
ProgressManager : : cancelTasks ( ClearCase : : Constants : : TASK_INDEX ) ;
2015-02-16 15:14:21 +01:00
Project * project = SessionManager : : startupProject ( ) ;
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 ( ) ;
2022-08-03 06:55:06 +02:00
QFuture < void > result = runAsync ( sync , transform ( project - > files ( Project : : SourceFiles ) , & FilePath : : toString ) ) ;
2011-06-05 17:58:02 +03:00
if ( ! m_settings . disableIndexer )
2022-09-29 14:47:34 +02:00
ProgressManager : : addTask ( result , Tr : : tr ( " Updating ClearCase Index " ) , 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
*/
2020-01-23 17:22:05 +01:00
QString ClearCasePluginPrivate : : getFile ( const QString & nativeFile , const QString & prefix )
2011-06-05 17:58:02 +03:00
{
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 ) ) {
2021-07-30 16:46:27 +02:00
bool res = QFile : : copy ( QDir ( m_topLevel . toString ( ) ) . absoluteFilePath ( file ) , tempFile ) ;
2011-06-05 17:58:02 +03:00
return res ? tempFile : QString ( ) ;
}
2022-10-05 16:59:07 +02:00
const CommandResult result = runCleartoolProc ( m_topLevel , { " get " , " -to " , tempFile , nativeFile } ) ;
2022-09-21 08:13:29 +02:00
if ( result . result ( ) ! = ProcessResult : : FinishedWithSuccess )
return { } ;
2011-06-05 17:58:02 +03:00
QFile : : setPermissions ( tempFile , QFile : : ReadOwner | QFile : : ReadUser |
QFile : : WriteOwner | QFile : : WriteUser ) ;
return tempFile ;
}
// runs external (GNU) diff, and returns the stdout result
2020-01-23 17:22:05 +01:00
QString ClearCasePluginPrivate : : diffExternal ( QString file1 , QString file2 , bool keep )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
QTextCodec * codec = VcsBaseEditor : : getCodec ( file1 ) ;
2011-06-05 17:58:02 +03:00
// 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 ;
}
2015-04-10 14:44:17 +02:00
const QString diffResponse = runExtDiff ( m_topLevel , args , m_settings . timeOutS , codec ) ;
2011-06-05 17:58:02 +03:00
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)
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : diffGraphical ( const QString & file1 , const QString & file2 )
2011-06-05 17:58:02 +03:00
{
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 ;
2022-08-02 17:39:00 +02:00
QtcProcess : : startDetached ( { m_settings . ccBinaryPath , args } , m_topLevel ) ;
2011-06-05 17:58:02 +03:00
}
2021-07-30 16:46:27 +02:00
QString ClearCasePluginPrivate : : runExtDiff ( const FilePath & workingDir , const QStringList & arguments ,
int timeOutS , QTextCodec * outputCodec )
2011-06-05 17:58:02 +03:00
{
2019-07-23 10:17:57 +02:00
CommandLine diff ( " diff " ) ;
2020-07-21 10:19:36 +02:00
diff . addArgs ( m_settings . diffArgs . split ( ' ' , Qt : : SkipEmptyParts ) ) ;
2019-06-06 16:27:55 +02:00
diff . addArgs ( arguments ) ;
2011-06-05 17:58:02 +03:00
2021-06-22 04:33:47 +02:00
QtcProcess process ;
2016-04-29 16:52:58 +02:00
process . setTimeoutS ( timeOutS ) ;
2011-06-05 17:58:02 +03:00
process . setWorkingDirectory ( workingDir ) ;
2016-04-29 16:52:58 +02:00
process . setCodec ( outputCodec ? outputCodec : QTextCodec : : codecForName ( " UTF-8 " ) ) ;
2021-05-17 12:02:42 +02:00
process . setCommand ( diff ) ;
2022-03-02 04:12:25 +01:00
process . runBlocking ( EventLoopMode : : On ) ;
if ( process . result ( ) ! = ProcessResult : : FinishedWithSuccess )
2022-09-21 08:13:29 +02:00
return { } ;
2021-05-12 14:25:50 +02:00
return process . allOutput ( ) ;
2011-06-05 17:58:02 +03:00
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : syncSlot ( )
2011-06-05 17:58:02 +03:00
{
2014-08-28 16:47:19 +02:00
VcsBasePluginState state = currentState ( ) ;
2011-06-05 17:58:02 +03:00
if ( ! state . hasProject ( ) | | ! state . hasTopLevel ( ) )
return ;
2021-07-30 16:46:27 +02:00
FilePath topLevel = state . topLevel ( ) ;
2011-06-05 17:58:02 +03:00
if ( topLevel ! = state . currentProjectTopLevel ( ) )
return ;
2022-08-03 06:55:06 +02:00
runAsync ( sync , QStringList ( ) ) ;
2011-06-05 17:58:02 +03:00
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : closing ( )
2011-06-05 17:58:02 +03:00
{
// prevent syncSlot from being called on shutdown
2013-09-03 15:18:37 +02:00
ProgressManager : : cancelTasks ( ClearCase : : Constants : : TASK_INDEX ) ;
2018-09-20 00:56:28 +03:00
disconnect ( qApp , & QApplication : : applicationStateChanged , nullptr , nullptr ) ;
2011-06-05 17:58:02 +03:00
}
2020-01-23 17:22:05 +01:00
void ClearCasePluginPrivate : : sync ( QFutureInterface < void > & future , QStringList files )
2011-06-05 17:58:02 +03:00
{
2020-01-23 17:22:05 +01:00
ClearCasePluginPrivate * plugin = ClearCasePluginPrivate : : instance ( ) ;
2020-02-06 17:49:35 +01:00
ClearCaseSync ccSync ( plugin - > m_statusMap ) ;
2020-01-23 17:22:05 +01:00
connect ( & ccSync , & ClearCaseSync : : updateStreamAndView , plugin , & ClearCasePluginPrivate : : updateStreamAndView ) ;
2013-04-18 22:25:23 +02:00
ccSync . run ( future , files ) ;
2011-06-05 17:58:02 +03:00
}
2020-01-30 12:31:47 +01:00
QString ClearCasePluginPrivate : : displayName ( ) const
{
return QLatin1String ( " ClearCase " ) ;
}
2022-08-03 06:55:06 +02:00
Id ClearCasePluginPrivate : : id ( ) const
2020-01-30 12:31:47 +01:00
{
return Constants : : VCS_ID_CLEARCASE ;
}
2021-07-29 09:31:09 +02:00
bool ClearCasePluginPrivate : : isVcsFileOrDirectory ( const FilePath & filePath ) const
2020-01-30 12:31:47 +01:00
{
2021-07-29 09:31:09 +02:00
Q_UNUSED ( filePath )
2020-01-30 12:31:47 +01:00
return false ; // ClearCase has no files/directories littering the sources
}
bool ClearCasePluginPrivate : : isConfigured ( ) const
{
# ifdef WITH_TESTS
if ( m_fakeClearTool )
return true ;
# endif
2022-08-03 06:19:44 +02:00
return m_settings . ccBinaryPath . isExecutableFile ( ) ;
2020-01-30 12:31:47 +01:00
}
bool ClearCasePluginPrivate : : supportsOperation ( Operation operation ) const
{
bool rc = isConfigured ( ) ;
switch ( operation ) {
case AddOperation :
case DeleteOperation :
case MoveOperation :
case AnnotateOperation :
break ;
case CreateRepositoryOperation :
case SnapshotOperations :
2022-08-03 06:55:06 +02:00
case IVersionControl : : InitialCheckoutOperation :
2020-01-30 12:31:47 +01:00
rc = false ;
break ;
}
return rc ;
}
2022-08-03 06:55:06 +02:00
IVersionControl : : OpenSupportMode ClearCasePluginPrivate : : openSupportMode ( const FilePath & filePath ) const
2020-01-30 12:31:47 +01:00
{
if ( isDynamic ( ) ) {
// NB! Has to use managesFile() and not vcsStatus() since the index can only be guaranteed
// to be up to date if the file has been explicitly opened, which is not the case when
// doing a search and replace as a part of a refactoring.
2021-07-29 09:31:09 +02:00
if ( managesFile ( FilePath : : fromString ( filePath . toFileInfo ( ) . absolutePath ( ) ) , filePath . toString ( ) ) ) {
2020-01-30 12:31:47 +01:00
// Checkout is the only option for managed files in dynamic views
return IVersionControl : : OpenMandatory ;
} else {
// Not managed files can be edited without noticing the VCS
return IVersionControl : : NoOpen ;
}
} else {
return IVersionControl : : OpenOptional ; // Snapshot views supports Hijack and check out
}
}
2021-07-29 09:31:09 +02:00
bool ClearCasePluginPrivate : : vcsOpen ( const FilePath & filePath )
2020-01-30 12:31:47 +01:00
{
2021-07-30 16:46:27 +02:00
return vcsOpen ( filePath . parentDir ( ) . absolutePath ( ) , filePath . fileName ( ) ) ;
2020-01-30 12:31:47 +01:00
}
2022-08-03 06:55:06 +02:00
IVersionControl : : SettingsFlags ClearCasePluginPrivate : : settingsFlags ( ) const
2020-01-30 12:31:47 +01:00
{
SettingsFlags rc ;
if ( m_settings . autoCheckOut )
rc | = AutoOpen ;
return rc ;
}
2021-07-29 09:31:09 +02:00
bool ClearCasePluginPrivate : : vcsAdd ( const FilePath & filePath )
2020-01-30 12:31:47 +01:00
{
2021-07-30 16:46:27 +02:00
return vcsAdd ( filePath . parentDir ( ) . absolutePath ( ) , filePath . fileName ( ) ) ;
2020-01-30 12:31:47 +01:00
}
2021-07-29 09:31:09 +02:00
bool ClearCasePluginPrivate : : vcsDelete ( const FilePath & filePath )
2020-01-30 12:31:47 +01:00
{
2021-07-30 16:46:27 +02:00
return vcsDelete ( filePath . parentDir ( ) . absoluteFilePath ( ) , filePath . fileName ( ) ) ;
2020-01-30 12:31:47 +01:00
}
2021-07-29 09:31:09 +02:00
bool ClearCasePluginPrivate : : vcsMove ( const FilePath & from , const FilePath & to )
2020-01-30 12:31:47 +01:00
{
2021-07-30 16:46:27 +02:00
return vcsMove ( from . parentDir ( ) . absolutePath ( ) , from . fileName ( ) , to . fileName ( ) ) ;
2020-01-30 12:31:47 +01:00
}
2021-07-29 09:31:09 +02:00
void ClearCasePluginPrivate : : vcsAnnotate ( const FilePath & filePath , int line )
2020-01-30 12:31:47 +01:00
{
2021-07-30 16:46:27 +02:00
vcsAnnotateHelper ( filePath . parentDir ( ) . absolutePath ( ) , filePath . fileName ( ) , QString ( ) , line ) ;
2020-01-30 12:31:47 +01:00
}
QString ClearCasePluginPrivate : : vcsOpenText ( ) const
{
2022-09-29 14:47:34 +02:00
return Tr : : tr ( " Check &Out " ) ;
2020-01-30 12:31:47 +01:00
}
QString ClearCasePluginPrivate : : vcsMakeWritableText ( ) const
{
if ( isDynamic ( ) )
2022-09-21 08:13:29 +02:00
return { } ;
2022-09-29 14:47:34 +02:00
return Tr : : tr ( " &Hijack " ) ;
2020-01-30 12:31:47 +01:00
}
2021-07-29 09:31:09 +02:00
QString ClearCasePluginPrivate : : vcsTopic ( const FilePath & directory )
2020-01-30 12:31:47 +01:00
{
2021-07-30 16:46:27 +02:00
return ccGetView ( directory ) . name ;
2020-01-30 12:31:47 +01:00
}
2021-07-29 09:31:09 +02:00
bool ClearCasePluginPrivate : : vcsCreateRepository ( const FilePath & )
2020-01-30 12:31:47 +01:00
{
return false ;
}
2020-02-06 17:49:35 +01:00
// ClearCasePlugin
ClearCasePlugin : : ~ ClearCasePlugin ( )
{
delete dd ;
dd = nullptr ;
}
bool ClearCasePlugin : : newActivity ( )
{
return dd - > newActivity ( ) ;
}
const QList < QStringPair > ClearCasePlugin : : activities ( int * current )
{
return dd - > activities ( current ) ;
}
QStringList ClearCasePlugin : : ccGetActiveVobs ( )
{
return dd - > ccGetActiveVobs ( ) ;
}
void ClearCasePlugin : : refreshActivities ( )
{
dd - > refreshActivities ( ) ;
}
const ViewData ClearCasePlugin : : viewData ( )
{
return dd - > m_viewData ;
}
void ClearCasePlugin : : setStatus ( const QString & file , FileStatus : : Status status , bool update )
{
dd - > setStatus ( file , status , update ) ;
}
const ClearCaseSettings & ClearCasePlugin : : settings ( )
{
return dd - > m_settings ;
}
void ClearCasePlugin : : setSettings ( const ClearCaseSettings & s )
{
dd - > setSettings ( s ) ;
}
QSharedPointer < StatusMap > ClearCasePlugin : : statusMap ( )
{
return dd - > m_statusMap ;
}
2013-01-19 23:19:38 +02:00
# ifdef WITH_TESTS
2020-01-23 17:22:05 +01:00
2013-01-19 23:19:38 +02:00
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 ( )
{
2020-02-12 11:51:45 +01:00
VcsBaseEditorWidget : : testDiffFileResolving ( dd - > diffEditorFactory ) ;
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 "
) ;
2020-02-12 11:51:45 +01:00
VcsBaseEditorWidget : : testLogResolving ( dd - > logEditorFactory , data ,
2013-01-28 22:02:35 +02:00
" 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 ( )
{
2020-01-23 17:22:05 +01:00
dd - > m_tempFile = QDir : : currentPath ( ) + QLatin1String ( " /cc_file.cpp " ) ;
2022-08-03 06:55:06 +02:00
FileSaver srcSaver ( FilePath : : fromString ( dd - > m_tempFile ) ) ;
2013-11-20 11:59:34 +01:00
srcSaver . write ( QByteArray ( ) ) ;
srcSaver . finalize ( ) ;
}
void ClearCasePlugin : : cleanupTestCase ( )
{
2020-01-23 17:22:05 +01:00
QVERIFY ( QFile : : remove ( dd - > m_tempFile ) ) ;
2013-11-20 11:59:34 +01:00
}
void ClearCasePlugin : : testFileStatusParsing_data ( )
{
QTest : : addColumn < QString > ( " filename " ) ;
QTest : : addColumn < QString > ( " cleartoolLsLine " ) ;
QTest : : addColumn < int > ( " status " ) ;
QTest : : newRow ( " CheckedOut " )
2020-01-23 17:22:05 +01:00
< < dd - > m_tempFile
< < QString ( dd - > m_tempFile + QLatin1String ( " @@/main/branch1/CHECKEDOUT from /main/branch1/0 Rule: CHECKEDOUT " ) )
2013-11-20 11:59:34 +01:00
< < static_cast < int > ( FileStatus : : CheckedOut ) ;
QTest : : newRow ( " CheckedIn " )
2020-01-23 17:22:05 +01:00
< < dd - > m_tempFile
< < QString ( dd - > m_tempFile + QLatin1String ( " @@/main/9 Rule: MY_LABEL_1.6.4 [-mkbranch branch1] " ) )
2013-11-20 11:59:34 +01:00
< < static_cast < int > ( FileStatus : : CheckedIn ) ;
QTest : : newRow ( " Hijacked " )
2020-01-23 17:22:05 +01:00
< < dd - > m_tempFile
< < QString ( dd - > m_tempFile + QLatin1String ( " @@/main/9 [hijacked] Rule: MY_LABEL_1.5.33 [-mkbranch myview1] " ) )
2013-11-20 11:59:34 +01:00
< < static_cast < int > ( FileStatus : : Hijacked ) ;
QTest : : newRow ( " Missing " )
2020-01-23 17:22:05 +01:00
< < dd - > m_tempFile
< < QString ( dd - > m_tempFile + QLatin1String ( " @@/main/9 [loaded but missing] Rule: MY_LABEL_1.5.33 [-mkbranch myview1] " ) )
2013-11-20 11:59:34 +01:00
< < static_cast < int > ( FileStatus : : Missing ) ;
}
void ClearCasePlugin : : testFileStatusParsing ( )
{
2020-01-23 17:22:05 +01:00
dd - > m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
2013-11-20 11:59:34 +01:00
QFETCH ( QString , filename ) ;
QFETCH ( QString , cleartoolLsLine ) ;
QFETCH ( int , status ) ;
2020-02-06 17:49:35 +01:00
ClearCaseSync ccSync ( dd - > m_statusMap ) ;
2013-11-20 11:59:34 +01:00
ccSync . verifyParseStatus ( filename , cleartoolLsLine , static_cast < FileStatus : : Status > ( status ) ) ;
}
void ClearCasePlugin : : testFileNotManaged ( )
{
2020-01-23 17:22:05 +01:00
dd - > m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
2020-02-06 17:49:35 +01:00
ClearCaseSync ccSync ( dd - > m_statusMap ) ;
2013-11-20 11:59:34 +01:00
ccSync . verifyFileNotManaged ( ) ;
}
2013-12-05 13:30:20 +01:00
void ClearCasePlugin : : testFileCheckedOutDynamicView ( )
{
2020-01-23 17:22:05 +01:00
dd - > m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
2013-12-05 13:30:20 +01:00
2020-02-06 17:49:35 +01:00
ClearCaseSync ccSync ( dd - > m_statusMap ) ;
2013-12-05 13:30:20 +01:00
ccSync . verifyFileCheckedOutDynamicView ( ) ;
}
void ClearCasePlugin : : testFileCheckedInDynamicView ( )
{
2020-01-23 17:22:05 +01:00
dd - > m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
2020-02-06 17:49:35 +01:00
ClearCaseSync ccSync ( dd - > m_statusMap ) ;
2013-12-05 13:30:20 +01:00
ccSync . verifyFileCheckedInDynamicView ( ) ;
}
void ClearCasePlugin : : testFileNotManagedDynamicView ( )
{
2020-01-23 17:22:05 +01:00
dd - > m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
2020-02-06 17:49:35 +01:00
ClearCaseSync ccSync ( dd - > m_statusMap ) ;
2013-12-05 13:30:20 +01:00
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 ) :
2018-09-20 00:56:28 +03:00
m_fileName ( fileName )
2013-11-20 11:59:34 +01:00
{
2020-01-23 17:22:05 +01:00
ClearCasePluginPrivate : : instance ( ) - > setFakeCleartool ( true ) ;
2017-06-15 12:48:22 +02:00
VcsManager : : clearVersionControlCache ( ) ;
2014-08-25 13:18:41 +02:00
2022-08-03 06:55:06 +02:00
const auto filePath = FilePath : : fromString ( fileName ) ;
2021-11-01 17:02:02 +01:00
FileSaver srcSaver ( filePath ) ;
2013-11-20 11:59:34 +01:00
srcSaver . write ( QByteArray ( ) ) ;
srcSaver . finalize ( ) ;
2021-11-01 17:02:02 +01:00
m_editor = EditorManager : : openEditor ( filePath ) ;
2013-11-20 11:59:34 +01:00
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 ( )
{
2020-09-29 10:24:48 +02:00
EditorManager : : closeDocuments ( { m_editor - > document ( ) } , false ) ;
2013-11-20 11:59:34 +01:00
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 ( ) ) ;
2020-01-23 17:22:05 +01:00
ClearCasePluginPrivate : : instance ( ) - > setFakeCleartool ( false ) ;
2013-11-20 11:59:34 +01:00
}
private :
QString m_fileName ;
2014-08-28 16:47:19 +02:00
IEditor * m_editor ;
2013-11-20 11:59:34 +01:00
} ;
}
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 ) ;
2020-01-23 17:22:05 +01:00
dd - > m_viewData = testCase . dummyViewData ( ) ;
2013-11-20 11:59:34 +01:00
QFETCH ( int , status ) ;
2018-09-20 00:56:28 +03:00
auto tempStatus = static_cast < FileStatus : : Status > ( status ) ;
2013-11-20 11:59:34 +01:00
// 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 )
2020-01-23 17:22:05 +01:00
dd - > setStatus ( fileName , tempStatus , true ) ;
2013-11-20 11:59:34 +01:00
QFETCH ( bool , checkOutAction ) ;
QFETCH ( bool , undoCheckOutAction ) ;
QFETCH ( bool , undoHijackAction ) ;
QFETCH ( bool , checkInCurrentAction ) ;
QFETCH ( bool , addFileAction ) ;
QFETCH ( bool , checkInActivityAction ) ;
QFETCH ( bool , diffActivityAction ) ;
2020-01-23 17:22:05 +01:00
QCOMPARE ( dd - > m_checkOutAction - > isEnabled ( ) , checkOutAction ) ;
QCOMPARE ( dd - > m_undoCheckOutAction - > isEnabled ( ) , undoCheckOutAction ) ;
QCOMPARE ( dd - > m_undoHijackAction - > isEnabled ( ) , undoHijackAction ) ;
QCOMPARE ( dd - > m_checkInCurrentAction - > isEnabled ( ) , checkInCurrentAction ) ;
QCOMPARE ( dd - > m_addFileAction - > isEnabled ( ) , addFileAction ) ;
QCOMPARE ( dd - > m_checkInActivityAction - > isEnabled ( ) , checkInActivityAction ) ;
QCOMPARE ( dd - > m_diffActivityAction - > isEnabled ( ) , diffActivityAction ) ;
2013-11-20 11:59:34 +01:00
}
2013-12-05 13:30:20 +01:00
void ClearCasePlugin : : testVcsStatusDynamicReadonlyNotManaged ( )
{
// File is not in map, and is read-only
2020-01-23 17:22:05 +01:00
ClearCasePluginPrivate : : instance ( ) ;
dd - > m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
2013-12-05 13:30:20 +01:00
const QString fileName = QDir : : currentPath ( ) + QLatin1String ( " /readonly_notmanaged_file.cpp " ) ;
2020-01-23 17:22:05 +01:00
dd - > m_viewData . isDynamic = true ;
2013-12-05 13:30:20 +01:00
TestCase testCase ( fileName ) ;
QFile : : setPermissions ( fileName , QFile : : ReadOwner |
QFile : : ReadUser |
QFile : : ReadGroup |
QFile : : ReadOther ) ;
2020-01-23 17:22:05 +01:00
dd - > m_viewData = testCase . dummyViewData ( ) ;
dd - > m_viewData . isDynamic = true ;
2013-12-05 13:30:20 +01:00
2020-01-23 17:22:05 +01:00
QCOMPARE ( dd - > vcsStatus ( fileName ) . status , FileStatus : : NotManaged ) ;
2013-12-05 13:30:20 +01:00
}
void ClearCasePlugin : : testVcsStatusDynamicNotManaged ( )
{
2020-01-23 17:22:05 +01:00
ClearCasePluginPrivate : : instance ( ) ;
dd - > m_statusMap = QSharedPointer < StatusMap > ( new StatusMap ) ;
2013-12-05 13:30:20 +01:00
const QString fileName = QDir : : currentPath ( ) + QLatin1String ( " /notmanaged_file.cpp " ) ;
2020-01-23 17:22:05 +01:00
dd - > m_viewData . isDynamic = true ;
2013-12-05 13:30:20 +01:00
TestCase testCase ( fileName ) ;
2020-01-23 17:22:05 +01:00
dd - > m_viewData = testCase . dummyViewData ( ) ;
dd - > m_viewData . isDynamic = true ;
2013-12-05 13:30:20 +01:00
2020-01-23 17:22:05 +01:00
QCOMPARE ( dd - > vcsStatus ( fileName ) . status , FileStatus : : NotManaged ) ;
2013-12-05 13:30:20 +01:00
}
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
2020-02-06 17:49:35 +01:00
# include "clearcaseplugin.moc"