From 0164783e9d38c643af352e96e16e2fe496344e8c Mon Sep 17 00:00:00 2001 From: Tom Ludwig Date: Sun, 4 Aug 2024 10:02:09 +0100 Subject: [PATCH 1/3] Use relatative path instead of absolute path for task execution --- .../CEWorkspaceSettings/Models/CETask.swift | 3 +-- .../CEWorkspaceSettings/Views/AddCETaskView.swift | 6 +++--- .../Views/CEWorkspaceSettingsView.swift | 2 +- .../CEWorkspaceSettings/Views/EditCETaskView.swift | 4 ++-- .../Documents/WorkspaceDocument/WorkspaceDocument.swift | 5 ++++- CodeEdit/Features/Tasks/CEActiveTask.swift | 5 +++-- CodeEdit/Features/Tasks/TaskManager.swift | 8 +++++--- 7 files changed, 19 insertions(+), 14 deletions(-) diff --git a/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Models/CETask.swift b/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Models/CETask.swift index ac45e39650..f316f90af0 100644 --- a/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Models/CETask.swift +++ b/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Models/CETask.swift @@ -30,9 +30,8 @@ class CETask: ObservableObject, Identifiable, Hashable, Codable { self.environmentVariables = environmentVariables } - init(target: String, workingDirectory: String) { + init(target: String) { self.target = target - self.workingDirectory = workingDirectory } var isInvalid: Bool { diff --git a/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Views/AddCETaskView.swift b/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Views/AddCETaskView.swift index a66ff55220..8b4c7f2c16 100644 --- a/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Views/AddCETaskView.swift +++ b/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Views/AddCETaskView.swift @@ -14,8 +14,8 @@ struct AddCETaskView: View { @EnvironmentObject var workspaceSettingsManager: CEWorkspaceSettings @StateObject var newTask: CETask - init(workingDirectory: String) { - self._newTask = StateObject(wrappedValue: CETask(target: "My Mac", workingDirectory: workingDirectory)) + init() { + self._newTask = StateObject(wrappedValue: CETask(target: "My Mac")) } var body: some View { // TODO: Discuss if this is needed @@ -47,5 +47,5 @@ struct AddCETaskView: View { } #Preview { - AddCETaskView(workingDirectory: "/User/") + AddCETaskView() } diff --git a/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Views/CEWorkspaceSettingsView.swift b/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Views/CEWorkspaceSettingsView.swift index 49cf6a6693..3529977471 100644 --- a/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Views/CEWorkspaceSettingsView.swift +++ b/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Views/CEWorkspaceSettingsView.swift @@ -70,7 +70,7 @@ struct CEWorkspaceSettingsView: View { selectedTaskIndex: selectedTaskIndex ) } else { - AddCETaskView(workingDirectory: workspace.fileURL?.relativePath ?? "") + AddCETaskView() } } } diff --git a/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Views/EditCETaskView.swift b/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Views/EditCETaskView.swift index c4264bae9e..5cf1dec053 100644 --- a/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Views/EditCETaskView.swift +++ b/CodeEdit/Features/CEWorkSpaceSettings/CEWorkspaceSettings/Views/EditCETaskView.swift @@ -12,7 +12,7 @@ struct EditCETaskView: View { var dismiss @EnvironmentObject var workspaceSettingsManager: CEWorkspaceSettings - @EnvironmentObject var taskManger: TaskManager + @EnvironmentObject var taskManager: TaskManager @ObservedObject var task: CETask let selectedTaskIndex: Int @@ -31,7 +31,7 @@ struct EditCETaskView: View { $0.id == task.id }) try? workspaceSettingsManager.savePreferences() - taskManger.deleteTask(taskID: task.id) + taskManager.deleteTask(taskID: task.id) self.dismiss() } diff --git a/CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument.swift b/CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument.swift index 3feea29705..3f3df8bfc9 100644 --- a/CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument.swift +++ b/CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument.swift @@ -133,7 +133,10 @@ final class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { self.commandsPaletteState = .init() self.workspaceSettingsManager = CEWorkspaceSettings(workspaceURL: url) if let workspaceSettingsManager { - self.taskManager = TaskManager(workspaceSettings: workspaceSettingsManager.settings) + self.taskManager = TaskManager( + workspaceSettings: workspaceSettingsManager.settings, + workspaceURL: url + ) } editorManager?.restoreFromState(self) diff --git a/CodeEdit/Features/Tasks/CEActiveTask.swift b/CodeEdit/Features/Tasks/CEActiveTask.swift index fa1358804a..1545862f7b 100644 --- a/CodeEdit/Features/Tasks/CEActiveTask.swift +++ b/CodeEdit/Features/Tasks/CEActiveTask.swift @@ -34,8 +34,9 @@ class CEActiveTask: ObservableObject, Identifiable, Hashable { }.store(in: &cancellables) } - func run() { + func run(workspaceURL: URL) { Task { + let fullCommand = "cd \(workspaceURL.relativePath) && \(task.fullCommand)" guard let process, let outputPipe else { return } await updateTaskStatus(to: .running) @@ -61,7 +62,7 @@ class CEActiveTask: ObservableObject, Identifiable, Hashable { do { try Shell.executeCommandWithShell( process: process, - command: self.task.fullCommand, + command: fullCommand, environmentVariables: self.task.environmentVariablesDictionary, shell: Shell.zsh, // TODO: Let user decide which shell he uses outputPipe: outputPipe diff --git a/CodeEdit/Features/Tasks/TaskManager.swift b/CodeEdit/Features/Tasks/TaskManager.swift index 935099c238..ee3cba3975 100644 --- a/CodeEdit/Features/Tasks/TaskManager.swift +++ b/CodeEdit/Features/Tasks/TaskManager.swift @@ -15,9 +15,11 @@ class TaskManager: ObservableObject { @ObservedObject var workspaceSettings: CEWorkspaceSettingsData + private var workspaceURL: URL private var settingsListener: AnyCancellable? - init(workspaceSettings: CEWorkspaceSettingsData) { + init(workspaceSettings: CEWorkspaceSettingsData, workspaceURL: URL) { + self.workspaceURL = workspaceURL self.workspaceSettings = workspaceSettings settingsListener = workspaceSettings.$tasks @@ -67,10 +69,10 @@ class TaskManager: ObservableObject { // but don't initialise a new object. if let activeTask = activeTasks[task.id] { activeTask.renew() - activeTask.run() + activeTask.run(workspaceURL: workspaceURL) } else { let runningTask = CEActiveTask(task: task) - runningTask.run() + runningTask.run(workspaceURL: workspaceURL) Task { await MainActor.run { activeTasks[task.id] = runningTask From 130422b64949a21fd24784b2b7c994e1c292af7d Mon Sep 17 00:00:00 2001 From: Tom Ludwig Date: Thu, 8 Aug 2024 11:39:23 +0100 Subject: [PATCH 2/3] Add comment --- CodeEdit/Features/Tasks/CEActiveTask.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CodeEdit/Features/Tasks/CEActiveTask.swift b/CodeEdit/Features/Tasks/CEActiveTask.swift index 1545862f7b..6e4e6d590d 100644 --- a/CodeEdit/Features/Tasks/CEActiveTask.swift +++ b/CodeEdit/Features/Tasks/CEActiveTask.swift @@ -36,6 +36,8 @@ class CEActiveTask: ObservableObject, Identifiable, Hashable { func run(workspaceURL: URL) { Task { + // Reconstruct the full command to ensure it executes in the correct directory. + // Because: CETask only contains information about the relative path. let fullCommand = "cd \(workspaceURL.relativePath) && \(task.fullCommand)" guard let process, let outputPipe else { return } From caa372517a67dbf47bfaea52fc52f94d2292bf22 Mon Sep 17 00:00:00 2001 From: Tom Ludwig Date: Thu, 8 Aug 2024 12:21:03 +0100 Subject: [PATCH 3/3] fix(test): TaskManger Tests The working directory is now optional because many commands no longer rely on a specified working directory. --- CodeEdit/Features/Tasks/Models/CEActiveTask.swift | 9 +++++++-- CodeEdit/Features/Tasks/TaskManager.swift | 4 ++-- .../Features/Documents/DocumentsUnitTests.swift | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CodeEdit/Features/Tasks/Models/CEActiveTask.swift b/CodeEdit/Features/Tasks/Models/CEActiveTask.swift index 2afd535917..0e0e59bd8d 100644 --- a/CodeEdit/Features/Tasks/Models/CEActiveTask.swift +++ b/CodeEdit/Features/Tasks/Models/CEActiveTask.swift @@ -34,11 +34,16 @@ class CEActiveTask: ObservableObject, Identifiable, Hashable { }.store(in: &cancellables) } - func run(workspaceURL: URL) { + func run(workspaceURL: URL? = nil) { Task { // Reconstruct the full command to ensure it executes in the correct directory. // Because: CETask only contains information about the relative path. - let fullCommand = "cd \(workspaceURL.relativePath) && \(task.fullCommand)" + let fullCommand: String + if let workspaceURL = workspaceURL { + fullCommand = "cd \(workspaceURL.relativePath) && \(task.fullCommand)" + } else { + fullCommand = task.fullCommand + } guard let process, let outputPipe else { return } await updateTaskStatus(to: .running) diff --git a/CodeEdit/Features/Tasks/TaskManager.swift b/CodeEdit/Features/Tasks/TaskManager.swift index 6678b300df..aeb96e2deb 100644 --- a/CodeEdit/Features/Tasks/TaskManager.swift +++ b/CodeEdit/Features/Tasks/TaskManager.swift @@ -16,10 +16,10 @@ class TaskManager: ObservableObject { @ObservedObject var workspaceSettings: CEWorkspaceSettingsData - private var workspaceURL: URL + private var workspaceURL: URL? private var settingsListener: AnyCancellable? - init(workspaceSettings: CEWorkspaceSettingsData, workspaceURL: URL) { + init(workspaceSettings: CEWorkspaceSettingsData, workspaceURL: URL? = nil) { self.workspaceURL = workspaceURL self.workspaceSettings = workspaceSettings diff --git a/CodeEditTests/Features/Documents/DocumentsUnitTests.swift b/CodeEditTests/Features/Documents/DocumentsUnitTests.swift index 503c226249..aa66fdac2b 100644 --- a/CodeEditTests/Features/Documents/DocumentsUnitTests.swift +++ b/CodeEditTests/Features/Documents/DocumentsUnitTests.swift @@ -22,7 +22,7 @@ final class DocumentsUnitTests: XCTestCase { super.setUp() hapticFeedbackPerformerMock = NSHapticFeedbackPerformerMock() navigatorViewModel = .init() - workspace.taskManager = TaskManager(workspaceSettings: .init()) + workspace.taskManager = TaskManager(workspaceSettings: CEWorkspaceSettingsData()) window = NSWindow() splitViewController = .init( workspace: workspace,