@@ -15,8 +15,37 @@ final class PackageManagerFactory {
1515 self . installationDirectory = installationDirectory
1616 }
1717
18+ /// Install a package from a registry entry
19+ func installFromRegistryEntry( _ entry: RegistryItem ) async throws {
20+ guard let method = Self . parseRegistryEntry ( entry) ,
21+ let manager = createPackageManager ( for: method) else {
22+ throw PackageManagerError . invalidConfiguration
23+ }
24+ try await manager. install ( method: method)
25+ }
26+
27+ /// Parse a registry entry and create the appropriate installation method
28+ private static func parseRegistryEntry( _ entry: RegistryItem ) -> InstallationMethod ? {
29+ let sourceId = entry. source. id
30+ if sourceId. hasPrefix ( " pkg:cargo/ " ) {
31+ return PackageSourceParser . parseCargoPackage ( entry)
32+ } else if sourceId. hasPrefix ( " pkg:npm/ " ) {
33+ return PackageSourceParser . parseNpmPackage ( entry)
34+ } else if sourceId. hasPrefix ( " pkg:pypi/ " ) {
35+ return PackageSourceParser . parsePythonPackage ( entry)
36+ } else if sourceId. hasPrefix ( " pkg:gem/ " ) {
37+ return PackageSourceParser . parseRubyGem ( entry)
38+ } else if sourceId. hasPrefix ( " pkg:golang/ " ) {
39+ return PackageSourceParser . parseGolangPackage ( entry)
40+ } else if sourceId. hasPrefix ( " pkg:github/ " ) {
41+ return PackageSourceParser . parseGithubPackage ( entry)
42+ } else {
43+ return . unknown
44+ }
45+ }
46+
1847 /// Create the appropriate package manager for the given installation method
19- func createPackageManager( for method: InstallationMethod ) -> PackageManagerProtocol ? {
48+ private func createPackageManager( for method: InstallationMethod ) -> PackageManagerProtocol ? {
2049 switch method. packageManagerType {
2150 case . npm:
2251 return NPMPackageManager ( installationDirectory: installationDirectory)
@@ -26,154 +55,13 @@ final class PackageManagerFactory {
2655 return PipPackageManager ( installationDirectory: installationDirectory)
2756 case . golang:
2857 return GolangPackageManager ( installationDirectory: installationDirectory)
29- case . nuget, . opam, . customBuild, . gem:
58+ case . github, . sourceBuild:
59+ return GithubPackageManager ( installationDirectory: installationDirectory)
60+ case . nuget, . opam, . gem, . composer:
3061 // TODO: IMPLEMENT OTHER PACKAGE MANAGERS
3162 return nil
32- case . github:
33- return createPackageManagerFromGithub ( for: method)
3463 case . none:
3564 return nil
3665 }
3766 }
38-
39- /// Parse a registry entry and create the appropriate installation method
40- static func parseRegistryEntry( _ entry: RegistryItem ) -> InstallationMethod ? {
41- // let buildInstructions = source["build"] as? [[String: Any]]
42- // entry.source.build
43- //
44- // // Detect the build tool from the registry entry
45- // var buildTool: String?
46- // if let bin = entry.bin {
47- // let binValues = Array(bin.values)
48- // if !binValues.isEmpty {
49- // let value = binValues[0]
50- // if value.hasPrefix("cargo:") {
51- // buildTool = "cargo"
52- // } else if value.hasPrefix("npm:") {
53- // buildTool = "npm"
54- // } else if value.hasPrefix("pypi:") {
55- // buildTool = "pip"
56- // } else if value.hasPrefix("gem:") {
57- // buildTool = "gem"
58- // } else if value.hasPrefix("golang:") {
59- // buildTool = "golang"
60- // }
61- // }
62- // }
63- //
64- // var method = PackageSourceParser.parse(entry.source.id, buildInstructions: buildInstructions)
65- //
66- // if let buildTool = buildTool {
67- // switch method {
68- // case .standardPackage(var source):
69- // var options = source.options
70- // options["buildTool"] = buildTool
71- // source = PackageSource(
72- // sourceId: source.sourceId,
73- // type: source.type,
74- // name: source.name,
75- // version: source.version,
76- // subpath: source.subpath,
77- // repositoryUrl: source.repositoryUrl,
78- // gitReference: source.gitReference,
79- // options: options
80- // )
81- // method = .standardPackage(source: source)
82- // case .sourceBuild(var source, let instructions):
83- // var options = source.options
84- // options["buildTool"] = buildTool
85- // source = PackageSource(
86- // sourceId: source.sourceId,
87- // type: source.type,
88- // name: source.name,
89- // version: source.version,
90- // subpath: source.subpath,
91- // repositoryUrl: source.repositoryUrl,
92- // gitReference: source.gitReference,
93- // options: options
94- // )
95- // method = .sourceBuild(source: source, buildInstructions: instructions)
96- // case .binaryDownload(var source, let url):
97- // var options = source.options
98- // options["buildTool"] = buildTool
99- // source = PackageSource(
100- // sourceId: source.sourceId,
101- // type: source.type,
102- // name: source.name,
103- // version: source.version,
104- // subpath: source.subpath,
105- // repositoryUrl: source.repositoryUrl,
106- // gitReference: source.gitReference,
107- // options: options
108- // )
109- // method = .binaryDownload(source: source, url: url)
110- // case .unknown:
111- // break
112- // }
113- // }
114- // return method
115- return nil
116- }
117-
118- /// Install a package from a registry entry
119- func installFromRegistryEntry( _ entry: [ String : Any ] ) async throws {
120- // guard let method = PackageManagerFactory.parseRegistryEntry(entry),
121- // let manager = createPackageManager(for: method) else {
122- // throw PackageManagerError.invalidConfiguration
123- // }
124- // try await manager.install(method: method)
125- }
126-
127- /// Install a package from a source ID string
128- func installFromSourceID( _ sourceID: String ) async throws {
129- let method = PackageSourceParser . parse ( sourceID)
130- guard let manager = createPackageManager ( for: method) else {
131- throw PackageManagerError . packageManagerNotInstalled
132- }
133- try await manager. install ( method: method)
134- }
135-
136- private func createPackageManagerFromGithub( for method: InstallationMethod ) -> PackageManagerProtocol ? {
137- if case let . sourceBuild( source, instructions) = method {
138- if let buildTool = source. options [ " buildTool " ] {
139- switch buildTool {
140- case " cargo " : return CargoPackageManager ( installationDirectory: installationDirectory)
141- case " npm " : return NPMPackageManager ( installationDirectory: installationDirectory)
142- case " pip " : return PipPackageManager ( installationDirectory: installationDirectory)
143- case " golang " : return GolangPackageManager ( installationDirectory: installationDirectory)
144- default : break
145- }
146- }
147-
148- // If no buildTool option, try to determine from build instructions
149- for instruction in instructions {
150- for command in instruction. commands {
151- if command. contains ( " cargo " ) {
152- return CargoPackageManager ( installationDirectory: installationDirectory)
153- } else if command. contains ( " npm " ) {
154- return NPMPackageManager ( installationDirectory: installationDirectory)
155- } else if command. contains ( " pip " ) || command. contains ( " python " ) {
156- return PipPackageManager ( installationDirectory: installationDirectory)
157- } else if command. contains ( " go " ) {
158- return GolangPackageManager ( installationDirectory: installationDirectory)
159- }
160- }
161- }
162-
163- // Check the binary path for clues if needed
164- let binPath = instructions. first? . binaryPath ?? " "
165- if binPath. contains ( " target/release " ) || binPath. hasSuffix ( " .rs " ) {
166- return CargoPackageManager ( installationDirectory: installationDirectory)
167- } else if binPath. contains ( " node_modules " ) {
168- return NPMPackageManager ( installationDirectory: installationDirectory)
169- } else if binPath. contains ( " .py " ) {
170- return PipPackageManager ( installationDirectory: installationDirectory)
171- } else if binPath. hasSuffix ( " .go " ) || binPath. contains ( " /go/bin " ) {
172- return GolangPackageManager ( installationDirectory: installationDirectory)
173- }
174- }
175-
176- // Default to cargo
177- return CargoPackageManager ( installationDirectory: installationDirectory)
178- }
17967}
0 commit comments