From cf6ef6d693b7ce334fc0928e7a5ed057a24d348a Mon Sep 17 00:00:00 2001 From: rtoohil Date: Sun, 30 Nov 2025 10:41:11 -0500 Subject: [PATCH 1/3] Changed the behavior of ComposeUp and ComposeDown to better handle expected behavior of the -f flag --- .../Commands/ComposeDown.swift | 40 +++++++++++++------ .../Commands/ComposeUp.swift | 40 +++++++++++++------ 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/Sources/Container-Compose/Commands/ComposeDown.swift b/Sources/Container-Compose/Commands/ComposeDown.swift index 000b41c..48a5d1a 100644 --- a/Sources/Container-Compose/Commands/ComposeDown.swift +++ b/Sources/Container-Compose/Commands/ComposeDown.swift @@ -44,25 +44,39 @@ public struct ComposeDown: AsyncParsableCommand { private var cwd: String { process.cwd ?? FileManager.default.currentDirectoryPath } @Option(name: [.customShort("f"), .customLong("file")], help: "The path to your Docker Compose file") - var composeFilename: String = "compose.yml" - private var composePath: String { "\(cwd)/\(composeFilename)" } // Path to compose.yml + var composeFilename: String? = nil + private var composePath: String { + let filename = composeFilename ?? "compose.yml" + // Handle absolute paths + if filename.hasPrefix("/") || filename.hasPrefix("~") { + return filename + } else { + return "\(cwd)/\(filename)" + } + } private var fileManager: FileManager { FileManager.default } private var projectName: String? public mutating func run() async throws { - // Check for supported filenames and extensions - let filenames = [ - "compose.yml", - "compose.yaml", - "docker-compose.yml", - "docker-compose.yaml", - ] - for filename in filenames { - if fileManager.fileExists(atPath: "\(cwd)/\(filename)") { - composeFilename = filename - break + // Check for supported filenames and extensions only if user didn't specify -f + if composeFilename == nil { + let filenames = [ + "compose.yml", + "compose.yaml", + "docker-compose.yml", + "docker-compose.yaml", + ] + for filename in filenames { + if fileManager.fileExists(atPath: "\(cwd)/\(filename)") { + composeFilename = filename + break + } + } + // If no file was found, default to compose.yml (will fail later with proper error) + if composeFilename == nil { + composeFilename = "compose.yml" } } diff --git a/Sources/Container-Compose/Commands/ComposeUp.swift b/Sources/Container-Compose/Commands/ComposeUp.swift index 126d637..ff9746c 100644 --- a/Sources/Container-Compose/Commands/ComposeUp.swift +++ b/Sources/Container-Compose/Commands/ComposeUp.swift @@ -46,8 +46,16 @@ public struct ComposeUp: AsyncParsableCommand, @unchecked Sendable { var detatch: Bool = false @Option(name: [.customShort("f"), .customLong("file")], help: "The path to your Docker Compose file") - var composeFilename: String = "compose.yml" - private var composePath: String { "\(cwd)/\(composeFilename)" } // Path to compose.yml + var composeFilename: String? = nil + private var composePath: String { + let filename = composeFilename ?? "compose.yml" + // Handle absolute paths + if filename.hasPrefix("/") || filename.hasPrefix("~") { + return filename + } else { + return "\(cwd)/\(filename)" + } + } @Flag(name: [.customShort("b"), .customLong("build")]) var rebuild: Bool = false @@ -75,17 +83,23 @@ public struct ComposeUp: AsyncParsableCommand, @unchecked Sendable { ] public mutating func run() async throws { - // Check for supported filenames and extensions - let filenames = [ - "compose.yml", - "compose.yaml", - "docker-compose.yml", - "docker-compose.yaml", - ] - for filename in filenames { - if fileManager.fileExists(atPath: "\(cwd)/\(filename)") { - composeFilename = filename - break + // Check for supported filenames and extensions only if user didn't specify -f + if composeFilename == nil { + let filenames = [ + "compose.yml", + "compose.yaml", + "docker-compose.yml", + "docker-compose.yaml", + ] + for filename in filenames { + if fileManager.fileExists(atPath: "\(cwd)/\(filename)") { + composeFilename = filename + break + } + } + // If no file was found, default to compose.yml (will fail later with proper error) + if composeFilename == nil { + composeFilename = "compose.yml" } } From d5aaad3ac002e65fd5255aec5a0f6a0ad61bd020 Mon Sep 17 00:00:00 2001 From: rtoohil Date: Mon, 1 Dec 2025 13:55:20 -0500 Subject: [PATCH 2/3] Fixed tilde path expansion --- Sources/Container-Compose/Commands/ComposeDown.swift | 11 +++++------ Sources/Container-Compose/Commands/ComposeUp.swift | 11 +++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Sources/Container-Compose/Commands/ComposeDown.swift b/Sources/Container-Compose/Commands/ComposeDown.swift index 48a5d1a..05fd661 100644 --- a/Sources/Container-Compose/Commands/ComposeDown.swift +++ b/Sources/Container-Compose/Commands/ComposeDown.swift @@ -47,9 +47,11 @@ public struct ComposeDown: AsyncParsableCommand { var composeFilename: String? = nil private var composePath: String { let filename = composeFilename ?? "compose.yml" - // Handle absolute paths - if filename.hasPrefix("/") || filename.hasPrefix("~") { + // Handle absolute paths and tilde expansion + if filename.hasPrefix("/") { return filename + } else if filename.hasPrefix("~") { + return NSString(string: filename).expandingTildeInPath } else { return "\(cwd)/\(filename)" } @@ -74,10 +76,7 @@ public struct ComposeDown: AsyncParsableCommand { break } } - // If no file was found, default to compose.yml (will fail later with proper error) - if composeFilename == nil { - composeFilename = "compose.yml" - } + // No need to set composeFilename = "compose.yml" here; composePath already handles the nil case } // Read docker-compose.yml content diff --git a/Sources/Container-Compose/Commands/ComposeUp.swift b/Sources/Container-Compose/Commands/ComposeUp.swift index ff9746c..9a54b22 100644 --- a/Sources/Container-Compose/Commands/ComposeUp.swift +++ b/Sources/Container-Compose/Commands/ComposeUp.swift @@ -49,9 +49,11 @@ public struct ComposeUp: AsyncParsableCommand, @unchecked Sendable { var composeFilename: String? = nil private var composePath: String { let filename = composeFilename ?? "compose.yml" - // Handle absolute paths - if filename.hasPrefix("/") || filename.hasPrefix("~") { + // Handle absolute paths and tilde expansion + if filename.hasPrefix("/") { return filename + } else if filename.hasPrefix("~") { + return NSString(string: filename).expandingTildeInPath } else { return "\(cwd)/\(filename)" } @@ -97,10 +99,7 @@ public struct ComposeUp: AsyncParsableCommand, @unchecked Sendable { break } } - // If no file was found, default to compose.yml (will fail later with proper error) - if composeFilename == nil { - composeFilename = "compose.yml" - } + // No need to set composeFilename = "compose.yml" here; composePath already handles the nil case } // Read compose.yml content From 2c44929924170542ca76cc191c6a6f8b2bda66a5 Mon Sep 17 00:00:00 2001 From: rtoohil Date: Tue, 2 Dec 2025 12:19:56 -0500 Subject: [PATCH 3/3] Removed vestigial comments --- .../Commands/ComposeDown.swift | 1 - .../Commands/ComposeUp.swift | 23 +++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Sources/Container-Compose/Commands/ComposeDown.swift b/Sources/Container-Compose/Commands/ComposeDown.swift index 05fd661..fa2aa52 100644 --- a/Sources/Container-Compose/Commands/ComposeDown.swift +++ b/Sources/Container-Compose/Commands/ComposeDown.swift @@ -76,7 +76,6 @@ public struct ComposeDown: AsyncParsableCommand { break } } - // No need to set composeFilename = "compose.yml" here; composePath already handles the nil case } // Read docker-compose.yml content diff --git a/Sources/Container-Compose/Commands/ComposeUp.swift b/Sources/Container-Compose/Commands/ComposeUp.swift index 9a54b22..08b699f 100644 --- a/Sources/Container-Compose/Commands/ComposeUp.swift +++ b/Sources/Container-Compose/Commands/ComposeUp.swift @@ -99,7 +99,6 @@ public struct ComposeUp: AsyncParsableCommand, @unchecked Sendable { break } } - // No need to set composeFilename = "compose.yml" here; composePath already handles the nil case } // Read compose.yml content @@ -331,7 +330,7 @@ public struct ComposeUp: AsyncParsableCommand, @unchecked Sendable { return } let commands = [actualNetworkName] - + var networkCreate = try Application.NetworkCreate.parse(commands + global.passThroughCommands()) try await networkCreate.run() @@ -344,7 +343,7 @@ public struct ComposeUp: AsyncParsableCommand, @unchecked Sendable { guard let projectName else { throw ComposeError.invalidProjectName } var imageToRun: String - + var runCommandArgs: [String] = [] // Handle 'build' configuration @@ -359,7 +358,7 @@ public struct ComposeUp: AsyncParsableCommand, @unchecked Sendable { // Should not happen due to Service init validation, but as a fallback throw ComposeError.imageNotFound(serviceName) } - + // Set Run Platform if let platform = service.platform { runCommandArgs.append(contentsOf: ["--platform", "\(platform)"]) @@ -582,11 +581,11 @@ public struct ComposeUp: AsyncParsableCommand, @unchecked Sendable { } print("Pulling Image \(imageName)...") - + var commands = [ imageName ] - + if let platform { commands.append(contentsOf: ["--platform", platform]) } @@ -613,30 +612,30 @@ public struct ComposeUp: AsyncParsableCommand, @unchecked Sendable { // Build command arguments var commands = ["\(self.cwd)/\(buildConfig.context)"] - + // Add build arguments for (key, value) in buildConfig.args ?? [:] { commands.append(contentsOf: ["--build-arg", "\(key)=\(resolveVariable(value, with: environmentVariables))"]) } - + // Add Dockerfile path commands.append(contentsOf: ["--file", "\(self.cwd)/\(buildConfig.dockerfile ?? "Dockerfile")"]) - + // Add caching options if noCache { commands.append("--no-cache") } - + // Add OS/Arch let split = service.platform?.split(separator: "/") let os = String(split?.first ?? "linux") let arch = String(((split ?? []).count >= 1 ? split?.last : nil) ?? "arm64") commands.append(contentsOf: ["--os", os]) commands.append(contentsOf: ["--arch", arch]) - + // Add image name commands.append(contentsOf: ["--tag", imageToRun]) - + // Add CPU & Memory let cpuCount = Int64(service.deploy?.resources?.limits?.cpus ?? "2") ?? 2 let memoryLimit = service.deploy?.resources?.limits?.memory ?? "2048MB"