gittools
This commit is contained in:
@@ -66,7 +66,7 @@ os.chmod('hero', 0o755) or { panic('Failed to make hero binary executable: ${err
|
||||
|
||||
// Ensure destination directory exists
|
||||
os.mkdir_all(os.dir(heropath)) or { panic('Failed to create directory ${os.dir(heropath)}: ${err}') }
|
||||
|
||||
println(heropath)
|
||||
// Copy to destination paths
|
||||
os.cp('hero', heropath) or { panic('Failed to copy hero binary to ${heropath}: ${err}') }
|
||||
os.cp('hero', '/tmp/hero') or { panic('Failed to copy hero binary to /tmp/hero: ${err}') }
|
||||
|
||||
@@ -1,30 +1,9 @@
|
||||
#!/usr/bin/env -S v -n -w -no-retry-compilation -d use_openssl -enable-globals run
|
||||
//#!/usr/bin/env -S v -n -w -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
#!/usr/bin/env -S v -n -w -gc none -cg -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
// #!/usr/bin/env -S v -n -w -cg -no-retry-compilation -d use_openssl -enable-globals run
|
||||
//-parallel-cc
|
||||
import os
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
// import freeflowuniverse.herolib.develop.performance
|
||||
|
||||
mut silent := false
|
||||
mut gs := gittools.get(reload:false)!
|
||||
|
||||
coderoot := if 'CODEROOT' in os.environ() {
|
||||
os.environ()['CODEROOT']
|
||||
} else {
|
||||
os.join_path(os.home_dir(), 'code')
|
||||
}
|
||||
|
||||
// timer := performance.new('gittools')
|
||||
|
||||
|
||||
mut gs := gittools.get()!
|
||||
if coderoot.len > 0 {
|
||||
// is a hack for now
|
||||
gs = gittools.new(coderoot: coderoot)!
|
||||
}
|
||||
|
||||
mypath := gs.do(
|
||||
recursive: true
|
||||
cmd: 'list'
|
||||
)!
|
||||
|
||||
// timer.timeline()
|
||||
gs.repos_print()!
|
||||
@@ -68,4 +68,10 @@ addtoscript('alias vtest=', 'alias vtest=\'v -stats -enable-globals -n -w -cg -g
|
||||
eprintln('Failed to add vtest alias: ${err}')
|
||||
}
|
||||
|
||||
addtoscript('HOME/hero/bin', 'export PATH="\$PATH:\$HOME/hero/bin"') or {
|
||||
eprintln('Failed to add path to hero, ${err}')
|
||||
}
|
||||
|
||||
// ulimit -n 32000
|
||||
|
||||
println('Added vtest alias to shell configuration')
|
||||
|
||||
@@ -45,7 +45,7 @@ repo.branch_create('feature-branch')!
|
||||
repo.branch_switch('feature-branch')!
|
||||
|
||||
// Check status and commit changes
|
||||
if repo.has_changes() {
|
||||
if repo.has_changes {
|
||||
repo.commit('feat: Add new feature')!
|
||||
repo.push()!
|
||||
}
|
||||
@@ -114,7 +114,7 @@ if repo.need_checkout() {
|
||||
|
||||
```v
|
||||
// Check for changes
|
||||
if repo.has_changes() {
|
||||
if repo.has_changes {
|
||||
// Handle changes
|
||||
}
|
||||
|
||||
|
||||
@@ -36,13 +36,8 @@ pub fn new(args_ GitStructureArgsNew) !&GitStructure {
|
||||
debug: args.debug
|
||||
ssh_key_name: args.ssh_key_name
|
||||
}
|
||||
// Retrieve the configuration from Redis.
|
||||
rediskey_ := rediskey(args.coderoot)
|
||||
mut redis := redis_get()
|
||||
datajson := json.encode(cfg)
|
||||
redis.set(rediskey_, datajson)!
|
||||
|
||||
return get(coderoot: args.coderoot, reload: args.reload)
|
||||
return get(coderoot: args.coderoot,reload:args.reload,cfg:cfg)
|
||||
}
|
||||
|
||||
@[params]
|
||||
@@ -50,6 +45,7 @@ pub struct GitStructureArgGet {
|
||||
pub mut:
|
||||
coderoot string
|
||||
reload bool
|
||||
cfg ?GitStructureConfig
|
||||
}
|
||||
|
||||
// Retrieve a GitStructure instance based on the given arguments.
|
||||
@@ -58,44 +54,29 @@ pub fn get(args_ GitStructureArgGet) !&GitStructure {
|
||||
if args.coderoot == '' {
|
||||
args.coderoot = '${os.home_dir()}/code'
|
||||
}
|
||||
if args.reload {
|
||||
cachereset()!
|
||||
}
|
||||
rediskey_ := rediskey(args.coderoot)
|
||||
|
||||
rediskey_ := cache_key(args.coderoot)
|
||||
|
||||
// Return existing instance if already created.
|
||||
if rediskey_ in gsinstances {
|
||||
mut gs := gsinstances[rediskey_] or {
|
||||
panic('Unexpected error: key not found in gsinstances')
|
||||
}
|
||||
if args.reload {
|
||||
gs.load()!
|
||||
}
|
||||
gs.load(args.reload)!
|
||||
return gs
|
||||
}
|
||||
|
||||
mut redis := redis_get()
|
||||
mut datajson := redis.get(rediskey_) or { '' }
|
||||
|
||||
if datajson == '' {
|
||||
if args_.coderoot == '' {
|
||||
return new()!
|
||||
}
|
||||
return error("can't find repostructure for coderoot: ${args.coderoot}")
|
||||
}
|
||||
|
||||
mut config := json.decode(GitStructureConfig, datajson) or { GitStructureConfig{} }
|
||||
|
||||
// Create and load the GitStructure instance.
|
||||
mut gs := GitStructure{
|
||||
key: rediskey_
|
||||
config: config
|
||||
coderoot: pathlib.get_dir(path: args.coderoot, create: true)!
|
||||
}
|
||||
|
||||
// TODO: should we load repos here disregarding the reload flag?
|
||||
gs.config()! //will load the config, don't remove
|
||||
gs.load(false)!
|
||||
|
||||
if gs.repos.keys().len == 0 || args.reload {
|
||||
gs.load()!
|
||||
gs.load(true)!
|
||||
}
|
||||
|
||||
gsinstances[rediskey_] = &gs
|
||||
@@ -103,25 +84,3 @@ pub fn get(args_ GitStructureArgGet) !&GitStructure {
|
||||
return gsinstances[rediskey_] or { panic('bug') }
|
||||
}
|
||||
|
||||
// Reset the configuration cache for Git structures.
|
||||
pub fn configreset() ! {
|
||||
mut redis := redis_get()
|
||||
key_check := 'git:config:*'
|
||||
keys := redis.keys(key_check)!
|
||||
|
||||
for key in keys {
|
||||
redis.del(key)!
|
||||
}
|
||||
}
|
||||
|
||||
// Reset all caches and configurations for all Git repositories.
|
||||
pub fn cachereset() ! {
|
||||
key_check := 'git:repos:**'
|
||||
mut redis := redis_get()
|
||||
keys := redis.keys(key_check)!
|
||||
|
||||
for key in keys {
|
||||
redis.del(key)!
|
||||
}
|
||||
configreset()!
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ pub fn (mut gs GitStructure) gitlocation_from_url(url string) !GitLocation {
|
||||
}
|
||||
|
||||
// Return a herolib path object on the filesystem pointing to the locator
|
||||
pub fn (mut l GitLocation) patho() !pathlib.Path {
|
||||
pub fn (l GitLocation) patho() !pathlib.Path {
|
||||
mut addrpath := pathlib.get_dir(path: '${l.provider}/${l.account}/${l.name}', create: false)!
|
||||
if l.path.len > 0 {
|
||||
return pathlib.get('${addrpath.path}/${l.path}')
|
||||
|
||||
@@ -5,33 +5,31 @@ import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.core.redisclient
|
||||
import os
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import json
|
||||
|
||||
pub struct GitStructureConfig {
|
||||
pub mut:
|
||||
coderoot string
|
||||
coderoot string //just to be informative, its not used
|
||||
light bool = true // If true, clones only the last history for all branches (clone with only 1 level deep)
|
||||
log bool = true // If true, logs git commands/statements
|
||||
debug bool = true
|
||||
ssh_key_name string
|
||||
}
|
||||
|
||||
fn rediskey(coderoot string) string {
|
||||
key := md5.hexhash(coderoot)
|
||||
return 'git:config:${key}'
|
||||
}
|
||||
|
||||
// GitStructure holds information about repositories within a specific code root.
|
||||
// This structure keeps track of loaded repositories, their configurations, and their status.
|
||||
@[heap]
|
||||
pub struct GitStructure {
|
||||
mut:
|
||||
config_ ?GitStructureConfig // Configuration settings for the git structure.
|
||||
pub mut:
|
||||
key string // Unique key representing the git structure (default is hash of $home/code).
|
||||
config GitStructureConfig // Configuration settings for the git structure.
|
||||
coderoot pathlib.Path // Root directory where repositories are located.
|
||||
repos map[string]&GitRepo // Map of repositories, keyed by their unique names.
|
||||
loaded bool // Indicates if the repositories have been loaded into memory.
|
||||
key string // Unique key representing the git structure (default is hash of $home/code).
|
||||
repos map[string]&GitRepo // Map of repositories
|
||||
coderoot pathlib.Path
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -39,45 +37,57 @@ pub mut:
|
||||
// Use the reload argument to force reloading from the disk.
|
||||
//
|
||||
// Args:
|
||||
// - args (StatusUpdateArgs): Arguments controlling the reload behavior.
|
||||
pub fn (mut gitstructure GitStructure) load(args StatusUpdateArgs) ! {
|
||||
// - args (StatusUpdateArgs): Arguments controlling the reload behavior. (is just a reload:bool)
|
||||
pub fn (mut gitstructure GitStructure) load(reload bool) ! {
|
||||
mut processed_paths := []string{}
|
||||
|
||||
if reload{
|
||||
gitstructure.repos=map[string]&GitRepo{}
|
||||
}
|
||||
gitstructure.load_recursive(gitstructure.coderoot.path, mut processed_paths)!
|
||||
|
||||
if args.reload {
|
||||
mut ths := []thread !{}
|
||||
redisclient.reset()! // make sure redis is empty, we don't want to reuse
|
||||
for _, mut repo_ in gitstructure.repos {
|
||||
mut myfunction := fn (mut repo GitRepo) ! {
|
||||
// println("reload repo ${repo.name} on ${repo.get_path()!}")
|
||||
redisclient.reset()!
|
||||
redisclient.checkempty()
|
||||
repo.status_update(reload: true)!
|
||||
}
|
||||
|
||||
ths << spawn myfunction(mut repo_)
|
||||
}
|
||||
console.print_debug('loaded all threads for git on ${gitstructure.coderoot.path}')
|
||||
|
||||
for th in ths {
|
||||
th.wait()!
|
||||
}
|
||||
// console.print_debug("threads finished")
|
||||
// exit(0)
|
||||
if reload{
|
||||
gitstructure.cache_reset()!
|
||||
}
|
||||
|
||||
// mut ths := []thread !{}
|
||||
//need to make sure redis is empty before doing the threads
|
||||
redisclient.reset()!
|
||||
redisclient.checkempty()
|
||||
|
||||
for _, mut repo in gitstructure.repos {
|
||||
// mut myfunction := fn (mut repo GitRepo) ! {
|
||||
// }
|
||||
//ths << spawn myfunction(mut repo_)
|
||||
repo.status_update(reload: reload) or {
|
||||
msg:="Error in git repo: ${repo.path()}\n${err}"
|
||||
console.print_stderr(msg)
|
||||
return error(msg)
|
||||
}
|
||||
}
|
||||
|
||||
// pp.work_on_items(todo)
|
||||
//console.print_debug('loaded all threads for git on ${gitstructure.coderoot}')
|
||||
// for th in ths {
|
||||
// th.wait()!
|
||||
// }
|
||||
|
||||
// for x in pp.get_results[SResult]() {
|
||||
// println('result: ${x.s}')
|
||||
// }
|
||||
|
||||
// console.print_debug("threads finished")
|
||||
|
||||
//now we need to load them back in our memory because these were done in sub process
|
||||
// for _, mut r in gitstructure.repos {
|
||||
// r.cache_get()!
|
||||
// }
|
||||
|
||||
|
||||
// gitstructure.init()!
|
||||
}
|
||||
|
||||
// // just some initialization mechanism
|
||||
// pub fn (mut gitstructure GitStructure) init() ! {
|
||||
// if gitstructure.repos.keys().len == 0 {
|
||||
// println('Before loading keys.')
|
||||
// gitstructure.load()!
|
||||
// }
|
||||
// }
|
||||
|
||||
// Recursively loads repositories from the provided path, updating their statuses.
|
||||
// Recursively loads repositories from the provided path, updating their statuses, does not check the status
|
||||
//
|
||||
// Args:
|
||||
// - path (string): The path to search for repositories.
|
||||
@@ -104,8 +114,8 @@ fn (mut gitstructure GitStructure) load_recursive(path string, mut processed_pat
|
||||
mut repo := gitstructure.repo_init_from_path_(current_path)!
|
||||
// repo.status_update()!
|
||||
|
||||
key_ := repo.get_key()
|
||||
path_ := repo.get_path()!
|
||||
key_ := repo.cache_key()
|
||||
path_ := repo.path()
|
||||
|
||||
if processed_paths.contains(key_) || processed_paths.contains(path_) {
|
||||
return error('Duplicate repository detected.\nPath: ${path_}\nKey: ${key_}')
|
||||
@@ -126,15 +136,6 @@ fn (mut gitstructure GitStructure) load_recursive(path string, mut processed_pat
|
||||
}
|
||||
}
|
||||
|
||||
// Resets the cache for the current Git structure, removing cached data from Redis.
|
||||
pub fn (mut gitstructure GitStructure) cachereset() ! {
|
||||
mut redis := redis_get()
|
||||
keys := redis.keys('git:repos:${gitstructure.key}:**')!
|
||||
|
||||
for key in keys {
|
||||
redis.del(key)!
|
||||
}
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct RepoInitParams {
|
||||
@@ -190,3 +191,77 @@ pub fn (mut gitstructure GitStructure) get_working_repo() ?GitRepo {
|
||||
curdir := pathlib.get_wd()
|
||||
return gitstructure.repo_init_from_path_(curdir.path) or { return none }
|
||||
}
|
||||
|
||||
|
||||
//key in redis used to store all config info
|
||||
fn cache_key(coderoot string) string {
|
||||
key := md5.hexhash(coderoot)
|
||||
return 'git:${key}'
|
||||
}
|
||||
|
||||
//key in redis used to store all config info
|
||||
pub fn (mut self GitStructure) cache_key() string {
|
||||
return cache_key(self.coderoot.path)
|
||||
}
|
||||
|
||||
//load from cache
|
||||
pub fn (mut self GitStructure) cache_load() ! {
|
||||
// Retrieve the configuration from Redis.
|
||||
mut redis := redis_get()
|
||||
keys := redis.keys("${self.cache_key()}:repos")!
|
||||
self.repos = map[string]&GitRepo{} //reset
|
||||
for key in keys {
|
||||
data:=redis.get(key)!
|
||||
mut r:=json.decode(GitRepo,data)!
|
||||
self.repos[key] = &r
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Reset all caches and configurations for all Git repositories.
|
||||
pub fn (mut self GitStructure) cache_reset() ! {
|
||||
mut redis := redis_get()
|
||||
keys := redis.keys("${self.cache_key()}:**")!
|
||||
for key in keys {
|
||||
redis.del(key)!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Load config from redis
|
||||
fn (mut self GitStructure) coderoot() !pathlib.Path {
|
||||
mut coderoot := pathlib.get_dir(path:self.coderoot.path,create:true)!
|
||||
return coderoot
|
||||
}
|
||||
|
||||
|
||||
////// CONFIG
|
||||
|
||||
// Load config from redis
|
||||
fn (mut self GitStructure) config() !GitStructureConfig {
|
||||
mut config := self.config_ or {
|
||||
mut redis := redis_get()
|
||||
data:=redis.get("${self.cache_key()}:config")!
|
||||
mut c:= GitStructureConfig{}
|
||||
if data.len>0{
|
||||
c = json.decode(GitStructureConfig,data)!
|
||||
}
|
||||
c
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
// Reset the configuration cache for Git structures.
|
||||
pub fn (mut self GitStructure) config_reset() ! {
|
||||
mut redis := redis_get()
|
||||
redis.del("${self.cache_key()}:config")!
|
||||
}
|
||||
|
||||
|
||||
//save to the cache
|
||||
pub fn (mut self GitStructure) config_save() ! {
|
||||
// Retrieve the configuration from Redis.
|
||||
mut redis := redis_get()
|
||||
datajson := json.encode(self.config)
|
||||
redis.set("${self.cache_key()}:config", datajson)!
|
||||
}
|
||||
|
||||
@@ -61,8 +61,8 @@ pub fn (mut gs GitStructure) do(args_ ReposActionsArgs) !string {
|
||||
mut ui := gui.new()!
|
||||
|
||||
if args.cmd == 'reload' {
|
||||
console.print_header(' - reload gitstructure ${gs.config.coderoot}')
|
||||
gs.load(reload: true)!
|
||||
console.print_header(' - reload gitstructure ${gs.config()!.coderoot}')
|
||||
gs.load(true)!
|
||||
return ''
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ pub fn (mut gs GitStructure) do(args_ ReposActionsArgs) !string {
|
||||
mut g := gs.get_repo(url: args.url)!
|
||||
g.load()!
|
||||
if args.cmd == 'cd' {
|
||||
return g.get_path()!
|
||||
return g.path()
|
||||
}
|
||||
if args.reset {
|
||||
g.remove_changes()!
|
||||
@@ -105,7 +105,7 @@ pub fn (mut gs GitStructure) do(args_ ReposActionsArgs) !string {
|
||||
g.push()!
|
||||
}
|
||||
if args.cmd == 'pull' || args.cmd == 'clone' || args.cmd == 'push' {
|
||||
gpath := g.get_path()!
|
||||
gpath := g.path()
|
||||
console.print_debug('git do ok, on path ${gpath}')
|
||||
return gpath
|
||||
}
|
||||
@@ -119,7 +119,7 @@ pub fn (mut gs GitStructure) do(args_ ReposActionsArgs) !string {
|
||||
if repos.len > 4 {
|
||||
return error('more than 4 repo found for cmd:${args.cmd}')
|
||||
}
|
||||
for r in repos {
|
||||
for mut r in repos {
|
||||
if args.cmd == 'edit' {
|
||||
r.open_vscode()!
|
||||
}
|
||||
|
||||
@@ -7,13 +7,14 @@ fn get_repo_status(gr GitRepo) !string {
|
||||
mut repo := gr
|
||||
mut statuses := []string{}
|
||||
|
||||
if repo.need_commit()! {
|
||||
if repo.has_changes {
|
||||
statuses << 'COMMIT'
|
||||
}
|
||||
|
||||
if repo.need_push_or_pull()! {
|
||||
statuses << 'PULL'
|
||||
statuses << 'PUSH'
|
||||
}
|
||||
|
||||
return statuses.join(', ')
|
||||
}
|
||||
|
||||
@@ -33,8 +34,8 @@ fn format_repo_info(repo GitRepo) ![]string {
|
||||
|
||||
// Print repositories based on the provided criteria, showing their statuses
|
||||
pub fn (mut gitstructure GitStructure) repos_print(args ReposGetArgs) ! {
|
||||
console.print_debug('#### Overview of repositories:')
|
||||
console.print_debug('')
|
||||
// console.print_debug('#### Overview of repositories:')
|
||||
// console.print_debug('')
|
||||
|
||||
mut repo_data := [][]string{}
|
||||
|
||||
@@ -49,11 +50,11 @@ pub fn (mut gitstructure GitStructure) repos_print(args ReposGetArgs) ! {
|
||||
|
||||
// Display header with optional argument filtering information
|
||||
// header := if args.str().len > 0 {
|
||||
// 'Repositories: ${gitstructure.config.coderoot} [${args.str()}]'
|
||||
// 'Repositories: ${gitstructure.config()!.coderoot} [${args.str()}]'
|
||||
// } else {
|
||||
// 'Repositories: ${gitstructure.config.coderoot}'
|
||||
// 'Repositories: ${gitstructure.config()!.coderoot}'
|
||||
// }
|
||||
header:='Repositories: ${gitstructure.config.coderoot}'
|
||||
header:='Repositories: ${gitstructure.config()!.coderoot}'
|
||||
console.print_header(header)
|
||||
|
||||
// Print the repository information in a formatted array
|
||||
|
||||
@@ -18,6 +18,7 @@ pub mut:
|
||||
config GitRepoConfig // Repository-specific configuration
|
||||
last_load int // Epoch timestamp of the last load from reality
|
||||
deploysshkey string // to use with git
|
||||
has_changes bool
|
||||
}
|
||||
|
||||
// this is the status we want, we need to work towards off
|
||||
@@ -77,7 +78,7 @@ pub fn (mut repo GitRepo) commit(msg string) ! {
|
||||
if msg == '' {
|
||||
return error('Commit message is empty.')
|
||||
}
|
||||
repo_path := repo.get_path()!
|
||||
repo_path := repo.path()
|
||||
repo.exec('git add . -A') or {
|
||||
return error('Cannot add to repo: ${repo_path}. Error: ${err}')
|
||||
}
|
||||
@@ -121,7 +122,7 @@ pub fn (mut repo GitRepo) pull(args_ PullCheckoutArgs) ! {
|
||||
}
|
||||
|
||||
repo.exec('git pull') or {
|
||||
return error('Cannot pull repo: ${repo.get_path()!}. Error: ${err}')
|
||||
return error('Cannot pull repo: ${repo.path()}. Error: ${err}')
|
||||
}
|
||||
|
||||
if args_.submodules {
|
||||
@@ -139,7 +140,7 @@ pub fn (mut repo GitRepo) checkout() ! {
|
||||
repo.reset()!
|
||||
}
|
||||
if repo.need_commit()! {
|
||||
return error('Cannot checkout branch due to uncommitted changes in ${repo.get_path()!}.')
|
||||
return error('Cannot checkout branch due to uncommitted changes in ${repo.path()}.')
|
||||
}
|
||||
if repo.status_wanted.tag.len > 0 {
|
||||
repo.exec('git checkout tags/${repo.status_wanted.tag}')!
|
||||
@@ -152,14 +153,14 @@ pub fn (mut repo GitRepo) checkout() ! {
|
||||
// Create a new branch in the repository.
|
||||
pub fn (mut repo GitRepo) branch_create(branchname string) ! {
|
||||
repo.exec('git branch -c ${branchname}') or {
|
||||
return error('Cannot Create branch: ${repo.get_path()!} to ${branchname}\nError: ${err}')
|
||||
return error('Cannot Create branch: ${repo.path()} to ${branchname}\nError: ${err}')
|
||||
}
|
||||
console.print_green('Branch ${branchname} created successfully.')
|
||||
}
|
||||
|
||||
pub fn (mut repo GitRepo) branch_switch(branchname string) ! {
|
||||
repo.exec('git switch ${branchname}') or {
|
||||
return error('Cannot switch branch: ${repo.get_path()!} to ${branchname}\nError: ${err}')
|
||||
return error('Cannot switch branch: ${repo.path()} to ${branchname}\nError: ${err}')
|
||||
}
|
||||
console.print_green('Branch ${branchname} switched successfully.')
|
||||
repo.status_local.branch = branchname
|
||||
@@ -169,7 +170,7 @@ pub fn (mut repo GitRepo) branch_switch(branchname string) ! {
|
||||
|
||||
// Create a new branch in the repository.
|
||||
pub fn (mut repo GitRepo) tag_create(tagname string) ! {
|
||||
repo_path := repo.get_path()!
|
||||
repo_path := repo.path()
|
||||
repo.exec('git tag ${tagname}') or {
|
||||
return error('Cannot create tag: ${repo_path}. Error: ${err}')
|
||||
}
|
||||
@@ -194,7 +195,7 @@ pub fn (mut repo GitRepo) tag_exists(tag string) !bool {
|
||||
|
||||
// Deletes the Git repository
|
||||
pub fn (mut repo GitRepo) delete() ! {
|
||||
repo_path := repo.get_path()!
|
||||
repo_path := repo.path()
|
||||
repo.cache_delete()!
|
||||
osal.rm(repo_path)!
|
||||
repo.load()!
|
||||
@@ -230,10 +231,7 @@ pub fn (mut gs GitRepo) gitlocation_from_path(path string) !GitLocation {
|
||||
|
||||
// Check if repo path exists and validate fields
|
||||
pub fn (mut repo GitRepo) init() ! {
|
||||
path_string := repo.get_path()!
|
||||
if repo.gs.coderoot.path == '' {
|
||||
return error('Coderoot cannot be empty')
|
||||
}
|
||||
path_string := repo.path()
|
||||
if repo.provider == '' {
|
||||
return error('Provider cannot be empty')
|
||||
}
|
||||
@@ -272,12 +270,12 @@ fn (mut repo GitRepo) set_sshkey(key_name string) ! {
|
||||
// Removes all changes from the repo; be cautious
|
||||
pub fn (mut repo GitRepo) remove_changes() ! {
|
||||
repo.status_update()!
|
||||
if repo.has_changes()! {
|
||||
console.print_header('Removing changes in ${repo.get_path()!}')
|
||||
if repo.has_changes {
|
||||
console.print_header('Removing changes in ${repo.path()}')
|
||||
repo.exec('git reset HEAD --hard && git clean -xfd') or {
|
||||
return error("can't remove changes on repo: ${repo.get_path()!}.\n${err}")
|
||||
return error("can't remove changes on repo: ${repo.path()}.\n${err}")
|
||||
// TODO: we can do this fall back later
|
||||
// console.print_header('Could not remove changes; will re-clone ${repo.get_path()!}')
|
||||
// console.print_header('Could not remove changes; will re-clone ${repo.path()}')
|
||||
// mut p := repo.patho()!
|
||||
// p.delete()! // remove path, this will re-clone the full thing
|
||||
// repo.load_from_url()!
|
||||
@@ -294,16 +292,14 @@ pub fn (mut repo GitRepo) reset() ! {
|
||||
// Update submodules
|
||||
fn (mut repo GitRepo) update_submodules() ! {
|
||||
repo.exec('git submodule update --init --recursive') or {
|
||||
return error('Cannot update submodules for repo: ${repo.get_path()!}. Error: ${err}')
|
||||
return error('Cannot update submodules for repo: ${repo.path()}. Error: ${err}')
|
||||
}
|
||||
}
|
||||
|
||||
fn (repo GitRepo) exec(cmd_ string) !string {
|
||||
repo_path := repo.get_path()!
|
||||
repo_path := repo.path()
|
||||
cmd := 'cd ${repo_path} && ${cmd_}'
|
||||
if repo.gs.config.log {
|
||||
console.print_green(cmd)
|
||||
}
|
||||
//console.print_debug(cmd)
|
||||
r := os.execute(cmd)
|
||||
if r.exit_code != 0 {
|
||||
return error('Repo failed to exec cmd: ${cmd}\n${r.output})')
|
||||
|
||||
@@ -12,7 +12,7 @@ fn redis_get() &redisclient.Redis {
|
||||
fn (mut repo GitRepo) cache_set() ! {
|
||||
mut redis_client := redis_get()
|
||||
repo_json := json.encode(repo)
|
||||
cache_key := repo.get_cache_key()
|
||||
cache_key := repo.cache_key()
|
||||
redis_client.set(cache_key, repo_json)!
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ fn (mut repo GitRepo) cache_set() ! {
|
||||
fn (mut repo GitRepo) cache_get() ! {
|
||||
mut repo_json := ''
|
||||
mut redis_client := redis_get()
|
||||
cache_key := repo.get_cache_key()
|
||||
cache_key := repo.cache_key()
|
||||
repo_json = redis_client.get(cache_key) or {
|
||||
return error('Failed to get redis key ${cache_key}\n${err}')
|
||||
return
|
||||
}
|
||||
|
||||
if repo_json.len > 0 {
|
||||
@@ -33,9 +33,9 @@ fn (mut repo GitRepo) cache_get() ! {
|
||||
}
|
||||
|
||||
// Remove cache
|
||||
fn (repo GitRepo) cache_delete() ! {
|
||||
fn (mut repo GitRepo) cache_delete() ! {
|
||||
mut redis_client := redis_get()
|
||||
cache_key := repo.get_cache_key()
|
||||
cache_key := repo.cache_key()
|
||||
redis_client.del(cache_key) or { return error('Cannot delete the repo cache due to: ${err}') }
|
||||
// TODO: report v bug, function should work without return as well
|
||||
return
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module gittools
|
||||
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.osal
|
||||
|
||||
import os
|
||||
|
||||
@[params]
|
||||
@@ -31,7 +31,7 @@ pub fn (mut gitstructure GitStructure) clone(args GitCloneArgs) !&GitRepo {
|
||||
parent_dir := repo.get_parent_dir(create: true)!
|
||||
|
||||
mut extra := ''
|
||||
if gitstructure.config.light {
|
||||
if gitstructure.config()!.light {
|
||||
extra = '--depth 1 --no-single-branch '
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ pub fn (repo GitRepo) get_changes_staged() ![]string {
|
||||
}
|
||||
|
||||
// Check if there are any unstaged or untracked changes in the repository.
|
||||
pub fn (mut repo GitRepo) has_changes() !bool {
|
||||
pub fn (mut repo GitRepo) detect_changes() !bool {
|
||||
repo.status_update()!
|
||||
r0 := repo.get_changes_unstaged()!
|
||||
r1 := repo.get_changes_staged()!
|
||||
@@ -46,10 +46,10 @@ pub fn (mut repo GitRepo) has_changes() !bool {
|
||||
|
||||
// Check if there are staged changes to commit.
|
||||
pub fn (mut repo GitRepo) need_commit() !bool {
|
||||
return repo.has_changes()!
|
||||
return repo.has_changes
|
||||
}
|
||||
|
||||
// Check if the repository has changes that need to be pushed.
|
||||
// Check if the repository has changes that need to be pushed (is against the cached info).
|
||||
pub fn (mut repo GitRepo) need_push_or_pull() !bool {
|
||||
repo.status_update()!
|
||||
last_remote_commit := repo.get_last_remote_commit() or {
|
||||
@@ -58,8 +58,7 @@ pub fn (mut repo GitRepo) need_push_or_pull() !bool {
|
||||
last_local_commit := repo.get_last_local_commit() or {
|
||||
return error('Failed to get last local commit: ${err}')
|
||||
}
|
||||
println('last_local_commit: ${last_local_commit}')
|
||||
println('last_remote_commit: ${last_remote_commit}')
|
||||
println('commit status: ${repo.name} ${last_local_commit} ${last_remote_commit}')
|
||||
return last_local_commit != last_remote_commit
|
||||
}
|
||||
|
||||
@@ -92,19 +91,19 @@ fn (mut repo GitRepo) get_remote_default_branchname() !string {
|
||||
}
|
||||
|
||||
// is always the commit for the branch as known remotely, if not known will return ""
|
||||
pub fn (repo GitRepo) get_last_remote_commit() !string {
|
||||
if repo.status_local.branch in repo.status_remote.branches {
|
||||
return repo.status_local.branches[repo.status_local.branch]
|
||||
pub fn (self GitRepo) get_last_remote_commit() !string {
|
||||
if self.status_local.branch in self.status_remote.branches {
|
||||
return self.status_remote.branches[self.status_local.branch]
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
// get commit for branch, will return '' if local branch doesn't exist remotely
|
||||
pub fn (repo GitRepo) get_last_local_commit() !string {
|
||||
if repo.status_local.branch in repo.status_local.branches {
|
||||
return repo.status_local.branches[repo.status_local.branch]
|
||||
pub fn (self GitRepo) get_last_local_commit() !string {
|
||||
if self.status_local.branch in self.status_local.branches {
|
||||
return self.status_local.branches[self.status_local.branch]
|
||||
}
|
||||
|
||||
return error("can't find branch: ${repo.status_local.branch} in local branches:\n${repo.status_local.branches}")
|
||||
return error("can't find branch: ${self.status_local.branch} in local branches:\n${self.status_local.branches}")
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@ module gittools
|
||||
|
||||
import time
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
import os
|
||||
@[params]
|
||||
pub struct StatusUpdateArgs {
|
||||
reload bool
|
||||
ssh_key_name string // name of ssh key to be used when loading
|
||||
}
|
||||
|
||||
pub fn (mut repo GitRepo) status_update(args StatusUpdateArgs) ! {
|
||||
@@ -27,14 +26,18 @@ pub fn (mut repo GitRepo) status_update(args StatusUpdateArgs) ! {
|
||||
// Load repo information
|
||||
// Does not check cache, it is the callers responsibility to check cache and load accordingly.
|
||||
fn (mut repo GitRepo) load() ! {
|
||||
console.print_debug('load ${repo.get_key()}')
|
||||
console.print_debug('load ${repo.cache_key()}')
|
||||
repo.init()!
|
||||
if os.exists("${repo.path()}/.git") == false{
|
||||
return error("Can't find git in repo ${repo.path()}")
|
||||
}
|
||||
repo.exec('git fetch --all') or {
|
||||
return error('Cannot fetch repo: ${repo.get_path()!}. Error: ${err}')
|
||||
return error('Cannot fetch repo: ${repo.path()}. Error: ${err}')
|
||||
}
|
||||
repo.load_branches()!
|
||||
repo.load_tags()!
|
||||
repo.last_load = int(time.now().unix())
|
||||
repo.has_changes = repo.detect_changes()!
|
||||
repo.cache_set()!
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
module gittools
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.osal.sshagent
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
@@ -14,22 +13,28 @@ pub mut:
|
||||
create bool
|
||||
}
|
||||
|
||||
fn (repo GitRepo) get_key() string {
|
||||
return '${repo.gs.key}:${repo.provider}:${repo.account}:${repo.name}'
|
||||
//get the key in redis where json cached info is
|
||||
pub fn (mut repo GitRepo) cache_key() string {
|
||||
return '${repo.gs.cache_key()}:${repo.provider}:${repo.account}:${repo.name}'
|
||||
}
|
||||
|
||||
fn (repo GitRepo) get_cache_key() string {
|
||||
return 'git:repos:${repo.gs.key}:${repo.provider}:${repo.account}:${repo.name}'
|
||||
//get path where the repo is on the fs
|
||||
pub fn (repo GitRepo) path() string {
|
||||
mut repo_:=repo
|
||||
mypath:=repo_.gs.coderoot.path
|
||||
return '${mypath}/${repo.provider}/${repo.account}/${repo.name}'
|
||||
}
|
||||
|
||||
pub fn (repo GitRepo) get_path() !string {
|
||||
return '${repo.gs.coderoot.path}/${repo.provider}/${repo.account}/${repo.name}'
|
||||
//get herolib path object
|
||||
pub fn (repo GitRepo) patho() !pathlib.Path {
|
||||
return pathlib.get_dir(path: repo.path(), create: false)!
|
||||
}
|
||||
|
||||
|
||||
// gets the path of a given url within a repo
|
||||
// ex: 'https://git.ourworld.tf/ourworld_holding/info_ourworld/src/branch/main/books/cocreation/SUMMARY.md'
|
||||
// returns <repo_path>/books/cocreation/SUMMARY.md
|
||||
pub fn (repo GitRepo) get_path_of_url(url string) !string {
|
||||
fn (mut repo GitRepo) get_path_of_url(url string) !string {
|
||||
// Split the URL into components
|
||||
url_parts := url.split('/')
|
||||
|
||||
@@ -41,9 +46,7 @@ pub fn (repo GitRepo) get_path_of_url(url string) !string {
|
||||
|
||||
if repo_root_idx == -1 {
|
||||
// maybe default repo url (without src and blob)
|
||||
return repo.get_path() or {
|
||||
return error('Invalid URL format: Cannot find repository path')
|
||||
}
|
||||
return repo.path()
|
||||
}
|
||||
|
||||
// Ensure that the repository path starts after the branch
|
||||
@@ -55,17 +58,18 @@ pub fn (repo GitRepo) get_path_of_url(url string) !string {
|
||||
path_in_repo := url_parts[repo_root_idx + 3..].join('/')
|
||||
|
||||
// Construct the full path
|
||||
return '${repo.get_path()!}/${path_in_repo}'
|
||||
return '${repo.path()}/${path_in_repo}'
|
||||
}
|
||||
|
||||
// Relative path inside the gitstructure, pointing to the repo
|
||||
pub fn (repo GitRepo) get_relative_path() !string {
|
||||
mut mypath := repo.patho()!
|
||||
return mypath.path_relative(repo.gs.coderoot.path) or { panic("couldn't get relative path") }
|
||||
mut repo_:=repo
|
||||
return mypath.path_relative(repo_.gs.coderoot.path) or { panic("couldn't get relative path") }
|
||||
}
|
||||
|
||||
pub fn (repo GitRepo) get_parent_dir(args GetParentDir) !string {
|
||||
repo_path := repo.get_path()!
|
||||
pub fn (mut repo GitRepo) get_parent_dir(args GetParentDir) !string {
|
||||
repo_path := repo.path()
|
||||
parent_dir := os.dir(repo_path)
|
||||
if !os.exists(parent_dir) && !args.create {
|
||||
return error('Parent directory does not exist: ${parent_dir}')
|
||||
@@ -114,9 +118,6 @@ fn (self GitRepo) get_http_url() !string {
|
||||
}
|
||||
|
||||
// Return rich path object from our library hero lib
|
||||
pub fn (repo GitRepo) patho() !pathlib.Path {
|
||||
return pathlib.get_dir(path: repo.get_path()!, create: false)!
|
||||
}
|
||||
|
||||
pub fn (mut repo GitRepo) display_current_status() ! {
|
||||
staged_changes := repo.get_changes_staged()!
|
||||
@@ -139,13 +140,13 @@ pub fn (mut repo GitRepo) display_current_status() ! {
|
||||
}
|
||||
|
||||
// Opens SourceTree for the Git repo
|
||||
pub fn (repo GitRepo) sourcetree() ! {
|
||||
sourcetree.open(path: repo.get_path()!)!
|
||||
pub fn (mut repo GitRepo) sourcetree() ! {
|
||||
sourcetree.open(path: repo.path())!
|
||||
}
|
||||
|
||||
// Opens Visual Studio Code for the repo
|
||||
pub fn (repo GitRepo) open_vscode() ! {
|
||||
path := repo.get_path()!
|
||||
pub fn (mut repo GitRepo) open_vscode() ! {
|
||||
path := repo.path()
|
||||
mut vs_code := vscode.new(path)
|
||||
vs_code.open()!
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ fn test_clone_repo() {
|
||||
repo_setup_tests = setup_repo()!
|
||||
mut gs := gittools.new(coderoot: repo_setup_tests.coderoot)!
|
||||
repo_tests = gs.get_repo(url: repo_setup_tests.repo_url)!
|
||||
repo_path_tests = repo_tests.get_path()!
|
||||
repo_path_tests = repo_tests.path()
|
||||
assert os.exists(repo_path_tests) == true
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ fn test_tag_create() {
|
||||
@[test]
|
||||
fn test_has_changes_add_changes_commit_changes() {
|
||||
file_name := create_new_file(repo_path_tests)!
|
||||
assert repo_tests.has_changes()! == true
|
||||
assert repo_tests.has_changes == true
|
||||
mut unstaged_changes := repo_tests.get_changes_unstaged()!
|
||||
assert unstaged_changes.len == 1
|
||||
mut staged_changes := repo_tests.get_changes_staged()!
|
||||
@@ -113,7 +113,7 @@ fn test_has_changes_add_changes_commit_changes() {
|
||||
@[test]
|
||||
fn test_push_changes() {
|
||||
file_name := create_new_file(repo_path_tests)!
|
||||
assert repo_tests.has_changes()! == true
|
||||
assert repo_tests.has_changes == true
|
||||
mut unstaged_changes := repo_tests.get_changes_unstaged()!
|
||||
assert unstaged_changes.len == 1
|
||||
mut staged_changes := repo_tests.get_changes_staged()!
|
||||
@@ -142,7 +142,7 @@ fn test_multiple_commits_and_push() {
|
||||
repo_tests.commit('feat: Added ${file_name_2} file.')!
|
||||
|
||||
repo_tests.push()!
|
||||
assert repo_tests.has_changes()! == false
|
||||
assert repo_tests.has_changes == false
|
||||
}
|
||||
|
||||
// Test committing with valid changes.
|
||||
@@ -165,7 +165,7 @@ fn test_commit_with_valid_changes() {
|
||||
// - Attempts to commit and expects a failure.
|
||||
@[test]
|
||||
fn test_commit_without_changes() {
|
||||
assert repo_tests.has_changes()! == false
|
||||
assert repo_tests.has_changes == false
|
||||
assert repo_tests.need_commit()! == false
|
||||
repo_tests.commit('Initial commit') or {
|
||||
assert false, 'Commit should be done with some changes'
|
||||
@@ -223,7 +223,7 @@ fn test_remove_changes() {
|
||||
assert staged_changes.len == 0
|
||||
|
||||
file_name := create_new_file(repo_path_tests)!
|
||||
assert repo_tests.has_changes()! == true
|
||||
assert repo_tests.has_changes == true
|
||||
|
||||
unstaged_changes = repo_tests.get_changes_unstaged()!
|
||||
assert unstaged_changes.len == 1
|
||||
|
||||
Reference in New Issue
Block a user