From 663775608876ce0e2f14d1c366d7037cb852c1f3 Mon Sep 17 00:00:00 2001 From: despiegk Date: Thu, 23 Jan 2025 14:09:20 +0100 Subject: [PATCH] gittools --- cli/compile.vsh | 2 +- examples/develop/gittools/example3.vsh | 29 +--- install_herolib.vsh | 6 + lib/develop/gittools/README.md | 4 +- lib/develop/gittools/factory.v | 59 ++----- lib/develop/gittools/gitlocation.v | 2 +- lib/develop/gittools/gitstructure.v | 179 +++++++++++++++------ lib/develop/gittools/gittools_do.v | 10 +- lib/develop/gittools/repos_print.v | 15 +- lib/develop/gittools/repository.v | 36 ++--- lib/develop/gittools/repository_cache.v | 10 +- lib/develop/gittools/repository_clone.v | 4 +- lib/develop/gittools/repository_info.v | 23 ++- lib/develop/gittools/repository_load.v | 11 +- lib/develop/gittools/repository_utils.v | 45 +++--- lib/develop/gittools/tests/gittools_test.v | 12 +- 16 files changed, 233 insertions(+), 214 deletions(-) diff --git a/cli/compile.vsh b/cli/compile.vsh index 36b05912..4dedb63e 100755 --- a/cli/compile.vsh +++ b/cli/compile.vsh @@ -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}') } diff --git a/examples/develop/gittools/example3.vsh b/examples/develop/gittools/example3.vsh index f24ceb7c..34af18c8 100755 --- a/examples/develop/gittools/example3.vsh +++ b/examples/develop/gittools/example3.vsh @@ -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()! \ No newline at end of file diff --git a/install_herolib.vsh b/install_herolib.vsh index d6cbbf3d..051d705d 100755 --- a/install_herolib.vsh +++ b/install_herolib.vsh @@ -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') diff --git a/lib/develop/gittools/README.md b/lib/develop/gittools/README.md index 8aa7efe8..55aa81c6 100644 --- a/lib/develop/gittools/README.md +++ b/lib/develop/gittools/README.md @@ -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 } diff --git a/lib/develop/gittools/factory.v b/lib/develop/gittools/factory.v index 6b2b10fc..c6af0525 100644 --- a/lib/develop/gittools/factory.v +++ b/lib/develop/gittools/factory.v @@ -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()! -} diff --git a/lib/develop/gittools/gitlocation.v b/lib/develop/gittools/gitlocation.v index f0be9fc0..904f66ba 100644 --- a/lib/develop/gittools/gitlocation.v +++ b/lib/develop/gittools/gitlocation.v @@ -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}') diff --git a/lib/develop/gittools/gitstructure.v b/lib/develop/gittools/gitstructure.v index ec7da029..295fac20 100644 --- a/lib/develop/gittools/gitstructure.v +++ b/lib/develop/gittools/gitstructure.v @@ -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)! +} diff --git a/lib/develop/gittools/gittools_do.v b/lib/develop/gittools/gittools_do.v index b434ca54..d8fa1712 100644 --- a/lib/develop/gittools/gittools_do.v +++ b/lib/develop/gittools/gittools_do.v @@ -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()! } diff --git a/lib/develop/gittools/repos_print.v b/lib/develop/gittools/repos_print.v index 44a2689d..e3ebaa2c 100644 --- a/lib/develop/gittools/repos_print.v +++ b/lib/develop/gittools/repos_print.v @@ -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 diff --git a/lib/develop/gittools/repository.v b/lib/develop/gittools/repository.v index 4480f2af..ff049ab6 100644 --- a/lib/develop/gittools/repository.v +++ b/lib/develop/gittools/repository.v @@ -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})') diff --git a/lib/develop/gittools/repository_cache.v b/lib/develop/gittools/repository_cache.v index f566cbf0..16823716 100644 --- a/lib/develop/gittools/repository_cache.v +++ b/lib/develop/gittools/repository_cache.v @@ -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 diff --git a/lib/develop/gittools/repository_clone.v b/lib/develop/gittools/repository_clone.v index 59dc08a8..27796762 100644 --- a/lib/develop/gittools/repository_clone.v +++ b/lib/develop/gittools/repository_clone.v @@ -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 ' } diff --git a/lib/develop/gittools/repository_info.v b/lib/develop/gittools/repository_info.v index caef93f5..5cea439d 100644 --- a/lib/develop/gittools/repository_info.v +++ b/lib/develop/gittools/repository_info.v @@ -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}") } diff --git a/lib/develop/gittools/repository_load.v b/lib/develop/gittools/repository_load.v index 013fe4b8..82046ae1 100644 --- a/lib/develop/gittools/repository_load.v +++ b/lib/develop/gittools/repository_load.v @@ -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()! } diff --git a/lib/develop/gittools/repository_utils.v b/lib/develop/gittools/repository_utils.v index c2f34301..79539172 100644 --- a/lib/develop/gittools/repository_utils.v +++ b/lib/develop/gittools/repository_utils.v @@ -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 /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()! } diff --git a/lib/develop/gittools/tests/gittools_test.v b/lib/develop/gittools/tests/gittools_test.v index 575fcc84..54a83b14 100644 --- a/lib/develop/gittools/tests/gittools_test.v +++ b/lib/develop/gittools/tests/gittools_test.v @@ -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