2009-02-25 09:15:00 +01:00
/**************************************************************************
2008-12-02 12:01:29 +01:00
* *
* * This file is part of Qt Creator
* *
2009-02-25 09:15:00 +01:00
* * Copyright ( c ) 2009 Nokia Corporation and / or its subsidiary ( - ies ) .
2008-12-02 12:01:29 +01:00
* *
2009-06-17 00:01:27 +10:00
* * Contact : Nokia Corporation ( qt - info @ nokia . com )
2008-12-02 12:01:29 +01:00
* *
2009-02-25 09:15:00 +01:00
* * Commercial Usage
2008-12-02 14:17:16 +01:00
* *
2009-02-25 09:15:00 +01:00
* * Licensees holding valid Qt Commercial licenses may use this file in
* * accordance with the Qt Commercial License Agreement provided with the
* * Software or , alternatively , in accordance with the terms contained in
* * a written agreement between you and Nokia .
2008-12-02 14:17:16 +01:00
* *
2009-02-25 09:15:00 +01:00
* * GNU Lesser General Public License Usage
2008-12-02 14:17:16 +01:00
* *
2009-02-25 09:15:00 +01:00
* * Alternatively , this file may be used under the terms of the GNU Lesser
* * General Public License version 2.1 as published by the Free Software
* * Foundation and appearing in the file LICENSE . LGPL included in the
* * packaging of this file . Please review the following information to
* * ensure the GNU Lesser General Public License version 2.1 requirements
* * will be met : http : //www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
2008-12-02 14:17:16 +01:00
* *
2009-02-25 09:15:00 +01:00
* * If you are unsure which license is appropriate for your use , please
2009-08-14 09:30:56 +02:00
* * contact the sales department at http : //qt.nokia.com/contact.
2008-12-02 12:01:29 +01:00
* *
2009-02-25 09:15:00 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-12-02 16:19:05 +01:00
2008-12-02 12:01:29 +01:00
# include "perforceplugin.h"
2008-12-09 15:25:01 +01:00
2008-12-02 12:01:29 +01:00
# include "changenumberdialog.h"
2008-12-09 15:25:01 +01:00
# include "pendingchangesdialog.h"
2008-12-02 12:01:29 +01:00
# include "perforceconstants.h"
# include "perforceeditor.h"
2008-12-09 15:25:01 +01:00
# include "perforcesubmiteditor.h"
# include "perforceversioncontrol.h"
2009-12-11 16:43:39 +01:00
# include "perforcechecker.h"
2008-12-09 15:25:01 +01:00
# include "settingspage.h"
2008-12-02 12:01:29 +01:00
2009-01-13 13:39:31 +01:00
# include <coreplugin/actionmanager/actionmanager.h>
2008-12-02 12:01:29 +01:00
# include <coreplugin/coreconstants.h>
2008-12-09 15:25:01 +01:00
# include <coreplugin/editormanager/editormanager.h>
2008-12-02 12:01:29 +01:00
# include <coreplugin/filemanager.h>
2008-12-09 15:25:01 +01:00
# include <coreplugin/icore.h>
2008-12-02 12:01:29 +01:00
# include <coreplugin/messagemanager.h>
2008-12-09 15:25:01 +01:00
# include <coreplugin/mimedatabase.h>
2008-12-02 12:01:29 +01:00
# include <coreplugin/uniqueidmanager.h>
2008-12-09 15:25:01 +01:00
# include <utils/qtcassert.h>
2008-12-02 12:01:29 +01:00
# include <utils/synchronousprocess.h>
2009-05-15 15:41:00 +02:00
# include <utils/parameteraction.h>
2008-12-02 12:01:29 +01:00
# include <vcsbase/basevcseditorfactory.h>
# include <vcsbase/basevcssubmiteditorfactory.h>
# include <vcsbase/vcsbaseeditor.h>
2009-08-10 15:46:45 +02:00
# include <vcsbase/vcsbaseoutputwindow.h>
2008-12-02 12:01:29 +01:00
2009-01-20 17:14:00 +01:00
# include <QtCore/QtPlugin>
2008-12-02 12:01:29 +01:00
# include <QtCore/QDebug>
# include <QtCore/QDir>
2008-12-09 15:25:01 +01:00
# include <QtCore/QFileInfo>
2008-12-02 12:01:29 +01:00
# include <QtCore/QSettings>
2008-12-09 15:25:01 +01:00
# include <QtCore/QTemporaryFile>
2008-12-02 12:01:29 +01:00
# include <QtCore/QTextCodec>
2008-12-09 15:25:01 +01:00
2008-12-02 12:01:29 +01:00
# include <QtGui/QAction>
2008-12-09 15:25:01 +01:00
# include <QtGui/QFileDialog>
# include <QtGui/QMainWindow>
2008-12-02 12:01:29 +01:00
# include <QtGui/QMenu>
# include <QtGui/QMessageBox>
enum { p4Timeout = 20000 } ;
2009-12-14 09:41:38 +01:00
enum { longTimeoutFactor = 4 } ;
2008-12-02 12:01:29 +01:00
static const VCSBase : : VCSBaseEditorParameters editorParameters [ ] = {
{
VCSBase : : RegularCommandOutput ,
2009-12-11 16:43:39 +01:00
Perforce : : Constants : : PERFORCE_COMMANDLOG_EDITOR_KIND ,
Perforce : : Constants : : PERFORCE_COMMANDLOG_EDITOR_CONTEXT ,
2008-12-02 12:01:29 +01:00
" application/vnd.nokia.text.scs_commandlog " ,
" scslog " } ,
{ VCSBase : : LogOutput ,
2009-12-11 16:43:39 +01:00
Perforce : : Constants : : PERFORCE_LOG_EDITOR_KIND ,
Perforce : : Constants : : PERFORCE_LOG_EDITOR_CONTEXT ,
2008-12-02 12:01:29 +01:00
" application/vnd.nokia.text.scs_filelog " ,
" scsfilelog " } ,
{ VCSBase : : AnnotateOutput ,
2009-12-11 16:43:39 +01:00
Perforce : : Constants : : PERFORCE_ANNOTATION_EDITOR_KIND ,
Perforce : : Constants : : PERFORCE_ANNOTATION_EDITOR_CONTEXT ,
2008-12-02 12:01:29 +01:00
" application/vnd.nokia.text.scs_annotation " ,
" scsannotate " } ,
{ VCSBase : : DiffOutput ,
2009-12-11 16:43:39 +01:00
Perforce : : Constants : : PERFORCE_DIFF_EDITOR_KIND ,
Perforce : : Constants : : PERFORCE_DIFF_EDITOR_CONTEXT ,
2008-12-02 12:01:29 +01:00
" text/x-patch " , " diff " }
} ;
// Utility to find a parameter set by type
static inline const VCSBase : : VCSBaseEditorParameters * findType ( int ie )
{
const VCSBase : : EditorContentType et = static_cast < VCSBase : : EditorContentType > ( ie ) ;
return VCSBase : : VCSBaseEditor : : findType ( editorParameters , sizeof ( editorParameters ) / sizeof ( VCSBase : : VCSBaseEditorParameters ) , et ) ;
}
static inline QString debugCodec ( const QTextCodec * c )
{
return c ? QString : : fromAscii ( c - > name ( ) ) : QString : : fromAscii ( " Null codec " ) ;
}
2009-12-11 16:43:39 +01:00
// Ensure adding "..." to relative paths which is p4's convention
// for the current directory
static inline QStringList perforceRelativeFileArguments ( const QStringList & args )
{
if ( args . isEmpty ( ) )
return QStringList ( QLatin1String ( " ... " ) ) ;
QTC_ASSERT ( args . size ( ) = = 1 , return QStringList ( ) )
QStringList p4Args = args ;
p4Args . front ( ) + = QLatin1String ( " /... " ) ;
return p4Args ;
}
static inline QStringList perforceRelativeProjectDirectory ( const VCSBase : : VCSBasePluginState & s )
{
return perforceRelativeFileArguments ( s . relativeCurrentProject ( ) ) ;
}
// Clean user setting off diff-binary for 'p4 resolve' and 'p4 diff'.
static inline QProcessEnvironment overrideDiffEnvironmentVariable ( )
{
QProcessEnvironment rc = QProcessEnvironment : : systemEnvironment ( ) ;
rc . remove ( QLatin1String ( " P4DIFF " ) ) ;
return rc ;
2009-03-10 11:02:12 +01:00
}
2009-07-13 14:48:44 +02:00
static const char * const CMD_ID_PERFORCE_MENU = " Perforce.Menu " ;
static const char * const CMD_ID_EDIT = " Perforce.Edit " ;
static const char * const CMD_ID_ADD = " Perforce.Add " ;
static const char * const CMD_ID_DELETE_FILE = " Perforce.Delete " ;
static const char * const CMD_ID_OPENED = " Perforce.Opened " ;
static const char * const CMD_ID_REVERT = " Perforce.Revert " ;
static const char * const CMD_ID_DIFF_CURRENT = " Perforce.DiffCurrent " ;
static const char * const CMD_ID_DIFF_PROJECT = " Perforce.DiffProject " ;
static const char * const CMD_ID_UPDATE_PROJECT = " Perforce.UpdateProject " ;
2009-12-11 16:43:39 +01:00
static const char * const CMD_ID_REVERT_PROJECT = " Perforce.RevertProject " ;
static const char * const CMD_ID_REVERT_UNCHANGED_PROJECT = " Perforce.RevertUnchangedProject " ;
2009-07-13 14:48:44 +02:00
static const char * const CMD_ID_DIFF_ALL = " Perforce.DiffAll " ;
static const char * const CMD_ID_RESOLVE = " Perforce.Resolve " ;
static const char * const CMD_ID_SUBMIT = " Perforce.Submit " ;
static const char * const CMD_ID_PENDING_CHANGES = " Perforce.PendingChanges " ;
static const char * const CMD_ID_DESCRIBE = " Perforce.Describe " ;
static const char * const CMD_ID_ANNOTATE_CURRENT = " Perforce.AnnotateCurrent " ;
static const char * const CMD_ID_ANNOTATE = " Perforce.Annotate " ;
static const char * const CMD_ID_FILELOG_CURRENT = " Perforce.FilelogCurrent " ;
static const char * const CMD_ID_FILELOG = " Perforce.Filelog " ;
static const char * const CMD_ID_UPDATEALL = " Perforce.UpdateAll " ;
static const char * const CMD_ID_SEPARATOR1 = " Perforce.Separator1 " ;
static const char * const CMD_ID_SEPARATOR2 = " Perforce.Separator2 " ;
static const char * const CMD_ID_SEPARATOR3 = " Perforce.Separator3 " ;
2008-12-02 12:01:29 +01:00
////
// PerforcePlugin
////
2009-12-11 16:43:39 +01:00
namespace Perforce {
namespace Internal {
PerforceResponse : : PerforceResponse ( ) :
error ( true ) ,
exitCode ( - 1 )
{
}
2008-12-02 12:01:29 +01:00
PerforcePlugin * PerforcePlugin : : m_perforcePluginInstance = NULL ;
PerforcePlugin : : PerforcePlugin ( ) :
2009-12-11 16:43:39 +01:00
VCSBase : : VCSBasePlugin ( QLatin1String ( Constants : : PERFORCE_SUBMIT_EDITOR_KIND ) ) ,
2008-12-02 12:01:29 +01:00
m_editAction ( 0 ) ,
m_addAction ( 0 ) ,
m_deleteAction ( 0 ) ,
m_openedAction ( 0 ) ,
2009-12-11 16:43:39 +01:00
m_revertFileAction ( 0 ) ,
m_diffFileAction ( 0 ) ,
2008-12-02 12:01:29 +01:00
m_diffProjectAction ( 0 ) ,
2009-07-13 14:48:44 +02:00
m_updateProjectAction ( 0 ) ,
2009-12-11 16:43:39 +01:00
m_revertProjectAction ( 0 ) ,
m_revertUnchangedAction ( 0 ) ,
2008-12-02 12:01:29 +01:00
m_diffAllAction ( 0 ) ,
2009-12-11 16:43:39 +01:00
m_submitProjectAction ( 0 ) ,
2008-12-02 12:01:29 +01:00
m_pendingAction ( 0 ) ,
m_describeAction ( 0 ) ,
m_annotateCurrentAction ( 0 ) ,
m_annotateAction ( 0 ) ,
m_filelogCurrentAction ( 0 ) ,
m_filelogAction ( 0 ) ,
2009-03-20 10:16:18 +01:00
m_submitCurrentLogAction ( 0 ) ,
2009-07-13 14:48:44 +02:00
m_updateAllAction ( 0 ) ,
2009-03-20 10:16:18 +01:00
m_submitActionTriggered ( false ) ,
m_diffSelectedFiles ( 0 ) ,
m_undoAction ( 0 ) ,
2009-12-08 14:26:41 +01:00
m_redoAction ( 0 )
2008-12-02 12:01:29 +01:00
{
}
static const VCSBase : : VCSBaseSubmitEditorParameters submitParameters = {
Perforce : : Constants : : SUBMIT_MIMETYPE ,
2009-12-11 16:43:39 +01:00
Perforce : : Constants : : PERFORCE_SUBMIT_EDITOR_KIND ,
Perforce : : Constants : : PERFORCESUBMITEDITOR_CONTEXT
2008-12-02 12:01:29 +01:00
} ;
2009-12-08 14:26:41 +01:00
bool PerforcePlugin : : initialize ( const QStringList & /* arguments */ , QString * errorMessage )
2008-12-02 12:01:29 +01:00
{
typedef VCSBase : : VCSEditorFactory < PerforceEditor > PerforceEditorFactory ;
typedef VCSBase : : VCSSubmitEditorFactory < PerforceSubmitEditor > PerforceSubmitEditorFactory ;
2009-12-08 14:26:41 +01:00
VCSBase : : VCSBasePlugin : : initialize ( new PerforceVersionControl ( this ) ) ;
2009-01-20 11:52:04 +01:00
Core : : ICore * core = Core : : ICore : : instance ( ) ;
if ( ! core - > mimeDatabase ( ) - > addMimeTypes ( QLatin1String ( " :/trolltech.perforce/Perforce.mimetypes.xml " ) , errorMessage ) )
2008-12-02 12:01:29 +01:00
return false ;
m_perforcePluginInstance = this ;
2009-01-20 11:52:04 +01:00
if ( QSettings * settings = core - > settings ( ) )
2008-12-02 12:01:29 +01:00
m_settings . fromSettings ( settings ) ;
2009-08-10 15:46:45 +02:00
addAutoReleasedObject ( new SettingsPage ) ;
2008-12-02 12:01:29 +01:00
// Editor factories
2009-08-10 15:46:45 +02:00
addAutoReleasedObject ( new PerforceSubmitEditorFactory ( & submitParameters ) ) ;
2008-12-02 12:01:29 +01:00
static const char * describeSlot = SLOT ( describe ( QString , QString ) ) ;
const int editorCount = sizeof ( editorParameters ) / sizeof ( VCSBase : : VCSBaseEditorParameters ) ;
2009-08-10 15:46:45 +02:00
for ( int i = 0 ; i < editorCount ; i + + )
addAutoReleasedObject ( new PerforceEditorFactory ( editorParameters + i , this , describeSlot ) ) ;
2008-12-02 12:01:29 +01:00
//register actions
2009-01-20 11:52:04 +01:00
Core : : ActionManager * am = Core : : ICore : : instance ( ) - > actionManager ( ) ;
2008-12-02 12:01:29 +01:00
2009-01-14 12:39:59 +01:00
Core : : ActionContainer * mtools =
2008-12-02 12:01:29 +01:00
am - > actionContainer ( Core : : Constants : : M_TOOLS ) ;
2009-01-14 12:39:59 +01:00
Core : : ActionContainer * mperforce =
2009-07-13 14:48:44 +02:00
am - > createMenu ( QLatin1String ( CMD_ID_PERFORCE_MENU ) ) ;
2008-12-02 12:01:29 +01:00
mperforce - > menu ( ) - > setTitle ( tr ( " &Perforce " ) ) ;
mtools - > addMenu ( mperforce ) ;
2009-12-08 14:26:41 +01:00
m_menuAction = mperforce - > menu ( ) - > menuAction ( ) ;
2008-12-02 12:01:29 +01:00
QList < int > globalcontext ;
globalcontext < < Core : : Constants : : C_GLOBAL_ID ;
QList < int > perforcesubmitcontext ;
2009-01-21 15:52:34 +01:00
perforcesubmitcontext < < Core : : UniqueIDManager : : instance ( ) - >
2009-12-11 16:43:39 +01:00
uniqueIdentifier ( Constants : : PERFORCESUBMITEDITOR_CONTEXT ) ;
2008-12-02 12:01:29 +01:00
2009-01-14 13:17:53 +01:00
Core : : Command * command ;
2008-12-02 12:01:29 +01:00
QAction * tmpaction ;
2009-10-05 11:06:05 +02:00
m_editAction = new Utils : : ParameterAction ( tr ( " Edit " ) , tr ( " Edit \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_editAction , CMD_ID_EDIT , globalcontext ) ;
2009-01-14 13:17:53 +01:00
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2008-12-02 12:01:29 +01:00
command - > setDefaultKeySequence ( QKeySequence ( tr ( " Alt+P,Alt+E " ) ) ) ;
command - > setDefaultText ( tr ( " Edit File " ) ) ;
connect ( m_editAction , SIGNAL ( triggered ( ) ) , this , SLOT ( openCurrentFile ( ) ) ) ;
mperforce - > addAction ( command ) ;
2009-10-05 11:06:05 +02:00
m_addAction = new Utils : : ParameterAction ( tr ( " Add " ) , tr ( " Add \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_addAction , CMD_ID_ADD , globalcontext ) ;
2009-01-14 13:17:53 +01:00
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2008-12-02 12:01:29 +01:00
command - > setDefaultKeySequence ( QKeySequence ( tr ( " Alt+P,Alt+A " ) ) ) ;
command - > setDefaultText ( tr ( " Add File " ) ) ;
connect ( m_addAction , SIGNAL ( triggered ( ) ) , this , SLOT ( addCurrentFile ( ) ) ) ;
mperforce - > addAction ( command ) ;
2009-10-05 11:06:05 +02:00
m_deleteAction = new Utils : : ParameterAction ( tr ( " Delete " ) , tr ( " Delete \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_deleteAction , CMD_ID_DELETE_FILE , globalcontext ) ;
2009-01-14 13:17:53 +01:00
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2008-12-02 12:01:29 +01:00
command - > setDefaultText ( tr ( " Delete File " ) ) ;
connect ( m_deleteAction , SIGNAL ( triggered ( ) ) , this , SLOT ( deleteCurrentFile ( ) ) ) ;
mperforce - > addAction ( command ) ;
2009-12-11 16:43:39 +01:00
m_revertFileAction = new Utils : : ParameterAction ( tr ( " Revert " ) , tr ( " Revert \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
command = am - > registerAction ( m_revertFileAction , CMD_ID_REVERT , globalcontext ) ;
2009-01-14 13:17:53 +01:00
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2008-12-02 12:01:29 +01:00
command - > setDefaultKeySequence ( QKeySequence ( tr ( " Alt+P,Alt+R " ) ) ) ;
command - > setDefaultText ( tr ( " Revert File " ) ) ;
2009-12-11 16:43:39 +01:00
connect ( m_revertFileAction , SIGNAL ( triggered ( ) ) , this , SLOT ( revertCurrentFile ( ) ) ) ;
2008-12-02 12:01:29 +01:00
mperforce - > addAction ( command ) ;
tmpaction = new QAction ( this ) ;
tmpaction - > setSeparator ( true ) ;
command = am - > registerAction ( tmpaction , QLatin1String ( " Perforce.Sep.Edit " ) , globalcontext ) ;
mperforce - > addAction ( command ) ;
2009-12-11 16:43:39 +01:00
m_diffFileAction = new Utils : : ParameterAction ( tr ( " Diff Current File " ) , tr ( " Diff \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
command = am - > registerAction ( m_diffFileAction , CMD_ID_DIFF_CURRENT , globalcontext ) ;
2009-01-14 13:17:53 +01:00
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2008-12-02 12:01:29 +01:00
command - > setDefaultText ( tr ( " Diff Current File " ) ) ;
2009-12-11 16:43:39 +01:00
connect ( m_diffFileAction , SIGNAL ( triggered ( ) ) , this , SLOT ( diffCurrentFile ( ) ) ) ;
2008-12-02 12:01:29 +01:00
mperforce - > addAction ( command ) ;
2009-07-13 14:48:44 +02:00
const QString diffProjectDefaultText = tr ( " Diff Current Project/Session " ) ;
2009-10-05 11:06:05 +02:00
m_diffProjectAction = new Utils : : ParameterAction ( diffProjectDefaultText , tr ( " Diff Project \" %1 \" " ) , Utils : : ParameterAction : : AlwaysEnabled , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_diffProjectAction , CMD_ID_DIFF_PROJECT , globalcontext ) ;
2009-01-14 13:17:53 +01:00
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2008-12-02 12:01:29 +01:00
command - > setDefaultKeySequence ( QKeySequence ( tr ( " Alt+P,Alt+D " ) ) ) ;
2009-07-13 14:48:44 +02:00
command - > setDefaultText ( diffProjectDefaultText ) ;
2008-12-02 12:01:29 +01:00
connect ( m_diffProjectAction , SIGNAL ( triggered ( ) ) , this , SLOT ( diffCurrentProject ( ) ) ) ;
mperforce - > addAction ( command ) ;
m_diffAllAction = new QAction ( tr ( " Diff Opened Files " ) , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_diffAllAction , CMD_ID_DIFF_ALL , globalcontext ) ;
2008-12-02 12:01:29 +01:00
connect ( m_diffAllAction , SIGNAL ( triggered ( ) ) , this , SLOT ( diffAllOpened ( ) ) ) ;
mperforce - > addAction ( command ) ;
tmpaction = new QAction ( this ) ;
tmpaction - > setSeparator ( true ) ;
command = am - > registerAction ( tmpaction , QLatin1String ( " Perforce.Sep.Diff " ) , globalcontext ) ;
mperforce - > addAction ( command ) ;
m_openedAction = new QAction ( tr ( " Opened " ) , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_openedAction , CMD_ID_OPENED , globalcontext ) ;
2008-12-02 12:01:29 +01:00
command - > setDefaultKeySequence ( QKeySequence ( tr ( " Alt+P,Alt+O " ) ) ) ;
connect ( m_openedAction , SIGNAL ( triggered ( ) ) , this , SLOT ( printOpenedFileList ( ) ) ) ;
mperforce - > addAction ( command ) ;
2009-12-11 16:43:39 +01:00
m_submitProjectAction = new Utils : : ParameterAction ( tr ( " Submit Project " ) , tr ( " Submit Project \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
command = am - > registerAction ( m_submitProjectAction , CMD_ID_SUBMIT , globalcontext ) ;
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2008-12-02 12:01:29 +01:00
command - > setDefaultKeySequence ( QKeySequence ( tr ( " Alt+P,Alt+S " ) ) ) ;
2009-12-11 16:43:39 +01:00
connect ( m_submitProjectAction , SIGNAL ( triggered ( ) ) , this , SLOT ( startSubmitProject ( ) ) ) ;
2008-12-02 12:01:29 +01:00
mperforce - > addAction ( command ) ;
m_pendingAction = new QAction ( tr ( " Pending Changes... " ) , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_pendingAction , CMD_ID_PENDING_CHANGES , globalcontext ) ;
2008-12-02 12:01:29 +01:00
connect ( m_pendingAction , SIGNAL ( triggered ( ) ) , this , SLOT ( printPendingChanges ( ) ) ) ;
mperforce - > addAction ( command ) ;
2009-12-11 16:43:39 +01:00
const QString updateProjectDefaultText = tr ( " Update Current Project " ) ;
2009-10-05 11:06:05 +02:00
m_updateProjectAction = new Utils : : ParameterAction ( updateProjectDefaultText , tr ( " Update Project \" %1 \" " ) , Utils : : ParameterAction : : AlwaysEnabled , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_updateProjectAction , CMD_ID_UPDATE_PROJECT , globalcontext ) ;
command - > setDefaultText ( updateProjectDefaultText ) ;
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
connect ( m_updateProjectAction , SIGNAL ( triggered ( ) ) , this , SLOT ( updateCurrentProject ( ) ) ) ;
mperforce - > addAction ( command ) ;
2009-12-11 16:43:39 +01:00
m_revertProjectAction = new Utils : : ParameterAction ( tr ( " Revert Project " ) , tr ( " Revert Project \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
command = am - > registerAction ( m_revertProjectAction , CMD_ID_REVERT_PROJECT , globalcontext ) ;
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
connect ( m_revertProjectAction , SIGNAL ( triggered ( ) ) , this , SLOT ( revertCurrentProject ( ) ) ) ;
mperforce - > addAction ( command ) ;
m_revertUnchangedAction = new Utils : : ParameterAction ( tr ( " Revert Unchanged " ) , tr ( " Revert Unchanged Files of Project \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
command = am - > registerAction ( m_revertUnchangedAction , CMD_ID_REVERT_UNCHANGED_PROJECT , globalcontext ) ;
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
connect ( m_revertUnchangedAction , SIGNAL ( triggered ( ) ) , this , SLOT ( revertUnchangedCurrentProject ( ) ) ) ;
mperforce - > addAction ( command ) ;
2008-12-02 12:01:29 +01:00
tmpaction = new QAction ( this ) ;
tmpaction - > setSeparator ( true ) ;
command = am - > registerAction ( tmpaction , QLatin1String ( " Perforce.Sep.Changes " ) , globalcontext ) ;
mperforce - > addAction ( command ) ;
m_describeAction = new QAction ( tr ( " Describe... " ) , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_describeAction , CMD_ID_DESCRIBE , globalcontext ) ;
2008-12-02 12:01:29 +01:00
connect ( m_describeAction , SIGNAL ( triggered ( ) ) , this , SLOT ( describeChange ( ) ) ) ;
mperforce - > addAction ( command ) ;
2009-10-05 11:06:05 +02:00
m_annotateCurrentAction = new Utils : : ParameterAction ( tr ( " Annotate Current File " ) , tr ( " Annotate \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_annotateCurrentAction , CMD_ID_ANNOTATE_CURRENT , globalcontext ) ;
2009-01-14 13:17:53 +01:00
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2008-12-02 12:01:29 +01:00
command - > setDefaultText ( tr ( " Annotate Current File " ) ) ;
connect ( m_annotateCurrentAction , SIGNAL ( triggered ( ) ) , this , SLOT ( annotateCurrentFile ( ) ) ) ;
mperforce - > addAction ( command ) ;
m_annotateAction = new QAction ( tr ( " Annotate... " ) , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_annotateAction , CMD_ID_ANNOTATE , globalcontext ) ;
2008-12-02 12:01:29 +01:00
connect ( m_annotateAction , SIGNAL ( triggered ( ) ) , this , SLOT ( annotate ( ) ) ) ;
mperforce - > addAction ( command ) ;
2009-10-05 11:06:05 +02:00
m_filelogCurrentAction = new Utils : : ParameterAction ( tr ( " Filelog Current File " ) , tr ( " Filelog \" %1 \" " ) , Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_filelogCurrentAction , CMD_ID_FILELOG_CURRENT , globalcontext ) ;
2009-01-14 13:17:53 +01:00
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2008-12-02 12:01:29 +01:00
command - > setDefaultKeySequence ( QKeySequence ( tr ( " Alt+P,Alt+F " ) ) ) ;
command - > setDefaultText ( tr ( " Filelog Current File " ) ) ;
connect ( m_filelogCurrentAction , SIGNAL ( triggered ( ) ) , this , SLOT ( filelogCurrentFile ( ) ) ) ;
mperforce - > addAction ( command ) ;
m_filelogAction = new QAction ( tr ( " Filelog... " ) , this ) ;
2009-07-13 14:48:44 +02:00
command = am - > registerAction ( m_filelogAction , CMD_ID_FILELOG , globalcontext ) ;
2008-12-02 12:01:29 +01:00
connect ( m_filelogAction , SIGNAL ( triggered ( ) ) , this , SLOT ( filelog ( ) ) ) ;
mperforce - > addAction ( command ) ;
2009-07-13 14:48:44 +02:00
m_updateAllAction = new QAction ( tr ( " Update All " ) , this ) ;
command = am - > registerAction ( m_updateAllAction , CMD_ID_UPDATEALL , globalcontext ) ;
connect ( m_updateAllAction , SIGNAL ( triggered ( ) ) , this , SLOT ( updateAll ( ) ) ) ;
mperforce - > addAction ( command ) ;
2008-12-02 17:05:53 +01:00
m_submitCurrentLogAction = new QAction ( VCSBase : : VCSBaseSubmitEditor : : submitIcon ( ) , tr ( " Submit " ) , this ) ;
2008-12-02 12:01:29 +01:00
command = am - > registerAction ( m_submitCurrentLogAction , Constants : : SUBMIT_CURRENT , perforcesubmitcontext ) ;
connect ( m_submitCurrentLogAction , SIGNAL ( triggered ( ) ) , this , SLOT ( submitCurrentLog ( ) ) ) ;
2008-12-02 17:05:53 +01:00
m_diffSelectedFiles = new QAction ( VCSBase : : VCSBaseSubmitEditor : : diffIcon ( ) , tr ( " Diff Selected Files " ) , this ) ;
2008-12-02 12:01:29 +01:00
command = am - > registerAction ( m_diffSelectedFiles , Constants : : DIFF_SELECTED , perforcesubmitcontext ) ;
m_undoAction = new QAction ( tr ( " &Undo " ) , this ) ;
command = am - > registerAction ( m_undoAction , Core : : Constants : : UNDO , perforcesubmitcontext ) ;
m_redoAction = new QAction ( tr ( " &Redo " ) , this ) ;
command = am - > registerAction ( m_redoAction , Core : : Constants : : REDO , perforcesubmitcontext ) ;
return true ;
}
void PerforcePlugin : : extensionsInitialized ( )
{
2009-12-11 16:43:39 +01:00
getTopLevel ( ) ;
2008-12-02 12:01:29 +01:00
}
void PerforcePlugin : : openCurrentFile ( )
{
2009-12-11 16:43:39 +01:00
const VCSBase : : VCSBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return )
vcsOpen ( state . currentFileTopLevel ( ) , state . relativeCurrentFile ( ) ) ;
2008-12-02 12:01:29 +01:00
}
void PerforcePlugin : : addCurrentFile ( )
{
2009-12-11 16:43:39 +01:00
const VCSBase : : VCSBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return )
vcsAdd ( state . currentFileTopLevel ( ) , state . relativeCurrentFile ( ) ) ;
2008-12-02 12:01:29 +01:00
}
void PerforcePlugin : : deleteCurrentFile ( )
{
2009-12-11 16:43:39 +01:00
const VCSBase : : VCSBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return )
vcsDelete ( state . currentFileTopLevel ( ) , state . relativeCurrentFile ( ) ) ;
2008-12-02 12:01:29 +01:00
}
void PerforcePlugin : : revertCurrentFile ( )
{
2009-12-11 16:43:39 +01:00
const VCSBase : : VCSBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return )
QTextCodec * codec = VCSBase : : VCSBaseEditor : : getCodec ( state . currentFile ( ) ) ;
2008-12-02 12:01:29 +01:00
QStringList args ;
2009-12-11 16:43:39 +01:00
args < < QLatin1String ( " diff " ) < < QLatin1String ( " -sa " ) < < state . relativeCurrentFile ( ) ;
PerforceResponse result = runP4Cmd ( state . currentFileTopLevel ( ) , args ,
RunFullySynchronous | CommandToWindow | StdErrToWindow | ErrorToWindow ,
QStringList ( ) , QByteArray ( ) , codec ) ;
2008-12-02 12:01:29 +01:00
if ( result . error )
return ;
2009-12-11 16:43:39 +01:00
// "foo.cpp - file(s) not opened on this client."
if ( result . stdOut . isEmpty ( ) | | result . stdOut . contains ( QLatin1String ( " - " ) ) )
return ;
2008-12-02 12:01:29 +01:00
2009-12-11 16:43:39 +01:00
const bool doNotRevert = QMessageBox : : warning ( 0 , tr ( " p4 revert " ) ,
tr ( " The file has been changed. Do you want to revert it? " ) ,
QMessageBox : : Yes , QMessageBox : : No ) = = QMessageBox : : No ;
if ( doNotRevert )
return ;
2008-12-02 12:01:29 +01:00
2009-12-11 16:43:39 +01:00
Core : : FileChangeBlocker fcb ( state . currentFile ( ) ) ;
2009-06-18 14:30:04 +02:00
fcb . setModifiedReload ( true ) ;
2009-12-11 16:43:39 +01:00
args . clear ( ) ;
args < < QLatin1String ( " revert " ) < < state . relativeCurrentFile ( ) ;
PerforceResponse result2 = runP4Cmd ( state . currentFileTopLevel ( ) , args ,
CommandToWindow | StdOutToWindow | StdErrToWindow | ErrorToWindow ) ;
2009-11-11 14:32:54 +01:00
if ( ! result2 . error )
2009-12-11 16:43:39 +01:00
perforceVersionControl ( ) - > emitFilesChanged ( QStringList ( state . currentFile ( ) ) ) ;
2008-12-02 12:01:29 +01:00
}
void PerforcePlugin : : diffCurrentFile ( )
{
2009-12-11 16:43:39 +01:00
const VCSBase : : VCSBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return )
p4Diff ( state . currentFileTopLevel ( ) , QStringList ( state . relativeCurrentFile ( ) ) ) ;
2008-12-02 12:01:29 +01:00
}
void PerforcePlugin : : diffCurrentProject ( )
{
2009-12-11 16:43:39 +01:00
const VCSBase : : VCSBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasProject ( ) , return )
p4Diff ( state . currentProjectTopLevel ( ) , perforceRelativeProjectDirectory ( state ) ) ;
2008-12-02 12:01:29 +01:00
}
void PerforcePlugin : : diffAllOpened ( )
{
2009-12-11 16:43:39 +01:00
p4Diff ( m_settings . topLevel ( ) , QStringList ( ) ) ;
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
void PerforcePlugin : : updateCurrentProject ( )
2009-07-13 14:48:44 +02:00
{
2009-12-11 16:43:39 +01:00
const VCSBase : : VCSBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasProject ( ) , return )
updateCheckout ( state . currentProjectTopLevel ( ) , perforceRelativeProjectDirectory ( state ) ) ;
2009-07-13 14:48:44 +02:00
}
2009-12-11 16:43:39 +01:00
void PerforcePlugin : : updateAll ( )
{
updateCheckout ( m_settings . topLevel ( ) ) ;
}
void PerforcePlugin : : revertCurrentProject ( )
2009-07-13 14:48:44 +02:00
{
2009-12-11 16:43:39 +01:00
const VCSBase : : VCSBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasProject ( ) , return )
const QString msg = tr ( " Do you want to revert all changes to the project \" %1 \" ? " ) . arg ( state . currentProjectName ( ) ) ;
if ( QMessageBox : : warning ( 0 , tr ( " p4 revert " ) , msg , QMessageBox : : Yes , QMessageBox : : No ) = = QMessageBox : : No )
2009-07-13 14:48:44 +02:00
return ;
2009-12-11 16:43:39 +01:00
revertProject ( state . currentProjectTopLevel ( ) , perforceRelativeProjectDirectory ( state ) , false ) ;
2009-07-13 14:48:44 +02:00
}
2009-12-11 16:43:39 +01:00
void PerforcePlugin : : revertUnchangedCurrentProject ( )
2009-07-13 14:48:44 +02:00
{
2009-12-11 16:43:39 +01:00
// revert -a.
const VCSBase : : VCSBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasProject ( ) , return )
revertProject ( state . currentProjectTopLevel ( ) , perforceRelativeProjectDirectory ( state ) , true ) ;
2009-07-13 14:48:44 +02:00
}
2009-12-11 16:43:39 +01:00
bool PerforcePlugin : : revertProject ( const QString & workingDir , const QStringList & pathArgs , bool unchangedOnly )
{
QStringList args ( QLatin1String ( " revert " ) ) ;
if ( unchangedOnly )
args . push_back ( QLatin1String ( " -a " ) ) ;
args . append ( pathArgs ) ;
const PerforceResponse resp = runP4Cmd ( workingDir , args ,
RunFullySynchronous | CommandToWindow | StdOutToWindow | StdErrToWindow | ErrorToWindow ) ;
return ! resp . error ;
}
void PerforcePlugin : : updateCheckout ( const QString & workingDir , const QStringList & dirs )
2009-07-13 14:48:44 +02:00
{
QStringList args ( QLatin1String ( " sync " ) ) ;
args . append ( dirs ) ;
2009-12-11 16:43:39 +01:00
const PerforceResponse resp = runP4Cmd ( workingDir , args ,
CommandToWindow | StdOutToWindow | StdErrToWindow | ErrorToWindow ) ;
if ( dirs . empty ( ) ) {
if ( ! workingDir . isEmpty ( ) )
perforceVersionControl ( ) - > emitRepositoryChanged ( workingDir ) ;
} else {
const QChar slash = QLatin1Char ( ' / ' ) ;
2009-11-11 14:32:54 +01:00
foreach ( const QString & dir , dirs )
2009-12-11 16:43:39 +01:00
perforceVersionControl ( ) - > emitRepositoryChanged ( workingDir + slash + dir ) ;
}
2009-07-13 14:48:44 +02:00
}
2008-12-02 12:01:29 +01:00
void PerforcePlugin : : printOpenedFileList ( )
{
2009-12-11 16:43:39 +01:00
runP4Cmd ( m_settings . topLevel ( ) , QStringList ( QLatin1String ( " opened " ) ) ,
CommandToWindow | StdOutToWindow | StdErrToWindow | ErrorToWindow ) ;
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
void PerforcePlugin : : startSubmitProject ( )
2008-12-02 12:01:29 +01:00
{
2009-05-27 16:17:24 +02:00
2009-12-11 16:43:39 +01:00
if ( VCSBase : : VCSBaseSubmitEditor : : raiseSubmitEditor ( ) )
2008-12-02 12:01:29 +01:00
return ;
2009-09-22 12:23:44 +02:00
if ( isCommitEditorOpen ( ) ) {
2009-08-10 15:46:45 +02:00
VCSBase : : VCSBaseOutputWindow : : instance ( ) - > appendWarning ( tr ( " Another submit is currently executed. " ) ) ;
2008-12-02 12:01:29 +01:00
return ;
}
2009-12-11 16:43:39 +01:00
const VCSBase : : VCSBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasProject ( ) , return )
2009-09-22 12:23:44 +02:00
QTemporaryFile changeTmpFile ;
changeTmpFile . setAutoRemove ( false ) ;
if ( ! changeTmpFile . open ( ) ) {
2009-08-10 15:46:45 +02:00
VCSBase : : VCSBaseOutputWindow : : instance ( ) - > appendError ( tr ( " Cannot create temporary file. " ) ) ;
2009-09-22 12:23:44 +02:00
cleanCommitMessageFile ( ) ;
2008-12-02 12:01:29 +01:00
return ;
}
2009-12-11 16:43:39 +01:00
// Revert all unchanged files.
if ( ! revertProject ( state . currentProjectTopLevel ( ) , perforceRelativeProjectDirectory ( state ) , true ) )
return ;
// Start a change
QStringList args ;
2008-12-02 12:01:29 +01:00
2009-12-11 16:43:39 +01:00
args < < QLatin1String ( " change " ) < < QLatin1String ( " -o " ) ;
PerforceResponse result = runP4Cmd ( state . currentProjectTopLevel ( ) , args ,
RunFullySynchronous | CommandToWindow | StdErrToWindow | ErrorToWindow ) ;
2008-12-02 12:01:29 +01:00
if ( result . error ) {
2009-09-22 12:23:44 +02:00
cleanCommitMessageFile ( ) ;
2008-12-02 12:01:29 +01:00
return ;
}
2009-09-22 12:23:44 +02:00
m_commitMessageFileName = changeTmpFile . fileName ( ) ;
changeTmpFile . write ( result . stdOut . toAscii ( ) ) ;
changeTmpFile . close ( ) ;
2008-12-02 12:01:29 +01:00
2009-12-11 16:43:39 +01:00
args . clear ( ) ;
args < < QLatin1String ( " fstat " ) ;
args . append ( perforceRelativeProjectDirectory ( state ) ) ;
PerforceResponse fstatResult = runP4Cmd ( state . currentProjectTopLevel ( ) , args ,
RunFullySynchronous | CommandToWindow | StdErrToWindow | ErrorToWindow ) ;
if ( fstatResult . error ) {
2009-09-22 12:23:44 +02:00
cleanCommitMessageFile ( ) ;
2008-12-02 12:01:29 +01:00
return ;
}
2009-12-11 16:43:39 +01:00
QStringList fstatLines = fstatResult . stdOut . split ( QLatin1Char ( ' \n ' ) ) ;
2008-12-02 12:01:29 +01:00
QStringList depotFileNames ;
2009-12-11 16:43:39 +01:00
foreach ( const QString & line , fstatLines ) {
2008-12-09 11:07:24 +01:00
if ( line . startsWith ( " ... depotFile " ) )
2008-12-02 12:01:29 +01:00
depotFileNames . append ( line . mid ( 14 ) ) ;
}
if ( depotFileNames . isEmpty ( ) ) {
2009-08-10 15:46:45 +02:00
VCSBase : : VCSBaseOutputWindow : : instance ( ) - > appendWarning ( tr ( " Project has no files " ) ) ;
2009-09-22 12:23:44 +02:00
cleanCommitMessageFile ( ) ;
2008-12-02 12:01:29 +01:00
return ;
}
2009-09-22 12:23:44 +02:00
openPerforceSubmitEditor ( m_commitMessageFileName , depotFileNames ) ;
2008-12-02 12:01:29 +01:00
}
Core : : IEditor * PerforcePlugin : : openPerforceSubmitEditor ( const QString & fileName , const QStringList & depotFileNames )
{
2009-01-21 15:52:34 +01:00
Core : : EditorManager * editorManager = Core : : EditorManager : : instance ( ) ;
2009-12-11 16:43:39 +01:00
Core : : IEditor * editor = editorManager - > openEditor ( fileName , Constants : : PERFORCE_SUBMIT_EDITOR_KIND ) ;
2009-01-21 15:52:34 +01:00
editorManager - > ensureEditorManagerVisible ( ) ;
2009-08-25 16:08:52 +02:00
PerforceSubmitEditor * submitEditor = static_cast < PerforceSubmitEditor * > ( editor ) ;
2008-12-02 12:01:29 +01:00
submitEditor - > restrictToProjectFiles ( depotFileNames ) ;
2009-01-13 14:06:42 +01:00
submitEditor - > registerActions ( m_undoAction , m_redoAction , m_submitCurrentLogAction , m_diffSelectedFiles ) ;
2009-12-11 16:43:39 +01:00
connect ( submitEditor , SIGNAL ( diffSelectedFiles ( QStringList ) ) , this , SLOT ( slotSubmitDiff ( QStringList ) ) ) ;
2009-12-14 10:56:50 +01:00
submitEditor - > setCheckScriptWorkingDirectory ( m_commitWorkingDirectory ) ;
2008-12-02 12:01:29 +01:00
return editor ;
}
void PerforcePlugin : : printPendingChanges ( )
{
qApp - > setOverrideCursor ( Qt : : WaitCursor ) ;
2009-01-20 11:52:04 +01:00
PendingChangesDialog dia ( pendingChangesData ( ) , Core : : ICore : : instance ( ) - > mainWindow ( ) ) ;
2008-12-02 12:01:29 +01:00
qApp - > restoreOverrideCursor ( ) ;
if ( dia . exec ( ) = = QDialog : : Accepted ) {
2008-12-04 16:24:15 +01:00
const int i = dia . changeNumber ( ) ;
QStringList args ( QLatin1String ( " submit " ) ) ;
args < < QLatin1String ( " -c " ) < < QString : : number ( i ) ;
2009-12-11 16:43:39 +01:00
runP4Cmd ( m_settings . topLevel ( ) , args ,
CommandToWindow | StdOutToWindow | StdErrToWindow | ErrorToWindow ) ;
2008-12-02 12:01:29 +01:00
}
}
void PerforcePlugin : : describeChange ( )
{
ChangeNumberDialog dia ;
if ( dia . exec ( ) = = QDialog : : Accepted & & dia . number ( ) > 0 )
describe ( QString ( ) , QString : : number ( dia . number ( ) ) ) ;
}
void PerforcePlugin : : annotateCurrentFile ( )
{
2009-12-11 16:43:39 +01:00
const VCSBase : : VCSBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return )
annotate ( state . currentFileTopLevel ( ) , state . relativeCurrentFile ( ) ) ;
2008-12-02 12:01:29 +01:00
}
void PerforcePlugin : : annotate ( )
{
2009-12-11 16:43:39 +01:00
const QString file = QFileDialog : : getOpenFileName ( 0 , tr ( " p4 annotate " ) ) ;
if ( ! file . isEmpty ( ) ) {
const QFileInfo fi ( file ) ;
annotate ( fi . absolutePath ( ) , fi . fileName ( ) ) ;
}
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
void PerforcePlugin : : annotate ( const QString & workingDir , const QString & fileName )
2008-12-02 12:01:29 +01:00
{
2009-12-11 16:43:39 +01:00
const QStringList files = QStringList ( fileName ) ;
QTextCodec * codec = VCSBase : : VCSBaseEditor : : getCodec ( workingDir , files ) ;
const QString id = VCSBase : : VCSBaseEditor : : getTitleId ( workingDir , files ) ;
const QString source = VCSBase : : VCSBaseEditor : : getSource ( workingDir , files ) ;
2008-12-02 12:01:29 +01:00
QStringList args ;
args < < QLatin1String ( " annotate " ) < < QLatin1String ( " -cqi " ) < < fileName ;
2009-12-11 16:43:39 +01:00
const PerforceResponse result = runP4Cmd ( workingDir , args ,
CommandToWindow | StdErrToWindow | ErrorToWindow ,
QStringList ( ) , QByteArray ( ) , codec ) ;
2008-12-02 12:01:29 +01:00
if ( ! result . error ) {
2009-12-11 16:43:39 +01:00
const int lineNumber = VCSBase : : VCSBaseEditor : : lineNumberOfCurrentEditor ( ) ;
2008-12-02 12:01:29 +01:00
const QFileInfo fi ( fileName ) ;
2009-12-11 16:43:39 +01:00
Core : : IEditor * ed = showOutputInEditor ( tr ( " p4 annotate %1 " ) . arg ( id ) ,
2009-10-01 17:32:26 +02:00
result . stdOut , VCSBase : : AnnotateOutput , codec ) ;
VCSBase : : VCSBaseEditor : : gotoLineOfEditor ( ed , lineNumber ) ;
2008-12-02 12:01:29 +01:00
}
}
void PerforcePlugin : : filelogCurrentFile ( )
{
2009-12-11 16:43:39 +01:00
const VCSBase : : VCSBasePluginState state = currentState ( ) ;
QTC_ASSERT ( state . hasFile ( ) , return )
filelog ( state . currentFileTopLevel ( ) , QStringList ( state . relativeCurrentFile ( ) ) ) ;
2008-12-02 12:01:29 +01:00
}
void PerforcePlugin : : filelog ( )
{
2009-12-11 16:43:39 +01:00
const QString file = QFileDialog : : getOpenFileName ( 0 , tr ( " p4 filelog " ) ) ;
if ( ! file . isEmpty ( ) ) {
const QFileInfo fi ( file ) ;
filelog ( fi . absolutePath ( ) , QStringList ( fi . fileName ( ) ) ) ;
}
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
void PerforcePlugin : : filelog ( const QString & workingDir , const QStringList & fileNames )
2008-12-02 12:01:29 +01:00
{
2009-12-11 16:43:39 +01:00
const QString id = VCSBase : : VCSBaseEditor : : getTitleId ( workingDir , fileNames ) ;
QTextCodec * codec = VCSBase : : VCSBaseEditor : : getCodec ( workingDir , fileNames ) ;
2008-12-02 12:01:29 +01:00
QStringList args ;
2009-12-11 16:43:39 +01:00
args < < QLatin1String ( " filelog " ) < < QLatin1String ( " -li " ) ;
args . append ( fileNames ) ;
const PerforceResponse result = runP4Cmd ( workingDir , args ,
CommandToWindow | StdErrToWindow | ErrorToWindow ,
QStringList ( ) , QByteArray ( ) , codec ) ;
if ( ! result . error )
showOutputInEditor ( tr ( " p4 filelog %1 " ) . arg ( id ) , result . stdOut , VCSBase : : LogOutput , codec ) ;
2008-12-02 12:01:29 +01:00
}
2009-12-08 14:26:41 +01:00
void PerforcePlugin : : updateActions ( VCSBase : : VCSBasePlugin : : ActionState as )
2008-12-02 12:01:29 +01:00
{
2009-12-08 14:26:41 +01:00
if ( ! VCSBase : : VCSBasePlugin : : enableMenuAction ( as , m_menuAction ) )
return ;
2009-12-11 16:43:39 +01:00
const QString fileName = currentState ( ) . currentFileName ( ) ;
m_editAction - > setParameter ( fileName ) ;
m_addAction - > setParameter ( fileName ) ;
m_deleteAction - > setParameter ( fileName ) ;
m_revertFileAction - > setParameter ( fileName ) ;
m_diffFileAction - > setParameter ( fileName ) ;
m_annotateCurrentAction - > setParameter ( fileName ) ;
m_filelogCurrentAction - > setParameter ( fileName ) ;
const QString projectName = currentState ( ) . currentProjectName ( ) ;
m_updateProjectAction - > setParameter ( projectName ) ;
m_diffProjectAction - > setParameter ( projectName ) ;
m_submitProjectAction - > setParameter ( projectName ) ;
m_revertProjectAction - > setParameter ( projectName ) ;
m_revertUnchangedAction - > setParameter ( projectName ) ;
2009-07-13 14:48:44 +02:00
2008-12-02 12:01:29 +01:00
m_diffAllAction - > setEnabled ( true ) ;
m_openedAction - > setEnabled ( true ) ;
m_describeAction - > setEnabled ( true ) ;
m_annotateAction - > setEnabled ( true ) ;
m_filelogAction - > setEnabled ( true ) ;
m_pendingAction - > setEnabled ( true ) ;
2009-07-13 14:48:44 +02:00
m_updateAllAction - > setEnabled ( true ) ;
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
bool PerforcePlugin : : managesDirectory ( const QString & directory )
2008-12-02 12:01:29 +01:00
{
2009-12-11 16:43:39 +01:00
if ( ! m_settings . isValid ( ) )
2009-02-19 16:11:29 +01:00
return false ;
2009-12-11 16:43:39 +01:00
// Cached?
const ManagedDirectoryCache : : const_iterator cit = m_managedDirectoryCache . constFind ( directory ) ;
if ( cit ! = m_managedDirectoryCache . constEnd ( ) )
return cit . value ( ) ;
// Determine value and insert into cache
bool managed = false ;
do {
// Quick check: Must be at or below top level and not "../../other_path"
const QStringList relativeDirArgs = m_settings . relativeToTopLevelArguments ( directory ) ;
if ( ! relativeDirArgs . empty ( ) & & relativeDirArgs . front ( ) . startsWith ( QLatin1String ( " .. " ) ) )
break ;
// Is it actually managed by perforce?
QStringList args ;
args < < QLatin1String ( " fstat " ) < < QLatin1String ( " -m1 " ) < < perforceRelativeFileArguments ( relativeDirArgs ) ;
const PerforceResponse result = runP4Cmd ( m_settings . topLevel ( ) , args ,
RunFullySynchronous ) ;
managed = result . stdOut . contains ( " depotFile " ) | | result . stdErr . contains ( " ... - no such file(s) " ) ;
} while ( false ) ;
m_managedDirectoryCache . insert ( directory , managed ) ;
return managed ;
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
QString PerforcePlugin : : findTopLevelForDirectory ( const QString & dir )
2008-12-02 12:01:29 +01:00
{
2009-12-11 16:43:39 +01:00
if ( ! m_settings . isValid ( ) )
return QString ( ) ;
return managesDirectory ( dir ) ? m_settings . topLevelSymLinkTarget ( ) : QString ( ) ;
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
bool PerforcePlugin : : vcsOpen ( const QString & workingDir , const QString & fileName )
2008-12-02 12:01:29 +01:00
{
2009-12-11 16:43:39 +01:00
if ( Perforce : : Constants : : debug )
qDebug ( ) < < " PerforcePlugin::vcsOpen " < < workingDir < < fileName ;
QStringList args ;
args < < QLatin1String ( " edit " ) < < QDir : : toNativeSeparators ( fileName ) ;
const PerforceResponse result = runP4Cmd ( workingDir , args ,
2008-12-04 16:24:15 +01:00
CommandToWindow | StdOutToWindow | StdErrToWindow | ErrorToWindow ) ;
2008-12-02 12:01:29 +01:00
return ! result . error ;
}
2009-12-11 16:43:39 +01:00
bool PerforcePlugin : : vcsAdd ( const QString & workingDir , const QString & fileName )
2008-12-02 12:01:29 +01:00
{
2009-12-11 16:43:39 +01:00
QStringList args ;
args < < QLatin1String ( " add " ) < < fileName ;
const PerforceResponse result = runP4Cmd ( workingDir , args ,
2008-12-04 16:24:15 +01:00
CommandToWindow | StdOutToWindow | StdErrToWindow | ErrorToWindow ) ;
2008-12-02 12:01:29 +01:00
return ! result . error ;
}
2009-12-11 16:43:39 +01:00
bool PerforcePlugin : : vcsDelete ( const QString & workingDir , const QString & fileName )
2008-12-02 12:01:29 +01:00
{
2009-12-11 16:43:39 +01:00
QStringList args ;
args < < QLatin1String ( " revert " ) < < fileName ;
const PerforceResponse revertResult = runP4Cmd ( workingDir , args ,
2008-12-04 16:24:15 +01:00
CommandToWindow | StdOutToWindow | StdErrToWindow | ErrorToWindow ) ;
2009-12-11 16:43:39 +01:00
if ( revertResult . error )
return false ;
args . clear ( ) ;
args < < QLatin1String ( " delete " ) < < fileName ;
const PerforceResponse deleteResult = runP4Cmd ( workingDir , args ,
CommandToWindow | StdOutToWindow | StdErrToWindow | ErrorToWindow ) ;
2008-12-02 12:01:29 +01:00
// TODO need to carefully parse the actual messages from perforce
// or do a fstat before to decide what to do
// Different states are:
// File is in depot and unopened => p4 delete %
// File is in depot and opened => p4 revert %, p4 delete %
// File is not in depot => p4 revert %
2009-12-11 16:43:39 +01:00
return ! deleteResult . error ;
2008-12-02 12:01:29 +01:00
}
2009-08-17 09:49:56 +02:00
static QString formatCommand ( const QString & cmd , const QStringList & args )
{
const QChar blank = QLatin1Char ( ' ' ) ;
QString command = cmd ;
command + = blank ;
command + = args . join ( QString ( blank ) ) ;
return PerforcePlugin : : tr ( " Executing: %1 \n " ) . arg ( command ) ;
}
2009-12-11 16:43:39 +01:00
// Write extra args to temporary file
QSharedPointer < QTemporaryFile >
PerforcePlugin : : createTemporaryArgumentFile ( const QStringList & extraArgs ) const
2008-12-02 12:01:29 +01:00
{
2009-12-11 16:43:39 +01:00
if ( extraArgs . isEmpty ( ) )
return QSharedPointer < QTemporaryFile > ( ) ;
// create pattern
if ( m_tempFilePattern . isEmpty ( ) ) {
m_tempFilePattern = QDir : : tempPath ( ) ;
if ( ! m_tempFilePattern . endsWith ( QDir : : separator ( ) ) )
m_tempFilePattern + = QDir : : separator ( ) ;
m_tempFilePattern + = QLatin1String ( " qtc_p4_XXXXXX.args " ) ;
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
QSharedPointer < QTemporaryFile > rc ( new QTemporaryFile ( m_tempFilePattern ) ) ;
rc - > setAutoRemove ( true ) ;
if ( ! rc - > open ( ) ) {
qWarning ( " Could not create temporary file: %s. Appending all file names to command line. " ,
qPrintable ( rc - > errorString ( ) ) ) ;
return QSharedPointer < QTemporaryFile > ( ) ;
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
const int last = extraArgs . size ( ) - 1 ;
for ( int i = 0 ; i < = last ; i + + ) {
rc - > write ( extraArgs . at ( i ) . toLocal8Bit ( ) ) ;
if ( i ! = last )
rc - > write ( " \n " ) ;
}
rc - > close ( ) ;
return rc ;
}
2008-12-02 12:01:29 +01:00
2009-12-11 16:43:39 +01:00
// Run messages
static inline QString msgNotStarted ( const QString & cmd )
{
return PerforcePlugin : : tr ( " Could not start perforce '%1'. Please check your settings in the preferences. " ) . arg ( cmd ) ;
}
2009-12-14 09:41:38 +01:00
static inline QString msgTimeout ( int timeOut )
2009-12-11 16:43:39 +01:00
{
2009-12-14 09:41:38 +01:00
return PerforcePlugin : : tr ( " Perforce did not respond within timeout limit (%1 ms). " ) . arg ( timeOut ) ;
2009-12-11 16:43:39 +01:00
}
static inline QString msgCrash ( )
{
return PerforcePlugin : : tr ( " The process terminated abnormally. " ) ;
}
static inline QString msgExitCode ( int ex )
{
return PerforcePlugin : : tr ( " The process terminated with exit code %1. " ) . arg ( ex ) ;
}
// Run using a SynchronousProcess, emitting signals to the message window
PerforceResponse PerforcePlugin : : synchronousProcess ( const QString & workingDir ,
const QStringList & args ,
unsigned flags ,
const QByteArray & stdInput ,
QTextCodec * outputCodec ) const
{
QTC_ASSERT ( stdInput . isEmpty ( ) , return PerforceResponse ( ) ) // Not supported here
2008-12-02 12:01:29 +01:00
2009-12-11 16:43:39 +01:00
VCSBase : : VCSBaseOutputWindow * outputWindow = VCSBase : : VCSBaseOutputWindow : : instance ( ) ;
2008-12-02 12:01:29 +01:00
// Run, connect stderr to the output window
2009-10-05 11:06:05 +02:00
Utils : : SynchronousProcess process ;
2009-12-14 09:41:38 +01:00
const int timeOut = ( flags & LongTimeOut ) ? longTimeoutFactor * p4Timeout : p4Timeout ;
process . setTimeout ( timeOut ) ;
2008-12-02 12:01:29 +01:00
process . setStdOutCodec ( outputCodec ) ;
2009-12-11 16:43:39 +01:00
if ( flags & OverrideDiffEnvironment )
process . setProcessEnvironment ( overrideDiffEnvironmentVariable ( ) ) ;
if ( ! workingDir . isEmpty ( ) )
process . setWorkingDirectory ( workingDir ) ;
2008-12-02 12:01:29 +01:00
// connect stderr to the output window if desired
2009-12-11 16:43:39 +01:00
if ( flags & StdErrToWindow ) {
2008-12-02 12:01:29 +01:00
process . setStdErrBufferedSignalsEnabled ( true ) ;
2009-08-10 15:46:45 +02:00
connect ( & process , SIGNAL ( stdErrBuffered ( QString , bool ) ) , outputWindow , SLOT ( append ( QString ) ) ) ;
2008-12-02 12:01:29 +01:00
}
// connect stdout to the output window if desired
2009-12-11 16:43:39 +01:00
if ( flags & StdOutToWindow ) {
2008-12-02 12:01:29 +01:00
process . setStdOutBufferedSignalsEnabled ( true ) ;
2009-08-10 15:46:45 +02:00
connect ( & process , SIGNAL ( stdOutBuffered ( QString , bool ) ) , outputWindow , SLOT ( append ( QString ) ) ) ;
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
if ( Perforce : : Constants : : debug )
qDebug ( ) < < " PerforcePlugin::run syncp actual args [ " < < process . workingDirectory ( ) < < ' ] ' < < args ;
const Utils : : SynchronousProcessResponse sp_resp = process . run ( m_settings . p4Command ( ) , args ) ;
2008-12-02 12:01:29 +01:00
if ( Perforce : : Constants : : debug )
qDebug ( ) < < sp_resp ;
2009-12-11 16:43:39 +01:00
PerforceResponse response ;
2008-12-02 12:01:29 +01:00
response . error = true ;
2009-12-11 16:43:39 +01:00
response . exitCode = sp_resp . exitCode ;
2008-12-02 12:01:29 +01:00
response . stdErr = sp_resp . stdErr ;
response . stdOut = sp_resp . stdOut ;
switch ( sp_resp . result ) {
2009-10-05 11:06:05 +02:00
case Utils : : SynchronousProcessResponse : : Finished :
2008-12-02 12:01:29 +01:00
response . error = false ;
break ;
2009-10-05 11:06:05 +02:00
case Utils : : SynchronousProcessResponse : : FinishedError :
2009-12-11 16:43:39 +01:00
response . message = msgExitCode ( sp_resp . exitCode ) ;
response . error = ! ( flags & IgnoreExitCode ) ;
2008-12-02 12:01:29 +01:00
break ;
2009-10-05 11:06:05 +02:00
case Utils : : SynchronousProcessResponse : : TerminatedAbnormally :
2009-12-11 16:43:39 +01:00
response . message = msgCrash ( ) ;
2008-12-02 12:01:29 +01:00
break ;
2009-10-05 11:06:05 +02:00
case Utils : : SynchronousProcessResponse : : StartFailed :
2009-12-11 16:43:39 +01:00
response . message = msgNotStarted ( m_settings . p4Command ( ) ) ;
2008-12-02 12:01:29 +01:00
break ;
2009-10-05 11:06:05 +02:00
case Utils : : SynchronousProcessResponse : : Hang :
2009-12-11 16:43:39 +01:00
response . message = msgCrash ( ) ;
2008-12-02 12:01:29 +01:00
break ;
}
2009-12-11 16:43:39 +01:00
return response ;
}
// Run using a QProcess, for short queries
PerforceResponse PerforcePlugin : : fullySynchronousProcess ( const QString & workingDir ,
const QStringList & args ,
unsigned flags ,
const QByteArray & stdInput ,
QTextCodec * outputCodec ) const
{
QProcess process ;
if ( flags & OverrideDiffEnvironment )
process . setProcessEnvironment ( overrideDiffEnvironmentVariable ( ) ) ;
if ( ! workingDir . isEmpty ( ) )
process . setWorkingDirectory ( workingDir ) ;
if ( Perforce : : Constants : : debug )
qDebug ( ) < < " PerforcePlugin::run fully syncp actual args [ " < < process . workingDirectory ( ) < < ' ] ' < < args ;
PerforceResponse response ;
process . start ( m_settings . p4Command ( ) , args ) ;
if ( stdInput . isEmpty ( ) )
process . closeWriteChannel ( ) ;
if ( ! process . waitForStarted ( 3000 ) ) {
response . error = true ;
response . message = msgNotStarted ( m_settings . p4Command ( ) ) ;
return response ;
}
if ( ! stdInput . isEmpty ( ) ) {
if ( process . write ( stdInput ) = = - 1 ) {
2009-12-11 17:04:13 +01:00
PerforceChecker : : ensureProcessStopped ( process ) ;
2009-12-11 16:43:39 +01:00
response . error = true ;
response . message = tr ( " Unable to write input data to process %1: %2 " ) . arg ( m_settings . p4Command ( ) , process . errorString ( ) ) ;
return response ;
}
process . closeWriteChannel ( ) ;
}
2009-12-14 09:41:38 +01:00
const int timeOut = ( flags & LongTimeOut ) ? longTimeoutFactor * p4Timeout : p4Timeout ;
if ( ! process . waitForFinished ( timeOut ) ) {
2009-12-11 16:43:39 +01:00
PerforceChecker : : ensureProcessStopped ( process ) ;
response . error = true ;
2009-12-14 09:41:38 +01:00
response . message = msgTimeout ( timeOut ) ;
2009-12-11 16:43:39 +01:00
return response ;
}
if ( process . exitStatus ( ) ! = QProcess : : NormalExit ) {
response . error = true ;
response . message = msgCrash ( ) ;
return response ;
}
response . exitCode = process . exitCode ( ) ;
response . error = response . exitCode ? ! ( flags & IgnoreExitCode ) : false ;
response . stdErr = QString : : fromLocal8Bit ( process . readAllStandardError ( ) ) ;
const QByteArray stdOut = process . readAllStandardOutput ( ) ;
response . stdOut = outputCodec ? outputCodec - > toUnicode ( stdOut . constData ( ) , stdOut . size ( ) ) :
QString : : fromLocal8Bit ( stdOut ) ;
2009-12-11 17:04:13 +01:00
const QChar cr = QLatin1Char ( ' \r ' ) ;
response . stdErr . remove ( cr ) ;
response . stdOut . remove ( cr ) ;
2009-12-11 16:43:39 +01:00
// Logging
VCSBase : : VCSBaseOutputWindow * outputWindow = VCSBase : : VCSBaseOutputWindow : : instance ( ) ;
if ( ( flags & StdErrToWindow ) & & ! response . stdErr . isEmpty ( ) )
outputWindow - > append ( response . stdErr ) ;
if ( ( flags & StdOutToWindow ) & & ! response . stdOut . isEmpty ( ) )
outputWindow - > append ( response . stdOut ) ;
return response ;
}
PerforceResponse PerforcePlugin : : runP4Cmd ( const QString & workingDir ,
const QStringList & args ,
unsigned flags ,
const QStringList & extraArgs ,
const QByteArray & stdInput ,
QTextCodec * outputCodec ) const
{
if ( Perforce : : Constants : : debug )
qDebug ( ) < < " PerforcePlugin::runP4Cmd [ " < < workingDir < < ' ] ' < < args < < extraArgs < < stdInput < < debugCodec ( outputCodec ) ;
VCSBase : : VCSBaseOutputWindow * outputWindow = VCSBase : : VCSBaseOutputWindow : : instance ( ) ;
if ( ! m_settings . isValid ( ) ) {
PerforceResponse invalidConfigResponse ;
invalidConfigResponse . error = true ;
invalidConfigResponse . message = tr ( " Perforce is not correctly configured. " ) ;
outputWindow - > appendError ( invalidConfigResponse . message ) ;
return invalidConfigResponse ;
}
QStringList actualArgs = m_settings . commonP4Arguments ( workingDir ) ;
QSharedPointer < QTemporaryFile > tempFile = createTemporaryArgumentFile ( extraArgs ) ;
if ( ! tempFile . isNull ( ) )
actualArgs < < QLatin1String ( " -x " ) < < tempFile - > fileName ( ) ;
actualArgs . append ( args ) ;
if ( flags & CommandToWindow )
outputWindow - > appendCommand ( formatCommand ( m_settings . p4Command ( ) , actualArgs ) ) ;
if ( flags & ShowBusyCursor )
QApplication : : setOverrideCursor ( QCursor ( Qt : : WaitCursor ) ) ;
const PerforceResponse response = ( flags & RunFullySynchronous ) ?
fullySynchronousProcess ( workingDir , actualArgs , flags , stdInput , outputCodec ) :
synchronousProcess ( workingDir , actualArgs , flags , stdInput , outputCodec ) ;
if ( flags & ShowBusyCursor )
QApplication : : restoreOverrideCursor ( ) ;
2008-12-04 16:24:15 +01:00
if ( response . error ) {
if ( Perforce : : Constants : : debug )
qDebug ( ) < < response . message ;
2009-12-11 16:43:39 +01:00
if ( flags & ErrorToWindow )
2009-08-10 15:46:45 +02:00
outputWindow - > appendError ( response . message ) ;
2008-12-04 16:24:15 +01:00
}
2008-12-02 12:01:29 +01:00
return response ;
}
Core : : IEditor * PerforcePlugin : : showOutputInEditor ( const QString & title , const QString output ,
int editorType , QTextCodec * codec )
{
const VCSBase : : VCSBaseEditorParameters * params = findType ( editorType ) ;
2008-12-09 15:25:01 +01:00
QTC_ASSERT ( params , return 0 ) ;
2008-12-02 12:01:29 +01:00
const QString kind = QLatin1String ( params - > kind ) ;
if ( Perforce : : Constants : : debug )
qDebug ( ) < < " PerforcePlugin::showOutputInEditor " < < title < < kind < < " Size= " < < output . size ( ) < < " Type= " < < editorType < < debugCodec ( codec ) ;
QString s = title ;
2009-08-12 10:41:30 +02:00
Core : : IEditor * editor = Core : : EditorManager : : instance ( ) - > openEditorWithContents ( kind , & s , output ) ;
2009-01-21 15:52:34 +01:00
PerforceEditor * e = qobject_cast < PerforceEditor * > ( editor - > widget ( ) ) ;
2008-12-02 12:01:29 +01:00
if ( ! e )
return 0 ;
s . replace ( QLatin1Char ( ' ' ) , QLatin1Char ( ' _ ' ) ) ;
e - > setSuggestedFileName ( s ) ;
if ( codec )
e - > setCodec ( codec ) ;
2009-03-10 11:02:12 +01:00
Core : : IEditor * ie = e - > editableInterface ( ) ;
Core : : EditorManager : : instance ( ) - > activateEditor ( ie ) ;
return ie ;
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
void PerforcePlugin : : slotSubmitDiff ( const QStringList & files )
2008-12-02 12:01:29 +01:00
{
2009-12-11 16:43:39 +01:00
p4Diff ( m_commitWorkingDirectory , files ) ;
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
void PerforcePlugin : : p4Diff ( const QString & workingDir , const QStringList & files )
2008-12-02 12:01:29 +01:00
{
Core : : IEditor * existingEditor = 0 ;
2009-12-11 16:43:39 +01:00
QTextCodec * codec = VCSBase : : VCSBaseEditor : : getCodec ( workingDir , files ) ;
const QString id = VCSBase : : VCSBaseEditor : : getTitleId ( workingDir , files ) ;
const QString source = VCSBase : : VCSBaseEditor : : getSource ( workingDir , files ) ;
// Reuse existing editors for that id
foreach ( Core : : IEditor * ed , Core : : EditorManager : : instance ( ) - > openedEditors ( ) ) {
if ( ed - > file ( ) - > property ( " originalFileName " ) . toString ( ) = = id ) {
existingEditor = ed ;
break ;
2008-12-02 12:01:29 +01:00
}
}
2009-12-11 16:43:39 +01:00
// Split arguments according to size
QStringList args ;
args < < QLatin1String ( " diff " ) < < QLatin1String ( " -du " ) ;
QStringList extraArgs ;
if ( files . size ( ) > 1 ) {
extraArgs = files ;
} else {
args . append ( files ) ;
}
const unsigned flags = CommandToWindow | StdErrToWindow | ErrorToWindow | OverrideDiffEnvironment ;
const PerforceResponse result = runP4Cmd ( workingDir , args , flags ,
extraArgs , QByteArray ( ) , codec ) ;
2008-12-02 12:01:29 +01:00
if ( result . error )
return ;
2009-12-11 16:43:39 +01:00
if ( existingEditor ) {
existingEditor - > createNew ( result . stdOut ) ;
Core : : EditorManager : : instance ( ) - > activateEditor ( existingEditor ) ;
} else {
Core : : IEditor * editor = showOutputInEditor ( tr ( " p4 diff %1 " ) . arg ( id ) , result . stdOut , VCSBase : : DiffOutput , codec ) ;
editor - > file ( ) - > setProperty ( " originalFileName " , id ) ;
2008-12-02 12:01:29 +01:00
}
}
void PerforcePlugin : : describe ( const QString & source , const QString & n )
{
2009-01-20 11:52:04 +01:00
QTextCodec * codec = source . isEmpty ( ) ? static_cast < QTextCodec * > ( 0 ) : VCSBase : : VCSBaseEditor : : getCodec ( source ) ;
2008-12-02 12:01:29 +01:00
QStringList args ;
args < < QLatin1String ( " describe " ) < < QLatin1String ( " -du " ) < < n ;
2009-12-11 16:43:39 +01:00
const PerforceResponse result = runP4Cmd ( m_settings . topLevel ( ) , args , CommandToWindow | StdErrToWindow | ErrorToWindow ,
QStringList ( ) , QByteArray ( ) , codec ) ;
2008-12-02 12:01:29 +01:00
if ( ! result . error )
showOutputInEditor ( tr ( " p4 describe %1 " ) . arg ( n ) , result . stdOut , VCSBase : : DiffOutput , codec ) ;
}
void PerforcePlugin : : submitCurrentLog ( )
{
2009-03-20 10:16:18 +01:00
m_submitActionTriggered = true ;
2009-01-21 15:52:34 +01:00
Core : : EditorManager * em = Core : : EditorManager : : instance ( ) ;
2009-01-20 11:52:04 +01:00
em - > closeEditors ( QList < Core : : IEditor * > ( ) < < em - > currentEditor ( ) ) ;
2008-12-02 12:01:29 +01:00
}
2009-09-22 12:23:44 +02:00
void PerforcePlugin : : cleanCommitMessageFile ( )
2009-03-20 16:52:22 +01:00
{
2009-09-22 12:23:44 +02:00
if ( ! m_commitMessageFileName . isEmpty ( ) ) {
QFile : : remove ( m_commitMessageFileName ) ;
m_commitMessageFileName . clear ( ) ;
2009-12-11 16:43:39 +01:00
m_commitWorkingDirectory . clear ( ) ;
2009-03-20 16:52:22 +01:00
}
}
2009-09-22 12:23:44 +02:00
bool PerforcePlugin : : isCommitEditorOpen ( ) const
{
return ! m_commitMessageFileName . isEmpty ( ) ;
}
2009-12-08 14:26:41 +01:00
bool PerforcePlugin : : submitEditorAboutToClose ( VCSBase : : VCSBaseSubmitEditor * submitEditor )
2008-12-02 12:01:29 +01:00
{
2009-12-08 14:26:41 +01:00
if ( ! isCommitEditorOpen ( ) )
2008-12-02 12:01:29 +01:00
return true ;
2009-12-08 14:26:41 +01:00
Core : : IFile * fileIFace = submitEditor - > file ( ) ;
const PerforceSubmitEditor * perforceEditor = qobject_cast < PerforceSubmitEditor * > ( submitEditor ) ;
if ( ! fileIFace | | ! perforceEditor )
2009-03-19 17:40:01 +01:00
return true ;
2009-12-11 16:43:39 +01:00
// Prompt the user. Force a prompt unless submit was actually invoked (that
// is, the editor was closed or shutdown).
bool wantsPrompt = m_settings . promptToSubmit ( ) ;
const VCSBase : : VCSBaseSubmitEditor : : PromptSubmitResult answer =
2009-03-19 17:40:01 +01:00
perforceEditor - > promptSubmit ( tr ( " Closing p4 Editor " ) ,
tr ( " Do you want to submit this change list? " ) ,
2009-03-20 10:16:18 +01:00
tr ( " The commit message check failed. Do you want to submit this change list " ) ,
2009-06-19 16:34:38 +02:00
& wantsPrompt , ! m_submitActionTriggered ) ;
2009-12-11 16:43:39 +01:00
m_submitActionTriggered = false ;
2009-03-19 17:40:01 +01:00
2009-12-11 16:43:39 +01:00
if ( answer = = VCSBase : : VCSBaseSubmitEditor : : SubmitCanceled )
return false ;
2008-12-02 12:01:29 +01:00
2009-12-11 16:43:39 +01:00
// Set without triggering the checking mechanism
if ( wantsPrompt ! = m_settings . promptToSubmit ( ) ) {
m_settings . setPromptToSubmit ( wantsPrompt ) ;
m_settings . toSettings ( Core : : ICore : : instance ( ) - > settings ( ) ) ;
}
Core : : FileManager * fileManager = Core : : ICore : : instance ( ) - > fileManager ( ) ;
fileManager - > blockFileChange ( fileIFace ) ;
fileIFace - > save ( ) ;
fileManager - > unblockFileChange ( fileIFace ) ;
if ( answer = = VCSBase : : VCSBaseSubmitEditor : : SubmitDiscarded ) {
2009-09-22 12:23:44 +02:00
cleanCommitMessageFile ( ) ;
2009-12-11 16:43:39 +01:00
return true ;
}
// Pipe file into p4 submit -i
QFile commitMessageFile ( m_commitMessageFileName ) ;
if ( ! commitMessageFile . open ( QIODevice : : ReadOnly | QIODevice : : Text ) ) {
VCSBase : : VCSBaseOutputWindow : : instance ( ) - > appendError ( tr ( " Cannot open temporary file. " ) ) ;
return false ;
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
const QByteArray changeDescription = commitMessageFile . readAll ( ) ;
commitMessageFile . close ( ) ;
QStringList submitArgs ;
submitArgs < < QLatin1String ( " submit " ) < < QLatin1String ( " -i " ) ;
const PerforceResponse submitResponse = runP4Cmd ( m_settings . topLevelSymLinkTarget ( ) , submitArgs ,
2009-12-14 09:41:38 +01:00
LongTimeOut | RunFullySynchronous | CommandToWindow | StdErrToWindow | ErrorToWindow | ShowBusyCursor ,
2009-12-11 16:43:39 +01:00
QStringList ( ) , changeDescription ) ;
if ( submitResponse . error ) {
VCSBase : : VCSBaseOutputWindow : : instance ( ) - > appendError ( tr ( " p4 submit failed: %1 " ) . arg ( submitResponse . message ) ) ;
return false ;
}
VCSBase : : VCSBaseOutputWindow : : instance ( ) - > append ( submitResponse . stdOut ) ;
if ( submitResponse . stdOut . contains ( QLatin1String ( " Out of date files must be resolved or reverted) " ) ) )
QMessageBox : : warning ( submitEditor - > widget ( ) , tr ( " Pending change " ) , tr ( " Could not submit the change, because your workspace was out of date. Created a pending submit instead. " ) ) ;
cleanCommitMessageFile ( ) ;
return true ;
2008-12-02 12:01:29 +01:00
}
QString PerforcePlugin : : clientFilePath ( const QString & serverFilePath )
{
2009-12-11 16:43:39 +01:00
QTC_ASSERT ( m_settings . isValid ( ) , return QString ( ) )
2008-12-02 12:01:29 +01:00
2009-12-11 16:43:39 +01:00
QStringList args ;
args < < QLatin1String ( " fstat " ) < < serverFilePath ;
const PerforceResponse response = runP4Cmd ( m_settings . topLevelSymLinkTarget ( ) , args ,
ShowBusyCursor | RunFullySynchronous | CommandToWindow | StdErrToWindow | ErrorToWindow ) ;
if ( response . error )
return QString : : null ;
QRegExp r ( QLatin1String ( " \\ . \\ . \\ . \\ sclientFile \\ s(.+) \ n " )) ;
r . setMinimal ( true ) ;
const QString path = r . indexIn ( response . stdOut ) ! = - 1 ? r . cap ( 1 ) . trimmed ( ) : QString ( ) ;
if ( Perforce : : Constants : : debug )
qDebug ( ) < < " clientFilePath " < < serverFilePath < < path ;
2008-12-02 12:01:29 +01:00
return path ;
}
2009-12-11 16:43:39 +01:00
QString PerforcePlugin : : pendingChangesData ( )
2008-12-02 12:01:29 +01:00
{
2009-12-11 16:43:39 +01:00
QTC_ASSERT ( m_settings . isValid ( ) , return QString ( ) )
2008-12-02 12:01:29 +01:00
2009-12-11 16:43:39 +01:00
QStringList args = QStringList ( QLatin1String ( " info " ) ) ;
const PerforceResponse userResponse = runP4Cmd ( m_settings . topLevelSymLinkTarget ( ) , args ,
RunFullySynchronous | CommandToWindow | StdErrToWindow | ErrorToWindow ) ;
if ( userResponse . error )
return QString : : null ;
2008-12-02 12:01:29 +01:00
2009-12-11 16:43:39 +01:00
QRegExp r ( QLatin1String ( " User \\ sname: \\ s( \\ S+) \ \ s * \ n " )) ;
QTC_ASSERT ( r . isValid ( ) , return QString ( ) )
r . setMinimal ( true ) ;
const QString user = r . indexIn ( userResponse . stdOut ) ! = - 1 ? r . cap ( 1 ) . trimmed ( ) : QString : : null ;
2008-12-02 12:01:29 +01:00
if ( user . isEmpty ( ) )
2009-12-11 16:43:39 +01:00
return QString : : null ;
args . clear ( ) ;
args < < QLatin1String ( " changes " ) < < QLatin1String ( " -s " ) < < QLatin1String ( " pending " ) < < QLatin1String ( " -u " ) < < user ;
const PerforceResponse dataResponse = runP4Cmd ( m_settings . topLevelSymLinkTarget ( ) , args ,
RunFullySynchronous | CommandToWindow | StdErrToWindow | ErrorToWindow ) ;
return dataResponse . error ? QString : : null : dataResponse . stdOut ;
2008-12-02 12:01:29 +01:00
}
PerforcePlugin : : ~ PerforcePlugin ( )
{
}
2009-02-19 16:11:29 +01:00
const PerforceSettings & PerforcePlugin : : settings ( ) const
2008-12-02 12:01:29 +01:00
{
return m_settings ;
}
2009-05-28 10:30:10 +02:00
void PerforcePlugin : : setSettings ( const Settings & newSettings )
2008-12-02 12:01:29 +01:00
{
2009-05-28 10:30:10 +02:00
if ( newSettings ! = m_settings . settings ( ) ) {
m_settings . setSettings ( newSettings ) ;
2009-12-11 16:43:39 +01:00
m_managedDirectoryCache . clear ( ) ;
2009-02-19 16:11:29 +01:00
m_settings . toSettings ( Core : : ICore : : instance ( ) - > settings ( ) ) ;
2009-12-11 16:43:39 +01:00
getTopLevel ( ) ;
2008-12-02 12:01:29 +01:00
}
}
2009-12-11 16:43:39 +01:00
static inline QString msgWhereFailed ( const QString & file , const QString & why )
{
return PerforcePlugin : : tr ( " Error running \" where \" on %1: %2 " ) . arg ( file , why ) ;
}
2008-12-02 12:01:29 +01:00
// Map a perforce name "//xx" to its real name in the file system
QString PerforcePlugin : : fileNameFromPerforceName ( const QString & perforceName ,
QString * errorMessage ) const
{
// All happy, already mapped
if ( ! perforceName . startsWith ( QLatin1String ( " // " ) ) )
return perforceName ;
// "where" remaps the file to client file tree
2009-12-11 16:43:39 +01:00
QStringList args ;
2008-12-02 12:01:29 +01:00
args < < QLatin1String ( " where " ) < < perforceName ;
2009-12-11 16:43:39 +01:00
const PerforceResponse response = runP4Cmd ( m_settings . topLevelSymLinkTarget ( ) , args ,
RunFullySynchronous | CommandToWindow | StdErrToWindow | ErrorToWindow ) ;
if ( response . error ) {
* errorMessage = msgWhereFailed ( perforceName , response . message ) ;
return QString : : null ;
2008-12-02 12:01:29 +01:00
}
2009-12-11 16:43:39 +01:00
QString output = response . stdOut ;
2008-12-02 12:01:29 +01:00
if ( output . endsWith ( QLatin1Char ( ' \r ' ) ) )
output . chop ( 1 ) ;
if ( output . endsWith ( QLatin1Char ( ' \n ' ) ) )
output . chop ( 1 ) ;
if ( output . isEmpty ( ) ) {
2009-12-11 16:43:39 +01:00
* errorMessage = msgWhereFailed ( perforceName , tr ( " The file is not mapped " ) ) ;
2008-12-02 12:01:29 +01:00
return QString ( ) ;
}
2009-12-11 16:43:39 +01:00
const QString p4fileSpec = output . mid ( output . lastIndexOf ( QLatin1Char ( ' ' ) ) + 1 ) ;
const QString rc = m_settings . mapToFileSystem ( p4fileSpec ) ;
2008-12-02 12:01:29 +01:00
if ( Perforce : : Constants : : debug )
2009-12-11 16:43:39 +01:00
qDebug ( ) < < " fileNameFromPerforceName " < < perforceName < < p4fileSpec < < rc ;
2008-12-02 12:01:29 +01:00
return rc ;
}
2008-12-09 15:25:01 +01:00
PerforcePlugin * PerforcePlugin : : perforcePluginInstance ( )
{
QTC_ASSERT ( m_perforcePluginInstance , return 0 ) ;
return m_perforcePluginInstance ;
}
2009-12-08 14:26:41 +01:00
PerforceVersionControl * PerforcePlugin : : perforceVersionControl ( ) const
{
return static_cast < PerforceVersionControl * > ( versionControl ( ) ) ;
}
2009-12-11 16:43:39 +01:00
void PerforcePlugin : : slotTopLevelFound ( const QString & t )
{
m_settings . setTopLevel ( t ) ;
VCSBase : : VCSBaseOutputWindow : : instance ( ) - > appendSilently ( tr ( " Perforce repository: %1 " ) . arg ( t ) ) ;
if ( Perforce : : Constants : : debug )
qDebug ( ) < < " P4: " < < t ;
}
void PerforcePlugin : : slotTopLevelFailed ( const QString & errorMessage )
{
2009-12-14 09:26:29 +01:00
VCSBase : : VCSBaseOutputWindow : : instance ( ) - > appendSilently ( tr ( " Perforce: Unable to determine the repository: %1 " ) . arg ( errorMessage ) ) ;
2009-12-11 16:43:39 +01:00
if ( Perforce : : Constants : : debug )
qDebug ( ) < < errorMessage ;
}
void PerforcePlugin : : getTopLevel ( )
{
// Run a new checker
if ( m_settings . p4Command ( ) . isEmpty ( ) )
return ;
PerforceChecker * checker = new PerforceChecker ( this ) ;
connect ( checker , SIGNAL ( failed ( QString ) ) , this , SLOT ( slotTopLevelFailed ( QString ) ) ) ;
connect ( checker , SIGNAL ( failed ( QString ) ) , checker , SLOT ( deleteLater ( ) ) ) ;
connect ( checker , SIGNAL ( succeeded ( QString ) ) , this , SLOT ( slotTopLevelFound ( QString ) ) ) ;
connect ( checker , SIGNAL ( succeeded ( QString ) ) , checker , SLOT ( deleteLater ( ) ) ) ;
checker - > start ( m_settings . p4Command ( ) , m_settings . commonP4Arguments ( QString ( ) ) , 30000 ) ;
}
}
}
2008-12-02 12:01:29 +01:00
2009-12-11 16:43:39 +01:00
Q_EXPORT_PLUGIN ( Perforce : : Internal : : PerforcePlugin )