Skip to content

Commit

Permalink
fix: Duplicating rules incorrectly duplicates identifiers (#501)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbmorley authored Nov 28, 2022
1 parent a6cd2cf commit 6a7c091
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 10 deletions.
10 changes: 10 additions & 0 deletions Fileaway.xcworkspace/xcshareddata/xcschemes/Fileaway iOS.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@
ReferencedContainer = "container:ios/Fileaway-iOS.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FileawayCoreTests"
BuildableName = "FileawayCoreTests"
BlueprintName = "FileawayCoreTests"
ReferencedContainer = "container:core">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@
ReferencedContainer = "container:macos/Fileaway-macOS.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FileawayCoreTests"
BuildableName = "FileawayCoreTests"
BlueprintName = "FileawayCoreTests"
ReferencedContainer = "container:core">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
Expand Down
2 changes: 1 addition & 1 deletion core/Sources/FileawayCore/Model/DirectoryModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public class DirectoryModel: ObservableObject, Identifiable, Hashable {
self.settings = settings
self.type = type
self.url = url
self.ruleSet = RulesModel(url: url)
self.ruleSet = RulesModel(archiveURL: url)
self.directoryMonitor = DirectoryMonitor(locations: [url])
}

Expand Down
8 changes: 8 additions & 0 deletions core/Sources/FileawayCore/Model/RuleModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ public class RuleModel: ObservableObject, Identifiable, CustomStringConvertible,
destination: ruleModel.destination.map { ComponentModel($0, variable: nil) })
}

public convenience init(id: UUID, ruleModel: RuleModel) {
self.init(id: id,
rootUrl: ruleModel.rootUrl,
name: String(ruleModel.name),
variables: ruleModel.variables,
destination: ruleModel.destination.map { ComponentModel($0, variable: nil) })
}

public convenience init(rootUrl: URL, rule: Rule) {
self.init(id: rule.id,
rootUrl: rootUrl,
Expand Down
16 changes: 8 additions & 8 deletions core/Sources/FileawayCore/Model/RulesModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ public class RulesModel: ObservableObject {

var rulesSubscription: Cancellable?

public init(url: URL) {
self.rootUrl = url
self.url = url.rulesUrl
public init(archiveURL: URL) {
self.rootUrl = archiveURL
self.url = archiveURL.rulesUrl
if FileManager.default.fileExists(atPath: self.url.path) {
do {
self.ruleModels = try RuleList(url: self.url).models(for: self.rootUrl)
Expand Down Expand Up @@ -120,12 +120,12 @@ public class RulesModel: ObservableObject {
return self.ruleModels.map { $0.validate() }.reduce(false, { $0 || $1 })
}

private func duplicate(_ rule: RuleModel, preferredName: String) throws -> RuleModel {
private func duplicate(_ ruleModel: RuleModel, preferredName: String) throws -> RuleModel {
let name = uniqueRuleName(preferredName: preferredName)
let newRule = RuleModel(rule)
newRule.name = name
try add(newRule)
return newRule
let newRuleModel = RuleModel(id: UUID(), ruleModel: ruleModel)
newRuleModel.name = name
try add(newRuleModel)
return newRuleModel
}

public func duplicate(ids: Set<RuleModel.ID>) throws -> [RuleModel] {
Expand Down
90 changes: 90 additions & 0 deletions core/Tests/FileawayCoreTests/RulesModelTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright (c) 2018-2022 InSeven Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import XCTest

@testable import FileawayCore

// TODO: Comprehensive RulesModel tests #500
// https://github.com/inseven/fileaway/issues/500
class RulesModelTests: XCTestCase {

func temporaryDirectoryURL() throws -> URL {

let fileManager = FileManager.default
let directoryURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString)
try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true)

var isDirectory: ObjCBool = false
XCTAssertTrue(fileManager.fileExists(atPath: directoryURL.path, isDirectory: &isDirectory))
XCTAssert(isDirectory.boolValue)

addTeardownBlock {
do {
let fileManager = FileManager.default
try fileManager.removeItem(at: directoryURL)
XCTAssertFalse(fileManager.fileExists(atPath: directoryURL.path))
} catch {
XCTFail("Failed to delete temporary directory with error \(error).")
}
}

return directoryURL
}

func emptyModel() throws -> RulesModel {
let archiveURL = try temporaryDirectoryURL()
let rules = RulesModel(archiveURL: archiveURL)
return rules
}

func testNewRule() throws {
let archiveURL = try temporaryDirectoryURL()

let rules = RulesModel(archiveURL: archiveURL)
XCTAssert(rules.ruleModels.isEmpty)

let rule = try rules.new()
XCTAssertEqual(rule.rootUrl, archiveURL)
XCTAssertEqual(rule.name, "Rule")
XCTAssertEqual(rules.ruleModels.count, 1)
}

func testDuplicate() throws {
let rules = try emptyModel()

let rule1 = try rules.new()
let duplicates = try rules.duplicate(ids: [rule1.id])
XCTAssertEqual(duplicates.count, 1)
XCTAssertEqual(rules.ruleModels.count, 2)

guard let rule2 = duplicates.first else {
XCTFail("Failed to get first duplicate rule.")
return
}

XCTAssertNotEqual(rule2.id, rule1.id)
XCTAssertEqual(rule2.rootUrl, rule1.rootUrl)
XCTAssertEqual(rule2.name, "Copy of Rule")
XCTAssertEqual(rule2.variables, rule1.variables)
XCTAssertEqual(rule2.destination, rule1.destination)
}

}
2 changes: 1 addition & 1 deletion ios/Fileaway/Views/Viewer/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ struct ContentView: View {
case .move(let files):
WizardView(file: files.first!)
case .editRules(let url):
RulesView(rulesModel: RulesModel(url: url))
RulesView(rulesModel: RulesModel(archiveURL: url))
}
}
.runs(sceneModel)
Expand Down

0 comments on commit 6a7c091

Please sign in to comment.