Files
herolib/lib/develop/gittools/gittools_do.v
2025-12-01 10:35:46 +01:00

390 lines
9.2 KiB
V

module gittools
import incubaid.herolib.ui as gui
import incubaid.herolib.core.pathlib
import incubaid.herolib.ui.console
import os
pub const gitcmds = 'clone,commit,pull,push,delete,reload,list,edit,sourcetree,path,exists,check,lfs'
@[params]
pub struct ReposActionsArgs {
pub mut:
cmd string // clone,commit,pull,push,delete,reload,list,edit,sourcetree
filter string // if used will only show the repo's which have the filter string inside
repo string
account string
provider string
msg string
url string
branch string
path string // path to start from
recursive bool
pull bool
reload bool // means reload the info into the cache
script bool // run non interactive
reset bool // means we will lose changes (only relevant for clone, pull)
}
// do group actions on repo
// args
//```
// cmd string // clone,commit,pull,push,delete,reload,list,edit,sourcetree,cd
// filter string // if used will only show the repo's which have the filter string inside
// repo string
// account string
// provider string
// msg string
// url string
// pull bool
// reload bool //means reload the info into the cache
// script bool // run non interactive
// reset bool// means we will lose changes (only relevant for clone, pull)
//```
pub fn (mut gs GitStructure) do(args_ ReposActionsArgs) !string {
mut args := args_
console.print_debug('git do ${args.cmd}')
if args.path.len > 0 && args.url.len > 0 {
panic('bug')
}
if args.path.len > 0 && args.filter.len > 0 {
panic('bug')
}
if args.url.len > 0 && args.filter.len > 0 {
panic('bug')
}
if args.path != '' {
if args.path.contains('*') {
panic('bug')
}
if args.path == '.' {
// means current dir
args.path = os.getwd()
mut curdiro := pathlib.get_dir(path: args.path, create: false)!
// mut parentpath := curdiro.parent_find('.git') or { pathlib.Path{} }
args.path = curdiro.path
}
if !os.exists(args.path) {
return error('Path does not exist: ${args.path}')
}
r0 := gs.repo_init_from_path_(args.path)!
args.repo = r0.name
args.account = r0.account
args.provider = r0.provider
} else {
if args.url.len > 0 {
if !(args.repo == '' && args.account == '' && args.provider == '' && args.filter == '') {
return error('when specify url cannot specify repo, account, profider or filter')
}
mut r0 := gs.get_repo(url: args.url)!
args.repo = r0.name
args.account = r0.account
args.provider = r0.provider
}
}
args.cmd = args.cmd.trim_space().to_lower()
mut ui := gui.new()!
mut repos := gs.get_repos(
filter: args.filter
name: args.repo
account: args.account
provider: args.provider
)!
// println(repos.map(it.name))
if repos.len < 4 || args.cmd in 'pull,push,commit'.split(',') {
args.reload = true
}
for mut repo in repos {
repo.status_update(reset: args.reload || args.cmd == 'reload')!
}
if args.cmd == 'list' {
gs.repos_print(
filter: args.filter
name: args.repo
account: args.account
provider: args.provider
)!
return ''
}
if args.cmd == 'exists' {
return gs.check_repos_exist(args)
}
if args.cmd == 'path' {
if repos.len == 0 {
return error('No repository found for path command')
}
if repos.len > 1 {
return error('Multiple repositories found for path command, please be more specific')
}
return repos[0].path()
}
// means we are on 1 repo
if args.cmd in 'sourcetree,edit'.split(',') {
if repos.len == 0 {
return error('please specify at least 1 repo for cmd:${args.cmd}')
}
if repos.len > 4 {
return error('more than 4 repo found for cmd:${args.cmd}')
}
for mut r in repos {
if args.cmd == 'edit' {
r.open_vscode()!
}
if args.cmd == 'sourcetree' {
r.sourcetree()!
}
}
return ''
}
if args.cmd == 'clone' {
if args.url.len == 0 {
return error('URL needs to be specified for clone operation.')
}
gs.clone(url: args.url, recursive: args.recursive)!
return ''
}
if args.cmd in 'pull,push,commit,delete'.split(',') {
gs.repos_print(
filter: args.filter
name: args.repo
account: args.account
provider: args.provider
)!
mut need_commit0 := false
mut need_pull0 := false
mut need_push0 := false
if repos.len == 0 {
console.print_header(' - nothing to do.')
return ''
}
// check on repos who needs what
for mut g in repos {
if args.cmd == 'push' && g.need_push_or_pull()! {
need_push0 = true
}
if args.cmd in ['push', 'pull'] && (need_push0 || g.need_push_or_pull()!) {
need_pull0 = true
}
if args.cmd in ['push', 'pull', 'commit'] && (g.need_commit()!) {
need_commit0 = true
}
// console.print_debug(" --- status repo ${g.name}'s\n need_commit0:${need_commit0} \n need_pull0:${need_pull0} \n need_push0:${need_push0}")
}
// console.print_debug(" --- status all repo's\n need_commit0:${need_commit0} \n need_pull0:${need_pull0} \n need_push0:${need_push0}")
// $dbg;
mut ok := false
if need_commit0 || need_pull0 || need_push0 {
mut out := '\n\n** NEED TO '
if need_commit0 {
out += 'COMMIT '
}
if need_pull0 {
out += 'PULL '
}
if need_push0 {
out += 'PUSH '
}
if args.reset {
out += ' (changes will be lost!)'
}
console.print_debug(out + ' ** \n')
if args.script {
ok = true
} else {
if need_commit0 || need_pull0 || need_push0 {
ok = ui.ask_yesno(question: 'Is above ok?')!
} else {
console.print_green('nothing to do')
}
}
if ok == false {
return error('cannot continue with action, you asked me to stop.\n${args}')
}
if need_commit0 {
if args.msg.len == 0 && args.script {
return error('message needs to be specified for commit.')
}
if args.msg.len == 0 {
args.msg = ui.ask_question(
question: 'commit message for the actions: '
)!
}
}
}
if args.cmd == 'delete' {
if args.script {
ok = true
} else {
ok = ui.ask_yesno(question: 'Is it ok to delete above repos? (DANGEROUS)')!
}
if ok == false {
return error('cannot continue with action, you asked me to stop.\n${args}')
}
}
mut has_changed := false
for mut g in repos {
need_push_repo := need_push0 && g.need_push_or_pull()!
need_pull_repo := need_push_repo || (need_pull0 && g.need_push_or_pull()!)
need_commit_repo := need_push_repo || need_pull_repo
|| (need_commit0 && g.need_commit()!)
// console.print_debug(" --- git_do ${g.cache_key()} \n need_commit_repo:${need_commit_repo} \n need_pull_repo:${need_pull_repo} \n need_push_repo:${need_push_repo}")
if need_commit_repo {
mut msg := args.msg
console.print_header(' - commit ${g.account}/${g.name}')
g.commit(msg)!
has_changed = true
}
if has_changed || need_pull_repo {
if args.reset {
console.print_header(' - remove changes ${g.account}/${g.name}')
g.remove_changes()!
}
console.print_header(' - pull ${g.account}/${g.name}')
g.pull()!
has_changed = true
}
if has_changed || need_push_repo {
console.print_header(' - push ${g.account}/${g.name}')
g.push()!
has_changed = true
}
if args.cmd == 'delete' {
g.delete()!
has_changed = true
}
}
if has_changed {
// console.clear()
console.print_header('Completed required actions.\n')
gs.repos_print(
filter: args.filter
name: args.repo
account: args.account
provider: args.provider
)!
}
return ''
}
// end for the commit, pull, push, delete
if args.cmd == 'check' {
gs.repos_print(
filter: args.filter
name: args.repo
account: args.account
provider: args.provider
)!
if repos.len == 0 {
console.print_header(' - nothing to check.')
return ''
}
mut ok := false
if args.script {
ok = true
} else {
ok = ui.ask_yesno(question: 'Run check on ${repos.len} repo(s)?')!
}
if !ok {
return error('Check cancelled by user.\n${args}')
}
for mut repo in repos {
console.print_header(' - checking LFS for ${repo.account}/${repo.name}')
repo.lfs_check() or {
console.print_stderr('LFS check failed for ${repo.name}: ${err}')
continue
}
}
return ''
}
if args.cmd == 'lfs' {
gs.repos_print(
filter: args.filter
name: args.repo
account: args.account
provider: args.provider
)!
if repos.len == 0 {
console.print_header(' - nothing to initialize.')
return ''
}
mut ok := false
if args.script {
ok = true
} else {
ok = ui.ask_yesno(
question: 'Initialize LFS for ${repos.len} repo(s)? This will modify repository configuration.'
)!
}
if !ok {
return error('LFS initialization cancelled by user.\n${args}')
}
for mut repo in repos {
console.print_header(' - initializing LFS for ${repo.account}/${repo.name}')
repo.lfs_init() or {
console.print_stderr('LFS initialization failed for ${repo.name}: ${err}')
if !args.script {
continue_anyway := ui.ask_yesno(
question: 'Continue with remaining repositories?'
)!
if !continue_anyway {
return error('LFS initialization stopped by user.')
}
}
continue
}
console.print_green('LFS initialized successfully for ${repo.name}')
}
return ''
}
$if debug {
print_backtrace()
}
return error('did not find cmd: ${args.cmd}')
}