deps dir moved to build. git builds work.

This commit is contained in:
Norayr Chilingarian 2025-07-19 19:06:11 +04:00
parent 49d24a5afe
commit ee137b10df
9 changed files with 452 additions and 129 deletions

View file

@ -19,31 +19,111 @@ BEGIN
END getGraphName; END getGraphName;
PROCEDURE createIfNotThere*(VAR fileName: ARRAY OF CHAR); PROCEDURE createIfNotThere*(VAR fileName: ARRAY OF CHAR);
VAR
workName: ARRAY 512 OF CHAR;
len: INTEGER;
BEGIN BEGIN
IF ~UnixFS.ExistsByName(fileName) THEN COPY(fileName, workName);
IF ~UnixFS.mkDir(fileName) THEN
Out.String("failed to create directory "); Out.String(fileName); Out.Ln; HALT(1);
END;
END;
(* Remove trailing slash for directory creation *)
len := Strings.Length(workName);
IF (len > 1) & (workName[len - 1] = '/') THEN
workName[len - 1] := 0X;
END;
IF ~UnixFS.ExistsByName(workName) THEN
IF ~UnixFS.mkDir(workName) THEN
Out.String("failed to create directory "); Out.String(workName); Out.Ln; HALT(1);
END;
END;
END createIfNotThere; END createIfNotThere;
PROCEDURE getSrcRelPath*(VAR depName, domain, path0: ARRAY OF CHAR): strTypes.pstring; (* Create directories recursively like mkdir -p *)
PROCEDURE mkDirRecursive*(VAR fullPath: ARRAY OF CHAR);
VAR
currentPath: ARRAY 512 OF CHAR;
component: ARRAY 128 OF CHAR;
pos, nextPos: INTEGER;
i: INTEGER;
BEGIN
(*
Out.String(">>> mkDirRecursive called with: '"); Out.String(fullPath); Out.String("'"); Out.Ln;
*)
COPY("", currentPath);
pos := 0;
(* Handle absolute paths starting with / *)
IF (Strings.Length(fullPath) > 0) & (fullPath[0] = '/') THEN
COPY("/", currentPath);
pos := 1;
END;
WHILE pos < Strings.Length(fullPath) DO
(* Find next '/' or end of string *)
nextPos := pos;
WHILE (nextPos < Strings.Length(fullPath)) & (fullPath[nextPos] # '/') DO
INC(nextPos);
END;
(* Extract component *)
IF nextPos > pos THEN
i := 0;
WHILE (pos < nextPos) & (i < LEN(component) - 1) DO
component[i] := fullPath[pos];
INC(i); INC(pos);
END;
component[i] := 0X;
(* Append component to current path *)
IF Strings.Length(currentPath) > 0 THEN
IF currentPath[Strings.Length(currentPath) - 1] # '/' THEN
Strings.Append("/", currentPath);
END;
END;
Strings.Append(component, currentPath);
(*
Out.String(">>> Creating directory: '"); Out.String(currentPath); Out.String("'"); Out.Ln;
*)
(* Create directory if it doesn't exist - createIfNotThere handles trailing slashes *)
createIfNotThere(currentPath);
END;
(* Skip the '/' *)
IF (pos < Strings.Length(fullPath)) & (fullPath[pos] = '/') THEN
INC(pos);
END;
END;
(*
Out.String(">>> mkDirRecursive completed"); Out.Ln;
*)
END mkDirRecursive;
PROCEDURE getSrcRelPath*(VAR depName, repoPath, path0: ARRAY OF CHAR): strTypes.pstring;
VAR VAR
p: strTypes.pstring; p: strTypes.pstring;
len: INTEGER; len: INTEGER;
BEGIN BEGIN
len := 12 + Strings.Length(depName) + Strings.Length(path0) + Strings.Length(domain); (*
(* 5 chars are ../, /, /, plus a couple of chars *) Out.String("@@@ getSrcRelPath called with:"); Out.Ln;
Out.String("@@@ depName: '"); Out.String(depName); Out.String("'"); Out.Ln;
Out.String("@@@ repoPath: '"); Out.String(repoPath); Out.String("'"); Out.Ln;
Out.String("@@@ path0: '"); Out.String(path0); Out.String("'"); Out.Ln;
*)
len := 16 + Strings.Length(path0) + Strings.Length(repoPath);
NEW(p, len); NEW(p, len);
COPY("../", p^); COPY("", p^); (* Start with empty string instead of "../" *)
Strings.Append(vpkSettings.vpkDepDir, p^); Strings.Append(vpkSettings.vpkDepDir, p^);
Strings.Append("/", p^); Strings.Append("/", p^);
Strings.Append(domain, p^); Strings.Append(repoPath, p^);
Strings.Append("/", p^);
Strings.Append(depName, p^);
Strings.Append("/", p^); Strings.Append("/", p^);
Strings.Append(path0, p^); Strings.Append(path0, p^);
(*
Out.String("@@@ result: '"); Out.String(p^); Out.String("'"); Out.Ln;
*)
RETURN p; RETURN p;
END getSrcRelPath; END getSrcRelPath;
@ -89,42 +169,82 @@ BEGIN
RETURN builddir RETURN builddir
END mkdefBldDir; END mkdefBldDir;
PROCEDURE mkdefPkgDirPath*(VAR domain, name, path: ARRAY OF CHAR); PROCEDURE mkdefPkgDirPath*(VAR repoPath, name, path: ARRAY OF CHAR);
VAR VAR
home: ARRAY 128 OF CHAR; home: ARRAY 128 OF CHAR;
finalPath: ARRAY 512 OF CHAR;
BEGIN BEGIN
getHome(home); getHome(home);
COPY(home, path);
Strings.Append("/", path); (* Build: <home>/<vpkPkgDir>/deps/<repoPath>/<name>/ *)
Strings.Append(vpkSettings.vpkPkgDir, path); COPY(home, finalPath);
createIfNotThere(path); Strings.Append("/", finalPath);
Strings.Append("/", path); Strings.Append(vpkSettings.vpkPkgDir, finalPath);
Strings.Append(vpkSettings.vpkDepDir, path); Strings.Append("/", finalPath);
createIfNotThere(path); Strings.Append(vpkSettings.vpkDepDir, finalPath);
Strings.Append("/", path); Strings.Append("/", finalPath);
Strings.Append(domain, path); Strings.Append(repoPath, finalPath);
createIfNotThere(path); Strings.Append("/", finalPath);
Strings.Append("/", path); Strings.Append(name, finalPath);
Strings.Append(name, path);
createIfNotThere(path); (* Create all directories recursively *)
mkDirRecursive(finalPath);
(* Return the path with trailing slash *)
COPY(finalPath, path);
Strings.Append("/", path); Strings.Append("/", path);
END mkdefPkgDirPath; END mkdefPkgDirPath;
PROCEDURE mkPkgDirPath*(VAR domain, name, path: ARRAY OF CHAR); PROCEDURE mkPkgDirPath*(VAR repoPath, name, path: ARRAY OF CHAR);
VAR
finalPath: ARRAY 512 OF CHAR;
len: INTEGER;
BEGIN BEGIN
Strings.Append("/", path); (*
createIfNotThere(path); Out.String("=== DEBUG mkPkgDirPath START ==="); Out.Ln;
Strings.Append(vpkSettings.vpkDepDir, path); Out.String("Input path: '"); Out.String(path); Out.String("'"); Out.Ln;
Strings.Append("/", path); Out.String("Input repoPath: '"); Out.String(repoPath); Out.String("'"); Out.Ln;
createIfNotThere(path); Out.String("Input name: '"); Out.String(name); Out.String("'"); Out.Ln;
Strings.Append(domain, path); *)
createIfNotThere(path);
Strings.Append("/", path);
Strings.Append(name, path);
createIfNotThere(path);
Strings.Append("/", path);
END mkPkgDirPath;
(* Start with clean path *)
COPY(path, finalPath);
(* Remove trailing slashes *)
len := Strings.Length(finalPath);
WHILE (len > 1) & (finalPath[len - 1] = '/') DO
finalPath[len - 1] := 0X;
DEC(len);
END;
(*
Out.String("After removing trailing slashes: '"); Out.String(finalPath); Out.String("'"); Out.Ln;
*)
(* Add /deps *)
Strings.Append("/", finalPath);
Strings.Append(vpkSettings.vpkDepDir, finalPath);
(*
Out.String("After adding deps: '"); Out.String(finalPath); Out.String("'"); Out.Ln;
*)
(* Add /<repoPath> - this already contains the package name! *)
Strings.Append("/", finalPath);
Strings.Append(repoPath, finalPath);
(*
Out.String("After adding repoPath: '"); Out.String(finalPath); Out.String("'"); Out.Ln;
*)
(* Create directories *)
mkDirRecursive(finalPath);
(* Return with trailing slash *)
COPY(finalPath, path);
Strings.Append("/", path);
(*
Out.String("Final output path: '"); Out.String(path); Out.String("'"); Out.Ln;
Out.String("=== DEBUG mkPkgDirPath END ==="); Out.Ln;
*)
END mkPkgDirPath;
PROCEDURE mkCmd*(VAR p0, p1: ARRAY OF CHAR): strTypes.pstring; PROCEDURE mkCmd*(VAR p0, p1: ARRAY OF CHAR): strTypes.pstring;
VAR VAR

View file

@ -4,28 +4,38 @@ IMPORT Out, Strings, Platform, vpkEnv;
PROCEDURE pull*(VAR url : ARRAY OF CHAR; VAR dst : ARRAY OF CHAR; VAR branch: ARRAY OF CHAR); PROCEDURE pull*(VAR url : ARRAY OF CHAR; VAR dst : ARRAY OF CHAR; VAR branch: ARRAY OF CHAR);
VAR i : INTEGER; VAR i : INTEGER;
cmd : ARRAY 2048 OF CHAR; cmd : ARRAY 2048 OF CHAR;
cleanDst: ARRAY 512 OF CHAR;
BEGIN BEGIN
cmd := "git init "; (* Clean destination path - remove trailing slash *)
Strings.Append(dst, cmd); COPY(dst, cleanDst);
i:=Platform.System(cmd); IF (Strings.Length(cleanDst) > 1) & (cleanDst[Strings.Length(cleanDst) - 1] = '/') THEN
(*cmd := "git -C "; cleanDst[Strings.Length(cleanDst) - 1] := 0X;
Strings.Append(dst, cmd); END;
Strings.Append(" remote add origin ", cmd);
Out.String("*** GIT: Cloning to: '"); Out.String(cleanDst); Out.String("'"); Out.Ln;
(* Remove directory if it exists to avoid conflicts *)
cmd := "rm -rf ";
Strings.Append(cleanDst, cmd);
i := Platform.System(cmd);
(* Use git clone directly - much simpler *)
cmd := "git clone ";
Strings.Append(url, cmd); Strings.Append(url, cmd);
i:=Platform.System(cmd);*)
cmd := "";
cmd := "git -C ";
Strings.Append(dst, cmd);
Strings.Append(" pull ", cmd);
Strings.Append(url, cmd);
Out.String("branch: '"); Out.String(branch); Out.String("'."); Out.Ln;
IF branch # "" THEN IF branch # "" THEN
Out.String("adding branch to commandline"); Out.Ln; Strings.Append(" --branch ", cmd);
Strings.Append(" ", cmd);
Strings.Append(branch, cmd); Strings.Append(branch, cmd);
END; END;
Out.String("fetch command: '"); Out.String(cmd); Out.Char("'"); Out.Ln; Strings.Append(" ", cmd);
Strings.Append(cleanDst, cmd);
Out.String("*** GIT: Executing: '"); Out.String(cmd); Out.String("'"); Out.Ln;
i := Platform.System(cmd); i := Platform.System(cmd);
IF i # 0 THEN
Out.String("*** GIT: Command failed with exit code: "); Out.Int(i, 0); Out.Ln;
ELSE
Out.String("*** GIT: Clone successful"); Out.Ln;
END;
END pull; END pull;
PROCEDURE syncTree*(url, branch: ARRAY OF CHAR); PROCEDURE syncTree*(url, branch: ARRAY OF CHAR);

View file

@ -11,7 +11,7 @@ END msgnopkg;
PROCEDURE main; PROCEDURE main;
VAR VAR
deps, sync, fetch, ask, local, init, withDeps: BOOLEAN; deps, sync, fetch, ask, local, init: BOOLEAN;
package, prefix, pkgTree, localFile: ARRAY 128 OF CHAR; package, prefix, pkgTree, localFile: ARRAY 128 OF CHAR;
options: opts.Options; options: opts.Options;
@ -86,7 +86,7 @@ BEGIN
opts.setOptName(opt, "-l"); opts.setOptName(opt, "-l");
opts.setOptLName(opt, "--local"); opts.setOptLName(opt, "--local");
opts.setOptHasVal(opt, FALSE); opts.setOptHasVal(opt, FALSE);
opts.setOptDesc(opt, "build local project from vipak.json file"); opts.setOptDesc(opt, "build local project from vipak.json file (includes dependencies)");
opts.setOptRequired(opt, FALSE); opts.setOptRequired(opt, FALSE);
options.add(options, opt); options.add(options, opt);
@ -98,14 +98,6 @@ BEGIN
opts.setOptRequired(opt, FALSE); opts.setOptRequired(opt, FALSE);
options.add(options, opt); 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); foptions := opts.populateOptions(options);
IF opts.reqsSatisfied(options, foptions) THEN IF opts.reqsSatisfied(options, foptions) THEN
Out.String("required options provided"); Out.Ln; Out.String("required options provided"); Out.Ln;
@ -118,7 +110,7 @@ BEGIN
COPY("", package); COPY("", prefix); COPY("", pkgTree); COPY("vipak.json", localFile); COPY("", package); COPY("", prefix); COPY("", pkgTree); COPY("vipak.json", localFile);
deps := FALSE; sync := FALSE; fetch := FALSE; ask := FALSE; deps := FALSE; sync := FALSE; fetch := FALSE; ask := FALSE;
local := FALSE; init := FALSE; withDeps := FALSE; local := FALSE; init := FALSE;
fopt := opts.createOpt(); fopt := opts.createOpt();
fopt := opts.findOpt("-d", foptions); fopt := opts.findOpt("-d", foptions);
@ -144,10 +136,6 @@ BEGIN
fopt := opts.findOpt("-i", foptions); fopt := opts.findOpt("-i", foptions);
IF fopt # NIL THEN init := TRUE END; 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, package);
opts.valOfOpt("-P", foptions, prefix); opts.valOfOpt("-P", foptions, prefix);
IF prefix = "" THEN IF prefix = "" THEN
@ -166,7 +154,7 @@ BEGIN
vpkLocalBuilder.init vpkLocalBuilder.init
ELSIF local THEN ELSIF local THEN
Out.String("Building local project from: "); Out.String(localFile); Out.Ln; Out.String("Building local project from: "); Out.String(localFile); Out.Ln;
vpkLocalBuilder.buildLocal(localFile, withDeps) vpkLocalBuilder.buildLocal(localFile)
ELSIF sync THEN ELSIF sync THEN
vpkSyncer.sync vpkSyncer.sync
ELSE ELSE
@ -187,4 +175,4 @@ END main;
BEGIN BEGIN
main main
END vipak. END vipak.

View file

@ -8,6 +8,7 @@ VAR
h: http.Client; h: http.Client;
answer: strTypes.pstring; answer: strTypes.pstring;
domain, path: ARRAY 128 OF CHAR; port: ARRAY 8 OF CHAR; domain, path: ARRAY 128 OF CHAR; port: ARRAY 8 OF CHAR;
repoPath: ARRAY 256 OF CHAR; (* Added for full repository path *)
filename: ARRAY 64 OF CHAR; filename: ARRAY 64 OF CHAR;
i, j: LONGINT; i, j: LONGINT;
node: List.Node; node: List.Node;
@ -25,12 +26,19 @@ BEGIN
IF node^.obj(vpkdepTree.File) # NIL THEN IF node^.obj(vpkdepTree.File) # NIL THEN
Out.String("getting "); Out.String(node^.obj(vpkdepTree.File)^.URI); Out.Ln; Out.String("getting "); Out.String(node^.obj(vpkdepTree.File)^.URI); Out.Ln;
(* Extract domain for connection *)
vpkTools.extractDomainFromUrl(node^.obj(vpkdepTree.File)^.URI, domain); vpkTools.extractDomainFromUrl(node^.obj(vpkdepTree.File)^.URI, domain);
Out.String("connecting to "); Out.String(domain); Out.Ln; Out.String("connecting to "); Out.String(domain); Out.Ln;
(* Extract full repository path for directory structure *)
vpkTools.extractRepoPathFromUrl(node^.obj(vpkdepTree.File)^.URI, repoPath);
Out.String("repo path: "); Out.String(repoPath); Out.Ln;
vpkTools.extractPathFromUrl(node^.obj(vpkdepTree.File)^.URI, path); vpkTools.extractPathFromUrl(node^.obj(vpkdepTree.File)^.URI, path);
vpkTools.extractFilenameFromUrl(node^.obj(vpkdepTree.File)^.URI, filename); vpkTools.extractFilenameFromUrl(node^.obj(vpkdepTree.File)^.URI, filename);
vpkEnv.mkPkgDirPath(domain, dep^.name^, dst); (* Use full repository path instead of just domain *)
vpkEnv.mkPkgDirPath(repoPath, dep^.name^, dst);
j := Platform.Chdir(dst); j := Platform.Chdir(dst);
@ -65,4 +73,4 @@ BEGIN
END fetchFiles; END fetchFiles;
END vpkHttp. END vpkHttp.

View file

@ -8,12 +8,14 @@ VAR
h: https.TLSClient; h: https.TLSClient;
answer: strTypes.pstring; answer: strTypes.pstring;
domain, path: ARRAY 128 OF CHAR; port: ARRAY 8 OF CHAR; domain, path: ARRAY 128 OF CHAR; port: ARRAY 8 OF CHAR;
repoPath: ARRAY 256 OF CHAR; (* Added for full repository path *)
filename: ARRAY 64 OF CHAR; filename: ARRAY 64 OF CHAR;
i, j: LONGINT; i, j: LONGINT;
node: List.Node; node: List.Node;
bool, continueFetching: BOOLEAN; bool, continueFetching: BOOLEAN;
initialDst: ARRAY 512 OF CHAR; initialDst: ARRAY 512 OF CHAR;
BEGIN BEGIN
Out.String("*** HTTPS: fetchFiles called"); Out.Ln;
COPY(dst, initialDst); COPY(dst, initialDst);
COPY("443", port); COPY("443", port);
i := 0; i := 0;
@ -25,12 +27,19 @@ BEGIN
IF node^.obj(vpkdepTree.File) # NIL THEN IF node^.obj(vpkdepTree.File) # NIL THEN
Out.String("getting "); Out.String(node^.obj(vpkdepTree.File)^.URI); Out.Ln; Out.String("getting "); Out.String(node^.obj(vpkdepTree.File)^.URI); Out.Ln;
(* Extract domain for connection *)
vpkTools.extractDomainFromUrl(node^.obj(vpkdepTree.File)^.URI, domain); vpkTools.extractDomainFromUrl(node^.obj(vpkdepTree.File)^.URI, domain);
Out.String("connecting to "); Out.String(domain); Out.Ln; Out.String("connecting to "); Out.String(domain); Out.Ln;
(* Extract full repository path for directory structure *)
vpkTools.extractRepoPathFromUrl(node^.obj(vpkdepTree.File)^.URI, repoPath);
Out.String("repo path: "); Out.String(repoPath); Out.Ln;
vpkTools.extractPathFromUrl(node^.obj(vpkdepTree.File)^.URI, path); vpkTools.extractPathFromUrl(node^.obj(vpkdepTree.File)^.URI, path);
vpkTools.extractFilenameFromUrl(node^.obj(vpkdepTree.File)^.URI, filename); vpkTools.extractFilenameFromUrl(node^.obj(vpkdepTree.File)^.URI, filename);
vpkEnv.mkPkgDirPath(domain, dep^.name^, dst); (* Use full repository path - DO NOT add package name again *)
vpkEnv.mkPkgDirPath(repoPath, dep^.name^, dst);
j := Platform.Chdir(dst); j := Platform.Chdir(dst);

View file

@ -47,14 +47,23 @@ VAR
depTree: vpkdepTree.TdepTree; depTree: vpkdepTree.TdepTree;
dep: vpkdepTree.Tdep; dep: vpkdepTree.Tdep;
i: LONGINT; i: LONGINT;
builddir: StringList.pstring;
BEGIN BEGIN
(* Create build directory path *)
IF prefix # "" THEN
builddir := vpkEnv.mkBldDir(prefix)
ELSE
builddir := vpkEnv.mkdefBldDir();
END;
depTree := resolve(package); depTree := resolve(package);
IF a THEN ask END; IF a THEN ask END;
i := 0; i := 0;
REPEAT REPEAT
dep := vpkdepTree.Get(depTree, i); dep := vpkdepTree.Get(depTree, i);
vpkJsonDepRetriever.getURIandType(dep); vpkJsonDepRetriever.getURIandType(dep);
vpkSyncer.fetch(dep, prefix); (* Pass build directory instead of prefix *)
vpkSyncer.fetch(dep, builddir^);
INC(i) INC(i)
UNTIL i = depTree.Count; UNTIL i = depTree.Count;
END fetch; END fetch;
@ -69,7 +78,7 @@ VAR
b: BOOLEAN; b: BOOLEAN;
builddir, cmd, srcPath: StringList.pstring; builddir, cmd, srcPath: StringList.pstring;
res: INTEGER; res: INTEGER;
domain: ARRAY 256 OF CHAR; repoPath: ARRAY 256 OF CHAR; (* Changed from domain to repoPath *)
node: List.Node; node: List.Node;
BEGIN BEGIN
IF prefix # "" THEN IF prefix # "" THEN
@ -83,12 +92,13 @@ BEGIN
REPEAT REPEAT
dep := vpkdepTree.Get(depTree, i); dep := vpkdepTree.Get(depTree, i);
vpkJsonDepRetriever.getURIandType(dep); vpkJsonDepRetriever.getURIandType(dep);
vpkSyncer.fetch(dep, prefix); (* Pass build directory instead of prefix *)
vpkSyncer.fetch(dep, builddir^);
b := FALSE; b := FALSE;
b := vpkJsonDepRetriever.getBuildInfo(dep, keys, values); b := vpkJsonDepRetriever.getBuildInfo(dep, keys, values);
IF b THEN IF b THEN
Out.String("Build info found for the package: "); Out.String(dep.name^); Out.Ln; Out.String("Build info found for the package: "); Out.String(dep.name^); Out.Ln;
(* Ensure keys and values are not NIL *) (* Ensure keys and values are not NIL *)
IF keys = NIL THEN IF keys = NIL THEN
Out.String("Error: keys list is NIL."); Out.Ln; Out.String("Error: keys list is NIL."); Out.Ln;
@ -98,17 +108,18 @@ BEGIN
Out.String("Error: values list is NIL."); Out.Ln; Out.String("Error: values list is NIL."); Out.Ln;
HALT(10); HALT(10);
END; END;
Out.String("keys.Count = "); Out.Int(keys.Count, 0); Out.Ln; Out.String("keys.Count = "); Out.Int(keys.Count, 0); Out.Ln;
Out.String("values.Count = "); Out.Int(values.Count, 0); Out.Ln; Out.String("values.Count = "); Out.Int(values.Count, 0); Out.Ln;
j := 0; j := 0;
REPEAT REPEAT
Out.String("Processing build step "); Out.Int(j, 0); Out.Ln; Out.String("Processing build step "); Out.Int(j, 0); Out.Ln;
IF dep^.rmt IS vpkdepTree.RemoteGit THEN IF dep^.rmt IS vpkdepTree.RemoteGit THEN
vpkTools.extractDomainFromUrl(dep^.rmt.URI, domain); (* Use extractRepoPathFromUrl instead of extractDomainFromUrl *)
vpkTools.extractRepoPathFromUrl(dep^.rmt.URI, repoPath);
ELSIF dep^.rmt IS vpkdepTree.RemoteHttps THEN ELSIF dep^.rmt IS vpkdepTree.RemoteHttps THEN
node := dep^.rmt(vpkdepTree.RemoteHttps)^.Files.Get(dep^.rmt(vpkdepTree.RemoteHttps)^.Files, j); node := dep^.rmt(vpkdepTree.RemoteHttps)^.Files.Get(dep^.rmt(vpkdepTree.RemoteHttps)^.Files, j);
vpkTools.extractDomainFromUrl(node^.obj(vpkdepTree.File)^.URI, domain) vpkTools.extractRepoPathFromUrl(node^.obj(vpkdepTree.File)^.URI, repoPath)
ELSE ELSE
Out.String("WARNING: building for neither git nor https sources not supported yet"); Out.Ln; Out.String("WARNING: building for neither git nor https sources not supported yet"); Out.Ln;
END; END;
@ -120,7 +131,8 @@ BEGIN
v := values.GetString(values, j); v := values.GetString(values, j);
Out.String("Got key: "); Out.String(k^); Out.Ln; Out.String("Got key: "); Out.String(k^); Out.Ln;
Out.String("Got value: "); Out.String(v^); Out.Ln; Out.String("Got value: "); Out.String(v^); Out.Ln;
srcPath := vpkEnv.getSrcRelPath(dep.name^, domain, v^); (* Use repoPath instead of domain, and deps/ prefix to reflect new structure *)
srcPath := vpkEnv.getSrcRelPath(dep.name^, repoPath, v^);
cmd := vpkEnv.mkCmd(k^, srcPath^); cmd := vpkEnv.mkCmd(k^, srcPath^);
Out.String("Command: "); Out.String(cmd^); Out.Ln; Out.String("Command: "); Out.String(cmd^); Out.Ln;
Out.String("Building in "); Out.String(builddir^); Out.Ln; Out.String("Building in "); Out.String(builddir^); Out.Ln;

View file

@ -2,7 +2,7 @@ MODULE vpkLocalBuilder;
IMPORT Files, Out, Strings, Platform, In, IMPORT Files, Out, Strings, Platform, In,
Json, StringList, strUtils, Json, StringList, strUtils,
vpkStorage, vpkSettings, vpkdepTree, vpkInstaller, vpkEnv, vpkJsonDepRetriever, vpkStorage, vpkSettings, vpkdepTree, vpkInstaller, vpkEnv, vpkJsonDepRetriever,
UnixFS; vpkResolver, vpkSyncer, vpkDot, vpkTools, UnixFS;
CONST CONST
DefaultProjectFile = "vipak.json"; DefaultProjectFile = "vipak.json";
@ -45,7 +45,7 @@ BEGIN
COPY("src/", filename); COPY("src/", filename);
Strings.Append(projectName, filename); Strings.Append(projectName, filename);
Strings.Append(".Mod", filename); Strings.Append(".Mod", filename);
(* Create template module content *) (* Create template module content *)
COPY("MODULE ", content); COPY("MODULE ", content);
Strings.Append(projectName, content); Strings.Append(projectName, content);
@ -96,7 +96,7 @@ VAR
BEGIN BEGIN
(* Use a simple default project name *) (* Use a simple default project name *)
COPY("myproject", projectName); COPY("myproject", projectName);
(* Create default JSON content *) (* Create default JSON content *)
COPY('{', content); COPY('{', content);
Strings.Append(eol, content); Strings.Append(eol, content);
@ -265,12 +265,117 @@ BEGIN
RETURN TRUE; RETURN TRUE;
END createBuildDir; END createBuildDir;
PROCEDURE buildDependencies(VAR projectFile: ARRAY OF CHAR); PROCEDURE resolveLocal(VAR projectFile: ARRAY OF CHAR): vpkdepTree.TdepTree;
VAR
localDep: vpkdepTree.Tdep;
depsList: StringList.TStringList;
depName: StringList.pstring;
combinedTree, subTree: vpkdepTree.TdepTree;
currentDep: vpkdepTree.Tdep;
i, j: LONGINT;
found: BOOLEAN;
graphName: ARRAY 32 OF CHAR;
lst: StringList.TStringList;
localName: ARRAY 16 OF CHAR;
BEGIN BEGIN
(* For now, skip dependency building in local mode *) Out.Ln; Out.String("resolving dependencies for local project..."); Out.Ln;
(* This can be implemented later when the infrastructure is ready *)
Out.String("Dependency building for local projects not yet implemented."); Out.Ln; (* Set the local project file for dependency reading *)
Out.String("Please build dependencies manually using 'vipak -p <package>'"); Out.Ln; vpkJsonDepRetriever.setLocalProjectFile(projectFile);
(* Create a dummy dependency object to read dependencies from local file *)
COPY("local-project", localName);
localDep := vpkdepTree.CreateDep(localName);
(* Create combined dependency tree *)
combinedTree := vpkdepTree.Create();
(* Get direct dependencies from the local project file *)
IF vpkJsonDepRetriever.getDepsFromFile(localDep, depsList) > 0 THEN
Out.String("Found "); Out.Int(depsList.Count, 0); Out.String(" direct dependencies"); Out.Ln;
(* Resolve each dependency using normal tree-based resolution *)
i := 0;
REPEAT
depName := depsList.GetString(depsList, i);
IF depName # NIL THEN
Out.String("Resolving: "); Out.String(depName^); Out.Ln;
(* Use normal vpkResolver.resolve for this dependency (it's in the tree) *)
subTree := vpkResolver.resolve(depName^, vpkJsonDepRetriever.getDeps);
(* Merge this subtree into combined tree (avoiding duplicates) *)
j := 0;
REPEAT
currentDep := vpkdepTree.Get(subTree, j);
IF currentDep # NIL THEN
(* Check if this dependency is already in combined tree *)
found := (combinedTree.GetByName(combinedTree, currentDep.name^) # NIL);
IF ~found THEN
vpkdepTree.AddCopy(combinedTree, currentDep);
END;
END;
INC(j);
UNTIL j = subTree.Count;
END;
INC(i);
UNTIL i = depsList.Count;
Out.String(" done! (:"); Out.Ln; Out.Ln;
(* Show dependency graph like normal vipak *)
vpkEnv.getGraphName(graphName);
lst := vpkDot.tree2dot(combinedTree);
Out.String("dependency graph:"); Out.Ln;
Out.String("-----------------"); Out.Ln;
StringList.DumpOut(lst);
lst.Dump(lst, graphName);
Out.String("-----------------"); Out.Ln;
Out.String("(use 'dot -Tpng deps.dot > deps.png' to get the graph image)"); Out.Ln; Out.Ln;
Out.String("dependencies will be installed in the following order:"); Out.Ln;
i := 0;
REPEAT
currentDep := vpkdepTree.Get(combinedTree, i);
IF currentDep # NIL THEN
Out.String(currentDep.name^); Out.Ln;
END;
INC(i);
UNTIL i = combinedTree.Count;
ELSE
Out.String("No dependencies found in project file."); Out.Ln;
END;
RETURN combinedTree;
END resolveLocal;
PROCEDURE buildDependencies(VAR projectFile: ARRAY OF CHAR);
VAR
depTree: vpkdepTree.TdepTree;
currentDep: vpkdepTree.Tdep;
i: LONGINT;
buildDir: ARRAY 128 OF CHAR;
BEGIN
(* Resolve all dependencies for local project *)
depTree := resolveLocal(projectFile);
IF depTree.Count > 0 THEN
(* Fetch all resolved dependencies *)
COPY("./", buildDir);
Strings.Append(DefaultBuildDir, buildDir);
i := 0;
REPEAT
currentDep := vpkdepTree.Get(depTree, i);
IF currentDep # NIL THEN
Out.String("Fetching: "); Out.String(currentDep.name^); Out.Ln;
vpkJsonDepRetriever.getURIandType(currentDep);
vpkSyncer.fetch(currentDep, buildDir);
END;
INC(i);
UNTIL i = depTree.Count;
Out.String("All dependencies fetched successfully!"); Out.Ln;
END;
END buildDependencies; END buildDependencies;
PROCEDURE buildProject(VAR projectFile: ARRAY OF CHAR; info: ProjectInfo): BOOLEAN; PROCEDURE buildProject(VAR projectFile: ARRAY OF CHAR; info: ProjectInfo): BOOLEAN;
@ -285,13 +390,13 @@ VAR
BEGIN BEGIN
(* Create a dummy dependency object for build info extraction *) (* Create a dummy dependency object for build info extraction *)
dep := vpkdepTree.CreateDep(info.name); dep := vpkdepTree.CreateDep(info.name);
(* Get build information using the procedure from vpkJsonDepRetriever *) (* Get build information using the procedure from vpkJsonDepRetriever *)
b := vpkJsonDepRetriever.getBuildInfoFromFile(dep, keys, values, projectFile); b := vpkJsonDepRetriever.getBuildInfoFromFile(dep, keys, values, projectFile);
IF b & (keys # NIL) & (values # NIL) THEN IF b & (keys # NIL) & (values # NIL) THEN
Out.String("Building project: "); Out.String(info.name); Out.Ln; Out.String("Building project: "); Out.String(info.name); Out.Ln;
(* Change to build directory *) (* Change to build directory *)
COPY(DefaultBuildDir, buildDirVar); COPY(DefaultBuildDir, buildDirVar);
res := Platform.Chdir(buildDirVar); res := Platform.Chdir(buildDirVar);
@ -299,18 +404,18 @@ BEGIN
Out.String("Failed to change to build directory"); Out.Ln; Out.String("Failed to change to build directory"); Out.Ln;
RETURN FALSE; RETURN FALSE;
END; END;
(* Execute build commands *) (* Execute build commands *)
i := 0; i := 0;
REPEAT REPEAT
k := keys.GetString(keys, i); k := keys.GetString(keys, i);
v := values.GetString(values, i); v := values.GetString(values, i);
(* Create command: copy from parent directory if needed *) (* Create command: copy from parent directory if needed *)
COPY(k^, cmd); COPY(k^, cmd);
Strings.Append(" ../", cmd); Strings.Append(" ../", cmd);
Strings.Append(v^, cmd); Strings.Append(v^, cmd);
Out.String("Executing: "); Out.String(cmd); Out.Ln; Out.String("Executing: "); Out.String(cmd); Out.Ln;
res := Platform.System(cmd); res := Platform.System(cmd);
IF res # 0 THEN IF res # 0 THEN
@ -321,7 +426,7 @@ BEGIN
END; END;
INC(i); INC(i);
UNTIL i = keys.Count; UNTIL i = keys.Count;
(* Restore original directory *) (* Restore original directory *)
COPY("..", buildDirVar); COPY("..", buildDirVar);
res := Platform.Chdir(buildDirVar); res := Platform.Chdir(buildDirVar);
@ -333,7 +438,7 @@ BEGIN
END; END;
END buildProject; END buildProject;
PROCEDURE buildLocal*(VAR projectFile: ARRAY OF CHAR; withDeps: BOOLEAN); PROCEDURE buildLocal*(VAR projectFile: ARRAY OF CHAR);
VAR VAR
info: ProjectInfo; info: ProjectInfo;
b: BOOLEAN; b: BOOLEAN;
@ -344,27 +449,27 @@ BEGIN
Out.String("Create one with 'vipak --init'"); Out.Ln; Out.String("Create one with 'vipak --init'"); Out.Ln;
HALT(1); HALT(1);
END; END;
(* Parse project file *) (* Parse project file *)
b := parseProjectFile(projectFile, info); b := parseProjectFile(projectFile, info);
IF ~b THEN IF ~b THEN
Out.String("Failed to parse project file: "); Out.String(projectFile); Out.Ln; Out.String("Failed to parse project file: "); Out.String(projectFile); Out.Ln;
HALT(1); HALT(1);
END; END;
Out.String("Building project: "); Out.String(info.name); Out.String("Building project: "); Out.String(info.name);
Out.String(" v"); Out.String(info.version); Out.Ln; Out.String(" v"); Out.String(info.version); Out.Ln;
(* Create build directory *) (* Create build directory *)
IF ~createBuildDir() THEN IF ~createBuildDir() THEN
HALT(1); HALT(1);
END; END;
(* Build dependencies if requested and available *) (* Build dependencies if available - default behavior for local projects *)
IF withDeps & info.hasDeps THEN IF info.hasDeps THEN
buildDependencies(projectFile); buildDependencies(projectFile);
END; END;
(* Build the project itself *) (* Build the project itself *)
IF info.hasBuild THEN IF info.hasBuild THEN
b := buildProject(projectFile, info); b := buildProject(projectFile, info);
@ -386,11 +491,11 @@ BEGIN
Out.String("Project file already exists: "); Out.String(projectFile); Out.Ln; Out.String("Project file already exists: "); Out.String(projectFile); Out.Ln;
HALT(1); HALT(1);
END; END;
COPY("myproject", projectName); COPY("myproject", projectName);
createDefaultProject(projectFile); createDefaultProject(projectFile);
createTemplateModule(projectName); createTemplateModule(projectName);
Out.Ln; Out.Ln;
Out.String("Project initialized! You can now:"); Out.Ln; Out.String("Project initialized! You can now:"); Out.Ln;
Out.String(" 1. Edit src/"); Out.String(projectName); Out.String(".Mod with your code"); Out.Ln; Out.String(" 1. Edit src/"); Out.String(projectName); Out.String(".Mod with your code"); Out.Ln;
@ -400,4 +505,4 @@ END init;
BEGIN BEGIN
eol[0] := 0AX; eol[1] := 0X; (* Unix line ending *) eol[0] := 0AX; eol[1] := 0X; (* Unix line ending *)
END vpkLocalBuilder. END vpkLocalBuilder.

View file

@ -24,10 +24,14 @@ BEGIN
END sync; END sync;
PROCEDURE fetch*(VAR dep: vpkdepTree.Tdep; dst: ARRAY OF CHAR); PROCEDURE fetch*(VAR dep: vpkdepTree.Tdep; dst: ARRAY OF CHAR);
VAR domain: ARRAY 64 OF CHAR; VAR repoPath: ARRAY 256 OF CHAR;
workingDst: ARRAY 512 OF CHAR; (* Local copy to modify *)
BEGIN BEGIN
Out.String("Starting fetch process..."); Out.Ln; Out.String("*** SYNCER: Starting fetch process..."); Out.Ln;
Out.String("Destination: "); Out.String(dst); Out.Ln; Out.String("*** SYNCER: Input destination: '"); Out.String(dst); Out.String("'"); Out.Ln;
COPY(dst, workingDst); (* Make a local copy to modify *)
Out.String("*** SYNCER: Working destination: '"); Out.String(workingDst); Out.String("'"); Out.Ln;
IF dep = NIL THEN IF dep = NIL THEN
Out.String("Dependency is NIL"); Out.Ln; Out.String("Dependency is NIL"); Out.Ln;
HALT(1); HALT(1);
@ -37,33 +41,42 @@ BEGIN
HALT(5); HALT(5);
ELSE ELSE
IF dep^.rmt IS vpkdepTree.RemoteGit THEN IF dep^.rmt IS vpkdepTree.RemoteGit THEN
Out.String("Remote type is Git"); Out.Ln; Out.String("*** SYNCER: Remote type is Git"); Out.Ln;
vpkTools.extractDomainFromUrl(dep^.rmt^.URI, domain); Out.String("*** SYNCER: Package name is: '"); Out.String(dep^.name^); Out.String("'"); Out.Ln;
Out.String("Extracted domain: "); Out.String(domain); Out.Ln; Out.String("*** SYNCER: Remote URI is: '"); Out.String(dep^.rmt^.URI); Out.String("'"); Out.Ln;
(* dst is changed by mkdefPkgDirPath and mkPkgdirPath *)
IF dst = "" THEN vpkTools.extractRepoPathFromUrl(dep^.rmt^.URI, repoPath);
vpkEnv.mkdefPkgDirPath(domain, dep^.name^, dst); Out.String("*** SYNCER: Extracted repo path: '"); Out.String(repoPath); Out.String("'"); Out.Ln;
Out.String("*** SYNCER: About to call mkPkgDirPath with:"); Out.Ln;
Out.String("*** repoPath = '"); Out.String(repoPath); Out.String("'"); Out.Ln;
Out.String("*** name = '"); Out.String(dep^.name^); Out.String("'"); Out.Ln;
Out.String("*** workingDst = '"); Out.String(workingDst); Out.String("'"); Out.Ln;
(* Build the proper destination path *)
IF Strings.Length(workingDst) = 0 THEN
vpkEnv.mkdefPkgDirPath(repoPath, dep^.name^, workingDst);
ELSE ELSE
vpkEnv.mkPkgDirPath(domain, dep^.name^, dst); vpkEnv.mkPkgDirPath(repoPath, dep^.name^, workingDst);
END; END;
Out.String("Final destination path: "); Out.String(dst); Out.Ln;
Out.String("Fetching repository..."); Out.Ln; Out.String("*** SYNCER: After mkPkgDirPath, workingDst = '"); Out.String(workingDst); Out.String("'"); Out.Ln;
vpkGit.fetchRepo(dep^.rmt^.URI, dst, dep^.rmt(vpkdepTree.RemoteGit).branch); Out.String("*** SYNCER: About to call git with destination: '"); Out.String(workingDst); Out.String("'"); Out.Ln;
vpkGit.fetchRepo(dep^.rmt^.URI, workingDst, dep^.rmt(vpkdepTree.RemoteGit).branch);
ELSIF dep^.rmt IS vpkdepTree.RemoteHttps THEN ELSIF dep^.rmt IS vpkdepTree.RemoteHttps THEN
Out.String("Remote type is HTTPS"); Out.Ln; Out.String("Remote type is HTTPS"); Out.Ln;
(* full dst will be determined in vpkHttps.fetchFiles for each file *) vpkHttps.fetchFiles(dep, workingDst);
vpkHttps.fetchFiles(dep, dst);
ELSIF dep^.rmt IS vpkdepTree.RemoteHttp THEN ELSIF dep^.rmt IS vpkdepTree.RemoteHttp THEN
Out.String("Remote type is HTTP"); Out.Ln; Out.String("Remote type is HTTP"); Out.Ln;
(* full dst will be determined in vpkHttps.fetchFiles for each file *) vpkHttp.fetchFiles(dep, workingDst);
vpkHttp.fetchFiles(dep, dst);
ELSE ELSE
Out.String("TODO: neither git nor https url"); Out.Ln; Out.String("TODO: neither git nor https url"); Out.Ln;
Out.String("not handled"); Out.String("not handled");
Out.Ln; Out.Ln;
END; END;
END; END;
Out.String("Fetch process completed."); Out.Ln; Out.String("*** SYNCER: Fetch process completed."); Out.Ln;
END fetch; END fetch;
END vpkSyncer. END vpkSyncer.

View file

@ -1,5 +1,5 @@
MODULE vpkTools; MODULE vpkTools;
IMPORT Strings, strUtils; IMPORT Strings, strUtils, Out;
PROCEDURE extractDomainFromUrl*(VAR url: ARRAY OF CHAR; VAR domain: ARRAY OF CHAR); PROCEDURE extractDomainFromUrl*(VAR url: ARRAY OF CHAR; VAR domain: ARRAY OF CHAR);
@ -78,5 +78,63 @@ BEGIN
END; END;
END extractFilenameFromUrl; END extractFilenameFromUrl;
PROCEDURE extractRepoPathFromUrl*(VAR url: ARRAY OF CHAR; VAR repoPath: ARRAY OF CHAR);
(* Extracts full repository path from URL like:
https://github.com/norayr/strutils -> github.com/norayr/strutils
https://codeberg.org/user/project -> codeberg.org/user/project
*)
VAR
start, i, j: INTEGER;
found: BOOLEAN;
BEGIN
Out.String("@@@ extractRepoPathFromUrl input: '"); Out.String(url); Out.String("'"); Out.Ln;
start := 0;
found := FALSE;
repoPath[0] := 0X; (* Initialize to empty string *)
(* Find the "://" pattern to skip protocol *)
WHILE (start < LEN(url) - 2) & (url[start] # 0X) & ~found DO
IF (url[start] = ':') & (url[start+1] = '/') & (url[start+2] = '/') THEN
found := TRUE;
start := start + 3; (* Skip "://" *)
ELSE
INC(start);
END;
END;
Out.String("@@@ After skipping protocol, start="); Out.Int(start, 0); Out.Ln;
IF ~found THEN
(* No protocol found, assume the whole URL is the path *)
COPY(url, repoPath);
Out.String("@@@ No protocol found, using whole URL: '"); Out.String(repoPath); Out.String("'"); Out.Ln;
RETURN;
END;
(* Find end of URL (exclude .git suffix if present) *)
i := start;
WHILE (i < LEN(url)) & (url[i] # 0X) DO
INC(i);
END;
Out.String("@@@ End of URL at position: "); Out.Int(i, 0); Out.Ln;
(* Remove .git suffix if present *)
IF (i >= 4) & (url[i-4] = '.') & (url[i-3] = 'g') & (url[i-2] = 'i') & (url[i-1] = 't') THEN
i := i - 4;
Out.String("@@@ Removed .git suffix, new end: "); Out.Int(i, 0); Out.Ln;
END;
(* Copy domain + path *)
j := 0;
WHILE (start < i) & (j < LEN(repoPath) - 1) DO
repoPath[j] := url[start];
INC(j); INC(start);
END;
repoPath[j] := 0X;
Out.String("@@@ extractRepoPathFromUrl output: '"); Out.String(repoPath); Out.String("'"); Out.Ln;
END extractRepoPathFromUrl;
END vpkTools. END vpkTools.