Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
ololx committed Sep 2, 2021
2 parents 949387f + 5206a22 commit 46aead9
Show file tree
Hide file tree
Showing 30 changed files with 610 additions and 121 deletions.
20 changes: 17 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,25 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p

- Refactor application.

## [0.8.0] - 2021-09-02

### Added

- Develop additional `Finder extension` which allows to create a `hard links` for selected folders and files via contextual menu.

### Changed

- Change build os version to 10.10.

### Fixed

- Fix soft link replace with function.

## [0.7.0] - 2021-08-22

### Added

- Added new classes `Path` for working with path's and creating relative path from specified directory.
- Add new classes `Path` for working with path's and creating relative path from specified directory.
- Add unit-tests cases for the `Path` class.

### Changed
Expand All @@ -25,13 +39,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p

### Changed

- Changed the activity property of some menu items according to the rule:
- Change the activity property of some menu items according to the rule:
- if no object was copied, then the menu items "Paste link to here" an "Move it here and replace with a link" are not active.
- if at least one object was not copied, then the menu items "Paste link to here" an "Move it here and replace with a link" are inactive.

### Added

- Added cleaning clipboard after inserting links.
- Add cleaning clipboard after inserting links.

## [0.5.0] - 2021-08-02

Expand Down
51 changes: 38 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

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_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)
[![status](https://img.shields.io/badge/status-active-active?style=flat-square)](BADGES_GUIDE.md#status) [![version](https://img.shields.io/badge/version-0.8.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-September_02,_2021-informational?style=flat-square)](BADGES_GUIDE.md#release-date) [![last commit](https://img.shields.io/badge/last_commit-September_02,_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)

[![platform](https://img.shields.io/badge/platform-OS_X_10.11+-important?style=flat-square)](https://en.wikipedia.org/wiki/Computing_platform)
[![platform](https://img.shields.io/badge/platform-OS_X_10.10+-important?style=flat-square)](https://en.wikipedia.org/wiki/Computing_platform)

---

Expand Down Expand Up @@ -55,10 +55,14 @@ This GIF demonstrates how the `Quick Symlink` allows quite simple to copy files
## 🎚 Features

- Create a symbolic links in a several clicks via the context menu instead of the terminal promt:
- Select files or folders and create symlink for them.
- Copy files or folders and paste symlink somewhere.
- Select files or folders and create symlinks for them.
- Copy files or folders and paste symlinks somewhere.
- Copy files or folders, paste them somewhere, and replace them with symlinks.

- Create a hard links in a several clicks via the context menu instead of the terminal promt:
- Select files or folders and create hard links for them.
- Copy files or folders and paste hard links somewhere.

### To Do

- For more information on an upcoming development, please read the [todo](TODO.md) list.
Expand All @@ -75,12 +79,12 @@ These instructions allow to get a copy of this project and run it on a local mac

Before using it, make sure that follows software are installed on the local machine:

- **[OS X 10.11+](https://www.apple.com/ru/macos/what-is/)** - the operating system under which the extention is executing.
- **[OS X 10.10+](https://www.apple.com/ru/macos/what-is/)** - the operating system under which the extention is executing.

If any of the listed programs is not installed, then it can be installed by instruction as described below.

1. #### OS X 10.11+
- Install macOS 10.11+ by [this](https://support.apple.com/ht201372) instruction.
1. #### OS X 10.10+
- Install macOS 10.10+ by [this](https://support.apple.com/ht201372) instruction.

### Installing

Expand All @@ -105,20 +109,24 @@ In order to install it is quite simple to:
open quick-symlink.app
```

4. Open up `System Preferences > Extensions` and enable the extension `quick-symlink`.
4. Open up `System Preferences > Extensions` and enable the follows extensions:
4.1. `quick-symlink-extension` - for the symlink actions.
4.2. `hard-link-actions-extension` - for the hard link actions.

**Otherwise, it's possible to install and remove the extention using the actual extension bundled into the app.**

1. To install and approve the extension, run this:

```bash
pluginkit -a quick-symlink.app/Contents/PlugIns/quick-symlink-extension.appex/
pluginkit -a quick-symlink.app/Contents/PlugIns/hard-link-action-extension.appex/
```

2. To remove it, run this:

```bash
pluginkit -r quick-symlink.app/Contents/PlugIns/quick-symlink-extension.appex/
pluginkit -r quick-symlink.app/Contents/PlugIns/hard-link-action-extension.appex/
```

### Downloading
Expand All @@ -144,27 +152,44 @@ This tool allows to:
<summary>Create symlinks in the current directory</summary>
1. Select folders or files for which a symbolic link is needed.<br/>
2. Call the contextual menu by the right-clicking on selected.<br/>
3. Select menu item `Quick Symlink --> Create symlink for`.<br/>
3. Select menu item `Symlink actions --> Create symlink for`.<br/>
</details>

<details close>
<summary>Create symlinks in another directory</summary>
1. Select folders or files for which a symbolic link is needed.<br/>
2. Call the contextual menu by the right-clicking on selected.<br/>
3. Select menu item `Quick Symlink --> Copy path from here`.<br/>
3. Select menu item `Symlink actions --> Copy path from here`.<br/>
4. Go to a destination folder.<br/>
5. Call the contextual menu by right-clicking on the filder.<br/>
6. Select menu item `Quick Symlink --> Paste to here`.<br/>
6. Select menu item `Symlink actions --> Paste to here`.<br/>
</details>

<details close>
<summary>Replace objects with symbolic links</summary>
1. Select folders or files for which a symbolic link is needed.<br/>
2. Call the contextual menu by the right-clicking on selected.<br/>
3. Select menu item `Quick Symlink --> Copy to clipboard`.<br/>
3. Select menu item `Symlink actions --> Copy to clipboard`.<br/>
4. Go to a destination folder.<br/>
5. Call the contextual menu by right-clicking on the filder.<br/>
6. Select menu item `Symlink actions --> Move it here and replace with a link`.<br/>
</details>

<details close>
<summary>Create hard links in the current directory</summary>
1. Select folders or files for which a symbolic link is needed.<br/>
2. Call the contextual menu by the right-clicking on selected.<br/>
3. Select menu item `Hard link actions --> Create symlink for`.<br/>
</details>

<details close>
<summary>Create symlinks in another directory</summary>
1. Select folders or files for which a symbolic link is needed.<br/>
2. Call the contextual menu by the right-clicking on selected.<br/>
3. Select menu item `Hard link actions --> Copy path from here`.<br/>
4. Go to a destination folder.<br/>
5. Call the contextual menu by right-clicking on the filder.<br/>
6. Select menu item `Quick Symlink --> Move it here and replace with a link`.<br/>
6. Select menu item `Hard link actions --> Paste to here`.<br/>
</details>

## 🛠 Built With
Expand Down
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- [x] Add the new menu item for creating symlink in a parent directory (parent for target objects).
- [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
- [x] 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
Expand Down
40 changes: 0 additions & 40 deletions commons/QuickSymlinkActions/QuickSymlinkAction.swift

This file was deleted.

89 changes: 89 additions & 0 deletions commons/link/FileLinkManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//
// FileManagerAdapter.swift
// quick-symlink
//
// Created by Alexander A. Kropotin on 01/09/2021.
// Copyright © 2021 Alexander A. Kropotin. All rights reserved.
//

import Foundation
import FinderSync

public protocol FileLinkManager {

func linkWith(of: URL!, with: URL!);

func replaceWith(of: URL!, with: URL!);
}

public extension FileLinkManager {

public func getTargetPath(_ from: URL!, to: URL!) -> URL! {
let originSourceName = from.absoluteURL.deletingPathExtension().lastPathComponent;
let fileType = from.absoluteURL.pathExtension;

var fileExtention = fileType;
if !fileType.isEmpty {
fileExtention = ".\(fileType)"
}

var fileName = "\(originSourceName)\(fileExtention)";
var counter = 1
var targetPath = to;
targetPath = targetPath?.appendingPathComponent(fileName);

while FileManager.default.fileExists(atPath: (targetPath?.path)!) {
fileName = "\(originSourceName)-\(counter)\(fileExtention)";
counter += 1;
targetPath = to.appendingPathComponent(fileName);
}

return targetPath!;
}
}

public class SoftLinkManager: FileLinkManager {

public func linkWith(of: URL!, with: URL!) {
do {
try FileManager.default.createSymbolicLink(at: with!, withDestinationURL: ResourcePath.of(url: of).relativize(to: ResourcePath.of(url: with?.deletingLastPathComponent())).toUrl()!);
} catch let error as NSError {
NSLog("FileManager.createSymbolicLink() failed to create file: %@", error.description as NSString);
}
}

public func replaceWith(of: URL!, with: URL!) {
do {
//FIXME: Add checking for existance of file & resolving this case with symply pastle link
try FileManager.default.moveItem(at: of, to: with);
try FileManager.default.createSymbolicLink(at: of, withDestinationURL: ResourcePath.of(url: with).relativize(to: ResourcePath.of(url: of.deletingLastPathComponent())).toUrl()!);
} catch let error as NSError {
NSLog("FileManager.createSymbolicLink() failed to create file: %@", error.description as NSString);
}
}
}

public class HardLinkManager: FileLinkManager {

public func linkWith(of: URL!, with: URL!) {

let pasteboard = NSPasteboard.general;
pasteboard.declareTypes([NSPasteboard.PasteboardType.string], owner: nil);

do {
try FileManager.default.linkItem(at: of, to: with);

} catch let error as NSError {
NSLog("FileManager.createSymbolicLink() failed to create file: %@", error.description as NSString);
}
}

public func replaceWith(of: URL!, with: URL!) {
do {
try FileManager.default.moveItem(at: of, to: with);
try FileManager.default.linkItem(at: with, to: of);
} catch let error as NSError {
NSLog("FileManager.createSymbolicLink() failed to create file: %@", error.description as NSString);
}
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ public class CreateLinkAction: QuickSymlinkAction {

private var finderController: FIFinderSyncController;

public init() {
private var fileLinkManager: FileLinkManager;

public init(fileLinkManager: FileLinkManager!) {
self.finderController = FIFinderSyncController.default();
self.fileLinkManager = fileLinkManager;
}

public func execute() {
Expand All @@ -26,14 +29,8 @@ public class CreateLinkAction: QuickSymlinkAction {
}

for path in target {
let targetPath = self.getTargetPath(path, to: path.deletingLastPathComponent());

do {
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);
}
let targetPath = self.fileLinkManager.getTargetPath(path, to: path.deletingLastPathComponent());
self.fileLinkManager.linkWith(of: path, with: targetPath);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ public class PasteLinkAction: QuickSymlinkAction {

private var finderController: FIFinderSyncController;

public init() {
private var fileLinkManager: FileLinkManager;

public init(fileLinkManager: FileLinkManager!) {
self.finderController = FIFinderSyncController.default();
self.fileLinkManager = fileLinkManager;
}

public func execute() {
Expand All @@ -35,13 +38,8 @@ public class PasteLinkAction: QuickSymlinkAction {
let paths = pathsFromClipboard.components(separatedBy: ";");
for path in paths {
let pathUrl = URL(fileURLWithPath: path);
let targetPath = self.getTargetPath(pathUrl, to: target);

do {
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);
}
let targetPath = self.fileLinkManager.getTargetPath(pathUrl, to: target);
self.fileLinkManager.linkWith(of: pathUrl, with: targetPath);
}
}
}
14 changes: 14 additions & 0 deletions commons/link/action/QuickSymlinkAction.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// QuickSymlinkAction.swift
// quick-symlink
//
// Created by Alexander A. Kropotin on 15/07/2021.
// Copyright © 2021 Alexander A. Kropotin. All rights reserved.
//

import Foundation

public protocol QuickSymlinkAction {

func execute();
}
Loading

0 comments on commit 46aead9

Please sign in to comment.