mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
105 lines
3 KiB
V
105 lines
3 KiB
V
module main
|
|
|
|
import os
|
|
import semver
|
|
|
|
// Supported version control system commands.
|
|
enum VCS {
|
|
git
|
|
hg
|
|
}
|
|
|
|
struct VCSInfo {
|
|
dir string @[required]
|
|
args struct {
|
|
install string @[required]
|
|
version string @[required] // flag to specify a version, added to install.
|
|
path string @[required] // flag to specify a path. E.g., used to explicitly work on a path during multithreaded updating.
|
|
update string @[required]
|
|
outdated []string @[required]
|
|
}
|
|
}
|
|
|
|
const vcs_info = init_vcs_info() or {
|
|
vpm_error(err.msg())
|
|
exit(1)
|
|
}
|
|
|
|
fn init_vcs_info() !map[VCS]VCSInfo {
|
|
git_installed_raw_ver := parse_git_version(os.execute_opt('git --version')!.output) or { '' }
|
|
git_installed_ver := semver.from(git_installed_raw_ver)!
|
|
git_submod_filter_ver := semver.from('2.36.0')!
|
|
mut git_install_cmd := 'clone --recursive --shallow-submodules --filter=blob:none'
|
|
if git_installed_ver >= git_submod_filter_ver {
|
|
git_install_cmd += ' --also-filter-submodules'
|
|
}
|
|
return {
|
|
VCS.git: VCSInfo{
|
|
dir: '.git'
|
|
args: struct {
|
|
install: git_install_cmd
|
|
version: '--single-branch -b'
|
|
update: 'pull --recurse-submodules' // pulling with `--depth=1` leads to conflicts when the upstream has more than 1 new commits.
|
|
path: '-C'
|
|
outdated: ['fetch', 'rev-parse @', 'rev-parse @{u}']
|
|
}
|
|
}
|
|
VCS.hg: VCSInfo{
|
|
dir: '.hg'
|
|
args: struct {
|
|
install: 'clone'
|
|
version: '--rev'
|
|
update: 'pull --update'
|
|
path: '-R'
|
|
outdated: ['incoming']
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn (vcs VCS) clone(url string, version string, path string) ! {
|
|
args := vcs_info[vcs].args
|
|
version_opt := if version != '' { '${args.version} ${version}' } else { '' }
|
|
cmd := [vcs.str(), args.install, version_opt, url, os.quoted_path(path)].join(' ')
|
|
vpm_log(@FILE_LINE, @FN, 'cmd: ${cmd}')
|
|
res := os.execute_opt(cmd)!
|
|
vpm_log(@FILE_LINE, @FN, 'cmd output: ${res.output}')
|
|
}
|
|
|
|
fn (vcs &VCS) is_executable() ! {
|
|
cmd := vcs.str()
|
|
os.find_abs_path_of_executable(cmd) or {
|
|
return error('VPM requires that `${cmd}` is executable.')
|
|
}
|
|
}
|
|
|
|
fn vcs_used_in_dir(dir string) ?VCS {
|
|
for vcs, info in vcs_info {
|
|
if os.is_dir(os.real_path(os.join_path(dir, info.dir))) {
|
|
return vcs
|
|
}
|
|
}
|
|
return none
|
|
}
|
|
|
|
fn vcs_from_str(str string) ?VCS {
|
|
return match str {
|
|
'git' { .git }
|
|
'hg' { .hg }
|
|
else { none }
|
|
}
|
|
}
|
|
|
|
// parse_git_version retrieves only the stable version part of the output of `git version`.
|
|
// For example: parse_git_version('git version 2.39.3')! will return just '2.39.3'.
|
|
pub fn parse_git_version(version string) !string {
|
|
git_version_start := 'git version '
|
|
// The output from `git version` varies, depending on how git was compiled. Here are some examples:
|
|
// `git version 2.44.0` when compiled from source, or from brew on macos.
|
|
// `git version 2.39.3 (Apple Git-146)` on macos with XCode's cli tools.
|
|
// `git version 2.44.0.windows.1` on windows's Git Bash shell.
|
|
if !version.starts_with(git_version_start) {
|
|
return error('should start with `${git_version_start}`')
|
|
}
|
|
return version.all_after(git_version_start).all_before(' ').all_before('.windows').trim_space()
|
|
}
|