diff --git a/GNUmakefile b/GNUmakefile index 0483499..c01addb 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -67,6 +67,7 @@ buildThis: cd $(BUILD) && $(VOC) -s $(mkfile_dir_path)/src/vpkResolver.Mod cd $(BUILD) && $(VOC) -s $(mkfile_dir_path)/src/vpkJsonDepRetriever.Mod cd $(BUILD) && $(VOC) -s $(mkfile_dir_path)/src/vpkInstaller.Mod + cd $(BUILD) && $(VOC) -s $(mkfile_dir_path)/src/vpkLocalBuilder.Mod cd $(BUILD) && $(VOC) $(mkfile_dir_path)/src/vipak.Mod -cm cd $(BUILD) && gcc -o vipak *.o -static -L/opt/voc/lib -lvoc-O2 /opt/voc/lib/libvoc-O2.a -L. -lmbedtls -lmbedcrypto -lmbedx509 libmbedcrypto.a libmbedtls.a libmbedx509.a @echo "________________________________________" diff --git a/src/vipak.Mod b/src/vipak.Mod index 09eccc9..7d9e0d5 100644 --- a/src/vipak.Mod +++ b/src/vipak.Mod @@ -1,88 +1,7 @@ MODULE vipak; IMPORT Texts, Strings, Oberon, Out, - vpkConf, vpkLogger, vpkSyncer, vpkInstaller, vpkdepTree, opts, StringList; -(* -PROCEDURE processArgs(VAR package, prefix, tree: ARRAY OF CHAR; deps, sync: BOOLEAN); -VAR - options: opts.Options; - foptions: opts.Options; - opt, fopt: opts.Option; -BEGIN - - options := opts.createOptions(); - foptions := opts.createOptions(); - - opt := opts.createOpt(); - opts.setOptName(opt, "-p"); - opts.setOptLName(opt, "--package"); - opts.setOptHasVal(opt, TRUE); - opts.setOptDesc(opt, "package name to download"); - opts.setOptRequired(opt, FALSE); - options.add(options, opt); - - opt := opts.createOpt(); - opts.setOptName(opt, "-d"); - opts.setOptLName(opt, "--showdeps"); - opts.setOptHasVal(opt, FALSE); - opts.setOptDesc(opt, "only resolve and show dependencies, do not fetch"); - opts.setOptRequired(opt, FALSE); - options.add(options, opt); - - opts.setOptRequired(opt, FALSE); - options.add(options, opt); - - opt := opts.createOpt(); - opts.setOptName(opt, "-s"); - opts.setOptLName(opt, "--sync"); - opts.setOptHasVal(opt, FALSE); - opts.setOptDesc(opt, "sync the package tree"); - opts.setOptRequired(opt, FALSE); - options.add(options, opt); - - opt := opts.createOpt(); - opts.setOptName(opt, "-P"); - opts.setOptLName(opt, "--prefix"); - opts.setOptHasVal(opt, TRUE); - opts.setOptDesc(opt, "where to download and build packages"); - opts.setOptRequired(opt, FALSE); - options.add(options, opt); - - opt := opts.createOpt(); - opts.setOptName(opt, "-t"); - opts.setOptLName(opt, "--tree"); - opts.setOptHasVal(opt, TRUE); - opts.setOptDesc(opt, "override the default package description tree"); - opts.setOptRequired(opt, FALSE); - options.add(options, opt); - - foptions := opts.populateOptions(options); - IF opts.reqsSatisfied(options, foptions) THEN - Out.String("required options provided"); Out.Ln; - ELSE - Out.String("required options not provided"); Out.Ln; - opts.showHelp(options); - HALT(3); - END; - Out.Ln; - - COPY("", package); COPY("", prefix); COPY("", tree); - deps := FALSE; sync := FALSE; - - fopt := opts.createOpt(); - fopt := opts.findOpt("-d", foptions); - IF fopt # NIL THEN deps := TRUE END; - - fopt := opts.createOpt(); - fopt := opts.findOpt("-s", foptions); - IF fopt # NIL THEN sync := TRUE END; - - - opts.valOfOpt("-p", foptions, package); - opts.valOfOpt("-P", foptions, prefix); - opts.valOfOpt("-t", foptions, tree); - -END processArgs; -*) + vpkConf, vpkLogger, vpkSyncer, vpkInstaller, vpkdepTree, opts, StringList, + vpkLocalBuilder; PROCEDURE msgnopkg(VAR options: opts.Options); BEGIN @@ -92,8 +11,8 @@ END msgnopkg; PROCEDURE main; VAR - deps, sync, fetch, ask: BOOLEAN; - package, prefix, pkgTree: ARRAY 128 OF CHAR; + deps, sync, fetch, ask, local, init, withDeps: BOOLEAN; + package, prefix, pkgTree, localFile: ARRAY 128 OF CHAR; options: opts.Options; foptions: opts.Options; @@ -134,7 +53,7 @@ BEGIN opts.setOptName(opt, "-a"); opts.setOptLName(opt, "--ask"); opts.setOptHasVal(opt, FALSE); - opts.setOptDesc(opt, "only resolve and fetch, do not build"); + opts.setOptDesc(opt, "ask before proceeding with build/fetch"); opts.setOptRequired(opt, FALSE); options.add(options, opt); @@ -162,6 +81,31 @@ BEGIN opts.setOptRequired(opt, FALSE); options.add(options, opt); + (* New local build options *) + opt := opts.createOpt(); + opts.setOptName(opt, "-l"); + opts.setOptLName(opt, "--local"); + opts.setOptHasVal(opt, TRUE); + opts.setOptDesc(opt, "build local project from specified vipak.json file"); + opts.setOptRequired(opt, FALSE); + options.add(options, opt); + + opt := opts.createOpt(); + opts.setOptName(opt, "-i"); + opts.setOptLName(opt, "--init"); + opts.setOptHasVal(opt, FALSE); + opts.setOptDesc(opt, "create default vipak.json in current directory"); + opts.setOptRequired(opt, FALSE); + options.add(options, opt); + + opt := opts.createOpt(); + opts.setOptName(opt, "-w"); + opts.setOptLName(opt, "--with-deps"); + opts.setOptHasVal(opt, FALSE); + opts.setOptDesc(opt, "also build dependencies when building local project"); + opts.setOptRequired(opt, FALSE); + options.add(options, opt); + foptions := opts.populateOptions(options); IF opts.reqsSatisfied(options, foptions) THEN Out.String("required options provided"); Out.Ln; @@ -172,9 +116,9 @@ BEGIN END; Out.Ln; - COPY("", package); COPY("", prefix); COPY("", pkgTree); - deps := FALSE; sync := FALSE; - fetch := FALSE; ask := FALSE; + COPY("", package); COPY("", prefix); COPY("", pkgTree); COPY("vipak.json", localFile); + deps := FALSE; sync := FALSE; fetch := FALSE; ask := FALSE; + local := FALSE; init := FALSE; withDeps := FALSE; fopt := opts.createOpt(); fopt := opts.findOpt("-d", foptions); @@ -184,7 +128,6 @@ BEGIN fopt := opts.findOpt("-a", foptions); IF fopt # NIL THEN ask := TRUE END; - fopt := opts.createOpt(); fopt := opts.findOpt("-f", foptions); IF fopt # NIL THEN fetch := TRUE END; @@ -193,6 +136,17 @@ BEGIN fopt := opts.findOpt("-s", foptions); IF fopt # NIL THEN sync := TRUE END; + fopt := opts.createOpt(); + fopt := opts.findOpt("-l", foptions); + IF fopt # NIL THEN local := TRUE END; + + fopt := opts.createOpt(); + fopt := opts.findOpt("-i", foptions); + IF fopt # NIL THEN init := TRUE END; + + fopt := opts.createOpt(); + fopt := opts.findOpt("-w", foptions); + IF fopt # NIL THEN withDeps := TRUE END; opts.valOfOpt("-p", foptions, package); opts.valOfOpt("-P", foptions, prefix); @@ -203,10 +157,18 @@ BEGIN IF pkgTree = "" THEN Out.String(" will use the default package tree location"); Out.Ln; END; + opts.valOfOpt("-l", foptions, localFile); IF pkgTree # "" THEN vpkConf.setTreeDir(pkgTree) END; - IF sync THEN + (* Handle new local build functionality *) + IF init THEN + Out.String("Initializing new vipak project..."); Out.Ln; + vpkLocalBuilder.init + ELSIF local THEN + Out.String("Building local project from: "); Out.String(localFile); Out.Ln; + vpkLocalBuilder.buildLocal(localFile, withDeps) + ELSIF sync THEN vpkSyncer.sync ELSE IF package # "" THEN @@ -224,48 +186,6 @@ BEGIN END main; -(* -PROCEDURE help(); -BEGIN - vpkLogger.Log("HelpText"); - Out.String("Vipack sync - syncing git tree and local tree"); Out.Ln; - Out.String("vipackConf.json path -> $HOME/.vipack/vipackConf.json"); Out.Ln; - Out.String("vipak tree path -> $HOME/.vipak/vipatsar") -END help; - -PROCEDURE main(); -VAR - S: Texts.Scanner; - unit, command: ARRAY 64 OF CHAR; (* because Texts.Scanner.s is 64 bytes long*) -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 *) - Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); - Texts.Scan(S); - - command := S.s; - - IF Strings.Match(command, "") OR Strings.Match(command, "help")THEN - help; - ELSE - - IF command = "sync" THEN - vpkSyncer.sync; - END; - - IF command = "install" THEN - Texts.Scan(S); - unit := S.s; - vpkInstaller.install(unit); - END; - - END; -END main; -*) - BEGIN main -END vipak. +END vipak. \ No newline at end of file diff --git a/src/vpkJsonDepRetriever.Mod b/src/vpkJsonDepRetriever.Mod index 029e006..e0992f8 100644 --- a/src/vpkJsonDepRetriever.Mod +++ b/src/vpkJsonDepRetriever.Mod @@ -5,6 +5,9 @@ IMPORT Strings, Out, CONST ErrmessSize = 4096; +VAR + currentLocalProjectFile: ARRAY 256 OF CHAR; + PROCEDURE ToLower(VAR stringVar: ARRAY OF CHAR); VAR i: INTEGER; @@ -399,4 +402,145 @@ BEGIN RETURN 0; END getDeps; +PROCEDURE setLocalProjectFile*(VAR filename: ARRAY OF CHAR); +BEGIN + COPY(filename, currentLocalProjectFile); +END setLocalProjectFile; + +PROCEDURE getBuildInfoFromFile*(VAR d: vpkdepTree.Tdep; VAR k, v: StringList.TStringList; VAR filename: ARRAY OF CHAR): BOOLEAN; +VAR + jsonstr, errstr: strUtils.pstring; + tree, buildValue, command, file: Json.Value; + rootObj, buildStep: Json.Obj; + buildArray: Json.Arr; + cm, fl, bl, cmLower, flLower: Json.jString; + b: BOOLEAN; +BEGIN + k := NIL; v := NIL; + b := FALSE; + jsonstr := NIL; + + (* Read from specified file instead of package tree *) + vpkStorage.fileToString(filename, jsonstr); + + IF jsonstr # NIL THEN + NEW(errstr, ErrmessSize); + b := Json.Parse(tree, jsonstr^, errstr^); + IF b THEN + IF tree IS Json.Obj THEN + rootObj := tree(Json.Obj); + NEW(bl, Strings.Length(vpkSettings.bldType) + 1); (* +1 for 0X *) + COPY(vpkSettings.bldType, bl^); + IF Json.ObjSelect(buildValue, rootObj, bl) THEN + IF buildValue IS Json.Arr THEN + buildArray := buildValue(Json.Arr); + WHILE buildArray # NIL DO + buildStep := buildArray.value(Json.Obj); + NEW(cm, Strings.Length(vpkSettings.bldCommand) + 1); (* +1 for 0X *) + NEW(fl, Strings.Length(vpkSettings.bldFile) + 1); (* +1 for 0X *) + COPY(vpkSettings.bldCommand, cm^); + COPY(vpkSettings.bldFile, fl^); + + (* Handle build steps (same logic as original getBuildInfo) *) + IF Json.ObjSelect(command, buildStep, cm) & Json.ObjSelect(file, buildStep, fl) THEN + IF (command IS Json.Str) & (file IS Json.Str) THEN + IF k = NIL THEN k := StringList.Create() END; + IF v = NIL THEN v := StringList.Create() END; + k.AppendString(k, command(Json.Str).str^); + v.AppendString(v, file(Json.Str).str^); + ELSE + Out.String("command and file must be strings"); Out.Ln; + HALT(5); + END; + ELSE + Out.String("Failed to select 'command' or 'file' from build step"); Out.Ln; + END; + buildArray := buildArray.next; + END; + ELSE + Out.String("Build section is not an array."); Out.Ln; + END; + ELSE + Out.String("Build section not found."); Out.Ln; + END; + ELSE + Out.String("JSON root is not an object."); Out.Ln; + END; + ELSE + Out.String("JSON parsing failed: "); Out.String(errstr^); Out.Ln; + END; + ELSE + Out.String("No JSON string provided."); Out.Ln; + END; + RETURN b; +END getBuildInfoFromFile; + +PROCEDURE getDepsFromFile*(VAR d: vpkdepTree.Tdep; VAR depstrlist: StringList.TStringList): LONGINT; +VAR + jsonstr, errstr: strUtils.pstring; + tree, depsValue, singleDep: Json.Value; + rootObj, depObj: Json.Obj; + depName, depVersion: Json.jString; + foundDepSection: BOOLEAN; + filename: ARRAY 128 OF CHAR; +BEGIN + depstrlist := NIL; + jsonstr := NIL; + + (* For local projects, read from current directory's vipak.json *) + IF currentLocalProjectFile = "" THEN + COPY("vipak.json", filename); + ELSE + COPY(currentLocalProjectFile, filename); + END; + vpkStorage.fileToString(filename, jsonstr); + + IF jsonstr # NIL THEN + NEW(errstr, ErrmessSize); + IF Json.Parse(tree, jsonstr^, errstr^) THEN + IF tree IS Json.Obj THEN + rootObj := tree(Json.Obj); + (* searching for dependencies section *) + foundDepSection := FALSE; + REPEAT + IF rootObj.name^ = vpkSettings.depTypKey THEN + foundDepSection := TRUE; + END; + IF ~foundDepSection THEN rootObj := rootObj.next END + UNTIL (rootObj = NIL) OR foundDepSection; + IF foundDepSection THEN + WHILE rootObj # NIL DO + depsValue := rootObj.value; + IF depsValue # NIL THEN + IF depsValue IS Json.Obj THEN + singleDep := depsValue(Json.Obj); + WHILE singleDep # NIL DO + IF singleDep IS Json.Obj THEN + depObj := singleDep(Json.Obj); + depName := depObj.name; + depVersion := depObj.value(Json.Str).str; + IF depstrlist = NIL THEN depstrlist := StringList.Create() END; + depstrlist.AppendString(depstrlist, depName^); + singleDep := depObj.next; (* Move to the next dependency *) + END; + END; (* End of inner WHILE loop for dependencies *) + RETURN depstrlist.Count; + END; (* End of IF depsValue IS Json.Obj *) + END; + rootObj := rootObj.next; (* Move to the next JSON object *) + END; (* End of WHILE rootObj # NIL loop *) + ELSE + RETURN 0; (* found no dependencies *) + END; + END; (* End of IF tree IS Json.Obj *) + ELSE + Out.String("JSON parsing failed: "); Out.String(errstr^); Out.Ln; + END; (* End of IF Json.Parse *) + ELSE + Out.String("local project file not found: "); Out.String(filename); Out.Ln; + RETURN -1; (* No such JSON file found *) + END; (* End of IF jsonstr # NIL *) + RETURN 0; +END getDepsFromFile; + END vpkJsonDepRetriever.