Add integration test for git status
This commit is contained in:
parent
e20eaca595
commit
65d4c4f6ed
4 changed files with 148 additions and 9 deletions
|
@ -86,8 +86,8 @@ CREATE TABLE "worktree_repositories" (
|
||||||
"project_id" INTEGER NOT NULL,
|
"project_id" INTEGER NOT NULL,
|
||||||
"worktree_id" INTEGER NOT NULL,
|
"worktree_id" INTEGER NOT NULL,
|
||||||
"work_directory_id" INTEGER NOT NULL,
|
"work_directory_id" INTEGER NOT NULL,
|
||||||
"scan_id" INTEGER NOT NULL,
|
|
||||||
"branch" VARCHAR,
|
"branch" VARCHAR,
|
||||||
|
"scan_id" INTEGER NOT NULL,
|
||||||
"is_deleted" BOOL NOT NULL,
|
"is_deleted" BOOL NOT NULL,
|
||||||
PRIMARY KEY(project_id, worktree_id, work_directory_id),
|
PRIMARY KEY(project_id, worktree_id, work_directory_id),
|
||||||
FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE,
|
FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE,
|
||||||
|
@ -96,6 +96,23 @@ CREATE TABLE "worktree_repositories" (
|
||||||
CREATE INDEX "index_worktree_repositories_on_project_id" ON "worktree_repositories" ("project_id");
|
CREATE INDEX "index_worktree_repositories_on_project_id" ON "worktree_repositories" ("project_id");
|
||||||
CREATE INDEX "index_worktree_repositories_on_project_id_and_worktree_id" ON "worktree_repositories" ("project_id", "worktree_id");
|
CREATE INDEX "index_worktree_repositories_on_project_id_and_worktree_id" ON "worktree_repositories" ("project_id", "worktree_id");
|
||||||
|
|
||||||
|
CREATE TABLE "worktree_repository_statuses" (
|
||||||
|
"project_id" INTEGER NOT NULL,
|
||||||
|
"worktree_id" INTEGER NOT NULL,
|
||||||
|
"work_directory_id" INTEGER NOT NULL,
|
||||||
|
"repo_path" VARCHAR NOT NULL,
|
||||||
|
"status" INTEGER NOT NULL,
|
||||||
|
"scan_id" INTEGER NOT NULL,
|
||||||
|
"is_deleted" BOOL NOT NULL,
|
||||||
|
PRIMARY KEY(project_id, worktree_id, work_directory_id, repo_path),
|
||||||
|
FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY(project_id, worktree_id, work_directory_id) REFERENCES worktree_entries (project_id, worktree_id, id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
CREATE INDEX "index_worktree_repository_statuses_on_project_id" ON "worktree_repository_statuses" ("project_id");
|
||||||
|
CREATE INDEX "index_worktree_repository_statuses_on_project_id_and_worktree_id" ON "worktree_repository_statuses" ("project_id", "worktree_id");
|
||||||
|
CREATE INDEX "index_worktree_repository_statuses_on_project_id_and_worktree_id_and_work_directory_id" ON "worktree_repository_statuses" ("project_id", "worktree_id", "work_directory_id");
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE "worktree_diagnostic_summaries" (
|
CREATE TABLE "worktree_diagnostic_summaries" (
|
||||||
"project_id" INTEGER NOT NULL,
|
"project_id" INTEGER NOT NULL,
|
||||||
"worktree_id" INTEGER NOT NULL,
|
"worktree_id" INTEGER NOT NULL,
|
||||||
|
|
|
@ -15,6 +15,7 @@ mod worktree;
|
||||||
mod worktree_diagnostic_summary;
|
mod worktree_diagnostic_summary;
|
||||||
mod worktree_entry;
|
mod worktree_entry;
|
||||||
mod worktree_repository;
|
mod worktree_repository;
|
||||||
|
mod worktree_repository_statuses;
|
||||||
|
|
||||||
use crate::executor::Executor;
|
use crate::executor::Executor;
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
|
@ -2397,6 +2398,74 @@ impl Database {
|
||||||
)
|
)
|
||||||
.exec(&*tx)
|
.exec(&*tx)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
for repository in update.updated_repositories.iter() {
|
||||||
|
if !repository.updated_worktree_statuses.is_empty() {
|
||||||
|
worktree_repository_statuses::Entity::insert_many(
|
||||||
|
repository
|
||||||
|
.updated_worktree_statuses
|
||||||
|
.iter()
|
||||||
|
.map(|status_entry| worktree_repository_statuses::ActiveModel {
|
||||||
|
project_id: ActiveValue::set(project_id),
|
||||||
|
worktree_id: ActiveValue::set(worktree_id),
|
||||||
|
work_directory_id: ActiveValue::set(
|
||||||
|
repository.work_directory_id as i64,
|
||||||
|
),
|
||||||
|
repo_path: ActiveValue::set(status_entry.repo_path.clone()),
|
||||||
|
status: ActiveValue::set(status_entry.status as i64),
|
||||||
|
scan_id: ActiveValue::set(update.scan_id as i64),
|
||||||
|
is_deleted: ActiveValue::set(false),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.on_conflict(
|
||||||
|
OnConflict::columns([
|
||||||
|
worktree_repository_statuses::Column::ProjectId,
|
||||||
|
worktree_repository_statuses::Column::WorktreeId,
|
||||||
|
worktree_repository_statuses::Column::WorkDirectoryId,
|
||||||
|
worktree_repository_statuses::Column::RepoPath,
|
||||||
|
])
|
||||||
|
.update_columns([
|
||||||
|
worktree_repository_statuses::Column::ScanId,
|
||||||
|
worktree_repository_statuses::Column::Status,
|
||||||
|
])
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.exec(&*tx)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !repository.removed_worktree_repo_paths.is_empty() {
|
||||||
|
worktree_repository_statuses::Entity::update_many()
|
||||||
|
.filter(
|
||||||
|
worktree_repository_statuses::Column::ProjectId
|
||||||
|
.eq(project_id)
|
||||||
|
.and(
|
||||||
|
worktree_repository_statuses::Column::WorktreeId
|
||||||
|
.eq(worktree_id),
|
||||||
|
)
|
||||||
|
.and(
|
||||||
|
worktree_repository_statuses::Column::WorkDirectoryId
|
||||||
|
.eq(repository.work_directory_id),
|
||||||
|
)
|
||||||
|
.and(
|
||||||
|
worktree_repository_statuses::Column::RepoPath.is_in(
|
||||||
|
repository
|
||||||
|
.removed_worktree_repo_paths
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.set(worktree_repository_statuses::ActiveModel {
|
||||||
|
is_deleted: ActiveValue::Set(true),
|
||||||
|
scan_id: ActiveValue::Set(update.scan_id as i64),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.exec(&*tx)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !update.removed_repositories.is_empty() {
|
if !update.removed_repositories.is_empty() {
|
||||||
|
@ -2417,6 +2486,25 @@ impl Database {
|
||||||
})
|
})
|
||||||
.exec(&*tx)
|
.exec(&*tx)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
// Flip all status entries associated with a given repository_entry
|
||||||
|
worktree_repository_statuses::Entity::update_many()
|
||||||
|
.filter(
|
||||||
|
worktree_repository_statuses::Column::ProjectId
|
||||||
|
.eq(project_id)
|
||||||
|
.and(worktree_repository_statuses::Column::WorktreeId.eq(worktree_id))
|
||||||
|
.and(
|
||||||
|
worktree_repository_statuses::Column::WorkDirectoryId
|
||||||
|
.is_in(update.removed_repositories.iter().map(|id| *id as i64)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.set(worktree_repository_statuses::ActiveModel {
|
||||||
|
is_deleted: ActiveValue::Set(true),
|
||||||
|
scan_id: ActiveValue::Set(update.scan_id as i64),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.exec(&*tx)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let connection_ids = self.project_guest_connection_ids(project_id, &tx).await?;
|
let connection_ids = self.project_guest_connection_ids(project_id, &tx).await?;
|
||||||
|
@ -2647,12 +2735,44 @@ impl Database {
|
||||||
if let Some(worktree) =
|
if let Some(worktree) =
|
||||||
worktrees.get_mut(&(db_repository_entry.worktree_id as u64))
|
worktrees.get_mut(&(db_repository_entry.worktree_id as u64))
|
||||||
{
|
{
|
||||||
worktree.repository_entries.push(proto::RepositoryEntry {
|
worktree.repository_entries.insert(
|
||||||
work_directory_id: db_repository_entry.work_directory_id as u64,
|
db_repository_entry.work_directory_id as u64,
|
||||||
branch: db_repository_entry.branch,
|
proto::RepositoryEntry {
|
||||||
removed_worktree_repo_paths: Default::default(),
|
work_directory_id: db_repository_entry.work_directory_id as u64,
|
||||||
updated_worktree_statuses: Default::default(),
|
branch: db_repository_entry.branch,
|
||||||
});
|
removed_worktree_repo_paths: Default::default(),
|
||||||
|
updated_worktree_statuses: Default::default(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut db_status_entries = worktree_repository_statuses::Entity::find()
|
||||||
|
.filter(
|
||||||
|
Condition::all()
|
||||||
|
.add(worktree_repository_statuses::Column::ProjectId.eq(project_id))
|
||||||
|
.add(worktree_repository_statuses::Column::IsDeleted.eq(false)),
|
||||||
|
)
|
||||||
|
.stream(&*tx)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
while let Some(db_status_entry) = db_status_entries.next().await {
|
||||||
|
let db_status_entry = db_status_entry?;
|
||||||
|
if let Some(worktree) = worktrees.get_mut(&(db_status_entry.worktree_id as u64))
|
||||||
|
{
|
||||||
|
if let Some(repository_entry) = worktree
|
||||||
|
.repository_entries
|
||||||
|
.get_mut(&(db_status_entry.work_directory_id as u64))
|
||||||
|
{
|
||||||
|
repository_entry
|
||||||
|
.updated_worktree_statuses
|
||||||
|
.push(proto::StatusEntry {
|
||||||
|
repo_path: db_status_entry.repo_path,
|
||||||
|
status: db_status_entry.status as i32,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3394,7 +3514,7 @@ pub struct Worktree {
|
||||||
pub root_name: String,
|
pub root_name: String,
|
||||||
pub visible: bool,
|
pub visible: bool,
|
||||||
pub entries: Vec<proto::Entry>,
|
pub entries: Vec<proto::Entry>,
|
||||||
pub repository_entries: Vec<proto::RepositoryEntry>,
|
pub repository_entries: BTreeMap<u64, proto::RepositoryEntry>,
|
||||||
pub diagnostic_summaries: Vec<proto::DiagnosticSummary>,
|
pub diagnostic_summaries: Vec<proto::DiagnosticSummary>,
|
||||||
pub scan_id: u64,
|
pub scan_id: u64,
|
||||||
pub completed_scan_id: u64,
|
pub completed_scan_id: u64,
|
||||||
|
|
|
@ -1385,7 +1385,7 @@ async fn join_project(
|
||||||
removed_entries: Default::default(),
|
removed_entries: Default::default(),
|
||||||
scan_id: worktree.scan_id,
|
scan_id: worktree.scan_id,
|
||||||
is_last_update: worktree.scan_id == worktree.completed_scan_id,
|
is_last_update: worktree.scan_id == worktree.completed_scan_id,
|
||||||
updated_repositories: worktree.repository_entries,
|
updated_repositories: worktree.repository_entries.into_values().collect(),
|
||||||
removed_repositories: Default::default(),
|
removed_repositories: Default::default(),
|
||||||
};
|
};
|
||||||
for update in proto::split_worktree_update(message, MAX_CHUNK_SIZE) {
|
for update in proto::split_worktree_update(message, MAX_CHUNK_SIZE) {
|
||||||
|
|
|
@ -2820,6 +2820,8 @@ async fn test_git_status_sync(
|
||||||
|
|
||||||
// And synchronization while joining
|
// And synchronization while joining
|
||||||
let project_remote_c = client_c.build_remote_project(project_id, cx_c).await;
|
let project_remote_c = client_c.build_remote_project(project_id, cx_c).await;
|
||||||
|
deterministic.run_until_parked();
|
||||||
|
|
||||||
project_remote_c.read_with(cx_c, |project, cx| {
|
project_remote_c.read_with(cx_c, |project, cx| {
|
||||||
assert_status(
|
assert_status(
|
||||||
&Path::new(A_TXT),
|
&Path::new(A_TXT),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue