@@ -9,40 +9,95 @@ import net.urllib
9
9
import term
10
10
import log
11
11
12
- struct Mod {
13
- id int
12
+ struct Module {
13
+ mut :
14
+ // Fields that can be populated via VPM API.
15
+ name string
16
+ url string
17
+ vcs string
18
+ // Fields based on input / environment.
19
+ version string // specifies the requested version.
20
+ install_path string
21
+ is_installed bool
22
+ installed_version string
23
+ }
24
+
25
+ struct ModuleVpmInfo {
26
+ // id int
14
27
name string
15
28
url string
16
- nr_downloads int
17
29
vcs string
30
+ nr_downloads int
18
31
}
19
32
20
- pub struct ModDateInfo {
33
+ pub struct ModuleDateInfo {
21
34
name string
22
35
mut :
23
36
outdated bool
24
37
exec_err bool
25
38
}
26
39
27
- struct ModNameInfo {
28
- mut :
29
- mname string // The-user.The-mod , *never* The-user.The-mod.git
30
- mname_normalised string // the_user.the_mod
31
- mname_as_path string // the_user/the_mod
32
- final_module_path string // ~/.vmodules/the_user/the_mod
33
- }
34
-
35
40
[params]
36
41
struct ErrorOptions {
37
42
details string
38
43
verbose bool // is used to only output the error message if the verbose setting is enabled.
39
44
}
40
45
41
- fn get_mod_date_info (mut pp pool.PoolProcessor, idx int , wid int ) & ModDateInfo {
42
- mut result := & ModDateInfo{
46
+ fn parse_query (query []string ) ([]Module, []Module) {
47
+ mut vpm_modules, mut extended_modules := []Module{}, []Module{}
48
+ mut errors := 0
49
+ for m in query {
50
+ ident , version := m.rsplit_once ('@' ) or { m, '' }
51
+ mut is_external := false
52
+ mut mod := if ident.starts_with ('https://' ) {
53
+ is_external = true
54
+ name := get_name_from_url (ident) or {
55
+ vpm_error (err.msg ())
56
+ errors++
57
+ continue
58
+ }
59
+ Module{
60
+ name: name
61
+ url: ident
62
+ install_path: os.real_path (os.join_path (settings.vmodules_path, name))
63
+ }
64
+ } else {
65
+ info := get_mod_vpm_info (ident) or {
66
+ vpm_error ('failed to retrieve metadata for `${ident} `.' , details: err.msg ())
67
+ errors++
68
+ continue
69
+ }
70
+ name_normalized := info.name.replace ('-' , '_' ).to_lower ()
71
+ name_as_path := name_normalized.replace ('.' , os.path_separator)
72
+ Module{
73
+ name: info.name
74
+ url: info.url
75
+ vcs: info.vcs
76
+ install_path: os.real_path (os.join_path (settings.vmodules_path, name_as_path))
77
+ }
78
+ }
79
+ mod.version = version
80
+ if v := os.execute_opt ('git ls-remote --tags ${mod.install_path} ' ) {
81
+ mod.is_installed = true
82
+ mod.installed_version = v.output.all_after_last ('/' ).trim_space ()
83
+ }
84
+ if is_external {
85
+ extended_modules << mod
86
+ } else {
87
+ vpm_modules << mod
88
+ }
89
+ }
90
+ if errors > 0 && errors == query.len {
91
+ exit (1 )
92
+ }
93
+ return vpm_modules, extended_modules
94
+ }
95
+
96
+ fn get_mod_date_info (mut pp pool.PoolProcessor, idx int , wid int ) & ModuleDateInfo {
97
+ mut result := & ModuleDateInfo{
43
98
name: pp.get_item[string ](idx)
44
99
}
45
- final_module_path := valid_final_path_of_existing_module (result.name) or { return result }
100
+ final_module_path := get_path_of_existing_module (result.name) or { return result }
46
101
vcs := vcs_used_in_dir (final_module_path) or { return result }
47
102
is_hg := vcs.cmd == 'hg'
48
103
mut outputs := []string {}
@@ -68,26 +123,14 @@ fn get_mod_date_info(mut pp pool.PoolProcessor, idx int, wid int) &ModDateInfo {
68
123
return result
69
124
}
70
125
71
- fn get_mod_name_info (mod_name string ) ModNameInfo {
72
- mut info := ModNameInfo{}
73
- info.mname = if mod_name.ends_with ('.git' ) { mod_name.replace ('.git' , '' ) } else { mod_name }
74
- info.mname_normalised = info.mname.replace ('-' , '_' ).to_lower ()
75
- info.mname_as_path = info.mname_normalised.replace ('.' , os.path_separator)
76
- info.final_module_path = os.real_path (os.join_path (settings.vmodules_path, info.mname_as_path))
77
- return info
78
- }
79
-
80
- fn get_module_meta_info (name string ) ! Mod {
81
- if mod := get_mod_by_url (name) {
82
- return mod
83
- }
126
+ fn get_mod_vpm_info (name string ) ! ModuleVpmInfo {
84
127
if name.len < 2 || (! name[0 ].is_digit () && ! name[0 ].is_letter ()) {
85
128
return error ('invalid module name `${name} `.' )
86
129
}
87
130
mut errors := []string {}
88
131
for server_url in vpm_server_urls {
89
132
modurl := server_url + '/api/packages/${name} '
90
- verbose_println ('Retrieving module metadata from `${modurl} ` ...' )
133
+ verbose_println ('Retrieving metadata for ` ${name} ` from `${modurl} `...' )
91
134
r := http.get (modurl) or {
92
135
errors << 'Http server did not respond to our request for `${modurl} `.'
93
136
errors << 'Error details: ${err} '
@@ -104,41 +147,39 @@ fn get_module_meta_info(name string) !Mod {
104
147
s := r.body
105
148
if s.len > 0 && s[0 ] != `{` {
106
149
errors << 'Invalid json data'
107
- errors << s.trim_space ().limit (100 ) + ' ...'
150
+ errors << s.trim_space ().limit (100 ) + '...'
108
151
continue
109
152
}
110
- mod := json.decode (Mod , s) or {
153
+ mod := json.decode (ModuleVpmInfo , s) or {
111
154
errors << 'Skipping module `${name} `, since its information is not in json format.'
112
155
continue
113
156
}
114
157
if '' == mod.url || '' == mod.name {
115
158
errors << 'Skipping module `${name} `, since it is missing name or url information.'
116
159
continue
117
160
}
161
+ vpm_log (@FILE_LINE, @FN, 'name: ${name} ; mod: ${mod} ' )
118
162
return mod
119
163
}
120
164
return error (errors.join_lines ())
121
165
}
122
166
123
- fn get_mod_by_url (name string ) ! Mod {
124
- if purl := urllib.parse (name) {
125
- verbose_println ('purl: ${purl} ' )
126
- mod := Mod{
127
- name: purl.path.trim_left ('/' ).trim_right ('/' ).replace ('/' , '.' )
128
- url: name
129
- }
130
- verbose_println (mod.str ())
131
- return mod
167
+ fn get_name_from_url (raw_url string ) ! string {
168
+ url := urllib.parse (raw_url) or { return error ('failed to parse module URL `${raw_url} `.' ) }
169
+ owner, mut name := url.path.trim_left ('/' ).rsplit_once ('/' ) or {
170
+ return error ('failed to retrieve module name for `${url} `.' )
132
171
}
133
- return error ('invalid url: ${name} ' )
172
+ vpm_log (@FILE_LINE, @FN, 'raw_url: ${raw_url} ; owner: ${owner} ; name: ${name} ' )
173
+ name = if name.ends_with ('.git' ) { name.replace ('.git' , '' ) } else { name }
174
+ return name.replace ('-' , '_' ).to_lower ()
134
175
}
135
176
136
177
fn get_outdated () ! []string {
137
178
module_names := get_installed_modules ()
138
179
mut outdated := []string {}
139
180
mut pp := pool.new_pool_processor (callback: get_mod_date_info)
140
181
pp.work_on_items (module_names)
141
- for res in pp.get_results[ModDateInfo ]() {
182
+ for res in pp.get_results[ModuleDateInfo ]() {
142
183
if res.exec_err {
143
184
return error ('failed to check the latest commits for `${res.name} `.' )
144
185
}
@@ -297,14 +338,6 @@ fn resolve_dependencies(name string, module_path string, module_names []string)
297
338
}
298
339
}
299
340
300
- fn url_to_module_name (modulename string ) string {
301
- mut res := if mod := get_mod_by_url (modulename) { mod.name } else { modulename }
302
- if res.ends_with ('.git' ) {
303
- res = res.replace ('.git' , '' )
304
- }
305
- return res
306
- }
307
-
308
341
fn vcs_used_in_dir (dir string ) ? VCS {
309
342
for vcs in supported_vcs.values () {
310
343
if os.is_dir (os.real_path (os.join_path (dir, vcs.dir))) {
@@ -314,22 +347,22 @@ fn vcs_used_in_dir(dir string) ?VCS {
314
347
return none
315
348
}
316
349
317
- fn valid_final_path_of_existing_module (modulename string ) ? string {
318
- name := if mod := get_mod_by_url (modulename) { mod.name } else { modulename }
319
- minfo := get_mod_name_info ( name)
320
- if ! os.exists (minfo.final_module_path ) {
321
- vpm_error ('failed to find a module with name `${minfo.mname_normalised } ` at `${minfo.final_module_path} ` ' )
350
+ fn get_path_of_existing_module (mod_name string ) ? string {
351
+ name := get_name_from_url (mod_name) or { mod_name. replace ( '-' , '_' ). to_lower () }
352
+ path := os. real_path (os. join_path (settings.vmodules_path, name. replace ( '.' , os.path_separator)) )
353
+ if ! os.exists (path ) {
354
+ vpm_error ('failed to find `${name } ` at `${path} `. ' )
322
355
return none
323
356
}
324
- if ! os.is_dir (minfo.final_module_path ) {
325
- vpm_error ('skipping `${minfo.final_module_path } `, since it is not a directory.' )
357
+ if ! os.is_dir (path ) {
358
+ vpm_error ('skipping `${path } `, since it is not a directory.' )
326
359
return none
327
360
}
328
- vcs_used_in_dir (minfo.final_module_path ) or {
329
- vpm_error ('skipping `${minfo.final_module_path } `, since it uses an unsupported version control system.' )
361
+ vcs_used_in_dir (path ) or {
362
+ vpm_error ('skipping `${path } `, since it uses an unsupported version control system.' )
330
363
return none
331
364
}
332
- return minfo.final_module_path
365
+ return path
333
366
}
334
367
335
368
fn verbose_println (s string ) {
0 commit comments