Skip to content

Commit 2f9593c

Browse files
committed
Merge PR Dimillian#585: allow patch stage and unstage
2 parents 67333e8 + 28d6fc0 commit 2f9593c

26 files changed

Lines changed: 4280 additions & 271 deletions

package-lock.json

Lines changed: 145 additions & 137 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/src/bin/codex_monitor_daemon.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,9 @@ use shared::{
8787
use storage::{read_settings, read_workspaces};
8888
use types::{
8989
AppSettings, GitCommitDiff, GitFileDiff, GitHubIssuesResponse, GitHubPullRequestComment,
90-
GitHubPullRequestDiff, GitHubPullRequestsResponse, GitLogResponse, LocalUsageSnapshot,
91-
WorkspaceEntry, WorkspaceInfo, WorkspaceSettings, WorktreeSetupStatus,
90+
GitHubPullRequestDiff, GitHubPullRequestsResponse, GitLogResponse, GitSelectionApplyResult,
91+
GitSelectionLine, LocalUsageSnapshot, WorkspaceEntry, WorkspaceInfo, WorkspaceSettings,
92+
WorktreeSetupStatus,
9293
};
9394
use workspace_settings::apply_workspace_settings_update;
9495

@@ -1087,6 +1088,41 @@ impl DaemonState {
10871088
git_ui_core::stage_git_all_core(&self.workspaces, workspace_id).await
10881089
}
10891090

1091+
async fn stage_git_selection(
1092+
&self,
1093+
workspace_id: String,
1094+
path: String,
1095+
op: String,
1096+
source: String,
1097+
lines: Vec<GitSelectionLine>,
1098+
) -> Result<GitSelectionApplyResult, String> {
1099+
git_ui_core::stage_git_selection_core(
1100+
&self.workspaces,
1101+
workspace_id,
1102+
path,
1103+
op,
1104+
source,
1105+
lines,
1106+
)
1107+
.await
1108+
}
1109+
1110+
async fn apply_git_display_hunk(
1111+
&self,
1112+
workspace_id: String,
1113+
path: String,
1114+
display_hunk_id: String,
1115+
) -> Result<GitSelectionApplyResult, String> {
1116+
git_ui_core::apply_git_display_hunk_core(
1117+
&self.workspaces,
1118+
&self.app_settings,
1119+
workspace_id,
1120+
path,
1121+
display_hunk_id,
1122+
)
1123+
.await
1124+
}
1125+
10901126
async fn unstage_git_file(&self, workspace_id: String, path: String) -> Result<(), String> {
10911127
git_ui_core::unstage_git_file_core(&self.workspaces, workspace_id, path).await
10921128
}

src-tauri/src/bin/codex_monitor_daemon/rpc/git.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::*;
22
use crate::shared::git_rpc;
3+
use crate::types::GitSelectionLine;
34
use serde::de::DeserializeOwned;
45
use serde::Serialize;
56
use std::future::Future;
@@ -102,6 +103,50 @@ pub(super) async fn try_handle(
102103
let request = parse_request_or_err!(params, git_rpc::WorkspaceIdRequest);
103104
Some(serialize_ok(state.stage_git_all(request.workspace_id)).await)
104105
}
106+
git_rpc::METHOD_APPLY_GIT_DISPLAY_HUNK => {
107+
let request = parse_request_or_err!(params, git_rpc::GitDisplayHunkActionRequest);
108+
Some(
109+
state
110+
.apply_git_display_hunk(
111+
request.workspace_id,
112+
request.path,
113+
request.display_hunk_id,
114+
)
115+
.await
116+
.and_then(|result| serde_json::to_value(result).map_err(|err| err.to_string())),
117+
)
118+
}
119+
"stage_git_selection" => {
120+
let workspace_id = match parse_string(params, "workspaceId") {
121+
Ok(value) => value,
122+
Err(err) => return Some(Err(err)),
123+
};
124+
let path = match parse_string(params, "path") {
125+
Ok(value) => value,
126+
Err(err) => return Some(Err(err)),
127+
};
128+
let op = match parse_string(params, "op") {
129+
Ok(value) => value,
130+
Err(err) => return Some(Err(err)),
131+
};
132+
let source = match parse_string(params, "source") {
133+
Ok(value) => value,
134+
Err(err) => return Some(Err(err)),
135+
};
136+
let lines = match parse_optional_value(params, "lines")
137+
.map(serde_json::from_value::<Vec<GitSelectionLine>>)
138+
.transpose()
139+
{
140+
Ok(value) => value.unwrap_or_default(),
141+
Err(err) => return Some(Err(format!("invalid `lines`: {err}"))),
142+
};
143+
Some(
144+
state
145+
.stage_git_selection(workspace_id, path, op, source, lines)
146+
.await
147+
.and_then(|result| serde_json::to_value(result).map_err(|err| err.to_string())),
148+
)
149+
}
105150
git_rpc::METHOD_UNSTAGE_GIT_FILE => {
106151
let request = parse_request_or_err!(params, git_rpc::WorkspacePathRequest);
107152
Some(serialize_ok(state.unstage_git_file(request.workspace_id, request.path)).await)

src-tauri/src/git/mod.rs

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
use serde::de::DeserializeOwned;
22
use serde::Serialize;
3-
use serde_json::Value;
3+
use serde_json::{json, Value};
44
use tauri::{AppHandle, State};
55

66
use crate::remote_backend;
77
use crate::shared::{git_rpc, git_ui_core};
88
use crate::state::AppState;
99
use crate::types::{
1010
GitCommitDiff, GitFileDiff, GitHubIssuesResponse, GitHubPullRequestComment,
11-
GitHubPullRequestDiff, GitHubPullRequestsResponse, GitLogResponse,
11+
GitHubPullRequestDiff, GitHubPullRequestsResponse, GitLogResponse, GitSelectionApplyResult,
12+
GitSelectionLine,
1213
};
1314

1415
fn git_remote_params<T: Serialize>(request: &T) -> Result<Value, String> {
@@ -187,6 +188,63 @@ pub(crate) async fn stage_git_all(
187188
git_ui_core::stage_git_all_core(&state.workspaces, workspace_id).await
188189
}
189190

191+
#[tauri::command]
192+
pub(crate) async fn stage_git_selection(
193+
workspace_id: String,
194+
path: String,
195+
op: String,
196+
source: String,
197+
lines: Vec<GitSelectionLine>,
198+
state: State<'_, AppState>,
199+
app: AppHandle,
200+
) -> Result<GitSelectionApplyResult, String> {
201+
try_remote_typed!(
202+
state,
203+
app,
204+
"stage_git_selection",
205+
json!({
206+
"workspaceId": &workspace_id,
207+
"path": &path,
208+
"op": &op,
209+
"source": &source,
210+
"lines": &lines
211+
}),
212+
GitSelectionApplyResult
213+
);
214+
git_ui_core::stage_git_selection_core(&state.workspaces, workspace_id, path, op, source, lines)
215+
.await
216+
}
217+
218+
#[tauri::command]
219+
pub(crate) async fn apply_git_display_hunk(
220+
workspace_id: String,
221+
path: String,
222+
display_hunk_id: String,
223+
state: State<'_, AppState>,
224+
app: AppHandle,
225+
) -> Result<GitSelectionApplyResult, String> {
226+
let request = git_rpc::GitDisplayHunkActionRequest {
227+
workspace_id: workspace_id.clone(),
228+
path: path.clone(),
229+
display_hunk_id: display_hunk_id.clone(),
230+
};
231+
try_remote_typed!(
232+
state,
233+
app,
234+
git_rpc::METHOD_APPLY_GIT_DISPLAY_HUNK,
235+
git_remote_params(&request)?,
236+
GitSelectionApplyResult
237+
);
238+
git_ui_core::apply_git_display_hunk_core(
239+
&state.workspaces,
240+
&state.app_settings,
241+
workspace_id,
242+
path,
243+
display_hunk_id,
244+
)
245+
.await
246+
}
247+
190248
#[tauri::command]
191249
pub(crate) async fn unstage_git_file(
192250
workspace_id: String,

src-tauri/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ pub fn run() {
240240
git::get_git_remote,
241241
git::stage_git_file,
242242
git::stage_git_all,
243+
git::stage_git_selection,
244+
git::apply_git_display_hunk,
243245
git::unstage_git_file,
244246
git::revert_git_file,
245247
git::revert_git_all,

src-tauri/src/shared/git_rpc.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub(crate) const METHOD_INIT_GIT_REPO: &str = "init_git_repo";
77
pub(crate) const METHOD_CREATE_GITHUB_REPO: &str = "create_github_repo";
88
pub(crate) const METHOD_STAGE_GIT_FILE: &str = "stage_git_file";
99
pub(crate) const METHOD_STAGE_GIT_ALL: &str = "stage_git_all";
10+
pub(crate) const METHOD_APPLY_GIT_DISPLAY_HUNK: &str = "apply_git_display_hunk";
1011
pub(crate) const METHOD_UNSTAGE_GIT_FILE: &str = "unstage_git_file";
1112
pub(crate) const METHOD_REVERT_GIT_FILE: &str = "revert_git_file";
1213
pub(crate) const METHOD_REVERT_GIT_ALL: &str = "revert_git_all";
@@ -86,6 +87,14 @@ pub(crate) struct WorkspacePathRequest {
8687
pub(crate) path: String,
8788
}
8889

90+
#[derive(Debug, Serialize, Deserialize)]
91+
#[serde(rename_all = "camelCase")]
92+
pub(crate) struct GitDisplayHunkActionRequest {
93+
pub(crate) workspace_id: String,
94+
pub(crate) path: String,
95+
pub(crate) display_hunk_id: String,
96+
}
97+
8998
#[derive(Debug, Serialize, Deserialize)]
9099
#[serde(rename_all = "camelCase")]
91100
pub(crate) struct ListGitRootsRequest {

src-tauri/src/shared/git_ui_core.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use tokio::sync::Mutex;
66

77
use crate::types::{
88
AppSettings, GitCommitDiff, GitFileDiff, GitHubIssuesResponse, GitHubPullRequestComment,
9-
GitHubPullRequestDiff, GitHubPullRequestsResponse, GitLogResponse, WorkspaceEntry,
9+
GitHubPullRequestDiff, GitHubPullRequestsResponse, GitLogResponse, GitSelectionApplyResult,
10+
GitSelectionLine, WorkspaceEntry,
1011
};
1112

1213
#[path = "git_ui_core/commands.rs"]
@@ -116,6 +117,38 @@ pub(crate) async fn stage_git_all_core(
116117
commands::stage_git_all_inner(workspaces, workspace_id).await
117118
}
118119

120+
pub(crate) async fn stage_git_selection_core(
121+
workspaces: &Mutex<HashMap<String, WorkspaceEntry>>,
122+
workspace_id: String,
123+
path: String,
124+
op: String,
125+
source: String,
126+
lines: Vec<GitSelectionLine>,
127+
) -> Result<GitSelectionApplyResult, String> {
128+
commands::stage_git_selection_inner(workspaces, workspace_id, path, op, source, lines).await
129+
}
130+
131+
pub(crate) async fn apply_git_display_hunk_core(
132+
workspaces: &Mutex<HashMap<String, WorkspaceEntry>>,
133+
app_settings: &Mutex<AppSettings>,
134+
workspace_id: String,
135+
path: String,
136+
display_hunk_id: String,
137+
) -> Result<GitSelectionApplyResult, String> {
138+
let ignore_whitespace_changes = {
139+
let settings = app_settings.lock().await;
140+
settings.git_diff_ignore_whitespace_changes
141+
};
142+
commands::apply_git_display_hunk_inner(
143+
workspaces,
144+
workspace_id,
145+
path,
146+
display_hunk_id,
147+
ignore_whitespace_changes,
148+
)
149+
.await
150+
}
151+
119152
pub(crate) async fn unstage_git_file_core(
120153
workspaces: &Mutex<HashMap<String, WorkspaceEntry>>,
121154
workspace_id: String,

0 commit comments

Comments
 (0)