v / cmd / tools / vpm / update.v
80 lines · 75 sloc · 2.62 KB · 9317f4b5078c90aee517b362099900f8f34c21ef
Raw
1module main
2
3import os
4import sync.pool
5import v.help
6
7struct UpdateSession {
8 idents []string
9}
10
11pub struct UpdateResult {
12mut:
13 success bool
14}
15
16fn vpm_update(query []string) {
17 if settings.is_help {
18 help.print_and_exit('update')
19 }
20 idents := if query.len == 0 { get_installed_modules() } else { query.clone() }
21 mut pp := pool.new_pool_processor(callback: update_module)
22 ctx := UpdateSession{idents}
23 pp.set_shared_context(ctx)
24 pp.work_on_items(idents)
25 mut errors := 0
26 for res in pp.get_results[UpdateResult]() {
27 if !res.success {
28 errors++
29 continue
30 }
31 }
32 if errors > 0 {
33 exit(1)
34 }
35}
36
37fn update_module(mut pp pool.PoolProcessor, idx int, _wid int) &UpdateResult {
38 ident := pp.get_item[string](idx)
39 install_path := get_path_of_existing_module(ident) or {
40 fallback_name := get_name_from_url(ident) or { ident }
41 vpm_error('failed to find path for `${fallback_name}`.', verbose: true)
42 return &UpdateResult{}
43 }
44 // Derive the canonical module name from the install path so URL-based
45 // updates report the registered name (e.g. `spytheman.vtray` for
46 // `<vmodules>/spytheman/vtray`) instead of the bare URL-derived `vtray`.
47 // Normalize both sides via real_path so macOS's `/tmp` -> `/private/tmp`
48 // resolution doesn't leave the prefix unstripped.
49 vmodules_real := os.real_path(settings.vmodules_path)
50 rel_install_path := install_path.trim_string_left(vmodules_real).trim_left(os.path_separator)
51 name := rel_install_path.replace(os.path_separator, '.')
52 vcs := vcs_used_in_dir(install_path) or {
53 vpm_error('failed to find version control system for `${name}`.', verbose: true)
54 return &UpdateResult{}
55 }
56 vcs.is_executable() or {
57 vpm_error(err.msg())
58 return &UpdateResult{}
59 }
60 args := vcs_info[vcs].args
61 cmd := [vcs.str(), args.path, os.quoted_path(install_path), args.update].join(' ')
62 vpm_log(@FILE_LINE, @FN, 'cmd: ${cmd}')
63 println('Updating module `${name}` in `${fmt_mod_path(install_path)}`...')
64 res := os.execute_opt(cmd) or {
65 vpm_error('failed to update module `${name}` in `${install_path}`.', details: err.msg())
66 return &UpdateResult{}
67 }
68 vpm_log(@FILE_LINE, @FN, 'cmd output: ${res.output.trim_space()}')
69 if res.output.contains('Already up to date.') {
70 println('Skipped module `${ident}`. Already up to date.')
71 } else {
72 println('Updated module `${ident}`.')
73 }
74 // Don't bail if the download count increment has failed.
75 increment_module_download_count(name, '') or { vpm_error(err.msg(), verbose: true) }
76 ctx := unsafe { &UpdateSession(pp.get_shared_context()) }
77 vpm_log(@FILE_LINE, @FN, 'ident: ${ident}; ctx: ${ctx}')
78 resolve_dependencies(get_manifest(install_path), ctx.idents)
79 return &UpdateResult{true}
80}
81