SRL Archive - Research & Development Lounge

Scar based SRL installer from SVN


mixster

2009-10-07 02:13:40

Um, title kind of says it all.
Could be improved, but it works. I have tested for compiling and aside from a TBooleanArray and T2DStringArray, it seems like everything was fine (Scar 3.15b does not want them :().

It is somewhat intelligent in that it stores the version number when it installs, however it doesn't check for pre-existing files, so having the ini file without SRL would mean it would assume you have an up to date SRL until the next rev. Likewise, if you have an up to date SRL, but haven't got an ini file it will assume it is out of date.
I have made it parse and store the rev number separate from the includes, but you can change where it is stored. I've tried to use as little absolute paths to ensure it is somewhat flexible.

const
CheckVersion = True;
DownloadSCAR = False;
DownloadSRL = True;
MoveSRLPlugins = True;
//SCARDirectory = 'C:\Program Files\SCAR 3.22 pre\';
RootDirectory = '';
SRLDirectory = 'Includes\SRL\';

var
SCARDirectory: string;

type
TFile = record
path, filename: string;
end;

TSVNFile = record
local, remote: TFile;
end;

TMatch = record
start, finish: string;
end;

TFilter = record
exp, dir, fil: string;
local, remote: TMatch;
end;

TSVN = record
name: string;
skip: TStringArray;
baseloc: TSVNFile;
files: array of TSVNFile;
filter: TFilter;
rev: TMatch;
col: Boolean;
end;

function srl_Explode(str, del: string): TStringArray;
{$IFNDEF SCAR320_UP}
var
i, l, dL: Integer;
begin
i := 0;
l := -1;
SetLength(Result, 0);
if (str = '') then
Exit;
dL := Length(del) - 1;
repeat
Inc(l);
SetLength(Result, l + 1);
i := Pos(del, str);
if i <= 0 then
Break;
Result[l] := Copy(str, 1, i - 1);
Delete(str, 1, i + dL);
until false
Result[l] := Copy(str, 1, Length(str));
{$ELSE}
begin
Result := Explode(del, str);
{$ENDIF}
end;

function ReturnPage(svn: TSVN; dir: TSVNFile): string;
var
url: string;
begin
url := svn.baseloc.remote.path + dir.remote.path;

try
Result := GetPage(url);
except
Writeln('Downloading url "' + url + '" failed');
Result := '';
end;
end;

procedure RawCollectSVN(var svn: TSVN; cur_dir: TSVNFile);
var
input, tmpLoc, tmpRem: string;
split: TStringArray;
h, i, t: Integer;
new_dir: TSVNFile;
sk: Boolean;
begin
input := ReturnPage(svn, cur_dir);
split := srl_Explode(input, svn.filter.exp);

for i := 0 to High(split) do
begin
for h := 0 to High(svn.skip) do
begin
sk := Pos(svn.skip[h], split[i]) > 0;
if sk then
Break;
end;

if sk then
Continue;

tmpLoc := Between(svn.filter.local.start, svn.filter.local.finish, split[i]);
tmpRem := Between(svn.filter.remote.start, svn.filter.remote.finish, split[i]);

if (tmpLoc = '') or (tmpRem = '') then
Continue;

if Pos(svn.filter.dir, split[i]) > 0 then // Handle directory
begin
new_dir.local.path := cur_dir.local.path + tmpLoc + '\';
new_dir.remote.path := cur_dir.remote.path + tmpRem;
Writeln('Discovered directory "' + tmpLoc + '"');
t := GetDebugLineCount - 1;
RawCollectSVN(svn, new_dir);
ReplaceDebugLine(t, 'Finished collecting from "' + tmpLoc + '"');
end
else if Pos(svn.filter.fil, split[i]) > 0 then // Handle file
begin;
h := Length(svn.files);
SetLength(svn.files, h + 1);
svn.files[h].local.path := cur_dir.local.path;
svn.files[h].local.filename := tmpLoc;
svn.files[h].remote.path := cur_dir.remote.path;
svn.files[h].remote.filename := tmpRem;
end;
end;
end;

procedure CollectSVN(var svn: TSVN);
var
start: TSVNFile;
t: Integer;
begin
Writeln('Now starting to collect "' + svn.name + '"');
t := GetSystemTime;
RawCollectSVN(svn, start);
svn.col := True;
t := GetSystemTime - t;
Writeln('Finished collecting "' + svn.name + '" in ' + IntToStr(t) + ' ms');
Writeln('A total of ' + IntToStr(Length(svn.files)) + ' files were collected');
end;

procedure DownloadSVN(svn: TSVN);
var
i, f, c, l, t, line: Integer;
begin
Writeln('Now starting to download "' + svn.name + '"');
Writeln('');
line := GetDebugLineCount - 1;

t := GetSystemTime;
c := 0;
l := Length(svn.files);
for i := 0 to l - 1 do
try
c := c + 1;
if c mod 10 = 0 then
ReplaceDebugLine(line, 'Downloading file ' + IntToStr(c) + ' of ' + IntToStr(l));
f := RewriteFile(svn.baseloc.local.path + svn.files[i].local.path + svn.files[i].local.filename, False);
WriteFileString(f, GetPage(svn.baseloc.remote.path + svn.files[i].remote.path + svn.files[i].remote.filename));
CloseFile(f);
except
Writeln('Failed to download file.');
end;
t := GetSystemTime - t;
Writeln('Finished downloading "' + svn.name + '" in ' + IntToStr(t) + ' ms');
end;

function ReturnSRLSVN: TSVN;
begin
Result.name := 'SRL';
Result.baseloc.remote.path := 'http://www.villavu.com/repositories/srl-opendev/';
Result.baseloc.local.path := SCARDirectory + SRLDirectory;
Result.filter.exp := '<';
Result.filter.dir := 'dir';
Result.filter.fil := 'file';
Result.filter.local.start := 'name="';
Result.filter.local.finish := '"';
Result.filter.remote.start := 'href="';
Result.filter.remote.finish := '"';
Result.rev.start := 'rev="';
Result.rev.finish := '"';
Result.skip := [];
end;

function ReturnSCARSVN: TSVN;
begin
Result.name := 'SCAR';
Result.baseloc.remote.path := 'http://freddy1990.com/svn/scarprerelease/';
Result.baseloc.local.path := SCARDirectory
Result.filter.exp := '<a';
Result.filter.dir := '/"';
Result.filter.fil := '.';
Result.filter.local.start := '">';
Result.filter.local.finish := '<';
Result.filter.remote.start := 'href="';
Result.filter.remote.finish := '"';
Result.rev.start := 'Revision ';
Result.rev.finish := ':';
Result.skip := ['http', '..'];
end;

function GetSVNVersion(svn: TSVN): Integer;
var
input: string;
begin
input := GetPage(svn.baseloc.remote.path);
Result := StrToIntDef(Between(svn.rev.start, svn.rev.finish, input), 0);
end;

procedure WriteSVNVersion(svn: TSVN);
var
rev: Integer;
begin
rev := GetSVNVersion(svn);
if rev = 0 then
begin
Writeln('Collecting rev number failed');
Writeln('You can manually set svn_settings.ini if this results in a problem');
exit;
end;

WriteINI(svn.name, 'REVISION', IntToStr(rev), SCARDirectory + 'svn_settings.ini');
end;

function IsSVNOld(svn: TSVN): Boolean;
var
curRev, locRev: Integer;
begin
locRev := StrToIntDef(ReadINI(svn.name, 'REVISION', AppPath + 'svn_settings.ini'), 0);
curRev := GetSVNVersion(svn);
if curRev = 0 then
begin
Writeln('Collecting current rev number failed');
Writeln('Assuming newer SVN is on local system to avoid problems');
Result := False;
exit;
end;

Result := locRev < curRev;

if Result then
Writeln(svn.name + ' has the latest rev downloaded')
else
Writeln(svn.name + ' is rev ' + IntToStr(locRev) + ' and latest is ' + IntToStr(curRev));
end;

procedure MovePlugins(svn: TSVN; dest: string);
var
i, f: Integer;
s: string;
o: Boolean;
begin
for i := 0 to High(svn.files) do
if ExtractFileExt(svn.files[i].local.filename) = '.dll' then
try
Writeln('Found plugin "' + svn.files[i].local.filename);
o := False;
f := OpenFile(svn.baseloc.local.path + svn.files[i].local.path + svn.files[i].local.filename, False);
ReadFileString(f, s, FileSize(f));
CloseFile(f);
o := True;
f := RewriteFile(dest + svn.files[i].local.filename, False);
WriteFileString(f, s);
CloseFile(f);
except
Writeln('Failed to save plugin.');
if o then
Writeln('Problem involved rewriting the file at target folder')
else
Writeln('Problem involved opening the sauce file to read');
end;
end;

var
scar, srl: TSVN;

begin
Writeln('Begin');

SCARDirectory := RootDirectory;
if SCARDirectory = '' then
SCARDirectory := AppPath;

scar := ReturnSCARSVN;
srl := ReturnSRLSVN;

if DownloadSCAR then
begin
if (not CheckVersion) or (CheckVersion and IsSVNOld(scar)) then
begin
CollectSVN(scar);
DownloadSVN(scar);
end;
end;

if DownloadSRL then
begin
if (not CheckVersion) or (CheckVersion and IsSVNOld(srl)) then
begin
CollectSVN(srl);
DownloadSVN(srl);

if MoveSRLPlugins then
MovePlugins(srl, scar.baseloc.local.path + 'Plugins\');
end;
end else if MoveSRLPlugins then
begin
CollectSVN(srl);
MovePlugins(srl, scar.baseloc.local.path + 'Plugins\');
end;

Writeln('End');
end.

Edit: Pretty much complete rewrite. Has OO style, which has kind of made it a lot less readable, but it has allowed me to combine both a SRL and Scar SVN downloader. In case you didn't just twig, this time it can also download latest pre-release Scar. Just like with SRL, it will keep a little tab of the current version of Scar as well as SRL. Only extra info is that it stores the INI file of SVN rev details where you set the Scar directory, so if you use it for downloading Scar, SRL and moving plugins then it will all be good, else just switch it to '' if installing SRL to the Scar you will run the script with. It should also work better as I make it parse the local and remote paths better where as I kind of just made it work before by applying a couple of replaces. Overall it should be nicer, but I can't guarantee that :)

Sir R. M8gic1an

2009-10-07 13:24:34

Actually, I was considering adding this to scripting tools.

How well does it work ? How many people have tested it? What platforms were they using?

~RM

mixster

2009-10-07 17:38:14

Only I have used it. Erm, I have tested it for compilation (using the Compile SRL.scar file) so I can say it downloaded all the files. Plugin related stuff all I have checked for is successful downloading and overwriting, but it to that fine. I'm on Ubuntu and used 3.15b, so I can say that it is compatible with that. However, it will have to be run without including srl or with compiler directives around the srl_Explode due to the name clash it would cause otherwise.

So, um, if more people want to test it to find any bugs, then I would be more than happy to fix them or for others to do so, but for now it is pretty just I who have used it and so I can only say it will work if you do it on my laptop.

Edit: Tested it on my old box. 500MHz running Scar SVN thingy ma jig through Wine on Gentoo and ti successfully worked as per all files were downloaded and plugins were moved. CompileSRL.scar successfully executed, so I'm assuming all files were downloaded :)

mixster

2009-10-19 12:31:04

Double post due to update (copy & pasted from 1st post edit):
Pretty much complete rewrite. Has OO style, which has kind of made it a lot less readable, but it has allowed me to combine both a SRL and Scar SVN downloader. In case you didn't just twig, this time it can also download latest pre-release Scar. Just like with SRL, it will keep a little tab of the current version of Scar as well as SRL. Only extra info is that it stores the INI file of SVN rev details where you set the Scar directory, so if you use it for downloading Scar, SRL and moving plugins then it will all be good, else just switch it to AppPath if installing to Scar you run the script with. It should also work better as I make it parse the local and remote paths better where as I kind of just made it work before by applying a couple of replaces. Overall it should be nicer, but I can't guarantee that :)

Edit: Quick little extra bit - Scar took ~6/7 mins to download and SRL ~2 mins when testing. Moving plugins should take no noticable amount of time unless you don't download SRL as it will take around 12 seconds to download SRL SVN structure and so use that to locate the plugin files on the local. Also, what I missed before, is that it only moves .dll files so all the .dpr's etc stay inside SRL as I'm lazy and I find it results in a nicer, cleaner /Plugins folder :)

Narcle

2009-10-19 16:06:00

Oh so you just download from open dev svn not the release then? Was thinking you would put an option in for dev/release.

mixster

2009-10-19 16:09:20

I did have an option and could add it back in, but I was thinking of it and there really wasn't any particular reason I could see for the main ones since the dev is usually stable and more up to date.

Also added a little fix. Silly AppPath is a function not const so it was giving some problems when someone was using it. Fixed now - just set RootDirectory to install SRL etc into same Scar else put in appropriate path :)