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
* *
* * Contact : Qt Software Information ( qt - info @ nokia . com )
* *
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
* * contact the sales department at qt - sales @ nokia . com .
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 "subversionplugin.h"
# include "settingspage.h"
# include "subversioneditor.h"
# include "subversionoutputwindow.h"
# include "subversionsubmiteditor.h"
# include "subversionconstants.h"
# include "subversioncontrol.h"
# include <vcsbase/basevcseditorfactory.h>
# include <vcsbase/vcsbaseeditor.h>
# include <vcsbase/basevcssubmiteditorfactory.h>
# 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 <coreplugin/icore.h>
# include <coreplugin/coreconstants.h>
# include <coreplugin/filemanager.h>
# include <coreplugin/messagemanager.h>
# include <coreplugin/mimedatabase.h>
# include <coreplugin/uniqueidmanager.h>
2009-01-13 13:39:31 +01:00
# include <coreplugin/actionmanager/actionmanager.h>
2008-12-02 12:01:29 +01:00
# include <coreplugin/editormanager/editormanager.h>
2009-01-14 15:08:46 +01:00
# include <projectexplorer/projectexplorer.h>
2008-12-09 15:25:01 +01:00
# include <utils/qtcassert.h>
2008-12-02 12:01:29 +01:00
# include <QtCore/QDebug>
2009-01-19 12:39:20 +01:00
# include <QtCore/QDir>
2008-12-02 12:01:29 +01:00
# include <QtCore/QFileInfo>
# include <QtCore/QTemporaryFile>
2009-01-19 12:39:20 +01:00
# include <QtCore/QTextCodec>
# include <QtCore/QtPlugin>
2008-12-02 12:01:29 +01:00
# include <QtGui/QAction>
2009-01-19 12:39:20 +01:00
# include <QtGui/QFileDialog>
# include <QtGui/QMainWindow>
2008-12-02 12:01:29 +01:00
# include <QtGui/QMenu>
# include <QtGui/QMessageBox>
2009-02-09 17:33:31 +01:00
# include <QtGui/QInputDialog>
# include <limits.h>
2008-12-02 12:01:29 +01:00
using namespace Subversion : : Internal ;
// Timeout for normal output commands
enum { subversionShortTimeOut = 10000 } ;
// Timeout for submit, update
enum { subversionLongTimeOut = 120000 } ;
// #pragma mark -- SubversionPlugin
const char * const SubversionPlugin : : SUBVERSION_MENU = " Subversion.Menu " ;
const char * const SubversionPlugin : : ADD = " Subversion.Add " ;
const char * const SubversionPlugin : : DELETE_FILE = " Subversion.Delete " ;
const char * const SubversionPlugin : : REVERT = " Subversion.Revert " ;
const char * const SubversionPlugin : : SEPARATOR0 = " Subversion.Separator0 " ;
const char * const SubversionPlugin : : DIFF_PROJECT = " Subversion.DiffAll " ;
const char * const SubversionPlugin : : DIFF_CURRENT = " Subversion.DiffCurrent " ;
const char * const SubversionPlugin : : SEPARATOR1 = " Subversion.Separator1 " ;
const char * const SubversionPlugin : : COMMIT_ALL = " Subversion.CommitAll " ;
const char * const SubversionPlugin : : COMMIT_CURRENT = " Subversion.CommitCurrent " ;
const char * const SubversionPlugin : : SEPARATOR2 = " Subversion.Separator2 " ;
const char * const SubversionPlugin : : FILELOG_CURRENT = " Subversion.FilelogCurrent " ;
const char * const SubversionPlugin : : ANNOTATE_CURRENT = " Subversion.AnnotateCurrent " ;
const char * const SubversionPlugin : : SEPARATOR3 = " Subversion.Separator3 " ;
const char * const SubversionPlugin : : STATUS = " Subversion.Status " ;
const char * const SubversionPlugin : : UPDATE = " Subversion.Update " ;
2009-02-09 17:33:31 +01:00
const char * const SubversionPlugin : : DESCRIBE = " Subversion.Describe " ;
2008-12-02 12:01:29 +01:00
2009-05-05 10:16:09 +02:00
static const char * nonInteractiveOptionC = " --non-interactive " ;
2008-12-02 12:01:29 +01:00
static const VCSBase : : VCSBaseEditorParameters editorParameters [ ] = {
{
VCSBase : : RegularCommandOutput ,
2009-02-16 12:50:15 +01:00
" Subversion Command Log Editor " , // kind
" Subversion Command Log Editor " , // context
2008-12-02 12:01:29 +01:00
" application/vnd.nokia.text.scs_svn_commandlog " ,
" scslog " } ,
{ VCSBase : : LogOutput ,
2009-02-16 12:50:15 +01:00
" Subversion File Log Editor " , // kind
" Subversion File Log Editor " , // context
2008-12-02 12:01:29 +01:00
" application/vnd.nokia.text.scs_svn_filelog " ,
" scsfilelog " } ,
{ VCSBase : : AnnotateOutput ,
2009-02-16 12:50:15 +01:00
" Subversion Annotation Editor " , // kind
" Subversion Annotation Editor " , // context
2008-12-02 12:01:29 +01:00
" application/vnd.nokia.text.scs_svn_annotation " ,
" scsannotate " } ,
{ VCSBase : : DiffOutput ,
2009-02-16 12:50:15 +01:00
" Subversion Diff Editor " , // kind
" Subversion 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-01-20 17:14:00 +01:00
Core : : IEditor * locateEditor ( const char * property , const QString & entry )
2008-12-02 12:01:29 +01:00
{
2009-01-21 15:52:34 +01:00
foreach ( Core : : IEditor * ed , Core : : EditorManager : : instance ( ) - > openedEditors ( ) )
2008-12-02 12:01:29 +01:00
if ( ed - > property ( property ) . toString ( ) = = entry )
return ed ;
return 0 ;
}
2009-01-12 17:44:04 +01:00
// Parse "svn status" output for added/modified/deleted files
// "M<7blanks>file"
typedef QList < SubversionSubmitEditor : : StatusFilePair > StatusList ;
StatusList parseStatusOutput ( const QString & output )
{
StatusList changeSet ;
const QString newLine = QString ( QLatin1Char ( ' \n ' ) ) ;
const QStringList list = output . split ( newLine , QString : : SkipEmptyParts ) ;
foreach ( const QString & l , list ) {
const QString line = l . trimmed ( ) ;
if ( line . size ( ) > 8 ) {
const QChar state = line . at ( 0 ) ;
if ( state = = QLatin1Char ( ' A ' ) | | state = = QLatin1Char ( ' D ' ) | | state = = QLatin1Char ( ' M ' ) ) {
2009-04-03 12:17:33 +02:00
const QString fileName = line . mid ( 7 ) ; // Column 8 starting from svn 1.6
changeSet . push_back ( SubversionSubmitEditor : : StatusFilePair ( QString ( state ) , fileName . trimmed ( ) ) ) ;
2009-01-12 17:44:04 +01:00
}
}
}
return changeSet ;
}
2009-05-26 12:25:32 +02:00
// Return a list of names for the internal svn directories
static inline QStringList svnDirectories ( )
{
QStringList rc ( QLatin1String ( " .svn " ) ) ;
# ifdef Q_OS_WIN
// Option on Windows systems to avoid hassle with some IDEs
rc . push_back ( QLatin1String ( " _svn " ) ) ;
# endif
return rc ;
}
2008-12-02 12:01:29 +01:00
// ------------- SubversionPlugin
SubversionPlugin * SubversionPlugin : : m_subversionPluginInstance = 0 ;
SubversionPlugin : : SubversionPlugin ( ) :
2009-05-26 12:25:32 +02:00
m_svnDirectories ( svnDirectories ( ) ) ,
2008-12-02 12:01:29 +01:00
m_versionControl ( 0 ) ,
m_coreListener ( 0 ) ,
m_settingsPage ( 0 ) ,
m_changeTmpFile ( 0 ) ,
m_submitEditorFactory ( 0 ) ,
m_subversionOutputWindow ( 0 ) ,
m_projectExplorer ( 0 ) ,
m_addAction ( 0 ) ,
m_deleteAction ( 0 ) ,
m_revertAction ( 0 ) ,
m_diffProjectAction ( 0 ) ,
m_diffCurrentAction ( 0 ) ,
m_commitAllAction ( 0 ) ,
m_commitCurrentAction ( 0 ) ,
m_filelogCurrentAction ( 0 ) ,
m_annotateCurrentAction ( 0 ) ,
m_statusAction ( 0 ) ,
m_updateProjectAction ( 0 ) ,
2009-02-09 17:33:31 +01:00
m_describeAction ( 0 ) ,
2008-12-02 12:01:29 +01:00
m_submitCurrentLogAction ( 0 ) ,
m_submitDiffAction ( 0 ) ,
m_submitUndoAction ( 0 ) ,
2009-03-20 10:16:18 +01:00
m_submitRedoAction ( 0 ) ,
m_submitActionTriggered ( false )
2008-12-02 12:01:29 +01:00
{
}
SubversionPlugin : : ~ SubversionPlugin ( )
{
if ( m_versionControl ) {
removeObject ( m_versionControl ) ;
delete m_versionControl ;
m_versionControl = 0 ;
}
if ( m_settingsPage ) {
removeObject ( m_settingsPage ) ;
delete m_settingsPage ;
m_settingsPage = 0 ;
}
if ( m_subversionOutputWindow ) {
removeObject ( m_subversionOutputWindow ) ;
delete m_subversionOutputWindow ;
m_subversionOutputWindow = 0 ;
}
if ( m_submitEditorFactory ) {
removeObject ( m_submitEditorFactory ) ;
delete m_submitEditorFactory ;
m_submitEditorFactory = 0 ;
}
if ( ! m_editorFactories . empty ( ) ) {
2008-12-09 11:07:24 +01:00
foreach ( Core : : IEditorFactory * pf , m_editorFactories )
2008-12-02 12:01:29 +01:00
removeObject ( pf ) ;
qDeleteAll ( m_editorFactories ) ;
m_editorFactories . clear ( ) ;
}
if ( m_coreListener ) {
removeObject ( m_coreListener ) ;
delete m_coreListener ;
m_coreListener = 0 ;
}
cleanChangeTmpFile ( ) ;
}
void SubversionPlugin : : cleanChangeTmpFile ( )
{
if ( m_changeTmpFile ) {
if ( m_changeTmpFile - > isOpen ( ) )
m_changeTmpFile - > close ( ) ;
delete m_changeTmpFile ;
m_changeTmpFile = 0 ;
}
}
static const VCSBase : : VCSBaseSubmitEditorParameters submitParameters = {
Subversion : : Constants : : SUBVERSION_SUBMIT_MIMETYPE ,
Subversion : : Constants : : SUBVERSIONCOMMITEDITOR_KIND ,
2009-01-13 14:06:42 +01:00
Subversion : : Constants : : SUBVERSIONCOMMITEDITOR
2008-12-02 12:01:29 +01:00
} ;
2009-02-09 17:33:31 +01:00
static inline Core : : Command * createSeparator ( QObject * parent ,
Core : : ActionManager * ami ,
const char * id ,
const QList < int > & globalcontext )
{
QAction * tmpaction = new QAction ( parent ) ;
tmpaction - > setSeparator ( true ) ;
return ami - > registerAction ( tmpaction , id , globalcontext ) ;
}
2009-01-20 11:52:04 +01:00
bool SubversionPlugin : : initialize ( const QStringList & arguments , QString * errorMessage )
2008-12-02 12:01:29 +01:00
{
2009-01-20 11:52:04 +01:00
Q_UNUSED ( arguments ) ;
2008-12-02 12:01:29 +01:00
typedef VCSBase : : VCSSubmitEditorFactory < SubversionSubmitEditor > SubversionSubmitEditorFactory ;
typedef VCSBase : : VCSEditorFactory < SubversionEditor > SubversionEditorFactory ;
using namespace Constants ;
using namespace Core : : Constants ;
using namespace ExtensionSystem ;
m_subversionPluginInstance = this ;
2009-01-20 17:14:00 +01:00
Core : : ICore * core = Core : : ICore : : instance ( ) ;
2008-12-02 12:01:29 +01:00
2009-01-20 17:14:00 +01:00
if ( ! core - > mimeDatabase ( ) - > addMimeTypes ( QLatin1String ( " :/trolltech.subversion/Subversion.mimetypes.xml " ) , errorMessage ) )
2008-12-02 12:01:29 +01:00
return false ;
m_versionControl = new SubversionControl ( this ) ;
addObject ( m_versionControl ) ;
2009-01-20 17:14:00 +01:00
if ( QSettings * settings = core - > settings ( ) )
2008-12-02 12:01:29 +01:00
m_settings . fromSettings ( settings ) ;
m_coreListener = new CoreListener ( this ) ;
addObject ( m_coreListener ) ;
m_settingsPage = new SettingsPage ;
addObject ( m_settingsPage ) ;
m_submitEditorFactory = new SubversionSubmitEditorFactory ( & submitParameters ) ;
addObject ( m_submitEditorFactory ) ;
static const char * describeSlot = SLOT ( describe ( QString , QString ) ) ;
const int editorCount = sizeof ( editorParameters ) / sizeof ( VCSBase : : VCSBaseEditorParameters ) ;
for ( int i = 0 ; i < editorCount ; i + + ) {
2009-01-20 15:31:33 +01:00
m_editorFactories . push_back (
new SubversionEditorFactory ( editorParameters + i , this , describeSlot ) ) ;
2008-12-02 12:01:29 +01:00
addObject ( m_editorFactories . back ( ) ) ;
}
m_subversionOutputWindow = new SubversionOutputWindow ( this ) ;
addObject ( m_subversionOutputWindow ) ;
//register actions
2009-01-20 17:14:00 +01:00
Core : : ActionManager * ami = core - > actionManager ( ) ;
2009-01-14 12:39:59 +01:00
Core : : ActionContainer * toolsContainer = ami - > actionContainer ( M_TOOLS ) ;
2008-12-02 12:01:29 +01:00
2009-01-14 12:39:59 +01:00
Core : : ActionContainer * subversionMenu =
2008-12-02 12:01:29 +01:00
ami - > createMenu ( QLatin1String ( SUBVERSION_MENU ) ) ;
subversionMenu - > menu ( ) - > setTitle ( tr ( " &Subversion " ) ) ;
toolsContainer - > addMenu ( subversionMenu ) ;
2008-12-03 15:04:51 +01:00
if ( QAction * ma = subversionMenu - > menu ( ) - > menuAction ( ) ) {
ma - > setEnabled ( m_versionControl - > isEnabled ( ) ) ;
connect ( m_versionControl , SIGNAL ( enabledChanged ( bool ) ) , ma , SLOT ( setVisible ( bool ) ) ) ;
}
2008-12-02 12:01:29 +01:00
QList < int > globalcontext ;
2009-01-20 17:14:00 +01:00
globalcontext < < core - > uniqueIDManager ( ) - > uniqueIdentifier ( C_GLOBAL ) ;
2008-12-02 12:01:29 +01:00
2009-01-14 13:17:53 +01:00
Core : : Command * command ;
2009-05-15 15:41:00 +02:00
m_addAction = new Core : : Utils : : ParameterAction ( tr ( " Add " ) , tr ( " Add \" %1 \" " ) , Core : : Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2008-12-02 12:01:29 +01:00
command = ami - > registerAction ( m_addAction , SubversionPlugin : : ADD ,
globalcontext ) ;
2009-01-14 13:17:53 +01:00
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2009-03-05 15:26:48 +01:00
# ifndef Q_OS_MAC
2008-12-02 12:01:29 +01:00
command - > setDefaultKeySequence ( QKeySequence ( tr ( " Alt+S,Alt+A " ) ) ) ;
2009-03-05 15:26:48 +01:00
# endif
2008-12-02 12:01:29 +01:00
connect ( m_addAction , SIGNAL ( triggered ( ) ) , this , SLOT ( addCurrentFile ( ) ) ) ;
subversionMenu - > addAction ( command ) ;
2009-05-15 15:41:00 +02:00
m_deleteAction = new Core : : Utils : : ParameterAction ( tr ( " Delete " ) , tr ( " Delete \" %1 \" " ) , Core : : Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2008-12-02 12:01:29 +01:00
command = ami - > registerAction ( m_deleteAction , SubversionPlugin : : 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
connect ( m_deleteAction , SIGNAL ( triggered ( ) ) , this , SLOT ( deleteCurrentFile ( ) ) ) ;
subversionMenu - > addAction ( command ) ;
2009-05-15 15:41:00 +02:00
m_revertAction = new Core : : Utils : : ParameterAction ( tr ( " Revert " ) , tr ( " Revert \" %1 \" " ) , Core : : Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2008-12-02 12:01:29 +01:00
command = ami - > registerAction ( m_revertAction , SubversionPlugin : : REVERT ,
globalcontext ) ;
2009-01-14 13:17:53 +01:00
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2008-12-02 12:01:29 +01:00
connect ( m_revertAction , SIGNAL ( triggered ( ) ) , this , SLOT ( revertCurrentFile ( ) ) ) ;
subversionMenu - > addAction ( command ) ;
2009-02-09 17:33:31 +01:00
subversionMenu - > addAction ( createSeparator ( this , ami , SubversionPlugin : : SEPARATOR0 , globalcontext ) ) ;
2008-12-02 12:01:29 +01:00
m_diffProjectAction = new QAction ( tr ( " Diff Project " ) , this ) ;
command = ami - > registerAction ( m_diffProjectAction , SubversionPlugin : : DIFF_PROJECT ,
globalcontext ) ;
connect ( m_diffProjectAction , SIGNAL ( triggered ( ) ) , this , SLOT ( diffProject ( ) ) ) ;
subversionMenu - > addAction ( command ) ;
2009-05-15 15:41:00 +02:00
m_diffCurrentAction = new Core : : Utils : : ParameterAction ( tr ( " Diff Current File " ) , tr ( " Diff \" %1 \" " ) , Core : : Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2008-12-02 12:01:29 +01:00
command = ami - > registerAction ( m_diffCurrentAction ,
SubversionPlugin : : DIFF_CURRENT , globalcontext ) ;
2009-01-14 13:17:53 +01:00
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2009-03-05 15:26:48 +01:00
# ifndef Q_OS_MAC
2008-12-02 12:01:29 +01:00
command - > setDefaultKeySequence ( QKeySequence ( tr ( " Alt+S,Alt+D " ) ) ) ;
2009-03-05 15:26:48 +01:00
# endif
2008-12-02 12:01:29 +01:00
connect ( m_diffCurrentAction , SIGNAL ( triggered ( ) ) , this , SLOT ( diffCurrentFile ( ) ) ) ;
subversionMenu - > addAction ( command ) ;
2009-02-09 17:33:31 +01:00
subversionMenu - > addAction ( createSeparator ( this , ami , SubversionPlugin : : SEPARATOR1 , globalcontext ) ) ;
2008-12-02 12:01:29 +01:00
m_commitAllAction = new QAction ( tr ( " Commit All Files " ) , this ) ;
command = ami - > registerAction ( m_commitAllAction , SubversionPlugin : : COMMIT_ALL ,
globalcontext ) ;
connect ( m_commitAllAction , SIGNAL ( triggered ( ) ) , this , SLOT ( startCommitAll ( ) ) ) ;
subversionMenu - > addAction ( command ) ;
2009-05-15 15:41:00 +02:00
m_commitCurrentAction = new Core : : Utils : : ParameterAction ( tr ( " Commit Current File " ) , tr ( " Commit \" %1 \" " ) , Core : : Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2008-12-02 12:01:29 +01:00
command = ami - > registerAction ( m_commitCurrentAction ,
SubversionPlugin : : COMMIT_CURRENT , globalcontext ) ;
2009-01-14 13:17:53 +01:00
command - > setAttribute ( Core : : Command : : CA_UpdateText ) ;
2009-03-05 15:26:48 +01:00
# ifndef Q_OS_MAC
2008-12-02 12:01:29 +01:00
command - > setDefaultKeySequence ( QKeySequence ( tr ( " Alt+S,Alt+C " ) ) ) ;
2009-03-05 15:26:48 +01:00
# endif
2008-12-02 12:01:29 +01:00
connect ( m_commitCurrentAction , SIGNAL ( triggered ( ) ) , this , SLOT ( startCommitCurrentFile ( ) ) ) ;
subversionMenu - > addAction ( command ) ;
2009-02-09 17:33:31 +01:00
subversionMenu - > addAction ( createSeparator ( this , ami , SubversionPlugin : : SEPARATOR2 , globalcontext ) ) ;
2008-12-02 12:01:29 +01:00
2009-05-15 15:41:00 +02:00
m_filelogCurrentAction = new Core : : Utils : : ParameterAction ( tr ( " Filelog Current File " ) , tr ( " Filelog \" %1 \" " ) , Core : : Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2008-12-02 12:01:29 +01:00
command = ami - > registerAction ( m_filelogCurrentAction ,
SubversionPlugin : : 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
connect ( m_filelogCurrentAction , SIGNAL ( triggered ( ) ) , this ,
SLOT ( filelogCurrentFile ( ) ) ) ;
subversionMenu - > addAction ( command ) ;
2009-05-15 15:41:00 +02:00
m_annotateCurrentAction = new Core : : Utils : : ParameterAction ( tr ( " Annotate Current File " ) , tr ( " Annotate \" %1 \" " ) , Core : : Utils : : ParameterAction : : EnabledWithParameter , this ) ;
2008-12-02 12:01:29 +01:00
command = ami - > registerAction ( m_annotateCurrentAction ,
SubversionPlugin : : 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
connect ( m_annotateCurrentAction , SIGNAL ( triggered ( ) ) , this ,
SLOT ( annotateCurrentFile ( ) ) ) ;
subversionMenu - > addAction ( command ) ;
2009-02-09 17:33:31 +01:00
m_describeAction = new QAction ( tr ( " Describe... " ) , this ) ;
command = ami - > registerAction ( m_describeAction , SubversionPlugin : : DESCRIBE , globalcontext ) ;
connect ( m_describeAction , SIGNAL ( triggered ( ) ) , this , SLOT ( slotDescribe ( ) ) ) ;
subversionMenu - > addAction ( command ) ;
subversionMenu - > addAction ( createSeparator ( this , ami , SubversionPlugin : : SEPARATOR3 , globalcontext ) ) ;
2008-12-02 12:01:29 +01:00
m_statusAction = new QAction ( tr ( " Project Status " ) , this ) ;
command = ami - > registerAction ( m_statusAction , SubversionPlugin : : STATUS ,
globalcontext ) ;
connect ( m_statusAction , SIGNAL ( triggered ( ) ) , this , SLOT ( projectStatus ( ) ) ) ;
subversionMenu - > addAction ( command ) ;
m_updateProjectAction = new QAction ( tr ( " Update Project " ) , this ) ;
command = ami - > registerAction ( m_updateProjectAction , SubversionPlugin : : UPDATE , globalcontext ) ;
connect ( m_updateProjectAction , SIGNAL ( triggered ( ) ) , this , SLOT ( updateProject ( ) ) ) ;
subversionMenu - > addAction ( command ) ;
// Actions of the submit editor
QList < int > svncommitcontext ;
2009-01-21 15:52:34 +01:00
svncommitcontext < < Core : : UniqueIDManager : : instance ( ) - > uniqueIdentifier ( Constants : : SUBVERSIONCOMMITEDITOR ) ;
2008-12-02 12:01:29 +01:00
2008-12-02 17:05:53 +01:00
m_submitCurrentLogAction = new QAction ( VCSBase : : VCSBaseSubmitEditor : : submitIcon ( ) , tr ( " Commit " ) , this ) ;
2008-12-02 12:01:29 +01:00
command = ami - > registerAction ( m_submitCurrentLogAction , Constants : : SUBMIT_CURRENT , svncommitcontext ) ;
connect ( m_submitCurrentLogAction , SIGNAL ( triggered ( ) ) , this , SLOT ( submitCurrentLog ( ) ) ) ;
2008-12-02 17:05:53 +01:00
m_submitDiffAction = new QAction ( VCSBase : : VCSBaseSubmitEditor : : diffIcon ( ) , tr ( " Diff Selected Files " ) , this ) ;
2008-12-02 12:01:29 +01:00
command = ami - > registerAction ( m_submitDiffAction , Constants : : DIFF_SELECTED , svncommitcontext ) ;
m_submitUndoAction = new QAction ( tr ( " &Undo " ) , this ) ;
command = ami - > registerAction ( m_submitUndoAction , Core : : Constants : : UNDO , svncommitcontext ) ;
m_submitRedoAction = new QAction ( tr ( " &Redo " ) , this ) ;
command = ami - > registerAction ( m_submitRedoAction , Core : : Constants : : REDO , svncommitcontext ) ;
2009-01-20 17:14:00 +01:00
connect ( Core : : ICore : : instance ( ) , SIGNAL ( contextChanged ( Core : : IContext * ) ) , this , SLOT ( updateActions ( ) ) ) ;
2008-12-02 12:01:29 +01:00
return true ;
}
void SubversionPlugin : : extensionsInitialized ( )
{
2009-03-04 09:38:01 +01:00
m_projectExplorer = ProjectExplorer : : ProjectExplorerPlugin : : instance ( ) ;
2008-12-02 12:01:29 +01:00
if ( m_projectExplorer ) {
connect ( m_projectExplorer ,
SIGNAL ( currentProjectChanged ( ProjectExplorer : : Project * ) ) ,
m_subversionPluginInstance , SLOT ( updateActions ( ) ) ) ;
}
updateActions ( ) ;
}
bool SubversionPlugin : : editorAboutToClose ( Core : : IEditor * iEditor )
{
if ( ! m_changeTmpFile | | ! iEditor | | qstrcmp ( Constants : : SUBVERSIONCOMMITEDITOR , iEditor - > kind ( ) ) )
return true ;
Core : : IFile * fileIFace = iEditor - > file ( ) ;
const SubversionSubmitEditor * editor = qobject_cast < SubversionSubmitEditor * > ( iEditor ) ;
if ( ! fileIFace | | ! editor )
return true ;
// Submit editor closing. Make it write out the commit message
// and retrieve files
const QFileInfo editorFile ( fileIFace - > fileName ( ) ) ;
const QFileInfo changeFile ( m_changeTmpFile - > fileName ( ) ) ;
if ( editorFile . absoluteFilePath ( ) ! = changeFile . absoluteFilePath ( ) )
return true ; // Oops?!
2009-03-20 10:16:18 +01:00
// Prompt user. Force a prompt unless submit was actually invoked (that
// is, the editor was closed or shutdown).
2009-03-19 17:40:01 +01:00
const VCSBase : : VCSBaseSubmitEditor : : PromptSubmitResult answer =
editor - > promptSubmit ( tr ( " Closing Subversion Editor " ) ,
tr ( " Do you want to commit the change? " ) ,
2009-03-20 10:16:18 +01:00
tr ( " The commit message check failed. Do you want to commit the change? " ) ,
! m_submitActionTriggered ) ;
m_submitActionTriggered = false ;
2008-12-02 12:01:29 +01:00
switch ( answer ) {
2009-03-19 17:40:01 +01:00
case VCSBase : : VCSBaseSubmitEditor : : SubmitCanceled :
2008-12-02 12:01:29 +01:00
return false ; // Keep editing and change file
2009-03-19 17:40:01 +01:00
case VCSBase : : VCSBaseSubmitEditor : : SubmitDiscarded :
2008-12-02 12:01:29 +01:00
cleanChangeTmpFile ( ) ;
return true ; // Cancel all
default :
break ;
}
const QStringList fileList = editor - > checkedFiles ( ) ;
2009-03-20 16:52:22 +01:00
bool closeEditor = true ;
2008-12-02 12:01:29 +01:00
if ( ! fileList . empty ( ) ) {
// get message & commit
2009-01-20 17:14:00 +01:00
Core : : ICore : : instance ( ) - > fileManager ( ) - > blockFileChange ( fileIFace ) ;
2008-12-02 12:01:29 +01:00
fileIFace - > save ( ) ;
2009-01-20 17:14:00 +01:00
Core : : ICore : : instance ( ) - > fileManager ( ) - > unblockFileChange ( fileIFace ) ;
2009-03-20 16:52:22 +01:00
closeEditor = commit ( m_changeTmpFile - > fileName ( ) , fileList ) ;
2008-12-02 12:01:29 +01:00
}
2009-03-20 16:52:22 +01:00
if ( closeEditor )
cleanChangeTmpFile ( ) ;
return closeEditor ;
2008-12-02 12:01:29 +01:00
}
void SubversionPlugin : : diffFiles ( const QStringList & files )
{
svnDiff ( files ) ;
}
void SubversionPlugin : : svnDiff ( const QStringList & files , QString diffname )
{
if ( Subversion : : Constants : : debug )
qDebug ( ) < < Q_FUNC_INFO < < files < < diffname ;
const QString source = files . empty ( ) ? QString ( ) : files . front ( ) ;
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
if ( files . count ( ) = = 1 & & diffname . isEmpty ( ) )
diffname = QFileInfo ( files . front ( ) ) . fileName ( ) ;
QStringList args ( QLatin1String ( " diff " ) ) ;
args < < files ;
const SubversionResponse response = runSvn ( args , subversionShortTimeOut , false , codec ) ;
if ( response . error )
return ;
// 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
if ( files . count ( ) = = 1 ) {
// Show in the same editor if diff has been executed before
2009-01-20 17:14:00 +01:00
if ( Core : : IEditor * editor = locateEditor ( " originalFileName " , files . front ( ) ) ) {
2008-12-02 12:01:29 +01:00
editor - > createNew ( response . stdOut ) ;
2009-01-26 16:36:02 +01:00
Core : : EditorManager : : instance ( ) - > activateEditor ( editor ) ;
2008-12-02 12:01:29 +01:00
return ;
}
}
2009-04-17 21:00:10 +02:00
const QString title = QString : : fromLatin1 ( " svn diff %1 " ) . arg ( diffname ) ;
2008-12-02 12:01:29 +01:00
Core : : IEditor * editor = showOutputInEditor ( title , response . stdOut , VCSBase : : DiffOutput , source , codec ) ;
if ( files . count ( ) = = 1 )
editor - > setProperty ( " originalFileName " , files . front ( ) ) ;
}
SubversionSubmitEditor * SubversionPlugin : : openSubversionSubmitEditor ( const QString & fileName )
{
2009-01-21 15:52:34 +01:00
Core : : IEditor * editor = Core : : EditorManager : : instance ( ) - > openEditor ( fileName , QLatin1String ( Constants : : SUBVERSIONCOMMITEDITOR_KIND ) ) ;
2008-12-02 12:01:29 +01:00
SubversionSubmitEditor * submitEditor = qobject_cast < SubversionSubmitEditor * > ( editor ) ;
2008-12-09 15:25:01 +01:00
QTC_ASSERT ( submitEditor , /**/ ) ;
2009-01-13 14:06:42 +01:00
submitEditor - > registerActions ( m_submitUndoAction , m_submitRedoAction , m_submitCurrentLogAction , m_submitDiffAction ) ;
2008-12-02 12:01:29 +01:00
connect ( submitEditor , SIGNAL ( diffSelectedFiles ( QStringList ) ) , this , SLOT ( diffFiles ( QStringList ) ) ) ;
return submitEditor ;
}
void SubversionPlugin : : updateActions ( )
{
m_diffProjectAction - > setEnabled ( true ) ;
m_commitAllAction - > setEnabled ( true ) ;
m_statusAction - > setEnabled ( true ) ;
2009-02-09 17:33:31 +01:00
m_describeAction - > setEnabled ( true ) ;
2008-12-02 12:01:29 +01:00
2009-05-15 15:41:00 +02:00
const QString fileName = currentFileName ( ) ;
const QString baseName = fileName . isEmpty ( ) ? fileName : QFileInfo ( fileName ) . fileName ( ) ;
m_addAction - > setParameter ( baseName ) ;
m_deleteAction - > setParameter ( baseName ) ;
m_revertAction - > setParameter ( baseName ) ;
m_diffCurrentAction - > setParameter ( baseName ) ;
m_commitCurrentAction - > setParameter ( baseName ) ;
m_filelogCurrentAction - > setParameter ( baseName ) ;
m_annotateCurrentAction - > setParameter ( baseName ) ;
2008-12-02 12:01:29 +01:00
}
void SubversionPlugin : : addCurrentFile ( )
{
const QString file = currentFileName ( ) ;
if ( ! file . isEmpty ( ) )
vcsAdd ( file ) ;
}
void SubversionPlugin : : deleteCurrentFile ( )
{
const QString file = currentFileName ( ) ;
if ( ! file . isEmpty ( ) )
vcsDelete ( file ) ;
}
void SubversionPlugin : : revertCurrentFile ( )
{
const QString file = QDir : : toNativeSeparators ( currentFileName ( ) ) ;
if ( file . isEmpty ( ) )
return ;
QStringList args ( QLatin1String ( " diff " ) ) ;
args . push_back ( file ) ;
const SubversionResponse diffResponse = runSvn ( args , subversionShortTimeOut , false ) ;
if ( diffResponse . error )
return ;
if ( diffResponse . stdOut . isEmpty ( ) )
return ;
2009-04-17 21:00:10 +02:00
if ( QMessageBox : : warning ( 0 , QLatin1String ( " svn revert " ) , tr ( " The file has been changed. Do you want to revert it? " ) ,
2008-12-02 12:01:29 +01:00
QMessageBox : : Yes , QMessageBox : : No ) = = QMessageBox : : No )
return ;
2009-01-20 17:14:00 +01:00
Core : : FileManager * fm = Core : : ICore : : instance ( ) - > fileManager ( ) ;
2008-12-02 12:01:29 +01:00
QList < Core : : IFile * > files = fm - > managedFiles ( file ) ;
2008-12-09 11:07:24 +01:00
foreach ( Core : : IFile * file , files )
2008-12-02 12:01:29 +01:00
fm - > blockFileChange ( file ) ;
// revert
args . clear ( ) ;
args . push_back ( QLatin1String ( " revert " ) ) ;
args . append ( file ) ;
const SubversionResponse revertResponse = runSvn ( args , subversionShortTimeOut , true ) ;
if ( revertResponse . error ) {
foreach ( Core : : IFile * file , files )
fm - > unblockFileChange ( file ) ;
return ;
}
Core : : IFile : : ReloadBehavior tempBehavior = Core : : IFile : : ReloadAll ;
foreach ( Core : : IFile * file , files ) {
file - > modified ( & tempBehavior ) ;
fm - > unblockFileChange ( file ) ;
}
}
// Get a unique set of toplevel directories for the current projects.
// To be used for "diff all" or "commit all".
QStringList SubversionPlugin : : currentProjectsTopLevels ( QString * name ) const
{
typedef QList < ProjectExplorer : : Project * > ProjectList ;
ProjectList projects ;
// Compile list of projects
if ( ProjectExplorer : : Project * currentProject = m_projectExplorer - > currentProject ( ) ) {
projects . push_back ( currentProject ) ;
} else {
if ( const ProjectExplorer : : SessionManager * session = m_projectExplorer - > session ( ) )
projects . append ( session - > projects ( ) ) ;
}
// Get unique set of toplevels and concat project names
QStringList toplevels ;
const QChar blank ( QLatin1Char ( ' ' ) ) ;
foreach ( const ProjectExplorer : : Project * p , projects ) {
if ( name ) {
if ( ! name - > isEmpty ( ) )
name - > append ( blank ) ;
name - > append ( p - > name ( ) ) ;
}
const QString projectPath = QFileInfo ( p - > file ( ) - > fileName ( ) ) . absolutePath ( ) ;
const QString topLevel = findTopLevelForDirectory ( projectPath ) ;
if ( ! topLevel . isEmpty ( ) & & ! toplevels . contains ( topLevel ) )
toplevels . push_back ( topLevel ) ;
}
return toplevels ;
}
void SubversionPlugin : : diffProject ( )
{
QString diffName ;
const QStringList topLevels = currentProjectsTopLevels ( & diffName ) ;
if ( ! topLevels . isEmpty ( ) )
svnDiff ( topLevels , diffName ) ;
}
void SubversionPlugin : : diffCurrentFile ( )
{
svnDiff ( QStringList ( currentFileName ( ) ) ) ;
}
void SubversionPlugin : : startCommitCurrentFile ( )
{
const QString file = QDir : : toNativeSeparators ( currentFileName ( ) ) ;
if ( ! file . isEmpty ( ) )
startCommit ( QStringList ( file ) ) ;
}
void SubversionPlugin : : startCommitAll ( )
{
// Make sure we have only repository for commit
const QStringList files = currentProjectsTopLevels ( ) ;
switch ( files . size ( ) ) {
case 0 :
break ;
case 1 :
startCommit ( files ) ;
break ;
default : {
const QString msg = tr ( " The commit list spans several respositories (%1). Please commit them one by one. " ) .
arg ( files . join ( QString ( QLatin1Char ( ' ' ) ) ) ) ;
2009-04-17 21:00:10 +02:00
QMessageBox : : warning ( 0 , QLatin1String ( " svn commit " ) , msg , QMessageBox : : Ok ) ;
2008-12-02 12:01:29 +01:00
}
break ;
}
}
/* Start commit of files of a single repository by displaying
* template and files in a submit editor . On closing , the real
* commit will start . */
void SubversionPlugin : : startCommit ( const QStringList & files )
{
if ( files . empty ( ) )
return ;
if ( m_changeTmpFile ) {
showOutput ( tr ( " Another commit is currently being executed. " ) ) ;
return ;
}
QStringList args ( QLatin1String ( " status " ) ) ;
args + = files ;
if ( args . size ( ) = = 1 )
return ;
const SubversionResponse response = runSvn ( args , subversionShortTimeOut , false ) ;
if ( response . error )
return ;
// Get list of added/modified/deleted files
2009-01-12 17:44:04 +01:00
const StatusList statusOutput = parseStatusOutput ( response . stdOut ) ;
2008-12-02 12:01:29 +01:00
if ( statusOutput . empty ( ) ) {
showOutput ( tr ( " There are no modified files. " ) , true ) ;
return ;
}
// Create a new submit change file containing the submit template
QTemporaryFile * changeTmpFile = new QTemporaryFile ( this ) ;
changeTmpFile - > setAutoRemove ( true ) ;
if ( ! changeTmpFile - > open ( ) ) {
showOutput ( tr ( " Cannot create temporary file: %1 " ) . arg ( changeTmpFile - > errorString ( ) ) ) ;
delete changeTmpFile ;
return ;
}
m_changeTmpFile = changeTmpFile ;
// TODO: Retrieve submit template from
const QString submitTemplate ;
// Create a submit
m_changeTmpFile - > write ( submitTemplate . toUtf8 ( ) ) ;
m_changeTmpFile - > flush ( ) ;
m_changeTmpFile - > seek ( 0 ) ;
// Create a submit editor and set file list
SubversionSubmitEditor * editor = openSubversionSubmitEditor ( m_changeTmpFile - > fileName ( ) ) ;
2009-01-12 17:44:04 +01:00
editor - > setStatusList ( statusOutput ) ;
2008-12-02 12:01:29 +01:00
}
bool SubversionPlugin : : commit ( const QString & messageFile ,
const QStringList & subVersionFileList )
{
if ( Subversion : : Constants : : debug )
qDebug ( ) < < Q_FUNC_INFO < < messageFile < < subVersionFileList ;
// Transform the status list which is sth
// "[ADM]<blanks>file" into an args list. The files of the status log
// can be relative or absolute depending on where the command was run.
QStringList args = QStringList ( QLatin1String ( " commit " ) ) ;
2009-05-05 10:16:09 +02:00
args < < QLatin1String ( nonInteractiveOptionC ) < < QLatin1String ( " --file " ) < < messageFile ;
2008-12-02 12:01:29 +01:00
args . append ( subVersionFileList ) ;
const SubversionResponse response = runSvn ( args , subversionLongTimeOut , true ) ;
return ! response . error ;
}
void SubversionPlugin : : filelogCurrentFile ( )
{
const QString file = currentFileName ( ) ;
if ( ! file . isEmpty ( ) )
filelog ( file ) ;
}
void SubversionPlugin : : filelog ( const QString & file )
{
2009-01-20 11:52:04 +01:00
QTextCodec * codec = VCSBase : : VCSBaseEditor : : getCodec ( file ) ;
2008-12-02 12:01:29 +01:00
// no need for temp file
QStringList args ( QLatin1String ( " log " ) ) ;
args . append ( QDir : : toNativeSeparators ( file ) ) ;
const SubversionResponse response = runSvn ( args , subversionShortTimeOut , false , codec ) ;
if ( response . error )
return ;
// Re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
2009-01-20 17:14:00 +01:00
if ( Core : : IEditor * editor = locateEditor ( " logFileName " , file ) ) {
2008-12-02 12:01:29 +01:00
editor - > createNew ( response . stdOut ) ;
2009-01-26 16:36:02 +01:00
Core : : EditorManager : : instance ( ) - > activateEditor ( editor ) ;
2008-12-02 12:01:29 +01:00
} else {
2009-04-17 21:00:10 +02:00
const QString title = QString : : fromLatin1 ( " svn log %1 " ) . arg ( QFileInfo ( file ) . fileName ( ) ) ;
2008-12-02 12:01:29 +01:00
Core : : IEditor * newEditor = showOutputInEditor ( title , response . stdOut , VCSBase : : LogOutput , file , codec ) ;
newEditor - > setProperty ( " logFileName " , file ) ;
}
}
void SubversionPlugin : : updateProject ( )
{
const QStringList topLevels = currentProjectsTopLevels ( ) ;
if ( topLevels . empty ( ) )
return ;
QStringList args ( QLatin1String ( " update " ) ) ;
2009-05-05 10:16:09 +02:00
args . push_back ( QLatin1String ( nonInteractiveOptionC ) ) ;
2008-12-02 12:01:29 +01:00
args . append ( topLevels ) ;
runSvn ( args , subversionLongTimeOut , false ) ;
}
void SubversionPlugin : : annotateCurrentFile ( )
{
const QString file = currentFileName ( ) ;
if ( ! file . isEmpty ( ) )
annotate ( file ) ;
}
void SubversionPlugin : : annotate ( const QString & file )
{
2009-01-20 11:52:04 +01:00
QTextCodec * codec = VCSBase : : VCSBaseEditor : : getCodec ( file ) ;
2008-12-02 12:01:29 +01:00
QStringList args ( QLatin1String ( " annotate " ) ) ;
args . push_back ( QLatin1String ( " -v " ) ) ;
args . append ( QDir : : toNativeSeparators ( file ) ) ;
const SubversionResponse response = runSvn ( args , subversionShortTimeOut , false , codec ) ;
if ( response . error )
return ;
// Re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
2009-01-20 17:14:00 +01:00
if ( Core : : IEditor * editor = locateEditor ( " annotateFileName " , file ) ) {
2008-12-02 12:01:29 +01:00
editor - > createNew ( response . stdOut ) ;
2009-01-26 16:36:02 +01:00
Core : : EditorManager : : instance ( ) - > activateEditor ( editor ) ;
2008-12-02 12:01:29 +01:00
} else {
2009-04-17 21:00:10 +02:00
const QString title = QString : : fromLatin1 ( " svn annotate %1 " ) . arg ( QFileInfo ( file ) . fileName ( ) ) ;
2008-12-02 12:01:29 +01:00
Core : : IEditor * newEditor = showOutputInEditor ( title , response . stdOut , VCSBase : : AnnotateOutput , file , codec ) ;
newEditor - > setProperty ( " annotateFileName " , file ) ;
}
}
void SubversionPlugin : : projectStatus ( )
{
if ( ! m_projectExplorer )
return ;
QStringList args ( QLatin1String ( " status " ) ) ;
args + = currentProjectsTopLevels ( ) ;
if ( args . size ( ) = = 1 )
return ;
runSvn ( args , subversionShortTimeOut , true ) ;
}
void SubversionPlugin : : describe ( const QString & source , const QString & changeNr )
{
// To describe a complete change, find the top level and then do
//svn diff -r 472958:472959 <top level>
const QFileInfo fi ( source ) ;
const QString topLevel = findTopLevelForDirectory ( fi . isDir ( ) ? source : fi . absolutePath ( ) ) ;
if ( topLevel . isEmpty ( ) )
return ;
if ( Subversion : : Constants : : debug )
qDebug ( ) < < Q_FUNC_INFO < < source < < topLevel < < changeNr ;
// Number must be > 1
bool ok ;
const int number = changeNr . toInt ( & ok ) ;
if ( ! ok | | number < 2 )
return ;
2009-02-10 08:38:12 +01:00
// Run log to obtain message (local utf8)
QString description ;
QStringList args ( QLatin1String ( " log " ) ) ;
args . push_back ( QLatin1String ( " -r " ) ) ;
args . push_back ( changeNr ) ;
args . push_back ( topLevel ) ;
const SubversionResponse logResponse = runSvn ( args , subversionShortTimeOut , false ) ;
if ( logResponse . error )
return ;
description = logResponse . stdOut ;
// Run diff (encoding via source codec)
args . clear ( ) ;
args . push_back ( QLatin1String ( " diff " ) ) ;
2008-12-02 12:01:29 +01:00
args . push_back ( QLatin1String ( " -r " ) ) ;
QString diffArg ;
QTextStream ( & diffArg ) < < ( number - 1 ) < < ' : ' < < number ;
args . push_back ( diffArg ) ;
args . push_back ( topLevel ) ;
2009-01-20 11:52:04 +01:00
QTextCodec * codec = VCSBase : : VCSBaseEditor : : getCodec ( source ) ;
2008-12-02 12:01:29 +01:00
const SubversionResponse response = runSvn ( args , subversionShortTimeOut , false , codec ) ;
if ( response . error )
return ;
2009-02-10 08:38:12 +01:00
description + = response . stdOut ;
2008-12-02 12:01:29 +01:00
// Re-use an existing view if possible to support
// the common usage pattern of continuously changing and diffing a file
const QString id = diffArg + source ;
2009-01-20 17:14:00 +01:00
if ( Core : : IEditor * editor = locateEditor ( " describeChange " , id ) ) {
2009-02-10 08:38:12 +01:00
editor - > createNew ( description ) ;
2009-02-10 13:51:59 +01:00
Core : : EditorManager : : instance ( ) - > activateEditor ( editor ) ;
2008-12-02 12:01:29 +01:00
} else {
2009-04-17 21:00:10 +02:00
const QString title = QString : : fromLatin1 ( " svn describe %1#%2 " ) . arg ( QFileInfo ( source ) . fileName ( ) , changeNr ) ;
2009-02-10 08:38:12 +01:00
Core : : IEditor * newEditor = showOutputInEditor ( title , description , VCSBase : : DiffOutput , source , codec ) ;
2008-12-02 12:01:29 +01:00
newEditor - > setProperty ( " describeChange " , id ) ;
}
}
2009-02-09 17:33:31 +01:00
void SubversionPlugin : : slotDescribe ( )
{
const QStringList topLevels = currentProjectsTopLevels ( ) ;
if ( topLevels . size ( ) ! = 1 )
return ;
QInputDialog inputDialog ( Core : : ICore : : instance ( ) - > mainWindow ( ) ) ;
inputDialog . setWindowFlags ( inputDialog . windowFlags ( ) & ~ Qt : : WindowContextHelpButtonHint ) ;
inputDialog . setInputMode ( QInputDialog : : IntInput ) ;
inputDialog . setIntRange ( 2 , INT_MAX ) ;
inputDialog . setWindowTitle ( tr ( " Describe " ) ) ;
inputDialog . setLabelText ( tr ( " Revision number: " ) ) ;
if ( inputDialog . exec ( ) ! = QDialog : : Accepted )
return ;
const int revision = inputDialog . intValue ( ) ;
describe ( topLevels . front ( ) , QString : : number ( revision ) ) ;
}
2008-12-02 12:01:29 +01:00
void SubversionPlugin : : submitCurrentLog ( )
{
2009-03-20 10:16:18 +01:00
m_submitActionTriggered = true ;
2009-01-21 15:52:34 +01:00
Core : : EditorManager : : instance ( ) - > closeEditors ( QList < Core : : IEditor * > ( )
< < Core : : EditorManager : : instance ( ) - > currentEditor ( ) ) ;
2008-12-02 12:01:29 +01:00
}
QString SubversionPlugin : : currentFileName ( ) const
{
2009-01-20 17:14:00 +01:00
const QString fileName = Core : : ICore : : instance ( ) - > fileManager ( ) - > currentFile ( ) ;
2008-12-02 12:01:29 +01:00
if ( ! fileName . isEmpty ( ) ) {
const QFileInfo fi ( fileName ) ;
if ( fi . exists ( ) )
return fi . canonicalFilePath ( ) ;
}
return QString ( ) ;
}
static inline QString processStdErr ( QProcess & proc )
{
return QString : : fromLocal8Bit ( proc . readAllStandardError ( ) ) . remove ( QLatin1Char ( ' \r ' ) ) ;
}
static inline QString processStdOut ( QProcess & proc , QTextCodec * outputCodec = 0 )
{
const QByteArray stdOutData = proc . readAllStandardOutput ( ) ;
QString stdOut = outputCodec ? outputCodec - > toUnicode ( stdOutData ) : QString : : fromLocal8Bit ( stdOutData ) ;
return stdOut . remove ( QLatin1Char ( ' \r ' ) ) ;
}
SubversionResponse SubversionPlugin : : runSvn ( const QStringList & arguments ,
int timeOut ,
bool showStdOutInOutputWindow ,
QTextCodec * outputCodec )
{
const QString executable = m_settings . svnCommand ;
SubversionResponse response ;
if ( executable . isEmpty ( ) ) {
response . error = true ;
response . message = tr ( " No subversion executable specified! " ) ;
return response ;
}
const QStringList allArgs = m_settings . addOptions ( arguments ) ;
// Hide passwords, etc in the log window
const QString timeStamp = QTime : : currentTime ( ) . toString ( QLatin1String ( " HH:mm " ) ) ;
2009-04-17 21:11:52 +02:00
//: <timestamp> Executing: <executable> <arguments>
2008-12-02 12:01:29 +01:00
const QString outputText = tr ( " %1 Executing: %2 %3 \n " ) . arg ( timeStamp , executable , SubversionSettings : : formatArguments ( allArgs ) ) ;
showOutput ( outputText , false ) ;
if ( Subversion : : Constants : : debug )
qDebug ( ) < < " runSvn " < < timeOut < < outputText ;
// Run, connect stderr to the output window
Core : : Utils : : SynchronousProcess process ;
process . setTimeout ( timeOut ) ;
process . setStdOutCodec ( outputCodec ) ;
process . setStdErrBufferedSignalsEnabled ( true ) ;
connect ( & process , SIGNAL ( stdErrBuffered ( QString , bool ) ) , m_subversionOutputWindow , SLOT ( append ( QString , bool ) ) ) ;
// connect stdout to the output window if desired
if ( showStdOutInOutputWindow ) {
process . setStdOutBufferedSignalsEnabled ( true ) ;
connect ( & process , SIGNAL ( stdOutBuffered ( QString , bool ) ) , m_subversionOutputWindow , SLOT ( append ( QString , bool ) ) ) ;
}
const Core : : Utils : : SynchronousProcessResponse sp_resp = process . run ( executable , allArgs ) ;
response . error = true ;
response . stdErr = sp_resp . stdErr ;
response . stdOut = sp_resp . stdOut ;
switch ( sp_resp . result ) {
case Core : : Utils : : SynchronousProcessResponse : : Finished :
response . error = false ;
break ;
case Core : : Utils : : SynchronousProcessResponse : : FinishedError :
response . message = tr ( " The process terminated with exit code %1. " ) . arg ( sp_resp . exitCode ) ;
break ;
case Core : : Utils : : SynchronousProcessResponse : : TerminatedAbnormally :
response . message = tr ( " The process terminated abnormally. " ) ;
break ;
case Core : : Utils : : SynchronousProcessResponse : : StartFailed :
response . message = tr ( " Could not start subversion '%1'. Please check your settings in the preferences. " ) . arg ( executable ) ;
break ;
case Core : : Utils : : SynchronousProcessResponse : : Hang :
response . message = tr ( " Subversion did not respond within timeout limit (%1 ms). " ) . arg ( timeOut ) ;
break ;
}
if ( response . error )
m_subversionOutputWindow - > append ( response . message , true ) ;
return response ;
}
void SubversionPlugin : : showOutput ( const QString & output , bool bringToForeground )
{
m_subversionOutputWindow - > append ( output ) ;
if ( bringToForeground )
m_subversionOutputWindow - > popup ( ) ;
}
Core : : IEditor * SubversionPlugin : : showOutputInEditor ( const QString & title , const QString & output ,
int editorType , const QString & source ,
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 ( Subversion : : Constants : : debug )
qDebug ( ) < < " SubversionPlugin::showOutputInEditor " < < title < < kind < < " Size= " < < output . size ( ) < < " Type= " < < editorType < < debugCodec ( codec ) ;
QString s = title ;
2009-01-21 15:52:34 +01:00
Core : : IEditor * editor = Core : : EditorManager : : instance ( ) - > newFile ( kind , & s , output . toLocal8Bit ( ) ) ;
SubversionEditor * e = qobject_cast < SubversionEditor * > ( editor - > widget ( ) ) ;
2008-12-02 12:01:29 +01:00
if ( ! e )
return 0 ;
s . replace ( QLatin1Char ( ' ' ) , QLatin1Char ( ' _ ' ) ) ;
e - > setSuggestedFileName ( s ) ;
if ( ! source . isEmpty ( ) )
e - > setSource ( source ) ;
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
}
SubversionSettings SubversionPlugin : : settings ( ) const
{
return m_settings ;
}
void SubversionPlugin : : setSettings ( const SubversionSettings & s )
{
if ( s ! = m_settings ) {
m_settings = s ;
2009-01-20 17:14:00 +01:00
if ( QSettings * settings = Core : : ICore : : instance ( ) - > settings ( ) )
2008-12-02 12:01:29 +01:00
m_settings . toSettings ( settings ) ;
}
}
SubversionPlugin * SubversionPlugin : : subversionPluginInstance ( )
{
2008-12-12 17:02:55 +01:00
QTC_ASSERT ( m_subversionPluginInstance , return m_subversionPluginInstance ) ;
2008-12-02 12:01:29 +01:00
return m_subversionPluginInstance ;
}
bool SubversionPlugin : : vcsAdd ( const QString & rawFileName )
{
const QString file = QDir : : toNativeSeparators ( rawFileName ) ;
QStringList args ( QLatin1String ( " add " ) ) ;
args . push_back ( file ) ;
const SubversionResponse response = runSvn ( args , subversionShortTimeOut , true ) ;
return ! response . error ;
}
bool SubversionPlugin : : vcsDelete ( const QString & rawFileName )
{
const QString file = QDir : : toNativeSeparators ( rawFileName ) ;
QStringList args ( QLatin1String ( " delete " ) ) ;
args . push_back ( file ) ;
const SubversionResponse response = runSvn ( args , subversionShortTimeOut , true ) ;
return ! response . error ;
}
/* Subversion has ".svn" directory in each directory
* it manages . The top level is the first directory
* under the directory that does not have a " .svn " . */
bool SubversionPlugin : : managesDirectory ( const QString & directory ) const
{
const QDir dir ( directory ) ;
const bool rc = dir . exists ( ) & & managesDirectory ( dir ) ;
if ( Subversion : : Constants : : debug )
qDebug ( ) < < " SubversionPlugin::managesDirectory " < < directory < < rc ;
return rc ;
}
bool SubversionPlugin : : managesDirectory ( const QDir & directory ) const
{
2009-05-26 12:25:32 +02:00
const int dirCount = m_svnDirectories . size ( ) ;
for ( int i = 0 ; i < dirCount ; i + + ) {
const QString svnDir = directory . absoluteFilePath ( m_svnDirectories . at ( i ) ) ;
if ( QFileInfo ( svnDir ) . isDir ( ) )
return true ;
}
return false ;
2008-12-02 12:01:29 +01:00
}
QString SubversionPlugin : : findTopLevelForDirectory ( const QString & directory ) const
{
// Debug wrapper
const QString rc = findTopLevelForDirectoryI ( directory ) ;
if ( Subversion : : Constants : : debug )
qDebug ( ) < < " SubversionPlugin::findTopLevelForDirectory " < < directory < < rc ;
return rc ;
}
QString SubversionPlugin : : findTopLevelForDirectoryI ( const QString & directory ) const
{
/* Recursing up, the top level is a child of the first directory that does
* not have a " .svn " directory . The starting directory must be a managed
* one . Go up and try to find the first unmanaged parent dir . */
QDir lastDirectory = QDir ( directory ) ;
if ( ! lastDirectory . exists ( ) | | ! managesDirectory ( lastDirectory ) )
return QString ( ) ;
for ( QDir parentDir = lastDirectory ; parentDir . cdUp ( ) ; lastDirectory = parentDir ) {
if ( ! managesDirectory ( parentDir ) )
return QDir : : toNativeSeparators ( lastDirectory . absolutePath ( ) ) ;
}
return QString ( ) ;
}
Q_EXPORT_PLUGIN ( SubversionPlugin )