Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: copyconstruct/swift-tools-support-async
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: apple/swift-tools-support-async
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Able to merge. These branches can be automatically merged.
Loading
Showing with 1,286 additions and 471 deletions.
  1. +15 −0 LICENSE.txt
  2. +33 −6 Package.resolved
  3. +30 −6 Package.swift
  4. +22 −0 Protos/CASFileTreeProtocol/file_tree.proto
  5. +2 −2 README.md
  6. +2 −1 Sources/TSFCAS/DataID.swift
  7. +4 −3 Sources/TSFCAS/Database.swift
  8. +1 −0 Sources/TSFCAS/DatabaseSpec.swift
  9. +10 −3 Sources/TSFCAS/Generated/CASProtocol/cas_object.pb.swift
  10. +9 −2 Sources/TSFCAS/Generated/CASProtocol/data_id.pb.swift
  11. +1 −0 Sources/TSFCAS/Implementations/Blake3DataID.swift
  12. +3 −6 Sources/TSFCAS/Implementations/FileBackedCASDatabase.swift
  13. +29 −22 Sources/TSFCAS/Implementations/InMemoryCASDatabase.swift
  14. +6 −4 Sources/TSFCAS/Object.swift
  15. +32 −13 Sources/TSFCASFileTree/CASBlob.swift
  16. +10 −3 Sources/TSFCASFileTree/CASFSClient.swift
  17. +4 −3 Sources/TSFCASFileTree/{Internal → }/ConcurrentFileTreeWalker.swift
  18. +2 −2 Sources/TSFCASFileTree/Context.swift
  19. +2 −3 Sources/TSFCASFileTree/DeclFileTree.swift
  20. +23 −6 Sources/TSFCASFileTree/DirectoryEntry.swift
  21. +4 −2 Sources/TSFCASFileTree/FileInfo.swift
  22. +35 −22 Sources/TSFCASFileTree/FileTree.swift
  23. +91 −37 Sources/TSFCASFileTree/FileTreeExport.swift
  24. +208 −111 Sources/TSFCASFileTree/FileTreeImport.swift
  25. +107 −29 Sources/TSFCASFileTree/FilesystemObject.swift
  26. +183 −23 Sources/TSFCASFileTree/Generated/CASFileTreeProtocol/file_tree.pb.swift
  27. +6 −4 Sources/TSFCASFileTree/Internal/ConcurrentFilesystemScanner.swift
  28. +7 −8 Sources/TSFCASFileTree/Internal/FileSegmenter.swift
  29. +21 −18 Sources/TSFCASFileTree/Internal/FileTreeParser.swift
  30. +12 −0 Sources/TSFCASFileTree/TSCCASFileSystem.swift
  31. +7 −6 Sources/TSFCASUtilities/BufferedStreamWriter.swift
  32. +1 −0 Sources/TSFCASUtilities/LinkedListStream.swift
  33. +1 −0 Sources/TSFCASUtilities/StreamReader.swift
  34. +15 −3 Sources/TSFFutures/BatchingFutureOperationQueue.swift
  35. +15 −0 Sources/TSFFutures/CancellableFuture.swift
  36. +9 −6 Sources/TSFFutures/CancellablePromise.swift
  37. +2 −2 Sources/TSFFutures/Canceller.swift
  38. +2 −0 Sources/TSFFutures/EventualResultsCache.swift
  39. +2 −1 Sources/TSFFutures/FutureDeduplicator.swift
  40. +69 −42 Sources/TSFFutures/FutureOperationQueue.swift
  41. +2 −2 Sources/TSFFutures/Futures.swift
  42. +25 −29 Sources/TSFFutures/OrderManager.swift
  43. +11 −5 Sources/TSFUtility/ByteBuffer.swift
  44. +1 −0 Sources/TSFUtility/FastData.swift
  45. +1 −0 Sources/TSFUtility/FutureFileSystem.swift
  46. +1 −0 Sources/TSFUtility/Serializable.swift
  47. +1 −1 Tests/TSFCASFileTreeTests/CASBlobTests.swift
  48. +52 −2 Tests/TSFCASFileTreeTests/FileTreeImportExportTests.swift
  49. +10 −10 Tests/TSFCASFileTreeTests/FileTreeTests.swift
  50. +3 −1 Tests/TSFCASTests/FileBackedCASDatabaseTests.swift
  51. +1 −1 Tests/TSFCASTests/InMemoryCASDatabaseTests.swift
  52. +2 −2 Tests/TSFCASUtilitiesTests/BufferedStreamWriterTests.swift
  53. +74 −0 Tests/TSFFuturesTests/BatchingFutureOperationQueue.swift
  54. +4 −3 Tests/TSFFuturesTests/CancellableFutureTests.swift
  55. +4 −3 Tests/TSFFuturesTests/CancellerTests.swift
  56. +55 −6 Tests/TSFFuturesTests/FutureOperationQueueTests.swift
  57. +0 −5 Tests/TSFFuturesTests/OrderManagerTests.swift
  58. +2 −2 Utilities/build_proto_toolchain.sh
15 changes: 15 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -208,3 +208,18 @@
portions of this Software are embedded into the binary product as a result,
you may redistribute such product without providing attribution as would
otherwise be required by Sections 4(a), 4(b) and 4(d) of the License.

## Copyrights and Licenses for Third Party Software Distributed with swift-tools-support-async: ##

The swift-tools-support-async software contains code written by third parties.
Such software will have its own individual LICENSE file as part of its
source or in the directory in which it appears. This file will describe the
copyrights, license, and restrictions which apply to that code.

The following pieces of software have additional or alternate copyrights,
licenses, and/or restrictions:

Program Directory
------- ---------
BLAKE3 ThirdParty/BLAKE3

39 changes: 33 additions & 6 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,31 +1,58 @@
{
"object": {
"pins": [
{
"package": "swift-atomics",
"repositoryURL": "https://github.com/apple/swift-atomics.git",
"state": {
"branch": null,
"revision": "cd142fd2f64be2100422d658e7411e39489da985",
"version": "1.2.0"
}
},
{
"package": "swift-collections",
"repositoryURL": "https://github.com/apple/swift-collections.git",
"state": {
"branch": null,
"revision": "671108c96644956dddcd89dd59c203dcdb36cec7",
"version": "1.1.4"
}
},
{
"package": "swift-nio",
"repositoryURL": "https://github.com/apple/swift-nio.git",
"state": {
"branch": null,
"revision": "43931b7a7daf8120a487601530c8bc03ce711992",
"version": "2.25.1"
"revision": "f7dc3f527576c398709b017584392fb58592e7f5",
"version": "2.75.0"
}
},
{
"package": "SwiftProtobuf",
"repositoryURL": "https://github.com/apple/swift-protobuf.git",
"state": {
"branch": null,
"revision": "e1904bf5a5f79cb7e0ff68a427a53a93b652fcd1",
"version": "1.15.0"
"revision": "ebc7251dd5b37f627c93698e4374084d98409633",
"version": "1.28.2"
}
},
{
"package": "swift-system",
"repositoryURL": "https://github.com/apple/swift-system.git",
"state": {
"branch": null,
"revision": "c8a44d836fe7913603e246acab7c528c2e780168",
"version": "1.4.0"
}
},
{
"package": "swift-tools-support-core",
"repositoryURL": "https://github.com/apple/swift-tools-support-core.git",
"state": {
"branch": null,
"revision": "2954e55faee5bfee928e844bb09e97fcfa8d24af",
"version": "0.2.0"
"revision": "ad2fc22a00b898c7af5d8c74a555666f67a06720",
"version": "0.7.0"
}
}
]
36 changes: 30 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
// swift-tools-version:5.1
// swift-tools-version:5.5
import PackageDescription
import class Foundation.ProcessInfo

let macOSPlatform: SupportedPlatform
let iOSPlatform: SupportedPlatform
if let deploymentTarget = ProcessInfo.processInfo.environment["SWIFTTSC_MACOS_DEPLOYMENT_TARGET"] {
macOSPlatform = .macOS(deploymentTarget)
} else {
macOSPlatform = .macOS(.v10_15)
}
if let deploymentTarget = ProcessInfo.processInfo.environment["SWIFTTSC_IOS_DEPLOYMENT_TARGET"] {
iOSPlatform = .iOS(deploymentTarget)
} else {
iOSPlatform = .iOS(.v13)
}

let package = Package(
name: "swift-tools-support-async",
platforms: [
macOSPlatform,
iOSPlatform
],
products: [
.library(
name: "SwiftToolsSupportAsync",
@@ -12,9 +30,9 @@ let package = Package(
targets: ["TSFCAS", "TSFCASFileTree", "TSFCASUtilities"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-nio.git", from: "2.8.0"),
.package(url: "https://github.com/apple/swift-protobuf.git", from: "1.8.0"),
.package(url: "https://github.com/apple/swift-tools-support-core.git", from: "0.1.8"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.68.0"),
.package(url: "https://github.com/apple/swift-protobuf.git", from: "1.28.0"),
.package(url: "https://github.com/apple/swift-tools-support-core.git", "0.5.8" ..< "0.8.0"),
],
targets: [
// BLAKE3 hash support
@@ -29,7 +47,9 @@ let package = Package(
.target(
name: "TSFFutures",
dependencies: [
"NIO", "SwiftToolsSupport-auto",
.product(name: "NIO", package: "swift-nio"),
.product(name: "NIOFoundationCompat", package: "swift-nio"),
.product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core")
]
),
.testTarget(
@@ -42,13 +62,17 @@ let package = Package(
name: "TSFUtility",
dependencies: [
"TSFFutures",
.product(name: "NIO", package: "swift-nio"),
.product(name: "NIOConcurrencyHelpers", package: "swift-nio"),
.product(name: "NIOFoundationCompat", package: "swift-nio"),
]
),

.target(
name: "TSFCAS",
dependencies: [
"TSFFutures", "TSFUtility", "CBLAKE3", "SwiftProtobuf",
"TSFFutures", "TSFUtility", "CBLAKE3",
.product(name: "SwiftProtobuf", package: "swift-protobuf")
]
),
.target(
22 changes: 22 additions & 0 deletions Protos/CASFileTreeProtocol/file_tree.proto
Original file line number Diff line number Diff line change
@@ -24,6 +24,20 @@ enum LLBFileType {
SYMLINK = 0x3;
}

message LLBPosixFileDetails {
/// The POSIX permissions (&0o7777). Masking is useful when storing entries
/// with very restricted permissions (such as (perm & 0o0007) == 0).
uint32 mode = 1;

/// Owner user identifier.
/// Semantically, absent owner == 0x0 ~= current uid.
uint32 owner = 2;

/// Owner group identifier.
/// Semantically, absent owner == 0x0 ~= current gid.
uint32 group = 3;
}

message LLBDirectoryEntry {
/// The name of the directory entry.
string name = 1;
@@ -33,6 +47,10 @@ message LLBDirectoryEntry {

/// The (aggregate) size of the directory entry.
uint64 size = 3;

/// Mode and permissions. _Can_ optionally be present in the
/// directory entry because the file can be just a direct blob reference.
LLBPosixFileDetails posixDetails = 4;
}

/// The list of file names and associated information, of a directory.
@@ -56,6 +74,7 @@ message LLBFileInfo {
/// is unspecified.
uint64 size = 2;

/// OBSOLETE. Use posixDetails.
/// The POSIX permissions (&0o777). Useful when storing entries
/// with very restricted permissions (such as (perm & 0o007) == 0).
uint32 posixPermissions = 3;
@@ -65,6 +84,9 @@ message LLBFileInfo {
/// * Compression is applied after chunking, to retain seekability.
LLBFileDataCompressionMethod compression = 4;

/// Permission info useful for POSIX filesystems.
LLBPosixFileDetails posixDetails = 5;

oneof payload {
/// Files and symlinks:
/// * The file payload is contained in one or more
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -7,6 +7,6 @@ Common infrastructural helpers on top of NIO for [llbuild2](https://github.com/a
Copyright (c) 2020 Apple Inc. and the Swift project authors.
Licensed under Apache License v2.0 with Runtime Library Exception.

See http://swift.org/LICENSE.txt for license information.
See https://swift.org/LICENSE.txt for license information.

See http://swift.org/CONTRIBUTORS.txt for Swift project authors.
See https://swift.org/CONTRIBUTORS.txt for Swift project authors.
3 changes: 2 additions & 1 deletion Sources/TSFCAS/DataID.swift
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@

import Foundation

import NIOCore
import TSCBasic
import TSFUtility

@@ -142,7 +143,7 @@ extension LLBDataID: LLBSerializable {

@inlinable
public init(from rawBytes: LLBByteBuffer) throws {
guard let bytes = rawBytes.getBytes(at: 0, length: rawBytes.readableBytes), let dataId = LLBDataID(bytes: bytes) else {
guard let dataId = LLBDataID(bytes: Array(buffer: rawBytes)) else {
throw LLBDataIDSliceError.decoding("from slice of size \(rawBytes.readableBytes)")
}
self = dataId
7 changes: 4 additions & 3 deletions Sources/TSFCAS/Database.swift
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@

import Foundation

import NIOCore
import TSCUtility

@_exported import TSFFutures
@@ -43,7 +44,7 @@ public struct LLBCASFeatures: Codable {
/// A content-addressable database protocol
///
/// THREAD-SAFETY: The database is expected to be thread-safe.
public protocol LLBCASDatabase: AnyObject {
public protocol LLBCASDatabase: AnyObject & Sendable {
var group: LLBFuturesDispatchGroup { get }

/// Get the supported features of this database implementation
@@ -151,10 +152,10 @@ public extension Context {

var db: LLBCASDatabase {
get {
guard let db = self[ObjectIdentifier(LLBCASDatabase.self)] else {
guard let db = self[ObjectIdentifier(LLBCASDatabase.self), as: LLBCASDatabase.self] else {
fatalError("no CAS database")
}
return db as! LLBCASDatabase
return db
}
set {
self[ObjectIdentifier(LLBCASDatabase.self)] = newValue
1 change: 1 addition & 0 deletions Sources/TSFCAS/DatabaseSpec.swift
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@

import Foundation

import NIOCore
import TSFFutures


13 changes: 10 additions & 3 deletions Sources/TSFCAS/Generated/CASProtocol/cas_object.pb.swift
Original file line number Diff line number Diff line change
@@ -37,13 +37,17 @@ public struct LLBPBCASObject {

public var refs: [LLBDataID] = []

public var data: Data = SwiftProtobuf.Internal.emptyData
public var data: Data = Data()

public var unknownFields = SwiftProtobuf.UnknownStorage()

public init() {}
}

#if swift(>=5.5) && canImport(_Concurrency)
extension LLBPBCASObject: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)

// MARK: - Code below here is support for the SwiftProtobuf runtime.

extension LLBPBCASObject: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
@@ -55,9 +59,12 @@ extension LLBPBCASObject: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement

public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeRepeatedMessageField(value: &self.refs)
case 2: try decoder.decodeSingularBytesField(value: &self.data)
case 1: try { try decoder.decodeRepeatedMessageField(value: &self.refs) }()
case 2: try { try decoder.decodeSingularBytesField(value: &self.data) }()
default: break
}
}
11 changes: 9 additions & 2 deletions Sources/TSFCAS/Generated/CASProtocol/data_id.pb.swift
Original file line number Diff line number Diff line change
@@ -37,13 +37,17 @@ public struct LLBDataID {
// methods supported on all messages.

//// The bytes containing the digest of the contents store in the CAS.
public var bytes: Data = SwiftProtobuf.Internal.emptyData
public var bytes: Data = Data()

public var unknownFields = SwiftProtobuf.UnknownStorage()

public init() {}
}

#if swift(>=5.5) && canImport(_Concurrency)
extension LLBDataID: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)

// MARK: - Code below here is support for the SwiftProtobuf runtime.

extension LLBDataID: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
@@ -54,8 +58,11 @@ extension LLBDataID: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation

public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularBytesField(value: &self.bytes)
case 1: try { try decoder.decodeSingularBytesField(value: &self.bytes) }()
default: break
}
}
1 change: 1 addition & 0 deletions Sources/TSFCAS/Implementations/Blake3DataID.swift
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@


import CBLAKE3
import NIOCore
import TSFUtility


9 changes: 3 additions & 6 deletions Sources/TSFCAS/Implementations/FileBackedCASDatabase.swift
Original file line number Diff line number Diff line change
@@ -88,10 +88,7 @@ public final class LLBFileBackedCASDatabase: LLBCASDatabase {
let dataFile = fileName(for: id, prefix: .data)

let refsBytes: LLBFuture<[UInt8]> = readFile(file: refsFile).map { refsData in
if let bytes = refsData.getBytes(at: 0, length: refsData.readableBytes) {
return bytes
}
return []
return Array(buffer: refsData)
}

let refs = refsBytes.flatMapThrowing {
@@ -135,7 +132,7 @@ public final class LLBFileBackedCASDatabase: LLBCASDatabase {

let refsFile = fileName(for: id, prefix: .refs)
let refData = try! JSONEncoder().encode(refs)
let refBytes = LLBByteBuffer.withBytes(ArraySlice<UInt8>(refData))
let refBytes = LLBByteBuffer.withBytes(refData)
let refFuture = writeIfNeeded(data: refBytes, path: refsFile)

return dataFuture.and(refFuture).map { _ in id }
@@ -188,7 +185,7 @@ public struct LLBFileBackedCASDatabaseScheme: LLBCASDatabaseScheme {
}

public static func open(group: LLBFuturesDispatchGroup, url: Foundation.URL) throws -> LLBCASDatabase {
return LLBFileBackedCASDatabase(group: group, path: AbsolutePath(url.path))
return try LLBFileBackedCASDatabase(group: group, path: AbsolutePath(validating: url.path))
}
}

Loading