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("telemetry_snapshot", 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, } }) }}
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("telemetry_snapshot", 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,
}
})
}
}