Skip to content

Commit 80a6ceb

Browse files
committed
Add sentinal file in scratchpath
Add a sentinal file (one for each build configuration) in the scratch path that contains the contents of the last build system used to build said configuration. Relates to: swiftlang/sourcekit-lsp#2576
1 parent 5446232 commit 80a6ceb

3 files changed

Lines changed: 134 additions & 17 deletions

File tree

Sources/CoreCommands/SwiftCommandState.swift

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ extension SwiftCommand {
130130
)
131131
defer {
132132
_ = createCacheDirFile(inDirectory: swiftCommandState.scratchDirectory)
133+
_ = createBuildSystemFile(
134+
inDirectory: swiftCommandState.scratchDirectory,
135+
for: swiftCommandState.options.build.configuration ?? swiftCommandState.preferredBuildConfiguration,
136+
buildSystem: swiftCommandState.options.build.buildSystem,
137+
)
133138
}
134139

135140
// We use this to attempt to catch misuse of the locking APIs since we only release the lock from here.
@@ -164,7 +169,8 @@ extension SwiftCommand {
164169

165170
package func createCacheDirFile(
166171
inDirectory directory: AbsolutePath,
167-
_ fileSystem: FileSystem = localFileSystem) -> AbsolutePath? {
172+
_ fileSystem: FileSystem = localFileSystem,
173+
) -> AbsolutePath? {
168174
// https://bford.info/cachedir/
169175
let path = directory.appending("CACHEDIR.TAG")
170176
do {
@@ -181,8 +187,25 @@ package func createCacheDirFile(
181187
// Don't error out if we fail to create the CACHEDIR.TAG file, as this is not critical to the functioning of the tool.
182188
return nil
183189
}
190+
}
184191

192+
package func createBuildSystemFile(
193+
inDirectory directory: AbsolutePath,
194+
for configuration: BuildConfiguration,
195+
buildSystem: BuildSystemProvider.Kind,
196+
fileSystem fs: FileSystem = localFileSystem,
197+
) -> AbsolutePath? {
198+
let path = directory.appending(".buildSystem_\(configuration)")
199+
do {
200+
try fs.createDirectory(path.parentDirectory, recursive: true)
201+
try fs.writeFileContents(path, string: "\(buildSystem)")
202+
return path
203+
} catch {
204+
// Don't error out if we fail to create the CACHEDIR.TAG file, as this is not critical to the functioning of the tool.
205+
return nil
206+
}
185207
}
208+
186209
public protocol AsyncSwiftCommand: AsyncParsableCommand, _SwiftCommand {
187210
func run(_ swiftCommandState: SwiftCommandState) async throws
188211
var addCacheDirTagFile: Bool { get }
@@ -206,6 +229,11 @@ extension AsyncSwiftCommand {
206229
if self.addCacheDirTagFile {
207230
_ = createCacheDirFile(inDirectory: swiftCommandState.scratchDirectory)
208231
}
232+
_ = createBuildSystemFile(
233+
inDirectory: swiftCommandState.scratchDirectory,
234+
for: swiftCommandState.options.build.configuration ?? swiftCommandState.preferredBuildConfiguration,
235+
buildSystem: swiftCommandState.options.build.buildSystem,
236+
)
209237
}
210238

211239
// We use this to attempt to catch misuse of the locking APIs since we only release the lock from here.

Sources/_InternalTestSupport/SwiftTesting+Helpers.swift

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import Testing
1717
fileprivate func fileErrorMessage(
1818
at path: AbsolutePath,
1919
prefix: Comment?,
20+
fileSystem fs: FileSystem = localFileSystem,
2021
comment: Comment,
2122
) -> Comment {
2223
let commentPrefix =
@@ -29,22 +30,24 @@ fileprivate func fileErrorMessage(
2930
let commentSuffix: String
3031
do {
3132
let parentDir = path.parentDirectory
32-
commentSuffix = try " Directory contents of \(parentDir) : \(localFileSystem.getDirectoryContents(parentDir))."
33+
commentSuffix = try " Directory contents of \(parentDir) : \(fs.getDirectoryContents(parentDir))."
3334
} catch {
3435
commentSuffix = ""
3536
}
36-
return Comment("\(commentPrefix)\(comment) \(commentSuffix).")
37+
return Comment("\(commentPrefix)\(comment)\(commentSuffix)")
3738
}
3839
public func expectFileExists(
3940
at path: AbsolutePath,
4041
_ comment: Comment? = nil,
42+
fileSystem fs: FileSystem = localFileSystem,
4143
sourceLocation: SourceLocation = #_sourceLocation,
4244
) {
4345
#expect(
44-
localFileSystem.exists(path),
46+
fs.exists(path),
4547
fileErrorMessage(
4648
at: path,
4749
prefix: comment,
50+
fileSystem: fs,
4851
comment: "File '\(path)' does not exist.",
4952
),
5053
sourceLocation: sourceLocation,
@@ -54,13 +57,15 @@ public func expectFileExists(
5457
public func requireFileExists(
5558
at path: AbsolutePath,
5659
_ comment: Comment? = nil,
60+
fileSystem fs: FileSystem = localFileSystem,
5761
sourceLocation: SourceLocation = #_sourceLocation,
5862
) throws {
5963
try #require(
60-
localFileSystem.exists(path),
64+
fs.exists(path),
6165
fileErrorMessage(
6266
at: path,
6367
prefix: comment,
68+
fileSystem: fs,
6469
comment: "File '\(path)' does not exist.",
6570
),
6671
sourceLocation: sourceLocation,
@@ -70,13 +75,15 @@ public func requireFileExists(
7075
public func expectFileDoesNotExists(
7176
at path: AbsolutePath,
7277
_ comment: Comment? = nil,
78+
fileSystem fs: FileSystem = localFileSystem,
7379
sourceLocation: SourceLocation = #_sourceLocation,
7480
) {
7581
#expect(
76-
!localFileSystem.exists(path),
82+
!fs.exists(path),
7783
fileErrorMessage(
7884
at: path,
7985
prefix: comment,
86+
fileSystem: fs,
8087
comment: "File: '\(path)' was not expected to exist, but does.",
8188
),
8289
sourceLocation: sourceLocation,
@@ -85,13 +92,15 @@ public func expectFileDoesNotExists(
8592
public func requireFileDoesNotExists(
8693
at path: AbsolutePath,
8794
_ comment: Comment? = nil,
95+
fileSystem fs: FileSystem = localFileSystem,
8896
sourceLocation: SourceLocation = #_sourceLocation,
8997
) throws {
9098
try #require(
91-
!localFileSystem.exists(path),
99+
!fs.exists(path),
92100
fileErrorMessage(
93101
at: path,
94102
prefix: comment,
103+
fileSystem: fs,
95104
comment: "File: '\(path)' was not expected to exist, but does.",
96105
),
97106
sourceLocation: sourceLocation,
@@ -101,6 +110,7 @@ public func requireFileDoesNotExists(
101110
public func expectFileIsExecutable(
102111
at fixturePath: AbsolutePath,
103112
_ comment: Comment? = nil,
113+
fileSystem fs: FileSystem = localFileSystem,
104114
sourceLocation: SourceLocation = #_sourceLocation,
105115
) {
106116
let commentPrefix =
@@ -110,15 +120,16 @@ public func expectFileIsExecutable(
110120
""
111121
}
112122
#expect(
113-
localFileSystem.isExecutableFile(fixturePath),
123+
fs.isExecutableFile(fixturePath),
114124
"\(commentPrefix)File '\(fixturePath)' expected to be executable, but is not.",
115125
sourceLocation: sourceLocation,
116126
)
117127
}
118128

119129
private func directoryExistsErrorMessage(
120130
for path: AbsolutePath,
121-
comment: Comment?
131+
comment: Comment?,
132+
fileSystem fs: FileSystem = localFileSystem,
122133
) -> Comment {
123134
let commentPrefix =
124135
if let comment {
@@ -128,7 +139,7 @@ private func directoryExistsErrorMessage(
128139
}
129140
let msgSuffix: String
130141
do {
131-
msgSuffix = try "Directory contents: \(localFileSystem.getDirectoryContents(path))"
142+
msgSuffix = try "Directory contents: \(fs.getDirectoryContents(path))"
132143
} catch {
133144
msgSuffix = ""
134145
}
@@ -138,40 +149,76 @@ private func directoryExistsErrorMessage(
138149
public func requireDirectoryExists(
139150
at path: AbsolutePath,
140151
_ comment: Comment? = nil,
141-
fileSystem: FileSystem = localFileSystem,
152+
fileSystem fs: FileSystem = localFileSystem,
142153
sourceLocation: SourceLocation = #_sourceLocation,
143154
) throws {
144155
try #require(
145-
localFileSystem.isDirectory(path),
156+
fs.isDirectory(path),
146157
directoryExistsErrorMessage(for: path, comment: comment),
147158
sourceLocation: sourceLocation,
148159
)
149160
}
150161

162+
@available(*, deprecated, message: "use `expectDirectoryExist` instead.")
151163
public func expectDirectoryExists(
152164
at path: AbsolutePath,
153165
_ comment: Comment? = nil,
166+
fileSystem fs: FileSystem = localFileSystem,
167+
sourceLocation: SourceLocation = #_sourceLocation,
168+
) {
169+
expectDirectoryExists(
170+
at: path,
171+
comment,
172+
fileSystem: fs,
173+
sourceLocation: sourceLocation,
174+
)
175+
}
176+
177+
public func expectDirectoryExist(
178+
at path: AbsolutePath,
179+
_ comment: Comment? = nil,
180+
fileSystem fs: FileSystem = localFileSystem,
154181
sourceLocation: SourceLocation = #_sourceLocation,
155182
) {
156183
#expect(
157-
localFileSystem.isDirectory(path),
158-
directoryExistsErrorMessage(for: path, comment: comment),
184+
fs.isDirectory(path),
185+
directoryExistsErrorMessage(for: path, comment: comment, fileSystem: fs),
186+
sourceLocation: sourceLocation,
187+
)
188+
}
189+
190+
public func requireDirectoryDoesNotExist(
191+
at path: AbsolutePath,
192+
fileSystem fs: FileSystem = localFileSystem,
193+
sourceLocation: SourceLocation = #_sourceLocation,
194+
) throws {
195+
let msgSuffix: String
196+
do {
197+
msgSuffix = try "Directory contents: \(fs.getDirectoryContents(path))"
198+
} catch {
199+
msgSuffix = ""
200+
}
201+
try #require(
202+
!fs.isDirectory(path),
203+
"Directory exists unexpectedly: '\(path)'.\(msgSuffix)",
159204
sourceLocation: sourceLocation,
160205
)
161206
}
162207

208+
163209
public func expectDirectoryDoesNotExist(
164210
at path: AbsolutePath,
211+
fileSystem fs: FileSystem = localFileSystem,
165212
sourceLocation: SourceLocation = #_sourceLocation,
166213
) {
167214
let msgSuffix: String
168215
do {
169-
msgSuffix = try "Directory contents: \(localFileSystem.getDirectoryContents(path))"
216+
msgSuffix = try "Directory contents: \(fs.getDirectoryContents(path))"
170217
} catch {
171218
msgSuffix = ""
172219
}
173220
#expect(
174-
!localFileSystem.isDirectory(path),
221+
!fs.isDirectory(path),
175222
"Directory exists unexpectedly: '\(path)'.\(msgSuffix)",
176223
sourceLocation: sourceLocation,
177224
)
@@ -181,10 +228,11 @@ public func expectDirectoryDoesNotExist(
181228
package func expectDirectoryContainsFile(
182229
dir: AbsolutePath,
183230
filename: String,
231+
fileSystem fs: FileSystem = localFileSystem,
184232
sourceLocation: SourceLocation = #_sourceLocation,
185233
) {
186234
do {
187-
for entry in try walk(dir) {
235+
for entry in try walk(dir, fileSystem: fs) {
188236
if entry.basename == filename { return }
189237
}
190238
} catch {

Tests/CommandsTests/SwiftCommandStateTests.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
@testable import Commands
1616
@testable import CoreCommands
1717

18+
import struct SPMBuildCore.BuildSystemProvider
1819
@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly)
1920
import func PackageGraph.loadModulesGraph
2021

@@ -55,6 +56,46 @@ struct SwiftCommandStateTestSuites {
5556
try #require(contentArray.isEmpty == false, "Content array is empty, when it shouldn't be. Content is: \(contents)")
5657
#expect(contentArray[0] == "Signature: 8a477f597d28d172789f06886806bc55")
5758
}
59+
60+
@Test(
61+
// arguments: getBuildData(for: BuildSystemProvider.Kind.allCases)
62+
) func createBuildSystemFileContainsExpectedContents(
63+
// buildData: BuildData,
64+
) async throws {
65+
let buildData = BuildData(
66+
buildSystem: BuildSystemProvider.Kind.swiftbuild,
67+
config: BuildConfiguration.debug,
68+
)
69+
70+
let fs = InMemoryFileSystem()
71+
let dir = AbsolutePath.root.appending(components: "tmp", "output", "build")
72+
let buildSystemDefinitionFile = dir.appending(".buildSystem_\(buildData.config)")
73+
74+
try requireFileDoesNotExists(
75+
at: buildSystemDefinitionFile,
76+
fileSystem: fs,
77+
)
78+
let actualBuildSystemDefinition = try #require(
79+
createBuildSystemFile(
80+
inDirectory: dir,
81+
for: buildData.config,
82+
buildSystem: buildData.buildSystem,
83+
fileSystem: fs,
84+
)
85+
)
86+
87+
// Assert
88+
try #require(actualBuildSystemDefinition == buildSystemDefinitionFile)
89+
try requireFileExists(
90+
at: actualBuildSystemDefinition,
91+
fileSystem: fs
92+
)
93+
let contents = try fs.readFileContents(actualBuildSystemDefinition).description
94+
#expect(
95+
contents == "\(buildData.buildSystem)",
96+
"Actual is not as expected",
97+
)
98+
}
5899
}
59100

60101
final class SwiftCommandStateTests: XCTestCase {

0 commit comments

Comments
 (0)