Giter Club home page Giter Club logo

files's Introduction

“Files”

BuddyBuild CocoaPods Carthage Swift Package Manager Twitter: @johnsundell

Welcome to Files, a compact library that provides a nicer way to handle files and folders in Swift. It’s primarily aimed at Swift scripting and tooling, but can also be embedded in applications that need to access the file system. It's essentially a thin wrapper around the FileManager APIs that Foundation provides.

Features

  • Modern, object-oriented API for accessing, reading and writing files & folders.
  • Unified, simple do, try, catch error handling.
  • Easily construct recursive and flat sequences of files and folders.

Examples

Iterate over the files contained in a folder:

for file in try Folder(path: "MyFolder").files {
    print(file.name)
}

Rename all files contained in a folder:

try Folder(path: "MyFolder").files.enumerated().forEach { (index, file) in
    try file.rename(to: file.nameWithoutExtension + "\(index)")
}

Recursively iterate over all folders in a tree:

Folder.home.subfolders.recursive.forEach { folder in
    print("Name : \(folder.name), parent: \(folder.parent)")
}

Create, write and delete files and folders:

let folder = try Folder(path: "/users/john/folder")
let file = try folder.createFile(named: "file.json")
try file.write("{\"hello\": \"world\"}")
try file.delete()
try folder.delete()

Move all files in a folder to another:

let originFolder = try Folder(path: "/users/john/folderA")
let targetFolder = try Folder(path: "/users/john/folderB")
try originFolder.files.move(to: targetFolder)

Easy access to system folders:

Folder.current
Folder.root
Folder.library
Folder.temporary
Folder.home
Folder.documents

Installation

Files can be easily used in either a Swift script, a command line tool, or in an app for iOS, macOS, tvOS or Linux.

Using the Swift Package Manager (preferred)

To install Files for use in a Swift Package Manager-powered tool, script or server-side application, add Files as a dependency to your Package.swift file. For more information, please see the Swift Package Manager documentation.

.package(url: "https://github.com/JohnSundell/Files", from: "4.0.0")

Using CocoaPods or Carthage

Please refer to CocoaPods’ or Carthage’s own documentation for instructions on how to add dependencies using those tools.

As a file

Since all of Files is implemented within a single file, you can easily use it in any project by simply dragging the file Files.swift into your Xcode project.

Backstory

So, why was this made? As I've migrated most of my build tools and other scripts from languages like Bash, Ruby and Python to Swift, I've found myself lacking an easy way to deal with the file system. Sure, FileManager has a quite nice API, but it can be quite cumbersome to use because of its string-based nature, which makes simple scripts that move or rename files quickly become quite complex.

So, I made Files, to enable me to quickly handle files and folders, in an expressive way. And, since I love open source, I thought - why not package it up and share it with the community? :)

Questions or feedback?

Feel free to open an issue, or find me @johnsundell on Twitter.

files's People

Contributors

amzd avatar andreweades avatar artemnovichkov avatar bogren avatar clayellis avatar cojoj avatar garriguv avatar gwikiera avatar iainsmith avatar ikhsan avatar johnsundell avatar krzyzanowskim avatar larsjk avatar maximelm avatar mkj-is avatar onurersel avatar vfuc avatar yageek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

files's Issues

Add a badge for SwiftPM

Hi,
If your component is compatible with SwiftPM it's will be good to add this badge 🙂
SwiftPM Compatible

Adding file append

Thanks for Files! I wrote a script with it for a database validation task at work, had a very nice warm feeling being able to write Swift scripts 😄

I have a suggestion though, I was a bit surprised that Files's writes only override but no support for appending. Can we have file append? Similar to >> in bash.

I'm happy to create a PR, but I want to make sure if this sounds like a good addition. I'm thinking to add new methods func append(data: Data) throws and its string counterpart. Or, we could change write to func write(data: Data, shouldAppend: Bool = false) throws. I prefer the former though, let me know what you think.

Open PRs

Hey @JohnSundell 👋

The Files 4.0 release looks great, lots a solid improvements. Those improvements, however, have broken some of the open PRs that myself and others have written. I'm wondering whether it's worth the effort to update my PRs to work with 4.0 or whether those updates will be for naught. I'd love to see them merged, but don't want to waste any time.

If those PRs won't ever be merged, will you let me and others know so we can close them out?

Best,

Clay

Recursive renaming

I want to rename some folders recursively. For example, I have a folder structure:

Folder1
-Folder2

And I want to replace "Folder" word with "Project" word. When I use Folder.makeSubfolderSequence(recursive:includeHidden:) method, I can't rename Folder2 after Folder1 renaming, because it has old path - Folder1/Folder2. How I can deal with it? Maybe Item.rename(to:keepExtension:) method should update paths of subfolders?

Should .xcodeproj be gitignored?

What are your thoughts on removing the .xcodeproj from the repo in favor of generating it using swift package generate-xcodeproj?

I was going to submit a quick PR to update Files to Swift 4.2, but I noticed that the .xcodeproj is committed to the repo. I was going to gitignore it, since that seems recommended for SPM libraries, but I wanted to ask first.

Command application output wrong.

Code:

import Foundation
import Files

print(Folder.current.path)
print(Folder.home.path)

Xcode run or marathon run output is right.

/Users/xxx/Desktop/AppIcon/
/Users/xxx/

When I use command application: exec, output result is wrong.

/Users/xxx/
/Users/xxx/

iterating over subFolders in background

Hi I have next code:

   guard 
        let url = self.documentDirURL,
        let folder = try? Folder(path:url.path)
        else { return }

    DispatchQueue.global().async {
        folder.makeSubfolderSequence(recursive: true).forEach { folder in
            let list = folder.subfolders.filter({
                $0.extension == self.projectExtention && $0.nameExcludingExtension != self.excludeProject
            }).flatMap { $0.parent }
            urls += list
        }
    }

as you may see - it scans all subfolders for subfolders with specific extension excluding specific filename, and put their parent folders in a list.

But when I put it in a DispatchQueue.global().async {} block (as shown above) - it stops at

    while let parentReferenceRange = path.range(of: "../") {

line in method
func pathByFillingInParentReferences(for path: String, prependCurrentFolderPath: Bool = false) throws -> String {
with error: Thread 2: EXC_BAD_ACCESS (code=2, address=0x70000bf20ff0)

In a stack I see over 1000 calls of FileSystemIterator.next() , so I think it's a recursion.

What I did wrong and how to fix it?

Moving a folder using move(to:) creates an invalid path

  1. Create folder A
  2. Create folder B inside A
  3. Create folder C inside B
.
├─ A
   └─ B
       └─ C
  1. Move B to same level as A
.
├─ A
├─ B
   └─ C
  1. Try getting subfolder C with b.subfolder(named: "C") - error

Invalid path given: /Users/clay/.filesTest/BC/

This is because move(to:) removes the trailing / from the moved item's path. I'm submitting a PR that fixes this along with a test to catch this in the future.

ContainsFile API

When asking if a folder contains a file, the API is currently

let folder = try Folder(named: "Foo")
let contains: Bool = folder.containsFile(named: "NameOfFile")

Could we extend this to handle an actual file variable instead?

let file: File = ...
let folder = try Folder(named: "Foo")
let contains: Bool = folder.containsFile(file)

An interesting point to add: I was getting a false result when using name instead of nameExcludingExtension.

let name = file.nameExcludingExtension
let doesContain = folder.containsFile(named: name) // true
let name = file.name
let doesContain = folder.containsFile(named: name) // false

I can understand why this happens, but it was unexpected at first.

LocalizedError for errors

Often I use simple error handling in catch block:

print("\(error.localizedDescription)")

For pretty-printed error messages I add confirmation of LocalizedError protocol and implement localizedDescription property. What's your opinion about this approach? Why you don't use it?

File observer

Have you considered extending files with this?

let observer = try FileObserver(file: file)

observer.start {
    print("File was changed")
}

Some guy called @JohnSundell wrote this as a blog post 😜 #SwiftBySundell

class FileObserver {
    private let file: File
    private let queue: DispatchQueue
    private var source: DispatchSourceFileSystemObject?

    init(file: File) {
        self.file = file
        self.queue = DispatchQueue(label: "com.myapp.fileObserving")
    }

    func start(closure: @escaping () -> Void) {
        // We can only convert an NSString into a file system representation
        let path = (file.path as NSString)
        let fileSystemRepresentation = path.fileSystemRepresentation

        // Obtain a descriptor from the file system
        let fileDescriptor = open(fileSystemRepresentation, O_EVTONLY)

        // Create our dispatch source
        let source = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fileDescriptor,
                                                               eventMask: .write,
                                                               queue: queue)

        // Assign the closure to it, and resume it to start observing
        source.setEventHandler(handler: closure)
        source.resume()
        self.source = source
    }
}

Object-oriented implementations

Hi,

There seems to be a danger passing File around, by reference.

If I have the following

let file = try folder.file(named: "name.pdf")

And I pass it into the following function.

func store(_ file: File) throws

Moving forward, if I interact with this same File reference, it may no longer have a valid path. The store function above may perform moveItem, for example.

Idea 1

Perhaps we could create an alias?

Idea 2

Might it be worth making a distinction between a File that you know exists and a PotentialFile that hasn't been confirmed to exist? You see this kind of 'evaluate at last minute' mentality throughout Swift.

The same kind of mentality as

  • A slice of a string or array
  • Copy on write
  • An optional has .some or .none

I suppose we would have to handle a change in state, in both directions.

  • PotentialFile becoming File
  • File becoming PotentialFile

Idea 3

Perhaps we could harness this API?

FileReferenceURL

Check Resource Is Reachable

Root subfolder parent is not root

Hello,

let rootFolder = try Folder(path: "/")
let subfolder = rootFolder.subfolders.first
print(subfolder?.parent?.path)

Expected result: Optional("/")
Actual result: current working directory

Because of this bug, iterating over a folder parents triggers an inifinite loop.

I will submit a pull request with the fix.

The file or folder attribute may be nil

Hello, yes, my English is still so bad.

I recently tried to write a Cloud Document manager in Files, and I found that in a particular case, the loadModificationDate method might crash my application. My guess is that Cloud is downloading or synchronizing files.

I tried to find the reason, and finally found that try! fileManager.attributesOfItem(atPath: path) is likely to make a mistake, because at this time it may not be able to get any attributes at all. Or return attributes[FileAttributeKey.modificationDate] as! Date is wrong because it may not have this attribute.

So I think Files, the way to read file attributes, should be nil. This makes Files more rigorous..

Just like this:

    func loadModificationDate() -> Date? {
        let attributes = try? fileManager.attributesOfItem(atPath: path)
        return attributes?[FileAttributeKey.modificationDate] as? Date
    }

Rename Item API

Hi @JohnSundell ,

I'm enjoying the Files API and I'm glad I can help in any way. Even if my contributions are just discussion points that lead to potential pull requests from others.

I have, yet another, discussion point to raise. I hope you don't mind.

RenameItem

Unless I examine the source, it's not clear here if newName is name only or name + extension.

public func rename(to newName: String, keepExtension: Bool = true) throws

Further, I currently have a situation where the above API is inconvenient.

At the moment I'm unpacking a .pdf file from a CKAsset instance (CloudKit).

  1. After digging through the asset, I find a file named asdkfjkajsdkfha.owkheorhjdsf
  2. The file is stored in temp dir so I need to also move it.
  3. I want the file to have a different name, including a new .pdf extension.

Perhaps, we might want to have something like the following?

public func rename(to newName: String) throws

And maybe we can examine the name to see if it contains a "."

Do you think this is a valid issue and do you have any ideas on this?

add data to current file

Can yo add method to a file, which will no replace current content in the file but instead add a new content at the end on the file, please.
UPD. I see that community already done it. I tested the parallel branch with that functional. It work nice.

Can't load underlying module for 'Files'

My Xcode is 9.0.1, macOS 10.12.6. I used cocoapods(1.3.1) to integrate this library (1.12.0).
After that, I can see a new folder named "Files" under my "Pods" folder
When I tried to use "import Files", I got this compile error - "Can't load underlying module for 'Files'"
Can you help me to work it out? Thank you.

Building paths

For the longest time, I was under the impression that the following would throw, if the file (or folder) didn't exist.

let rulesDocument = try folder.file(named: "Rules.pdf")

The code seems to read: "Try to build a path to this file named Rules.pdf at this location."

Similar to how a browser might behave if you "try" a URL to nowhere.

Might it be worth making a distinction between a File that you know exists and a PotentialFile that hasn't been confirmed to exist? You see this kind of 'evaluate at last minute' mentality throughout Swift.

The same kind of mentality as

  • A slice of a string or array
  • Copy on write
  • An optional has .some or .none

newb question: why use strings instead of URLs?

Just wondering why Files uses strings instead of URLs?

Apple states:

Where possible, you should use instances of NSURL to represent paths—the operating system deals with URLs more efficiently than with string representations of paths.

Sorry if this "meta" question is out of place in the issue queue.

Cannot create new folders

Hey @JohnSundell

Love the work you're doing for the community!

I must be doing something stupid as I just cannot figure this out. I am testing Files, for the first time and followed the read me. So, I created a script with the very following:

let folder = try Folder(path: "/Users/robert/TestFolder")
let file = try folder.createFile(named: "file.json")
try file.write(string: "{\"hello\": \"world\"}")

What I expected

For a folder named 'TestFolder' to be created in the /Users/robert/ directory

What actually happened

I received the following error in Terminal

💥 Failed to run script
👉 Fatal error: Error raised at top level: Invalid path given: /Users/robert/TestFolder/: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang_Fall2018/swiftlang_Fall2018-1000.11.37.1/src/swift/stdlib/public/core/ErrorType.swift, line 191
/bin/bash: line 1: 21533 Illegal instruction: 4 /Users/robert/.marathon/Scripts/Cache/-Users-robert-Developer-MyApp-Scripts-TestScript/.build/debug/TestScript

Is there something I am misunderstanding or doing wrong here?

If I create the folder manually, the script works and adds the file.json to the folder. Its the folder creation that seems to be the issue.

Appreciate any insight / help into this

Copying, not moving

Hi, John! I want to copy existing file to another folder. How I can do it? I found only Item.move(to:) method, but I want to keep original file.

Folder.documents doesn't seem to work

Hey there! I'm wondering if I'm doing something wrong...

I've imported the library with swift package manager, and added (import Files) at the top of the swift file.

This is the build output:

Screen Shot 2019-10-05 at 8 36 46 AM

With Swift 5.1 and Xcode 11 GE

Documentation

Fully appreciate the work you have put in to this.

Humbly ask: Would be good to have a bit more documentation?

Struggled a bit with #57

Support glob

It would be great to have a way of getting all files in a folder using a glob pattern

let files = folder.glob("*.swift")

You could use Glibc.glob on Linux and Darwin.glob on Darwin

'NSWorkspace' is unavailable in Mac Catalyst

The new File.open() is only defined if AppKit can be imported. However, in a Mac Catalyst app, AppKit is available but NSWorkspace is not. This result in a compilation when adding Files.swift to a Mac Catalyst project.

Traversing folders seems to be a problem

let folders = Array(try Folder(path: "/xx/xx/").makeSubfolderSequence(recursive: true, includeHidden: false));

This is the swift code, I'm not running in the main thread main, and when my files are less, it's no problem. But if I have more files (about 150), there will be a problem, and Xcode directly locate the error.

CurrentChildIterator = childIteratorQueue.removeFirst()

I can't understand what this is, and I hope to be able to get the solution.

[Enquiry] Iterate over files with filetype in current directory

Dear John,

Thank you for the excellent lib. I am trying to learn how to use it. How can I iterate over all files with .md extension in the current folder?

I am stuck with:

for file in try Folder(path: Folder.current).files {
...
}

What is the proper use?

Thank you.

Heads-up: The next major version (5.0) will drop CocoaPods + Carthage support

Since the Swift Package Manager is now integrated into Xcode, all of my open source projects will stop supporting CocoaPods + Carthage starting with their next major version, which for Files will be 5.0. There's no set timeline for when Files 5.0 will be released, it might take months (or even years), but I just want to give all users who depend on Files using either of those two package managers a heads-up so that you can plan accordingly.

Possibility obtaining bytesWritten/totalBytesInFile

First of all thanks for a great job like "Files";

It would be great to obtain bytesWritten/totalBytesInFile.
This way it would be possible to control the traffic and implement progressIndicators or some other visual progress help.

Thanks for all.

Examples are buggy

Hello,

As a new to Swift developer, I found your great code when trying to manipulate files!

With my Swift knowledge being not so shiny so far, my problem is that your example codes generate errors in Xcode (Version 11.3.1), so they just cannot be build and run.

E.g you wrote:

Move all files in a folder to another:

let originFolder = try Folder(path: "/users/john/folderA")
let targetFolder = try Folder(path: "/users/john/folderB")
try originFolder.files.move(to: targetFolder)

Now Xcode gives me the same error at all the above lines:

Errors thrown from here are not handled.

So what is the proper coding to use Files?
E.g. what is the full code to move all files in a folder to another? Could you put it down it, please?

Thanks a lot in advance!
Devy

Changes in v4.0.0

Since upgrading to 4.0.0 and Xcode 11 two features seem to have disappeared.
file.copy used to return a reference to the new file.
Screenshot 2019-09-24 at 06 52 27

FileSystem().createFolderIfNeeded no longer exists.

Screenshot 2019-09-24 at 08 18 46

Are these depreciated?

Thanks

Capturing the underlying error.

The following explains that the folder 'clone' failed to delete.

Failed to delete item: Folder(name: clone, path: /Users/robertnash/.marathon/Scripts/Temp/https:--github.com-johnsundell-testdrive.git/clone/)
  - deleteFailed : Folder(name: clone, path: /Users/robertnash/.marathon/Scripts/Temp/https:--github.com-johnsundell-testdrive.git/clone/)

This is likely a permissions issue or some other trivial problem. But I'm more interested in how to find the underlying error.

What's your opinion on capturing the underlying error here ?

public func delete() throws {
    do {
        try fileManager.removeItem(atPath: path)
    } catch let underlyingError as NSError {
        throw OperationError.deleteFailed(self, underlyingError)
    } catch {
      throw OperationError.deleteFailed(self, _)
  }
}

Or something like that.

Taking inspiration from NSError, further investigation into an error could be done by unwrapping objects associated with keys like NSUnderlyingErrorKey or NSValidationMultipleErrorsError.

Documents Directory iOS

Hi,

There is API for the docs directory, but it's not public. Any reason for this?

The 'home' API seems to work as follows

let home = Folder.home.path
macOS: /Users/robertnash/
iOS: /Users/robertnash/Library/Developer/CoreSimulator/Devices/91BA8C3F-9B72-42AB-89D1-6401B183E5EB/data/Containers/Data/Application/

The docs directory is a little deeper.

let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
macOS: file:///Users/robertnash/Documents/
iOS: file:///Users/robertnash/Library/Developer/CoreSimulator/Devices/91BA8C3F-9B72-42AB-89D1-6401B183E5EB/data/Containers/Data/Application/A568FA48-5C29-4368-9123-008EAC5DA331/Documents/

Would be good to get the applicationSupportDirectory too

let storeDirectory = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
macOS: file:///Users/robertnash/Library/Application%20Support/
iOS: file:///Users/robertnash/Library/Developer/CoreSimulator/Devices/91BA8C3F-9B72-42AB-89D1-6401B183E5EB/data/Containers/Data/Application/A568FA48-5C29-4368-9123-008EAC5DA331/Library/Application Support/

Failing tests at Linux, possibly related to `FileSystemIterator`

Hello,

I was running the tests on official Swift Docker image while working on #5 (fed3fb9), and encountered three failures.

Here's the test log:

$ swift test
Compile Swift Module 'Files' (1 sources)
Compile Swift Module 'FilesTests' (1 sources)
Linking ./.build/debug/FilesPackageTests.xctest
Test Suite 'All tests' started at 18:19:24.811
Test Suite 'debug.xctest' started at 18:19:24.811
Test Suite 'FilesTests' started at 18:19:24.812
Test Case 'FilesTests.testCreatingAndDeletingFile' started at 18:19:24.812
Test Case 'FilesTests.testCreatingAndDeletingFile' passed (0.002 seconds).
Test Case 'FilesTests.testCreatingAndDeletingFolder' started at 18:19:24.814
Test Case 'FilesTests.testCreatingAndDeletingFolder' passed (0.001 seconds).
Test Case 'FilesTests.testRenamingFile' started at 18:19:24.815
Test Case 'FilesTests.testRenamingFile' passed (0.001 seconds).
Test Case 'FilesTests.testRenamingFileWithNameIncludingExtension' started at 18:19:24.815
Test Case 'FilesTests.testRenamingFileWithNameIncludingExtension' passed (0.001 seconds).
Test Case 'FilesTests.testReadingFileWithRelativePath' started at 18:19:24.816
Test Case 'FilesTests.testReadingFileWithRelativePath' passed (0.001 seconds).
Test Case 'FilesTests.testReadingFileWithTildePath' started at 18:19:24.816
Test Case 'FilesTests.testReadingFileWithTildePath' passed (0.001 seconds).
Test Case 'FilesTests.testRenamingFolder' started at 18:19:24.817
Test Case 'FilesTests.testRenamingFolder' passed (0.0 seconds).
Test Case 'FilesTests.testMovingFiles' started at 18:19:24.817
Test Case 'FilesTests.testMovingFiles' passed (0.001 seconds).
Test Case 'FilesTests.testEnumeratingFiles' started at 18:19:24.818
Test Case 'FilesTests.testEnumeratingFiles' passed (0.001 seconds).
Test Case 'FilesTests.testEnumeratingFilesIncludingHidden' started at 18:19:24.819
Test Case 'FilesTests.testEnumeratingFilesIncludingHidden' passed (0.001 seconds).
Test Case 'FilesTests.testEnumeratingFilesRecursively' started at 18:19:24.820
Test Case 'FilesTests.testEnumeratingFilesRecursively' passed (0.001 seconds).
Test Case 'FilesTests.testEnumeratingSubfolders' started at 18:19:24.821
Test Case 'FilesTests.testEnumeratingSubfolders' passed (0.001 seconds).
Test Case 'FilesTests.testEnumeratingSubfoldersRecursively' started at 18:19:24.822
/root/Files/Tests/FilesTests/FilesTests.swift:227: error: FilesTests.testEnumeratingSubfoldersRecursively : XCTAssertEqual failed: ("["1", "2", "1B", "1A", "2B", "2A"]") is not equal to ("["1", "2", "1A", "1B", "2A", "2B"]") - 
Test Case 'FilesTests.testEnumeratingSubfoldersRecursively' failed (0.001 seconds).
Test Case 'FilesTests.testFirstAndLastInFileSequence' started at 18:19:24.824
/root/Files/Tests/FilesTests/FilesTests.swift:238: error: FilesTests.testFirstAndLastInFileSequence : XCTAssertEqual failed: ("Optional("C")") is not equal to ("Optional("A")") - 
/root/Files/Tests/FilesTests/FilesTests.swift:239: error: FilesTests.testFirstAndLastInFileSequence : XCTAssertEqual failed: ("Optional("B")") is not equal to ("Optional("C")") - 
Test Case 'FilesTests.testFirstAndLastInFileSequence' failed (0.001 seconds).
Test Case 'FilesTests.testParent' started at 18:19:24.825
Test Case 'FilesTests.testParent' passed (0.001 seconds).
Test Case 'FilesTests.testRootFolderParentIsNil' started at 18:19:24.826
Test Case 'FilesTests.testRootFolderParentIsNil' passed (0.0 seconds).
Test Case 'FilesTests.testOpeningFileWithEmptyPathThrows' started at 18:19:24.826
Test Case 'FilesTests.testOpeningFileWithEmptyPathThrows' passed (0.0 seconds).
Test Case 'FilesTests.testDeletingNonExistingFileThrows' started at 18:19:24.827
Test Case 'FilesTests.testDeletingNonExistingFileThrows' passed (0.001 seconds).
Test Case 'FilesTests.testWritingDataToFile' started at 18:19:24.827
Test Case 'FilesTests.testWritingDataToFile' passed (0.012 seconds).
Test Case 'FilesTests.testWritingStringToFile' started at 18:19:24.840
Test Case 'FilesTests.testWritingStringToFile' passed (0.011 seconds).
Test Case 'FilesTests.testFileDescription' started at 18:19:24.851
Test Case 'FilesTests.testFileDescription' passed (0.001 seconds).
Test Case 'FilesTests.testFolderDescription' started at 18:19:24.852
Test Case 'FilesTests.testFolderDescription' passed (0.0 seconds).
Test Case 'FilesTests.testAccessingHomeFolder' started at 18:19:24.852
Test Case 'FilesTests.testAccessingHomeFolder' passed (0.0 seconds).
Test Case 'FilesTests.testNameExcludingExtensionWithLongFileName' started at 18:19:24.853
Test Case 'FilesTests.testNameExcludingExtensionWithLongFileName' passed (0.001 seconds).
Test Case 'FilesTests.testUsingCustomFileManager' started at 18:19:24.853
Test Case 'FilesTests.testUsingCustomFileManager' passed (0.001 seconds).
Test Case 'FilesTests.testAccessingDocumentFolder' started at 18:19:24.854
Test Case 'FilesTests.testAccessingDocumentFolder' passed (0.0 seconds).
Test Case 'FilesTests.testAccessingLibraryFolder' started at 18:19:24.854
Test Case 'FilesTests.testAccessingLibraryFolder' passed (0.0 seconds).
Test Suite 'FilesTests' failed at 18:19:24.854
	 Executed 27 tests, with 3 failures (0 unexpected) in 0.041 (0.041) seconds
Test Suite 'debug.xctest' failed at 18:19:24.855
	 Executed 27 tests, with 3 failures (0 unexpected) in 0.041 (0.041) seconds
Test Suite 'All tests' failed at 18:19:24.855
	 Executed 27 tests, with 3 failures (0 unexpected) in 0.041 (0.041) seconds

System information:

DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"
NAME="Ubuntu"
VERSION="16.04.1 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.1 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial

Swift version 3.0.2 (swift-3.0.2-RELEASE)

Folder.current.path showing build path, not project directory

Trying to locate the actual path where my project is located. for example, Users/userName/Desktop/porjectName.

however, when I run:
Folder.current.path
I get the following:
/Users/userName/Library/Developer/Xcode/DerivedData/projectName-ajpbrmlcmenwspeipndfoqpvyzce/Build/Products/Debug/

perhaps this is not how I get the actual directory of the project, if not, can someone please help to figure out how I can get the project directory as in "Users/userName/Desktop/porjectName."

I am using macOS commandLine tool btw,

thank you

Build errors

I added Files as dependency to sasha project. Everything worked fine, but now I have an error during build:

artemnovichkov@ sasha (master) $ swift build -c release -Xswiftc -static-stdlib
Compile Swift Module 'Swiftline' (28 sources)
Compile Swift Module 'Files' (1 sources)
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.apinotes:8:28: error: unknown key 'SwiftImportAsNonGeneric'
  SwiftImportAsNonGeneric: true
                           ^
<unknown>:0: error: could not build Objective-C module 'Foundation'
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.apinotes:8:28: error: unknown key 'SwiftImportAsNonGeneric'
  SwiftImportAsNonGeneric: true
                           ^
<unknown>:0: error: could not build Objective-C module 'Foundation'
<unknown>:0: error: build had 2 command failures
error: exit(1): /Applications/XcodeOLD.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-build-tool -f /Users/artemnovichkov/Documents/Projects/sasha/.build/release.yaml

What I do wrong? BTW, I use Xcode GM.

Proposal for subclassing Folder

When setting up a permanent directory structure for an App, it might be good to create dedicated subclasses of Folder for frequent use. Could the following code be inside a failable initialiser?

var rulesFolder: Folder {
    let folder = try! Folder(path: FileSystem().homeFolder.path)
    let documents = try! folder.subfolder(named: "Documents")
    return try! documents.createSubfolderIfNeeded(withName: "Rules")
}

RulesFolder.swift

init?() {
    do {
        // self = 
    } catch {
        return nil
    }
}

Make item kind checking public

In the current implementation there's a privet extension on FileManager with this cool method: itemKind(atPath path: String) -> FileSystem.Item.Kind?.
I'd love to see something like this being public, so it's easier to decide what we can do with this item.

We can make current implementation public by simply creating wrapper in FileSystem, but the problem is that this method relies of existence of this Item, so we can't simply say: itemKind(atPath: "fake/path/to/something.txt"), cause we'll get nil. We can use URL's method called hasDirectoryPath(), but strangely, Xcode shows warning, so I had to put #available check (which is kinda limiting...) as this API is available since iOS 9.

This kind of functionality can bring a nice and unified way of creating new Items at specific path, like: createItem(atPath: String) -> Item and createItemIfNeeded(atPath: String) -> Item.

What do you guys think about having a method just for checking the type of Item at specified path without requiring existence? I'm still not sure whether this isn't something beyond the scope of Files?

Folder(path: <path>) doesn't seem to work

A lot of the below code from the docs is causing me issue:

let folder = try Folder(path: "/users/john/folder")
let file = try folder.createFile(named: "file.json")
try file.write(string: "{\"hello\": \"world\"}")
try file.delete()
try folder.delete()

That first line gives:

Incorrect argument label in call (have 'path:', expected 'storage:')

As the init(path:) is in the parent protocol extension, I'm not sure quite how this works. This project is making me see there is a lot I don't know about swift.

Any help or input is appreciated.

Add convenience methods for reading Codable objects

Note: This will require Codable from Swift 3.2/4, which is why I'm not submitting a PR for this yet.

This is a proposal for adding convenience methods to use the Codable protocol, to allow reading a File directly to a decoded object type.

Example JSON Decodable convenience:

extension File {
	func readAsDecodedJSON<D: Decodable>(using decoder: JSONDecoder = .init()) throws -> D {
		let fileData = try read()
		return try decoder.decode(D.self, from: fileData)
	}
}

Example JSON Decodable call site:

let myObjectFile = File(path: ...)
let myObject: DecodedJSONObject = try myObjectFile.readAsDecodedJSON()

URL vs String

Discussion

Would it be better to return instances of URL wherever possible, instead of stringPath ?

URL objects are the preferred way to refer to local files. Most objects that read data from or write data to a file have methods that accept an NSURL object instead of a pathname as the file reference. For example, you can get the contents of a local file URL as an NSString object using the init(contentsOf:encoding:) initializer, or as an NSData object using the init(contentsOf:options:) initializer.

You can also use URLs for interapplication communication. In macOS, the NSWorkspace class provides the open(:) method to open a location specified by a URL. Similarly, in iOS, the UIApplication class provides the openURL(:) method.

Additionally, you can use URLs when working with pasteboards, as described in NSURL Additions Reference (part of the AppKit framework).

The NSURL class is “toll-free bridged” with its Core Foundation counterpart, CFURL. See Toll-Free Bridging for more information on toll-free bridging.

Failed Test in only Files-mac-OS Scheme

In Files-mac-OS, 40 / 43 tests failed due to the following error,

Error Domain=NSCocoaErrorDomain Code=513 "“AppTranslocation” couldn’t be removed because you don’t have permission to access it." UserInfo={NSFilePath=/var/folders/rz/_1zd0tj50rdbrdpy47j1s6j40000gn/T/AppTranslocation/, NSUserStringVariant=(
    Remove
), NSUnderlyingError=0x101953f10 {Error Domain=NSPOSIXErrorDomain Code=66 "Directory not empty"}}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.