endringer_async/
async_api.rs1use std::path::Path;
4use std::sync::Arc;
5use std::time::SystemTime;
6
7use endringer::Error as EndringerError;
8use endringer::Result;
9use endringer::repository::{Repository, jj_repository, repository};
10use endringer::{
11 AheadBehind, BlameEntry, BranchInfo, BranchTrackingInfo, CommitId, CommitInfo,
12 DiffSummary, RepositoryInfo, SortOrder, StashEntry, StatusDigest, SubmoduleInfo,
13 TagInfo, WorktreeInfo, WorktreeStatus,
14};
15
16fn join_err(e: tokio::task::JoinError) -> EndringerError {
18 EndringerError::TaskJoin { message: e.to_string() }
19}
20
21#[derive(Clone)]
27pub struct AsyncRepository {
28 inner: Arc<Repository>,
29}
30
31impl AsyncRepository {
32 pub async fn open(path: &Path) -> Result<Self> {
34 let path = path.to_path_buf();
35 let inner = tokio::task::spawn_blocking(move || repository(&path))
36 .await
37 .map_err(join_err)??;
38 Ok(AsyncRepository { inner: Arc::new(inner) })
39 }
40
41 pub async fn open_jj(path: &Path) -> Result<Self> {
43 let path = path.to_path_buf();
44 let inner = tokio::task::spawn_blocking(move || jj_repository(&path))
45 .await
46 .map_err(join_err)??;
47 Ok(AsyncRepository { inner: Arc::new(inner) })
48 }
49
50 pub async fn status_digest(&self) -> Result<StatusDigest> {
53 let r = Arc::clone(&self.inner);
54 tokio::task::spawn_blocking(move || r.status_digest()).await.map_err(join_err)?
55 }
56
57 pub async fn local_branches(&self) -> Result<Vec<BranchInfo>> {
60 let r = Arc::clone(&self.inner);
61 tokio::task::spawn_blocking(move || r.local_branches()).await.map_err(join_err)?
62 }
63
64 pub async fn remote_branches(&self) -> Result<Vec<BranchInfo>> {
65 let r = Arc::clone(&self.inner);
66 tokio::task::spawn_blocking(move || r.remote_branches()).await.map_err(join_err)?
67 }
68
69 pub async fn list_commits(&self) -> Result<Vec<CommitInfo>> {
72 let r = Arc::clone(&self.inner);
73 tokio::task::spawn_blocking(move || r.list_commits()).await.map_err(join_err)?
74 }
75
76 pub async fn list_commits_sorted(&self, order: SortOrder) -> Result<Vec<CommitInfo>> {
77 let r = Arc::clone(&self.inner);
78 tokio::task::spawn_blocking(move || r.list_commits_sorted(order)).await.map_err(join_err)?
79 }
80
81 pub async fn log_since(&self, since: SystemTime, until: SystemTime) -> Result<Vec<CommitInfo>> {
82 let r = Arc::clone(&self.inner);
83 tokio::task::spawn_blocking(move || r.log_since(since, until)).await.map_err(join_err)?
84 }
85
86 pub async fn find_commit(&self, id: CommitId) -> Result<CommitInfo> {
87 let r = Arc::clone(&self.inner);
88 tokio::task::spawn_blocking(move || r.find_commit(&id)).await.map_err(join_err)?
89 }
90
91 pub async fn list_tags(&self) -> Result<Vec<TagInfo>> {
94 let r = Arc::clone(&self.inner);
95 tokio::task::spawn_blocking(move || r.list_tags()).await.map_err(join_err)?
96 }
97
98 pub async fn list_tags_sorted(&self, order: SortOrder) -> Result<Vec<TagInfo>> {
99 let r = Arc::clone(&self.inner);
100 tokio::task::spawn_blocking(move || r.list_tags_sorted(order)).await.map_err(join_err)?
101 }
102
103 pub async fn create_tag(&self, name: String) -> Result<()> {
104 let r = Arc::clone(&self.inner);
105 tokio::task::spawn_blocking(move || r.create_tag(&name)).await.map_err(join_err)?
106 }
107
108 pub async fn create_annotated_tag(&self, name: String, message: String) -> Result<()> {
109 let r = Arc::clone(&self.inner);
110 tokio::task::spawn_blocking(move || r.create_annotated_tag(&name, &message)).await.map_err(join_err)?
111 }
112
113 pub async fn delete_tag(&self, name: String) -> Result<()> {
114 let r = Arc::clone(&self.inner);
115 tokio::task::spawn_blocking(move || r.delete_tag(&name)).await.map_err(join_err)?
116 }
117
118 pub async fn diff(&self, from: CommitId, to: CommitId) -> Result<DiffSummary> {
121 let r = Arc::clone(&self.inner);
122 tokio::task::spawn_blocking(move || r.diff(&from, &to)).await.map_err(join_err)?
123 }
124
125 pub async fn remote_url(&self, name: String) -> Result<Option<String>> {
128 let r = Arc::clone(&self.inner);
129 tokio::task::spawn_blocking(move || r.remote_url(&name))
130 .await
131 .map_err(join_err)?
132 }
133
134 pub async fn is_dirty(&self) -> Result<bool> {
137 let r = Arc::clone(&self.inner);
138 tokio::task::spawn_blocking(move || r.is_dirty()).await.map_err(join_err)?
139 }
140
141 pub async fn merge_base(&self, a: CommitId, b: CommitId) -> Result<Option<CommitId>> {
144 let r = Arc::clone(&self.inner);
145 tokio::task::spawn_blocking(move || r.merge_base(&a, &b)).await.map_err(join_err)?
146 }
147
148 pub async fn is_ancestor(&self, candidate: CommitId, descendant: CommitId) -> Result<bool> {
149 let r = Arc::clone(&self.inner);
150 tokio::task::spawn_blocking(move || r.is_ancestor(&candidate, &descendant)).await.map_err(join_err)?
151 }
152
153 pub async fn blame(&self, path: std::path::PathBuf) -> Result<Vec<BlameEntry>> {
156 let r = Arc::clone(&self.inner);
157 tokio::task::spawn_blocking(move || r.blame(&path)).await.map_err(join_err)?
158 }
159
160 pub async fn worktree_status(&self) -> Result<WorktreeStatus> {
161 let r = Arc::clone(&self.inner);
162 tokio::task::spawn_blocking(move || r.worktree_status()).await.map_err(join_err)?
163 }
164
165 pub async fn file_at_commit(
166 &self,
167 path: std::path::PathBuf,
168 commit_id: CommitId,
169 ) -> Result<Vec<u8>> {
170 let r = Arc::clone(&self.inner);
171 tokio::task::spawn_blocking(move || r.file_at_commit(&path, &commit_id)).await.map_err(join_err)?
172 }
173
174 pub async fn submodules(&self) -> Result<Vec<SubmoduleInfo>> {
175 let r = Arc::clone(&self.inner);
176 tokio::task::spawn_blocking(move || r.submodules()).await.map_err(join_err)?
177 }
178
179 pub async fn stash_entries(&self) -> Result<Vec<StashEntry>> {
180 let r = Arc::clone(&self.inner);
181 tokio::task::spawn_blocking(move || r.stash_entries()).await.map_err(join_err)?
182 }
183
184 pub async fn worktrees(&self) -> Result<Vec<WorktreeInfo>> {
185 let r = Arc::clone(&self.inner);
186 tokio::task::spawn_blocking(move || r.worktrees()).await.map_err(join_err)?
187 }
188
189 pub async fn ahead_behind(
192 &self,
193 local: CommitId,
194 upstream: CommitId,
195 ) -> Result<AheadBehind> {
196 let r = Arc::clone(&self.inner);
197 tokio::task::spawn_blocking(move || r.ahead_behind(&local, &upstream)).await.map_err(join_err)?
198 }
199
200 pub async fn branch_ahead_behind(
201 &self,
202 branch: String,
203 ) -> Result<Option<AheadBehind>> {
204 let r = Arc::clone(&self.inner);
205 tokio::task::spawn_blocking(move || r.branch_ahead_behind(&branch)).await.map_err(join_err)?
206 }
207
208 pub async fn repository_info(&self) -> Result<RepositoryInfo> {
211 let r = Arc::clone(&self.inner);
212 tokio::task::spawn_blocking(move || r.repository_info()).await.map_err(join_err)?
213 }
214
215 pub async fn branch_tracking(&self, branch: String) -> Result<BranchTrackingInfo> {
218 let r = Arc::clone(&self.inner);
219 tokio::task::spawn_blocking(move || r.branch_tracking(&branch)).await.map_err(join_err)?
220 }
221
222 pub async fn local_branch_tracking(&self) -> Result<Vec<BranchTrackingInfo>> {
223 let r = Arc::clone(&self.inner);
224 tokio::task::spawn_blocking(move || r.local_branch_tracking()).await.map_err(join_err)?
225 }
226
227 pub async fn is_merged_into(&self, branch: String, target: String) -> Result<bool> {
228 let r = Arc::clone(&self.inner);
229 tokio::task::spawn_blocking(move || r.is_merged_into(&branch, &target)).await.map_err(join_err)?
230 }
231}