Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/apps/desktop/src/api/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,8 @@ pub struct ResetWorkspacePersonaFilesRequest {
#[derive(Debug, Deserialize)]
pub struct CheckPathExistsRequest {
pub path: String,
#[serde(default, rename = "remoteConnectionId")]
pub remote_connection_id: Option<String>,
}

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -2774,7 +2776,12 @@ pub async fn check_path_exists(
state: State<'_, AppState>,
request: CheckPathExistsRequest,
) -> Result<bool, String> {
path_exists(&state, &request.path).await
path_exists(
&state,
&request.path,
request.remote_connection_id.as_deref(),
)
.await
}

#[tauri::command]
Expand Down
8 changes: 6 additions & 2 deletions src/apps/desktop/src/api/path_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,12 @@ pub async fn write_text_file(
}
}

pub async fn path_exists(app_state: &AppState, raw_path: &str) -> Result<bool, String> {
match resolve_desktop_path_target(app_state, raw_path, None).await? {
pub async fn path_exists(
app_state: &AppState,
raw_path: &str,
preferred_remote_connection_id: Option<&str>,
) -> Result<bool, String> {
match resolve_desktop_path_target(app_state, raw_path, preferred_remote_connection_id).await? {
DesktopPathTarget::Local { resolved_path, .. } => Ok(resolved_path.exists()),
DesktopPathTarget::Remote {
requested_path,
Expand Down
93 changes: 73 additions & 20 deletions src/apps/desktop/src/api/review_platform_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

use crate::api::app_state::AppState;
use bitfun_core::service::review_platform::{
ReviewPlatformCiLog, ReviewPlatformDetailSection, ReviewPlatformError,
ReviewPlatformIssueEvidence, ReviewPlatformKind, ReviewPlatformPullRequestDetail,
ReviewPlatformPullRequestDetailPage, ReviewPlatformPullRequestReviewTarget,
ReviewPlatformService, ReviewPlatformWorkspaceSnapshot,
untrusted_repository_error_message, ReviewPlatformCiLog, ReviewPlatformDetailSection,
ReviewPlatformError, ReviewPlatformIssueEvidence, ReviewPlatformKind,
ReviewPlatformPullRequestDetail, ReviewPlatformPullRequestDetailPage,
ReviewPlatformPullRequestReviewTarget, ReviewPlatformService, ReviewPlatformWorkspaceSnapshot,
};
use log::error;
use serde::Deserialize;
Expand Down Expand Up @@ -88,10 +88,7 @@ pub async fn review_platform_get_workspace_snapshot(
"Failed to get review platform workspace snapshot: path={}, remote_id={:?}, error={}",
request.repository_path, request.remote_id, error
);
format!(
"Failed to get review platform workspace snapshot: {}",
error
)
review_platform_command_error("Failed to get review platform workspace snapshot", &error)
})
}

Expand All @@ -104,10 +101,13 @@ pub async fn review_platform_get_workspace_context(
.await
.map_err(|error| {
error!(
"Failed to get review platform workspace context: path={}, remote_id={:?}, error={}",
request.repository_path, request.remote_id, error
);
format!("Failed to get review platform workspace context: {}", error)
"Failed to get review platform workspace context: path={}, remote_id={:?}, error={}",
request.repository_path, request.remote_id, error
);
review_platform_command_error(
"Failed to get review platform workspace context",
&error,
)
})
}

Expand All @@ -130,7 +130,10 @@ pub async fn review_platform_get_pull_request_detail(
request.pull_request_id,
error
);
format!("Failed to get review platform pull request detail: {}", error)
review_platform_command_error(
"Failed to get review platform pull request detail",
&error,
)
})
}

Expand All @@ -153,7 +156,7 @@ pub async fn review_platform_get_pull_request_review_target(
request.pull_request_id,
error
);
format!("Failed to prepare pull request Review target: {}", error)
review_platform_command_error("Failed to prepare pull request Review target", &error)
})
}

Expand Down Expand Up @@ -182,7 +185,7 @@ pub async fn review_platform_get_issue(
request.issue_id,
safe_error
);
format!("Failed to get provider Issue evidence: {safe_error}")
safe_review_platform_command_error("Failed to get provider Issue evidence", &error)
})
}

Expand All @@ -209,10 +212,26 @@ pub async fn review_platform_get_pull_request_review_target_by_identity(
request.pull_request_id,
safe_error
);
format!("Failed to prepare pull request Review target: {safe_error}")
safe_review_platform_command_error("Failed to prepare pull request Review target", &error)
})
}

fn review_platform_command_error(context: &str, error: &ReviewPlatformError) -> String {
if let Some(repository_path) = error.untrusted_repository_path() {
return untrusted_repository_error_message(repository_path);
}

format!("{context}: {error}")
}

fn safe_review_platform_command_error(context: &str, error: &ReviewPlatformError) -> String {
if let Some(repository_path) = error.untrusted_repository_path() {
return untrusted_repository_error_message(repository_path);
}

format!("{context}: {}", safe_review_platform_error(error))
}

fn safe_review_platform_error(error: &ReviewPlatformError) -> String {
match error {
ReviewPlatformError::Http { status, .. } => format!("provider returned HTTP {status}"),
Expand All @@ -228,6 +247,9 @@ fn safe_review_platform_error(error: &ReviewPlatformError) -> String {
"requested Issue is a pull request".to_string()
}
ReviewPlatformError::InvalidRepository(_) => "invalid repository".to_string(),
ReviewPlatformError::RepositoryUntrusted { .. } => {
"repository ownership is not trusted".to_string()
}
ReviewPlatformError::RemoteNotFound(_) => "provider remote was not found".to_string(),
ReviewPlatformError::UnsupportedPlatform(_) => "unsupported provider".to_string(),
ReviewPlatformError::Api(_) => "provider request was rejected".to_string(),
Expand Down Expand Up @@ -259,9 +281,9 @@ pub async fn review_platform_get_pull_request_detail_page(
request.per_page,
error
);
format!(
"Failed to get review platform pull request detail page: {}",
error
review_platform_command_error(
"Failed to get review platform pull request detail page",
&error,
)
})
}
Expand All @@ -288,7 +310,7 @@ pub async fn review_platform_get_pull_request_ci_log(
request.ci_item_id,
error
);
format!("Failed to get review platform CI log: {}", error)
review_platform_command_error("Failed to get review platform CI log", &error)
})
}

Expand Down Expand Up @@ -351,6 +373,37 @@ mod tests {
use super::*;
use serde_json::json;

#[test]
fn review_platform_command_errors_preserve_the_repository_trust_code() {
let error = ReviewPlatformError::RepositoryUntrusted {
repository_path: "/srv/shared/repo".to_string(),
detail: "fatal: detected dubious ownership".to_string(),
};

assert_eq!(
review_platform_command_error("Failed to load review platform", &error),
"git_repository_untrusted: /srv/shared/repo"
);
assert_eq!(
safe_review_platform_command_error("Failed to load review platform", &error),
"git_repository_untrusted: /srv/shared/repo"
);
}

#[test]
fn review_platform_command_errors_keep_context_for_other_failures() {
let error = ReviewPlatformError::RemoteNotFound("origin".to_string());

assert_eq!(
review_platform_command_error("Failed to load review platform", &error),
"Failed to load review platform: Remote not found: origin"
);
assert_eq!(
safe_review_platform_command_error("Failed to load review platform", &error),
"Failed to load review platform: provider remote was not found"
);
}

#[test]
fn review_platform_request_wire_deserializes_issue_identity_fields() {
let request: ReviewPlatformIssueRequest = serde_json::from_value(json!({
Expand Down
8 changes: 5 additions & 3 deletions src/crates/assembly/core/src/service/review_platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ use crate::infrastructure::try_get_path_manager_arc;
use std::sync::Arc;

pub use bitfun_services_integrations::review_platform::{
ReviewAuthSource, ReviewAuthState, ReviewChecks, ReviewDecision, ReviewEvidenceCompleteness,
ReviewFileStatus, ReviewItemState, ReviewPlatformAccount, ReviewPlatformActionResult,
classify_git_command_failure, untrusted_repository_error_message, ReviewAuthSource,
ReviewAuthState, ReviewChecks, ReviewDecision, ReviewEvidenceCompleteness, ReviewFileStatus,
ReviewItemState, ReviewPlatformAccount, ReviewPlatformActionResult,
ReviewPlatformApprovalRequest, ReviewPlatformAuthChallenge, ReviewPlatformAuthChallengeState,
ReviewPlatformCapabilities, ReviewPlatformCiItem, ReviewPlatformCiLog, ReviewPlatformCommit,
ReviewPlatformCreatePullRequestRequest, ReviewPlatformDetailSection, ReviewPlatformError,
Expand Down Expand Up @@ -98,7 +99,8 @@ impl ReviewPlatformWorkspaceClassifier for CoreReviewPlatformWorkspaceClassifier
} else {
stderr
};
return Err(ReviewPlatformError::InvalidRepository(
return Err(classify_git_command_failure(
current_dir,
message.trim().to_string(),
));
}
Expand Down
Loading