MODULE SVN;
IMPORT
Files, Commands, SVNArgument, WebHTTP, Strings, Modules, KernelLog,
OdSvn,
SVNAdmin, SVNOutput, SVNUtil, SVNWebDAV;
TYPE
Subversion = OBJECT
VAR
f : Files.File;
svn : OdSvn.OdSvn;
PROCEDURE &Init;
BEGIN
NEW ( svn );
svn.UseSvn ( TRUE );
svn.client.SvnSetBasicAuth ( "test:test" );
END Init;
PROCEDURE SetPassword ( args : SVNArgument.Argument; context : Commands.Context );
VAR
str, tmp : ARRAY 256 OF CHAR;
BEGIN
args.Push ( "username", 1 );
args.Push ( "password", 1 );
args.Read ( context );
IF args.IsSet ( "username" ) OR args.IsSet ( "password" ) THEN
args.GetKeyedArgument ( "username", str, 0 );
args.GetKeyedArgument ( "password", tmp, 0 );
Strings.Append ( str, ":" );
Strings.Append ( str, tmp );
svn.client.SvnSetBasicAuth ( str );
END;
END SetPassword;
PROCEDURE Info (context: Commands.Context);
VAR
i : INTEGER;
res : LONGINT;
s : ARRAY 256 OF CHAR;
args : SVNArgument.Argument;
b : BOOLEAN;
adminEntry : SVNAdmin.Entry;
m : SVNOutput.Message;
BEGIN { EXCLUSIVE }
NEW ( adminEntry, context );
NEW ( args );
NEW ( m, context );
SetPassword ( args, context );
svn.context := context;
b := TRUE;
FOR i := 0 TO args.CountUnkeyedArguments()-1 DO
IF ~b THEN context.out.Ln END;
b := FALSE;
args.GetUnkeyedArgument ( s, i );
adminEntry.SetPath ( s, res );
IF res = SVNOutput.ResOK THEN
adminEntry.ReadData ( res );
IF res = SVNOutput.ResOK THEN
adminEntry.PrintData;
END;
END;
m.Print ( res, s );
END;
IF b THEN
adminEntry.SetPath ( ".", res );
IF res = SVNOutput.ResOK THEN
adminEntry.ReadData ( res );
IF res = SVNOutput.ResOK THEN
adminEntry.PrintData;
END;
END;
m.Print ( res, s );
END;
END Info;
PROCEDURE Update (context: Commands.Context);
VAR
s, tmp, tmp2, svndir : ARRAY 256 OF CHAR;
b : BOOLEAN;
i : INTEGER;
args : SVNArgument.Argument;
adminEntry : SVNAdmin.Entry;
m : SVNOutput.Message;
res : LONGINT;
BEGIN { EXCLUSIVE }
NEW ( adminEntry, context );
NEW ( args );
NEW ( m, context );
SetPassword ( args, context );
svn.context := context;
b := TRUE;
FOR i := 0 TO args.CountUnkeyedArguments()-1 DO
IF ~b THEN
context.out.Ln;
ELSE
b := FALSE;
END;
args.GetUnkeyedArgument ( s, i );
SVNUtil.RemoveFileDelimiterAtEnd ( s );
adminEntry.SetPath ( s, res );
IF res # SVNOutput.ResOK THEN
m.Print ( res, s );
ELSE
adminEntry.ReadData ( res );
IF res # SVNOutput.ResOK THEN
m.Print ( res, s );
ELSE
adminEntry.GetRepo( tmp );
adminEntry.GetUrl ( tmp2 );
WebHTTP.GetPath ( tmp2, svndir );
svn.client.SvnSetRepos ( tmp );
SVNWebDAV.Update ( svn, svndir, adminEntry.GetVersion(), s, res );
m.Print ( res, s );
IF res = SVNOutput.ResOK THEN
IF svn.svnUpdated THEN
context.out.String ( "Updated to revision " );
context.out.String ( svn.nextVersion );
ELSE
context.out.String ( "At revision " );
context.out.Int ( adminEntry.GetVersion(), 0 );
END;
context.out.String ( "." ); context.out.Ln;
END;
END;
END;
END;
IF b THEN
m.Print ( SVNOutput.UsageUpdate, "" );
END;
svn.client.CloseConnection;
END Update;
PROCEDURE Commit (context: Commands.Context);
VAR
adminEntry : SVNAdmin.Entry;
args : SVNArgument.Argument;
m : SVNOutput.Message;
i : INTEGER;
s, tmp, tmp2, svndir : ARRAY 256 OF CHAR;
b : BOOLEAN;
res : LONGINT;
BEGIN { EXCLUSIVE }
NEW ( adminEntry, context );
NEW ( args );
NEW ( m, context );
args.Push ( "m", 1 );
SetPassword ( args, context );
svn.context := context;
IF ~args.IsSet ( "m" ) THEN
m.Print ( SVNOutput.ResCOMMITNOMESSAGE, "" ); KernelLog.Ln;
m.Print ( SVNOutput.UsageCommit, "" );
RETURN;
END;
FOR i := 0 TO args.CountUnkeyedArguments()-1 DO
IF ~b THEN
context.out.Ln;
ELSE
b := FALSE;
END;
args.GetUnkeyedArgument ( s, i );
SVNUtil.RemoveFileDelimiterAtEnd ( s );
adminEntry.SetPath ( s, res );
IF res # SVNOutput.ResOK THEN
m.Print ( res, s );
ELSE
adminEntry.ReadData ( res );
IF res # SVNOutput.ResOK THEN
m.Print ( res, s );
ELSE
adminEntry.GetRepo( tmp );
adminEntry.GetUrl ( tmp2 );
WebHTTP.GetPath ( tmp2, svndir );
svn.client.SvnSetRepos ( tmp );
svn.context := context;
args.GetKeyedArgument ( "m", tmp, 0 );
SVNWebDAV.Commit ( svn, svndir, s, tmp, res );
m.Print ( res, s );
END;
END;
END;
context.out.String ( "done." ); context.out.Ln;
IF b THEN
m.Print ( SVNOutput.UsageCommit, "" );
END;
svn.client.CloseConnection;
END Commit;
PROCEDURE Add (context: Commands.Context);
VAR
s : ARRAY 256 OF CHAR;
b : BOOLEAN;
i : INTEGER;
res : LONGINT;
cnt, j : LONGINT;
args : SVNArgument.Argument;
adminEntry : SVNAdmin.Entry;
m : SVNOutput.Message;
tmp : Strings.StringArray;
entriesfile, path, name, repoDir : Strings.String;
searcher : SVNUtil.FSItemSearch;
fAdmin : Files.File;
w : Files.Writer;
BEGIN { EXCLUSIVE }
NEW ( adminEntry, context );
NEW ( args );
NEW ( m, context );
NEW ( entriesfile, 512 );
NEW ( path, 512 );
NEW ( name, 512 );
NEW ( repoDir, 512 );
NEW ( searcher );
SetPassword ( args, context );
svn.context := context;
b := TRUE;
FOR i := 0 TO args.CountUnkeyedArguments()-1 DO
IF ~b THEN
context.out.Ln;
ELSE
b := FALSE;
END;
args.GetUnkeyedArgument ( s, i );
SVNUtil.RemoveFileDelimiterAtEnd ( s );
searcher.Open ( s, {} );
IF ~searcher.Exists () THEN
m.Print ( SVNOutput.ResFILENOTFOUND, s );
ELSE
COPY(s, path^);
tmp := Strings.Split ( path^, Files.PathDelimiter );
cnt := LEN ( tmp );
f := NIL;
WHILE (path^ # "") & (f = NIL) DO
Files.SplitPath ( path^, path^, name^ );
Files.JoinPath ( path^, ".svn/entries", entriesfile^ );
f := Files.Old ( entriesfile^ );
DEC ( cnt );
END;
ASSERT ( cnt >= 0 );
IF f # NIL THEN
adminEntry.SetPath ( path^, res );
IF (cnt > LEN(tmp)-2) & (adminEntry.IsItemVersioned ( name^ )) THEN
m.Print ( SVNOutput.ResALREADYVERSIONED, s );
ELSE
repoDir^ := "";
SVNAdmin.RemoveFileAttribute ( entriesfile^ );
fAdmin := Files.Old ( entriesfile^ );
SVNAdmin.RemoveFileAttribute2 ( entriesfile^, fAdmin );
adminEntry.ReadData ( res );
ASSERT ( res = SVNOutput.ResOK );
SVNAdmin.RemoveFileAttribute ( entriesfile^ );
fAdmin := Files.Old ( entriesfile^ );
SVNAdmin.RemoveFileAttribute2 ( entriesfile^, fAdmin );
Files.OpenWriter ( w, fAdmin, fAdmin.Length() );
FOR j := cnt TO LEN(tmp)-2 DO
SVNAdmin.WriteAddEntry ( w, tmp[j]^, FALSE );
w.Update;
Files.JoinPath ( path^, tmp[j]^, path^ );
Files.JoinPath ( path^, ".svn/entries", entriesfile^ );
IF j = cnt THEN
Strings.AppendX ( repoDir^, tmp[j]^ );
ELSE
Files.JoinPath ( repoDir^, tmp[j]^, repoDir^ );
END;
w := adminEntry.CreateDummy ( path^, repoDir^ );
END;
KernelLog.String ( " A " ); KernelLog.String ( path^ ); KernelLog.String ( Files.PathDelimiter );
KernelLog.String ( tmp[j]^ ); KernelLog.Ln;
IF searcher.FileExists () THEN
SVNAdmin.WriteAddEntry ( w, tmp[j]^, TRUE );
w.Update;
ELSE
w.Update;
adminEntry.Add ( path^, tmp[j]^, TRUE, res );
m.Print ( res, s );
END;
SVNAdmin.SetFileAttribute2 ( entriesfile^, fAdmin );
END;
ELSE
Files.SplitPath ( s, path^, name^ );
m.Print ( SVNOutput.ResNOTVERSIONED, path^ );
END;
END;
END;
IF b THEN
m.Print ( SVNOutput.UsageAdd, "" );
END;
svn.client.CloseConnection;
END Add;
PROCEDURE Delete (context: Commands.Context);
BEGIN { EXCLUSIVE }
END Delete;
PROCEDURE Checkout (context: Commands.Context);
VAR
args : SVNArgument.Argument;
m : SVNOutput.Message;
tmp, svndir, tmp2 : ARRAY 256 OF CHAR;
res : LONGINT;
adminEntry : SVNAdmin.Entry;
searcher : SVNUtil.FSItemSearch;
BEGIN { EXCLUSIVE }
NEW ( adminEntry, context );
NEW ( args );
NEW ( m, context );
SetPassword ( args, context );
svn.context := context;
IF args.CountUnkeyedArguments() # 2 THEN
m.Print ( SVNOutput.UsageCheckout, "" );
RETURN;
END;
args.GetUnkeyedArgument ( tmp, 0 );
svn.client.SvnSetRepos ( tmp );
COPY ( tmp, svn.repositoryURL );
WebHTTP.GetPath ( tmp, svndir );
args.GetUnkeyedArgument ( tmp, 1 );
SVNUtil.RemoveFileDelimiterAtEnd ( tmp );
Files.CreateDirectory ( tmp, res );
ASSERT ( (res = 0) OR (res=1) );
IF res = 1 THEN
adminEntry.SetPath ( tmp, res );
IF res = SVNOutput.ResOK THEN
m.Print ( SVNOutput.ResCHECKOUTALREADYDONE, tmp );
RETURN;
ELSE
Files.JoinPath ( tmp, ".svn", tmp2 );
NEW ( searcher );
searcher.Open ( tmp2, {Files.Directory} );
IF searcher.Exists () THEN
m.Print ( SVNOutput.ResCHECKOUTALREADYDONE, tmp );
RETURN;
END;
END;
END;
SVNAdmin.CreateDirectory ( tmp );
SVNWebDAV.Checkout ( svn, svndir, tmp, res );
m.Print ( res, tmp );
IF res = SVNOutput.ResOK THEN
context.out.String ( "Checked out revision " );
context.out.String ( svn.nextVersion );
context.out.String ( "." );
context.out.Ln;
END;
svn.client.CloseConnection;
END Checkout;
PROCEDURE Close ;
BEGIN
END Close;
END Subversion;
VAR
svn : Subversion;
PROCEDURE Cleanup;
BEGIN {EXCLUSIVE}
IF svn # NIL THEN
svn.Close;
svn := NIL;
END;
ASSERT ( svn = NIL );
END Cleanup;
PROCEDURE CreateSubversion;
BEGIN { EXCLUSIVE }
IF svn = NIL THEN
NEW ( svn );
END;
ASSERT ( svn # NIL );
END CreateSubversion;
PROCEDURE info* ( c : Commands.Context );
BEGIN
CreateSubversion();
svn.Info ( c );
END info;
PROCEDURE update* ( c : Commands.Context );
BEGIN
CreateSubversion ();
svn.Update ( c );
END update;
PROCEDURE commit* ( c : Commands.Context );
BEGIN
CreateSubversion ();
svn.Commit ( c );
END commit;
PROCEDURE add* ( c : Commands.Context );
BEGIN
CreateSubversion ();
svn.Add ( c );
END add;
PROCEDURE delete* ( c : Commands.Context );
BEGIN
CreateSubversion ();
svn.Delete ( c );
END delete;
PROCEDURE checkout* ( c : Commands.Context );
BEGIN
CreateSubversion ();
svn.Checkout ( c );
END checkout;
PROCEDURE close*;
BEGIN
Cleanup;
END close;
BEGIN
Modules.InstallTermHandler(Cleanup);
END SVN.