Skip to content

Commit f0d75b0

Browse files
authored
Merge pull request bakaq#44 from jjtolton/main
Fix relative path resolution for pkg() imports in subdirectories
2 parents c65a457 + 478d9fa commit f0d75b0

File tree

8 files changed

+120
-4
lines changed

8 files changed

+120
-4
lines changed

bakage.pl

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
:- use_module(library(os), [argv/1, setenv/2, shell/1, unsetenv/1, getenv/2]).
2828
:- use_module(library(files), [
2929
directory_exists/1, make_directory_path/1, directory_files/2, file_exists/1,
30-
delete_file/1, delete_directory/1
30+
delete_file/1, delete_directory/1, working_directory/2
3131
]).
3232
:- use_module(library(dcgs), [phrase/2, phrase/3, ... //0]). % 13211-3
3333
:- use_module(library(charsio), [write_term_to_chars/3]).
@@ -356,10 +356,78 @@
356356
define_script_arg(Arg-Value) :- setenv(Arg, Value).
357357
undefine_script_arg(Arg-_) :- unsetenv(Arg).
358358

359+
% join_sep_split/3: Monotonic join and split by separator.
360+
% Implementation by @bakaq from https://github.com/mthom/scryer-prolog/discussions/3121
361+
%
362+
% True when `Joined` is a list consisting of all the lists in `Segments`
363+
% separated by `Separator`, and `Separator` doesn't appear in any of the
364+
% lists in `Segments`. Can be used as both a split and a join depending
365+
% on the mode.
366+
join_sep_split(Joined, Separator, Segments) :-
367+
join_sep_split_(Separator, Joined, Segments).
368+
369+
% The empty separator case is just append/2
370+
join_sep_split_([], Joined, Segments) :-
371+
append(Segments, Joined).
372+
join_sep_split_([S|Ss], Joined, Segments) :-
373+
join_sep_split(Joined, [], [S|Ss], Segments, []).
374+
375+
% Stuff like this that needs 2 list differences is hard to encode
376+
% in a DCG in my experience.
377+
join_sep_split([], [], _, [], []).
378+
join_sep_split([L0|LT0], Ls, Sep, [Seg|Segs0], Segs) :-
379+
Ls0 = [L0|LT0],
380+
next_segment(Ls0, Seg, Sep, Ls1, Reason),
381+
join_sep_split_(Ls1, Ls, Sep, Segs0, Segs, Reason).
382+
383+
join_sep_split_([], [], _, Segs0, Segs, Reason) :-
384+
reason_segs(Reason, Segs0, Segs).
385+
join_sep_split_([L0|LT0], Ls, Sep, Segs0, Segs, _) :-
386+
join_sep_split([L0|LT0], Ls, Sep, Segs0, Segs).
387+
388+
reason_segs(sep, [[]|Segs], Segs).
389+
reason_segs(end, Segs, Segs).
390+
391+
next_segment([], [], _, [], end).
392+
next_segment([L0|Ls0], Seg, Sep, Ls, Reason) :-
393+
if_(
394+
starts_with_t(Sep, [L0|Ls0], Ls1),
395+
(Ls = Ls1, Seg = [], Reason = sep),
396+
(Seg = [L0|Seg1], next_segment(Ls0, Seg1, Sep, Ls, Reason))
397+
).
398+
399+
starts_with_t([], Ls, Ls, true).
400+
starts_with_t([S|Ss], Ls0, Ls, T) :-
401+
starts_with_t_(Ls0, Ls, S, Ss, T).
402+
403+
starts_with_t_([], _, _, _, false).
404+
starts_with_t_([L|Ls0], Ls, S, Ss, T) :-
405+
if_(
406+
S = L,
407+
starts_with_t(Ss, Ls0, Ls, T),
408+
T = false
409+
).
410+
411+
find_project_root(Root) :-
412+
working_directory(CWD, CWD),
413+
find_project_root_from(CWD, Root).
414+
415+
find_project_root_from(Dir, Root) :-
416+
append(Dir, "/scryer-manifest.pl", ManifestPath),
417+
( file_exists(ManifestPath) ->
418+
Root = Dir
419+
; join_sep_split(Dir, "/", Segments),
420+
append(ParentSegments, [_LastSegment], Segments),
421+
ParentSegments \= [],
422+
join_sep_split(ParentDir, "/", ParentSegments),
423+
find_project_root_from(ParentDir, Root)
424+
).
425+
359426
scryer_path(ScryerPath) :-
360-
( getenv("SCRYER_PATH", ScryerPath) ->
361-
true
362-
; ScryerPath = "scryer_libs"
427+
( getenv("SCRYER_PATH", EnvPath) ->
428+
ScryerPath = EnvPath
429+
; find_project_root(RootChars),
430+
append([RootChars, "/scryer_libs"], ScryerPath)
363431
).
364432

365433
% the message sent to the user when a dependency is malformed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
:- module(my_module, [greet/1]).
2+
3+
greet(Name) :-
4+
write('Hello, '),
5+
write(Name),
6+
write('!'), nl.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
name("bakage-repro").
2+
3+
dependencies([
4+
dependency("testing", git("https://github.com/bakaq/testing.pl.git"))
5+
]).
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
:- use_module('../../../../../bakage.pl').
2+
:- use_module(pkg(testing)).
3+
:- use_module('../my_module.pl').
4+
5+
test("greet succeeds", (
6+
greet('World')
7+
)).
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/sh
2+
3+
bakage() {
4+
../../../../bakage.pl "$@"
5+
}
6+
7+
echo "=== Installing dependencies ==="
8+
bakage install
9+
10+
echo ""
11+
echo "=== Running test from project root ==="
12+
scryer-prolog tests/test_my_module.pl -g "run_tests, halt."
13+
14+
echo ""
15+
echo "=== Running test from subdirectory ==="
16+
cd tests
17+
scryer-prolog test_my_module.pl -g "run_tests, halt."
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0

tests/snapshot/cases/subdirectory_imports.stderr

Whitespace-only changes.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
=== Installing dependencies ===
2+
Ensuring is installed: git("https://github.com/bakaq/testing.pl.git")
3+
4+
=== Running test from project root ===
5+
Running tests in module user.
6+
test "greet succeeds" ... Hello, World!
7+
succeeded
8+
9+
=== Running test from subdirectory ===
10+
Running tests in module user.
11+
test "greet succeeds" ... Hello, World!
12+
succeeded

0 commit comments

Comments
 (0)