Files
herolib/lib/develop/gittools/repos_get.v
2024-12-25 19:17:23 +01:00

146 lines
4.5 KiB
V

module gittools
import freeflowuniverse.herolib.core.redisclient
import time
// ReposGetArgs defines arguments to retrieve repositories from the git structure.
// It includes filters by name, account, provider, and an option to clone a missing repo.
@[params]
pub struct ReposGetArgs {
pub mut:
filter string // Optional filter for repository names
name string // Specific repository name to retrieve.
account string // Git account associated with the repository.
provider string // Git provider (e.g., GitHub).
pull bool // Pull the last changes.
reset bool // Reset the changes.
reload bool // Reload the repo into redis cache
url string // Repository URL
}
// Retrieves a list of repositories from the git structure that match the provided arguments.
// if pull will force a pull, if it can't will be error, if reset will remove the changes
//
// Args:
//```
// ReposGetArgs {
// filter string // Optional filter for repository names
// name string // Specific repository name to retrieve.
// account string // Git account associated with the repository.
// provider string // Git provider (e.g., GitHub).
// pull bool // Pull the last changes.
// reset bool // Reset the changes.
// reload bool // Reload the repo into redis cache
// url string // Repository URL, used if cloning is needed.
//```
// Returns:
// - []&GitRepo: A list of repository references that match the criteria.
pub fn (mut gitstructure GitStructure) get_repos(args_ ReposGetArgs) ![]&GitRepo {
mut args := args_
mut res := []&GitRepo{}
for _, repo in gitstructure.repos {
relpath := repo.get_relative_path()!
if args.filter != '' && relpath.contains(args.filter) {
res << repo
continue
}
if args.url.len > 0 {
// if being mathed from url load repo info
git_location := gitstructure.gitlocation_from_url(args.url)!
args.account = git_location.account
args.provider = git_location.provider
args.name = git_location.name
}
if repo_match_check(repo, args) {
res << repo
}
}
// operate per repo on thread based on args
mut ths := []thread !{}
for mut repo in res {
// check redis cache outside, in threads is problematic
repo.cache_get() or { return error('failed to get repo cache ${err}') }
if time.since(time.unix(repo.last_load)) > 24 * time.hour {
args.reload = true
}
ths << spawn fn (mut repo GitRepo, args ReposGetArgs) ! {
redisclient.reset()!
redisclient.checkempty()
if args.pull {
repo.pull()!
} else if args.reset {
repo.reset()!
} else if args.reload {
repo.load()!
}
}(mut repo, args)
}
for th in ths {
th.wait()!
}
return res
}
// Retrieves a single repository based on the provided arguments.
// if pull will force a pull, if it can't will be error, if reset will remove the changes
// If the repository does not exist, it will clone it
//
// Args:
//```
// ReposGetArgs {
// filter string // Optional filter for repository names
// name string // Specific repository name to retrieve.
// account string // Git account associated with the repository.
// provider string // Git provider (e.g., GitHub).
// pull bool // Pull the last changes.
// reset bool // Reset the changes.
// reload bool // Reload the repo into redis cache
// url string // Repository URL, used if cloning is needed.
//```
//
// Returns:
// - &GitRepo: Reference to the retrieved or cloned repository.
//
// Raises:
// - Error: If multiple repositories are found with similar names or if cloning fails.
pub fn (mut gitstructure GitStructure) get_repo(args_ ReposGetArgs) !&GitRepo {
mut args := args_
repositories := gitstructure.get_repos(args)!
if repositories.len == 0 {
if args.url.len == 0 {
return error('Cannot clone the repository, no URL provided: ${args.url}')
}
return gitstructure.clone(url: args.url)!
}
if repositories.len > 1 {
repos := repositories.map('- ${it} ${it.account}.${it.name}').join_lines()
return error('Found more than one repository for \n${args}\n${repos}')
}
return repositories[0]
}
// Helper function to check if a repository matches the criteria (name, account, provider).
//
// Args:
// - repo (GitRepo): The repository to check.
// - args (ReposGetArgs): The criteria to match against.
//
// Returns:
// - bool: True if the repository matches, false otherwise.
fn repo_match_check(repo GitRepo, args ReposGetArgs) bool {
return (args.name.len == 0 || repo.name == args.name)
&& (args.account.len == 0 || repo.account == args.account)
&& (args.provider.len == 0 || repo.provider == args.provider)
}