├── Makefile ├── Sources ├── DI │ ├── target.json │ ├── Models │ │ ├── Scope.swift │ │ └── DiError.swift │ ├── Facade │ │ └── InitializableWithNoArguments.swift │ ├── DependencyInjection │ │ └── DependencyInjection.swift │ ├── README.md │ ├── DependencyInjectionFactory │ │ └── DependencyInjectionFactory.swift │ ├── DependencyCollectionRegisterer │ │ ├── DependencyCollectionRegisterer.swift │ │ └── CompoundDependencyCollectionRegisterer.swift │ ├── Implementation │ │ └── DependencyInjection │ │ │ ├── DependencyInjectionFactoryImpl.swift │ │ │ └── RegisteredDependency.swift │ ├── HashableType │ │ └── HashableType.swift │ ├── DependencyResolver │ │ ├── DependencyResolver.swift │ │ └── WeakDependencyResolver.swift │ ├── Modular │ │ └── ModuleDependencies.swift │ └── DependencyRegisterer │ │ ├── DependencyRegisterer+RegisterMultiple.swift │ │ └── DependencyRegisterer.swift ├── JSONStream │ ├── target.json │ ├── JSONReaderEventStream.swift │ ├── AppendableJSONStream.swift │ ├── JSONReaderFatalError.swift │ └── JSONStream.swift ├── PlistLib │ ├── target.json │ ├── PlistReader │ │ ├── PlistReader.swift │ │ └── PlistReaderImpl.swift │ ├── DI │ │ └── PlistLibModuleDependencies.swift │ ├── RootPlistEntry.swift │ └── PlistEntry.swift ├── Console │ ├── target.json │ ├── ANSIConsoleHandler │ │ ├── Trace │ │ │ └── TraceClock.swift │ │ ├── Question │ │ │ └── QuestionComponentState.swift │ │ ├── Input │ │ │ ├── InputComponentState.swift │ │ │ └── ANSIConsoleHandler+Input.swift │ │ ├── Log │ │ │ ├── LogComponent.swift │ │ │ └── LogComponentState.swift │ │ └── LogStream │ │ │ ├── ANSIConsoleHandler+LogStream.swift │ │ │ └── LogStreamComponentState.swift │ ├── ANSI │ │ └── README.md │ ├── TrackingConsoleHandler │ │ ├── TraceMetadata.swift │ │ └── ConsoleActionStorage.swift │ ├── ConsoleTextFragment.swift │ ├── DI │ │ └── ConsoleModuleDependencies.swift │ └── Utils │ │ └── String+Symbols.swift ├── UserDefaultsLib │ ├── target.json │ ├── README.md │ ├── Defaults.swift │ └── SystemDefaults.swift ├── DateProvider │ ├── DateProvider.swift │ ├── SystemDateProvider.swift │ └── DI │ │ └── DateProviderModuleDependencies.swift ├── Types │ ├── ThrowingProperty │ │ ├── ThrowingProperty.swift │ │ ├── SettableThrowingProperty.swift │ │ ├── GettableThrowingProperty.swift │ │ ├── GettableThrowingPropertyOf.swift │ │ └── SettableThrowingPropertyOf.swift │ ├── MutableBox.swift │ ├── CompoundError.swift │ └── CustomOrDefault.swift ├── CommandSupport │ ├── CommandLogicProvider.swift │ ├── AsyncCommandLogic.swift │ ├── AsyncCommandLogicProvider.swift │ ├── CompoundCommandLogic.swift │ ├── AbsolutePath+ExpressibleByArgument.swift │ ├── CommandLogic.swift │ ├── CompoundAsyncCommandLogic.swift │ └── TestableCommand.swift ├── ImagesInterfaces │ ├── ImageFactoryGenerator.swift │ ├── ImageParser.swift │ ├── ImageError.swift │ ├── KnownImageCategories.swift │ └── ImageSetGenerator.swift ├── CLTExtensions │ ├── String+LocalizedError.swift │ ├── Collections │ │ ├── Array+Uniquify.swift │ │ ├── SetAlgebra+Intersects.swift │ │ ├── Set+PlusOperator.swift │ │ ├── Array+Comparable.swift │ │ ├── Collection+Single.swift │ │ ├── Dictionary+Inverse.swift │ │ ├── Dictionary+Map.swift │ │ ├── Bool+Order.swift │ │ └── Sequence+SortingByKey.swift │ ├── NSLocking+WhileLocked.swift │ ├── Models │ │ └── KeyValuePair.swift │ ├── Casting.swift │ └── String+UTF8.swift ├── FileSystem │ ├── File │ │ ├── WorkingWithProperties │ │ │ ├── FileExistenceCheckType.swift │ │ │ └── FileExistence.swift │ │ └── WorkingWithContents │ │ │ ├── FileReader │ │ │ ├── FileReader.swift │ │ │ └── FileReaderImpl.swift │ │ │ └── DataWriter │ │ │ └── DataWriterImpl.swift │ └── Files │ │ ├── RealPathProvider │ │ └── RealpathProvider.swift │ │ ├── Properties │ │ ├── FileSystemPropertiesContainer.swift │ │ └── DefaultFileSystemPropertiesContainer.swift │ │ ├── FileSystem │ │ ├── FileSystemEnumeratorFactory │ │ │ ├── ContentEnumerationStyle.swift │ │ │ ├── FileSystemEnumeratorFactory.swift │ │ │ └── FileSystemEnumeratorFactoryImpl.swift │ │ ├── FileAppender │ │ │ ├── FileAppender.swift │ │ │ └── FileAppenderImpl.swift │ │ ├── FilePropertiesProvider │ │ │ ├── FilePropertiesProviderImpl.swift │ │ │ ├── FileExistenceChecker.swift │ │ │ └── FilePropertiesProvider.swift │ │ ├── FileToucher │ │ │ ├── FileToucher.swift │ │ │ └── FileToucherImpl.swift │ │ ├── FileCreator │ │ │ ├── FileCreator.swift │ │ │ └── FileCreatorImpl.swift │ │ ├── FileSystemPropertiesProvider │ │ │ ├── FileSystemPropertiesProviderImpl.swift │ │ │ └── FileSystemPropertiesProvider.swift │ │ ├── PathDeleter │ │ │ ├── PathDeleter.swift │ │ │ └── PathDeleterImpl.swift │ │ ├── CommonlyUsedPathsProviderFactory │ │ │ └── CommonlyUsedPathsProviderFactoryImpl.swift │ │ ├── PathLinker │ │ │ ├── PathLinker.swift │ │ │ └── PathLinkerImpl.swift │ │ ├── PathCopier │ │ │ ├── PathCopier.swift │ │ │ └── PathCopierImpl.swift │ │ ├── DirectoryCreator │ │ │ └── DirectoryCreator.swift │ │ ├── PathMover │ │ │ ├── PathMover.swift │ │ │ └── PathMoverImpl.swift │ │ └── Support │ │ │ └── DestinationPreparer.swift │ │ ├── Enumeration │ │ ├── Glob │ │ │ └── GlobFileSystemEnumerator.swift │ │ ├── Shallow │ │ │ └── ShallowFileSystemEnumerator.swift │ │ └── Deep │ │ │ ├── DeepFileSystemEnumerator.swift │ │ │ └── DeepFollowSymlinksFileSystemEnumerator.swift │ │ └── CommonlyUsedPathsProvider │ │ ├── CommonlyUsedPathsProvider.swift │ │ └── LinuxCommonlyUsedPathsProvider.swift ├── XcodeLocator │ ├── XcodeLocator │ │ └── XcodeLocator.swift │ ├── ApplicationPathsProvider │ │ ├── ApplicationPathsProvider.swift │ │ └── ApplicationPathsProviderImpl.swift │ ├── XcodeApplicationVerifier │ │ ├── XcodeApplicationVerifier.swift │ │ └── XcodeApplicationVerifierImpl.swift │ └── ApplicationPlistReader │ │ ├── ApplicationPlistReader.swift │ │ └── ApplicationPlistReaderImpl.swift ├── RepoRoot │ ├── RepoRootProvider │ │ ├── RepoRootProvider.swift │ │ ├── RepoRootProviderImplementations │ │ │ ├── ClosureRepoRootProvider.swift │ │ │ ├── CachingRepoRootProvider.swift │ │ │ └── WorkdirRepoRootProvider.swift │ │ ├── RepoRootProviderFactory.swift │ │ └── RepoRootProviderFactoryImplementations │ │ │ ├── CachingRepoRootProviderFactory.swift │ │ │ ├── MarkerFileRepoRootProviderFactory.swift │ │ │ └── GitRepoRootProviderFactory.swift │ └── DI │ │ └── RepoRootModuleDependencies.swift ├── Statsd │ ├── StatsdMetricHandler.swift │ └── StatsdClient.swift ├── Graphite │ ├── GraphiteMetricHandler.swift │ └── NoOpGraphiteMetricHandler.swift ├── Environment │ ├── CurrentExecutableProvider │ │ ├── CurrentExecutableProvider.swift │ │ └── ProcessInfoCurrentExecutableProvider.swift │ ├── EnvironmentProvider │ │ ├── ProcessInfoEnvironmentProvider.swift │ │ ├── EnvironmentProvider.swift │ │ └── Conversion.swift │ └── DI │ │ └── EnvironmentModuleDependencies.swift ├── ProcessController │ ├── ProcessControllerProvider.swift │ ├── BashEscapedCommandMaker │ │ └── BashEscapedCommandMaker.swift │ ├── SubprocessInfo.swift │ ├── ProcessControllerError.swift │ ├── ProcessListener.swift │ ├── ProcessStatus.swift │ ├── DefaultProcessControllerProvider.swift │ ├── DI │ │ └── ProcessControllerDependencies.swift │ ├── EnvironmentValue.swift │ ├── SubprocessArgument.swift │ ├── Subprocess.swift │ └── Process+ProcessGroup.swift ├── TeamcityMessaging │ ├── TeamcityMessageRenderer │ │ └── TeamcityMessageRenderer.swift │ ├── ControlMessage │ │ ├── ControlMessageParameter.swift │ │ ├── ControlMessageWithSingleParameter.swift │ │ ├── ControlMessage.swift │ │ └── ControlMessageBuilder.swift │ └── DI │ │ └── TeamcityMessagingModuleDependencies.swift ├── CLTLogging │ ├── Logger+TypedInit.swift │ ├── FileHandle+TextOutputStream.swift │ ├── LoggerHandler.swift │ ├── SubprocessInfo+PidInfo.swift │ ├── NoOpLoggerHandler.swift │ ├── FileState.swift │ ├── RedirectingLoggerHandler.swift │ ├── LimitingLoggerHandler.swift │ ├── AggregatedLoggerHandler.swift │ └── FileSystem+Logging.swift ├── CLTLoggingModels │ ├── LogEntryTextFormatter.swift │ ├── PidInfo.swift │ ├── LogEntryCoordinate.swift │ ├── LoggableOptional.swift │ ├── LoggableDate.swift │ └── LoggableDouble.swift ├── SynchronousWaiter │ ├── NoOpWaiter.swift │ ├── Timeout.swift │ ├── SynchronousWaiter.swift │ └── Waiter+ErrorMapping.swift ├── MetricsRecording │ ├── MutableMetricRecorder.swift │ ├── NoOpMetricHandler.swift │ ├── MetricRecorder.swift │ └── TimeMeasurer.swift ├── Kibana │ └── KibanaClient.swift ├── MetricsUtils │ └── String+MetricComponent.swift ├── SocketModels │ └── Port.swift ├── XcodeLocatorModels │ └── DiscoveredXcode.swift ├── Downloader │ ├── DI │ │ └── DownloaderModuleDependencies.swift │ └── Downloader.swift ├── PathLib │ ├── Path.swift │ ├── FileManager+Extensions.swift │ ├── StringPathParsing.swift │ └── String+ShellEscaping.swift ├── MutualTLS │ ├── AbsolutePath+Credentials.swift │ ├── DI │ │ └── MutualTLSModuleDependencies.swift │ └── PEM.swift ├── Waitable │ └── Waitable.swift ├── CLTTypes │ ├── Credentials.swift │ └── Http │ │ └── HttpAuthorizationScheme.swift ├── Cloc │ └── Cloc.swift ├── KibanaModels │ └── KibanaConfiguration.swift ├── CLTCollections │ └── Array+Set.swift ├── Concurrency │ ├── ThrowingThreadSafeLazy.swift │ └── ThreadSafeLazy.swift ├── Tmp │ └── TempErrors.swift ├── LaunchdUtils │ ├── LaunchdSocketActivationError.swift │ └── LaunchdSocketActivation.swift └── AtomicModels │ └── AtomicValue.swift ├── Tests ├── TestHelpers │ ├── target.json │ ├── ExpectationAwaitingError.swift │ ├── XCTestCase+WaitForExpectation.swift │ ├── XCTestCase+testDirectory.swift │ ├── ErrorForTestingPurposes.swift │ ├── Casting.swift │ ├── PreventingExecutionAfterFailure.swift │ ├── ExpectationCreation.swift │ ├── TestFailing.swift │ ├── AssertFalse.swift │ ├── AssertTrue.swift │ ├── Equals.swift │ ├── NilHelpers.swift │ ├── XCTestCase+XCTAssertEqualSorted.swift │ ├── XCTestCase+Syncronious.swift │ └── README.md ├── MetricsTestHelpers │ ├── Metric+TestCompare.swift │ ├── NoOpMetricRecorder.swift │ └── FakeMetricHandler.swift ├── ImagesTestHelpers │ └── Mocks │ │ ├── ImageFactoryGeneratorMock.swift │ │ ├── ImageParserMock.swift │ │ ├── ImageValidatorMock.swift │ │ └── KnownImageCategoriesMock.swift ├── FileSystemTestHelpers │ ├── FakeFileSystemPropertiesContainer.swift │ ├── FakeFileSystemEnumerator.swift │ ├── FakeFileReader.swift │ └── FakeThrowingProperty.swift ├── TmpTestHelpers │ └── TmpFixtures.swift ├── CLTExtensionsTests │ ├── NSLocking+WhileLockedTests.swift │ ├── Array+Comparable_Tests.swift │ ├── String+UTF8Tests.swift │ └── Array+UniquifyTests.swift ├── DateProviderTestHelpers │ └── DateProviderFixture.swift ├── FileSystemTests │ ├── TestDataForEnumeration.swift │ ├── LocalFileSystemTests.swift │ ├── DeepFileSystemEnumeratorTests.swift │ ├── ShallowFileSystemEnumeratorTests.swift │ ├── DirectoryCreatorImplTests.swift │ └── AppleCommonlyUsedPathsProviderTests.swift ├── SignalHandlingTests │ └── SignalHandlingTests.swift ├── CLTLoggingTestHelpers │ └── FakeLoggerHandler.swift ├── UserDefaultsLibTestHelpers │ └── FakeDefaults.swift ├── ProcessControllerTests │ └── EnvironmentSecureValueTests.swift ├── ProcessControllerTestHelpers │ └── FakeProcessControllerProvider.swift ├── CLTLoggingTests │ ├── FakeFileHandle.swift │ ├── SimpleLogEntryTextFormatter.swift │ ├── AggregatedLoggerHandlerTests.swift │ └── LimitingLoggerHandlerTests.swift ├── GraphiteTestHelpers │ └── GraphiteClient.swift ├── StatsdTests │ ├── FakeStatsdClient.swift │ └── StatsdMetricTests.swift ├── JSONStreamTests │ ├── JSONReaderStringEdgeCaseTests.swift │ └── Helpers.swift ├── KibanaTestHelpers │ └── FakeKibanaClient.swift └── WaitableTests │ └── WaitableTests.swift ├── PackageGenerator ├── Sources │ └── PackageGenerator │ │ ├── Utils │ │ ├── String+Error.swift │ │ └── Sequence+Duplicates.swift │ │ ├── Statements │ │ ├── OsRequirement+Statement.swift │ │ ├── PackagePlatform+Statement.swift │ │ ├── IndentedStatement.swift │ │ ├── ConditionalCompilationTargetRequirement+Statement.swift │ │ ├── LinkerSettings+Statement.swift │ │ ├── ExternalPackageVersion+Statement.swift │ │ ├── PackageDependencies+Statement.swift │ │ ├── SwiftSetting+Statement.swift │ │ └── PackageProduct+Statement.swift │ │ ├── PackagejJson │ │ ├── PackageProductType.swift │ │ ├── PackagePlatform.swift │ │ ├── PackageProduct.swift │ │ ├── PackageDependencies.swift │ │ └── ConditionalCompilationTargetRequirement.swift │ │ ├── log.swift │ │ ├── Generation │ │ └── Errors │ │ │ ├── StoreGenerationResultError.swift │ │ │ ├── PackageSwiftMissingError.swift │ │ │ └── ContentMismatchError.swift │ │ ├── TargetJson │ │ └── LinkerSettings.swift │ │ └── FirstNonThrowingResultOf.swift ├── Package.swift └── Tests │ └── PackageGeneratorTests │ └── XCTestCase+JSON.swift ├── custom_actions.sh ├── .gitignore ├── shared_makefile └── Makefile └── README.md /Makefile: -------------------------------------------------------------------------------- 1 | shared_makefile/Makefile -------------------------------------------------------------------------------- /Sources/DI/target.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": "README.md" 3 | } 4 | -------------------------------------------------------------------------------- /Sources/JSONStream/target.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": "README.md" 3 | } 4 | -------------------------------------------------------------------------------- /Sources/PlistLib/target.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": "README.md" 3 | } 4 | -------------------------------------------------------------------------------- /Tests/TestHelpers/target.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": "README.md" 3 | } 4 | -------------------------------------------------------------------------------- /Sources/Console/target.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": "ANSI/README.md" 3 | } 4 | -------------------------------------------------------------------------------- /Sources/UserDefaultsLib/target.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": "README.md" 3 | } 4 | -------------------------------------------------------------------------------- /Sources/DI/Models/Scope.swift: -------------------------------------------------------------------------------- 1 | public enum Scope { 2 | case single 3 | case unique 4 | } 5 | -------------------------------------------------------------------------------- /Sources/Console/ANSIConsoleHandler/Trace/TraceClock.swift: -------------------------------------------------------------------------------- 1 | public typealias TraceClock = ContinuousClock 2 | -------------------------------------------------------------------------------- /Sources/DI/Facade/InitializableWithNoArguments.swift: -------------------------------------------------------------------------------- 1 | public protocol InitializableWithNoArguments { 2 | init() 3 | } 4 | -------------------------------------------------------------------------------- /Sources/Console/ANSI/README.md: -------------------------------------------------------------------------------- 1 | # Source 2 | 3 | Adapted it from [ANSITerminal](https://github.com/pakLebah/ANSITerminal.git) 4 | -------------------------------------------------------------------------------- /Sources/DI/DependencyInjection/DependencyInjection.swift: -------------------------------------------------------------------------------- 1 | public typealias DependencyInjection = DependencyResolver & DependencyRegisterer 2 | -------------------------------------------------------------------------------- /Sources/DateProvider/DateProvider.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol DateProvider { 4 | func currentDate() -> Date 5 | } 6 | -------------------------------------------------------------------------------- /Sources/Types/ThrowingProperty/ThrowingProperty.swift: -------------------------------------------------------------------------------- 1 | public typealias ThrowingProperty = SettableThrowingProperty & GettableThrowingProperty 2 | -------------------------------------------------------------------------------- /Sources/CommandSupport/CommandLogicProvider.swift: -------------------------------------------------------------------------------- 1 | public protocol CommandLogicProvider { 2 | func commandLogic() throws -> CommandLogic 3 | } 4 | -------------------------------------------------------------------------------- /Sources/DI/README.md: -------------------------------------------------------------------------------- 1 | # DI 2 | 3 | Copied from to avoid excess dependencies in SPM. -------------------------------------------------------------------------------- /Sources/CommandSupport/AsyncCommandLogic.swift: -------------------------------------------------------------------------------- 1 | /// Allows to run asynchronous commands 2 | public protocol AsyncCommandLogic { 3 | func run() async throws 4 | } 5 | -------------------------------------------------------------------------------- /Sources/ImagesInterfaces/ImageFactoryGenerator.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol ImageFactoryGenerator { 4 | func generateFactoryFile() throws 5 | } 6 | -------------------------------------------------------------------------------- /Sources/CLTExtensions/String+LocalizedError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension String: LocalizedError { 4 | public var errorDescription: String? { self } 5 | } 6 | -------------------------------------------------------------------------------- /Sources/DI/DependencyInjectionFactory/DependencyInjectionFactory.swift: -------------------------------------------------------------------------------- 1 | public protocol DependencyInjectionFactory { 2 | func dependencyInjection() -> DependencyInjection 3 | } 4 | -------------------------------------------------------------------------------- /Sources/FileSystem/File/WorkingWithProperties/FileExistenceCheckType.swift: -------------------------------------------------------------------------------- 1 | public enum FileExistenceCheckType { 2 | case file 3 | case directory 4 | case any 5 | } 6 | -------------------------------------------------------------------------------- /Sources/Types/MutableBox.swift: -------------------------------------------------------------------------------- 1 | public final class MutableBox { 2 | public var value: T 3 | 4 | public init(value: T) { 5 | self.value = value 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Sources/XcodeLocator/XcodeLocator/XcodeLocator.swift: -------------------------------------------------------------------------------- 1 | import XcodeLocatorModels 2 | 3 | public protocol XcodeLocator { 4 | func discoverXcodes() throws -> [DiscoveredXcode] 5 | } 6 | -------------------------------------------------------------------------------- /Sources/PlistLib/PlistReader/PlistReader.swift: -------------------------------------------------------------------------------- 1 | import FileSystem 2 | import PathLib 3 | 4 | public protocol PlistReader { 5 | func readPlist(path: AbsolutePath) throws -> Plist 6 | } 7 | -------------------------------------------------------------------------------- /Sources/CLTExtensions/Collections/Array+Uniquify.swift: -------------------------------------------------------------------------------- 1 | extension Array where Element: Hashable { 2 | public func uniquify() -> [Element] { 3 | return Array(Set(self)) 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/RealPathProvider/RealpathProvider.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol RealpathProvider { 4 | func realpath(path: AbsolutePath) throws -> AbsolutePath 5 | } 6 | -------------------------------------------------------------------------------- /Sources/RepoRoot/RepoRootProvider/RepoRootProvider.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | public protocol RepoRootProvider { 5 | func repoRoot() throws -> AbsolutePath 6 | } 7 | -------------------------------------------------------------------------------- /Sources/DI/DependencyCollectionRegisterer/DependencyCollectionRegisterer.swift: -------------------------------------------------------------------------------- 1 | public protocol DependencyCollectionRegisterer { 2 | func register(dependencyRegisterer: DependencyRegisterer) 3 | } 4 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/Properties/FileSystemPropertiesContainer.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol FileSystemPropertiesContainer { 4 | func systemFreeSize() throws -> Int64 5 | } 6 | -------------------------------------------------------------------------------- /Sources/Statsd/StatsdMetricHandler.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol StatsdMetricHandler { 4 | func handle(metric: StatsdMetric) 5 | func tearDown(timeout: TimeInterval) 6 | } 7 | -------------------------------------------------------------------------------- /Sources/Types/ThrowingProperty/SettableThrowingProperty.swift: -------------------------------------------------------------------------------- 1 | public protocol SettableThrowingProperty { 2 | associatedtype PropertyType 3 | 4 | func set(_ value: PropertyType) throws 5 | } 6 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Utils/String+Error.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension String: LocalizedError { 4 | public var errorDescription: String? { 5 | self 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Sources/CLTExtensions/Collections/SetAlgebra+Intersects.swift: -------------------------------------------------------------------------------- 1 | extension SetAlgebra { 2 | @inlinable public func intersects(with other: Self) -> Bool { 3 | !isDisjoint(with: other) 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/FileSystemEnumeratorFactory/ContentEnumerationStyle.swift: -------------------------------------------------------------------------------- 1 | public enum ContentEnumerationStyle { 2 | case deep 3 | case deepFollowSymlinks 4 | case shallow 5 | } 6 | -------------------------------------------------------------------------------- /Sources/Graphite/GraphiteMetricHandler.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol GraphiteMetricHandler { 4 | func handle(metric: GraphiteMetric) 5 | func tearDown(timeout: TimeInterval) 6 | } 7 | -------------------------------------------------------------------------------- /Sources/XcodeLocator/ApplicationPathsProvider/ApplicationPathsProvider.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol ApplicationPathsProvider { 4 | func applicationPaths() throws -> [AbsolutePath] 5 | } 6 | -------------------------------------------------------------------------------- /Sources/Environment/CurrentExecutableProvider/CurrentExecutableProvider.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol CurrentExecutableProvider { 4 | func currentExecutablePath() throws -> AbsolutePath 5 | } 6 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Statements/OsRequirement+Statement.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension OsRequirement { 4 | var statement: String { 5 | return rawValue 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Sources/CommandSupport/AsyncCommandLogicProvider.swift: -------------------------------------------------------------------------------- 1 | /// Provides command logic for async commands 2 | public protocol AsyncCommandLogicProvider { 3 | func asyncCommandLogic() throws -> AsyncCommandLogic 4 | } 5 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/FileAppender/FileAppender.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | import Foundation 3 | 4 | public protocol FileAppender { 5 | func appendToFile(path: AbsolutePath, data: Data) throws 6 | } 7 | -------------------------------------------------------------------------------- /Sources/ProcessController/ProcessControllerProvider.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol ProcessControllerProvider { 4 | func createProcessController(subprocess: Subprocess) throws -> ProcessController 5 | } 6 | -------------------------------------------------------------------------------- /Sources/TeamcityMessaging/TeamcityMessageRenderer/TeamcityMessageRenderer.swift: -------------------------------------------------------------------------------- 1 | public protocol TeamcityMessageRenderer { 2 | func renderControlMessage( 3 | controlMessage: ControlMessage 4 | ) throws -> String 5 | } 6 | -------------------------------------------------------------------------------- /Tests/TestHelpers/ExpectationAwaitingError.swift: -------------------------------------------------------------------------------- 1 | public final class ExpectationAwaitingError: Error, CustomStringConvertible { 2 | public var description: String { 3 | return "Awaiting for result failed" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /Sources/CLTLogging/Logger+TypedInit.swift: -------------------------------------------------------------------------------- 1 | import Logging 2 | 3 | extension Logger { 4 | public init(for type: Target.Type) { 5 | let label = String(describing: type) 6 | self.init(label: label) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Sources/CLTLoggingModels/LogEntryTextFormatter.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | public protocol LogEntryTextFormatter { 8 | func format(logEntry: LogEntry) -> String 9 | } 10 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/PackagejJson/PackageProductType.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum PackageProductType: String, Codable, Hashable { 4 | case executable 5 | case library 6 | case dynamicLibrary 7 | } 8 | -------------------------------------------------------------------------------- /Sources/XcodeLocator/XcodeApplicationVerifier/XcodeApplicationVerifier.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | import Foundation 3 | import PlistLib 4 | 5 | public protocol XcodeApplicationVerifier { 6 | func isXcodeApplicaton(infoPlist: Plist) -> Bool 7 | } 8 | -------------------------------------------------------------------------------- /Sources/DateProvider/SystemDateProvider.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public final class SystemDateProvider: DateProvider { 4 | public init() {} 5 | 6 | public func currentDate() -> Date { 7 | return Date() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Sources/ProcessController/BashEscapedCommandMaker/BashEscapedCommandMaker.swift: -------------------------------------------------------------------------------- 1 | /// Makes string from arguments that can be used as command in BASH. 2 | public protocol BashEscapedCommandMaker { 3 | func escapedCommand(arguments: [String]) -> String 4 | } 5 | -------------------------------------------------------------------------------- /Sources/SynchronousWaiter/NoOpWaiter.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public final class NoOpWaiter: Waiter { 4 | public init() {} 5 | 6 | public func waitWhile(pollPeriod: TimeInterval, timeout: Timeout, condition: () throws -> Bool) throws {} 7 | } 8 | -------------------------------------------------------------------------------- /Sources/XcodeLocator/ApplicationPlistReader/ApplicationPlistReader.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PlistLib 3 | import PathLib 4 | 5 | public protocol ApplicationPlistReader { 6 | func applicationPlist(pathToApplication: AbsolutePath) throws -> Plist 7 | } 8 | -------------------------------------------------------------------------------- /Sources/ImagesInterfaces/ImageParser.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol ImageParser { 4 | func imageSource(rootPath: AbsolutePath) throws -> ImageSource 5 | func assetSource(consoleInput: String, assetsPath: RelativePath) throws -> AbsolutePath 6 | } 7 | -------------------------------------------------------------------------------- /Sources/ImagesInterfaces/ImageError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct ImageError: Error, CustomStringConvertible { 4 | public init(_ description: String) { 5 | self.description = description 6 | } 7 | public let description: String 8 | } 9 | -------------------------------------------------------------------------------- /Sources/CLTExtensions/NSLocking+WhileLocked.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension NSLocking { 4 | func whileLocked(_ work: () throws -> T) rethrows -> T { 5 | lock() 6 | defer { unlock() } 7 | return try work() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Sources/MetricsRecording/MutableMetricRecorder.swift: -------------------------------------------------------------------------------- 1 | import Graphite 2 | import Statsd 3 | 4 | public protocol MutableMetricRecorder: MetricRecorder { 5 | func setGraphiteMetric(handler: GraphiteMetricHandler) 6 | func setStatsdMetric(handler: StatsdMetricHandler) 7 | } 8 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Statements/PackagePlatform+Statement.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension PackagePlatform { 4 | var statement: String { 5 | "." + name + "(.v" + version.replacingOccurrences(of: ".", with: "_") + ")" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Tests/TestHelpers/XCTestCase+WaitForExpectation.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | 4 | extension XCTestCase { 5 | public func wait(for expectation: XCTestExpectation, timeout: TimeInterval = 10) { 6 | wait(for: [expectation], timeout: timeout) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/log.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public func log(_ text: String) { 4 | if ProcessInfo.processInfo.environment["DEBUG"] != nil, let data = (text + "\n").data(using: .utf8) { 5 | FileHandle.standardOutput.write(data) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Sources/CLTLogging/FileHandle+TextOutputStream.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | extension FileHandle: TextOutputStream { 8 | public func write(_ string: String) { 9 | self.write(Data(string.utf8)) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Sources/CLTLogging/LoggerHandler.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import CLTLoggingModels 6 | import Foundation 7 | 8 | public protocol LoggerHandler { 9 | func handle(logEntry: LogEntry) 10 | func tearDownLogging(timeout: TimeInterval) 11 | } 12 | -------------------------------------------------------------------------------- /custom_actions.sh: -------------------------------------------------------------------------------- 1 | # Default action makes release build, but it doesn't work with test helpers. 2 | action___build() { 3 | perform_inside_project swift build 4 | } 5 | 6 | action___generate() { 7 | swift run --package-path "$PROJECT_DIR/PackageGenerator/" package-gen "$PROJECT_DIR" 8 | } -------------------------------------------------------------------------------- /Sources/DI/Models/DiError.swift: -------------------------------------------------------------------------------- 1 | public final class DiError: Error, CustomStringConvertible { 2 | public let value: String 3 | 4 | public init(_ value: String) { 5 | self.value = value 6 | } 7 | 8 | public var description: String { 9 | return value 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Sources/Types/ThrowingProperty/GettableThrowingProperty.swift: -------------------------------------------------------------------------------- 1 | // Note: if you don't use (or plan to use) `SettableThrowingProperty`, consider using Swift's throwable properties. 2 | public protocol GettableThrowingProperty { 3 | associatedtype PropertyType 4 | 5 | func get() throws -> PropertyType 6 | } 7 | -------------------------------------------------------------------------------- /Tests/MetricsTestHelpers/Metric+TestCompare.swift: -------------------------------------------------------------------------------- 1 | import Graphite 2 | import MetricsRecording 3 | 4 | public extension GraphiteMetric { 5 | func testCompare(_ other: GraphiteMetric) -> Bool { 6 | return self.components == other.components 7 | && self.value == other.value 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Sources/TeamcityMessaging/ControlMessage/ControlMessageParameter.swift: -------------------------------------------------------------------------------- 1 | public final class ControlMessageParameter { 2 | public let name: String 3 | public let value: String 4 | 5 | public init(name: String, value: String) { 6 | self.name = name 7 | self.value = value 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # System 2 | .DS_Store 3 | 4 | # Swift 5 | .build 6 | .cache 7 | .swiftpm 8 | /Packages 9 | /*.xcodeproj 10 | xcuserdata 11 | 12 | # Python 13 | *.pyc 14 | .idea 15 | .cache 16 | __pycache__ 17 | .pytest_cache 18 | venv 19 | .python-version 20 | .mypy_cache 21 | .coverage 22 | 23 | # Utility 24 | *.ignored* 25 | -------------------------------------------------------------------------------- /Sources/DI/Implementation/DependencyInjection/DependencyInjectionFactoryImpl.swift: -------------------------------------------------------------------------------- 1 | public final class DependencyInjectionFactoryImpl: DependencyInjectionFactory { 2 | public init() { 3 | } 4 | 5 | public func dependencyInjection() -> DependencyInjection { 6 | return DependencyInjectionImpl() 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Statements/IndentedStatement.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct IndentedStatement { 4 | public let level: Int 5 | public let string: String 6 | 7 | public var statement: String { 8 | Array(repeating: " ", count: 4 * level) + string 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Sources/CLTExtensions/Models/KeyValuePair.swift: -------------------------------------------------------------------------------- 1 | public final class KeyValuePair { 2 | public let key: Key 3 | public let value: Value 4 | 5 | public init( 6 | key: Key, 7 | value: Value 8 | ) { 9 | self.key = key 10 | self.value = value 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Sources/CLTLogging/SubprocessInfo+PidInfo.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import CLTLoggingModels 6 | import Foundation 7 | import ProcessController 8 | 9 | extension SubprocessInfo { 10 | public var pidInfo: PidInfo { 11 | PidInfo(pid: subprocessId, name: subprocessName) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/FileSystemEnumeratorFactory/FileSystemEnumeratorFactory.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol FileSystemEnumeratorFactory { 4 | func contentEnumerator(forPath: AbsolutePath, style: ContentEnumerationStyle) -> FileSystemEnumerator 5 | func glob(pattern: GlobPattern) -> FileSystemEnumerator 6 | } 7 | -------------------------------------------------------------------------------- /Sources/Kibana/KibanaClient.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | public protocol KibanaClient { 8 | func send( 9 | level: String, 10 | message: String, 11 | metadata: [String: String], 12 | completion: @escaping (Error?) -> () 13 | ) throws 14 | } 15 | -------------------------------------------------------------------------------- /Tests/TestHelpers/XCTestCase+testDirectory.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | import XCTest 4 | 5 | public extension XCTestCase { 6 | func testDirectory() -> AbsolutePath { 7 | AbsolutePath(URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(String(describing: type(of: self)))) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Sources/CLTLoggingModels/PidInfo.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | public struct PidInfo: Hashable { 8 | public let pid: Int32 9 | public let name: String 10 | 11 | public init(pid: Int32, name: String) { 12 | self.pid = pid 13 | self.name = name 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Sources/MetricsUtils/String+MetricComponent.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension String { 4 | var suitableForMetric: String { 5 | return self 6 | .replacingOccurrences(of: ".", with: "_") 7 | .replacingOccurrences(of: " ", with: "_") 8 | .replacingOccurrences(of: "#", with: "_") 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Sources/JSONStream/JSONReaderEventStream.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol JSONReaderEventStream { 4 | /// Called when JSON reader consumes a root JSON array. 5 | func newArray(_ array: NSArray, data: Data) 6 | 7 | /// Called when JSON reader consumes a root JSON object. 8 | func newObject(_ object: NSDictionary, data: Data) 9 | } 10 | -------------------------------------------------------------------------------- /Sources/CLTExtensions/Collections/Set+PlusOperator.swift: -------------------------------------------------------------------------------- 1 | public func +(lhs: Set, rhs: Set) -> Set { 2 | return lhs.union(rhs) 3 | } 4 | 5 | public func +(lhs: [T], rhs: Set) -> Set { 6 | return rhs.union(lhs) 7 | } 8 | 9 | public func +(lhs: Set, rhs: [T]) -> Set { 10 | return lhs.union(rhs) 11 | } 12 | -------------------------------------------------------------------------------- /Tests/ImagesTestHelpers/Mocks/ImageFactoryGeneratorMock.swift: -------------------------------------------------------------------------------- 1 | import ImagesInterfaces 2 | import PathLib 3 | 4 | public final class ImageFactoryGeneratorMock: ImageFactoryGenerator { 5 | 6 | public var isCalled = false 7 | 8 | public init() {} 9 | 10 | public func generateFactoryFile() throws { 11 | isCalled = true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Sources/Graphite/NoOpGraphiteMetricHandler.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public final class NoOpGraphiteMetricHandler: GraphiteMetricHandler { 4 | public init() { 5 | 6 | } 7 | 8 | public func handle(metric: GraphiteMetric) { 9 | 10 | } 11 | 12 | public func tearDown(timeout: TimeInterval) { 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Statements/ConditionalCompilationTargetRequirement+Statement.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension ConditionalCompilationTargetRequirement { 4 | var statement: String { 5 | switch self { 6 | case .os(let osRequirement): 7 | return "os(\(osRequirement.statement))" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Sources/CLTExtensions/Collections/Array+Comparable.swift: -------------------------------------------------------------------------------- 1 | extension Array: Comparable where Element: Comparable { 2 | public static func <(lhs: Array, rhs: Array) -> Bool { 3 | for i in 0.. FilePropertiesContainer { 8 | return DefaultFilePropertiesContainer(path: path) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Sources/MetricsRecording/NoOpMetricHandler.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Graphite 3 | import Statsd 4 | 5 | public final class NoOpMetricHandler: GraphiteMetricHandler, StatsdMetricHandler { 6 | public init() {} 7 | public func handle(metric: GraphiteMetric) {} 8 | public func handle(metric: StatsdMetric) {} 9 | public func tearDown(timeout: TimeInterval) {} 10 | } 11 | -------------------------------------------------------------------------------- /Sources/SocketModels/Port.swift: -------------------------------------------------------------------------------- 1 | import Types 2 | 3 | public final class Port: NewIntType, Strideable { 4 | public typealias Stride = Int 5 | 6 | public func distance(to other: Port) -> Int { 7 | other.value - self.value 8 | } 9 | 10 | public func advanced(by n: Int) -> Self { 11 | return type(of: self).init(value: value + n) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Sources/XcodeLocatorModels/DiscoveredXcode.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public struct DiscoveredXcode: Hashable { 4 | public let path: AbsolutePath 5 | public let shortVersion: String 6 | 7 | public init( 8 | path: AbsolutePath, 9 | shortVersion: String 10 | ) { 11 | self.path = path 12 | self.shortVersion = shortVersion 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Generation/Errors/StoreGenerationResultError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct StoreGenerationResultError: Error, CustomStringConvertible { 4 | let errors: [Error] 5 | 6 | public var description: String { 7 | "Failed to store generated content. Errors: \n" + errors.map { "\($0)" }.joined(separator: "\n") 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Sources/DateProvider/DI/DateProviderModuleDependencies.swift: -------------------------------------------------------------------------------- 1 | import DI 2 | 3 | public final class DateProviderModuleDependencies: ModuleDependencies { 4 | public init() { 5 | } 6 | 7 | public func registerDependenciesOfCurrentModule(di: DependencyRegisterer) { 8 | di.register(type: DateProvider.self) { _ in 9 | SystemDateProvider() 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/FilePropertiesProvider/FileExistenceChecker.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol FileExistenceChecker { 4 | func existence(path: AbsolutePath) -> FileExistence 5 | } 6 | 7 | extension FileExistenceChecker { 8 | public func exists( 9 | path: AbsolutePath 10 | ) -> Bool { 11 | return existence(path: path).exists 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Tests/FileSystemTestHelpers/FakeFileSystemPropertiesContainer.swift: -------------------------------------------------------------------------------- 1 | import FileSystem 2 | import Foundation 3 | import PathLib 4 | 5 | open class FakeFileSystemPropertiesContainer: FileSystemPropertiesContainer { 6 | public init() {} 7 | 8 | public var systemFreeSizeValue: Int64 = 42 9 | public func systemFreeSize() throws -> Int64 { 10 | systemFreeSizeValue 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/FileToucher/FileToucher.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | // TODO: Add `ensureDirectoryExists` parameter. 4 | // Note that `FileCreator` in `FileToucherImpl` duplicates `DataWriter` 5 | // and missed `ensureDirectoryExists` too (`DataWriter` doesn't) 6 | // This should be addressed first. 7 | public protocol FileToucher { 8 | func touch(path: AbsolutePath) throws 9 | } 10 | -------------------------------------------------------------------------------- /Tests/MetricsTestHelpers/NoOpMetricRecorder.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Graphite 3 | import MetricsRecording 4 | import Statsd 5 | 6 | public final class NoOpMetricRecorder: MetricRecorder { 7 | public init() {} 8 | 9 | public func capture(_ metric: GraphiteMetric) {} 10 | public func capture(_ metric: StatsdMetric) {} 11 | public func tearDown(timeout: TimeInterval) {} 12 | } 13 | -------------------------------------------------------------------------------- /Tests/TestHelpers/ErrorForTestingPurposes.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct ErrorForTestingPurposes: Error, CustomStringConvertible { 4 | public let text: String 5 | 6 | public init(text: String = "Error for testing purposes") { 7 | self.text = text 8 | } 9 | 10 | public var description: String { 11 | return "\(type(of: self)) \(text)" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Statements/LinkerSettings+Statement.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension LinkerSettings { 4 | var statements: [String] { 5 | var result = [String]() 6 | if !unsafeFlags.isEmpty { 7 | result.append(".unsafeFlags([" + unsafeFlags.map { "\"\($0)\"" }.joined(separator: ", ") + "])") 8 | } 9 | return result 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/TargetJson/LinkerSettings.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct LinkerSettings: Codable, Hashable { 4 | public let unsafeFlags: [String] 5 | 6 | public init( 7 | unsafeFlags: [String] 8 | ) { 9 | self.unsafeFlags = unsafeFlags 10 | } 11 | 12 | public var isDefined: Bool { 13 | !unsafeFlags.isEmpty 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Sources/CLTLogging/NoOpLoggerHandler.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import CLTLoggingModels 6 | import Foundation 7 | 8 | public final class NoOpLoggerHandler: LoggerHandler { 9 | public init() {} 10 | 11 | public func handle(logEntry: LogEntry) { 12 | 13 | } 14 | 15 | public func tearDownLogging(timeout: TimeInterval) { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Sources/Downloader/DI/DownloaderModuleDependencies.swift: -------------------------------------------------------------------------------- 1 | import DI 2 | 3 | public final class DownloaderModuleDependencies: ModuleDependencies { 4 | public init() { 5 | } 6 | 7 | public func registerDependenciesOfCurrentModule(di: DependencyRegisterer) { 8 | di.register(type: Downloader.self) { di in 9 | DownloaderImpl(dateProvider: try di.resolve()) 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/FileCreator/FileCreator.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | import Foundation 3 | 4 | // TODO: Remove code duplication with `DataWriter`. 5 | public protocol FileCreator { 6 | func createFile( 7 | path: AbsolutePath, 8 | data: Data? 9 | ) throws 10 | 11 | func createExucatableFile( 12 | path: AbsolutePath, 13 | data: Data? 14 | ) throws 15 | } 16 | -------------------------------------------------------------------------------- /Sources/Statsd/StatsdClient.swift: -------------------------------------------------------------------------------- 1 | import Dispatch 2 | import Foundation 3 | 4 | public protocol StatsdClient: AnyObject { 5 | func send( 6 | content: Data, 7 | queue: DispatchQueue, 8 | completion: @escaping (Error?) -> () 9 | ) 10 | 11 | func tearDown( 12 | queue: DispatchQueue, 13 | timeout: TimeInterval, 14 | completion: @escaping () -> () 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /Tests/TestHelpers/Casting.swift: -------------------------------------------------------------------------------- 1 | import CLTExtensions 2 | import Foundation 3 | import XCTest 4 | 5 | @discardableResult 6 | public func assertCast( 7 | file: StaticString = #filePath, 8 | line: UInt = #line, 9 | provider: () throws -> Any 10 | ) rethrows -> T { 11 | let value = try provider() 12 | 13 | return assertDoesNotThrow { 14 | try cast(value: value, to: T.self) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Tests/TmpTestHelpers/TmpFixtures.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Tmp 3 | import TestHelpers 4 | import XCTest 5 | 6 | public extension XCTestCase { 7 | func createTempFolder( 8 | deleteOnDealloc: Bool = true 9 | ) -> TemporaryFolder { 10 | assertDoesNotThrow { 11 | try TemporaryFolder( 12 | deleteOnDealloc: deleteOnDealloc 13 | ) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/CLTLoggingModels/LogEntryCoordinate.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | public struct LogEntryCoordinate: Hashable, Codable { 8 | public let name: String 9 | public let value: String? 10 | 11 | public init( 12 | name: String, 13 | value: String? = nil 14 | ) { 15 | self.name = name 16 | self.value = value 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Sources/DI/HashableType/HashableType.swift: -------------------------------------------------------------------------------- 1 | final class HashableType: Hashable { 2 | private let type: Any.Type 3 | 4 | init(type: Any.Type) { 5 | self.type = type 6 | } 7 | 8 | func hash(into hasher: inout Hasher) { 9 | hasher.combine("\(type)") 10 | } 11 | 12 | static func ==(lhs: HashableType, rhs: HashableType) -> Bool { 13 | return lhs.type == rhs.type 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Sources/ProcessController/ProcessControllerError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | public enum ProcessControllerError: CustomStringConvertible, Error { 5 | case fileIsNotExecutable(path: AbsolutePath) 6 | 7 | public var description: String { 8 | switch self { 9 | case .fileIsNotExecutable(let path): 10 | return "File is not executable: \(path)" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Tests/TestHelpers/PreventingExecutionAfterFailure.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | 4 | public extension XCTestCase { 5 | func withoutContinuingTestAfterFailure( 6 | work: () -> T 7 | ) -> T { 8 | let shouldContinue = continueAfterFailure 9 | defer { continueAfterFailure = shouldContinue } 10 | 11 | continueAfterFailure = false 12 | return work() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Utils/Sequence+Duplicates.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Sequence where Element: Hashable { 4 | func removeDuplicates() -> [Element] { 5 | var deduplicationSet: Set = [] 6 | 7 | return compactMap { element in 8 | let (inserted, value) = deduplicationSet.insert(element) 9 | return inserted ? value : nil 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/FileSystemPropertiesProvider/FileSystemPropertiesProviderImpl.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public final class FileSystemPropertiesProviderImpl: FileSystemPropertiesProvider { 4 | public init() { 5 | } 6 | 7 | public func fileSystemProperties(forFileAtPath path: AbsolutePath) -> FileSystemPropertiesContainer { 8 | return DefaultFileSystemPropertiesContainer(path: path) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Sources/JSONStream/AppendableJSONStream.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol AppendableJSONStream: JSONStream { 4 | func append(bytes: [UInt8]) 5 | } 6 | 7 | public extension AppendableJSONStream { 8 | func append(data: Data) { 9 | let bytes = [UInt8](data) 10 | append(bytes: bytes) 11 | } 12 | 13 | func append(string: String) { 14 | append(bytes: Array(string.utf8)) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/Environment/EnvironmentProvider/ProcessInfoEnvironmentProvider.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public final class ProcessInfoEnvironmentProvider: EnvironmentProvider { 4 | private let processInfo: ProcessInfo 5 | 6 | public init(processInfo: ProcessInfo) { 7 | self.processInfo = processInfo 8 | } 9 | 10 | public var environment: [String: String] { 11 | return processInfo.environment 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/FilePropertiesProvider/FilePropertiesProvider.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | import Foundation 3 | 4 | public protocol FilePropertiesProvider: FileExistenceChecker { 5 | func properties(path: AbsolutePath) -> FilePropertiesContainer 6 | } 7 | 8 | extension FilePropertiesProvider { 9 | public func existence(path: AbsolutePath) -> FileExistence { 10 | properties(path: path).existence 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Sources/PathLib/Path.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol Path: CustomStringConvertible { 4 | init(components: [S]) 5 | 6 | var components: [String] { get } 7 | var pathString: String { get } 8 | } 9 | 10 | extension Path { 11 | public var description: String { 12 | return pathString 13 | } 14 | 15 | public var asString: String { 16 | return pathString 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Sources/FileSystem/File/WorkingWithProperties/FileExistence.swift: -------------------------------------------------------------------------------- 1 | public enum FileExistence { 2 | case isFile 3 | case isDirectory 4 | case doesntExist 5 | 6 | public var exists: Bool { 7 | return self != .doesntExist 8 | } 9 | 10 | public var isFile: Bool { 11 | return self == .isFile 12 | } 13 | 14 | public var isDirectory: Bool { 15 | return self == .isDirectory 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/PlistLib/DI/PlistLibModuleDependencies.swift: -------------------------------------------------------------------------------- 1 | import DI 2 | 3 | public final class PlistLibModuleDependencies: ModuleDependencies { 4 | public init() { 5 | } 6 | 7 | public func registerDependenciesOfCurrentModule(di: DependencyRegisterer) { 8 | di.register(type: PlistReader.self) { di in 9 | try PlistReaderImpl( 10 | fileReader: di.resolve() 11 | ) 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Tests/TestHelpers/ExpectationCreation.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | 4 | public func testExpectation(_ description: String = "") -> XCTestExpectation { 5 | return XCTestExpectation(description: description) 6 | } 7 | 8 | public func invertedTestExpectation(_ description: String = "") -> XCTestExpectation { 9 | let expectation = testExpectation(description) 10 | expectation.isInverted = true 11 | return expectation 12 | } 13 | -------------------------------------------------------------------------------- /Tests/TestHelpers/TestFailing.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | 4 | public func failTest( 5 | _ message: String, 6 | file: StaticString = #filePath, 7 | line: UInt = #line 8 | ) -> Never { 9 | XCTFail(message, file: file, line: line) 10 | #if os(macOS) 11 | NSException(name: NSExceptionName(rawValue: message), reason: nil, userInfo: nil).raise() 12 | #endif 13 | fatalError(message, file: (file), line: line) 14 | } 15 | -------------------------------------------------------------------------------- /Tests/TestHelpers/AssertFalse.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | 4 | public func assertFalse( 5 | message: @autoclosure () -> String = { "Unexpected result: got true instead of false" }(), 6 | file: StaticString = #filePath, 7 | line: UInt = #line, 8 | work: () throws -> Bool 9 | ) { 10 | let result = assertDoesNotThrow(file: file, line: line, work: work) 11 | XCTAssertFalse(result, message(), file: file, line: line) 12 | } 13 | -------------------------------------------------------------------------------- /Tests/TestHelpers/AssertTrue.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | 4 | public func assertTrue( 5 | message: @autoclosure () -> String = { "Unexpected result: got false instead of true" }(), 6 | file: StaticString = #filePath, 7 | line: UInt = #line, 8 | work: () throws -> Bool 9 | ) { 10 | let result = assertDoesNotThrow(file: file, line: line, work: work) 11 | XCTAssertTrue(result, message(), file: file, line: line) 12 | } 13 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Generation/Errors/PackageSwiftMissingError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct PackageSwiftMissingError: Error, CustomStringConvertible { 4 | let packageSwiftFileUrl: URL 5 | 6 | public var description: String { 7 | """ 8 | File doesn't exist at path \(packageSwiftFileUrl.path), but is expected to be present. Please re-generate package and commit changes. 9 | """ 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/FileSystemPropertiesProvider/FileSystemPropertiesProvider.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol FileSystemPropertiesProvider { 4 | func fileSystemProperties(forFileAtPath: AbsolutePath) -> FileSystemPropertiesContainer 5 | } 6 | 7 | extension FileSystem { 8 | public func systemFreeSize(for path: AbsolutePath) throws -> Int64 { 9 | try fileSystemProperties(forFileAtPath: path).systemFreeSize() 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Sources/CommandSupport/CompoundCommandLogic.swift: -------------------------------------------------------------------------------- 1 | /// Allows to chain execution of nested ``CommandLogic``'s 2 | public final class CompoundCommandLogic: CommandLogic { 3 | private let commandLogics: [CommandLogic] 4 | 5 | public init(_ commandLogics: [CommandLogic]) { 6 | self.commandLogics = commandLogics 7 | } 8 | 9 | public func run() throws { 10 | for logic in commandLogics { 11 | try logic.run() 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/PackagejJson/PackagePlatform.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Platform that package supports 4 | public struct PackagePlatform: Codable, Hashable { 5 | 6 | /// Name, e.g. "macOS" 7 | public let name: String 8 | 9 | /// Version, e.g. "10.15" 10 | public let version: String 11 | 12 | public init(name: String, version: String) { 13 | self.name = name 14 | self.version = version 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/DI/Implementation/DependencyInjection/RegisteredDependency.swift: -------------------------------------------------------------------------------- 1 | final class RegisteredDependency { 2 | let scope: Scope 3 | let factory: (DependencyResolver) throws -> Any 4 | let instance: Any? 5 | 6 | init( 7 | scope: Scope, 8 | factory: @escaping (DependencyResolver) throws -> Any, 9 | instance: Any?) 10 | { 11 | self.scope = scope 12 | self.factory = factory 13 | self.instance = instance 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Sources/JSONStream/JSONReaderFatalError.swift: -------------------------------------------------------------------------------- 1 | /// Describes a fatal logic error. 2 | /// These errors should never happen in production. 3 | /// Unit tests should cover edges cases to ensure these errors won't happen. 4 | enum JSONReaderFatalError: Error { 5 | case arrayCannotHaveKeys(parent: ParsingContext, child: ParsingContext) 6 | case objectMustHaveKey(parent: ParsingContext, child: ParsingContext) 7 | case unhandledContextCombination(parent: ParsingContext, child: ParsingContext) 8 | } 9 | -------------------------------------------------------------------------------- /Tests/CLTExtensionsTests/NSLocking+WhileLockedTests.swift: -------------------------------------------------------------------------------- 1 | import CLTExtensions 2 | import XCTest 3 | 4 | final class NSLockingWhileLockedTests: XCTestCase { 5 | let lock = NSLock() 6 | 7 | func test___returns_value() { 8 | let value: Bool = lock.whileLocked { true } 9 | 10 | XCTAssertTrue(value) 11 | } 12 | 13 | func test___locks() { 14 | lock.whileLocked { 15 | XCTAssertFalse(lock.try()) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Sources/PlistLib/PlistReader/PlistReaderImpl.swift: -------------------------------------------------------------------------------- 1 | import FileSystem 2 | import PathLib 3 | 4 | public final class PlistReaderImpl: PlistReader { 5 | private let fileReader: FileReader 6 | 7 | public init(fileReader: FileReader) { 8 | self.fileReader = fileReader 9 | } 10 | 11 | public func readPlist(path: AbsolutePath) throws -> Plist { 12 | try Plist.create( 13 | fromData: fileReader.contents(filePath: path) 14 | ) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/TeamcityMessaging/ControlMessage/ControlMessageWithSingleParameter.swift: -------------------------------------------------------------------------------- 1 | public final class ControlMessageWithSingleParameter { 2 | public let type: String 3 | public let value: String 4 | 5 | public init( 6 | type: String, 7 | value: String 8 | ) { 9 | self.type = type 10 | self.value = value 11 | } 12 | 13 | public func toControlMessage() -> ControlMessage { 14 | return .withSingleParameter(self) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/CommandSupport/AbsolutePath+ExpressibleByArgument.swift: -------------------------------------------------------------------------------- 1 | import ArgumentParser 2 | import Foundation 3 | import PathLib 4 | 5 | extension AbsolutePath: ExpressibleByArgument { 6 | public init?(argument: String) { 7 | guard argument.starts(with: "/") else { return nil } 8 | self.init(argument) 9 | } 10 | 11 | public static var defaultCompletionKind: CompletionKind = .file() 12 | 13 | public var defaultValueDescription: String { "Абсолютный путь" } 14 | } 15 | -------------------------------------------------------------------------------- /Tests/DateProviderTestHelpers/DateProviderFixture.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import DateProvider 3 | 4 | public final class DateProviderFixture: DateProvider { 5 | public var result: Date 6 | 7 | public init(_ date: Date = Date()) { 8 | self.result = date 9 | } 10 | 11 | public func with(date: Date) -> Self { 12 | result = date 13 | return self 14 | } 15 | 16 | public func currentDate() -> Date { 17 | return result 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/Console/TrackingConsoleHandler/TraceMetadata.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import AtomicModels 3 | 4 | public final class TraceMetadata { 5 | @TaskLocal public static var current: TraceMetadata = .init() 6 | 7 | @AtomicValue 8 | public private(set) var metadata: [String: TraceMetadataValue] = [:] 9 | 10 | init() {} 11 | 12 | public subscript (_ key: String) -> TraceMetadataValue? { 13 | get { metadata[key] } 14 | set { metadata[key] = newValue } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/TeamcityMessaging/ControlMessage/ControlMessage.swift: -------------------------------------------------------------------------------- 1 | public enum ControlMessage { 2 | case withSingleParameter(ControlMessageWithSingleParameter) 3 | case withMultipleParameters(ControlMessageWithMultipleParameters) 4 | 5 | public var type: String { 6 | switch self { 7 | case .withSingleParameter(let message): 8 | return message.type 9 | case .withMultipleParameters(let message): 10 | return message.type 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/PathDeleter/PathDeleter.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol PathDeleter { 4 | /// Deletes file or directory (recursively) 5 | func delete( 6 | path: AbsolutePath, 7 | ignoreMissing: Bool 8 | ) throws 9 | } 10 | 11 | extension PathDeleter { 12 | public func delete( 13 | path: AbsolutePath 14 | ) throws { 15 | try delete( 16 | path: path, 17 | ignoreMissing: true 18 | ) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/RepoRoot/RepoRootProvider/RepoRootProviderImplementations/ClosureRepoRootProvider.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public final class ClosureRepoRootProvider: RepoRootProvider { 4 | private let repoRootProvider: () throws -> AbsolutePath 5 | 6 | public init(repoRootProvider: @escaping () throws -> AbsolutePath) { 7 | self.repoRootProvider = repoRootProvider 8 | } 9 | 10 | public func repoRoot() throws -> AbsolutePath { 11 | try repoRootProvider() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Sources/RepoRoot/RepoRootProvider/RepoRootProviderFactory.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol RepoRootProviderFactory { 4 | func repoRootProvider( 5 | anyPathWithinRepo: AbsolutePath 6 | ) -> RepoRootProvider 7 | } 8 | 9 | extension RepoRootProviderFactory { 10 | public func repoRoot( 11 | anyPathWithinRepo: AbsolutePath 12 | ) throws -> AbsolutePath { 13 | try repoRootProvider( 14 | anyPathWithinRepo: anyPathWithinRepo 15 | ).repoRoot() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/Console/ConsoleTextFragment.swift: -------------------------------------------------------------------------------- 1 | /// A single piece of `ConsoleText`. Contains a raw `String` and the desired `ConsoleStyle`. 2 | struct ConsoleTextFragment: Equatable { 3 | /// The raw `String`. 4 | var string: String 5 | 6 | /// `ConsoleStyle` to use when displaying the `string`. 7 | var style: ConsoleStyle 8 | 9 | /// Creates a new `ConsoleTextFragment`. 10 | init(string: String, style: ConsoleStyle = .plain) { 11 | self.string = string 12 | self.style = style 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Sources/MutualTLS/AbsolutePath+Credentials.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | extension AbsolutePath { 4 | public static var certsPath: AbsolutePath { 5 | return .home.appending(relativePath: ".ai/certs/") 6 | } 7 | 8 | public static var personalPrivateKeyPath: AbsolutePath { 9 | return .certsPath.appending(relativePath: "personal.key") 10 | } 11 | 12 | public static var personalCertificatePath: AbsolutePath { 13 | return .certsPath.appending(relativePath: "personal.crt") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Sources/Console/DI/ConsoleModuleDependencies.swift: -------------------------------------------------------------------------------- 1 | import DI 2 | import TeamcityMessaging 3 | 4 | public final class ConsoleModuleDependencies: ModuleDependencies { 5 | public init() { 6 | } 7 | 8 | public func otherModulesDependecies() -> [any ModuleDependencies] { 9 | [TeamcityMessagingModuleDependencies()] 10 | } 11 | 12 | public func registerDependenciesOfCurrentModule(di: DependencyRegisterer) { 13 | di.register(type: Console.self) { 14 | Console() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Tests/FileSystemTests/TestDataForEnumeration.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | import Tmp 4 | 5 | func createTestDataForEnumeration(tempFolder: TemporaryFolder) throws -> Set { 6 | return Set([ 7 | try tempFolder.createFile(filename: "root_file"), 8 | try tempFolder.createDirectory(components: ["empty_folder"]), 9 | try tempFolder.createDirectory(components: ["subfolder"]), 10 | try tempFolder.createFile(components: ["subfolder"], filename: "file_in_subfolder") 11 | ]) 12 | } 13 | -------------------------------------------------------------------------------- /Sources/CommandSupport/CommandLogic.swift: -------------------------------------------------------------------------------- 1 | public protocol CommandLogic { 2 | func run() throws 3 | } 4 | 5 | extension CommandLogic { 6 | public func toAsync() -> AsyncCommandLogic { 7 | SyncCommandLogicWrapper(command: self) 8 | } 9 | } 10 | 11 | private final class SyncCommandLogicWrapper: AsyncCommandLogic { 12 | private let job: () throws -> () 13 | 14 | init(command: CommandLogic) { 15 | job = command.run 16 | } 17 | 18 | func run() async throws { 19 | try job() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Sources/ProcessController/ProcessListener.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias Unsubscribe = () -> () 4 | public typealias SignalListener = (ProcessController, Int32, @escaping Unsubscribe) -> () 5 | public typealias StartListener = (ProcessController, @escaping Unsubscribe) -> () 6 | public typealias StderrListener = (ProcessController, Data, @escaping Unsubscribe) -> () 7 | public typealias StdoutListener = (ProcessController, Data, @escaping Unsubscribe) -> () 8 | public typealias TerminationListener = (ProcessController, @escaping Unsubscribe) -> () 9 | -------------------------------------------------------------------------------- /Tests/FileSystemTestHelpers/FakeFileSystemEnumerator.swift: -------------------------------------------------------------------------------- 1 | import FileSystem 2 | import Foundation 3 | import PathLib 4 | 5 | open class FakeFileSystemEnumerator: FileSystemEnumerator { 6 | public let path: AbsolutePath 7 | public var items = [AbsolutePath]() 8 | 9 | public init(path: AbsolutePath, items: [AbsolutePath] = []) { 10 | self.path = path 11 | self.items = items 12 | } 13 | 14 | public func each(iterator: (AbsolutePath) throws -> ()) throws { 15 | try items.forEach(iterator) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/TeamcityMessaging/DI/TeamcityMessagingModuleDependencies.swift: -------------------------------------------------------------------------------- 1 | import DI 2 | 3 | public final class TeamcityMessagingModuleDependencies: ModuleDependencies { 4 | public init() { 5 | } 6 | 7 | public func registerDependenciesOfCurrentModule(di: DependencyRegisterer) { 8 | di.register(type: TeamcityMessageGenerator.self) { _ in 9 | TeamcityMessageGenerator() 10 | } 11 | di.register(type: TeamcityMessageRenderer.self) { _ in 12 | TeamcityMessageRendererImpl() 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Sources/Waitable/Waitable.swift: -------------------------------------------------------------------------------- 1 | import Dispatch 2 | import Foundation 3 | 4 | public class Waitable { 5 | private let semaphore = DispatchSemaphore(value: 1) 6 | 7 | public init() {} 8 | 9 | /// Blocks until signal occurs 10 | public func wait() { 11 | semaphore.wait() 12 | semaphore.wait() // waits here until `signal` is called 13 | semaphore.signal() 14 | } 15 | 16 | /// Unblocks thread which waits for `wait` call. 17 | public func signal() { 18 | semaphore.signal() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/CommandSupport/CompoundAsyncCommandLogic.swift: -------------------------------------------------------------------------------- 1 | /// Allows to chain execution of nested ``AsyncCommandLogic``'s 2 | public final class CompoundAsyncCommandLogic: AsyncCommandLogic { 3 | private let commandLogics: [AsyncCommandLogic] 4 | 5 | public init(_ commandLogics: [AsyncCommandLogic]) { 6 | self.commandLogics = commandLogics 7 | } 8 | 9 | public func run() async throws { 10 | for logic in commandLogics { 11 | try await logic.run() 12 | try Task.checkCancellation() 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/CommonlyUsedPathsProviderFactory/CommonlyUsedPathsProviderFactoryImpl.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public final class CommonlyUsedPathsProviderFactoryImpl: CommonlyUsedPathsProviderFactory { 4 | public init() { 5 | } 6 | 7 | public var commonlyUsedPathsProvider: CommonlyUsedPathsProvider { 8 | #if os(macOS) 9 | return AppleCommonlyUsedPathsProvider() 10 | #elseif os(Linux) 11 | return LinuxCommonlyUsedPathsProvider() 12 | #else 13 | #error("Unsupported OS") 14 | #endif 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/ProcessController/ProcessStatus.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum ProcessStatus: Equatable, CustomStringConvertible { 4 | case notStarted 5 | case stillRunning 6 | case terminated(exitCode: Int32) 7 | 8 | public var description: String { 9 | switch self { 10 | case .notStarted: 11 | return "not started" 12 | case .stillRunning: 13 | return "still running" 14 | case .terminated(let exitCode): 15 | return "exit code \(exitCode)" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Tests/FileSystemTestHelpers/FakeFileReader.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import FileSystem 3 | import PathLib 4 | 5 | open class FakeFileReader: FileReader { 6 | public var provider: (AbsolutePath) throws -> Data 7 | 8 | public init( 9 | provider: @escaping (AbsolutePath) throws -> Data = { _ in 10 | Data() 11 | } 12 | ) { 13 | self.provider = provider 14 | } 15 | 16 | public func contents( 17 | filePath: AbsolutePath 18 | ) throws -> Data { 19 | try provider(filePath) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Tests/SignalHandlingTests/SignalHandlingTests.swift: -------------------------------------------------------------------------------- 1 | import SignalHandling 2 | import Signals 3 | import XCTest 4 | 5 | final class SignalHandlerTests: XCTestCase { 6 | func test___hanlder_fires_when_signal_occurs() { 7 | var didHandle = false 8 | 9 | SignalHandling.addSignalHandler(signal: Signal.user(20)) { value in 10 | XCTAssertEqual(value, 20) 11 | didHandle = true 12 | } 13 | 14 | Signals.raise(signal: Signals.Signal.user(20)) 15 | 16 | XCTAssertTrue(didHandle) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Statements/ExternalPackageVersion+Statement.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension ExternalPackageVersion { 4 | var statement: String { 5 | switch self { 6 | case let .exact(value): 7 | return #"exact: "\#(value)""# 8 | case let .from(value): 9 | return #"from: "\#(value)""# 10 | case let .branch(value): 11 | return #"branch: "\#(value)""# 12 | case let .revision(value): 13 | return #"revision: "\#(value)""# 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/CLTTypes/Credentials.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | import CLTExtensions 8 | 9 | public struct Credentials: Codable, Hashable { 10 | public var username: String 11 | public var password: String 12 | 13 | public init(username: String, password: String) { 14 | self.username = username 15 | self.password = password 16 | } 17 | 18 | public func asHTTPHeaderValue() throws -> String { 19 | try "\(username):\(password)".dataUsingUtf8().base64EncodedString() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Tests/CLTLoggingTestHelpers/FakeLoggerHandler.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | import CLTLogging 7 | import CLTLoggingModels 8 | 9 | public final class FakeLoggerHandle: LoggerHandler { 10 | public init() {} 11 | 12 | public var logEntries = [LogEntry]() 13 | 14 | public func handle(logEntry: LogEntry) { 15 | logEntries.append(logEntry) 16 | } 17 | 18 | public var tornDown = false 19 | public func tearDownLogging(timeout: TimeInterval) { 20 | tornDown = true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Tests/UserDefaultsLibTestHelpers/FakeDefaults.swift: -------------------------------------------------------------------------------- 1 | import PlistLib 2 | import UserDefaultsLib 3 | 4 | open class FakeDefaults: Defaults { 5 | public var storage = [String: PlistEntry]() 6 | 7 | public init() {} 8 | 9 | public func entryForKey(_ key: String) throws -> PlistEntry? { 10 | storage[key] 11 | } 12 | 13 | public func set(entry: PlistEntry?, key: String) { 14 | storage[key] = entry 15 | } 16 | 17 | public func removeEntryForKey(_ key: String) { 18 | storage.removeValue(forKey: key) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/Console/ANSIConsoleHandler/Question/QuestionComponentState.swift: -------------------------------------------------------------------------------- 1 | struct QuestionComponentState: Hashable { 2 | enum QuestionResult: Hashable { 3 | case cancelled 4 | case selected(answer: Bool) 5 | } 6 | 7 | var title: String 8 | var defaultAnswer: Bool 9 | var help: String? 10 | 11 | private(set) var result: QuestionResult? 12 | 13 | mutating func cancel() { 14 | self.result = .cancelled 15 | } 16 | 17 | mutating func confirm(answer: Bool) { 18 | self.result = .selected(answer: answer) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Tests/ProcessControllerTests/EnvironmentSecureValueTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import ProcessController 3 | import TestHelpers 4 | import XCTest 5 | 6 | final class EnvironmentSecureValueTests: XCTestCase { 7 | func test() { 8 | let env: Environment = [ 9 | "env1": "12345".secured, 10 | "env2": "54321", 11 | ] 12 | 13 | assertFalse { 14 | env.description.contains("12345") 15 | } 16 | 17 | assertTrue { 18 | env.description.contains("54321") 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Sources/CLTExtensions/Collections/Collection+Single.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Collection { 4 | public func single(where matcher: (Element) -> (Bool) = { _ in true }) throws -> Element { 5 | let filtered = self.filter(matcher) 6 | guard !filtered.isEmpty else { 7 | throw "Didn't find a single matching element in: \(self) of type \(type(of: self))" 8 | } 9 | guard filtered.count == 1 else { 10 | throw "Found more than one matching element: \(filtered)" 11 | } 12 | return filtered[0] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Sources/DI/DependencyCollectionRegisterer/CompoundDependencyCollectionRegisterer.swift: -------------------------------------------------------------------------------- 1 | public final class CompoundDependencyCollectionRegisterer: DependencyCollectionRegisterer { 2 | private let registerers: [DependencyCollectionRegisterer] 3 | 4 | public init(registerers: [DependencyCollectionRegisterer]) { 5 | self.registerers = registerers 6 | } 7 | 8 | public func register(dependencyRegisterer: DependencyRegisterer) { 9 | registerers.forEach { 10 | $0.register(dependencyRegisterer: dependencyRegisterer) 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/FileAppender/FileAppenderImpl.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | import Foundation 3 | 4 | public final class FileAppenderImpl: FileAppender { 5 | public init() {} 6 | 7 | public func appendToFile(path: AbsolutePath, data: Data) throws { 8 | if let fileHandle = FileHandle(forWritingAtPath: path.pathString) { 9 | defer { fileHandle.closeFile() } 10 | try fileHandle.seekToEnd() 11 | fileHandle.write(data) 12 | } else { 13 | try data.write(to: path.fileUrl, options: .atomic) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/XcodeLocator/XcodeApplicationVerifier/XcodeApplicationVerifierImpl.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | import Foundation 3 | import PlistLib 4 | 5 | public final class XcodeApplicationVerifierImpl: XcodeApplicationVerifier { 6 | public init() { 7 | } 8 | 9 | public func isXcodeApplicaton(infoPlist: Plist) -> Bool { 10 | let bundleIdentifier = try? infoPlist 11 | .root 12 | .plistEntry 13 | .entry(forKey: "CFBundleIdentifier") 14 | .stringValue() 15 | 16 | return bundleIdentifier == "com.apple.dt.Xcode" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /shared_makefile/Makefile: -------------------------------------------------------------------------------- 1 | project_makefile_path := $(abspath $(lastword $(MAKEFILE_LIST))) 2 | project_dir := $(shell dirname "$(project_makefile_path)") 3 | shared_makefile_path := $(shell readlink "$(project_makefile_path)") 4 | shared_makefile_dir := $(shell dirname "$(shared_makefile_path)") 5 | shared_make_sh_path := "$(shared_makefile_dir)/make.sh" 6 | 7 | targets := $(shell "$(shared_make_sh_path)" --project-dir "$(project_dir)" --targets) 8 | 9 | __first_target_aka_default_target__: help 10 | 11 | $(targets): 12 | @bash "${shared_make_sh_path}" --project-dir "${project_dir}" $@ 13 | .PHONY: $(targets) -------------------------------------------------------------------------------- /Sources/CLTLoggingModels/LoggableOptional.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | public final class LoggableOptional: CustomStringConvertible { 8 | private let value: T? 9 | private let nilReplacement: String 10 | 11 | public init(_ value: T?, nilReplacement: String = "nil") { 12 | self.value = value 13 | self.nilReplacement = nilReplacement 14 | } 15 | 16 | public var description: String { 17 | if let value = value { 18 | return "\(value)" 19 | } 20 | return nilReplacement 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Sources/JSONStream/JSONStream.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A basic interface that allows JSONReader to read the stream symbol by symbol, consuming the JSON element by element 4 | /// rather than having the whole JSON object availbla to parse upfront. 5 | public protocol JSONStream { 6 | /// Provides back a next scalar without actually moving a pointer. Returns nil if no more data avaiable. 7 | func touch() -> UInt8? 8 | /// Moves a pointer to the next scalar and provides it back. Returns nil if no more data avaiable. 9 | func read() -> UInt8? 10 | /// Closes the stream. 11 | func close() 12 | } 13 | -------------------------------------------------------------------------------- /Sources/Console/ANSIConsoleHandler/Input/InputComponentState.swift: -------------------------------------------------------------------------------- 1 | /// State of input component 2 | struct InputComponentState: Hashable { 3 | enum InputResult: Hashable { 4 | case cancelled 5 | case success(input: String) 6 | } 7 | 8 | var title: String 9 | var input: String = "" 10 | var defaultValue: String? 11 | var cursorIndex: Int = 0 12 | 13 | private(set) var result: InputResult? 14 | 15 | mutating func cancel() { 16 | self.result = .cancelled 17 | } 18 | 19 | mutating func confirm() { 20 | self.result = .success(input: input) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Generation/Errors/ContentMismatchError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct ContentMismatchError: Error, CustomStringConvertible { 4 | let packageSwiftFileUrl: URL 5 | let currentContents: String 6 | let generatedContents: String 7 | 8 | public var description: String { 9 | """ 10 | Contents of \(packageSwiftFileUrl.path) differs from expected. Please re-generate it and commit changes. 11 | 12 | Generated contents: 13 | \(generatedContents) 14 | 15 | Current contents: 16 | \(currentContents) 17 | """ 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/Cloc/Cloc.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | public enum IncludeLangOption: String { 5 | case swift = "swift" 6 | case objc = "objective-c" 7 | case cCPlusPlusHeader = "h" 8 | } 9 | 10 | public protocol Cloc { 11 | func countLinesOfCode( 12 | sourceFiles: [AbsolutePath], 13 | includeLangOptions: Set 14 | ) throws -> Int 15 | } 16 | 17 | public extension Cloc { 18 | func countLinesOfCode( 19 | sourceFiles: [AbsolutePath] 20 | ) throws -> Int { 21 | try countLinesOfCode(sourceFiles: sourceFiles, includeLangOptions: [.swift]) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/CLTExtensions/Collections/Dictionary+Inverse.swift: -------------------------------------------------------------------------------- 1 | extension Dictionary where Value: Hashable { 2 | public func inverseKeysAndValuesWithNonUniqueKeys() -> [Value: [Key]] { 3 | map { key, value in 4 | KeyValuePair(key: value, value: key) 5 | }.nonUniquelyKeyedToDictionary { pair in 6 | pair 7 | } 8 | } 9 | 10 | public func inverseKeysAndValuesWithUniqueKeys() throws -> [Value: Key] { 11 | try map { key, value in 12 | KeyValuePair(key: value, value: key) 13 | }.uniquelyKeyedToDictionary { pair in 14 | pair 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/DI/DependencyResolver/DependencyResolver.swift: -------------------------------------------------------------------------------- 1 | public protocol DependencyResolver: AnyObject { 2 | // Use this function in custom implementations/wrappers of `DependencyResolver`. 3 | // See `CompoundDependencyResolver`. Use `resolve()` for everything else, for 4 | // example, for resolving your dependencies. 5 | func resolve(nestedDependencyResolver: DependencyResolver) throws -> T 6 | } 7 | 8 | extension DependencyResolver { 9 | // Use this function for most cases. 10 | public func resolve(type: T.Type = T.self) throws -> T { 11 | return try resolve(nestedDependencyResolver: self) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Sources/Types/CompoundError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public final class CompoundError: LocalizedError { 4 | public let errors: [Error] 5 | public let descriptionPreparer: ([Error]) -> String 6 | 7 | public init( 8 | errors: [Error], 9 | descriptionPreparer: @escaping ([Error]) -> String = { errors in 10 | errors.map { "\($0)" }.joined(separator: "\n") 11 | } 12 | ) { 13 | self.errors = errors 14 | self.descriptionPreparer = descriptionPreparer 15 | } 16 | 17 | public var errorDescription: String? { 18 | descriptionPreparer(errors) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/KibanaModels/KibanaConfiguration.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | import CLTTypes 8 | 9 | public struct KibanaConfiguration: Codable, Hashable { 10 | public let endpoints: [URL] 11 | public let indexPattern: String 12 | public let authorization: HttpAuthorizationScheme? 13 | 14 | public init( 15 | endpoints: [URL], 16 | indexPattern: String, 17 | authorization: HttpAuthorizationScheme? 18 | ) { 19 | self.endpoints = endpoints 20 | self.indexPattern = indexPattern 21 | self.authorization = authorization 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/UserDefaultsLib/README.md: -------------------------------------------------------------------------------- 1 | # UserDefaultsLib 2 | 3 | Provides a little DSL to work with `NSUserDefaults` to allow type checking. 4 | 5 | Since UserDefaults accepts only property list objects, this library adopts `PlistLib` APIs. 6 | 7 | Simple example: 8 | 9 | ```swift 10 | 11 | // create 12 | let defaults = try SystemDefaults(suiteName: "com.domain.name") 13 | 14 | // read 15 | var numbers = try defaults.entryForKey("arrayOfNumbers").toTypedArray(Int.self) 16 | 17 | numbers.append(numbers.count) 18 | 19 | // update 20 | defaults.set( 21 | entry: .array(numbers.map { .number($0) }), 22 | key: "arrayOfNumbers" 23 | ) 24 | 25 | ``` 26 | -------------------------------------------------------------------------------- /Tests/ProcessControllerTestHelpers/FakeProcessControllerProvider.swift: -------------------------------------------------------------------------------- 1 | import ProcessController 2 | import Foundation 3 | import Tmp 4 | 5 | public final class FakeProcessControllerProvider: ProcessControllerProvider { 6 | public var creator: (Subprocess) throws -> (ProcessController) 7 | 8 | public init( 9 | creator: @escaping (Subprocess) throws -> ProcessController = { FakeProcessController(subprocess: $0) } 10 | ) { 11 | self.creator = creator 12 | } 13 | 14 | public func createProcessController(subprocess: Subprocess) throws -> ProcessController { 15 | return try creator(subprocess) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/CLTExtensions/Collections/Dictionary+Map.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Dictionary { 4 | @inlinable 5 | public func mapKeys( 6 | keyMapping: (Key) throws -> R 7 | ) rethrows -> [R: Value] { 8 | .init(uniqueKeysWithValues: try map { 9 | (try keyMapping($0.key), $0.value) 10 | }) 11 | } 12 | 13 | @inlinable 14 | public func mapValuesWithKeys( 15 | transform: (Key, Value) throws -> T 16 | ) rethrows -> [Key: T] { 17 | .init(uniqueKeysWithValues: try map { 18 | try ($0.key, transform($0.key, $0.value)) 19 | }) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Sources/CLTLogging/FileState.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | enum FileState { 8 | case open(FileHandle) 9 | case closed 10 | 11 | var openedFileHandle: FileHandle? { 12 | switch self { 13 | case .open(let handle): 14 | return handle 15 | case .closed: 16 | return nil 17 | } 18 | } 19 | 20 | mutating func close() { 21 | switch self { 22 | case .open(let handle): 23 | handle.closeFile() 24 | self = .closed 25 | case .closed: 26 | break 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/PackagejJson/PackageProduct.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Describes a product 4 | public struct PackageProduct: Codable, Hashable { 5 | 6 | /// Name of the product 7 | public let name: String 8 | 9 | /// Type of the product 10 | public let productType: PackageProductType 11 | 12 | /// Name of the targets this product consists of. 13 | public let targets: [String] 14 | 15 | public init(name: String, productType: PackageProductType, targets: [String]) { 16 | self.name = name 17 | self.productType = productType 18 | self.targets = targets 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/Enumeration/Glob/GlobFileSystemEnumerator.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Glob 3 | import PathLib 4 | 5 | public final class GlobFileSystemEnumerator: FileSystemEnumerator { 6 | private let pattern: GlobPattern 7 | 8 | public init( 9 | pattern: GlobPattern 10 | ) { 11 | self.pattern = pattern 12 | } 13 | 14 | public func each(iterator: (AbsolutePath) throws -> ()) throws { 15 | let glob = Glob( 16 | pattern: pattern.value, 17 | behavior: .BashV4 18 | ) 19 | for path in glob { 20 | try iterator(AbsolutePath(path)) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Tests/CLTLoggingTests/FakeFileHandle.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | class FakeFileHandle: FileHandle { 8 | 9 | var isClosed = false 10 | var closeCounter = 0 11 | 12 | override init(fileDescriptor fd: Int32 = 0, closeOnDealloc closeopt: Bool = true) { 13 | super.init(fileDescriptor: fd, closeOnDealloc: closeopt) 14 | } 15 | 16 | @available(*, unavailable) 17 | required init?(coder: NSCoder) { 18 | fatalError("init(coder:) has not been implemented") 19 | } 20 | 21 | override func closeFile() { 22 | isClosed = true 23 | closeCounter += 1 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Tests/FileSystemTestHelpers/FakeThrowingProperty.swift: -------------------------------------------------------------------------------- 1 | import Types 2 | 3 | public final class FakeThrowingProperty: ThrowingPropertyOf { 4 | public var value: T { 5 | get { 6 | valueBox.value 7 | } 8 | set { 9 | valueBox.value = newValue 10 | } 11 | } 12 | 13 | private let valueBox: MutableBox 14 | 15 | public init(value: T) { 16 | let valueBox = MutableBox(value: value) 17 | 18 | self.valueBox = valueBox 19 | 20 | super.init( 21 | getter: { valueBox.value }, 22 | setter: { valueBox.value = $0 } 23 | ) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Tests/TestHelpers/Equals.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | 4 | public func assert( 5 | file: StaticString = #filePath, 6 | line: UInt = #line, 7 | left: () throws -> T, 8 | equals right: () throws -> T 9 | ) { 10 | do { 11 | let leftResult = try left() 12 | let rightResult = try right() 13 | 14 | if leftResult != rightResult { 15 | XCTFail("Values not equal.\nLeft value: \n\(leftResult)\nRight value:\n\(rightResult)", file: file, line: line) 16 | } 17 | } catch { 18 | XCTFail("Error thrown during value comparison.\nError: \(error)", file: file, line: line) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/CommandSupport/TestableCommand.swift: -------------------------------------------------------------------------------- 1 | /// If you are using `CommandDiValidator`, it creates commands to validate them. 2 | /// And if some commands have required arguments, they can not be created without them. 3 | /// You can use `TestableCommand` to help `CommandDiValidator` create such commands. 4 | /// 5 | /// Example: 6 | /// 7 | /// ``` 8 | /// extension MyCommand: TestableCommand { 9 | /// public static func testableCommandArguments() -> [String] { 10 | /// return ["irrelevant_foo_argument", "irrelevant_bar_argument"] 11 | /// } 12 | /// } 13 | /// ``` 14 | 15 | public protocol TestableCommand { 16 | static func testableCommandArguments() -> [String] 17 | } 18 | -------------------------------------------------------------------------------- /Sources/XcodeLocator/ApplicationPlistReader/ApplicationPlistReaderImpl.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | import CLTExtensions 3 | import PlistLib 4 | import Foundation 5 | 6 | public final class ApplicationPlistReaderImpl: ApplicationPlistReader { 7 | public init() { 8 | } 9 | 10 | public func applicationPlist(pathToApplication: AbsolutePath) throws -> Plist { 11 | let plistPath = pathToApplication 12 | .appending("Contents/Info.plist") 13 | 14 | return try Plist.create( 15 | fromData: Data( 16 | contentsOf: plistPath.fileUrl, 17 | options: .mappedIfSafe 18 | ) 19 | ) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Statements/PackageDependencies+Statement.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension PackageDependencies { 4 | var statements: [String] { 5 | external.sorted { left, right -> Bool in 6 | left.key < right.key 7 | } 8 | .map { (name: String, value: ExternalPackageLocation) -> String in 9 | switch value { 10 | case let .url(url, version, _, _): 11 | return ".package(url: \"\(url)\", \(version.statement))" 12 | case let .local(path, _): 13 | return ".package(name: \"\(name)\", path: \"\(path)\")" 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/CLTTypes/Http/HttpAuthorizationScheme.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | public enum HttpAuthorizationScheme: Codable, Hashable { 8 | case basic(credentials: Credentials) 9 | case bearer(token: String) 10 | case apiKey(token: String) 11 | 12 | public func httpHeaderValue() throws -> String { 13 | switch self { 14 | case let .basic(credentials): 15 | return "Basic \(try credentials.asHTTPHeaderValue())" 16 | case let .bearer(token): 17 | return "Bearer \(token)" 18 | case let .apiKey(token): 19 | return "ApiKey \(token)" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Tests/CLTLoggingTests/SimpleLogEntryTextFormatter.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | import CLTLogging 7 | import CLTLoggingModels 8 | 9 | final class SimpleLogEntryTextFormatter: LogEntryTextFormatter { 10 | func format(logEntry: LogEntry) -> String { 11 | var result = "" 12 | result += "\(logEntry.timestamp)" 13 | 14 | if !logEntry.coordinates.isEmpty { 15 | result += " " + logEntry.coordinates.map { $0.stringValue }.joined(separator: " ") 16 | } 17 | 18 | result += ":" 19 | result += " \(logEntry.message)" 20 | 21 | return result 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/Enumeration/Shallow/ShallowFileSystemEnumerator.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | public final class ShallowFileSystemEnumerator: FileSystemEnumerator { 5 | private let path: AbsolutePath 6 | private let fileManager = FileManager() 7 | 8 | public init( 9 | path: AbsolutePath 10 | ) { 11 | self.path = path 12 | } 13 | 14 | public func each(iterator: (AbsolutePath) throws -> ()) throws { 15 | let contents = try fileManager.contentsOfDirectory(atPath: path.pathString) 16 | 17 | for element in contents { 18 | try iterator(path.appending(element)) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Sources/FileSystem/File/WorkingWithContents/FileReader/FileReader.swift: -------------------------------------------------------------------------------- 1 | import CLTExtensions 2 | import Foundation 3 | import PathLib 4 | 5 | public protocol FileReader { 6 | func contents(filePath: AbsolutePath) throws -> Data 7 | } 8 | 9 | extension FileReader { 10 | public func string(filePath: AbsolutePath) throws -> String { 11 | return try String(utf8Data: contents(filePath: filePath)) 12 | } 13 | 14 | public func decodable( 15 | type: T.Type = T.self, 16 | jsonFilePath: AbsolutePath, 17 | decoder: JSONDecoder = JSONDecoder() 18 | ) throws -> T { 19 | try decoder.decode(type, from: contents(filePath: jsonFilePath)) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Tests/TestHelpers/NilHelpers.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | 4 | @discardableResult 5 | public func assertNotNil( 6 | file: StaticString = #filePath, 7 | line: UInt = #line, 8 | work: () throws -> T? 9 | ) rethrows -> T { 10 | guard let value = try work() else { 11 | failTest("Unexpected nil value", file: file, line: line) 12 | } 13 | return value 14 | } 15 | 16 | public func assertNil( 17 | file: StaticString = #filePath, 18 | line: UInt = #line, 19 | work: () throws -> T? 20 | ) rethrows { 21 | guard let value = try work() else { 22 | return 23 | } 24 | failTest("Expected nil value, but got \(value)", file: file, line: line) 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CommandLineToolkit 2 | 3 | Various things that make it easier to implement command line tools in Swift. 4 | 5 | - [JSONStream](Sources/JSONStream/) — a set of APIs to parse a stream of JSON objects on the fly 6 | - [PlistLib](Sources/PlistLib/) — small DSL to create, read and write Plists 7 | - [TestHelpers](Tests/TestHelpers/) — a set of convenience functions for cleaner test expression 8 | - [UserDefaultsLib](Sources/UserDefaultsLib/) — small DSL to read and write UserDefaults 9 | - and even more... — have a look at subfolders! 10 | 11 | ## Development 12 | 13 | - To generate and open Xcode project: `make open` 14 | - To generate `Package.swift` only: `make generate` 15 | - To run tests: `make test` 16 | -------------------------------------------------------------------------------- /Sources/CLTExtensions/Collections/Bool+Order.swift: -------------------------------------------------------------------------------- 1 | // Comparison operators for Boolean (note that from a logical point of view `<` makes no sense for boolean values) 2 | extension Bool { 3 | // false, false -> false 4 | // false, true -> true 5 | // true, false -> false 6 | // true, true -> false 7 | public static func isOrderedFromFalseToTrue(_ lhs: Bool, _ rhs: Bool) -> Bool { 8 | return !lhs && rhs 9 | } 10 | 11 | // false, false -> false 12 | // false, true -> false 13 | // true, false -> true 14 | // true, true -> false 15 | public static func isOrderedFromTrueToFalse(_ lhs: Bool, _ rhs: Bool) -> Bool { 16 | return lhs && !rhs 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Tests/MetricsTestHelpers/FakeMetricHandler.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Graphite 3 | import MetricsRecording 4 | import Statsd 5 | 6 | public final class FakeMetricHandler { 7 | public var metrics = [Metric]() 8 | 9 | public init() {} 10 | 11 | public func handle(metric: Metric) { 12 | metrics.append(metric) 13 | } 14 | 15 | public var tearDownTimeout: TimeInterval = 0 16 | 17 | public func tearDown(timeout: TimeInterval) { 18 | tearDownTimeout = timeout 19 | } 20 | } 21 | 22 | extension FakeMetricHandler: GraphiteMetricHandler where Metric == GraphiteMetric {} 23 | extension FakeMetricHandler: StatsdMetricHandler where Metric == StatsdMetric {} 24 | -------------------------------------------------------------------------------- /Sources/Environment/EnvironmentProvider/EnvironmentProvider.swift: -------------------------------------------------------------------------------- 1 | public protocol EnvironmentProvider: AnyObject { 2 | var environment: [String: String] { get } 3 | 4 | func get(_ key: EnvironmentKey) throws -> Value? 5 | } 6 | 7 | extension EnvironmentProvider { 8 | public func get(_ key: EnvironmentKey) throws -> Value? { 9 | guard let value = environment[key.key] else { 10 | return nil 11 | } 12 | 13 | return try key.conversion.apply(value) 14 | } 15 | 16 | public func get(_ key: EnvironmentKey, default value: @autoclosure () -> Value) throws -> Value { 17 | return try get(key) ?? value() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/Types/ThrowingProperty/GettableThrowingPropertyOf.swift: -------------------------------------------------------------------------------- 1 | open class GettableThrowingPropertyOf: GettableThrowingProperty { 2 | public typealias PropertyType = T 3 | 4 | private let getter: () throws -> PropertyType 5 | 6 | public init( 7 | getter: @escaping () throws -> PropertyType 8 | ) { 9 | self.getter = getter 10 | } 11 | 12 | public convenience init( 13 | throwingProperty: Other 14 | ) where Other.PropertyType == PropertyType { 15 | self.init( 16 | getter: { try throwingProperty.get() } 17 | ) 18 | } 19 | public func get() throws -> PropertyType { 20 | try getter() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Sources/CLTCollections/Array+Set.swift: -------------------------------------------------------------------------------- 1 | extension Array where Element: Hashable { 2 | public func uniquified() -> [Element] { 3 | Array(toSet()) 4 | } 5 | 6 | public func uniquified(by keyPath: KeyPath) -> [Element] { 7 | var processedValues = Set() 8 | 9 | var result = [Element]() 10 | 11 | for element in self { 12 | let value = element[keyPath: keyPath] 13 | if processedValues.insert(value).inserted { 14 | result.append(element) 15 | } 16 | } 17 | 18 | return result 19 | } 20 | 21 | public func toSet() -> Set { 22 | Set(self) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/TeamcityMessaging/ControlMessage/ControlMessageBuilder.swift: -------------------------------------------------------------------------------- 1 | public final class ControlMessageBuilder { 2 | public init() { 3 | } 4 | 5 | public func build( 6 | type: String 7 | ) -> ControlMessageWithMultipleParameters { 8 | return ControlMessageWithMultipleParameters( 9 | type: type, 10 | flowId: nil, 11 | timestamp: nil, 12 | parameters: [] 13 | ) 14 | } 15 | 16 | public func build( 17 | type: String, 18 | value: String 19 | ) -> ControlMessageWithSingleParameter { 20 | return ControlMessageWithSingleParameter( 21 | type: type, 22 | value: value 23 | ) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Tests/CLTExtensionsTests/Array+Comparable_Tests.swift: -------------------------------------------------------------------------------- 1 | import CLTExtensions 2 | import XCTest 3 | 4 | class ArrayComparableTests: XCTestCase { 5 | func test() { 6 | XCTAssertFalse( 7 | [] < [] 8 | ) 9 | XCTAssert( 10 | [0] < [1] 11 | ) 12 | XCTAssertFalse( 13 | [0] < [0] 14 | ) 15 | XCTAssert( 16 | [0, 0] < [0, 1] 17 | ) 18 | XCTAssertFalse( 19 | [0, 1] < [0, 0] 20 | ) 21 | XCTAssertFalse( 22 | [0, 0] < [0, 0] 23 | ) 24 | XCTAssert( 25 | [0] < [0, 0] 26 | ) 27 | XCTAssertFalse( 28 | [1] < [0, 0] 29 | ) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sources/ImagesInterfaces/KnownImageCategories.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol KnownImageCategories { 4 | var moduleName: String { get } 5 | var factoryFileName: String { get } 6 | var assetContentFileName: String { get } 7 | var assetsPath: RelativePath { get } 8 | var imageFactoryPath: RelativePath { get } 9 | var assetsExtention: String { get } 10 | var imagesetExtention: String { get } 11 | var all: [KnownImageCategory] { get } 12 | } 13 | 14 | public struct KnownImageCategory: Equatable { 15 | public let name: String 16 | public let path: RelativePath 17 | 18 | public init(name: String, path: RelativePath) { 19 | self.name = name 20 | self.path = path 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Tests/FileSystemTests/LocalFileSystemTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import FileSystem 3 | import XCTest 4 | 5 | final class FilePropertiesProviderImplTests: XCTestCase { 6 | private let fileManager = FileManager() 7 | private lazy var tempFolder = createTempFolder() 8 | private let provider = FilePropertiesProviderImpl() 9 | 10 | func test___properties() throws { 11 | let path = try tempFolder.createFile(filename: "file") 12 | 13 | let properties = provider.properties(path: path) 14 | 15 | XCTAssertEqual( 16 | try properties.modificationDate.get(), 17 | try fileManager.attributesOfItem(atPath: path.pathString)[.modificationDate] as? Date 18 | ) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/FirstNonThrowingResultOf.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum FirstNonThrowingResultOf { 4 | private final class NoWorkWasDoneError: Error, CustomStringConvertible { 5 | var description: String { 6 | return "Throwable.works expects array with at least one value" 7 | } 8 | } 9 | 10 | public static func perform(_ works: () throws -> T...) throws -> T { 11 | var lastCaughtError: Error? 12 | for work in works { 13 | do { 14 | return try work() 15 | } catch { 16 | lastCaughtError = error 17 | } 18 | } 19 | throw (lastCaughtError ?? NoWorkWasDoneError()) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Sources/DI/DependencyResolver/WeakDependencyResolver.swift: -------------------------------------------------------------------------------- 1 | public final class WeakDependencyResolver: DependencyResolver { 2 | private weak var dependencyResolver: DependencyResolver? 3 | 4 | public init( 5 | dependencyResolver: DependencyResolver) 6 | { 7 | self.dependencyResolver = dependencyResolver 8 | } 9 | 10 | public func resolve(nestedDependencyResolver: DependencyResolver) throws -> T { 11 | guard let dependencyResolver = dependencyResolver else { 12 | throw DiError("Failed to resolve dependency: DependencyResolver has been deallocated.") 13 | } 14 | 15 | return try dependencyResolver.resolve(nestedDependencyResolver: nestedDependencyResolver) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/PathLinker/PathLinker.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol PathLinker { 4 | func symLink( 5 | source: AbsolutePath, 6 | destination: AbsolutePath, 7 | overwrite: Bool, 8 | ensureDirectoryExists: Bool 9 | ) throws 10 | } 11 | 12 | public extension PathLinker { 13 | func symLink( 14 | source: AbsolutePath, 15 | destination: AbsolutePath, 16 | overwrite: Bool = true, 17 | ensureDirectoryExists: Bool = true 18 | ) throws { 19 | try symLink( 20 | source: source, 21 | destination: destination, 22 | overwrite: overwrite, 23 | ensureDirectoryExists: overwrite 24 | ) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/PathCopier/PathCopier.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol PathCopier { 4 | func copy( 5 | source: AbsolutePath, 6 | destination: AbsolutePath, 7 | overwrite: Bool, 8 | ensureDirectoryExists: Bool 9 | ) throws 10 | } 11 | 12 | extension PathCopier { 13 | public func copy( 14 | source: AbsolutePath, 15 | destination: AbsolutePath, 16 | overwrite: Bool = true, 17 | ensureDirectoryExists: Bool = true 18 | ) throws { 19 | try copy( 20 | source: source, 21 | destination: destination, 22 | overwrite: overwrite, 23 | ensureDirectoryExists: ensureDirectoryExists 24 | ) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/Properties/DefaultFileSystemPropertiesContainer.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | public final class DefaultFileSystemPropertiesContainer: FileSystemPropertiesContainer { 5 | private let path: AbsolutePath 6 | public init(path: AbsolutePath) { 7 | self.path = path 8 | } 9 | 10 | public func systemFreeSize() throws -> Int64 { 11 | let attributes = try FileManager().attributesOfFileSystem(forPath: path.pathString) 12 | guard let value = attributes[.systemFreeSize], let number = value as? NSNumber else { 13 | throw FilePropertiesContainerError.emptyFileAttributeValue(path: path, key: .systemFreeSize) 14 | } 15 | return number.int64Value 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/MetricsRecording/MetricRecorder.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Graphite 3 | import Statsd 4 | 5 | public protocol MetricRecorder { 6 | func capture(_ metric: GraphiteMetric) 7 | func capture(_ metric: StatsdMetric) 8 | func tearDown(timeout: TimeInterval) 9 | } 10 | 11 | extension MetricRecorder { 12 | public func capture(_ metrics: [GraphiteMetric]) { 13 | metrics.forEach(capture) 14 | } 15 | 16 | public func capture(_ metrics: [StatsdMetric]) { 17 | metrics.forEach(capture) 18 | } 19 | 20 | public func capture(_ metrics: GraphiteMetric...) { 21 | capture(metrics) 22 | } 23 | 24 | public func capture(_ metrics: StatsdMetric...) { 25 | capture(metrics) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/Types/ThrowingProperty/SettableThrowingPropertyOf.swift: -------------------------------------------------------------------------------- 1 | open class SettableThrowingPropertyOf: SettableThrowingProperty { 2 | public typealias PropertyType = T 3 | 4 | private let setter: (PropertyType) throws -> () 5 | 6 | public init( 7 | setter: @escaping (PropertyType) throws -> () 8 | ) { 9 | self.setter = setter 10 | } 11 | 12 | public convenience init( 13 | throwingProperty: Other 14 | ) where Other.PropertyType == PropertyType { 15 | self.init( 16 | setter: { try throwingProperty.set($0) } 17 | ) 18 | } 19 | 20 | public func set(_ value: PropertyType) throws { 21 | try setter(value) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/Console/Utils/String+Symbols.swift: -------------------------------------------------------------------------------- 1 | extension String { 2 | static let noBlockSymbol: Self = "╶" 3 | static let blockStartSymbol: Self = "╭" 4 | static let blockBorderSymbol: Self = "│" 5 | static let blockBorderJunction: Self = "├" 6 | static let blockEndSymbol: Self = "╰" 7 | static let blockHorizontalBorder: Self = "─" 8 | static let dashSpacerSymbol: Self = "⸱" 9 | static let spaceSpacerSymbol: Self = " " 10 | static let successSymbol: Self = "✔" 11 | static let failureSymbol: Self = "✘" 12 | static let cancelSymbol: Self = "⛔︎" 13 | static let activeSymbol: Self = "▶" 14 | static let inputSymbol: Self = "❯" 15 | static let selectedSymbol: Self = "●" 16 | static let unselectedSymbol: Self = "○" 17 | } 18 | -------------------------------------------------------------------------------- /Tests/GraphiteTestHelpers/GraphiteClient.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Graphite 3 | 4 | open class FakeGraphiteMetricHandler: GraphiteMetricHandler { 5 | public var handleClosure: (GraphiteMetric) -> () 6 | public var tearDownClosure: (TimeInterval) -> () 7 | 8 | public init( 9 | handleClosure: @escaping (GraphiteMetric) -> () = { _ in }, 10 | tearDownClosure: @escaping (TimeInterval) -> () = { _ in } 11 | ) { 12 | self.handleClosure = handleClosure 13 | self.tearDownClosure = tearDownClosure 14 | } 15 | 16 | public func handle(metric: GraphiteMetric) { 17 | handleClosure(metric) 18 | } 19 | 20 | public func tearDown(timeout: TimeInterval) { 21 | tearDownClosure(timeout) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/RepoRoot/RepoRootProvider/RepoRootProviderFactoryImplementations/CachingRepoRootProviderFactory.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public final class CachingRepoRootProviderFactory: RepoRootProviderFactory { 4 | private let repoRootProviderFactory: RepoRootProviderFactory 5 | 6 | public init(repoRootProviderFactory: RepoRootProviderFactory) { 7 | self.repoRootProviderFactory = repoRootProviderFactory 8 | } 9 | 10 | public func repoRootProvider( 11 | anyPathWithinRepo: AbsolutePath 12 | ) -> RepoRootProvider { 13 | return CachingRepoRootProvider( 14 | repoRootProvider: repoRootProviderFactory.repoRootProvider( 15 | anyPathWithinRepo: anyPathWithinRepo 16 | ) 17 | ) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/DI/Modular/ModuleDependencies.swift: -------------------------------------------------------------------------------- 1 | public protocol ModuleDependencies: CurrentModuleDependenciesRegisterer, OtherModuleDependenciesProvider { 2 | var identifier: AnyHashable { get } 3 | } 4 | 5 | public protocol CurrentModuleDependenciesRegisterer { 6 | func registerDependenciesOfCurrentModule(di: DependencyRegisterer) 7 | } 8 | 9 | public protocol OtherModuleDependenciesProvider { 10 | func otherModulesDependecies() -> [ModuleDependencies] 11 | } 12 | 13 | extension ModuleDependencies { 14 | public var identifier: AnyHashable { 15 | return HashableType(type: type(of: self)) 16 | } 17 | } 18 | 19 | extension OtherModuleDependenciesProvider { 20 | public func otherModulesDependecies() -> [ModuleDependencies] { 21 | return [] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Tests/CLTExtensionsTests/String+UTF8Tests.swift: -------------------------------------------------------------------------------- 1 | import CLTExtensions 2 | import Foundation 3 | import XCTest 4 | 5 | final class StringUTF8Tests: XCTestCase { 6 | func test___initializing___with_utf8_bytes_sequence___is_successful() throws { 7 | try XCTAssertEqual( 8 | String(utf8Data: Data([0xf0, 0x9f, 0x98, 0x80])), 9 | "😀" 10 | ) 11 | } 12 | 13 | func test___initializing___bogus_bytes_sequence___throws_error() throws { 14 | var error: Error? 15 | try XCTAssertThrowsError( 16 | String(utf8Data: Data([0x01, 0x9f, 0x98, 0x80])) 17 | ) { error = $0 } 18 | XCTAssertEqual( 19 | error.map { String(describing: $0) }, 20 | "Bytes AZ+YgA== are not utf8" 21 | ) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /PackageGenerator/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.9 2 | import PackageDescription 3 | let package = Package( 4 | name: "PackageGenerator", 5 | platforms: [ 6 | .macOS(.v10_15), 7 | ], 8 | products: [ 9 | .executable(name: "package-gen", targets: ["Bin"]), 10 | ], 11 | targets: [ 12 | .executableTarget( 13 | name: "Bin", 14 | dependencies: ["PackageGenerator"] 15 | ), 16 | .target( 17 | name: "PackageGenerator", 18 | linkerSettings: [.unsafeFlags([])] 19 | ), 20 | .testTarget( 21 | name: "PackageGeneratorTests", 22 | dependencies: [ 23 | "PackageGenerator", 24 | ] 25 | ), 26 | ], 27 | swiftLanguageVersions: [.v5] 28 | ) 29 | -------------------------------------------------------------------------------- /Sources/FileSystem/File/WorkingWithContents/DataWriter/DataWriterImpl.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | public final class DataWriterImpl: DataWriter { 5 | private let directoryCreator: DirectoryCreator 6 | 7 | public init( 8 | directoryCreator: DirectoryCreator 9 | ) { 10 | self.directoryCreator = directoryCreator 11 | } 12 | 13 | public func write( 14 | data: Data, 15 | filePath: AbsolutePath, 16 | ensureDirectoryExists: Bool 17 | ) throws { 18 | if ensureDirectoryExists { 19 | try directoryCreator.ensureDirectoryExists( 20 | path: filePath.removingLastComponent 21 | ) 22 | } 23 | 24 | try data.write(to: filePath.fileUrl, options: .atomic) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/Environment/DI/EnvironmentModuleDependencies.swift: -------------------------------------------------------------------------------- 1 | import DI 2 | import Foundation 3 | 4 | public final class EnvironmentModuleDependencies: ModuleDependencies { 5 | public init() { 6 | } 7 | 8 | public func registerDependenciesOfCurrentModule(di: DependencyRegisterer) { 9 | di.register(type: ProcessInfo.self) { _ in 10 | ProcessInfo.processInfo 11 | } 12 | di.register(type: CurrentExecutableProvider.self) { di in 13 | try ProcessInfoCurrentExecutableProvider( 14 | processInfo: di.resolve() 15 | ) 16 | } 17 | di.register(type: EnvironmentProvider.self) { di in 18 | try ProcessInfoEnvironmentProvider( 19 | processInfo: di.resolve() 20 | ) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Tests/FileSystemTests/DeepFileSystemEnumeratorTests.swift: -------------------------------------------------------------------------------- 1 | import FileSystem 2 | import Foundation 3 | import PathLib 4 | import TestHelpers 5 | import TmpTestHelpers 6 | import XCTest 7 | 8 | final class DeepFileSystemEnumeratorTests: XCTestCase { 9 | private lazy var tempFolder = createTempFolder() 10 | 11 | func test___enumerating___complete() throws { 12 | let expectedPaths = try createTestDataForEnumeration(tempFolder: tempFolder) 13 | 14 | let enumerator = DeepFileSystemEnumerator( 15 | path: tempFolder.absolutePath 16 | ) 17 | 18 | var paths = Set() 19 | try enumerator.each { (path: AbsolutePath) in 20 | paths.insert(path) 21 | } 22 | 23 | XCTAssertEqual(expectedPaths, paths) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/FileToucher/FileToucherImpl.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public final class FileToucherImpl: FileToucher { 4 | private let filePropertiesProvider: FilePropertiesProvider 5 | private let fileCreator: FileCreator 6 | 7 | public init( 8 | filePropertiesProvider: FilePropertiesProvider, 9 | fileCreator: FileCreator 10 | ) { 11 | self.filePropertiesProvider = filePropertiesProvider 12 | self.fileCreator = fileCreator 13 | } 14 | 15 | public func touch(path: AbsolutePath) throws { 16 | if filePropertiesProvider.existence(path: path).exists { 17 | try filePropertiesProvider.properties(path: path).touch() 18 | } else { 19 | try fileCreator.createFile(path: path, data: nil) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/DirectoryCreator/DirectoryCreator.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol DirectoryCreator { 4 | func createDirectory( 5 | path: AbsolutePath, 6 | withIntermediateDirectories: Bool 7 | ) throws 8 | } 9 | 10 | extension DirectoryCreator { 11 | public func createDirectory( 12 | path: AbsolutePath, 13 | withIntermediateDirectories: Bool = true 14 | ) throws { 15 | try createDirectory( 16 | path: path, 17 | withIntermediateDirectories: withIntermediateDirectories 18 | ) 19 | } 20 | 21 | public func ensureDirectoryExists( 22 | path: AbsolutePath 23 | ) throws { 24 | try createDirectory( 25 | path: path, 26 | withIntermediateDirectories: true 27 | ) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Tests/StatsdTests/FakeStatsdClient.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Statsd 3 | 4 | final class FakeStatsdClient: StatsdClient { 5 | var sentData: [Data] = [] 6 | 7 | init() { 8 | 9 | } 10 | 11 | var onTearDown: (DispatchQueue, TimeInterval, @escaping () -> ()) -> () = { queue, _, callback in 12 | queue.async { 13 | callback() 14 | } 15 | } 16 | 17 | func tearDown(queue: DispatchQueue, timeout: TimeInterval, completion: @escaping () -> ()) { 18 | onTearDown(queue, timeout, completion) 19 | } 20 | 21 | var onSend: (Data, @escaping (Error?) -> ()) -> () = { $1(nil) } 22 | 23 | func send(content: Data, queue: DispatchQueue, completion: @escaping (Error?) -> ()) { 24 | sentData.append(content) 25 | onSend(content, completion) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/CLTLogging/RedirectingLoggerHandler.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import AtomicModels 6 | import CLTLoggingModels 7 | import Foundation 8 | 9 | public final class RedirectingLoggerHandler: LoggerHandler { 10 | private let target: AtomicValue 11 | 12 | public init( 13 | target: LoggerHandler = NoOpLoggerHandler() 14 | ) { 15 | self.target = AtomicValue(target) 16 | } 17 | 18 | public func setTarget(_ newTarget: LoggerHandler) { 19 | target.set(newTarget) 20 | } 21 | 22 | public func handle(logEntry: LogEntry) { 23 | target.currentValue().handle(logEntry: logEntry) 24 | } 25 | 26 | public func tearDownLogging(timeout: TimeInterval) { 27 | target.currentValue().tearDownLogging(timeout: timeout) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/PathMover/PathMover.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | public protocol PathMover { 4 | /// Moves `source` file to `destination` if `destination` it doesn't exist, throws otherwise 5 | func move( 6 | source: AbsolutePath, 7 | destination: AbsolutePath, 8 | overwrite: Bool, 9 | ensureDirectoryExists: Bool 10 | ) throws 11 | } 12 | 13 | extension PathMover { 14 | public func move( 15 | source: AbsolutePath, 16 | destination: AbsolutePath, 17 | overwrite: Bool = true, 18 | ensureDirectoryExists: Bool = true 19 | ) throws { 20 | try move( 21 | source: source, 22 | destination: destination, 23 | overwrite: overwrite, 24 | ensureDirectoryExists: ensureDirectoryExists 25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/MutualTLS/DI/MutualTLSModuleDependencies.swift: -------------------------------------------------------------------------------- 1 | #if os(macOS) 2 | import DI 3 | import ProcessController 4 | import Environment 5 | 6 | public final class MutualTLSModuleDependencies: ModuleDependencies { 7 | public init() { 8 | } 9 | 10 | public func otherModulesDependecies() -> [ModuleDependencies] { 11 | [ 12 | ProcessControllerModuleDependencies(), 13 | EnvironmentModuleDependencies(), 14 | ] 15 | } 16 | 17 | public func registerDependenciesOfCurrentModule(di: DependencyRegisterer) { 18 | di.register(type: MutualTLSCredentialProvider.self) { di in 19 | try MutualTLSCredentialProviderImpl( 20 | processControllerProvider: di.resolve(), 21 | environmentProvider: di.resolve() 22 | ) 23 | } 24 | } 25 | } 26 | #endif 27 | -------------------------------------------------------------------------------- /Tests/StatsdTests/StatsdMetricTests.swift: -------------------------------------------------------------------------------- 1 | import MetricsRecording 2 | import Statsd 3 | import XCTest 4 | 5 | final class StatsdMetricTests: XCTestCase { 6 | func test___building___for_gauge() { 7 | XCTAssertEqual( 8 | StatsdMetric( 9 | fixedComponents: ["c", "d"], 10 | variableComponents: ["e", "f"], 11 | value: .gauge(1) 12 | ).build(domain: ["a", "b"]), 13 | "a.b.c.d.e.f:1|g" 14 | ) 15 | } 16 | 17 | func test___building___for_time() { 18 | XCTAssertEqual( 19 | StatsdMetric( 20 | fixedComponents: ["c", "d"], 21 | variableComponents: ["e", "f"], 22 | value: .time(1) 23 | ).build(domain: ["a", "b"]), 24 | "a.b.c.d.e.f:1000|ms" 25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/RepoRoot/RepoRootProvider/RepoRootProviderImplementations/CachingRepoRootProvider.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | import Foundation 3 | 4 | public final class CachingRepoRootProvider: RepoRootProvider { 5 | private let repoRootProvider: RepoRootProvider 6 | private var cachedValue: AbsolutePath? 7 | private let lock = NSLock() 8 | 9 | public init(repoRootProvider: RepoRootProvider) { 10 | self.repoRootProvider = repoRootProvider 11 | } 12 | 13 | public func repoRoot() throws -> AbsolutePath { 14 | lock.lock() 15 | defer { lock.unlock() } 16 | 17 | if let cachedValue = cachedValue { 18 | return cachedValue 19 | } else { 20 | let value = try repoRootProvider.repoRoot() 21 | self.cachedValue = value 22 | return value 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/CLTLoggingModels/LoggableDate.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | public final class LoggableDate: CustomStringConvertible { 8 | private let date: Date 9 | private let dateFormatter: DateFormatter 10 | 11 | public init( 12 | _ date: Date, 13 | dateFormatter: DateFormatter = NSLogLikeLogEntryTextFormatter.logDateFormatter 14 | ) { 15 | self.date = date 16 | self.dateFormatter = dateFormatter 17 | } 18 | 19 | public var description: String { 20 | dateFormatter.string(from: date) 21 | } 22 | } 23 | 24 | extension Date { 25 | public func loggable( 26 | dateFormatter: DateFormatter = NSLogLikeLogEntryTextFormatter.logDateFormatter 27 | ) -> LoggableDate { 28 | LoggableDate(self, dateFormatter: dateFormatter) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Tests/TestHelpers/XCTestCase+XCTAssertEqualSorted.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | 4 | public extension XCTestCase { 5 | func XCTAssertEqualSorted( 6 | _ expression1: @autoclosure () throws -> [T], 7 | _ expression2: @autoclosure () throws -> [T], 8 | by keyPath: KeyPath, 9 | _ message: @autoclosure () -> String = "", 10 | file: StaticString = #filePath, 11 | line: UInt = #line 12 | ) rethrows { 13 | let array1 = try expression1().sorted { lhs, rhs in 14 | lhs[keyPath: keyPath] < rhs[keyPath: keyPath] 15 | } 16 | let array2 = try expression2().sorted { lhs, rhs in 17 | lhs[keyPath: keyPath] < rhs[keyPath: keyPath] 18 | } 19 | XCTAssertEqual(array1, array2, message(), file: file, line: line) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Sources/CLTLoggingModels/LoggableDouble.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | 7 | public final class LoggableDouble: CustomStringConvertible { 8 | private let value: Double 9 | private let suffix: String 10 | 11 | public init(_ value: Double, suffix: String) { 12 | self.value = value 13 | self.suffix = suffix 14 | } 15 | 16 | public var description: String { 17 | let string = String(format: "%.3f", value) 18 | return [string, suffix].filter { !$0.isEmpty }.joined(separator: " ") 19 | } 20 | } 21 | 22 | extension TimeInterval { 23 | public func loggableInSeconds() -> LoggableDouble { 24 | loggable(suffix: "sec") 25 | } 26 | 27 | public func loggable(suffix: String) -> LoggableDouble { 28 | LoggableDouble(self, suffix: suffix) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Sources/Concurrency/ThrowingThreadSafeLazy.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | public final class ThrowingThreadSafeLazy { 5 | private let threadSafeLazy: ThreadSafeLazy> 6 | 7 | public init(factory: @escaping () throws -> T) { 8 | self.threadSafeLazy = ThreadSafeLazy { 9 | do { 10 | return .success(try factory()) 11 | } catch { 12 | return .failure(error) 13 | } 14 | } 15 | } 16 | 17 | public var value: T { 18 | get throws { 19 | let value = try threadSafeLazy.value 20 | 21 | switch value { 22 | case .success(let success): 23 | return success 24 | case .failure(let error): 25 | throw error 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/CLTLogging/LimitingLoggerHandler.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import CLTLoggingModels 6 | import Foundation 7 | 8 | public final class LimitingLoggerHandler: LoggerHandler { 9 | private let maximumVerbosity: Verbosity 10 | private let target: LoggerHandler 11 | 12 | public init( 13 | maximumVerbosity: Verbosity, 14 | target: LoggerHandler 15 | ) { 16 | self.maximumVerbosity = maximumVerbosity 17 | self.target = target 18 | } 19 | 20 | public func handle(logEntry: LogEntry) { 21 | guard maximumVerbosity.allowsLoggingWthVerbosity(logEntry.verbosity) else { return } 22 | 23 | target.handle(logEntry: logEntry) 24 | } 25 | 26 | public func tearDownLogging(timeout: TimeInterval) { 27 | target.tearDownLogging(timeout: timeout) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/Console/ANSIConsoleHandler/Log/LogComponent.swift: -------------------------------------------------------------------------------- 1 | import Logging 2 | 3 | struct LogComponent: ConsoleComponent { 4 | let state: LogComponentState 5 | var result: Result? { .success(()) } 6 | 7 | var isVisible: Bool { 8 | let verbositySettings = ConsoleContext.current.verbositySettings 9 | return verbositySettings.verbose || state.level >= verbositySettings.logLevel 10 | } 11 | 12 | func canBeCollapsed(at level: Logger.Level) -> Bool { 13 | let verbositySettings = ConsoleContext.current.verbositySettings 14 | return !verbositySettings.verbose && state.level <= level 15 | } 16 | 17 | func handle(event: ConsoleControlEvent) { 18 | } 19 | 20 | func renderer() -> some Renderer { 21 | LogComponentRenderer() 22 | .withCache() 23 | .withState(state: state) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/Console/ANSIConsoleHandler/LogStream/ANSIConsoleHandler+LogStream.swift: -------------------------------------------------------------------------------- 1 | import Logging 2 | 3 | extension ANSIConsoleHandler { 4 | public func logStream( 5 | level: Logger.Level, 6 | name: String, 7 | renderTail: Int, 8 | file: StaticString, 9 | line: UInt 10 | ) -> LogSink { 11 | guard isInteractive, let activeContainer = ConsoleContext.current.activeContainer else { 12 | return LogHandlerSink( 13 | level: level, 14 | logHandler: ConsoleLogHandler(handler: self, label: name) 15 | ) 16 | } 17 | 18 | let component = LogStreamComponent(state: .init(level: level, name: name, renderTail: renderTail)) 19 | 20 | let sink = ComponentLogSink(component: component) 21 | 22 | activeContainer.add(child: component) 23 | 24 | return sink 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/Console/TrackingConsoleHandler/ConsoleActionStorage.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public final actor ConsoleActionStorage { 4 | @TaskLocal public static var current: ConsoleActionStorage = .init() 5 | 6 | public enum Action { 7 | case input(id: String, result: Result) 8 | case question(id: String, result: Result) 9 | case select(id: String, result: Result<[String], Error>) 10 | case trace( 11 | id: String, 12 | start: TraceClock.Instant, 13 | duration: TraceClock.Duration, 14 | actions: [Action], 15 | metadata: [String: TraceMetadataValue], 16 | result: Result 17 | ) 18 | } 19 | 20 | public private(set) var actions: [Action] = [] 21 | 22 | func add(action: Action) { 23 | actions.append(action) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /PackageGenerator/Sources/PackageGenerator/Statements/SwiftSetting+Statement.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension SwiftSettings { 4 | var statements: [String] { 5 | map(\.statement) 6 | } 7 | } 8 | 9 | extension SwiftSetting { 10 | var statement: String { 11 | switch self { 12 | case let .define(name: name): 13 | #".define("\#(name)")"# 14 | case let .unsafeFlags(flags: flags): 15 | #".unsafeFlags([\#(flags.map({ "\"\($0)\"" }).joined(separator: ", "))])"# 16 | case let .enableExperimentalFeature(name: name): 17 | #".enableExperimentalFeature("\#(name)")"# 18 | case let .enableUpcomingFeature(name: name): 19 | #".enableUpcomingFeature("\#(name)")"# 20 | case let .interoperabilityMode(mode: mode): 21 | #".interoperabilityMode(.\#(mode.rawValue))"# 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/RepoRoot/RepoRootProvider/RepoRootProviderImplementations/WorkdirRepoRootProvider.swift: -------------------------------------------------------------------------------- 1 | import Environment 2 | import PathLib 3 | import FileSystem 4 | 5 | // When executable is inside repo or program is running from Xcode 6 | // and sources are in repo 7 | public final class WorkdirRepoRootProvider: RepoRootProvider { 8 | private let repoRootProviderFactory: RepoRootProviderFactory 9 | private let fileSystem: FileSystem 10 | 11 | public init( 12 | repoRootProviderFactory: RepoRootProviderFactory, 13 | fileSystem: FileSystem 14 | ) { 15 | self.repoRootProviderFactory = repoRootProviderFactory 16 | self.fileSystem = fileSystem 17 | } 18 | 19 | public func repoRoot() throws -> AbsolutePath { 20 | try repoRootProviderFactory.repoRoot( 21 | anyPathWithinRepo: fileSystem.currentWorkingDirectory 22 | ) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/FileSystem/File/WorkingWithContents/FileReader/FileReaderImpl.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | public final class FileReaderImpl: FileReader { 5 | public enum Errors: Error, CustomStringConvertible { 6 | case noContent(filePath: AbsolutePath) 7 | 8 | public var description: String { 9 | switch self { 10 | case let .noContent(filePath): 11 | return "Content not found for file at \(filePath)" 12 | } 13 | } 14 | } 15 | 16 | private let fileManager = FileManager() 17 | 18 | public init() { 19 | } 20 | 21 | public func contents(filePath: AbsolutePath) throws -> Data { 22 | guard let content = fileManager.contents(atPath: filePath.pathString) else { 23 | throw Errors.noContent(filePath: filePath) 24 | } 25 | return content 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/UserDefaultsLib/Defaults.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PlistLib 3 | 4 | /// NSUserDefaults allows to store plist entities (NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary). 5 | /// That's why `Defaults` uses `PlistEntry` objects in its API. 6 | public protocol Defaults { 7 | 8 | /// Returns plist object for a given key, or nil. 9 | /// - Parameter key: defaults key 10 | func entryForKey(_ key: String) throws -> PlistEntry? 11 | 12 | /// Stores plist object under a given key. 13 | /// - Parameters: 14 | /// - entry: plist object to set under the given key. If entry is `nil`, object for the given key will be deleted. 15 | /// - key: defaults key 16 | func set(entry: PlistEntry?, key: String) 17 | 18 | /// Removes an stored object for a given key 19 | /// - Parameter key: defaults key 20 | func removeEntryForKey(_ key: String) 21 | } 22 | -------------------------------------------------------------------------------- /Sources/PlistLib/RootPlistEntry.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// This is a plist root object. Plists may have only an array or dict as their root objects. 4 | public enum RootPlistEntry: CustomStringConvertible, Equatable { 5 | case array([PlistEntry]) 6 | case dict([String: PlistEntry]) 7 | 8 | /// Provides `PlistEntry` from this root object, this should be used to query plist. 9 | public var plistEntry: PlistEntry { 10 | switch self { 11 | case .array(let value): 12 | return .array(value) 13 | case .dict(let value): 14 | return .dict(value) 15 | } 16 | } 17 | 18 | public var description: String { 19 | switch self { 20 | case .array(let element): 21 | return "" 22 | case .dict(let element): 23 | return "" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/RepoRoot/RepoRootProvider/RepoRootProviderFactoryImplementations/MarkerFileRepoRootProviderFactory.swift: -------------------------------------------------------------------------------- 1 | import FileSystem 2 | import PathLib 3 | 4 | public final class MarkerFileRepoRootProviderFactory: RepoRootProviderFactory { 5 | private let fileExistenceChecker: FileExistenceChecker 6 | private let markerFileName: String 7 | 8 | public init( 9 | fileExistenceChecker: FileExistenceChecker, 10 | markerFileName: String 11 | ) { 12 | self.fileExistenceChecker = fileExistenceChecker 13 | self.markerFileName = markerFileName 14 | } 15 | 16 | public func repoRootProvider(anyPathWithinRepo: AbsolutePath) -> RepoRootProvider { 17 | MarkerFileRepoRootProvider( 18 | fileExistenceChecker: fileExistenceChecker, 19 | markerFileName: markerFileName, 20 | anyPathWithinRepo: anyPathWithinRepo 21 | ) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/CLTExtensions/Casting.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct FailedCast: Error, CustomStringConvertible { 4 | public let value: Any? 5 | 6 | public var description: String { 7 | "Can't cast value \(value ?? "nil") of type \(type(of: value)) to type \(T.self)" 8 | } 9 | } 10 | 11 | public func cast( 12 | value: Any, 13 | to targetType: T.Type 14 | ) throws -> T { 15 | guard let castedValue = value as? T else { 16 | throw FailedCast(value: value) 17 | } 18 | return castedValue 19 | } 20 | 21 | public func cast( 22 | optionalValue: V?, 23 | to targetType: T.Type 24 | ) throws -> T { 25 | if let value = optionalValue { 26 | return try cast(value: value, to: T.self) 27 | } 28 | throw FailedCast(value: nil) 29 | } 30 | 31 | public func cast(value: Any) throws -> T { 32 | return try cast(value: value, to: T.self) 33 | } 34 | -------------------------------------------------------------------------------- /Sources/Environment/CurrentExecutableProvider/ProcessInfoCurrentExecutableProvider.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import CLTExtensions 3 | import PathLib 4 | 5 | public final class ProcessInfoCurrentExecutableProvider: CurrentExecutableProvider { 6 | private let processInfo: ProcessInfo 7 | 8 | public init(processInfo: ProcessInfo) { 9 | self.processInfo = processInfo 10 | } 11 | 12 | public func currentExecutablePath() throws -> AbsolutePath { 13 | let path = try processInfo.arguments.first.unwrapOrThrow( 14 | message: "processInfo's arguments list is empty" 15 | ) 16 | 17 | if AbsolutePath.isAbsolute(path: path) { 18 | return AbsolutePath(path) 19 | } else { 20 | return AbsolutePath(FileManager().currentDirectoryPath).appending( 21 | relativePath: RelativePath(path) 22 | ) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/SynchronousWaiter/Timeout.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct Timeout: CustomStringConvertible { 4 | public let description: String 5 | public let value: TimeInterval 6 | 7 | public init(description: String, value: TimeInterval) { 8 | self.description = description 9 | self.value = value 10 | } 11 | 12 | public static var infinity: Timeout { 13 | return Timeout(description: "Infinite wait will never timeout", value: .infinity) 14 | } 15 | } 16 | 17 | public enum TimeoutError: Error, CustomStringConvertible { 18 | case waitTimeout(Timeout) 19 | 20 | public var description: String { 21 | switch self { 22 | case .waitTimeout(let timeout): 23 | let rounded = (timeout.value * 1000.0).rounded() / 1000.0 24 | return "Waiter reached timeout of \(rounded) s for '\(timeout.description)' operation" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/DI/DependencyRegisterer/DependencyRegisterer+RegisterMultiple.swift: -------------------------------------------------------------------------------- 1 | extension DependencyRegisterer { 2 | // Usage: 3 | // 4 | // ``` 5 | // di.registerMultiple { _ in RecordedAssertionFailuresHolder() } 6 | // .reregister { $0 as AssertionFailureRecorder } 7 | // .reregister { $0 as RecordedAssertionFailuresProvider } 8 | // ``` 9 | // 10 | public func registerMultiple( 11 | scope: Scope = .single, 12 | type: T.Type = T.self, 13 | factory: @escaping (DependencyResolver) throws -> T) 14 | -> MultipleDependenciesRegistrationContinuation 15 | { 16 | register( 17 | scope: scope, 18 | type: type, 19 | factory: factory 20 | ) 21 | 22 | return MultipleDependenciesRegistrationContinuation( 23 | dependencyRegisterer: self, 24 | scope: scope 25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/ProcessController/DefaultProcessControllerProvider.swift: -------------------------------------------------------------------------------- 1 | import DateProvider 2 | import Foundation 3 | import FileSystem 4 | import PathLib 5 | 6 | public final class DefaultProcessControllerProvider: ProcessControllerProvider { 7 | private let dateProvider: DateProvider 8 | private let filePropertiesProvider: FilePropertiesProvider 9 | 10 | public init( 11 | dateProvider: DateProvider, 12 | filePropertiesProvider: FilePropertiesProvider 13 | ) { 14 | self.dateProvider = dateProvider 15 | self.filePropertiesProvider = filePropertiesProvider 16 | } 17 | 18 | public func createProcessController(subprocess: Subprocess) throws -> ProcessController { 19 | return try DefaultProcessController( 20 | dateProvider: dateProvider, 21 | filePropertiesProvider: filePropertiesProvider, 22 | subprocess: subprocess 23 | ) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/Console/ANSIConsoleHandler/LogStream/LogStreamComponentState.swift: -------------------------------------------------------------------------------- 1 | import Logging 2 | 3 | public struct LogStreamError: Error { 4 | public var statusCode: Int32 5 | 6 | public init(statusCode: Int32) { 7 | self.statusCode = statusCode 8 | } 9 | } 10 | 11 | struct LogStreamComponentState { 12 | var level: Logger.Level 13 | let name: String 14 | var renderTail: Int = 1 15 | var lines: [String] = [] 16 | var result: Result? 17 | var isCancelled: Bool = false 18 | var frame: Int = 0 19 | var frames: [String] = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"] 20 | 21 | var isFinished: Bool { 22 | result != nil 23 | } 24 | 25 | var isSuccess: Bool { 26 | if case .success = result { true } else { false } 27 | } 28 | 29 | var isFailure: Bool { 30 | if case .failure = result { true } else { false } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/ProcessController/DI/ProcessControllerDependencies.swift: -------------------------------------------------------------------------------- 1 | import DI 2 | import FileSystem 3 | import DateProvider 4 | 5 | public final class ProcessControllerModuleDependencies: ModuleDependencies { 6 | public init() { 7 | } 8 | 9 | public func otherModulesDependecies() -> [ModuleDependencies] { 10 | [ 11 | DateProviderModuleDependencies(), 12 | FileSystemModuleDependencies() 13 | ] 14 | } 15 | 16 | public func registerDependenciesOfCurrentModule(di: DependencyRegisterer) { 17 | di.register(type: ProcessControllerProvider.self) { di in 18 | try DefaultProcessControllerProvider( 19 | dateProvider: di.resolve(), 20 | filePropertiesProvider: di.resolve() 21 | ) 22 | } 23 | di.register(type: BashEscapedCommandMaker.self) { _ in 24 | BashEscapedCommandMakerImpl() 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Tests/FileSystemTests/ShallowFileSystemEnumeratorTests.swift: -------------------------------------------------------------------------------- 1 | import FileSystem 2 | import PathLib 3 | import TestHelpers 4 | import Tmp 5 | import XCTest 6 | 7 | final class ShallowFileSystemEnumeratorTests: XCTestCase { 8 | private lazy var tempFolder = assertDoesNotThrow { try TemporaryFolder(deleteOnDealloc: true) } 9 | 10 | func test___enumerating___complete() throws { 11 | let expectedPaths = try createTestDataForEnumeration(tempFolder: tempFolder).filter { 12 | $0.components.count == tempFolder.absolutePath.components.count + 1 13 | } 14 | 15 | let enumerator = ShallowFileSystemEnumerator( 16 | path: tempFolder.absolutePath 17 | ) 18 | 19 | var paths = Set() 20 | try enumerator.each { (path: AbsolutePath) in 21 | paths.insert(path) 22 | } 23 | 24 | XCTAssertEqual(expectedPaths, paths) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/Tmp/TempErrors.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | public enum ErrnoError: Error, CustomStringConvertible { 5 | case failedToCreateTemporaryFolder(AbsolutePath, code: Int32) 6 | case failedToCreateTemporaryFile(AbsolutePath, code: Int32) 7 | 8 | public var description: String { 9 | switch self { 10 | case let .failedToCreateTemporaryFolder(template, code): 11 | return "Failed to create temporary directory with template \(template), error code: \(code)" 12 | case let .failedToCreateTemporaryFile(template, code): 13 | return "Failed to create temporary file with template \(template), error code: \(code)" 14 | } 15 | } 16 | } 17 | 18 | public struct UnknownCanonicalPath: Error, CustomStringConvertible { 19 | let path: String 20 | 21 | public var description: String { 22 | return "Failed to determine canonical path for \(path)" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Tests/CLTLoggingTests/AggregatedLoggerHandlerTests.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | import CLTLogging 7 | import CLTLoggingModels 8 | import CLTLoggingTestHelpers 9 | import XCTest 10 | 11 | final class AggregatedLoggerHandlerTests: XCTestCase { 12 | func test() { 13 | let handler1 = FakeLoggerHandle() 14 | let handler2 = FakeLoggerHandle() 15 | let aggregatedHandler = AggregatedLoggerHandler(handlers: [handler1, handler2]) 16 | 17 | let logEntry = LogEntry( 18 | file: "file", 19 | line: 42, 20 | coordinates: [], 21 | message: "", 22 | timestamp: Date(), 23 | verbosity: .always 24 | ) 25 | aggregatedHandler.handle(logEntry: logEntry) 26 | 27 | XCTAssertEqual(handler1.logEntries, [logEntry]) 28 | XCTAssertEqual(handler2.logEntries, [logEntry]) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Sources/ProcessController/EnvironmentValue.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol EnvironmentValue: CustomStringConvertible { 4 | var value: String { get } 5 | } 6 | 7 | extension String: EnvironmentValue { 8 | public var value: String { self } 9 | } 10 | 11 | extension Int: EnvironmentValue { 12 | public var value: String { "\(self)" } 13 | } 14 | 15 | public struct SecureEnvironmentValue: EnvironmentValue { 16 | private let environmentValue: EnvironmentValue 17 | 18 | public init(environmentValue: EnvironmentValue) { 19 | self.environmentValue = environmentValue 20 | } 21 | 22 | public var value: String { 23 | environmentValue.value 24 | } 25 | 26 | public var description: String { 27 | "" 28 | } 29 | } 30 | 31 | extension EnvironmentValue { 32 | public var secured: EnvironmentValue { 33 | return SecureEnvironmentValue(environmentValue: self) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Tests/ImagesTestHelpers/Mocks/ImageParserMock.swift: -------------------------------------------------------------------------------- 1 | import ImagesInterfaces 2 | import PathLib 3 | 4 | public final class ImageParserMock: ImageParser { 5 | 6 | public var inputSourcePath: AbsolutePath? 7 | public var inputAssetsSourcePath: String? 8 | public var inputAssetsSourceAssetsPath: RelativePath? 9 | 10 | // swiftlint:disable implicitly_unwrapped_optional 11 | public var imageSourceResult: ImageSource! 12 | public var assetSourceResult: AbsolutePath! 13 | 14 | public init() {} 15 | 16 | public func imageSource(rootPath: AbsolutePath) throws -> ImageSource { 17 | inputSourcePath = rootPath 18 | return imageSourceResult 19 | } 20 | 21 | public func assetSource(consoleInput: String, assetsPath: RelativePath) throws -> AbsolutePath { 22 | inputAssetsSourcePath = consoleInput 23 | inputAssetsSourceAssetsPath = assetsPath 24 | return assetSourceResult 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/PathDeleter/PathDeleterImpl.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | import Foundation 3 | 4 | public final class PathDeleterImpl: PathDeleter { 5 | private let fileManager = FileManager() 6 | private let filePropertiesProvider: FilePropertiesProvider 7 | 8 | public init( 9 | filePropertiesProvider: FilePropertiesProvider 10 | ) { 11 | self.filePropertiesProvider = filePropertiesProvider 12 | } 13 | 14 | public func delete(path: AbsolutePath, ignoreMissing: Bool) throws { 15 | if ignoreMissing { 16 | if filePropertiesProvider.exists(path: path) { 17 | try delete(path: path) 18 | } else { 19 | // ignore 20 | } 21 | } else { 22 | try delete(path: path) 23 | } 24 | } 25 | 26 | private func delete(path: AbsolutePath) throws { 27 | try fileManager.removeItem(at: path.fileUrl) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Tests/FileSystemTests/DirectoryCreatorImplTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Foundation 3 | import FileSystem 4 | import TmpTestHelpers 5 | 6 | final class DirectoryCreatorImplTests: XCTestCase { 7 | private let fileManager = FileManager() 8 | private lazy var tempFolder = createTempFolder() 9 | private let directoryCreator = DirectoryCreatorImpl( 10 | filePropertiesProvider: FilePropertiesProviderImpl() 11 | ) 12 | 13 | func test___creating_directory() throws { 14 | let path = tempFolder.pathWith(components: ["new_folder"]) 15 | 16 | XCTAssertFalse(fileManager.fileExists(atPath: path.pathString)) 17 | try directoryCreator.createDirectory( 18 | path: path, 19 | withIntermediateDirectories: true 20 | ) 21 | 22 | var isDir: ObjCBool = false 23 | XCTAssertTrue(fileManager.fileExists(atPath: path.pathString, isDirectory: &isDir)) 24 | XCTAssertTrue(isDir.boolValue) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/Downloader/Downloader.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | public struct DownloadProgress { 5 | public let bytesCompleted: Int64 6 | public let bytesTotal: Int64 7 | public let bytesPerSecond: Double 8 | 9 | public var fraction: Double { 10 | Double(bytesCompleted) / Double(bytesTotal) 11 | } 12 | } 13 | 14 | public protocol Downloader { 15 | func download( 16 | url: URL, 17 | callbackQueue: DispatchQueue, 18 | progressHandler: @escaping (DownloadProgress) -> (), 19 | completion: @escaping (Result) -> () 20 | ) 21 | 22 | func download( 23 | url: URL, 24 | progressHandler: @escaping (DownloadProgress) -> () 25 | ) async -> Result 26 | } 27 | 28 | public extension Downloader { 29 | func download(url: URL) async -> Result { 30 | return await download(url: url, progressHandler: { _ in }) 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /Sources/PathLib/FileManager+Extensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension FileManager { 4 | func createDirectory( 5 | atPath path: AbsolutePath, 6 | withIntermediateDirectories: Bool = true, 7 | attributes: [FileAttributeKey: Any]? = nil 8 | ) throws { 9 | if !directoryExists(path: path) { 10 | try createDirectory( 11 | atPath: path.pathString, 12 | withIntermediateDirectories: withIntermediateDirectories, 13 | attributes: attributes 14 | ) 15 | } 16 | } 17 | 18 | var currentAbsolutePath: AbsolutePath { 19 | return AbsolutePath(currentDirectoryPath) 20 | } 21 | 22 | func directoryExists(path: AbsolutePath) -> Bool { 23 | var isDirectory: ObjCBool = false 24 | let fileExists = fileExists(atPath: path.pathString, isDirectory: &isDirectory) 25 | 26 | return fileExists && isDirectory.boolValue 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/FileSystem/Support/DestinationPreparer.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | 3 | final class DestinationPreparer { 4 | private let pathDeleter: PathDeleter 5 | private let directoryCreator: DirectoryCreator 6 | 7 | init( 8 | pathDeleter: PathDeleter, 9 | directoryCreator: DirectoryCreator 10 | ) { 11 | self.pathDeleter = pathDeleter 12 | self.directoryCreator = directoryCreator 13 | } 14 | 15 | func prepareForModification( 16 | destination: AbsolutePath, 17 | prepareForOverwriting: Bool, 18 | ensureDirectoryExists: Bool 19 | ) throws { 20 | if prepareForOverwriting { 21 | try pathDeleter.delete( 22 | path: destination 23 | ) 24 | } 25 | 26 | if ensureDirectoryExists { 27 | try directoryCreator.ensureDirectoryExists( 28 | path: destination.removingLastComponent 29 | ) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/PathLib/StringPathParsing.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | final class StringPathParsing { 4 | static func slashSeparatedComponents(path: S) -> [String] { 5 | return filteringDotComponents( 6 | components: slashSeparatedComponentsWithoutFiltering(path: path) 7 | ) 8 | } 9 | 10 | static func slashSeparatedComponents(paths: [S]) -> [String] { 11 | return filteringDotComponents( 12 | components: paths.flatMap { 13 | slashSeparatedComponentsWithoutFiltering(path: $0) 14 | } 15 | ) 16 | } 17 | 18 | private static func slashSeparatedComponentsWithoutFiltering(path: S) -> [String] { 19 | return path.components(separatedBy: "/").filter { !$0.isEmpty } 20 | } 21 | 22 | private static func filteringDotComponents(components: [String]) -> [String] { 23 | return components.filter { 24 | $0 != "." 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/Concurrency/ThreadSafeLazy.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | public final class ThreadSafeLazy { 5 | private let lock = NSLock() 6 | private let factory: () -> T 7 | 8 | private var cachedValue: T? 9 | 10 | public init(factory: @escaping () -> T) { 11 | self.factory = factory 12 | } 13 | 14 | public var value: T { 15 | get throws { 16 | if let cachedValue = cachedValue { 17 | return cachedValue 18 | } else { 19 | lock.lock() 20 | 21 | defer { 22 | lock.unlock() 23 | } 24 | 25 | if let cachedValue = cachedValue { 26 | return cachedValue 27 | } else { 28 | let cachedValue = factory() 29 | self.cachedValue = cachedValue 30 | return cachedValue 31 | } 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sources/FileSystem/Files/CommonlyUsedPathsProvider/CommonlyUsedPathsProvider.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | public enum SearchDomain { 5 | /// User's home directory --- place to install user's personal items (`~`) 6 | case user 7 | 8 | /// Local to the current machine --- place to install items available to everyone on this machine (`/Library`) 9 | case local 10 | 11 | #if os(macOS) 12 | /// Publically available location in the local area network --- place to install items available on the network (`/Network`) 13 | case network 14 | 15 | /// Provided by Apple, unmodifiable (/System) 16 | case system 17 | #endif 18 | } 19 | 20 | public protocol CommonlyUsedPathsProvider { 21 | func applications(inDomain: SearchDomain, create: Bool) throws -> AbsolutePath 22 | func caches(inDomain: SearchDomain, create: Bool) throws -> AbsolutePath 23 | func library(inDomain: SearchDomain, create: Bool) throws -> AbsolutePath 24 | var currentWorkingDirectory: AbsolutePath { get } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/XcodeLocator/ApplicationPathsProvider/ApplicationPathsProviderImpl.swift: -------------------------------------------------------------------------------- 1 | import PathLib 2 | import FileSystem 3 | 4 | public final class ApplicationPathsProviderImpl: ApplicationPathsProvider { 5 | private let commonlyUsedPathsProvider: CommonlyUsedPathsProvider 6 | private let fileSystemEnumeratorFactory: FileSystemEnumeratorFactory 7 | 8 | public init( 9 | commonlyUsedPathsProvider: CommonlyUsedPathsProvider, 10 | fileSystemEnumeratorFactory: FileSystemEnumeratorFactory 11 | ) { 12 | self.commonlyUsedPathsProvider = commonlyUsedPathsProvider 13 | self.fileSystemEnumeratorFactory = fileSystemEnumeratorFactory 14 | } 15 | 16 | public func applicationPaths() throws -> [AbsolutePath] { 17 | try fileSystemEnumeratorFactory.contentEnumerator( 18 | forPath: commonlyUsedPathsProvider.applications( 19 | inDomain: .local, 20 | create: false 21 | ), 22 | style: .shallow 23 | ).allPaths() 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Tests/JSONStreamTests/JSONReaderStringEdgeCaseTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import JSONStream 3 | import XCTest 4 | 5 | class JSONReaderStringEdgeCaseTests: XCTestCase { 6 | let eventStream = FakeEventStream() 7 | 8 | func testInputWithEscapedSymbols() throws { 9 | let jsonStream = FakeJSONStream(string: "{ \"key\": \"__\\\"hello world\\\"__\" }") 10 | let reader = JSONReader(inputStream: jsonStream, eventStream: eventStream) 11 | try reader.start() 12 | 13 | XCTAssertEqual(eventStream.all.count, 1) 14 | XCTAssertEqual(eventStream.allObjects[0], ["key": "__\\\"hello world\\\"__"]) 15 | } 16 | 17 | func testEmoji() throws { 18 | let jsonStream = FakeJSONStream(string: "{\"key\": \"💅🏻\"}") 19 | let reader = JSONReader(inputStream: jsonStream, eventStream: eventStream) 20 | try reader.start() 21 | 22 | XCTAssertEqual(eventStream.all.count, 1) 23 | XCTAssertEqual(eventStream.allObjects[0], ["key": "💅🏻"]) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Tests/KibanaTestHelpers/FakeKibanaClient.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Avito Tech LLC 3 | */ 4 | 5 | import Foundation 6 | import Kibana 7 | 8 | public class FakeKibanaClient: KibanaClient { 9 | public init() {} 10 | 11 | public struct Payload { 12 | public let level: String 13 | public let message: String 14 | public let metadata: [String: String] 15 | public let completion: (Error?) -> () 16 | } 17 | 18 | public var onSend: (Payload) throws -> () = { _ in } 19 | public var capturedEvents = [Payload]() 20 | 21 | public func send( 22 | level: String, 23 | message: String, 24 | metadata: [String: String], 25 | completion: @escaping (Error?) -> () 26 | ) throws { 27 | let payload = Payload( 28 | level: level, 29 | message: message, 30 | metadata: metadata, 31 | completion: completion 32 | ) 33 | capturedEvents.append(payload) 34 | try onSend(payload) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/MutualTLS/PEM.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import PathLib 3 | 4 | struct PEM { 5 | struct DecodingError: Error { 6 | var description: String { 7 | "Failed to decode pem" 8 | } 9 | } 10 | 11 | let contents: String 12 | 13 | init(contents: String) { 14 | self.contents = contents 15 | } 16 | 17 | init(path: AbsolutePath) throws { 18 | self.contents = try String(contentsOfFile: path.pathString) 19 | } 20 | 21 | func asDER() throws -> DER { 22 | let headerRegex = #"-----(?:BEGIN|END) (?