Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix watcher crashing in package subdirectories #67

Merged
merged 6 commits into from
Jul 25, 2020
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
5 changes: 5 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
"type": "shell",
"command": "swift build && cd TestApp && ../.build/debug/carton dev --product TestApp"
},
{
"label": "build and run dev in subdirectory",
"type": "shell",
"command": "swift build && cd TestApp/Sources/TestApp && ../../../.build/debug/carton dev --product TestApp"
},
{
"label": "build and run test",
"type": "shell",
Expand Down
6 changes: 5 additions & 1 deletion Sources/CartonHelpers/ProcessRunner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ public final class ProcessRunner {
}, receiveCompletion: {
switch $0 {
case .finished:
terminal.write("\nProcess completed successfully\n", inColor: .green, bold: false)
terminal.write(
"\n`\(AbsolutePath(arguments[0]).basename)` process finished successfully\n",
inColor: .green,
bold: false
)
case let .failure(error):
let errorString = String(describing: error)
if errorString.isEmpty {
Expand Down
30 changes: 27 additions & 3 deletions Sources/SwiftToolchain/Toolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ enum ToolchainError: Error, CustomStringConvertible {
case .failedToBuildTestBundle:
return "Failed to build the test bundle"
case .missingPackage:
return "No package found"
return """
The `Package.swift` manifest file could not be found. Please navigate to a directory that \
contains `Package.swift` and restart.
"""
}
}
}
Expand Down Expand Up @@ -118,8 +121,27 @@ public final class Toolchain {
}
}

private func inferManifestDirectory() throws -> AbsolutePath {
guard package != nil, var cwd = fileSystem.currentWorkingDirectory else {
throw ToolchainError.missingPackage
}

repeat {
guard !fileSystem.isFile(cwd.appending(component: "Package.swift")) else {
return cwd
}

// `parentDirectory` just returns `self` if it's `root`
cwd = cwd.parentDirectory
} while !cwd.isRoot

throw ToolchainError.missingPackage
}

public func inferSourcesPaths() throws -> [AbsolutePath] {
let package = try Package(with: swiftPath, terminal)
guard let package = package else {
throw ToolchainError.missingPackage
}

let targetPaths = package.targets.compactMap { target -> String? in
guard let path = target.path else {
Expand All @@ -133,8 +155,10 @@ public final class Toolchain {
return path
}

let manifestDirectory = try inferManifestDirectory()

return try targetPaths.compactMap {
try fileSystem.currentWorkingDirectory?.appending(RelativePath(validating: $0))
try manifestDirectory.appending(RelativePath(validating: $0))
}
}

Expand Down
2 changes: 2 additions & 0 deletions Sources/carton/Combine/Watcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ final class Watcher {
init(_ paths: [AbsolutePath]) throws {
publisher = subject.eraseToAnyPublisher()

guard !paths.isEmpty else { return }

fsWatch = FSWatch(paths: paths, latency: 0.1) { [weak self] in
self?.subject.send($0)
}
Expand Down
15 changes: 11 additions & 4 deletions Sources/carton/Helpers/FileSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,18 @@ import Foundation
import TSCBasic

extension FileSystem {
func traverseRecursively(_ root: AbsolutePath) throws -> [AbsolutePath] {
precondition(isDirectory(root))
var result = [root]
func traverseRecursively(_ traversalRoot: AbsolutePath) throws -> [AbsolutePath] {
guard exists(traversalRoot, followSymlink: true) else {
return []
}

var result = [traversalRoot]

guard isDirectory(traversalRoot) else {
return result
}

var pathsToTraverse = [root]
var pathsToTraverse = result
while let currentDirectory = pathsToTraverse.popLast() {
let directoryContents = try getDirectoryContents(currentDirectory)
.map(currentDirectory.appending)
Expand Down