can be compiled, syncs tree. needs check for bugs.

This commit is contained in:
Norayr Chilingarian 2020-05-09 01:19:17 +04:00
parent 7a741b509a
commit 163102bd19
15 changed files with 264 additions and 216 deletions

View file

@ -15,23 +15,28 @@ create_build_dir:
copy-version-file-to-build-dir: copy-version-file-to-build-dir:
cp ./$(VERSION_FILE) ./$(BUILDDIR)/$(VERSION_FILE) cp ./$(VERSION_FILE) ./$(BUILDDIR)/$(VERSION_FILE)
all: http all:
cd $(BUILDDIR) && \ cd $(BUILDDIR) && \
$(VOC) -s \ $(VOC) -s \
../src/vpkGit.Mod \ ../Internet/src/types.Mod \
../src/vpkFsHelper.Mod \ ../Internet/src/sockets.Mod \
../Internet/src/netdb.Mod \
../Internet/src/Internet.Mod \
../src/vpkSettings.Mod \ ../src/vpkSettings.Mod \
../src/vpkConf.Mod \ ../src/unix/vpkFiles.Mod \
../src/vpkFileManager.Mod \ ../src/unix/vpkTime.Mod \
../src/vpkLogger.Mod \
../src/vpkHttp.Mod \
../src/unix/vpkEnv.Mod \
../src/unix/vpkGit.Mod \
../lists/src/Sys.Mod \ ../lists/src/Sys.Mod \
../lists/src/List.Mod \ ../lists/src/List.Mod \
../lists/src/strutils.Mod \ ../lists/src/strutils.Mod \
../src/vpkCharacterStack.Mod \ ../src/vpkCharacterStack.Mod \
../src/vpkJsonParser.Mod \ ../src/vpkJsonParser.Mod \
../src/vpkConf.Mod \
../src/vpkFileManager.Mod \
../src/vpkSyncer.Mod \ ../src/vpkSyncer.Mod \
../src/vpkUserDetails.Mod \
../src/vpkTime.Mod \
../src/vpkLogger.Mod \
../src/vpkPackageResolver.Mod \ ../src/vpkPackageResolver.Mod \
../src/vpkDependencyResolver.Mod \ ../src/vpkDependencyResolver.Mod \
../src/vpkPackageFileParser.Mod \ ../src/vpkPackageFileParser.Mod \
@ -41,17 +46,6 @@ all: http
run: run:
$(BUILDDIR)/vipack install $(BUILDDIR)/vipack install
http: clean
cd $(BUILDDIR) && \
$(VOC) -s ../src/vpkTime.Mod \
../src/vpkLogger.Mod \
../Internet/src/types.Mod \
../Internet/src/sockets.Mod \
../Internet/src/netdb.Mod \
../Internet/src/Internet.Mod \
../src/vpkHttp.Mod
clean: clean:
if [ -d "$(BUILDDIR)" ]; then rm -rf $(BUILDDIR); fi if [ -d "$(BUILDDIR)" ]; then rm -rf $(BUILDDIR); fi

104
src/unix/vpkEnv.Mod Normal file
View file

@ -0,0 +1,104 @@
MODULE vpkEnv;
IMPORT Files, Platform, Strings, Out, vpkSettings, vpkFiles;
VAR
conf, confDir : ARRAY 256 OF CHAR;
PROCEDURE getHome*(VAR path: ARRAY OF CHAR);
BEGIN
IF ~(Platform.getEnv("HOME", path)) THEN
Out.String("HOME variable is not found"); Out.Ln;
HALT(1);
END;
END getHome;
PROCEDURE mkConfDirPath(home: ARRAY OF CHAR; VAR path: ARRAY OF CHAR);
BEGIN
confDir := home;
Strings.Append("/", path);
Strings.Append(vpkSettings.vpkConfDir, path);
END mkConfDirPath;
PROCEDURE setConfFileName;
VAR
home: ARRAY 128 OF CHAR;
BEGIN
getHome(home);
mkConfDirPath(home, confDir);
conf := confDir;
Strings.Append("/", conf);
Strings.Append(vpkSettings.vpkConfFile, conf);
END setConfFileName;
PROCEDURE getConfPath(VAR path: ARRAY OF CHAR);
BEGIN
COPY(conf, path);
END getConfPath;
PROCEDURE getConfDir*(VAR path: ARRAY OF CHAR);
BEGIN
COPY(confDir, path);
END getConfDir;
PROCEDURE getConfFile*(): Files.File;
VAR f: Files.File;
BEGIN
f := Files.Old(conf);
IF f = NIL THEN
f := Files.New(conf)
END;
RETURN f;
END getConfFile;
PROCEDURE checkConfig*(): BOOLEAN;
VAR
file : vpkFiles.fileInfo;
BEGIN
file.name := conf;
RETURN vpkFiles.Exists(file);
END checkConfig;
PROCEDURE getTreeDir*(VAR path: ARRAY OF CHAR);
BEGIN
COPY(confDir, path);
Strings.Append("/", path);
Strings.Append(vpkSettings.vpkTreeDir, path);
END getTreeDir;
PROCEDURE checkEnv*;
VAR
file : vpkFiles.fileInfo;
tmp : ARRAY 256 OF CHAR;
BEGIN
file.name := conf;
IF ~vpkFiles.Exists(file) THEN
(* Checking if ~/.vipack directory already exists *)
file.name := confDir;
IF ~vpkFiles.Exists(file) THEN (* exists!!! *)
Out.String("Creating directory "); Out.String(confDir);Out.Ln;
IF ~vpkFiles.mkDir(confDir) THEN
Out.String("failed to create "); Out.String(confDir); Out.String(" directory"); Out.Ln;
HALT(1);
END;
ELSE
IF ~(vpkFiles.dir IN file.attr) THEN
Out.String(confDir); Out.String(" exists, but is not a directory"); Out.Ln;
HALT(1);
END;
END;
END;
tmp := confDir;
Strings.Append('/', tmp);
Strings.Append(vpkSettings.vpkTreeDir, tmp);
file.name := tmp;
IF ~vpkFiles.Exists(file) THEN
IF ~vpkFiles.mkDir(file.name) THEN
Out.String("failed to create tree dir "); Out.String(tmp); Out.Ln; HALT(1);
END;
END;
END checkEnv;
BEGIN
setConfFileName;
END vpkEnv.

View file

@ -1,4 +1,4 @@
MODULE vpkFsHelper; MODULE vpkFiles;
IMPORT SYSTEM; IMPORT SYSTEM;
CONST CONST
@ -96,4 +96,4 @@ BEGIN
END Exists; END Exists;
END vpkFsHelper. END vpkFiles.

28
src/unix/vpkGit.Mod Normal file
View file

@ -0,0 +1,28 @@
MODULE vpkGit;
IMPORT Out, Strings, Platform, vpkEnv;
PROCEDURE pull*(url : ARRAY OF CHAR; dst : ARRAY OF CHAR);
VAR i : INTEGER;
cmd : ARRAY 120 OF CHAR;
BEGIN
cmd:= "git init ";
Strings.Append(dst, cmd);
i:=Platform.System(cmd);
cmd := "";
cmd := "git -C ";
Strings.Append(dst, cmd);
Strings.Append(" pull ", cmd);
Strings.Append(url, cmd);
i := Platform.System(cmd);
Out.Int(i, 0);
END pull;
PROCEDURE syncTree*(url: ARRAY OF CHAR);
VAR
tmp: ARRAY 256 OF CHAR;
BEGIN
vpkEnv.getTreeDir(tmp);
pull(url, tmp);
END syncTree;
END vpkGit.

View file

@ -1,6 +1,6 @@
MODULE vipack; MODULE vipack;
IMPORT Texts, Strings, Oberon, Out, IMPORT Texts, Strings, Oberon, Out,
vpkJsonParser, vpkGit, vpkConf, vpkLogger, vpkPackageFileParser, vpkSyncer; vpkConf, vpkLogger, vpkPackageFileParser, vpkSyncer;
PROCEDURE help(); PROCEDURE help();
BEGIN BEGIN
@ -12,13 +12,13 @@ END help;
PROCEDURE main(); PROCEDURE main();
VAR VAR
user, str: ARRAY 32 OF CHAR;
i : INTEGER;
ch : CHAR;
S: Texts.Scanner; S: Texts.Scanner;
project, command: ARRAY 500 OF CHAR; project, command: ARRAY 64 OF CHAR; (* because Texts.Scanner.s is 64 bytes long*)
jsonRecord: vpkJsonParser.JsonTypePointer;
BEGIN BEGIN
(* this could go to vpkConf init section,
but here it is more visible. though may be it doesn't have to be *)
IF ~vpkConf.configured() THEN vpkConf.mkDefConfig END;
(* Getting 1 argument and outputting it *) (* Getting 1 argument and outputting it *)
Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
Texts.Scan(S); Texts.Scan(S);
@ -29,7 +29,7 @@ BEGIN
IF Strings.Match(command, "") OR Strings.Match(command, "help")THEN IF Strings.Match(command, "") OR Strings.Match(command, "help")THEN
help; help;
ELSE ELSE
vpkConf.configure;
IF command = "sync" THEN IF command = "sync" THEN
vpkSyncer.sync; vpkSyncer.sync;
END; END;
@ -44,9 +44,6 @@ BEGIN
END; END;
END main; END main;
BEGIN BEGIN
main
main();
END vipack. END vipack.

View file

@ -1,105 +1,76 @@
MODULE vpkConf; MODULE vpkConf;
IMPORT Out, Files, Strings, Platform, IMPORT Out, Files, Strings, Platform,
vpkFsHelper, vpkSettings; vpkSettings, vpkEnv, vpkJsonParser;
VAR CONST
conf, confDir : ARRAY 256 OF CHAR; open = '{"';
close = '"}';
PROCEDURE getHome(VAR path: ARRAY OF CHAR); is = '": "';
BEGIN newkey = '", "';
IF ~(Platform.getEnv("HOME", path)) THEN
Out.String("HOME variable is not found"); Out.Ln;
HALT(1);
END;
END getHome;
PROCEDURE mkConfContent(VAR path: ARRAY OF CHAR); PROCEDURE mkConfContent(VAR path: ARRAY OF CHAR);
(* constructing the line like:
{"path" : "https://github.com/vishaps/vipackTree"}, "type" : "git"}
*)
BEGIN BEGIN
Strings.Append('{"path" : "', path); COPY("", path);
Strings.Append(vpkSettings.treeURL, path); Strings.Append(open, path);
Strings.Append('"}, "type" : "git"}', path); Strings.Append(vpkSettings.confTreeKey, path);
Strings.Append(is, path);
Strings.Append(vpkSettings.defTreeVal, path);
Strings.Append(newkey, path);
Strings.Append(vpkSettings.confTypKey, path);
Strings.Append(is, path);
Strings.Append(vpkSettings.defTypVal, path);
Strings.Append(close, path);
END mkConfContent; END mkConfContent;
PROCEDURE makeFile(VAR confFilePath: ARRAY OF CHAR; VAR f: Files.File; VAR r: Files.Rider); PROCEDURE mkDefConfig*;
VAR
content: ARRAY 96 OF CHAR;
f: Files.File;
r: Files.Rider;
BEGIN BEGIN
f := Files.New(confFilePath); vpkEnv.checkEnv;
f := vpkEnv.getConfFile();
Files.Set(r, f, 0); Files.Set(r, f, 0);
END makeFile; mkConfContent(content);
Files.WriteBytes(r, content, Strings.Length(content));
PROCEDURE writeInFile(VAR f: Files.File; r: Files.Rider; VAR text : ARRAY OF CHAR);
BEGIN
Files.WriteBytes(r, text, Strings.Length(text));
END writeInFile;
PROCEDURE closeFile(VAR f: Files.File);
BEGIN
Files.Register(f); Files.Register(f);
Files.Close(f); Files.Close(f);
END closeFile; END mkDefConfig;
PROCEDURE mkConfDirPath(home: ARRAY OF CHAR; VAR path: ARRAY OF CHAR); PROCEDURE configured*(): BOOLEAN;
BEGIN BEGIN
confDir := home; RETURN vpkEnv.checkConfig()
Strings.Append("/", path); END configured;
Strings.Append(vpkSettings.vpkConfDir, path);
END mkConfDirPath;
PROCEDURE setConfPath; PROCEDURE getConfigTreeVal*(VAR tree: vpkSettings.tree);
VAR VAR
home: ARRAY 128 OF CHAR; f: Files.File; r: Files.Rider;
dt: ARRAY 256 OF CHAR;
i : INTEGER; ch: CHAR;
jsonRecord : vpkJsonParser.JsonTypePointer;
b: BOOLEAN;
treeTyp: ARRAY 8 OF CHAR;
BEGIN BEGIN
getHome(home); f := vpkEnv.getConfFile();
mkConfDirPath(home, confDir); Files.Set(r, f, 0);
conf := confDir; i := 0;
Strings.Append("/", conf); WHILE ~ r.eof & (i < LEN(dt)) DO Files.Read(r, ch); dt[i] := ch; INC(i) END;
Strings.Append(vpkSettings.vpkConfFile, conf); Files.Close(f);
END setConfPath; jsonRecord := vpkJsonParser.Create(dt);
b := vpkJsonParser.GetTerminal(jsonRecord, vpkSettings.confTreeKey, tree.url);
PROCEDURE getConfPath*(VAR path: ARRAY OF CHAR); IF ~b THEN Out.String("unable to read "); Out.String (vpkSettings.confTreeKey); Out.String(" from json"); Out.Ln; HALT(1); END;
BEGIN b := vpkJsonParser.GetTerminal(jsonRecord, vpkSettings.confTypKey, treeTyp);
COPY(conf, path); IF ~b THEN Out.String("unable to read "); Out.String (vpkSettings.confTypKey); Out.String(" from json"); Out.Ln; HALT(1); END;
END getConfPath; IF treeTyp = vpkSettings.confTypGitVal THEN
tree.typ := vpkSettings.git;
PROCEDURE getConfDir*(VAR path: ARRAY OF CHAR); ELSIF treeTyp = vpkSettings.confTypHttpVal THEN
BEGIN tree.typ := vpkSettings.http
COPY(confDir, path);
END getConfDir;
PROCEDURE configure*;
VAR
content: ARRAY 256 OF CHAR;
file : vpkFsHelper.fileInfo;
fd: Files.File;
rd: Files.Rider;
BEGIN
file.name := conf;
IF ~vpkFsHelper.Exists(file) THEN
(* Checking if ~/.vipack directory already exists *)
file.name := confDir;
IF ~vpkFsHelper.Exists(file) THEN (* exists!!! *)
Out.String("Creating directory "); Out.String(confDir);Out.Ln;
IF ~vpkFsHelper.mkDir(confDir) THEN
Out.String("failed to create "); Out.String(confDir); Out.String(" directory"); Out.Ln;
HALT(1);
END;
ELSE ELSE
IF ~(vpkFsHelper.dir IN file.attr) THEN tree.typ := vpkSettings.unkn;
Out.String(confDir); Out.String(" exists, but is not a directory"); Out.Ln;
HALT(1);
END; END;
END; END getConfigTreeVal;
(* create conf file *)
Out.String("Creating the configuration file "); Out.String(conf);Out.Ln;
content := "";
makeFile(conf, fd, rd);
mkConfContent(content);
writeInFile(fd, rd, content);
closeFile(fd);
ELSE
Out.String("File already exists");Out.Ln;
END;
END configure;
BEGIN
setConfPath;
END vpkConf. END vpkConf.

View file

@ -1,12 +1,13 @@
MODULE vpkFileManager; MODULE vpkFileManager;
IMPORT Files, Out, vpkLogger, Strings, Platform; IMPORT Files, Out, Strings, Platform,
vpkLogger, vpkFiles;
PROCEDURE WriteString(VAR r : Files.Rider; str : ARRAY OF CHAR); PROCEDURE WriteString(VAR r : Files.Rider; str : ARRAY OF CHAR);
BEGIN BEGIN
Files.WriteBytes(r, str, Strings.Length(str)); Files.WriteBytes(r, str, Strings.Length(str));
END WriteString; END WriteString;
PROCEDURE Read*(fileName: ARRAY OF CHAR; VAR returnString: ARRAY OF CHAR): BOOLEAN; PROCEDURE fileToString*(fileName: ARRAY OF CHAR; VAR returnString: ARRAY OF CHAR): BOOLEAN;
VAR VAR
f: Files.File; f: Files.File;
r: Files.Rider; r: Files.Rider;
@ -32,9 +33,9 @@ BEGIN
UNTIL r.eof OR (i>=LEN(returnString)); UNTIL r.eof OR (i>=LEN(returnString));
RETURN TRUE; RETURN TRUE;
END Read; END fileToString;
PROCEDURE Write*(fileName, content: ARRAY OF CHAR): BOOLEAN; PROCEDURE stringToFile*(fileName, content: ARRAY OF CHAR): BOOLEAN;
VAR VAR
f: Files.File; f: Files.File;
r: Files.Rider; r: Files.Rider;
@ -60,22 +61,17 @@ BEGIN
Files.Register(f); Files.Register(f);
RETURN TRUE; RETURN TRUE;
END Write; END stringToFile;
PROCEDURE CreateDirectory*(name, path: ARRAY OF CHAR): BOOLEAN; PROCEDURE createDir*(name, path: ARRAY OF CHAR): BOOLEAN;
VAR VAR
command, path0: ARRAY 100 OF CHAR; p : POINTER TO ARRAY OF CHAR;
errorCode: LONGINT;
BEGIN BEGIN
COPY(path, path0); NEW(p, Strings.Length(name) + Strings.Length(path) + 1);
COPY("mkdir -p ", command); COPY(path, p^);
Strings.Append("/", path0); Strings.Append("/", p^);
Strings.Append(name, path0); Strings.Append(name, p^);
Strings.Append(path0, command); RETURN vpkFiles.mkDir(p^)
errorCode := Platform.System(command); END createDir;
IF errorCode = 0 THEN RETURN TRUE
ELSE RETURN FALSE END;
END CreateDirectory;
END vpkFileManager. END vpkFileManager.

View file

@ -1,23 +0,0 @@
MODULE vpkGit;
IMPORT Out, Strings, Platform;
PROCEDURE pull*(URL : ARRAY OF CHAR; dst : ARRAY OF CHAR);
VAR i : INTEGER;
cmd : ARRAY 120 OF CHAR;
BEGIN
cmd:= "git init ";
Strings.Append(dst, cmd);
i:=Platform.System(cmd);
cmd := "";
cmd := "git -C ";
Strings.Append(dst,cmd);
Strings.Append(" pull ",cmd);
Strings.Append(URL, cmd);
i := Platform.System(cmd);
Out.Int(i,0);
END pull;
BEGIN
END vpkGit.

View file

@ -1,5 +1,5 @@
MODULE vpkLogger; MODULE vpkLogger;
IMPORT vpkTime, Out, Strings; IMPORT Out, Strings, vpkTime;
CONST CONST
deca = 10; deca = 10;

View file

@ -14,7 +14,7 @@ VAR
success: BOOLEAN; success: BOOLEAN;
BEGIN BEGIN
vpkLogger.Log("Starting install process"); vpkLogger.Log("Starting install process");
success := vpkFileManager.Read(vpkSettings.packageFileName, jsonData); success := vpkFileManager.fileToString(vpkSettings.packageFileName, jsonData);
IF ~success THEN vpkLogger.Log("Some ERROR occured while reading VERSIONFILE") END; IF ~success THEN vpkLogger.Log("Some ERROR occured while reading VERSIONFILE") END;
ASSERT(success); ASSERT(success);

View file

@ -12,7 +12,7 @@ BEGIN
vpkLogger.Log(path); vpkLogger.Log(path);
vpkHttp.get(host, port, path, returnValue); vpkHttp.get(host, port, path, returnValue);
vpkHttp.getClean(returnValue, returnValue); vpkHttp.getClean(returnValue, returnValue);
isSuccessfull := vpkFileManager.CreateDirectory(packageName, vpkSettings.installPath); isSuccessfull := vpkFileManager.createDir(packageName, vpkSettings.installPath);
IF ~isSuccessfull THEN vpkLogger.Log("Something went wrong, while downloading files") END; IF ~isSuccessfull THEN vpkLogger.Log("Something went wrong, while downloading files") END;
ASSERT(isSuccessfull); ASSERT(isSuccessfull);
@ -26,7 +26,7 @@ BEGIN
Strings.Append("/", localPath); Strings.Append("/", localPath);
Strings.Append(fileName, localPath); Strings.Append(fileName, localPath);
isSuccessfull := vpkFileManager.Write(localPath, returnValue); isSuccessfull := vpkFileManager.stringToFile(localPath, returnValue);
END ResolveFile; END ResolveFile;

View file

@ -4,13 +4,27 @@ CONST
vpkConfDir* = ".vipack"; vpkConfDir* = ".vipack";
vpkConfFile* = "vipackConf.json"; vpkConfFile* = "vipackConf.json";
vpkTreeDir* = "vipackTree"; vpkTreeDir* = "vipackTree";
treeURL* = "https://github.com/vishaps/vipackTree";
confTypGit* = "git"; confTypKey* = "type";
confType* = "type"; confTypGitVal* = "git";
confTermPath* = "path"; confTypHttpVal* = "http";
confTreeKey* = "path";
defTreeVal* = "https://github.com/vishaps/vipackTree";
confTreeVal* = defTreeVal;
defTypVal* = confTypGitVal;
packageFileName* = "VersionFile.json"; packageFileName* = "VersionFile.json";
host* = "localhost"; host* = "localhost";
port* = "80"; port* = "80";
installPath* = "dependencies"; installPath* = "dependencies";
http* = 0;
git* = 1;
unkn* = -1;
TYPE
tree* = RECORD
url* : ARRAY 128 OF CHAR;
typ* : SHORTINT
END;
END vpkSettings. END vpkSettings.

View file

@ -1,48 +1,24 @@
MODULE vpkSyncer; MODULE vpkSyncer;
IMPORT Strings, Out, IMPORT Strings, Out,
vpkSettings, vpkConf, vpkFsHelper, vpkFileManager, vpkJsonParser, vpkGit; vpkSettings, vpkEnv, vpkConf, vpkFiles, vpkGit;
PROCEDURE mkTreePath(VAR path: ARRAY OF CHAR); PROCEDURE mkTreePath(VAR path: ARRAY OF CHAR);
BEGIN BEGIN
vpkConf.getConfDir(path); vpkEnv.getConfDir(path);
Strings.Append('/', path); Strings.Append('/', path);
Strings.Append(vpkSettings.vpkTreeDir, path); Strings.Append(vpkSettings.vpkTreeDir, path);
END mkTreePath; END mkTreePath;
PROCEDURE sync*; PROCEDURE sync*;
VAR VAR
dir : vpkFsHelper.fileInfo; tree: vpkSettings.tree;
jsonData: ARRAY 256 OF CHAR;
jsonURL: ARRAY 64 OF CHAR;
jsonType: ARRAY 8 OF CHAR;
b: BOOLEAN;
confPath, treePath : ARRAY 256 OF CHAR;
jsonRecord : vpkJsonParser.JsonTypePointer;
BEGIN BEGIN
mkTreePath(treePath);
Out.String("*****************************************"); Out.Ln;
Out.String("TreePath = "); Out.String(treePath); Out.Ln;
(* Check tree directory if doesn't exist create*)
dir.name := treePath;
IF ~vpkFsHelper.Exists(dir) THEN
Out.String(treePath); Out.String(" directory doesn't exist, creating"); Out.Ln;
b := vpkFsHelper.mkDir(treePath);
END;
IF ~(vpkFsHelper.dir IN dir.attr) THEN
Out.String(treePath); Out.String(" exists but is not a directory"); Out.Ln;
HALT(1);
END;
(* Syncing *) (* Syncing *)
vpkConf.getConfPath(confPath); vpkConf.getConfigTreeVal(tree);
b := vpkFileManager.Read(confPath, jsonData); IF tree.typ = vpkSettings.git THEN
jsonRecord := vpkJsonParser.Create(jsonData); vpkGit.syncTree(tree.url)
b := vpkJsonParser.GetTerminal(jsonRecord, vpkSettings.confTermPath, jsonURL);
Out.String("URL = "); Out.String(jsonURL); Out.Ln;
b := vpkJsonParser.GetTerminal(jsonRecord, vpkSettings.confType, jsonType);
IF jsonType = vpkSettings.confTypGit THEN
vpkGit.pull(jsonURL, treePath)
ELSE ELSE
Out.String("not a git url"); Out.Ln Out.String("TODO: not a git url"); Out.Ln
END; END;
END sync; END sync;

View file

@ -1,9 +0,0 @@
MODULE vpkUserDetails;
IMPORT Platform;
PROCEDURE GetUsername*(VAR str : ARRAY OF CHAR):BOOLEAN;
BEGIN
RETURN Platform.getEnv("USER", str);
END GetUsername;
END vpkUserDetails.