Skip to content
This repository was archived by the owner on Mar 1, 2020. It is now read-only.

Commit a6bb1db

Browse files
committed
Switch to Conche
1 parent 9466b53 commit a6bb1db

File tree

9 files changed

+247
-276
lines changed

9 files changed

+247
-276
lines changed

.gitignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
bin/querykit
2-
Rome/
31
querykit-cli.tar.gz
4-
2+
.conche/

.travis.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
language: objective-c
2-
osx_image: xcode7
3-
before_install:
4-
- gem install cocoapods --pre --no-document
5-
- gem install cocoapods-rome --no-document
2+
osx_image: xcode7.1
3+
install: brew install --HEAD kylef/formulae/conche
64
script:
5+
- conche build
76
- make tarball
87
deploy:
98
provider: releases

Makefile

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,14 @@
11
DESTDIR := /usr/local
22

3-
all: dependencies querykit
4-
5-
querykit:
6-
xcrun -sdk macosx swiftc -O -o bin/querykit -F Rome -framework CoreData -framework PathKit -framework Stencil bin/querykit.swift
7-
8-
dependencies:
9-
pod install --no-integrate
10-
113
install:
12-
mkdir -p "$(DESTDIR)/bin/"
13-
mkdir -p "$(DESTDIR)/share/querykit/"
14-
mkdir -p "$(DESTDIR)/Frameworks/"
15-
cp -f "bin/querykit" "$(DESTDIR)/bin/"
16-
cp -f "share/querykit/template.swift" "$(DESTDIR)/share/querykit/"
17-
cp -fr "Rome/" "$(DESTDIR)/Frameworks/"
18-
install_name_tool -add_rpath "@executable_path/../Frameworks/" "$(DESTDIR)/bin/querykit"
4+
conche install --prefix "$(DESTDIR)"
5+
install -d "$(DESTDIR)/share/querykit"
6+
install -C "share/querykit/template.swift" "$(DESTDIR)/share/querykit/"
197

20-
clean:
21-
rm -fr Rome build bin/querykit
22-
23-
tarball: all
24-
git checkout-index --all --prefix=build/
25-
GZIP=-9 tar -czf querykit-cli.tar.gz Makefile Rome/ bin/querykit share/
8+
tarball:
9+
make DESTDIR=build install
10+
install -C -m 644 Makefile.binary build/Makefile
11+
GZIP=-9 tar -czf querykit-cli.tar.gz build/
2612

13+
clean:
14+
rm -fr build querykit-cli.tar.gz

Makefile.binary

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
DESTDIR := /usr/local
2+
3+
LIBS=$(shell ls lib/QueryKitCLI/*.dylib)
4+
5+
install:
6+
install -d "$(DESTDIR)/bin" "$(DESTDIR)/share/querykit" "$(DESTDIR)/lib/QueryKitCLI"
7+
install -C "bin/querykit" "$(DESTDIR)/bin"
8+
install -C $(LIBS) "$(DESTDIR)/lib/QueryKitCLI"
9+
install -C -m 644 "share/querykit/template.swift" "$(DESTDIR)/share/querykit"

Podfile

Lines changed: 0 additions & 9 deletions
This file was deleted.

Podfile.lock

Lines changed: 0 additions & 27 deletions
This file was deleted.

QueryKitCLI.podspec.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "QueryKitCLI",
3+
"version": "0.2.0",
4+
"dependencies": {
5+
"Stencil": ["~> 0.4.0"],
6+
"PathKit": [],
7+
"Commander": ["~> 0.2.2"]
8+
},
9+
"source_files": "QueryKitCLI/QueryKit.swift",
10+
"entry_points": {
11+
"cli": {
12+
"querykit": "bin/querykit.swift"
13+
}
14+
}
15+
}

QueryKitCLI/QueryKit.swift

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
import Darwin.libc
2+
import CoreData
3+
import Commander
4+
import PathKit
5+
import Stencil
6+
7+
8+
extension Path {
9+
static var processPath: Path {
10+
if Process.arguments[0].componentsSeparatedByString(Path.separator).count > 1 {
11+
return Path.current + Process.arguments[0]
12+
}
13+
14+
let PATH = NSProcessInfo.processInfo().environment["PATH"]!
15+
let paths = PATH.componentsSeparatedByString(":").map {
16+
Path($0) + Process.arguments[0]
17+
}.filter { $0.exists }
18+
19+
return paths.first!
20+
}
21+
22+
public static var defaultTemplatePath: Path {
23+
return processPath + "../../share/querykit/template.swift"
24+
}
25+
}
26+
27+
28+
func compileCoreDataModel(source: Path) -> Path {
29+
let destinationExtension = source.`extension`!.hasSuffix("d") ? ".momd" : ".mom"
30+
let destination = try! Path.uniqueTemporary() + (source.lastComponentWithoutExtension + destinationExtension)
31+
system("xcrun momc \(source.absolute()) \(destination.absolute())")
32+
return destination
33+
}
34+
35+
class AttributeDescription : NSObject {
36+
let name: String
37+
let type: String
38+
39+
init(name: String, type: String) {
40+
self.name = name
41+
self.type = type
42+
}
43+
}
44+
45+
extension NSAttributeDescription {
46+
var qkClassName: String? {
47+
switch attributeType {
48+
case .BooleanAttributeType:
49+
return "Bool"
50+
case .StringAttributeType:
51+
return "String"
52+
default:
53+
return attributeValueClassName
54+
}
55+
}
56+
57+
var qkAttributeDescription: AttributeDescription? {
58+
if let className = qkClassName {
59+
return AttributeDescription(name: name, type: className)
60+
}
61+
62+
return nil
63+
}
64+
}
65+
66+
extension NSRelationshipDescription {
67+
var qkAttributeDescription: AttributeDescription? {
68+
if let destinationEntity = destinationEntity {
69+
var type = destinationEntity.qk_className
70+
71+
if toMany {
72+
type = "Set<\(type)>"
73+
74+
if ordered {
75+
type = "NSOrderedSet"
76+
}
77+
}
78+
79+
return AttributeDescription(name: name, type: type)
80+
}
81+
82+
return nil
83+
}
84+
}
85+
86+
extension NSEntityDescription {
87+
var qk_className: String {
88+
if managedObjectClassName.hasPrefix(".") {
89+
// "Current Module"
90+
return managedObjectClassName.substringFromIndex(managedObjectClassName.startIndex.successor())
91+
}
92+
93+
return managedObjectClassName
94+
}
95+
96+
func qk_hasSuperProperty(name: String) -> Bool {
97+
if let superentity = superentity {
98+
if superentity.qk_className != "NSManagedObject" && superentity.propertiesByName[name] != nil {
99+
return true
100+
}
101+
102+
return superentity.qk_hasSuperProperty(name)
103+
}
104+
105+
return false
106+
}
107+
}
108+
109+
class CommandError : ErrorType {
110+
let description: String
111+
112+
init(description: String) {
113+
self.description = description
114+
}
115+
}
116+
117+
func render(entity: NSEntityDescription, destination: Path, template: Template) throws {
118+
let attributes = entity.properties.flatMap { property -> AttributeDescription? in
119+
if entity.qk_hasSuperProperty(property.name) {
120+
return nil
121+
}
122+
123+
if let attribute = property as? NSAttributeDescription {
124+
return attribute.qkAttributeDescription
125+
} else if let relationship = property as? NSRelationshipDescription {
126+
return relationship.qkAttributeDescription
127+
}
128+
129+
return nil
130+
}
131+
132+
let context = Context(dictionary: [
133+
"className": entity.qk_className,
134+
"attributes": attributes,
135+
"entityName": entity.name ?? "Unknown",
136+
])
137+
138+
try destination.write(try template.render(context))
139+
}
140+
141+
func render(model: NSManagedObjectModel, destination: Path, templatePath: Path) throws {
142+
if !destination.exists {
143+
try destination.mkpath()
144+
}
145+
146+
for entity in model.entities {
147+
let template = try Template(path: templatePath)
148+
let className = entity.qk_className
149+
150+
if className == "NSManagedObject" {
151+
let name = entity.name ?? "Unknown"
152+
print("-> Skipping entity '\(name)', doesn't use a custom class.")
153+
continue
154+
}
155+
156+
let destinationFile = destination + (className + "+QueryKit.swift")
157+
158+
do {
159+
try render(entity, destination: destinationFile, template: template)
160+
print("-> Generated '\(className)' '\(destinationFile)'")
161+
} catch {
162+
print(error)
163+
}
164+
}
165+
}
166+
167+
public func generate(model: Path, output: Path, template: Path) throws {
168+
let compiledModel = compileCoreDataModel(model)
169+
let modelURL = NSURL(fileURLWithPath: compiledModel.description)
170+
let model = NSManagedObjectModel(contentsOfURL: modelURL)!
171+
try render(model, destination: output, templatePath: template)
172+
}
173+
174+
extension Path: ArgumentConvertible {
175+
public init(parser: ArgumentParser) throws {
176+
if let path = parser.shift() {
177+
self.init(path)
178+
} else {
179+
throw ArgumentError.MissingValue(argument: nil)
180+
}
181+
}
182+
}
183+
184+
public func isReadable(path: Path) -> Path {
185+
if !path.isReadable {
186+
print("'\(path)' does not exist or is not readable.")
187+
exit(1)
188+
}
189+
190+
return path
191+
}
192+
193+
public func isCoreDataModel(path: Path) -> Path {
194+
let ext = path.`extension`
195+
if ext == "xcdatamodel" || ext == "xcdatamodeld" {
196+
return isReadable(path)
197+
}
198+
199+
print("'\(path)' is not a Core Data model.")
200+
exit(1)
201+
}

0 commit comments

Comments
 (0)