Compare commits

...

44 Commits

Author SHA1 Message Date
Maxim Khatskevich 89e8d109f3 Merge branch 'release/5.4.0' 2021-09-26 00:12:38 +02:00
Maxim Khatskevich 6f014c3ff6 [MAKE] request body/parameters encoding specified per request
plus few other improvements on request customizatons.
2021-09-26 00:12:19 +02:00
Maxim Khatskevich f270e16c6f [IMPROVE] `prepareRequest` method signature
with explicit separation of parameters vs. variables.
2021-09-25 17:34:45 +02:00
Maxim Khatskevich aed7af9dd3 Merge branch 'release/5.3.0' 2021-08-15 19:25:21 +02:00
Maxim Khatskevich 65a4a05ac0 Merge tag '5.3.0' into develop
[FIX] incorrect handling of optional parameters in request definition.
2021-08-15 19:25:21 +02:00
Maxim Khatskevich e228e4beb3 [FIX] incorrect handling of optional parameters in request definition 2021-08-15 19:24:47 +02:00
Maxim Khatskevich 792c159774 [ADD] unit tests to expose incorrect handling of optional parameters in request definition 2021-08-15 19:05:04 +02:00
Maxim Khatskevich 7e99ee5a65 Merge branch 'release/5.2.1' 2021-03-20 21:33:35 +01:00
Maxim Khatskevich 7f323ec75c Merge tag '5.2.1' into develop
Updated CI config with Xcode 12
2021-03-20 21:33:35 +01:00
Maxim Khatskevich 87fd31b2ea [UPDATE] CI config for Swift 5.3 (Xcode 12) 2021-03-20 21:33:09 +01:00
Maxim Khatskevich 79db02c391 Merge branch 'release/5.2.0' 2021-03-20 21:22:12 +01:00
Maxim Khatskevich c72de279d3 Merge tag '5.2.0' into develop
Update configuration with Swift 5.3
2021-03-20 21:22:12 +01:00
Maxim Khatskevich 22e8b5dfe4 [UPDATE] configuration with Swift 5.3 2021-03-20 21:20:38 +01:00
Maxim Khatskevich 1b9d653e57 Merge branch 'release/5.1.1' 2021-03-07 04:02:37 +01:00
Maxim Khatskevich bbaff73a60 Merge tag '5.1.1' into develop
Updated CI config - removed Xcode 10 and added Xcode 12.
2021-03-07 04:02:37 +01:00
Maxim Khatskevich c2245892ce [UPDATE] CI config for Xcode 12 2021-03-07 04:01:41 +01:00
Maxim Khatskevich 782d69a254 Merge branch 'release/5.1.0' 2021-03-07 03:53:24 +01:00
Maxim Khatskevich b489bbd69b Merge tag '5.1.0' into develop
Various renamings, improvements and interface simplifications, plus switched to Swift 5 `Result` type instead of more generic `throw`.
2021-03-07 03:53:24 +01:00
Maxim Khatskevich baee6c080b Merge branch 'feature/update_implementation_swift5' into develop 2021-03-07 03:51:20 +01:00
Maxim Khatskevich b23c11e027 [ADD] inline documentation 2021-03-07 03:51:11 +01:00
Maxim Khatskevich 1a8ef9d80d [MINOR] improvements in ‘ParameterEncoding’ file 2021-03-07 03:11:38 +01:00
Maxim Khatskevich 95067a629b [REPLACE] generic ‘throws’ with ‘Result’ where applicable 2021-03-07 02:55:19 +01:00
Maxim Khatskevich d9ba72a165 [IMPROVE] request builder/definition 2021-03-07 02:11:28 +01:00
Maxim Khatskevich 3943f46a08 [SIMPLIFY] core protocol
Eliminate concrete implementations of “data task” requests and unneessary HTTP requests helpers, plus few other minor improvements and renamings.
2021-03-07 01:41:35 +01:00
Maxim Khatskevich 168e544eae [MINOR] project structure reorganization 2021-03-06 22:42:20 +01:00
Maxim Khatskevich 174b902420 [MINOR] cleanup 2021-03-06 20:46:56 +01:00
Maxim Khatskevich 212ee044c4 Merge branch 'release/5.0.1' 2021-03-06 20:37:19 +01:00
Maxim Khatskevich c6fdecc999 Merge tag '5.0.1' into develop
Updated repo config with Swift 5.3
2021-03-06 20:37:19 +01:00
Maxim Khatskevich 6e917c9f8d [UPDATE] repo configuration with Swift 5.3 2021-03-06 20:32:14 +01:00
Maxim Khatskevich 440fcc418f Merge branch 'release/5.0.0' 2019-08-03 21:46:05 +02:00
Maxim Khatskevich 7b7ff95032 [ADD] ‘TravisCI’ config 2019-08-03 21:39:46 +02:00
Maxim Khatskevich f4540f84de [ADD] modern ‘setup’ script 2019-08-03 21:39:28 +02:00
Maxim Khatskevich cc040c7a69 [REMOVE] usage of ‘Fastlane’ 2019-08-03 21:33:56 +02:00
Maxim Khatskevich d248ae4101 [REMOVE] ‘CocoaPods’ support 2019-08-03 21:33:30 +02:00
Maxim Khatskevich f1f993a64e [REMOVE] ‘SwiftLint’ usage 2019-08-03 21:33:13 +02:00
Maxim Khatskevich f093b2c102 [IMPROVE] folder structure 2019-08-03 21:32:58 +02:00
Maxim Khatskevich 7c5e47c76e [REMOVE] legacy setup script with dependencies 2019-08-03 21:32:10 +02:00
Maxim Khatskevich aa34fe51b6 Merge branch 'release/4.0.3' 2017-09-27 02:51:53 +05:00
Maxim Khatskevich 8af8f58381 Merge tag '4.0.3' into develop
Added helpers for building requests.
2017-09-27 02:51:53 +05:00
Maxim Khatskevich 0c625dbd34 Version Bump to 4.0.3 in Podspec file 2017-09-27 02:51:34 +05:00
Maxim Khatskevich 6546131a00 Version Bump to 4.0.3 (16) 2017-09-27 02:51:34 +05:00
Maxim Khatskevich 3a160ee775 Added license info to all files 2017-09-27 02:50:37 +05:00
Maxim Khatskevich ffb9477d5d Added helpers for building requests 2017-09-27 02:46:56 +05:00
Maxim Khatskevich b8941c4c20 Merge tag '4.0.2' into develop
Important bug fix
2017-09-18 04:15:00 +05:00
68 changed files with 856 additions and 6670 deletions

156
.gitignore vendored
View File

@ -1,14 +1,14 @@
# Created by https://www.gitignore.io/api/osx
### OSX ###
.DS_Store
# ==========
### macOS ###
*.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
# Icon must end with two
Icon
# Thumbnails
._*
@ -19,6 +19,7 @@ Icon
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
@ -27,18 +28,20 @@ Network Trash Folder
Temporary Items
.apdisk
# ================================
# Created by https://www.gitignore.io/api/objective-c
### Objective-C ###
# Xcode
### macOS ###
# ==========
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
#
#
# ==========
### Cocoa ###
# Xcode
## Build generated
build/
DerivedData
DerivedData/
## Various settings
*.pbxuser
@ -49,119 +52,52 @@ DerivedData
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
xcuserdata/
## Other
*.xccheckout
*.moved-aside
*.xcuserstate
*.xccheckout
*.xcscmblueprint
## Obj-C/Swift specific
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
### Objective-C Patch ###
*.xcscmblueprint
## Playgrounds
timeline.xctimeline
playground.xcworkspace
# ================================
# Created by https://www.gitignore.io/api/swift
# Swift Package Manager
### Cocoa ###
# ==========
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
#
#
# ==========
### Swift Package Manager ###
#
Packages/
Package.pins
.swiftpm/
.build/
# ================================
# Generic iOS development
# CocoaPods
### Swift Package Manager ###
# ==========
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
# Pods/
# Podfile.lock
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
fastlane/report.xml
# fastlane/screenshots
# custom fastlane-related addition:
#
Export
# ==========
### Custom repo-specific ###
# ================================
# we don't need to store project file,
# as we generate it on-demand
*.xcodeproj
# Created by https://www.gitignore.io/api/appcode
### AppCode ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# .idea/shelf
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Custom repo-specific ###
# ==========
#
#
#

61
.setup/Package.resolved Normal file
View File

@ -0,0 +1,61 @@
{
"object": {
"pins": [
{
"package": "PathKit",
"repositoryURL": "https://github.com/kylef/PathKit",
"state": {
"branch": null,
"revision": "73f8e9dca9b7a3078cb79128217dc8f2e585a511",
"version": "1.0.0"
}
},
{
"package": "XCERepoConfigurator",
"repositoryURL": "https://github.com/XCEssentials/RepoConfigurator",
"state": {
"branch": null,
"revision": "f08151170b33e38adae5d5271e3d039996638330",
"version": "3.0.4"
}
},
{
"package": "ShellOut",
"repositoryURL": "https://github.com/JohnSundell/ShellOut.git",
"state": {
"branch": null,
"revision": "e1577acf2b6e90086d01a6d5e2b8efdaae033568",
"version": "2.3.0"
}
},
{
"package": "Spectre",
"repositoryURL": "https://github.com/kylef/Spectre.git",
"state": {
"branch": null,
"revision": "f79d4ecbf8bc4e1579fbd86c3e1d652fb6876c53",
"version": "0.9.2"
}
},
{
"package": "SwiftHamcrest",
"repositoryURL": "https://github.com/nschum/SwiftHamcrest",
"state": {
"branch": null,
"revision": "8293762e84a6d59f0742d6f9bc94132accfc31f9",
"version": "2.2.2"
}
},
{
"package": "Version",
"repositoryURL": "https://github.com/mxcl/Version.git",
"state": {
"branch": null,
"revision": "200046c93f6d5d78a6d72bfd9c0b27a95e9c0a2b",
"version": "1.2.0"
}
}
]
},
"version": 1
}

32
.setup/Package.swift Normal file
View File

@ -0,0 +1,32 @@
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "APIClientSetup",
platforms: [
.macOS(.v10_11),
],
dependencies: [
.package(
name: "PathKit",
url: "https://github.com/kylef/PathKit",
from: "1.0.0"
),
.package(
name: "XCERepoConfigurator",
url: "https://github.com/XCEssentials/RepoConfigurator",
from: "3.0.0"
)
],
targets: [
.target(
name: "APIClientSetup",
dependencies: [
"XCERepoConfigurator",
"PathKit"
],
path: "Setup"
)
]
)

187
.setup/Setup/main.swift Normal file
View File

@ -0,0 +1,187 @@
import PathKit
import XCERepoConfigurator
// MARK: - PRE-script invocation output
print("\n")
print("--- BEGIN of '\(Executable.name)' script ---")
// MARK: -
// MARK: Parameters
Spec.BuildSettings.swiftVersion.value = "5.3"
let localRepo = try Spec.LocalRepo.current()
let remoteRepo = try Spec.RemoteRepo(
accountName: localRepo.context,
name: localRepo.name
)
let travisCI = (
address: "https://travis-ci.com/\(remoteRepo.accountName)/\(remoteRepo.name)",
branch: "master"
)
let company = (
prefix: "XCE",
name: remoteRepo.accountName
)
let project = (
name: remoteRepo.name,
summary: "Lightweight HTTP-based API client",
copyrightYear: 2016
)
let productName = company.prefix + project.name
let authors = [
("Maxim Khatskevich", "maxim@khatskevi.ch")
]
typealias PerSubSpec<T> = (
core: T,
tests: T
)
let subSpecs: PerSubSpec = (
"Core",
"AllTests"
)
let targetNames: PerSubSpec = (
productName,
productName + subSpecs.tests
)
let sourcesLocations: PerSubSpec = (
Spec.Locations.sources + subSpecs.core,
Spec.Locations.tests + subSpecs.tests
)
// MARK: Parameters - Summary
localRepo.report()
remoteRepo.report()
// MARK: -
// MARK: Write - ReadMe
try ReadMe()
.addGitHubLicenseBadge(
account: company.name,
repo: project.name
)
.addGitHubTagBadge(
account: company.name,
repo: project.name
)
.addSwiftPMCompatibleBadge()
.addWrittenInSwiftBadge(
version: Spec.BuildSettings.swiftVersion.value
)
.addStaticShieldsBadge(
"platforms",
status: "macOS | iOS | tvOS | watchOS | Linux",
color: "blue",
title: "Supported platforms",
link: "Package.swift"
)
.add("""
[![Build Status](\(travisCI.address).svg?branch=\(travisCI.branch))](\(travisCI.address))
"""
)
.add("""
# \(project.name)
\(project.summary)
"""
)
.prepare(
removeRepeatingEmptyLines: false
)
.writeToFileSystem(
ifFileExists: .skip
)
// MARK: Write - License
try License
.MIT(
copyrightYear: UInt(project.copyrightYear),
copyrightEntity: authors.map{ $0.0 }.joined(separator: ", ")
)
.prepare()
.writeToFileSystem()
// MARK: Write - GitHub - PagesConfig
try GitHub
.PagesConfig()
.prepare()
.writeToFileSystem()
// MARK: Write - Git - .gitignore
try Git
.RepoIgnore()
.addMacOSSection()
.addCocoaSection()
.addSwiftPackageManagerSection(ignoreSources: true)
.add(
"""
# we don't need to store project file,
# as we generate it on-demand
*.\(Xcode.Project.extension)
"""
)
.prepare()
.writeToFileSystem()
// MARK: Write - Package.swift
try CustomTextFile("""
// swift-tools-version:\(Spec.BuildSettings.swiftVersion.value)
import PackageDescription
let package = Package(
name: "\(productName)",
products: [
.library(
name: "\(productName)",
targets: [
"\(targetNames.core)"
]
)
],
targets: [
.target(
name: "\(targetNames.core)",
path: "\(sourcesLocations.core)"
),
.testTarget(
name: "\(targetNames.tests)",
dependencies: [
"\(targetNames.core)"
],
path: "\(sourcesLocations.tests)"
),
]
)
"""
)
.prepare(
at: ["Package.swift"]
)
.writeToFileSystem()
// MARK: - POST-script invocation output
print("--- END of '\(Executable.name)' script ---")

View File

@ -1 +0,0 @@
3.1

View File

@ -1,20 +0,0 @@
disabled_rules: # rule identifiers to exclude from running
- opening_brace
- nesting
- large_tuple
# - trailing_whitespace # remove this later!!!
excluded: # paths to ignore during linting. Takes precedence over `included`.
- Resources
- Carthage
- Pods
# # configurable rules can be customized from this configuration file
# # binary rules can set their severity level
line_length:
ignores_comments: true
trailing_whitespace:
ignores_empty_lines: true
type_name:
allowed_symbols: _
statement_position:
statement_mode: uncuddled_else # https://github.com/realm/SwiftLint/issues/1181#issuecomment-272445593

26
.travis.yml Normal file
View File

@ -0,0 +1,26 @@
# https://docs.travis-ci.com/user/customizing-the-build/
# https://docs.travis-ci.com/user/job-lifecycle/#the-job-lifecycle
# https://docs.travis-ci.com/user/languages/objective-c/
branches:
only:
- master
- /^hotfix.*$/
- /^release.*$/
- /^feature.*$/
git:
depth: 3
submodules: false
language: objective-c # fine for Swift as well
osx_image:
- xcode12
before_script:
# cd ./.setup && swift run && cd ./.. # RUN this manually!
- swift --version
script:
- swift test

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:README.md">
</FileRef>
<FileRef
location = "group:Main.xcodeproj">
</FileRef>
</Workspace>

View File

@ -1 +0,0 @@
github "XCEssentials/ProjectGenerator" ~> 2.1

View File

@ -1 +0,0 @@
github "XCEssentials/ProjectGenerator" "2.1.4"

View File

@ -1,167 +0,0 @@
# Created by https://www.gitignore.io/api/osx
### OSX ###
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# ================================
# Created by https://www.gitignore.io/api/objective-c
### Objective-C ###
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
## Other
*.xccheckout
*.moved-aside
*.xcuserstate
*.xcscmblueprint
## Obj-C/Swift specific
*.hmap
*.ipa
### Objective-C Patch ###
*.xcscmblueprint
# ================================
# Created by https://www.gitignore.io/api/swift
# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
.build/
# ================================
# Generic iOS development
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
Pods/
Podfile.lock
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
fastlane/report.xml
# fastlane/screenshots
# custom fastlane-related addition:
#
Export
# ================================
# Created by https://www.gitignore.io/api/appcode
### AppCode ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# .idea/shelf
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

View File

@ -1,99 +0,0 @@
import XCEProjectGenerator
//===
let params =
(
repoName: "MyAwesomeFramework",
deploymentTarget: "8.0",
companyIdentifier: "khatskevich.maxim",
developmentTeamId: "UJA88X59XP" // 'Maxim Khatskevich'
)
let bundleId =
(
fwk: "\(params.companyIdentifier).\(params.repoName)",
tst: "\(params.companyIdentifier).\(params.repoName).Tst"
)
//===
let specFormat = Spec.Format.v2_1_0
let project = Project(params.repoName) { project in
project.configurations.all.override(
"IPHONEOS_DEPLOYMENT_TARGET" <<< params.deploymentTarget, // bug wokraround
"DEVELOPMENT_TEAM" <<< params.developmentTeamId,
"SWIFT_VERSION" <<< "3.0",
"VERSIONING_SYSTEM" <<< "apple-generic"
)
project.configurations.debug.override(
"SWIFT_OPTIMIZATION_LEVEL" <<< "-Onone"
)
//---
project.target("App", .iOS, .framework) { app in
app.include("Src")
//---
app.configurations.all.override(
"IPHONEOS_DEPLOYMENT_TARGET" <<< params.deploymentTarget, // bug wokraround
"PRODUCT_BUNDLE_IDENTIFIER" <<< bundleId.fwk,
"INFOPLIST_FILE" <<< "Info/Fwk.plist",
//--- iOS related:
"SDKROOT" <<< "iphoneos",
"TARGETED_DEVICE_FAMILY" <<< DeviceFamily.iOS.universal,
//--- Framework related:
"DEFINES_MODULE" <<< "NO",
"SKIP_INSTALL" <<< "YES"
)
app.configurations.debug.override(
"MTL_ENABLE_DEBUG_INFO" <<< true
)
//---
app.unitTests { appTests in
appTests.include("Tst")
//---
appTests.configurations.all.override(
// very important for unit tests,
// prevents the error when unit test do not start at all
"LD_RUNPATH_SEARCH_PATHS" <<<
"$(inherited) @executable_path/Frameworks @loader_path/Frameworks",
"IPHONEOS_DEPLOYMENT_TARGET" <<< params.deploymentTarget, // bug wokraround
"PRODUCT_BUNDLE_IDENTIFIER" <<< bundleId.tst,
"INFOPLIST_FILE" <<< "Info/Tst.plist",
"FRAMEWORK_SEARCH_PATHS" <<< "$(inherited) $(BUILT_PRODUCTS_DIR)"
)
appTests.configurations.debug.override(
"MTL_ENABLE_DEBUG_INFO" <<< true
)
}
}
}

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.1.4</string>
<key>CFBundleVersion</key>
<string>17</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2017 Maxim Khatskevich. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2017 Maxim Khatskevich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,26 +0,0 @@
//
// main.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/15/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
import Foundation
import XCEProjectGenerator
//===
let specData =
Manager.prepareSpec(specFormat, for: project)
.data(using: .utf8)
let targetPath = "\(CommandLine.arguments[1])/project.yml"
FileManager
.default
.createFile(
atPath: targetPath,
contents: specData,
attributes: nil)

View File

@ -1,687 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
943179991E7D82D500F3796D /* Project.Struct.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943179981E7D820C00F3796D /* Project.Struct.swift */; };
943C0C291E7B14CB00C8DF86 /* MKHProjGen.h in Headers */ = {isa = PBXBuildFile; fileRef = 943C0C141E7B141400C8DF86 /* MKHProjGen.h */; settings = {ATTRIBUTES = (Public, ); }; };
943C0C4C1E7B198D00C8DF86 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943C0C4A1E7B198D00C8DF86 /* main.swift */; };
9479E3351EDD4AA5006CCC68 /* Spec.2.0.0.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9479E3341EDD4AA5006CCC68 /* Spec.2.0.0.swift */; };
94848C011EF994E300EA3F4C /* Spec.2.1.0.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94848C001EF994E300EA3F4C /* Spec.2.1.0.swift */; };
949521F41E7B2A2C00812390 /* XCEProjectGenerator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 943C0C021E7B134500C8DF86 /* XCEProjectGenerator.framework */; };
9495220B1E7BF62A00812390 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943C0C4A1E7B198D00C8DF86 /* main.swift */; };
9495220D1E7BF62A00812390 /* XCEProjectGenerator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 943C0C021E7B134500C8DF86 /* XCEProjectGenerator.framework */; };
949522131E7BF66C00812390 /* Spec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943C0C481E7B198D00C8DF86 /* Spec.swift */; };
949BB45C1E87E43E008F599B /* Device.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB4491E87E43E008F599B /* Device.swift */; };
949BB45D1E87E43E008F599B /* Manager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB44A1E87E43E008F599B /* Manager.swift */; };
949BB45E1E87E43E008F599B /* Misc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB44B1E87E43E008F599B /* Misc.swift */; };
949BB45F1E87E43E008F599B /* Platform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB44C1E87E43E008F599B /* Platform.swift */; };
949BB4601E87E43E008F599B /* Project.BuildConfig.Defaults.General.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB44E1E87E43E008F599B /* Project.BuildConfig.Defaults.General.swift */; };
949BB4611E87E43E008F599B /* Project.BuildConfig.Defaults.iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB44F1E87E43E008F599B /* Project.BuildConfig.Defaults.iOS.swift */; };
949BB4621E87E43E008F599B /* Project.BuildConfig.Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB4501E87E43E008F599B /* Project.BuildConfig.Defaults.swift */; };
949BB4631E87E43E008F599B /* Project.BuildConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB4511E87E43E008F599B /* Project.BuildConfig.swift */; };
949BB4641E87E43E008F599B /* Project.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB4521E87E43E008F599B /* Project.swift */; };
949BB4651E87E43E008F599B /* Spec.1.2.1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB4541E87E43E008F599B /* Spec.1.2.1.swift */; };
949BB4661E87E43E008F599B /* Spec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB4551E87E43E008F599B /* Spec.swift */; };
949BB4671E87E43E008F599B /* Target.BuildConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB4571E87E43E008F599B /* Target.BuildConfig.swift */; };
949BB4681E87E43E008F599B /* Target.Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB4581E87E43E008F599B /* Target.Dependencies.swift */; };
949BB4691E87E43E008F599B /* Target.Script.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB4591E87E43E008F599B /* Target.Script.swift */; };
949BB46A1E87E43E008F599B /* Target.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB45A1E87E43E008F599B /* Target.swift */; };
949BB46B1E87E43E008F599B /* Target.Type.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB45B1E87E43E008F599B /* Target.Type.swift */; };
949BB46D1E87E96A008F599B /* Spec.1.3.0.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BB46C1E87E96A008F599B /* Spec.1.3.0.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
949521F21E7B2A2600812390 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 943C0BF91E7B134500C8DF86 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 943C0C011E7B134500C8DF86;
remoteInfo = MKHProjGen;
};
949522091E7BF62A00812390 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 943C0BF91E7B134500C8DF86 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 943C0C011E7B134500C8DF86;
remoteInfo = MKHProjGen;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
943C0C3E1E7B196200C8DF86 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
9495220E1E7BF62A00812390 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
943179981E7D820C00F3796D /* Project.Struct.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Project.Struct.swift; path = ../../../../Project.Struct.swift; sourceTree = "<group>"; };
943C0C021E7B134500C8DF86 /* XCEProjectGenerator.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = XCEProjectGenerator.framework; sourceTree = BUILT_PRODUCTS_DIR; };
943C0C141E7B141400C8DF86 /* MKHProjGen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKHProjGen.h; sourceTree = "<group>"; };
943C0C401E7B196200C8DF86 /* Launcher */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Launcher; sourceTree = BUILT_PRODUCTS_DIR; };
943C0C481E7B198D00C8DF86 /* Spec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Spec.swift; sourceTree = "<group>"; };
943C0C4A1E7B198D00C8DF86 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
9479E3341EDD4AA5006CCC68 /* Spec.2.0.0.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Spec.2.0.0.swift; sourceTree = "<group>"; };
94848C001EF994E300EA3F4C /* Spec.2.1.0.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Spec.2.1.0.swift; sourceTree = "<group>"; };
949522121E7BF62A00812390 /* Example */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Example; sourceTree = BUILT_PRODUCTS_DIR; };
949BB4491E87E43E008F599B /* Device.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Device.swift; sourceTree = "<group>"; };
949BB44A1E87E43E008F599B /* Manager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Manager.swift; sourceTree = "<group>"; };
949BB44B1E87E43E008F599B /* Misc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Misc.swift; sourceTree = "<group>"; };
949BB44C1E87E43E008F599B /* Platform.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Platform.swift; sourceTree = "<group>"; };
949BB44E1E87E43E008F599B /* Project.BuildConfig.Defaults.General.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Project.BuildConfig.Defaults.General.swift; sourceTree = "<group>"; };
949BB44F1E87E43E008F599B /* Project.BuildConfig.Defaults.iOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Project.BuildConfig.Defaults.iOS.swift; sourceTree = "<group>"; };
949BB4501E87E43E008F599B /* Project.BuildConfig.Defaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Project.BuildConfig.Defaults.swift; sourceTree = "<group>"; };
949BB4511E87E43E008F599B /* Project.BuildConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Project.BuildConfig.swift; sourceTree = "<group>"; };
949BB4521E87E43E008F599B /* Project.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Project.swift; sourceTree = "<group>"; };
949BB4541E87E43E008F599B /* Spec.1.2.1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Spec.1.2.1.swift; sourceTree = "<group>"; };
949BB4551E87E43E008F599B /* Spec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Spec.swift; sourceTree = "<group>"; };
949BB4571E87E43E008F599B /* Target.BuildConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Target.BuildConfig.swift; sourceTree = "<group>"; };
949BB4581E87E43E008F599B /* Target.Dependencies.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Target.Dependencies.swift; sourceTree = "<group>"; };
949BB4591E87E43E008F599B /* Target.Script.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Target.Script.swift; sourceTree = "<group>"; };
949BB45A1E87E43E008F599B /* Target.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Target.swift; sourceTree = "<group>"; };
949BB45B1E87E43E008F599B /* Target.Type.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Target.Type.swift; sourceTree = "<group>"; };
949BB46C1E87E96A008F599B /* Spec.1.3.0.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Spec.1.3.0.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
943C0BFE1E7B134500C8DF86 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
943C0C3D1E7B196200C8DF86 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
949521F41E7B2A2C00812390 /* XCEProjectGenerator.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9495220C1E7BF62A00812390 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9495220D1E7BF62A00812390 /* XCEProjectGenerator.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
943C0BF81E7B134500C8DF86 = {
isa = PBXGroup;
children = (
943C0C471E7B198D00C8DF86 /* Example */,
943C0C491E7B198D00C8DF86 /* Launcher */,
949BB4481E87E43E008F599B /* Src */,
943C0C131E7B141400C8DF86 /* Src-Extra */,
943C0C031E7B134500C8DF86 /* Products */,
);
sourceTree = "<group>";
};
943C0C031E7B134500C8DF86 /* Products */ = {
isa = PBXGroup;
children = (
943C0C021E7B134500C8DF86 /* XCEProjectGenerator.framework */,
943C0C401E7B196200C8DF86 /* Launcher */,
949522121E7BF62A00812390 /* Example */,
);
name = Products;
sourceTree = "<group>";
};
943C0C131E7B141400C8DF86 /* Src-Extra */ = {
isa = PBXGroup;
children = (
943C0C141E7B141400C8DF86 /* MKHProjGen.h */,
);
path = "Src-Extra";
sourceTree = "<group>";
};
943C0C471E7B198D00C8DF86 /* Example */ = {
isa = PBXGroup;
children = (
943C0C481E7B198D00C8DF86 /* Spec.swift */,
);
path = Example;
sourceTree = "<group>";
};
943C0C491E7B198D00C8DF86 /* Launcher */ = {
isa = PBXGroup;
children = (
943C0C4A1E7B198D00C8DF86 /* main.swift */,
943179981E7D820C00F3796D /* Project.Struct.swift */,
);
path = Launcher;
sourceTree = "<group>";
};
949BB4481E87E43E008F599B /* Src */ = {
isa = PBXGroup;
children = (
949BB4491E87E43E008F599B /* Device.swift */,
949BB44A1E87E43E008F599B /* Manager.swift */,
949BB44B1E87E43E008F599B /* Misc.swift */,
949BB44C1E87E43E008F599B /* Platform.swift */,
949BB44D1E87E43E008F599B /* Project */,
949BB4531E87E43E008F599B /* Spec */,
949BB4561E87E43E008F599B /* Target */,
);
path = Src;
sourceTree = "<group>";
};
949BB44D1E87E43E008F599B /* Project */ = {
isa = PBXGroup;
children = (
949BB44E1E87E43E008F599B /* Project.BuildConfig.Defaults.General.swift */,
949BB44F1E87E43E008F599B /* Project.BuildConfig.Defaults.iOS.swift */,
949BB4501E87E43E008F599B /* Project.BuildConfig.Defaults.swift */,
949BB4511E87E43E008F599B /* Project.BuildConfig.swift */,
949BB4521E87E43E008F599B /* Project.swift */,
);
path = Project;
sourceTree = "<group>";
};
949BB4531E87E43E008F599B /* Spec */ = {
isa = PBXGroup;
children = (
949BB4551E87E43E008F599B /* Spec.swift */,
949BB4541E87E43E008F599B /* Spec.1.2.1.swift */,
949BB46C1E87E96A008F599B /* Spec.1.3.0.swift */,
9479E3341EDD4AA5006CCC68 /* Spec.2.0.0.swift */,
94848C001EF994E300EA3F4C /* Spec.2.1.0.swift */,
);
path = Spec;
sourceTree = "<group>";
};
949BB4561E87E43E008F599B /* Target */ = {
isa = PBXGroup;
children = (
949BB4571E87E43E008F599B /* Target.BuildConfig.swift */,
949BB4581E87E43E008F599B /* Target.Dependencies.swift */,
949BB4591E87E43E008F599B /* Target.Script.swift */,
949BB45A1E87E43E008F599B /* Target.swift */,
949BB45B1E87E43E008F599B /* Target.Type.swift */,
);
path = Target;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
943C0BFF1E7B134500C8DF86 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
943C0C291E7B14CB00C8DF86 /* MKHProjGen.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
943C0C011E7B134500C8DF86 /* ProjectGenerator */ = {
isa = PBXNativeTarget;
buildConfigurationList = 943C0C0A1E7B134500C8DF86 /* Build configuration list for PBXNativeTarget "ProjectGenerator" */;
buildPhases = (
943C0BFD1E7B134500C8DF86 /* Sources */,
943C0BFE1E7B134500C8DF86 /* Frameworks */,
943C0BFF1E7B134500C8DF86 /* Headers */,
943C0C001E7B134500C8DF86 /* Resources */,
943C0C791E7B258700C8DF86 /* BuildStatic */,
);
buildRules = (
);
dependencies = (
);
name = ProjectGenerator;
productName = MKHProjGen;
productReference = 943C0C021E7B134500C8DF86 /* XCEProjectGenerator.framework */;
productType = "com.apple.product-type.framework";
};
943C0C3F1E7B196200C8DF86 /* Launcher */ = {
isa = PBXNativeTarget;
buildConfigurationList = 943C0C441E7B196200C8DF86 /* Build configuration list for PBXNativeTarget "Launcher" */;
buildPhases = (
943C0C3C1E7B196200C8DF86 /* Sources */,
943C0C3D1E7B196200C8DF86 /* Frameworks */,
943C0C3E1E7B196200C8DF86 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
949521F31E7B2A2600812390 /* PBXTargetDependency */,
);
name = Launcher;
productName = MKHProjGenLauncher;
productReference = 943C0C401E7B196200C8DF86 /* Launcher */;
productType = "com.apple.product-type.tool";
};
949522071E7BF62A00812390 /* Example */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9495220F1E7BF62A00812390 /* Build configuration list for PBXNativeTarget "Example" */;
buildPhases = (
9495220A1E7BF62A00812390 /* Sources */,
9495220C1E7BF62A00812390 /* Frameworks */,
9495220E1E7BF62A00812390 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
949522081E7BF62A00812390 /* PBXTargetDependency */,
);
name = Example;
productName = MKHProjGenLauncher;
productReference = 949522121E7BF62A00812390 /* Example */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
943C0BF91E7B134500C8DF86 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0820;
LastUpgradeCheck = 0820;
ORGANIZATIONNAME = "Maxim Khatskevich";
TargetAttributes = {
943C0C011E7B134500C8DF86 = {
CreatedOnToolsVersion = 8.2.1;
DevelopmentTeam = UJA88X59XP;
ProvisioningStyle = Automatic;
};
943C0C3F1E7B196200C8DF86 = {
CreatedOnToolsVersion = 8.2.1;
DevelopmentTeam = UJA88X59XP;
ProvisioningStyle = Automatic;
};
949522071E7BF62A00812390 = {
DevelopmentTeam = UJA88X59XP;
};
};
};
buildConfigurationList = 943C0BFC1E7B134500C8DF86 /* Build configuration list for PBXProject "ProjectGenerator" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 943C0BF81E7B134500C8DF86;
productRefGroup = 943C0C031E7B134500C8DF86 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
943C0C011E7B134500C8DF86 /* ProjectGenerator */,
943C0C3F1E7B196200C8DF86 /* Launcher */,
949522071E7BF62A00812390 /* Example */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
943C0C001E7B134500C8DF86 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
943C0C791E7B258700C8DF86 /* BuildStatic */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"$(LD_DEPENDENCY_INFO_FILE)",
);
name = BuildStatic;
outputPaths = (
"$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_PATH)",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "#!/bin/sh\n\ncd \"$BUILT_PRODUCTS_DIR\"\n\narchs=( $ARCHS ) lfls=()\nfor v in \"${archs[@]/#/LINK_FILE_LIST_${CURRENT_VARIANT}_}\"; do\nlfls+=( -filelist \"${!v}\" )\ndone\n\nlibtool -static -syslibroot \"$SDKROOT\" -L. \"${lfls[@]}\" -o \"$EXECUTABLE_PATH\"";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
943C0BFD1E7B134500C8DF86 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
949BB45D1E87E43E008F599B /* Manager.swift in Sources */,
949BB46D1E87E96A008F599B /* Spec.1.3.0.swift in Sources */,
9479E3351EDD4AA5006CCC68 /* Spec.2.0.0.swift in Sources */,
949BB45F1E87E43E008F599B /* Platform.swift in Sources */,
94848C011EF994E300EA3F4C /* Spec.2.1.0.swift in Sources */,
949BB45C1E87E43E008F599B /* Device.swift in Sources */,
949BB45E1E87E43E008F599B /* Misc.swift in Sources */,
949BB46A1E87E43E008F599B /* Target.swift in Sources */,
949BB4671E87E43E008F599B /* Target.BuildConfig.swift in Sources */,
949BB4681E87E43E008F599B /* Target.Dependencies.swift in Sources */,
949BB4691E87E43E008F599B /* Target.Script.swift in Sources */,
949BB46B1E87E43E008F599B /* Target.Type.swift in Sources */,
949BB4641E87E43E008F599B /* Project.swift in Sources */,
949BB4631E87E43E008F599B /* Project.BuildConfig.swift in Sources */,
949BB4621E87E43E008F599B /* Project.BuildConfig.Defaults.swift in Sources */,
949BB4611E87E43E008F599B /* Project.BuildConfig.Defaults.iOS.swift in Sources */,
949BB4601E87E43E008F599B /* Project.BuildConfig.Defaults.General.swift in Sources */,
949BB4661E87E43E008F599B /* Spec.swift in Sources */,
949BB4651E87E43E008F599B /* Spec.1.2.1.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
943C0C3C1E7B196200C8DF86 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
943C0C4C1E7B198D00C8DF86 /* main.swift in Sources */,
943179991E7D82D500F3796D /* Project.Struct.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9495220A1E7BF62A00812390 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
949522131E7BF66C00812390 /* Spec.swift in Sources */,
9495220B1E7BF62A00812390 /* main.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
949521F31E7B2A2600812390 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 943C0C011E7B134500C8DF86 /* ProjectGenerator */;
targetProxy = 949521F21E7B2A2600812390 /* PBXContainerItemProxy */;
};
949522081E7BF62A00812390 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 943C0C011E7B134500C8DF86 /* ProjectGenerator */;
targetProxy = 949522091E7BF62A00812390 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
943C0C081E7B134500C8DF86 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 17;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
943C0C091E7B134500C8DF86 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 17;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
943C0C0B1E7B134500C8DF86 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = UJA88X59XP;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 17;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = Info/Fwk.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.XCEssentials.ProjectGenerator;
PRODUCT_NAME = XCEProjectGenerator;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
943C0C0C1E7B134500C8DF86 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = UJA88X59XP;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 17;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = Info/Fwk.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.XCEssentials.ProjectGenerator;
PRODUCT_NAME = XCEProjectGenerator;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Release;
};
943C0C451E7B196200C8DF86 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "Mac Developer";
DEVELOPMENT_TEAM = UJA88X59XP;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)",
);
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
"$(inherited)",
"-all_load",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
943C0C461E7B196200C8DF86 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "Mac Developer";
DEVELOPMENT_TEAM = UJA88X59XP;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)",
);
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
"$(inherited)",
"-all_load",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
949522101E7BF62A00812390 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "Mac Developer";
DEVELOPMENT_TEAM = UJA88X59XP;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)",
);
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
"$(inherited)",
"-all_load",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
949522111E7BF62A00812390 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "Mac Developer";
DEVELOPMENT_TEAM = UJA88X59XP;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)",
);
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
"$(inherited)",
"-all_load",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
943C0BFC1E7B134500C8DF86 /* Build configuration list for PBXProject "ProjectGenerator" */ = {
isa = XCConfigurationList;
buildConfigurations = (
943C0C081E7B134500C8DF86 /* Debug */,
943C0C091E7B134500C8DF86 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
943C0C0A1E7B134500C8DF86 /* Build configuration list for PBXNativeTarget "ProjectGenerator" */ = {
isa = XCConfigurationList;
buildConfigurations = (
943C0C0B1E7B134500C8DF86 /* Debug */,
943C0C0C1E7B134500C8DF86 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
943C0C441E7B196200C8DF86 /* Build configuration list for PBXNativeTarget "Launcher" */ = {
isa = XCConfigurationList;
buildConfigurations = (
943C0C451E7B196200C8DF86 /* Debug */,
943C0C461E7B196200C8DF86 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9495220F1E7BF62A00812390 /* Build configuration list for PBXNativeTarget "Example" */ = {
isa = XCConfigurationList;
buildConfigurations = (
949522101E7BF62A00812390 /* Debug */,
949522111E7BF62A00812390 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 943C0BF91E7B134500C8DF86 /* Project object */;
}

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:/Users/maxim/Dev/XCEssentials/ProjectGenerator/ProjectGenerator.xcodeproj">
</FileRef>
</Workspace>

View File

@ -1,99 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0820"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "943C0C3F1E7B196200C8DF86"
BuildableName = "Launcher"
BlueprintName = "Launcher"
ReferencedContainer = "container:ProjectGenerator.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "943C0C3F1E7B196200C8DF86"
BuildableName = "Launcher"
BlueprintName = "Launcher"
ReferencedContainer = "container:ProjectGenerator.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "943C0C3F1E7B196200C8DF86"
BuildableName = "Launcher"
BlueprintName = "Launcher"
ReferencedContainer = "container:ProjectGenerator.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "&quot;$(SRCROOT)/../../..&quot;"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "943C0C3F1E7B196200C8DF86"
BuildableName = "Launcher"
BlueprintName = "Launcher"
ReferencedContainer = "container:ProjectGenerator.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,92 +0,0 @@
[![GitHub tag](https://img.shields.io/github/tag/XCEssentials/ProjectGenerator.svg)](https://github.com/XCEssentials/FunctionalState/releases)
[![license](https://img.shields.io/github/license/XCEssentials/ProjectGenerator.svg)](https://opensource.org/licenses/MIT)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
# Introduction
Describe Xcode project declaratively in pure Swift.
# Problem
Xcode uses an undocumented proprietary format for describing project structure, settings, etc. in **`*.xcodeproj`** files. That kind of file is hard to read and understand for a human, impossible to merge without merge conflicts if changes were made on two different local copies of the same repo/project, or even on different branches inside the same repo on the same workstation. That makes working together on the same Xcode project file a nightmare, when you need to merge changes "*.xcodeproj" always has conflicts and developers have to resolve them manually, wasting lots of time for routine that might be done by computer. We need a better solution!
# Existing solution
There is a command line tool that allows developer to write project specification in a form of plain text configuration file (using Ruby or YAML) and then generate **`*.xcodeproj`** file on the fly from this specification - [Struct](https://github.com/workshop/struct).
The specification file format features very concise hierarchic notation that's easy and intuitive, and you only need to specify explicitly settings which can not be inferred somehow or you need a value that differs from defaults (provided by the tool itself or, most often, by Xcode).
For vast majority of iOS developers, this tool should be already a good enough solution, but there are still few inconveniences:
- you have to learn a new language/syntax (not every iOS developer knows Ruby and feel comfortable to deal with it on daily basis);
- you need to leave Xcode and switch to another text editor with proper syntax highlight for Ruby/YAML to edit the specification file, because Xcode does not support YAML and have limited syntax highligh for Ruby;
- due to nature of Ruby/YAML, you do not have development time syntax check, you have to try to run the tool in order to disciover a syntax error in your specification.
# Wishlist
Based on the downsides of Struct listed above, here is a list of wishes for an "ideal" tool like that:
- write project specification in pure Swift;
- use Xcode to edit specification file;
- get full syntax highlight and real time syntax check in specification file.
# About this tool
To archive the goals listed above, this project has been made. Think of it as a thin wrapper on top of [Struct](https://github.com/workshop/struct) CLI tool. It brings no extra functionality in comparison with [Struct](https://github.com/workshop/struct), but adds some convenience to writing project file specification.
# How to install
Use [Carthage](https://github.com/Carthage/Carthage) to install the tool into your project. Put into your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile):
```ruby
github "XCEssentials/ProjectGenerator" ~> 2.1
```
The project folder will be downloaded by [Carthage](https://github.com/Carthage/Carthage), but nothing will be built, that's expected behavior, ignor warnings from Carthage.
# How it is organized
**Remember**, you are not supposed to make any changes in the project, except your project specification file.
The poject consists of 3 main parts, each of them has its own scheme:
1. Scheme **"Fwk"** - macOS framework that implements functionality related to parsing your Swift specification file and writing target specification file in YAML for [Struct](https://github.com/workshop/struct).
2. Scheme **"Launcher"** - a command line tool that gets the job done. It includes the framework module as dependency and starts the process of parsing your Swift specification file into [Struct](https://github.com/workshop/struct) YAML spec file. This target contains just 2 source files. First one is the **`main.swift`** file, it will be executed when the target will be run in Xcode. Second file is **`Project.Struct.swift`** and it's missing in the project out of the box intentinonally. It's expected location is in your project root directory (given that `ProjectGenerator` is installed with [Carthage](https://github.com/Carthage/Carthage)) and it's your responsibility to put this file there.
3. Scheme **"Example"** - very similar to the "Launcher" scheme, with only difference that it contains a sample Swift project specification file with all the necessery statements isnside. Use this sample Swift specification file as starting point for your project specification.
# How to start using
If using first time:
1. copy the [sample file](https://github.com/XCEssentials/ProjectGenerator/blob/master/Example/Spec.swift) from [Example](https://github.com/XCEssentials/ProjectGenerator/tree/master/Example) folder to your project root folder and rename it with **`Project.Struct.swift`**;
2. open the project (from your project root folder, go to `./Carthage/Checkouts/ProjectGenerator`, open file `ProjectGenerator.xcodeproj`), make sure that you have the `Launcher` scheme selected (notice, that if you've done everything correctly at the previous step, the `Project.Struct.swift` under `Launcher` group on Project Navigator panel will be in place, not missing);
3. make initial editing of the `Project.Struct.swift` file to describe at least basic structure for your project;
4. when project specification is ready, just hit "Cmd+R" hotkey in Xcode (Run the scheme), Xcode will build and run the scheme, a new file named `project.yml` will be created at project root folder. That's it!
To actually generate project file from the created `project.yml` file - use Struct itself from your project root folder.
# How to use
When yoiu need to make a change into your project configuration:
1. open the project (from your project root folder, go to `./Carthage/Checkouts/ProjectGenerator`, open file `ProjectGenerator.xcodeproj`), make sure that you have the `Launcher` scheme selected;
2. make the necessary changes in the `Project.Struct.swift` file;
3. run the scheme, a new file named `project.yml` will be created at project root folder (will override previous version).
To actually (re)generate project file from the newly created `project.yml` file - use Struct itself from your project root folder.
# Notes on versioning
This project follows [Semantic Versioning](http://semver.org), its MAJOR (and MINOR, when possible) version number is syncronized with corresponding version numbers of the [Struct](https://github.com/workshop/struct) specification format, which is used as blueprint for the output YAML project specification file.
For example, if this project has version number `2.1.0`, that means the output specification file `project.yml` will be generated using [Spec format: v2.0](https://github.com/workshop/struct/wiki/Spec-format:-v2.0).
## Future plans
This project will be kept up to date with latest MAJOR version of [Struct](https://github.com/workshop/struct). Also there is a chance that the execution of [Struct](https://github.com/workshop/struct) CLI tool after (re)generation of `project.yml` file will by automated as well, but so far it seems to be a bit out of scope for the tool.
## Contribution, feedback, questions...
If you want to contirbute to the project - feel free to open a pull request.
If you have any questions, suggestions, feedback or believe you found a bug - feel free to create an issue.

View File

@ -1,19 +0,0 @@
//
// MKHProjGen.h
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/16/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
#import <Cocoa/Cocoa.h>
//! Project version number for MKHProjGen.
FOUNDATION_EXPORT double MKHProjGenVersionNumber;
//! Project version string for MKHProjGen.
FOUNDATION_EXPORT const unsigned char MKHProjGenVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <MKHProjGen/PublicHeader.h>

View File

@ -1,31 +0,0 @@
//
// Device.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/18/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
import Foundation
//===
public
enum DeviceFamily
{
public
enum iOS
{
public
static
let universal = "1,2"
public
static
let phone = "1" // iPhone and iPod Touch
public
static
let pad = "2" // iPad
}
}

View File

@ -1,44 +0,0 @@
//
// Manager.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/16/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
public
enum Manager
{
public
static
func prepareSpec(
_ format: Spec.Format,
for project: Project
) -> String
{
let rawSpec: RawSpec
//===
switch format
{
case .v1_2_1:
rawSpec = Spec_1_2_1.generate(for: project)
case .v1_3_0:
rawSpec = Spec_1_3_0.generate(for: project)
case .v2_0_0:
rawSpec = Spec_2_0_0.generate(for: project)
case .v2_1_0:
rawSpec = Spec_2_1_0.generate(for: project)
}
//===
return rawSpec
.map { "\(Spec.ident($0))\($1)" }
.joined(separator: "\n")
}
}

View File

@ -1,30 +0,0 @@
//
// Misc.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/15/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
public
typealias KeyValuePair = (key: String, value: Any)
//===
infix operator <<<
public
func <<< (keyName: String, value: Any) -> KeyValuePair
{
return (keyName, value)
}
//===
//infix operator </
//
//public
//func </ (keyName: String, value: Any) -> KeyValuePair
//{
// return (keyName, value)
//}

View File

@ -1,19 +0,0 @@
//
// Platform.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/15/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
public
extension Project
{
public
enum Platform: String
{
case
iOS = "ios" /*,
macOS = "mac" */
}
}

View File

@ -1,31 +0,0 @@
//
// Project.BuildConfig.Defaults.General.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/16/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
extension Project.BuildConfiguration.Defaults
{
enum General
{
static
func debug(_ profiles: [String] = []) -> Project.BuildConfiguration
{
return
Project.BuildConfiguration
.Defaults
.debug(["general:debug"] + profiles)
}
static
func release(_ profiles: [String] = []) -> Project.BuildConfiguration
{
return
Project.BuildConfiguration
.Defaults
.release(["general:release"] + profiles)
}
}
}

View File

@ -1,39 +0,0 @@
//
// Project.BuildConfig.Defaults.iOS.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/16/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
extension Project.BuildConfiguration.Defaults
{
enum iOS
{
static
func base(_ profiles: [String] = []) -> Project.BuildConfiguration.Base
{
return
Project.BuildConfiguration
.Base(["platform:ios"] + profiles)
}
static
func debug(_ profiles: [String] = []) -> Project.BuildConfiguration
{
return
Project.BuildConfiguration
.Defaults
.debug(["ios:debug"] + profiles)
}
static
func release(_ profiles: [String] = []) -> Project.BuildConfiguration
{
return
Project.BuildConfiguration
.Defaults
.release(["ios:release"] + profiles)
}
}
}

View File

@ -1,35 +0,0 @@
//
// Project.BuildConfig.Defaults.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/16/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
extension Project.BuildConfiguration
{
enum Defaults
{
static
func debug(_ profiles: [String] = []) -> Project.BuildConfiguration
{
return
Project.BuildConfiguration(
"Debug",
.debug,
profiles
)
}
static
func release(_ profiles: [String] = []) -> Project.BuildConfiguration
{
return
Project.BuildConfiguration(
"Release",
.release,
profiles
)
}
}
}

View File

@ -1,98 +0,0 @@
//
// Project.BuildConfig.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/18/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
import Foundation
//===
public
extension Project
{
public
struct BuildConfiguration
{
public
struct Base
{
public
let profiles: [String]
//===
// internal
init(_ profiles: [String] = [])
{
self.profiles = profiles
}
//===
public private(set)
var overrides: [KeyValuePair] = []
public
mutating
func override(_ pairs: KeyValuePair...)
{
overrides.append(contentsOf: pairs)
}
}
//===
public
enum InternalType: String
{
case
debug,
release
}
//===
public
let name: String
public
let type: InternalType
public
let profiles: [String]
//---
public
var externalConfig: String? = nil // *.xcconfig file
//---
public private(set)
var overrides: [KeyValuePair] = []
public
mutating
func override(_ pairs: KeyValuePair...)
{
overrides.append(contentsOf: pairs)
}
//---
// internal
init(
_ name: String,
_ type: InternalType,
_ profiles: [String] = []
)
{
self.name = name
self.type = type
self.profiles = profiles
}
}
}

View File

@ -1,73 +0,0 @@
//
// Project.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/15/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
public
struct Project
{
public
typealias BuildConfigurations =
(
all: BuildConfiguration.Base,
debug: BuildConfiguration,
release: BuildConfiguration
)
//---
public
let name: String
//---
public
var configurations: BuildConfigurations =
(
BuildConfiguration.Base(
// nothing on this level
),
BuildConfiguration.Defaults.General.debug(
//
),
BuildConfiguration.Defaults.General.release(
//
)
)
public private(set)
var targets: [Target] = []
//---
public
init(
_ name: String,
_ configureProject: (inout Project) -> Void
)
{
self.name = name
//---
configureProject(&self)
}
//===
public
mutating
func target(
_ name: String,
_ platform: Platform,
_ type: Target.InternalType,
_ configureTarget: (inout Target) -> Void
)
{
targets
.append(Target(platform, name, type, configureTarget))
}
}

View File

@ -1,699 +0,0 @@
import Foundation
//===
enum Spec_1_2_1
{
static
func generate(for p: Project) -> RawSpec
{
var result: RawSpec = []
var idention: Int = 0
//===
result <<< (idention, "# generated with MKHProjGen")
result <<< (idention, "# https://github.com/maximkhatskevich/MKHProjGen")
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#version-number
result <<< (idention, Spec.key("version") + " \(Spec.Format.v1_2_1.rawValue)")
//===
result <<< process(&idention, p.configurations)
//===
result <<< process(&idention, p.targets)
//===
result <<< (idention, Spec.key("variants"))
idention += 1
result <<< (idention, Spec.key("$base"))
idention += 1
result <<< (idention, Spec.key("abstract") + " true")
idention -= 1
result <<< (idention, Spec.key(p.name))
idention -= 1
//===
result <<< (0, "") // empty line in the EOF
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ set: Project.BuildConfigurations
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#configurations
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("configurations"))
//===
idention += 1
//===
result <<< process(&idention, set.all, set.debug)
result <<< process(&idention, set.all, set.release)
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ b: Project.BuildConfiguration.Base,
_ c: Project.BuildConfiguration
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#configurations
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key(c.name))
//===
idention += 1
//===
result <<< (idention, Spec.key("type") + Spec.value(c.type))
//===
if
let externalConfig = c.externalConfig
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#xcconfig-references
// NOTE: when using xcconfig files,
// any overrides or profiles will be ignored.
result <<< (idention, Spec.key("source") + Spec.value(externalConfig) )
}
else
{
// NO source/xcconfig provided
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#profiles
result <<< (idention, Spec.key("profiles"))
for p in b.profiles + c.profiles
{
result <<< (idention, "-" + Spec.value(p))
}
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#overrides
result <<< (idention, Spec.key("overrides"))
idention += 1
for o in b.overrides + c.overrides
{
result <<< (idention, Spec.key(o.key) + Spec.value(o.value))
}
idention -= 1
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ targets: [Project.Target]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#targets
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("targets"))
//===
idention += 1
//===
for t in targets
{
result <<< process(&idention, t)
//===
for tst in t.tests
{
result <<< process(&idention, tst)
}
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ t: Project.Target
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#targets
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key(t.name))
//===
idention += 1
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#platform
result <<< (idention, Spec.key("platform") + Spec.value(t.platform.rawValue))
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#type
result <<< (idention, Spec.key("type") + Spec.value(t.type.rawValue))
//===
result <<< process(&idention, t.dependencies)
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#sources
if
!t.includes.isEmpty
{
result <<< (idention, "sources:")
for path in t.includes
{
result <<< (idention, "-" + Spec.value(path))
}
}
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#excludes
if
!t.excludes.isEmpty
{
result <<< (idention, Spec.key("excludes"))
idention += 1
result <<< (idention, Spec.key("files"))
for path in t.excludes
{
result <<< (idention, "-" + Spec.value(path))
}
idention -= 1
}
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#i18n-resources
if
!t.i18nResources.isEmpty
{
result <<< (idention, Spec.key("i18n-resources"))
for path in t.i18nResources
{
result <<< (idention, "-" + Spec.value(path))
}
}
//===
result <<< process(&idention, t.configurations)
//===
result <<< process(&idention, scripts: t.scripts)
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#cocoapods
if
t.includeCocoapods
{
result <<<
(idention,
Spec.key("includes_cocoapods") + Spec.value(t.includeCocoapods))
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ deps: Project.Target.Dependencies
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#references
//===
var result: RawSpec = []
//===
if
!deps.fromSDKs.isEmpty ||
!deps.otherTargets.isEmpty ||
!deps.binaries.isEmpty ||
!deps.projects.isEmpty
{
result <<< (idention, Spec.key("references"))
//===
result <<< processDependencies(&idention, fromSDK: deps.fromSDKs)
result <<< processDependencies(&idention, targets: deps.otherTargets)
result <<< processDependencies(&idention, binaries: deps.binaries)
result <<< processDependencies(&idention, projects: deps.projects)
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
fromSDK: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#references
//===
var result: RawSpec = []
//===
for dep in fromSDK
{
result <<< (idention, "-" + Spec.value("sdkroot:\(dep)"))
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
targets: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#references
//===
var result: RawSpec = []
//===
for t in targets
{
result <<< (idention, "-" + Spec.value(t))
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
binaries: [Project.Target.BinaryDependency]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#references
//===
var result: RawSpec = []
//===
for b in binaries
{
result <<< (idention, Spec.key("- location") + Spec.value(b.location))
result <<< (idention, Spec.key(" codeSignOnCopy") + Spec.value(b.codeSignOnCopy))
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
projects: [Project.Target.ProjectDependencies]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#references
//===
var result: RawSpec = []
//===
for p in projects
{
result <<< (idention, Spec.key("- location") + Spec.value(p.location))
result <<< (idention, Spec.key(" frameworks"))
for f in p.frameworks
{
result <<< (idention, Spec.key(" - name") + Spec.value(f.name))
result <<< (idention, Spec.key(" copy") + Spec.value(f.copy))
result <<< (idention, Spec.key(" codeSignOnCopy") + Spec.value(f.codeSignOnCopy))
}
}
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ set: Project.Target.BuildConfigurations
) -> RawSpec
{
// https://github.com/lyptt/struct/issues/77#issuecomment-287573381
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("configurations"))
//===
idention += 1
//===
result <<< process(&idention, set.all, set.debug)
result <<< process(&idention, set.all, set.release)
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ b: Project.Target.BuildConfiguration.Base,
_ c: Project.Target.BuildConfiguration
) -> RawSpec
{
// https://github.com/lyptt/struct/issues/77#issuecomment-287573381
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key(c.name))
//===
idention += 1
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#overrides
for o in b.overrides + c.overrides
{
result <<< (idention, Spec.key(o.key) + Spec.value(o.value))
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
scripts: Project.Target.Scripts
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#scripts
//===
var result: RawSpec = []
//===
if
!scripts.regulars.isEmpty ||
!scripts.beforeBuilds.isEmpty ||
!scripts.afterBuilds.isEmpty
{
result <<< (idention, Spec.key("scripts"))
//===
idention += 1
//===
if
!scripts.regulars.isEmpty
{
result <<< processScripts(&idention, regulars: scripts.regulars)
}
if
!scripts.beforeBuilds.isEmpty
{
result <<< processScripts(&idention, beforeBuild: scripts.beforeBuilds)
}
if
!scripts.afterBuilds.isEmpty
{
result <<< processScripts(&idention, afterBuild: scripts.afterBuilds)
}
//===
idention -= 1
}
//===
return result
}
//===
static
func processScripts(
_ idention: inout Int,
regulars: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#scripts
//===
var result: RawSpec = []
//===
for s in regulars
{
result <<< (idention, "-" + Spec.value(s))
}
//===
return result
}
//===
static
func processScripts(
_ idention: inout Int,
beforeBuild: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#scripts
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("prebuild"))
for s in beforeBuild
{
result <<< (idention, "-" + Spec.value(s))
}
//===
return result
}
//===
static
func processScripts(
_ idention: inout Int,
afterBuild: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#scripts
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("postbuild"))
for s in afterBuild
{
result <<< (idention, "-" + Spec.value(s))
}
//===
return result
}
}

View File

@ -1,718 +0,0 @@
import Foundation
//===
enum Spec_1_3_0
{
static
func generate(for p: Project) -> RawSpec
{
var result: RawSpec = []
var idention: Int = 0
//===
result <<< (idention, "# generated with MKHProjGen")
result <<< (idention, "# https://github.com/maximkhatskevich/MKHProjGen")
result <<< (idention, "# https://github.com/workshop/struct/wiki/Spec-format:-v1.3")
//===
// https://github.com/workshop/struct/wiki/Spec-format:-v1.3#version-number
result <<< (idention, Spec.key("version") + " \(Spec.Format.v1_3_0.rawValue)")
//===
result <<< process(&idention, p.configurations)
//===
result <<< process(&idention, p.targets)
//===
result <<< (idention, Spec.key("variants"))
idention += 1
result <<< (idention, Spec.key("$base"))
idention += 1
result <<< (idention, Spec.key("abstract") + " true")
idention -= 1
result <<< (idention, Spec.key(p.name))
idention -= 1
//===
result <<< (0, "") // empty line in the EOF
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ set: Project.BuildConfigurations
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#configurations
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("configurations"))
//===
idention += 1
//===
result <<< process(&idention, set.all, set.debug)
result <<< process(&idention, set.all, set.release)
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ b: Project.BuildConfiguration.Base,
_ c: Project.BuildConfiguration
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#configurations
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key(c.name))
//===
idention += 1
//===
result <<< (idention, Spec.key("type") + Spec.value(c.type))
//===
if
let externalConfig = c.externalConfig
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#xcconfig-references
// NOTE: when using xcconfig files,
// any overrides or profiles will be ignored.
result <<< (idention, Spec.key("source") + Spec.value(externalConfig) )
}
else
{
// NO source/xcconfig provided
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#profiles
result <<< (idention, Spec.key("profiles"))
for p in b.profiles + c.profiles
{
result <<< (idention, "-" + Spec.value(p))
}
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#overrides
result <<< (idention, Spec.key("overrides"))
idention += 1
for o in b.overrides + c.overrides
{
result <<< (idention, Spec.key(o.key) + Spec.value(o.value))
}
idention -= 1
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ targets: [Project.Target]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#targets
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("targets"))
//===
idention += 1
//===
for t in targets
{
result <<< process(&idention, t)
//===
for tst in t.tests
{
result <<< process(&idention, tst)
}
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ t: Project.Target
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#targets
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key(t.name))
//===
idention += 1
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#platform
result <<< (idention, Spec.key("platform") + Spec.value(t.platform.rawValue))
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#type
result <<< (idention, Spec.key("type") + Spec.value(t.type.rawValue))
//===
result <<< process(&idention, t.dependencies)
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#sources
if
!t.includes.isEmpty
{
result <<< (idention, "sources:")
for path in t.includes
{
result <<< (idention, "-" + Spec.value(path))
}
}
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#excludes
if
!t.excludes.isEmpty
{
result <<< (idention, Spec.key("excludes"))
idention += 1
result <<< (idention, Spec.key("files"))
for path in t.excludes
{
result <<< (idention, "-" + Spec.value(path))
}
idention -= 1
}
//===
// https://github.com/workshop/struct/wiki/Spec-format:-v1.3#options
if
!t.sourceOptions.isEmpty
{
result <<< (idention, "source_options:")
idention += 1
for (path, opt) in t.sourceOptions
{
result <<< (idention, Spec.key(path) + Spec.value(opt))
}
idention -= 1
}
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#i18n-resources
if
!t.i18nResources.isEmpty
{
result <<< (idention, Spec.key("i18n-resources"))
for path in t.i18nResources
{
result <<< (idention, "-" + Spec.value(path))
}
}
//===
result <<< process(&idention, t.configurations)
//===
result <<< process(&idention, scripts: t.scripts)
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#cocoapods
if
t.includeCocoapods
{
result <<<
(idention,
Spec.key("includes_cocoapods") + Spec.value(t.includeCocoapods))
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ deps: Project.Target.Dependencies
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#references
//===
var result: RawSpec = []
//===
if
!deps.fromSDKs.isEmpty ||
!deps.otherTargets.isEmpty ||
!deps.binaries.isEmpty ||
!deps.projects.isEmpty
{
result <<< (idention, Spec.key("references"))
//===
result <<< processDependencies(&idention, fromSDK: deps.fromSDKs)
result <<< processDependencies(&idention, targets: deps.otherTargets)
result <<< processDependencies(&idention, binaries: deps.binaries)
result <<< processDependencies(&idention, projects: deps.projects)
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
fromSDK: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#references
//===
var result: RawSpec = []
//===
for dep in fromSDK
{
result <<< (idention, "-" + Spec.value("sdkroot:\(dep)"))
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
targets: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#references
//===
var result: RawSpec = []
//===
for t in targets
{
result <<< (idention, "-" + Spec.value(t))
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
binaries: [Project.Target.BinaryDependency]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#references
//===
var result: RawSpec = []
//===
for b in binaries
{
result <<< (idention, Spec.key("- location") + Spec.value(b.location))
result <<< (idention, Spec.key(" codeSignOnCopy") + Spec.value(b.codeSignOnCopy))
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
projects: [Project.Target.ProjectDependencies]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#references
//===
var result: RawSpec = []
//===
for p in projects
{
result <<< (idention, Spec.key("- location") + Spec.value(p.location))
result <<< (idention, Spec.key(" frameworks"))
for f in p.frameworks
{
result <<< (idention, Spec.key(" - name") + Spec.value(f.name))
result <<< (idention, Spec.key(" copy") + Spec.value(f.copy))
result <<< (idention, Spec.key(" codeSignOnCopy") + Spec.value(f.codeSignOnCopy))
}
}
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ set: Project.Target.BuildConfigurations
) -> RawSpec
{
// https://github.com/lyptt/struct/issues/77#issuecomment-287573381
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("configurations"))
//===
idention += 1
//===
result <<< process(&idention, set.all, set.debug)
result <<< process(&idention, set.all, set.release)
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ b: Project.Target.BuildConfiguration.Base,
_ c: Project.Target.BuildConfiguration
) -> RawSpec
{
// https://github.com/lyptt/struct/issues/77#issuecomment-287573381
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key(c.name))
//===
idention += 1
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#overrides
for o in b.overrides + c.overrides
{
result <<< (idention, Spec.key(o.key) + Spec.value(o.value))
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
scripts: Project.Target.Scripts
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#scripts
//===
var result: RawSpec = []
//===
if
!scripts.regulars.isEmpty ||
!scripts.beforeBuilds.isEmpty ||
!scripts.afterBuilds.isEmpty
{
result <<< (idention, Spec.key("scripts"))
//===
idention += 1
//===
if
!scripts.regulars.isEmpty
{
result <<< processScripts(&idention, regulars: scripts.regulars)
}
if
!scripts.beforeBuilds.isEmpty
{
result <<< processScripts(&idention, beforeBuild: scripts.beforeBuilds)
}
if
!scripts.afterBuilds.isEmpty
{
result <<< processScripts(&idention, afterBuild: scripts.afterBuilds)
}
//===
idention -= 1
}
//===
return result
}
//===
static
func processScripts(
_ idention: inout Int,
regulars: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#scripts
//===
var result: RawSpec = []
//===
for s in regulars
{
result <<< (idention, "-" + Spec.value(s))
}
//===
return result
}
//===
static
func processScripts(
_ idention: inout Int,
beforeBuild: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#scripts
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("prebuild"))
for s in beforeBuild
{
result <<< (idention, "-" + Spec.value(s))
}
//===
return result
}
//===
static
func processScripts(
_ idention: inout Int,
afterBuild: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#scripts
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("postbuild"))
for s in afterBuild
{
result <<< (idention, "-" + Spec.value(s))
}
//===
return result
}
}

View File

@ -1,712 +0,0 @@
import Foundation
//===
enum Spec_2_0_0
{
static
func generate(for p: Project) -> RawSpec
{
var result: RawSpec = []
var idention: Int = 0
//===
result <<< (idention, "# generated with XCEProjectGenerator")
result <<< (idention, "# https://github.com/XCEssentials/ProjectGenerator")
result <<< (idention, "# https://github.com/workshop/struct/wiki/Spec-format:-v2.0")
//===
// https://github.com/workshop/struct/wiki/Spec-format:-v2.0#version-number
result <<< (idention, Spec.key("version") + " \(Spec.Format.v2_0_0.rawValue)")
//===
result <<< process(&idention, p.configurations)
//===
result <<< process(&idention, p.targets)
//===
result <<< (idention, Spec.key("variants"))
idention += 1
result <<< (idention, Spec.key("$base"))
idention += 1
result <<< (idention, Spec.key("abstract") + " true")
idention -= 1
result <<< (idention, Spec.key(p.name))
idention -= 1
//===
result <<< (0, "") // empty line in the EOF
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ set: Project.BuildConfigurations
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#configurations
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("configurations"))
//===
idention += 1
//===
result <<< process(&idention, set.all, set.debug)
result <<< process(&idention, set.all, set.release)
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ b: Project.BuildConfiguration.Base,
_ c: Project.BuildConfiguration
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#configurations
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key(c.name))
//===
idention += 1
//===
result <<< (idention, Spec.key("type") + Spec.value(c.type))
//===
if
let externalConfig = c.externalConfig
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#xcconfig-references
// NOTE: when using xcconfig files,
// any overrides or profiles will be ignored.
result <<< (idention, Spec.key("source") + Spec.value(externalConfig) )
}
else
{
// NO source/xcconfig provided
//===
// NO profiles anymore
// https://github.com/workshop/struct/wiki/Migrating-from-Spec-1.3.1-to-Spec-2.0.0
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#overrides
result <<< (idention, Spec.key("overrides"))
idention += 1
for o in b.overrides + c.overrides
{
result <<< (idention, Spec.key(o.key) + Spec.value(o.value))
}
idention -= 1
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ targets: [Project.Target]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#targets
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("targets"))
//===
idention += 1
//===
for t in targets
{
result <<< process(&idention, t)
//===
for tst in t.tests
{
result <<< process(&idention, tst)
}
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ t: Project.Target
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#targets
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key(t.name))
//===
idention += 1
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#platform
result <<< (idention, Spec.key("platform") + Spec.value(t.platform.rawValue))
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#type
result <<< (idention, Spec.key("type") + Spec.value(t.type.rawValue))
//===
result <<< process(&idention, t.dependencies)
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#sources
if
!t.includes.isEmpty
{
result <<< (idention, "sources:")
for path in t.includes
{
result <<< (idention, "-" + Spec.value(path))
}
}
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#excludes
if
!t.excludes.isEmpty
{
result <<< (idention, Spec.key("excludes"))
idention += 1
result <<< (idention, Spec.key("files"))
for path in t.excludes
{
result <<< (idention, "-" + Spec.value(path))
}
idention -= 1
}
//===
// https://github.com/workshop/struct/wiki/Spec-format:-v2.0#options
if
!t.sourceOptions.isEmpty
{
result <<< (idention, "source_options:")
idention += 1
for (path, opt) in t.sourceOptions
{
result <<< (idention, Spec.key(path) + Spec.value(opt))
}
idention -= 1
}
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#i18n-resources
if
!t.i18nResources.isEmpty
{
result <<< (idention, Spec.key("i18n-resources"))
for path in t.i18nResources
{
result <<< (idention, "-" + Spec.value(path))
}
}
//===
result <<< process(&idention, t.configurations)
//===
result <<< process(&idention, scripts: t.scripts)
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#cocoapods
if
t.includeCocoapods
{
result <<<
(idention,
Spec.key("includes_cocoapods") + Spec.value(t.includeCocoapods))
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ deps: Project.Target.Dependencies
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#references
//===
var result: RawSpec = []
//===
if
!deps.fromSDKs.isEmpty ||
!deps.otherTargets.isEmpty ||
!deps.binaries.isEmpty ||
!deps.projects.isEmpty
{
result <<< (idention, Spec.key("references"))
//===
result <<< processDependencies(&idention, fromSDK: deps.fromSDKs)
result <<< processDependencies(&idention, targets: deps.otherTargets)
result <<< processDependencies(&idention, binaries: deps.binaries)
result <<< processDependencies(&idention, projects: deps.projects)
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
fromSDK: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#references
//===
var result: RawSpec = []
//===
for dep in fromSDK
{
result <<< (idention, "-" + Spec.value("sdkroot:\(dep)"))
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
targets: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#references
//===
var result: RawSpec = []
//===
for t in targets
{
result <<< (idention, "-" + Spec.value(t))
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
binaries: [Project.Target.BinaryDependency]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#references
//===
var result: RawSpec = []
//===
for b in binaries
{
result <<< (idention, Spec.key("- location") + Spec.value(b.location))
result <<< (idention, Spec.key(" codeSignOnCopy") + Spec.value(b.codeSignOnCopy))
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
projects: [Project.Target.ProjectDependencies]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#references
//===
var result: RawSpec = []
//===
for p in projects
{
result <<< (idention, Spec.key("- location") + Spec.value(p.location))
result <<< (idention, Spec.key(" frameworks"))
for f in p.frameworks
{
result <<< (idention, Spec.key(" - name") + Spec.value(f.name))
result <<< (idention, Spec.key(" copy") + Spec.value(f.copy))
result <<< (idention, Spec.key(" codeSignOnCopy") + Spec.value(f.codeSignOnCopy))
}
}
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ set: Project.Target.BuildConfigurations
) -> RawSpec
{
// https://github.com/lyptt/struct/issues/77#issuecomment-287573381
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("configurations"))
//===
idention += 1
//===
result <<< process(&idention, set.all, set.debug)
result <<< process(&idention, set.all, set.release)
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ b: Project.Target.BuildConfiguration.Base,
_ c: Project.Target.BuildConfiguration
) -> RawSpec
{
// https://github.com/lyptt/struct/issues/77#issuecomment-287573381
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key(c.name))
//===
idention += 1
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#overrides
for o in b.overrides + c.overrides
{
result <<< (idention, Spec.key(o.key) + Spec.value(o.value))
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
scripts: Project.Target.Scripts
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#scripts
//===
var result: RawSpec = []
//===
if
!scripts.regulars.isEmpty ||
!scripts.beforeBuilds.isEmpty ||
!scripts.afterBuilds.isEmpty
{
result <<< (idention, Spec.key("scripts"))
//===
idention += 1
//===
if
!scripts.regulars.isEmpty
{
result <<< processScripts(&idention, regulars: scripts.regulars)
}
if
!scripts.beforeBuilds.isEmpty
{
result <<< processScripts(&idention, beforeBuild: scripts.beforeBuilds)
}
if
!scripts.afterBuilds.isEmpty
{
result <<< processScripts(&idention, afterBuild: scripts.afterBuilds)
}
//===
idention -= 1
}
//===
return result
}
//===
static
func processScripts(
_ idention: inout Int,
regulars: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#scripts
//===
var result: RawSpec = []
//===
for s in regulars
{
result <<< (idention, "-" + Spec.value(s))
}
//===
return result
}
//===
static
func processScripts(
_ idention: inout Int,
beforeBuild: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#scripts
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("prebuild"))
for s in beforeBuild
{
result <<< (idention, "-" + Spec.value(s))
}
//===
return result
}
//===
static
func processScripts(
_ idention: inout Int,
afterBuild: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#scripts
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("postbuild"))
for s in afterBuild
{
result <<< (idention, "-" + Spec.value(s))
}
//===
return result
}
}

View File

@ -1,712 +0,0 @@
import Foundation
//===
enum Spec_2_1_0
{
static
func generate(for p: Project) -> RawSpec
{
var result: RawSpec = []
var idention: Int = 0
//===
result <<< (idention, "# generated with XCEProjectGenerator")
result <<< (idention, "# https://github.com/XCEssentials/ProjectGenerator")
result <<< (idention, "# https://github.com/workshop/struct/wiki/Spec-format:-v2.0")
//===
// https://github.com/workshop/struct/wiki/Spec-format:-v2.0#version-number
result <<< (idention, Spec.key("version") + " \(Spec.Format.v2_1_0.rawValue)")
//===
result <<< process(&idention, p.configurations)
//===
result <<< process(&idention, p.targets)
//===
result <<< (idention, Spec.key("variants"))
idention += 1
result <<< (idention, Spec.key("$base"))
idention += 1
result <<< (idention, Spec.key("abstract") + " true")
idention -= 1
result <<< (idention, Spec.key(p.name))
idention -= 1
//===
result <<< (0, "") // empty line in the EOF
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ set: Project.BuildConfigurations
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#configurations
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("configurations"))
//===
idention += 1
//===
result <<< process(&idention, set.all, set.debug)
result <<< process(&idention, set.all, set.release)
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ b: Project.BuildConfiguration.Base,
_ c: Project.BuildConfiguration
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#configurations
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key(c.name))
//===
idention += 1
//===
result <<< (idention, Spec.key("type") + Spec.value(c.type))
//===
if
let externalConfig = c.externalConfig
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#xcconfig-references
// NOTE: when using xcconfig files,
// any overrides or profiles will be ignored.
result <<< (idention, Spec.key("source") + Spec.value(externalConfig) )
}
else
{
// NO source/xcconfig provided
//===
// NO profiles anymore
// https://github.com/workshop/struct/wiki/Migrating-from-Spec-1.3.1-to-Spec-2.0.0
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#overrides
result <<< (idention, Spec.key("overrides"))
idention += 1
for o in b.overrides + c.overrides
{
result <<< (idention, Spec.key(o.key) + Spec.value(o.value))
}
idention -= 1
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ targets: [Project.Target]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#targets
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("targets"))
//===
idention += 1
//===
for t in targets
{
result <<< process(&idention, t)
//===
for tst in t.tests
{
result <<< process(&idention, tst)
}
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ t: Project.Target
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#targets
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key(t.name))
//===
idention += 1
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#platform
result <<< (idention, Spec.key("platform") + Spec.value(t.platform.rawValue))
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#type
result <<< (idention, Spec.key("type") + Spec.value(t.type.rawValue))
//===
result <<< process(&idention, t.dependencies)
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#sources
if
!t.includes.isEmpty
{
result <<< (idention, "sources:")
for path in t.includes
{
result <<< (idention, "-" + Spec.value(path))
}
}
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#excludes
if
!t.excludes.isEmpty
{
result <<< (idention, Spec.key("excludes"))
idention += 1
result <<< (idention, Spec.key("files"))
for path in t.excludes
{
result <<< (idention, "-" + Spec.value(path))
}
idention -= 1
}
//===
// https://github.com/workshop/struct/wiki/Spec-format:-v2.0#options
if
!t.sourceOptions.isEmpty
{
result <<< (idention, "source_options:")
idention += 1
for (path, opt) in t.sourceOptions
{
result <<< (idention, Spec.key(path) + Spec.value(opt))
}
idention -= 1
}
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#i18n-resources
if
!t.i18nResources.isEmpty
{
result <<< (idention, Spec.key("i18n-resources"))
for path in t.i18nResources
{
result <<< (idention, "-" + Spec.value(path))
}
}
//===
result <<< process(&idention, t.configurations)
//===
result <<< process(&idention, scripts: t.scripts)
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#cocoapods
if
t.includeCocoapods
{
result <<<
(idention,
Spec.key("includes_cocoapods") + Spec.value(t.includeCocoapods))
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ deps: Project.Target.Dependencies
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#references
//===
var result: RawSpec = []
//===
if
!deps.fromSDKs.isEmpty ||
!deps.otherTargets.isEmpty ||
!deps.binaries.isEmpty ||
!deps.projects.isEmpty
{
result <<< (idention, Spec.key("references"))
//===
result <<< processDependencies(&idention, fromSDK: deps.fromSDKs)
result <<< processDependencies(&idention, targets: deps.otherTargets)
result <<< processDependencies(&idention, binaries: deps.binaries)
result <<< processDependencies(&idention, projects: deps.projects)
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
fromSDK: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#references
//===
var result: RawSpec = []
//===
for dep in fromSDK
{
result <<< (idention, "-" + Spec.value("sdkroot:\(dep)"))
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
targets: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#references
//===
var result: RawSpec = []
//===
for t in targets
{
result <<< (idention, "-" + Spec.value(t))
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
binaries: [Project.Target.BinaryDependency]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#references
//===
var result: RawSpec = []
//===
for b in binaries
{
result <<< (idention, Spec.key("- location") + Spec.value(b.location))
result <<< (idention, Spec.key(" codeSignOnCopy") + Spec.value(b.codeSignOnCopy))
}
//===
return result
}
//===
static
func processDependencies(
_ idention: inout Int,
projects: [Project.Target.ProjectDependencies]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#references
//===
var result: RawSpec = []
//===
for p in projects
{
result <<< (idention, Spec.key("- location") + Spec.value(p.location))
result <<< (idention, Spec.key(" frameworks"))
for f in p.frameworks
{
result <<< (idention, Spec.key(" - name") + Spec.value(f.name))
result <<< (idention, Spec.key(" copy") + Spec.value(f.copy))
result <<< (idention, Spec.key(" codeSignOnCopy") + Spec.value(f.codeSignOnCopy))
}
}
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ set: Project.Target.BuildConfigurations
) -> RawSpec
{
// https://github.com/lyptt/struct/issues/77#issuecomment-287573381
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("configurations"))
//===
idention += 1
//===
result <<< process(&idention, set.all, set.debug)
result <<< process(&idention, set.all, set.release)
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
_ b: Project.Target.BuildConfiguration.Base,
_ c: Project.Target.BuildConfiguration
) -> RawSpec
{
// https://github.com/lyptt/struct/issues/77#issuecomment-287573381
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key(c.name))
//===
idention += 1
//===
// https://github.com/lyptt/struct/wiki/Spec-format:-v1.2#overrides
for o in b.overrides + c.overrides
{
result <<< (idention, Spec.key(o.key) + Spec.value(o.value))
}
//===
idention -= 1
//===
return result
}
//===
static
func process(
_ idention: inout Int,
scripts: Project.Target.Scripts
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#scripts
//===
var result: RawSpec = []
//===
if
!scripts.regulars.isEmpty ||
!scripts.beforeBuilds.isEmpty ||
!scripts.afterBuilds.isEmpty
{
result <<< (idention, Spec.key("scripts"))
//===
idention += 1
//===
if
!scripts.regulars.isEmpty
{
result <<< processScripts(&idention, regulars: scripts.regulars)
}
if
!scripts.beforeBuilds.isEmpty
{
result <<< processScripts(&idention, beforeBuild: scripts.beforeBuilds)
}
if
!scripts.afterBuilds.isEmpty
{
result <<< processScripts(&idention, afterBuild: scripts.afterBuilds)
}
//===
idention -= 1
}
//===
return result
}
//===
static
func processScripts(
_ idention: inout Int,
regulars: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#scripts
//===
var result: RawSpec = []
//===
for s in regulars
{
result <<< (idention, "-" + Spec.value(s))
}
//===
return result
}
//===
static
func processScripts(
_ idention: inout Int,
beforeBuild: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#scripts
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("prebuild"))
for s in beforeBuild
{
result <<< (idention, "-" + Spec.value(s))
}
//===
return result
}
//===
static
func processScripts(
_ idention: inout Int,
afterBuild: [String]
) -> RawSpec
{
// https://github.com/lyptt/struct/wiki/Spec-format:-v2.0#scripts
//===
var result: RawSpec = []
//===
result <<< (idention, Spec.key("postbuild"))
for s in afterBuild
{
result <<< (idention, "-" + Spec.value(s))
}
//===
return result
}
}

View File

@ -1,57 +0,0 @@
import Foundation
//===
typealias SpecLine = (idention: Int, line: String)
typealias RawSpec = [SpecLine]
//===
func <<< (list: inout RawSpec, element: SpecLine)
{
list.append(element)
}
func <<< (list: inout RawSpec, elements: RawSpec)
{
list.append(contentsOf: elements)
}
//===
public
enum Spec
{
public
enum Format: String
{
case
v1_2_1 = "1.2.1",
v1_3_0 = "1.3.0",
v2_0_0 = "2.0.0",
v2_1_0 = "2.1.0"
}
}
//===
extension Spec
{
static
func ident(_ idention: Int) -> String
{
return Array(repeating: " ", count: idention).joined()
}
static
func key(_ v: Any) -> String
{
return "\(v):"
}
static
func value(_ v: Any) -> String
{
return " \"\(v)\""
}
}

View File

@ -1,68 +0,0 @@
//
// Project.BuildConfig.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/18/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
import Foundation
//===
public
extension Project.Target
{
public
struct BuildConfiguration
{
public
struct Base
{
// internal
init(_ overrides: [KeyValuePair] = [])
{
self.overrides = overrides
}
//===
public private(set)
var overrides: [KeyValuePair] = []
public
mutating
func override(_ pairs: KeyValuePair...)
{
overrides.append(contentsOf: pairs)
}
}
//===
public
let name: String
//---
public private(set)
var overrides: [KeyValuePair] = []
public
mutating
func override(_ pairs: KeyValuePair...)
{
overrides.append(contentsOf: pairs)
}
//---
// internal
init(
_ name: String
)
{
self.name = name
}
}
}

View File

@ -1,97 +0,0 @@
//
// Target.Dependencies.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/17/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
import Foundation
//===
public
extension Project.Target
{
public
typealias BinaryDependency =
(
location: String,
codeSignOnCopy: Bool
)
public
typealias ProjectDependencies =
(
location: String,
frameworks: [ProjectDependency]
)
public
typealias ProjectDependency =
(
name: String,
copy: Bool,
codeSignOnCopy: Bool
)
//===
public
struct Dependencies
{
public private(set)
var fromSDKs: [String] = []
public
mutating
func fromSDK(_ element: String...)
{
fromSDKs.append(contentsOf: element)
}
//===
public private(set)
var otherTargets: [String] = []
public
mutating
func otherTarget(_ element: String...)
{
otherTargets.append(contentsOf: element)
}
//===
public private(set)
var binaries: [BinaryDependency] = []
public
mutating
func binary(_ element: BinaryDependency...)
{
binaries.append(contentsOf: element)
}
//===
public private(set)
var projects: [ProjectDependencies] = []
public
mutating
func project(_ element: ProjectDependencies...)
{
projects.append(contentsOf: element)
}
//===
// internal
init()
{
//
}
}
}

View File

@ -1,53 +0,0 @@
//
// Target.Script.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/18/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
import Foundation
//===
public
extension Project.Target
{
public
struct Scripts
{
public private(set)
var regulars: [String] = []
public
mutating
func regular(_ paths: String...)
{
regulars.append(contentsOf: paths)
}
//---
public private(set)
var beforeBuilds: [String] = []
public
mutating
func beforeBuild(_ paths: String...)
{
beforeBuilds.append(contentsOf: paths)
}
//---
public private(set)
var afterBuilds: [String] = []
public
mutating
func afterBuild(_ paths: String...)
{
afterBuilds.append(contentsOf: paths)
}
}
}

View File

@ -1,34 +0,0 @@
//
// Target.Type.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/16/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
extension Project.Target
{
public
enum InternalType: String
{
case
app = ":application",
framework = ":framework",
dynamicLibrary = ":library.dynamic",
staticLibrary = ":library.static",
bundle = ":bundle",
unitTest = ":bundle.unit-test",
uiTest = ":bundle.ui-testing",
appExtension = ":app-extension",
tool = ":tool",
watchApp = ":application.watchapp",
watchApp2 = ":application.watchapp2",
watchKitExtension = ":watchkit-extension",
watchKit2Extension = ":watchkit2-extension",
tvAppExtension = ":tv-app-extension",
messagesApp = ":application.messages",
appExtensionMessages = ":app-extension.messages",
appExtensionMessagesStickers = ":app-extension.messages-sticker-pack",
xpcService = ":xpc-service"
}
}

View File

@ -1,169 +0,0 @@
//
// Target.swift
// MKHProjGen
//
// Created by Maxim Khatskevich on 3/16/17.
// Copyright © 2017 Maxim Khatskevich. All rights reserved.
//
public
extension Project
{
public
struct Target
{
public
typealias BuildConfigurations =
(
all: BuildConfiguration.Base,
debug: BuildConfiguration,
release: BuildConfiguration
)
//---
public
let name: String
public
let platform: Platform
public
let type: InternalType
//---
public private(set)
var includes: [String] = []
public
mutating
func include(_ paths: String...)
{
includes.append(contentsOf: paths)
}
//---
public private(set)
var excludes: [String] = []
public
mutating
func exclude(_ patterns: String...)
{
excludes.append(contentsOf: patterns)
}
//---
public
var sourceOptions: [String: String] = [:]
//---
public private(set)
var i18nResources: [String] = []
public
mutating
func i18nResource(_ paths: String...)
{
i18nResources.append(contentsOf: paths)
}
//---
public
var configurations: BuildConfigurations =
(
Project.Target.BuildConfiguration.Base(
//
),
Project.Target.BuildConfiguration(
Project.BuildConfiguration.Defaults.iOS.debug().name
),
Project.Target.BuildConfiguration(
Project.BuildConfiguration.Defaults.iOS.release().name
)
)
public
var dependencies = Dependencies()
public
var scripts = Scripts()
public
var includeCocoapods = false
//---
public private(set)
var tests: [Target] = []
public
mutating
func unitTests(
_ name: String = "Tests",
_ configureTarget: (inout Target) -> Void
)
{
var ut = Target(self.platform, name, .unitTest, configureTarget)
//===
ut.dependencies.otherTarget(self.name)
if
type == .app
{
ut.configurations.all.override(
// https://github.com/workshop/struct/blob/master/examples/iOS_Application/project.yml#L115
"TEST_HOST"
<<< "$(BUILT_PRODUCTS_DIR)/\(self.name).app/\(self.name)"
)
}
//===
tests.append(ut)
}
public
mutating
func uiTests(
_ name: String = "UITests",
_ configureTarget: (inout Target) -> Void
)
{
var uit = Target(self.platform, name, .uiTest, configureTarget)
uit.dependencies.otherTarget(self.name)
//===
tests.append(uit)
}
//---
// internal
init(
_ platform: Platform,
_ name: String,
_ type: InternalType,
_ configureTarget: (inout Target) -> Void
)
{
self.name = name
self.platform = platform
self.type = type
//---
configureTarget(&self)
}
}
}

View File

@ -1 +0,0 @@
theme: jekyll-theme-cayman

View File

@ -1,103 +0,0 @@
# Customise this file, documentation can be found here:
# https://github.com/KrauseFx/fastlane/tree/master/docs
# All available actions: https://github.com/KrauseFx/fastlane/blob/master/docs/Actions.md
# can also be listed using the `fastlane actions` command
# Change the syntax highlighting to Ruby
# All lines starting with a # are ignored when running `fastlane`
# By default, fastlane will send which actions are used
# No personal data is shared, more information on https://github.com/fastlane/enhancer
# Uncomment the following line to opt out
# opt_out_usage
# If you want to automatically update fastlane if a new version is available:
# update_fastlane
# This is the minimum version number required.
# Update this, if you use features of a newer version
fastlane_version '1.100.0'
default_platform :ios
#===
projName = 'ProjectGenerator'
projFileName = projName + '.xcodeproj'
#===
platform :ios do
lane :inc_version_and_commit do
ensure_git_status_clean
# ===
versionNumber = get_version_number(xcodeproj: projFileName)
puts 'Current VERSION number: ' + versionNumber
# === Infer new version number, suppose we are using GitFlow
currentBranch = git_branch
if currentBranch.include? 'release/'
# we are on a release branch
defaultNewVersion = currentBranch.split('/').last
else
# we are NOT on a release branch
defaultNewVersion = ''
end
# === Define new version number
useInferredNEWVersionNumber = prompt(
text: 'Proceed with inferred NEW version number (' + defaultNewVersion + ')?',
boolean: true
)
if useInferredNEWVersionNumber
newVersionNumber = defaultNewVersion
else
newVersionNumber = prompt(text: 'New VERSION number:')
end
# === Apply NEW version number and increment build number
increment_version_number(
xcodeproj: projFileName,
version_number: newVersionNumber
)
increment_build_number(
xcodeproj: projFileName
)
# ===
newBuildNumber = get_build_number(xcodeproj: projFileName)
commit_version_bump( # it will fail if more than version bump
xcodeproj: projFileName,
message: 'Version Bump to ' + newVersionNumber + ' (' + newBuildNumber + ')'
)
end
end
# More information about multiple platforms in fastlane: https://github.com/KrauseFx/fastlane/blob/master/docs/Platforms.md
# All available actions: https://github.com/KrauseFx/fastlane/blob/master/docs/Actions.md

View File

@ -1,43 +0,0 @@
fastlane documentation
================
# Installation
Make sure you have the latest version of the Xcode command line tools installed:
```
xcode-select --install
```
## Choose your installation method:
<table width="100%" >
<tr>
<th width="33%"><a href="http://brew.sh">Homebrew</a></td>
<th width="33%">Installer Script</td>
<th width="33%">Rubygems</td>
</tr>
<tr>
<td width="33%" align="center">macOS</td>
<td width="33%" align="center">macOS</td>
<td width="33%" align="center">macOS or Linux with Ruby 2.0.0 or above</td>
</tr>
<tr>
<td width="33%"><code>brew cask install fastlane</code></td>
<td width="33%"><a href="https://download.fastlane.tools">Download the zip file</a>. Then double click on the <code>install</code> script (or run it in a terminal window).</td>
<td width="33%"><code>sudo gem install fastlane -NV</code></td>
</tr>
</table>
# Available Actions
## iOS
### ios inc_version_and_commit
```
fastlane ios inc_version_and_commit
```
----
This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run.
More information about fastlane can be found on [fastlane.tools](https://fastlane.tools).
The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools).

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>4.0.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>15</string>
</dict>
</plist>

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>4.0.2</string>
<key>CFBundleVersion</key>
<string>15</string>
</dict>
</plist>

View File

@ -1,4 +1,4 @@
The MIT License (MIT)
MIT License
Copyright (c) 2016 Maxim Khatskevich
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View File

@ -1,488 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
12DBE06F02A69A23AD00A19C /* APIClientCoreDataTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9C812DC927AF7032A021E16 /* APIClientCoreDataTask.swift */; };
399D0C16ADFBE2C8EA990A18 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E677A431D403CA9D8ECAFED4 /* Foundation.framework */; };
A42DABB5B1092510E2A9CB08 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 251C51C995346153DEDAE04A /* Errors.swift */; };
A9E6885E6E907665E4B2EA53 /* APIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF75623D8A56DED230031F87 /* APIClient.swift */; };
AABCDA7A21F2E7A931838429 /* ParameterEncoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66731D489B7910695907D944 /* ParameterEncoding.swift */; };
B039528494C493CF130CCB5F /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCB746BB775FA85E38BF7F37 /* Helpers.swift */; };
B886924D7AB457089D7E26D2 /* Main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EFD62CB696DAD1CB9A01A35 /* Main.swift */; };
F9CE7997842446ADF7D76E8A /* APIClientCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BE923FEE047824539FC30E6 /* APIClientCore.swift */; };
FF152D43B4CD991A3EA6B45A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E677A431D403CA9D8ECAFED4 /* Foundation.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
38A3725B3347C876916B4AC3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = EC48B3EFE12B117C267E041D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 4F0EF988506D118A621A11B4;
remoteInfo = Fwk;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
B47F9B78D47883A263413718 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
C3725B0673309F547D260EBE /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
251C51C995346153DEDAE04A /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = "<group>"; };
66731D489B7910695907D944 /* ParameterEncoding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ParameterEncoding.swift; sourceTree = "<group>"; };
7BE923FEE047824539FC30E6 /* APIClientCore.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = APIClientCore.swift; sourceTree = "<group>"; };
9EFD62CB696DAD1CB9A01A35 /* Main.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Main.swift; sourceTree = "<group>"; };
A96B3E2071881F2268A2A8C1 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
BF75623D8A56DED230031F87 /* APIClient.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = APIClient.swift; sourceTree = "<group>"; };
D065E9FE308E0E924F1A931F /* Fwk.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Fwk.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DCB746BB775FA85E38BF7F37 /* Helpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
E677A431D403CA9D8ECAFED4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
F9C812DC927AF7032A021E16 /* APIClientCoreDataTask.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = APIClientCoreDataTask.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
ABED045EC6FFF74E75E2ABD1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
399D0C16ADFBE2C8EA990A18 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
BFAE368585619E29CD3DB052 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FF152D43B4CD991A3EA6B45A /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
20CC1177CC2370C397161954 = {
isa = PBXGroup;
children = (
9FD971BB6B4661CDFCECA7C3 /* Frameworks */,
34BA48FD91A14184B87F067B /* Products */,
D16BA9CBC9CB44F4E5369D8E /* Sources */,
BF8BB7A0465ABAD739AA69DC /* Tests */,
);
sourceTree = "<group>";
};
34BA48FD91A14184B87F067B /* Products */ = {
isa = PBXGroup;
children = (
D065E9FE308E0E924F1A931F /* Fwk.framework */,
A96B3E2071881F2268A2A8C1 /* Tests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
9683752BD21D3DFAEA848AA9 /* $local */ = {
isa = PBXGroup;
children = (
);
name = "$local";
sourceTree = "<group>";
};
9FD971BB6B4661CDFCECA7C3 /* Frameworks */ = {
isa = PBXGroup;
children = (
9683752BD21D3DFAEA848AA9 /* $local */,
FC6792309EBA5AEAF7BC4DE7 /* iOS */,
);
name = Frameworks;
sourceTree = "<group>";
};
BF8BB7A0465ABAD739AA69DC /* Tests */ = {
isa = PBXGroup;
children = (
9EFD62CB696DAD1CB9A01A35 /* Main.swift */,
);
name = Tests;
path = Tests;
sourceTree = SOURCE_ROOT;
};
D16BA9CBC9CB44F4E5369D8E /* Sources */ = {
isa = PBXGroup;
children = (
BF75623D8A56DED230031F87 /* APIClient.swift */,
7BE923FEE047824539FC30E6 /* APIClientCore.swift */,
F9C812DC927AF7032A021E16 /* APIClientCoreDataTask.swift */,
251C51C995346153DEDAE04A /* Errors.swift */,
DCB746BB775FA85E38BF7F37 /* Helpers.swift */,
66731D489B7910695907D944 /* ParameterEncoding.swift */,
);
name = Sources;
path = Sources;
sourceTree = SOURCE_ROOT;
};
FC6792309EBA5AEAF7BC4DE7 /* iOS */ = {
isa = PBXGroup;
children = (
E677A431D403CA9D8ECAFED4 /* Foundation.framework */,
);
name = iOS;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
43A694E8DF34920D190A5EF1 /* Tests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 50BA8EEDD2B782EAE5395AF2 /* Build configuration list for PBXNativeTarget "Tests" */;
buildPhases = (
59EDE752033D38B4E12BC82E /* Sources */,
ABED045EC6FFF74E75E2ABD1 /* Frameworks */,
C3725B0673309F547D260EBE /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
2896BE2E19C9C9E765000D6F /* PBXTargetDependency */,
);
name = Tests;
productName = Tests;
productReference = A96B3E2071881F2268A2A8C1 /* Tests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
4F0EF988506D118A621A11B4 /* Fwk */ = {
isa = PBXNativeTarget;
buildConfigurationList = A44A62D468F308AF53F0F1D9 /* Build configuration list for PBXNativeTarget "Fwk" */;
buildPhases = (
6A2F0AA23A5271954E1815C4 /* SwiftLint */,
2AFF568BC7FCD16185F22493 /* Sources */,
BFAE368585619E29CD3DB052 /* Frameworks */,
B47F9B78D47883A263413718 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = Fwk;
productName = Fwk;
productReference = D065E9FE308E0E924F1A931F /* Fwk.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
EC48B3EFE12B117C267E041D /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0830;
LastUpgradeCheck = 0700;
Struct.Version = 2.1.0;
};
buildConfigurationList = 4E6301B6C457E67783E88728 /* Build configuration list for PBXProject "Main" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 20CC1177CC2370C397161954;
productRefGroup = 34BA48FD91A14184B87F067B /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
4F0EF988506D118A621A11B4 /* Fwk */,
43A694E8DF34920D190A5EF1 /* Tests */,
);
};
/* End PBXProject section */
/* Begin PBXShellScriptBuildPhase section */
6A2F0AA23A5271954E1815C4 /* SwiftLint */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = SwiftLint;
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
showEnvVarsInLog = 1;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
2AFF568BC7FCD16185F22493 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A9E6885E6E907665E4B2EA53 /* APIClient.swift in Sources */,
F9CE7997842446ADF7D76E8A /* APIClientCore.swift in Sources */,
12DBE06F02A69A23AD00A19C /* APIClientCoreDataTask.swift in Sources */,
A42DABB5B1092510E2A9CB08 /* Errors.swift in Sources */,
B039528494C493CF130CCB5F /* Helpers.swift in Sources */,
AABCDA7A21F2E7A931838429 /* ParameterEncoding.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
59EDE752033D38B4E12BC82E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B886924D7AB457089D7E26D2 /* Main.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
2896BE2E19C9C9E765000D6F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = Fwk;
target = 4F0EF988506D118A621A11B4 /* Fwk */;
targetProxy = 38A3725B3347C876916B4AC3 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
08B7630C92533C2C6625D593 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 15;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
1AF5F77D7C5CB2A330031DD4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(BUILT_PRODUCTS_DIR)",
);
INFOPLIST_FILE = Info/Tst.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.XCEssentials.APIClient.Tst;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_VERSION = 3.0;
};
name = Release;
};
5792574AD2FB139DCAF6E852 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CURRENT_PROJECT_VERSION = 15;
DEFINES_MODULE = NO;
ENABLE_TESTABILITY = YES;
INFOPLIST_FILE = Info/Fwk.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = true;
PRODUCT_BUNDLE_IDENTIFIER = io.XCEssentials.APIClient;
PRODUCT_NAME = XCEAPIClient;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
A741D36914092C3D6DE7EBFB /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(BUILT_PRODUCTS_DIR)",
);
INFOPLIST_FILE = Info/Tst.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = true;
PRODUCT_BUNDLE_IDENTIFIER = io.XCEssentials.APIClient.Tst;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
D7665931C20C0E744F5C657A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 15;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
EC3B04AAA1FCD67E4F0E1949 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CURRENT_PROJECT_VERSION = 15;
DEFINES_MODULE = NO;
ENABLE_TESTABILITY = YES;
INFOPLIST_FILE = Info/Fwk.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.XCEssentials.APIClient;
PRODUCT_NAME = XCEAPIClient;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
4E6301B6C457E67783E88728 /* Build configuration list for PBXProject "Main" */ = {
isa = XCConfigurationList;
buildConfigurations = (
08B7630C92533C2C6625D593 /* Debug */,
D7665931C20C0E744F5C657A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
};
50BA8EEDD2B782EAE5395AF2 /* Build configuration list for PBXNativeTarget "Tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A741D36914092C3D6DE7EBFB /* Debug */,
1AF5F77D7C5CB2A330031DD4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A44A62D468F308AF53F0F1D9 /* Build configuration list for PBXNativeTarget "Fwk" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5792574AD2FB139DCAF6E852 /* Debug */,
EC3B04AAA1FCD67E4F0E1949 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = EC48B3EFE12B117C267E041D /* Project object */;
}

28
Package.swift Normal file
View File

@ -0,0 +1,28 @@
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "XCEAPIClient",
products: [
.library(
name: "XCEAPIClient",
targets: [
"XCEAPIClient"
]
)
],
targets: [
.target(
name: "XCEAPIClient",
path: "Sources/Core"
),
.testTarget(
name: "XCEAPIClientAllTests",
dependencies: [
"XCEAPIClient"
],
path: "Tests/AllTests"
),
]
)

View File

@ -1,101 +0,0 @@
import XCEProjectGenerator
//===
let params =
(
repoName: "APIClient",
deploymentTarget: "8.0",
companyIdentifier: "io.XCEssentials",
companyPrefix: "XCE"
)
let bundleId =
(
fwk: "\(params.companyIdentifier).\(params.repoName)",
tst: "\(params.companyIdentifier).\(params.repoName).Tst"
)
//===
let specFormat = Spec.Format.v2_1_0
let project = Project("Main") { project in
project.configurations.all.override(
"IPHONEOS_DEPLOYMENT_TARGET" <<< params.deploymentTarget, // bug wokraround
"SWIFT_VERSION" <<< "3.0",
"VERSIONING_SYSTEM" <<< "apple-generic",
"CURRENT_PROJECT_VERSION" <<< "0" // just a default non-empty value
)
project.configurations.debug.override(
"SWIFT_OPTIMIZATION_LEVEL" <<< "-Onone"
)
//---
project.target("Fwk", .iOS, .framework) { target in
target.include("Sources")
//---
target.configurations.all.override(
"PRODUCT_NAME" <<< "\(params.companyPrefix)\(params.repoName)",
"IPHONEOS_DEPLOYMENT_TARGET" <<< params.deploymentTarget, // bug wokraround
"PRODUCT_BUNDLE_IDENTIFIER" <<< bundleId.fwk,
"INFOPLIST_FILE" <<< "Info/Fwk.plist",
//--- iOS related:
"SDKROOT" <<< "iphoneos",
"TARGETED_DEVICE_FAMILY" <<< DeviceFamily.iOS.universal,
//--- Framework related:
"DEFINES_MODULE" <<< "NO",
"SKIP_INSTALL" <<< "YES"
)
target.configurations.debug.override(
"MTL_ENABLE_DEBUG_INFO" <<< true
)
//---
target.unitTests { unitTests in
unitTests.include("Tests")
//---
unitTests.configurations.all.override(
// very important for unit tests,
// prevents the error when unit test do not start at all
"LD_RUNPATH_SEARCH_PATHS" <<<
"$(inherited) @executable_path/Frameworks @loader_path/Frameworks",
"IPHONEOS_DEPLOYMENT_TARGET" <<< params.deploymentTarget, // bug wokraround
"PRODUCT_BUNDLE_IDENTIFIER" <<< bundleId.tst,
"INFOPLIST_FILE" <<< "Info/Tst.plist",
"FRAMEWORK_SEARCH_PATHS" <<< "$(inherited) $(BUILT_PRODUCTS_DIR)"
)
unitTests.configurations.debug.override(
"MTL_ENABLE_DEBUG_INFO" <<< true
)
}
}
}

View File

@ -1,9 +1,12 @@
[![GitHub License](https://img.shields.io/github/license/XCEssentials/APIClient.svg?longCache=true)](LICENSE)
[![GitHub Tag](https://img.shields.io/github/tag/XCEssentials/APIClient.svg?longCache=true)](https://github.com/XCEssentials/APIClient/tags)
[![Swift Package Manager Compatible](https://img.shields.io/badge/SPM-compatible-brightgreen.svg?longCache=true)](Package.swift)
[![Written in Swift](https://img.shields.io/badge/Swift-5.3-orange.svg?longCache=true)](https://swift.org)
[![Supported platforms](https://img.shields.io/badge/platforms-macOS%20%7C%20iOS%20%7C%20tvOS%20%7C%20watchOS%20%7C%20Linux-blue.svg?longCache=true)](Package.swift)
[![Build Status](https://travis-ci.com/XCEssentials/APIClient.svg?branch=master)](https://travis-ci.com/XCEssentials/APIClient)
# APIClient
URLSession-based API client for Cocoa and Cocoa Touch.
Lightweight HTTP-based API client.
Inspired by https://thatthinginswift.com/write-your-own-api-clients-swift/
## Swift 3
Starting from [version 3.0](https://github.com/maximkhatskevich/MKHAPIClient/releases/tag/3.0.0), this library supports Swift 3. For compatibility with Swift 2.2 and Swift 2.3 use [older version](https://github.com/maximkhatskevich/MKHAPIClient/releases/tag/2.1.1).

View File

@ -1,25 +0,0 @@
projFileName = ARGV[0]
fullProjFilePath = Dir.pwd + '/' + ARGV[0]
#===
require 'xcodeproj'
project = Xcodeproj::Project.open(fullProjFilePath)
mainTarget = project.targets.first
# === SwiftLint
swiftLintPhase = mainTarget.new_shell_script_build_phase("SwiftLint")
swiftLintPhase.shell_script = 'if which swiftlint >/dev/null; then
swiftlint
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi'
# swiftLintPhase.run_only_for_deployment_postprocessing = '1'
mainTarget.build_phases.delete(swiftLintPhase)
mainTarget.build_phases.unshift(swiftLintPhase)
# ===
project.save()

View File

@ -1,68 +0,0 @@
import Foundation
//===
public
struct APIClient: APIClientCore
{
// MARK: - APIClientCore conformance
public
let session: URLSession
public
let basePath: String
public
let onConfigureRequest: OnConfigureRequest
public
let onDidPrepareRequest: OnDidPrepareRequest?
public
let onDidReceiveDataResponse: OnDidReceiveDataResponse?
// MARK: - Defautls
public
static
let onConfigureRequest: OnConfigureRequest = {
try $0 = URLEncoding.default.encode($0, with: $1)
}
// MARK: - Initializers
public
init(
basePath: String,
onConfigureRequest: @escaping OnConfigureRequest = APIClient.onConfigureRequest,
onDidPrepareRequest: OnDidPrepareRequest? = nil,
onDidReceiveDataResponse: OnDidReceiveDataResponse? = nil,
sessionConfig: URLSessionConfiguration = .default,
sessionDelegate: URLSessionDelegate? = nil,
sessionDelegateQueue: OperationQueue? = nil
) throws
{
guard
URL(string: basePath) != nil
else
{
throw InvalidBasePath(basePath: basePath)
}
//===
self.basePath = basePath
self.session = URLSession(
configuration: sessionConfig,
delegate: sessionDelegate,
delegateQueue: sessionDelegateQueue
)
self.onConfigureRequest = onConfigureRequest
self.onDidPrepareRequest = onDidPrepareRequest
self.onDidReceiveDataResponse = onDidReceiveDataResponse
}
}

View File

@ -1,94 +0,0 @@
import Foundation
//===
public
typealias DataTaskCompletion = (Data?, URLResponse?, Error?) -> Void
public
typealias DataTaskHTTPCompletion = (Data?, HTTPURLResponse?, Error?) -> Void
public
typealias DataTaskResult = (data: Data?, response: URLResponse?, error: Error?)
//public
//typealias UploadTaskResult =
// (data: Data?, response: URLResponse?, error: NSError?)
//
//public
//typealias DownloadTaskResult =
// (tempFile: URL?, response: URLResponse?, error: NSError?)
//===
public
typealias OnConfigureRequest = (inout URLRequest, Parameters?) throws -> Void
public
typealias OnDidPrepareRequest = (URLRequest) -> Void
public
typealias OnDidReceiveDataResponse = (URLRequest, DataTaskResult) -> Void
//===
public
protocol APIClientCore
{
var session: URLSession { get }
var basePath: String { get }
var onConfigureRequest: OnConfigureRequest { get }
var onDidPrepareRequest: OnDidPrepareRequest? { get }
var onDidReceiveDataResponse: OnDidReceiveDataResponse? { get }
init(
basePath: String,
onConfigureRequest: @escaping OnConfigureRequest,
onDidPrepareRequest: OnDidPrepareRequest?,
onDidReceiveDataResponse: OnDidReceiveDataResponse?,
sessionConfig: URLSessionConfiguration,
sessionDelegate: URLSessionDelegate?,
sessionDelegateQueue: OperationQueue?
) throws
}
// MARK: - Internal methods
extension APIClientCore
{
func prepareRequest(
_ method: HTTPMethod? = nil,
relativePath: String,
parameters: Parameters? = nil
) throws -> URLRequest
{
guard
let rPath = relativePath.addingPercentEncoding(
withAllowedCharacters: .urlPathAllowed
),
let url = URL(string: basePath + rPath)
else
{
throw InvalidRelativePath(
basePath: basePath,
relativePath: relativePath
)
}
//===
var result = URLRequest(url: url)
result.httpMethod = method?.rawValue
try onConfigureRequest(&result, parameters)
onDidPrepareRequest?(result)
//===
return result
}
}

View File

@ -1,177 +0,0 @@
import Foundation
//===
public
extension APIClientCore
{
// MARK: - DataTask
func dataTask(
relativePath: String,
parameters: Parameters? = nil,
completion: @escaping DataTaskCompletion
) throws
{
let request = try prepareRequest(
relativePath: relativePath,
parameters: parameters
)
session.dataTask(with: request) {
self.onDidReceiveDataResponse?(request, ($0, $1, $2))
completion($0, $1, $2)
}
.resume()
}
func dataTaskHTTP(
_ method: HTTPMethod,
relativePath: String,
parameters: Parameters? = nil,
completion: @escaping DataTaskHTTPCompletion
) throws
{
let request = try prepareRequest(
method,
relativePath: relativePath,
parameters: parameters
)
session.dataTask(with: request) {
self.onDidReceiveDataResponse?(request, ($0, $1, $2))
completion($0, $1 as? HTTPURLResponse, $2)
}
.resume()
}
// MARK: - HTTP helpers
func get(
_ relativePath: String,
parameters: Parameters? = nil,
completion: @escaping DataTaskHTTPCompletion
) throws
{
try dataTaskHTTP(
.get,
relativePath: relativePath,
parameters: parameters,
completion: completion
)
}
func post(
_ relativePath: String,
parameters: Parameters? = nil,
completion: @escaping DataTaskHTTPCompletion
) throws
{
try dataTaskHTTP(
.post,
relativePath: relativePath,
parameters: parameters,
completion: completion
)
}
func put(
_ relativePath: String,
parameters: Parameters? = nil,
completion: @escaping DataTaskHTTPCompletion
) throws
{
try dataTaskHTTP(
.put,
relativePath: relativePath,
parameters: parameters,
completion: completion
)
}
func patch(
_ relativePath: String,
parameters: Parameters? = nil,
completion: @escaping DataTaskHTTPCompletion
) throws
{
try dataTaskHTTP(
.patch,
relativePath: relativePath,
parameters: parameters,
completion: completion
)
}
func delete(
_ relativePath: String,
parameters: Parameters? = nil,
completion: @escaping DataTaskHTTPCompletion
) throws
{
try dataTaskHTTP(
.delete,
relativePath: relativePath,
parameters: parameters,
completion: completion
)
}
func head(
_ relativePath: String,
parameters: Parameters? = nil,
completion: @escaping DataTaskHTTPCompletion
) throws
{
try dataTaskHTTP(
.head,
relativePath: relativePath,
parameters: parameters,
completion: completion
)
}
func trace(
_ relativePath: String,
parameters: Parameters? = nil,
completion: @escaping DataTaskHTTPCompletion
) throws
{
try dataTaskHTTP(
.trace,
relativePath: relativePath,
parameters: parameters,
completion: completion
)
}
func connect(
_ relativePath: String,
parameters: Parameters? = nil,
completion: @escaping DataTaskHTTPCompletion
) throws
{
try dataTaskHTTP(
.connect,
relativePath: relativePath,
parameters: parameters,
completion: completion
)
}
func options(
_ relativePath: String,
parameters: Parameters? = nil,
completion: @escaping DataTaskHTTPCompletion
) throws
{
try dataTaskHTTP(
.options,
relativePath: relativePath,
parameters: parameters,
completion: completion
)
}
}

View File

@ -54,7 +54,7 @@ public protocol ParameterEncoding {
/// - throws: An `AFError.parameterEncodingFailed` error if encoding fails.
///
/// - returns: The encoded request.
func encode(_ urlRequest: URLRequest, with parameters: Parameters?) throws -> URLRequest
func encode(_ urlRequest: URLRequest, with parameters: Parameters?) -> Result<URLRequest, RequestEncodingIssue>
}
// MARK: -
@ -115,14 +115,14 @@ public struct URLEncoding: ParameterEncoding {
/// - throws: An `Error` if the encoding process encounters an error.
///
/// - returns: The encoded request.
public func encode(_ urlRequest: URLRequest, with parameters: Parameters?) throws -> URLRequest {
public func encode(_ urlRequest: URLRequest, with parameters: Parameters?) -> Result<URLRequest, RequestEncodingIssue> {
var urlRequest = urlRequest
guard let parameters = parameters else { return urlRequest }
guard let parameters = parameters else { return .success(urlRequest) }
if let method = HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET"), encodesParametersInURL(with: method) {
if let method = HTTPMethod(rawValue: urlRequest.httpMethod ?? HTTPMethod.get.rawValue), encodesParametersInURL(with: method) {
guard let url = urlRequest.url else {
throw ParameterEncodingFailed(reason: "URL encoding failed - missing URL", error: nil)
return .failure(RequestEncodingIssue(reason: "URL encoding failed - missing URL", error: nil))
}
if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty {
@ -131,14 +131,14 @@ public struct URLEncoding: ParameterEncoding {
urlRequest.url = urlComponents.url
}
} else {
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
urlRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
if urlRequest.value(forHTTPHeaderField: HTTPHeaderFieldName.contentType.rawValue) == nil {
urlRequest.setValue(ContentType.formURLEncoded.rawValue, forHTTPHeaderField: HTTPHeaderFieldName.contentType.rawValue)
}
urlRequest.httpBody = query(parameters).data(using: .utf8, allowLossyConversion: false)
}
return urlRequest
return .success(urlRequest)
}
/// Creates percent-escaped, URL encoded query string components from the given key-value pair using recursion.
@ -291,24 +291,24 @@ public struct JSONEncoding: ParameterEncoding {
/// - throws: An `Error` if the encoding process encounters an error.
///
/// - returns: The encoded request.
public func encode(_ urlRequest: URLRequest, with parameters: Parameters?) throws -> URLRequest {
public func encode(_ urlRequest: URLRequest, with parameters: Parameters?) -> Result<URLRequest, RequestEncodingIssue> {
var urlRequest = urlRequest
guard let parameters = parameters else { return urlRequest }
guard let parameters = parameters else { return .success(urlRequest) }
do {
let data = try JSONSerialization.data(withJSONObject: parameters, options: options)
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
if urlRequest.value(forHTTPHeaderField: HTTPHeaderFieldName.contentType.rawValue) == nil {
urlRequest.setValue(ContentType.json.rawValue, forHTTPHeaderField: HTTPHeaderFieldName.contentType.rawValue)
}
urlRequest.httpBody = data
} catch {
throw ParameterEncodingFailed(reason: "JSON encoding failed", error: error)
return .failure(RequestEncodingIssue(reason: "JSON encoding failed", error: error))
}
return urlRequest
return .success(urlRequest)
}
/// Creates a URL request by encoding the JSON object and setting the resulting data on the HTTP body.
@ -327,13 +327,13 @@ public struct JSONEncoding: ParameterEncoding {
do {
let data = try JSONSerialization.data(withJSONObject: jsonObject, options: options)
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
if urlRequest.value(forHTTPHeaderField: HTTPHeaderFieldName.contentType.rawValue) == nil {
urlRequest.setValue(ContentType.json.rawValue, forHTTPHeaderField: HTTPHeaderFieldName.contentType.rawValue)
}
urlRequest.httpBody = data
} catch {
throw ParameterEncodingFailed(reason: "JSON encoding failed", error: error)
throw RequestEncodingIssue(reason: "JSON encoding failed", error: error)
}
return urlRequest
@ -386,10 +386,10 @@ public struct PropertyListEncoding: ParameterEncoding {
/// - throws: An `Error` if the encoding process encounters an error.
///
/// - returns: The encoded request.
public func encode(_ urlRequest: URLRequest, with parameters: Parameters?) throws -> URLRequest {
public func encode(_ urlRequest: URLRequest, with parameters: Parameters?) -> Result<URLRequest, RequestEncodingIssue> {
var urlRequest = urlRequest
guard let parameters = parameters else { return urlRequest }
guard let parameters = parameters else { return .success(urlRequest) }
do {
let data = try PropertyListSerialization.data(
@ -398,16 +398,16 @@ public struct PropertyListEncoding: ParameterEncoding {
options: options
)
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
urlRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type")
if urlRequest.value(forHTTPHeaderField: HTTPHeaderFieldName.contentType.rawValue) == nil {
urlRequest.setValue(ContentType.plist.rawValue, forHTTPHeaderField: HTTPHeaderFieldName.contentType.rawValue)
}
urlRequest.httpBody = data
} catch {
throw ParameterEncodingFailed(reason: "Property list encoding failed", error: error)
return .failure(RequestEncodingIssue(reason: "Property list encoding failed", error: error))
}
return urlRequest
return .success(urlRequest)
}
}

View File

@ -0,0 +1,53 @@
/*
MIT License
Copyright (c) 2016 Maxim Khatskevich (maxim@khatskevi.ch)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import Foundation
//---
/// Minimal implementation of `URLRequestFacilitator`,
/// suitable for wde variaty of URL requests in most usecases.
public
struct BasicURLRequestFacilitator: URLRequestFacilitator
{
public
let session: URLSession
public
let sharedPrefixURL: URL
// MARK: - Initializers
public
init(
sharedPrefixURL: URL,
session: URLSession = .shared
)
{
self.sharedPrefixURL = sharedPrefixURL
self.session = session
}
}

47
Sources/Core/Errors.swift Normal file
View File

@ -0,0 +1,47 @@
/*
MIT License
Copyright (c) 2016 Maxim Khatskevich (maxim@khatskevi.ch)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
public
protocol URLRequestFacilitatorError: Error {}
//---
public
struct RequestEncodingIssue: URLRequestFacilitatorError
{
let reason: String
let error: Error?
}
public
enum PrepareRequestIssue: URLRequestFacilitatorError
{
case conversionIntoDataFailed(Error)
case conversionDataIntoJSONObjectFailed(Error)
case conversionJSONObjectIntoDictionaryFailed(theObject: Any)
case invalidRelativePath(String)
case requestEncodingFailed(RequestEncodingIssue)
}

View File

@ -0,0 +1,47 @@
/*
MIT License
Copyright (c) 2016 Maxim Khatskevich (maxim@khatskevi.ch)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import Foundation
//---
public
enum HTTPHeaderFieldName: String
{
case
authorization = "Authorization",
contentType = "Content-Type"
}
//---
public
enum ContentType: String
{
case formURLEncoded = "application/x-www-form-urlencoded; charset=utf-8"
case json = "application/json"
case plist = "application/x-plist"
}

View File

@ -0,0 +1,60 @@
/*
MIT License
Copyright (c) 2016 Maxim Khatskevich (maxim@khatskevi.ch)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import Foundation
//---
public
protocol RequestDefinition: Encodable
{
static
var relativePath: String { get }
static
var method: HTTPMethod? { get }
static
var parameterEncoding: ParameterEncoding { get }
static
var toDataConverter: (Self) throws -> Data { get }
static
var dataToDictionaryConversionOptions: JSONSerialization.ReadingOptions { get }
}
//---
public
extension RequestDefinition
{
static
var toDataConverter: (Self) throws -> Data { JSONEncoder().encode }
static
var dataToDictionaryConversionOptions: JSONSerialization.ReadingOptions { .init() }
}

View File

@ -0,0 +1,131 @@
/*
MIT License
Copyright (c) 2016 Maxim Khatskevich (maxim@khatskevi.ch)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import Foundation
//---
public
protocol URLRequestFacilitator
{
var session: URLSession { get }
var sharedPrefixURL: URL { get }
}
// MARK: - Commands - Public
public
extension URLRequestFacilitator
{
func prepareRequest<R: RequestDefinition>(
from definition: R
) -> Result<URLRequest, PrepareRequestIssue>
{
let parametersData: Data
do
{
parametersData = try R.toDataConverter(definition)
}
catch
{
return .failure(.conversionIntoDataFailed(error))
}
//---
let parametersObject: Any
do
{
parametersObject = try JSONSerialization
.jsonObject(
with: parametersData,
options: R.dataToDictionaryConversionOptions
)
}
catch
{
return .failure(.conversionDataIntoJSONObjectFailed(error))
}
//---
guard
let parameters = parametersObject as? Parameters
else
{
return .failure(.conversionJSONObjectIntoDictionaryFailed(theObject: parametersObject))
}
//---
return prepareRequest(
R.method,
relativePath: R.relativePath,
parameterEncoding: R.parameterEncoding,
parameters: parameters
)
}
}
// MARK: - Internal methods
extension URLRequestFacilitator
{
func prepareRequest(
_ method: HTTPMethod? = nil,
relativePath: String,
parameterEncoding: ParameterEncoding,
parameters: Parameters? = nil
) -> Result<URLRequest, PrepareRequestIssue>
{
guard
let encodedRelativePath = relativePath
.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)
else
{
return .failure(.invalidRelativePath(relativePath))
}
//---
var targetURL = sharedPrefixURL
targetURL.appendPathComponent(encodedRelativePath)
var result = URLRequest(url: targetURL)
result.httpMethod = method?.rawValue
switch parameterEncoding.encode(result, with: parameters)
{
case .success(let output):
return .success(output)
case .failure(let error):
return .failure(.requestEncodingFailed(error))
}
}
}

View File

@ -1,29 +0,0 @@
import Foundation
//===
public
protocol APIClientError: Error {}
//===
struct InvalidBasePath: APIClientError
{
let basePath: String
}
//===
struct InvalidRelativePath: APIClientError
{
let basePath: String
let relativePath: String
}
//===
struct ParameterEncodingFailed: APIClientError
{
let reason: String
let error: Error?
}

View File

@ -1,19 +0,0 @@
import Foundation
//===
public
enum HTTPHeaderFieldName: String
{
case
authorization = "Authorization",
contentType = "Content-Type"
}
//===
public
enum ContentType: String
{
case formURLEncoded = "application/x-www-form-urlencoded"
}

View File

@ -0,0 +1,66 @@
import XCTest
@testable
import XCEAPIClient
//---
final
class RequestDefinitionTests: XCTestCase
{
struct UserRequestDefinition: RequestDefinition
{
static
let relativePath: String = "user"
static
let method: HTTPMethod? = .get
static
let parameterEncoding: ParameterEncoding = URLEncoding.default
let id: String
var optionalFlag: Int? = nil
}
var facilitator: URLRequestFacilitator!
override func setUp() {
super.setUp()
facilitator = BasicURLRequestFacilitator(sharedPrefixURL: .init(string: "host.com")!)
}
override func tearDown() {
facilitator = nil
super.tearDown()
}
}
//---
extension RequestDefinitionTests
{
func test_buildParameters_withoutOptional()
{
let definition = UserRequestDefinition(id: "123")
let request = try! facilitator.prepareRequest(from: definition).get()
let components = URLComponents(string: request.url!.absoluteString)!
let sut = components.queryItems!
XCTAssertEqual(sut.count, 1)
XCTAssertTrue(sut.contains(where: { $0.name == "id" && $0.value == "123" }))
}
func test_buildParameters_withOptional()
{
let definition = UserRequestDefinition(id: "123", optionalFlag: 22)
let request = try! facilitator.prepareRequest(from: definition).get()
let components = URLComponents(string: request.url!.absoluteString)!
let sut = components.queryItems!
XCTAssertEqual(sut.count, 2)
XCTAssertTrue(sut.contains(where: { $0.name == "id" && $0.value == "123" }))
XCTAssertTrue(sut.contains(where: { $0.name == "optionalFlag" && $0.value == "22" }))
}
}

View File

@ -0,0 +1,39 @@
import XCTest
@testable
import XCEAPIClient
//---
final
class URLRequestFacilitatorTests: XCTestCase
{
let facilitator = BasicURLRequestFacilitator(
sharedPrefixURL: URL(string: "example.com")!
)
}
//---
extension URLRequestFacilitatorTests
{
func test_prepareRequest_happyPath()
{
let sut = facilitator.prepareRequest(
.get,
relativePath: "user",
parameterEncoding: URLEncoding.default,
parameters: ["id": "123"]
)
switch sut
{
case .success(let request):
XCTAssertEqual(request.httpMethod, "GET")
XCTAssertEqual(request.url?.absoluteString, "example.com/user?id=123")
default:
XCTFail("Expected a success")
}
}
}

View File

@ -1 +0,0 @@

View File

@ -1,28 +0,0 @@
projName = 'APIClient'
projSummary = 'URLSession-based API client for Cocoa and Cocoa Touch.'
companyPrefix = 'XCE'
companyName = 'XCEssentials'
companyGitHubAccount = 'https://github.com/' + companyName
companyGitHubPage = 'https://' + companyName + '.github.io'
#===
Pod::Spec.new do |s|
s.name = companyPrefix + projName
s.summary = projSummary
s.version = '4.0.2'
s.homepage = companyGitHubPage + '/' + projName
s.source = { :git => companyGitHubAccount + '/' + projName + '.git', :tag => s.version }
s.source_files = 'Sources/**/*.swift'
s.ios.deployment_target = '8.0'
s.requires_arc = true
# s.dependency 'XXX', '~> 1.4'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'Maxim Khatskevich' => 'maxim@khatskevi.ch' }
end

View File

@ -1,188 +0,0 @@
# Customise this file, documentation can be found here:
# https://github.com/KrauseFx/fastlane/tree/master/docs
# All available actions: https://github.com/KrauseFx/fastlane/blob/master/docs/Actions.md
# can also be listed using the `fastlane actions` command
# Change the syntax highlighting to Ruby
# All lines starting with a # are ignored when running `fastlane`
# By default, fastlane will send which actions are used
# No personal data is shared, more information on https://github.com/fastlane/enhancer
# Uncomment the following line to opt out
# opt_out_usage
# If you want to automatically update fastlane if a new version is available:
# update_fastlane
# This is the minimum version number required.
# Update this, if you use features of a newer version
fastlane_version '1.100.0'
default_platform :ios
#===
companyName = 'XCEssentials'
companyPrefix = 'XCE'
repoName = 'APIClient'
repoURL = 'https://github.com/' + companyName + '/' + repoName
moduleName = companyPrefix + repoName
projName = 'Main' + '.xcodeproj'
podspecFilePath = './' + moduleName + '.podspec'
#===
platform :ios do
lane :finalize_release do
ensure_git_branch(
branch: 'release/*'
)
# ===
ensure_git_status_clean
# ===
pod_lib_lint
# ===
versionNumber = get_version_number(xcodeproj: projName)
puts 'Current VERSION number: ' + versionNumber
# === Infer new version number
defaultNewVersion = git_branch.split('/').last
# === Define new version number
useInferredNEWVersionNumber = prompt(
text: 'Proceed with inferred NEW version number (' + defaultNewVersion + ')?',
boolean: true
)
if useInferredNEWVersionNumber
newVersionNumber = defaultNewVersion
else
newVersionNumber = prompt(text: 'New VERSION number:')
end
# === Apply NEW version number and increment build number
increment_version_number(
xcodeproj: projName,
version_number: newVersionNumber
)
increment_build_number(
xcodeproj: projName
)
# ===
newBuildNumber = get_build_number(xcodeproj: projName)
commit_version_bump( # it will fail if more than version bump
xcodeproj: projName,
message: 'Version Bump to ' + newVersionNumber + ' (' + newBuildNumber + ')'
)
# ===
version_bump_podspec(
path: podspecFilePath,
version_number: newVersionNumber
)
git_commit(
path: podspecFilePath,
message: 'Version Bump to ' + newVersionNumber + ' in Podspec file'
)
end
# ===
lane :regenerate_project do
# === Remember current version and build numbers
versionNumber = get_version_number(xcodeproj: projName)
buildNumber = get_build_number(xcodeproj: projName)
# === Remove completely current project file/folder
sh 'cd ./.. && rm -r ./' + projName
# === Regenerate project
# default initial location for any command
# is inside 'Fastlane' folder
sh 'cd ./.. && struct generate'
# === Set proper current version and build numbers
increment_version_number(
xcodeproj: projName,
version_number: versionNumber
)
increment_build_number(
xcodeproj: projName,
build_number: buildNumber
)
# === Sort all project entries
sh 'cd ./.. && xcodeproj sort'
# === Add custom 'Run Script Phase' entries
sh 'cd ./.. && ruby ./Scripts/AfterReGenerateProject.rb ' + projName
end
# ===
lane :generate_project do
# === Generate project from scratch
# default initial location for any command
# is inside 'Fastlane' folder
sh 'cd ./.. && struct generate'
# === Set proper build number (proper version number is stored in the Info file)
newBuildNumber = prompt(text: 'Desired BUILD number:')
increment_build_number(
xcodeproj: projName,
build_number: newBuildNumber
)
# === Sort all project entries
sh 'cd ./.. && xcodeproj sort'
# === Add custom 'Run Script Phase' entries
sh 'cd ./.. && ruby ./Scripts/AfterReGenerateProject.rb ' + projName
end
end
# More information about multiple platforms in fastlane: https://github.com/KrauseFx/fastlane/blob/master/docs/Platforms.md
# All available actions: https://github.com/KrauseFx/fastlane/blob/master/docs/Actions.md

View File

@ -1,53 +0,0 @@
fastlane documentation
================
# Installation
Make sure you have the latest version of the Xcode command line tools installed:
```
xcode-select --install
```
## Choose your installation method:
<table width="100%" >
<tr>
<th width="33%"><a href="http://brew.sh">Homebrew</a></td>
<th width="33%">Installer Script</td>
<th width="33%">Rubygems</td>
</tr>
<tr>
<td width="33%" align="center">macOS</td>
<td width="33%" align="center">macOS</td>
<td width="33%" align="center">macOS or Linux with Ruby 2.0.0 or above</td>
</tr>
<tr>
<td width="33%"><code>brew cask install fastlane</code></td>
<td width="33%"><a href="https://download.fastlane.tools">Download the zip file</a>. Then double click on the <code>install</code> script (or run it in a terminal window).</td>
<td width="33%"><code>sudo gem install fastlane -NV</code></td>
</tr>
</table>
# Available Actions
## iOS
### ios finalize_release
```
fastlane ios finalize_release
```
### ios regenerate_project
```
fastlane ios regenerate_project
```
### ios generate_project
```
fastlane ios generate_project
```
----
This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run.
More information about fastlane can be found on [fastlane.tools](https://fastlane.tools).
The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools).

View File

@ -1,71 +0,0 @@
# generated with XCEProjectGenerator
# https://github.com/XCEssentials/ProjectGenerator
# https://github.com/workshop/struct/wiki/Spec-format:-v2.0
version: 2.1.0
configurations:
Debug:
type: "debug"
overrides:
IPHONEOS_DEPLOYMENT_TARGET: "8.0"
SWIFT_VERSION: "3.0"
VERSIONING_SYSTEM: "apple-generic"
CURRENT_PROJECT_VERSION: "0"
SWIFT_OPTIMIZATION_LEVEL: "-Onone"
Release:
type: "release"
overrides:
IPHONEOS_DEPLOYMENT_TARGET: "8.0"
SWIFT_VERSION: "3.0"
VERSIONING_SYSTEM: "apple-generic"
CURRENT_PROJECT_VERSION: "0"
targets:
Fwk:
platform: "ios"
type: ":framework"
sources:
- "Sources"
configurations:
Debug:
PRODUCT_NAME: "XCEAPIClient"
IPHONEOS_DEPLOYMENT_TARGET: "8.0"
PRODUCT_BUNDLE_IDENTIFIER: "io.XCEssentials.APIClient"
INFOPLIST_FILE: "Info/Fwk.plist"
SDKROOT: "iphoneos"
TARGETED_DEVICE_FAMILY: "1,2"
DEFINES_MODULE: "NO"
SKIP_INSTALL: "YES"
MTL_ENABLE_DEBUG_INFO: "true"
Release:
PRODUCT_NAME: "XCEAPIClient"
IPHONEOS_DEPLOYMENT_TARGET: "8.0"
PRODUCT_BUNDLE_IDENTIFIER: "io.XCEssentials.APIClient"
INFOPLIST_FILE: "Info/Fwk.plist"
SDKROOT: "iphoneos"
TARGETED_DEVICE_FAMILY: "1,2"
DEFINES_MODULE: "NO"
SKIP_INSTALL: "YES"
Tests:
platform: "ios"
type: ":bundle.unit-test"
references:
- "Fwk"
sources:
- "Tests"
configurations:
Debug:
LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"
IPHONEOS_DEPLOYMENT_TARGET: "8.0"
PRODUCT_BUNDLE_IDENTIFIER: "io.XCEssentials.APIClient.Tst"
INFOPLIST_FILE: "Info/Tst.plist"
FRAMEWORK_SEARCH_PATHS: "$(inherited) $(BUILT_PRODUCTS_DIR)"
MTL_ENABLE_DEBUG_INFO: "true"
Release:
LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"
IPHONEOS_DEPLOYMENT_TARGET: "8.0"
PRODUCT_BUNDLE_IDENTIFIER: "io.XCEssentials.APIClient.Tst"
INFOPLIST_FILE: "Info/Tst.plist"
FRAMEWORK_SEARCH_PATHS: "$(inherited) $(BUILT_PRODUCTS_DIR)"
variants:
$base:
abstract: true
Main: