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

Commit db788d5

Browse files
authored
Use ProStoreTools instead of SigningManager
1 parent 2d2e941 commit db788d5

3 files changed

Lines changed: 8 additions & 205 deletions

File tree

Lines changed: 0 additions & 198 deletions
Original file line numberDiff line numberDiff line change
@@ -1,202 +1,4 @@
1-
import Foundation
2-
import ZsignSwift
3-
import ZIPFoundation
4-
51
struct FileItem {
62
var url: URL?
73
var name: String { url?.lastPathComponent ?? "" }
8-
}
9-
10-
class SigningManager {
11-
static func sign(
12-
appPath: String,
13-
provisionPath: String,
14-
p12Path: String,
15-
p12Password: String,
16-
entitlementsPath: String,
17-
removeProvision: Bool,
18-
completion: @escaping (Bool, Error?) -> Void
19-
) {
20-
// Explicitly discard result to silence "result unused" warning
21-
_ = Zsign.sign(
22-
appPath: appPath,
23-
provisionPath: provisionPath,
24-
p12Path: p12Path,
25-
p12Password: p12Password,
26-
entitlementsPath: entitlementsPath,
27-
removeProvision: removeProvision,
28-
completion: completion
29-
)
30-
}
31-
32-
static func prepareTemporaryWorkspace() throws -> (URL, URL, URL) {
33-
let fm = FileManager.default
34-
let tmpRoot = fm.temporaryDirectory.appendingPathComponent("zsign_ios_\(UUID().uuidString)")
35-
let inputs = tmpRoot.appendingPathComponent("inputs")
36-
let work = tmpRoot.appendingPathComponent("work")
37-
try fm.createDirectory(at: inputs, withIntermediateDirectories: true)
38-
try fm.createDirectory(at: work, withIntermediateDirectories: true)
39-
return (tmpRoot, inputs, work)
40-
}
41-
42-
static func copyInputFiles(ipaURL: URL, p12URL: URL, provURL: URL, to inputsDir: URL) throws -> (URL, URL, URL) {
43-
let fm = FileManager.default
44-
45-
let localIPA = inputsDir.appendingPathComponent(ipaURL.lastPathComponent)
46-
let localP12 = inputsDir.appendingPathComponent(p12URL.lastPathComponent)
47-
let localProv = inputsDir.appendingPathComponent(provURL.lastPathComponent)
48-
49-
[localIPA, localP12, localProv].forEach {
50-
if fm.fileExists(atPath: $0.path) {
51-
try? fm.removeItem(at: $0)
52-
}
53-
}
54-
55-
try fm.copyItem(at: ipaURL, to: localIPA)
56-
try fm.copyItem(at: p12URL, to: localP12)
57-
try fm.copyItem(at: provURL, to: localProv)
58-
59-
return (localIPA, localP12, localProv)
60-
}
61-
62-
static func extractIPA(ipaURL: URL, to workDir: URL) throws {
63-
// Use throwing initializer (deprecated non-throwing variant removed)
64-
let archive = try Archive(url: ipaURL, accessMode: .read)
65-
66-
let fm = FileManager.default
67-
for entry in archive {
68-
let dest = workDir.appendingPathComponent(entry.path)
69-
try fm.createDirectory(at: dest.deletingLastPathComponent(), withIntermediateDirectories: true)
70-
if entry.type == .directory {
71-
try fm.createDirectory(at: dest, withIntermediateDirectories: true)
72-
} else {
73-
// Explicit discard in case extract returns a value in this version
74-
_ = try archive.extract(entry, to: dest)
75-
}
76-
}
77-
}
78-
79-
static func findAppBundle(in payloadDir: URL) throws -> URL {
80-
let fm = FileManager.default
81-
guard fm.fileExists(atPath: payloadDir.path) else {
82-
throw NSError(domain: "Zsign", code: 1, userInfo: [NSLocalizedDescriptionKey: "Payload not found"])
83-
}
84-
85-
let contents = try fm.contentsOfDirectory(atPath: payloadDir.path)
86-
guard let appName = contents.first(where: { $0.hasSuffix(".app") }) else {
87-
throw NSError(domain: "Zsign", code: 2, userInfo: [NSLocalizedDescriptionKey: "No .app bundle in Payload"])
88-
}
89-
90-
return payloadDir.appendingPathComponent(appName)
91-
}
92-
93-
static func createSignedIPA(from workDir: URL, originalIPAURL: URL, outputDir: URL) throws -> URL {
94-
let fm = FileManager.default
95-
96-
let originalBase = originalIPAURL.deletingPathExtension().lastPathComponent
97-
let finalFileName = "\(originalBase)_signed_\(UUID().uuidString).ipa"
98-
let signedIpa = outputDir.appendingPathComponent(finalFileName)
99-
100-
// Throwing initializer
101-
let writeArchive = try Archive(url: signedIpa, accessMode: .create)
102-
103-
let enumerator = fm.enumerator(at: workDir, includingPropertiesForKeys: [.isDirectoryKey], options: [], errorHandler: nil)!
104-
var directories: [URL] = []
105-
var filesList: [URL] = []
106-
107-
for case let file as URL in enumerator {
108-
if file == workDir { continue }
109-
let isDir = (try? file.resourceValues(forKeys: [.isDirectoryKey]).isDirectory) ?? file.hasDirectoryPath
110-
if isDir { directories.append(file) } else { filesList.append(file) }
111-
}
112-
113-
directories.sort { $0.path.count < $1.path.count }
114-
let base = workDir
115-
116-
for dir in directories {
117-
let relative = dir.path.replacingOccurrences(of: base.path + "/", with: "")
118-
let entryPath = relative.hasSuffix("/") ? relative : relative + "/"
119-
try writeArchive.addEntry(with: entryPath, relativeTo: base, compressionMethod: .none)
120-
}
121-
122-
for file in filesList {
123-
let relative = file.path.replacingOccurrences(of: base.path + "/", with: "")
124-
try writeArchive.addEntry(with: relative, relativeTo: base, compressionMethod: .deflate)
125-
}
126-
127-
let docs = fm.urls(for: .documentDirectory, in: .userDomainMask).first!
128-
let outURL = docs.appendingPathComponent(finalFileName)
129-
if fm.fileExists(atPath: outURL.path) { try fm.removeItem(at: outURL) }
130-
try fm.copyItem(at: signedIpa, to: outURL)
131-
132-
return outURL
133-
}
134-
135-
static func cleanupTemporaryFiles(at url: URL) {
136-
try? FileManager.default.removeItem(at: url)
137-
}
138-
139-
static func processSigning(
140-
ipaURL: URL,
141-
p12URL: URL,
142-
provURL: URL,
143-
p12Password: String,
144-
progressUpdate: @escaping (String) -> Void,
145-
completion: @escaping (Result<URL, Error>) -> Void
146-
) {
147-
DispatchQueue.global(qos: .userInitiated).async {
148-
do {
149-
progressUpdate("Preparing files 📂")
150-
151-
let (tmpRoot, inputsDir, workDir) = try prepareTemporaryWorkspace()
152-
defer { cleanupTemporaryFiles(at: tmpRoot) }
153-
154-
let (localIPA, localP12, localProv) = try copyInputFiles(
155-
ipaURL: ipaURL,
156-
p12URL: p12URL,
157-
provURL: provURL,
158-
to: inputsDir
159-
)
160-
161-
progressUpdate("Unzipping IPA 🔓")
162-
try extractIPA(ipaURL: localIPA, to: workDir)
163-
164-
let payloadDir = workDir.appendingPathComponent("Payload")
165-
let appDir = try findAppBundle(in: payloadDir)
166-
167-
progressUpdate("Signing \(appDir.lastPathComponent) ✍️")
168-
169-
// Replace spin-wait with semaphore (optional improvement)
170-
let sema = DispatchSemaphore(value: 0)
171-
var signingError: Error?
172-
173-
sign(
174-
appPath: appDir.path,
175-
provisionPath: localProv.path,
176-
p12Path: localP12.path,
177-
p12Password: p12Password,
178-
entitlementsPath: "",
179-
removeProvision: false
180-
) { _, error in
181-
signingError = error
182-
sema.signal()
183-
}
184-
185-
sema.wait()
186-
if let error = signingError { throw error }
187-
188-
progressUpdate("Zipping signed IPA 📦")
189-
let signedIPAURL = try createSignedIPA(
190-
from: workDir,
191-
originalIPAURL: ipaURL,
192-
outputDir: tmpRoot
193-
)
194-
195-
completion(.success(signedIPAURL))
196-
197-
} catch {
198-
completion(.failure(error))
199-
}
200-
}
201-
}
2024
}

Sources/prosign/views/SignerView.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import SwiftUI
22
import UniformTypeIdentifiers
3+
import ProStoreTools
34

45
struct SignerView: View {
56
@State private var ipa = FileItem()
@@ -154,7 +155,7 @@ struct SignerView: View {
154155
isProcessing = true
155156
progressMessage = "Starting signing process..."
156157

157-
SigningManager.processSigning(
158+
ProStoreTools.sign(
158159
ipaURL: ipaURL,
159160
p12URL: p12URL,
160161
provURL: provURL,

project.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ configs:
77
Release: release
88

99
packages:
10-
ZsignPackage:
11-
url: https://github.com/khcrysalis/Zsign-Package.git
12-
branch: package
10+
ProStoreTools:
11+
url: https://github.com/ProStore-iOS/ProStoreTools.git
12+
branch: main
1313
ZIPFoundation:
1414
url: https://github.com/weichsel/ZIPFoundation.git
1515
branch: main
@@ -44,7 +44,7 @@ targets:
4444
- prosign
4545
- ProSign
4646
dependencies:
47-
- package: ZsignPackage
48-
product: ZsignSwift
47+
- package: ProStoreTools
48+
product: ProStoreTools
4949
- package: ZIPFoundation
50-
product: ZIPFoundation
50+
product: ZIPFoundation

0 commit comments

Comments
 (0)