Page MenuHomePhorge

mod.rs
No OneTemporary

Size
8 KB
Referenced Files
None
Subscribers
None
use jj_lib::{
config::StackedConfig,
git::{
self, GitFetch, GitFetchError, GitFetchPrepareError, GitImportError,
GitRemoteManagementError, RemoteCallbacks,
},
op_heads_store::OpHeadsStoreError,
op_store::OpStoreError,
repo::{ReadonlyRepo, Repo, RepoLoaderError, StoreFactories},
settings::{GitSettings, UserSettings},
str_util::StringPattern,
workspace::{
DefaultWorkspaceLoaderFactory, Workspace, WorkspaceInitError, WorkspaceLoadError,
WorkspaceLoaderFactory, default_working_copy_factories,
},
};
use std::{
collections::HashMap,
path::{Path, PathBuf},
sync::Arc,
};
use thiserror::Error;
pub mod transaction;
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum CodeStateError {
#[error("Failed to clone repository at {0}: {1}")]
CloneError(PathBuf, CodeCloneError),
#[error("Repository already exists: {0}")]
RepositoryExists(PathBuf),
}
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum CodeCloneError {
#[error("Failed to initialize workspace: {0}")]
WorkspaceInit(#[from] WorkspaceInitError),
#[error("Failed to add remote: {0}")]
RemoteAddError(#[from] GitRemoteManagementError),
#[error("Failed to store operation: {0}")]
WorkspaceOperationStoreError(#[from] OpStoreError),
#[error("Failed to store heads: {0}")]
WorkspaceOperationHeadsStoreError(#[from] OpHeadsStoreError),
#[error("Failed to load workspace: {0}")]
WorkspaceLoadError(#[from] WorkspaceLoadError),
#[error("Failed to load repository: {0}")]
RepositoryLoadError(#[from] RepoLoaderError),
#[error("Failed to fetch repository: {0}")]
FetchPrepareError(#[from] GitFetchPrepareError),
#[error("Failed to fetch repository: {0}")]
FetchError(#[from] GitFetchError),
#[error("Failed to import refs: {0}")]
ImportReferencesError(#[from] GitImportError),
}
pub struct CodeState {
repository_path: PathBuf,
repositories: HashMap<String, PathBuf>,
user_settings: UserSettings,
}
impl CodeState {
pub fn new(repository_path: PathBuf) -> Self {
Self {
repository_path,
repositories: HashMap::new(),
user_settings: UserSettings::from_config(StackedConfig::with_defaults())
.expect("Failed to load user settings"),
}
}
pub fn get_repository_directory(&self) -> &Path {
&self.repository_path
}
pub fn add_repository_from_path(
&mut self,
path: PathBuf,
) -> Result<(Workspace, Arc<ReadonlyRepo>), CodeStateError> {
let name = path
.file_name()
.expect("Failed to get file name")
.to_string_lossy()
.to_string();
let workspace =
Workspace::init_internal_git(&self.user_settings, &path).map_err(|err| {
CodeStateError::CloneError(path.clone(), CodeCloneError::WorkspaceInit(err))
})?;
self.repositories.insert(name, path);
Ok(workspace)
}
/// Adds a repository from a URL.
/// The repository will be cloned to the repository path
pub fn add_repository_from_url(
&mut self,
name: &str,
url: &str,
) -> Result<(Workspace, Arc<ReadonlyRepo>), CodeStateError> {
let path = std::path::absolute(self.repository_path.join(name)).unwrap();
if path.exists() {
return Err(CodeStateError::RepositoryExists(path));
}
// Create the repository path if it doesn't exist and the path/.jj
// directory if it doesn't exist
std::fs::create_dir_all(&path).expect("Failed to create repository path");
let (_workspace, repository) = Workspace::init_internal_git(&self.user_settings, &path)
.map_err(|err| {
CodeStateError::CloneError(path.clone(), CodeCloneError::WorkspaceInit(err))
})?;
let remote_name = "upstream";
git::add_remote(repository.store(), remote_name, url).map_err(|err| {
CodeStateError::CloneError(path.clone(), CodeCloneError::RemoteAddError(err))
})?;
let loader = DefaultWorkspaceLoaderFactory.create(&path).map_err(|err| {
CodeStateError::CloneError(path.clone(), CodeCloneError::WorkspaceLoadError(err))
})?;
let workspace = loader
.load(
&self.user_settings,
&StoreFactories::default(),
&default_working_copy_factories(),
)
.map_err(|err| {
CodeStateError::CloneError(path.clone(), CodeCloneError::WorkspaceLoadError(err))
})?;
let op = workspace
.repo_loader()
.load_operation(repository.op_id())
.map_err(|err| {
CodeStateError::CloneError(
path.clone(),
CodeCloneError::WorkspaceOperationStoreError(err),
)
})?;
let repository = workspace.repo_loader().load_at(&op).map_err(|err| {
CodeStateError::CloneError(path.clone(), CodeCloneError::RepositoryLoadError(err))
})?;
let mut transaction = repository.start_transaction();
let mutable_repository = transaction.repo_mut();
let git_settings = GitSettings {
auto_local_bookmark: true,
abandon_unreachable_commits: true,
..Default::default()
};
let mut git_fetch = GitFetch::new(mutable_repository, &git_settings).map_err(|err| {
CodeStateError::CloneError(path.clone(), CodeCloneError::FetchPrepareError(err))
})?;
git_fetch
.fetch(
remote_name,
&[StringPattern::everything()],
RemoteCallbacks::default(),
None,
)
.map_err(|err| {
CodeStateError::CloneError(path.clone(), CodeCloneError::FetchError(err))
})?;
git_fetch
.get_default_branch(remote_name, RemoteCallbacks::default())
.map_err(|err| {
CodeStateError::CloneError(path.clone(), CodeCloneError::FetchError(err))
})?;
git_fetch.import_refs().map_err(|err| {
CodeStateError::CloneError(path.clone(), CodeCloneError::ImportReferencesError(err))
})?;
transaction.commit("Initial commit").map_err(|err| {
CodeStateError::CloneError(
path.clone(),
CodeCloneError::WorkspaceOperationHeadsStoreError(err),
)
})?;
Ok((workspace, repository))
}
pub fn remove_repository(&mut self, name: &str) {
self.repositories.remove(name);
}
pub fn get_repository(&self, name: &str) -> Result<PathBuf, CodeStateError> {
let path = self.repositories.get(name);
match path {
Some(path) => Ok(path.clone()),
None => Err(CodeStateError::RepositoryExists(
self.repository_path.join(name),
)),
}
}
pub fn load_repository(
&self,
path: &Path,
) -> Result<(Workspace, Arc<ReadonlyRepo>), CodeStateError> {
let workspace = Workspace::load(
&self.user_settings,
path,
&StoreFactories::default(),
&default_working_copy_factories(),
)
.map_err(|err| {
CodeStateError::CloneError(path.to_path_buf(), CodeCloneError::WorkspaceLoadError(err))
})?;
let repository = workspace.repo_loader().load_at_head().map_err(|err| {
CodeStateError::CloneError(path.to_path_buf(), CodeCloneError::RepositoryLoadError(err))
})?;
Ok((workspace, repository))
}
pub fn discover_repositories(&mut self) {
if !self.repository_path.exists() {
std::fs::create_dir_all(&self.repository_path)
.expect("Failed to create repository path");
}
// Look for repositories in the repository path
// and add them to the repositories map
let paths =
std::fs::read_dir(&self.repository_path).expect("Failed to read repository path");
for entry in paths {
let entry = entry.expect("Failed to read entry");
let path = entry.path();
if path.is_dir() {
let name = path
.file_name()
.expect("Failed to get file name")
.to_string_lossy()
.to_string();
self.repositories.insert(name, path);
}
}
}
}

File Metadata

Mime Type
text/x-asm
Expires
Sun, Apr 20, 11:22 PM (1 d, 23 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
48337
Default Alt Text
mod.rs (8 KB)

Event Timeline