天天看点

TortoiseSVN2IDE.pas源代码

unit TortoiseSVN2IDE;

{$R 'icons.res'}

interface

uses ToolsAPI, SysUtils, Windows, Dialogs, Menus, Registry, ShellApi,

    Classes, Controls, Graphics, ImgList, ExtCtrls, ActnList,Forms;//增加了对Forms单元的引用

const

    SVN_PROJECT_EXPLORER = 0;

    SVN_LOG = 1;

    SVN_CHECK_MODIFICATIONS = 2;

    SVN_ADD = 3;

    SVN_UPDATE = 4;

    SVN_COMMIT = 5;

    SVN_DIFF = 6;

    SVN_REVERT = 7;

    SVN_REPOSITORY_BROWSER = 8;

    SVN_SETTINGS = 9;

    SVN_ABOUT = 10;

    SVN_VERB_COUNT = 11;

type TTortoiseSVN = class(TNotifierObject, IOTANotifier, IOTAWizard)

private

    timer: TTimer;

    tsvnMenu: TMenuItem;

    TSVNPath: string;

    procedure Tick( sender: tobject );

    procedure TSVNExec( params: string );

    function GetBitmapName(Index: Integer): string;

    function GetVerb(Index: Integer): string;

    function GetVerbState(Index: Integer): Word;

    procedure ExecuteVerb(Index: Integer);

    procedure CreateMenu;

    procedure UpdateAction( sender: TObject );

    procedure ExecuteAction( sender: TObject );

public

    constructor Create;

    destructor Destroy; override;

    function GetIDString: string;

    function GetName: string;

    function GetState: TWizardState;

    procedure Execute;

end;

{$IFNDEF DLL_MODE}

procedure Register;

{$ELSE}

function InitWizard(const BorlandIDEServices: IBorlandIDEServices;

  RegisterProc: TWizardRegisterProc;

  var Terminate: TWizardTerminateProc): Boolean; stdcall;

{$ENDIF}

implementation

function GetCurrentProject: IOTAProject;

var

  ModServices: IOTAModuleServices;

  Module: IOTAModule;

  Project: IOTAProject;

  ProjectGroup: IOTAProjectGroup;

  i: Integer;

begin

  Result := nil;

  ModServices := BorlandIDEServices as IOTAModuleServices;

  if ModServices <> nil then

      for i := 0 to ModServices.ModuleCount - 1 do

      begin

        Module := ModServices.Modules[i];

        if Supports(Module, IOTAProjectGroup, ProjectGroup) then

        begin

          Result := ProjectGroup.ActiveProject;

          Exit;

        end

        else if Supports(Module, IOTAProject, Project) then

        begin // In the case of unbound packages, return the 1st

          if Result = nil then

            Result := Project;

        end;

      end;

function GetCurrentFileName: string;

var editor: IOTAEditorServices;

    result:= '';

    editor:= BorlandIDEServices as IOTAEditorServices;

    if editor <> nil then begin

        if editor.TopBuffer <> nil then

            result:= editor.TopBuffer.FileName;

    end;

constructor TTortoiseSVN.Create;

var reg: TRegistry;

    Reg := TRegistry.Create;

    try

        Reg.RootKey := HKEY_LOCAL_MACHINE;

        if Reg.OpenKeyReadOnly( '\SOFTWARE\TortoiseSVN' ) then

            TSVNPath:= Reg.ReadString( 'ProcPath' );

    finally

        Reg.CloseKey;

        Reg.Free;

    tsvnMenu:= nil;

    timer:= TTimer.create(nil);

    timer.interval:= 200;

    timer.OnTimer:= tick;

    timer.enabled:= true;

procedure TTortoiseSVN.Tick( sender: tobject );

var intf: INTAServices;

    if BorlandIDEServices.QueryInterface( INTAServices, intf ) = s_OK then begin

        self.createMenu;

        timer.free;

        timer:= nil;

procedure TTortoiseSVN.CreateMenu;

var mainMenu: TMainMenu;

    item: TMenuItem;

    i: integer;

    bmp: TBitmap;

    action: TAction;

    if tsvnMenu <> nil then exit;

    tsvnMenu:= TMenuItem.Create(nil);

    tsvnMenu.Caption:= 'TortoiseSVN';

    for i:= 0 to SVN_VERB_COUNT-1 do begin

        bmp:= TBitmap.create;

        try

          bmp.LoadFromResourceName( HInstance, getBitmapName(i) );

        except end;

        action:= TAction.Create(nil);

        action.ActionList:= (BorlandIDEServices as INTAServices).ActionList;

        action.Caption:= getVerb(i);

        action.Hint:= getVerb(i);

        if (bmp.Width = 16) and (bmp.height = 16) then

            action.ImageIndex:= (BorlandIDEServices as INTAServices).AddMasked( bmp, clBlack );

        bmp.free;

        action.OnUpdate:= updateAction;

        action.OnExecute:= executeAction;

        action.Tag:= i;

        item:= TMenuItem.Create( tsvnMenu );

        item.action:= action;

        tsvnMenu.add( item );

    mainMenu:= (BorlandIDEServices as INTAServices).MainMenu;

    mainMenu.Items.Insert( mainMenu.Items.Count-1, tsvnMenu );

destructor TTortoiseSVN.Destroy;

    if tsvnMenu <> nil then begin

        tsvnMenu.free;

    inherited;

function TTortoiseSVN.GetBitmapName(Index: Integer): string;

    case index of

        SVN_PROJECT_EXPLORER:

            Result:= 'explorer';

        SVN_LOG:

            Result:= 'log';

        SVN_CHECK_MODIFICATIONS:

            Result:= 'check';

        SVN_ADD:

            Result:= 'add';

        SVN_UPDATE:

            Result:= 'update';

        SVN_COMMIT:

            Result:= 'commit';

        SVN_DIFF:

            Result:= 'diff';

        SVN_REVERT:

            Result:= 'revert';

        SVN_REPOSITORY_BROWSER:

            Result:= 'repository';

        SVN_SETTINGS:

            Result:= 'settings';

        SVN_ABOUT:

            Result:= 'about';

function TTortoiseSVN.GetVerb(Index: Integer): string;

            Result:= '浏览项目文件夹[&P]...';//'&Project explorer...';

            Result:= '日志[&L]...';//'&Log...';

            Result:= '检查更新[&M]...';//'Check &modifications...';

            Result:= '添加[&A]...';//'&Add...';

            Result:= '更新为某一版本[&U]...';//'&Update to revision...';

            Result:= '提交[&C]...';//'&Commit...';

            Result:= '差异比较[&D]...';//'&Diff...';

            Result:= '还原[&R]...';//'&Revert...';

            Result:= '浏览版本库[&B]...';//'Repository &browser...';

            Result:= '设置[&S]...';//'&Settings...';

            Result:= '关于[&A]...';//'&About...';

const vsEnabled = 1;

function TTortoiseSVN.GetVerbState(Index: Integer): Word;

    Result:= 0;

            if GetCurrentProject <> nil then

                Result:= vsEnabled;

            if GetCurrentFileName <> '' then

            Result:= vsEnabled;

procedure TTortoiseSVN.TSVNExec( params: string );

    WinExec( pchar( TSVNPath + ' ' + params ), SW_SHOW );

procedure TTortoiseSVN.ExecuteVerb(Index: Integer);

var project: IOTAProject;

    filename: string;

    project:= GetCurrentProject();

    filename:= getCurrentFileName();

            if project <> nil then

                ShellExecute( 0, 'open', pchar( ExtractFilePath(project.GetFileName) ), '', '', SW_SHOWNORMAL );

                TSVNExec( '/command:log /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );

                TSVNExec( '/command:repostatus /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );

                TSVNExec( '/command:add /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );

                if Application.MessageBox('更新之前,所有的项目文件都将被保存。继续吗?  ', '提示',MB_YESNO + MB_ICONQUESTION) = IDYES then begin

                //if MessageDlg( '更新之前,所有的项目文件都将被保存。继续吗?', mtConfirmation, [mbYes, mbNo], 0 ) = mrYes then begin

                    (BorlandIDEServices as IOTAModuleServices).saveAll;

                    TSVNExec( '/command:update /rev /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );

                end;

                if Application.MessageBox('提交之前,所有的项目文件都将被保存。继续吗?  ', '提示',MB_YESNO + MB_ICONQUESTION) = IDYES then begin

                //if MessageDlg( '提交之前,所有的项目文件都将被保存。继续吗?', mtConfirmation, [mbYes, mbNo], 0 ) = mrYes then begin

                    TSVNExec( '/command:commit /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );

            if filename <> '' then

                TSVNExec( '/command:diff /notempfile /path:' + AnsiQuotedStr( filename, '"' ) );

                TSVNExec( '/command:revert /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );

                TSVNExec( '/command:repobrowser /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) )

            else

                TSVNExec( '/command:repobrowser' );

            TSVNExec( '/command:settings' );

            TSVNExec( '/command:about' );

procedure TTortoiseSVN.UpdateAction( sender: TObject );

var action: TAction;

    action:= sender as TAction;

    action.Enabled:= getVerbState( action.tag ) = vsEnabled;

procedure TTortoiseSVN.ExecuteAction( sender: TObject );

    executeVerb( action.tag );

function TTortoiseSVN.GetIDString: string;

    result:= 'Subversion.TortoiseSVN';

function TTortoiseSVN.GetName: string;

    result:= 'TortoiseSVN add-in';

function TTortoiseSVN.GetState: TWizardState;

    result:= [wsEnabled];

procedure TTortoiseSVN.Execute;

    RegisterPackageWizard(TTortoiseSVN.create);

var wizardID: integer;

procedure FinalizeWizard;

  WizardServices: IOTAWizardServices;

    Assert(Assigned(BorlandIDEServices));

    WizardServices := BorlandIDEServices as IOTAWizardServices;

    Assert(Assigned(WizardServices));

    WizardServices.RemoveWizard( wizardID );

    Assert(BorlandIDEServices <> nil);

    Assert(ToolsAPI.BorlandIDEServices = BorlandIDEServices);

    Terminate := FinalizeWizard;

    wizardID:= WizardServices.AddWizard(TTortoiseSVN.Create as IOTAWizard);

    result:= wizardID >= 0;

exports

  InitWizard name WizardEntryPoint;

end.