Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 2 additions & 67 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,67 +1,2 @@
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore

## Build generated
build/
DerivedData/

## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/

## Other
*.moved-aside
*.xcuserstate
*.xcscmblueprint

## Obj-C/Swift specific
*.hmap
*.ipa
*.dSYM.zip
*.dSYM

## Playgrounds
timeline.xctimeline
playground.xcworkspace

# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
.build/
.swiftpm/

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/

# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts

Carthage/Build

# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
# macOS
.DS_Store
7 changes: 7 additions & 0 deletions .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>Files.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
</dict>
</plist>
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.0
// swift-tools-version:6.2

/**
* Files
Expand Down
40 changes: 35 additions & 5 deletions Sources/Files.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ public protocol Location: Equatable, CustomStringConvertible {
init(storage: Storage<Self>)
}

/// Protocol adopted by locations that represent files.
public protocol FileLocation: Location {}

public extension FileLocation {
/// The file size, in bytes. Returns `0` if the size couldn't be determined.
var size: UInt64 {
let number = storage.attributes[.size] as? NSNumber
return number?.uint64Value ?? 0
}
}

public extension Location {
static func ==(lhs: Self, rhs: Self) -> Bool {
return lhs.storage.path == rhs.storage.path
Expand Down Expand Up @@ -79,6 +90,19 @@ public extension Location {
return components.dropLast().joined()
}

/// Disco: The name of the location, excluding its `extension`.
var baseName: String {
get {
let components = name.split(separator: ".")
guard components.count > 1 else { return name }
return components.dropLast().joined()
}
set {
try? rename(to: newValue, keepExtension: true)
}
}


/// The file extension of the item at the location.
var `extension`: String? {
let components = name.split(separator: ".")
Expand Down Expand Up @@ -364,7 +388,7 @@ private extension Storage where LocationType == Folder {
/// Type that represents a file on disk. You can either reference an existing
/// file by initializing an instance with a `path`, or you can create new files
/// using the various `createFile...` APIs available on `Folder`.
public struct File: Location {
public struct File: Location, FileLocation {
public let storage: Storage<File>

public init(storage: Storage<File>) {
Expand Down Expand Up @@ -406,9 +430,15 @@ public extension File {
func append(_ data: Data) throws {
do {
let handle = try FileHandle(forWritingTo: url)
handle.seekToEndOfFile()
handle.write(data)
handle.closeFile()
if #available(macOS 10.15.4, *) {
_ = try handle.seekToEnd()
try handle.write(contentsOf: data)
try handle.close()
} else {
handle.seekToEndOfFile()
handle.write(data)
handle.closeFile()
}
} catch {
throw WriteError(path: path, reason: .writeFailed(error))
}
Expand Down Expand Up @@ -466,7 +496,7 @@ import AppKit
public extension File {
/// Open the file.
func open() {
NSWorkspace.shared.openFile(path)
NSWorkspace.shared.open(url)
}
}

Expand Down
8 changes: 8 additions & 0 deletions Tests/FilesTests/FilesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,14 @@ class FilesTests: XCTestCase {
try assert(nonIntFile.readAsInt(), throwsErrorOfType: ReadError.self)
}
}

func testFileSize() {
performTest {
let data = Data("Hello".utf8)
let file = try folder.createFile(named: "size.txt", contents: data)
XCTAssertEqual(file.size, UInt64(data.count))
}
}

func testRenamingFile() {
performTest {
Expand Down