mirror of
https://github.com/tsolomko/SWCompression.git
synced 2026-06-23 14:56:41 +00:00
Merge branch 'release-4.6.0' into develop
This commit is contained in:
+2
-2
@@ -3,11 +3,11 @@ sourcekitten_sourcefile: docs.json
|
||||
clean: false
|
||||
author: Timofey Solomko
|
||||
module: SWCompression
|
||||
module_version: 4.5.11
|
||||
module_version: 4.6.0
|
||||
copyright: '© 2021 Timofey Solomko'
|
||||
readme: README.md
|
||||
github_url: https://github.com/tsolomko/SWCompression
|
||||
github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.5.11
|
||||
github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.6.0
|
||||
theme: fullwidth
|
||||
|
||||
custom_categories:
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# Changelog
|
||||
|
||||
## 4.6.0
|
||||
|
||||
- Swift 4.2 is no longer supported.
|
||||
- Minimum iOS deployment version (when installed via CocoaPods or Carthage) is now 9.0.
|
||||
- Increased the lowest required version of BitByteData dependency to 2.0.
|
||||
- Added the `TarContainer.create(from:force:)` function which allows to specify TAR format.
|
||||
- It is now possible to create TAR containers of GNU, ustar (POSIX), and pre-POSIX formats.
|
||||
- The `TarContainer.create(from:)` function (alongside with the newly added function) no longer throws.
|
||||
- The `TarCreateError.utf8NonEncodable` error is now never thrown.
|
||||
- Handling of truncated TAR containers should now be more consistent.
|
||||
- Previously introduced check for truncated containers now throws the `TarError.tooSmallFileIsPassed` error instead
|
||||
of `TarError.wrongField`.
|
||||
- Documentation has been updated:
|
||||
- Adjusted documentation of the `TarEntryInfo` properties to account for other formats used in creation of a
|
||||
container.
|
||||
- Adjusted documentation of the `TarError.tooSmallFileIsPassed` error to mention its use in all situations when
|
||||
truncated data is encountered.
|
||||
- swcomp changes:
|
||||
- `zip -i` command now prints entry comments only if they are not empty.
|
||||
- Slight grammatical improvements to the help messages of swcomp.
|
||||
|
||||
## 4.5.11
|
||||
|
||||
- Fixed a crash when processing a truncated TAR file.
|
||||
|
||||
@@ -1 +1 @@
|
||||
github "tsolomko/BitByteData" "2.0.0-test.2"
|
||||
github "tsolomko/BitByteData" ~> 2.0.0
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ let package = Package(
|
||||
// .package(url: "https://github.com/jakeheis/SwiftCLI",
|
||||
// from: "5.2.0"),
|
||||
.package(url: "https://github.com/tsolomko/BitByteData",
|
||||
from: "2.0.0-test.2"),
|
||||
from: "2.0.0"),
|
||||
],
|
||||
targets: [
|
||||
// SWCOMP: Uncomment the lines below to build swcomp example program.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# SWCompression
|
||||
|
||||
[](https://developer.apple.com/swift/)
|
||||
[](https://developer.apple.com/swift/)
|
||||
[](https://raw.githubusercontent.com/tsolomko/SWCompression/master/LICENSE)
|
||||
[](https://travis-ci.com/tsolomko/SWCompression)
|
||||
@@ -10,7 +9,7 @@ A framework with (de)compression algorithms and functions for working with vario
|
||||
|
||||
## What is this?
|
||||
|
||||
SWCompression — is a framework with a collection of functions for:
|
||||
SWCompression is a framework with a collection of functions for:
|
||||
|
||||
1. Decompression (and sometimes compression) using different algorithms.
|
||||
2. Reading (and sometimes writing) archives of different formats.
|
||||
@@ -34,7 +33,7 @@ Also, SWCompression is _written with Swift only._
|
||||
|
||||
## Installation
|
||||
|
||||
SWCompression can be integrated into your project using Swift Package Manager, CocoaPods or Carthage.
|
||||
SWCompression can be integrated into your project using Swift Package Manager, CocoaPods, or Carthage.
|
||||
|
||||
### Swift Package Manager
|
||||
|
||||
@@ -47,7 +46,7 @@ let package = Package(
|
||||
name: "PackageName",
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/tsolomko/SWCompression.git",
|
||||
from: "4.5.0")
|
||||
from: "4.6.0")
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
@@ -62,7 +61,7 @@ More details you can find in [Swift Package Manager's Documentation](https://git
|
||||
|
||||
### CocoaPods
|
||||
|
||||
Add `pod 'SWCompression', '~> 4.5'` and `use_frameworks!` lines to your Podfile.
|
||||
Add `pod 'SWCompression', '~> 4.6'` and `use_frameworks!` lines to your Podfile.
|
||||
|
||||
To complete installation, run `pod install`.
|
||||
|
||||
@@ -105,19 +104,17 @@ BZip2 and LZMA/LZMA2 support).
|
||||
|
||||
### Carthage
|
||||
|
||||
__Important:__ Only Swift 5.x is supported when installing SWCompression via Carthage.
|
||||
|
||||
Add to your Cartfile `github "tsolomko/SWCompression" ~> 4.5`.
|
||||
Add to your Cartfile `github "tsolomko/SWCompression" ~> 4.6`.
|
||||
|
||||
Then:
|
||||
|
||||
1. If you use Xcode 12 or later you should run `carthage update --use-xcframeworks --no-use-binaries`. After that drag
|
||||
and drop both `SWCompression.xcframework` and `BitByteData.xcframework` files from from the `Carthage/Build/` directory
|
||||
into the "Frameworks, Libraries, and Embedded Content" section of your target's "General" tab in Xcode.
|
||||
1. If you use Xcode 12 or later you should run `carthage update --use-xcframeworks`. After that drag and drop both
|
||||
`SWCompression.xcframework` and `BitByteData.xcframework` files from from the `Carthage/Build/` directory into the
|
||||
"Frameworks, Libraries, and Embedded Content" section of your target's "General" tab in Xcode.
|
||||
|
||||
2. If you use Xcode 11 or earlier you should run `carthage update --no-use-binaries`. After that drag and drop both
|
||||
`SWCompression.framework` and `BitByteData.framework` files from from the `Carthage/Build/<platform>/` directory into the
|
||||
"Embedded Binaries" section of your target's "General" tab in Xcode.
|
||||
2. If you use Xcode 11 or earlier you should run `carthage update`. After that drag and drop both
|
||||
`SWCompression.framework` and `BitByteData.framework` files from from the `Carthage/Build/<platform>/` directory into
|
||||
the "Embedded Binaries" section of your target's "General" tab in Xcode.
|
||||
|
||||
For Xcode 12 or later you can currently also use the
|
||||
[xconfig workaround](https://github.com/Carthage/Carthage/blob/master/Documentation/Xcode12Workaround.md).
|
||||
@@ -165,7 +162,8 @@ do {
|
||||
### Documentation
|
||||
|
||||
Every function or type of SWCompression's public API is documented. This documentation can be found at its own
|
||||
[website](http://tsolomko.github.io/SWCompression).
|
||||
[website](http://tsolomko.github.io/SWCompression) or via a slightly shorter link:
|
||||
[swcompression.tsolomko.me](http://swcompression.tsolomko.me)
|
||||
|
||||
### Sophisticated example
|
||||
|
||||
@@ -175,7 +173,8 @@ you need to uncomment several lines in "Package.swift" and run `swift build -c r
|
||||
## Contributing
|
||||
|
||||
Whether you find a bug, have a suggestion, idea, feedback or something else, please
|
||||
[create an issue](https://github.com/tsolomko/SWCompression/issues) on GitHub.
|
||||
[create an issue](https://github.com/tsolomko/SWCompression/issues) on GitHub. If you have any questions, you can ask
|
||||
them on the [Discussions](https://github.com/tsolomko/SWCompression/discussions) page.
|
||||
|
||||
In the case of a bug, it will be especially helpful if you attach a file (archive, etc.) that caused the bug to occur.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
s.name = "SWCompression"
|
||||
s.version = "4.5.11"
|
||||
s.version = "4.6.0"
|
||||
s.summary = "A framework with functions for working with compression, archives and containers."
|
||||
|
||||
s.description = "A framework with (de)compression algorithms and functions for processing various archives and containers."
|
||||
@@ -22,7 +22,7 @@ Pod::Spec.new do |s|
|
||||
|
||||
s.swift_versions = ["5"]
|
||||
|
||||
s.dependency "BitByteData", "~> 1.4.4"
|
||||
s.dependency "BitByteData", "~> 2.0"
|
||||
|
||||
s.subspec "Deflate" do |sp|
|
||||
sp.source_files = "Sources/{Deflate/*,Common/*,Common/CodingTree/*}.swift"
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.5.11</string>
|
||||
<string>4.6.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>78</string>
|
||||
<string>80</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2021 Timofey Solomko</string>
|
||||
</dict>
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.5.11</string>
|
||||
<string>4.6.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>78</string>
|
||||
<string>80</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1270,7 +1270,7 @@
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CURRENT_PROJECT_VERSION = 78;
|
||||
CURRENT_PROJECT_VERSION = 80;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@@ -1351,7 +1351,7 @@
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CURRENT_PROJECT_VERSION = 78;
|
||||
CURRENT_PROJECT_VERSION = 80;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
"FRAMEWORK_SEARCH_PATHS[sdk=appletvos*]" = (
|
||||
@@ -1412,7 +1412,7 @@
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 78;
|
||||
DYLIB_CURRENT_VERSION = 80;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = SWCompression.xcodeproj/SWCompression.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
@@ -1439,7 +1439,7 @@
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 78;
|
||||
DYLIB_CURRENT_VERSION = 80;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = SWCompression.xcodeproj/SWCompression.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
|
||||
@@ -29,6 +29,9 @@ extension Data {
|
||||
}
|
||||
|
||||
// Base-256 encoding.
|
||||
// As long as we have at least 8 bytes for our value, conversion to base-256 will always succeed, since (64-bit)
|
||||
// Int.max neatly fits into 8 bytes of 256-base encoding.
|
||||
assert(maxLength >= 8 && Int.bitWidth <= 64)
|
||||
var buffer = Array(repeating: 0 as UInt8, count: maxLength)
|
||||
for i in stride(from: maxLength - 1, to: 0, by: -1) {
|
||||
buffer[i] = UInt8(truncatingIfNeeded: value & 0xFF)
|
||||
@@ -50,7 +53,6 @@ extension Data {
|
||||
/// This should work in the same way as `String.padding(toLength: length, withPad: "\0", startingAt: 0)`.
|
||||
@inline(__always)
|
||||
private func zeroPad(_ length: Int) -> Data {
|
||||
// TODO: Maybe this should modify self
|
||||
var out = length < self.count ? self.prefix(upTo: length) : self
|
||||
out.append(Data(count: length - out.count))
|
||||
return out
|
||||
|
||||
@@ -47,11 +47,10 @@ public class TarContainer: Container {
|
||||
} else if specialEntryType == .longName || specialEntryType == .longLinkName {
|
||||
return .gnu
|
||||
}
|
||||
case .entryInfo(let info, _):
|
||||
// TODO: Probably this case (depending on how info.format is set) is already covered by the above.
|
||||
switch info.format {
|
||||
case .entryInfo(_, _, let headerFormat):
|
||||
switch headerFormat {
|
||||
case .pax:
|
||||
return .pax
|
||||
fatalError("Unexpected format of basic header: pax")
|
||||
case .gnu:
|
||||
return .gnu
|
||||
case .ustar:
|
||||
@@ -84,7 +83,24 @@ public class TarContainer: Container {
|
||||
return create(from: entries, force: .pax)
|
||||
}
|
||||
|
||||
public static func create(from entries: [TarEntry], force format: TarContainer.Format) -> Data {
|
||||
/**
|
||||
Creates a new TAR container with `entries` as its content and generates its `Data` using the specified `format`.
|
||||
|
||||
This function forces the usage of the `format`, meaning that certain properties about the `entries` may be missing
|
||||
from the resulting container data if the chosen format doesn't support certain features. For example, relatively
|
||||
long names (and linknames) will be truncated if the `.ustar` or `.prePosix` format is specified.
|
||||
|
||||
It is highly recommended to use the `TarContainer.create(from:)` function (or use the `.pax` format) to ensure the
|
||||
best representation of the `entries` in the output. Other (non-PAX) formats should only be used if you have a
|
||||
specific need for them and you understand limitations of those formats.
|
||||
|
||||
- Parameter entries: TAR entries to store in the container.
|
||||
- Parameter force: For the usage of the specified format.
|
||||
|
||||
- SeeAlso: `TarEntryInfo` properties documenation to see how their values are connected with the specific TAR
|
||||
format used during container creation.
|
||||
*/
|
||||
public static func create(from entries: [TarEntry], force format: TarContainer.Format) -> Data {
|
||||
// The general strategy is as follows. For each entry we:
|
||||
// 1. Create special entries if required by the entry's info and if supported by the format.
|
||||
// 2. For each special entry we create a TarHeader.
|
||||
@@ -94,17 +110,17 @@ public class TarContainer: Container {
|
||||
// Every time we append something to the output we also make sure that the data is padded to 512 byte-long blocks.
|
||||
|
||||
// In theory if the counters are big enough, the names of the special entries can become long enough to cause
|
||||
// problems (truncation, etc.). In practice, the largest possible counter (Int.max) is 19 symbols long, which
|
||||
// problems (truncation, etc.). In practice, the largest possible counter (UInt.max) is 20 symbols long, which
|
||||
// when combined with the longest used special entry name can never cause any problems, since it is still
|
||||
// shorter then 99 symbols available in the "name" field of the TAR header.
|
||||
// However, if in the distant future Int.max becomes large enough to cause any issues (e.g. 128-bit and higher
|
||||
// integers), the following check will catch it.
|
||||
assert(String(Int.max).count < 100 - 19) // "SWC_LocalPaxHeader_".count == 19
|
||||
assert(String(UInt.max).count < 100 - 19) // "SWC_LocalPaxHeader_".count == 19
|
||||
// We also use &+ when incrementing counters to prevent integer overflow crashes: we rather deal with the special
|
||||
// entries having the same name, then crash the program.
|
||||
var longNameCounter = 0
|
||||
var longLinkNameCounter = 0
|
||||
var localPaxHeaderCounter = 0
|
||||
// entries having repeating names, then crash the program.
|
||||
var longNameCounter = 0 as UInt
|
||||
var longLinkNameCounter = 0 as UInt
|
||||
var localPaxHeaderCounter = 0 as UInt
|
||||
|
||||
var out = Data()
|
||||
for entry in entries {
|
||||
@@ -178,7 +194,7 @@ public class TarContainer: Container {
|
||||
switch result {
|
||||
case .specialEntry:
|
||||
continue parsingLoop
|
||||
case .entryInfo(let info, let blockStartIndex):
|
||||
case .entryInfo(let info, let blockStartIndex, _):
|
||||
if info.type == .directory {
|
||||
var entry = TarEntry(info: info, data: nil)
|
||||
entry.info.size = 0
|
||||
@@ -230,7 +246,7 @@ public class TarContainer: Container {
|
||||
switch result {
|
||||
case .specialEntry:
|
||||
continue parsingLoop
|
||||
case .entryInfo(let info, _):
|
||||
case .entryInfo(let info, _, _):
|
||||
entries.append(info)
|
||||
case .truncated:
|
||||
// We don't have an error with a more suitable name.
|
||||
|
||||
@@ -167,8 +167,6 @@ public struct TarEntryInfo: ContainerEntryInfo {
|
||||
*/
|
||||
public var unknownExtendedHeaderRecords: [String: String]?
|
||||
|
||||
let format: TarContainer.Format
|
||||
|
||||
/**
|
||||
Initializes the entry's info with its name and type.
|
||||
|
||||
@@ -181,8 +179,6 @@ public struct TarEntryInfo: ContainerEntryInfo {
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.linkName = ""
|
||||
// These properties are only used when entry is loaded from the container.
|
||||
self.format = .pax
|
||||
}
|
||||
|
||||
init(_ header: TarHeader, _ global: TarExtendedHeader?, _ local: TarExtendedHeader?,
|
||||
@@ -215,16 +211,6 @@ public struct TarEntryInfo: ContainerEntryInfo {
|
||||
self.deviceMajorNumber = header.deviceMajorNumber
|
||||
self.deviceMinorNumber = header.deviceMinorNumber
|
||||
|
||||
if local != nil || global != nil {
|
||||
self.format = .pax
|
||||
} else if header.format == .gnu || longName != nil || longLinkName != nil {
|
||||
self.format = .gnu
|
||||
} else if header.format == .ustar {
|
||||
self.format = .ustar
|
||||
} else {
|
||||
self.format = .prePosix
|
||||
}
|
||||
|
||||
// Set `name` and `linkName` to values from PAX or GNU format if possible.
|
||||
var name = header.name
|
||||
if let prefix = header.prefix, prefix != "" {
|
||||
|
||||
@@ -157,7 +157,7 @@ struct TarHeader {
|
||||
init(_ info: TarEntryInfo) {
|
||||
self.name = info.name
|
||||
self.type = .normal(info.type)
|
||||
self.size = info.size ?? 0 // TODO: tarInt(...) may not work as expected for 0 instead of nil.
|
||||
self.size = info.size ?? 0
|
||||
self.atime = info.accessTime
|
||||
self.ctime = info.creationTime
|
||||
self.mtime = info.modificationTime
|
||||
@@ -169,7 +169,7 @@ struct TarHeader {
|
||||
self.deviceMajorNumber = info.deviceMajorNumber
|
||||
self.deviceMinorNumber = info.deviceMinorNumber
|
||||
self.linkName = info.linkName
|
||||
self.format = .pax // TODO: If TarEntryInfo.format is not removed than this should be `info.format`.
|
||||
self.format = .pax
|
||||
// Unused if header was created using this initializer.
|
||||
self.blockStartIndex = -1
|
||||
}
|
||||
@@ -237,7 +237,6 @@ struct TarHeader {
|
||||
// ustar and pax formats contain prefix field.
|
||||
if format == .ustar || format == .pax {
|
||||
// Splitting the name property into the name and prefix fields.
|
||||
// TODO: Review
|
||||
let nameData = Data(self.name.utf8)
|
||||
if nameData.count > 100 {
|
||||
var maxPrefixLength = nameData.count
|
||||
@@ -252,6 +251,8 @@ struct TarHeader {
|
||||
|
||||
// Looking for the last slash in the potential prefix. -1 if not found.
|
||||
// It determines the end of the actual prefix and the beginning of the updated name field.
|
||||
// This way of finding the last slash works, since there is no other Unicode character that contains
|
||||
// the 0x2F byte when encoded in UTF-8.
|
||||
let lastPrefixSlashIndex = nameData.prefix(upTo: maxPrefixLength)
|
||||
.range(of: Data([0x2f]), options: .backwards)?.lowerBound ?? -1
|
||||
let updatedNameLength = nameData.count - lastPrefixSlashIndex - 1
|
||||
|
||||
@@ -15,7 +15,7 @@ struct TarParser {
|
||||
case eofMarker
|
||||
case finished
|
||||
case specialEntry(TarHeader.SpecialEntryType)
|
||||
case entryInfo(TarEntryInfo, Int)
|
||||
case entryInfo(TarEntryInfo, Int, TarContainer.Format)
|
||||
}
|
||||
|
||||
private let reader: LittleEndianByteReader
|
||||
@@ -70,7 +70,7 @@ struct TarParser {
|
||||
lastLocalExtendedHeader = nil
|
||||
longName = nil
|
||||
longLinkName = nil
|
||||
return .entryInfo(info, header.blockStartIndex)
|
||||
return .entryInfo(info, header.blockStartIndex, header.format)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import Foundation
|
||||
import SWCompression
|
||||
import SwiftCLI
|
||||
|
||||
let cli = CLI(name: "swcomp", version: "4.5.11",
|
||||
let cli = CLI(name: "swcomp", version: "4.6.0",
|
||||
description: """
|
||||
swcomp - a small command-line client for SWCompression framework.
|
||||
Serves as an example of SWCompression usage.
|
||||
|
||||
+21
-19
@@ -219,27 +219,29 @@ class TarCreateTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testBigUid() throws {
|
||||
let uid = (1 << 32) - 1
|
||||
var info = TarEntryInfo(name: "file.txt", type: .regular)
|
||||
info.ownerID = uid
|
||||
// Int.max tests that base-256 encoding of integer fields works in the edge case.
|
||||
for uid in [(1 << 32) - 1, Int.max] {
|
||||
var info = TarEntryInfo(name: "file.txt", type: .regular)
|
||||
info.ownerID = uid
|
||||
|
||||
let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())])
|
||||
XCTAssertEqual(try TarContainer.formatOf(container: containerData), .pax)
|
||||
let newInfo = try TarContainer.open(container: containerData)[0].info
|
||||
let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())])
|
||||
XCTAssertEqual(try TarContainer.formatOf(container: containerData), .pax)
|
||||
let newInfo = try TarContainer.open(container: containerData)[0].info
|
||||
|
||||
XCTAssertEqual(newInfo.name, "file.txt")
|
||||
XCTAssertEqual(newInfo.type, .regular)
|
||||
XCTAssertEqual(newInfo.size, 0)
|
||||
XCTAssertEqual(newInfo.ownerID, uid)
|
||||
XCTAssertEqual(newInfo.linkName, "")
|
||||
XCTAssertEqual(newInfo.ownerUserName, "")
|
||||
XCTAssertEqual(newInfo.ownerGroupName, "")
|
||||
XCTAssertNil(newInfo.permissions)
|
||||
XCTAssertNil(newInfo.groupID)
|
||||
XCTAssertNil(newInfo.accessTime)
|
||||
XCTAssertNil(newInfo.creationTime)
|
||||
XCTAssertNil(newInfo.modificationTime)
|
||||
XCTAssertNil(newInfo.comment)
|
||||
XCTAssertEqual(newInfo.name, "file.txt")
|
||||
XCTAssertEqual(newInfo.type, .regular)
|
||||
XCTAssertEqual(newInfo.size, 0)
|
||||
XCTAssertEqual(newInfo.ownerID, uid)
|
||||
XCTAssertEqual(newInfo.linkName, "")
|
||||
XCTAssertEqual(newInfo.ownerUserName, "")
|
||||
XCTAssertEqual(newInfo.ownerGroupName, "")
|
||||
XCTAssertNil(newInfo.permissions)
|
||||
XCTAssertNil(newInfo.groupID)
|
||||
XCTAssertNil(newInfo.accessTime)
|
||||
XCTAssertNil(newInfo.creationTime)
|
||||
XCTAssertNil(newInfo.modificationTime)
|
||||
XCTAssertNil(newInfo.comment)
|
||||
}
|
||||
}
|
||||
|
||||
func testGnuLongName() throws {
|
||||
|
||||
Reference in New Issue
Block a user