Revert "vpm: support `v install ui https://github.com/vlang/markdown` (git urls by default), cleanup vpm.v (#11189)"

This reverts commit eee71cebd4.
pull/11234/head
Delyan Angelov 2021-08-18 18:58:04 +03:00
parent 6983f74a9d
commit 0cbc77d881
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
3 changed files with 266 additions and 402 deletions

View File

@ -4,7 +4,6 @@
module main module main
import os import os
import regex
import os.cmdline import os.cmdline
import net.http import net.http
import json import json
@ -30,86 +29,27 @@ const (
'git': ['git fetch', 'git rev-parse @', 'git rev-parse @{u}'] 'git': ['git fetch', 'git rev-parse @', 'git rev-parse @{u}']
'hg': ['hg incoming'] 'hg': ['hg incoming']
} }
settings = &VpmSettings{}
normal_flags = ['-v', '-h', '-f', '-force']
flags_with_value = ['-git', '-hg']
) )
// 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()
}
struct Mod { struct Mod {
id int id int
name string
url string url string
nr_downloads int nr_downloads int
vcs string vcs string
}
struct Vmod {
mut: mut:
name string name string
failed bool version string
installed bool deps []string
updated bool
} }
fn (mod Mod) path() string { enum Source {
return real_path_of_module(mod.name) git
} hg
vpm
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
}
}
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)
} }
fn main() { fn main() {
@ -117,10 +57,8 @@ fn main() {
// This tool is intended to be launched by the v frontend, // This tool is intended to be launched by the v frontend,
// which provides the path to V inside os.getenv('VEXE') // which provides the path to V inside os.getenv('VEXE')
// args are: vpm [options] SUBCOMMAND module names // args are: vpm [options] SUBCOMMAND module names
mut modules := map[string]Mod{}
params := cmdline.only_non_options(os.args[1..]) params := cmdline.only_non_options(os.args[1..])
options := cmdline.only_options(os.args[1..])
verbose_println('cli params: $params') verbose_println('cli params: $params')
if params.len < 1 { if params.len < 1 {
vpm_help() vpm_help()
@ -129,46 +67,32 @@ fn main() {
vpm_command := params[0] vpm_command := params[0]
mut module_names := params[1..] mut module_names := params[1..]
ensure_vmodules_dir_exist() ensure_vmodules_dir_exist()
verbose_println('module names: ') // println('module names: ') println(module_names)
match vpm_command { match vpm_command {
'help' { 'help' {
vpm_help() vpm_help()
} }
'search' { 'search' {
if settings.is_help {
vhelp.show_topic('search')
exit(0)
}
vpm_search(module_names) vpm_search(module_names)
} }
'install' { 'install' {
if settings.is_help { if module_names.len == 0 && os.exists('./v.mod') {
vhelp.show_topic('install')
exit(0)
}
modules = parse_modules()
if modules.len == 0 && os.exists('./v.mod') {
println('Detected v.mod file inside the project directory. Using it...') println('Detected v.mod file inside the project directory. Using it...')
resolve_dependencies('./v.mod', mut modules) manifest := vmod.from_file('./v.mod') or { panic(err) }
module_names = manifest.dependencies
}
mut source := Source.vpm
if '--git' in options {
source = Source.git
}
if '--hg' in options {
source = Source.hg
} }
vpm_install(mut modules) vpm_install(module_names, source)
} }
'update' { 'update' {
if settings.is_help { vpm_update(module_names)
vhelp.show_topic('update')
exit(0)
}
modules = parse_modules()
if modules.len == 0 {
modules = get_installed_modules()
}
vpm_update(mut modules)
} }
'upgrade' { 'upgrade' {
vpm_upgrade() vpm_upgrade()
@ -196,80 +120,12 @@ fn main() {
} }
} }
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
}
fn vpm_search(keywords []string) { fn vpm_search(keywords []string) {
search_keys := keywords.map(it.replace('_', '-')) search_keys := keywords.map(it.replace('_', '-'))
if settings.is_help {
vhelp.show_topic('search')
exit(0)
}
if search_keys.len == 0 { if search_keys.len == 0 {
println('´v search´ requires *at least one* keyword.') println('´v search´ requires *at least one* keyword.')
exit(2) exit(2)
@ -278,17 +134,17 @@ fn vpm_search(keywords []string) {
installed_modules := get_installed_modules() installed_modules := get_installed_modules()
joined := search_keys.join(', ') joined := search_keys.join(', ')
mut index := 0 mut index := 0
for _, mod in modules { for mod in modules {
// TODO for some reason .filter results in substr error, so do it manually // TODO for some reason .filter results in substr error, so do it manually
for k in search_keys { for k in search_keys {
if !mod.name.contains(k) { if !mod.contains(k) {
continue continue
} }
if index == 0 { if index == 0 {
println('Search results for "$joined":\n') println('Search results for "$joined":\n')
} }
index++ index++
mut parts := mod.name.split('.') mut parts := mod.split('.')
// in case the author isn't present // in case the author isn't present
if parts.len == 1 { if parts.len == 1 {
parts << parts[0] parts << parts[0]
@ -296,8 +152,8 @@ fn vpm_search(keywords []string) {
} else { } else {
parts[0] = ' by ${parts[0]} ' parts[0] = ' by ${parts[0]} '
} }
installed := if mod.name in installed_modules { ' (installed)' } else { '' } installed := if mod in installed_modules { ' (installed)' } else { '' }
println('${index}. ${parts[1]}${parts[0]}[$mod.name]$installed') println('${index}. ${parts[1]}${parts[0]}[$mod]$installed')
break break
} }
} }
@ -318,10 +174,14 @@ fn vpm_search(keywords []string) {
} }
} }
fn vpm_install(mut modules map[string]Mod) { fn vpm_install_from_vpm(module_names []string) {
mut errors := 0 mut errors := 0
for _, mut mod in modules { for n in module_names {
if mod.failed || mod.updated || mod.installed { name := n.trim_space().replace('_', '-')
mod := get_module_meta_info(name) or {
errors++
println('Errors while retrieving meta data for module $name:')
println(err)
continue continue
} }
mut vcs := mod.vcs mut vcs := mod.vcs
@ -330,57 +190,85 @@ fn vpm_install(mut modules map[string]Mod) {
} }
if vcs !in supported_vcs_systems { if vcs !in supported_vcs_systems {
errors++ errors++
println('Skipping module "$mod.name", since it uses an unsupported VCS {$vcs} .') println('Skipping module "$name", since it uses an unsupported VCS {$vcs} .')
continue continue
} }
mut final_module_path := mod.path() mod_name_as_path := mod.name.replace('.', os.path_separator).replace('-', '_').to_lower()
final_module_path := os.real_path(os.join_path(settings.vmodules_path, mod_name_as_path))
if os.exists(final_module_path) { if os.exists(final_module_path) {
mut mods := { vpm_update([name])
mod.name: mod
}
vpm_update(mut mods)
continue continue
} }
println('Installing module "$mod.name" from $mod.url to $final_module_path ...') println('Installing module "$name" from $mod.url to $final_module_path ...')
vcs_install_cmd := supported_vcs_install_cmds[vcs] vcs_install_cmd := supported_vcs_install_cmds[vcs]
cmd := '$vcs_install_cmd "$mod.url" "$final_module_path"' cmd := '$vcs_install_cmd "$mod.url" "$final_module_path"'
verbose_println(' command: $cmd') verbose_println(' command: $cmd')
cmdres := os.execute(cmd) cmdres := os.execute(cmd)
mod.updated = true
if cmdres.exit_code != 0 { if cmdres.exit_code != 0 {
errors++ errors++
println('Failed installing module "$mod.name" to "$final_module_path" .') println('Failed installing module "$name" to "$final_module_path" .')
verbose_println('Failed command: $cmd')
verbose_println('Failed command output:\n$cmdres.output')
continue
}
resolve_dependencies(name, final_module_path, module_names)
}
if errors > 0 {
exit(1)
}
}
fn vpm_install_from_vcs(module_names []string, vcs_key string) {
mut errors := 0
for n in module_names {
url := n.trim_space()
first_cut_pos := url.last_index('/') or {
errors++
println('Errors while retrieving name for module $url:')
println(err)
continue
}
mod_name := url.substr(first_cut_pos + 1, url.len)
second_cut_pos := url.substr(0, first_cut_pos).last_index('/') or {
errors++
println('Errors while retrieving name for module $url:')
println(err)
continue
}
repo_name := url.substr(second_cut_pos + 1, first_cut_pos)
mut name := repo_name + os.path_separator + mod_name
mod_name_as_path := name.replace('-', '_').to_lower()
mut final_module_path := os.real_path(os.join_path(settings.vmodules_path, mod_name_as_path))
if os.exists(final_module_path) {
vpm_update([name.replace('-', '_')])
continue
}
println('Installing module "$name" from $url to $final_module_path ...')
vcs_install_cmd := supported_vcs_install_cmds[vcs_key]
cmd := '$vcs_install_cmd "$url" "$final_module_path"'
verbose_println(' command: $cmd')
cmdres := os.execute(cmd)
if cmdres.exit_code != 0 {
errors++
println('Failed installing module "$name" to "$final_module_path" .')
verbose_println('Failed command: $cmd') verbose_println('Failed command: $cmd')
verbose_println('Failed command output:\n$cmdres.output') verbose_println('Failed command output:\n$cmdres.output')
mod.failed = true
continue continue
} }
vmod_path := os.join_path(final_module_path, 'v.mod') vmod_path := os.join_path(final_module_path, 'v.mod')
if os.exists(vmod_path) { if os.exists(vmod_path) {
vmod := module_from_file(vmod_path) or { data := os.read_file(vmod_path) or { return }
println('Error in reading v.mod from "$vmod_path":') vmod := parse_vmod(data)
println(err) mod_path := os.real_path(os.join_path(settings.vmodules_path, vmod.name.replace('.',
continue os.path_separator)))
} println('Relocating module from "$name" to "$vmod.name" ( $mod_path ) ...')
mod_path := vmod.path()
if final_module_path == mod_path {
continue
}
println('Relocating module from "$mod.name" to "$vmod.name" ( $mod_path ) ...')
if os.exists(mod_path) { if os.exists(mod_path) {
println('Warning module "$mod_path" already exsits!') println('Warning module "$mod_path" already exsits!')
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
}
println('Removing module "$mod_path" ...') println('Removing module "$mod_path" ...')
os.rmdir_all(mod_path) or { os.rmdir_all(mod_path) or {
errors++ errors++
@ -391,111 +279,129 @@ fn vpm_install(mut modules map[string]Mod) {
} }
os.mv(final_module_path, mod_path) or { os.mv(final_module_path, mod_path) or {
errors++ errors++
println('Errors while relocating module "$mod.name" :') println('Errors while relocating module "$name" :')
println(err) println(err)
os.rmdir_all(final_module_path) or {
errors++
println('Errors while removing "$final_module_path" :')
println(err)
continue
}
continue continue
} }
println('Module "$mod.name" relocated to "$vmod.name" successfully.') println('Module "$name" relocated to "$vmod.name" successfully.')
final_module_path = mod_path final_module_path = mod_path
mod.name = vmod.name name = vmod.name
} }
resolve_dependencies(os.join_path(mod.path(), 'v.mod'), mut modules) resolve_dependencies(name, final_module_path, module_names)
} }
if errors > 0 { if errors > 0 {
exit(1) exit(1)
} }
} }
fn vpm_update(mut modules map[string]Mod) { fn vpm_install(module_names []string, source Source) {
if settings.is_help {
vhelp.show_topic('install')
exit(0)
}
if module_names.len == 0 {
println('´v install´ requires *at least one* module name.')
exit(2)
}
if source == .vpm {
vpm_install_from_vpm(module_names)
}
if source == .git {
vpm_install_from_vcs(module_names, 'git')
}
if source == .hg {
vpm_install_from_vcs(module_names, 'hg')
}
}
fn vpm_update(m []string) {
mut module_names := m.clone()
if settings.is_help {
vhelp.show_topic('update')
exit(0)
}
if module_names.len == 0 {
module_names = get_installed_modules()
}
mut errors := 0 mut errors := 0
for _, mut mod in modules { for name in module_names {
if mod.updated || mod.failed { final_module_path := valid_final_path_of_existing_module(name) or { continue }
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
}
os.chdir(final_module_path) os.chdir(final_module_path)
println('Updating module "$mod.name"...') println('Updating module "$name"...')
verbose_println(' work folder: $final_module_path') verbose_println(' work folder: $final_module_path')
vcs := vcs_used_in_path(final_module_path) vcs := vcs_used_in_dir(final_module_path) or { continue }
vcs_cmd := supported_vcs_update_cmds[vcs] vcs_cmd := supported_vcs_update_cmds[vcs[0]]
verbose_println(' command: $vcs_cmd') verbose_println(' command: $vcs_cmd')
vcs_res := os.execute('$vcs_cmd') vcs_res := os.execute('$vcs_cmd')
if vcs_res.exit_code != 0 { if vcs_res.exit_code != 0 {
errors++ errors++
println('Failed updating module "$mod.name".') println('Failed updating module "$name".')
verbose_println('Failed command: $vcs_cmd') verbose_println('Failed command: $vcs_cmd')
verbose_println('Failed details:\n$vcs_res.output') verbose_println('Failed details:\n$vcs_res.output')
mod.failed = true
continue continue
} else { } else {
verbose_println(' $vcs_res.output.trim_space()') verbose_println(' $vcs_res.output.trim_space()')
mod.updated = true
mod.installed = true
} }
resolve_dependencies(os.join_path(mod.path(), 'v.mod'), mut modules) resolve_dependencies(name, final_module_path, module_names)
} }
if errors > 0 { if errors > 0 {
exit(1) exit(1)
} }
} }
fn get_outdated() ?map[string]Mod { fn get_outdated() ?[]string {
modules := get_installed_modules() module_names := get_installed_modules()
mut outdated := map[string]Mod{} mut outdated := []string{}
for _, mod in modules { for name in module_names {
final_module_path := mod.path() final_module_path := valid_final_path_of_existing_module(name) or { continue }
os.chdir(final_module_path) os.chdir(final_module_path)
vcs := vcs_used_in_path(final_module_path) vcs := vcs_used_in_dir(final_module_path) or { continue }
vcs_cmd_steps := supported_vcs_outdated_steps[vcs] vcs_cmd_steps := supported_vcs_outdated_steps[vcs[0]]
mut outputs := []string{} mut outputs := []string{}
for step in vcs_cmd_steps { for step in vcs_cmd_steps {
res := os.execute(step) res := os.execute(step)
if res.exit_code < 0 { if res.exit_code < 0 {
verbose_println('Error command: $step') verbose_println('Error command: $step')
verbose_println('Error details:\n$res.output') verbose_println('Error details:\n$res.output')
panic('Error while checking latest commits for "$mod.name".') return error('Error while checking latest commits for "$name".')
} }
if vcs == 'hg' { if vcs[0] == 'hg' {
if res.exit_code == 1 { if res.exit_code == 1 {
outdated[mod.name] = mod outdated << name
} }
} else { } else {
outputs << res.output outputs << res.output
} }
} }
if vcs == 'git' && outputs[1] != outputs[2] { if vcs[0] == 'git' && outputs[1] != outputs[2] {
outdated[mod.name] = mod outdated << name
} }
} }
return outdated return outdated
} }
fn vpm_upgrade() { fn vpm_upgrade() {
mut outdated := get_outdated() or { outdated := get_outdated() or { exit(1) }
println(err)
exit(1)
}
if outdated.len > 0 { if outdated.len > 0 {
vpm_update(mut &outdated) vpm_update(outdated)
} else { } else {
println('Modules are up to date.') println('Modules are up to date.')
} }
} }
fn vpm_outdated() { fn vpm_outdated() {
outdated := get_outdated() or { outdated := get_outdated() or { exit(1) }
println(err)
exit(1)
}
if outdated.len > 0 { if outdated.len > 0 {
println('Outdated modules:') println('Outdated modules:')
for _, m in outdated { for m in outdated {
println(' $m.name') println(' $m')
} }
} else { } else {
println('Modules are up to date.') println('Modules are up to date.')
@ -503,14 +409,14 @@ fn vpm_outdated() {
} }
fn vpm_list() { fn vpm_list() {
modules := get_installed_modules() module_names := get_installed_modules()
if modules.len == 0 { if module_names.len == 0 {
println('You have no modules installed.') println('You have no modules installed.')
exit(0) exit(0)
} }
println('Installed modules:') println('Installed modules:')
for _, mod in modules { for mod in module_names {
println(' $mod.name') println(' $mod')
} }
} }
@ -546,16 +452,21 @@ fn vpm_remove(module_names []string) {
} }
fn valid_final_path_of_existing_module(name string) ?string { fn valid_final_path_of_existing_module(name string) ?string {
final_module_path := real_path_of_module(name) 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)
final_module_path := os.real_path(name_of_vmodules_folder)
if !os.exists(final_module_path) { if !os.exists(final_module_path) {
println('No module with name "$name" exists at $final_module_path') println('No module with name "$name" exists at $name_of_vmodules_folder')
return none return none
} }
if !os.is_dir(final_module_path) { if !os.is_dir(final_module_path) {
println('Skipping "$final_module_path", since it is not a folder.') println('Skipping "$name_of_vmodules_folder", since it is not a folder.')
return none
}
vcs_used_in_dir(final_module_path) or {
println('Skipping "$name_of_vmodules_folder", since it does not use a supported vcs.')
return none return none
} }
return final_module_path return final_module_path
} }
@ -570,69 +481,44 @@ fn vpm_help() {
vhelp.show_topic('vpm') vhelp.show_topic('vpm')
} }
fn vcs_used_in_path(dir string) string { fn vcs_used_in_dir(dir string) ?[]string {
mut vcs := []string{}
for repo_subfolder in supported_vcs_folders { for repo_subfolder in supported_vcs_folders {
checked_folder := os.real_path(os.join_path(dir, repo_subfolder)) checked_folder := os.real_path(os.join_path(dir, repo_subfolder))
if os.is_dir(checked_folder) { if os.is_dir(checked_folder) {
return repo_subfolder.replace('.', '') vcs << repo_subfolder.replace('.', '')
} }
} }
return 'git' if vcs.len == 0 {
return none
}
return vcs
} }
fn get_installed_modules() map[string]Mod { fn get_installed_modules() []string {
dirs := os.ls(settings.vmodules_path) or { return map[string]Mod{} } dirs := os.ls(settings.vmodules_path) or { return [] }
mut modules := map[string]Mod{} mut modules := []string{}
for dir in dirs { for dir in dirs {
adir := os.join_path(settings.vmodules_path, dir) adir := os.join_path(settings.vmodules_path, dir)
if dir in excluded_dirs || !os.is_dir(adir) { if dir in excluded_dirs || !os.is_dir(adir) {
continue continue
} }
mut vmod_path := os.join_path(adir, 'v.mod') if os.exists(os.join_path(adir, 'v.mod')) && os.exists(os.join_path(adir, '.git', 'config')) {
if os.exists(vmod_path) && os.exists(os.join_path(adir, '.git', 'config')) {
// an official vlang module with a short module name, like `vsl`, `ui` or `markdown` // an official vlang module with a short module name, like `vsl`, `ui` or `markdown`
modules << dir
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
continue continue
} }
author := dir author := dir
mods := os.ls(adir) or { continue } mods := os.ls(adir) or { continue }
for m in mods { for m in mods {
vmod_path = os.join_path(adir, m, 'v.mod') vcs_used_in_dir(os.join_path(adir, m)) or { continue }
if os.exists(vmod_path) { modules << '${author}.$m'
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
}
} }
} }
return modules return modules
} }
fn get_all_modules() map[string]Mod { fn get_all_modules() []string {
url := get_working_server_url() url := get_working_server_url()
r := http.get(url) or { panic(err) } r := http.get(url) or { panic(err) }
if r.status_code != 200 { if r.status_code != 200 {
@ -641,7 +527,7 @@ fn get_all_modules() map[string]Mod {
} }
s := r.text s := r.text
mut read_len := 0 mut read_len := 0
mut names := []string{} mut modules := []string{}
for read_len < s.len { for read_len < s.len {
mut start_token := '<a href="/mod' mut start_token := '<a href="/mod'
end_token := '</a>' end_token := '</a>'
@ -659,89 +545,45 @@ fn get_all_modules() map[string]Mod {
if end_index == -1 { if end_index == -1 {
break break
} }
names << s[start_index..end_index] modules << s[start_index..end_index]
read_len = end_index read_len = end_index
if read_len >= s.len { if read_len >= s.len {
break break
} }
} }
mut modules := map[string]Mod{}
for name in names {
modules[name] = Mod{
name: name
}
}
return modules return modules
} }
fn resolve_dependencies(path string, mut modules map[string]Mod) { fn resolve_dependencies(name string, module_path string, module_names []string) {
manifest := vmod.from_file(path) or { return } vmod_path := os.join_path(module_path, 'v.mod')
url_query := r'([\w+]+\://)?((\w*@)?((\w+\.)+(\w*)))[/+\:](\w+)/([\w+\-]+)(\.\w*)?' if !os.exists(vmod_path) {
mod_query := r'(\w*)(\.\w*)?' return
}
mut url_re := regex.regex_opt(url_query) or { panic(err) } data := os.read_file(vmod_path) or { return }
mut mod_re := regex.regex_opt(mod_query) or { panic(err) } vmod := parse_vmod(data)
mut deps := []string{} mut deps := []string{}
for dep in manifest.dependencies { // filter out dependencies that were already specified by the user
if dep.starts_with('hg:') { for d in vmod.deps {
mod := module_from_url(dep[3..], 'hg') or { if d !in module_names {
println('Errors while retrieving meta data for module $dep:') deps << d
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
}
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!')
} }
if deps.len > 0 { if deps.len > 0 {
println('Resolving $deps.len dependencies for module "$manifest.name"...') println('Resolving $deps.len dependencies for module "$name"...')
verbose_println('Found dependencies: $deps') verbose_println('Found dependencies: $deps')
vpm_update(mut modules) vpm_install(deps, Source.vpm)
vpm_install(mut modules)
} }
} }
fn parse_vmod(data string) Vmod {
manifest := vmod.decode(data) or { vmod.Manifest{} }
mut vmod := Vmod{}
vmod.name = manifest.name
vmod.version = manifest.version
vmod.deps = manifest.dependencies
return vmod
}
fn get_working_server_url() string { fn get_working_server_url() string {
server_urls := if settings.server_urls.len > 0 { server_urls := if settings.server_urls.len > 0 {
settings.server_urls settings.server_urls
@ -759,6 +601,30 @@ fn get_working_server_url() string {
panic('No responding vpm server found. Please check your network connectivity and try again later.') panic('No responding vpm server found. Please check your network connectivity and try again later.')
} }
// settings context:
struct VpmSettings {
mut:
is_help bool
is_verbose bool
server_urls []string
vmodules_path string
}
const (
settings = &VpmSettings{}
)
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_verbose = '-v' in os.args
s.server_urls = cmdline.options(os.args, '-server-url')
s.vmodules_path = os.vmodules_dir()
}
fn verbose_println(s string) { fn verbose_println(s string) {
if settings.is_verbose { if settings.is_verbose {
println(s) println(s)
@ -804,30 +670,29 @@ fn get_module_meta_info(name string) ?Mod {
fn vpm_show(module_names []string) { fn vpm_show(module_names []string) {
installed_modules := get_installed_modules() installed_modules := get_installed_modules()
mut installed_modules_names := []string{}
for _, installed in installed_modules {
installed_modules_names << installed.name
}
for module_name in module_names { for module_name in module_names {
if module_name !in installed_modules_names { if module_name !in installed_modules {
module_meta_info := get_module_meta_info(module_name) or { continue } module_meta_info := get_module_meta_info(module_name) or { continue }
println('Name: $module_meta_info.name') print('
println('Homepage: $module_meta_info.url') Name: $module_meta_info.name
println('Downloads: $module_meta_info.nr_downloads') Homepage: $module_meta_info.url
println('Installed: False') Downloads: $module_meta_info.nr_downloads
println('--------') Installed: False
--------
')
continue continue
} }
path := real_path_of_module(module_name) path := os.join_path(os.vmodules_dir(), module_name.replace('.', os.path_separator))
mod := vmod.from_file(path) or { continue } mod := vmod.from_file(os.join_path(path, 'v.mod')) or { continue }
println('Name: $mod.name') print('Name: $mod.name
println('Version: $mod.version') Version: $mod.version
println('Description: $mod.description') Description: $mod.description
println('Homepage: $mod.repo_url') Homepage: $mod.repo_url
println('Author: $mod.author') Author: $mod.author
println('License: $mod.license') License: $mod.license
println('Location: $path') Location: $path
println('Requires: ${mod.dependencies.join(', ')}') Requires: ${mod.dependencies.join(', ')}
println('--------') --------
')
} }
} }

View File

@ -1,13 +1,13 @@
Usage: Usage:
v install [GIT_REPO_URL...|MODULE...] v install [MODULE...]
Installs each MODULE. Installs each MODULE.
If no MODULEs, the modules listed in the `v.mod` file are installed instead. If no MODULEs, the modules listed in the `v.mod` file are installed instead.
Options: Options:
-git - Install from git repository url --vpm - [Default] Install from vpm
-hg - Install from mercurial repository url --git - Install from git repository url
-f|-force - force module installation, regardless of existing install --hg - Install from mercurial repository url
-help - Show usage info. -help - Show usage info.
-v - Print more details about the performed operation. -v - Print more details about the performed operation.
-server-url - When doing network operations, use this vpm server. Can be given multiple times. -server-url - When doing network operations, use this vpm server. Can be given multiple times.

View File

@ -2463,13 +2463,12 @@ v install ui
``` ```
Modules could install directly from git or mercurial repositories. Modules could install directly from git or mercurial repositories.
The -git flag is the default for repository urls, and can be skipped.
```powershell ```powershell
v install [-git|-hg] [url] v install [--git|--hg] [url]
``` ```
**Example:** **Example:**
```powershell ```powershell
v install https://github.com/vlang/markdown v install --git https://github.com/vlang/markdown
``` ```
Removing a module with v: Removing a module with v: