From bb90084d2561317f4dbc7479ce4911bcc5842511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Wed, 21 Jul 2021 09:41:52 +0200 Subject: [PATCH 01/15] Delete all snippets if namespace is nil --- Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift b/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift index fa42bb8..935eb64 100644 --- a/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift +++ b/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift @@ -7,9 +7,9 @@ struct RemoveSnippetsCommand: ParsableCommand { @Option( name: .shortAndLong, - help: "The snippet namespace to delete." + help: "The snippet namespace to delete. All the snippets are deleted if not specified." ) - var namespace: String = "FABERNOVEL" + var namespace: String? public static let configuration = CommandConfiguration( commandName: "remove", @@ -19,6 +19,15 @@ struct RemoveSnippetsCommand: ParsableCommand { // MARK: - ParsableCommand func run() throws { - try XCSnippetCLI().removeSnippets(for: XCSnippetNamespace(namespace)) + let cli = XCSnippetCLI() + if let namespace = namespace { + let xcnamespace = XCSnippetNamespace(namespace) + try cli..removeSnippets(for: xcnamespace) + } else { + let namespaces = try cli.snippetNamespaces() + try namespaces.forEach { namespace in + try cli..removeSnippets(for:namespace) + } + } } } From 802943f0dc22a084fa9f73edc8fe1fa0c6edd879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Wed, 21 Jul 2021 11:55:24 +0200 Subject: [PATCH 02/15] Ensure code snippets folder exists before installing templates --- .../XCResource/XCSnippet/XCSnippetLibrary.swift | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Sources/XCResource/XCSnippet/XCSnippetLibrary.swift b/Sources/XCResource/XCSnippet/XCSnippetLibrary.swift index bd05944..530cda1 100644 --- a/Sources/XCResource/XCSnippet/XCSnippetLibrary.swift +++ b/Sources/XCResource/XCSnippet/XCSnippetLibrary.swift @@ -3,6 +3,7 @@ import Foundation public class XCSnippetLibrary { + private let fileManager: FileManager private let snippetFileManager: XCSnippetFileManager private let downloader: XCSnippetsDownloader private let urlProvider: XCSnippetFolderURLProviding @@ -10,21 +11,25 @@ public class XCSnippetLibrary { // MARK: - Life Cycle public convenience init() { - let snippetFileManager = XCSnippetFileManager(fileManager: .default) + let fileManager = FileManager.default + let snippetFileManager = XCSnippetFileManager(fileManager: fileManager) self.init( + fileManager: fileManager, snippetFileManager: snippetFileManager, downloader: XCSnippetsDownloader( - fileManager: .default, + fileManager: fileManager, snippetFileManager: snippetFileManager, - strategyFactory: XCSnippetDownloadingStrategyFactory(fileManager: .default) + strategyFactory: XCSnippetDownloadingStrategyFactory(fileManager: fileManager) ), urlProvider: NativeNamespaceFolderURLProvider() ) } - internal init(snippetFileManager: XCSnippetFileManager, + internal init(fileManager: FileManager, + snippetFileManager: XCSnippetFileManager, downloader: XCSnippetsDownloader, urlProvider: XCSnippetFolderURLProviding) { + self.fileManager = fileManager self.snippetFileManager = snippetFileManager self.downloader = downloader self.urlProvider = urlProvider @@ -34,8 +39,10 @@ public class XCSnippetLibrary { public func installSnippets(for namespace: XCSnippetNamespace, from source: XCSnippetSource) throws { + let destination = urlProvider.rootSnippetFolderURL() + try? fileManager.createDirectory(at: destination, withIntermediateDirectories: true, attributes: nil) try downloader.downloadSnippets( - at: urlProvider.rootSnippetFolderURL(), + at: destination, from: source, namespace: namespace ) From 7ab5301f6560e4781e73599b537b6bf64e4146ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Wed, 21 Jul 2021 12:36:45 +0200 Subject: [PATCH 03/15] Create XCTemplateLibrary --- .../XCTemplate/XCTemplateLibrary.swift | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 Sources/XCResource/XCTemplate/XCTemplateLibrary.swift diff --git a/Sources/XCResource/XCTemplate/XCTemplateLibrary.swift b/Sources/XCResource/XCTemplate/XCTemplateLibrary.swift new file mode 100644 index 0000000..7be2cb4 --- /dev/null +++ b/Sources/XCResource/XCTemplate/XCTemplateLibrary.swift @@ -0,0 +1,69 @@ + +import Foundation + +public class XCTemplateLibrary { + + private let fileManager: XCTemplateFileManager + private let downloader: XCTemplatesDownloader + private let urlProvider: XCTemplateFolderURLProviding + + // MARK: - Life Cycle + + internal init(fileManager: XCTemplateFileManager, + downloader: XCTemplatesDownloader, + urlProvider: XCTemplateFolderURLProviding) { + self.fileManager = fileManager + self.downloader = downloader + self.urlProvider = urlProvider + } + + public convenience init() { + let fileManager = XCTemplateFileManager( + fileManager: .default + ) + self.init( + fileManager: fileManager, + downloader: XCTemplatesDownloader( + factory: XCTemplateFolderDownloadingStrategyFactory( + fileManager: .default, + templateManager: fileManager + ) + ), + urlProvider: NativeNamespaceFolderURLProvider() + ) + } + + // MARK: - Public + + public func downloadTemplates(for namespace: XCTemplateNamespace, + from source: XCTemplateSource) throws { + try downloader.downloadTemplates( + at: url(for: namespace), + from: source + ) + } + + public func removeTemplates(for namespace: XCTemplateNamespace) throws { + try fileManager.removeTemplateFolder(at: url(for: namespace)) + } + + public func rootTemplateFolder() throws -> XCTemplateFolder { + let folder = try fileManager.templateFolder(at: urlProvider.rootTemplateURL()) + return XCTemplateFolderMapper().map(folder) + } + + public func templateFolder(for namespace: XCTemplateNamespace) throws -> XCTemplateFolder { + let folder = try fileManager.templateFolder(at: url(for: namespace)) + return XCTemplateFolderMapper().map(folder) + } + + public func rootTemplateFolderURL() -> URL { + urlProvider.rootTemplateURL() + } + + // MARK: - Private + + private func url(for namespace: XCTemplateNamespace) -> URL { + urlProvider.url(for: namespace) + } +} From 8569993f65b77264fcfe09e6a89a69299a3b53ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Wed, 21 Jul 2021 12:37:06 +0200 Subject: [PATCH 04/15] Use XCTemplateLibrary in XCTemplateCLI --- .../CLI/XCSnippet/RemoveSnippetsCommand.swift | 4 +- .../XCTemplate/InstallTemplatesCommand.swift | 18 ++--- .../CLI/XCTemplate/ListTemplatesCommand.swift | 8 +- .../XCTemplate/RemoveTemplatesCommand.swift | 2 +- .../XCResource/XCTemplate/XCTemplateCLI.swift | 81 ++++++++----------- 5 files changed, 43 insertions(+), 70 deletions(-) diff --git a/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift b/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift index 935eb64..5487143 100644 --- a/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift +++ b/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift @@ -22,11 +22,11 @@ struct RemoveSnippetsCommand: ParsableCommand { let cli = XCSnippetCLI() if let namespace = namespace { let xcnamespace = XCSnippetNamespace(namespace) - try cli..removeSnippets(for: xcnamespace) + try cli.removeSnippets(for: xcnamespace) } else { let namespaces = try cli.snippetNamespaces() try namespaces.forEach { namespace in - try cli..removeSnippets(for:namespace) + try cli.removeSnippets(for:namespace) } } } diff --git a/Sources/CLI/XCTemplate/InstallTemplatesCommand.swift b/Sources/CLI/XCTemplate/InstallTemplatesCommand.swift index c76208c..226bdb3 100644 --- a/Sources/CLI/XCTemplate/InstallTemplatesCommand.swift +++ b/Sources/CLI/XCTemplate/InstallTemplatesCommand.swift @@ -47,20 +47,12 @@ struct InstallTemplatesCommand: ParsableCommand { // MARK: - ParsableCommand func run() throws { - guard let url = URL(string: url) else { - throw Error.invalidURL - } - let templateNamespace = XCTemplateNamespace(namespace) - let cli = XCTemplateCLI() - try cli.downloadTemplates( - for: templateNamespace, - from: .git( - url: url, - reference: GitReference(pointer), - folderPath: templatesPath - ) + let folder = try XCTemplateCLI().downloadTemplates( + url: url, + pointer: pointer, + namespace: namespace, + templatesPath: templatesPath ) - let folder = try cli.templateFolder(for: templateNamespace) print("\(folder.templateCount()) templates successfully installed 🎉") } } diff --git a/Sources/CLI/XCTemplate/ListTemplatesCommand.swift b/Sources/CLI/XCTemplate/ListTemplatesCommand.swift index ca8e2c4..0247cd6 100644 --- a/Sources/CLI/XCTemplate/ListTemplatesCommand.swift +++ b/Sources/CLI/XCTemplate/ListTemplatesCommand.swift @@ -19,13 +19,7 @@ struct ListTemplatesCommand: ParsableCommand { // MARK: - ParsableCommand func run() throws { - let folder: XCTemplateFolder - let cli = XCTemplateCLI() - if let namespace = namespace { - folder = try cli.templateFolder(for: XCTemplateNamespace(namespace)) - } else { - folder = try cli.rootTemplateFolder() - } + let folder = try XCTemplateCLI().templateFolder(namespace: namespace) if folder.isEmpty() { print("No templates installed") } else { diff --git a/Sources/CLI/XCTemplate/RemoveTemplatesCommand.swift b/Sources/CLI/XCTemplate/RemoveTemplatesCommand.swift index 745dbf0..d8bbdee 100644 --- a/Sources/CLI/XCTemplate/RemoveTemplatesCommand.swift +++ b/Sources/CLI/XCTemplate/RemoveTemplatesCommand.swift @@ -19,6 +19,6 @@ struct RemoveTemplatesCommand: ParsableCommand { // MARK: - ParsableCommand func run() throws { - try XCTemplateCLI().removeTemplates(for: XCTemplateNamespace(namespace)) + try XCTemplateCLI().removeTemplates(namespace: namespace) } } diff --git a/Sources/XCResource/XCTemplate/XCTemplateCLI.swift b/Sources/XCResource/XCTemplate/XCTemplateCLI.swift index cdc730f..4dfc552 100644 --- a/Sources/XCResource/XCTemplate/XCTemplateCLI.swift +++ b/Sources/XCResource/XCTemplate/XCTemplateCLI.swift @@ -3,67 +3,54 @@ import Foundation public class XCTemplateCLI { - private let fileManager: XCTemplateFileManager - private let downloader: XCTemplatesDownloader - private let urlProvider: XCTemplateFolderURLProviding + enum Error: Swift.Error { + case invalidURL + } - // MARK: - Life Cycle + private let templateLibrary: XCTemplateLibrary - internal init(fileManager: XCTemplateFileManager, - downloader: XCTemplatesDownloader, - urlProvider: XCTemplateFolderURLProviding) { - self.fileManager = fileManager - self.downloader = downloader - self.urlProvider = urlProvider - } + // MARK: - Life Cycle - public convenience init() { - let fileManager = XCTemplateFileManager( - fileManager: .default - ) - self.init( - fileManager: fileManager, - downloader: XCTemplatesDownloader( - factory: XCTemplateFolderDownloadingStrategyFactory( - fileManager: .default, - templateManager: fileManager - ) - ), - urlProvider: NativeNamespaceFolderURLProvider() - ) + public init() { + self.templateLibrary = XCTemplateLibrary() } // MARK: - Public - public func downloadTemplates(for namespace: XCTemplateNamespace, - from source: XCTemplateSource) throws { - try downloader.downloadTemplates( - at: url(for: namespace), - from: source + public func downloadTemplates(url: String, + pointer: String, + namespace: String, + templatesPath: String) throws -> XCTemplateFolder { + guard let url = URL(string: url) else { + throw Error.invalidURL + } + let templateNamespace = XCTemplateNamespace(namespace) + try templateLibrary.downloadTemplates( + for: templateNamespace, + from: .git( + url: url, + reference: GitReference(pointer), + folderPath: templatesPath + ) ) + return try templateLibrary.templateFolder(for: templateNamespace) } - public func removeTemplates(for namespace: XCTemplateNamespace) throws { - try fileManager.removeTemplateFolder(at: url(for: namespace)) + public func removeTemplates(namespace: String) throws { + try templateLibrary.removeTemplates(for: XCTemplateNamespace(namespace)) } - public func rootTemplateFolder() throws -> XCTemplateFolder { - let folder = try fileManager.templateFolder(at: urlProvider.rootTemplateURL()) - return XCTemplateFolderMapper().map(folder) - } - - public func templateFolder(for namespace: XCTemplateNamespace) throws -> XCTemplateFolder { - let folder = try fileManager.templateFolder(at: url(for: namespace)) - return XCTemplateFolderMapper().map(folder) + public func templateFolder(namespace: String?) throws -> XCTemplateFolder { + let folder: XCTemplateFolder + if let namespace = namespace { + folder = try templateLibrary.templateFolder(for: XCTemplateNamespace(namespace)) + } else { + folder = try templateLibrary.rootTemplateFolder() + } + return folder } public func openRootTemplateFolder() throws { - try Shell().execute(.open(path: urlProvider.rootTemplateURL().path)) - } - - // MARK: - Private - - private func url(for namespace: XCTemplateNamespace) -> URL { - urlProvider.url(for: namespace) + try Shell().execute(.open(path: templateLibrary.rootTemplateFolderURL().path)) } } From 008954874c32714cff872f0c55ae119a11460a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Thu, 22 Jul 2021 10:35:09 +0200 Subject: [PATCH 05/15] Create URLInputParser --- .../XCTemplate/URLInputParser.swift | 46 +++++++++++++++++++ .../XCResource/XCTemplate/XCTemplateCLI.swift | 6 +-- .../XCResourceTests/URLInputParserTests.swift | 39 ++++++++++++++++ 3 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 Sources/XCResource/XCTemplate/URLInputParser.swift create mode 100644 Tests/XCResourceTests/URLInputParserTests.swift diff --git a/Sources/XCResource/XCTemplate/URLInputParser.swift b/Sources/XCResource/XCTemplate/URLInputParser.swift new file mode 100644 index 0000000..13e1da2 --- /dev/null +++ b/Sources/XCResource/XCTemplate/URLInputParser.swift @@ -0,0 +1,46 @@ +// +// File.swift +// +// +// Created by Gaétan Zanella on 21/07/2021. +// + +import Foundation + +class URLInputParser { + + enum ParsingError: Error { + case invalidURL + } + + func absoluteURL(fromInput url: String) throws -> URL { + let resultURL: URL + // Issue #7: Handling relative URLs + let fileURL = URL(fileURLWithPath: url) + if url.hasPrefix("~") { + resultURL = expandTildeInPath(url) + } else if url.hasPrefix("/") || fileURL.isReachable() { + resultURL = fileURL + } else if let url = URL(string: url) { + resultURL = url + } else { + throw ParsingError.invalidURL + } + return resultURL.absoluteURL + } + + private func expandTildeInPath(_ path: String) -> URL { + URL(fileURLWithPath: NSString(string: path).expandingTildeInPath).standardized + } +} + +private extension URL { + + func isReachable() -> Bool { + do { + return try checkResourceIsReachable() + } catch { + return false + } + } +} diff --git a/Sources/XCResource/XCTemplate/XCTemplateCLI.swift b/Sources/XCResource/XCTemplate/XCTemplateCLI.swift index 4dfc552..684805b 100644 --- a/Sources/XCResource/XCTemplate/XCTemplateCLI.swift +++ b/Sources/XCResource/XCTemplate/XCTemplateCLI.swift @@ -3,7 +3,7 @@ import Foundation public class XCTemplateCLI { - enum Error: Swift.Error { + public enum Error: Swift.Error { case invalidURL } @@ -21,9 +21,7 @@ public class XCTemplateCLI { pointer: String, namespace: String, templatesPath: String) throws -> XCTemplateFolder { - guard let url = URL(string: url) else { - throw Error.invalidURL - } + let url = try URLInputParser().absoluteURL(fromInput: url) let templateNamespace = XCTemplateNamespace(namespace) try templateLibrary.downloadTemplates( for: templateNamespace, diff --git a/Tests/XCResourceTests/URLInputParserTests.swift b/Tests/XCResourceTests/URLInputParserTests.swift new file mode 100644 index 0000000..1c2b48a --- /dev/null +++ b/Tests/XCResourceTests/URLInputParserTests.swift @@ -0,0 +1,39 @@ + +@testable import XCResource +import XCTest + +import Foundation + +final class URLInputParserTests: XCTestCase { + + var parser: URLInputParser! + + override func setUp() { + parser = URLInputParser() + } + + func testRemoteURL() throws { + let remoteURL = "git@github.com:faberNovel/CodeSnippet_iOS.git" + let url = try parser.absoluteURL(fromInput: "git@github.com:faberNovel/CodeSnippet_iOS.git") + XCTAssertEqual(url.path , remoteURL) + } + + func testCurrentDirectoryURL() throws { + let target = URL(fileURLWithPath: "./tst") + FileManager.default.createDirectoryIfNeeded(at: target) + let url = try parser.absoluteURL(fromInput: "./tst") + try? FileManager.default.removeItem(at: target) + XCTAssertEqual(url.path, target.path) + } + + func testHomeRelativeURL() throws { + let url = try parser.absoluteURL(fromInput: "~") + XCTAssertEqual(url, FileManager.default.homeDirectoryForCurrentUser) + } + + func testAbsoluteURL() throws { + let target = "/private/tmp/tst" + let url = try parser.absoluteURL(fromInput: target) + XCTAssertEqual(url.path, target) + } +} From 7c8dcca5bf6d1b17991158a30aa9cbbe7a7173d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Thu, 22 Jul 2021 10:53:17 +0200 Subject: [PATCH 06/15] Use library in XCSnippetCLI --- .../XCSnippet/InstallSnippetsCommand.swift | 15 +++--- .../CLI/XCSnippet/ListSnippetsCommand.swift | 21 ++------- .../CLI/XCSnippet/RemoveSnippetsCommand.swift | 10 +--- .../XCTemplate/InstallTemplatesCommand.swift | 2 +- .../XCResource/XCSnippet/XCSnippetCLI.swift | 46 ++++++++++++++----- 5 files changed, 48 insertions(+), 46 deletions(-) diff --git a/Sources/CLI/XCSnippet/InstallSnippetsCommand.swift b/Sources/CLI/XCSnippet/InstallSnippetsCommand.swift index 06e3a4f..5c3dccc 100644 --- a/Sources/CLI/XCSnippet/InstallSnippetsCommand.swift +++ b/Sources/CLI/XCSnippet/InstallSnippetsCommand.swift @@ -41,14 +41,13 @@ struct InstallSnippetsCommand: ParsableCommand { // MARK: - ParsableCommand func run() throws { - guard let url = URL(string: url) else { throw Error.invalidURL } - try XCSnippetCLI().downloadSnippets( - for: .init(namespace), - from: .git( - url: url, - reference: GitReference(pointer), - folderPath: snippetsPath - ) + let cli = XCSnippetCLI() + let list = try cli.installSnippets( + url: url, + pointer: pointer, + namespace: namespace, + snippetsPath: snippetsPath ) + print("🎉 \(list.snippets.count) snippets successfully installed") } } diff --git a/Sources/CLI/XCSnippet/ListSnippetsCommand.swift b/Sources/CLI/XCSnippet/ListSnippetsCommand.swift index 002ac17..25ba20c 100644 --- a/Sources/CLI/XCSnippet/ListSnippetsCommand.swift +++ b/Sources/CLI/XCSnippet/ListSnippetsCommand.swift @@ -20,24 +20,11 @@ struct ListSnippetsCommand: ParsableCommand { func run() throws { let cli = XCSnippetCLI() - if let namespace = namespace { - let xcnamespace = XCSnippetNamespace(namespace) - try cli.describe(xcnamespace) - } else { - let namespaces = try cli.snippetNamespaces() - try namespaces.forEach { namespace in - try cli.describe(namespace) + try cli.snippetList(namespace: namespace).forEach { namespace, list in + print("#", namespace.name) + list.snippets.forEach { snippet in + print("-", snippet.name) } } } } - -private extension XCSnippetCLI { - - func describe(_ namespace: XCSnippetNamespace) throws { - print("#", namespace.name) - try snippetList(for: namespace).snippets.forEach { snippet in - print("-", snippet.name) - } - } -} diff --git a/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift b/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift index 5487143..a8fb1f7 100644 --- a/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift +++ b/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift @@ -20,14 +20,6 @@ struct RemoveSnippetsCommand: ParsableCommand { func run() throws { let cli = XCSnippetCLI() - if let namespace = namespace { - let xcnamespace = XCSnippetNamespace(namespace) - try cli.removeSnippets(for: xcnamespace) - } else { - let namespaces = try cli.snippetNamespaces() - try namespaces.forEach { namespace in - try cli.removeSnippets(for:namespace) - } - } + try cli.removeSnippets(namespace: namespace) } } diff --git a/Sources/CLI/XCTemplate/InstallTemplatesCommand.swift b/Sources/CLI/XCTemplate/InstallTemplatesCommand.swift index 226bdb3..5abd0c8 100644 --- a/Sources/CLI/XCTemplate/InstallTemplatesCommand.swift +++ b/Sources/CLI/XCTemplate/InstallTemplatesCommand.swift @@ -53,6 +53,6 @@ struct InstallTemplatesCommand: ParsableCommand { namespace: namespace, templatesPath: templatesPath ) - print("\(folder.templateCount()) templates successfully installed 🎉") + print("🎉 \(folder.templateCount()) templates successfully installed") } } diff --git a/Sources/XCResource/XCSnippet/XCSnippetCLI.swift b/Sources/XCResource/XCSnippet/XCSnippetCLI.swift index 842c411..a5d3e6f 100644 --- a/Sources/XCResource/XCSnippet/XCSnippetCLI.swift +++ b/Sources/XCResource/XCSnippet/XCSnippetCLI.swift @@ -11,21 +11,45 @@ public class XCSnippetCLI { // MARK: - Public - public func downloadSnippets(for namespace: XCSnippetNamespace, - from source: XCSnippetSource) throws { - try library.installSnippets(for: namespace, from: source) + public func installSnippets(url: String, + pointer: String, + namespace: String, + snippetsPath: String) throws -> XCSnippetList { + let url = try URLInputParser().absoluteURL(fromInput: url) + let namespace = XCSnippetNamespace(namespace) + try library.installSnippets( + for: namespace, + from: .git( + url: url, + reference: GitReference(pointer), + folderPath: snippetsPath + ) + ) + return try library.snippetList(for: namespace) } - public func removeSnippets(for namespace: XCSnippetNamespace) throws { - try library.removeSnippets(for: namespace) + public func removeSnippets(namespace: String?) throws { + if let namespace = namespace { + let xcnamespace = XCSnippetNamespace(namespace) + try library.removeSnippets(for: xcnamespace) + } else { + let namespaces = try library.snippetNamespaces() + try namespaces.forEach { namespace in + try library.removeSnippets(for:namespace) + } + } } - public func snippetList(for namespace: XCSnippetNamespace) throws -> XCSnippetList { - try library.snippetList(for: namespace) - } - - public func snippetNamespaces() throws -> [XCSnippetNamespace] { - try library.snippetNamespaces() + public func snippetList(namespace: String?) throws -> [XCSnippetNamespace: XCSnippetList] { + if let namespace = namespace { + let xcnamespace = XCSnippetNamespace(namespace) + return [xcnamespace: try library.snippetList(for: xcnamespace)] + } else { + let namespaces = try library.snippetNamespaces() + return Dictionary(uniqueKeysWithValues: try namespaces.map { + ($0, try library.snippetList(for: $0)) + }) + } } public func openSnippetFolder() throws { From a03d3f21669d78515f73e13c77f0e858ead836aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Thu, 22 Jul 2021 11:03:05 +0200 Subject: [PATCH 07/15] Update Changelog --- Changelog.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Changelog.md b/Changelog.md index cf952bd..1d109c4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,16 @@ All notable changes to this project will be documented in this file. +## [0.1.3] + +### Fixed + +- Fixed relative URL parameters #7 + +### Updated + +- Updated CLI messages + ## [0.1.2] ### Updated From 577d5462ac6546d659591eda3595c7c722ff17c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Thu, 22 Jul 2021 11:34:13 +0200 Subject: [PATCH 08/15] Fix gitignore --- .gitignore | 1 - Package.resolved | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 Package.resolved diff --git a/.gitignore b/.gitignore index 39528fd..b04d04f 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,5 @@ xcuserdata *.xcodeproj Utilities/Docker/*.tar.gz .swiftpm -Package.resolved /build *.pyc \ No newline at end of file diff --git a/Package.resolved b/Package.resolved new file mode 100644 index 0000000..6c3b8c8 --- /dev/null +++ b/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "swift-argument-parser", + "repositoryURL": "https://github.com/apple/swift-argument-parser", + "state": { + "branch": null, + "revision": "831ed5e860a70e745bc1337830af4786b2576881", + "version": "0.4.1" + } + } + ] + }, + "version": 1 +} From 0beb98bd60b691f994f360808a8078f1de5c1d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Thu, 22 Jul 2021 11:41:22 +0200 Subject: [PATCH 09/15] Update Changelog --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 1d109c4..1b657fc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. ### Fixed - Fixed relative URL parameters #7 +- Fixed empty code snippets folder #11 ### Updated From cd651bcc3c6e97417db4d1a5c316c0e193a10e46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Thu, 22 Jul 2021 11:46:25 +0200 Subject: [PATCH 10/15] Cleaning --- Sources/XCResource/XCTemplate/XCTemplateCLI.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Sources/XCResource/XCTemplate/XCTemplateCLI.swift b/Sources/XCResource/XCTemplate/XCTemplateCLI.swift index 684805b..726cd20 100644 --- a/Sources/XCResource/XCTemplate/XCTemplateCLI.swift +++ b/Sources/XCResource/XCTemplate/XCTemplateCLI.swift @@ -3,10 +3,6 @@ import Foundation public class XCTemplateCLI { - public enum Error: Swift.Error { - case invalidURL - } - private let templateLibrary: XCTemplateLibrary // MARK: - Life Cycle From 4b43b7e97979fcb8f49bbb0abe7f65b1603e7570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Thu, 22 Jul 2021 11:50:54 +0200 Subject: [PATCH 11/15] Fix typo --- Sources/XCResource/Shared/Shell.swift | 2 +- .../XCResource/XCSnippet/XCSnippetDownloadingStrategy.swift | 2 +- .../XCTemplateFolderDownloadingStrategyFactory.swift | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Sources/XCResource/Shared/Shell.swift b/Sources/XCResource/Shared/Shell.swift index 30c7609..8c5156b 100644 --- a/Sources/XCResource/Shared/Shell.swift +++ b/Sources/XCResource/Shared/Shell.swift @@ -12,7 +12,7 @@ public struct GitReference { enum ShellCommand { case open(path: String) - case gitDownload(url: String, reference: GitReference, destionation: String) + case gitDownload(url: String, reference: GitReference, destination: String) } class Shell { diff --git a/Sources/XCResource/XCSnippet/XCSnippetDownloadingStrategy.swift b/Sources/XCResource/XCSnippet/XCSnippetDownloadingStrategy.swift index 30fad23..e611ff7 100644 --- a/Sources/XCResource/XCSnippet/XCSnippetDownloadingStrategy.swift +++ b/Sources/XCResource/XCSnippet/XCSnippetDownloadingStrategy.swift @@ -41,7 +41,7 @@ struct GitSourceSnippetDownloadingStrategy: XCSnippetDownloadingStrategy { try? fileManager.removeItem(at: tmp) } try Shell().execute( - .gitDownload(url: url.absoluteString, reference: reference, destionation: tmp.path) + .gitDownload(url: url.absoluteString, reference: reference, destination: tmp.path) ) let snippetsDirectoryURL = tmp.appendingPathComponent(folderPath) let snippetURLs = try fileManager.contentsOfDirectory(at: snippetsDirectoryURL) diff --git a/Sources/XCResource/XCTemplate/XCTemplateFolderDownloadingStrategyFactory.swift b/Sources/XCResource/XCTemplate/XCTemplateFolderDownloadingStrategyFactory.swift index 29a423e..b9aa313 100644 --- a/Sources/XCResource/XCTemplate/XCTemplateFolderDownloadingStrategyFactory.swift +++ b/Sources/XCResource/XCTemplate/XCTemplateFolderDownloadingStrategyFactory.swift @@ -41,7 +41,11 @@ struct GitSourceDownloadingStrategy: XCTemplateFolderDownloadingStrategy { try? fileManager.removeItem(at: tmp) } try Shell().execute( - .gitDownload(url: url.absoluteString, reference: reference, destionation: tmp.path) + .gitDownload( + url: url.absoluteString, + reference: reference, + destination: tmp.absoluteString + ) ) let folder = try templateManager.templateFolder(at: tmp.appendingPathComponent(folderPath)) try? fileManager.removeItem(at: destination) From 8ac8c0e0a15bc540fac64abb1718f042cc4db8f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Thu, 22 Jul 2021 12:22:20 +0200 Subject: [PATCH 12/15] Fix git downloading --- .../XCTemplateFolderDownloadingStrategyFactory.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/XCResource/XCTemplate/XCTemplateFolderDownloadingStrategyFactory.swift b/Sources/XCResource/XCTemplate/XCTemplateFolderDownloadingStrategyFactory.swift index b9aa313..2a81347 100644 --- a/Sources/XCResource/XCTemplate/XCTemplateFolderDownloadingStrategyFactory.swift +++ b/Sources/XCResource/XCTemplate/XCTemplateFolderDownloadingStrategyFactory.swift @@ -42,9 +42,9 @@ struct GitSourceDownloadingStrategy: XCTemplateFolderDownloadingStrategy { } try Shell().execute( .gitDownload( - url: url.absoluteString, + url: url.path, reference: reference, - destination: tmp.absoluteString + destination: tmp.path ) ) let folder = try templateManager.templateFolder(at: tmp.appendingPathComponent(folderPath)) From ee37c9a2f64b960289d9776569da5677869eacc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Thu, 22 Jul 2021 16:28:54 +0200 Subject: [PATCH 13/15] Cleaning --- Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift | 3 +-- Sources/XCResource/XCSnippet/XCSnippetLibrary.swift | 3 +-- .../XCResource/XCSnippet/XCSnippetsDownloader.swift | 6 ------ Sources/XCResource/XCTemplate/URLInputParser.swift | 6 ------ .../XCResource/XCTemplate/XCTemplateLibrary.swift | 12 ++++++------ 5 files changed, 8 insertions(+), 22 deletions(-) diff --git a/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift b/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift index a8fb1f7..6d814d1 100644 --- a/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift +++ b/Sources/CLI/XCSnippet/RemoveSnippetsCommand.swift @@ -19,7 +19,6 @@ struct RemoveSnippetsCommand: ParsableCommand { // MARK: - ParsableCommand func run() throws { - let cli = XCSnippetCLI() - try cli.removeSnippets(namespace: namespace) + try XCSnippetCLI().removeSnippets(namespace: namespace) } } diff --git a/Sources/XCResource/XCSnippet/XCSnippetLibrary.swift b/Sources/XCResource/XCSnippet/XCSnippetLibrary.swift index 530cda1..146edc2 100644 --- a/Sources/XCResource/XCSnippet/XCSnippetLibrary.swift +++ b/Sources/XCResource/XCSnippet/XCSnippetLibrary.swift @@ -10,8 +10,7 @@ public class XCSnippetLibrary { // MARK: - Life Cycle - public convenience init() { - let fileManager = FileManager.default + public convenience init(fileManager: FileManager = .default) { let snippetFileManager = XCSnippetFileManager(fileManager: fileManager) self.init( fileManager: fileManager, diff --git a/Sources/XCResource/XCSnippet/XCSnippetsDownloader.swift b/Sources/XCResource/XCSnippet/XCSnippetsDownloader.swift index 87f528e..29b8f2e 100644 --- a/Sources/XCResource/XCSnippet/XCSnippetsDownloader.swift +++ b/Sources/XCResource/XCSnippet/XCSnippetsDownloader.swift @@ -1,9 +1,3 @@ -// -// File.swift -// -// -// Created by Gaétan Zanella on 07/07/2021. -// import Foundation diff --git a/Sources/XCResource/XCTemplate/URLInputParser.swift b/Sources/XCResource/XCTemplate/URLInputParser.swift index 13e1da2..cd52714 100644 --- a/Sources/XCResource/XCTemplate/URLInputParser.swift +++ b/Sources/XCResource/XCTemplate/URLInputParser.swift @@ -1,9 +1,3 @@ -// -// File.swift -// -// -// Created by Gaétan Zanella on 21/07/2021. -// import Foundation diff --git a/Sources/XCResource/XCTemplate/XCTemplateLibrary.swift b/Sources/XCResource/XCTemplate/XCTemplateLibrary.swift index 7be2cb4..729e5ea 100644 --- a/Sources/XCResource/XCTemplate/XCTemplateLibrary.swift +++ b/Sources/XCResource/XCTemplate/XCTemplateLibrary.swift @@ -17,16 +17,16 @@ public class XCTemplateLibrary { self.urlProvider = urlProvider } - public convenience init() { - let fileManager = XCTemplateFileManager( - fileManager: .default + public convenience init(fileManager: FileManager = .default) { + let templateManager = XCTemplateFileManager( + fileManager: fileManager ) self.init( - fileManager: fileManager, + fileManager: templateManager, downloader: XCTemplatesDownloader( factory: XCTemplateFolderDownloadingStrategyFactory( - fileManager: .default, - templateManager: fileManager + fileManager: fileManager, + templateManager: templateManager ) ), urlProvider: NativeNamespaceFolderURLProvider() From e0727ec41153bb22248674703d8376adce7d96f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Thu, 22 Jul 2021 16:29:25 +0200 Subject: [PATCH 14/15] Avoid deleting custom snippets --- Sources/XCResource/XCSnippet/XCSnippetCLI.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/XCResource/XCSnippet/XCSnippetCLI.swift b/Sources/XCResource/XCSnippet/XCSnippetCLI.swift index a5d3e6f..47b253c 100644 --- a/Sources/XCResource/XCSnippet/XCSnippetCLI.swift +++ b/Sources/XCResource/XCSnippet/XCSnippetCLI.swift @@ -33,7 +33,7 @@ public class XCSnippetCLI { let xcnamespace = XCSnippetNamespace(namespace) try library.removeSnippets(for: xcnamespace) } else { - let namespaces = try library.snippetNamespaces() + let namespaces = try library.snippetNamespaces().filter { $0 != .xcodeDefault } try namespaces.forEach { namespace in try library.removeSnippets(for:namespace) } From e1bd438557c229545566cc06503a00124f43991b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=81tan=20Zanella?= Date: Thu, 22 Jul 2021 16:34:47 +0200 Subject: [PATCH 15/15] Update Changelog --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 1b657fc..b4baacc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. ### Updated +- Updated `xcresource snippet remove`: it can not delete custom snippets - Updated CLI messages ## [0.1.2]