mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-27 15:17:38 +00:00
Remove control directory creation logic from TunnelServer
The tty-fwd binary should handle its own directory requirements. This removes: - ensureControlDirectoryExists() function - All calls to ensure control directory exists during startup and API calls - Directory writability checks The control directory path is still passed to tty-fwd, but VibeTunnel no longer manages its creation.
This commit is contained in:
parent
63d02b4ed6
commit
975705ae80
4 changed files with 50 additions and 54 deletions
|
|
@ -288,7 +288,7 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "# Build tty-fwd universal binary\necho \"Building tty-fwd universal binary...\"\n\n# Get the project directory\nPROJECT_DIR=\"${SRCROOT}\"\nTTY_FWD_DIR=\"${PROJECT_DIR}/tty-fwd\"\nBUILD_SCRIPT=\"${TTY_FWD_DIR}/build-universal.sh\"\nSOURCE_BINARY=\"${TTY_FWD_DIR}/target/release/tty-fwd-universal\"\nDEST_BINARY=\"${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/Resources/tty-fwd\"\n\n# Check if build script exists\nif [ ! -f \"${BUILD_SCRIPT}\" ]; then\n echo \"error: Build script not found at ${BUILD_SCRIPT}\"\n exit 1\nfi\n\n# Make build script executable\nchmod +x \"${BUILD_SCRIPT}\"\n\n# Change to tty-fwd directory and run build\ncd \"${TTY_FWD_DIR}\"\n./build-universal.sh\n\n# Check if build succeeded\nif [ ! -f \"${SOURCE_BINARY}\" ]; then\n echo \"error: Universal binary not found at ${SOURCE_BINARY}\"\n exit 1\nfi\n\n# Create Resources directory if it doesn't exist\nmkdir -p \"${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/Resources\"\n\n# Copy the binary\ncp \"${SOURCE_BINARY}\" \"${DEST_BINARY}\"\nchmod +x \"${DEST_BINARY}\"\n\necho \"tty-fwd universal binary copied to ${DEST_BINARY}\"\n";
|
shellScript = "# Build tty-fwd universal binary\necho \"Building tty-fwd universal binary...\"\n\n# Get the project directory\nPROJECT_DIR=\"${SRCROOT}\"\nTTY_FWD_DIR=\"${PROJECT_DIR}/tty-fwd\"\nBUILD_SCRIPT=\"${TTY_FWD_DIR}/build-universal.sh\"\nSOURCE_BINARY=\"${TTY_FWD_DIR}/target/release/tty-fwd-universal\"\nDEST_BINARY=\"${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/Resources/tty-fwd\"\n\n# Check if build script exists\nif [ ! -f \"${BUILD_SCRIPT}\" ]; then\n echo \"error: Build script not found at ${BUILD_SCRIPT}\"\n exit 1\nfi\n\n# Make build script executable\nchmod +x \"${BUILD_SCRIPT}\"\n\n# Change to tty-fwd directory and run build\ncd \"${TTY_FWD_DIR}\"\n./build-universal.sh\n\n# Check if build succeeded\nif [ ! -f \"${SOURCE_BINARY}\" ]; then\n echo \"error: Universal binary not found at ${SOURCE_BINARY}\"\n exit 1\nfi\n\n# Create Resources directory if it doesn't exist\nmkdir -p \"${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/Resources\"\n\n# Copy the binary\ncp \"${SOURCE_BINARY}\" \"${DEST_BINARY}\"\nchmod +x \"${DEST_BINARY}\"\n\n# Sign the binary\necho \"Signing tty-fwd binary...\"\ncodesign --force --sign - \"${DEST_BINARY}\"\n\necho \"tty-fwd universal binary copied and signed to ${DEST_BINARY}\"\n";
|
||||||
};
|
};
|
||||||
B2C3D4E5F6A7B8C9D0E1F234 /* Build Web Frontend */ = {
|
B2C3D4E5F6A7B8C9D0E1F234 /* Build Web Frontend */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -111,34 +111,6 @@ public final class TunnelServer {
|
||||||
private let ttyFwdControlDir = FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(".vibetunnel")
|
private let ttyFwdControlDir = FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(".vibetunnel")
|
||||||
.appendingPathComponent("control").path
|
.appendingPathComponent("control").path
|
||||||
|
|
||||||
private func ensureControlDirectoryExists() throws {
|
|
||||||
let controlDirURL = URL(fileURLWithPath: ttyFwdControlDir)
|
|
||||||
|
|
||||||
var isDirectory: ObjCBool = false
|
|
||||||
let exists = FileManager.default.fileExists(atPath: ttyFwdControlDir, isDirectory: &isDirectory)
|
|
||||||
|
|
||||||
if !exists {
|
|
||||||
logger.info("Control directory does not exist, creating at: \(ttyFwdControlDir)")
|
|
||||||
try FileManager.default.createDirectory(at: controlDirURL, withIntermediateDirectories: true, attributes: nil)
|
|
||||||
logger.info("Successfully created control directory at: \(ttyFwdControlDir)")
|
|
||||||
} else if !isDirectory.boolValue {
|
|
||||||
logger.error("Control path exists but is not a directory: \(ttyFwdControlDir)")
|
|
||||||
throw NSError(domain: "TunnelServer", code: 1, userInfo: [NSLocalizedDescriptionKey: "Control path exists but is not a directory"])
|
|
||||||
} else {
|
|
||||||
logger.info("Control directory already exists at: \(ttyFwdControlDir)")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify we can write to the directory
|
|
||||||
let testFile = controlDirURL.appendingPathComponent(".test")
|
|
||||||
do {
|
|
||||||
try "test".write(to: testFile, atomically: true, encoding: .utf8)
|
|
||||||
try FileManager.default.removeItem(at: testFile)
|
|
||||||
logger.info("Control directory is writable")
|
|
||||||
} catch {
|
|
||||||
logger.error("Control directory is not writable: \(error)")
|
|
||||||
throw NSError(domain: "TunnelServer", code: 2, userInfo: [NSLocalizedDescriptionKey: "Control directory is not writable: \(error.localizedDescription)"])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(port: Int = 4_020) {
|
public init(port: Int = 4_020) {
|
||||||
self.port = port
|
self.port = port
|
||||||
|
|
@ -149,13 +121,6 @@ public final class TunnelServer {
|
||||||
|
|
||||||
logger.info("Starting TunnelServer on port \(port)")
|
logger.info("Starting TunnelServer on port \(port)")
|
||||||
|
|
||||||
// Ensure control directory exists at startup
|
|
||||||
do {
|
|
||||||
try ensureControlDirectoryExists()
|
|
||||||
} catch {
|
|
||||||
logger.error("Failed to create control directory: \(error)")
|
|
||||||
throw ServerError.failedToStart("Failed to create control directory: \(error.localizedDescription)")
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let router = Router(context: BasicRequestContext.self)
|
let router = Router(context: BasicRequestContext.self)
|
||||||
|
|
@ -254,15 +219,6 @@ public final class TunnelServer {
|
||||||
|
|
||||||
// Legacy endpoint for backwards compatibility
|
// Legacy endpoint for backwards compatibility
|
||||||
router.get("/sessions") { _, _ async -> Response in
|
router.get("/sessions") { _, _ async -> Response in
|
||||||
// Ensure control directory exists
|
|
||||||
do {
|
|
||||||
try await MainActor.run {
|
|
||||||
try self.ensureControlDirectoryExists()
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
self.logger.error("Failed to ensure control directory exists: \(error)")
|
|
||||||
return self.errorResponse(message: "Failed to initialize control directory: \(error.localizedDescription)")
|
|
||||||
}
|
|
||||||
|
|
||||||
let process = await MainActor.run {
|
let process = await MainActor.run {
|
||||||
TTYForwardManager.shared.createTTYForwardProcess(with: ["--control-path", self.ttyFwdControlDir, "--list-sessions"])
|
TTYForwardManager.shared.createTTYForwardProcess(with: ["--control-path", self.ttyFwdControlDir, "--list-sessions"])
|
||||||
|
|
@ -661,8 +617,6 @@ public final class TunnelServer {
|
||||||
|
|
||||||
private func listSessions() async -> Response {
|
private func listSessions() async -> Response {
|
||||||
do {
|
do {
|
||||||
// Ensure control directory exists
|
|
||||||
try ensureControlDirectoryExists()
|
|
||||||
|
|
||||||
let output = try await executeTtyFwd(args: ["--control-path", ttyFwdControlDir, "--list-sessions"])
|
let output = try await executeTtyFwd(args: ["--control-path", ttyFwdControlDir, "--list-sessions"])
|
||||||
let sessionsData = output.data(using: .utf8) ?? Data()
|
let sessionsData = output.data(using: .utf8) ?? Data()
|
||||||
|
|
@ -724,8 +678,6 @@ public final class TunnelServer {
|
||||||
return errorResponse(message: "Command array is required and cannot be empty", status: .badRequest)
|
return errorResponse(message: "Command array is required and cannot be empty", status: .badRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure control directory exists
|
|
||||||
try ensureControlDirectoryExists()
|
|
||||||
|
|
||||||
let sessionName = "session_\(Int(Date().timeIntervalSince1970))_\(UUID().uuidString.prefix(9))"
|
let sessionName = "session_\(Int(Date().timeIntervalSince1970))_\(UUID().uuidString.prefix(9))"
|
||||||
let cwd = resolvePath(sessionRequest.workingDir ?? "", fallback: FileManager.default.currentDirectoryPath)
|
let cwd = resolvePath(sessionRequest.workingDir ?? "", fallback: FileManager.default.currentDirectoryPath)
|
||||||
|
|
@ -939,7 +891,49 @@ public final class TunnelServer {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get initial file size
|
// Store buffer for incomplete lines
|
||||||
|
var lineBuffer = ""
|
||||||
|
|
||||||
|
// Read existing file content first
|
||||||
|
let fileSize = lseek(fileDescriptor, 0, SEEK_END)
|
||||||
|
if fileSize > 0 {
|
||||||
|
// Read the entire file (or last portion if very large)
|
||||||
|
let maxInitialRead: Int64 = 1024 * 1024 // 1MB max initial read
|
||||||
|
let readSize = min(fileSize, maxInitialRead)
|
||||||
|
let startOffset = max(0, fileSize - readSize)
|
||||||
|
|
||||||
|
lseek(fileDescriptor, startOffset, SEEK_SET)
|
||||||
|
|
||||||
|
let buffer = UnsafeMutablePointer<CChar>.allocate(capacity: Int(readSize) + 1)
|
||||||
|
defer { buffer.deallocate() }
|
||||||
|
|
||||||
|
let bytesRead = read(fileDescriptor, buffer, Int(readSize))
|
||||||
|
if bytesRead > 0 {
|
||||||
|
let data = Data(bytes: buffer, count: bytesRead)
|
||||||
|
if let initialContent = String(data: data, encoding: .utf8) {
|
||||||
|
lineBuffer = initialContent
|
||||||
|
let lines = lineBuffer.components(separatedBy: .newlines)
|
||||||
|
|
||||||
|
// Process all complete lines from existing content
|
||||||
|
if lines.count > 1 {
|
||||||
|
for i in 0..<(lines.count - 1) {
|
||||||
|
let line = lines[i]
|
||||||
|
Task { @MainActor in
|
||||||
|
await self.processNewLine(
|
||||||
|
line: line,
|
||||||
|
startTime: startTime,
|
||||||
|
continuation: continuation
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Keep the last incomplete line in buffer
|
||||||
|
lineBuffer = lines.last ?? ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set position to current end for monitoring new content
|
||||||
var lastReadPosition = lseek(fileDescriptor, 0, SEEK_END)
|
var lastReadPosition = lseek(fileDescriptor, 0, SEEK_END)
|
||||||
|
|
||||||
// Create dispatch source for monitoring file writes
|
// Create dispatch source for monitoring file writes
|
||||||
|
|
@ -949,9 +943,6 @@ public final class TunnelServer {
|
||||||
queue: DispatchQueue.main
|
queue: DispatchQueue.main
|
||||||
)
|
)
|
||||||
|
|
||||||
// Store buffer for incomplete lines
|
|
||||||
var lineBuffer = ""
|
|
||||||
|
|
||||||
source.setEventHandler { [weak self] in
|
source.setEventHandler { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,3 +30,8 @@ lipo -create -output target/release/tty-fwd-universal \
|
||||||
echo "Universal binary created: target/release/tty-fwd-universal"
|
echo "Universal binary created: target/release/tty-fwd-universal"
|
||||||
echo "Verifying architecture support:"
|
echo "Verifying architecture support:"
|
||||||
lipo -info target/release/tty-fwd-universal
|
lipo -info target/release/tty-fwd-universal
|
||||||
|
|
||||||
|
# Sign the universal binary
|
||||||
|
echo "Signing universal binary..."
|
||||||
|
codesign --force --sign - target/release/tty-fwd-universal
|
||||||
|
echo "Code signing complete"
|
||||||
Loading…
Reference in a new issue