Files
herolib/lib/develop/gittools/repository_info.v
2025-05-18 10:58:49 +03:00

144 lines
4.8 KiB
V

module gittools
// FUNCITONS TO GET INFO FROM REALITY
// Retrieves a list of unstaged changes in the repository.
//
// This function returns a list of files that are modified or untracked.
//
// Returns:
// - An array of strings representing file paths of unstaged changes.
// - Throws an error if the command execution fails.
pub fn (repo GitRepo) get_changes_unstaged() ![]string {
unstaged_result := repo.exec('git ls-files --other --modified --exclude-standard') or {
return error('Failed to check for unstaged changes: ${repo.path()}\n${err}')
}
// Filter out any empty lines from the result.
return unstaged_result.split('\n').filter(it.len > 0)
}
// Retrieves a list of staged changes in the repository.
//
// This function returns a list of files that are staged and ready to be committed.
//
// Returns:
// - An array of strings representing file paths of staged changes.
// - Throws an error if the command execution fails.
pub fn (repo GitRepo) get_changes_staged() ![]string {
staged_result := repo.exec('git diff --name-only --staged') or {
return error('Failed to check for staged changes: ${repo.path()}\n${err}')
}
// Filter out any empty lines from the result.
return staged_result.split('\n').filter(it.len > 0)
}
// Check if there are any unstaged or untracked changes in the repository.
pub fn (mut repo GitRepo) detect_changes() !bool {
r0 := repo.get_changes_unstaged()!
r1 := repo.get_changes_staged()!
if r0.len + r1.len > 0 {
return true
}
return false
}
// Check if there are staged changes to commit.
pub fn (mut repo GitRepo) need_commit() !bool {
return repo.has_changes
}
// Check if the repository has local changes that need to be pushed to remote
pub fn (mut repo GitRepo) need_push() !bool {
repo.status_update()!
last_remote_commit := repo.get_last_remote_commit() or {
return error('Failed to get last remote commit: ${repo.path()}\n${err}')
}
last_local_commit := repo.get_last_local_commit() or {
return error('Failed to get last local commit: ${repo.path()}\n${err}')
}
// If remote commit is empty, it means the branch doesn't exist remotely yet
if last_remote_commit.len == 0 {
return true
}
// If local commit is different from remote and exists, we need to push
return last_local_commit != last_remote_commit
}
// Check if the repository needs to pull changes from remote
pub fn (mut repo GitRepo) need_pull() !bool {
repo.status_update()!
last_remote_commit := repo.get_last_remote_commit() or {
return error('Failed to get last remote commit: ${repo.path()}\n${err}')
}
// If remote doesn't exist, no need to pull
if last_remote_commit.len == 0 {
return false
}
// Check if the remote commit exists in our local history
// If it doesn't exist, we need to pull
result := repo.exec('git merge-base --is-ancestor ${last_remote_commit} HEAD') or {
// if err.msg().contains('exit code: 1') {
// // Exit code 1 means the remote commit is not in our history
// // Therefore we need to pull
// return true
// }
return true
// return error('Failed to check merge-base: ${err}')
}
// If we get here, the remote commit is in our history
// Therefore we don't need to pull
return false
}
// Legacy function for backward compatibility
pub fn (mut repo GitRepo) need_push_or_pull() !bool {
return repo.need_push()! || repo.need_pull()!
}
// Determine if the repository needs to checkout to a different branch or tag
fn (mut repo GitRepo) need_checkout() bool {
if repo.status_wanted.branch.len > 0 {
if repo.status_wanted.branch != repo.status_local.branch {
return true
}
} else if repo.status_wanted.tag.len > 0 {
if repo.status_wanted.tag != repo.status_local.tag {
return true
}
}
// it could be empty since the status_wanted are optional.
// else{
// panic("bug, should never be empty ${repo.status_wanted.branch}, ${repo.status_local.branch}")
// }
return false
}
fn (mut repo GitRepo) get_remote_default_branchname() !string {
if repo.status_remote.ref_default.len == 0 {
return error('ref_default cannot be empty for ${repo.path()}')
}
return repo.status_remote.branches[repo.status_remote.ref_default] or {
return error("can't find ref_default in branches for ${repo.path()}")
}
}
// is always the commit for the branch as known remotely, if not known will return ""
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 (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: ${self.status_local.branch} in local branches:\n${self.status_local.branches}")
}