diff --git a/FSNotes/Business/Project+Git.swift b/FSNotes/Business/Project+Git.swift index 71ded2ba3..9d24ae7c5 100644 --- a/FSNotes/Business/Project+Git.swift +++ b/FSNotes/Business/Project+Git.swift @@ -14,7 +14,7 @@ extension Project { return nil } - let parentURL = getGitProject().url + let parentURL = getRepositoryProject().url let relative = url.path.replacingOccurrences(of: parentURL.path, with: "") if relative.first == "/" { @@ -29,43 +29,67 @@ extension Project { } public func getGitOrigin() -> String? { - if let origin = gitOrigin, origin.count > 0 { + if let origin = getRepositoryProject().gitOrigin, origin.count > 0 { return origin } - let parentProject = getParent() + return nil + } + + public func isRepositoryRoot(project: Project) -> Bool { + if project.isRoot { + return true + } - if parentProject.isDefault, let origin = UserDefaultsManagement.gitOrigin, origin.count > 0 { - return UserDefaultsManagement.gitOrigin + if project.isDefault { + return true } - if let gitOrigin = parentProject.gitOrigin, gitOrigin.count > 0 { - return gitOrigin + if project.isArchive { + return true } - return nil + if let origin = project.gitOrigin, origin.count > 0 { + return true + } + + return false } - public func getGitRepositoryUrl() -> URL { - if UserDefaultsManagement.separateRepo && !isCloudProject() { - return url.appendingPathComponent(".git", isDirectory: true) + public func getRepositoryProject() -> Project { + if isRepositoryRoot(project: self) { + return self + } + + var parent = self.parent + + while let unwrapedParent = parent { + if isRepositoryRoot(project: unwrapedParent) { + return unwrapedParent + } + + parent = unwrapedParent.parent } - return UserDefaultsManagement.gitStorage.appendingPathComponent(getShortSign() + " - " + label + ".git", isDirectory: true) + return self } - public func isRepoExist() -> Bool { - let url = getGitRepositoryUrl() - return FileManager.default.directoryExists(atUrl: url) + public func getRepositoryUrl() -> URL { + let rootProject = getRepositoryProject() + + if UserDefaultsManagement.separateRepo && !rootProject.isCloudProject() { + return rootProject.url.appendingPathComponent(".git", isDirectory: true) + } + + let repoURL = UserDefaultsManagement.gitStorage.appendingPathComponent(getShortSign() + " - " + rootProject.label + ".git") + + return repoURL } public func getRepository() throws -> Repository? { - if UserDefaultsManagement.separateRepo && !isCloudProject() { - return getSeparateRepository() - } - let repositoryManager = RepositoryManager() - let repoURL = UserDefaultsManagement.gitStorage.appendingPathComponent(getShortSign() + " - " + label + ".git") + let repositoryProject = getRepositoryProject() + let repoURL = getRepositoryUrl() // Open do { @@ -73,16 +97,18 @@ extension Project { return repository } catch {/*_*/} + // Prepare temporary dir + let cloneURL = UserDefaultsManagement.gitStorage.appendingPathComponent("tmp") + + try? FileManager.default.removeItem(at: cloneURL) + try? FileManager.default.createDirectory(at: cloneURL, withIntermediateDirectories: true) + // Clone if let originString = getGitOrigin(), let origin = URL(string: originString) { - let cloneURL = UserDefaultsManagement.gitStorage.appendingPathComponent("tmp") - try? FileManager.default.removeItem(at: cloneURL) - do { let repository = try repositoryManager.cloneRepository(from: origin, at: cloneURL, authentication: getHandler()) - repository.setWorkTree(path: url.path) - + repository.setWorkTree(path: repositoryProject.url.path) let dotGit = cloneURL.appendingPathComponent(".git") if FileManager.default.directoryExists(atUrl: dotGit) { @@ -90,20 +116,18 @@ extension Project { return try repositoryManager.openRepository(at: repoURL) } - } catch {/*_*/} + } catch { + print("Repo clone error: \(error)") + } return nil } // Init do { - let cloneURL = UserDefaultsManagement.gitStorage.appendingPathComponent("tmp") - try? FileManager.default.createDirectory(at: cloneURL, withIntermediateDirectories: true) - let signature = Signature(name: "FSNotes App", email: "support@fsnot.es") let repository = try repositoryManager.initRepository(at: cloneURL, signature: signature) - - repository.setWorkTree(path: url.path) + repository.setWorkTree(path: repositoryProject.url.path) let dotGit = cloneURL.appendingPathComponent(".git") @@ -119,43 +143,22 @@ extension Project { return nil } - public func getSeparateRepository() -> Repository? { - let repositoryManager = RepositoryManager() - let repoURL = url.appendingPathComponent(".git", isDirectory: true) - - do { - let repository = try repositoryManager.openRepository(at: repoURL) - return repository - } catch {/*_*/} - - guard let originString = getGitOrigin(), let origin = URL(string: originString) else { return nil } - - let cloneURL = UserDefaultsManagement.gitStorage.appendingPathComponent("tmp") - try? FileManager.default.removeItem(at: cloneURL) - - do { - _ = try repositoryManager.cloneRepository(from: origin, at: cloneURL, authentication: getHandler()) - let dotGit = cloneURL.appendingPathComponent(".git") - - if FileManager.default.directoryExists(atUrl: dotGit) { - try FileManager.default.moveItem(at: dotGit, to: repoURL) - - return try repositoryManager.openRepository(at: repoURL) - } - } catch { - print("Clone error: \(error)") - } - - return nil - } - - public func isUseSeparateRepo() -> Bool { + public func useSeparateRepo() -> Bool { return UserDefaultsManagement.separateRepo && !isCloudProject() } public func isCloudProject() -> Bool { - return UserDefaultsManagement.storagePath == UserDefaultsManagement.iCloudDocumentsContainer?.path - && url.path == UserDefaultsManagement.storagePath + if UserDefaultsManagement.storagePath == UserDefaultsManagement.iCloudDocumentsContainer?.path { + if url.path == UserDefaultsManagement.storagePath { + return true + } + + if getParent().isCloudDrive { + return true + } + } + + return false } public func getHandler() -> SshKeyHandler? { @@ -241,9 +244,10 @@ extension Project { public func pull() throws { guard let repository = try getRepository() else { return } + let repositoryProject = getRepositoryProject() if !UserDefaultsManagement.separateRepo || isCloudProject() { - repository.setWorkTree(path: url.path) + repository.setWorkTree(path: repositoryProject.url.path) } let handler = getHandler() @@ -252,17 +256,9 @@ extension Project { let remote = repository.remotes let origin = try remote.get(remoteName: "origin") - _ = try origin.pull(signature: sign, authentication: handler, project: self) - } - - public func getGitProject() -> Project { - if isGitOriginExist() { - return self - } else { - return getParent() - } + _ = try origin.pull(signature: sign, authentication: handler, project: repositoryProject) } - + public func isGitOriginExist() -> Bool { if let origin = gitOrigin, origin.count > 0 { return true diff --git a/FSNotes/Business/Storage.swift b/FSNotes/Business/Storage.swift index 366915976..a5d512c78 100644 --- a/FSNotes/Business/Storage.swift +++ b/FSNotes/Business/Storage.swift @@ -555,15 +555,7 @@ class Storage { && $0.showInSidebar }) } - - public func getCloudDriveProjects() -> [Project] { - return projects.filter({$0.isCloudDrive == true}) - } - - public func getLocalProjects() -> [Project] { - return projects.filter({$0.isCloudDrive == false}) - } - + public func getProjectPaths() -> [String] { var pathList: [String] = [] let projects = getProjects() diff --git a/FSNotes/Helpers/FileSystemEventManager.swift b/FSNotes/Helpers/FileSystemEventManager.swift index 56e917b2a..74c73ba82 100644 --- a/FSNotes/Helpers/FileSystemEventManager.swift +++ b/FSNotes/Helpers/FileSystemEventManager.swift @@ -90,6 +90,10 @@ class FileSystemEventManager { let dirURL = URL(fileURLWithPath: event.path, isDirectory: true) let project = self.storage.getProjectBy(url: dirURL) + guard dirURL.lastPathComponent != ".git" else { + return + } + guard !dirURL.isHidden() else { // hide if exist and hidden (xattr "es.fsnot.hidden.dir") if event.dirChange { diff --git a/FSNotes/Preferences/PreferencesGitViewController.swift b/FSNotes/Preferences/PreferencesGitViewController.swift index a8f6045b4..fb6e98ac8 100644 --- a/FSNotes/Preferences/PreferencesGitViewController.swift +++ b/FSNotes/Preferences/PreferencesGitViewController.swift @@ -140,6 +140,7 @@ class PreferencesGitViewController: NSViewController { @IBAction func origin(_ sender: NSTextField) { let project = Storage.sharedInstance().getDefault() project?.gitOrigin = sender.stringValue + project?.saveSettings() UserDefaultsManagement.gitOrigin = sender.stringValue } diff --git a/FSNotes/ProjectSettingsViewController.swift b/FSNotes/ProjectSettingsViewController.swift index a6d94609e..3f84d146e 100644 --- a/FSNotes/ProjectSettingsViewController.swift +++ b/FSNotes/ProjectSettingsViewController.swift @@ -116,7 +116,7 @@ class ProjectSettingsViewController: NSViewController { return } - if project.isRepoExist() { + if FileManager.default.directoryExists(atUrl: project.getRepositoryUrl()) { let alert = NSAlert() alert.messageText = NSLocalizedString("Git repository already exists, delete it and clone again??", comment: "") alert.informativeText = NSLocalizedString("This action cannot be undone.", comment: "") @@ -125,7 +125,7 @@ class ProjectSettingsViewController: NSViewController { alert.beginSheetModal(for: window) { (returnCode: NSApplication.ModalResponse) -> Void in if returnCode == NSApplication.ModalResponse.alertFirstButtonReturn { do { - try FileManager.default.removeItem(at: project.getGitRepositoryUrl()) + try FileManager.default.removeItem(at: project.getRepositoryUrl()) ProjectSettingsViewController.cloneAndPull(project: project) } catch {/*_*/} diff --git a/FSNotes/View/SidebarOutlineView.swift b/FSNotes/View/SidebarOutlineView.swift index 366b984ec..d37697c10 100644 --- a/FSNotes/View/SidebarOutlineView.swift +++ b/FSNotes/View/SidebarOutlineView.swift @@ -989,7 +989,7 @@ class SidebarOutlineView: NSOutlineView, guard let project = ViewController.shared()?.getSidebarProject() else { return } vc.gitQueue.addOperation({ - let project = project.getGitProject() + let project = project.getRepositoryProject() do { try project.commit() diff --git a/FSNotes/ViewController+Git.swift b/FSNotes/ViewController+Git.swift index 8ab59dd50..3e5db0702 100644 --- a/FSNotes/ViewController+Git.swift +++ b/FSNotes/ViewController+Git.swift @@ -49,7 +49,7 @@ extension EditorViewController { guard let note = getSelectedNotes()?.first, let window = self.view.window else { return } ViewController.shared()?.gitQueue.addOperation({ - let project = note.project.getGitProject() + let project = note.project.getRepositoryProject() try? project.commit(message: commitMessage) // No hands – no mults