390 lines
9.2 KiB
V
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}')
|
|
}
|