@@ -23,6 +23,8 @@ import Foundation
2323import GRPC
2424
2525actor BuildFSSync : BuildPipelineHandler {
26+ private static let archiveRootURL = URL ( filePath: " / " , directoryHint: . isDirectory)
27+
2628 let contextDir : URL
2729
2830 init ( _ contextDir: URL ) throws {
@@ -114,7 +116,6 @@ actor BuildFSSync: BuildPipelineHandler {
114116 }
115117
116118 private struct DirEntry : Hashable {
117- let url : URL
118119 let isDirectory : Bool
119120 let relativePath : String
120121
@@ -133,30 +134,32 @@ actor BuildFSSync: BuildPipelineHandler {
133134 _ buildID: String
134135 ) async throws {
135136 let wantsTar = packet. mode ( ) == " tar "
137+ let contextPath = contextDir. path
138+ let contextPrefix = contextPath. hasSuffix ( " / " ) ? contextPath : contextPath + " / "
136139
137140 var entries : [ String : Set < DirEntry > ] = [ : ]
138141 let followPaths : [ String ] = packet. followPaths ( ) ?? [ ]
139142
140143 let followPathsWalked = try walk ( root: self . contextDir, includePatterns: followPaths)
141144 for url in followPathsWalked {
142- guard self . contextDir. absoluteURL. cleanPath != url. absoluteURL. cleanPath else {
145+ let path = url. path
146+ guard path != contextPath else {
143147 continue
144148 }
145- guard self . contextDir . parentOf ( url ) else {
149+ guard let relPath = Self . relativeChildPath ( path : path , contextPath : contextPath , contextPrefix : contextPrefix ) else {
146150 continue
147151 }
148152
149- let relPath = try url. relativeChildPath ( to: contextDir)
150- let parentPath = try url. deletingLastPathComponent ( ) . relativeChildPath ( to: contextDir)
151- let entry = DirEntry ( url: url, isDirectory: url. hasDirectoryPath, relativePath: relPath)
153+ let parentPath = Self . relativeParentPath ( path: path, contextPath: contextPath, contextPrefix: contextPrefix)
154+ let entry = DirEntry ( isDirectory: url. hasDirectoryPath, relativePath: relPath)
152155 entries [ parentPath, default: [ ] ] . insert ( entry)
153156
154157 if url. isSymlink {
155158 let target : URL = url. resolvingSymlinksInPath ( )
156- if self . contextDir . parentOf ( target ) {
157- let relPath = try target . relativeChildPath ( to : self . contextDir )
158- let entry = DirEntry ( url : target , isDirectory: target. hasDirectoryPath, relativePath: relPath)
159- let parentPath : String = try target . deletingLastPathComponent ( ) . relativeChildPath ( to : self . contextDir )
159+ let targetPath = target . path
160+ if let relPath = Self . relativeChildPath ( path : targetPath , contextPath : contextPath , contextPrefix : contextPrefix ) {
161+ let entry = DirEntry ( isDirectory: target. hasDirectoryPath, relativePath: relPath)
162+ let parentPath = Self . relativeParentPath ( path : targetPath , contextPath : contextPath , contextPrefix : contextPrefix )
160163 entries [ parentPath, default: [ ] ] . insert ( entry)
161164 }
162165 }
@@ -200,35 +203,18 @@ actor BuildFSSync: BuildPipelineHandler {
200203 format: . paxRestricted,
201204 filter: . none)
202205
206+ let archiveEntries = fileOrder. map { rel in
207+ Archiver . ArchiveEntryInfo (
208+ pathOnHost: contextDir. appending ( path: rel, directoryHint: . notDirectory) ,
209+ pathInArchive: URL ( filePath: rel, directoryHint: . notDirectory, relativeTo: Self . archiveRootURL)
210+ )
211+ }
212+
203213 let tarHash = try Archiver . compress (
204- source : contextDir ,
214+ entries : archiveEntries ,
205215 destination: tarURL,
206216 writerConfiguration: writerCfg
207- ) { url in
208- guard let rel = try ? url. relativeChildPath ( to: contextDir) else {
209- return nil
210- }
211-
212- guard let parent = try ? url. deletingLastPathComponent ( ) . relativeChildPath ( to: self . contextDir) else {
213- return nil
214- }
215-
216- guard let items = entries [ parent] else {
217- return nil
218- }
219-
220- let include = items. contains { item in
221- item. relativePath == rel
222- }
223-
224- guard include else {
225- return nil
226- }
227-
228- return Archiver . ArchiveEntryInfo (
229- pathOnHost: url,
230- pathInArchive: URL ( fileURLWithPath: rel) )
231- }
217+ )
232218
233219 let hash = tarHash. compactMap { String ( format: " %02x " , $0) } . joined ( )
234220 let header = BuildTransfer (
@@ -323,6 +309,21 @@ actor BuildFSSync: BuildPipelineHandler {
323309 }
324310 }
325311
312+ private static func relativeChildPath( path: String , contextPath: String , contextPrefix: String ) -> String ? {
313+ if path == contextPath {
314+ return " "
315+ }
316+ guard path. hasPrefix ( contextPrefix) else {
317+ return nil
318+ }
319+ return String ( path. dropFirst ( contextPrefix. count) )
320+ }
321+
322+ private static func relativeParentPath( path: String , contextPath: String , contextPrefix: String ) -> String {
323+ let parentPath = ( path as NSString ) . deletingLastPathComponent
324+ return relativeChildPath ( path: parentPath, contextPath: contextPath, contextPrefix: contextPrefix) ?? " "
325+ }
326+
326327 struct FileInfo : Codable {
327328 let name : String
328329 let modTime : String
0 commit comments