lazsvn: added Makefile, from Bernd: new features: diff, sorting, patch #17117

git-svn-id: trunk@27943 -
This commit is contained in:
mattias 2010-10-29 11:44:27 +00:00
parent 64ed209693
commit 18c69037b3
21 changed files with 4040 additions and 514 deletions

3
.gitattributes vendored
View File

@ -1585,6 +1585,9 @@ components/lazreport/source/lr_view.lfm svneol=native#text/plain
components/lazreport/source/lr_view.pas svneol=native#text/pascal
components/lazreport/source/sysutilsadds.pas svneol=native#text/pascal
components/lazreport/tools/localize.sh svneol=native#text/plain
components/lazsvnpkg/Makefile svneol=native#text/plain
components/lazsvnpkg/Makefile.compiled svneol=native#text/plain
components/lazsvnpkg/Makefile.fpc svneol=native#text/plain
components/lazsvnpkg/images/menu_svn.png -text
components/lazsvnpkg/images/menu_svn_commit.png -text
components/lazsvnpkg/images/menu_svn_diff.png -text

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
<?xml version="1.0"?>
<CONFIG>
<Makefile Value="True"/>
<Params Value=" -MObjFPC -Sgi -O1 -gl -vewnhi -l -Fu../../lcl/units/%(CPU_TARGET)-%(OS_TARGET);../../ideintf/units/%(CPU_TARGET)-%(OS_TARGET);lib/%(CPU_TARGET)-%(OS_TARGET);../../units/%(CPU_TARGET)-%(OS_TARGET);../codetools/units/%(CPU_TARGET)-%(OS_TARGET);../synedit/units/%(CPU_TARGET)-%(OS_TARGET);../../lcl/units/%(CPU_TARGET)-%(OS_TARGET)/%(LCL_PLATFORM);../../packager/units/%(CPU_TARGET)-%(OS_TARGET);. -Fi. -dLCL -dLCL%(LCL_PLATFORM)"/>
</CONFIG>

View File

@ -0,0 +1,56 @@
# File generated automatically by Lazarus Package Manager
#
# Makefile.fpc for lazsvnpkg 0.0.1
#
# This file was generated on 10/29/2010
[package]
name=lazsvnpkg
version=0.0.1
[compiler]
unittargetdir=lib/$(CPU_TARGET)-$(OS_TARGET)
unitdir=../../lcl/units/$(CPU_TARGET)-$(OS_TARGET) ../../ideintf/units/$(CPU_TARGET)-$(OS_TARGET) lib/$(CPU_TARGET)-$(OS_TARGET) ../../units/$(CPU_TARGET)-$(OS_TARGET) ../codetools/units/$(CPU_TARGET)-$(OS_TARGET) ../synedit/units/$(CPU_TARGET)-$(OS_TARGET) ../../lcl/units/$(CPU_TARGET)-$(OS_TARGET)/$(LCL_PLATFORM) ../../packager/units/$(CPU_TARGET)-$(OS_TARGET) .
includedir=.
options= -MObjFPC -Sgi -O1 -gl -vewnhi -l -dLCL -dLCL$(LCL_PLATFORM)
[target]
units=lazsvnpkg.pas
[clean]
files=$(wildcard $(COMPILER_UNITTARGETDIR)/*$(OEXT)) \
$(wildcard $(COMPILER_UNITTARGETDIR)/*$(PPUEXT)) \
$(wildcard $(COMPILER_UNITTARGETDIR)/*$(RSTEXT)) \
$(wildcard $(COMPILER_UNITTARGETDIR)/*.lfm) \
$(wildcard $(COMPILER_UNITTARGETDIR)/*.res) \
$(wildcard $(COMPILER_UNITTARGETDIR)/*.compiled) \
$(wildcard *$(OEXT)) $(wildcard *$(PPUEXT)) $(wildcard *$(RSTEXT))
[prerules]
# LCL Platform
ifndef LCL_PLATFORM
ifeq ($(OS_TARGET),win32)
LCL_PLATFORM=win32
else
ifeq ($(OS_TARGET),win64)
LCL_PLATFORM=win32
else
ifeq ($(OS_TARGET),darwin)
LCL_PLATFORM=carbon
else
LCL_PLATFORM=gtk2
endif
endif
endif
endif
export LCL_PLATFORM
[rules]
.PHONY: cleartarget compiled all
cleartarget:
-$(DEL) $(COMPILER_UNITTARGETDIR)/lazsvnpkg$(PPUEXT)
compiled:
$(COPY) Makefile.compiled $(COMPILER_UNITTARGETDIR)/lazsvnpkg.compiled
all: cleartarget $(COMPILER_UNITTARGETDIR) lazsvnpkg$(PPUEXT) compiled

View File

@ -13,6 +13,10 @@ msgstr ""
msgid "Action"
msgstr "Aktion"
#: svnclasses.rsadd
msgid "Add to version control"
msgstr "Zu Versionskontrolle hinzufügen"
#: svnclasses.rsadded
msgid "Added"
msgstr "Hinzugefügt"
@ -37,6 +41,10 @@ msgstr "Konflikt"
msgid "Copy from path"
msgstr "kopiert von"
#: svnclasses.rscreatepatchfile
msgid "Create patch file"
msgstr "Patch erzeugen"
#: svnclasses.rsdate
msgid "Date"
msgstr "Datum"
@ -61,6 +69,10 @@ msgstr "Bearbeiten"
msgid "Extension"
msgstr "Erweiterung"
#: svnclasses.rsfilenotinworkingcopyanymore
msgid "File is not part of local working copy (anymore)"
msgstr "Datei ist nicht (mehr) Bestandteil der lokalen Arbeitskopie"
#: svnclasses.rsfilestatus
msgid "File status"
msgstr "Dateistatus"
@ -97,6 +109,22 @@ msgstr "Meldung"
msgid "(no author)"
msgstr "(kein Autor)"
#: svnclasses.rsonlymodifieditemscanbediffed
msgid "Only modified (M) Items can be diffed"
msgstr "Nur geänderte (M) Dateien können verglichen werden"
#: svnclasses.rsopenfileineditor
msgid "Open file in editor"
msgstr "Öffne Datei im Editor"
#: svnclasses.rsopenpreviousrevisionineditor
msgid "Open previous revision in editor"
msgstr "Öffne vorhergehende Version im Editor"
#: svnclasses.rsopenthisrevisionineditor
msgid "Open this revision in editor"
msgstr "Öffne diese Revision im Editor"
#: svnclasses.rspath
msgid "Path"
msgstr "Pfad"
@ -125,13 +153,17 @@ msgstr "Projekteinstellungen"
msgid "Property status"
msgstr "Eigenschaftsstatus"
#: svnclasses.rsremove
msgid "Remove from version control (keep local)"
msgstr "Aus Versionskontrolle entfernen (lokal behalten)"
#: svnclasses.rsrepositorypath
msgid "Repository path"
msgstr "Repository-Pfad"
#: svnclasses.rsrevert
msgid "Revert"
msgstr "Umkehren"
msgstr "Änderungen zurücknemen"
#: svnclasses.rsrevision
msgid "Revision"
@ -149,10 +181,22 @@ msgstr "Einstellungen"
msgid "Show diff"
msgstr "Zeige Vergleich"
#: svnclasses.rsshowdiffbase
msgid "Show diff of local changes"
msgstr "Zeige Vergleich der lokalen Änderungen"
#: svnclasses.rsshowdiffcountrev
msgid "Show last X commits"
msgstr "Zeige letzte x Übertragungen"
#: svnclasses.rsshowdiffhead
msgid "Show diff against HEAD"
msgstr "Zeige Vergleich mit HEAD"
#: svnclasses.rsshowdiffprev
msgid "Show diff against previous version"
msgstr "Zeige Vergleich mit vorheriger Version"
#: svnclasses.rsshowlog
msgid "Show log"
msgstr "Zeige Protokoll"

View File

@ -15,6 +15,10 @@ msgstr ""
msgid "Action"
msgstr "Veiksmas"
#: svnclasses.rsadd
msgid "Add to version control"
msgstr ""
#: svnclasses.rsadded
msgid "Added"
msgstr "Pridėta"
@ -39,6 +43,10 @@ msgstr "Konfliktas"
msgid "Copy from path"
msgstr "Kopijuoti iš kelio"
#: svnclasses.rscreatepatchfile
msgid "Create patch file"
msgstr ""
#: svnclasses.rsdate
msgid "Date"
msgstr "Data"
@ -63,6 +71,10 @@ msgstr "Keisti"
msgid "Extension"
msgstr "Plėtinys"
#: svnclasses.rsfilenotinworkingcopyanymore
msgid "File is not part of local working copy (anymore)"
msgstr ""
#: svnclasses.rsfilestatus
msgid "File status"
msgstr "Failo būsena"
@ -99,6 +111,22 @@ msgstr "Pranešimas"
msgid "(no author)"
msgstr "(autoriaus nėra)"
#: svnclasses.rsonlymodifieditemscanbediffed
msgid "Only modified (M) Items can be diffed"
msgstr ""
#: svnclasses.rsopenfileineditor
msgid "Open file in editor"
msgstr ""
#: svnclasses.rsopenpreviousrevisionineditor
msgid "Open previous revision in editor"
msgstr ""
#: svnclasses.rsopenthisrevisionineditor
msgid "Open this revision in editor"
msgstr ""
#: svnclasses.rspath
msgid "Path"
msgstr "Kelias"
@ -127,6 +155,10 @@ msgstr "Projekto parinktys"
msgid "Property status"
msgstr "Savybės būsena"
#: svnclasses.rsremove
msgid "Remove from version control (keep local)"
msgstr ""
#: svnclasses.rsrepositorypath
msgid "Repository path"
msgstr "Saugyklos kelias"
@ -151,10 +183,22 @@ msgstr "Nuostatos"
msgid "Show diff"
msgstr "Rodyti skirtumus"
#: svnclasses.rsshowdiffbase
msgid "Show diff of local changes"
msgstr ""
#: svnclasses.rsshowdiffcountrev
msgid "Show last X commits"
msgstr "Rodyti paskutiniuosius X nusiuntimus"
#: svnclasses.rsshowdiffhead
msgid "Show diff against HEAD"
msgstr ""
#: svnclasses.rsshowdiffprev
msgid "Show diff against previous version"
msgstr ""
#: svnclasses.rsshowlog
msgid "Show log"
msgstr "Rodyti žurnalą"

View File

@ -13,6 +13,10 @@ msgstr ""
msgid "Action"
msgstr "Ação"
#: svnclasses.rsadd
msgid "Add to version control"
msgstr ""
#: svnclasses.rsadded
msgid "Added"
msgstr "Adicionado"
@ -37,6 +41,10 @@ msgstr "Conflita"
msgid "Copy from path"
msgstr "Copiar do caminho"
#: svnclasses.rscreatepatchfile
msgid "Create patch file"
msgstr ""
#: svnclasses.rsdate
msgid "Date"
msgstr "Data"
@ -61,6 +69,10 @@ msgstr "Editar"
msgid "Extension"
msgstr "Extensão"
#: svnclasses.rsfilenotinworkingcopyanymore
msgid "File is not part of local working copy (anymore)"
msgstr ""
#: svnclasses.rsfilestatus
msgid "File status"
msgstr "Estado arquivo"
@ -97,6 +109,22 @@ msgstr "Mensagem"
msgid "(no author)"
msgstr "(nenhum autor)"
#: svnclasses.rsonlymodifieditemscanbediffed
msgid "Only modified (M) Items can be diffed"
msgstr ""
#: svnclasses.rsopenfileineditor
msgid "Open file in editor"
msgstr ""
#: svnclasses.rsopenpreviousrevisionineditor
msgid "Open previous revision in editor"
msgstr ""
#: svnclasses.rsopenthisrevisionineditor
msgid "Open this revision in editor"
msgstr ""
#: svnclasses.rspath
msgid "Path"
msgstr "Caminho"
@ -125,6 +153,10 @@ msgstr "Opções Projeto"
msgid "Property status"
msgstr "Estado Propriedade"
#: svnclasses.rsremove
msgid "Remove from version control (keep local)"
msgstr ""
#: svnclasses.rsrepositorypath
msgid "Repository path"
msgstr "Caminho repositório"
@ -149,10 +181,22 @@ msgstr "Configurações"
msgid "Show diff"
msgstr "Exibir diferenças"
#: svnclasses.rsshowdiffbase
msgid "Show diff of local changes"
msgstr ""
#: svnclasses.rsshowdiffcountrev
msgid "Show last X commits"
msgstr "Exibir últimos X envios"
#: svnclasses.rsshowdiffhead
msgid "Show diff against HEAD"
msgstr ""
#: svnclasses.rsshowdiffprev
msgid "Show diff against previous version"
msgstr ""
#: svnclasses.rsshowlog
msgid "Show log"
msgstr "Exibir log"

View File

@ -5,6 +5,10 @@ msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Action"
msgstr ""
#: svnclasses.rsadd
msgid "Add to version control"
msgstr ""
#: svnclasses.rsadded
msgid "Added"
msgstr ""
@ -29,6 +33,10 @@ msgstr ""
msgid "Copy from path"
msgstr ""
#: svnclasses.rscreatepatchfile
msgid "Create patch file"
msgstr ""
#: svnclasses.rsdate
msgid "Date"
msgstr ""
@ -53,6 +61,10 @@ msgstr ""
msgid "Extension"
msgstr ""
#: svnclasses.rsfilenotinworkingcopyanymore
msgid "File is not part of local working copy (anymore)"
msgstr ""
#: svnclasses.rsfilestatus
msgid "File status"
msgstr ""
@ -89,6 +101,22 @@ msgstr ""
msgid "(no author)"
msgstr ""
#: svnclasses.rsonlymodifieditemscanbediffed
msgid "Only modified (M) Items can be diffed"
msgstr ""
#: svnclasses.rsopenfileineditor
msgid "Open file in editor"
msgstr ""
#: svnclasses.rsopenpreviousrevisionineditor
msgid "Open previous revision in editor"
msgstr ""
#: svnclasses.rsopenthisrevisionineditor
msgid "Open this revision in editor"
msgstr ""
#: svnclasses.rspath
msgid "Path"
msgstr ""
@ -117,6 +145,10 @@ msgstr ""
msgid "Property status"
msgstr ""
#: svnclasses.rsremove
msgid "Remove from version control (keep local)"
msgstr ""
#: svnclasses.rsrepositorypath
msgid "Repository path"
msgstr ""
@ -141,10 +173,22 @@ msgstr ""
msgid "Show diff"
msgstr ""
#: svnclasses.rsshowdiffbase
msgid "Show diff of local changes"
msgstr ""
#: svnclasses.rsshowdiffcountrev
msgid "Show last X commits"
msgstr ""
#: svnclasses.rsshowdiffhead
msgid "Show diff against HEAD"
msgstr ""
#: svnclasses.rsshowdiffprev
msgid "Show diff against previous version"
msgstr ""
#: svnclasses.rsshowlog
msgid "Show log"
msgstr ""

View File

@ -13,6 +13,10 @@ msgstr ""
msgid "Action"
msgstr "Действие"
#: svnclasses.rsadd
msgid "Add to version control"
msgstr ""
#: svnclasses.rsadded
msgid "Added"
msgstr "Добавлено"
@ -37,6 +41,10 @@ msgstr "Конфликт"
msgid "Copy from path"
msgstr "Копия из пути"
#: svnclasses.rscreatepatchfile
msgid "Create patch file"
msgstr ""
#: svnclasses.rsdate
msgid "Date"
msgstr "Дата"
@ -61,6 +69,10 @@ msgstr "Редактировать"
msgid "Extension"
msgstr "Расширение"
#: svnclasses.rsfilenotinworkingcopyanymore
msgid "File is not part of local working copy (anymore)"
msgstr ""
#: svnclasses.rsfilestatus
msgid "File status"
msgstr "Статус файла"
@ -97,6 +109,22 @@ msgstr "Сообщение"
msgid "(no author)"
msgstr "(нет)"
#: svnclasses.rsonlymodifieditemscanbediffed
msgid "Only modified (M) Items can be diffed"
msgstr ""
#: svnclasses.rsopenfileineditor
msgid "Open file in editor"
msgstr ""
#: svnclasses.rsopenpreviousrevisionineditor
msgid "Open previous revision in editor"
msgstr ""
#: svnclasses.rsopenthisrevisionineditor
msgid "Open this revision in editor"
msgstr ""
#: svnclasses.rspath
msgid "Path"
msgstr "Путь"
@ -125,6 +153,10 @@ msgstr "Параметры проекта"
msgid "Property status"
msgstr "Статус свойства"
#: svnclasses.rsremove
msgid "Remove from version control (keep local)"
msgstr ""
#: svnclasses.rsrepositorypath
msgid "Repository path"
msgstr "Путь к репозитарию"
@ -149,10 +181,22 @@ msgstr "Параметры"
msgid "Show diff"
msgstr "Показать разницу Diff"
#: svnclasses.rsshowdiffbase
msgid "Show diff of local changes"
msgstr ""
#: svnclasses.rsshowdiffcountrev
msgid "Show last X commits"
msgstr "Показать последние X ревизий"
#: svnclasses.rsshowdiffhead
msgid "Show diff against HEAD"
msgstr ""
#: svnclasses.rsshowdiffprev
msgid "Show diff against previous version"
msgstr ""
#: svnclasses.rsshowlog
msgid "Show log"
msgstr "Показать журнал"

View File

@ -23,12 +23,14 @@ unit LazSVNIntf;
interface
uses
Classes, SysUtils, LCLtype, LResources, ProjectIntf, LCLProc;
SysUtils, LCLtype, LResources, LCLProc;
procedure ProcSVNLog(Sender: TObject);
procedure ProcSVNCommit(Sender: TObject);
procedure ProcSVNUpdate(Sender: TObject);
procedure ProcSVNDiff(Sender: TObject);
procedure ProcSVNDiffPrev(Sender: TObject);
procedure ProcSVNDiffHead(Sender: TObject);
procedure ProcSVNSettings(Sender: TObject);
procedure Register;
@ -44,6 +46,8 @@ var
CmdSVNCommit : TIDECommand;
CmdSVNUpdate : TIDECommand;
CmdSVNDiff : TIDECommand;
CmdSVNDiffPrev : TIDECommand;
CmdSVNDiffHead : TIDECommand;
CmdSVNSettings : TIDECommand;
procedure Register;
@ -65,20 +69,25 @@ begin
CmdSVNLog:=RegisterIDECommand(Cat, 'SVNLog', rsShowLog, Key, nil, @ProcSVNLog);
CmdSVNCommit:=RegisterIDECommand(Cat, 'SVNCommit', rsCommit, Key, nil, @ProcSVNCommit);
CmdSVNUpdate:=RegisterIDECommand(Cat, 'SVNUpdate', rsUpdate, Key, nil, @ProcSVNUpdate);
CmdSVNDiff:=RegisterIDECommand(Cat, 'SVNDiff', rsShowDiff, Key, nil, @ProcSVNDiff);
CmdSVNDiff:=RegisterIDECommand(Cat, 'SVNDiff', rsShowDiffBase, Key, nil, @ProcSVNDiff);
CmdSVNDiffPrev:=RegisterIDECommand(Cat, 'SVNDiffPrev', rsShowDiffPrev, Key, nil, @ProcSVNDiffPrev);
CmdSVNDiffHead:=RegisterIDECommand(Cat, 'SVNDiffHead', rsShowDiffHead, Key, nil, @ProcSVNDiffHead);
CmdSVNSettings:=RegisterIDECommand(Cat, 'SVNSettings', rsSVNSettings, Key, nil, @ProcSVNSettings);
{$note add menu_svn bitmap in the main menu}
mnuSVNMain := RegisterIDEMenuSection(itmCustomTools, 'SVN');
mnuSVNSection:=RegisterIDESubMenu(mnuSVNMain, 'SVN', 'SVN', nil, nil);
mnuSVNSection:=RegisterIDESubMenu(mnuSVNMain, 'SVN', 'SVN', nil, nil, 'menu_svn');
RegisterIDEMenuCommand(mnuSVNSection, 'SVNLog', rsShowLog, nil, nil,
CmdSVNLog, 'menu_svn_log');
RegisterIDEMenuCommand(mnuSVNSection, 'SVNCommit', rsCommit, nil, nil,
CmdSVNCommit, 'menu_svn_commit');
RegisterIDEMenuCommand(mnuSVNSection, 'SVNUpdate', rsUpdate, nil, nil,
CmdSVNUpdate, 'menu_svn_update');
RegisterIDEMenuCommand(mnuSVNSection, 'SVNDiff', rsShowDiff, nil, nil,
RegisterIDEMenuCommand(mnuSVNSection, 'SVNDiff', rsShowDiffBase, nil, nil,
CmdSVNDiff, 'menu_svn_diff');
RegisterIDEMenuCommand(mnuSVNSection, 'SVNDiffPrev', rsShowDiffPrev, nil, nil,
CmdSVNDiffPrev, 'menu_svn_diff');
RegisterIDEMenuCommand(mnuSVNSection, 'SVNDiffHead', rsShowDiffHead, nil, nil,
CmdSVNDiffHead, 'menu_svn_diff');
RegisterIDEMenuCommand(mnuSVNSection, 'SVNSettings', rsSettings, nil, nil,
CmdSVNSettings, 'menu_environment_options');
end;
@ -151,7 +160,7 @@ begin
end;
end;
procedure ProcSVNDiff(Sender: TObject);
procedure DoSVNDiff(ASwitches: String);
var
Repo: string;
IsActive: boolean;
@ -170,17 +179,28 @@ begin
if IsActive and (Repo <> '') then
begin
SrcFile := SourceEditorManagerIntf.ActiveEditor.FileName;
if LazarusIDE.ActiveProject.FindFile(SrcFile, [pfsfOnlyEditorFiles]).IsPartOfProject then
ShowSVNDiffFrm('-r PREV', '"' + SrcFile + '"')
else
ShowMessage(rsSourceFileDoesNotBelongToTheProjectPleaseAddFirst);
ShowSVNDiffFrm(ASwitches, SrcFile);
end
else
ShowMessage(rsProjectIsNotActiveInSVNSettingsPleaseActivateFirst);
end;
end;
procedure ProcSvnDiff(Sender: TObject);
begin
DoSvnDiff('-r BASE');
end;
procedure ProcSvnDiffHead(Sender: TObject);
begin
DoSvnDiff('-r HEAD');
end;
procedure ProcSvnDiffPrev(Sender: TObject);
begin
DoSvnDiff('-r PREV');
end;
procedure ProcSVNSettings(Sender: TObject);
begin
ShowSVNAddProjectFrm;

View File

@ -2,16 +2,18 @@
<CONFIG>
<Package Version="3">
<Name Value="lazsvnpkg"/>
<AddToProjectUsesSection Value="False"/>
<Author Value="Darius Blaszyk"/>
<CompilerOptions>
<Version Value="8"/>
<Version Value="9"/>
<SearchPaths>
<OtherUnitFiles Value="$(LazarusDir)/lcl/units/$(TargetCPU)-$(TargetOS)/;$(LazarusDir)/ideintf/units/$(TargetCPU)-$(TargetOS)/;$(LazarusDir)/components/lazsvnpkg/lib/$(TargetCPU)-$(TargetOS)/;$(LazarusDir)/units/$(TargetCPU)-$(TargetOS)/;$(LazarusDir)/components/codetools/units/$(TargetCPU)-$(TargetOS)/;$(LazarusDir)/components/synedit/units/$(TargetCPU)-$(TargetOS)/"/>
<OtherUnitFiles Value="$(LazarusDir)/lcl/units/$(TargetCPU)-$(TargetOS);$(LazarusDir)/ideintf/units/$(TargetCPU)-$(TargetOS);$(LazarusDir)/components/lazsvnpkg/lib/$(TargetCPU)-$(TargetOS);$(LazarusDir)/units/$(TargetCPU)-$(TargetOS);$(LazarusDir)/components/codetools/units/$(TargetCPU)-$(TargetOS);$(LazarusDir)/components/synedit/units/$(TargetCPU)-$(TargetOS)"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Parsing>
<SyntaxOptions>
<CStyleOperator Value="False"/>
<UseAnsiStrings Value="False"/>
</SyntaxOptions>
</Parsing>
<Other>
@ -128,7 +130,7 @@
</Item5>
</RequiredPkgs>
<UsageOptions>
<UnitPath Value="$(PkgOutDir)/"/>
<UnitPath Value="$(PkgOutDir)"/>
</UsageOptions>
<PublishOptions>
<Version Value="2"/>

View File

@ -23,23 +23,26 @@ unit SVNClasses;
interface
uses
Classes, SysUtils, ComCtrls, FileUtil, LCLProc, Dialogs, Controls,
Classes, SysUtils, ComCtrls, FileUtil, LCLProc, Controls,
XMLRead, DOM, Process, StdCtrls, Forms;
resourcestring
rsAction = 'Action';
rsAdded = 'Added';
rsAdd = 'Add to version control';
rsAuthor = 'Author';
rsCommit = 'Commit';
rsCommitRevision = 'Commit revision';
rsConflict = 'Conflict';
rsCopyFromPath = 'Copy from path';
rsCreatePatchFile = 'Create patch file';
rsDate = 'Date';
rsDelete = 'Delete';
rsDeleted = 'Deleted';
rsDiffActiveFile = 'Diff active file';
rsEdit = 'Edit';
rsExtension = 'Extension';
rsFileNotInWorkingCopyAnymore = 'File is not part of local working copy (anymore)';
rsFileStatus = 'File status';
rsIndexOutOfBoundsD = 'Index out of bounds (%d)';
rsLazarusSVNCommit = 'LazarusSVN Commit';
@ -49,6 +52,10 @@ resourcestring
rsMerged = 'Merged';
rsMessage = 'Message';
rsNoAuthor = '(no author)';
rsOpenFileInEditor = 'Open file in editor';
rsOpenThisRevisionInEditor = 'Open this revision in editor';
rsOpenPreviousRevisionInEditor = 'Open previous revision in editor';
rsOnlyModifiedItemsCanBeDiffed = 'Only modified (M) Items can be diffed';
rsPath = 'Path';
rsProjectFilename = 'Project filename';
rsProjectIsActive = 'Project is active';
@ -57,6 +64,7 @@ resourcestring
rsProjectName = 'Project name';
rsProjectOptions = 'Project options';
rsPropertyStatus = 'Property status';
rsRemove = 'Remove from version control (keep local)';
rsRepositoryPath = 'Repository path';
rsRevert = 'Revert';
rsRevision = 'Revision';
@ -64,6 +72,9 @@ resourcestring
rsSettings = 'Settings';
rsSVNSettings = 'SVN settings';
rsShowDiff = 'Show diff';
rsShowDiffBase = 'Show diff of local changes';
rsShowDiffPrev = 'Show diff against previous version';
rsShowDiffHead = 'Show diff against HEAD';
rsShowDiffCountRev = 'Show last X commits';
rsShowLog = 'Show log';
rsSourceFileDoesNotBelongToTheProjectPleaseAddFirst = 'Source file does not '
@ -106,7 +117,7 @@ type
public
List: TFPList;
constructor Create(const ARepoPath: string);
constructor Create(const ARepoPath: string; verbose: Boolean);
destructor Destroy; override;
property RepositoryPath: string read FRepositoryPath write FrepositoryPath;
@ -117,6 +128,7 @@ type
end;
procedure CmdLineToMemo(CmdLine: string; Memo: TMemo);
function ExecuteSvnReturnXml(ACommand: string): TXMLDocument;
procedure SetColumn(ListView: TListView; ColNo, DefaultWidth: integer; AName: string; AutoSize: boolean = true);
function SVNExecutable: string;
function ReplaceLineEndings(const s, NewLineEnds: string): string;
@ -124,8 +136,7 @@ function ISO8601ToDateTime(ADateTime: string): TDateTime;
implementation
uses
SVNAddProjectForm;
procedure CmdLineToMemo(CmdLine: string; Memo: TMemo);
var
@ -133,25 +144,24 @@ var
BytesRead: LongInt;
n: LongInt;
M: TMemoryStream;
ProcessMsg: string;
procedure UpdateStringsFromStream(Strings: TStrings; var M: TMemoryStream; var BytesRead: LongInt);
procedure UpdateMemoFromStream;
var
s: string;
begin
SetLength(s, BytesRead);
M.Read(s[1], BytesRead);
if BytesRead > 0 then begin
SetLength(s, BytesRead);
M.Read(s[1], BytesRead);
ProcessMsg := ProcessMsg + ReplaceLineEndings(s, LineEnding);
Strings.Text := ProcessMsg;
// this woks exactly like Append() only without the newline bug
Memo.SelText := ReplaceLineEndings(s, LineEnding);
M.SetSize(0);
BytesRead:=0;
M.SetSize(0);
BytesRead:=0;
end;
end;
begin
ProcessMsg := '';
AProcess := TProcess.Create(nil);
AProcess.CommandLine := CmdLine;
debugln('CmdLineToMemo commandline=', AProcess.CommandLine);
@ -161,6 +171,7 @@ begin
M := TMemoryStream.Create;
BytesRead := 0;
Memo.Lines.Text := '';
while AProcess.Running do
begin
@ -172,7 +183,7 @@ begin
if n > 0
then begin
Inc(BytesRead, n);
UpdateStringsFromStream(Memo.Lines, M, BytesRead);
UpdateMemoFromStream;
Application.ProcessMessages;
end
else
@ -188,13 +199,10 @@ begin
if n > 0
then begin
Inc(BytesRead, n);
UpdateStringsFromStream(Memo.Lines, M, BytesRead);
UpdateMemoFromStream;
Application.ProcessMessages;
end;
until n <= 0;
M.SetSize(BytesRead);
UpdateStringsFromStream(Memo.Lines, M, BytesRead);
AProcess.Free;
M.Free;
@ -251,22 +259,6 @@ begin
Result := EncodeDate(y,m,d) + EncodeTime(h,n,s,0);
end;
function SortSelectedAscending(Item1, Item2: Pointer): Integer;
begin
if PSVNStatusItem(Item1)^.Checked > PSVNStatusItem(Item2)^.Checked then
Result := 1
else
if PSVNStatusItem(Item1)^.Checked = PSVNStatusItem(Item2)^.Checked then
Result := 0
else
Result := -1;
end;
function SortSelectedDescending(Item1, Item2: Pointer): Integer;
begin
Result := -SortSelectedAscending(Item1, Item2);
end;
function SortPathAscending(Item1, Item2: Pointer): Integer;
begin
Result := CompareText(PSVNStatusItem(Item1)^.Path, PSVNStatusItem(Item2)^.Path);
@ -277,6 +269,22 @@ begin
Result := -SortPathAscending(Item1, Item2);
end;
function SortSelectedAscending(Item1, Item2: Pointer): Integer;
begin
if PSVNStatusItem(Item1)^.Checked > PSVNStatusItem(Item2)^.Checked then
Result := 1
else
if PSVNStatusItem(Item1)^.Checked = PSVNStatusItem(Item2)^.Checked then
Result := SortPathDescending(Item1, Item2)
else
Result := -1;
end;
function SortSelectedDescending(Item1, Item2: Pointer): Integer;
begin
Result := -SortSelectedAscending(Item1, Item2);
end;
function SortExtensionAscending(Item1, Item2: Pointer): Integer;
begin
Result := CompareText(PSVNStatusItem(Item1)^.Extension, PSVNStatusItem(Item2)^.Extension);
@ -365,19 +373,68 @@ begin
Result := -SortPropertyDateAscending(Item1, Item2);
end;
function ExecuteSvnReturnXml(ACommand: string): TXMLDocument;
var
AProcess: TProcess;
M: TMemoryStream;
n, BytesRead: Integer;
begin
AProcess := TProcess.Create(nil);
AProcess.CommandLine := SVNExecutable + ' ' + ACommand;
debugln('TSVNLogFrm.ExecuteSvnReturnXml CommandLine ' + AProcess.CommandLine);
AProcess.Options := AProcess.Options + [poUsePipes, poStdErrToOutput];
AProcess.ShowWindow := swoHIDE;
AProcess.Execute;
M := TMemoryStream.Create;
BytesRead := 0;
while AProcess.Running do
begin
// make sure we have room
M.SetSize(BytesRead + READ_BYTES);
// try reading it
n := AProcess.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
if n > 0
then begin
Inc(BytesRead, n);
end
else begin
// no data, wait 100 ms
Sleep(100);
end;
end;
// read last part
repeat
// make sure we have room
M.SetSize(BytesRead + READ_BYTES);
// try reading it
n := AProcess.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
if n > 0
then begin
Inc(BytesRead, n);
end;
until n <= 0;
M.SetSize(BytesRead);
ReadXMLFile(Result, M);
M.Free;
AProcess.Free;
end;
{ TSVNStatus }
constructor TSVNStatus.Create(const ARepoPath: string);
constructor TSVNStatus.Create(const ARepoPath: string; Verbose: Boolean);
var
ActNode: TDOMNode;
AProcess: TProcess;
BytesRead: LongInt;
Doc: TXMLDocument;
F: LongInt;
i: integer;
ListItem: PSVNStatusItem;
M: TMemoryStream;
n: LongInt;
Node: TDOMNode;
NodeName: string;
NodeValue: string;
@ -387,53 +444,25 @@ begin
List := TFPList.Create;
RepositoryPath := ARepoPath;
M := TMemoryStream.Create;
BytesRead := 0;
if Verbose then
Doc := ExecuteSvnReturnXml('stat --verbose --xml "' + RepositoryPath + '" --non-interactive')
else
Doc := ExecuteSvnReturnXml('stat --xml "' + RepositoryPath + '" --non-interactive');
AProcess := TProcess.Create(nil);
AProcess.CommandLine := SVNExecutable + ' stat --verbose --xml "' + RepositoryPath + '" --non-interactive';
debugln('TSVNStatus.Create CommandLine ' + AProcess.CommandLine);
AProcess.Options := AProcess.Options + [poUsePipes, poStdErrToOutput];
AProcess.ShowWindow := swoHIDE;
AProcess.Execute;
while AProcess.Running do
begin
// make sure we have room
M.SetSize(BytesRead + READ_BYTES);
// try reading it
n := AProcess.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
if n > 0 then
Inc(BytesRead, n)
else
// no data, wait 100 ms
Sleep(100);
end;
// read last part
repeat
// make sure we have room
M.SetSize(BytesRead + READ_BYTES);
// try reading it
n := AProcess.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
if n > 0 then
Inc(BytesRead, n);
until n <= 0;
M.SetSize(BytesRead);
ReadXMLFile(Doc, M);
AProcess.Free;
M.Free;
//now process the XML file
Node := Doc.DocumentElement.FirstChild.FirstChild;
if Node = nil then begin
// no <entry> node found, list is empty.
Doc.Free;
Exit();
end;
repeat
SubNode := Node;
New(ListItem);
Path := SubNode.Attributes.Item[0].NodeValue;
debugln('TSVNStatus.Create ' + Path);
F:=FileGetAttr(Path);
If F<>-1 then
@ -460,7 +489,7 @@ begin
if NodeName = 'item' then
begin
//ItemStatus
ListItem^.ItemStatus := NodeValue;
ListItem^.ItemStatus := LowerCase(NodeValue);
//Checked
ListItem^.Checked:=(NodeValue<>'unversioned') and (NodeValue<>'normal');
@ -506,6 +535,7 @@ begin
Node := Node.NextSibling;
until not Assigned(Node);
Doc.Free;
end;
destructor TSVNStatus.Destroy;

View File

@ -1,51 +1,41 @@
object SVNDiffFrm: TSVNDiffFrm
Left = 154
Height = 416
Top = 200
Width = 731
HelpContext = 0
ActiveControl = SVNDiffMemo
Left = 283
Height = 466
Top = 102
Width = 617
Caption = 'SVNDiffFrm'
ChildSizing.LeftRightSpacing = 0
ChildSizing.TopBottomSpacing = 0
ChildSizing.HorizontalSpacing = 0
ChildSizing.VerticalSpacing = 0
ChildSizing.ControlsPerLine = 0
ClientHeight = 416
ClientWidth = 731
Font.Height = 0
Font.Style = []
ClientHeight = 466
ClientWidth = 617
OnCreate = FormCreate
OnShow = FormShow
Position = poScreenCenter
LCLVersion = '0.9.27'
LCLVersion = '0.9.29'
object ButtonPanel: TButtonPanel
Left = 6
Height = 48
Top = 368
Width = 719
HelpContext = 0
Align = alBottom
AutoSize = True
ButtonOrder = boDefault
Height = 34
Top = 426
Width = 605
OKButton.Name = 'OKButton'
OKButton.Caption = '&OK'
HelpButton.Name = 'HelpButton'
HelpButton.Caption = '&Help'
HelpButton.Enabled = False
CloseButton.Name = 'CloseButton'
CloseButton.Caption = '&Close'
CloseButton.Enabled = False
CancelButton.Name = 'CancelButton'
CancelButton.Caption = 'Cancel'
CancelButton.Enabled = False
TabOrder = 0
DefaultButton = pbOK
ShowButtons = [pbOK]
object SaveButton: TBitBtn
Left = 78
Height = 34
Top = 8
Width = 106
HelpContext = 0
Left = 6
Height = 22
Top = 6
Width = 101
Align = alLeft
AutoSize = True
BorderSpacing.Left = 0
BorderSpacing.Top = 0
BorderSpacing.Right = 0
BorderSpacing.Bottom = 0
BorderSpacing.Around = 6
BorderSpacing.CellAlignHorizontal = ccaFill
BorderSpacing.CellAlignVertical = ccaFill
Caption = 'SaveButton'
Glyph.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
@ -91,31 +81,22 @@ object SVNDiffFrm: TSVNDiffFrm
object SVNDiffMemo: TMemo
Cursor = crHourGlass
Left = 6
Height = 356
Height = 414
Top = 6
Width = 719
HelpContext = 0
Width = 605
Align = alClient
BorderSpacing.Left = 0
BorderSpacing.Top = 0
BorderSpacing.Right = 0
BorderSpacing.Bottom = 0
BorderSpacing.Around = 6
BorderSpacing.CellAlignHorizontal = ccaFill
BorderSpacing.CellAlignVertical = ccaFill
Font.Height = -13
Font.Name = 'Courier'
Font.Style = []
ParentFont = False
ScrollBars = ssAutoBoth
TabOrder = 1
WordWrap = False
end
object SaveDialog: TSaveDialog
Width = 0
Height = 0
DefaultExt = '.diff'
Filter = 'Patch|.diff;.patch'
Filter = 'Patch|*.diff;*.patch|All Files|*.*'
Options = [ofOverwritePrompt, ofEnableSizing, ofViewDetail]
left = 21
top = 317
end

View File

@ -1,82 +1,77 @@
{ This is an automatically generated lazarus resource file }
LazarusResources.Add('TSVNDiffFrm','FORMDATA',[
'TPF0'#11'TSVNDiffFrm'#10'SVNDiffFrm'#4'Left'#3#154#0#6'Height'#3#160#1#3'Top'
+#3#200#0#5'Width'#3#219#2#11'HelpContext'#2#0#13'ActiveControl'#7#11'SVNDiff'
+'Memo'#7'Caption'#6#10'SVNDiffFrm'#28'ChildSizing.LeftRightSpacing'#2#0#28'C'
+'hildSizing.TopBottomSpacing'#2#0#29'ChildSizing.HorizontalSpacing'#2#0#27'C'
+'hildSizing.VerticalSpacing'#2#0#27'ChildSizing.ControlsPerLine'#2#0#12'Clie'
+'ntHeight'#3#160#1#11'ClientWidth'#3#219#2#11'Font.Height'#2#0#10'Font.Style'
+#11#0#8'OnCreate'#7#10'FormCreate'#6'OnShow'#7#8'FormShow'#8'Position'#7#14
+'poScreenCenter'#10'LCLVersion'#6#6'0.9.27'#0#12'TButtonPanel'#11'ButtonPane'
+'l'#4'Left'#2#6#6'Height'#2'0'#3'Top'#3'p'#1#5'Width'#3#207#2#11'HelpContext'
+#2#0#5'Align'#7#8'alBottom'#8'AutoSize'#9#11'ButtonOrder'#7#9'boDefault'#8'T'
+'abOrder'#2#0#13'DefaultButton'#7#4'pbOK'#11'ShowButtons'#11#4'pbOK'#0#0#7'T'
+'BitBtn'#10'SaveButton'#4'Left'#2'N'#6'Height'#2'"'#3'Top'#2#8#5'Width'#2'j'
+#11'HelpContext'#2#0#5'Align'#7#6'alLeft'#8'AutoSize'#9#18'BorderSpacing.Lef'
+'t'#2#0#17'BorderSpacing.Top'#2#0#19'BorderSpacing.Right'#2#0#20'BorderSpaci'
+'ng.Bottom'#2#0#20'BorderSpacing.Around'#2#6'!BorderSpacing.CellAlignHorizon'
+'tal'#7#7'ccaFill'#31'BorderSpacing.CellAlignVertical'#7#7'ccaFill'#7'Captio'
+'n'#6#10'SaveButton'#10'Glyph.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0
+'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0
+#0#0#0#0#0#0#0#0#0'h;'#30#255#131'K&'#255#172'b1'#255#183'h5'#255#181'h5'#255
+#180'g4'#255#178'f4'#255#176'e3'#255#174'd3'#255#172'c2'#255#170'b2'#255#169
+'a2'#255#168'`1'#255#166'`1'#255#157'[.'#255#129'K&'#255#162'\.'#255#235#198
+#173#255#234#197#173#255#254#251#248#255#254#251#248#255#254#251#248#255#254
'TPF0'#11'TSVNDiffFrm'#10'SVNDiffFrm'#4'Left'#3#27#1#6'Height'#3#210#1#3'Top'
+#2'f'#5'Width'#3'i'#2#7'Caption'#6#10'SVNDiffFrm'#12'ClientHeight'#3#210#1#11
+'ClientWidth'#3'i'#2#8'OnCreate'#7#10'FormCreate'#6'OnShow'#7#8'FormShow'#8
+'Position'#7#14'poScreenCenter'#10'LCLVersion'#6#6'0.9.29'#0#12'TButtonPanel'
+#11'ButtonPanel'#4'Left'#2#6#6'Height'#2'"'#3'Top'#3#170#1#5'Width'#3']'#2#13
+'OKButton.Name'#6#8'OKButton'#16'OKButton.Caption'#6#3'&OK'#15'HelpButton.Na'
+'me'#6#10'HelpButton'#18'HelpButton.Caption'#6#5'&Help'#18'HelpButton.Enable'
+'d'#8#16'CloseButton.Name'#6#11'CloseButton'#19'CloseButton.Caption'#6#6'&Cl'
+'ose'#19'CloseButton.Enabled'#8#17'CancelButton.Name'#6#12'CancelButton'#20
+'CancelButton.Caption'#6#6'Cancel'#20'CancelButton.Enabled'#8#8'TabOrder'#2#0
+#11'ShowButtons'#11#4'pbOK'#0#0#7'TBitBtn'#10'SaveButton'#4'Left'#2#6#6'Heig'
+'ht'#2#22#3'Top'#2#6#5'Width'#2'e'#5'Align'#7#6'alLeft'#8'AutoSize'#9#20'Bor'
+'derSpacing.Around'#2#6#7'Caption'#6#10'SaveButton'#10'Glyph.Data'#10':'#4#0
+#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0
+#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0'h;'#30#255#131'K&'#255#172
+'b1'#255#183'h5'#255#181'h5'#255#180'g4'#255#178'f4'#255#176'e3'#255#174'd3'
+#255#172'c2'#255#170'b2'#255#169'a2'#255#168'`1'#255#166'`1'#255#157'[.'#255
+#129'K&'#255#162'\.'#255#235#198#173#255#234#197#173#255#254#251#248#255#254
+#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255
+#254#251#248#255#254#251#248#255#200#154'|'#255#199#152'y'#255#155'Y.'#255
+#185'k7'#255#237#202#179#255#224#162'z'#255#254#250#247#255'b'#192#136#255'b'
+#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'
+#192#136#255'b'#192#136#255#253#249#246#255#202#141'e'#255#201#155'|'#255#166
+'`1'#255#187'l8'#255#238#204#182#255#225#162'z'#255#254#250#247#255#191#220
+#194#255#191#220#194#255#191#220#194#255#191#220#194#255#191#220#194#255#191
+#220#194#255#191#220#194#255#191#220#194#255#253#249#246#255#205#144'h'#255
+#204#158#129#255#168'a2'#255#187'k8'#255#239#206#184#255#225#162'y'#255#254
+#250#247#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'
+#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255#253#249#246#255#207
+#147'j'#255#206#163#132#255#170'a2'#255#186'j6'#255#239#208#187#255#226#162
+'z'#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254
+#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255
+#254#251#248#255#211#150'm'#255#210#167#138#255#171'b2'#255#187'j6'#255#240
+#210#190#255#226#163'z'#255#226#163'z'#255#225#163'z'#255#226#163'{'#255#225
+#163'{'#255#224#161'x'#255#222#159'w'#255#221#159'v'#255#220#157't'#255#217
+#155'r'#255#216#153'q'#255#214#153'p'#255#213#171#142#255#173'c3'#255#187'j6'
+#255#242#213#194#255#227#163'z'#255#227#163'z'#255#226#163'{'#255#226#163'{'
+#255#226#164'{'#255#225#162'y'#255#224#161'x'#255#222#160'w'#255#222#158'u'
+#255#220#157't'#255#218#155's'#255#217#155's'#255#218#176#149#255#175'd3'#255
+#187'j6'#255#242#216#197#255#227#164'{'#255#227#163'z'#255#227#164'z'#255#226
+#164'{'#255#226#163'{'#255#225#163'{'#255#225#162'y'#255#223#160'w'#255#222
+#159'v'#255#221#158't'#255#219#156'r'#255#220#157't'#255#221#181#154#255#177
+'e4'#255#187'k6'#255#244#217#199#255#230#166'}'#255#200#140'd'#255#201#141'e'
+#255#201#142'g'#255#203#146'l'#255#203#146'm'#255#202#144'i'#255#200#140'e'
+#255#200#140'd'#255#200#140'd'#255#200#140'd'#255#218#156't'#255#225#186#159
+#255#179'f4'#255#187'l7'#255#244#220#201#255#231#167'}'#255#249#236#225#255
+#249#236#225#255#249#237#227#255#252#244#238#255#253#250#247#255#253#247#243
+#255#250#237#229#255#247#231#219#255#247#229#217#255#246#229#216#255#222#160
+'w'#255#228#190#164#255#180'g4'#255#188'm9'#255#245#221#204#255#231#168'~'
+#255#250#240#232#255#250#240#232#255#201#141'f'#255#250#240#233#255#253#248
+#243#255#254#250#248#255#252#244#239#255#249#233#223#255#247#231#219#255#247
+#229#217#255#224#162'x'#255#231#194#169#255#182'h5'#255#177'e3'#255#246#223
+#208#255#232#168'~'#255#252#246#241#255#252#246#241#255#200#140'd'#255#250
+#241#233#255#251#244#238#255#253#250#247#255#253#249#246#255#250#240#232#255
+#248#232#221#255#247#230#219#255#225#163'z'#255#239#213#195#255#182'i5'#255
+#159'[.'#255#246#223#209#255#233#170#128#255#254#250#246#255#253#250#246#255
+#200#140'd'#255#251#243#238#255#251#241#234#255#252#246#242#255#254#251#248
+#255#252#246#241#255#249#236#226#255#248#231#219#255#238#208#186#255#236#208
+#189#255#182'm<'#255'rA!'#255#246#224#209#255#247#224#209#255#254#251#248#255
+#254#251#247#255#253#249#246#255#252#245#240#255#250#240#234#255#251#242#237
,#255#253#249#246#255#253#250#247#255#251#241#235#255#248#233#223#255#232#205
+#186#255#186'W'#255'F)'#21#0'S/'#24#0'j<'#30#255#150'V+'#255#175'd2'#255#188
+'m9'#255#187'l7'#255#187'k6'#255#187'j6'#255#187'j6'#255#188'l9'#255#189'n;'
+#255#187'm:'#255#175'd4'#255#149'Y1'#255'<#'#17#0#0#0#0#0#9'NumGlyphs'#2#0#7
+'OnClick'#7#15'SaveButtonClick'#8'TabOrder'#2#4#0#0#0#5'TMemo'#11'SVNDiffMem'
+'o'#6'Cursor'#7#11'crHourGlass'#4'Left'#2#6#6'Height'#3'd'#1#3'Top'#2#6#5'Wi'
+'dth'#3#207#2#11'HelpContext'#2#0#5'Align'#7#8'alClient'#18'BorderSpacing.Le'
+'ft'#2#0#17'BorderSpacing.Top'#2#0#19'BorderSpacing.Right'#2#0#20'BorderSpac'
+'ing.Bottom'#2#0#20'BorderSpacing.Around'#2#6'!BorderSpacing.CellAlignHorizo'
+'ntal'#7#7'ccaFill'#31'BorderSpacing.CellAlignVertical'#7#7'ccaFill'#11'Font'
+'.Height'#2#243#9'Font.Name'#6#7'Courier'#10'Font.Style'#11#0#10'ParentFont'
+#8#10'ScrollBars'#7#10'ssAutoBoth'#8'TabOrder'#2#1#8'WordWrap'#8#0#0#11'TSav'
+'eDialog'#10'SaveDialog'#5'Width'#2#0#6'Height'#2#0#10'DefaultExt'#6#5'.diff'
+#6'Filter'#6#18'Patch|.diff;.patch'#4'left'#2#21#3'top'#3'='#1#0#0#0
+#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#200#154'|'
+#255#199#152'y'#255#155'Y.'#255#185'k7'#255#237#202#179#255#224#162'z'#255
+#254#250#247#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255
+'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255#253#249#246#255
+#202#141'e'#255#201#155'|'#255#166'`1'#255#187'l8'#255#238#204#182#255#225
+#162'z'#255#254#250#247#255#191#220#194#255#191#220#194#255#191#220#194#255
+#191#220#194#255#191#220#194#255#191#220#194#255#191#220#194#255#191#220#194
+#255#253#249#246#255#205#144'h'#255#204#158#129#255#168'a2'#255#187'k8'#255
+#239#206#184#255#225#162'y'#255#254#250#247#255'b'#192#136#255'b'#192#136#255
+'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255
+'b'#192#136#255#253#249#246#255#207#147'j'#255#206#163#132#255#170'a2'#255
+#186'j6'#255#239#208#187#255#226#162'z'#255#254#251#248#255#254#251#248#255
+#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248
+#255#254#251#248#255#254#251#248#255#254#251#248#255#211#150'm'#255#210#167
+#138#255#171'b2'#255#187'j6'#255#240#210#190#255#226#163'z'#255#226#163'z'
+#255#225#163'z'#255#226#163'{'#255#225#163'{'#255#224#161'x'#255#222#159'w'
+#255#221#159'v'#255#220#157't'#255#217#155'r'#255#216#153'q'#255#214#153'p'
+#255#213#171#142#255#173'c3'#255#187'j6'#255#242#213#194#255#227#163'z'#255
+#227#163'z'#255#226#163'{'#255#226#163'{'#255#226#164'{'#255#225#162'y'#255
+#224#161'x'#255#222#160'w'#255#222#158'u'#255#220#157't'#255#218#155's'#255
+#217#155's'#255#218#176#149#255#175'd3'#255#187'j6'#255#242#216#197#255#227
+#164'{'#255#227#163'z'#255#227#164'z'#255#226#164'{'#255#226#163'{'#255#225
+#163'{'#255#225#162'y'#255#223#160'w'#255#222#159'v'#255#221#158't'#255#219
+#156'r'#255#220#157't'#255#221#181#154#255#177'e4'#255#187'k6'#255#244#217
+#199#255#230#166'}'#255#200#140'd'#255#201#141'e'#255#201#142'g'#255#203#146
+'l'#255#203#146'm'#255#202#144'i'#255#200#140'e'#255#200#140'd'#255#200#140
+'d'#255#200#140'd'#255#218#156't'#255#225#186#159#255#179'f4'#255#187'l7'#255
+#244#220#201#255#231#167'}'#255#249#236#225#255#249#236#225#255#249#237#227
+#255#252#244#238#255#253#250#247#255#253#247#243#255#250#237#229#255#247#231
+#219#255#247#229#217#255#246#229#216#255#222#160'w'#255#228#190#164#255#180
+'g4'#255#188'm9'#255#245#221#204#255#231#168'~'#255#250#240#232#255#250#240
+#232#255#201#141'f'#255#250#240#233#255#253#248#243#255#254#250#248#255#252
+#244#239#255#249#233#223#255#247#231#219#255#247#229#217#255#224#162'x'#255
+#231#194#169#255#182'h5'#255#177'e3'#255#246#223#208#255#232#168'~'#255#252
+#246#241#255#252#246#241#255#200#140'd'#255#250#241#233#255#251#244#238#255
+#253#250#247#255#253#249#246#255#250#240#232#255#248#232#221#255#247#230#219
+#255#225#163'z'#255#239#213#195#255#182'i5'#255#159'[.'#255#246#223#209#255
+#233#170#128#255#254#250#246#255#253#250#246#255#200#140'd'#255#251#243#238
+#255#251#241#234#255#252#246#242#255#254#251#248#255#252#246#241#255#249#236
+#226#255#248#231#219#255#238#208#186#255#236#208#189#255#182'm<'#255'rA!'#255
+#246#224#209#255#247#224#209#255#254#251#248#255#254#251#247#255#253#249#246
+#255#252#245#240#255#250#240#234#255#251#242#237#255#253#249#246#255#253#250
+#247#255#251#241#235#255#248#233#223#255#232#205#186#255#186#127'W'#255'F)'
+#21#0'S/'#24#0'j<'#30#255#150'V+'#255#175'd2'#255#188'm9'#255#187'l7'#255#187
+'k6'#255#187'j6'#255#187'j6'#255#188'l9'#255#189'n;'#255#187'm:'#255#175'd4'
,#255#149'Y1'#255'<#'#17#0#0#0#0#0#9'NumGlyphs'#2#0#7'OnClick'#7#15'SaveButto'
+'nClick'#8'TabOrder'#2#4#0#0#0#5'TMemo'#11'SVNDiffMemo'#6'Cursor'#7#11'crHou'
+'rGlass'#4'Left'#2#6#6'Height'#3#158#1#3'Top'#2#6#5'Width'#3']'#2#5'Align'#7
+#8'alClient'#20'BorderSpacing.Around'#2#6#11'Font.Height'#2#243#9'Font.Name'
+#6#7'Courier'#10'ParentFont'#8#10'ScrollBars'#7#10'ssAutoBoth'#8'TabOrder'#2
+#1#8'WordWrap'#8#0#0#11'TSaveDialog'#10'SaveDialog'#10'DefaultExt'#6#5'.diff'
+#6'Filter'#6'"Patch|*.diff;*.patch|All Files|*.*'#7'Options'#11#17'ofOverwri'
+'tePrompt'#14'ofEnableSizing'#12'ofViewDetail'#0#4'left'#2#21#3'top'#3'='#1#0
+#0#0
]);

View File

@ -23,8 +23,8 @@ unit SVNDiffForm;
interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
ButtonPanel, StdCtrls, Process, Buttons, LCLProc;
Classes, SysUtils, FileUtil, LResources, Forms, Dialogs,
ButtonPanel, StdCtrls, Buttons, LazIDEIntf;
type
@ -38,31 +38,44 @@ type
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure SaveButtonClick(Sender: TObject);
destructor Destroy; override;
private
FRepositoryPath: string;
{ private declarations }
FFileList: TStringList;
FSwitches: string;
FRepoBaseDir: string;
public
{ public declarations }
procedure Execute(Data: PtrInt);
property RepositoryPath: string read FRepositoryPath write FrepositoryPath;
{list of filenames with absolute path}
property FileList: TStringList read FFileList write FFileList;
{switches for the diff command}
property Switches: string read FSwitches write FSwitches;
end;
procedure ShowSVNDiffFrm(ASwitches, ARepoPath: string);
procedure ShowSVNDiffFrm(ASwitches, AFileName: string);
procedure ShowSVNDiffFrm(ASwitches: string; AFileList: TStringList); overload;
implementation
uses
SVNClasses;
procedure ShowSVNDiffFrm(ASwitches, ARepoPath: string);
procedure ShowSVNDiffFrm(ASwitches, AFileName: string);
var
List: TStringList;
begin
List := TStringList.Create;
List.Append(AFileName);
ShowSVNDiffFrm(ASwitches, List);
end;
procedure ShowSVNDiffFrm(ASwitches: string; AFileList: TStringList);
var
SVNDiffFrm: TSVNDiffFrm;
begin
SVNDiffFrm := TSVNDiffFrm.Create(nil);
SVNDiffFrm.RepositoryPath:=ARepoPath;
SVNDiffFrm.FSwitches:=ASwitches;
SVNDiffFrm.FileList:=AFileList;
SVNDiffFrm.Switches:=ASwitches;
SVNDiffFrm.ShowModal;
SVNDiffFrm.Free;
@ -71,13 +84,21 @@ end;
{ TSVNDiffFrm }
procedure TSVNDiffFrm.FormShow(Sender: TObject);
var
CaptionName: string;
begin
Caption := Format(rsLazarusSVNDiff, [RepositoryPath]);
FRepoBaseDir := LazarusIDE.ActiveProject.CustomSessionData.Values[SVN_REPOSITORY];
if FileList.Count = 1 then
CaptionName := CreateRelativePath(FileList.Strings[0], FRepoBaseDir, false)
else
CaptionName := FRepoBaseDir;
Caption := Format(rsLazarusSVNDiff, [CaptionName]);
Application.QueueAsyncCall(@Execute, 0);
end;
procedure TSVNDiffFrm.FormCreate(Sender: TObject);
begin
SaveButton.Enabled := False;
SaveButton.Caption:=rsSave;
end;
@ -88,9 +109,32 @@ begin
end;
procedure TSVNDiffFrm.Execute(Data: PtrInt);
var
i: Integer;
FileNames: String; // all filenames concatenated for the command line
begin
CmdLineToMemo(SVNExecutable + ' diff ' + FSwitches + ' ' + RepositoryPath + ' --non-interactive',
FileNames := '';
for i := 0 to FileList.Count - 1 do begin
if FileExists(FileList.Strings[i]) then
FileNames += ' "' + CreateRelativePath(FileList.Strings[i], FRepoBaseDir, False) + '"'
else
FileNames += ' "' + FileList.Strings[i] + '"' // might be a http:// url
end;
// in the previous step we made the filenames relative because we don't
// want absolute paths in our diff files. Now we must make sure we execute
// the svn diff command from within the repository base directory.
chdir(FRepoBaseDir);
CmdLineToMemo(SVNExecutable + ' diff ' + FSwitches + FileNames + ' --non-interactive',
SVNDiffMemo);
SaveButton.Enabled := True;
end;
destructor TSVNDiffFrm.Destroy;
begin
FFileList.Free;
inherited Destroy;
end;
initialization

View File

@ -1,9 +1,8 @@
object SVNLogFrm: TSVNLogFrm
Left = 407
Left = 289
Height = 566
Top = 176
Top = 135
Width = 726
ActiveControl = LogListView
Caption = 'SVNLogFrm'
ClientHeight = 566
ClientWidth = 726
@ -18,9 +17,9 @@ object SVNLogFrm: TSVNLogFrm
AnchorSideBottom.Control = SVNLogLimit
AnchorSideBottom.Side = asrBottom
Left = 6
Height = 18
Top = 496
Width = 143
Height = 14
Top = 506
Width = 97
Anchors = [akLeft, akBottom]
BorderSpacing.Left = 6
BorderSpacing.Right = 6
@ -29,7 +28,7 @@ object SVNLogFrm: TSVNLogFrm
end
object LogListView: TListView
Left = 6
Height = 159
Height = 200
Top = 6
Width = 714
Align = alTop
@ -54,8 +53,8 @@ object SVNLogFrm: TSVNLogFrm
end
object SVNLogMsgMemo: TMemo
Left = 6
Height = 151
Top = 170
Height = 60
Top = 210
Width = 714
Align = alTop
BorderSpacing.Left = 6
@ -67,8 +66,8 @@ object SVNLogFrm: TSVNLogFrm
object SVNActionsListView: TListView
AnchorSideBottom.Control = RefreshButton
Left = 6
Height = 153
Top = 326
Height = 217
Top = 274
Width = 714
Align = alTop
Anchors = [akTop, akLeft, akRight, akBottom]
@ -93,17 +92,28 @@ object SVNLogFrm: TSVNLogFrm
end
object ButtonPanel: TButtonPanel
Left = 6
Height = 40
Top = 520
Height = 34
Top = 526
Width = 714
OKButton.Name = 'OKButton'
OKButton.Caption = '&OK'
HelpButton.Name = 'HelpButton'
HelpButton.Caption = '&Help'
HelpButton.Enabled = False
CloseButton.Name = 'CloseButton'
CloseButton.Caption = '&Close'
CloseButton.Enabled = False
CancelButton.Name = 'CancelButton'
CancelButton.Caption = 'Cancel'
CancelButton.Enabled = False
TabOrder = 3
ShowButtons = [pbOK]
end
object Splitter1: TSplitter
Cursor = crVSplit
Left = 0
Height = 5
Top = 165
Height = 4
Top = 270
Width = 726
Align = alTop
ResizeAnchor = akTop
@ -111,8 +121,8 @@ object SVNLogFrm: TSVNLogFrm
object Splitter2: TSplitter
Cursor = crVSplit
Left = 0
Height = 5
Top = 321
Height = 4
Top = 206
Width = 726
Align = alTop
ResizeAnchor = akTop
@ -121,9 +131,9 @@ object SVNLogFrm: TSVNLogFrm
AnchorSideLeft.Control = Label1
AnchorSideLeft.Side = asrBottom
AnchorSideBottom.Control = ButtonPanel
Left = 155
Height = 27
Top = 487
Left = 109
Height = 21
Top = 499
Width = 94
Anchors = [akLeft, akBottom]
BorderSpacing.Around = 6
@ -135,10 +145,10 @@ object SVNLogFrm: TSVNLogFrm
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = ButtonPanel
Left = 655
Height = 29
Top = 485
Width = 65
Left = 656
Height = 23
Top = 497
Width = 64
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Around = 6
@ -148,13 +158,28 @@ object SVNLogFrm: TSVNLogFrm
end
object SVNActionsPopupMenu: TPopupMenu
Images = ImageList
OnPopup = SVNActionsPopupMenuPopup
left = 37
top = 369
object mnuShowDiff: TMenuItem
Caption = 'New Item1'
Caption = 'diff'
ImageIndex = 0
OnClick = mnuShowDiffClick
end
object mnuOpenCurent: TMenuItem
Caption = 'open'
OnClick = mnuOpenCurentClick
end
object mnuOpenRevision: TMenuItem
Caption = 'open rev'
Enabled = False
OnClick = mnuOpenRevisionClick
end
object mnuOpenPrevRevision: TMenuItem
Caption = 'open rev-1'
Enabled = False
OnClick = mnuOpenPrevRevisionClick
end
end
object ImageList: TImageList
left = 75

View File

@ -1,47 +1,57 @@
{ This is an automatically generated lazarus resource file }
LazarusResources.Add('TSVNLogFrm','FORMDATA',[
'TPF0'#10'TSVNLogFrm'#9'SVNLogFrm'#4'Left'#3#151#1#6'Height'#3'6'#2#3'Top'#3
+#176#0#5'Width'#3#214#2#13'ActiveControl'#7#11'LogListView'#7'Caption'#6#9'S'
+'VNLogFrm'#12'ClientHeight'#3'6'#2#11'ClientWidth'#3#214#2#8'OnCreate'#7#10
+'FormCreate'#9'OnDestroy'#7#11'FormDestroy'#6'OnShow'#7#8'FormShow'#8'Positi'
+'on'#7#14'poScreenCenter'#10'LCLVersion'#6#6'0.9.29'#0#6'TLabel'#6'Label1'#22
+'AnchorSideLeft.Control'#7#5'Owner'#21'AnchorSideTop.Control'#7#11'SVNLogLim'
+'it'#24'AnchorSideBottom.Control'#7#11'SVNLogLimit'#21'AnchorSideBottom.Side'
+#7#9'asrBottom'#4'Left'#2#6#6'Height'#2#18#3'Top'#3#240#1#5'Width'#3#143#0#7
+'Anchors'#11#6'akLeft'#8'akBottom'#0#18'BorderSpacing.Left'#2#6#19'BorderSpa'
+'cing.Right'#2#6#7'Caption'#6#19'Show last X commits'#11'ParentColor'#8#0#0#9
+'TListView'#11'LogListView'#4'Left'#2#6#6'Height'#3#159#0#3'Top'#2#6#5'Width'
+#3#202#2#5'Align'#7#5'alTop'#18'BorderSpacing.Left'#2#6#17'BorderSpacing.Top'
+#2#6#19'BorderSpacing.Right'#2#6#7'Columns'#14#1#0#1#0#1#0#1#5'Width'#3'"'#2
+#0#0#9'ItemIndex'#2#255#9'RowSelect'#9#8'TabOrder'#2#0#9'ViewStyle'#7#8'vsRe'
+'port'#12'OnSelectItem'#7#21'LogListViewSelectItem'#0#0#5'TMemo'#13'SVNLogMs'
+'gMemo'#4'Left'#2#6#6'Height'#3#151#0#3'Top'#3#170#0#5'Width'#3#202#2#5'Alig'
+'n'#7#5'alTop'#18'BorderSpacing.Left'#2#6#19'BorderSpacing.Right'#2#6#10'Par'
+'entFont'#8#8'ReadOnly'#9#8'TabOrder'#2#1#0#0#9'TListView'#18'SVNActionsList'
+'View'#24'AnchorSideBottom.Control'#7#13'RefreshButton'#4'Left'#2#6#6'Height'
+#3#153#0#3'Top'#3'F'#1#5'Width'#3#202#2#5'Align'#7#5'alTop'#7'Anchors'#11#5
+'akTop'#6'akLeft'#7'akRight'#8'akBottom'#0#18'BorderSpacing.Left'#2#6#19'Bor'
+'derSpacing.Right'#2#6#20'BorderSpacing.Bottom'#2#6#7'Columns'#14#1#0#1#0#1#0
+#1#5'Width'#3'"'#2#0#0#9'ItemIndex'#2#255#9'PopupMenu'#7#19'SVNActionsPopupM'
+'enu'#9'RowSelect'#9#8'TabOrder'#2#2#9'ViewStyle'#7#8'vsReport'#0#0#12'TButt'
+'onPanel'#11'ButtonPanel'#4'Left'#2#6#6'Height'#2'('#3'Top'#3#8#2#5'Width'#3
+#202#2#8'TabOrder'#2#3#11'ShowButtons'#11#4'pbOK'#0#0#0#9'TSplitter'#9'Split'
+'ter1'#6'Cursor'#7#8'crVSplit'#4'Left'#2#0#6'Height'#2#5#3'Top'#3#165#0#5'Wi'
+'dth'#3#214#2#5'Align'#7#5'alTop'#12'ResizeAnchor'#7#5'akTop'#0#0#9'TSplitte'
+'r'#9'Splitter2'#6'Cursor'#7#8'crVSplit'#4'Left'#2#0#6'Height'#2#5#3'Top'#3
+'A'#1#5'Width'#3#214#2#5'Align'#7#5'alTop'#12'ResizeAnchor'#7#5'akTop'#0#0#9
+'TSpinEdit'#11'SVNLogLimit'#22'AnchorSideLeft.Control'#7#6'Label1'#19'Anchor'
+'SideLeft.Side'#7#9'asrBottom'#24'AnchorSideBottom.Control'#7#11'ButtonPanel'
+#4'Left'#3#155#0#6'Height'#2#27#3'Top'#3#231#1#5'Width'#2'^'#7'Anchors'#11#6
+'akLeft'#8'akBottom'#0#20'BorderSpacing.Around'#2#6#8'MaxValue'#4#160#134#1#0
+#8'TabOrder'#2#6#5'Value'#2'd'#0#0#7'TButton'#13'RefreshButton'#23'AnchorSid'
+'eRight.Control'#7#5'Owner'#20'AnchorSideRight.Side'#7#9'asrBottom'#24'Ancho'
+'rSideBottom.Control'#7#11'ButtonPanel'#4'Left'#3#143#2#6'Height'#2#29#3'Top'
+#3#229#1#5'Width'#2'A'#7'Anchors'#11#7'akRight'#8'akBottom'#0#8'AutoSize'#9
+#20'BorderSpacing.Around'#2#6#7'Caption'#6#7'Refresh'#7'OnClick'#7#18'Refres'
+'hButtonClick'#8'TabOrder'#2#7#0#0#10'TPopupMenu'#19'SVNActionsPopupMenu'#6
+'Images'#7#9'ImageList'#4'left'#2'%'#3'top'#3'q'#1#0#9'TMenuItem'#11'mnuShow'
+'Diff'#7'Caption'#6#9'New Item1'#10'ImageIndex'#2#0#7'OnClick'#7#16'mnuShowD'
+'iffClick'#0#0#0#10'TImageList'#9'ImageList'#4'left'#2'K'#3'top'#3'q'#1#0#0#0
'TPF0'#10'TSVNLogFrm'#9'SVNLogFrm'#4'Left'#3'!'#1#6'Height'#3'6'#2#3'Top'#3
+#135#0#5'Width'#3#214#2#7'Caption'#6#9'SVNLogFrm'#12'ClientHeight'#3'6'#2#11
+'ClientWidth'#3#214#2#8'OnCreate'#7#10'FormCreate'#9'OnDestroy'#7#11'FormDes'
+'troy'#6'OnShow'#7#8'FormShow'#8'Position'#7#14'poScreenCenter'#10'LCLVersio'
+'n'#6#6'0.9.29'#0#6'TLabel'#6'Label1'#22'AnchorSideLeft.Control'#7#5'Owner'
+#21'AnchorSideTop.Control'#7#11'SVNLogLimit'#24'AnchorSideBottom.Control'#7
+#11'SVNLogLimit'#21'AnchorSideBottom.Side'#7#9'asrBottom'#4'Left'#2#6#6'Heig'
+'ht'#2#14#3'Top'#3#250#1#5'Width'#2'a'#7'Anchors'#11#6'akLeft'#8'akBottom'#0
+#18'BorderSpacing.Left'#2#6#19'BorderSpacing.Right'#2#6#7'Caption'#6#19'Show'
+' last X commits'#11'ParentColor'#8#0#0#9'TListView'#11'LogListView'#4'Left'
+#2#6#6'Height'#3#200#0#3'Top'#2#6#5'Width'#3#202#2#5'Align'#7#5'alTop'#18'Bo'
+'rderSpacing.Left'#2#6#17'BorderSpacing.Top'#2#6#19'BorderSpacing.Right'#2#6
+#7'Columns'#14#1#0#1#0#1#0#1#5'Width'#3'"'#2#0#0#9'ItemIndex'#2#255#9'RowSel'
+'ect'#9#8'TabOrder'#2#0#9'ViewStyle'#7#8'vsReport'#12'OnSelectItem'#7#21'Log'
+'ListViewSelectItem'#0#0#5'TMemo'#13'SVNLogMsgMemo'#4'Left'#2#6#6'Height'#2
+'<'#3'Top'#3#210#0#5'Width'#3#202#2#5'Align'#7#5'alTop'#18'BorderSpacing.Lef'
+'t'#2#6#19'BorderSpacing.Right'#2#6#10'ParentFont'#8#8'ReadOnly'#9#8'TabOrde'
+'r'#2#1#0#0#9'TListView'#18'SVNActionsListView'#24'AnchorSideBottom.Control'
+#7#13'RefreshButton'#4'Left'#2#6#6'Height'#3#217#0#3'Top'#3#18#1#5'Width'#3
+#202#2#5'Align'#7#5'alTop'#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#8'akB'
+'ottom'#0#18'BorderSpacing.Left'#2#6#19'BorderSpacing.Right'#2#6#20'BorderSp'
+'acing.Bottom'#2#6#7'Columns'#14#1#0#1#0#1#0#1#5'Width'#3'"'#2#0#0#9'ItemInd'
+'ex'#2#255#9'PopupMenu'#7#19'SVNActionsPopupMenu'#9'RowSelect'#9#8'TabOrder'
+#2#2#9'ViewStyle'#7#8'vsReport'#0#0#12'TButtonPanel'#11'ButtonPanel'#4'Left'
+#2#6#6'Height'#2'"'#3'Top'#3#14#2#5'Width'#3#202#2#13'OKButton.Name'#6#8'OKB'
+'utton'#16'OKButton.Caption'#6#3'&OK'#15'HelpButton.Name'#6#10'HelpButton'#18
+'HelpButton.Caption'#6#5'&Help'#18'HelpButton.Enabled'#8#16'CloseButton.Name'
+#6#11'CloseButton'#19'CloseButton.Caption'#6#6'&Close'#19'CloseButton.Enable'
+'d'#8#17'CancelButton.Name'#6#12'CancelButton'#20'CancelButton.Caption'#6#6
+'Cancel'#20'CancelButton.Enabled'#8#8'TabOrder'#2#3#11'ShowButtons'#11#4'pbO'
+'K'#0#0#0#9'TSplitter'#9'Splitter1'#6'Cursor'#7#8'crVSplit'#4'Left'#2#0#6'He'
+'ight'#2#4#3'Top'#3#14#1#5'Width'#3#214#2#5'Align'#7#5'alTop'#12'ResizeAncho'
+'r'#7#5'akTop'#0#0#9'TSplitter'#9'Splitter2'#6'Cursor'#7#8'crVSplit'#4'Left'
+#2#0#6'Height'#2#4#3'Top'#3#206#0#5'Width'#3#214#2#5'Align'#7#5'alTop'#12'Re'
+'sizeAnchor'#7#5'akTop'#0#0#9'TSpinEdit'#11'SVNLogLimit'#22'AnchorSideLeft.C'
+'ontrol'#7#6'Label1'#19'AnchorSideLeft.Side'#7#9'asrBottom'#24'AnchorSideBot'
+'tom.Control'#7#11'ButtonPanel'#4'Left'#2'm'#6'Height'#2#21#3'Top'#3#243#1#5
+'Width'#2'^'#7'Anchors'#11#6'akLeft'#8'akBottom'#0#20'BorderSpacing.Around'#2
+#6#8'MaxValue'#4#160#134#1#0#8'TabOrder'#2#6#5'Value'#2'd'#0#0#7'TButton'#13
+'RefreshButton'#23'AnchorSideRight.Control'#7#5'Owner'#20'AnchorSideRight.Si'
+'de'#7#9'asrBottom'#24'AnchorSideBottom.Control'#7#11'ButtonPanel'#4'Left'#3
+#144#2#6'Height'#2#23#3'Top'#3#241#1#5'Width'#2'@'#7'Anchors'#11#7'akRight'#8
+'akBottom'#0#8'AutoSize'#9#20'BorderSpacing.Around'#2#6#7'Caption'#6#7'Refre'
+'sh'#7'OnClick'#7#18'RefreshButtonClick'#8'TabOrder'#2#7#0#0#10'TPopupMenu'
+#19'SVNActionsPopupMenu'#6'Images'#7#9'ImageList'#7'OnPopup'#7#24'SVNActions'
+'PopupMenuPopup'#4'left'#2'%'#3'top'#3'q'#1#0#9'TMenuItem'#11'mnuShowDiff'#7
+'Caption'#6#4'diff'#10'ImageIndex'#2#0#7'OnClick'#7#16'mnuShowDiffClick'#0#0
+#9'TMenuItem'#13'mnuOpenCurent'#7'Caption'#6#4'open'#7'OnClick'#7#18'mnuOpen'
+'CurentClick'#0#0#9'TMenuItem'#15'mnuOpenRevision'#7'Caption'#6#8'open rev'#7
+'Enabled'#8#7'OnClick'#7#20'mnuOpenRevisionClick'#0#0#9'TMenuItem'#19'mnuOpe'
+'nPrevRevision'#7'Caption'#6#10'open rev-1'#7'Enabled'#8#7'OnClick'#7#24'mnu'
+'OpenPrevRevisionClick'#0#0#0#10'TImageList'#9'ImageList'#4'left'#2'K'#3'top'
+#3'q'#1#0#0#0
]);

View File

@ -23,9 +23,9 @@ unit SVNLogForm;
interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
Classes, SysUtils, LResources, Forms, Dialogs, Controls, FileUtil,
ComCtrls, StdCtrls, ButtonPanel, ExtCtrls, Process, Spin, XMLRead, DOM,
Menus, LCLProc;
Menus, LCLProc, LazIDEIntf;
type
TActionItem = record
@ -44,13 +44,12 @@ type
FMsg: string;
FRevision: integer;
FAction: array of TActionItem;
function GetAction(Index: Integer): TActionItem;
private
function GetAction(Index: Integer): TActionItem;
public
constructor Create;
destructor Destroy; override;
function GetActionPointer(Index: Integer): Pointer;
procedure AddAction(AActionItem: TActionItem);
property Action[Index: Integer]: TActionItem read GetAction;
property Count: integer read FCount write FCount;
@ -64,6 +63,9 @@ type
TSVNLogFrm = class(TForm)
ImageList: TImageList;
mnuOpenCurent: TMenuItem;
mnuOpenPrevRevision: TMenuItem;
mnuOpenRevision: TMenuItem;
mnuShowDiff: TMenuItem;
SVNActionsPopupMenu: TPopupMenu;
RefreshButton: TButton;
@ -75,6 +77,9 @@ type
SVNLogLimit: TSpinEdit;
Splitter1: TSplitter;
Splitter2: TSplitter;
procedure mnuOpenCurentClick(Sender: TObject);
procedure mnuOpenPrevRevisionClick(Sender: TObject);
procedure mnuOpenRevisionClick(Sender: TObject);
procedure mnuShowDiffClick(Sender: TObject);
procedure RefreshButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
@ -82,6 +87,7 @@ type
procedure FormShow(Sender: TObject);
procedure LogListViewSelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
procedure SVNActionsPopupMenuPopup(Sender: TObject);
private
FRepositoryPath: string;
{ private declarations }
@ -92,7 +98,7 @@ type
{ public declarations }
procedure Execute(Data: PtrInt);
property RepositoryPath: string read FRepositoryPath write FrepositoryPath;
property RepositoryPath: string read FRepositoryPath write FRepositoryPath;
end;
procedure ShowSVNLogFrm(ARepoPath: string);
@ -124,6 +130,13 @@ begin
Result := FAction[Index];
end;
function TSVNLogItem.GetActionPointer(Index: Integer): Pointer;
begin
if (Index < 0) or (Index >= Count) then
raise Exception.CreateFmt(rsIndexOutOfBoundsD, [Index]);
Result := @FAction[Index];
end;
constructor TSVNLogItem.Create;
begin
//initialize author to unknown, beacuse in anonymous repositories this really happens
@ -201,6 +214,7 @@ begin
SVNLogItem := FindSVNLogItemByRevision(LogList, RevNo);
SVNActionsListView.Visible := False; // BeginUpdate won't help when autosize is true
SVNActionsListView.Clear;
if Assigned(SVNLogItem) then
@ -211,13 +225,27 @@ begin
with SVNActionsListView.Items.Add do
begin
Caption := SVNLogItem.Action[i].Action;
SubItems.Add(SVNLogItem.Action[i].Path);
SubItems.Add(SVNLogItem.Action[i].CopyPath);
SubItems.Add(CreateRelativePath(SVNLogItem.Action[i].Path, RepositoryPath));
SubItems.Add(CreateRelativePath(SVNLogItem.Action[i].CopyPath, RepositoryPath));
SubItems.Add(SVNLogItem.Action[i].CopyRev);
Data := SVNLogItem.GetActionPointer(i);
end;
end
else
SVNLogMsgMemo.Clear;
SVNActionsListView.Visible := True;
end;
procedure TSVNLogFrm.SVNActionsPopupMenuPopup(Sender: TObject);
var
P: TPoint;
LI: TListItem;
begin
// make sure the row under the mouse is selected
P := SVNActionsListView.ScreenToControl(Mouse.CursorPos);
LI := SVNActionsListView.GetItemAt(P.X, P.Y);
if LI <> nil then
SVNActionsListView.Selected := LI;
end;
procedure TSVNLogFrm.UpdateLogListView;
@ -262,20 +290,43 @@ end;
procedure TSVNLogFrm.mnuShowDiffClick(Sender: TObject);
var
path: string;
Path: string;
i: integer;
revision: integer;
Revision: integer;
begin
{$note implement opening file in source editor}
if Assigned(SVNActionsListView.Selected) and Assigned(LogListView.Selected) then
begin
debugln('TSVNLogFrm.mnuShowDiffClick Path=' ,SVNActionsListView.Selected.SubItems[0]);
revision := StrToInt(LogListView.Selected.Caption);
path := SVNActionsListView.Selected.SubItems[0];
Delete(path, 1, 1);
i := pos('/', path);
ShowSVNDiffFrm(Format('-r %d:%d', [revision - 1, revision]),
RepositoryPath + Copy(path, i, length(path) - i + 1));
Revision := StrToInt(LogListView.Selected.Caption);
Path := TActionItem(SVNActionsListView.Selected.Data^).Path;
DebugLn('TSVNLogFrm.mnuShowDiffClick Path=' , Path);
if TActionItem(SVNActionsListView.Selected.Data^).Action = 'M' then
ShowSVNDiffFrm(Format('-r %d:%d', [Revision - 1, Revision]), Path)
else
ShowMessage(rsOnlyModifiedItemsCanBeDiffed);
end;
end;
procedure TSVNLogFrm.mnuOpenRevisionClick(Sender: TObject);
begin
end;
procedure TSVNLogFrm.mnuOpenPrevRevisionClick(Sender: TObject);
begin
end;
procedure TSVNLogFrm.mnuOpenCurentClick(Sender: TObject);
var
Path: String;
begin
if Assigned(SVNActionsListView.Selected) and Assigned(LogListView.Selected) then
begin
Path := TActionItem(SVNActionsListView.Selected.Data^).Path;
if FileExists(Path) then
LazarusIDE.DoOpenEditorFile(Path, -1, -1, [ofOnlyIfExists])
else
ShowMessage(rsFileNotInWorkingCopyAnymore);
end;
end;
@ -296,6 +347,10 @@ begin
ImageList.AddLazarusResource('menu_svn_diff');
mnuShowDiff.Caption := rsShowDiff;
mnuOpenCurent.Caption := rsOpenFileInEditor;
mnuOpenRevision.Caption := rsOpenThisRevisionInEditor;
mnuOpenPrevRevision.Caption := rsOpenPreviousRevisionInEditor;
Label1.Caption:=rsShowDiffCountRev;
end;
@ -312,13 +367,11 @@ procedure TSVNLogFrm.Execute(Data: PtrInt);
var
ActionItem: TActionItem;
ActionNode: TDOMNode;
AProcess: TProcess;
BytesRead: LongInt;
Doc: TXMLDocument;
InfoUrl: String;
InfoRoot: String;
i: integer;
LogItem: TSVNLogItem;
M: TMemoryStream;
n: LongInt;
Node: TDOMNode;
NodeName: string;
SubNode: TDOMNode;
@ -332,57 +385,66 @@ var
Caption := Node.NodeName;
end;
end;
begin
debugln('TSVNLogFrm.Execute RepositoryPath=' ,RepositoryPath);
AProcess := TProcess.Create(nil);
AProcess.CommandLine := SVNExecutable + ' log --xml --verbose --limit ' + IntToStr(SVNLogLimit.Value) + ' "' + RepositoryPath + '" --non-interactive';
debugln('TSVNLogFrm.Execute CommandLine ' + AProcess.CommandLine);
AProcess.Options := AProcess.Options + [poUsePipes, poStdErrToOutput];
AProcess.ShowWindow := swoHIDE;
AProcess.Execute;
M := TMemoryStream.Create;
BytesRead := 0;
while AProcess.Running do
function AbsPath(APath: String): String;
var
Prefix: String;
PrefixLength: Integer;
APathBak: String;
begin
// make sure we have room
M.SetSize(BytesRead + READ_BYTES);
// svn will always output a path that is relative
// to the repository root on the server
// it starts with '/trunk/' or '/branches/foo/'
// we have already done 'svn info' and this gave
// us 'root' and 'url' so we can now use this to
// cut off the prefix and then make
// it into an absolute path on our harddrive
// try reading it
n := AProcess.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
if n > 0
then begin
Inc(BytesRead, n);
end
else begin
// no data, wait 100 ms
Sleep(100);
PrefixLength := Length(InfoUrl) - Length(InfoRoot);
Prefix := InfoUrl;
Delete(Prefix, 1, Length(InfoRoot));
if Pos(Prefix, APath) = 1 then begin
APathBak := APath;
// first make the path relative to our working copy
// by cutting of the prefix (that only exists on the server)
Delete(APath, 1, PrefixLength + 1);
// now make it an absolute path with our local repository
// base path on our harddrive
Result := CreateAbsolutePath(APath, RepositoryPath);
// never ever return an absolute local path for a
// file that does not exist on our harddrive
if not FileExists(Result) then
Result := InfoRoot + APathBak;
end else begin
// if it does not have our prefix then it is from
// another directory or branch on the server.
Result := InfoRoot + APath;
end;
end;
// read last part
repeat
// make sure we have room
M.SetSize(BytesRead + READ_BYTES);
// try reading it
n := AProcess.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
if n > 0
then begin
Inc(BytesRead, n);
end;
until n <= 0;
M.SetSize(BytesRead);
ReadXMLFile(Doc, M);
M.Free;
AProcess.Free;
begin
// first get 'svn info' because we need the paths 'root' and 'url'
// for some path manipulation to gnerate the absolute paths
// of the files on our hard drive
Doc := ExecuteSvnReturnXml('info --xml "' + RepositoryPath + '"');
try
Node := Doc.DocumentElement.FirstChild.FindNode('url');
InfoUrl := Node.TextContent;
Node := Doc.DocumentElement.FirstChild.FindNode('repository').FindNode('root');
InfoRoot := Node.TextContent;
except
Doc.Free;
UpdateLogListView;
ChangeCursor(crDefault);
exit();
end;
Doc.Free;
Doc := ExecuteSvnReturnXml('log --xml --verbose --limit ' + IntToStr(SVNLogLimit.Value) + ' "' + RepositoryPath + '" --non-interactive');
LogList.Clear;
Node := Doc.DocumentElement.FirstChild;
if Assigned(Node) then
begin
@ -395,8 +457,6 @@ begin
LogItem.Revision := StrToInt(SubNode.Attributes.Item[0].NodeValue);
//action
ActionItem.CopyRev := '';
ActionItem.CopyPath := '';
tmpNode := SubNode.FirstChild;
while Assigned(tmpNode) do
begin
@ -418,6 +478,8 @@ begin
ActionNode := tmpNode.FirstChild;
if Assigned(ActionNode) and Assigned(ActionNode.Attributes) then
repeat
ActionItem.CopyRev := '';
ActionItem.CopyPath := '';
//attributes
for i := 0 to ActionNode.Attributes.Length-1 do
@ -431,14 +493,14 @@ begin
ActionItem.CopyRev := ActionNode.Attributes.Item[i].NodeValue
else
if t = 'copyfrom-path' then
ActionItem.CopyPath := ActionNode.Attributes.Item[i].NodeValue;
ActionItem.CopyPath := AbsPath(
ActionNode.Attributes.Item[i].NodeValue);
end;
//paths
ActionItem.Path:=ActionNode.FirstChild.NodeValue;
ActionItem.Path:=AbsPath(ActionNode.FirstChild.NodeValue);
LogItem.AddAction(ActionItem);
ActionNode := ActionNode.NextSibling;
until not Assigned(ActionNode);
tmpNode := tmpNode.NextSibling;

View File

@ -1,69 +1,83 @@
object SVNStatusFrm: TSVNStatusFrm
Left = 310
Left = 277
Height = 408
Top = 174
Width = 738
HelpContext = 0
ActiveControl = SVNFileListView
Caption = 'SVNStatusFrm'
ChildSizing.LeftRightSpacing = 0
ChildSizing.TopBottomSpacing = 0
ChildSizing.HorizontalSpacing = 0
ChildSizing.VerticalSpacing = 0
ChildSizing.ControlsPerLine = 0
ClientHeight = 408
ClientWidth = 738
Font.Height = 0
Font.Style = []
OnCreate = FormCreate
OnShow = FormShow
Position = poScreenCenter
LCLVersion = '0.9.27'
LCLVersion = '0.9.29'
object ButtonPanel: TButtonPanel
Left = 6
Height = 34
Top = 368
Width = 726
OKButton.Name = 'OKButton'
OKButton.Caption = '&Commit'
OKButton.OnClick = OKButtonClick
HelpButton.Name = 'PatchButton'
HelpButton.Caption = 'Create &Patch File'
HelpButton.OnClick = PatchButtonClick
CloseButton.Name = 'PatchFileButton'
CloseButton.Caption = 'Close'
CloseButton.Enabled = False
CancelButton.Name = 'CancelButton'
CancelButton.Caption = 'Cancel'
TabOrder = 2
ShowButtons = [pbOK, pbCancel, pbHelp]
ShowGlyphs = [pbOK, pbCancel, pbClose]
end
object SVNFileListView: TListView
Left = 6
Height = 266
Height = 274
Top = 88
Width = 726
HelpContext = 0
Align = alClient
BorderSpacing.Left = 6
BorderSpacing.Top = 0
BorderSpacing.Right = 6
BorderSpacing.Bottom = 6
BorderSpacing.Around = 0
BorderSpacing.CellAlignHorizontal = ccaFill
BorderSpacing.CellAlignVertical = ccaFill
Checkboxes = True
Columns = <
item
AutoSize = False
AutoSize = True
Width = 6
end
item
AutoSize = False
AutoSize = True
Width = 12
end
item
AutoSize = False
AutoSize = True
Width = 12
end
item
AutoSize = False
AutoSize = True
Width = 12
end
item
AutoSize = False
Width = 329
AutoSize = True
Width = 12
end
item
AutoSize = False
Width = 179
AutoSize = True
Width = 12
end
item
AutoSize = False
AutoSize = True
Width = 12
end
item
AutoSize = False
AutoSize = True
Width = 12
end
item
AutoSize = False
AutoSize = True
Width = 12
end>
ItemIndex = -1
PopupMenu = PopupMenu1
RowSelect = True
SortColumn = 1
@ -71,71 +85,57 @@ object SVNStatusFrm: TSVNStatusFrm
TabOrder = 0
ViewStyle = vsReport
OnColumnClick = SVNFileListViewColumnClick
OnSelectItem = SVNFileListViewSelectItem
end
object SVNCommitMsgMemo: TMemo
Left = 6
Height = 77
Top = 6
Width = 726
HelpContext = 0
Align = alTop
BorderSpacing.Left = 6
BorderSpacing.Top = 6
BorderSpacing.Right = 6
BorderSpacing.Bottom = 0
BorderSpacing.Around = 0
BorderSpacing.CellAlignHorizontal = ccaFill
BorderSpacing.CellAlignVertical = ccaFill
Font.Height = 0
Font.Style = []
ParentFont = False
TabOrder = 1
end
object ButtonPanel: TButtonPanel
Left = 6
Height = 48
Top = 360
Width = 726
HelpContext = 0
Align = alBottom
AutoSize = True
ButtonOrder = boDefault
TabOrder = 2
DefaultButton = pbOK
ShowButtons = [pbOK, pbCancel]
end
object Splitter: TSplitter
Cursor = crVSplit
Left = 0
Height = 5
Top = 83
Width = 738
HelpContext = 0
Align = alTop
ResizeAnchor = akTop
end
object PopupMenu1: TPopupMenu
Images = ImageList
OnPopup = PopupMenu1Popup
left = 53
top = 213
object mnuShowDiff: TMenuItem
Caption = 'New Item1'
Caption = 'svn diff'
ImageIndex = 0
RightJustify = False
ShowAlwaysCheckable = False
OnClick = mnuShowDiffClick
end
object mnuOpen: TMenuItem
Caption = 'open'
OnClick = mnuOpenClick
end
object mnuAdd: TMenuItem
Caption = 'svn add'
OnClick = mnuAddClick
end
object mnuRemove: TMenuItem
Caption = 'svn remove --keep-local'
OnClick = mnuRemoveClick
end
object mnuRevert: TMenuItem
Caption = 'New Item2'
Caption = 'svn revert'
ImageIndex = 1
RightJustify = False
ShowAlwaysCheckable = False
OnClick = mnuRevertClick
end
end
object ImageList: TImageList
Masked = False
left = 88
top = 213
end

View File

@ -1,41 +1,40 @@
{ This is an automatically generated lazarus resource file }
LazarusResources.Add('TSVNStatusFrm','FORMDATA',[
'TPF0'#13'TSVNStatusFrm'#12'SVNStatusFrm'#4'Left'#3'6'#1#6'Height'#3#152#1#3
+'Top'#3#174#0#5'Width'#3#226#2#11'HelpContext'#2#0#13'ActiveControl'#7#15'SV'
+'NFileListView'#7'Caption'#6#12'SVNStatusFrm'#28'ChildSizing.LeftRightSpacin'
+'g'#2#0#28'ChildSizing.TopBottomSpacing'#2#0#29'ChildSizing.HorizontalSpacin'
+'g'#2#0#27'ChildSizing.VerticalSpacing'#2#0#27'ChildSizing.ControlsPerLine'#2
+#0#12'ClientHeight'#3#152#1#11'ClientWidth'#3#226#2#11'Font.Height'#2#0#10'F'
+'ont.Style'#11#0#8'OnCreate'#7#10'FormCreate'#6'OnShow'#7#8'FormShow'#8'Posi'
+'tion'#7#14'poScreenCenter'#10'LCLVersion'#6#6'0.9.27'#0#9'TListView'#15'SVN'
+'FileListView'#4'Left'#2#6#6'Height'#3#10#1#3'Top'#2'X'#5'Width'#3#214#2#11
+'HelpContext'#2#0#5'Align'#7#8'alClient'#18'BorderSpacing.Left'#2#6#17'Borde'
+'rSpacing.Top'#2#0#19'BorderSpacing.Right'#2#6#20'BorderSpacing.Bottom'#2#6
+#20'BorderSpacing.Around'#2#0'!BorderSpacing.CellAlignHorizontal'#7#7'ccaFil'
+'l'#31'BorderSpacing.CellAlignVertical'#7#7'ccaFill'#10'Checkboxes'#9#7'Colu'
+'mns'#14#1#8'AutoSize'#8#0#1#8'AutoSize'#8#0#1#8'AutoSize'#8#0#1#8'AutoSize'
+#8#0#1#8'AutoSize'#8#5'Width'#3'I'#1#0#1#8'AutoSize'#8#5'Width'#3#179#0#0#1#8
+'AutoSize'#8#0#1#8'AutoSize'#8#0#1#8'AutoSize'#8#0#0#9'PopupMenu'#7#10'Popup'
+'Menu1'#9'RowSelect'#9#10'SortColumn'#2#1#8'SortType'#7#6'stText'#8'TabOrder'
+#2#0#9'ViewStyle'#7#8'vsReport'#13'OnColumnClick'#7#26'SVNFileListViewColumn'
+'Click'#12'OnSelectItem'#7#25'SVNFileListViewSelectItem'#0#0#5'TMemo'#16'SVN'
+'CommitMsgMemo'#4'Left'#2#6#6'Height'#2'M'#3'Top'#2#6#5'Width'#3#214#2#11'He'
+'lpContext'#2#0#5'Align'#7#5'alTop'#18'BorderSpacing.Left'#2#6#17'BorderSpac'
+'ing.Top'#2#6#19'BorderSpacing.Right'#2#6#20'BorderSpacing.Bottom'#2#0#20'Bo'
+'rderSpacing.Around'#2#0'!BorderSpacing.CellAlignHorizontal'#7#7'ccaFill'#31
+'BorderSpacing.CellAlignVertical'#7#7'ccaFill'#11'Font.Height'#2#0#10'Font.S'
+'tyle'#11#0#10'ParentFont'#8#8'TabOrder'#2#1#0#0#12'TButtonPanel'#11'ButtonP'
+'anel'#4'Left'#2#6#6'Height'#2'0'#3'Top'#3'h'#1#5'Width'#3#214#2#11'HelpCont'
+'ext'#2#0#5'Align'#7#8'alBottom'#8'AutoSize'#9#11'ButtonOrder'#7#9'boDefault'
+#8'TabOrder'#2#2#13'DefaultButton'#7#4'pbOK'#11'ShowButtons'#11#4'pbOK'#8'pb'
+'Cancel'#0#0#0#9'TSplitter'#8'Splitter'#6'Cursor'#7#8'crVSplit'#4'Left'#2#0#6
+'Height'#2#5#3'Top'#2'S'#5'Width'#3#226#2#11'HelpContext'#2#0#5'Align'#7#5'a'
+'lTop'#12'ResizeAnchor'#7#5'akTop'#0#0#10'TPopupMenu'#10'PopupMenu1'#6'Image'
+'s'#7#9'ImageList'#4'left'#2'5'#3'top'#3#213#0#0#9'TMenuItem'#11'mnuShowDiff'
+#7'Caption'#6#9'New Item1'#10'ImageIndex'#2#0#12'RightJustify'#8#19'ShowAlwa'
+'ysCheckable'#8#7'OnClick'#7#16'mnuShowDiffClick'#0#0#9'TMenuItem'#9'mnuReve'
+'rt'#7'Caption'#6#9'New Item2'#10'ImageIndex'#2#1#12'RightJustify'#8#19'Show'
+'AlwaysCheckable'#8#7'OnClick'#7#14'mnuRevertClick'#0#0#0#10'TImageList'#9'I'
+'mageList'#6'Masked'#8#4'left'#2'X'#3'top'#3#213#0#0#0#0
'TPF0'#13'TSVNStatusFrm'#12'SVNStatusFrm'#4'Left'#3#21#1#6'Height'#3#152#1#3
+'Top'#3#174#0#5'Width'#3#226#2#7'Caption'#6#12'SVNStatusFrm'#12'ClientHeight'
+#3#152#1#11'ClientWidth'#3#226#2#8'OnCreate'#7#10'FormCreate'#6'OnShow'#7#8
+'FormShow'#8'Position'#7#14'poScreenCenter'#10'LCLVersion'#6#6'0.9.29'#0#12
+'TButtonPanel'#11'ButtonPanel'#4'Left'#2#6#6'Height'#2'"'#3'Top'#3'p'#1#5'Wi'
+'dth'#3#214#2#13'OKButton.Name'#6#8'OKButton'#16'OKButton.Caption'#6#7'&Comm'
+'it'#16'OKButton.OnClick'#7#13'OKButtonClick'#15'HelpButton.Name'#6#11'Patch'
+'Button'#18'HelpButton.Caption'#6#18'Create &Patch File'#18'HelpButton.OnCli'
+'ck'#7#16'PatchButtonClick'#16'CloseButton.Name'#6#15'PatchFileButton'#19'Cl'
+'oseButton.Caption'#6#5'Close'#19'CloseButton.Enabled'#8#17'CancelButton.Nam'
+'e'#6#12'CancelButton'#20'CancelButton.Caption'#6#6'Cancel'#8'TabOrder'#2#2
+#11'ShowButtons'#11#4'pbOK'#8'pbCancel'#6'pbHelp'#0#10'ShowGlyphs'#11#4'pbOK'
+#8'pbCancel'#7'pbClose'#0#0#0#9'TListView'#15'SVNFileListView'#4'Left'#2#6#6
+'Height'#3#18#1#3'Top'#2'X'#5'Width'#3#214#2#5'Align'#7#8'alClient'#18'Borde'
+'rSpacing.Left'#2#6#19'BorderSpacing.Right'#2#6#20'BorderSpacing.Bottom'#2#6
+#10'Checkboxes'#9#7'Columns'#14#1#8'AutoSize'#9#5'Width'#2#6#0#1#8'AutoSize'
+#9#5'Width'#2#12#0#1#8'AutoSize'#9#5'Width'#2#12#0#1#8'AutoSize'#9#5'Width'#2
+#12#0#1#8'AutoSize'#9#5'Width'#2#12#0#1#8'AutoSize'#9#5'Width'#2#12#0#1#8'Au'
+'toSize'#9#5'Width'#2#12#0#1#8'AutoSize'#9#5'Width'#2#12#0#1#8'AutoSize'#9#5
+'Width'#2#12#0#0#9'ItemIndex'#2#255#9'PopupMenu'#7#10'PopupMenu1'#9'RowSelec'
+'t'#9#10'SortColumn'#2#1#8'SortType'#7#6'stText'#8'TabOrder'#2#0#9'ViewStyle'
+#7#8'vsReport'#13'OnColumnClick'#7#26'SVNFileListViewColumnClick'#0#0#5'TMem'
+'o'#16'SVNCommitMsgMemo'#4'Left'#2#6#6'Height'#2'M'#3'Top'#2#6#5'Width'#3#214
+#2#5'Align'#7#5'alTop'#18'BorderSpacing.Left'#2#6#17'BorderSpacing.Top'#2#6
+#19'BorderSpacing.Right'#2#6#10'ParentFont'#8#8'TabOrder'#2#1#0#0#9'TSplitte'
+'r'#8'Splitter'#6'Cursor'#7#8'crVSplit'#4'Left'#2#0#6'Height'#2#5#3'Top'#2'S'
+#5'Width'#3#226#2#5'Align'#7#5'alTop'#12'ResizeAnchor'#7#5'akTop'#0#0#10'TPo'
+'pupMenu'#10'PopupMenu1'#6'Images'#7#9'ImageList'#7'OnPopup'#7#15'PopupMenu1'
+'Popup'#4'left'#2'5'#3'top'#3#213#0#0#9'TMenuItem'#11'mnuShowDiff'#7'Caption'
+#6#8'svn diff'#10'ImageIndex'#2#0#7'OnClick'#7#16'mnuShowDiffClick'#0#0#9'TM'
+'enuItem'#7'mnuOpen'#7'Caption'#6#4'open'#7'OnClick'#7#12'mnuOpenClick'#0#0#9
+'TMenuItem'#6'mnuAdd'#7'Caption'#6#7'svn add'#7'OnClick'#7#11'mnuAddClick'#0
+#0#9'TMenuItem'#9'mnuRemove'#7'Caption'#6#23'svn remove --keep-local'#7'OnCl'
+'ick'#7#14'mnuRemoveClick'#0#0#9'TMenuItem'#9'mnuRevert'#7'Caption'#6#10'svn'
+' revert'#10'ImageIndex'#2#1#7'OnClick'#7#14'mnuRevertClick'#0#0#0#10'TImage'
+'List'#9'ImageList'#4'left'#2'X'#3'top'#3#213#0#0#0#0
]);

View File

@ -23,9 +23,9 @@ unit SVNStatusForm;
interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Dialogs,
ComCtrls, StdCtrls, ButtonPanel, ExtCtrls, LCLProc, Process,
SVNClasses, Menus;
SVNClasses, Menus, LazIDEIntf;
type
{ TSVNStatusFrm }
@ -33,6 +33,9 @@ type
TSVNStatusFrm = class(TForm)
ButtonPanel: TButtonPanel;
ImageList: TImageList;
mnuOpen: TMenuItem;
mnuRemove: TMenuItem;
mnuAdd: TMenuItem;
mnuRevert: TMenuItem;
mnuShowDiff: TMenuItem;
PopupMenu1: TPopupMenu;
@ -42,22 +45,26 @@ type
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure mnuAddClick(Sender: TObject);
procedure mnuOpenClick(Sender: TObject);
procedure mnuRemoveClick(Sender: TObject);
procedure mnuRevertClick(Sender: TObject);
procedure mnuShowDiffClick(Sender: TObject);
procedure OKButtonClick(Sender: TObject);
procedure PatchButtonClick(Sender: TObject);
procedure PopupMenu1Popup(Sender: TObject);
procedure SVNFileListViewColumnClick(Sender: TObject; Column: TListColumn);
procedure SVNFileListViewSelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
private
FRepositoryPath: string;
{ private declarations }
SVNStatus: TSVNStatus;
procedure SetRepositoryPath(const AValue: string);
procedure UpdateFilesListView(Data: PtrInt);
procedure Initialize(Data: PtrInt);
procedure ExecuteSvnCommand(ACommand: String; AFile: String);
procedure UpdateFilesListView;
procedure ChangeCursor(ACursor: TCursor);
procedure UpdateCheckedStatus;
public
{ public declarations }
property RepositoryPath: string read FRepositoryPath write SetRepositoryPath;
{path the root of the local working copy}
property RepositoryPath: string read FRepositoryPath write FRepositoryPath;
end;
procedure ShowSVNStatusFrm(ARepoPath: string);
@ -72,6 +79,7 @@ var
SVNStatusFrm: TSVNStatusFrm;
begin
SVNStatusFrm := TSVNStatusFrm.Create(nil);
SVNStatusFrm.ChangeCursor(crHourGlass);
SVNStatusFrm.RepositoryPath:=ARepoPath;
SVNStatusFrm.ShowModal;
@ -83,41 +91,89 @@ end;
procedure TSVNStatusFrm.FormShow(Sender: TObject);
begin
SVNStatus := TSVNStatus.Create(RepositoryPath);
SVNStatus.Sort(siChecked, sdAscending);
Caption := Format('%s - %s...', [RepositoryPath, rsLazarusSVNCommit]);
Application.QueueAsyncCall(@UpdateFilesListView, 0);
Application.QueueAsyncCall(@Initialize, 0);
end;
procedure TSVNStatusFrm.Initialize(Data: PtrInt);
begin
SVNStatus := TSVNStatus.Create(RepositoryPath, false);
SVNStatus.Sort(siChecked, sdAscending);
UpdateFilesListView;
ChangeCursor(crDefault);
end;
procedure TSVNStatusFrm.mnuRevertClick(Sender: TObject);
var
AProcess: TProcess;
begin
if Assigned(SVNFileListView.Selected) then
begin
AProcess := TProcess.Create(nil);
if pos(RepositoryPath,SVNFileListView.Selected.SubItems[0]) <> 0 then
AProcess.CommandLine := SVNExecutable + ' revert "' + SVNFileListView.Selected.SubItems[0] + '"'
else
AProcess.CommandLine := SVNExecutable + ' revert "' + AppendPathDelim(RepositoryPath) + SVNFileListView.Selected.SubItems[0] + '"';
debugln('TSVNStatusFrm.mnuRevertClick commandline=', AProcess.CommandLine);
AProcess.Options := AProcess.Options + [poWaitOnExit];
AProcess.ShowWindow := swoHIDE;
AProcess.Execute;
AProcess.Free;
ExecuteSvnCommand('revert', SVNFileListView.Selected.SubItems[0]);
//now delete the entry from the list
SVNStatus.List.Delete(SVNFileListView.Selected.Index);
//update the listview again
UpdateFilesListView(0);
UpdateFilesListView;
end;
end;
procedure TSVNStatusFrm.mnuAddClick(Sender: TObject);
begin
if Assigned(SVNFileListView.Selected) then
begin
ExecuteSvnCommand('add', SVNFileListView.Selected.SubItems[0]);
// completely re-read the status
SVNStatus.Free;
SVNStatus := TSVNStatus.Create(RepositoryPath, false);
SVNStatus.Sort(siChecked, sdAscending);
UpdateFilesListView;
end;
end;
procedure TSVNStatusFrm.mnuOpenClick(Sender: TObject);
var
FileName: String;
begin
if Assigned(SVNFileListView.Selected) then
begin
FileName := CreateAbsolutePath(SVNFileListView.Selected.SubItems[0], RepositoryPath);
LazarusIDE.DoOpenEditorFile(FileName, -1, -1, [ofOnlyIfExists]);
end;
end;
procedure TSVNStatusFrm.mnuRemoveClick(Sender: TObject);
begin
if Assigned(SVNFileListView.Selected) then
begin
ExecuteSvnCommand('remove --keep-local', SVNFileListView.Selected.SubItems[0]);
// completely re-read the status
SVNStatus.Free;
SVNStatus := TSVNStatus.Create(RepositoryPath, false);
SVNStatus.Sort(siChecked, sdAscending);
UpdateFilesListView;
end;
end;
procedure TSVNStatusFrm.ExecuteSvnCommand(ACommand: String; AFile: String);
var
AProcess: TProcess;
begin
AProcess := TProcess.Create(nil);
if pos(RepositoryPath, AFile) <> 0 then
AProcess.CommandLine := SVNExecutable + ' ' + ACommand + ' "' + AFile + '"'
else
AProcess.CommandLine := SVNExecutable + ' ' + ACommand + ' "' + AppendPathDelim(RepositoryPath) + AFile + '"';
debugln('TSVNStatusFrm.ExecuteSvnCommand commandline=', AProcess.CommandLine);
AProcess.Options := AProcess.Options + [poWaitOnExit];
AProcess.ShowWindow := swoHIDE;
AProcess.Execute;
AProcess.Free;
end;
procedure TSVNStatusFrm.mnuShowDiffClick(Sender: TObject);
begin
{$note implement opening file in source editor}
@ -126,9 +182,9 @@ begin
debugln('TSVNStatusFrm.mnuShowDiffClick Path=' ,SVNFileListView.Selected.SubItems[0]);
if pos(RepositoryPath,SVNFileListView.Selected.SubItems[0]) <> 0 then
ShowSVNDiffFrm('-r HEAD', '"' + SVNFileListView.Selected.SubItems[0] + '"')
ShowSVNDiffFrm('-r BASE', SVNFileListView.Selected.SubItems[0])
else
ShowSVNDiffFrm('-r HEAD', '"' + AppendPathDelim(RepositoryPath) + SVNFileListView.Selected.SubItems[0] + '"');
ShowSVNDiffFrm('-r BASE', AppendPathDelim(RepositoryPath) + SVNFileListView.Selected.SubItems[0]);
end;
end;
@ -139,6 +195,7 @@ var
StatusItem : PSVNStatusItem;
FileName: string;
begin
UpdateCheckedStatus;
if SVNCommitMsgMemo.Text = '' then
if MessageDlg ('No message set.', 'Do you wish to continue?', mtConfirmation,
[mbYes, mbNo],0) <> mrYes then
@ -166,6 +223,54 @@ begin
DeleteFile(FileName);
end;
procedure TSVNStatusFrm.PatchButtonClick(Sender: TObject);
var
i: Integer;
StatusItem: PSVNStatusItem;
FileNames: TStringList;
begin
UpdateCheckedStatus;
Filenames := TStringList.Create;
FileNames.Sorted := True;
for i := 0 to SVNStatus.List.Count - 1 do
begin
StatusItem := PSVNStatusItem(SVNStatus.List.Items[i]);
if StatusItem^.Checked then
if pos(RepositoryPath,StatusItem^.Path) = 0 then
FileNames.Append(AppendPathDelim(RepositoryPath) + StatusItem^.Path)
else
FileNames.Append(StatusItem^.Path);
end;
ShowSVNDiffFrm('-r BASE', FileNames);
end;
procedure TSVNStatusFrm.PopupMenu1Popup(Sender: TObject);
var
P: TPoint;
LI: TListItem;
begin
// make sure the row under the mouse is selected
P := SVNFileListView.ScreenToControl(Mouse.CursorPos);
LI := SVNFileListView.GetItemAt(P.X, P.Y);
if LI <> nil then begin
SVNFileListView.Selected := LI;
{$note: using hardcoded column index!}
if LI.SubItems[2] = 'unversioned' then
mnuRevert.Enabled := False
else
mnuRevert.Enabled := True;
if (LI.SubItems[2] = 'unversioned') or (LI.SubItems[2] = 'deleted') then begin
mnuShowDiff.Enabled := False;
mnuRemove.Enabled := False;
mnuAdd.Enabled := True;
end else begin
mnuShowDiff.Enabled := True;
mnuRemove.Enabled := True;
mnuAdd.Enabled := False;
end;
end;
end;
procedure TSVNStatusFrm.SVNFileListViewColumnClick(Sender: TObject;
Column: TListColumn);
begin
@ -181,16 +286,10 @@ begin
8: SVNStatus.ReverseSort(siDate);
end;
UpdateFilesListView(0);
UpdateFilesListView;
end;
procedure TSVNStatusFrm.SVNFileListViewSelectItem(Sender: TObject;
Item: TListItem; Selected: Boolean);
begin
PSVNStatusItem(SVNStatus.List.Items[Item.Index])^.Checked:=Item.Checked;
end;
procedure TSVNStatusFrm.UpdateFilesListView(Data: PtrInt);
procedure TSVNStatusFrm.UpdateFilesListView;
var
i: integer;
StatusItem : PSVNStatusItem;
@ -213,7 +312,7 @@ begin
//path
Path := StatusItem^.Path;
if pos(RepositoryPath, Path) = 1 then
System.Delete(Path, 1, Length(RepositoryPath) - 1);
path := CreateRelativePath(path, RepositoryPath, false);
SubItems.Add(Path);
//extension
@ -244,27 +343,37 @@ begin
end;
end;
SVNFileListView.EndUpdate;
ChangeCursor(crDefault);
end;
procedure TSVNStatusFrm.SetRepositoryPath(const AValue: string);
begin
FRepositoryPath := AppendPathDelim(AValue);
end;
procedure TSVNStatusFrm.ChangeCursor(ACursor: TCursor);
begin
Cursor := ACursor;
SVNCommitMsgMemo.Cursor := ACursor;
SVNFileListView.Cursor := ACursor;
Application.ProcessMessages;
end;
procedure TSVNStatusFrm.UpdateCheckedStatus;
var
i : Integer;
begin
for i := 0 to SVNFileListView.Items.Count - 1 do
with SVNFileListView.Items[i] do
begin
PSVNStatusItem(SVNStatus.List.Items[Index])^.Checked := Checked;
end;
end;
procedure TSVNStatusFrm.FormCreate(Sender: TObject);
begin
ChangeCursor(crHourGlass);
mnuShowDiff.Caption:=rsShowDiff;
mnuShowDiff.Caption := rsShowDiff;
mnuOpen.Caption := rsOpenFileInEditor;
mnuRevert.Caption := rsRevert;
mnuAdd.Caption := rsAdd;
mnuRemove.Caption := rsRemove;
ButtonPanel.HelpButton.Caption:=rsCreatePatchFile;
ButtonPanel.OKButton.Caption:=rsCommit;
ButtonPanel.OKButton.OnClick:=@OKButtonClick;