| 1 | module main |
| 2 | |
| 3 | import os |
| 4 | import rand |
| 5 | import v.vmod |
| 6 | import test_utils { cmd_ok } |
| 7 | |
| 8 | const test_path = os.join_path(os.vtmp_dir(), 'vpm_install_local_test_${rand.ulid()}') |
| 9 | |
| 10 | struct LocalInstallCase { |
| 11 | args string |
| 12 | module_name string |
| 13 | workdir string |
| 14 | } |
| 15 | |
| 16 | fn testsuite_begin() { |
| 17 | test_utils.set_test_env(test_path) |
| 18 | } |
| 19 | |
| 20 | fn testsuite_end() { |
| 21 | os.rmdir_all(test_path) or {} |
| 22 | } |
| 23 | |
| 24 | fn test_install_from_local_git_repository_variants() { |
| 25 | repo_path := os.join_path(test_path, 'local_repo') |
| 26 | repo_dot_git_path := os.join_path(test_path, 'local_repo.git') |
| 27 | create_local_git_module(repo_path, 'local_repo_pkg') |
| 28 | create_local_git_module(repo_dot_git_path, 'local_repo_dot_git_pkg') |
| 29 | |
| 30 | cases := [ |
| 31 | LocalInstallCase{ |
| 32 | args: os.quoted_path(repo_path) |
| 33 | module_name: 'local_repo_pkg' |
| 34 | }, |
| 35 | LocalInstallCase{ |
| 36 | args: file_url(repo_path) |
| 37 | module_name: 'local_repo_pkg' |
| 38 | }, |
| 39 | LocalInstallCase{ |
| 40 | args: '--git ${os.quoted_path(repo_path)}' |
| 41 | module_name: 'local_repo_pkg' |
| 42 | }, |
| 43 | LocalInstallCase{ |
| 44 | args: '--git ${file_url(repo_path)}' |
| 45 | module_name: 'local_repo_pkg' |
| 46 | }, |
| 47 | LocalInstallCase{ |
| 48 | args: os.file_name(repo_path) |
| 49 | module_name: 'local_repo_pkg' |
| 50 | workdir: test_path |
| 51 | }, |
| 52 | LocalInstallCase{ |
| 53 | args: os.quoted_path(repo_dot_git_path) |
| 54 | module_name: 'local_repo_dot_git_pkg' |
| 55 | }, |
| 56 | LocalInstallCase{ |
| 57 | args: file_url(repo_dot_git_path) |
| 58 | module_name: 'local_repo_dot_git_pkg' |
| 59 | }, |
| 60 | LocalInstallCase{ |
| 61 | args: '--git ${os.quoted_path(repo_dot_git_path)}' |
| 62 | module_name: 'local_repo_dot_git_pkg' |
| 63 | }, |
| 64 | LocalInstallCase{ |
| 65 | args: '--git ${file_url(repo_dot_git_path)}' |
| 66 | module_name: 'local_repo_dot_git_pkg' |
| 67 | }, |
| 68 | LocalInstallCase{ |
| 69 | args: os.file_name(repo_dot_git_path) |
| 70 | module_name: 'local_repo_dot_git_pkg' |
| 71 | workdir: test_path |
| 72 | }, |
| 73 | ] |
| 74 | for i, c in cases { |
| 75 | vmodules_path := os.join_path(test_path, 'vmodules_case_${i}') |
| 76 | test_utils.set_test_env(vmodules_path) |
| 77 | cmd := '${vexe} install ${c.args}' |
| 78 | old_dir := os.getwd() |
| 79 | if c.workdir != '' { |
| 80 | os.chdir(c.workdir) or { panic(err) } |
| 81 | } |
| 82 | res := cmd_ok(@LOCATION, cmd) |
| 83 | if c.workdir != '' { |
| 84 | os.chdir(old_dir) or {} |
| 85 | } |
| 86 | assert res.output.contains('Installed `${c.module_name}`'), res.output |
| 87 | manifest := vmod.from_file(os.join_path(vmodules_path, c.module_name, 'v.mod')) or { |
| 88 | panic('Failed to parse v.mod for `${c.module_name}`. ${err}') |
| 89 | } |
| 90 | assert manifest.name == c.module_name |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | // Regression test for https://github.com/vlang/v/issues/27192. |
| 95 | // VPM-registered installs lowercase the on-disk path via `normalize_mod_path`, |
| 96 | // so `v update <Ident>` and `v remove <Ident>` must apply the same |
| 97 | // normalization when looking up existing modules — otherwise users with |
| 98 | // capitalized publisher names (e.g. `Frothy7650.chalk`) cannot update or |
| 99 | // remove the modules they just installed. |
| 100 | fn test_update_and_remove_with_capitalized_ident() { |
| 101 | vmodules_path := os.join_path(test_path, 'vmodules_capitalized') |
| 102 | test_utils.set_test_env(vmodules_path) |
| 103 | // Simulate the post-install state of `v install Frothy7650.chalk`: |
| 104 | // a real VPM install places the module under the lowercased publisher dir. |
| 105 | publisher_dir := os.join_path(vmodules_path, 'frothy7650') |
| 106 | installed_path := os.join_path(publisher_dir, 'chalk') |
| 107 | os.mkdir_all(installed_path) or { panic(err) } |
| 108 | os.write_file(os.join_path(installed_path, 'v.mod'), |
| 109 | "Module{\n\tname: 'Frothy7650.chalk'\n\tversion: '0.0.1'\n}\n") or { panic(err) } |
| 110 | // Remove with the original (capitalized) ident must succeed and clean up the author dir. |
| 111 | res := cmd_ok(@LOCATION, '${vexe} remove Frothy7650.chalk') |
| 112 | assert !res.output.contains('failed to find'), res.output |
| 113 | assert !os.exists(installed_path) |
| 114 | assert !os.exists(publisher_dir) |
| 115 | } |
| 116 | |
| 117 | fn create_local_git_module(repo_path string, module_name string) { |
| 118 | os.mkdir_all(repo_path) or { panic(err) } |
| 119 | os.write_file(os.join_path(repo_path, 'v.mod'), |
| 120 | "Module{\n\tname: '${module_name}'\n\tversion: '0.0.1'\n}\n") or { panic(err) } |
| 121 | cmd_ok(@LOCATION, 'git init ${os.quoted_path(repo_path)}') |
| 122 | cmd_ok(@LOCATION, 'git -C ${os.quoted_path(repo_path)} add v.mod') |
| 123 | cmd_ok(@LOCATION, |
| 124 | 'git -C ${os.quoted_path(repo_path)} -c user.email="[email protected]" -c user.name="V CI" commit -m "initial commit"') |
| 125 | } |
| 126 | |
| 127 | fn file_url(path string) string { |
| 128 | mut normalized_path := path.replace('\\', '/') |
| 129 | if !normalized_path.starts_with('/') { |
| 130 | normalized_path = '/${normalized_path}' |
| 131 | } |
| 132 | return 'file://${normalized_path}' |
| 133 | } |
| 134 | |