v: support multiple paths in VMODULES env variable (#7048)

pull/7052/head
Delyan Angelov 2020-11-30 19:31:37 +02:00 committed by GitHub
parent 376833aea7
commit b11d285680
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 109 additions and 19 deletions

View File

@ -37,10 +37,9 @@ enum HighlightTokenTyp {
const (
css_js_assets = ['doc.css', 'normalize.css', 'doc.js']
allowed_formats = ['md', 'markdown', 'json', 'text', 'stdout', 'html', 'htm']
exe_path = os.executable()
exe_dir = os.dir(exe_path)
res_path = os.join_path(exe_dir, 'vdoc-resources')
vexe_path = os.dir(@VEXE)
res_path = os.resource_abs_path('vdoc-resources')
vexe = pref.vexe_path()
vroot = os.dir(vexe)
html_content = '
<!DOCTYPE html>
<html lang="en">
@ -192,7 +191,9 @@ struct VdocHttpServerContext {
}
fn handle_http_connection(mut con net.TcpConn, ctx &VdocHttpServerContext) {
mut reader := io.new_buffered_reader(reader: io.make_reader(con))
mut reader := io.new_buffered_reader({
reader: io.make_reader(con)
})
first_line := reader.read_line() or {
send_http_response(mut con, 501, ctx.content_type, 'bad request')
return
@ -715,7 +716,7 @@ fn (mut cfg DocConfig) generate_docs_from_file() {
exit(1)
}
dir_path := if cfg.is_vlib {
vexe_path
vroot
} else if os.is_dir(cfg.input_path) {
cfg.input_path
} else {
@ -935,11 +936,11 @@ fn (cfg DocConfig) get_resource(name string, minify bool) string {
}
fn main() {
args := os.args[2..].clone()
if args.len == 0 || args[0] in ['help', '-h', '--help'] {
os.system('${@VEXE} help doc')
if os.args.len < 2 || '-h' in os.args || '--help' in os.args || os.args[1..] == ['doc', 'help'] {
os.system('$vexe help doc')
exit(0)
}
args := os.args[2..].clone()
mut cfg := DocConfig{
manifest: vmod.Manifest{
repo_url: ''
@ -1050,7 +1051,7 @@ fn main() {
if cfg.input_path.trim_right('/') == 'vlib' {
cfg.is_vlib = true
cfg.is_multi = true
cfg.input_path = os.join_path(vexe_path, 'vlib')
cfg.input_path = os.join_path(vroot, 'vlib')
} else if !is_path {
cfg.vprintln('Input "$cfg.input_path" is not a valid path. Looking for modules named "$cfg.input_path"...')
mod_path := doc.lookup_module(cfg.input_path) or {

View File

@ -1354,13 +1354,27 @@ pub fn temp_dir() string {
return path
}
fn default_vmodules_path() string {
return os.join_path(os.home_dir(), '.vmodules')
}
// vmodules_dir returns the path to a folder, where v stores its global modules.
pub fn vmodules_dir() string {
paths := vmodules_paths()
if paths.len > 0 {
return paths[0]
}
return os.default_vmodules_path()
}
// vmodules_paths returns a list of paths, where v looks up for modules.
// You can customize it through setting the environment variable VMODULES
pub fn vmodules_paths() []string {
mut path := os.getenv('VMODULES')
if path == '' {
path = os.join_path(os.home_dir(), '.vmodules')
path = os.default_vmodules_path()
}
return path
list := path.split(os.path_delimiter).map(it.trim_right(os.path_separator))
return list
}
// chmod change file access attributes of `path` to `mode`.

View File

@ -1,9 +1,10 @@
module doc
import os
import v.table
import v.parser
import v.ast
import os
import v.pref
// get_parent_mod - return the parent mod name, in dot format.
// It works by climbing up the folder hierarchy, until a folder,
@ -61,12 +62,17 @@ fn get_parent_mod(input_dir string) ?string {
}
pub fn lookup_module_with_path(mod string, base_path string) ?string {
vexe := pref.vexe_path()
vroot := os.dir(vexe)
mod_path := mod.replace('.', os.path_separator)
compile_dir := os.real_path(base_path)
modules_dir := os.join_path(compile_dir, 'modules', mod_path)
vlib_path := os.join_path(os.dir(@VEXE), 'vlib', mod_path)
vmodules_path := os.join_path(os.vmodules_dir(), mod_path)
paths := [modules_dir, vlib_path, vmodules_path]
vlib_path := os.join_path(vroot, 'vlib', mod_path)
mut paths := [modules_dir, vlib_path]
vmodules_paths := os.vmodules_paths()
for vmpath in vmodules_paths {
paths << os.join_path(vmpath, mod_path)
}
for path in paths {
if !os.exists(path) || os.is_dir_empty(path) {
continue

View File

@ -16,7 +16,7 @@ pub fn new_preferences() Preferences {
return p
}
pub fn (mut p Preferences) fill_with_defaults() {
fn (mut p Preferences) expand_lookup_paths() {
if p.vroot == '' {
// Location of all vlib files
p.vroot = os.dir(vexe_path())
@ -25,9 +25,19 @@ pub fn (mut p Preferences) fill_with_defaults() {
if p.lookup_path.len == 0 {
p.lookup_path = ['@vlib', '@vmodules']
}
for i, path in p.lookup_path {
p.lookup_path[i] = path.replace('@vlib', vlib_path).replace('@vmodules', default_module_path)
mut expanded_paths := []string{}
for path in p.lookup_path {
match path {
'@vlib' { expanded_paths << vlib_path }
'@vmodules' { expanded_paths << os.vmodules_paths() }
else { expanded_paths << path }
}
}
p.lookup_path = expanded_paths
}
pub fn (mut p Preferences) fill_with_defaults() {
p.expand_lookup_paths()
rpath := os.real_path(p.path)
if p.out_name == '' {
filename := os.file_name(rpath).trim_space()

View File

@ -0,0 +1,9 @@
import yyy
import xxx
import zzz
fn main() {
all := [xxx.f(), yyy.f(), zzz.f()]
println(all)
assert all == ['x','y','z']
}

View File

@ -0,0 +1,4 @@
## this folder is the first one that will be put in vmodules.
## V uses that to put there its cache too.
## Just ignore it for now.
cache/

View File

@ -0,0 +1,4 @@
module xxx
pub fn f() string {
return 'x'
}

View File

@ -0,0 +1,4 @@
module yyy
pub fn f() string {
return 'y'
}

View File

@ -0,0 +1,4 @@
module zzz
pub fn f() string {
return 'z'
}

View File

@ -0,0 +1,34 @@
import os
const (
vexe = os.getenv('VEXE')
vroot = os.dir(vexe)
basepath = os.real_path(os.join_path(vroot, 'vlib', 'v', 'tests', 'multiple_paths_in_vmodules'))
mainvv = os.join_path(basepath, 'main.vv')
)
fn test_vexe_is_set() {
assert vexe != ''
println('vexe: $vexe')
}
fn test_compiling_without_vmodules_fails() {
os.chdir(vroot)
os.setenv('VMODULES', '', true)
res := os.exec('"$vexe" run "$mainvv"') or {
panic(err)
}
assert res.exit_code == 1
assert res.output.trim_space() == 'builder error: cannot import module "yyy" (not found)'
}
fn test_compiling_with_vmodules_works() {
os.chdir(vroot)
vmpaths := ['path1', 'path2', 'path3'].map(os.join_path(basepath, it))
os.setenv('VMODULES', vmpaths.join(os.path_delimiter), true)
res := os.exec('"$vexe" run "$mainvv"') or {
panic(err)
}
assert res.exit_code == 0
assert res.output.trim_space() == "['x', 'y', 'z']"
}