diff --git a/CHANGELOG.md b/CHANGELOG.md
index 64713e8..b158d0f 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Refactor application.
+## [0.7.0] - 2021-08-22
+
+### Added
+
+- Added new classes `Path` for working with path's and creating relative path from specified directory.
+- Add unit-tests cases for the `Path` class.
+
+### Changed
+
+- Change soft link creation using relative instead absolute path.
+
## [0.6.0] - 2021-08-02
### Changed
diff --git a/README.md b/README.md
index a224cac..e09474a 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
The Quick Symlink is a `Finder extension` which provides a `contextual menu item` for the symbolic links creation on macOS.
-[![status](https://img.shields.io/badge/status-active-active?style=flat-square)](BADGES_GUIDE.md#status) [![version](https://img.shields.io/badge/version-0.6.0-informational?style=flat-square)](BADGES_GUIDE.md#version) [![oss lifecycle](https://img.shields.io/badge/oss_lifecycle-active-important?style=flat-square)](BADGES_GUIDE.md#oss-lifecycle) [![maintenance](https://img.shields.io/badge/maintenance-yes-informational?style=flat-square)](BADGES_GUIDE.md#maintenance) [![last release](https://img.shields.io/badge/last_release-August_07,_2021-informational?style=flat-square)](BADGES_GUIDE.md#release-date) [![last commit](https://img.shields.io/badge/last_commit-August_20,_2021-informational?style=flat-square)](BADGES_GUIDE.md#commit-date)
+[![status](https://img.shields.io/badge/status-active-active?style=flat-square)](BADGES_GUIDE.md#status) [![version](https://img.shields.io/badge/version-0.6.0-informational?style=flat-square)](BADGES_GUIDE.md#version) [![oss lifecycle](https://img.shields.io/badge/oss_lifecycle-active-important?style=flat-square)](BADGES_GUIDE.md#oss-lifecycle) [![maintenance](https://img.shields.io/badge/maintenance-yes-informational?style=flat-square)](BADGES_GUIDE.md#maintenance) [![last release](https://img.shields.io/badge/last_release-August_22,_2021-informational?style=flat-square)](BADGES_GUIDE.md#release-date) [![last commit](https://img.shields.io/badge/last_commit-August_22,_2021-informational?style=flat-square)](BADGES_GUIDE.md#commit-date)
[![license](https://img.shields.io/badge/license-MIT-informational?style=flat-square)](LICENSE) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg?style=flat-square)](CODE_OF_CONDUCT.md)
diff --git a/TODO.md b/TODO.md
index 3aee519..a3ffbc5 100755
--- a/TODO.md
+++ b/TODO.md
@@ -5,8 +5,9 @@
- [x] Develop the `Finder extension` which allows to create a symlinks for selected folders and files via contextual menu.
- [x] Add the new menu item for replacing selected folders and files with symlinks.
- [x] Add the new menu item for creating symlink in a parent directory (parent for target objects).
-- [ ] Optional feature - use relative path instead absolute path in symlink target URL (if target and link located in one volume)
-- [ ] Develop additional `Finder extension` which allows to create a `hard links` for selected folders and files via contextual menu.
+- [x] Optional feature - use relative path instead absolute path in symlink target URL (if target and link located in one volume)
+- [ ] Refactor code in `commons/*` part and add unit-tests
+- [ ] Develop additional `Finder extension` which allows to create a `hard links` for selected folders and files via contextual menu
- [ ] Develop the action panel for created symbolic links and hard lonks (in the app window):
- [ ] a) (if broken) process to browse finder for 'Find/fix missing target'
- [ ] b) Modify existing paths and symbolic link features
diff --git a/commons/FileSystem/Path.swift b/commons/FileSystem/Path.swift
new file mode 100644
index 0000000..cc1f269
--- /dev/null
+++ b/commons/FileSystem/Path.swift
@@ -0,0 +1,20 @@
+//
+// Path.swift
+// quick-symlink
+//
+// Created by Alexander A. Kropotin on 22/08/2021.
+// Copyright © 2021 Alexander A. Kropotin. All rights reserved.
+//
+
+import Foundation
+
+public protocol Path {
+
+ func relativize(to other: Path!) -> Path!;
+
+ func getPathFragments() -> [String]!;
+
+ func toUrl() -> URL?;
+
+ func toUriString() -> String?;
+}
diff --git a/commons/FileSystem/ResourcePath.swift b/commons/FileSystem/ResourcePath.swift
new file mode 100644
index 0000000..fa4fb6c
--- /dev/null
+++ b/commons/FileSystem/ResourcePath.swift
@@ -0,0 +1,82 @@
+//
+// ResourcePath.swift
+// quick-symlink
+//
+// Created by Alexander A. Kropotin on 22/08/2021.
+// Copyright © 2021 Alexander A. Kropotin. All rights reserved.
+//
+
+import Foundation
+
+public class ResourcePath: Path {
+
+ public static func of(url: URL!) -> Path! {
+ return ResourcePath.of(fragments: url.pathComponents)
+ }
+
+ public static func of(fragments: [String]!) -> Path! {
+ return ResourcePath.init(of: fragments);
+ }
+
+ private var uriFragments: [String]!;
+
+ public init(of fragments: [String]) {
+ self.uriFragments = fragments;
+ }
+
+ public func getPathFragments() -> [String]! {
+ return self.uriFragments;
+ }
+
+ public func relativize(to other: Path!) -> Path! {
+ var pathFragments = self.uriFragments;
+ var targetPathFragments = other.getPathFragments();
+
+ var destinationPath = URL.init(string: "./")!;
+ for targetPathFragment in targetPathFragments! {
+ if (!(pathFragments?.contains(targetPathFragment))!) {
+ break;
+ }
+
+ pathFragments?.remove(at: 0);
+ targetPathFragments?.remove(at: 0);
+ }
+
+ for _ in targetPathFragments! {
+ destinationPath.appendPathComponent("../");
+ }
+
+ for pathFragment in pathFragments! {
+ destinationPath.appendPathComponent(pathFragment);
+ }
+
+ //pathFragments!.append(contentsOf: targetPathFragments!);
+
+ return ResourcePath.of(url: destinationPath);
+ }
+
+ public func toUrl() -> URL? {
+ if self.uriFragments.count == 0 {
+ return nil;
+ }
+
+ var uri = URL.init(string: self.uriFragments.first!)!;
+ for fragment in self.uriFragments.dropFirst().dropLast() {
+ uri.appendPathComponent(fragment);
+ uri.appendPathComponent("/");
+ }
+ uri.appendPathComponent(self.uriFragments.last!);
+
+ return uri;
+ }
+
+ public func toUriString() -> String? {
+ if self.uriFragments.count == 0 {
+ return nil;
+ }
+
+ return self.toUrl()!.absoluteString;
+ }
+
+
+}
diff --git a/commons/CopyPathAction.swift b/commons/QuickSymlinkActions/CopyPathAction.swift
similarity index 100%
rename from commons/CopyPathAction.swift
rename to commons/QuickSymlinkActions/CopyPathAction.swift
diff --git a/commons/CreateLinkAction.swift b/commons/QuickSymlinkActions/CreateLinkAction.swift
similarity index 88%
rename from commons/CreateLinkAction.swift
rename to commons/QuickSymlinkActions/CreateLinkAction.swift
index 7f6dc76..ac97835 100644
--- a/commons/CreateLinkAction.swift
+++ b/commons/QuickSymlinkActions/CreateLinkAction.swift
@@ -29,7 +29,7 @@ public class CreateLinkAction: QuickSymlinkAction {
let targetPath = self.getTargetPath(path, to: path.deletingLastPathComponent());
do {
- try FileManager.default.createSymbolicLink(at: targetPath!, withDestinationURL: path);
+ try FileManager.default.createSymbolicLink(at: targetPath!, withDestinationURL: ResourcePath.of(url: path).relativize(to: ResourcePath.of(url: targetPath?.deletingLastPathComponent())).toUrl()!);
} catch let error as NSError {
NSLog("FileManager.createSymbolicLink() failed to create file: %@", error.description as NSString);
}
diff --git a/commons/PasteLinkAction.swift b/commons/QuickSymlinkActions/PasteLinkAction.swift
similarity index 90%
rename from commons/PasteLinkAction.swift
rename to commons/QuickSymlinkActions/PasteLinkAction.swift
index b174aa1..991fbbe 100644
--- a/commons/PasteLinkAction.swift
+++ b/commons/QuickSymlinkActions/PasteLinkAction.swift
@@ -38,7 +38,7 @@ public class PasteLinkAction: QuickSymlinkAction {
let targetPath = self.getTargetPath(pathUrl, to: target);
do {
- try FileManager.default.createSymbolicLink(at: targetPath!, withDestinationURL: URL(fileURLWithPath: path));
+ try FileManager.default.createSymbolicLink(at: targetPath!, withDestinationURL: ResourcePath.of(url: pathUrl).relativize(to: ResourcePath.of(url: targetPath?.deletingLastPathComponent())).toUrl()!);
} catch let error as NSError {
NSLog("FileManager.createSymbolicLink() failed to create file: %@", error.description as NSString);
}
diff --git a/commons/QuickSymlinkAction.swift b/commons/QuickSymlinkActions/QuickSymlinkAction.swift
similarity index 100%
rename from commons/QuickSymlinkAction.swift
rename to commons/QuickSymlinkActions/QuickSymlinkAction.swift
diff --git a/commons/ReplaceWithLinkAction.swift b/commons/QuickSymlinkActions/ReplaceWithLinkAction.swift
similarity index 91%
rename from commons/ReplaceWithLinkAction.swift
rename to commons/QuickSymlinkActions/ReplaceWithLinkAction.swift
index 07c988f..d2a9c1b 100644
--- a/commons/ReplaceWithLinkAction.swift
+++ b/commons/QuickSymlinkActions/ReplaceWithLinkAction.swift
@@ -39,7 +39,7 @@ public class ReplaceWithLinkAction: QuickSymlinkAction {
do {
try FileManager.default.moveItem(at: pathUrl, to: targetPath!);
- try FileManager.default.createSymbolicLink(at: pathUrl, withDestinationURL: targetPath!);
+ try FileManager.default.createSymbolicLink(at: pathUrl, withDestinationURL: ResourcePath.of(url: targetPath).relativize(to: ResourcePath.of(url: pathUrl.deletingLastPathComponent())).toUrl()!);
} catch let error as NSError {
NSLog("FileManager.createSymbolicLink() failed to create file: %@", error.description as NSString);
}
diff --git a/quick-symlink-tests/Info.plist b/quick-symlink-tests/Info.plist
new file mode 100644
index 0000000..6c40a6c
--- /dev/null
+++ b/quick-symlink-tests/Info.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+
+
diff --git a/quick-symlink-tests/ResourcePathTest.swift b/quick-symlink-tests/ResourcePathTest.swift
new file mode 100644
index 0000000..40f4b7e
--- /dev/null
+++ b/quick-symlink-tests/ResourcePathTest.swift
@@ -0,0 +1,49 @@
+//
+// ResourcePathTest.swift
+// quick-symlink-tests
+//
+// Created by Alexander A. Kropotin on 22/08/2021.
+// Copyright © 2021 Alexander A. Kropotin. All rights reserved.
+//
+
+import XCTest
+
+class ResourcePathTest: XCTestCase {
+
+ func test_toURL_methodExecution_returnedURLIsEqualToInitialURL() {
+ let uri: URL = URL.init(string: "/a/b/c/d")!;
+ let path: Path = ResourcePath.of(url: uri);
+
+ XCTAssert(path.toUrl() == uri, "The Path URL is not equal to URL");
+ }
+
+ func test_relativize_whenCurrentDirectoryIsNestedToOtherDirectory_thenReturnPathStartingFromOtherDirectory() {
+ let currentUri: URL = URL.init(string: "/a/b/c/d")!;
+ let otherUri: URL = URL.init(string: "/a/b")!;
+
+ let relativePath: Path = ResourcePath.of(url: currentUri)
+ .relativize(to: ResourcePath.of(url: otherUri));
+
+ XCTAssert(relativePath.toUriString() == "./c/d", "The relative path is wrong");
+ }
+
+ func test_relativize_whenOtherDirectoryIsNestedToCurrentDirectory_thenReturnPathWithOnlyJumpsAboveOtherDirectory() {
+ let currentUri: URL = URL.init(string: "/a/b")!;
+ let otherUri: URL = URL.init(string: "/a/b/c/d")!;
+
+ let relativePath: Path = ResourcePath.of(url: currentUri)
+ .relativize(to: ResourcePath.of(url: otherUri));
+
+ XCTAssert(relativePath.toUriString() == "./../..", "The relative path is wrong");
+ }
+
+ func test_relativize_whenCurrentDirectoryAndOtherDirectoryAreNestedToGeneralDirectoryy_thenReturnPathWithJumpsAboveOtherDirectoryAndPartOfCurrentDirectory() {
+ let currentUri: URL = URL.init(string: "/a/b/c1/d1")!;
+ let otherUri: URL = URL.init(string: "/a/b/c2/d2")!;
+
+ let relativePath: Path = ResourcePath.of(url: currentUri)
+ .relativize(to: ResourcePath.of(url: otherUri));
+
+ XCTAssert(relativePath.toUriString() == "./../../c1/d1", "The relative path is wrong");
+ }
+}
diff --git a/quick-symlink.xcodeproj/project.pbxproj b/quick-symlink.xcodeproj/project.pbxproj
index 7e1ab47..1de801c 100644
--- a/quick-symlink.xcodeproj/project.pbxproj
+++ b/quick-symlink.xcodeproj/project.pbxproj
@@ -7,6 +7,13 @@
objects = {
/* Begin PBXBuildFile section */
+ A307B41726D21E39002EEF58 /* Path.swift in Sources */ = {isa = PBXBuildFile; fileRef = A307B41626D21E39002EEF58 /* Path.swift */; };
+ A307B41826D21E39002EEF58 /* Path.swift in Sources */ = {isa = PBXBuildFile; fileRef = A307B41626D21E39002EEF58 /* Path.swift */; };
+ A307B41A26D22116002EEF58 /* ResourcePath.swift in Sources */ = {isa = PBXBuildFile; fileRef = A307B41926D22116002EEF58 /* ResourcePath.swift */; };
+ A307B41B26D22116002EEF58 /* ResourcePath.swift in Sources */ = {isa = PBXBuildFile; fileRef = A307B41926D22116002EEF58 /* ResourcePath.swift */; };
+ A307B42F26D2563B002EEF58 /* ResourcePathTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A307B42E26D2563B002EEF58 /* ResourcePathTest.swift */; };
+ A307B43026D257C5002EEF58 /* ResourcePath.swift in Sources */ = {isa = PBXBuildFile; fileRef = A307B41926D22116002EEF58 /* ResourcePath.swift */; };
+ A307B43126D257CA002EEF58 /* Path.swift in Sources */ = {isa = PBXBuildFile; fileRef = A307B41626D21E39002EEF58 /* Path.swift */; };
A30B9AAB265CA63300ACAA63 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A30B9AAA265CA63300ACAA63 /* AppDelegate.swift */; };
A30B9AAD265CA63300ACAA63 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A30B9AAC265CA63300ACAA63 /* ViewController.swift */; };
A30B9AAF265CA63300ACAA63 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A30B9AAE265CA63300ACAA63 /* Assets.xcassets */; };
@@ -28,6 +35,13 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
+ A307B42926D255FB002EEF58 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = A30B9A9F265CA63300ACAA63 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = A30B9AA6265CA63300ACAA63;
+ remoteInfo = "quick-symlink";
+ };
A30B9AC4265CA68900ACAA63 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A30B9A9F265CA63300ACAA63 /* Project object */;
@@ -52,6 +66,11 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ A307B41626D21E39002EEF58 /* Path.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Path.swift; sourceTree = ""; };
+ A307B41926D22116002EEF58 /* ResourcePath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourcePath.swift; sourceTree = ""; };
+ A307B42426D255FB002EEF58 /* quick-symlink-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "quick-symlink-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+ A307B42826D255FB002EEF58 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ A307B42E26D2563B002EEF58 /* ResourcePathTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourcePathTest.swift; sourceTree = ""; };
A30B9AA7265CA63300ACAA63 /* quick-symlink.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "quick-symlink.app"; sourceTree = BUILT_PRODUCTS_DIR; };
A30B9AAA265CA63300ACAA63 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
A30B9AAC265CA63300ACAA63 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
@@ -80,6 +99,13 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
+ A307B42126D255FB002EEF58 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
A30B9AA4265CA63300ACAA63 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -97,6 +123,36 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ A307B41426D21DBE002EEF58 /* QuickSymlinkActions */ = {
+ isa = PBXGroup;
+ children = (
+ A316477626B7B403001DD969 /* CreateLinkAction.swift */,
+ A345C9C726A0B552004FBF0F /* ReplaceWithLinkAction.swift */,
+ A345C9C426A0B49C004FBF0F /* PasteLinkAction.swift */,
+ A345C9C126A0B30F004FBF0F /* CopyPathAction.swift */,
+ A345C9BE26A0B200004FBF0F /* QuickSymlinkAction.swift */,
+ );
+ path = QuickSymlinkActions;
+ sourceTree = "";
+ };
+ A307B41526D21E23002EEF58 /* FileSystem */ = {
+ isa = PBXGroup;
+ children = (
+ A307B41626D21E39002EEF58 /* Path.swift */,
+ A307B41926D22116002EEF58 /* ResourcePath.swift */,
+ );
+ path = FileSystem;
+ sourceTree = "";
+ };
+ A307B42526D255FB002EEF58 /* quick-symlink-tests */ = {
+ isa = PBXGroup;
+ children = (
+ A307B42826D255FB002EEF58 /* Info.plist */,
+ A307B42E26D2563B002EEF58 /* ResourcePathTest.swift */,
+ );
+ path = "quick-symlink-tests";
+ sourceTree = "";
+ };
A30B9A9E265CA63300ACAA63 = {
isa = PBXGroup;
children = (
@@ -104,6 +160,7 @@
A3D93EB726A09B5A004E068D /* Localizable.strings */,
A30B9AA9265CA63300ACAA63 /* quick-symlink */,
A30B9ABF265CA68900ACAA63 /* quick-symlink-extension */,
+ A307B42526D255FB002EEF58 /* quick-symlink-tests */,
A30B9AA8265CA63300ACAA63 /* Products */,
);
sourceTree = "";
@@ -113,6 +170,7 @@
children = (
A30B9AA7265CA63300ACAA63 /* quick-symlink.app */,
A30B9ABE265CA68900ACAA63 /* quick-symlink-extension.appex */,
+ A307B42426D255FB002EEF58 /* quick-symlink-tests.xctest */,
);
name = Products;
sourceTree = "";
@@ -145,11 +203,8 @@
A345C9BD26A0B12C004FBF0F /* commons */ = {
isa = PBXGroup;
children = (
- A345C9BE26A0B200004FBF0F /* QuickSymlinkAction.swift */,
- A345C9C126A0B30F004FBF0F /* CopyPathAction.swift */,
- A345C9C426A0B49C004FBF0F /* PasteLinkAction.swift */,
- A345C9C726A0B552004FBF0F /* ReplaceWithLinkAction.swift */,
- A316477626B7B403001DD969 /* CreateLinkAction.swift */,
+ A307B41526D21E23002EEF58 /* FileSystem */,
+ A307B41426D21DBE002EEF58 /* QuickSymlinkActions */,
);
path = commons;
sourceTree = "";
@@ -157,6 +212,24 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
+ A307B42326D255FB002EEF58 /* quick-symlink-tests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = A307B42B26D255FB002EEF58 /* Build configuration list for PBXNativeTarget "quick-symlink-tests" */;
+ buildPhases = (
+ A307B42026D255FB002EEF58 /* Sources */,
+ A307B42126D255FB002EEF58 /* Frameworks */,
+ A307B42226D255FB002EEF58 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ A307B42A26D255FB002EEF58 /* PBXTargetDependency */,
+ );
+ name = "quick-symlink-tests";
+ productName = "quick-symlink-tests";
+ productReference = A307B42426D255FB002EEF58 /* quick-symlink-tests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
A30B9AA6265CA63300ACAA63 /* quick-symlink */ = {
isa = PBXNativeTarget;
buildConfigurationList = A30B9AB7265CA63300ACAA63 /* Build configuration list for PBXNativeTarget "quick-symlink" */;
@@ -203,6 +276,11 @@
LastUpgradeCheck = 0920;
ORGANIZATIONNAME = "Alexander A. Kropotin";
TargetAttributes = {
+ A307B42326D255FB002EEF58 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Automatic;
+ TestTargetID = A30B9AA6265CA63300ACAA63;
+ };
A30B9AA6265CA63300ACAA63 = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Automatic;
@@ -235,11 +313,19 @@
targets = (
A30B9AA6265CA63300ACAA63 /* quick-symlink */,
A30B9ABD265CA68900ACAA63 /* quick-symlink-extension */,
+ A307B42326D255FB002EEF58 /* quick-symlink-tests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
+ A307B42226D255FB002EEF58 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
A30B9AA5265CA63300ACAA63 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -261,12 +347,24 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
+ A307B42026D255FB002EEF58 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A307B43026D257C5002EEF58 /* ResourcePath.swift in Sources */,
+ A307B42F26D2563B002EEF58 /* ResourcePathTest.swift in Sources */,
+ A307B43126D257CA002EEF58 /* Path.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
A30B9AA3265CA63300ACAA63 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ A307B41A26D22116002EEF58 /* ResourcePath.swift in Sources */,
A345C9C826A0B552004FBF0F /* ReplaceWithLinkAction.swift in Sources */,
A316477726B7B403001DD969 /* CreateLinkAction.swift in Sources */,
+ A307B41726D21E39002EEF58 /* Path.swift in Sources */,
A30B9AAD265CA63300ACAA63 /* ViewController.swift in Sources */,
A345C9C226A0B30F004FBF0F /* CopyPathAction.swift in Sources */,
A345C9BF26A0B200004FBF0F /* QuickSymlinkAction.swift in Sources */,
@@ -280,6 +378,8 @@
buildActionMask = 2147483647;
files = (
A30B9AC1265CA68900ACAA63 /* FinderSync.swift in Sources */,
+ A307B41826D21E39002EEF58 /* Path.swift in Sources */,
+ A307B41B26D22116002EEF58 /* ResourcePath.swift in Sources */,
A30D4A4B26A0C14400BA775B /* PasteLinkAction.swift in Sources */,
A30D4A4C26A0C14400BA775B /* ReplaceWithLinkAction.swift in Sources */,
A316477826B7B403001DD969 /* CreateLinkAction.swift in Sources */,
@@ -291,6 +391,11 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
+ A307B42A26D255FB002EEF58 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = A30B9AA6265CA63300ACAA63 /* quick-symlink */;
+ targetProxy = A307B42926D255FB002EEF58 /* PBXContainerItemProxy */;
+ };
A30B9AC5265CA68900ACAA63 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = A30B9ABD265CA68900ACAA63 /* quick-symlink-extension */;
@@ -325,6 +430,38 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
+ A307B42C26D255FB002EEF58 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = "quick-symlink-tests/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.14;
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ololx.quick-symlink-tests";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 4.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/quick-symlink.app/Contents/MacOS/quick-symlink";
+ };
+ name = Debug;
+ };
+ A307B42D26D255FB002EEF58 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = "quick-symlink-tests/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.14;
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ololx.quick-symlink-tests";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 4.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/quick-symlink.app/Contents/MacOS/quick-symlink";
+ };
+ name = Release;
+ };
A30B9AB5265CA63300ACAA63 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -502,6 +639,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
+ A307B42B26D255FB002EEF58 /* Build configuration list for PBXNativeTarget "quick-symlink-tests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ A307B42C26D255FB002EEF58 /* Debug */,
+ A307B42D26D255FB002EEF58 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
A30B9AA2265CA63300ACAA63 /* Build configuration list for PBXProject "quick-symlink" */ = {
isa = XCConfigurationList;
buildConfigurations = (