TortoiseSVN2IDE.pas源代码

本文介绍了一个名为TortoiseSVN的版本控制系统如何与集成开发环境(IDE)进行深度集成,通过创建定制菜单和操作,使开发者能够直接从IDE中执行SVN的各种操作,如更新、提交和差异比较等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
end;

function GetCurrentFileName: string;
var editor: IOTAEditorServices;
begin
    result:= '';
    editor:= BorlandIDEServices as IOTAEditorServices;
    if editor <> nil then begin
        if editor.TopBuffer <> nil then
            result:= editor.TopBuffer.FileName;
    end;
end;

constructor TTortoiseSVN.Create;
var reg: TRegistry;
begin
    Reg := TRegistry.Create;
    try
        Reg.RootKey := HKEY_LOCAL_MACHINE;
        if Reg.OpenKeyReadOnly( '\SOFTWARE\TortoiseSVN' ) then
            TSVNPath:= Reg.ReadString( 'ProcPath' );
    finally
        Reg.CloseKey;
        Reg.Free;
    end;

    tsvnMenu:= nil;

    timer:= TTimer.create(nil);
    timer.interval:= 200;
    timer.OnTimer:= tick;
    timer.enabled:= true;

end;

procedure TTortoiseSVN.Tick( sender: tobject );
var intf: INTAServices;
begin
    if BorlandIDEServices.QueryInterface( INTAServices, intf ) = s_OK then begin
        self.createMenu;
        timer.free;
        timer:= nil;
    end;
end;

procedure TTortoiseSVN.CreateMenu;
var mainMenu: TMainMenu;
    item: TMenuItem;
    i: integer;
    bmp: TBitmap;
    action: TAction;
begin
    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 );
    end;

    mainMenu:= (BorlandIDEServices as INTAServices).MainMenu;
    mainMenu.Items.Insert( mainMenu.Items.Count-1, tsvnMenu );
end;

destructor TTortoiseSVN.Destroy;
begin
    if tsvnMenu <> nil then begin
        tsvnMenu.free;
    end;
    inherited;
end;

function TTortoiseSVN.GetBitmapName(Index: Integer): string;
begin
    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';
    end;
end;

function TTortoiseSVN.GetVerb(Index: Integer): string;
begin
    case index of
        SVN_PROJECT_EXPLORER:
            Result:= '浏览项目文件夹[&P]...';//'&Project explorer...';
        SVN_LOG:
            Result:= '日志[&L]...';//'&Log...';
        SVN_CHECK_MODIFICATIONS:
            Result:= '检查更新[&M]...';//'Check &modifications...';
        SVN_ADD:
            Result:= '添加[&A]...';//'&Add...';
        SVN_UPDATE:
            Result:= '更新为某一版本[&U]...';//'&Update to revision...';
        SVN_COMMIT:
            Result:= '提交[&C]...';//'&Commit...';
        SVN_DIFF:
            Result:= '差异比较[&D]...';//'&Diff...';
        SVN_REVERT:
            Result:= '还原[&R]...';//'&Revert...';
        SVN_REPOSITORY_BROWSER:
            Result:= '浏览版本库[&B]...';//'Repository &browser...';
        SVN_SETTINGS:
            Result:= '设置[&S]...';//'&Settings...';
        SVN_ABOUT:
            Result:= '关于[&A]...';//'&About...';
    end;
end;

const vsEnabled = 1;

function TTortoiseSVN.GetVerbState(Index: Integer): Word;
begin
    Result:= 0;
    case index of
        SVN_PROJECT_EXPLORER:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_LOG:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_CHECK_MODIFICATIONS:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_ADD:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_UPDATE:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_COMMIT:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_DIFF:
            if GetCurrentFileName <> '' then
                Result:= vsEnabled;
        SVN_REVERT:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_REPOSITORY_BROWSER:
            Result:= vsEnabled;
        SVN_SETTINGS:
            Result:= vsEnabled;
        SVN_ABOUT:
            Result:= vsEnabled;
    end;
end;

procedure TTortoiseSVN.TSVNExec( params: string );
begin
    WinExec( pchar( TSVNPath + ' ' + params ), SW_SHOW );
end;

procedure TTortoiseSVN.ExecuteVerb(Index: Integer);
var project: IOTAProject;
    filename: string;
begin
    project:= GetCurrentProject();
    filename:= getCurrentFileName();
    case index of
        SVN_PROJECT_EXPLORER:
            if project <> nil then
                ShellExecute( 0, 'open', pchar( ExtractFilePath(project.GetFileName) ), '', '', SW_SHOWNORMAL );
        SVN_LOG:
            if project <> nil then
                TSVNExec( '/command:log /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );
        SVN_CHECK_MODIFICATIONS:
            if project <> nil then
                TSVNExec( '/command:repostatus /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );
        SVN_ADD:
            if project <> nil then
                TSVNExec( '/command:add /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );
        SVN_UPDATE:
            if project <> nil then

                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;
        SVN_COMMIT:
            if project <> nil then
                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:commit /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );
                end;
        SVN_DIFF:
            if filename <> '' then
                TSVNExec( '/command:diff /notempfile /path:' + AnsiQuotedStr( filename, '"' ) );
        SVN_REVERT:
            if project <> nil then
                TSVNExec( '/command:revert /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );
        SVN_REPOSITORY_BROWSER:
            if project <> nil then
                TSVNExec( '/command:repobrowser /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) )
            else
                TSVNExec( '/command:repobrowser' );
        SVN_SETTINGS:
            TSVNExec( '/command:settings' );
        SVN_ABOUT:
            TSVNExec( '/command:about' );
    end;
end;

procedure TTortoiseSVN.UpdateAction( sender: TObject );
var action: TAction;
begin
    action:= sender as TAction;
    action.Enabled:= getVerbState( action.tag ) = vsEnabled;
end;

procedure TTortoiseSVN.ExecuteAction( sender: TObject );
var action: TAction;
begin
    action:= sender as TAction;
    executeVerb( action.tag );
end;


function TTortoiseSVN.GetIDString: string;
begin
    result:= 'Subversion.TortoiseSVN';
end;

function TTortoiseSVN.GetName: string;
begin
    result:= 'TortoiseSVN add-in';
end;

function TTortoiseSVN.GetState: TWizardState;
begin
    result:= [wsEnabled];
end;

procedure TTortoiseSVN.Execute;
begin
end;

 

{$IFNDEF DLL_MODE}

procedure Register;
begin
    RegisterPackageWizard(TTortoiseSVN.create);
end;

{$ELSE}

var wizardID: integer;

procedure FinalizeWizard;
var
  WizardServices: IOTAWizardServices;
begin
    Assert(Assigned(BorlandIDEServices));

    WizardServices := BorlandIDEServices as IOTAWizardServices;
    Assert(Assigned(WizardServices));

    WizardServices.RemoveWizard( wizardID );

end;

function InitWizard(const BorlandIDEServices: IBorlandIDEServices;
  RegisterProc: TWizardRegisterProc;
  var Terminate: TWizardTerminateProc): Boolean; stdcall;
var
  WizardServices: IOTAWizardServices;
begin
    Assert(BorlandIDEServices <> nil);
    Assert(ToolsAPI.BorlandIDEServices = BorlandIDEServices);

    Terminate := FinalizeWizard;

    WizardServices := BorlandIDEServices as IOTAWizardServices;
    Assert(Assigned(WizardServices));

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

    result:= wizardID >= 0;
end;


exports
  InitWizard name WizardEntryPoint;

{$ENDIF}

 

end.

SVN的简介: TortoiseSVN2IDE最初来源于DelphiAddinForTortoiseSVN,这是一个把TortoiseSVN集成到Delphi IDE环境中的一个小工具,但博主嫌它是个英文软件且名字又不直观,于是就对它按照TortoiseSVN的官方中文包进行了中文化并DelphiForTortoiseSVN改名为TortoiseSVN2IDE。上图就是安装TortoiseSVN2IDE之后的Delphi IDE 的截图。 SVN(Subversion)是用于源码版本控制的开源软件。它可以替代CVS,VSS等轻量级版本控制工具,它支持Local和Web(Apache)两种工作方式,并且最关键就是完全免费的。 在组织团队开发时,除了服务器端的工具之外,客户端也需要相应的工具才能访问源码库。而且,最好能和Delphi IDE集成。TortoiseSVN是与Windows系统高度集成的Subversion的客户端,而TortoiseSVN2IDE是一个把TortoiseSVN集成到Delphi IDE中去的一个小工具。 在使用Subversion时,客户端工具可以有如下选择, 1、SourceConneXion+PushOk SVN Proxy(目前没找到破解),这两个工具都是收费的; 2TortoiseSVNTortoiseSVN2IDE,这两个工具都是免费、开源的; 在客户端安装TortoiseSVN后,再通过TortoiseSVN2IDE集成进Dlephi的IDE集成开发环境就可以了。 ---------- 使用方法: 1、先安装TortoiseSVN 1.4.1.7992官方最新版。 TortoiseSVN 1.4.1.7992下截地址为:http://prdownloads.sourceforge.net/tortoisesvn/TortoiseSVN-1.4.1.7992-win32-svn-1.4.2.msi?download 或者:http://xieyunc.gbaopan.com/files/98f41debcba440cb91592b5dd60358ff.gbp 官方简体中文语言包下载地址:http://prdownloads.sourceforge.net/tortoisesvn/LanguagePack-1.4.1.7992-win32-zh_CN.exe?download 或者: http://xieyunc.gbaopan.com/files/1fec39e24aa446ce935cae9b16424409.gbp 2、再安装本IDE集成工具。本软件的安装方法为:先建立一包工程,再加入本文件,编译-->Install,OK! TortoiseSVN2IDE下载地址:http://www.2ccc.com/go.asp?id=3867&url=http://downloads.2ccc.com/vcl/experts/xieyunc_tsvnWizard.rar(这个少了icon.res文件) 完整文件下载地址在这里: http://xieyunc.gbaopan.com/files/c7c9a5efead24736bb4c17d1fdb5cf50.gbp SVN好站推荐: 1、TortoiseSVN实战使用介绍 http://xieyunc.blog.163.com/blog/static/136306012006112010209410 2TortoiseSVN全面使用说明书:http://www.subversion.org.cn/tsvndoc/ 注:转载时请注明TortoiseSVN2IDE的来龙去脉。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值