Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tools: prepare vpm version installs #19821

Merged
merged 1 commit into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 58 additions & 63 deletions cmd/tools/vpm/common.v
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
module main

import json
import os
import v.vmod
import sync.pool
import net.http
import net.urllib
import sync.pool
import v.vmod
import json
import term
import log

struct Module {
mut:
// Fields that can be populated via VPM API.
// Fields determined by the url or the info received from the VPM API.
name string
url string
vcs string
// Fields based on input / environment.
// Fields based on preference / environment.
version string // specifies the requested version.
install_path string
is_installed bool
Expand Down Expand Up @@ -44,7 +44,7 @@ struct ErrorOptions {
}

fn parse_query(query []string) ([]Module, []Module) {
mut vpm_modules, mut extended_modules := []Module{}, []Module{}
mut vpm_modules, mut external_modules := []Module{}, []Module{}
mut errors := 0
for m in query {
ident, version := m.rsplit_once('@') or { m, '' }
Expand Down Expand Up @@ -82,27 +82,27 @@ fn parse_query(query []string) ([]Module, []Module) {
mod.installed_version = v.output.all_after_last('/').trim_space()
}
if is_external {
extended_modules << mod
external_modules << mod
} else {
vpm_modules << mod
}
}
if errors > 0 && errors == query.len {
exit(1)
}
return vpm_modules, extended_modules
return vpm_modules, external_modules
}

fn get_mod_date_info(mut pp pool.PoolProcessor, idx int, wid int) &ModuleDateInfo {
mut result := &ModuleDateInfo{
name: pp.get_item[string](idx)
}
final_module_path := get_path_of_existing_module(result.name) or { return result }
vcs := vcs_used_in_dir(final_module_path) or { return result }
path := get_path_of_existing_module(result.name) or { return result }
vcs := vcs_used_in_dir(path) or { return result }
is_hg := vcs.cmd == 'hg'
mut outputs := []string{}
for step in vcs.args.outdated {
cmd := '${vcs.cmd} ${vcs.args.path} "${final_module_path}" ${step}'
cmd := '${vcs.cmd} ${vcs.args.path} "${path}" ${step}'
res := os.execute(cmd)
if res.exit_code < 0 {
verbose_println('Error command: ${cmd}')
Expand All @@ -128,20 +128,20 @@ fn get_mod_vpm_info(name string) !ModuleVpmInfo {
return error('invalid module name `${name}`.')
}
mut errors := []string{}
for server_url in vpm_server_urls {
modurl := server_url + '/api/packages/${name}'
for url in vpm_server_urls {
modurl := url + '/api/packages/${name}'
verbose_println('Retrieving metadata for `${name}` from `${modurl}`...')
r := http.get(modurl) or {
errors << 'Http server did not respond to our request for `${modurl}`.'
errors << 'Error details: ${err}'
continue
}
if r.status_code == 404 || r.body.trim_space() == '404' {
errors << 'Skipping module `${name}`, since `${server_url}` reported that `${name}` does not exist.'
errors << 'Skipping module `${name}`, since `${url}` reported that `${name}` does not exist.'
continue
}
if r.status_code != 200 {
errors << 'Skipping module `${name}`, since `${server_url}` responded with ${r.status_code} http status code. Please try again later.'
errors << 'Skipping module `${name}`, since `${url}` responded with ${r.status_code} http status code. Please try again later.'
continue
}
s := r.body
Expand Down Expand Up @@ -175,10 +175,10 @@ fn get_name_from_url(raw_url string) !string {
}

fn get_outdated() ![]string {
module_names := get_installed_modules()
installed := get_installed_modules()
mut outdated := []string{}
mut pp := pool.new_pool_processor(callback: get_mod_date_info)
pp.work_on_items(module_names)
pp.work_on_items(installed)
for res in pp.get_results[ModuleDateInfo]() {
if res.exec_err {
return error('failed to check the latest commits for `${res.name}`.')
Expand All @@ -193,9 +193,7 @@ fn get_outdated() ![]string {
fn get_all_modules() []string {
url := get_working_server_url()
r := http.get(url) or {
vpm_error(err.msg(),
verbose: true
)
vpm_error(err.msg(), verbose: true)
exit(1)
}
if r.status_code != 200 {
Expand Down Expand Up @@ -259,6 +257,24 @@ fn get_installed_modules() []string {
return modules
}

fn get_path_of_existing_module(mod_name string) ?string {
name := get_name_from_url(mod_name) or { mod_name.replace('-', '_').to_lower() }
path := os.real_path(os.join_path(settings.vmodules_path, name.replace('.', os.path_separator)))
if !os.exists(path) {
vpm_error('failed to find `${name}` at `${path}`.')
return none
}
if !os.is_dir(path) {
vpm_error('skipping `${path}`, since it is not a directory.')
return none
}
vcs_used_in_dir(path) or {
vpm_error('skipping `${path}`, since it uses an unsupported version control system.')
return none
}
return path
}

fn get_working_server_url() string {
server_urls := if settings.server_urls.len > 0 {
settings.server_urls
Expand All @@ -268,27 +284,26 @@ fn get_working_server_url() string {
for url in server_urls {
verbose_println('Trying server url: ${url}')
http.head(url) or {
verbose_println(' ${url} failed.')
vpm_error('failed to connect to server url `${url}`.', details: err.msg())
continue
}
return url
}
panic('No responding vpm server found. Please check your network connectivity and try again later.')
vpm_error('No responding vpm server found. Please check your network connectivity and try again later.')
exit(1)
}

fn ensure_vmodules_dir_exist() {
if !os.is_dir(settings.vmodules_path) {
println('Creating `${settings.vmodules_path}` ...')
println('Creating `${settings.vmodules_path}`...')
os.mkdir(settings.vmodules_path) or {
vpm_error(err.msg(),
verbose: true
)
vpm_error(err.msg(), verbose: true)
exit(1)
}
}
}

fn ensure_vcs_is_installed(vcs &VCS) ! {
fn (vcs &VCS) is_executable() ! {
os.find_abs_path_of_executable(vcs.cmd) or {
return error('VPM needs `${vcs.cmd}` to be installed.')
}
Expand All @@ -300,39 +315,37 @@ fn increment_module_download_count(name string) ! {
return
}
mut errors := []string{}

for server_url in vpm_server_urls {
modurl := server_url + '/api/packages/${name}/incr_downloads'
for url in vpm_server_urls {
modurl := url + '/api/packages/${name}/incr_downloads'
r := http.post(modurl, '') or {
errors << 'Http server did not respond to our request for `${modurl}`.'
errors << 'Error details: ${err}'
continue
}
if r.status_code != 200 {
errors << 'Failed to increment the download count for module `${name}`, since `${server_url}` responded with ${r.status_code} http status code. Please try again later.'
errors << 'Failed to increment the download count for module `${name}`, since `${url}` responded with ${r.status_code} http status code. Please try again later.'
continue
}
return
}
return error(errors.join_lines())
}

fn resolve_dependencies(name string, module_path string, module_names []string) {
vmod_path := os.join_path(module_path, 'v.mod')
if !os.exists(vmod_path) {
return
}
manifest := vmod.from_file(vmod_path) or {
vpm_error(err.msg(),
verbose: true
)
return
fn get_manifest(path string) ?vmod.Manifest {
return vmod.from_file(os.join_path(path, 'v.mod')) or {
eprintln(term.ecolorize(term.yellow, 'warning: ') +
'failed to find v.mod file for `${path.all_after_last(os.path_separator)}`.')
return none
}
}

fn resolve_dependencies(manifest ?vmod.Manifest, modules []string) {
mod := manifest or { return }
// Filter out modules that are both contained in the input query and listed as
// dependencies in the mod file of the module that is supposed to be installed.
deps := manifest.dependencies.filter(it !in module_names)
deps := mod.dependencies.filter(it !in modules)
if deps.len > 0 {
println('Resolving ${deps.len} dependencies for module `${name}` ...')
println('Resolving ${deps.len} dependencies for module `${mod.name}`...')
verbose_println('Found dependencies: ${deps}')
vpm_install(deps)
}
Expand All @@ -347,27 +360,9 @@ fn vcs_used_in_dir(dir string) ?VCS {
return none
}

fn get_path_of_existing_module(mod_name string) ?string {
name := get_name_from_url(mod_name) or { mod_name.replace('-', '_').to_lower() }
path := os.real_path(os.join_path(settings.vmodules_path, name.replace('.', os.path_separator)))
if !os.exists(path) {
vpm_error('failed to find `${name}` at `${path}`.')
return none
}
if !os.is_dir(path) {
vpm_error('skipping `${path}`, since it is not a directory.')
return none
}
vcs_used_in_dir(path) or {
vpm_error('skipping `${path}`, since it uses an unsupported version control system.')
return none
}
return path
}

fn verbose_println(s string) {
fn verbose_println(msg string) {
if settings.is_verbose {
println(s)
println(msg)
}
}

Expand Down
Loading
Loading