Skip to content

Commit aba929f

Browse files
committed
Model the Linux getent command
1 parent 8dc6b7e commit aba929f

File tree

3 files changed

+75
-9
lines changed

3 files changed

+75
-9
lines changed

Sources/LinuxPlatform/Linux.swift

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Foundation
22
import SwiftlyCore
33
import SystemPackage
44

5+
typealias sys = SwiftlyCore.SystemCommand
56
typealias fs = SwiftlyCore.FileSystem
67

78
/// `Platform` implementation for Linux systems.
@@ -605,15 +606,8 @@ public struct Linux: Platform {
605606

606607
public func getShell() async throws -> String {
607608
let userName = ProcessInfo.processInfo.userName
608-
let prefix = "\(userName):"
609-
if let passwds = try await runProgramOutput("getent", "passwd") {
610-
for line in passwds.components(separatedBy: "\n") {
611-
if line.hasPrefix(prefix) {
612-
if case let comps = line.components(separatedBy: ":"), comps.count > 1 {
613-
return comps[comps.count - 1]
614-
}
615-
}
616-
}
609+
if let entry = try await sys.getent(database: "passwd", keys: userName).entries(self).first {
610+
if let shell = entry.last { return shell }
617611
}
618612

619613
// Fall back on bash on Linux and other Unixes

Sources/SwiftlyCore/Commands.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,61 @@ extension SystemCommand {
221221
}
222222

223223
extension SystemCommand.PkgbuildCommand: Runnable {}
224+
225+
// get entries from Name Service Switch libraries
226+
// See getent(1) for more details
227+
extension SystemCommand {
228+
public static func getent(executable: Executable = GetentCommand.defaultExecutable, database: String, keys: String...) -> GetentCommand {
229+
Self.getent(executable: executable, database: database, keys: keys)
230+
}
231+
232+
public static func getent(executable: Executable = GetentCommand.defaultExecutable, database: String, keys: [String]) -> GetentCommand {
233+
GetentCommand(executable: executable, database: database, keys: keys)
234+
}
235+
236+
public struct GetentCommand {
237+
public static var defaultExecutable: Executable { .name("getent") }
238+
239+
var executable: Executable
240+
241+
var database: String
242+
243+
var keys: [String]
244+
245+
internal init(
246+
executable: Executable,
247+
database: String,
248+
keys: [String]
249+
) {
250+
self.executable = executable
251+
self.database = database
252+
self.keys = keys
253+
}
254+
255+
public func config() -> Configuration {
256+
var args: [String] = []
257+
258+
args += [self.database]
259+
args += self.keys
260+
261+
return Configuration(
262+
executable: self.executable,
263+
arguments: Arguments(args),
264+
environment: .inherit
265+
)
266+
}
267+
}
268+
}
269+
270+
extension SystemCommand.GetentCommand: Output {
271+
public func entries(_ platform: Platform) async throws -> [[String]] {
272+
let output = try await output(platform)
273+
guard let output else { return [] }
274+
275+
var entries: [[String]] = []
276+
for line in output.components(separatedBy: "\n") {
277+
entries.append(line.components(separatedBy: ":"))
278+
}
279+
return entries
280+
}
281+
}

Tests/SwiftlyTests/CommandLineTests.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,19 @@ public struct CommandLineTests {
4646

4747
config = sys.pkgbuild(.version("1234"), root: "somepath", packageOutputPath: "output").config()
4848
#expect(String(describing: config) == "pkgbuild --version 1234 --root somepath output")
49+
50+
config = sys.pkgbuild(.installLocation("/usr/local"), .version("1.0.0"), .identifier("org.foo.bar"), .sign("mycert"), root: "someroot", packageOutputPath: "my.pkg").config()
51+
#expect(String(describing: config) == "pkgbuild --install-location /usr/local --version 1.0.0 --identifier org.foo.bar --sign mycert --root someroot my.pkg")
52+
53+
config = sys.pkgbuild(.installLocation("/usr/local"), .version("1.0.0"), .identifier("org.foo.bar"), root: "someroot", packageOutputPath: "my.pkg").config()
54+
#expect(String(describing: config) == "pkgbuild --install-location /usr/local --version 1.0.0 --identifier org.foo.bar --root someroot my.pkg")
55+
}
56+
57+
@Test func testGetent() {
58+
var config = sys.getent(database: "passwd", keys: "swiftly").config()
59+
#expect(String(describing: config) == "getent passwd swiftly")
60+
61+
config = sys.getent(database: "foo", keys: "abc", "def").config()
62+
#expect(String(describing: config) == "getent foo abc def")
4963
}
5064
}

0 commit comments

Comments
 (0)