Depends on: https://github.com/zed-industries/zed/pull/45768 Refactor plan: https://gist.github.com/mikayla-maki/6c4bf263fd80050715ba01f45478796e Overall plan: https://gist.github.com/mikayla-maki/7bb5078e4385a2e683e1e1eb40d17d38 This is the big one. Release Notes: - N/A --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
118 lines
3.9 KiB
Rust
118 lines
3.9 KiB
Rust
use git::repository::DiffType;
|
|
use gpui::{App, Entity, Task};
|
|
use serde::{Deserialize, Serialize};
|
|
use worktree::Worktree;
|
|
|
|
use crate::{
|
|
Project,
|
|
git_store::{GitStore, LocalRepositoryState, RepositoryState},
|
|
};
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub struct TelemetrySnapshot {
|
|
pub worktree_snapshots: Vec<TelemetryWorktreeSnapshot>,
|
|
}
|
|
|
|
impl TelemetrySnapshot {
|
|
pub fn new(project: &Entity<Project>, cx: &mut App) -> Task<TelemetrySnapshot> {
|
|
let git_store = project.read(cx).git_store().clone();
|
|
let worktree_snapshots: Vec<_> = project
|
|
.read(cx)
|
|
.visible_worktrees(cx)
|
|
.map(|worktree| TelemetryWorktreeSnapshot::new(worktree, git_store.clone(), cx))
|
|
.collect();
|
|
|
|
cx.spawn(async move |_| {
|
|
let worktree_snapshots = futures::future::join_all(worktree_snapshots).await;
|
|
|
|
Self { worktree_snapshots }
|
|
})
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub struct TelemetryWorktreeSnapshot {
|
|
pub worktree_path: String,
|
|
pub git_state: Option<GitState>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub struct GitState {
|
|
pub remote_url: Option<String>,
|
|
pub head_sha: Option<String>,
|
|
pub current_branch: Option<String>,
|
|
pub diff: Option<String>,
|
|
}
|
|
|
|
impl TelemetryWorktreeSnapshot {
|
|
fn new(
|
|
worktree: Entity<Worktree>,
|
|
git_store: Entity<GitStore>,
|
|
cx: &App,
|
|
) -> Task<TelemetryWorktreeSnapshot> {
|
|
cx.spawn(async move |cx| {
|
|
// Get worktree path and snapshot
|
|
let worktree_info = cx.update(|app_cx| {
|
|
let worktree = worktree.read(app_cx);
|
|
let path = worktree.abs_path().to_string_lossy().into_owned();
|
|
let snapshot = worktree.snapshot();
|
|
(path, snapshot)
|
|
});
|
|
|
|
let (worktree_path, _snapshot) = worktree_info;
|
|
|
|
let git_state = git_store
|
|
.update(cx, |git_store, cx| {
|
|
git_store
|
|
.repositories()
|
|
.values()
|
|
.find(|repo| {
|
|
repo.read(cx)
|
|
.abs_path_to_repo_path(&worktree.read(cx).abs_path())
|
|
.is_some()
|
|
})
|
|
.cloned()
|
|
})
|
|
.map(|repo| {
|
|
repo.update(cx, |repo, _| {
|
|
let current_branch =
|
|
repo.branch.as_ref().map(|branch| branch.name().to_owned());
|
|
repo.send_job(None, |state, _| async move {
|
|
let RepositoryState::Local(LocalRepositoryState { backend, .. }) =
|
|
state
|
|
else {
|
|
return GitState {
|
|
remote_url: None,
|
|
head_sha: None,
|
|
current_branch,
|
|
diff: None,
|
|
};
|
|
};
|
|
|
|
let remote_url = backend.remote_url("origin").await;
|
|
let head_sha = backend.head_sha().await;
|
|
let diff = backend.diff(DiffType::HeadToWorktree).await.ok();
|
|
|
|
GitState {
|
|
remote_url,
|
|
head_sha,
|
|
current_branch,
|
|
diff,
|
|
}
|
|
})
|
|
})
|
|
});
|
|
|
|
let git_state = match git_state {
|
|
Some(receiver) => receiver.await.ok(),
|
|
None => None,
|
|
};
|
|
|
|
TelemetryWorktreeSnapshot {
|
|
worktree_path,
|
|
git_state,
|
|
}
|
|
})
|
|
}
|
|
}
|