2021-01-18 13:20:06 +01:00
|
|
|
|
// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
|
2020-09-15 18:35:00 +02:00
|
|
|
|
// Use of this source code is governed by an MIT license
|
|
|
|
|
// that can be found in the LICENSE file.
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
module main
|
|
|
|
|
|
2020-04-26 08:32:05 +02:00
|
|
|
|
import os
|
2021-08-18 13:05:10 +02:00
|
|
|
|
import regex
|
2020-04-26 08:32:05 +02:00
|
|
|
|
import os.cmdline
|
|
|
|
|
import net.http
|
|
|
|
|
import json
|
|
|
|
|
import vhelp
|
2020-05-24 14:25:29 +02:00
|
|
|
|
import v.vmod
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
|
|
|
|
|
const (
|
2021-04-29 01:17:37 +02:00
|
|
|
|
default_vpm_server_urls = ['https://vpm.vlang.io']
|
|
|
|
|
valid_vpm_commands = ['help', 'search', 'install', 'update', 'upgrade', 'outdated',
|
2021-05-24 14:17:57 +02:00
|
|
|
|
'list', 'remove', 'show']
|
2021-04-29 01:17:37 +02:00
|
|
|
|
excluded_dirs = ['cache', 'vlib']
|
|
|
|
|
supported_vcs_systems = ['git', 'hg']
|
|
|
|
|
supported_vcs_folders = ['.git', '.hg']
|
2021-08-04 11:44:41 +02:00
|
|
|
|
supported_vcs_update_cmds = {
|
2020-05-13 07:19:12 +02:00
|
|
|
|
'git': 'git pull'
|
2021-01-26 15:43:10 +01:00
|
|
|
|
'hg': 'hg pull --update'
|
2020-01-03 22:07:58 +01:00
|
|
|
|
}
|
2021-08-04 11:44:41 +02:00
|
|
|
|
supported_vcs_install_cmds = {
|
2020-01-03 22:07:58 +01:00
|
|
|
|
'git': 'git clone --depth=1'
|
2021-01-26 15:43:10 +01:00
|
|
|
|
'hg': 'hg clone'
|
2020-01-03 22:07:58 +01:00
|
|
|
|
}
|
2021-08-04 11:44:41 +02:00
|
|
|
|
supported_vcs_outdated_steps = {
|
2020-07-22 02:25:20 +02:00
|
|
|
|
'git': ['git fetch', 'git rev-parse @', 'git rev-parse @{u}']
|
2021-01-26 15:43:10 +01:00
|
|
|
|
'hg': ['hg incoming']
|
2020-07-15 21:55:07 +02:00
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
settings = &VpmSettings{}
|
|
|
|
|
normal_flags = ['-v', '-h', '-f', '-force']
|
|
|
|
|
flags_with_value = ['-git', '-hg']
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
)
|
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
// settings context:
|
|
|
|
|
struct VpmSettings {
|
|
|
|
|
mut:
|
|
|
|
|
is_help bool
|
|
|
|
|
is_verbose bool
|
|
|
|
|
is_global bool
|
|
|
|
|
is_forced bool
|
|
|
|
|
server_urls []string
|
|
|
|
|
vmodules_path string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn init_settings() {
|
|
|
|
|
mut s := &VpmSettings(0)
|
|
|
|
|
unsafe {
|
|
|
|
|
s = settings
|
|
|
|
|
}
|
|
|
|
|
s.is_help = '-h' in os.args || '--help' in os.args || 'help' in os.args
|
|
|
|
|
s.is_forced = '-f' in os.args || '-force' in os.args
|
|
|
|
|
s.is_verbose = '-v' in os.args
|
|
|
|
|
s.server_urls = cmdline.options(os.args, '-server-url')
|
|
|
|
|
s.vmodules_path = os.vmodules_dir()
|
|
|
|
|
}
|
|
|
|
|
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
struct Mod {
|
2019-12-23 11:02:50 +01:00
|
|
|
|
id int
|
|
|
|
|
url string
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
nr_downloads int
|
2020-01-03 22:07:58 +01:00
|
|
|
|
vcs string
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mut:
|
|
|
|
|
name string
|
|
|
|
|
failed bool
|
|
|
|
|
installed bool
|
|
|
|
|
updated bool
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
fn (mod Mod) path() string {
|
|
|
|
|
return real_path_of_module(mod.name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn real_path_of_module(name string) string {
|
|
|
|
|
mod_name_as_path := name.replace('.', os.path_separator).replace('-', '_').to_lower()
|
|
|
|
|
name_of_vmodules_folder := os.join_path(settings.vmodules_path, mod_name_as_path)
|
|
|
|
|
return os.real_path(name_of_vmodules_folder)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn module_from_url(url string, vcs string) ?Mod {
|
|
|
|
|
query := r'([\w+]+\://)?((\w*@)?((\w+\.)+(\w*)))[/+\:](\w+)/([\w+\-]+)(\.\w*)?'
|
|
|
|
|
mut re := regex.regex_opt(query) or { panic(err) }
|
|
|
|
|
|
|
|
|
|
start, end := re.match_string(url)
|
|
|
|
|
|
|
|
|
|
if start < 0 || end <= start {
|
|
|
|
|
panic('"$url" is not a valid url!')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
author := re.get_group_by_id(url, 6)
|
|
|
|
|
name := re.get_group_by_id(url, 7)
|
|
|
|
|
|
|
|
|
|
return Mod{
|
|
|
|
|
name: '${author}.$name'
|
|
|
|
|
url: url
|
|
|
|
|
vcs: vcs
|
|
|
|
|
}
|
2019-12-30 05:22:28 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
fn module_from_manifest(manifest vmod.Manifest) Mod {
|
|
|
|
|
return Mod{
|
|
|
|
|
name: manifest.name
|
|
|
|
|
url: manifest.repo_url
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn module_from_file(vpath string) ?Mod {
|
|
|
|
|
manifest := vmod.from_file(vpath) or { panic(err) }
|
|
|
|
|
return module_from_manifest(manifest)
|
2021-08-13 11:28:30 +02:00
|
|
|
|
}
|
|
|
|
|
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
fn main() {
|
2020-01-03 22:07:58 +01:00
|
|
|
|
init_settings()
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
// This tool is intended to be launched by the v frontend,
|
2019-12-23 11:02:50 +01:00
|
|
|
|
// which provides the path to V inside os.getenv('VEXE')
|
2020-12-20 16:08:56 +01:00
|
|
|
|
// args are: vpm [options] SUBCOMMAND module names
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mut modules := map[string]Mod{}
|
|
|
|
|
|
2020-12-20 16:08:56 +01:00
|
|
|
|
params := cmdline.only_non_options(os.args[1..])
|
2021-08-18 13:05:10 +02:00
|
|
|
|
|
2020-01-03 22:07:58 +01:00
|
|
|
|
verbose_println('cli params: $params')
|
|
|
|
|
if params.len < 1 {
|
2020-03-13 20:52:49 +01:00
|
|
|
|
vpm_help()
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
exit(5)
|
|
|
|
|
}
|
2020-01-03 22:07:58 +01:00
|
|
|
|
vpm_command := params[0]
|
2020-05-24 14:25:29 +02:00
|
|
|
|
mut module_names := params[1..]
|
2020-01-03 22:07:58 +01:00
|
|
|
|
ensure_vmodules_dir_exist()
|
2021-08-18 13:05:10 +02:00
|
|
|
|
verbose_println('module names: ')
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
match vpm_command {
|
2019-12-23 11:02:50 +01:00
|
|
|
|
'help' {
|
2020-03-13 20:52:49 +01:00
|
|
|
|
vpm_help()
|
2019-12-23 11:02:50 +01:00
|
|
|
|
}
|
|
|
|
|
'search' {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
if settings.is_help {
|
|
|
|
|
vhelp.show_topic('search')
|
|
|
|
|
exit(0)
|
|
|
|
|
}
|
2019-12-23 11:02:50 +01:00
|
|
|
|
vpm_search(module_names)
|
|
|
|
|
}
|
|
|
|
|
'install' {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
if settings.is_help {
|
|
|
|
|
vhelp.show_topic('install')
|
|
|
|
|
exit(0)
|
2021-08-13 11:28:30 +02:00
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
|
|
|
|
|
modules = parse_modules()
|
|
|
|
|
|
|
|
|
|
if modules.len == 0 && os.exists('./v.mod') {
|
|
|
|
|
println('Detected v.mod file inside the project directory. Using it...')
|
|
|
|
|
resolve_dependencies('./v.mod', mut modules)
|
2021-08-13 11:28:30 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
vpm_install(mut modules)
|
2019-12-23 11:02:50 +01:00
|
|
|
|
}
|
|
|
|
|
'update' {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
if settings.is_help {
|
|
|
|
|
vhelp.show_topic('update')
|
|
|
|
|
exit(0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
modules = parse_modules()
|
|
|
|
|
|
|
|
|
|
if modules.len == 0 {
|
|
|
|
|
modules = get_installed_modules()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vpm_update(mut modules)
|
2019-12-23 11:02:50 +01:00
|
|
|
|
}
|
2020-08-18 02:44:18 +02:00
|
|
|
|
'upgrade' {
|
|
|
|
|
vpm_upgrade()
|
|
|
|
|
}
|
2020-07-15 21:55:07 +02:00
|
|
|
|
'outdated' {
|
|
|
|
|
vpm_outdated()
|
|
|
|
|
}
|
2020-07-20 16:39:37 +02:00
|
|
|
|
'list' {
|
|
|
|
|
vpm_list()
|
|
|
|
|
}
|
2019-12-23 11:02:50 +01:00
|
|
|
|
'remove' {
|
|
|
|
|
vpm_remove(module_names)
|
|
|
|
|
}
|
2021-05-24 14:17:57 +02:00
|
|
|
|
'show' {
|
|
|
|
|
vpm_show(module_names)
|
|
|
|
|
}
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
else {
|
|
|
|
|
println('Error: you tried to run "v $vpm_command"')
|
|
|
|
|
println('... but the v package management tool vpm only knows about these commands:')
|
|
|
|
|
for validcmd in valid_vpm_commands {
|
|
|
|
|
println(' v $validcmd')
|
|
|
|
|
}
|
|
|
|
|
exit(3)
|
2019-12-30 05:22:28 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
fn parse_modules() map[string]Mod {
|
|
|
|
|
mut modules := map[string]Mod{}
|
|
|
|
|
args := os.args[1..]
|
|
|
|
|
url_query := r'([\w+]+\://)?((\w*@)?((\w+\.)+(\w*)))[/+\:](\w+)/([\w+\-]+)(\.\w*)?'
|
|
|
|
|
mod_query := r'(\w*)(\.\w*)?'
|
|
|
|
|
|
|
|
|
|
mut url_re := regex.regex_opt(url_query) or { panic(err) }
|
|
|
|
|
mut mod_re := regex.regex_opt(mod_query) or { panic(err) }
|
|
|
|
|
|
|
|
|
|
for git in cmdline.options(args, '-git') {
|
|
|
|
|
arg_git_mod := module_from_url(git, 'git') or {
|
|
|
|
|
println('Error in parsing url:')
|
|
|
|
|
println(err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
modules[arg_git_mod.name] = arg_git_mod
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for hg in cmdline.options(args, '-hg') {
|
|
|
|
|
hg_mod := module_from_url(hg, 'hg') or {
|
|
|
|
|
println('Error in parsing url:')
|
|
|
|
|
println(err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
modules[hg_mod.name] = hg_mod
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mut ignore := true
|
|
|
|
|
for arg in args {
|
|
|
|
|
if arg in normal_flags {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if ignore {
|
|
|
|
|
ignore = false
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if arg in flags_with_value {
|
|
|
|
|
ignore = true
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// detect urls without option as git
|
|
|
|
|
mut start, mut end := url_re.match_string(arg)
|
|
|
|
|
if start >= 0 && end > start {
|
|
|
|
|
git_mod := module_from_url(arg, 'git') or {
|
|
|
|
|
println('Error in parsing url:')
|
|
|
|
|
println(err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
modules[git_mod.name] = git_mod
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
start, end = mod_re.match_string(arg)
|
|
|
|
|
if start >= 0 && end > start {
|
|
|
|
|
vpm_mod := get_module_meta_info(arg) or {
|
|
|
|
|
println('Errors while retrieving meta data for module $arg:')
|
|
|
|
|
println(err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
modules[vpm_mod.name] = vpm_mod
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
println('Error in parsing module name:')
|
|
|
|
|
println('"$arg" is not a valid module name or url!')
|
|
|
|
|
}
|
|
|
|
|
return modules
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-30 05:22:28 +01:00
|
|
|
|
fn vpm_search(keywords []string) {
|
2020-07-02 18:20:42 +02:00
|
|
|
|
search_keys := keywords.map(it.replace('_', '-'))
|
2021-08-18 13:05:10 +02:00
|
|
|
|
|
2020-07-02 18:20:42 +02:00
|
|
|
|
if search_keys.len == 0 {
|
2021-03-12 20:32:34 +01:00
|
|
|
|
println('´v search´ requires *at least one* keyword.')
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
exit(2)
|
|
|
|
|
}
|
2019-12-30 05:22:28 +01:00
|
|
|
|
modules := get_all_modules()
|
2020-10-20 23:02:17 +02:00
|
|
|
|
installed_modules := get_installed_modules()
|
2020-07-02 18:20:42 +02:00
|
|
|
|
joined := search_keys.join(', ')
|
2019-12-30 05:22:28 +01:00
|
|
|
|
mut index := 0
|
2021-08-18 13:05:10 +02:00
|
|
|
|
for _, mod in modules {
|
2019-12-30 05:22:28 +01:00
|
|
|
|
// TODO for some reason .filter results in substr error, so do it manually
|
2020-07-02 18:20:42 +02:00
|
|
|
|
for k in search_keys {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
if !mod.name.contains(k) {
|
2019-12-30 05:22:28 +01:00
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if index == 0 {
|
|
|
|
|
println('Search results for "$joined":\n')
|
|
|
|
|
}
|
|
|
|
|
index++
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mut parts := mod.name.split('.')
|
2019-12-30 05:22:28 +01:00
|
|
|
|
// in case the author isn't present
|
|
|
|
|
if parts.len == 1 {
|
|
|
|
|
parts << parts[0]
|
2020-10-20 23:02:17 +02:00
|
|
|
|
parts[0] = ' '
|
|
|
|
|
} else {
|
|
|
|
|
parts[0] = ' by ${parts[0]} '
|
2019-12-30 05:22:28 +01:00
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
installed := if mod.name in installed_modules { ' (installed)' } else { '' }
|
|
|
|
|
println('${index}. ${parts[1]}${parts[0]}[$mod.name]$installed')
|
2019-12-30 05:22:28 +01:00
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if index == 0 {
|
2020-11-07 17:02:16 +01:00
|
|
|
|
vexe := os.getenv('VEXE')
|
|
|
|
|
vroot := os.real_path(os.dir(vexe))
|
|
|
|
|
mut messages := ['No module(s) found for `$joined` .']
|
|
|
|
|
for vlibmod in search_keys {
|
|
|
|
|
if os.is_dir(os.join_path(vroot, 'vlib', vlibmod)) {
|
|
|
|
|
messages << 'There is already an existing "$vlibmod" module in vlib, so you can just `import $vlibmod` .'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for m in messages {
|
|
|
|
|
println(m)
|
|
|
|
|
}
|
2020-07-02 18:20:42 +02:00
|
|
|
|
} else {
|
2020-10-20 23:02:17 +02:00
|
|
|
|
println('\nUse "v install author_name.module_name" to install the module.')
|
2019-12-30 05:22:28 +01:00
|
|
|
|
}
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
fn vpm_install(mut modules map[string]Mod) {
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
mut errors := 0
|
2021-08-18 13:05:10 +02:00
|
|
|
|
for _, mut mod in modules {
|
|
|
|
|
if mod.failed || mod.updated || mod.installed {
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
continue
|
|
|
|
|
}
|
2020-01-03 22:07:58 +01:00
|
|
|
|
mut vcs := mod.vcs
|
|
|
|
|
if vcs == '' {
|
|
|
|
|
vcs = supported_vcs_systems[0]
|
|
|
|
|
}
|
2020-04-13 19:59:57 +02:00
|
|
|
|
if vcs !in supported_vcs_systems {
|
2020-01-03 22:07:58 +01:00
|
|
|
|
errors++
|
2021-08-18 13:05:10 +02:00
|
|
|
|
println('Skipping module "$mod.name", since it uses an unsupported VCS {$vcs} .')
|
2020-01-03 22:07:58 +01:00
|
|
|
|
continue
|
|
|
|
|
}
|
2021-08-13 11:28:30 +02:00
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mut final_module_path := mod.path()
|
|
|
|
|
|
2019-12-30 05:22:28 +01:00
|
|
|
|
if os.exists(final_module_path) {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mut mods := {
|
|
|
|
|
mod.name: mod
|
|
|
|
|
}
|
|
|
|
|
vpm_update(mut mods)
|
2019-12-30 05:22:28 +01:00
|
|
|
|
continue
|
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
println('Installing module "$mod.name" from $mod.url to $final_module_path ...')
|
2020-01-03 22:07:58 +01:00
|
|
|
|
vcs_install_cmd := supported_vcs_install_cmds[vcs]
|
2020-06-30 21:42:16 +02:00
|
|
|
|
cmd := '$vcs_install_cmd "$mod.url" "$final_module_path"'
|
2020-01-03 22:07:58 +01:00
|
|
|
|
verbose_println(' command: $cmd')
|
2021-03-08 19:52:13 +01:00
|
|
|
|
cmdres := os.execute(cmd)
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mod.updated = true
|
2020-01-03 22:07:58 +01:00
|
|
|
|
if cmdres.exit_code != 0 {
|
|
|
|
|
errors++
|
2021-08-18 13:05:10 +02:00
|
|
|
|
println('Failed installing module "$mod.name" to "$final_module_path" .')
|
2021-08-13 11:28:30 +02:00
|
|
|
|
verbose_println('Failed command: $cmd')
|
|
|
|
|
verbose_println('Failed command output:\n$cmdres.output')
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mod.failed = true
|
2021-08-13 11:28:30 +02:00
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
vmod_path := os.join_path(final_module_path, 'v.mod')
|
|
|
|
|
if os.exists(vmod_path) {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
vmod := module_from_file(vmod_path) or {
|
|
|
|
|
println('Error in reading v.mod from "$vmod_path":')
|
|
|
|
|
println(err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
mod_path := vmod.path()
|
|
|
|
|
if final_module_path == mod_path {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
println('Relocating module from "$mod.name" to "$vmod.name" ( $mod_path ) ...')
|
2021-08-13 11:28:30 +02:00
|
|
|
|
if os.exists(mod_path) {
|
|
|
|
|
println('Warning module "$mod_path" already exsits!')
|
2021-08-18 13:05:10 +02:00
|
|
|
|
if !settings.is_forced {
|
|
|
|
|
println('Undoing module "$final_module_path" installation ...')
|
|
|
|
|
os.rmdir_all(final_module_path) or {
|
|
|
|
|
errors++
|
|
|
|
|
println('Errors while removing "$final_module_path" :')
|
|
|
|
|
println(err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
2021-08-13 11:28:30 +02:00
|
|
|
|
println('Removing module "$mod_path" ...')
|
|
|
|
|
os.rmdir_all(mod_path) or {
|
|
|
|
|
errors++
|
|
|
|
|
println('Errors while removing "$mod_path" :')
|
|
|
|
|
println(err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
os.mv(final_module_path, mod_path) or {
|
|
|
|
|
errors++
|
2021-08-18 13:05:10 +02:00
|
|
|
|
println('Errors while relocating module "$mod.name" :')
|
2021-08-13 11:28:30 +02:00
|
|
|
|
println(err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
println('Module "$mod.name" relocated to "$vmod.name" successfully.')
|
2021-08-13 11:28:30 +02:00
|
|
|
|
final_module_path = mod_path
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mod.name = vmod.name
|
2021-08-13 11:28:30 +02:00
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
resolve_dependencies(os.join_path(mod.path(), 'v.mod'), mut modules)
|
2021-08-13 11:28:30 +02:00
|
|
|
|
}
|
|
|
|
|
if errors > 0 {
|
|
|
|
|
exit(1)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
fn vpm_update(mut modules map[string]Mod) {
|
2019-12-30 05:22:28 +01:00
|
|
|
|
mut errors := 0
|
2021-08-18 13:05:10 +02:00
|
|
|
|
for _, mut mod in modules {
|
|
|
|
|
if mod.updated || mod.failed {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
mut final_module_path := mod.path()
|
|
|
|
|
if !os.exists(final_module_path) {
|
|
|
|
|
println('Error in updating "$mod.name" module:')
|
|
|
|
|
println('"$mod.name" is not insalled!')
|
|
|
|
|
continue
|
|
|
|
|
}
|
2019-12-30 05:22:28 +01:00
|
|
|
|
os.chdir(final_module_path)
|
2021-08-18 13:05:10 +02:00
|
|
|
|
println('Updating module "$mod.name"...')
|
2020-01-03 22:07:58 +01:00
|
|
|
|
verbose_println(' work folder: $final_module_path')
|
2021-08-18 13:05:10 +02:00
|
|
|
|
vcs := vcs_used_in_path(final_module_path)
|
|
|
|
|
vcs_cmd := supported_vcs_update_cmds[vcs]
|
2020-08-07 17:33:13 +02:00
|
|
|
|
verbose_println(' command: $vcs_cmd')
|
2021-03-08 19:52:13 +01:00
|
|
|
|
vcs_res := os.execute('$vcs_cmd')
|
2020-01-03 22:07:58 +01:00
|
|
|
|
if vcs_res.exit_code != 0 {
|
|
|
|
|
errors++
|
2021-08-18 13:05:10 +02:00
|
|
|
|
println('Failed updating module "$mod.name".')
|
2020-06-30 21:42:16 +02:00
|
|
|
|
verbose_println('Failed command: $vcs_cmd')
|
|
|
|
|
verbose_println('Failed details:\n$vcs_res.output')
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mod.failed = true
|
2019-12-30 05:22:28 +01:00
|
|
|
|
continue
|
2020-08-07 17:33:13 +02:00
|
|
|
|
} else {
|
|
|
|
|
verbose_println(' $vcs_res.output.trim_space()')
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mod.updated = true
|
|
|
|
|
mod.installed = true
|
2019-12-30 05:22:28 +01:00
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
resolve_dependencies(os.join_path(mod.path(), 'v.mod'), mut modules)
|
2019-12-30 05:22:28 +01:00
|
|
|
|
}
|
|
|
|
|
if errors > 0 {
|
|
|
|
|
exit(1)
|
|
|
|
|
}
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
fn get_outdated() ?map[string]Mod {
|
|
|
|
|
modules := get_installed_modules()
|
|
|
|
|
mut outdated := map[string]Mod{}
|
|
|
|
|
for _, mod in modules {
|
|
|
|
|
final_module_path := mod.path()
|
2020-07-15 21:55:07 +02:00
|
|
|
|
os.chdir(final_module_path)
|
2021-08-18 13:05:10 +02:00
|
|
|
|
vcs := vcs_used_in_path(final_module_path)
|
|
|
|
|
vcs_cmd_steps := supported_vcs_outdated_steps[vcs]
|
2020-07-22 02:25:20 +02:00
|
|
|
|
mut outputs := []string{}
|
|
|
|
|
for step in vcs_cmd_steps {
|
2021-03-08 19:52:13 +01:00
|
|
|
|
res := os.execute(step)
|
|
|
|
|
if res.exit_code < 0 {
|
2020-09-15 18:35:00 +02:00
|
|
|
|
verbose_println('Error command: $step')
|
2021-03-08 19:52:13 +01:00
|
|
|
|
verbose_println('Error details:\n$res.output')
|
2021-08-18 13:05:10 +02:00
|
|
|
|
panic('Error while checking latest commits for "$mod.name".')
|
2020-07-22 02:25:20 +02:00
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
if vcs == 'hg' {
|
2020-09-15 18:35:00 +02:00
|
|
|
|
if res.exit_code == 1 {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
outdated[mod.name] = mod
|
2020-09-15 18:35:00 +02:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
outputs << res.output
|
|
|
|
|
}
|
2020-07-15 21:55:07 +02:00
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
if vcs == 'git' && outputs[1] != outputs[2] {
|
|
|
|
|
outdated[mod.name] = mod
|
2020-07-15 21:55:07 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-08-18 02:44:18 +02:00
|
|
|
|
return outdated
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn vpm_upgrade() {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mut outdated := get_outdated() or {
|
|
|
|
|
println(err)
|
|
|
|
|
exit(1)
|
|
|
|
|
}
|
2020-08-18 02:44:18 +02:00
|
|
|
|
if outdated.len > 0 {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
vpm_update(mut &outdated)
|
2020-08-18 02:44:18 +02:00
|
|
|
|
} else {
|
|
|
|
|
println('Modules are up to date.')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn vpm_outdated() {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
outdated := get_outdated() or {
|
|
|
|
|
println(err)
|
|
|
|
|
exit(1)
|
|
|
|
|
}
|
2020-07-15 21:55:07 +02:00
|
|
|
|
if outdated.len > 0 {
|
|
|
|
|
println('Outdated modules:')
|
2021-08-18 13:05:10 +02:00
|
|
|
|
for _, m in outdated {
|
|
|
|
|
println(' $m.name')
|
2020-07-15 21:55:07 +02:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
println('Modules are up to date.')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-20 16:39:37 +02:00
|
|
|
|
fn vpm_list() {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
modules := get_installed_modules()
|
|
|
|
|
if modules.len == 0 {
|
2020-07-20 16:39:37 +02:00
|
|
|
|
println('You have no modules installed.')
|
|
|
|
|
exit(0)
|
|
|
|
|
}
|
2020-08-07 17:33:13 +02:00
|
|
|
|
println('Installed modules:')
|
2021-08-18 13:05:10 +02:00
|
|
|
|
for _, mod in modules {
|
|
|
|
|
println(' $mod.name')
|
2020-07-20 16:39:37 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-23 11:02:50 +01:00
|
|
|
|
fn vpm_remove(module_names []string) {
|
2020-01-03 22:07:58 +01:00
|
|
|
|
if settings.is_help {
|
2020-03-13 20:52:49 +01:00
|
|
|
|
vhelp.show_topic('remove')
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
exit(0)
|
|
|
|
|
}
|
2019-12-30 05:22:28 +01:00
|
|
|
|
if module_names.len == 0 {
|
2021-03-12 20:32:34 +01:00
|
|
|
|
println('´v remove´ requires *at least one* module name.')
|
2019-12-30 05:22:28 +01:00
|
|
|
|
exit(2)
|
|
|
|
|
}
|
|
|
|
|
for name in module_names {
|
2021-01-26 15:43:10 +01:00
|
|
|
|
final_module_path := valid_final_path_of_existing_module(name) or { continue }
|
2019-12-30 05:22:28 +01:00
|
|
|
|
println('Removing module "$name"...')
|
2020-01-03 22:07:58 +01:00
|
|
|
|
verbose_println('removing folder $final_module_path')
|
2021-03-26 10:37:54 +01:00
|
|
|
|
os.rmdir_all(final_module_path) or {
|
|
|
|
|
verbose_println('error while removing "$final_module_path": $err.msg')
|
|
|
|
|
}
|
2020-01-03 22:07:58 +01:00
|
|
|
|
// delete author directory if it is empty
|
2019-12-30 05:22:28 +01:00
|
|
|
|
author := name.split('.')[0]
|
2020-06-30 21:42:16 +02:00
|
|
|
|
author_dir := os.real_path(os.join_path(settings.vmodules_path, author))
|
2021-03-26 10:37:54 +01:00
|
|
|
|
if !os.exists(author_dir) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2019-12-30 05:22:28 +01:00
|
|
|
|
if os.is_dir_empty(author_dir) {
|
2020-01-03 22:07:58 +01:00
|
|
|
|
verbose_println('removing author folder $author_dir')
|
2021-03-26 10:37:54 +01:00
|
|
|
|
os.rmdir(author_dir) or {
|
|
|
|
|
verbose_println('error while removing "$author_dir": $err.msg')
|
|
|
|
|
}
|
2019-12-30 05:22:28 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-03 22:07:58 +01:00
|
|
|
|
fn valid_final_path_of_existing_module(name string) ?string {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
final_module_path := real_path_of_module(name)
|
2020-01-03 22:07:58 +01:00
|
|
|
|
if !os.exists(final_module_path) {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
println('No module with name "$name" exists at $final_module_path')
|
2020-01-03 22:07:58 +01:00
|
|
|
|
return none
|
|
|
|
|
}
|
|
|
|
|
if !os.is_dir(final_module_path) {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
println('Skipping "$final_module_path", since it is not a folder.')
|
2020-01-03 22:07:58 +01:00
|
|
|
|
return none
|
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
|
2020-01-03 22:07:58 +01:00
|
|
|
|
return final_module_path
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn ensure_vmodules_dir_exist() {
|
2020-01-03 22:07:58 +01:00
|
|
|
|
if !os.is_dir(settings.vmodules_path) {
|
|
|
|
|
println('Creating $settings.vmodules_path/ ...')
|
2021-03-01 00:18:14 +01:00
|
|
|
|
os.mkdir(settings.vmodules_path) or { panic(err) }
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 20:52:49 +01:00
|
|
|
|
fn vpm_help() {
|
|
|
|
|
vhelp.show_topic('vpm')
|
tools/vget => tools/v , search, install, etc
* compiler: rename vget to tools/vpm, implement draft support for v vpm search, v vpm update, v vpm install, v vpm remove, v vpm help .
* compiler: use "v pm" instead of "v vpm" to reduce the redundancy of typing, as suggested by slapden
* Use 'v install modulename', 'v search keywords', 'v update modulename', 'v remove modulename' instead of the longer 'v pm install modulename' etc.
2019-11-01 13:19:04 +01:00
|
|
|
|
}
|
2019-12-23 11:02:50 +01:00
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
fn vcs_used_in_path(dir string) string {
|
2020-01-03 22:07:58 +01:00
|
|
|
|
for repo_subfolder in supported_vcs_folders {
|
2020-06-30 21:42:16 +02:00
|
|
|
|
checked_folder := os.real_path(os.join_path(dir, repo_subfolder))
|
2020-01-03 22:07:58 +01:00
|
|
|
|
if os.is_dir(checked_folder) {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
return repo_subfolder.replace('.', '')
|
2020-01-03 22:07:58 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
return 'git'
|
2020-01-03 22:07:58 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
fn get_installed_modules() map[string]Mod {
|
|
|
|
|
dirs := os.ls(settings.vmodules_path) or { return map[string]Mod{} }
|
|
|
|
|
mut modules := map[string]Mod{}
|
2019-12-30 05:22:28 +01:00
|
|
|
|
for dir in dirs {
|
2020-06-30 21:42:16 +02:00
|
|
|
|
adir := os.join_path(settings.vmodules_path, dir)
|
2020-01-03 22:07:58 +01:00
|
|
|
|
if dir in excluded_dirs || !os.is_dir(adir) {
|
2019-12-30 05:22:28 +01:00
|
|
|
|
continue
|
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mut vmod_path := os.join_path(adir, 'v.mod')
|
|
|
|
|
if os.exists(vmod_path) && os.exists(os.join_path(adir, '.git', 'config')) {
|
2020-05-31 18:18:24 +02:00
|
|
|
|
// an official vlang module with a short module name, like `vsl`, `ui` or `markdown`
|
2021-08-18 13:05:10 +02:00
|
|
|
|
|
|
|
|
|
mut mod := module_from_file(vmod_path) or {
|
|
|
|
|
println('Error while reading "$vmod_path":')
|
|
|
|
|
println(err)
|
|
|
|
|
url := 'https://github.com/vlang/$dir'
|
|
|
|
|
modules[dir] = Mod{
|
|
|
|
|
name: dir
|
|
|
|
|
url: url
|
|
|
|
|
installed: true
|
|
|
|
|
vcs: 'git'
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
modules[dir] = mod
|
2020-05-31 18:18:24 +02:00
|
|
|
|
continue
|
|
|
|
|
}
|
2019-12-30 05:22:28 +01:00
|
|
|
|
author := dir
|
2021-01-26 15:43:10 +01:00
|
|
|
|
mods := os.ls(adir) or { continue }
|
2019-12-30 05:22:28 +01:00
|
|
|
|
for m in mods {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
vmod_path = os.join_path(adir, m, 'v.mod')
|
|
|
|
|
if os.exists(vmod_path) {
|
|
|
|
|
mut mod := module_from_file(vmod_path) or {
|
|
|
|
|
println('Error while reading "$vmod_path":')
|
|
|
|
|
println(err)
|
|
|
|
|
name := '${author}.$m'
|
|
|
|
|
url := 'https://github.com/vlang/$author/$m'
|
|
|
|
|
modules[name] = Mod{
|
|
|
|
|
name: name
|
|
|
|
|
url: url
|
|
|
|
|
installed: true
|
|
|
|
|
vcs: 'git'
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
modules[mod.name] = mod
|
|
|
|
|
}
|
2019-12-30 05:22:28 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return modules
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
fn get_all_modules() map[string]Mod {
|
2020-01-03 22:07:58 +01:00
|
|
|
|
url := get_working_server_url()
|
2021-03-01 00:18:14 +01:00
|
|
|
|
r := http.get(url) or { panic(err) }
|
2019-12-30 05:22:28 +01:00
|
|
|
|
if r.status_code != 200 {
|
2020-03-16 10:53:28 +01:00
|
|
|
|
println('Failed to search vpm.vlang.io. Status code: $r.status_code')
|
2019-12-30 05:22:28 +01:00
|
|
|
|
exit(1)
|
|
|
|
|
}
|
|
|
|
|
s := r.text
|
|
|
|
|
mut read_len := 0
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mut names := []string{}
|
2019-12-30 05:22:28 +01:00
|
|
|
|
for read_len < s.len {
|
|
|
|
|
mut start_token := '<a href="/mod'
|
|
|
|
|
end_token := '</a>'
|
|
|
|
|
// get the start index of the module entry
|
|
|
|
|
mut start_index := s.index_after(start_token, read_len)
|
|
|
|
|
if start_index == -1 {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
// get the index of the end of anchor (a) opening tag
|
|
|
|
|
// we use the previous start_index to make sure we are getting a module and not just a random 'a' tag
|
|
|
|
|
start_token = '">'
|
|
|
|
|
start_index = s.index_after(start_token, start_index) + start_token.len
|
|
|
|
|
// get the index of the end of module entry
|
|
|
|
|
end_index := s.index_after(end_token, start_index)
|
|
|
|
|
if end_index == -1 {
|
|
|
|
|
break
|
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
names << s[start_index..end_index]
|
2019-12-30 05:22:28 +01:00
|
|
|
|
read_len = end_index
|
|
|
|
|
if read_len >= s.len {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mut modules := map[string]Mod{}
|
|
|
|
|
|
|
|
|
|
for name in names {
|
|
|
|
|
modules[name] = Mod{
|
|
|
|
|
name: name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-30 05:22:28 +01:00
|
|
|
|
return modules
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 13:05:10 +02:00
|
|
|
|
fn resolve_dependencies(path string, mut modules map[string]Mod) {
|
|
|
|
|
manifest := vmod.from_file(path) or { return }
|
|
|
|
|
url_query := r'([\w+]+\://)?((\w*@)?((\w+\.)+(\w*)))[/+\:](\w+)/([\w+\-]+)(\.\w*)?'
|
|
|
|
|
mod_query := r'(\w*)(\.\w*)?'
|
|
|
|
|
|
|
|
|
|
mut url_re := regex.regex_opt(url_query) or { panic(err) }
|
|
|
|
|
mut mod_re := regex.regex_opt(mod_query) or { panic(err) }
|
|
|
|
|
|
2020-04-26 13:49:31 +02:00
|
|
|
|
mut deps := []string{}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
for dep in manifest.dependencies {
|
|
|
|
|
if dep.starts_with('hg:') {
|
|
|
|
|
mod := module_from_url(dep[3..], 'hg') or {
|
|
|
|
|
println('Errors while retrieving meta data for module $dep:')
|
|
|
|
|
println(err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if mod.name !in modules {
|
|
|
|
|
modules[mod.name] = mod
|
|
|
|
|
deps << mod.name
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mut start, mut end := url_re.match_string(dep)
|
|
|
|
|
|
|
|
|
|
if start >= 0 && end > start {
|
|
|
|
|
mod := module_from_url(dep, 'git') or {
|
|
|
|
|
println('Errors while retrieving meta data for module $dep:')
|
|
|
|
|
println(err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if mod.name !in modules {
|
|
|
|
|
modules[mod.name] = mod
|
|
|
|
|
deps << mod.name
|
|
|
|
|
}
|
|
|
|
|
continue
|
2019-12-30 05:22:28 +01:00
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
|
|
|
|
|
start, end = mod_re.match_string(dep)
|
|
|
|
|
|
|
|
|
|
if start >= 0 && end > start {
|
|
|
|
|
mod := get_module_meta_info(dep) or {
|
|
|
|
|
println('Errors while retrieving meta data for module $dep:')
|
|
|
|
|
println(err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if mod.name !in modules {
|
|
|
|
|
modules[mod.name] = mod
|
|
|
|
|
deps << mod.name
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
println('Error in parsing module name:')
|
|
|
|
|
println('"$dep" is not a valid module name or url!')
|
2019-12-30 05:22:28 +01:00
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
|
2019-12-30 05:22:28 +01:00
|
|
|
|
if deps.len > 0 {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
println('Resolving $deps.len dependencies for module "$manifest.name"...')
|
2020-01-03 22:07:58 +01:00
|
|
|
|
verbose_println('Found dependencies: $deps')
|
2021-08-18 13:05:10 +02:00
|
|
|
|
vpm_update(mut modules)
|
|
|
|
|
vpm_install(mut modules)
|
2019-12-30 05:22:28 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-03 22:07:58 +01:00
|
|
|
|
fn get_working_server_url() string {
|
2021-01-26 15:43:10 +01:00
|
|
|
|
server_urls := if settings.server_urls.len > 0 {
|
|
|
|
|
settings.server_urls
|
|
|
|
|
} else {
|
|
|
|
|
default_vpm_server_urls
|
|
|
|
|
}
|
2020-01-03 22:07:58 +01:00
|
|
|
|
for url in server_urls {
|
|
|
|
|
verbose_println('Trying server url: $url')
|
|
|
|
|
http.head(url) or {
|
|
|
|
|
verbose_println(' $url failed.')
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
return url
|
|
|
|
|
}
|
|
|
|
|
panic('No responding vpm server found. Please check your network connectivity and try again later.')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn verbose_println(s string) {
|
|
|
|
|
if settings.is_verbose {
|
|
|
|
|
println(s)
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-16 14:30:22 +01:00
|
|
|
|
|
|
|
|
|
fn get_module_meta_info(name string) ?Mod {
|
2020-04-26 13:49:31 +02:00
|
|
|
|
mut errors := []string{}
|
2020-03-16 14:30:22 +01:00
|
|
|
|
for server_url in default_vpm_server_urls {
|
|
|
|
|
modurl := server_url + '/jsmod/$name'
|
|
|
|
|
verbose_println('Retrieving module metadata from: $modurl ...')
|
|
|
|
|
r := http.get(modurl) or {
|
|
|
|
|
errors << 'Http server did not respond to our request for ${modurl}.'
|
|
|
|
|
errors << 'Error details: $err'
|
|
|
|
|
continue
|
|
|
|
|
}
|
2021-02-25 08:05:18 +01:00
|
|
|
|
if r.status_code == 404 || r.text.trim_space() == '404' {
|
2021-01-26 15:43:10 +01:00
|
|
|
|
errors << 'Skipping module "$name", since $server_url reported that "$name" does not exist.'
|
2020-03-16 14:30:22 +01:00
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if r.status_code != 200 {
|
2021-01-26 15:43:10 +01:00
|
|
|
|
errors << 'Skipping module "$name", since $server_url responded with $r.status_code http status code. Please try again later.'
|
2020-03-16 14:30:22 +01:00
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
s := r.text
|
|
|
|
|
if s.len > 0 && s[0] != `{` {
|
|
|
|
|
errors << 'Invalid json data'
|
|
|
|
|
errors << s.trim_space().limit(100) + '...'
|
|
|
|
|
continue
|
|
|
|
|
}
|
2020-06-30 21:42:16 +02:00
|
|
|
|
mod := json.decode(Mod, s) or {
|
2020-03-16 14:30:22 +01:00
|
|
|
|
errors << 'Skipping module "$name", since its information is not in json format.'
|
|
|
|
|
continue
|
|
|
|
|
}
|
2020-03-29 10:08:42 +02:00
|
|
|
|
if '' == mod.url || '' == mod.name {
|
2020-03-16 14:30:22 +01:00
|
|
|
|
errors << 'Skipping module "$name", since it is missing name or url information.'
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
return mod
|
|
|
|
|
}
|
|
|
|
|
return error(errors.join_lines())
|
|
|
|
|
}
|
2021-05-24 14:17:57 +02:00
|
|
|
|
|
|
|
|
|
fn vpm_show(module_names []string) {
|
|
|
|
|
installed_modules := get_installed_modules()
|
2021-08-18 13:05:10 +02:00
|
|
|
|
mut installed_modules_names := []string{}
|
|
|
|
|
for _, installed in installed_modules {
|
|
|
|
|
installed_modules_names << installed.name
|
|
|
|
|
}
|
2021-05-24 14:17:57 +02:00
|
|
|
|
for module_name in module_names {
|
2021-08-18 13:05:10 +02:00
|
|
|
|
if module_name !in installed_modules_names {
|
2021-05-24 14:17:57 +02:00
|
|
|
|
module_meta_info := get_module_meta_info(module_name) or { continue }
|
2021-08-18 13:05:10 +02:00
|
|
|
|
println('Name: $module_meta_info.name')
|
|
|
|
|
println('Homepage: $module_meta_info.url')
|
|
|
|
|
println('Downloads: $module_meta_info.nr_downloads')
|
|
|
|
|
println('Installed: False')
|
|
|
|
|
println('--------')
|
2021-05-24 14:17:57 +02:00
|
|
|
|
continue
|
|
|
|
|
}
|
2021-08-18 13:05:10 +02:00
|
|
|
|
path := real_path_of_module(module_name)
|
|
|
|
|
mod := vmod.from_file(path) or { continue }
|
|
|
|
|
println('Name: $mod.name')
|
|
|
|
|
println('Version: $mod.version')
|
|
|
|
|
println('Description: $mod.description')
|
|
|
|
|
println('Homepage: $mod.repo_url')
|
|
|
|
|
println('Author: $mod.author')
|
|
|
|
|
println('License: $mod.license')
|
|
|
|
|
println('Location: $path')
|
|
|
|
|
println('Requires: ${mod.dependencies.join(', ')}')
|
|
|
|
|
println('--------')
|
2021-05-24 14:17:57 +02:00
|
|
|
|
}
|
|
|
|
|
}
|