Skip to content

Commit e784662

Browse files
committed
Add support for GLJPATH env var
This allows people to customize where glj looks for libraries at runtime.
1 parent d18fcaf commit e784662

File tree

4 files changed

+78
-25
lines changed

4 files changed

+78
-25
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ $ glj server.glj
125125
Server starting on :8080...
126126
```
127127

128+
### Environment Variables
129+
130+
Glojure recognizes the following environment variables:
131+
132+
- **`GLJPATH`**
133+
134+
Colon-separated list of directories to search for `.glj` libraries.
135+
This allows you to organize Glojure libraries in a custom manner.
136+
Note: Glojure will always search the current directory for `.glj` libraries.
137+
128138
### Embedding Glojure in Go Applications
129139

130140
You can also embed Glojure as a scripting language within your Go applications.

pkg/gljmain/gljmain.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ Options:
2626
-h, --help Show this help message
2727
--version Show version information
2828
29+
Environment Variables:
30+
GLJPATH PATH of directories for .glj libraries
31+
2932
Examples:
3033
glj # Start REPL
3134
glj -e "(+ 1 2)" # Evaluate expression
@@ -38,6 +41,9 @@ For more information, visit: https://github.com/glojurelang/glojure
3841
}
3942

4043
func Main(args []string) {
44+
// Add GLJPATH directories to load path if set
45+
runtime.AddLoadPathFromEnv(os.Getenv("GLJPATH"))
46+
4147
runtime.AddLoadPath(os.DirFS("."))
4248

4349
if len(args) == 0 {

pkg/runtime/rtcompat.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"io"
66
"io/fs"
7+
"os"
78
"reflect"
89
"strings"
910
"sync"
@@ -31,6 +32,24 @@ func AddLoadPath(fs fs.FS) {
3132
loadPath = append(loadPath, fs)
3233
}
3334

35+
// AddLoadPathFromEnv adds directories from an environment variable to the load
36+
// path. The environment variable should contain colon-separated paths.
37+
func AddLoadPathFromEnv(envVar string) {
38+
if envVar == "" {
39+
return
40+
}
41+
42+
paths := strings.Split(envVar, ":")
43+
for _, path := range paths {
44+
if path != "" {
45+
// Skip non-existent path directories
46+
if _, err := os.Stat(path); err == nil {
47+
AddLoadPath(os.DirFS(path))
48+
}
49+
}
50+
}
51+
}
52+
3453
// RT is a struct with methods that map to Clojure's RT class' static
3554
// methods. This approach is used to make translation of core.clj to
3655
// Glojure easier.

test/glojure/test_glojure/cli.glj

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@
3131
(first (str/split-lines out))
3232
(throw (Exception. (str "Failed to find glj bin: " err))))))
3333

34+
(deftest help-flag-test
35+
(test-that
36+
"glj --help flag works correctly"
37+
(let [[out err] (run-cli-cmd glj "--help")]
38+
(is (re-matches
39+
#"(?s).*Glojure v\d+\.\d+\.\d+.*Usage: glj.*Options:.*-e.*-h.*--help.*--version.*Examples:.*"
40+
out)
41+
"Command should output help information")
42+
(is (re-matches
43+
#"(?s).*Environment Variables:.*GLJPATH.*PATH of directories for \.glj libraries.*"
44+
out)
45+
"Help should document GLJPATH environment variable")
46+
(is (empty? err) "Command should not return an error"))))
47+
3448
(deftest e-flag-test
3549
(test-that
3650
"glj -e flag works correctly"
@@ -46,32 +60,36 @@
4660
"Command should output version")
4761
(is (empty? err) "Command should not return an error"))))
4862

49-
(deftest glojure-version-test
50-
(test-that
51-
"*glojure-version* should be set correctly"
52-
(let [[out err] (run-cli-cmd glj "-e" "*glojure-version*")]
53-
(is (= out "{:major 0, :minor 3, :incremental 0, :qualifier nil}\n")
54-
"Version should match expected format")
55-
(is (empty? err) "Command should not return an error"))))
56-
57-
(deftest help-flag-test
63+
(deftest gljpath-test
5864
(test-that
59-
"glj --help flag works correctly"
60-
(let [[out err] (run-cli-cmd glj "--help")]
61-
(is (re-matches
62-
#"(?s).*Glojure v0\.3\.0.*Usage: glj.*Options:.*-e.*-h.*--help.*--version.*Examples:.*"
63-
out)
64-
"Command should output help information")
65-
(is (empty? err) "Command should not return an error"))))
66-
67-
(deftest short-help-flag-test
68-
(test-that
69-
"glj -h flag works correctly"
70-
(let [[out err] (run-cli-cmd glj "-h")]
71-
(is (re-matches
72-
#"(?s).*Glojure v0\.3\.0.*Usage: glj.*Options:.*-e.*-h.*--help.*--version.*Examples:.*"
73-
out)
74-
"Command should output help information")
65+
"GLJPATH can load libraries from specified directories"
66+
(let [lib1-dir (str (os.Getenv "PWD") "/test_gljpath_priority1")
67+
lib2-dir (str (os.Getenv "PWD") "/test_gljpath_priority2")
68+
lib1-file (str lib1-dir "/conflict.glj")
69+
lib2-file (str lib2-dir "/conflict.glj")
70+
test-script (str (os.Getenv "PWD") "/test_gljpath_priority_script.glj")
71+
;; Create conflicting libraries with same name but different content
72+
_ (do
73+
(os.MkdirAll lib1-dir 0755)
74+
(os.MkdirAll lib2-dir 0755)
75+
(os.WriteFile lib1-file
76+
(str "(ns conflict)\n(defn version [] \"version 1\")")
77+
0644)
78+
(os.WriteFile lib2-file
79+
(str "(ns conflict)\n(defn version [] \"version 2\")")
80+
0644)
81+
(os.WriteFile test-script
82+
(str "(ns main)\n(use 'conflict)\n(println (version))")
83+
0644))
84+
;; Test that first directory in GLJPATH takes precedence
85+
[out err] (run-cli-cmd "sh" "-c"
86+
(str "GLJPATH=" lib1-dir ":" lib2-dir " " glj " " test-script))
87+
;; Cleanup
88+
_ (do
89+
(os.RemoveAll lib1-dir)
90+
(os.RemoveAll lib2-dir)
91+
(os.Remove test-script))]
92+
(is (= out "version 1\n") "First directory in GLJPATH should take precedence")
7593
(is (empty? err) "Command should not return an error"))))
7694

7795
(run-tests)

0 commit comments

Comments
 (0)