mirror of
https://github.com/swift-server/swift-memcache-gsoc.git
synced 2026-05-03 07:42:31 +00:00
Migrate to GitHub Actions (#44)
Migrate CI to use GitHub Actions. ### Motivation: To migrate to GitHub actions and centralised infrastructure. ### Modifications: Changes of note: * Bump minimum Swift version to 5.9 in line with CI coverage. * Adopt NIO formatting rules * Remove scripts and docker files which are no longer needed. * Fixup minor changes in `NIOAsyncChannel` API usage ### Result: Feature parity with old CI plus additional soundness checks.
This commit is contained in:
committed by
GitHub
parent
c63219e40b
commit
5b9db4ad3b
@@ -0,0 +1,8 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
@@ -0,0 +1,14 @@
|
||||
changelog:
|
||||
categories:
|
||||
- title: SemVer Major
|
||||
labels:
|
||||
- ⚠️ semver/major
|
||||
- title: SemVer Minor
|
||||
labels:
|
||||
- semver/minor
|
||||
- title: SemVer Patch
|
||||
labels:
|
||||
- semver/patch
|
||||
- title: Other Changes
|
||||
labels:
|
||||
- semver/none
|
||||
@@ -0,0 +1,18 @@
|
||||
name: Main
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: "0 8,20 * * *"
|
||||
|
||||
jobs:
|
||||
unit-tests:
|
||||
name: Unit tests
|
||||
uses: ./.github/workflows/unit_tests.yml
|
||||
with:
|
||||
linux_5_9_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -strict-concurrency=complete"
|
||||
linux_5_10_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -strict-concurrency=complete"
|
||||
linux_6_0_arguments_override: "--explicit-target-dependency-import-check error"
|
||||
linux_nightly_6_0_arguments_override: "--explicit-target-dependency-import-check error"
|
||||
linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error"
|
||||
@@ -0,0 +1,26 @@
|
||||
name: PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
|
||||
jobs:
|
||||
soundness:
|
||||
name: Soundness
|
||||
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
|
||||
with:
|
||||
license_header_check_project_name: "swift-memcache-gsoc"
|
||||
|
||||
unit-tests:
|
||||
name: Unit tests
|
||||
uses: ./.github/workflows/unit_tests.yml
|
||||
with:
|
||||
linux_5_9_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -strict-concurrency=complete"
|
||||
linux_5_10_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -strict-concurrency=complete"
|
||||
linux_6_0_arguments_override: "--explicit-target-dependency-import-check error"
|
||||
linux_nightly_6_0_arguments_override: "--explicit-target-dependency-import-check error"
|
||||
linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error"
|
||||
|
||||
cxx-interop:
|
||||
name: Cxx interop
|
||||
uses: apple/swift-nio/.github/workflows/cxx_interop.yml@main
|
||||
@@ -0,0 +1,18 @@
|
||||
name: PR label
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled, unlabeled, opened, reopened, synchronize]
|
||||
|
||||
jobs:
|
||||
semver-label-check:
|
||||
name: Semantic version label check
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 1
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Check for Semantic Version label
|
||||
uses: apple/swift-nio/.github/actions/pull_request_semver_label_checker@main
|
||||
@@ -0,0 +1,99 @@
|
||||
name: Unit tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
linux_5_9_enabled:
|
||||
type: boolean
|
||||
description: "Boolean to enable the Linux 5.9 Swift version matrix job. Defaults to true."
|
||||
default: true
|
||||
linux_5_9_arguments_override:
|
||||
type: string
|
||||
description: "The arguments passed to swift test in the Linux 5.9 Swift version matrix job."
|
||||
default: ""
|
||||
linux_5_10_enabled:
|
||||
type: boolean
|
||||
description: "Boolean to enable the Linux 5.10 Swift version matrix job. Defaults to true."
|
||||
default: true
|
||||
linux_5_10_arguments_override:
|
||||
type: string
|
||||
description: "The arguments passed to swift test in the Linux 5.10 Swift version matrix job."
|
||||
default: ""
|
||||
linux_6_0_enabled:
|
||||
type: boolean
|
||||
description: "Boolean to enable the Linux 6.0 Swift version matrix job. Defaults to true."
|
||||
default: true
|
||||
linux_6_0_arguments_override:
|
||||
type: string
|
||||
description: "The arguments passed to swift test in the Linux 6.0 Swift version matrix job."
|
||||
default: ""
|
||||
linux_nightly_6_0_enabled:
|
||||
type: boolean
|
||||
description: "Boolean to enable the Linux nightly 6.0 Swift version matrix job. Defaults to true."
|
||||
default: true
|
||||
linux_nightly_6_0_arguments_override:
|
||||
type: string
|
||||
description: "The arguments passed to swift test in the Linux nightly 6.0 Swift version matrix job."
|
||||
default: ""
|
||||
linux_nightly_main_enabled:
|
||||
type: boolean
|
||||
description: "Boolean to enable the Linux nightly main Swift version matrix job. Defaults to true."
|
||||
default: true
|
||||
linux_nightly_main_arguments_override:
|
||||
type: string
|
||||
description: "The arguments passed to swift test in the Linux nightly main Swift version matrix job."
|
||||
default: ""
|
||||
|
||||
jobs:
|
||||
unit-tests:
|
||||
name: Unit tests
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# We are specifying only the major and minor of the docker images to automatically pick up the latest patch release
|
||||
swift:
|
||||
- image: "swift:5.9-jammy"
|
||||
swift_version: "5.9"
|
||||
enabled: ${{ inputs.linux_5_9_enabled }}
|
||||
- image: "swift:5.10-jammy"
|
||||
swift_version: "5.10"
|
||||
enabled: ${{ inputs.linux_5_10_enabled }}
|
||||
- image: "swift:6.0-jammy"
|
||||
swift_version: "6.0"
|
||||
enabled: ${{ inputs.linux_6_0_enabled }}
|
||||
- image: "swiftlang/swift:nightly-6.0-jammy"
|
||||
swift_version: "nightly-6.0"
|
||||
enabled: ${{ inputs.linux_nightly_6_0_enabled }}
|
||||
- image: "swiftlang/swift:nightly-main-jammy"
|
||||
swift_version: "nightly-main"
|
||||
enabled: ${{ inputs.linux_nightly_main_enabled }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
if: ${{ matrix.swift.enabled }}
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: true
|
||||
- name: Mark the workspace as safe
|
||||
if: ${{ matrix.swift.enabled }}
|
||||
# https://github.com/actions/checkout/issues/766
|
||||
run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
|
||||
- name: Run matrix job
|
||||
if: ${{ matrix.swift.enabled }}
|
||||
env:
|
||||
SWIFT_VERSION: ${{ matrix.swift.swift_version }}
|
||||
COMMAND: "swift test"
|
||||
COMMAND_OVERRIDE_5_9: "swift test ${{ inputs.linux_5_9_arguments_override }}"
|
||||
COMMAND_OVERRIDE_5_10: "swift test ${{ inputs.linux_5_10_arguments_override }}"
|
||||
COMMAND_OVERRIDE_6_0: "swift test ${{ inputs.linux_6_0_arguments_override }}"
|
||||
COMMAND_OVERRIDE_NIGHTLY_6_0: "swift test ${{ inputs.linux_nightly_6_0_arguments_override }}"
|
||||
COMMAND_OVERRIDE_NIGHTLY_MAIN: "swift test ${{ inputs.linux_nightly_main_arguments_override }}"
|
||||
run: |
|
||||
apt-get -qq update && apt-get -qq -y install curl
|
||||
curl -s https://raw.githubusercontent.com/apple/swift-nio/main/scripts/check-matrix-job.sh | bash
|
||||
container:
|
||||
image: ${{ matrix.swift.image }}
|
||||
services:
|
||||
memcached:
|
||||
image: memcached:latest
|
||||
@@ -0,0 +1,36 @@
|
||||
.gitignore
|
||||
**/.gitignore
|
||||
.licenseignore
|
||||
.gitattributes
|
||||
.git-blame-ignore-revs
|
||||
.mailfilter
|
||||
.mailmap
|
||||
.spi.yml
|
||||
.swift-format
|
||||
.swiftformatignore
|
||||
.editorconfig
|
||||
.github/*
|
||||
*.md
|
||||
*.txt
|
||||
*.yml
|
||||
*.yaml
|
||||
*.json
|
||||
Package.swift
|
||||
**/Package.swift
|
||||
Package@-*.swift
|
||||
**/Package@-*.swift
|
||||
Package.resolved
|
||||
**/Package.resolved
|
||||
Makefile
|
||||
*.modulemap
|
||||
**/*.modulemap
|
||||
**/*.docc/*
|
||||
*.xcprivacy
|
||||
**/*.xcprivacy
|
||||
*.symlink
|
||||
**/*.symlink
|
||||
Dockerfile
|
||||
**/Dockerfile
|
||||
Snippets/*
|
||||
dev/git.commit.template
|
||||
.unacceptablelanguageignore
|
||||
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"version" : 1,
|
||||
"indentation" : {
|
||||
"spaces" : 4
|
||||
},
|
||||
"tabWidth" : 4,
|
||||
"fileScopedDeclarationPrivacy" : {
|
||||
"accessLevel" : "private"
|
||||
},
|
||||
"spacesAroundRangeFormationOperators" : false,
|
||||
"indentConditionalCompilationBlocks" : false,
|
||||
"indentSwitchCaseLabels" : false,
|
||||
"lineBreakAroundMultilineExpressionChainComponents" : false,
|
||||
"lineBreakBeforeControlFlowKeywords" : false,
|
||||
"lineBreakBeforeEachArgument" : true,
|
||||
"lineBreakBeforeEachGenericRequirement" : true,
|
||||
"lineLength" : 120,
|
||||
"maximumBlankLines" : 1,
|
||||
"respectsExistingLineBreaks" : true,
|
||||
"prioritizeKeepingFunctionOutputTogether" : true,
|
||||
"noAssignmentInExpressions" : {
|
||||
"allowedFunctions" : [
|
||||
"XCTAssertNoThrow",
|
||||
"XCTAssertThrowsError"
|
||||
]
|
||||
},
|
||||
"rules" : {
|
||||
"AllPublicDeclarationsHaveDocumentation" : false,
|
||||
"AlwaysUseLiteralForEmptyCollectionInit" : false,
|
||||
"AlwaysUseLowerCamelCase" : false,
|
||||
"AmbiguousTrailingClosureOverload" : true,
|
||||
"BeginDocumentationCommentWithOneLineSummary" : false,
|
||||
"DoNotUseSemicolons" : true,
|
||||
"DontRepeatTypeInStaticProperties" : true,
|
||||
"FileScopedDeclarationPrivacy" : true,
|
||||
"FullyIndirectEnum" : true,
|
||||
"GroupNumericLiterals" : true,
|
||||
"IdentifiersMustBeASCII" : true,
|
||||
"NeverForceUnwrap" : false,
|
||||
"NeverUseForceTry" : false,
|
||||
"NeverUseImplicitlyUnwrappedOptionals" : false,
|
||||
"NoAccessLevelOnExtensionDeclaration" : true,
|
||||
"NoAssignmentInExpressions" : true,
|
||||
"NoBlockComments" : true,
|
||||
"NoCasesWithOnlyFallthrough" : true,
|
||||
"NoEmptyTrailingClosureParentheses" : true,
|
||||
"NoLabelsInCasePatterns" : true,
|
||||
"NoLeadingUnderscores" : false,
|
||||
"NoParensAroundConditions" : true,
|
||||
"NoVoidReturnOnFunctionSignature" : true,
|
||||
"OmitExplicitReturns" : true,
|
||||
"OneCasePerLine" : true,
|
||||
"OneVariableDeclarationPerLine" : true,
|
||||
"OnlyOneTrailingClosureArgument" : true,
|
||||
"OrderedImports" : true,
|
||||
"ReplaceForEachWithForLoop" : true,
|
||||
"ReturnVoidInsteadOfEmptyTuple" : true,
|
||||
"UseEarlyExits" : false,
|
||||
"UseExplicitNilCheckInConditions" : false,
|
||||
"UseLetInEveryBoundCaseVariable" : false,
|
||||
"UseShorthandTypeNames" : true,
|
||||
"UseSingleLinePropertyGetter" : false,
|
||||
"UseSynthesizedInitializer" : false,
|
||||
"UseTripleSlashForDocumentationComments" : true,
|
||||
"UseWhereClausesInForLoops" : false,
|
||||
"ValidateDocumentationComments" : false
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
# file options
|
||||
|
||||
--swiftversion 5.7
|
||||
--exclude .build
|
||||
|
||||
# format options
|
||||
|
||||
--self insert
|
||||
--patternlet inline
|
||||
--ranges nospace
|
||||
--stripunusedargs unnamed-only
|
||||
--ifdef no-indent
|
||||
--extensionacl on-declarations
|
||||
--disable typeSugar # https://github.com/nicklockwood/SwiftFormat/issues/636
|
||||
--disable andOperator
|
||||
--disable wrapMultilineStatementBraces
|
||||
--disable enumNamespaces
|
||||
--disable redundantExtensionACL
|
||||
--disable redundantReturn
|
||||
--disable preferKeyPath
|
||||
--disable sortedSwitchCases
|
||||
--disable hoistTry
|
||||
--disable hoistAwait
|
||||
|
||||
# rules
|
||||
@@ -21,7 +21,7 @@ private let eventLoopGroup = MultiThreadedEventLoopGroup.singleton.next()
|
||||
|
||||
let benchmarks = {
|
||||
let defaultMetrics: [BenchmarkMetric] = [
|
||||
.mallocCountTotal,
|
||||
.mallocCountTotal
|
||||
]
|
||||
|
||||
Benchmark(
|
||||
@@ -41,7 +41,10 @@ let benchmarks = {
|
||||
timeUnits: .milliseconds
|
||||
)
|
||||
) { benchmark in
|
||||
try await runSetWithTTLRequest(iterations: benchmark.scaledIterations.upperBound, eventLoopGroup: eventLoopGroup)
|
||||
try await runSetWithTTLRequest(
|
||||
iterations: benchmark.scaledIterations.upperBound,
|
||||
eventLoopGroup: eventLoopGroup
|
||||
)
|
||||
}
|
||||
Benchmark(
|
||||
"Delete Request",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// swift-tools-version: 5.7
|
||||
// swift-tools-version: 5.9
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the SwiftCertificates open source project
|
||||
@@ -18,7 +18,7 @@ import PackageDescription
|
||||
let package = Package(
|
||||
name: "Benchmarks",
|
||||
platforms: [
|
||||
.macOS(.v13),
|
||||
.macOS(.v13)
|
||||
],
|
||||
dependencies: [
|
||||
.package(name: "swift-memcache-gsoc", path: "../"),
|
||||
@@ -36,8 +36,8 @@ let package = Package(
|
||||
],
|
||||
path: "Benchmarks/MemcacheBenchmarks",
|
||||
plugins: [
|
||||
.plugin(name: "BenchmarkPlugin", package: "package-benchmark"),
|
||||
.plugin(name: "BenchmarkPlugin", package: "package-benchmark")
|
||||
]
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
// swift-tools-version: 5.7
|
||||
// swift-tools-version: 5.9
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the swift-memcache-gsoc open source project
|
||||
@@ -27,10 +27,10 @@ let package = Package(
|
||||
.library(
|
||||
name: "Memcache",
|
||||
targets: ["Memcache"]
|
||||
),
|
||||
)
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/apple/swift-nio.git", from: "2.56.0"),
|
||||
.package(url: "https://github.com/apple/swift-nio.git", from: "2.76.1"),
|
||||
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
|
||||
.package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "2.0.0"),
|
||||
],
|
||||
@@ -52,7 +52,7 @@ let package = Package(
|
||||
.executableTarget(
|
||||
name: "MemcacheExample",
|
||||
dependencies: [
|
||||
.target(name: "Memcache"),
|
||||
.target(name: "Memcache")
|
||||
]
|
||||
),
|
||||
]
|
||||
|
||||
@@ -12,12 +12,13 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import NIOCore
|
||||
|
||||
#if os(Linux)
|
||||
import Glibc
|
||||
#else
|
||||
import Darwin
|
||||
#endif
|
||||
import NIOCore
|
||||
|
||||
extension ByteBuffer {
|
||||
/// Write `integer` into this `ByteBuffer` as ASCII digits, without leading zeros, moving the writer index forward appropriately.
|
||||
@@ -40,7 +41,8 @@ extension ByteBuffer {
|
||||
mutating func readIntegerFromASCII<T: FixedWidthInteger>() -> T? {
|
||||
var value: T = 0
|
||||
while self.readableBytes > 0, let currentByte = self.readInteger(as: UInt8.self),
|
||||
currentByte >= UInt8.zero && currentByte <= UInt8.nine {
|
||||
currentByte >= UInt8.zero && currentByte <= UInt8.nine
|
||||
{
|
||||
value = (value * 10) + T(currentByte - UInt8.zero)
|
||||
}
|
||||
return value > 0 ? value : nil
|
||||
@@ -58,7 +60,10 @@ extension ByteBuffer {
|
||||
/// - flags: An instance of MemcacheFlags that holds the flags intended to be serialized and written to the ByteBuffer.
|
||||
mutating func writeMemcacheFlags(flags: MemcacheFlags) {
|
||||
// Ensure that both storageMode and arithmeticMode aren't set at the same time.
|
||||
precondition(!(flags.storageMode != nil && flags.arithmeticMode != nil), "Cannot specify both a storage and arithmetic mode.")
|
||||
precondition(
|
||||
!(flags.storageMode != nil && flags.arithmeticMode != nil),
|
||||
"Cannot specify both a storage and arithmetic mode."
|
||||
)
|
||||
|
||||
if let shouldReturnValue = flags.shouldReturnValue, shouldReturnValue {
|
||||
self.writeInteger(UInt8.whitespace)
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
@_spi(AsyncChannel)
|
||||
|
||||
import NIOCore
|
||||
@_spi(AsyncChannel) import NIOCore
|
||||
import NIOPosix
|
||||
import ServiceLifecycle
|
||||
|
||||
@@ -92,7 +90,7 @@ public actor MemcacheConnection: Service {
|
||||
let channel = try await ClientBootstrap(group: eventLoopGroup)
|
||||
.connect(host: self.host, port: self.port)
|
||||
.flatMap { channel in
|
||||
return channel.eventLoop.makeCompletedFuture {
|
||||
channel.eventLoop.makeCompletedFuture {
|
||||
try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(MemcacheRequestEncoder()))
|
||||
try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(MemcacheResponseDecoder()))
|
||||
return try NIOAsyncChannel<MemcacheResponse, MemcacheRequest>(synchronouslyWrapping: channel)
|
||||
@@ -106,12 +104,12 @@ public actor MemcacheConnection: Service {
|
||||
requestContinuation: continuation
|
||||
)
|
||||
|
||||
var iterator = channel.inboundStream.makeAsyncIterator()
|
||||
var iterator = channel.inbound.makeAsyncIterator()
|
||||
switch self.state {
|
||||
case .running(_, let channel, let requestStream, let requestContinuation):
|
||||
for await (request, continuation) in requestStream {
|
||||
do {
|
||||
try await channel.outboundWriter.write(request)
|
||||
try await channel.outbound.write(request)
|
||||
let responseBuffer = try await iterator.next()
|
||||
|
||||
if let response = responseBuffer {
|
||||
@@ -119,24 +117,29 @@ public actor MemcacheConnection: Service {
|
||||
} else {
|
||||
self.state = .finished
|
||||
requestContinuation.finish()
|
||||
continuation.resume(throwing: MemcacheError(
|
||||
code: .connectionShutdown,
|
||||
message: "The connection to the Memcache server was unexpectedly closed.",
|
||||
cause: nil,
|
||||
location: .here()
|
||||
))
|
||||
continuation.resume(
|
||||
throwing: MemcacheError(
|
||||
code: .connectionShutdown,
|
||||
message: "The connection to the Memcache server was unexpectedly closed.",
|
||||
cause: nil,
|
||||
location: .here()
|
||||
)
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
switch self.state {
|
||||
case .running:
|
||||
self.state = .finished
|
||||
requestContinuation.finish()
|
||||
continuation.resume(throwing: MemcacheError(
|
||||
code: .connectionShutdown,
|
||||
message: "The connection to the Memcache server has shut down while processing a request.",
|
||||
cause: error,
|
||||
location: .here()
|
||||
))
|
||||
continuation.resume(
|
||||
throwing: MemcacheError(
|
||||
code: .connectionShutdown,
|
||||
message:
|
||||
"The connection to the Memcache server has shut down while processing a request.",
|
||||
cause: error,
|
||||
location: .here()
|
||||
)
|
||||
)
|
||||
case .initial, .finished:
|
||||
break
|
||||
}
|
||||
@@ -152,19 +155,21 @@ public actor MemcacheConnection: Service {
|
||||
private func sendRequest(_ request: MemcacheRequest) async throws -> MemcacheResponse {
|
||||
switch self.state {
|
||||
case .initial(_, _, _, let requestContinuation),
|
||||
.running(_, _, _, let requestContinuation):
|
||||
.running(_, _, _, let requestContinuation):
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
switch requestContinuation.yield((request, continuation)) {
|
||||
case .enqueued:
|
||||
break
|
||||
case .dropped, .terminated:
|
||||
continuation.resume(throwing: MemcacheError(
|
||||
code: .connectionShutdown,
|
||||
message: "Unable to enqueue request due to the connection being shutdown.",
|
||||
cause: nil,
|
||||
location: .here()
|
||||
))
|
||||
continuation.resume(
|
||||
throwing: MemcacheError(
|
||||
code: .connectionShutdown,
|
||||
message: "Unable to enqueue request due to the connection being shutdown.",
|
||||
cause: nil,
|
||||
location: .here()
|
||||
)
|
||||
)
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -190,7 +195,7 @@ public actor MemcacheConnection: Service {
|
||||
private func getBufferAllocator() throws -> ByteBufferAllocator {
|
||||
switch self.state {
|
||||
case .initial(_, let bufferAllocator, _, _),
|
||||
.running(let bufferAllocator, _, _, _):
|
||||
.running(let bufferAllocator, _, _, _):
|
||||
return bufferAllocator
|
||||
case .finished:
|
||||
throw MemcacheError(
|
||||
@@ -264,7 +269,7 @@ public actor MemcacheConnection: Service {
|
||||
public func set(_ key: String, value: some MemcacheValue, timeToLive: TimeToLive = .indefinitely) async throws {
|
||||
switch self.state {
|
||||
case .initial(_, let bufferAllocator, _, _),
|
||||
.running(let bufferAllocator, _, _, _):
|
||||
.running(let bufferAllocator, _, _, _):
|
||||
|
||||
var buffer = bufferAllocator.buffer(capacity: 0)
|
||||
value.writeToBuffer(&buffer)
|
||||
|
||||
@@ -37,7 +37,7 @@ public struct MemcacheError: Error, @unchecked Sendable {
|
||||
}
|
||||
|
||||
func copy() -> Self {
|
||||
return Self(
|
||||
Self(
|
||||
code: self.code,
|
||||
message: self.message,
|
||||
cause: self.cause,
|
||||
@@ -111,7 +111,8 @@ extension MemcacheError: CustomStringConvertible {
|
||||
extension MemcacheError: CustomDebugStringConvertible {
|
||||
public var debugDescription: String {
|
||||
if let cause = self.cause {
|
||||
return "\(String(reflecting: self.code)): \(String(reflecting: self.message)) (\(String(reflecting: cause)))"
|
||||
return
|
||||
"\(String(reflecting: self.code)): \(String(reflecting: self.message)) (\(String(reflecting: cause)))"
|
||||
} else {
|
||||
return "\(String(reflecting: self.code)): \(String(reflecting: self.message))"
|
||||
}
|
||||
@@ -146,7 +147,7 @@ extension MemcacheError {
|
||||
///
|
||||
/// - Returns: A multi-line description of the error.
|
||||
public func detailedDescription() -> String {
|
||||
return self.detailedDescriptionLines().joined(separator: "\n")
|
||||
self.detailedDescriptionLines().joined(separator: "\n")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +230,7 @@ extension MemcacheError {
|
||||
file: String = #fileID,
|
||||
line: Int = #line
|
||||
) -> Self {
|
||||
return SourceLocation(function: function, file: file, line: line)
|
||||
SourceLocation(function: function, file: file, line: line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import NIOCore
|
||||
|
||||
enum MemcacheRequest: Sendable {
|
||||
struct SetCommand: Sendable {
|
||||
let key: String
|
||||
|
||||
@@ -109,8 +109,10 @@ struct MemcacheResponseDecoder: NIOSingleStepByteToMessageDecoder {
|
||||
mutating func next(buffer: inout ByteBuffer) throws -> NextDecodeAction {
|
||||
// Check if the buffer contains "\r\n"
|
||||
let bytesView = buffer.readableBytesView
|
||||
guard let crIndex = bytesView.firstIndex(of: UInt8.carriageReturn), bytesView.index(after: crIndex) < bytesView.endIndex,
|
||||
bytesView[bytesView.index(after: crIndex)] == UInt8.newline else {
|
||||
guard let crIndex = bytesView.firstIndex(of: UInt8.carriageReturn),
|
||||
bytesView.index(after: crIndex) < bytesView.endIndex,
|
||||
bytesView[bytesView.index(after: crIndex)] == UInt8.newline
|
||||
else {
|
||||
return .waitForMoreBytes
|
||||
}
|
||||
switch self.nextStep {
|
||||
@@ -130,7 +132,9 @@ struct MemcacheResponseDecoder: NIOSingleStepByteToMessageDecoder {
|
||||
return .waitForMoreBytes
|
||||
}
|
||||
|
||||
if let currentByte = buffer.getInteger(at: buffer.readerIndex, as: UInt8.self), currentByte == UInt8.whitespace {
|
||||
if let currentByte = buffer.getInteger(at: buffer.readerIndex, as: UInt8.self),
|
||||
currentByte == UInt8.whitespace
|
||||
{
|
||||
buffer.moveReaderIndex(forwardBy: 1)
|
||||
}
|
||||
|
||||
@@ -152,7 +156,9 @@ struct MemcacheResponseDecoder: NIOSingleStepByteToMessageDecoder {
|
||||
return .continueDecodeLoop
|
||||
}
|
||||
|
||||
if let currentByte = buffer.getInteger(at: buffer.readerIndex, as: UInt8.self), currentByte == UInt8.whitespace {
|
||||
if let currentByte = buffer.getInteger(at: buffer.readerIndex, as: UInt8.self),
|
||||
currentByte == UInt8.whitespace
|
||||
{
|
||||
buffer.moveReaderIndex(forwardBy: 1)
|
||||
}
|
||||
|
||||
@@ -162,7 +168,12 @@ struct MemcacheResponseDecoder: NIOSingleStepByteToMessageDecoder {
|
||||
self.nextStep = .decodeValue(returnCode, dataLength!, flags)
|
||||
return .continueDecodeLoop
|
||||
} else {
|
||||
let response = MemcacheResponse(returnCode: returnCode, dataLength: dataLength, flags: flags, value: nil)
|
||||
let response = MemcacheResponse(
|
||||
returnCode: returnCode,
|
||||
dataLength: dataLength,
|
||||
flags: flags,
|
||||
value: nil
|
||||
)
|
||||
self.nextStep = .returnCode
|
||||
return .returnDecodedResponse(response)
|
||||
}
|
||||
@@ -177,10 +188,11 @@ struct MemcacheResponseDecoder: NIOSingleStepByteToMessageDecoder {
|
||||
}
|
||||
|
||||
guard buffer.readableBytes >= 2,
|
||||
let nextByte = buffer.readInteger(as: UInt8.self),
|
||||
nextByte == UInt8.carriageReturn,
|
||||
let nextNextByte = buffer.readInteger(as: UInt8.self),
|
||||
nextNextByte == UInt8.newline else {
|
||||
let nextByte = buffer.readInteger(as: UInt8.self),
|
||||
nextByte == UInt8.carriageReturn,
|
||||
let nextNextByte = buffer.readInteger(as: UInt8.self),
|
||||
nextNextByte == UInt8.newline
|
||||
else {
|
||||
preconditionFailure("Expected to find CRLF at end of response")
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ extension MemcacheValue where Self: FixedWidthInteger {
|
||||
///
|
||||
/// - Parameter buffer: The ByteBuffer from which the value should be read.
|
||||
public static func readFromBuffer(_ buffer: inout ByteBuffer) -> Self? {
|
||||
return buffer.readIntegerFromASCII()
|
||||
buffer.readIntegerFromASCII()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ extension MemcacheValue where Self: StringProtocol {
|
||||
///
|
||||
/// - Parameter buffer: The ByteBuffer from which the value should be read.
|
||||
public static func readFromBuffer(_ buffer: inout ByteBuffer) -> Self? {
|
||||
return buffer.readString(length: buffer.readableBytes) as? Self
|
||||
buffer.readString(length: buffer.readableBytes) as? Self
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,11 +12,12 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Memcache
|
||||
import NIOCore
|
||||
import NIOPosix
|
||||
import XCTest
|
||||
|
||||
@testable import Memcache
|
||||
|
||||
final class MemcacheIntegrationTest: XCTestCase {
|
||||
var channel: ClientBootstrap!
|
||||
var group: EventLoopGroup!
|
||||
@@ -27,7 +28,9 @@ final class MemcacheIntegrationTest: XCTestCase {
|
||||
self.channel = ClientBootstrap(group: self.group)
|
||||
.channelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
|
||||
.channelInitializer { channel in
|
||||
return channel.pipeline.addHandlers([MessageToByteHandler(MemcacheRequestEncoder()), ByteToMessageHandler(MemcacheResponseDecoder())])
|
||||
channel.pipeline.addHandlers([
|
||||
MessageToByteHandler(MemcacheRequestEncoder()), ByteToMessageHandler(MemcacheResponseDecoder()),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +277,11 @@ final class MemcacheIntegrationTest: XCTestCase {
|
||||
|
||||
// Get value for key after prepend operation
|
||||
let updatedValue: String? = try await memcacheConnection.get("greet")
|
||||
XCTAssertEqual(updatedValue, prependValue + initialValue, "Received value should be the same as the concatenation of prependValue and initialValue")
|
||||
XCTAssertEqual(
|
||||
updatedValue,
|
||||
prependValue + initialValue,
|
||||
"Received value should be the same as the concatenation of prependValue and initialValue"
|
||||
)
|
||||
|
||||
group.cancelAll()
|
||||
}
|
||||
@@ -300,7 +307,11 @@ final class MemcacheIntegrationTest: XCTestCase {
|
||||
|
||||
// Get value for key after append operation
|
||||
let updatedValue: String? = try await memcacheConnection.get("greet")
|
||||
XCTAssertEqual(updatedValue, initialValue + appendValue, "Received value should be the same as the concatenation of initialValue and appendValue")
|
||||
XCTAssertEqual(
|
||||
updatedValue,
|
||||
initialValue + appendValue,
|
||||
"Received value should be the same as the concatenation of initialValue and appendValue"
|
||||
)
|
||||
|
||||
group.cancelAll()
|
||||
}
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Memcache
|
||||
import XCTest
|
||||
|
||||
@testable import Memcache
|
||||
|
||||
final class MemcacheErrorTests: XCTestCase {
|
||||
func testInitialization() {
|
||||
let location = MemcacheError.SourceLocation(function: "testFunction", file: "testFile.swift", line: 8)
|
||||
@@ -31,7 +32,12 @@ final class MemcacheErrorTests: XCTestCase {
|
||||
func testCustomStringConvertible() {
|
||||
let location = MemcacheError.SourceLocation.here()
|
||||
let causeError = MemcacheError(code: .protocolError, message: "No response", cause: nil, location: location)
|
||||
let mainError = MemcacheError(code: .connectionShutdown, message: "Connection lost", cause: causeError, location: location)
|
||||
let mainError = MemcacheError(
|
||||
code: .connectionShutdown,
|
||||
message: "Connection lost",
|
||||
cause: causeError,
|
||||
location: location
|
||||
)
|
||||
|
||||
let description = mainError.description
|
||||
|
||||
@@ -53,7 +59,12 @@ final class MemcacheErrorTests: XCTestCase {
|
||||
func testDetailedDescription() {
|
||||
let location = MemcacheError.SourceLocation.here()
|
||||
let causeError = MemcacheError(code: .protocolError, message: "No response", cause: nil, location: location)
|
||||
let mainError = MemcacheError(code: .connectionShutdown, message: "Connection lost", cause: causeError, location: location)
|
||||
let mainError = MemcacheError(
|
||||
code: .connectionShutdown,
|
||||
message: "Connection lost",
|
||||
cause: causeError,
|
||||
location: location
|
||||
)
|
||||
|
||||
let detailedDesc = mainError.detailedDescription()
|
||||
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Memcache
|
||||
import XCTest
|
||||
|
||||
@testable import Memcache
|
||||
|
||||
final class MemcacheFlagsTests: XCTestCase {
|
||||
func testVFlag() {
|
||||
var flags = MemcacheFlags()
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Memcache
|
||||
import NIOCore
|
||||
import XCTest
|
||||
|
||||
@testable import Memcache
|
||||
|
||||
final class MemcacheRequestEncoderTests: XCTestCase {
|
||||
var encoder: MemcacheRequestEncoder!
|
||||
|
||||
@@ -120,7 +121,11 @@ final class MemcacheRequestEncoderTests: XCTestCase {
|
||||
// Extract the encoded Time-To-Live
|
||||
let encodedString = outBuffer.getString(at: 0, length: outBuffer.readableBytes)!
|
||||
let regex = try! NSRegularExpression(pattern: "T(\\d+)", options: .caseInsensitive)
|
||||
let match = regex.firstMatch(in: encodedString, options: [], range: NSRange(location: 0, length: encodedString.utf16.count))
|
||||
let match = regex.firstMatch(
|
||||
in: encodedString,
|
||||
options: [],
|
||||
range: NSRange(location: 0, length: encodedString.utf16.count)
|
||||
)
|
||||
let encodedTTLRange = Range(match!.range(at: 1), in: encodedString)!
|
||||
let encodedTTL = Int32(encodedString[encodedTTLRange])!
|
||||
|
||||
|
||||
@@ -12,11 +12,12 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Memcache
|
||||
import NIOCore
|
||||
import NIOEmbedded
|
||||
import XCTest
|
||||
|
||||
@testable import Memcache
|
||||
|
||||
final class MemcacheResponseDecoderTests: XCTestCase {
|
||||
var decoder: MemcacheResponseDecoder!
|
||||
|
||||
@@ -155,7 +156,10 @@ final class MemcacheResponseDecoderTests: XCTestCase {
|
||||
// VA 2
|
||||
var firstPartBuffer = buffer.getSlice(at: buffer.readerIndex, length: splitIndex)!
|
||||
// \r\nhi\r\n
|
||||
var secondPartBuffer = buffer.getSlice(at: buffer.readerIndex + splitIndex, length: buffer.readableBytes - splitIndex)!
|
||||
var secondPartBuffer = buffer.getSlice(
|
||||
at: buffer.readerIndex + splitIndex,
|
||||
length: buffer.readableBytes - splitIndex
|
||||
)!
|
||||
|
||||
// Try to decode the first part, which should return .waitForMoreBytes
|
||||
switch try self.decoder.next(buffer: &firstPartBuffer) {
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Memcache
|
||||
import NIOCore
|
||||
import XCTest
|
||||
|
||||
@testable import Memcache
|
||||
|
||||
final class MemcacheTimeToLiveTests: XCTestCase {
|
||||
let clock = ContinuousClock()
|
||||
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Memcache
|
||||
import NIOCore
|
||||
import XCTest
|
||||
|
||||
@testable import Memcache
|
||||
|
||||
final class MemcacheValueTests: XCTestCase {
|
||||
func testMemcacheValueConformance() {
|
||||
var buffer = ByteBufferAllocator().buffer(capacity: 0)
|
||||
|
||||
@@ -45,10 +45,10 @@ set -o pipefail
|
||||
here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
target_repo=${2-"$here/.."}
|
||||
|
||||
for f in 57 58 59 510 -nightly; do
|
||||
for f in 59 510 -nightly; do
|
||||
echo "swift$f"
|
||||
|
||||
docker_file=$(if [[ "$f" == "-nightly" ]]; then f=main; fi && ls "$target_repo/docker/docker-compose."*"$f"*".yaml")
|
||||
|
||||
docker-compose -f docker/docker-compose.yaml -f $docker_file run update-benchmark-baseline
|
||||
docker-compose -f docker/docker-compose.yaml -f "$docker_file" run update-benchmark-baseline
|
||||
done
|
||||
|
||||
+2
-8
@@ -1,4 +1,4 @@
|
||||
ARG swift_version=5.7
|
||||
ARG swift_version=5.9
|
||||
ARG ubuntu_version=jammy
|
||||
ARG base_image=swift:$swift_version-$ubuntu_version
|
||||
FROM $base_image
|
||||
@@ -16,11 +16,5 @@ ENV LANGUAGE en_US.UTF-8
|
||||
RUN mkdir -p $HOME/.tools
|
||||
RUN echo 'export PATH="$HOME/.tools:$PATH"' >> $HOME/.profile
|
||||
|
||||
# swiftformat (until part of the toolchain)
|
||||
ARG swiftformat_version=0.51.8
|
||||
RUN git clone --branch $swiftformat_version --depth 1 https://github.com/nicklockwood/SwiftFormat $HOME/.tools/swift-format
|
||||
RUN cd $HOME/.tools/swift-format && swift build -c release
|
||||
RUN ln -s $HOME/.tools/swift-format/.build/release/swiftformat $HOME/.tools/swiftformat
|
||||
|
||||
# install jemalloc for running allocation benchmarks
|
||||
RUN apt-get update & apt-get install -y libjemalloc-dev
|
||||
RUN apt-get update & apt-get install -y libjemalloc-dev
|
||||
|
||||
@@ -17,9 +17,8 @@ services:
|
||||
|
||||
shell:
|
||||
image: swift-memcache-gsoc:22.04-5.10
|
||||
|
||||
|
||||
update-benchmark-baseline:
|
||||
image: swift-memcache-gsoc:22.04-5.10
|
||||
environment:
|
||||
- SWIFT_VERSION=5.10
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
|
||||
runtime-setup:
|
||||
image: swift-memcache-gsoc:22.04-5.7
|
||||
build:
|
||||
args:
|
||||
ubuntu_version: "jammy"
|
||||
swift_version: "5.7"
|
||||
|
||||
test:
|
||||
image: swift-memcache-gsoc:22.04-5.7
|
||||
environment:
|
||||
- WARN_AS_ERROR_ARG=-Xswiftc -warnings-as-errors
|
||||
# - SANITIZER_ARG=--sanitize=thread # TSan broken still
|
||||
|
||||
shell:
|
||||
image: swift-memcache-gsoc:22.04-5.7
|
||||
|
||||
update-benchmark-baseline:
|
||||
image: swift-memcache-gsoc:22.04-5.7
|
||||
environment:
|
||||
- SWIFT_VERSION=5.7
|
||||
@@ -1,25 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
|
||||
runtime-setup:
|
||||
image: swift-memcache-gsoc:22.04-5.8
|
||||
build:
|
||||
args:
|
||||
ubuntu_version: "jammy"
|
||||
swift_version: "5.8"
|
||||
|
||||
test:
|
||||
image: swift-memcache-gsoc:22.04-5.8
|
||||
environment:
|
||||
- WARN_AS_ERROR_ARG=-Xswiftc -warnings-as-errors
|
||||
- IMPORT_CHECK_ARG=--explicit-target-dependency-import-check error
|
||||
# - SANITIZER_ARG=--sanitize=thread # TSan broken still
|
||||
|
||||
shell:
|
||||
image: swift-memcache-gsoc:22.04-5.8
|
||||
|
||||
update-benchmark-baseline:
|
||||
image: swift-memcache-gsoc:22.04-5.8
|
||||
environment:
|
||||
- SWIFT_VERSION=5.8
|
||||
@@ -21,4 +21,4 @@ services:
|
||||
update-benchmark-baseline:
|
||||
image: swift-memcache-gsoc:22.04-main
|
||||
environment:
|
||||
- SWIFT_VERSION=main
|
||||
- SWIFT_VERSION=main
|
||||
|
||||
@@ -3,14 +3,14 @@ version: "3.9"
|
||||
services:
|
||||
# Swift on Server CI
|
||||
# e.g. docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.2204.57.yaml run test
|
||||
|
||||
|
||||
memcached:
|
||||
image: memcached:latest
|
||||
networks:
|
||||
- memcached
|
||||
ports:
|
||||
- 11211
|
||||
|
||||
- 11211
|
||||
|
||||
runtime-setup:
|
||||
image: swift-memcache-gsoc:default
|
||||
build:
|
||||
@@ -32,8 +32,8 @@ services:
|
||||
test:
|
||||
<<: *common
|
||||
depends_on:
|
||||
- runtime-setup
|
||||
- memcached
|
||||
- runtime-setup
|
||||
- memcached
|
||||
command: /bin/bash -xcl "swift $${SWIFT_TEST_VERB-test} $${WARN_AS_ERROR_ARG-} $${SANITIZER_ARG-} $${IMPORT_CHECK_ARG-} && cd Benchmarks && swift package --disable-sandbox benchmark baseline check --check-absolute-path Thresholds/$${SWIFT_VERSION-}/"
|
||||
networks:
|
||||
- memcached
|
||||
@@ -47,8 +47,8 @@ services:
|
||||
update-benchmark-baseline:
|
||||
<<: *common
|
||||
depends_on:
|
||||
- runtime-setup
|
||||
- memcached
|
||||
- runtime-setup
|
||||
- memcached
|
||||
command: /bin/bash -xcl "cd Benchmarks && swift package --disable-sandbox --scratch-path .build/$${SWIFT_VERSION-}/ --allow-writing-to-package-directory benchmark --format metricP90AbsoluteThresholds --path Thresholds/$${SWIFT_VERSION-}/"
|
||||
|
||||
# dedicated network
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#!/bin/bash
|
||||
##===----------------------------------------------------------------------===##
|
||||
##
|
||||
## This source file is part of the swift-memcache-gsoc open source project
|
||||
##
|
||||
## Copyright (c) 2023 Apple Inc. and the swift-memcache-gsoc project authors
|
||||
## Licensed under Apache License v2.0
|
||||
##
|
||||
## See LICENSE.txt for license information
|
||||
## See CONTRIBUTORS.txt for the list of swift-memcache-gsoc project authors
|
||||
##
|
||||
## SPDX-License-Identifier: Apache-2.0
|
||||
##
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
set -eu
|
||||
here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
contributors=$( cd "$here"/.. && git shortlog -es | cut -f2 | sed 's/^/- /' )
|
||||
|
||||
cat > "$here/../CONTRIBUTORS.txt" <<- EOF
|
||||
For the purpose of tracking copyright, this is the list of individuals and
|
||||
organizations who have contributed source code to swift-memcache-gsoc.
|
||||
|
||||
For employees of an organization/company where the copyright of work done
|
||||
by employees of that company is held by the company itself, only the company
|
||||
needs to be listed here.
|
||||
|
||||
## COPYRIGHT HOLDERS
|
||||
|
||||
- Apple Inc. (all contributors with '@apple.com')
|
||||
|
||||
### Contributors
|
||||
|
||||
$contributors
|
||||
|
||||
**Updating this list**
|
||||
|
||||
Please do not edit this file manually. It is generated using \`./scripts/generate_contributors_list.sh\`. If a name is misspelled or appearing multiple times: add an entry in \`./.mailmap\`
|
||||
EOF
|
||||
@@ -1,179 +0,0 @@
|
||||
#!/bin/bash
|
||||
##===----------------------------------------------------------------------===##
|
||||
##
|
||||
## This source file is part of the swift-memcache-gsoc open source project
|
||||
##
|
||||
## Copyright (c) 2023 Apple Inc. and the swift-memcache-gsoc project authors
|
||||
## Licensed under Apache License v2.0
|
||||
##
|
||||
## See LICENSE.txt for license information
|
||||
## See CONTRIBUTORS.txt for the list of swift-memcache-gsoc project authors
|
||||
##
|
||||
## SPDX-License-Identifier: Apache-2.0
|
||||
##
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
set -eu
|
||||
here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
function replace_acceptable_years() {
|
||||
# this needs to replace all acceptable forms with 'YEARS'
|
||||
sed -e 's/20[12][7890123]-20[12][890123]/YEARS/' -e 's/20[12][890123]/YEARS/'
|
||||
}
|
||||
|
||||
printf "=> Checking for unacceptable language... "
|
||||
# This greps for unacceptable terminology. The square bracket[s] are so that
|
||||
# "git grep" doesn't find the lines that greps :).
|
||||
unacceptable_terms=(
|
||||
-e blacklis[t]
|
||||
-e whitelis[t]
|
||||
-e slav[e]
|
||||
-e sanit[y]
|
||||
)
|
||||
|
||||
# We have to exclude the code of conduct because it gives examples of unacceptable language.
|
||||
exclude_files=(
|
||||
CODE_OF_CONDUCT.md
|
||||
)
|
||||
for word in "${exclude_files[@]}"; do
|
||||
exclude_files+=(":(exclude)$word")
|
||||
done
|
||||
exclude_files_str=$(printf " %s" "${exclude_files[@]}")
|
||||
|
||||
if git grep --color=never -i "${unacceptable_terms[@]}" -- . $exclude_files_str > /dev/null; then
|
||||
printf "\033[0;31mUnacceptable language found.\033[0m\n"
|
||||
git grep -i "${unacceptable_terms[@]}" -- . $exclude_files_str
|
||||
exit 1
|
||||
fi
|
||||
printf "\033[0;32mokay.\033[0m\n"
|
||||
|
||||
printf "=> Checking format... "
|
||||
FIRST_OUT="$(git status --porcelain)"
|
||||
swiftformat . > /dev/null 2>&1
|
||||
SECOND_OUT="$(git status --porcelain)"
|
||||
if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then
|
||||
printf "\033[0;31mformatting issues!\033[0m\n"
|
||||
git --no-pager diff
|
||||
exit 1
|
||||
else
|
||||
printf "\033[0;32mokay.\033[0m\n"
|
||||
fi
|
||||
|
||||
printf "=> Checking license headers... "
|
||||
tmp=$(mktemp /tmp/.swift-memcache-gsoc-soundness_XXXXXX)
|
||||
|
||||
for language in swift-or-c bash dtrace python; do
|
||||
declare -a matching_files
|
||||
declare -a exceptions
|
||||
expections=( )
|
||||
matching_files=( -name '*' )
|
||||
case "$language" in
|
||||
swift-or-c)
|
||||
exceptions=( -name Package.swift )
|
||||
matching_files=( -name '*.swift' -o -name '*.c' -o -name '*.h' )
|
||||
cat > "$tmp" <<"EOF"
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the swift-memcache-gsoc open source project
|
||||
//
|
||||
// Copyright (c) YEARS Apple Inc. and the swift-memcache-gsoc project authors
|
||||
// Licensed under Apache License v2.0
|
||||
//
|
||||
// See LICENSE.txt for license information
|
||||
// See CONTRIBUTORS.txt for the list of swift-memcache-gsoc project authors
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
EOF
|
||||
;;
|
||||
bash)
|
||||
matching_files=( -name '*.sh' )
|
||||
cat > "$tmp" <<"EOF"
|
||||
#!/bin/bash
|
||||
##===----------------------------------------------------------------------===##
|
||||
##
|
||||
## This source file is part of the swift-memcache-gsoc open source project
|
||||
##
|
||||
## Copyright (c) YEARS Apple Inc. and the swift-memcache-gsoc project authors
|
||||
## Licensed under Apache License v2.0
|
||||
##
|
||||
## See LICENSE.txt for license information
|
||||
## See CONTRIBUTORS.txt for the list of swift-memcache-gsoc project authors
|
||||
##
|
||||
## SPDX-License-Identifier: Apache-2.0
|
||||
##
|
||||
##===----------------------------------------------------------------------===##
|
||||
EOF
|
||||
;;
|
||||
python)
|
||||
matching_files=( -name '*.py' )
|
||||
cat > "$tmp" <<"EOF"
|
||||
#!/usr/bin/env python3
|
||||
##===----------------------------------------------------------------------===##
|
||||
##
|
||||
## This source file is part of the swift-memcache-gsoc open source project
|
||||
##
|
||||
## Copyright (c) YEARS Apple Inc. and the swift-memcache-gsoc project authors
|
||||
## Licensed under Apache License v2.0
|
||||
##
|
||||
## See LICENSE.txt for license information
|
||||
## See CONTRIBUTORS.txt for the list of swift-memcache-gsoc project authors
|
||||
##
|
||||
## SPDX-License-Identifier: Apache-2.0
|
||||
##
|
||||
##===----------------------------------------------------------------------===##
|
||||
EOF
|
||||
;;
|
||||
dtrace)
|
||||
matching_files=( -name '*.d' )
|
||||
cat > "$tmp" <<"EOF"
|
||||
#!/usr/sbin/dtrace -q -s
|
||||
/*===----------------------------------------------------------------------===*
|
||||
*
|
||||
* This source file is part of the swift-memcache-gsoc open source project
|
||||
*
|
||||
* Copyright (c) YEARS Apple Inc. and the swift-memcache-gsoc project authors
|
||||
* Licensed under Apache License v2.0
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
* See CONTRIBUTORS.txt for the list of swift-memcache-gsoc project authors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*===----------------------------------------------------------------------===*/
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
echo >&2 "ERROR: unknown language '$language'"
|
||||
;;
|
||||
esac
|
||||
|
||||
expected_lines=$(cat "$tmp" | wc -l)
|
||||
expected_sha=$(cat "$tmp" | shasum)
|
||||
|
||||
(
|
||||
cd "$here/.."
|
||||
{
|
||||
find . \
|
||||
\( \! -path '*/.build/*' -a \
|
||||
\( "${matching_files[@]}" \) -a \
|
||||
\( \! \( "${exceptions[@]}" \) \) \)
|
||||
|
||||
if [[ "$language" = bash ]]; then
|
||||
# add everything with a shell shebang too
|
||||
git grep --full-name -l '#!/bin/bash'
|
||||
git grep --full-name -l '#!/bin/sh'
|
||||
fi
|
||||
} | while read line; do
|
||||
if [[ "$(cat "$line" | replace_acceptable_years | head -n $expected_lines | shasum)" != "$expected_sha" ]]; then
|
||||
printf "\033[0;31mmissing headers in file '$line'!\033[0m\n"
|
||||
diff -u <(cat "$line" | replace_acceptable_years | head -n $expected_lines) "$tmp"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
printf "\033[0;32mokay.\033[0m\n"
|
||||
)
|
||||
done
|
||||
|
||||
rm "$tmp"
|
||||
Reference in New Issue
Block a user