核心功能: - ✅ Categories/Series双视图管理(category_view.rs + import_markdown.rs) - ✅ FUSE Multi-Volume支持(tree_type参数) - ✅ SSH/SFTP/SCP/rsync协议完整实现(4042行) - ✅ NFS/SMB Module Phase 1-3完成 - ✅ Archive Module Phase 1-4完成(2916行) - ✅ Download Center API完整实现 - ✅ S3兼容API实现(560行) Git配置修正: - ✅ 删除错误origin(gitea.momentry.ddns.net) - ✅ 删除m5max128(指向机器名) - ✅ 设置origin = m5max128gitea.momentry.ddns.net/admin/markbase - ✅ 设置m4minigitea = m4minigitea.momentry.ddns.net/warren/markbase 数据清理: - ✅ 删除38个临时SQLite(保留accusys.sqlite、demo.sqlite) - ✅ 删除.bak、test_*.bin、调试脚本等临时文件 - ✅ 删除临时目录(build/、download files/、raid_test/等) - ✅ 更新.gitignore排除临时文件 架构优化: - 52个文件修改,2434行新增,4739行删除 - Workspace成员整合(16个crate) - 数据库状态:accusys.sqlite保留(主demo测试) 远程同步: - ✅ 准备推送到m5max128gitea(远程Gitea) - ✅ 准备推送到m4minigitea(本地Gitea)
245 lines
9.2 KiB
Ruby
245 lines
9.2 KiB
Ruby
#!/usr/bin/env ruby
|
|
require 'xcodeproj'
|
|
|
|
# Create project
|
|
project_path = 'MarkBaseInstaller.xcodeproj'
|
|
project = Xcodeproj::Project.new(project_path)
|
|
|
|
# Create target (use macOS 14.0 as base platform, will update deployment target later)
|
|
target = project.new_target(:application, 'MarkBaseInstaller', :macos, '14.0')
|
|
|
|
# Create group for source files
|
|
main_group = project.main_group
|
|
sources_group = main_group.new_group('Sources')
|
|
|
|
# Create AppDelegate.swift file reference
|
|
app_delegate_file = sources_group.new_file('AppDelegate.swift')
|
|
|
|
# Add file to target
|
|
target.source_build_phase.add_file_reference(app_delegate_file)
|
|
|
|
# Configure build settings
|
|
target.build_configurations.each do |config|
|
|
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'com.momentry.markbase.installer'
|
|
config.build_settings['DEVELOPMENT_TEAM'] = 'K3TDMD9Y6B'
|
|
config.build_settings['CODE_SIGN_IDENTITY'] = 'Developer ID Application'
|
|
config.build_settings['SWIFT_VERSION'] = '6.0'
|
|
config.build_settings['MACOSX_DEPLOYMENT_TARGET'] = '26.0'
|
|
config.build_settings['PRODUCT_NAME'] = 'MarkBaseInstaller'
|
|
config.build_settings['INFOPLIST_FILE'] = 'Info.plist'
|
|
config.build_settings['CODE_SIGN_ENTITLEMENTS'] = 'MarkBaseInstaller.entitlements'
|
|
|
|
# Disable automatic signing (use manual Developer ID)
|
|
config.build_settings['CODE_SIGN_STYLE'] = 'Manual'
|
|
end
|
|
|
|
# Create Info.plist
|
|
info_plist_path = 'Info.plist'
|
|
File.write(info_plist_path, <<-PLIST)
|
|
<?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>CFBundleIdentifier</key>
|
|
<string>com.momentry.markbase.installer</string>
|
|
<key>CFBundleName</key>
|
|
<string>MarkBase Installer</string>
|
|
<key>CFBundleVersion</key>
|
|
<string>1.0.0</string>
|
|
<key>CFBundleShortVersionString</key>
|
|
<string>1.0.0</string>
|
|
<key>CFBundleExecutable</key>
|
|
<string>MarkBaseInstaller</string>
|
|
<key>CFBundlePackageType</key>
|
|
<string>APPL</string>
|
|
<key>LSMinimumSystemVersion</key>
|
|
<string>26.0</string>
|
|
<key>NSHighResolutionCapable</key>
|
|
<true/>
|
|
<key>NSPrincipalClass</key>
|
|
<string>NSApplication</string>
|
|
</dict>
|
|
</plist>
|
|
PLIST
|
|
|
|
# Create entitlements
|
|
entitlements_path = 'MarkBaseInstaller.entitlements'
|
|
File.write(entitlements_path, <<-ENTITLEMENTS)
|
|
<?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>com.apple.developer.system-extension.install</key>
|
|
<true/>
|
|
</dict>
|
|
</plist>
|
|
ENTITLEMENTS
|
|
|
|
# Create AppDelegate.swift
|
|
app_delegate_path = 'Sources/AppDelegate.swift'
|
|
File.write(app_delegate_path, <<-SWIFT)
|
|
import Cocoa
|
|
import SystemExtensions
|
|
import OSLog
|
|
|
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
|
let logger = Logger(subsystem: "com.momentry.markbase.installer", category: "AppDelegate")
|
|
var window: NSWindow!
|
|
var statusLabel: NSTextField!
|
|
var installButton: NSButton!
|
|
var extensionDelegate: ExtensionDelegate?
|
|
|
|
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
|
logger.info("MarkBase Installer started")
|
|
createWindow()
|
|
setupUI()
|
|
window.makeKeyAndOrderFront(nil)
|
|
}
|
|
|
|
func createWindow() {
|
|
window = NSWindow(
|
|
contentRect: NSRect(x: 0, y: 0, width: 500, height: 400),
|
|
styleMask: [.titled, .closable, .miniaturizable],
|
|
backing: .buffered,
|
|
defer: false
|
|
)
|
|
window.title = "MarkBase Installer"
|
|
window.center()
|
|
window.isReleasedWhenClosed = false
|
|
}
|
|
|
|
func setupUI() {
|
|
let contentView = window.contentView!
|
|
|
|
// Title
|
|
let titleLabel = NSTextField(labelWithString: "MarkBase System Extension Installer")
|
|
titleLabel.font = NSFont.systemFont(ofSize: 18, weight: .bold)
|
|
titleLabel.alignment = .center
|
|
contentView.addSubview(titleLabel)
|
|
|
|
// Status Label
|
|
statusLabel = NSTextField(wrappingLabelWithString: "Ready to install MarkBaseFS System Extension")
|
|
statusLabel.font = NSFont.systemFont(ofSize: 14)
|
|
statusLabel.alignment = .center
|
|
contentView.addSubview(statusLabel)
|
|
|
|
// Install Button
|
|
installButton = NSButton(title: "Install System Extension", target: self, action: #selector(installExtension))
|
|
installButton.bezelStyle = .rounded
|
|
installButton.font = NSFont.systemFont(ofSize: 13, weight: .medium)
|
|
contentView.addSubview(installButton)
|
|
|
|
// Layout
|
|
titleLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
statusLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
installButton.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
NSLayoutConstraint.activate([
|
|
titleLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
|
|
titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 50),
|
|
|
|
statusLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
|
|
statusLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 40),
|
|
statusLabel.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.8),
|
|
|
|
installButton.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
|
|
installButton.topAnchor.constraint(equalTo: statusLabel.bottomAnchor, constant: 40),
|
|
installButton.widthAnchor.constraint(equalToConstant: 200),
|
|
installButton.heightAnchor.constraint(equalToConstant: 30),
|
|
])
|
|
}
|
|
|
|
@objc func installExtension() {
|
|
logger.info("Install button clicked")
|
|
|
|
let extensionID = "com.momentry.markbase.fskit"
|
|
logger.info("Requesting activation for extension: \(extensionID)")
|
|
|
|
updateStatus("Requesting installation...")
|
|
installButton.isEnabled = false
|
|
|
|
let request = OSSystemExtensionRequest.activationRequest(
|
|
forExtensionWithIdentifier: extensionID,
|
|
queue: .main
|
|
)
|
|
|
|
// Create delegate and store as strong reference
|
|
extensionDelegate = ExtensionDelegate(
|
|
onSuccess: {
|
|
self.logger.info("Extension activated successfully")
|
|
self.updateStatus("✅ Installation successful!")
|
|
self.installButton.isEnabled = true
|
|
self.extensionDelegate = nil
|
|
},
|
|
onError: { error in
|
|
self.logger.error("Extension activation failed: \(error.localizedDescription)")
|
|
self.updateStatus("❌ Installation failed: \(error.localizedDescription)")
|
|
self.installButton.isEnabled = true
|
|
self.extensionDelegate = nil
|
|
},
|
|
onNeedsApproval: {
|
|
self.logger.info("Extension needs user approval")
|
|
self.updateStatus("⏳ Waiting for approval in System Settings")
|
|
}
|
|
)
|
|
|
|
request.delegate = extensionDelegate
|
|
OSSystemExtensionManager.shared.submitRequest(request)
|
|
}
|
|
|
|
func updateStatus(_ message: String) {
|
|
DispatchQueue.main.async {
|
|
self.statusLabel.stringValue = message
|
|
}
|
|
}
|
|
}
|
|
|
|
class ExtensionDelegate: NSObject, OSSystemExtensionRequestDelegate {
|
|
let onSuccess: () -> Void
|
|
let onError: (Error) -> Void
|
|
let onNeedsApproval: () -> Void
|
|
|
|
init(onSuccess: @escaping () -> Void, onError: @escaping (Error) -> Void, onNeedsApproval: @escaping () -> Void) {
|
|
self.onSuccess = onSuccess
|
|
self.onError = onError
|
|
self.onNeedsApproval = onNeedsApproval
|
|
super.init()
|
|
}
|
|
|
|
func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) {
|
|
Logger(subsystem: "com.momentry.markbase.installer", category: "ExtensionDelegate")
|
|
.info("Request finished with result")
|
|
onSuccess()
|
|
}
|
|
|
|
func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) {
|
|
Logger(subsystem: "com.momentry.markbase.installer", category: "ExtensionDelegate")
|
|
.error("Request failed with error: \(error.localizedDescription)")
|
|
onError(error)
|
|
}
|
|
|
|
func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) {
|
|
Logger(subsystem: "com.momentry.markbase.installer", category: "ExtensionDelegate")
|
|
.info("Request needs user approval")
|
|
onNeedsApproval()
|
|
}
|
|
|
|
func request(_ request: OSSystemExtensionRequest, actionForReplacingExtension existing: OSSystemExtensionProperties, withExtension ext: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction {
|
|
Logger(subsystem: "com.momentry.markbase.installer", category: "ExtensionDelegate")
|
|
.info("Replacing extension")
|
|
return .replace
|
|
}
|
|
}
|
|
SWIFT
|
|
|
|
# Save project
|
|
project.save
|
|
|
|
puts "Project created successfully at #{project_path}"
|
|
puts "Files created:"
|
|
puts " - Info.plist"
|
|
puts " - MarkBaseInstaller.entitlements"
|
|
puts " - Sources/AppDelegate.swift"
|
|
puts ""
|
|
puts "Next step: Build the project with:"
|
|
puts " xcodebuild -project #{project_path} -scheme MarkBaseInstaller -configuration Release build" |