use std::path::Path;
use super::{
checked_git_root, git, now_rfc3339, open_store, path_string, require_repo,
source_type_for_kind, status_text, store, validate_asr_home_outside_repo, validate_repo_name,
AsrPaths, AsrResult, InitOutput, RepoAddOutput, RepoListOutput, RepoRecord, RepoStatusOutput,
};
pub(crate) fn init() -> AsrResult<InitOutput> {
let paths = AsrPaths::resolve()?;
let created = paths.create_all()?;
let store = store::Store::open(&paths.db_path)?;
store.init_schema()?;
Ok(InitOutput {
ok: true,
asr_home: path_string(&paths.home),
db_path: path_string(&paths.db_path),
created,
})
}
pub(crate) fn repo_add(name: &str, path: &Path) -> AsrResult<RepoAddOutput> {
validate_repo_name(name)?;
let (paths, store) = open_store()?;
if store.get_repo(name)?.is_some() {
return Err(super::AsrError::new(
"repo_name_exists",
format!("Repository name already exists: {name}"),
));
}
let resolved = git::canonical_repo_root(path)?;
let git_root = resolved.root;
validate_asr_home_outside_repo(&paths, &git_root)?;
let branch = git::current_branch(&git_root);
let head_commit = git::head_commit(&git_root);
let now = now_rfc3339();
let record = RepoRecord {
name: name.to_string(),
source_type: source_type_for_kind(resolved.kind).to_string(),
remote_url: None,
local_path: path_string(&git_root),
git_root: path_string(&git_root),
default_branch: branch,
head_commit,
created_at: now.clone(),
updated_at: now,
};
store.insert_repo(&record)?;
Ok(RepoAddOutput { repo: record })
}
pub(crate) fn repo_list() -> AsrResult<RepoListOutput> {
let (_paths, store) = open_store()?;
Ok(RepoListOutput {
repos: store.list_repos()?,
})
}
pub(crate) fn repo_status(name: &str) -> AsrResult<RepoStatusOutput> {
validate_repo_name(name)?;
let (_paths, store) = open_store()?;
let repo = require_repo(&store, name)?;
let git_root = checked_git_root(&repo)?;
let branch = git::current_branch(&git_root);
let head_commit = git::head_commit(&git_root);
let worktree = git::repository_status(&git_root, super::repo_is_bare(&repo))?;
let status = status_text(head_commit.as_deref(), worktree.dirty);
Ok(RepoStatusOutput {
repo: repo.name.clone(),
source_type: repo.source_type,
local_path: repo.local_path,
git_root: repo.git_root.clone(),
branch,
head_commit,
dirty: worktree.dirty,
untracked: worktree.untracked,
modified: worktree.modified,
worktree_fingerprint: worktree.worktree_fingerprint,
status: status.to_string(),
index_state: store.get_index_state(&repo.name)?,
})
}