Git Tools Module
GitTools HeroScript
!!git.define
Configure or retrieve a GitStructure, if not set will use the default
!!git.define
coderoot:'/tmp/code' //when we overrule the location, the default is ~/code
light:true //depth of git clone is 1
log:true
debug:false //give more error reporting
offline:false //makes sure will not try to get to internet, but do all locally
ssh_key_path:'' //if a specific ssh key is needed
reload:false //if set then will remove cache and load full status, this is slow !
!!git.clone
Clones a Git repository from a specified URL into the configured coderoot.
!!git.clone
url: 'https://github.com/incubaid/test_repo.git'
pull: true // Optional: if true, pulls latest changes after cloning
reset: false // Optional: if true, resets the repository before cloning/pulling
light: true // Optional: if true, clones only the last history (default: is from git structure as defined above)
recursive: false // Optional: if true, also clones submodules (default: false)
!!git.repo_action
Performs various Git operations on an existing repository, the filter matches more than 1 repo, gives error if none found
!!git.repo_action
filter: 'incubaid/test_repo'
action: 'pull' // pull, commit, push, reset, branch_create, branch_switch, tag_create, tag_switch, delete
message: 'feat: Added new feature' // Optional: for 'commit' action
branchname: 'feature-branch' // Optional: for 'branch_create' or 'branch_switch' actions
tagname: 'v1.0.0' // Optional: for 'tag_create' or 'tag_switch' actions
submodules: true // Optional: for 'pull' action, if true, also updates submodules
error_ignore: false // Optional: if true, ignores errors during the action and continue for the next repo
Parameters:
filter(string, required): A substring to filter repositories by name or relative path. This can match multiple repositories.action(string, required): The Git operation to perform. Valid values:pull: Pulls latest changes from the remote.commit: Commits staged changes. Requiresmessage.push: Pushes local commits to the remote.reset: Resets all local changes (hard reset).branch_create: Creates a new branch. Requiresbranchname.branch_switch: Switches to an existing branch. Requiresbranchname.tag_create: Creates a new tag. Requirestagname.tag_switch: Switches to an existing tag. Requirestagname.delete: Deletes the local repository.
!!git.list
Lists known Git repositories managed by the gittools module.
!!git.list
filter: 'my_project' // Optional: filter by repository name or path
reload: true //if true then will check the status of those repo's against the remote's
!!git.reload
Forces a reload of all Git repositories in the cache, re-scanning the coderoot and updating their statuses.
!!git.reload
filter: 'my_project' // Optional: filter by repository name or path
Get a specific path starting from url
below is powerful command, will get the repo, put on right location, you can force a pull or even reset everything
import incubaid.herolib.develop.gittools
// path string
// git_url string
// git_reset bool
// git_root string
// git_pull bool
// currentdir bool // can use currentdir, if true, will use current directory as base path if not giturl or path specified
mydocs_path:=gittools.path(
git_pull:true,
git_url:'https://git.threefold.info/tfgrid/info_docs_depin/src/branch/main/docs'
)!
println(mydocs_path)
//the returned path is from pathlib, so its easy to further process
//more complete example
@[params]
pub struct GitPathGetArgs {
pub mut:
someotherparams string // you can add other params here if you want
//gittools will use these params to find the right path
path string
git_url string
git_reset bool
git_root string
git_pull bool
}
pub fn something(args GitPathGetArgs) !string{
mut path := gittools.path(path: args.path, git_url: args.git_url, git_reset: args.git_reset, git_root: args.git_root, git_pull: args.git_pull)!
if !path.is_dir() {
return error('path is not a directory')
}
if path.file_exists('.site') {
move_site_to_collection(mut path)!
}
return path.path
}
Repository Management
import incubaid.herolib.develop.gittools
// Initialize with code root directory
mut gs := gittools.new(coderoot: '~/code')!
// Clone a repository
mut repo := gs.clone(GitCloneArgs{
url: 'git@github.com:username/repo.git'
sshkey: 'deploy_key' // Optional SSH key name
})!
// Or get existing repository
mut repo := gs.get_repo(name: 'existing_repo')!
// Delete repository
repo.delete()!
Branch Operations
// Create and switch to new branch
repo.branch_create('feature-branch')!
repo.branch_switch('feature-branch')!
// Check status and commit changes
if repo.has_changes {
repo.commit('feat: Add new feature')!
repo.push()!
}
// Pull latest changes
repo.pull()!
// Pull with submodules
repo.pull(submodules: true)!
Tag Management
// Create a new tag
repo.tag_create('v1.0.0')!
// Switch to tag
repo.tag_switch('v1.0.0')!
// Check if tag exists
exists := repo.tag_exists('v1.0.0')!
// Get tag information
if repo.status_local.tag == 'v1.0.0' {
// Currently on tag v1.0.0
}
Advanced Features
SSH Key Integration
// Clone with SSH key
mut repo := gs.clone(GitCloneArgs{
url: 'git@github.com:username/repo.git'
sshkey: 'deploy_key'
})!
// Set SSH key for existing repository
repo.set_sshkey('deploy_key')!
Repository Status
// Update repository status
repo.status_update()!
// Check various status conditions
if repo.need_commit() {
// Has uncommitted changes
}
if repo.need_push_or_pull() {
// Has unpushed/unpulled changes
}
if repo.need_checkout() {
// Needs to checkout different branch/tag
}
Change Management
// Check for changes
if repo.has_changes {
// Handle changes
}
// Reset all changes
repo.reset()!
// or
repo.remove_changes()!
// Update submodules
repo.update_submodules()!
Repository Configuration & Status
The gittools module uses an imperative model. The GitRepo struct holds the current status of a repository in a unified GitStatus object. To change the state, you call explicit functions like repo.branch_switch('my-feature').
GitRepo and GitStatus Structure
// GitRepo represents a single git repository.
pub struct GitRepo {
pub mut:
provider string
account string
name string
config GitRepoConfig
status GitStatus // Unified struct holding the CURRENT repo status.
}
// GitStatus holds all live status information for a repository.
pub struct GitStatus {
pub mut:
// State from local and remote (`git fetch`)
branches map[string]string // branch name -> commit hash
tags map[string]string // tag name -> commit hash
// Current local state
branch string // The current checked-out branch
tag string // The current checked-out tag (if any)
ahead int // Commits ahead of remote
behind int // Commits behind remote
// Overall status
has_changes bool // True if there are uncommitted local changes
error string // Error message if any status update fails
}
Error Handling
The module provides comprehensive error handling:
// Clone with error handling
mut repo := gs.clone(url: 'invalid_url') or {
println('Clone failed: ${err}')
return
}
// Commit with error handling
repo.commit('feat: New feature') or {
if err.msg().contains('nothing to commit') {
println('No changes to commit')
} else {
println('Commit failed: ${err}')
}
return
}
Testing
Run the test suite:
v -enable-globals test herolib/develop/gittools/tests/
Notes
- SSH keys should be properly configured in
~/.ssh/ - For readonly repositories, all local changes will be reset on pull
- Light cloning option (
config.light: true) creates shallow clones - Repository status is automatically cached and updated
- Submodules are handled recursively when specified
- All operations maintain repository consistency