Skip to content

Commit

Permalink
Fix: Tasks In Folder With Spaces (#1978)
Browse files Browse the repository at this point in the history
* Fix: Tasks In Folder With Spaces

* Escape Quotes, Fix Git Client Cases
thecoolwinter authored Jan 30, 2025

Verified

This commit was signed with the committer’s verified signature.
nickzelei Nick Zelei
1 parent 40d6016 commit f24981a
Showing 9 changed files with 77 additions and 23 deletions.
8 changes: 4 additions & 4 deletions CodeEdit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
@@ -344,7 +344,7 @@
661EF7BD2BEE215300C3E577 /* LoadingFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 661EF7BC2BEE215300C3E577 /* LoadingFileView.swift */; };
664935422C35A5BC00461C35 /* NSTableViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664935412C35A5BC00461C35 /* NSTableViewWrapper.swift */; };
6653EE552C34817900B82DE2 /* QuickSearchResultLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6653EE542C34817900B82DE2 /* QuickSearchResultLabel.swift */; };
669A50512C380C1800304CD8 /* String+escapedWhiteSpaces.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669A50502C380C1800304CD8 /* String+escapedWhiteSpaces.swift */; };
669A50512C380C1800304CD8 /* String+Escaped.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669A50502C380C1800304CD8 /* String+Escaped.swift */; };
669A50532C380C8E00304CD8 /* Collection+subscript_safe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669A50522C380C8E00304CD8 /* Collection+subscript_safe.swift */; };
669BC4082BED306400D1197C /* AnyFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669BC4072BED306400D1197C /* AnyFileView.swift */; };
66AF6CE22BF17CC300D83C9D /* StatusBarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66AF6CE12BF17CC300D83C9D /* StatusBarViewModel.swift */; };
@@ -1049,7 +1049,7 @@
661EF7BC2BEE215300C3E577 /* LoadingFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingFileView.swift; sourceTree = "<group>"; };
664935412C35A5BC00461C35 /* NSTableViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSTableViewWrapper.swift; sourceTree = "<group>"; };
6653EE542C34817900B82DE2 /* QuickSearchResultLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSearchResultLabel.swift; sourceTree = "<group>"; };
669A50502C380C1800304CD8 /* String+escapedWhiteSpaces.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+escapedWhiteSpaces.swift"; sourceTree = "<group>"; };
669A50502C380C1800304CD8 /* String+Escaped.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Escaped.swift"; sourceTree = "<group>"; };
669A50522C380C8E00304CD8 /* Collection+subscript_safe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+subscript_safe.swift"; sourceTree = "<group>"; };
669BC4072BED306400D1197C /* AnyFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyFileView.swift; sourceTree = "<group>"; };
66AF6CE12BF17CC300D83C9D /* StatusBarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBarViewModel.swift; sourceTree = "<group>"; };
@@ -2534,7 +2534,7 @@
children = (
61538B8F2B111FE800A88846 /* String+AppearancesOfSubstring.swift */,
61538B922B11201900A88846 /* String+Character.swift */,
669A50502C380C1800304CD8 /* String+escapedWhiteSpaces.swift */,
669A50502C380C1800304CD8 /* String+Escaped.swift */,
85745D622A38F8D900089AAB /* String+HighlightOccurrences.swift */,
6CED16E32A3E660D000EC962 /* String+Lines.swift */,
58D01C8E293167DC00C5B6B4 /* String+MD5.swift */,
@@ -4537,7 +4537,7 @@
B65B10F52B081A0C002852CF /* SourceControlAddExistingRemoteView.swift in Sources */,
58D01C99293167DC00C5B6B4 /* String+MD5.swift in Sources */,
20EBB505280C329800F3A5DA /* CommitListItemView.swift in Sources */,
669A50512C380C1800304CD8 /* String+escapedWhiteSpaces.swift in Sources */,
669A50512C380C1800304CD8 /* String+Escaped.swift in Sources */,
5878DAB2291D627C00DD95A3 /* EditorJumpBarView.swift in Sources */,
664935422C35A5BC00461C35 /* NSTableViewWrapper.swift in Sources */,
04BC1CDE2AD9B4B000A83EA5 /* EditorFileTabCloseButton.swift in Sources */,
2 changes: 1 addition & 1 deletion CodeEdit/Features/CEWorkspaceSettings/Models/CETask.swift
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ class CETask: ObservableObject, Identifiable, Hashable, Codable {
/// Ensures that the shell navigates to the correct folder, and then executes the specified command.
var fullCommand: String {
// Move into the specified folder if needed
let changeDirectoryCommand = workingDirectory.isEmpty ? "" : "cd \(workingDirectory) && "
let changeDirectoryCommand = workingDirectory.isEmpty ? "" : "cd \(workingDirectory.escapedDirectory()) && "

// Construct the full command
return "\(changeDirectoryCommand)\(command)"
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ extension GitClient {
remoteUrl: URL,
localPath: URL
) -> AsyncThrowingMapSequence<LiveCommandStream, CloneProgress> {
let command = "clone \(remoteUrl.absoluteString) \(localPath.relativePath.escapedWhiteSpaces()) --progress"
let command = "clone \(remoteUrl.absoluteString) \(localPath.relativePath.escapedDirectory()) --progress"

return self.runLive(command)
.map { line in
2 changes: 1 addition & 1 deletion CodeEdit/Features/SourceControl/Client/GitClient.swift
Original file line number Diff line number Diff line change
@@ -78,7 +78,7 @@ class GitClient {
}

private func generateCommand(_ command: String) -> String {
"cd \(directoryURL.relativePath.escapedWhiteSpaces());git \(command)"
"cd \(directoryURL.relativePath.escapedDirectory());git \(command)"
}

private func processCommonErrors(_ output: String) throws -> String {
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ class GitConfigClient {
if global {
fullCommand += " --global"
} else if let projectURL = projectURL {
fullCommand = "cd \(projectURL.relativePath.escapedWhiteSpaces()); " + fullCommand
fullCommand = "cd \(projectURL.relativePath.escapedDirectory()); " + fullCommand
}

fullCommand += " \(command)"
2 changes: 1 addition & 1 deletion CodeEdit/Features/Tasks/Models/CEActiveTask.swift
Original file line number Diff line number Diff line change
@@ -40,7 +40,7 @@ class CEActiveTask: ObservableObject, Identifiable, Hashable {
// Because: CETask only contains information about the relative path.
let fullCommand: String
if let workspaceURL = workspaceURL {
fullCommand = "cd \(workspaceURL.relativePath) && \(task.fullCommand)"
fullCommand = "cd \(workspaceURL.relativePath.escapedDirectory()) && \(task.fullCommand)"
} else {
fullCommand = task.fullCommand
}
51 changes: 51 additions & 0 deletions CodeEdit/Utils/Extensions/String/String+Escaped.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// String+escapedWhiteSpaces.swift
// CodeEdit
//
// Created by Paul Ebose on 2024/07/05.
//

import Foundation

extension String {
/// Escapes the string so it's an always-valid directory
func escapedDirectory() -> String {
"\"\(self.escapedQuotes())\""
}

/// Returns a new string, replacing all occurrences of ` ` with `\ ` if they aren't already escaped.
func escapedWhiteSpaces() -> String {
escape(replacing: " ")
}

/// Returns a new string, replacing all occurrences of `"` with `\"` if they aren't already escaped.
func escapedQuotes() -> String {
escape(replacing: #"""#)
}

func escape(replacing: Character) -> String {
var string = ""
var lastChar: Character?

for char in self {
defer {
lastChar = char
}

guard char == replacing else {
string.append(char)
continue
}

if let lastChar, lastChar == #"\"# {
string.append(char)
continue
}

string.append(#"\"#)
string.append(char)
}

return string
}
}
14 changes: 0 additions & 14 deletions CodeEdit/Utils/Extensions/String/String+escapedWhiteSpaces.swift

This file was deleted.

17 changes: 17 additions & 0 deletions CodeEditTests/Utils/UnitTests_Extensions.swift
Original file line number Diff line number Diff line change
@@ -179,4 +179,21 @@ final class CodeEditUtilsExtensionsUnitTests: XCTestCase {
XCTAssertFalse(invalidCase.isValidFilename, "Detected valid case \"\(invalidCase)\", should be invalid.")
}
}

// MARK: - STRING + ESCAPED

func testEscapeQuotes() {
let string = #"this/is/"a path/Hello "world"#
XCTAssertEqual(string.escapedQuotes(), #"this/is/\"a path/Hello \"world"#)
}

func testEscapeQuotesForAlreadyEscapedString() {
let string = #"this/is/"a path/Hello \"world"#
XCTAssertEqual(string.escapedQuotes(), #"this/is/\"a path/Hello \"world"#)
}

func testEscapedDirectory() {
let path = #"/Hello World/ With Spaces/ And " Characters "#
XCTAssertEqual(path.escapedDirectory(), #""/Hello World/ With Spaces/ And \" Characters ""#)
}
}

0 comments on commit f24981a

Please sign in to comment.