From e329e0c2aa6c0453ec6a3d91c6a65d1da9487953 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 1 May 2019 19:18:10 +0300 Subject: [PATCH 01/97] Migrate (somewhat) to Swift 5.0 I am unable to perform automatic migration using Xcode 10.2, since my macbook doesn't support that version of Xcode, so I installed Swift 5.0 toolchain and performed most of the steps manually. --- .swift-version | 2 +- .travis.yml | 4 ++-- Package.swift | 4 ++-- SWCompression.podspec | 2 +- SWCompression.xcodeproj/project.pbxproj | 6 ++---- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.swift-version b/.swift-version index bf77d549..819e07a2 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.2 +5.0 diff --git a/.travis.yml b/.travis.yml index a70db7bf..f99967d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ jobs: - stage: test language: swift os: osx - osx_image: xcode10.1 + osx_image: xcode10.2 before_install: - brew update install: @@ -26,7 +26,7 @@ jobs: if: tag IS present language: generic os: osx - osx_image: xcode10.1 + osx_image: xcode10.2 env: secure: iavIkrus2Xd3b086nz2srMGl52yqzLuCdhyEAhMODVqkzqMQ17s10y1TNb+vkepd0HgxI9j57d5X7tfChjWuWDwE2hZKjr/Kx2DfiUr1AKQD6ymuGrq/0Vv6yL9dfPU8goFArcrsBcyVKczLtTuLCKL498ZqokkQc/3kGvzW74lv+z410MfHS9/tvToO/yXJckL6qJ2XBAiElfOO0rEkllTeCo6N3bjcHZ2o7PE0K+CHYxwNKj0TmPmuNWZ3U4fzoWzkk01re1C1l5cpSb20g+2aGyi0yYX+PomX7fIIqNq9vmmyoeNdr35yqoQv/0zFeFnps83NKmZLAjSUhiUdhlbuBLBE+w8544LOaZnMDlFmpDjgyaVnRrOh0NrBB1FwU48aGfX5ljRQmk/07FTEUjvwvGGoOpz8lrLZi148FMHEospL3Sf7d8K+Q9WdtLTGk7HCnbOVcxS6oB/SWF/Cj6n5wu+EI1floBaZEsNPR40Gd4eM/Ik/E3lDrZThGDCWQsao981wm7IfEDBR1nuMME8gpZINFANNS1+5miFaGdTnDTp4Yd5MGEFZm+K8x+TG1891NwNH1ZmKXlypJXiUzvSjbh2ViNJGekdQj9q2gj2ZFlCfHJ05adwJ4w9qRuF00HpAOD6At6EnsjDXFJeTZS5dj8fi2YsU9or8KfTFoNY= addons: diff --git a/Package.swift b/Package.swift index 15c77670..6b4303b5 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:4.0 +// swift-tools-version:5.0 import PackageDescription let package = Package( @@ -28,5 +28,5 @@ let package = Package( path: "Sources", sources: ["Common", "7-Zip", "BZip2", "Deflate", "GZip", "LZMA", "LZMA2", "TAR", "XZ", "ZIP", "Zlib"]), ], - swiftLanguageVersions: [4] + swiftLanguageVersions: [.v5] ) diff --git a/SWCompression.podspec b/SWCompression.podspec index e00a0841..23e3e9a4 100644 --- a/SWCompression.podspec +++ b/SWCompression.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.tvos.deployment_target = "9.0" s.watchos.deployment_target = "2.0" - s.swift_version = "4.2" + s.swift_version = "5.0" s.dependency "BitByteData", "~> 1.4.0" diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index d524c248..a1b004c0 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -1265,6 +1265,7 @@ SDKROOT = macosx; SUPPORTED_PLATFORMS = "macosx watchsimulator iphonesimulator appletvsimulator watchos appletvos iphoneos"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TVOS_DEPLOYMENT_TARGET = 9.0; VERSIONING_SYSTEM = "apple-generic"; WATCHOS_DEPLOYMENT_TARGET = 2.0; @@ -1319,6 +1320,7 @@ SDKROOT = macosx; SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_VERSION = 5.0; TVOS_DEPLOYMENT_TARGET = 9.0; VERSIONING_SYSTEM = "apple-generic"; WATCHOS_DEPLOYMENT_TARGET = 2.0; @@ -1349,7 +1351,6 @@ PRODUCT_BUNDLE_IDENTIFIER = me.tsolomko.SWCompression; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -1377,7 +1378,6 @@ PRODUCT_BUNDLE_IDENTIFIER = me.tsolomko.SWCompression; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.2; }; name = Release; }; @@ -1395,7 +1395,6 @@ ); PRODUCT_BUNDLE_IDENTIFIER = me.tsolomko.TestSWCompression; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -1413,7 +1412,6 @@ ); PRODUCT_BUNDLE_IDENTIFIER = me.tsolomko.TestSWCompression; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.2; }; name = Release; }; From db82490ed8f0b73cfbee3ddeba956cfc26257e0f Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 1 May 2019 19:30:48 +0300 Subject: [PATCH 02/97] Replace the usage of the deprecated Data(bytes:) initializer --- Sources/7-Zip/7zContainer.swift | 4 ++-- Sources/BZip2/BZip2.swift | 2 +- Sources/Common/DeltaFilter.swift | 2 +- Sources/Deflate/Deflate.swift | 2 +- Sources/GZip/GzipArchive.swift | 6 +++--- Sources/LZMA/LZMA.swift | 2 +- Sources/LZMA2/LZMA2.swift | 2 +- Sources/TAR/TarEntryInfo.swift | 4 ++-- Sources/ZIP/ZipContainer.swift | 2 +- Sources/ZIP/ZipEndOfCentralDirectory.swift | 2 +- Sources/Zlib/ZlibArchive.swift | 4 ++-- Tests/TestZipExtraField.swift | 2 +- 12 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Sources/7-Zip/7zContainer.swift b/Sources/7-Zip/7zContainer.swift index df2d304f..632f4231 100644 --- a/Sources/7-Zip/7zContainer.swift +++ b/Sources/7-Zip/7zContainer.swift @@ -97,7 +97,7 @@ public class SevenZipContainer: Container { } // Load the stream. - let streamData = Data(bytes: byteReader.bytes(count: packInfo.packSizes[streamIndex])) + let streamData = Data(byteReader.bytes(count: packInfo.packSizes[streamIndex])) // Check stream's CRC, if it's available. if streamIndex < packInfo.digests.count, @@ -122,7 +122,7 @@ public class SevenZipContainer: Container { // Check, if we aren't about to read too much from a stream. guard fileSize <= unpackedStreamData.bytesLeft else { throw SevenZipError.internalStructureError } - let fileData = Data(bytes: unpackedStreamData.bytes(count: fileSize)) + let fileData = Data(unpackedStreamData.bytes(count: fileSize)) let calculatedFileCRC = CheckSums.crc32(fileData) if nonEmptyFileIndex < substreamInfo.digests.count { diff --git a/Sources/BZip2/BZip2.swift b/Sources/BZip2/BZip2.swift index f48a1148..c84e658a 100644 --- a/Sources/BZip2/BZip2.swift +++ b/Sources/BZip2/BZip2.swift @@ -218,7 +218,7 @@ public class BZip2: DecompressionAlgorithm { } } - return Data(bytes: out) + return Data(out) } } diff --git a/Sources/Common/DeltaFilter.swift b/Sources/Common/DeltaFilter.swift index 5dc5e1cc..8f05ddba 100644 --- a/Sources/Common/DeltaFilter.swift +++ b/Sources/Common/DeltaFilter.swift @@ -29,7 +29,7 @@ final class DeltaFilter { } } - return Data(bytes: out) + return Data(out) } } diff --git a/Sources/Deflate/Deflate.swift b/Sources/Deflate/Deflate.swift index 0df8a454..19c6f26c 100644 --- a/Sources/Deflate/Deflate.swift +++ b/Sources/Deflate/Deflate.swift @@ -203,7 +203,7 @@ public class Deflate: DecompressionAlgorithm { } } - return Data(bytes: out) + return Data(out) } } diff --git a/Sources/GZip/GzipArchive.swift b/Sources/GZip/GzipArchive.swift index 9b58d381..bee4cc20 100644 --- a/Sources/GZip/GzipArchive.swift +++ b/Sources/GZip/GzipArchive.swift @@ -170,7 +170,7 @@ public class GzipArchive: Archive { headerBytes.append(2) // Extra flags; 2 means that DEFLATE used slowest algorithm. headerBytes.append(os) - var outData = Data(bytes: headerBytes) + var outData = Data(headerBytes) outData.append(fileNameData) outData.append(commentData) @@ -189,14 +189,14 @@ public class GzipArchive: Archive { for i: UInt32 in 0..<4 { crcBytes.append(UInt8(truncatingIfNeeded: (crc32 & (0xFF << (i * 8))) >> (i * 8))) } - outData.append(Data(bytes: crcBytes)) + outData.append(Data(crcBytes)) let isize = UInt64(data.count) % UInt64(1) << 32 var isizeBytes = [UInt8]() for i: UInt64 in 0..<4 { isizeBytes.append(UInt8(truncatingIfNeeded: (isize & (0xFF << (i * 8))) >> (i * 8))) } - outData.append(Data(bytes: isizeBytes)) + outData.append(Data(isizeBytes)) return outData } diff --git a/Sources/LZMA/LZMA.swift b/Sources/LZMA/LZMA.swift index 039ec105..3d4e39b9 100644 --- a/Sources/LZMA/LZMA.swift +++ b/Sources/LZMA/LZMA.swift @@ -65,7 +65,7 @@ public class LZMA: DecompressionAlgorithm { decoder.uncompressedSize = uncompSize ?? -1 try decoder.decode() - return Data(bytes: decoder.out) + return Data(decoder.out) } } diff --git a/Sources/LZMA2/LZMA2.swift b/Sources/LZMA2/LZMA2.swift index 535bd501..dad7de02 100644 --- a/Sources/LZMA2/LZMA2.swift +++ b/Sources/LZMA2/LZMA2.swift @@ -30,7 +30,7 @@ public class LZMA2: DecompressionAlgorithm { static func decompress(_ byteReader: ByteReader, _ dictSizeByte: UInt8) throws -> Data { let decoder = try LZMA2Decoder(byteReader, dictSizeByte) try decoder.decode() - return Data(bytes: decoder.out) + return Data(decoder.out) } } diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index b26d5dfc..b59be802 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -406,7 +406,7 @@ public struct TarEntryInfo: ContainerEntryInfo { // It determines the end of the actual prefix and the beginning of the updated name field. #if (swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) || !os(Linux) let lastPrefixSlashIndex = nameData.prefix(upTo: maxPrefixLength) - .range(of: Data(bytes: [0x2f]), options: .backwards)?.lowerBound ?? -1 + .range(of: Data([0x2f]), options: .backwards)?.lowerBound ?? -1 #else // TODO: This is a workaround for runtime crash in `Data.prefix(upTo:).range(of:options:)` on Linux with // Swift 4.1. It seems like it is fixed in 4.2 and master snapshots, so it will be removed when Swift @@ -480,7 +480,7 @@ fileprivate extension Data { value >>= 8 } buffer[0] |= 0x80 // Highest bit indicates base-256 encoding. - self.append(Data(bytes: buffer)) + self.append(Data(buffer)) } mutating func append(tarString string: String?, maxLength: Int) throws { diff --git a/Sources/ZIP/ZipContainer.swift b/Sources/ZIP/ZipContainer.swift index 1c8903e9..5f4df6b2 100644 --- a/Sources/ZIP/ZipContainer.swift +++ b/Sources/ZIP/ZipContainer.swift @@ -66,7 +66,7 @@ public class ZipContainer: Container { byteReader.offset = helper.dataOffset switch helper.entryInfo.compressionMethod { case .copy: - fileData = Data(bytes: byteReader.bytes(count: uncompSize.toInt())) + fileData = Data(byteReader.bytes(count: uncompSize.toInt())) case .deflate: let bitReader = LsbBitReader(byteReader) fileData = try Deflate.decompress(bitReader) diff --git a/Sources/ZIP/ZipEndOfCentralDirectory.swift b/Sources/ZIP/ZipEndOfCentralDirectory.swift index ee2c95da..4c10798f 100644 --- a/Sources/ZIP/ZipEndOfCentralDirectory.swift +++ b/Sources/ZIP/ZipEndOfCentralDirectory.swift @@ -41,7 +41,7 @@ struct ZipEndOfCentralDirectory { // There is also a .ZIP file comment, but we don't need it. // Here's how it can be processed: // let zipCommentLength = byteReader.int(fromBytes: 2) - // let zipComment = String(data: Data(bytes: byteReader.bytes(count: zipCommentLength)), + // let zipComment = String(data: Data(byteReader.bytes(count: zipCommentLength)), // encoding: .utf8) // Check if zip64 records are present. diff --git a/Sources/Zlib/ZlibArchive.swift b/Sources/Zlib/ZlibArchive.swift index b5a7cb33..5d50fd1b 100644 --- a/Sources/Zlib/ZlibArchive.swift +++ b/Sources/Zlib/ZlibArchive.swift @@ -53,7 +53,7 @@ public class ZlibArchive: Archive { 120, // CM (Compression Method) = 8 (DEFLATE), CINFO (Compression Info) = 7 (32K window size). 218 // Flags: slowest algorithm, no preset dictionary. ] - var outData = Data(bytes: out) + var outData = Data(out) outData.append(Deflate.compress(data: data)) let adler32 = CheckSums.adler32(data) @@ -61,7 +61,7 @@ public class ZlibArchive: Archive { for i in 0..<4 { adlerBytes.append(UInt8(truncatingIfNeeded: (adler32 & (0xFF << ((3 - i) * 8))) >> ((3 - i) * 8))) } - outData.append(Data(bytes: adlerBytes)) + outData.append(Data(adlerBytes)) return outData } diff --git a/Tests/TestZipExtraField.swift b/Tests/TestZipExtraField.swift index a8812986..ee0e62be 100644 --- a/Tests/TestZipExtraField.swift +++ b/Tests/TestZipExtraField.swift @@ -19,7 +19,7 @@ struct TestZipExtraField: ZipExtraField { init(_ byteReader: ByteReader, _ size: Int, location: ZipExtraFieldLocation) { self.size = size self.location = location - self.helloString = String(data: Data(bytes: byteReader.bytes(count: size)), encoding: .utf8) + self.helloString = String(data: Data(byteReader.bytes(count: size)), encoding: .utf8) } } From 9753e7e48c170ebea6e3644e7f11e4df104eea32 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 1 May 2019 19:33:19 +0300 Subject: [PATCH 03/97] Switch to the "develop" branch of BBD --- Cartfile | 2 +- Package.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cartfile b/Cartfile index 4025b2c3..da1117b1 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1 @@ -github "tsolomko/BitByteData" ~> 1.4 +github "tsolomko/BitByteData" "develop" diff --git a/Package.swift b/Package.swift index 6b4303b5..445ff43d 100644 --- a/Package.swift +++ b/Package.swift @@ -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: "1.4.0"), + .branch("develop")), ], targets: [ // SWCOMP: Uncomment the lines below to build swcomp example program. From 75b21ae1075c275bbab7bda36e9b8a321e1c2e06 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 1 May 2019 19:34:30 +0300 Subject: [PATCH 04/97] Replace usage of ByteReader with LittleEndianByteReader --- Sources/7-Zip/7zContainer.swift | 8 ++++---- Sources/7-Zip/7zFolder.swift | 4 ++-- Sources/Common/DeltaFilter.swift | 2 +- Sources/GZip/GzipHeader.swift | 4 ++-- Sources/LZMA/LZMA.swift | 6 +++--- Sources/LZMA/LZMADecoder.swift | 4 ++-- Sources/LZMA/LZMAProperties.swift | 2 +- Sources/LZMA/LZMARangeDecoder.swift | 6 +++--- Sources/LZMA2/LZMA2.swift | 4 ++-- Sources/LZMA2/LZMA2Decoder.swift | 4 ++-- Sources/TAR/ByteReader+Tar.swift | 2 +- Sources/TAR/TarEntryInfo.swift | 2 +- Sources/TAR/TarEntryInfoProvider.swift | 4 ++-- Sources/XZ/ByteReader+XZ.swift | 2 +- Sources/XZ/XZArchive.swift | 12 ++++++------ Sources/XZ/XZBlock.swift | 6 +++--- Sources/XZ/XZStreamHeader.swift | 2 +- Sources/ZIP/BuiltinExtraFields.swift | 8 ++++---- Sources/ZIP/ByteReader+Zip.swift | 2 +- Sources/ZIP/ZipCentralDirectoryEntry.swift | 2 +- Sources/ZIP/ZipContainer.swift | 4 ++-- Sources/ZIP/ZipEndOfCentralDirectory.swift | 2 +- Sources/ZIP/ZipEntryInfo.swift | 2 +- Sources/ZIP/ZipEntryInfoHelper.swift | 2 +- Sources/ZIP/ZipExtraField.swift | 2 +- Sources/ZIP/ZipLocalHeader.swift | 2 +- Sources/Zlib/ZlibHeader.swift | 4 ++-- Tests/TestZipExtraField.swift | 2 +- 28 files changed, 53 insertions(+), 53 deletions(-) diff --git a/Sources/7-Zip/7zContainer.swift b/Sources/7-Zip/7zContainer.swift index 632f4231..2c59fca8 100644 --- a/Sources/7-Zip/7zContainer.swift +++ b/Sources/7-Zip/7zContainer.swift @@ -49,10 +49,10 @@ public class SevenZipContainer: Container { /// Combined calculated CRC of entire folder == all files in folder. var folderCRC = CheckSums.crc32(Data()) - /// `ByteReader` object with unpacked stream's data. - var unpackedStreamData = ByteReader(data: Data()) + /// `LittleEndianByteReader` object with unpacked stream's data. + var unpackedStreamData = LittleEndianByteReader(data: Data()) - let byteReader = ByteReader(data: data) + let byteReader = LittleEndianByteReader(data: data) for file in files { if file.isEmptyStream { @@ -108,7 +108,7 @@ public class SevenZipContainer: Container { // One stream can contain data for several files, so we need to decode the stream first, then split // it into files. - unpackedStreamData = ByteReader(data: try folder.unpack(data: streamData)) + unpackedStreamData = LittleEndianByteReader(data: try folder.unpack(data: streamData)) } // `SevenZipSubstreamInfo` object must contain information about file's size and may also contain diff --git a/Sources/7-Zip/7zFolder.swift b/Sources/7-Zip/7zFolder.swift index 45f3ac4a..ad296ade 100644 --- a/Sources/7-Zip/7zFolder.swift +++ b/Sources/7-Zip/7zFolder.swift @@ -164,7 +164,7 @@ class SevenZipFolder { properties.count == 1 else { throw LZMA2Error.wrongDictionarySize } - decodedData = try LZMA2.decompress(ByteReader(data: decodedData), properties[0]) + decodedData = try LZMA2.decompress(LittleEndianByteReader(data: decodedData), properties[0]) case .lzma: // Both properties' byte (lp, lc, pb) and dictionary size are stored in coder's properties. guard let properties = coder.properties, @@ -185,7 +185,7 @@ class SevenZipFolder { properties.count == 1 else { throw SevenZipError.internalStructureError } - decodedData = DeltaFilter.decode(ByteReader(data: decodedData), (properties[0] &+ 1).toInt()) + decodedData = DeltaFilter.decode(LittleEndianByteReader(data: decodedData), (properties[0] &+ 1).toInt()) } else if coder.isEncryptionMethod { throw SevenZipError.encryptionNotSupported } else { diff --git a/Sources/Common/DeltaFilter.swift b/Sources/Common/DeltaFilter.swift index 8f05ddba..59ff6f9f 100644 --- a/Sources/Common/DeltaFilter.swift +++ b/Sources/Common/DeltaFilter.swift @@ -8,7 +8,7 @@ import BitByteData final class DeltaFilter { - static func decode(_ byteReader: ByteReader, _ distance: Int) -> Data { + static func decode(_ byteReader: LittleEndianByteReader, _ distance: Int) -> Data { var out = [UInt8]() var pos = 0 diff --git a/Sources/GZip/GzipHeader.swift b/Sources/GZip/GzipHeader.swift index 43bbb442..7f88ef12 100644 --- a/Sources/GZip/GzipHeader.swift +++ b/Sources/GZip/GzipHeader.swift @@ -53,11 +53,11 @@ public struct GzipHeader { it might not be archived with GZip at all. */ public init(archive data: Data) throws { - let byteReader = ByteReader(data: data) + let byteReader = LittleEndianByteReader(data: data) try self.init(byteReader) } - init(_ byteReader: ByteReader) throws { + init(_ byteReader: LittleEndianByteReader) throws { // First two bytes should be correct 'magic' bytes let magic = byteReader.uint16() guard magic == 0x8b1f else { throw GzipError.wrongMagic } diff --git a/Sources/LZMA/LZMA.swift b/Sources/LZMA/LZMA.swift index 3d4e39b9..adb8b520 100644 --- a/Sources/LZMA/LZMA.swift +++ b/Sources/LZMA/LZMA.swift @@ -23,7 +23,7 @@ public class LZMA: DecompressionAlgorithm { - Returns: Decompressed data. */ public static func decompress(data: Data) throws -> Data { - let byteReader = ByteReader(data: data) + let byteReader = LittleEndianByteReader(data: data) let properties = try LZMAProperties(byteReader) let uncompSize = byteReader.int(fromBytes: 8) return try decompress(byteReader, properties, uncompSize) @@ -52,11 +52,11 @@ public class LZMA: DecompressionAlgorithm { public static func decompress(data: Data, properties: LZMAProperties, uncompressedSize: Int? = nil) throws -> Data { - let byteReader = ByteReader(data: data) + let byteReader = LittleEndianByteReader(data: data) return try decompress(byteReader, properties, uncompressedSize) } - static func decompress(_ byteReader: ByteReader, + static func decompress(_ byteReader: LittleEndianByteReader, _ properties: LZMAProperties, _ uncompSize: Int?) throws -> Data { let decoder = LZMADecoder(byteReader) diff --git a/Sources/LZMA/LZMADecoder.swift b/Sources/LZMA/LZMADecoder.swift index 9191e5b1..415dab3d 100644 --- a/Sources/LZMA/LZMADecoder.swift +++ b/Sources/LZMA/LZMADecoder.swift @@ -8,7 +8,7 @@ import BitByteData final class LZMADecoder { - private let byteReader: ByteReader + private let byteReader: LittleEndianByteReader var properties = LZMAProperties() @@ -72,7 +72,7 @@ final class LZMADecoder { /// Used to select exact variable from 'IsRep', 'IsRepG0', 'IsRepG1' and 'IsRepG2' arrays. private var state = 0 - init(_ byteReader: ByteReader) { + init(_ byteReader: LittleEndianByteReader) { self.byteReader = byteReader } diff --git a/Sources/LZMA/LZMAProperties.swift b/Sources/LZMA/LZMAProperties.swift index 8073566e..971b76a0 100644 --- a/Sources/LZMA/LZMAProperties.swift +++ b/Sources/LZMA/LZMAProperties.swift @@ -58,7 +58,7 @@ public struct LZMAProperties { self.dictionarySize = dictSize } - init(_ byteReader: ByteReader) throws { + init(_ byteReader: LittleEndianByteReader) throws { try self.init(lzmaByte: byteReader.byte(), byteReader.int(fromBytes: 4)) } diff --git a/Sources/LZMA/LZMARangeDecoder.swift b/Sources/LZMA/LZMARangeDecoder.swift index 05dcdf53..a9be0939 100644 --- a/Sources/LZMA/LZMARangeDecoder.swift +++ b/Sources/LZMA/LZMARangeDecoder.swift @@ -8,7 +8,7 @@ import BitByteData final class LZMARangeDecoder { - private var byteReader: ByteReader + private var byteReader: LittleEndianByteReader private var range = 0xFFFFFFFF as UInt32 private var code = 0 as UInt32 @@ -18,7 +18,7 @@ final class LZMARangeDecoder { return self.code == 0 } - init?(_ byteReader: ByteReader) { + init?(_ byteReader: LittleEndianByteReader) { self.byteReader = byteReader let byte = self.byteReader.byte() @@ -31,7 +31,7 @@ final class LZMARangeDecoder { } init() { - self.byteReader = ByteReader(data: Data()) + self.byteReader = LittleEndianByteReader(data: Data()) } /// `range` property cannot be smaller than `(1 << 24)`. This function keeps it bigger. diff --git a/Sources/LZMA2/LZMA2.swift b/Sources/LZMA2/LZMA2.swift index dad7de02..97c3e670 100644 --- a/Sources/LZMA2/LZMA2.swift +++ b/Sources/LZMA2/LZMA2.swift @@ -23,11 +23,11 @@ public class LZMA2: DecompressionAlgorithm { - Returns: Decompressed data. */ public static func decompress(data: Data) throws -> Data { - let byteReader = ByteReader(data: data) + let byteReader = LittleEndianByteReader(data: data) return try decompress(byteReader, byteReader.byte()) } - static func decompress(_ byteReader: ByteReader, _ dictSizeByte: UInt8) throws -> Data { + static func decompress(_ byteReader: LittleEndianByteReader, _ dictSizeByte: UInt8) throws -> Data { let decoder = try LZMA2Decoder(byteReader, dictSizeByte) try decoder.decode() return Data(decoder.out) diff --git a/Sources/LZMA2/LZMA2Decoder.swift b/Sources/LZMA2/LZMA2Decoder.swift index 4ae5c0b1..ef4e9a63 100644 --- a/Sources/LZMA2/LZMA2Decoder.swift +++ b/Sources/LZMA2/LZMA2Decoder.swift @@ -8,14 +8,14 @@ import BitByteData final class LZMA2Decoder { - private let byteReader: ByteReader + private let byteReader: LittleEndianByteReader private let decoder: LZMADecoder var out: [UInt8] { return self.decoder.out } - init(_ byteReader: ByteReader, _ dictSizeByte: UInt8) throws { + init(_ byteReader: LittleEndianByteReader, _ dictSizeByte: UInt8) throws { self.byteReader = byteReader self.decoder = LZMADecoder(byteReader) diff --git a/Sources/TAR/ByteReader+Tar.swift b/Sources/TAR/ByteReader+Tar.swift index be375ec4..43a8351a 100644 --- a/Sources/TAR/ByteReader+Tar.swift +++ b/Sources/TAR/ByteReader+Tar.swift @@ -6,7 +6,7 @@ import Foundation import BitByteData -extension ByteReader { +extension LittleEndianByteReader { /** Reads a `String` field from TAR container. The end of the field is defined by either: diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index b59be802..8979af0a 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -199,7 +199,7 @@ public struct TarEntryInfo: ContainerEntryInfo { self.blockStartIndex = 0 } - init(_ byteReader: ByteReader, _ global: TarExtendedHeader?, _ local: TarExtendedHeader?, + init(_ byteReader: LittleEndianByteReader, _ global: TarExtendedHeader?, _ local: TarExtendedHeader?, _ longName: String?, _ longLinkName: String?) throws { self.blockStartIndex = byteReader.offset diff --git a/Sources/TAR/TarEntryInfoProvider.swift b/Sources/TAR/TarEntryInfoProvider.swift index 839722bf..2fb6a7ad 100644 --- a/Sources/TAR/TarEntryInfoProvider.swift +++ b/Sources/TAR/TarEntryInfoProvider.swift @@ -10,14 +10,14 @@ import BitByteData // impossible to do so, since `TarEntryInfo.init(...)` is throwing and `IteratorProtocol.next()` cannot be throwing. struct TarEntryInfoProvider { - private let byteReader: ByteReader + private let byteReader: LittleEndianByteReader private var lastGlobalExtendedHeader: TarExtendedHeader? private var lastLocalExtendedHeader: TarExtendedHeader? private var longLinkName: String? private var longName: String? init(_ data: Data) { - self.byteReader = ByteReader(data: data) + self.byteReader = LittleEndianByteReader(data: data) } mutating func next() throws -> TarEntryInfo? { diff --git a/Sources/XZ/ByteReader+XZ.swift b/Sources/XZ/ByteReader+XZ.swift index 7cf89663..0033f24b 100644 --- a/Sources/XZ/ByteReader+XZ.swift +++ b/Sources/XZ/ByteReader+XZ.swift @@ -6,7 +6,7 @@ import Foundation import BitByteData -extension ByteReader { +extension LittleEndianByteReader { func multiByteDecode() throws -> Int { var i = 1 diff --git a/Sources/XZ/XZArchive.swift b/Sources/XZ/XZArchive.swift index db21a665..c21d30f9 100644 --- a/Sources/XZ/XZArchive.swift +++ b/Sources/XZ/XZArchive.swift @@ -26,7 +26,7 @@ public class XZArchive: Archive { */ public static func unarchive(archive data: Data) throws -> Data { /// Object with input data which supports convenient work with bytes. - let byteReader = ByteReader(data: data) + let byteReader = LittleEndianByteReader(data: data) // Note: We don't check footer's magic bytes at the beginning, // because it is impossible to determine the end of each stream in multi-stream archives @@ -64,7 +64,7 @@ public class XZArchive: Archive { */ public static func splitUnarchive(archive data: Data) throws -> [Data] { // Same code as in `unarchive(archive:)` but with different type of `result`. - let byteReader = ByteReader(data: data) + let byteReader = LittleEndianByteReader(data: data) var result = [Data]() while !byteReader.isFinished { @@ -79,7 +79,7 @@ public class XZArchive: Archive { return result } - private static func processStream(_ byteReader: ByteReader) throws -> (data: Data, checkError: Bool) { + private static func processStream(_ byteReader: LittleEndianByteReader) throws -> (data: Data, checkError: Bool) { var out = Data() let streamHeader = try XZStreamHeader(byteReader) @@ -122,7 +122,7 @@ public class XZArchive: Archive { } private static func processIndex(_ blockInfos: [(unpaddedSize: Int, uncompSize: Int)], - _ byteReader: ByteReader) throws -> Int { + _ byteReader: LittleEndianByteReader) throws -> Int { let indexStartIndex = byteReader.offset - 1 let recordsCount = try byteReader.multiByteDecode() guard recordsCount == blockInfos.count @@ -159,7 +159,7 @@ public class XZArchive: Archive { } private static func processFooter(_ streamHeader: XZStreamHeader, _ indexSize: Int, - _ byteReader: ByteReader) throws { + _ byteReader: LittleEndianByteReader) throws { let footerCRC = byteReader.uint32() /// Indicates the size of Index field. Should match its real size. let backwardSize = (byteReader.int(fromBytes: 4) + 1) * 4 @@ -184,7 +184,7 @@ public class XZArchive: Archive { } /// Returns `true` if end of archive is reached, `false` otherwise. - private static func processPadding(_ byteReader: ByteReader) throws { + private static func processPadding(_ byteReader: LittleEndianByteReader) throws { guard !byteReader.isFinished else { return } diff --git a/Sources/XZ/XZBlock.swift b/Sources/XZ/XZBlock.swift index 199e961c..43326e95 100644 --- a/Sources/XZ/XZBlock.swift +++ b/Sources/XZ/XZBlock.swift @@ -15,7 +15,7 @@ struct XZBlock { return data.count } - init(_ blockHeaderSize: UInt8, _ byteReader: ByteReader, _ checkSize: Int) throws { + init(_ blockHeaderSize: UInt8, _ byteReader: LittleEndianByteReader, _ checkSize: Int) throws { let blockHeaderStartIndex = byteReader.offset - 1 let realBlockHeaderSize = (blockHeaderSize.toInt() + 1) * 4 @@ -34,7 +34,7 @@ struct XZBlock { /// Should match the size of data after decompression. let uncompressedSize = blockFlags & 0x80 != 0 ? try byteReader.multiByteDecode() : -1 - var filters: [(ByteReader) throws -> Data] = [] + var filters: [(LittleEndianByteReader) throws -> Data] = [] for _ in 0.. String? { guard length > 0 diff --git a/Sources/ZIP/ZipCentralDirectoryEntry.swift b/Sources/ZIP/ZipCentralDirectoryEntry.swift index 63f1e95c..b30d17a8 100644 --- a/Sources/ZIP/ZipCentralDirectoryEntry.swift +++ b/Sources/ZIP/ZipCentralDirectoryEntry.swift @@ -43,7 +43,7 @@ struct ZipCentralDirectoryEntry { let nextEntryOffset: Int - init(_ byteReader: ByteReader) throws { + init(_ byteReader: LittleEndianByteReader) throws { // Check signature. guard byteReader.uint32() == 0x02014b50 else { throw ZipError.wrongSignature } diff --git a/Sources/ZIP/ZipContainer.swift b/Sources/ZIP/ZipContainer.swift index 5f4df6b2..85ed5285 100644 --- a/Sources/ZIP/ZipContainer.swift +++ b/Sources/ZIP/ZipContainer.swift @@ -62,7 +62,7 @@ public class ZipContainer: Container { var crc32 = helper.entryInfo.crc let fileData: Data - let byteReader = ByteReader(data: data) + let byteReader = LittleEndianByteReader(data: data) byteReader.offset = helper.dataOffset switch helper.entryInfo.compressionMethod { case .copy: @@ -141,7 +141,7 @@ public class ZipContainer: Container { } private static func infoWithHelper(_ data: Data) throws -> [ZipEntryInfoHelper] { - let byteReader = ByteReader(data: data) + let byteReader = LittleEndianByteReader(data: data) var entries = [ZipEntryInfoHelper]() // First, we are looking for End of Central Directory record, specifically, for its signature. diff --git a/Sources/ZIP/ZipEndOfCentralDirectory.swift b/Sources/ZIP/ZipEndOfCentralDirectory.swift index 4c10798f..8b4c9dcb 100644 --- a/Sources/ZIP/ZipEndOfCentralDirectory.swift +++ b/Sources/ZIP/ZipEndOfCentralDirectory.swift @@ -17,7 +17,7 @@ struct ZipEndOfCentralDirectory { private(set) var cdSize: UInt64 private(set) var cdOffset: UInt64 - init(_ byteReader: ByteReader) throws { + init(_ byteReader: LittleEndianByteReader) throws { /// Indicates if Zip64 records should be present. var zip64RecordExists = false diff --git a/Sources/ZIP/ZipEntryInfo.swift b/Sources/ZIP/ZipEntryInfo.swift index 1314c977..c27b33d7 100644 --- a/Sources/ZIP/ZipEntryInfo.swift +++ b/Sources/ZIP/ZipEntryInfo.swift @@ -102,7 +102,7 @@ public struct ZipEntryInfo: ContainerEntryInfo { /// CRC32 of entry's data. public let crc: UInt32 - init(_ byteReader: ByteReader, _ cdEntry: ZipCentralDirectoryEntry, _ localHeader: ZipLocalHeader, + init(_ byteReader: LittleEndianByteReader, _ cdEntry: ZipCentralDirectoryEntry, _ localHeader: ZipLocalHeader, _ hasDataDescriptor: Bool) { self.name = cdEntry.fileName diff --git a/Sources/ZIP/ZipEntryInfoHelper.swift b/Sources/ZIP/ZipEntryInfoHelper.swift index 7a08b827..15158855 100644 --- a/Sources/ZIP/ZipEntryInfoHelper.swift +++ b/Sources/ZIP/ZipEntryInfoHelper.swift @@ -21,7 +21,7 @@ struct ZipEntryInfoHelper { let compSize: UInt64 let uncompSize: UInt64 - init(_ byteReader: ByteReader, _ currentDiskNumber: UInt32) throws { + init(_ byteReader: LittleEndianByteReader, _ currentDiskNumber: UInt32) throws { // Read Central Directory entry. let cdEntry = try ZipCentralDirectoryEntry(byteReader) diff --git a/Sources/ZIP/ZipExtraField.swift b/Sources/ZIP/ZipExtraField.swift index 9e98876c..d36a7985 100644 --- a/Sources/ZIP/ZipExtraField.swift +++ b/Sources/ZIP/ZipExtraField.swift @@ -33,7 +33,7 @@ public protocol ZipExtraField { - Postcondition: `size` property of a created instance must be equal to the second argument. - Postcondition: exactly `size` amount of bytes must be read by initializer from `byteReader`. */ - init?(_ byteReader: ByteReader, _ size: Int, location: ZipExtraFieldLocation) + init?(_ byteReader: LittleEndianByteReader, _ size: Int, location: ZipExtraFieldLocation) } diff --git a/Sources/ZIP/ZipLocalHeader.swift b/Sources/ZIP/ZipLocalHeader.swift index 7de293ef..2c80e67c 100644 --- a/Sources/ZIP/ZipLocalHeader.swift +++ b/Sources/ZIP/ZipLocalHeader.swift @@ -38,7 +38,7 @@ struct ZipLocalHeader { let dataOffset: Int - init(_ byteReader: ByteReader) throws { + init(_ byteReader: LittleEndianByteReader) throws { // Check signature. guard byteReader.uint32() == 0x04034b50 else { throw ZipError.wrongSignature } diff --git a/Sources/Zlib/ZlibHeader.swift b/Sources/Zlib/ZlibHeader.swift index 163b4500..ef06bd47 100644 --- a/Sources/Zlib/ZlibHeader.swift +++ b/Sources/Zlib/ZlibHeader.swift @@ -40,11 +40,11 @@ public struct ZlibHeader { - Throws: `ZlibError`. It may indicate that either archive is damaged or it might not be archived with Zlib at all. */ public init(archive data: Data) throws { - let byteReader = ByteReader(data: data) + let byteReader = LittleEndianByteReader(data: data) try self.init(byteReader) } - init(_ byteReader: ByteReader) throws { + init(_ byteReader: LittleEndianByteReader) throws { // compressionMethod and compressionInfo combined are needed later for integrity check. let cmf = byteReader.byte() // First four bits are compression method. diff --git a/Tests/TestZipExtraField.swift b/Tests/TestZipExtraField.swift index ee0e62be..6dd87491 100644 --- a/Tests/TestZipExtraField.swift +++ b/Tests/TestZipExtraField.swift @@ -16,7 +16,7 @@ struct TestZipExtraField: ZipExtraField { var helloString: String? - init(_ byteReader: ByteReader, _ size: Int, location: ZipExtraFieldLocation) { + init(_ byteReader: LittleEndianByteReader, _ size: Int, location: ZipExtraFieldLocation) { self.size = size self.location = location self.helloString = String(data: Data(byteReader.bytes(count: size)), encoding: .utf8) From 04b87f9e95dbce63284c8c0d49ed47563e3a113f Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 1 May 2019 19:36:51 +0300 Subject: [PATCH 05/97] Mark @inline(__always) functions as @inlinable --- Sources/Common/Extensions.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/Common/Extensions.swift b/Sources/Common/Extensions.swift index 1c0b590d..2a76470c 100644 --- a/Sources/Common/Extensions.swift +++ b/Sources/Common/Extensions.swift @@ -7,7 +7,7 @@ import Foundation extension UnsignedInteger { - @inline(__always) + @inlinable @inline(__always) func toInt() -> Int { return Int(truncatingIfNeeded: self) } @@ -15,12 +15,12 @@ extension UnsignedInteger { extension Int { - @inline(__always) + @inlinable @inline(__always) func toUInt8() -> UInt8 { return UInt8(truncatingIfNeeded: UInt(self)) } - @inline(__always) + @inlinable @inline(__always) func roundTo512() -> Int { if self >= Int.max - 510 { return Int.max From 8d0e6d5567c2349456039862565bfa493bff55e6 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 1 May 2019 19:39:14 +0300 Subject: [PATCH 06/97] Move public identifier from extension to enum itself (BZip2.BlockSize) --- Sources/BZip2/BZip2+BlockSize.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/BZip2/BZip2+BlockSize.swift b/Sources/BZip2/BZip2+BlockSize.swift index 0e78ea0c..c18e5ad5 100644 --- a/Sources/BZip2/BZip2+BlockSize.swift +++ b/Sources/BZip2/BZip2+BlockSize.swift @@ -5,7 +5,7 @@ import Foundation -public extension BZip2 { +extension BZip2 { /// Represents the size of the blocks in which data is split during BZip2 compression. public enum BlockSize: Int { @@ -62,4 +62,5 @@ public extension BZip2 { } } + } From 35a93815b366930b68179c0dafd6ae6a9aaad588 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 1 May 2019 19:39:41 +0300 Subject: [PATCH 07/97] Replace usage of deprecated index(...) functions with the new ones --- Sources/BZip2/BZip2+Compress.swift | 2 +- Sources/Deflate/Deflate+Compress.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/BZip2/BZip2+Compress.swift b/Sources/BZip2/BZip2+Compress.swift index 15c925e6..54519fbf 100644 --- a/Sources/BZip2/BZip2+Compress.swift +++ b/Sources/BZip2/BZip2+Compress.swift @@ -250,7 +250,7 @@ extension BZip2: CompressionAlgorithm { /// Mutable copy of `characters`. var dictionary = characters for i in 0.. distance.toInt() }) ?? 30) - 1 + let distanceSymbol = ((Constants.distanceBase.firstIndex { $0 > distance.toInt() }) ?? 30) - 1 let distanceExtraBits = distance.toInt() - Constants.distanceBase[distanceSymbol] let distanceExtraBitsCount = distanceSymbol == 0 || distanceSymbol == 1 ? 0 : ((distanceSymbol >> 1) - 1) @@ -184,7 +184,7 @@ extension Deflate: CompressionAlgorithm { buffer.append(BLDCode.lengthDistance(UInt16(truncatingIfNeeded: matchLength), UInt16(truncatingIfNeeded: distance))) stats[Constants.lengthCode[matchLength - 3]] += 1 // Length symbol. - stats[286 + ((Constants.distanceBase.index { $0 > distance }) ?? 30) - 1] += 1 // Distance symbol. + stats[286 + ((Constants.distanceBase.firstIndex { $0 > distance }) ?? 30) - 1] += 1 // Distance symbol. inputIndex += matchLength } else { buffer.append(BLDCode.byte(byte)) From 5c4af98ff896e8aa8a766e56a7309d02f58efa41 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 1 May 2019 19:41:09 +0300 Subject: [PATCH 08/97] Use the non-deprecated version of the Data.withUnsafeBytes function in Sha256 --- Sources/XZ/Sha256.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Sources/XZ/Sha256.swift b/Sources/XZ/Sha256.swift index 2c3b64f8..73eb3cf9 100644 --- a/Sources/XZ/Sha256.swift +++ b/Sources/XZ/Sha256.swift @@ -36,9 +36,7 @@ struct Sha256 { var h7 = 0x5be0cd19 as UInt32 // Padding - var bytes = data.withUnsafeBytes { - [UInt8](UnsafeBufferPointer(start: $0, count: data.count / MemoryLayout.size)) - } + var bytes = data.withUnsafeBytes { $0.map { $0 } } let originalLength = bytes.count var newLength = originalLength * 8 + 1 From b699f6e310ae63e14961f352ae4540fe4e208ae1 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 1 Jan 2020 19:04:54 +0300 Subject: [PATCH 09/97] Update travis badge in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9436c3f1..cedf1722 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Swift 4.2](https://img.shields.io/badge/Swift-4.2-blue.svg)](https://developer.apple.com/swift/) [![GitHub license](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://raw.githubusercontent.com/tsolomko/SWCompression/master/LICENSE) -[![Build Status](https://travis-ci.org/tsolomko/SWCompression.svg?branch=develop)](https://travis-ci.org/tsolomko/SWCompression) +[![Build Status](https://travis-ci.com/tsolomko/SWCompression.svg?branch=develop)](https://travis-ci.com/tsolomko/SWCompression) A framework with (de)compression algorithms and functions for processing various archives and containers. From 31ec1f1553a0a9b7211e26410b615c4e959fa7e7 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 1 Jan 2020 19:06:33 +0300 Subject: [PATCH 10/97] Update copyright year to 2020 --- .jazzy.yaml | 2 +- LICENSE | 2 +- SWCompression.xcodeproj/SWCompression.plist | 2 +- Sources/7-Zip/7zCoder+Equatable.swift | 2 +- Sources/7-Zip/7zCoder.swift | 2 +- Sources/7-Zip/7zCoderInfo.swift | 2 +- Sources/7-Zip/7zContainer.swift | 2 +- Sources/7-Zip/7zEntry.swift | 2 +- Sources/7-Zip/7zEntryInfo.swift | 2 +- Sources/7-Zip/7zError.swift | 2 +- Sources/7-Zip/7zFileInfo.swift | 2 +- Sources/7-Zip/7zFolder.swift | 2 +- Sources/7-Zip/7zHeader.swift | 2 +- Sources/7-Zip/7zPackInfo.swift | 2 +- Sources/7-Zip/7zProperty.swift | 2 +- Sources/7-Zip/7zStreamInfo.swift | 2 +- Sources/7-Zip/7zSubstreamInfo.swift | 2 +- Sources/7-Zip/CompressionMethod+7z.swift | 2 +- Sources/7-Zip/MsbBitReader+7z.swift | 2 +- Sources/BZip2/BZip2+BlockSize.swift | 2 +- Sources/BZip2/BZip2+Compress.swift | 2 +- Sources/BZip2/BZip2+Lengths.swift | 2 +- Sources/BZip2/BZip2.swift | 2 +- Sources/BZip2/BZip2Error.swift | 2 +- Sources/BZip2/BurrowsWheeler.swift | 2 +- Sources/BZip2/SuffixArray.swift | 2 +- Sources/Common/Archive.swift | 2 +- Sources/Common/CheckSums.swift | 2 +- Sources/Common/CodingTree/Code.swift | 2 +- Sources/Common/CodingTree/CodeLength.swift | 2 +- Sources/Common/CodingTree/DecodingTree.swift | 2 +- Sources/Common/CodingTree/EncodingTree.swift | 2 +- Sources/Common/CompressionAlgorithm.swift | 2 +- Sources/Common/CompressionMethod.swift | 2 +- Sources/Common/Container/Container.swift | 2 +- Sources/Common/Container/ContainerEntry.swift | 2 +- Sources/Common/Container/ContainerEntryInfo.swift | 2 +- Sources/Common/Container/ContainerEntryType.swift | 2 +- Sources/Common/Container/DosAttributes.swift | 2 +- Sources/Common/Container/Permissions.swift | 2 +- Sources/Common/DecompressionAlgorithm.swift | 2 +- Sources/Common/DeltaFilter.swift | 2 +- Sources/Common/Extensions.swift | 2 +- Sources/Common/FileSystemType.swift | 2 +- Sources/Deflate/Deflate+Compress.swift | 2 +- Sources/Deflate/Deflate+Constants.swift | 2 +- Sources/Deflate/Deflate+Lengths.swift | 2 +- Sources/Deflate/Deflate.swift | 2 +- Sources/Deflate/DeflateError.swift | 2 +- Sources/GZip/FileSystemType+Gzip.swift | 2 +- Sources/GZip/GzipArchive.swift | 2 +- Sources/GZip/GzipError.swift | 2 +- Sources/GZip/GzipHeader.swift | 2 +- Sources/LZMA/LZMA.swift | 2 +- Sources/LZMA/LZMABitTreeDecoder.swift | 2 +- Sources/LZMA/LZMAConstants.swift | 2 +- Sources/LZMA/LZMADecoder.swift | 2 +- Sources/LZMA/LZMAError.swift | 2 +- Sources/LZMA/LZMALenDecoder.swift | 2 +- Sources/LZMA/LZMAProperties.swift | 2 +- Sources/LZMA/LZMARangeDecoder.swift | 2 +- Sources/LZMA2/LZMA2.swift | 2 +- Sources/LZMA2/LZMA2Decoder.swift | 2 +- Sources/LZMA2/LZMA2Error.swift | 2 +- Sources/TAR/ByteReader+Tar.swift | 2 +- Sources/TAR/ContainerEntryType+Tar.swift | 2 +- Sources/TAR/TarContainer.swift | 2 +- Sources/TAR/TarCreateError.swift | 2 +- Sources/TAR/TarEntry.swift | 2 +- Sources/TAR/TarEntryInfo.swift | 2 +- Sources/TAR/TarEntryInfoProvider.swift | 2 +- Sources/TAR/TarError.swift | 2 +- Sources/TAR/TarExtendedHeader.swift | 2 +- Sources/XZ/ByteReader+XZ.swift | 2 +- Sources/XZ/Sha256.swift | 2 +- Sources/XZ/XZArchive.swift | 2 +- Sources/XZ/XZBlock.swift | 2 +- Sources/XZ/XZError.swift | 2 +- Sources/XZ/XZStreamHeader.swift | 2 +- Sources/ZIP/BuiltinExtraFields.swift | 2 +- Sources/ZIP/ByteReader+Zip.swift | 2 +- Sources/ZIP/CompressionMethod+Zip.swift | 2 +- Sources/ZIP/FileSystemType+Zip.swift | 2 +- Sources/ZIP/ZipCentralDirectoryEntry.swift | 2 +- Sources/ZIP/ZipContainer.swift | 2 +- Sources/ZIP/ZipEndOfCentralDirectory.swift | 2 +- Sources/ZIP/ZipEntry.swift | 2 +- Sources/ZIP/ZipEntryInfo.swift | 2 +- Sources/ZIP/ZipEntryInfoHelper.swift | 2 +- Sources/ZIP/ZipError.swift | 2 +- Sources/ZIP/ZipExtraField.swift | 2 +- Sources/ZIP/ZipLocalHeader.swift | 2 +- Sources/Zlib/ZlibArchive.swift | 2 +- Sources/Zlib/ZlibError.swift | 2 +- Sources/Zlib/ZlibHeader.swift | 2 +- Sources/swcomp/Archives/BZip2Command.swift | 2 +- Sources/swcomp/Archives/GZipCommand.swift | 2 +- Sources/swcomp/Archives/LZMACommand.swift | 2 +- Sources/swcomp/Archives/XZCommand.swift | 2 +- Sources/swcomp/Benchmarks/BenchmarkCommand.swift | 2 +- Sources/swcomp/Benchmarks/BenchmarkGroup.swift | 2 +- Sources/swcomp/Benchmarks/CompBz2.swift | 2 +- Sources/swcomp/Benchmarks/CompDeflate.swift | 2 +- Sources/swcomp/Benchmarks/Info7z.swift | 2 +- Sources/swcomp/Benchmarks/InfoTar.swift | 2 +- Sources/swcomp/Benchmarks/InfoZip.swift | 2 +- Sources/swcomp/Benchmarks/UnBz2.swift | 2 +- Sources/swcomp/Benchmarks/UnGzip.swift | 2 +- Sources/swcomp/Benchmarks/UnXz.swift | 2 +- Sources/swcomp/Containers/7ZipCommand.swift | 2 +- Sources/swcomp/Containers/CommonFunctions.swift | 2 +- Sources/swcomp/Containers/ContainerCommand.swift | 2 +- Sources/swcomp/Containers/TarCommand.swift | 2 +- Sources/swcomp/Containers/ZipCommand.swift | 2 +- Sources/swcomp/Extensions/BlockSize+Keyable.swift | 2 +- .../Extensions/CompressionMethod+CustomStringConvertible.swift | 2 +- .../Extensions/ContainerEntryInfo+CustomStringConvertible.swift | 2 +- .../Extensions/FileSystemType+CustomStringConvertible.swift | 2 +- .../swcomp/Extensions/GzipHeader+CustomStringConvertible.swift | 2 +- Sources/swcomp/main.swift | 2 +- Tests/BZip2CompressionTests.swift | 2 +- Tests/BZip2Tests.swift | 2 +- Tests/Constants.swift | 2 +- Tests/DeflateCompressionTests.swift | 2 +- Tests/GzipTests.swift | 2 +- Tests/LzmaTests.swift | 2 +- Tests/SevenZipTests.swift | 2 +- Tests/Sha256Tests.swift | 2 +- Tests/TarCreateTests.swift | 2 +- Tests/TarTests.swift | 2 +- Tests/TestZipExtraField.swift | 2 +- Tests/XzTests.swift | 2 +- Tests/ZipTests.swift | 2 +- Tests/ZlibTests.swift | 2 +- 134 files changed, 134 insertions(+), 134 deletions(-) diff --git a/.jazzy.yaml b/.jazzy.yaml index 3cb73961..b639cfce 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -4,7 +4,7 @@ clean: true author: Timofey Solomko module: SWCompression module_version: 4.5.1 -copyright: '© 2019 Timofey Solomko' +copyright: '© 2020 Timofey Solomko' readme: README.md github_url: https://github.com/tsolomko/SWCompression github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.5.1 diff --git a/LICENSE b/LICENSE index 68939368..536dba60 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Timofey Solomko +Copyright (c) 2020 Timofey Solomko Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/SWCompression.xcodeproj/SWCompression.plist b/SWCompression.xcodeproj/SWCompression.plist index 177be55a..38aac5b1 100644 --- a/SWCompression.xcodeproj/SWCompression.plist +++ b/SWCompression.xcodeproj/SWCompression.plist @@ -19,6 +19,6 @@ CFBundleVersion 67 NSHumanReadableCopyright - Copyright © 2019 Timofey Solomko. All rights reserved. + Copyright © 2020 Timofey Solomko. All rights reserved. diff --git a/Sources/7-Zip/7zCoder+Equatable.swift b/Sources/7-Zip/7zCoder+Equatable.swift index 5a586237..c3e0aee5 100644 --- a/Sources/7-Zip/7zCoder+Equatable.swift +++ b/Sources/7-Zip/7zCoder+Equatable.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zCoder.swift b/Sources/7-Zip/7zCoder.swift index e4bd1494..063c79c7 100644 --- a/Sources/7-Zip/7zCoder.swift +++ b/Sources/7-Zip/7zCoder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zCoderInfo.swift b/Sources/7-Zip/7zCoderInfo.swift index 51e8ae7d..66e7af7d 100644 --- a/Sources/7-Zip/7zCoderInfo.swift +++ b/Sources/7-Zip/7zCoderInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zContainer.swift b/Sources/7-Zip/7zContainer.swift index 2c59fca8..c0c3e4f9 100644 --- a/Sources/7-Zip/7zContainer.swift +++ b/Sources/7-Zip/7zContainer.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zEntry.swift b/Sources/7-Zip/7zEntry.swift index ea90ec5e..1548086a 100644 --- a/Sources/7-Zip/7zEntry.swift +++ b/Sources/7-Zip/7zEntry.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zEntryInfo.swift b/Sources/7-Zip/7zEntryInfo.swift index 92e19b17..91a02274 100644 --- a/Sources/7-Zip/7zEntryInfo.swift +++ b/Sources/7-Zip/7zEntryInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zError.swift b/Sources/7-Zip/7zError.swift index 39240d59..e73426ac 100644 --- a/Sources/7-Zip/7zError.swift +++ b/Sources/7-Zip/7zError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zFileInfo.swift b/Sources/7-Zip/7zFileInfo.swift index b8eedf7f..61b1da80 100644 --- a/Sources/7-Zip/7zFileInfo.swift +++ b/Sources/7-Zip/7zFileInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zFolder.swift b/Sources/7-Zip/7zFolder.swift index ad296ade..da62994c 100644 --- a/Sources/7-Zip/7zFolder.swift +++ b/Sources/7-Zip/7zFolder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zHeader.swift b/Sources/7-Zip/7zHeader.swift index 1842ff3f..abbe9751 100644 --- a/Sources/7-Zip/7zHeader.swift +++ b/Sources/7-Zip/7zHeader.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zPackInfo.swift b/Sources/7-Zip/7zPackInfo.swift index da0881da..c076272b 100644 --- a/Sources/7-Zip/7zPackInfo.swift +++ b/Sources/7-Zip/7zPackInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zProperty.swift b/Sources/7-Zip/7zProperty.swift index 18ebecc0..a2a64203 100644 --- a/Sources/7-Zip/7zProperty.swift +++ b/Sources/7-Zip/7zProperty.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zStreamInfo.swift b/Sources/7-Zip/7zStreamInfo.swift index 53790b3a..bc37a035 100644 --- a/Sources/7-Zip/7zStreamInfo.swift +++ b/Sources/7-Zip/7zStreamInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zSubstreamInfo.swift b/Sources/7-Zip/7zSubstreamInfo.swift index 6afb245e..3d5ed598 100644 --- a/Sources/7-Zip/7zSubstreamInfo.swift +++ b/Sources/7-Zip/7zSubstreamInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/CompressionMethod+7z.swift b/Sources/7-Zip/CompressionMethod+7z.swift index d17b2345..a4aeea96 100644 --- a/Sources/7-Zip/CompressionMethod+7z.swift +++ b/Sources/7-Zip/CompressionMethod+7z.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/MsbBitReader+7z.swift b/Sources/7-Zip/MsbBitReader+7z.swift index 774c168a..e4b18798 100644 --- a/Sources/7-Zip/MsbBitReader+7z.swift +++ b/Sources/7-Zip/MsbBitReader+7z.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/BZip2+BlockSize.swift b/Sources/BZip2/BZip2+BlockSize.swift index c18e5ad5..aca076eb 100644 --- a/Sources/BZip2/BZip2+BlockSize.swift +++ b/Sources/BZip2/BZip2+BlockSize.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/BZip2+Compress.swift b/Sources/BZip2/BZip2+Compress.swift index 54519fbf..c7a7a72d 100644 --- a/Sources/BZip2/BZip2+Compress.swift +++ b/Sources/BZip2/BZip2+Compress.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/BZip2+Lengths.swift b/Sources/BZip2/BZip2+Lengths.swift index c9e2b5bb..aabf655e 100644 --- a/Sources/BZip2/BZip2+Lengths.swift +++ b/Sources/BZip2/BZip2+Lengths.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/BZip2.swift b/Sources/BZip2/BZip2.swift index c84e658a..d1c9e8fb 100644 --- a/Sources/BZip2/BZip2.swift +++ b/Sources/BZip2/BZip2.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/BZip2Error.swift b/Sources/BZip2/BZip2Error.swift index a9930331..849782c2 100644 --- a/Sources/BZip2/BZip2Error.swift +++ b/Sources/BZip2/BZip2Error.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/BurrowsWheeler.swift b/Sources/BZip2/BurrowsWheeler.swift index 9aee8b16..ae46a2ee 100644 --- a/Sources/BZip2/BurrowsWheeler.swift +++ b/Sources/BZip2/BurrowsWheeler.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/SuffixArray.swift b/Sources/BZip2/SuffixArray.swift index d0bcd673..13a8c471 100644 --- a/Sources/BZip2/SuffixArray.swift +++ b/Sources/BZip2/SuffixArray.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Archive.swift b/Sources/Common/Archive.swift index d9ed4dac..b9e68111 100644 --- a/Sources/Common/Archive.swift +++ b/Sources/Common/Archive.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CheckSums.swift b/Sources/Common/CheckSums.swift index 480da37e..da9fd8ef 100644 --- a/Sources/Common/CheckSums.swift +++ b/Sources/Common/CheckSums.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CodingTree/Code.swift b/Sources/Common/CodingTree/Code.swift index 3ab83e39..8dc4aa87 100644 --- a/Sources/Common/CodingTree/Code.swift +++ b/Sources/Common/CodingTree/Code.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CodingTree/CodeLength.swift b/Sources/Common/CodingTree/CodeLength.swift index 788886ad..e1f7d952 100644 --- a/Sources/Common/CodingTree/CodeLength.swift +++ b/Sources/Common/CodingTree/CodeLength.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CodingTree/DecodingTree.swift b/Sources/Common/CodingTree/DecodingTree.swift index b3c04c59..5af7a020 100644 --- a/Sources/Common/CodingTree/DecodingTree.swift +++ b/Sources/Common/CodingTree/DecodingTree.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CodingTree/EncodingTree.swift b/Sources/Common/CodingTree/EncodingTree.swift index 1b54d135..fbfe8602 100644 --- a/Sources/Common/CodingTree/EncodingTree.swift +++ b/Sources/Common/CodingTree/EncodingTree.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CompressionAlgorithm.swift b/Sources/Common/CompressionAlgorithm.swift index b259eafe..746fc965 100644 --- a/Sources/Common/CompressionAlgorithm.swift +++ b/Sources/Common/CompressionAlgorithm.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CompressionMethod.swift b/Sources/Common/CompressionMethod.swift index faab89c1..602b1604 100644 --- a/Sources/Common/CompressionMethod.swift +++ b/Sources/Common/CompressionMethod.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Container/Container.swift b/Sources/Common/Container/Container.swift index 2a38b6bb..938687dc 100644 --- a/Sources/Common/Container/Container.swift +++ b/Sources/Common/Container/Container.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Container/ContainerEntry.swift b/Sources/Common/Container/ContainerEntry.swift index 0f4e3b14..1e115e99 100644 --- a/Sources/Common/Container/ContainerEntry.swift +++ b/Sources/Common/Container/ContainerEntry.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Container/ContainerEntryInfo.swift b/Sources/Common/Container/ContainerEntryInfo.swift index e02ad690..87265e40 100644 --- a/Sources/Common/Container/ContainerEntryInfo.swift +++ b/Sources/Common/Container/ContainerEntryInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Container/ContainerEntryType.swift b/Sources/Common/Container/ContainerEntryType.swift index 8f9a28b7..2e9035c1 100644 --- a/Sources/Common/Container/ContainerEntryType.swift +++ b/Sources/Common/Container/ContainerEntryType.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Container/DosAttributes.swift b/Sources/Common/Container/DosAttributes.swift index e7e843f6..06d8b5d9 100644 --- a/Sources/Common/Container/DosAttributes.swift +++ b/Sources/Common/Container/DosAttributes.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Container/Permissions.swift b/Sources/Common/Container/Permissions.swift index f181a5b0..462e0419 100644 --- a/Sources/Common/Container/Permissions.swift +++ b/Sources/Common/Container/Permissions.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/DecompressionAlgorithm.swift b/Sources/Common/DecompressionAlgorithm.swift index a93f1c50..9c235171 100644 --- a/Sources/Common/DecompressionAlgorithm.swift +++ b/Sources/Common/DecompressionAlgorithm.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/DeltaFilter.swift b/Sources/Common/DeltaFilter.swift index 59ff6f9f..fe1c802b 100644 --- a/Sources/Common/DeltaFilter.swift +++ b/Sources/Common/DeltaFilter.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Extensions.swift b/Sources/Common/Extensions.swift index 2a76470c..ab1cb9f4 100644 --- a/Sources/Common/Extensions.swift +++ b/Sources/Common/Extensions.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/FileSystemType.swift b/Sources/Common/FileSystemType.swift index 0aae59ad..2898843e 100644 --- a/Sources/Common/FileSystemType.swift +++ b/Sources/Common/FileSystemType.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Deflate/Deflate+Compress.swift b/Sources/Deflate/Deflate+Compress.swift index c63bde03..a231b731 100644 --- a/Sources/Deflate/Deflate+Compress.swift +++ b/Sources/Deflate/Deflate+Compress.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Deflate/Deflate+Constants.swift b/Sources/Deflate/Deflate+Constants.swift index 8af6ac4a..067fbf5e 100644 --- a/Sources/Deflate/Deflate+Constants.swift +++ b/Sources/Deflate/Deflate+Constants.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Deflate/Deflate+Lengths.swift b/Sources/Deflate/Deflate+Lengths.swift index eab5561b..6ee430e2 100644 --- a/Sources/Deflate/Deflate+Lengths.swift +++ b/Sources/Deflate/Deflate+Lengths.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Deflate/Deflate.swift b/Sources/Deflate/Deflate.swift index 19c6f26c..10212b5a 100644 --- a/Sources/Deflate/Deflate.swift +++ b/Sources/Deflate/Deflate.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Deflate/DeflateError.swift b/Sources/Deflate/DeflateError.swift index f98eac9f..600e4e09 100644 --- a/Sources/Deflate/DeflateError.swift +++ b/Sources/Deflate/DeflateError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/GZip/FileSystemType+Gzip.swift b/Sources/GZip/FileSystemType+Gzip.swift index 434e0e56..0032f9a2 100644 --- a/Sources/GZip/FileSystemType+Gzip.swift +++ b/Sources/GZip/FileSystemType+Gzip.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/GZip/GzipArchive.swift b/Sources/GZip/GzipArchive.swift index bee4cc20..a5b1cad4 100644 --- a/Sources/GZip/GzipArchive.swift +++ b/Sources/GZip/GzipArchive.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/GZip/GzipError.swift b/Sources/GZip/GzipError.swift index 31f92380..02964d2d 100644 --- a/Sources/GZip/GzipError.swift +++ b/Sources/GZip/GzipError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/GZip/GzipHeader.swift b/Sources/GZip/GzipHeader.swift index 7f88ef12..b5c51463 100644 --- a/Sources/GZip/GzipHeader.swift +++ b/Sources/GZip/GzipHeader.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMA.swift b/Sources/LZMA/LZMA.swift index adb8b520..ad86fb42 100644 --- a/Sources/LZMA/LZMA.swift +++ b/Sources/LZMA/LZMA.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMABitTreeDecoder.swift b/Sources/LZMA/LZMABitTreeDecoder.swift index 5b01c8b2..3a032b0a 100644 --- a/Sources/LZMA/LZMABitTreeDecoder.swift +++ b/Sources/LZMA/LZMABitTreeDecoder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMAConstants.swift b/Sources/LZMA/LZMAConstants.swift index 58fea10c..28e52625 100644 --- a/Sources/LZMA/LZMAConstants.swift +++ b/Sources/LZMA/LZMAConstants.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMADecoder.swift b/Sources/LZMA/LZMADecoder.swift index 415dab3d..9512e4ee 100644 --- a/Sources/LZMA/LZMADecoder.swift +++ b/Sources/LZMA/LZMADecoder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMAError.swift b/Sources/LZMA/LZMAError.swift index 4573b4ab..c8ad4628 100644 --- a/Sources/LZMA/LZMAError.swift +++ b/Sources/LZMA/LZMAError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMALenDecoder.swift b/Sources/LZMA/LZMALenDecoder.swift index 53c931c8..e4895a2d 100644 --- a/Sources/LZMA/LZMALenDecoder.swift +++ b/Sources/LZMA/LZMALenDecoder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMAProperties.swift b/Sources/LZMA/LZMAProperties.swift index 971b76a0..70a097b3 100644 --- a/Sources/LZMA/LZMAProperties.swift +++ b/Sources/LZMA/LZMAProperties.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMARangeDecoder.swift b/Sources/LZMA/LZMARangeDecoder.swift index a9be0939..fde97a95 100644 --- a/Sources/LZMA/LZMARangeDecoder.swift +++ b/Sources/LZMA/LZMARangeDecoder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA2/LZMA2.swift b/Sources/LZMA2/LZMA2.swift index 97c3e670..be927b81 100644 --- a/Sources/LZMA2/LZMA2.swift +++ b/Sources/LZMA2/LZMA2.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA2/LZMA2Decoder.swift b/Sources/LZMA2/LZMA2Decoder.swift index ef4e9a63..f5531b22 100644 --- a/Sources/LZMA2/LZMA2Decoder.swift +++ b/Sources/LZMA2/LZMA2Decoder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA2/LZMA2Error.swift b/Sources/LZMA2/LZMA2Error.swift index 008f350b..cb86e8f2 100644 --- a/Sources/LZMA2/LZMA2Error.swift +++ b/Sources/LZMA2/LZMA2Error.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/ByteReader+Tar.swift b/Sources/TAR/ByteReader+Tar.swift index 43a8351a..21d8c710 100644 --- a/Sources/TAR/ByteReader+Tar.swift +++ b/Sources/TAR/ByteReader+Tar.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/ContainerEntryType+Tar.swift b/Sources/TAR/ContainerEntryType+Tar.swift index 12c05e14..6278876d 100644 --- a/Sources/TAR/ContainerEntryType+Tar.swift +++ b/Sources/TAR/ContainerEntryType+Tar.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 329bc424..6fc376b2 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarCreateError.swift b/Sources/TAR/TarCreateError.swift index 00351b09..c9bc9c95 100644 --- a/Sources/TAR/TarCreateError.swift +++ b/Sources/TAR/TarCreateError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarEntry.swift b/Sources/TAR/TarEntry.swift index 9188a397..73218ab0 100644 --- a/Sources/TAR/TarEntry.swift +++ b/Sources/TAR/TarEntry.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index 8979af0a..88daba26 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarEntryInfoProvider.swift b/Sources/TAR/TarEntryInfoProvider.swift index 2fb6a7ad..6dee12aa 100644 --- a/Sources/TAR/TarEntryInfoProvider.swift +++ b/Sources/TAR/TarEntryInfoProvider.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarError.swift b/Sources/TAR/TarError.swift index ee68ce35..c1f8c5f2 100644 --- a/Sources/TAR/TarError.swift +++ b/Sources/TAR/TarError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarExtendedHeader.swift b/Sources/TAR/TarExtendedHeader.swift index 2f074181..db02ccf5 100644 --- a/Sources/TAR/TarExtendedHeader.swift +++ b/Sources/TAR/TarExtendedHeader.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/XZ/ByteReader+XZ.swift b/Sources/XZ/ByteReader+XZ.swift index 0033f24b..6d0af7c8 100644 --- a/Sources/XZ/ByteReader+XZ.swift +++ b/Sources/XZ/ByteReader+XZ.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/XZ/Sha256.swift b/Sources/XZ/Sha256.swift index 73eb3cf9..72fa0e33 100644 --- a/Sources/XZ/Sha256.swift +++ b/Sources/XZ/Sha256.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/XZ/XZArchive.swift b/Sources/XZ/XZArchive.swift index c21d30f9..ca6aea6e 100644 --- a/Sources/XZ/XZArchive.swift +++ b/Sources/XZ/XZArchive.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/XZ/XZBlock.swift b/Sources/XZ/XZBlock.swift index 43326e95..c70dbe84 100644 --- a/Sources/XZ/XZBlock.swift +++ b/Sources/XZ/XZBlock.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/XZ/XZError.swift b/Sources/XZ/XZError.swift index 889f1f5b..c5c22121 100644 --- a/Sources/XZ/XZError.swift +++ b/Sources/XZ/XZError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/XZ/XZStreamHeader.swift b/Sources/XZ/XZStreamHeader.swift index f1c9513a..14b58421 100644 --- a/Sources/XZ/XZStreamHeader.swift +++ b/Sources/XZ/XZStreamHeader.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/BuiltinExtraFields.swift b/Sources/ZIP/BuiltinExtraFields.swift index 83d25759..f776ffd9 100644 --- a/Sources/ZIP/BuiltinExtraFields.swift +++ b/Sources/ZIP/BuiltinExtraFields.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ByteReader+Zip.swift b/Sources/ZIP/ByteReader+Zip.swift index 7c900d2d..0087a54c 100644 --- a/Sources/ZIP/ByteReader+Zip.swift +++ b/Sources/ZIP/ByteReader+Zip.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/CompressionMethod+Zip.swift b/Sources/ZIP/CompressionMethod+Zip.swift index 139f6d6d..ec19833c 100644 --- a/Sources/ZIP/CompressionMethod+Zip.swift +++ b/Sources/ZIP/CompressionMethod+Zip.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/FileSystemType+Zip.swift b/Sources/ZIP/FileSystemType+Zip.swift index 5876a90a..a5509834 100644 --- a/Sources/ZIP/FileSystemType+Zip.swift +++ b/Sources/ZIP/FileSystemType+Zip.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipCentralDirectoryEntry.swift b/Sources/ZIP/ZipCentralDirectoryEntry.swift index b30d17a8..568fe653 100644 --- a/Sources/ZIP/ZipCentralDirectoryEntry.swift +++ b/Sources/ZIP/ZipCentralDirectoryEntry.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipContainer.swift b/Sources/ZIP/ZipContainer.swift index 85ed5285..736ed7a0 100644 --- a/Sources/ZIP/ZipContainer.swift +++ b/Sources/ZIP/ZipContainer.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipEndOfCentralDirectory.swift b/Sources/ZIP/ZipEndOfCentralDirectory.swift index 8b4c9dcb..0fbdc706 100644 --- a/Sources/ZIP/ZipEndOfCentralDirectory.swift +++ b/Sources/ZIP/ZipEndOfCentralDirectory.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipEntry.swift b/Sources/ZIP/ZipEntry.swift index c81deb86..2e139e07 100644 --- a/Sources/ZIP/ZipEntry.swift +++ b/Sources/ZIP/ZipEntry.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipEntryInfo.swift b/Sources/ZIP/ZipEntryInfo.swift index c27b33d7..7b7e4376 100644 --- a/Sources/ZIP/ZipEntryInfo.swift +++ b/Sources/ZIP/ZipEntryInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipEntryInfoHelper.swift b/Sources/ZIP/ZipEntryInfoHelper.swift index 15158855..dfab18b4 100644 --- a/Sources/ZIP/ZipEntryInfoHelper.swift +++ b/Sources/ZIP/ZipEntryInfoHelper.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipError.swift b/Sources/ZIP/ZipError.swift index 5a336e16..59535904 100644 --- a/Sources/ZIP/ZipError.swift +++ b/Sources/ZIP/ZipError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipExtraField.swift b/Sources/ZIP/ZipExtraField.swift index d36a7985..d79be696 100644 --- a/Sources/ZIP/ZipExtraField.swift +++ b/Sources/ZIP/ZipExtraField.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipLocalHeader.swift b/Sources/ZIP/ZipLocalHeader.swift index 2c80e67c..b093bbd0 100644 --- a/Sources/ZIP/ZipLocalHeader.swift +++ b/Sources/ZIP/ZipLocalHeader.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Zlib/ZlibArchive.swift b/Sources/Zlib/ZlibArchive.swift index 5d50fd1b..8e6b8593 100644 --- a/Sources/Zlib/ZlibArchive.swift +++ b/Sources/Zlib/ZlibArchive.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Zlib/ZlibError.swift b/Sources/Zlib/ZlibError.swift index 9c861e5e..15afea51 100644 --- a/Sources/Zlib/ZlibError.swift +++ b/Sources/Zlib/ZlibError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Zlib/ZlibHeader.swift b/Sources/Zlib/ZlibHeader.swift index ef06bd47..bbce6dcd 100644 --- a/Sources/Zlib/ZlibHeader.swift +++ b/Sources/Zlib/ZlibHeader.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Archives/BZip2Command.swift b/Sources/swcomp/Archives/BZip2Command.swift index a38b755b..6dafd247 100644 --- a/Sources/swcomp/Archives/BZip2Command.swift +++ b/Sources/swcomp/Archives/BZip2Command.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Archives/GZipCommand.swift b/Sources/swcomp/Archives/GZipCommand.swift index 52440458..be7d3b12 100644 --- a/Sources/swcomp/Archives/GZipCommand.swift +++ b/Sources/swcomp/Archives/GZipCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Archives/LZMACommand.swift b/Sources/swcomp/Archives/LZMACommand.swift index ed25c2c8..bf360d1b 100644 --- a/Sources/swcomp/Archives/LZMACommand.swift +++ b/Sources/swcomp/Archives/LZMACommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Archives/XZCommand.swift b/Sources/swcomp/Archives/XZCommand.swift index 666c5398..34636f2f 100644 --- a/Sources/swcomp/Archives/XZCommand.swift +++ b/Sources/swcomp/Archives/XZCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/BenchmarkCommand.swift b/Sources/swcomp/Benchmarks/BenchmarkCommand.swift index f25709cf..591c291a 100644 --- a/Sources/swcomp/Benchmarks/BenchmarkCommand.swift +++ b/Sources/swcomp/Benchmarks/BenchmarkCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/BenchmarkGroup.swift b/Sources/swcomp/Benchmarks/BenchmarkGroup.swift index 085c34db..26e625b3 100644 --- a/Sources/swcomp/Benchmarks/BenchmarkGroup.swift +++ b/Sources/swcomp/Benchmarks/BenchmarkGroup.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/CompBz2.swift b/Sources/swcomp/Benchmarks/CompBz2.swift index 430f7a3a..05d1652c 100644 --- a/Sources/swcomp/Benchmarks/CompBz2.swift +++ b/Sources/swcomp/Benchmarks/CompBz2.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/CompDeflate.swift b/Sources/swcomp/Benchmarks/CompDeflate.swift index 9e19b2a1..df6c4bc3 100644 --- a/Sources/swcomp/Benchmarks/CompDeflate.swift +++ b/Sources/swcomp/Benchmarks/CompDeflate.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/Info7z.swift b/Sources/swcomp/Benchmarks/Info7z.swift index d4166b65..7f3dff80 100644 --- a/Sources/swcomp/Benchmarks/Info7z.swift +++ b/Sources/swcomp/Benchmarks/Info7z.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/InfoTar.swift b/Sources/swcomp/Benchmarks/InfoTar.swift index 71d6ed1d..671082f0 100644 --- a/Sources/swcomp/Benchmarks/InfoTar.swift +++ b/Sources/swcomp/Benchmarks/InfoTar.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/InfoZip.swift b/Sources/swcomp/Benchmarks/InfoZip.swift index 4d72fcc7..a295ea47 100644 --- a/Sources/swcomp/Benchmarks/InfoZip.swift +++ b/Sources/swcomp/Benchmarks/InfoZip.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/UnBz2.swift b/Sources/swcomp/Benchmarks/UnBz2.swift index b0e06cd6..721e8d9d 100644 --- a/Sources/swcomp/Benchmarks/UnBz2.swift +++ b/Sources/swcomp/Benchmarks/UnBz2.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/UnGzip.swift b/Sources/swcomp/Benchmarks/UnGzip.swift index 94bcce5f..fc8f1c26 100644 --- a/Sources/swcomp/Benchmarks/UnGzip.swift +++ b/Sources/swcomp/Benchmarks/UnGzip.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/UnXz.swift b/Sources/swcomp/Benchmarks/UnXz.swift index 46976423..eb24ec85 100644 --- a/Sources/swcomp/Benchmarks/UnXz.swift +++ b/Sources/swcomp/Benchmarks/UnXz.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Containers/7ZipCommand.swift b/Sources/swcomp/Containers/7ZipCommand.swift index e6b80e3b..56e20a02 100644 --- a/Sources/swcomp/Containers/7ZipCommand.swift +++ b/Sources/swcomp/Containers/7ZipCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Containers/CommonFunctions.swift b/Sources/swcomp/Containers/CommonFunctions.swift index 1ddbff64..1c0ea211 100644 --- a/Sources/swcomp/Containers/CommonFunctions.swift +++ b/Sources/swcomp/Containers/CommonFunctions.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Containers/ContainerCommand.swift b/Sources/swcomp/Containers/ContainerCommand.swift index a98ce8b5..76cda15f 100644 --- a/Sources/swcomp/Containers/ContainerCommand.swift +++ b/Sources/swcomp/Containers/ContainerCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Containers/TarCommand.swift b/Sources/swcomp/Containers/TarCommand.swift index d8bdb04b..df03f19b 100644 --- a/Sources/swcomp/Containers/TarCommand.swift +++ b/Sources/swcomp/Containers/TarCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Containers/ZipCommand.swift b/Sources/swcomp/Containers/ZipCommand.swift index 6621e92b..95ea0491 100644 --- a/Sources/swcomp/Containers/ZipCommand.swift +++ b/Sources/swcomp/Containers/ZipCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Extensions/BlockSize+Keyable.swift b/Sources/swcomp/Extensions/BlockSize+Keyable.swift index 1d44f980..3917084d 100644 --- a/Sources/swcomp/Extensions/BlockSize+Keyable.swift +++ b/Sources/swcomp/Extensions/BlockSize+Keyable.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Extensions/CompressionMethod+CustomStringConvertible.swift b/Sources/swcomp/Extensions/CompressionMethod+CustomStringConvertible.swift index de3dc554..62617f43 100644 --- a/Sources/swcomp/Extensions/CompressionMethod+CustomStringConvertible.swift +++ b/Sources/swcomp/Extensions/CompressionMethod+CustomStringConvertible.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Extensions/ContainerEntryInfo+CustomStringConvertible.swift b/Sources/swcomp/Extensions/ContainerEntryInfo+CustomStringConvertible.swift index e51a9d6f..6dc152cd 100644 --- a/Sources/swcomp/Extensions/ContainerEntryInfo+CustomStringConvertible.swift +++ b/Sources/swcomp/Extensions/ContainerEntryInfo+CustomStringConvertible.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Extensions/FileSystemType+CustomStringConvertible.swift b/Sources/swcomp/Extensions/FileSystemType+CustomStringConvertible.swift index 6602b340..4aee5724 100644 --- a/Sources/swcomp/Extensions/FileSystemType+CustomStringConvertible.swift +++ b/Sources/swcomp/Extensions/FileSystemType+CustomStringConvertible.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Extensions/GzipHeader+CustomStringConvertible.swift b/Sources/swcomp/Extensions/GzipHeader+CustomStringConvertible.swift index 100c8ec4..013776f3 100644 --- a/Sources/swcomp/Extensions/GzipHeader+CustomStringConvertible.swift +++ b/Sources/swcomp/Extensions/GzipHeader+CustomStringConvertible.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/main.swift b/Sources/swcomp/main.swift index a9fb8607..feee7f15 100644 --- a/Sources/swcomp/main.swift +++ b/Sources/swcomp/main.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/BZip2CompressionTests.swift b/Tests/BZip2CompressionTests.swift index 89fff1c9..c14f3c43 100644 --- a/Tests/BZip2CompressionTests.swift +++ b/Tests/BZip2CompressionTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/BZip2Tests.swift b/Tests/BZip2Tests.swift index 9463629d..4db58c1d 100644 --- a/Tests/BZip2Tests.swift +++ b/Tests/BZip2Tests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/Constants.swift b/Tests/Constants.swift index b9039734..7aade238 100644 --- a/Tests/Constants.swift +++ b/Tests/Constants.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/DeflateCompressionTests.swift b/Tests/DeflateCompressionTests.swift index f6ce4ca5..312cf4f7 100644 --- a/Tests/DeflateCompressionTests.swift +++ b/Tests/DeflateCompressionTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/GzipTests.swift b/Tests/GzipTests.swift index 4fb0c229..13fc74e0 100644 --- a/Tests/GzipTests.swift +++ b/Tests/GzipTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/LzmaTests.swift b/Tests/LzmaTests.swift index 7c7dc397..63a0c68d 100644 --- a/Tests/LzmaTests.swift +++ b/Tests/LzmaTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/SevenZipTests.swift b/Tests/SevenZipTests.swift index 52fa9dda..049a4fbe 100644 --- a/Tests/SevenZipTests.swift +++ b/Tests/SevenZipTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/Sha256Tests.swift b/Tests/Sha256Tests.swift index 5782ba77..6d3340f2 100644 --- a/Tests/Sha256Tests.swift +++ b/Tests/Sha256Tests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/TarCreateTests.swift b/Tests/TarCreateTests.swift index 53aaf399..210524eb 100644 --- a/Tests/TarCreateTests.swift +++ b/Tests/TarCreateTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/TarTests.swift b/Tests/TarTests.swift index 5426c7ee..2debc652 100644 --- a/Tests/TarTests.swift +++ b/Tests/TarTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/TestZipExtraField.swift b/Tests/TestZipExtraField.swift index 6dd87491..d350fa9b 100644 --- a/Tests/TestZipExtraField.swift +++ b/Tests/TestZipExtraField.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/XzTests.swift b/Tests/XzTests.swift index 9575e352..558c7bf3 100644 --- a/Tests/XzTests.swift +++ b/Tests/XzTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/ZipTests.swift b/Tests/ZipTests.swift index 0e65f2e7..90c41bde 100644 --- a/Tests/ZipTests.swift +++ b/Tests/ZipTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/ZlibTests.swift b/Tests/ZlibTests.swift index 380f7ba5..d24dfa56 100644 --- a/Tests/ZlibTests.swift +++ b/Tests/ZlibTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Timofey Solomko +// Copyright (c) 2020 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information From 3c2769a47a394754baddebdfc2c2ba8ca436fd04 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 1 Jan 2020 22:04:07 +0300 Subject: [PATCH 11/97] CI updates: use xcode 10.3 (instead of 10.2), additionally test using xcode 11.3 --- .travis.yml | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index f99967d1..edd0893e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ jobs: - stage: test language: swift os: osx - osx_image: xcode10.2 + osx_image: xcode10.3 before_install: - brew update install: @@ -15,7 +15,20 @@ jobs: - Utils/prepare-workspace-macos.sh script: - Utils/ci-script-macos.sh - - language: generic + - stage: test + language: swift + os: osx + osx_image: xcode11.3 + before_install: + - brew update + install: + - Utils/ci-install-macos.sh + before_script: + - Utils/prepare-workspace-macos.sh + script: + - Utils/ci-script-macos.sh + - stage: test + language: generic os: linux dist: xenial install: @@ -26,7 +39,7 @@ jobs: if: tag IS present language: generic os: osx - osx_image: xcode10.2 + osx_image: xcode10.3 env: secure: iavIkrus2Xd3b086nz2srMGl52yqzLuCdhyEAhMODVqkzqMQ17s10y1TNb+vkepd0HgxI9j57d5X7tfChjWuWDwE2hZKjr/Kx2DfiUr1AKQD6ymuGrq/0Vv6yL9dfPU8goFArcrsBcyVKczLtTuLCKL498ZqokkQc/3kGvzW74lv+z410MfHS9/tvToO/yXJckL6qJ2XBAiElfOO0rEkllTeCo6N3bjcHZ2o7PE0K+CHYxwNKj0TmPmuNWZ3U4fzoWzkk01re1C1l5cpSb20g+2aGyi0yYX+PomX7fIIqNq9vmmyoeNdr35yqoQv/0zFeFnps83NKmZLAjSUhiUdhlbuBLBE+w8544LOaZnMDlFmpDjgyaVnRrOh0NrBB1FwU48aGfX5ljRQmk/07FTEUjvwvGGoOpz8lrLZi148FMHEospL3Sf7d8K+Q9WdtLTGk7HCnbOVcxS6oB/SWF/Cj6n5wu+EI1floBaZEsNPR40Gd4eM/Ik/E3lDrZThGDCWQsao981wm7IfEDBR1nuMME8gpZINFANNS1+5miFaGdTnDTp4Yd5MGEFZm+K8x+TG1891NwNH1ZmKXlypJXiUzvSjbh2ViNJGekdQj9q2gj2ZFlCfHJ05adwJ4w9qRuF00HpAOD6At6EnsjDXFJeTZS5dj8fi2YsU9or8KfTFoNY= addons: From 82f150d437124f511115e5e5b2f23ee5e63bdd5d Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 2 Jan 2020 12:29:24 +0300 Subject: [PATCH 12/97] Use LsbBitReader argument in the Gzip and Zlib headers' initializers This fixes issues arising from the removal of _subclass_ relations between bit and byte readers in BBD. --- Sources/GZip/GzipHeader.swift | 28 ++++++++++++++-------------- Sources/Zlib/ZlibHeader.swift | 12 ++++++------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Sources/GZip/GzipHeader.swift b/Sources/GZip/GzipHeader.swift index b5c51463..74401b1e 100644 --- a/Sources/GZip/GzipHeader.swift +++ b/Sources/GZip/GzipHeader.swift @@ -53,23 +53,23 @@ public struct GzipHeader { it might not be archived with GZip at all. */ public init(archive data: Data) throws { - let byteReader = LittleEndianByteReader(data: data) - try self.init(byteReader) + let reader = LsbBitReader(data: data) + try self.init(reader) } - init(_ byteReader: LittleEndianByteReader) throws { + init(_ reader: LsbBitReader) throws { // First two bytes should be correct 'magic' bytes - let magic = byteReader.uint16() + let magic = reader.uint16() guard magic == 0x8b1f else { throw GzipError.wrongMagic } var headerBytes: [UInt8] = [0x1f, 0x8b] // Third byte is a method of compression. Only type 8 (DEFLATE) compression is supported for GZip archives. - let method = byteReader.byte() + let method = reader.byte() guard method == 8 else { throw GzipError.wrongCompressionMethod } headerBytes.append(method) self.compressionMethod = .deflate - let rawFlags = byteReader.byte() + let rawFlags = reader.byte() guard rawFlags & 0xE0 == 0 else { throw GzipError.wrongFlags } let flags = Flags(rawValue: rawFlags) @@ -77,16 +77,16 @@ public struct GzipHeader { var mtime = 0 for i in 0..<4 { - let byte = byteReader.byte() + let byte = reader.byte() mtime |= byte.toInt() << (8 * i) headerBytes.append(byte) } self.modificationTime = mtime == 0 ? nil : Date(timeIntervalSince1970: TimeInterval(mtime)) - let extraFlags = byteReader.byte() + let extraFlags = reader.byte() headerBytes.append(extraFlags) - let rawOsType = byteReader.byte() + let rawOsType = reader.byte() self.osType = FileSystemType(rawOsType) headerBytes.append(rawOsType) @@ -96,12 +96,12 @@ public struct GzipHeader { if flags.contains(.fextra) { var xlen = 0 for i in 0..<2 { - let byte = byteReader.byte() + let byte = reader.byte() xlen |= byte.toInt() << (8 * i) headerBytes.append(byte) } for _ in 0.. Date: Thu, 2 Jan 2020 15:31:08 +0300 Subject: [PATCH 13/97] Fix various xcode11-related CI problems --- SWCompression.xcodeproj/project.pbxproj | 4 +++- Utils/ci-script-macos.sh | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index a1b004c0..dba9e97d 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -1077,7 +1077,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "if [[ ${SDK_NAME} == iphone* ]]; then\n if [[ ! -d ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/ ]]; then\n mkdir -p ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/\n fi\n cp -r ${PROJECT_DIR}/Carthage/Build/iOS/BitByteData.framework ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/\nelif [[ ${SDK_NAME} == appletv* ]]; then\n if [[ ! -d ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/ ]]; then\n mkdir -p ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/\n fi\n cp -r ${PROJECT_DIR}/Carthage/Build/tvOS/BitByteData.framework ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/\nelif [[ ${SDK_NAME} == watch* ]]; then\n if [[ ! -d ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/ ]]; then\n mkdir -p ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/\n fi\n cp -r ${PROJECT_DIR}/Carthage/Build/watchOS/BitByteData.framework ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/\nelif [[ ${SDK_NAME} == macos* ]]; then\n if [[ ! -d ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Contents/Frameworks/ ]]; then\n mkdir -p ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Contents/Frameworks/\n fi\n cp -r ${PROJECT_DIR}/Carthage/Build/Mac/BitByteData.framework ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Contents/Frameworks/\nfi\n\nxattr -rc ${BUILT_PRODUCTS_DIR}"; + shellScript = "if [[ ${SDK_NAME} == iphone* ]]; then\n if [[ ! -d ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/ ]]; then\n mkdir -p ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/\n fi\n cp -a ${PROJECT_DIR}/Carthage/Build/iOS/BitByteData.framework ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/\nelif [[ ${SDK_NAME} == appletv* ]]; then\n if [[ ! -d ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/ ]]; then\n mkdir -p ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/\n fi\n cp -a ${PROJECT_DIR}/Carthage/Build/tvOS/BitByteData.framework ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/\nelif [[ ${SDK_NAME} == watch* ]]; then\n if [[ ! -d ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/ ]]; then\n mkdir -p ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/\n fi\n cp -a ${PROJECT_DIR}/Carthage/Build/watchOS/BitByteData.framework ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Frameworks/\nelif [[ ${SDK_NAME} == macos* ]]; then\n if [[ ! -d ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Contents/Frameworks/ ]]; then\n mkdir -p ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Contents/Frameworks/\n fi\n cp -a ${PROJECT_DIR}/Carthage/Build/Mac/BitByteData.framework ${BUILT_PRODUCTS_DIR}/TestSWCompression.xctest/Contents/Frameworks/\nfi\n\nxattr -rc ${BUILT_PRODUCTS_DIR}\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -1258,6 +1258,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; + OTHER_CODE_SIGN_FLAGS = "--deep"; OTHER_LDFLAGS = ( "-framework", BitByteData, @@ -1313,6 +1314,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; MACOSX_DEPLOYMENT_TARGET = 10.10; + OTHER_CODE_SIGN_FLAGS = "--deep"; OTHER_LDFLAGS = ( "-framework", BitByteData, diff --git a/Utils/ci-script-macos.sh b/Utils/ci-script-macos.sh index cffe8232..cda1458a 100755 --- a/Utils/ci-script-macos.sh +++ b/Utils/ci-script-macos.sh @@ -3,6 +3,6 @@ set -euxo pipefail xcodebuild -project SWCompression.xcodeproj -scheme SWCompression -destination "platform=OS X" clean test | xcpretty -f `xcpretty-travis-formatter` -xcodebuild -project SWCompression.xcodeproj -scheme SWCompression -destination "platform=iOS Simulator,name=iPhone 6S" clean test | xcpretty -f `xcpretty-travis-formatter` +xcodebuild -project SWCompression.xcodeproj -scheme SWCompression -destination "platform=iOS Simulator,name=iPhone 8" clean test | xcpretty -f `xcpretty-travis-formatter` xcodebuild -project SWCompression.xcodeproj -scheme SWCompression -destination "platform=watchOS Simulator,name=Apple Watch - 38mm" clean build | xcpretty -f `xcpretty-travis-formatter` xcodebuild -project SWCompression.xcodeproj -scheme SWCompression -destination "platform=tvOS Simulator,name=Apple TV" clean test | xcpretty -f `xcpretty-travis-formatter` From bd8901a4065a09c22bd875b9db134d197992696c Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Fri, 20 Mar 2020 09:31:59 +0300 Subject: [PATCH 14/97] Several deployment-related changes Remove .swift-version file (it's deprecated by Cocoapods), run deploy phase in CI using xcode 11.3, remove extra swift build in CI deploy phase (sourcekitten now runs it itself), adjusted swift_versions setting in podspec, fix builds in linux CI by specifying swift version in the config. --- .swift-version | 1 - .travis.yml | 6 ++++-- SWCompression.podspec | 2 +- Utils/ci-before-deploy.sh | 1 - 4 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 .swift-version diff --git a/.swift-version b/.swift-version deleted file mode 100644 index 819e07a2..00000000 --- a/.swift-version +++ /dev/null @@ -1 +0,0 @@ -5.0 diff --git a/.travis.yml b/.travis.yml index edd0893e..3bf75bab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,15 +31,17 @@ jobs: language: generic os: linux dist: xenial + env: + - SWIFT_VERSION=5.0 install: - - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" + - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" script: - Utils/ci-script-linux.sh - stage: deploy if: tag IS present language: generic os: osx - osx_image: xcode10.3 + osx_image: xcode11.3 env: secure: iavIkrus2Xd3b086nz2srMGl52yqzLuCdhyEAhMODVqkzqMQ17s10y1TNb+vkepd0HgxI9j57d5X7tfChjWuWDwE2hZKjr/Kx2DfiUr1AKQD6ymuGrq/0Vv6yL9dfPU8goFArcrsBcyVKczLtTuLCKL498ZqokkQc/3kGvzW74lv+z410MfHS9/tvToO/yXJckL6qJ2XBAiElfOO0rEkllTeCo6N3bjcHZ2o7PE0K+CHYxwNKj0TmPmuNWZ3U4fzoWzkk01re1C1l5cpSb20g+2aGyi0yYX+PomX7fIIqNq9vmmyoeNdr35yqoQv/0zFeFnps83NKmZLAjSUhiUdhlbuBLBE+w8544LOaZnMDlFmpDjgyaVnRrOh0NrBB1FwU48aGfX5ljRQmk/07FTEUjvwvGGoOpz8lrLZi148FMHEospL3Sf7d8K+Q9WdtLTGk7HCnbOVcxS6oB/SWF/Cj6n5wu+EI1floBaZEsNPR40Gd4eM/Ik/E3lDrZThGDCWQsao981wm7IfEDBR1nuMME8gpZINFANNS1+5miFaGdTnDTp4Yd5MGEFZm+K8x+TG1891NwNH1ZmKXlypJXiUzvSjbh2ViNJGekdQj9q2gj2ZFlCfHJ05adwJ4w9qRuF00HpAOD6At6EnsjDXFJeTZS5dj8fi2YsU9or8KfTFoNY= addons: diff --git a/SWCompression.podspec b/SWCompression.podspec index 23e3e9a4..e02ab340 100644 --- a/SWCompression.podspec +++ b/SWCompression.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.tvos.deployment_target = "9.0" s.watchos.deployment_target = "2.0" - s.swift_version = "5.0" + s.swift_versions = ["4", "5"] s.dependency "BitByteData", "~> 1.4.0" diff --git a/Utils/ci-before-deploy.sh b/Utils/ci-before-deploy.sh index ed1c53df..67977edd 100755 --- a/Utils/ci-before-deploy.sh +++ b/Utils/ci-before-deploy.sh @@ -12,6 +12,5 @@ rm -rf Carthage/Checkouts (set +x; echo "=> Preparing deployment files.") carthage build --no-skip-current carthage archive SWCompression -swift build sourcekitten doc --spm-module SWCompression > docs.json jazzy From 79a7a2ab7af94b2099e2be9baa763e7fda8cf297 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 11 Apr 2020 01:29:46 +0300 Subject: [PATCH 15/97] CI changes: don't test Swift 4.2, deploy using Xcode 11.4 --- .travis.yml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 79e81c0d..4ade654f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,16 +47,6 @@ jobs: - ./utils.py prepare-workspace macos script: - ./utils.py ci script-macos - - stage: test - language: generic - os: linux - dist: xenial - env: - - SWIFT_VERSION=4.2 - install: - - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" - script: - - ./utils.py ci script-linux - stage: test language: generic os: linux @@ -91,7 +81,7 @@ jobs: if: tag IS present language: generic os: osx - osx_image: xcode11.3 + osx_image: xcode11.4 env: - HOMEBREW_NO_INSTALL_CLEANUP=1 env: From 8ec7299e08711605f1eb4b439539d1fc1e0e3def Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 11 Apr 2020 23:45:16 +0300 Subject: [PATCH 16/97] Fix a link in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f115dafd..081ddea8 100644 --- a/README.md +++ b/README.md @@ -191,7 +191,7 @@ There are two reasons for this complicated setup. Firstly, some of these files c unfortunate if the users of SWCompression had to download them every time during the installation. Secondly, Swift Package Manager and contemporary versions of Xcode don't always work well with git-lfs-enabled repositories. To prevent any potential problems test files were moved into another repository. Additionaly, the custom command line tool `utils.py` -is used to work around issues occuring on certain user systems (see, for example, #9). +is used to work around issues occuring on certain user systems (see, for example, [#9](https://github.com/tsolomko/SWCompression/issues/9)). Please note, that if you want to add a new _type_ of test files, in addition to running `git lfs track`, you have to also copy into the "Tests/Test Files/gitattributes-copy" file a line this command adds to the "Tests/Test Files/.gitattributes" From efd2e00ba6b8b875df93d00f0fc98e5172d3e395 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 11 Apr 2020 23:45:47 +0300 Subject: [PATCH 17/97] Remove configuration files for linters They aren't used anyway, especially swiftlint. --- .markdownlint.json | 7 ------- .swiftlint.yml | 33 --------------------------------- 2 files changed, 40 deletions(-) delete mode 100644 .markdownlint.json delete mode 100644 .swiftlint.yml diff --git a/.markdownlint.json b/.markdownlint.json deleted file mode 100644 index f520e6d4..00000000 --- a/.markdownlint.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "MD007": { "indent": 4 }, - "MD013": { "line_length": 120 }, - "MD024": false, - "MD026": { "punctuation": ".,;:!"}, - "MD029": { "style": "ordered" } -} \ No newline at end of file diff --git a/.swiftlint.yml b/.swiftlint.yml deleted file mode 100644 index 13f4fa2f..00000000 --- a/.swiftlint.yml +++ /dev/null @@ -1,33 +0,0 @@ -excluded: - - .build/ - - Package.swift - - Carthage/ -disabled_rules: - - cyclomatic_complexity - - file_length - - for_where - - function_body_length - - identifier_name - - type_body_length -opt_in_rules: - - array_init - - block_based_kvo - - conditional_returns_on_newline - - contains_over_first_not_nil - - discouraged_direct_init - - discouraged_object_literal - - discouraged_optional_boolean - - explicit_init - - fatal_error_message - - first_where - - implicit_return - - implicitly_unwrapped_optional - - joined_default_parameter - - literal_expression_end_indentation - - operator_usage_whitespace - - pattern_matching_keywords - - redundant_nil_coalescing - - single_test_class - - sorted_first_last - - switch_case_on_newline - - trailing_closure From 0f15e1c29b1f441b2d96c7005dbe662e458e22b2 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 11 Apr 2020 23:56:37 +0300 Subject: [PATCH 18/97] Remove Swift-4.2-support code-path from Sha256.swift --- Sources/XZ/Sha256.swift | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Sources/XZ/Sha256.swift b/Sources/XZ/Sha256.swift index 2bab306f..72fa0e33 100644 --- a/Sources/XZ/Sha256.swift +++ b/Sources/XZ/Sha256.swift @@ -36,13 +36,7 @@ struct Sha256 { var h7 = 0x5be0cd19 as UInt32 // Padding - #if compiler(>=5.0) - var bytes = data.withUnsafeBytes { $0.map { $0 } } - #else - var bytes = data.withUnsafeBytes { - [UInt8](UnsafeBufferPointer(start: $0, count: data.count / MemoryLayout.size)) - } - #endif + var bytes = data.withUnsafeBytes { $0.map { $0 } } let originalLength = bytes.count var newLength = originalLength * 8 + 1 From b40aca21c0ec563b5cfaa99615f38518338e0556 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 16 Apr 2020 00:22:13 +0300 Subject: [PATCH 19/97] CI changes: move linux install to utils.py; make linux install swift step more verbose to find out why it doesn't work sometimes; print swift version on every script step to check that everything is working --- .travis.yml | 6 +++--- utils.py | 12 +++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4ade654f..8411ffda 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,7 +54,7 @@ jobs: env: - SWIFT_VERSION=5.0 install: - - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" + - ./utils.py ci install-linux script: - ./utils.py ci script-linux - stage: test @@ -64,7 +64,7 @@ jobs: env: - SWIFT_VERSION=5.1 install: - - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" + - ./utils.py ci install-linux script: - ./utils.py ci script-linux - stage: test @@ -74,7 +74,7 @@ jobs: env: - SWIFT_VERSION=5.2 install: - - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" + - ./utils.py ci install-linux script: - ./utils.py ci script-linux - stage: deploy diff --git a/utils.py b/utils.py index 173012ac..4e78e31f 100755 --- a/utils.py +++ b/utils.py @@ -28,11 +28,19 @@ def _ci_install_macos(): _sprun(["git", "lfs", "install"]) _sprun(["gem", "install", "-N", "xcpretty-travis-formatter"]) +def _ci_install_linux(): + _sprun("curl -sL https://swiftenv.fuller.li/install.sh > install.sh", shell=True) + _sprun(["cat", "install.sh"]) + _sprun(["chmod", "+x", "install.sh"]) + _sprun(["./install.sh"]) + def _ci_script_linux(): + _sprun(["swift", "--version"]) _sprun(["swift", "build"]) _sprun(["swift", "build", "-c", "release"]) def _ci_script_macos(): + _sprun(["swift", "--version"]) xcodebuild_command_parts = ["xcodebuild", "-project", "SWCompression.xcodeproj", "-scheme", "SWCompression"] destinations_actions = [(["-destination 'platform=OS X'"], ["clean", "test"]), (["-destination 'platform=iOS Simulator,name=iPhone 8'"], ["clean", "test"]), @@ -51,6 +59,8 @@ def action_ci(args): _ci_before_deploy() elif args.cmd == "install-macos": _ci_install_macos() + elif args.cmd == "install-linux": + _ci_install_linux() elif args.cmd == "script-linux": _ci_script_linux() elif args.cmd == "script-macos": @@ -93,7 +103,7 @@ subparsers = parser.add_subparsers(title="commands", help="a command to perform" # Parser for 'ci' command. parser_ci = subparsers.add_parser("ci", help="a subset of commands used by CI", description="a subset of commands used by CI") -parser_ci.add_argument("cmd", choices=["before-deploy", "install-macos", "script-linux", "script-macos"], +parser_ci.add_argument("cmd", choices=["before-deploy", "install-macos", "install-linux", "script-linux", "script-macos"], help="a command to perform on CI", metavar="CI_CMD") parser_ci.set_defaults(func=action_ci) From 14252fe6d6ebf0ca01fe00d76ee6cf9afec9cc50 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 16 Apr 2020 00:22:45 +0300 Subject: [PATCH 20/97] Add config file for azure pipelines As an experiment we will run azure pipelines alongside travis ci until the next major release. If it turns to out be more convenient then we will switch permanently. Note: deployment stage is not configured yet. Also there is potential to simplify the config using templates. --- azure-pipelines.yml | 61 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 azure-pipelines.yml diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 00000000..b0892baa --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,61 @@ +trigger: + branches: + include: + - develop + - release-* + - hotfix-* + tags: + include: + - '*' + +stages: +- stage: test + displayName: 'Build & Test' + jobs: + - job: macos + strategy: + matrix: + macosSwift50: + imageName: 'macOS-10.14' + DEVELOPER_DIR: '/Applications/Xcode_10.3.app' + macosSwift51: + imageName: 'macOS-10.15' + DEVELOPER_DIR: '/Applications/Xcode_11.3.1.app' + macosSwift52: + imageName: 'macOS-10.15' + DEVELOPER_DIR: '/Applications/Xcode_11.4.app' + pool: + vmImage: $(imageName) + steps: + - script: | + brew update + ./utils.py ci install-macos + displayName: 'Install' + - script: ./utils.py prepare-workspace macos + displayName: 'Prepare Workspace' + - script: ./utils.py ci script-macos + displayName: 'Build & Test' + - script: swift build -c release # Check Release build just in case. + displayName: 'Build SPM Release' + - job: linux + strategy: + matrix: + linuxSwift50: + imageName: 'ubuntu-18.04' + SWIFT_VERSION: '5.0' + linuxSwift51: + imageName: 'ubuntu-18.04' + SWIFT_VERSION: '5.1' + linuxSwift52: + imageName: 'ubuntu-18.04' + SWIFT_VERSION: '5.2' + pool: + vmImage: $(imageName) + steps: + - script: ./utils.py ci install-linux + displayName: 'Install' + - script: ./utils.py ci script-linux + displayName: 'Build SPM Debug & Release' +# - stage: Deploy +# dependsOn: Test +# condition: startsWith(variables['Build.SourceBranch'], 'refs/tags') # Deploy on tags only From 049bac586162d69f0e890b439326706c073f9859 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 16 Apr 2020 00:42:54 +0300 Subject: [PATCH 21/97] CI changes: add azp versions of utils.py commands (script and install) because of the different xcpretty formatter; fix curl command being printed weirdly --- azure-pipelines.yml | 4 ++-- utils.py | 45 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b0892baa..91f3b3a7 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -29,11 +29,11 @@ stages: steps: - script: | brew update - ./utils.py ci install-macos + ./utils.py ci install-macos-azp displayName: 'Install' - script: ./utils.py prepare-workspace macos displayName: 'Prepare Workspace' - - script: ./utils.py ci script-macos + - script: ./utils.py ci script-macos-azp displayName: 'Build & Test' - script: swift build -c release # Check Release build just in case. displayName: 'Build SPM Release' diff --git a/utils.py b/utils.py index 4e78e31f..011dcfa1 100755 --- a/utils.py +++ b/utils.py @@ -28,16 +28,16 @@ def _ci_install_macos(): _sprun(["git", "lfs", "install"]) _sprun(["gem", "install", "-N", "xcpretty-travis-formatter"]) +def _ci_install_macos_azp(): + _sprun(["brew", "install", "git-lfs"]) + _sprun(["git", "lfs", "install"]) + _sprun(["gem", "install", "-N", "xcpretty-azure-pipelines-formatter"]) + def _ci_install_linux(): - _sprun("curl -sL https://swiftenv.fuller.li/install.sh > install.sh", shell=True) + _sprun(["curl -sL https://swiftenv.fuller.li/install.sh > install.sh"], shell=True) _sprun(["cat", "install.sh"]) _sprun(["chmod", "+x", "install.sh"]) - _sprun(["./install.sh"]) - -def _ci_script_linux(): - _sprun(["swift", "--version"]) - _sprun(["swift", "build"]) - _sprun(["swift", "build", "-c", "release"]) + _sprun(["./install.sh"], shell=True) def _ci_script_macos(): _sprun(["swift", "--version"]) @@ -54,17 +54,41 @@ def _ci_script_macos(): xcpretty_command = ["xcpretty", "-f", "`xcpretty-travis-formatter`"] subprocess.run(xcpretty_command, stdin=xcodebuild_process.stdout, shell=True, check=True) +def _ci_script_macos_azp(): + _sprun(["swift", "--version"]) + xcodebuild_command_parts = ["xcodebuild", "-project", "SWCompression.xcodeproj", "-scheme", "SWCompression"] + destinations_actions = [(["-destination 'platform=OS X'"], ["clean", "test"]), + (["-destination 'platform=iOS Simulator,name=iPhone 8'"], ["clean", "test"]), + (["-destination 'platform=watchOS Simulator,name=Apple Watch - 38mm'"], ["clean", "build"]), + (["-destination 'platform=tvOS Simulator,name=Apple TV'"], ["clean", "test"])] + + for destination, action in destinations_actions: + xcodebuild_command = xcodebuild_command_parts + destination + action + print("+ {0} | xcpretty -f `xcpretty-azure-pipelines-formatter`".format(" ".join(xcodebuild_command))) + xcodebuild_process = subprocess.Popen(xcodebuild_command, stdout=subprocess.PIPE) + xcpretty_command = ["xcpretty", "-f", "`xcpretty-azure-pipelines-formatter`"] + subprocess.run(xcpretty_command, stdin=xcodebuild_process.stdout, shell=True, check=True) + +def _ci_script_linux(): + _sprun(["swift", "--version"]) + _sprun(["swift", "build"]) + _sprun(["swift", "build", "-c", "release"]) + def action_ci(args): if args.cmd == "before-deploy": _ci_before_deploy() elif args.cmd == "install-macos": _ci_install_macos() + elif args.cmd == "install-macos-azp": + _ci_install_macos_azp() elif args.cmd == "install-linux": _ci_install_linux() - elif args.cmd == "script-linux": - _ci_script_linux() elif args.cmd == "script-macos": _ci_script_macos() + elif args.cmd == "script-macos-azp": + _ci_script_macos_azp() + elif args.cmd == "script-linux": + _ci_script_linux() else: raise Exception("Unknown CI command") @@ -103,7 +127,8 @@ subparsers = parser.add_subparsers(title="commands", help="a command to perform" # Parser for 'ci' command. parser_ci = subparsers.add_parser("ci", help="a subset of commands used by CI", description="a subset of commands used by CI") -parser_ci.add_argument("cmd", choices=["before-deploy", "install-macos", "install-linux", "script-linux", "script-macos"], +parser_ci.add_argument("cmd", choices=["before-deploy", "install-macos", "install-macos-azp", "install-linux", + "script-macos", "script-macos-azp", "script-linux"], help="a command to perform on CI", metavar="CI_CMD") parser_ci.set_defaults(func=action_ci) From 741ef861c36d47b48a6f5659fc4b675e792c59ba Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 16 Apr 2020 00:44:12 +0300 Subject: [PATCH 22/97] Add azp badge to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 081ddea8..8ee3e83b 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Swift 5.X](https://img.shields.io/badge/Swift-5.X-blue.svg)](https://developer.apple.com/swift/) [![GitHub license](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://raw.githubusercontent.com/tsolomko/SWCompression/master/LICENSE) [![Build Status](https://travis-ci.com/tsolomko/SWCompression.svg?branch=develop)](https://travis-ci.com/tsolomko/SWCompression) +[![Build Status](https://dev.azure.com/tsolomko/SWCompression/_apis/build/status/tsolomko.SWCompression?branchName=develop)](https://dev.azure.com/tsolomko/SWCompression/_build/latest?definitionId=3&branchName=develop) A framework with (de)compression algorithms and functions for working with various archives and containers. From 153f805bd478c6d1e6bd899bb4e47d28ac2743b7 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 16 Apr 2020 13:42:37 +0300 Subject: [PATCH 23/97] CI changes: use ubuntu-18.04 on travis; run azp on all branches except master; don't use xcpretty and don't install it; remove azp-specific utils commands; set some env vars via os python module in utils.py to fix swift on linux issues; use -quiet argument for xcode to fix travis log length issues; remove verbosity from ci install linux step --- .travis.yml | 6 +++--- azure-pipelines.yml | 10 ++++----- utils.py | 50 ++++++++++----------------------------------- 3 files changed, 18 insertions(+), 48 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8411ffda..35832465 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,7 +50,7 @@ jobs: - stage: test language: generic os: linux - dist: xenial + dist: bionic env: - SWIFT_VERSION=5.0 install: @@ -60,7 +60,7 @@ jobs: - stage: test language: generic os: linux - dist: xenial + dist: bionic env: - SWIFT_VERSION=5.1 install: @@ -70,7 +70,7 @@ jobs: - stage: test language: generic os: linux - dist: xenial + dist: bionic env: - SWIFT_VERSION=5.2 install: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 91f3b3a7..12faf3de 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,9 +1,7 @@ trigger: branches: - include: - - develop - - release-* - - hotfix-* + exclude: + - master tags: include: - '*' @@ -29,11 +27,11 @@ stages: steps: - script: | brew update - ./utils.py ci install-macos-azp + ./utils.py ci install-macos displayName: 'Install' - script: ./utils.py prepare-workspace macos displayName: 'Prepare Workspace' - - script: ./utils.py ci script-macos-azp + - script: ./utils.py ci script-macos displayName: 'Build & Test' - script: swift build -c release # Check Release build just in case. displayName: 'Build SPM Release' diff --git a/utils.py b/utils.py index 011dcfa1..478761e2 100755 --- a/utils.py +++ b/utils.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import argparse +import os import subprocess import sys @@ -26,22 +27,13 @@ def _ci_before_deploy(): def _ci_install_macos(): _sprun(["brew", "install", "git-lfs"]) _sprun(["git", "lfs", "install"]) - _sprun(["gem", "install", "-N", "xcpretty-travis-formatter"]) - -def _ci_install_macos_azp(): - _sprun(["brew", "install", "git-lfs"]) - _sprun(["git", "lfs", "install"]) - _sprun(["gem", "install", "-N", "xcpretty-azure-pipelines-formatter"]) def _ci_install_linux(): - _sprun(["curl -sL https://swiftenv.fuller.li/install.sh > install.sh"], shell=True) - _sprun(["cat", "install.sh"]) - _sprun(["chmod", "+x", "install.sh"]) - _sprun(["./install.sh"], shell=True) + _sprun(["eval \"$(curl -sL https://swiftenv.fuller.li/install.sh)\""], shell=True) def _ci_script_macos(): _sprun(["swift", "--version"]) - xcodebuild_command_parts = ["xcodebuild", "-project", "SWCompression.xcodeproj", "-scheme", "SWCompression"] + xcodebuild_command_parts = ["xcodebuild", "-quiet", "-project", "SWCompression.xcodeproj", "-scheme", "SWCompression"] destinations_actions = [(["-destination 'platform=OS X'"], ["clean", "test"]), (["-destination 'platform=iOS Simulator,name=iPhone 8'"], ["clean", "test"]), (["-destination 'platform=watchOS Simulator,name=Apple Watch - 38mm'"], ["clean", "build"]), @@ -49,44 +41,25 @@ def _ci_script_macos(): for destination, action in destinations_actions: xcodebuild_command = xcodebuild_command_parts + destination + action - print("+ {0} | xcpretty -f `xcpretty-travis-formatter`".format(" ".join(xcodebuild_command))) - xcodebuild_process = subprocess.Popen(xcodebuild_command, stdout=subprocess.PIPE) - xcpretty_command = ["xcpretty", "-f", "`xcpretty-travis-formatter`"] - subprocess.run(xcpretty_command, stdin=xcodebuild_process.stdout, shell=True, check=True) - -def _ci_script_macos_azp(): - _sprun(["swift", "--version"]) - xcodebuild_command_parts = ["xcodebuild", "-project", "SWCompression.xcodeproj", "-scheme", "SWCompression"] - destinations_actions = [(["-destination 'platform=OS X'"], ["clean", "test"]), - (["-destination 'platform=iOS Simulator,name=iPhone 8'"], ["clean", "test"]), - (["-destination 'platform=watchOS Simulator,name=Apple Watch - 38mm'"], ["clean", "build"]), - (["-destination 'platform=tvOS Simulator,name=Apple TV'"], ["clean", "test"])] - - for destination, action in destinations_actions: - xcodebuild_command = xcodebuild_command_parts + destination + action - print("+ {0} | xcpretty -f `xcpretty-azure-pipelines-formatter`".format(" ".join(xcodebuild_command))) - xcodebuild_process = subprocess.Popen(xcodebuild_command, stdout=subprocess.PIPE) - xcpretty_command = ["xcpretty", "-f", "`xcpretty-azure-pipelines-formatter`"] - subprocess.run(xcpretty_command, stdin=xcodebuild_process.stdout, shell=True, check=True) + _sprun(xcodebuild_command) def _ci_script_linux(): - _sprun(["swift", "--version"]) - _sprun(["swift", "build"]) - _sprun(["swift", "build", "-c", "release"]) + env = os.environ.copy() + env["SWIFTENV_ROOT"] = env["HOME"] +"/.swiftenv" + env["PATH"] = env["SWIFTENV_ROOT"] + "/bin:" + env["SWIFTENV_ROOT"] + "/shims:"+ env["PATH"] + _sprun(["swift", "--version"], env=env) + _sprun(["swift", "build"], env=env) + _sprun(["swift", "build", "-c", "release"], env=env) def action_ci(args): if args.cmd == "before-deploy": _ci_before_deploy() elif args.cmd == "install-macos": _ci_install_macos() - elif args.cmd == "install-macos-azp": - _ci_install_macos_azp() elif args.cmd == "install-linux": _ci_install_linux() elif args.cmd == "script-macos": _ci_script_macos() - elif args.cmd == "script-macos-azp": - _ci_script_macos_azp() elif args.cmd == "script-linux": _ci_script_linux() else: @@ -127,8 +100,7 @@ subparsers = parser.add_subparsers(title="commands", help="a command to perform" # Parser for 'ci' command. parser_ci = subparsers.add_parser("ci", help="a subset of commands used by CI", description="a subset of commands used by CI") -parser_ci.add_argument("cmd", choices=["before-deploy", "install-macos", "install-macos-azp", "install-linux", - "script-macos", "script-macos-azp", "script-linux"], +parser_ci.add_argument("cmd", choices=["before-deploy", "install-macos", "install-linux", "script-macos", "script-linux"], help="a command to perform on CI", metavar="CI_CMD") parser_ci.set_defaults(func=action_ci) From 247def898ba4a7dd4e36bce1d0a71d65bad57953 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 16 Apr 2020 22:41:41 +0300 Subject: [PATCH 24/97] [BZip2][ZIP] Small code optimizations A variable in BZip2 code changed to let-constant and two fields of ZIP's "end of central directory" struct are no longer properties since they aren't used anywhere. --- Sources/BZip2/BZip2.swift | 2 +- Sources/ZIP/ZipEndOfCentralDirectory.swift | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Sources/BZip2/BZip2.swift b/Sources/BZip2/BZip2.swift index d1c9e8fb..ad717fbe 100644 --- a/Sources/BZip2/BZip2.swift +++ b/Sources/BZip2/BZip2.swift @@ -69,7 +69,7 @@ public class BZip2: DecompressionAlgorithm { guard isRandomized == 0 else { throw BZip2Error.randomizedBlock } - var pointer = bitReader.int(fromBits: 24) + let pointer = bitReader.int(fromBits: 24) func computeUsed() -> [Bool] { let huffmanUsedMap = bitReader.int(fromBits: 16) diff --git a/Sources/ZIP/ZipEndOfCentralDirectory.swift b/Sources/ZIP/ZipEndOfCentralDirectory.swift index 0fbdc706..9006c859 100644 --- a/Sources/ZIP/ZipEndOfCentralDirectory.swift +++ b/Sources/ZIP/ZipEndOfCentralDirectory.swift @@ -11,19 +11,21 @@ struct ZipEndOfCentralDirectory { /// Number of the current disk. private(set) var currentDiskNumber: UInt32 - /// Number of the disk with the start of CD. - private(set) var cdDiskNumber: UInt32 private(set) var cdEntries: UInt64 - private(set) var cdSize: UInt64 private(set) var cdOffset: UInt64 + // There are two fields in the EndOfCD that aren't currently used anywhere except in the initalizer. + // /// Number of the disk with the start of CD. + // private var cdDiskNumber: UInt32 + // private var cdSize: UInt64 + init(_ byteReader: LittleEndianByteReader) throws { /// Indicates if Zip64 records should be present. var zip64RecordExists = false self.currentDiskNumber = byteReader.uint32(fromBytes: 2) - self.cdDiskNumber = byteReader.uint32(fromBytes: 2) - guard self.currentDiskNumber == self.cdDiskNumber + var cdDiskNumber = byteReader.uint32(fromBytes: 2) + guard self.currentDiskNumber == cdDiskNumber else { throw ZipError.multiVolumesNotSupported } /// Number of CD entries on the current disk. @@ -34,7 +36,7 @@ struct ZipEndOfCentralDirectory { else { throw ZipError.multiVolumesNotSupported } /// Size of Central Directory. - self.cdSize = byteReader.uint64(fromBytes: 4) + var cdSize = byteReader.uint64(fromBytes: 4) /// Offset to the start of Central Directory. self.cdOffset = byteReader.uint64(fromBytes: 4) @@ -45,9 +47,9 @@ struct ZipEndOfCentralDirectory { // encoding: .utf8) // Check if zip64 records are present. - if self.currentDiskNumber == 0xFFFF || self.cdDiskNumber == 0xFFFF || + if self.currentDiskNumber == 0xFFFF || cdDiskNumber == 0xFFFF || cdEntriesCurrentDisk == 0xFFFF || self.cdEntries == 0xFFFF || - self.cdSize == 0xFFFFFFFF || self.cdOffset == 0xFFFFFFFF { + cdSize == 0xFFFFFFFF || self.cdOffset == 0xFFFFFFFF { zip64RecordExists = true } @@ -88,7 +90,7 @@ struct ZipEndOfCentralDirectory { // Update values read from basic End of CD with the ones from Zip64 End of CD. self.currentDiskNumber = byteReader.uint32() - self.cdDiskNumber = byteReader.uint32() + cdDiskNumber = byteReader.uint32() guard currentDiskNumber == cdDiskNumber else { throw ZipError.multiVolumesNotSupported } @@ -97,7 +99,7 @@ struct ZipEndOfCentralDirectory { guard cdEntries == cdEntriesCurrentDisk else { throw ZipError.multiVolumesNotSupported } - self.cdSize = byteReader.uint64() + cdSize = byteReader.uint64() self.cdOffset = byteReader.uint64() // Then, there might be 'zip64 extensible data sector' with 'special purpose data'. From 67f208a216847050e4bdecff6d295903d42a2b24 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Tue, 12 May 2020 23:32:57 +0300 Subject: [PATCH 25/97] Drop support for Swift 4 in podspec --- SWCompression.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SWCompression.podspec b/SWCompression.podspec index 582f64cd..04fa93a9 100644 --- a/SWCompression.podspec +++ b/SWCompression.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.tvos.deployment_target = "9.0" s.watchos.deployment_target = "2.0" - s.swift_versions = ["4", "5"] + s.swift_versions = ["5"] s.dependency "BitByteData", "~> 1.4.3" From 3cd927233199ae65ee4afc4a7bf793139487e5ed Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Tue, 12 May 2020 23:38:34 +0300 Subject: [PATCH 26/97] Fix azp issues --- utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.py b/utils.py index 478761e2..0d68d819 100755 --- a/utils.py +++ b/utils.py @@ -25,7 +25,7 @@ def _ci_before_deploy(): _sprun(["jazzy"]) def _ci_install_macos(): - _sprun(["brew", "install", "git-lfs"]) + _sprun(["brew", "upgrade", "git-lfs"]) _sprun(["git", "lfs", "install"]) def _ci_install_linux(): From a984486c62c5ff77d7f93a1a578bf075dcb8531a Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Mon, 18 May 2020 13:17:17 +0300 Subject: [PATCH 27/97] [swcomp] Don't print zip comment if it's empty --- .../ContainerEntryInfo+CustomStringConvertible.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/swcomp/Extensions/ContainerEntryInfo+CustomStringConvertible.swift b/Sources/swcomp/Extensions/ContainerEntryInfo+CustomStringConvertible.swift index 6dc152cd..997f82fd 100644 --- a/Sources/swcomp/Extensions/ContainerEntryInfo+CustomStringConvertible.swift +++ b/Sources/swcomp/Extensions/ContainerEntryInfo+CustomStringConvertible.swift @@ -62,7 +62,9 @@ extension ContainerEntryInfo where Self: CustomStringConvertible { } if let zipEntry = self as? ZipEntryInfo { - output += "Comment: \(zipEntry.comment)\n" + if !zipEntry.comment.isEmpty { + output += "Comment: \(zipEntry.comment)\n" + } output += String(format: "External File Attributes: 0x%08X\n", zipEntry.externalFileAttributes) output += "Is text file: \(zipEntry.isTextFile)\n" output += "File system type: \(zipEntry.fileSystemType)\n" From 8ef90146e725b973703979e0c08c4ffd064b200b Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Mon, 18 May 2020 13:18:32 +0300 Subject: [PATCH 28/97] [swcomp] Improve the usage of articles in help messages --- Sources/swcomp/Archives/BZip2Command.swift | 8 ++++---- Sources/swcomp/Archives/GZipCommand.swift | 10 +++++----- Sources/swcomp/Archives/LZMACommand.swift | 2 +- Sources/swcomp/Archives/XZCommand.swift | 2 +- Sources/swcomp/Benchmarks/BenchmarkGroup.swift | 2 +- Sources/swcomp/Containers/7ZipCommand.swift | 6 +++--- Sources/swcomp/Containers/TarCommand.swift | 10 +++++----- Sources/swcomp/Containers/ZipCommand.swift | 6 +++--- Sources/swcomp/main.swift | 2 +- 9 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Sources/swcomp/Archives/BZip2Command.swift b/Sources/swcomp/Archives/BZip2Command.swift index 6dafd247..d660f34a 100644 --- a/Sources/swcomp/Archives/BZip2Command.swift +++ b/Sources/swcomp/Archives/BZip2Command.swift @@ -10,14 +10,14 @@ import SwiftCLI class BZip2Command: Command { let name = "bz2" - let shortDescription = "Creates or extracts BZip2 archive" + let shortDescription = "Creates or extracts a BZip2 archive" - let compress = Flag("-c", "--compress", description: "Compress input file into BZip2 archive") - let decompress = Flag("-d", "--decompress", description: "Decompress BZip2 archive") + let compress = Flag("-c", "--compress", description: "Compress an input file into a BZip2 archive") + let decompress = Flag("-d", "--decompress", description: "Decompress a BZip2 archive") let blockSize = Key("-b", "--block-size", description: """ - Set block size for compression to a multiple of 100k bytes; \ + Set the block size for compression to a multiple of 100k bytes; \ possible values are from '1' (default) to '9' """) diff --git a/Sources/swcomp/Archives/GZipCommand.swift b/Sources/swcomp/Archives/GZipCommand.swift index be7d3b12..716aa60a 100644 --- a/Sources/swcomp/Archives/GZipCommand.swift +++ b/Sources/swcomp/Archives/GZipCommand.swift @@ -10,14 +10,14 @@ import SwiftCLI class GZipCommand: Command { let name = "gz" - let shortDescription = "Creates or extracts GZip archive" + let shortDescription = "Creates or extracts a GZip archive" - let compress = Flag("-c", "--compress", description: "Compress input file into GZip archive") - let decompress = Flag("-d", "--decompress", description: "Decompress GZip archive") - let info = Flag("-i", "--info", description: "Print information from GZip header") + let compress = Flag("-c", "--compress", description: "Compress an input file into a GZip archive") + let decompress = Flag("-d", "--decompress", description: "Decompress a GZip archive") + let info = Flag("-i", "--info", description: "Print information from a GZip header") let useGZipName = Flag("-n", "--use-gzip-name", - description: "Use name saved inside GZip archive as output path, if possible") + description: "Use the name saved inside a GZip archive as an output path, if possible") var optionGroups: [OptionGroup] { let actions = OptionGroup(options: [compress, decompress, info], restriction: .exactlyOne) diff --git a/Sources/swcomp/Archives/LZMACommand.swift b/Sources/swcomp/Archives/LZMACommand.swift index bf360d1b..d5d8f3d2 100644 --- a/Sources/swcomp/Archives/LZMACommand.swift +++ b/Sources/swcomp/Archives/LZMACommand.swift @@ -10,7 +10,7 @@ import SwiftCLI class LZMACommand: Command { let name = "lzma" - let shortDescription = "Extracts LZMA archive" + let shortDescription = "Extracts a LZMA archive" let archive = Parameter() let outputPath = OptionalParameter() diff --git a/Sources/swcomp/Archives/XZCommand.swift b/Sources/swcomp/Archives/XZCommand.swift index 34636f2f..4251400b 100644 --- a/Sources/swcomp/Archives/XZCommand.swift +++ b/Sources/swcomp/Archives/XZCommand.swift @@ -10,7 +10,7 @@ import SwiftCLI class XZCommand: Command { let name = "xz" - let shortDescription = "Extracts XZ archive" + let shortDescription = "Extracts a XZ archive" let archive = Parameter() let outputPath = OptionalParameter() diff --git a/Sources/swcomp/Benchmarks/BenchmarkGroup.swift b/Sources/swcomp/Benchmarks/BenchmarkGroup.swift index 26e625b3..ea7150c7 100644 --- a/Sources/swcomp/Benchmarks/BenchmarkGroup.swift +++ b/Sources/swcomp/Benchmarks/BenchmarkGroup.swift @@ -9,7 +9,7 @@ import SwiftCLI class BenchmarkGroup: CommandGroup { let name = "benchmark" - let shortDescription = "Run specified benchmark using external files" + let shortDescription = "Run the specified benchmark using external files" let children: [Routable] = [UnGzip(), UnXz(), UnBz2(), InfoTar(), InfoZip(), Info7z(), CompDeflate(), CompBz2()] diff --git a/Sources/swcomp/Containers/7ZipCommand.swift b/Sources/swcomp/Containers/7ZipCommand.swift index 56e20a02..1ef28412 100644 --- a/Sources/swcomp/Containers/7ZipCommand.swift +++ b/Sources/swcomp/Containers/7ZipCommand.swift @@ -10,10 +10,10 @@ import SwiftCLI class SevenZipCommand: ContainerCommand { let name = "7z" - let shortDescription = "Extracts 7-Zip container" + let shortDescription = "Extracts a 7-Zip container" - let info = Flag("-i", "--info", description: "Print list of entries in container and their attributes") - let extract = Key("-e", "--extract", description: "Extract container into specified directory") + let info = Flag("-i", "--info", description: "Print the list of entries in a container and their attributes") + let extract = Key("-e", "--extract", description: "Extract a container into the specified directory") let verbose = Flag("-v", "--verbose", description: "Print the list of extracted files and directories.") let archive = Parameter() diff --git a/Sources/swcomp/Containers/TarCommand.swift b/Sources/swcomp/Containers/TarCommand.swift index df03f19b..08390d73 100644 --- a/Sources/swcomp/Containers/TarCommand.swift +++ b/Sources/swcomp/Containers/TarCommand.swift @@ -10,17 +10,17 @@ import SwiftCLI class TarCommand: Command { let name = "tar" - let shortDescription = "Extracts TAR container" + let shortDescription = "Extracts a TAR container" let gz = Flag("-z", "--gz", description: "Decompress with GZip first") let bz2 = Flag("-j", "--bz2", description: "Decompress with BZip2 first") let xz = Flag("-x", "--xz", description: "Decompress with XZ first") - let info = Flag("-i", "--info", description: "Print list of entries in container and their attributes") - let extract = Key("-e", "--extract", description: "Extract container into specified directory") - let format = Flag("-f", "--format", description: "Print \"format\" of the container") + let info = Flag("-i", "--info", description: "Print the list of entries in a container and their attributes") + let extract = Key("-e", "--extract", description: "Extract a container into specified directory") + let format = Flag("-f", "--format", description: "Print the \"format\" of a container") let create = Key("-c", "--create", - description: "Create a new container containing specified file/directory (recursively)") + description: "Create a new container containing the specified file/directory (recursively)") let verbose = Flag("-v", "--verbose", description: "Print the list of extracted files and directories.") diff --git a/Sources/swcomp/Containers/ZipCommand.swift b/Sources/swcomp/Containers/ZipCommand.swift index 95ea0491..52fe2403 100644 --- a/Sources/swcomp/Containers/ZipCommand.swift +++ b/Sources/swcomp/Containers/ZipCommand.swift @@ -10,10 +10,10 @@ import SwiftCLI class ZipCommand: ContainerCommand { let name = "zip" - let shortDescription = "Extracts ZIP container" + let shortDescription = "Extracts a ZIP container" - let info = Flag("-i", "--info", description: "Print list of entries in container and their attributes") - let extract = Key("-e", "--extract", description: "Extract container into specified directory") + let info = Flag("-i", "--info", description: "Print the list of entries in a container and their attributes") + let extract = Key("-e", "--extract", description: "Extract a container into the specified directory") let verbose = Flag("-v", "--verbose", description: "Print the list of extracted files and directories.") let archive = Parameter() diff --git a/Sources/swcomp/main.swift b/Sources/swcomp/main.swift index 89ee03e2..9b8654a5 100644 --- a/Sources/swcomp/main.swift +++ b/Sources/swcomp/main.swift @@ -9,7 +9,7 @@ import SwiftCLI let cli = CLI(name: "swcomp", version: "4.5.5", description: """ - swcomp - small command-line client for SWCompression framework. + swcomp - a small command-line client for SWCompression framework. Serves as an example of SWCompression usage. """) cli.commands = [XZCommand(), From d4e261675e1b181a4c34f92225f0abb9ea258b3e Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 24 Sep 2020 11:01:59 +0300 Subject: [PATCH 29/97] Add -d option to utils.py prepare-workspace to build bbd in debug mode on macos --- utils.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/utils.py b/utils.py index 0d68d819..65841428 100755 --- a/utils.py +++ b/utils.py @@ -76,13 +76,16 @@ def action_cw(args): _sprun(["rm", "-f", "Package.resolved"]) _sprun(["rm", "-f", "SWCompression.framework.zip"]) -def _pw_macos(): +def _pw_macos(debug): print("=> Downloading dependency (BitByteData) using Carthage") - _sprun(["carthage", "bootstrap"]) + if debug: + _sprun(["carthage", "bootstrap", "--configuration", "Debug", "--no-use-binaries"]) + else: + _sprun(["carthage", "bootstrap"]) def action_pw(args): if args.os == "macos": - _pw_macos() + _pw_macos(args.debug) elif args.os == "other": pass else: @@ -115,6 +118,8 @@ parser_pw = subparsers.add_parser("prepare-workspace", help="prepare workspace", parser_pw.add_argument("os", choices=["macos", "other"], help="development operating system", metavar="OS") parser_pw.add_argument("--no-test-files", "-T", action="store_true", dest="no_test_files", help="don't download example files used for testing") +parser_pw.add_argument("--debug", "-d", action="store_true", dest="debug", + help="build BitByteData in Debug configuration") parser_pw.set_defaults(func=action_pw) args = parser.parse_args() From a69ff5f389bdb5ff825ffbc452ab78ef98cbec59 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Mon, 5 Oct 2020 13:02:25 +0300 Subject: [PATCH 30/97] Perform xcode project upgrade Added base internationalization and changed development language to stop xcode from complaining, increased minimum ios deployment target to 9.0, project is now compatible with xcode 10 or later. --- SWCompression.xcodeproj/project.pbxproj | 13 +++++----- .../xcschemes/SWCompression.xcscheme | 24 ++++++++----------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index 83eb2cfa..aee91300 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ @@ -928,7 +928,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = "Timofey Solomko"; TargetAttributes = { 06BE1AC71DB410F100EE0F59 = { @@ -942,11 +942,12 @@ }; }; buildConfigurationList = 06BE1AC21DB410F100EE0F59 /* Build configuration list for PBXProject "SWCompression" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = English; + compatibilityVersion = "Xcode 10.0"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 06BE1ABE1DB410F100EE0F59; productRefGroup = 06BE1AC91DB410F100EE0F59 /* Products */; @@ -1259,7 +1260,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; OTHER_CODE_SIGN_FLAGS = "--deep"; @@ -1316,7 +1317,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_CODE_SIGN_FLAGS = "--deep"; OTHER_LDFLAGS = ( diff --git a/SWCompression.xcodeproj/xcshareddata/xcschemes/SWCompression.xcscheme b/SWCompression.xcodeproj/xcshareddata/xcschemes/SWCompression.xcscheme index 0f4b19d0..18ba22e1 100644 --- a/SWCompression.xcodeproj/xcshareddata/xcschemes/SWCompression.xcscheme +++ b/SWCompression.xcodeproj/xcshareddata/xcschemes/SWCompression.xcscheme @@ -1,6 +1,6 @@ + + + + - - - - - - - - Date: Mon, 5 Oct 2020 13:03:03 +0300 Subject: [PATCH 31/97] Fix a copy-paste typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ee3e83b..f77b6811 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ BZip2 and LZMA/LZMA2 support). ### Carthage -__Important:__ Only Swift 5.x is supported when installing BitByteData via Carthage. +__Important:__ Only Swift 5.x is supported when installing SWCompression via Carthage. Add to your Cartfile `github "tsolomko/SWCompression" ~> 4.5`. From d091498e3e3566beefe921ef53fc7dc6fee21483 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Mon, 5 Oct 2020 13:15:26 +0300 Subject: [PATCH 32/97] CI updates: enable testing with swift 5.3 in AZP, add temporary script which work arounds the issue with carthage, fix an issue with installing/upgrading git-lfs. --- .travis.yml | 9 +-------- azure-pipelines.yml | 6 ++++++ bbd-bootstrap.sh | 15 +++++++++++++++ utils.py | 19 +++++++++++++++---- 4 files changed, 37 insertions(+), 12 deletions(-) create mode 100755 bbd-bootstrap.sh diff --git a/.travis.yml b/.travis.yml index e9f7d142..056bbbbc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,14 +58,7 @@ jobs: install: - ./utils.py ci install-macos before_script: - # - ./utils.py prepare-workspace macos - # TODO: Remove lines below when Carthage gets a workaround for problems with Xcode 12 - - xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX) - - trap 'rm -f "$xcconfig"' INT TERM HUP EXIT - - echo 'EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200 = arm64 arm64e armv7 armv7s armv6 armv8' >> $xcconfig - - echo 'EXCLUDED_ARCHS = $(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(EFFECTIVE_PLATFORM_SUFFIX)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT)__XCODE_$(XCODE_VERSION_MAJOR))' >> $xcconfig - - export XCODE_XCCONFIG_FILE="$xcconfig" - - carthage bootstrap + - ./utils.py prepare-workspace macos script: - ./utils.py ci script-macos - stage: test diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 12faf3de..aa57b511 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -22,6 +22,9 @@ stages: macosSwift52: imageName: 'macOS-10.15' DEVELOPER_DIR: '/Applications/Xcode_11.4.app' + macosSwift53: + imageName: 'macOS-10.15' + DEVELOPER_DIR: '/Applications/Xcode_12.app' pool: vmImage: $(imageName) steps: @@ -47,6 +50,9 @@ stages: linuxSwift52: imageName: 'ubuntu-18.04' SWIFT_VERSION: '5.2' + linuxSwift53: + imageName: 'ubuntu-18.04' + SWIFT_VERSION: '5.3' pool: vmImage: $(imageName) steps: diff --git a/bbd-bootstrap.sh b/bbd-bootstrap.sh new file mode 100755 index 00000000..0007bbf7 --- /dev/null +++ b/bbd-bootstrap.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# Temporary solution until the issue with Carthage is fixed + +set -euo pipefail + +xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX) +trap 'rm -f "$xcconfig"' INT TERM HUP EXIT + +# For Xcode 12 (beta 3+) make sure EXCLUDED_ARCHS is set to arm architectures otherwise +# the build will fail on lipo due to duplicate architectures. +echo 'EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200 = arm64 arm64e armv7 armv7s armv6 armv8' >> $xcconfig +echo 'EXCLUDED_ARCHS = $(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(EFFECTIVE_PLATFORM_SUFFIX)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT)__XCODE_$(XCODE_VERSION_MAJOR))' >> $xcconfig + +export XCODE_XCCONFIG_FILE="$xcconfig" +carthage bootstrap "$@" diff --git a/utils.py b/utils.py index 65841428..1b536f84 100755 --- a/utils.py +++ b/utils.py @@ -25,7 +25,12 @@ def _ci_before_deploy(): _sprun(["jazzy"]) def _ci_install_macos(): - _sprun(["brew", "upgrade", "git-lfs"]) + script = """if brew ls --versions "git-lfs" >/dev/null; then + HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade "git-lfs" + else + HOMEBREW_NO_AUTO_UPDATE=1 brew install "git-lfs" + fi""" + _sprun([script], shell=True) _sprun(["git", "lfs", "install"]) def _ci_install_linux(): @@ -79,10 +84,16 @@ def action_cw(args): def _pw_macos(debug): print("=> Downloading dependency (BitByteData) using Carthage") if debug: - _sprun(["carthage", "bootstrap", "--configuration", "Debug", "--no-use-binaries"]) + # _sprun(["carthage", "bootstrap", "--configuration", "Debug", "--no-use-binaries"]) + # TODO: Temporary solution until the issue with Carthage is fixed + script = "./bbd-bootstrap.sh --configuration Debug --no-use-binaries" + _sprun([script], shell=True) else: - _sprun(["carthage", "bootstrap"]) - + # _sprun(["carthage", "bootstrap"]) + # TODO: Temporary solution until the issue with Carthage is fixed + script = "./bbd-bootstrap.sh" + _sprun([script], shell=True) + def action_pw(args): if args.os == "macos": _pw_macos(args.debug) From 83f64b439e5474135b75c3776e814a9c2512de00 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Mon, 26 Oct 2020 16:25:22 +0200 Subject: [PATCH 33/97] CI changes (both azp and travis): use latest patch versions of swift on linux, use latest xcode for swfit 5.3, use ubuntu 20.04 on linux --- .travis.yml | 12 ++++++------ azure-pipelines.yml | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 056bbbbc..ee8e282e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,7 +50,7 @@ jobs: - stage: test language: swift os: osx - osx_image: xcode12 # Swift 5.3 + osx_image: xcode12.3 # Swift 5.3 env: - HOMEBREW_NO_INSTALL_CLEANUP=1 before_install: @@ -66,7 +66,7 @@ jobs: os: linux dist: bionic env: - - SWIFT_VERSION=5.0 + - SWIFT_VERSION=5.0.3 install: - ./utils.py ci install-linux script: @@ -76,7 +76,7 @@ jobs: os: linux dist: bionic env: - - SWIFT_VERSION=5.1 + - SWIFT_VERSION=5.1.5 install: - ./utils.py ci install-linux script: @@ -86,7 +86,7 @@ jobs: os: linux dist: bionic env: - - SWIFT_VERSION=5.2 + - SWIFT_VERSION=5.2.5 install: - ./utils.py ci install-linux script: @@ -94,9 +94,9 @@ jobs: - stage: test language: generic os: linux - dist: xenial + dist: focal env: - - SWIFT_VERSION=5.3 + - SWIFT_VERSION=5.3.2 install: - eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" script: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index aa57b511..9164e0af 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -21,10 +21,10 @@ stages: DEVELOPER_DIR: '/Applications/Xcode_11.3.1.app' macosSwift52: imageName: 'macOS-10.15' - DEVELOPER_DIR: '/Applications/Xcode_11.4.app' + DEVELOPER_DIR: '/Applications/Xcode_11.4.1.app' macosSwift53: imageName: 'macOS-10.15' - DEVELOPER_DIR: '/Applications/Xcode_12.app' + DEVELOPER_DIR: '/Applications/Xcode_12.3.app' pool: vmImage: $(imageName) steps: @@ -43,16 +43,16 @@ stages: matrix: linuxSwift50: imageName: 'ubuntu-18.04' - SWIFT_VERSION: '5.0' + SWIFT_VERSION: '5.0.3' linuxSwift51: imageName: 'ubuntu-18.04' - SWIFT_VERSION: '5.1' + SWIFT_VERSION: '5.1.5' linuxSwift52: imageName: 'ubuntu-18.04' - SWIFT_VERSION: '5.2' + SWIFT_VERSION: '5.2.5' linuxSwift53: - imageName: 'ubuntu-18.04' - SWIFT_VERSION: '5.3' + imageName: 'ubuntu-20.04' + SWIFT_VERSION: '5.3.2' pool: vmImage: $(imageName) steps: From e83f23effa4671a06290bccea9bf64897f0d139e Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Tue, 5 Jan 2021 15:58:22 +0200 Subject: [PATCH 34/97] Update copyright year to 2021 --- .jazzy.yaml | 2 +- LICENSE | 2 +- SWCompression.xcodeproj/SWCompression.plist | 2 +- Sources/7-Zip/7zCoder+Equatable.swift | 2 +- Sources/7-Zip/7zCoder.swift | 2 +- Sources/7-Zip/7zCoderInfo.swift | 2 +- Sources/7-Zip/7zContainer.swift | 2 +- Sources/7-Zip/7zEntry.swift | 2 +- Sources/7-Zip/7zEntryInfo.swift | 2 +- Sources/7-Zip/7zError.swift | 2 +- Sources/7-Zip/7zFileInfo.swift | 2 +- Sources/7-Zip/7zFolder.swift | 2 +- Sources/7-Zip/7zHeader.swift | 2 +- Sources/7-Zip/7zPackInfo.swift | 2 +- Sources/7-Zip/7zProperty.swift | 2 +- Sources/7-Zip/7zStreamInfo.swift | 2 +- Sources/7-Zip/7zSubstreamInfo.swift | 2 +- Sources/7-Zip/CompressionMethod+7z.swift | 2 +- Sources/7-Zip/MsbBitReader+7z.swift | 2 +- Sources/BZip2/BZip2+BlockSize.swift | 2 +- Sources/BZip2/BZip2+Compress.swift | 2 +- Sources/BZip2/BZip2+Lengths.swift | 2 +- Sources/BZip2/BZip2.swift | 2 +- Sources/BZip2/BZip2Error.swift | 2 +- Sources/BZip2/BurrowsWheeler.swift | 2 +- Sources/BZip2/SuffixArray.swift | 2 +- Sources/Common/Archive.swift | 2 +- Sources/Common/CheckSums.swift | 2 +- Sources/Common/CodingTree/Code.swift | 2 +- Sources/Common/CodingTree/CodeLength.swift | 2 +- Sources/Common/CodingTree/DecodingTree.swift | 2 +- Sources/Common/CodingTree/EncodingTree.swift | 2 +- Sources/Common/CompressionAlgorithm.swift | 2 +- Sources/Common/CompressionMethod.swift | 2 +- Sources/Common/Container/Container.swift | 2 +- Sources/Common/Container/ContainerEntry.swift | 2 +- Sources/Common/Container/ContainerEntryInfo.swift | 2 +- Sources/Common/Container/ContainerEntryType.swift | 2 +- Sources/Common/Container/DosAttributes.swift | 2 +- Sources/Common/Container/Permissions.swift | 2 +- Sources/Common/DecompressionAlgorithm.swift | 2 +- Sources/Common/DeltaFilter.swift | 2 +- Sources/Common/Extensions.swift | 2 +- Sources/Common/FileSystemType.swift | 2 +- Sources/Deflate/Deflate+Compress.swift | 2 +- Sources/Deflate/Deflate+Constants.swift | 2 +- Sources/Deflate/Deflate+Lengths.swift | 2 +- Sources/Deflate/Deflate.swift | 2 +- Sources/Deflate/DeflateError.swift | 2 +- Sources/GZip/FileSystemType+Gzip.swift | 2 +- Sources/GZip/GzipArchive.swift | 2 +- Sources/GZip/GzipError.swift | 2 +- Sources/GZip/GzipHeader.swift | 2 +- Sources/LZMA/LZMA.swift | 2 +- Sources/LZMA/LZMABitTreeDecoder.swift | 2 +- Sources/LZMA/LZMAConstants.swift | 2 +- Sources/LZMA/LZMADecoder.swift | 2 +- Sources/LZMA/LZMAError.swift | 2 +- Sources/LZMA/LZMALenDecoder.swift | 2 +- Sources/LZMA/LZMAProperties.swift | 2 +- Sources/LZMA/LZMARangeDecoder.swift | 2 +- Sources/LZMA2/LZMA2.swift | 2 +- Sources/LZMA2/LZMA2Decoder.swift | 2 +- Sources/LZMA2/LZMA2Error.swift | 2 +- Sources/TAR/ByteReader+Tar.swift | 2 +- Sources/TAR/ContainerEntryType+Tar.swift | 2 +- Sources/TAR/TarContainer.swift | 2 +- Sources/TAR/TarCreateError.swift | 2 +- Sources/TAR/TarEntry.swift | 2 +- Sources/TAR/TarEntryInfo.swift | 2 +- Sources/TAR/TarEntryInfoProvider.swift | 2 +- Sources/TAR/TarError.swift | 2 +- Sources/TAR/TarExtendedHeader.swift | 2 +- Sources/XZ/ByteReader+XZ.swift | 2 +- Sources/XZ/Sha256.swift | 2 +- Sources/XZ/XZArchive.swift | 2 +- Sources/XZ/XZBlock.swift | 2 +- Sources/XZ/XZError.swift | 2 +- Sources/XZ/XZStreamHeader.swift | 2 +- Sources/ZIP/BuiltinExtraFields.swift | 2 +- Sources/ZIP/ByteReader+Zip.swift | 2 +- Sources/ZIP/CompressionMethod+Zip.swift | 2 +- Sources/ZIP/FileSystemType+Zip.swift | 2 +- Sources/ZIP/ZipCentralDirectoryEntry.swift | 2 +- Sources/ZIP/ZipContainer.swift | 2 +- Sources/ZIP/ZipEndOfCentralDirectory.swift | 2 +- Sources/ZIP/ZipEntry.swift | 2 +- Sources/ZIP/ZipEntryInfo.swift | 2 +- Sources/ZIP/ZipEntryInfoHelper.swift | 2 +- Sources/ZIP/ZipError.swift | 2 +- Sources/ZIP/ZipExtraField.swift | 2 +- Sources/ZIP/ZipLocalHeader.swift | 2 +- Sources/Zlib/ZlibArchive.swift | 2 +- Sources/Zlib/ZlibError.swift | 2 +- Sources/Zlib/ZlibHeader.swift | 2 +- Sources/swcomp/Archives/BZip2Command.swift | 2 +- Sources/swcomp/Archives/GZipCommand.swift | 2 +- Sources/swcomp/Archives/LZMACommand.swift | 2 +- Sources/swcomp/Archives/XZCommand.swift | 2 +- Sources/swcomp/Benchmarks/BenchmarkCommand.swift | 2 +- Sources/swcomp/Benchmarks/BenchmarkGroup.swift | 2 +- Sources/swcomp/Benchmarks/CompBz2.swift | 2 +- Sources/swcomp/Benchmarks/CompDeflate.swift | 2 +- Sources/swcomp/Benchmarks/Info7z.swift | 2 +- Sources/swcomp/Benchmarks/InfoTar.swift | 2 +- Sources/swcomp/Benchmarks/InfoZip.swift | 2 +- Sources/swcomp/Benchmarks/UnBz2.swift | 2 +- Sources/swcomp/Benchmarks/UnGzip.swift | 2 +- Sources/swcomp/Benchmarks/UnXz.swift | 2 +- Sources/swcomp/Containers/7ZipCommand.swift | 2 +- Sources/swcomp/Containers/CommonFunctions.swift | 2 +- Sources/swcomp/Containers/ContainerCommand.swift | 2 +- Sources/swcomp/Containers/TarCommand.swift | 2 +- Sources/swcomp/Containers/ZipCommand.swift | 2 +- Sources/swcomp/Extensions/BlockSize+Keyable.swift | 2 +- .../Extensions/CompressionMethod+CustomStringConvertible.swift | 2 +- .../Extensions/ContainerEntryInfo+CustomStringConvertible.swift | 2 +- .../Extensions/FileSystemType+CustomStringConvertible.swift | 2 +- .../swcomp/Extensions/GzipHeader+CustomStringConvertible.swift | 2 +- Sources/swcomp/main.swift | 2 +- Tests/BZip2CompressionTests.swift | 2 +- Tests/BZip2Tests.swift | 2 +- Tests/Constants.swift | 2 +- Tests/DeflateCompressionTests.swift | 2 +- Tests/GzipTests.swift | 2 +- Tests/LzmaTests.swift | 2 +- Tests/SevenZipTests.swift | 2 +- Tests/Sha256Tests.swift | 2 +- Tests/TarCreateTests.swift | 2 +- Tests/TarTests.swift | 2 +- Tests/TestZipExtraField.swift | 2 +- Tests/XzTests.swift | 2 +- Tests/ZipTests.swift | 2 +- Tests/ZlibTests.swift | 2 +- 134 files changed, 134 insertions(+), 134 deletions(-) diff --git a/.jazzy.yaml b/.jazzy.yaml index 6fa59613..2b2abf98 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -4,7 +4,7 @@ clean: true author: Timofey Solomko module: SWCompression module_version: 4.5.7 -copyright: '© 2020 Timofey Solomko' +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.7 diff --git a/LICENSE b/LICENSE index 536dba60..005f75c9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Timofey Solomko +Copyright (c) 2021 Timofey Solomko Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/SWCompression.xcodeproj/SWCompression.plist b/SWCompression.xcodeproj/SWCompression.plist index 46a41309..7c77252a 100644 --- a/SWCompression.xcodeproj/SWCompression.plist +++ b/SWCompression.xcodeproj/SWCompression.plist @@ -19,6 +19,6 @@ CFBundleVersion 74 NSHumanReadableCopyright - Copyright © 2020 Timofey Solomko. All rights reserved. + Copyright © 2021 Timofey Solomko. All rights reserved. diff --git a/Sources/7-Zip/7zCoder+Equatable.swift b/Sources/7-Zip/7zCoder+Equatable.swift index c3e0aee5..40d5b20f 100644 --- a/Sources/7-Zip/7zCoder+Equatable.swift +++ b/Sources/7-Zip/7zCoder+Equatable.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zCoder.swift b/Sources/7-Zip/7zCoder.swift index 063c79c7..42d5f011 100644 --- a/Sources/7-Zip/7zCoder.swift +++ b/Sources/7-Zip/7zCoder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zCoderInfo.swift b/Sources/7-Zip/7zCoderInfo.swift index 66e7af7d..1e7757f1 100644 --- a/Sources/7-Zip/7zCoderInfo.swift +++ b/Sources/7-Zip/7zCoderInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zContainer.swift b/Sources/7-Zip/7zContainer.swift index d9fa1794..ff7b1892 100644 --- a/Sources/7-Zip/7zContainer.swift +++ b/Sources/7-Zip/7zContainer.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zEntry.swift b/Sources/7-Zip/7zEntry.swift index 1548086a..672f96e9 100644 --- a/Sources/7-Zip/7zEntry.swift +++ b/Sources/7-Zip/7zEntry.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zEntryInfo.swift b/Sources/7-Zip/7zEntryInfo.swift index 91a02274..63da9a0d 100644 --- a/Sources/7-Zip/7zEntryInfo.swift +++ b/Sources/7-Zip/7zEntryInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zError.swift b/Sources/7-Zip/7zError.swift index e73426ac..4868d656 100644 --- a/Sources/7-Zip/7zError.swift +++ b/Sources/7-Zip/7zError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zFileInfo.swift b/Sources/7-Zip/7zFileInfo.swift index 61b1da80..5dc2b7d5 100644 --- a/Sources/7-Zip/7zFileInfo.swift +++ b/Sources/7-Zip/7zFileInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zFolder.swift b/Sources/7-Zip/7zFolder.swift index da62994c..a463f3e5 100644 --- a/Sources/7-Zip/7zFolder.swift +++ b/Sources/7-Zip/7zFolder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zHeader.swift b/Sources/7-Zip/7zHeader.swift index abbe9751..7be81d17 100644 --- a/Sources/7-Zip/7zHeader.swift +++ b/Sources/7-Zip/7zHeader.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zPackInfo.swift b/Sources/7-Zip/7zPackInfo.swift index c076272b..b4af78d3 100644 --- a/Sources/7-Zip/7zPackInfo.swift +++ b/Sources/7-Zip/7zPackInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zProperty.swift b/Sources/7-Zip/7zProperty.swift index a2a64203..b719c96f 100644 --- a/Sources/7-Zip/7zProperty.swift +++ b/Sources/7-Zip/7zProperty.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zStreamInfo.swift b/Sources/7-Zip/7zStreamInfo.swift index bc37a035..022ba096 100644 --- a/Sources/7-Zip/7zStreamInfo.swift +++ b/Sources/7-Zip/7zStreamInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/7zSubstreamInfo.swift b/Sources/7-Zip/7zSubstreamInfo.swift index 3d5ed598..da691d3b 100644 --- a/Sources/7-Zip/7zSubstreamInfo.swift +++ b/Sources/7-Zip/7zSubstreamInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/CompressionMethod+7z.swift b/Sources/7-Zip/CompressionMethod+7z.swift index a4aeea96..65ce4b9e 100644 --- a/Sources/7-Zip/CompressionMethod+7z.swift +++ b/Sources/7-Zip/CompressionMethod+7z.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/7-Zip/MsbBitReader+7z.swift b/Sources/7-Zip/MsbBitReader+7z.swift index e4b18798..141df1ee 100644 --- a/Sources/7-Zip/MsbBitReader+7z.swift +++ b/Sources/7-Zip/MsbBitReader+7z.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/BZip2+BlockSize.swift b/Sources/BZip2/BZip2+BlockSize.swift index aca076eb..de5debc9 100644 --- a/Sources/BZip2/BZip2+BlockSize.swift +++ b/Sources/BZip2/BZip2+BlockSize.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/BZip2+Compress.swift b/Sources/BZip2/BZip2+Compress.swift index c7a7a72d..6222bd9a 100644 --- a/Sources/BZip2/BZip2+Compress.swift +++ b/Sources/BZip2/BZip2+Compress.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/BZip2+Lengths.swift b/Sources/BZip2/BZip2+Lengths.swift index aabf655e..a6c00037 100644 --- a/Sources/BZip2/BZip2+Lengths.swift +++ b/Sources/BZip2/BZip2+Lengths.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/BZip2.swift b/Sources/BZip2/BZip2.swift index aed1442f..07c01588 100644 --- a/Sources/BZip2/BZip2.swift +++ b/Sources/BZip2/BZip2.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/BZip2Error.swift b/Sources/BZip2/BZip2Error.swift index 849782c2..9b41537d 100644 --- a/Sources/BZip2/BZip2Error.swift +++ b/Sources/BZip2/BZip2Error.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/BurrowsWheeler.swift b/Sources/BZip2/BurrowsWheeler.swift index ae46a2ee..d08b64ca 100644 --- a/Sources/BZip2/BurrowsWheeler.swift +++ b/Sources/BZip2/BurrowsWheeler.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/BZip2/SuffixArray.swift b/Sources/BZip2/SuffixArray.swift index 13a8c471..6c208d61 100644 --- a/Sources/BZip2/SuffixArray.swift +++ b/Sources/BZip2/SuffixArray.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Archive.swift b/Sources/Common/Archive.swift index b9e68111..604026d0 100644 --- a/Sources/Common/Archive.swift +++ b/Sources/Common/Archive.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CheckSums.swift b/Sources/Common/CheckSums.swift index da9fd8ef..0c926afa 100644 --- a/Sources/Common/CheckSums.swift +++ b/Sources/Common/CheckSums.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CodingTree/Code.swift b/Sources/Common/CodingTree/Code.swift index 8dc4aa87..5f4f1d57 100644 --- a/Sources/Common/CodingTree/Code.swift +++ b/Sources/Common/CodingTree/Code.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CodingTree/CodeLength.swift b/Sources/Common/CodingTree/CodeLength.swift index e1f7d952..17a94c9a 100644 --- a/Sources/Common/CodingTree/CodeLength.swift +++ b/Sources/Common/CodingTree/CodeLength.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CodingTree/DecodingTree.swift b/Sources/Common/CodingTree/DecodingTree.swift index 5af7a020..f6a7d092 100644 --- a/Sources/Common/CodingTree/DecodingTree.swift +++ b/Sources/Common/CodingTree/DecodingTree.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CodingTree/EncodingTree.swift b/Sources/Common/CodingTree/EncodingTree.swift index fbfe8602..a0fc7f8f 100644 --- a/Sources/Common/CodingTree/EncodingTree.swift +++ b/Sources/Common/CodingTree/EncodingTree.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CompressionAlgorithm.swift b/Sources/Common/CompressionAlgorithm.swift index 746fc965..7b439e49 100644 --- a/Sources/Common/CompressionAlgorithm.swift +++ b/Sources/Common/CompressionAlgorithm.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/CompressionMethod.swift b/Sources/Common/CompressionMethod.swift index 602b1604..6b497e27 100644 --- a/Sources/Common/CompressionMethod.swift +++ b/Sources/Common/CompressionMethod.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Container/Container.swift b/Sources/Common/Container/Container.swift index 938687dc..23c54216 100644 --- a/Sources/Common/Container/Container.swift +++ b/Sources/Common/Container/Container.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Container/ContainerEntry.swift b/Sources/Common/Container/ContainerEntry.swift index 1e115e99..50fc60c8 100644 --- a/Sources/Common/Container/ContainerEntry.swift +++ b/Sources/Common/Container/ContainerEntry.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Container/ContainerEntryInfo.swift b/Sources/Common/Container/ContainerEntryInfo.swift index 87265e40..11d24dd6 100644 --- a/Sources/Common/Container/ContainerEntryInfo.swift +++ b/Sources/Common/Container/ContainerEntryInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Container/ContainerEntryType.swift b/Sources/Common/Container/ContainerEntryType.swift index 2e9035c1..e885f2d4 100644 --- a/Sources/Common/Container/ContainerEntryType.swift +++ b/Sources/Common/Container/ContainerEntryType.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Container/DosAttributes.swift b/Sources/Common/Container/DosAttributes.swift index 06d8b5d9..8d5780ca 100644 --- a/Sources/Common/Container/DosAttributes.swift +++ b/Sources/Common/Container/DosAttributes.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Container/Permissions.swift b/Sources/Common/Container/Permissions.swift index 462e0419..2248df6b 100644 --- a/Sources/Common/Container/Permissions.swift +++ b/Sources/Common/Container/Permissions.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/DecompressionAlgorithm.swift b/Sources/Common/DecompressionAlgorithm.swift index 9c235171..79d9b994 100644 --- a/Sources/Common/DecompressionAlgorithm.swift +++ b/Sources/Common/DecompressionAlgorithm.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/DeltaFilter.swift b/Sources/Common/DeltaFilter.swift index fe1c802b..66618723 100644 --- a/Sources/Common/DeltaFilter.swift +++ b/Sources/Common/DeltaFilter.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/Extensions.swift b/Sources/Common/Extensions.swift index ab1cb9f4..ed4972a0 100644 --- a/Sources/Common/Extensions.swift +++ b/Sources/Common/Extensions.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Common/FileSystemType.swift b/Sources/Common/FileSystemType.swift index 2898843e..b829605b 100644 --- a/Sources/Common/FileSystemType.swift +++ b/Sources/Common/FileSystemType.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Deflate/Deflate+Compress.swift b/Sources/Deflate/Deflate+Compress.swift index a231b731..97283927 100644 --- a/Sources/Deflate/Deflate+Compress.swift +++ b/Sources/Deflate/Deflate+Compress.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Deflate/Deflate+Constants.swift b/Sources/Deflate/Deflate+Constants.swift index 067fbf5e..7b1da0de 100644 --- a/Sources/Deflate/Deflate+Constants.swift +++ b/Sources/Deflate/Deflate+Constants.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Deflate/Deflate+Lengths.swift b/Sources/Deflate/Deflate+Lengths.swift index 6ee430e2..fdabf5f2 100644 --- a/Sources/Deflate/Deflate+Lengths.swift +++ b/Sources/Deflate/Deflate+Lengths.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Deflate/Deflate.swift b/Sources/Deflate/Deflate.swift index 10212b5a..250d5b52 100644 --- a/Sources/Deflate/Deflate.swift +++ b/Sources/Deflate/Deflate.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Deflate/DeflateError.swift b/Sources/Deflate/DeflateError.swift index 600e4e09..39d34a5c 100644 --- a/Sources/Deflate/DeflateError.swift +++ b/Sources/Deflate/DeflateError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/GZip/FileSystemType+Gzip.swift b/Sources/GZip/FileSystemType+Gzip.swift index 0032f9a2..8b37a53d 100644 --- a/Sources/GZip/FileSystemType+Gzip.swift +++ b/Sources/GZip/FileSystemType+Gzip.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/GZip/GzipArchive.swift b/Sources/GZip/GzipArchive.swift index 648e1f35..81a80b4c 100644 --- a/Sources/GZip/GzipArchive.swift +++ b/Sources/GZip/GzipArchive.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/GZip/GzipError.swift b/Sources/GZip/GzipError.swift index 02964d2d..65b9e75b 100644 --- a/Sources/GZip/GzipError.swift +++ b/Sources/GZip/GzipError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/GZip/GzipHeader.swift b/Sources/GZip/GzipHeader.swift index b2f85de5..878231c0 100644 --- a/Sources/GZip/GzipHeader.swift +++ b/Sources/GZip/GzipHeader.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMA.swift b/Sources/LZMA/LZMA.swift index 06a922e3..d8644301 100644 --- a/Sources/LZMA/LZMA.swift +++ b/Sources/LZMA/LZMA.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMABitTreeDecoder.swift b/Sources/LZMA/LZMABitTreeDecoder.swift index 3a032b0a..8b760e07 100644 --- a/Sources/LZMA/LZMABitTreeDecoder.swift +++ b/Sources/LZMA/LZMABitTreeDecoder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMAConstants.swift b/Sources/LZMA/LZMAConstants.swift index 28e52625..41a192a8 100644 --- a/Sources/LZMA/LZMAConstants.swift +++ b/Sources/LZMA/LZMAConstants.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMADecoder.swift b/Sources/LZMA/LZMADecoder.swift index a18f5a95..4a875b15 100644 --- a/Sources/LZMA/LZMADecoder.swift +++ b/Sources/LZMA/LZMADecoder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMAError.swift b/Sources/LZMA/LZMAError.swift index c8ad4628..fd305bff 100644 --- a/Sources/LZMA/LZMAError.swift +++ b/Sources/LZMA/LZMAError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMALenDecoder.swift b/Sources/LZMA/LZMALenDecoder.swift index e4895a2d..5d020f1b 100644 --- a/Sources/LZMA/LZMALenDecoder.swift +++ b/Sources/LZMA/LZMALenDecoder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMAProperties.swift b/Sources/LZMA/LZMAProperties.swift index 70a097b3..98425e02 100644 --- a/Sources/LZMA/LZMAProperties.swift +++ b/Sources/LZMA/LZMAProperties.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA/LZMARangeDecoder.swift b/Sources/LZMA/LZMARangeDecoder.swift index 3521c213..6cb55561 100644 --- a/Sources/LZMA/LZMARangeDecoder.swift +++ b/Sources/LZMA/LZMARangeDecoder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA2/LZMA2.swift b/Sources/LZMA2/LZMA2.swift index be927b81..ff0d8413 100644 --- a/Sources/LZMA2/LZMA2.swift +++ b/Sources/LZMA2/LZMA2.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA2/LZMA2Decoder.swift b/Sources/LZMA2/LZMA2Decoder.swift index f5531b22..cfff730f 100644 --- a/Sources/LZMA2/LZMA2Decoder.swift +++ b/Sources/LZMA2/LZMA2Decoder.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/LZMA2/LZMA2Error.swift b/Sources/LZMA2/LZMA2Error.swift index cb86e8f2..b4c43f65 100644 --- a/Sources/LZMA2/LZMA2Error.swift +++ b/Sources/LZMA2/LZMA2Error.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/ByteReader+Tar.swift b/Sources/TAR/ByteReader+Tar.swift index 21d8c710..9efd476c 100644 --- a/Sources/TAR/ByteReader+Tar.swift +++ b/Sources/TAR/ByteReader+Tar.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/ContainerEntryType+Tar.swift b/Sources/TAR/ContainerEntryType+Tar.swift index 6278876d..de9f6fc8 100644 --- a/Sources/TAR/ContainerEntryType+Tar.swift +++ b/Sources/TAR/ContainerEntryType+Tar.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 6fc376b2..ad3329f3 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarCreateError.swift b/Sources/TAR/TarCreateError.swift index c9bc9c95..61312585 100644 --- a/Sources/TAR/TarCreateError.swift +++ b/Sources/TAR/TarCreateError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarEntry.swift b/Sources/TAR/TarEntry.swift index 73218ab0..20918f01 100644 --- a/Sources/TAR/TarEntry.swift +++ b/Sources/TAR/TarEntry.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index 36a12873..3de3a8d9 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarEntryInfoProvider.swift b/Sources/TAR/TarEntryInfoProvider.swift index 6dee12aa..b8687085 100644 --- a/Sources/TAR/TarEntryInfoProvider.swift +++ b/Sources/TAR/TarEntryInfoProvider.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarError.swift b/Sources/TAR/TarError.swift index c1f8c5f2..4dcbbff2 100644 --- a/Sources/TAR/TarError.swift +++ b/Sources/TAR/TarError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/TAR/TarExtendedHeader.swift b/Sources/TAR/TarExtendedHeader.swift index db02ccf5..d7f23922 100644 --- a/Sources/TAR/TarExtendedHeader.swift +++ b/Sources/TAR/TarExtendedHeader.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/XZ/ByteReader+XZ.swift b/Sources/XZ/ByteReader+XZ.swift index 6d0af7c8..fb25213c 100644 --- a/Sources/XZ/ByteReader+XZ.swift +++ b/Sources/XZ/ByteReader+XZ.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/XZ/Sha256.swift b/Sources/XZ/Sha256.swift index 72fa0e33..cc7d1769 100644 --- a/Sources/XZ/Sha256.swift +++ b/Sources/XZ/Sha256.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/XZ/XZArchive.swift b/Sources/XZ/XZArchive.swift index 3a6c605f..5ca1ad15 100644 --- a/Sources/XZ/XZArchive.swift +++ b/Sources/XZ/XZArchive.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/XZ/XZBlock.swift b/Sources/XZ/XZBlock.swift index c70dbe84..fcc25417 100644 --- a/Sources/XZ/XZBlock.swift +++ b/Sources/XZ/XZBlock.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/XZ/XZError.swift b/Sources/XZ/XZError.swift index c5c22121..30d3fc93 100644 --- a/Sources/XZ/XZError.swift +++ b/Sources/XZ/XZError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/XZ/XZStreamHeader.swift b/Sources/XZ/XZStreamHeader.swift index 14b58421..c30d9bc4 100644 --- a/Sources/XZ/XZStreamHeader.swift +++ b/Sources/XZ/XZStreamHeader.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/BuiltinExtraFields.swift b/Sources/ZIP/BuiltinExtraFields.swift index 1c1fe26f..65b9d885 100644 --- a/Sources/ZIP/BuiltinExtraFields.swift +++ b/Sources/ZIP/BuiltinExtraFields.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ByteReader+Zip.swift b/Sources/ZIP/ByteReader+Zip.swift index 75bf73bc..f47c955a 100644 --- a/Sources/ZIP/ByteReader+Zip.swift +++ b/Sources/ZIP/ByteReader+Zip.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/CompressionMethod+Zip.swift b/Sources/ZIP/CompressionMethod+Zip.swift index ec19833c..207d576b 100644 --- a/Sources/ZIP/CompressionMethod+Zip.swift +++ b/Sources/ZIP/CompressionMethod+Zip.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/FileSystemType+Zip.swift b/Sources/ZIP/FileSystemType+Zip.swift index a5509834..1a9fd77d 100644 --- a/Sources/ZIP/FileSystemType+Zip.swift +++ b/Sources/ZIP/FileSystemType+Zip.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipCentralDirectoryEntry.swift b/Sources/ZIP/ZipCentralDirectoryEntry.swift index 568fe653..fa353765 100644 --- a/Sources/ZIP/ZipCentralDirectoryEntry.swift +++ b/Sources/ZIP/ZipCentralDirectoryEntry.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipContainer.swift b/Sources/ZIP/ZipContainer.swift index 020d6239..f683adeb 100644 --- a/Sources/ZIP/ZipContainer.swift +++ b/Sources/ZIP/ZipContainer.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipEndOfCentralDirectory.swift b/Sources/ZIP/ZipEndOfCentralDirectory.swift index 9006c859..5268b26f 100644 --- a/Sources/ZIP/ZipEndOfCentralDirectory.swift +++ b/Sources/ZIP/ZipEndOfCentralDirectory.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipEntry.swift b/Sources/ZIP/ZipEntry.swift index 2e139e07..19ac5a82 100644 --- a/Sources/ZIP/ZipEntry.swift +++ b/Sources/ZIP/ZipEntry.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipEntryInfo.swift b/Sources/ZIP/ZipEntryInfo.swift index 7b7e4376..a833b006 100644 --- a/Sources/ZIP/ZipEntryInfo.swift +++ b/Sources/ZIP/ZipEntryInfo.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipEntryInfoHelper.swift b/Sources/ZIP/ZipEntryInfoHelper.swift index dfab18b4..d815b45f 100644 --- a/Sources/ZIP/ZipEntryInfoHelper.swift +++ b/Sources/ZIP/ZipEntryInfoHelper.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipError.swift b/Sources/ZIP/ZipError.swift index 59535904..8886a475 100644 --- a/Sources/ZIP/ZipError.swift +++ b/Sources/ZIP/ZipError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipExtraField.swift b/Sources/ZIP/ZipExtraField.swift index d79be696..6bc69703 100644 --- a/Sources/ZIP/ZipExtraField.swift +++ b/Sources/ZIP/ZipExtraField.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/ZIP/ZipLocalHeader.swift b/Sources/ZIP/ZipLocalHeader.swift index b093bbd0..da86d100 100644 --- a/Sources/ZIP/ZipLocalHeader.swift +++ b/Sources/ZIP/ZipLocalHeader.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Zlib/ZlibArchive.swift b/Sources/Zlib/ZlibArchive.swift index e7d5084a..7dc10724 100644 --- a/Sources/Zlib/ZlibArchive.swift +++ b/Sources/Zlib/ZlibArchive.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Zlib/ZlibError.swift b/Sources/Zlib/ZlibError.swift index 15afea51..edac17bd 100644 --- a/Sources/Zlib/ZlibError.swift +++ b/Sources/Zlib/ZlibError.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/Zlib/ZlibHeader.swift b/Sources/Zlib/ZlibHeader.swift index f71c8218..a1fc4bcf 100644 --- a/Sources/Zlib/ZlibHeader.swift +++ b/Sources/Zlib/ZlibHeader.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Archives/BZip2Command.swift b/Sources/swcomp/Archives/BZip2Command.swift index d660f34a..04d2f659 100644 --- a/Sources/swcomp/Archives/BZip2Command.swift +++ b/Sources/swcomp/Archives/BZip2Command.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Archives/GZipCommand.swift b/Sources/swcomp/Archives/GZipCommand.swift index 716aa60a..fa37590d 100644 --- a/Sources/swcomp/Archives/GZipCommand.swift +++ b/Sources/swcomp/Archives/GZipCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Archives/LZMACommand.swift b/Sources/swcomp/Archives/LZMACommand.swift index d5d8f3d2..16ea9f06 100644 --- a/Sources/swcomp/Archives/LZMACommand.swift +++ b/Sources/swcomp/Archives/LZMACommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Archives/XZCommand.swift b/Sources/swcomp/Archives/XZCommand.swift index 4251400b..3ea58577 100644 --- a/Sources/swcomp/Archives/XZCommand.swift +++ b/Sources/swcomp/Archives/XZCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/BenchmarkCommand.swift b/Sources/swcomp/Benchmarks/BenchmarkCommand.swift index 591c291a..c731780c 100644 --- a/Sources/swcomp/Benchmarks/BenchmarkCommand.swift +++ b/Sources/swcomp/Benchmarks/BenchmarkCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/BenchmarkGroup.swift b/Sources/swcomp/Benchmarks/BenchmarkGroup.swift index ea7150c7..984acca1 100644 --- a/Sources/swcomp/Benchmarks/BenchmarkGroup.swift +++ b/Sources/swcomp/Benchmarks/BenchmarkGroup.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/CompBz2.swift b/Sources/swcomp/Benchmarks/CompBz2.swift index 05d1652c..a1b06f61 100644 --- a/Sources/swcomp/Benchmarks/CompBz2.swift +++ b/Sources/swcomp/Benchmarks/CompBz2.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/CompDeflate.swift b/Sources/swcomp/Benchmarks/CompDeflate.swift index df6c4bc3..addfaf82 100644 --- a/Sources/swcomp/Benchmarks/CompDeflate.swift +++ b/Sources/swcomp/Benchmarks/CompDeflate.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/Info7z.swift b/Sources/swcomp/Benchmarks/Info7z.swift index 7f3dff80..943294e4 100644 --- a/Sources/swcomp/Benchmarks/Info7z.swift +++ b/Sources/swcomp/Benchmarks/Info7z.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/InfoTar.swift b/Sources/swcomp/Benchmarks/InfoTar.swift index 671082f0..55bf3aab 100644 --- a/Sources/swcomp/Benchmarks/InfoTar.swift +++ b/Sources/swcomp/Benchmarks/InfoTar.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/InfoZip.swift b/Sources/swcomp/Benchmarks/InfoZip.swift index a295ea47..a44aeae9 100644 --- a/Sources/swcomp/Benchmarks/InfoZip.swift +++ b/Sources/swcomp/Benchmarks/InfoZip.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/UnBz2.swift b/Sources/swcomp/Benchmarks/UnBz2.swift index 721e8d9d..b6c279e3 100644 --- a/Sources/swcomp/Benchmarks/UnBz2.swift +++ b/Sources/swcomp/Benchmarks/UnBz2.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/UnGzip.swift b/Sources/swcomp/Benchmarks/UnGzip.swift index fc8f1c26..690a0037 100644 --- a/Sources/swcomp/Benchmarks/UnGzip.swift +++ b/Sources/swcomp/Benchmarks/UnGzip.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Benchmarks/UnXz.swift b/Sources/swcomp/Benchmarks/UnXz.swift index eb24ec85..f0cb7a2c 100644 --- a/Sources/swcomp/Benchmarks/UnXz.swift +++ b/Sources/swcomp/Benchmarks/UnXz.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Containers/7ZipCommand.swift b/Sources/swcomp/Containers/7ZipCommand.swift index 1ef28412..b96fbea9 100644 --- a/Sources/swcomp/Containers/7ZipCommand.swift +++ b/Sources/swcomp/Containers/7ZipCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Containers/CommonFunctions.swift b/Sources/swcomp/Containers/CommonFunctions.swift index 1c0ea211..fb0ae8de 100644 --- a/Sources/swcomp/Containers/CommonFunctions.swift +++ b/Sources/swcomp/Containers/CommonFunctions.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Containers/ContainerCommand.swift b/Sources/swcomp/Containers/ContainerCommand.swift index 76cda15f..32459532 100644 --- a/Sources/swcomp/Containers/ContainerCommand.swift +++ b/Sources/swcomp/Containers/ContainerCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Containers/TarCommand.swift b/Sources/swcomp/Containers/TarCommand.swift index 08390d73..acfd2d97 100644 --- a/Sources/swcomp/Containers/TarCommand.swift +++ b/Sources/swcomp/Containers/TarCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Containers/ZipCommand.swift b/Sources/swcomp/Containers/ZipCommand.swift index 52fe2403..f104b072 100644 --- a/Sources/swcomp/Containers/ZipCommand.swift +++ b/Sources/swcomp/Containers/ZipCommand.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Extensions/BlockSize+Keyable.swift b/Sources/swcomp/Extensions/BlockSize+Keyable.swift index 3917084d..1a4a51fa 100644 --- a/Sources/swcomp/Extensions/BlockSize+Keyable.swift +++ b/Sources/swcomp/Extensions/BlockSize+Keyable.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Extensions/CompressionMethod+CustomStringConvertible.swift b/Sources/swcomp/Extensions/CompressionMethod+CustomStringConvertible.swift index 62617f43..16b978ab 100644 --- a/Sources/swcomp/Extensions/CompressionMethod+CustomStringConvertible.swift +++ b/Sources/swcomp/Extensions/CompressionMethod+CustomStringConvertible.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Extensions/ContainerEntryInfo+CustomStringConvertible.swift b/Sources/swcomp/Extensions/ContainerEntryInfo+CustomStringConvertible.swift index 997f82fd..783fc7b2 100644 --- a/Sources/swcomp/Extensions/ContainerEntryInfo+CustomStringConvertible.swift +++ b/Sources/swcomp/Extensions/ContainerEntryInfo+CustomStringConvertible.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Extensions/FileSystemType+CustomStringConvertible.swift b/Sources/swcomp/Extensions/FileSystemType+CustomStringConvertible.swift index 4aee5724..595a58a8 100644 --- a/Sources/swcomp/Extensions/FileSystemType+CustomStringConvertible.swift +++ b/Sources/swcomp/Extensions/FileSystemType+CustomStringConvertible.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/Extensions/GzipHeader+CustomStringConvertible.swift b/Sources/swcomp/Extensions/GzipHeader+CustomStringConvertible.swift index 013776f3..c797639b 100644 --- a/Sources/swcomp/Extensions/GzipHeader+CustomStringConvertible.swift +++ b/Sources/swcomp/Extensions/GzipHeader+CustomStringConvertible.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Sources/swcomp/main.swift b/Sources/swcomp/main.swift index f7c62315..721a2301 100644 --- a/Sources/swcomp/main.swift +++ b/Sources/swcomp/main.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/BZip2CompressionTests.swift b/Tests/BZip2CompressionTests.swift index c14f3c43..2f8add59 100644 --- a/Tests/BZip2CompressionTests.swift +++ b/Tests/BZip2CompressionTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/BZip2Tests.swift b/Tests/BZip2Tests.swift index 3107c973..a93f6fe3 100644 --- a/Tests/BZip2Tests.swift +++ b/Tests/BZip2Tests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/Constants.swift b/Tests/Constants.swift index 7aade238..de03d332 100644 --- a/Tests/Constants.swift +++ b/Tests/Constants.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/DeflateCompressionTests.swift b/Tests/DeflateCompressionTests.swift index 312cf4f7..6711eee2 100644 --- a/Tests/DeflateCompressionTests.swift +++ b/Tests/DeflateCompressionTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/GzipTests.swift b/Tests/GzipTests.swift index 8f662df5..3c350d74 100644 --- a/Tests/GzipTests.swift +++ b/Tests/GzipTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/LzmaTests.swift b/Tests/LzmaTests.swift index 1081a273..580b5bf9 100644 --- a/Tests/LzmaTests.swift +++ b/Tests/LzmaTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/SevenZipTests.swift b/Tests/SevenZipTests.swift index affbe2c2..d01c8cc0 100644 --- a/Tests/SevenZipTests.swift +++ b/Tests/SevenZipTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/Sha256Tests.swift b/Tests/Sha256Tests.swift index 6d3340f2..166552a4 100644 --- a/Tests/Sha256Tests.swift +++ b/Tests/Sha256Tests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/TarCreateTests.swift b/Tests/TarCreateTests.swift index 210524eb..4c85bab9 100644 --- a/Tests/TarCreateTests.swift +++ b/Tests/TarCreateTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/TarTests.swift b/Tests/TarTests.swift index 17ccce19..a5db96e2 100644 --- a/Tests/TarTests.swift +++ b/Tests/TarTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/TestZipExtraField.swift b/Tests/TestZipExtraField.swift index d350fa9b..5f99ba69 100644 --- a/Tests/TestZipExtraField.swift +++ b/Tests/TestZipExtraField.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/XzTests.swift b/Tests/XzTests.swift index af7a1de9..40f8c880 100644 --- a/Tests/XzTests.swift +++ b/Tests/XzTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/ZipTests.swift b/Tests/ZipTests.swift index 69fd3ec6..77aa05b9 100644 --- a/Tests/ZipTests.swift +++ b/Tests/ZipTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information diff --git a/Tests/ZlibTests.swift b/Tests/ZlibTests.swift index 5040f746..d90369b3 100644 --- a/Tests/ZlibTests.swift +++ b/Tests/ZlibTests.swift @@ -1,4 +1,4 @@ -// Copyright (c) 2020 Timofey Solomko +// Copyright (c) 2021 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information From 0c6c201907b1816e6f77508b4d88349860beddcb Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 7 Jan 2021 11:48:07 +0200 Subject: [PATCH 35/97] Xcode project upgrade --- SWCompression.xcodeproj/project.pbxproj | 4 +++- .../xcshareddata/xcschemes/SWCompression.xcscheme | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index da0e0662..b2d07406 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -934,7 +934,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1200; + LastUpgradeCheck = 1230; ORGANIZATIONNAME = "Timofey Solomko"; TargetAttributes = { 06BE1AC71DB410F100EE0F59 = { @@ -1244,6 +1244,7 @@ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -1303,6 +1304,7 @@ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; diff --git a/SWCompression.xcodeproj/xcshareddata/xcschemes/SWCompression.xcscheme b/SWCompression.xcodeproj/xcshareddata/xcschemes/SWCompression.xcscheme index 18ba22e1..7aafb41b 100644 --- a/SWCompression.xcodeproj/xcshareddata/xcschemes/SWCompression.xcscheme +++ b/SWCompression.xcodeproj/xcshareddata/xcschemes/SWCompression.xcscheme @@ -1,6 +1,6 @@ Date: Mon, 18 Jan 2021 16:00:22 +0200 Subject: [PATCH 36/97] [BZip2] Explain zero RLE in the comments --- Sources/BZip2/BZip2+Compress.swift | 8 +++++--- Sources/ZIP/ZipLocalHeader.swift | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Sources/BZip2/BZip2+Compress.swift b/Sources/BZip2/BZip2+Compress.swift index 6222bd9a..96af5b3d 100644 --- a/Sources/BZip2/BZip2+Compress.swift +++ b/Sources/BZip2/BZip2+Compress.swift @@ -268,6 +268,9 @@ extension BZip2: CompressionAlgorithm { lengthOfZerosRun += 1 } if (byte == 0 && i == array.count - 1) || byte != 0 { + // Runs of zeros are represented using a modified binary system with two "digits", RUNA and RUNB, where + // RUNA represents 1 and RUNB represents 2 (whereas in the usual base-2 system the digits are 0 and 1). + // (We don't need a digit for zero since we can't get a run of length 0 by definition.) if lengthOfZerosRun > 0 { let digitsNumber = Int(floor(log2(Double(lengthOfZerosRun) + 1))) var remainder = lengthOfZerosRun @@ -285,16 +288,15 @@ extension BZip2: CompressionAlgorithm { } } if byte != 0 { + // We add one, because 1 is used as RUNB. let newSymbol = byte + 1 - // We add one because, 1 is used as RUNB. - // We don't add two instead, because 0 is never encountered as separate symbol, without RUNA meaning. out.append(newSymbol) if newSymbol > maxSymbol { maxSymbol = newSymbol } } } - // Add 'end of stream' symbol. + // Add the 'end of stream' symbol. out.append(maxSymbol + 1) return (out, maxSymbol) } diff --git a/Sources/ZIP/ZipLocalHeader.swift b/Sources/ZIP/ZipLocalHeader.swift index da86d100..e3cd7bae 100644 --- a/Sources/ZIP/ZipLocalHeader.swift +++ b/Sources/ZIP/ZipLocalHeader.swift @@ -75,7 +75,7 @@ struct ZipLocalHeader { case 0x0001: // Zip64 // Zip64 extra field is a special case, because it requires knowledge about local header fields, // in particular, uncompressed and compressed sizes. - // In local header both uncompressed size and compressed size fields are required. + // In the local header both uncompressed size and compressed size fields are required. self.uncompSize = byteReader.uint64() self.compSize = byteReader.uint64() self.zip64FieldsArePresent = true From d7adf13355aeb271750bb6dc5d4ce290e609e26d Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Fri, 26 Mar 2021 15:24:45 +0200 Subject: [PATCH 37/97] CI: add option to utils.py prepare-workspace to build BBD as xcf, remove testing of carthage-xcode12 workaround, update versions of xcode to 12.4 and swift to 5.3.3 in azp, fix github pages not being deployed, fix source code link to the latest tree in deployed documentation --- .jazzy.yaml | 2 +- .travis.yml | 40 ++++------------------------------------ azure-pipelines.yml | 4 ++-- bbd-bootstrap.sh | 15 --------------- utils.py | 21 ++++++++++----------- 5 files changed, 17 insertions(+), 65 deletions(-) delete mode 100755 bbd-bootstrap.sh diff --git a/.jazzy.yaml b/.jazzy.yaml index 90e1a3cb..2b1d81c0 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -7,7 +7,7 @@ module_version: 4.5.8 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.7 +github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.5.8 theme: fullwidth custom_categories: diff --git a/.travis.yml b/.travis.yml index 775e663c..37a70118 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ git: submodules: false jobs: include: - # We cannot test with Swift 4.2 on macOS since Carthage doesn't work with multiple Swift versions. - stage: test language: swift os: osx @@ -47,32 +46,6 @@ jobs: - ./utils.py prepare-workspace macos script: - ./utils.py ci script-macos - - stage: test - # TODO: Remove this stage when the non-xcf installation method with Carthage is no longer supported. - language: swift - os: osx - osx_image: xcode12.3 # Swift 5.3 - env: - - HOMEBREW_NO_INSTALL_CLEANUP=1 - before_install: - - brew update - install: - - ./utils.py ci install-macos - before_script: - - xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX) - - trap 'rm -f "$xcconfig"' INT TERM HUP EXIT - - echo 'EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200 = arm64 arm64e armv7 armv7s armv6 armv8' >> $xcconfig - - echo 'EXCLUDED_ARCHS = $(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(EFFECTIVE_PLATFORM_SUFFIX)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT)__XCODE_$(XCODE_VERSION_MAJOR))' >> $xcconfig - - export XCODE_XCCONFIG_FILE="$xcconfig" - - carthage bootstrap - - git submodule update --init --recursive - - cp "Tests/Test Files/gitattributes-copy" "Tests/Test Files/.gitattributes" - - cd "Tests/Test Files/" - - git lfs pull - - git lfs checkout - - cd - - script: - - ./utils.py ci script-macos - stage: test language: swift os: osx @@ -84,15 +57,7 @@ jobs: install: - ./utils.py ci install-macos before_script: - # TODO: Move this line into ./utils.py prepare-workspace macos when the old Swift versions and non-xcf installation - # method with Carthage are no longer supported. - - carthage bootstrap --use-xcframeworks --no-use-binaries - - git submodule update --init --recursive - - cp "Tests/Test Files/gitattributes-copy" "Tests/Test Files/.gitattributes" - - cd "Tests/Test Files/" - - git lfs pull - - git lfs checkout - - cd - + - ./utils.py prepare-workspace macos --xcf script: - ./utils.py ci script-macos - stage: test @@ -160,3 +125,6 @@ jobs: skip_cleanup: true github_token: $GITHUB_TOKEN local_dir: docs + skip_cleanup: true + on: + tags: true diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9164e0af..1c97c39e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -24,7 +24,7 @@ stages: DEVELOPER_DIR: '/Applications/Xcode_11.4.1.app' macosSwift53: imageName: 'macOS-10.15' - DEVELOPER_DIR: '/Applications/Xcode_12.3.app' + DEVELOPER_DIR: '/Applications/Xcode_12.4.app' pool: vmImage: $(imageName) steps: @@ -52,7 +52,7 @@ stages: SWIFT_VERSION: '5.2.5' linuxSwift53: imageName: 'ubuntu-20.04' - SWIFT_VERSION: '5.3.2' + SWIFT_VERSION: '5.3.3' pool: vmImage: $(imageName) steps: diff --git a/bbd-bootstrap.sh b/bbd-bootstrap.sh deleted file mode 100755 index 0007bbf7..00000000 --- a/bbd-bootstrap.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -# Temporary solution until the issue with Carthage is fixed - -set -euo pipefail - -xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX) -trap 'rm -f "$xcconfig"' INT TERM HUP EXIT - -# For Xcode 12 (beta 3+) make sure EXCLUDED_ARCHS is set to arm architectures otherwise -# the build will fail on lipo due to duplicate architectures. -echo 'EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200 = arm64 arm64e armv7 armv7s armv6 armv8' >> $xcconfig -echo 'EXCLUDED_ARCHS = $(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(EFFECTIVE_PLATFORM_SUFFIX)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT)__XCODE_$(XCODE_VERSION_MAJOR))' >> $xcconfig - -export XCODE_XCCONFIG_FILE="$xcconfig" -carthage bootstrap "$@" diff --git a/utils.py b/utils.py index 23355338..5e562d31 100755 --- a/utils.py +++ b/utils.py @@ -32,6 +32,7 @@ def _ci_script_macos(): xcodebuild_command_parts = ["xcodebuild", "-quiet", "-project", "SWCompression.xcodeproj", "-scheme", "SWCompression"] destinations_actions = [(["-destination 'platform=OS X'"], ["clean", "test"]), (["-destination 'platform=iOS Simulator,name=iPhone 8'"], ["clean", "test"]), + # For Swift 5.3 watchOS simulator is called differently. (["-destination 'platform=watchOS Simulator,name=Apple Watch - 38mm'"], ["clean", "build"]), (["-destination 'platform=tvOS Simulator,name=Apple TV'"], ["clean", "test"])] @@ -72,22 +73,18 @@ def action_cw(args): _sprun(["rm", "-f", "Package.resolved"]) _sprun(["rm", "-f", "SWCompression.framework.zip"]) -def _pw_macos(debug): +def _pw_macos(debug, xcf): print("=> Downloading dependency (BitByteData) using Carthage") + script = ["carthage", "bootstrap", "--no-use-binaries"] if debug: - # _sprun(["carthage", "bootstrap", "--configuration", "Debug", "--no-use-binaries"]) - # TODO: Temporary solution until the issue with Carthage is fixed - script = "./bbd-bootstrap.sh --configuration Debug --no-use-binaries" - _sprun([script], shell=True) - else: - # _sprun(["carthage", "bootstrap"]) - # TODO: Temporary solution until the issue with Carthage is fixed - script = "./bbd-bootstrap.sh" - _sprun([script], shell=True) + script += ["--configuration", "Debug"] + if xcf: + script += ["--use-xcframeworks"] + _sprun(script) def action_pw(args): if args.os == "macos": - _pw_macos(args.debug) + _pw_macos(args.debug, args.xcf) elif args.os == "other": pass else: @@ -122,6 +119,8 @@ parser_pw.add_argument("--no-test-files", "-T", action="store_true", dest="no_te help="don't download example files used for testing") parser_pw.add_argument("--debug", "-d", action="store_true", dest="debug", help="build BitByteData in Debug configuration") +parser_pw.add_argument("--xcf", action="store_true", dest="xcf", + help="build BitByteData as a XCFramework") parser_pw.set_defaults(func=action_pw) args = parser.parse_args() From bf4b00890acecd615d6cbcb3467b09b9141b3036 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Fri, 26 Mar 2021 15:28:27 +0200 Subject: [PATCH 38/97] Increased ios deployment target in cocoapods to 9.0 --- SWCompression.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SWCompression.podspec b/SWCompression.podspec index 2b446759..86c981fc 100644 --- a/SWCompression.podspec +++ b/SWCompression.podspec @@ -15,7 +15,7 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/tsolomko/SWCompression.git", :tag => "#{s.version}" } - s.ios.deployment_target = "8.0" + s.ios.deployment_target = "9.0" s.osx.deployment_target = "10.10" s.tvos.deployment_target = "9.0" s.watchos.deployment_target = "2.0" From aaaed7639c8a318789a11e60d97ecd9bed86aec1 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Mon, 29 Mar 2021 23:59:38 +0300 Subject: [PATCH 39/97] Split AZP macos swift 5.3 job into a separate matrix so we can use a new name for wachos simulator and xcframeworks --- azure-pipelines.yml | 27 +++++++++++++++++++++++---- utils.py | 16 +++++++++++----- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1c97c39e..252430e7 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -10,7 +10,7 @@ stages: - stage: test displayName: 'Build & Test' jobs: - - job: macos + - job: macosLegacy strategy: matrix: macosSwift50: @@ -22,9 +22,6 @@ stages: macosSwift52: imageName: 'macOS-10.15' DEVELOPER_DIR: '/Applications/Xcode_11.4.1.app' - macosSwift53: - imageName: 'macOS-10.15' - DEVELOPER_DIR: '/Applications/Xcode_12.4.app' pool: vmImage: $(imageName) steps: @@ -36,6 +33,28 @@ stages: displayName: 'Prepare Workspace' - script: ./utils.py ci script-macos displayName: 'Build & Test' + - script: swift build -c release + displayName: 'Build SPM Release' + - job: macosNew + # We split Xcode 12+ jobs into a separate matrix since we need to use XCFramework for this versions. + # We also need to use a different watchos simulator name for newer Xcode versions. + # For it is only for Swift 5.3 but future versions will also probably be included here. + strategy: + matrix: + macosSwift53: + imageName: 'macOS-10.15' + DEVELOPER_DIR: '/Applications/Xcode_12.4.app' + pool: + vmImage: $(imageName) + steps: + - script: | + brew update + ./utils.py ci install-macos + displayName: 'Install' + - script: ./utils.py prepare-workspace macos --xcf + displayName: 'Prepare Workspace' + - script: ./utils.py ci script-macos --new-watchos-simulator + displayName: 'Build & Test' - script: swift build -c release # Check Release build just in case. displayName: 'Build SPM Release' - job: linux diff --git a/utils.py b/utils.py index 5e562d31..b94df808 100755 --- a/utils.py +++ b/utils.py @@ -27,15 +27,18 @@ def _ci_install_macos(): def _ci_install_linux(): _sprun(["eval \"$(curl -sL https://swiftenv.fuller.li/install.sh)\""], shell=True) -def _ci_script_macos(): +def _ci_script_macos(new_watchos_simulator): _sprun(["swift", "--version"]) xcodebuild_command_parts = ["xcodebuild", "-quiet", "-project", "SWCompression.xcodeproj", "-scheme", "SWCompression"] destinations_actions = [(["-destination 'platform=OS X'"], ["clean", "test"]), (["-destination 'platform=iOS Simulator,name=iPhone 8'"], ["clean", "test"]), - # For Swift 5.3 watchOS simulator is called differently. - (["-destination 'platform=watchOS Simulator,name=Apple Watch - 38mm'"], ["clean", "build"]), (["-destination 'platform=tvOS Simulator,name=Apple TV'"], ["clean", "test"])] - + + if new_watchos_simulator: + destinations_actions.append((["-destination 'platform=watchOS Simulator,name=Apple Watch Series 6 - 44mm'"], ["clean", "build"])) + else: + destinations_actions.append((["-destination 'platform=watchOS Simulator,name=Apple Watch - 38mm'"], ["clean", "build"])) + for destination, action in destinations_actions: xcodebuild_command = xcodebuild_command_parts + destination + action _sprun(xcodebuild_command) @@ -56,7 +59,7 @@ def action_ci(args): elif args.cmd == "install-linux": _ci_install_linux() elif args.cmd == "script-macos": - _ci_script_macos() + _ci_script_macos(args.new_watchos_simulator) elif args.cmd == "script-linux": _ci_script_linux() else: @@ -104,6 +107,9 @@ parser_ci = subparsers.add_parser("ci", help="a subset of commands used by CI", description="a subset of commands used by CI") parser_ci.add_argument("cmd", choices=["before-deploy", "install-macos", "install-linux", "script-macos", "script-linux"], help="a command to perform on CI", metavar="CI_CMD") +parser_ci.add_argument("--new-watchos-simulator", action="store_true", dest="new_watchos_simulator", + help="use the newest watchos simulator which is necessary for xcode 12+ \ + (used only by 'script-macos' subcommand)") parser_ci.set_defaults(func=action_ci) # Parser for 'cleanup-workspace' command. From 2d8f9e90b68cb40edc9ef7f5af42adc43cc33c43 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 1 May 2021 16:24:54 +0300 Subject: [PATCH 40/97] AZP: merge macos jobs using env variables, add swift 5.4 on linux, use ubntu 18.04 --- azure-pipelines.yml | 50 ++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 252430e7..b986d69d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -10,53 +10,50 @@ stages: - stage: test displayName: 'Build & Test' jobs: - - job: macosLegacy + - job: macos strategy: matrix: macosSwift50: imageName: 'macOS-10.14' DEVELOPER_DIR: '/Applications/Xcode_10.3.app' + WATCHOS_ACTIONS: 'clean build' + WATCHOS_SIMULATOR: 'Apple Watch Series 4 - 44mm' macosSwift51: imageName: 'macOS-10.15' DEVELOPER_DIR: '/Applications/Xcode_11.3.1.app' + WATCHOS_ACTIONS: 'clean build' + WATCHOS_SIMULATOR: 'Apple Watch Series 4 - 44mm' macosSwift52: imageName: 'macOS-10.15' DEVELOPER_DIR: '/Applications/Xcode_11.4.1.app' + WATCHOS_ACTIONS: 'clean build' + WATCHOS_SIMULATOR: 'Apple Watch Series 4 - 44mm' + macosSwift53: + imageName: 'macOS-10.15' + DEVELOPER_DIR: '/Applications/Xcode_12.4.app' + WATCHOS_ACTIONS: 'clean build' + WATCHOS_SIMULATOR: 'Apple Watch Series 4 - 44mm' + UTILS_PW_XCF_FLAG: '--xcf' + # macosSwift54: + # imageName: 'macOS-11.3' + # DEVELOPER_DIR: '/Applications/Xcode_12.5.app' + # WATCHOS_ACTIONS: 'clean test' + # WATCHOS_SIMULATOR: 'Apple Watch Series 6 - 44mm' + # UTILS_PW_XCF_FLAG: '--xcf' pool: vmImage: $(imageName) steps: - script: | + set -e -o xtrace brew update ./utils.py ci install-macos displayName: 'Install' - - script: ./utils.py prepare-workspace macos + - script: ./utils.py prepare-workspace macos $UTILS_PW_XCF_FLAG displayName: 'Prepare Workspace' - script: ./utils.py ci script-macos displayName: 'Build & Test' - script: swift build -c release displayName: 'Build SPM Release' - - job: macosNew - # We split Xcode 12+ jobs into a separate matrix since we need to use XCFramework for this versions. - # We also need to use a different watchos simulator name for newer Xcode versions. - # For it is only for Swift 5.3 but future versions will also probably be included here. - strategy: - matrix: - macosSwift53: - imageName: 'macOS-10.15' - DEVELOPER_DIR: '/Applications/Xcode_12.4.app' - pool: - vmImage: $(imageName) - steps: - - script: | - brew update - ./utils.py ci install-macos - displayName: 'Install' - - script: ./utils.py prepare-workspace macos --xcf - displayName: 'Prepare Workspace' - - script: ./utils.py ci script-macos --new-watchos-simulator - displayName: 'Build & Test' - - script: swift build -c release # Check Release build just in case. - displayName: 'Build SPM Release' - job: linux strategy: matrix: @@ -70,8 +67,11 @@ stages: imageName: 'ubuntu-18.04' SWIFT_VERSION: '5.2.5' linuxSwift53: - imageName: 'ubuntu-20.04' + imageName: 'ubuntu-18.04' SWIFT_VERSION: '5.3.3' + linuxSwift54: + imageName: 'ubuntu-18.04' + SWIFT_VERSION: '5.4' pool: vmImage: $(imageName) steps: From 336d547c0b9af53d29468256717e638851d0102b Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 13 May 2021 20:28:07 +0300 Subject: [PATCH 41/97] CI: allow linux builds with Swift 5.4 to fail --- .travis.yml | 4 ++++ azure-pipelines.yml | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b614ba0c..496d4cde 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,10 @@ git: depth: 1 submodules: false jobs: + allow_failures: + # There is an issue with Swift 5.4 on Linux which fails the build. See https://bugs.swift.org/browse/SR-14594. + env: + - SWIFT_VERSION=5.4 include: - stage: test language: swift diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b986d69d..5a2592ba 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -77,7 +77,14 @@ stages: steps: - script: ./utils.py ci install-linux displayName: 'Install' - - script: ./utils.py ci script-linux + # There is an issue with Swift 5.4 on Linux which fails the build. See https://bugs.swift.org/browse/SR-14594. + - script: | + if [[ $SWIFT_VERSION = '5.4' ]] + then + echo "Skipping Swift 5.4 on linux due to issue with Swift itself." + else + ./utils.py ci script-linux + fi displayName: 'Build SPM Debug & Release' # - stage: Deploy # dependsOn: Test From 69eb11437a99e317d2025bb8d6157ac134bd765c Mon Sep 17 00:00:00 2001 From: Eric Thorpe Date: Thu, 13 May 2021 16:15:49 +1000 Subject: [PATCH 42/97] [ZIP] Fix CP437 support on Windows --- Sources/ZIP/ByteReader+Zip.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Sources/ZIP/ByteReader+Zip.swift b/Sources/ZIP/ByteReader+Zip.swift index f47c955a..bcb9f870 100644 --- a/Sources/ZIP/ByteReader+Zip.swift +++ b/Sources/ZIP/ByteReader+Zip.swift @@ -21,8 +21,12 @@ extension LittleEndianByteReader { return String(data: stringData, encoding: .utf8) } if String.cp437Available && !stringData.needsUtf8() { + #if os(Windows) + return String(data: stringData, encoding: String.cp437Encoding) + #else return String(data: stringData, encoding: String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(String.cp437Encoding))) + #endif } else { return String(data: stringData, encoding: .utf8) } @@ -39,6 +43,10 @@ fileprivate extension String { static let cp437Encoding: CFStringEncoding = UInt32(truncatingIfNeeded: UInt(kCFStringEncodingDOSLatinUS)) #endif static let cp437Available: Bool = CFStringIsEncodingAvailable(cp437Encoding) + #elseif os(Windows) + // "Latin-US (DOS)" CP437-2147483120 + static let cp437Encoding = String.Encoding(rawValue: 0x80000400) + static let cp437Available = String.availableStringEncodings.contains(cp437Encoding) #else static let cp437Encoding = CFStringEncoding(CFStringEncodings.dosLatinUS.rawValue) static let cp437Available = CFStringIsEncodingAvailable(cp437Encoding) From 1c9533df7434bb1da5496f43ce67a9d865ccea83 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 27 May 2021 16:22:32 +0300 Subject: [PATCH 43/97] CI: remove all stages from travis but macos11-swift5.4 (since it is impossible to use it due to the free plan limit), exclude test releases tags on azp, use containers for swift on linux on azp, enable building with swift 5.4.1 on linux since the issue is fixed --- .travis.yml | 145 -------------------------------------------- azure-pipelines.yml | 27 ++++----- 2 files changed, 13 insertions(+), 159 deletions(-) diff --git a/.travis.yml b/.travis.yml index 496d4cde..c82083ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,75 +3,7 @@ git: depth: 1 submodules: false jobs: - allow_failures: - # There is an issue with Swift 5.4 on Linux which fails the build. See https://bugs.swift.org/browse/SR-14594. - env: - - SWIFT_VERSION=5.4 include: - - stage: test - language: swift - os: osx - osx_image: xcode10.3 # Swift 5.0 - env: - - HOMEBREW_NO_INSTALL_CLEANUP=1 - - WATCHOS_ACTIONS='clean build' - - WATCHOS_SIMULATOR='Apple Watch Series 4 - 44mm' - before_install: - - brew update - install: - - ./utils.py ci install-macos - before_script: - - ./utils.py prepare-workspace macos - script: - - ./utils.py ci script-macos - - stage: test - language: swift - os: osx - osx_image: xcode11.3 # Swift 5.1 - env: - - HOMEBREW_NO_INSTALL_CLEANUP=1 - - WATCHOS_ACTIONS='clean build' - - WATCHOS_SIMULATOR='Apple Watch Series 4 - 44mm' - before_install: - - brew update - install: - - ./utils.py ci install-macos - before_script: - - ./utils.py prepare-workspace macos - script: - - ./utils.py ci script-macos - - stage: test - language: swift - os: osx - osx_image: xcode11.4 # Swift 5.2 - env: - - HOMEBREW_NO_INSTALL_CLEANUP=1 - - WATCHOS_ACTIONS='clean build' - - WATCHOS_SIMULATOR='Apple Watch Series 4 - 44mm' - before_install: - - brew update - install: - - ./utils.py ci install-macos - before_script: - - ./utils.py prepare-workspace macos - script: - - ./utils.py ci script-macos - - stage: test - language: swift - os: osx - osx_image: xcode12.4 # Swift 5.3.2 - env: - - HOMEBREW_NO_INSTALL_CLEANUP=1 - - WATCHOS_ACTIONS='clean build' - - WATCHOS_SIMULATOR='Apple Watch Series 6 - 44mm' - before_install: - - brew update - install: - - ./utils.py ci install-macos - before_script: - - ./utils.py prepare-workspace macos --xcf - script: - - ./utils.py ci script-macos - stage: test language: swift os: osx @@ -88,80 +20,3 @@ jobs: - ./utils.py prepare-workspace macos --xcf script: - ./utils.py ci script-macos - - stage: test - language: generic - os: linux - dist: bionic - env: - - SWIFT_VERSION=5.0.3 - install: - - ./utils.py ci install-linux - script: - - ./utils.py ci script-linux - - stage: test - language: generic - os: linux - dist: bionic - env: - - SWIFT_VERSION=5.1.5 - install: - - ./utils.py ci install-linux - script: - - ./utils.py ci script-linux - - stage: test - language: generic - os: linux - dist: bionic - env: - - SWIFT_VERSION=5.2.5 - install: - - ./utils.py ci install-linux - script: - - ./utils.py ci script-linux - - stage: test - language: generic - os: linux - dist: bionic - env: - - SWIFT_VERSION=5.3.3 - install: - - ./utils.py ci install-linux - script: - - ./utils.py ci script-linux - - stage: test - language: generic - os: linux - dist: bionic - env: - - SWIFT_VERSION=5.4 - install: - - ./utils.py ci install-linux - script: - - ./utils.py ci script-linux - - stage: deploy - # Don't deploy if it is a test release. - if: (tag IS present) AND (tag =~ /^\d+\.\d+\.\d+$/) - language: generic - os: osx - osx_image: xcode12 - env: - - HOMEBREW_NO_INSTALL_CLEANUP=1 - env: - secure: iavIkrus2Xd3b086nz2srMGl52yqzLuCdhyEAhMODVqkzqMQ17s10y1TNb+vkepd0HgxI9j57d5X7tfChjWuWDwE2hZKjr/Kx2DfiUr1AKQD6ymuGrq/0Vv6yL9dfPU8goFArcrsBcyVKczLtTuLCKL498ZqokkQc/3kGvzW74lv+z410MfHS9/tvToO/yXJckL6qJ2XBAiElfOO0rEkllTeCo6N3bjcHZ2o7PE0K+CHYxwNKj0TmPmuNWZ3U4fzoWzkk01re1C1l5cpSb20g+2aGyi0yYX+PomX7fIIqNq9vmmyoeNdr35yqoQv/0zFeFnps83NKmZLAjSUhiUdhlbuBLBE+w8544LOaZnMDlFmpDjgyaVnRrOh0NrBB1FwU48aGfX5ljRQmk/07FTEUjvwvGGoOpz8lrLZi148FMHEospL3Sf7d8K+Q9WdtLTGk7HCnbOVcxS6oB/SWF/Cj6n5wu+EI1floBaZEsNPR40Gd4eM/Ik/E3lDrZThGDCWQsao981wm7IfEDBR1nuMME8gpZINFANNS1+5miFaGdTnDTp4Yd5MGEFZm+K8x+TG1891NwNH1ZmKXlypJXiUzvSjbh2ViNJGekdQj9q2gj2ZFlCfHJ05adwJ4w9qRuF00HpAOD6At6EnsjDXFJeTZS5dj8fi2YsU9or8KfTFoNY= - addons: - homebrew: - packages: - - sourcekitten - update: true - install: - - gem install -N jazzy - - gem update -N cocoapods - before_deploy: - - ./utils.py ci before-deploy - deploy: - - provider: pages - github_token: $GITHUB_TOKEN - local_dir: docs - skip_cleanup: true - on: - tags: true diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 5a2592ba..e3abad7e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -5,12 +5,15 @@ trigger: tags: include: - '*' + exclude: + - '*-test*' stages: - stage: test displayName: 'Build & Test' jobs: - job: macos + # TODO: Add Xcode 12.5/Swift 5.4. It requires macOS 11 which is currently unavailable on AZP. For Xcode 12.5 we can also enable testing on watchos. strategy: matrix: macosSwift50: @@ -59,32 +62,28 @@ stages: matrix: linuxSwift50: imageName: 'ubuntu-18.04' - SWIFT_VERSION: '5.0.3' + containerImage: 'swift:5.0.3-bionic' linuxSwift51: imageName: 'ubuntu-18.04' - SWIFT_VERSION: '5.1.5' + containerImage: 'swift:5.1.5-bionic' linuxSwift52: imageName: 'ubuntu-18.04' - SWIFT_VERSION: '5.2.5' + containerImage: 'swift:5.2.5-bionic' linuxSwift53: imageName: 'ubuntu-18.04' - SWIFT_VERSION: '5.3.3' + containerImage: 'swift:5.3.3-bionic' linuxSwift54: imageName: 'ubuntu-18.04' - SWIFT_VERSION: '5.4' + containerImage: 'swift:5.4.1-bionic' pool: vmImage: $(imageName) + container: $[ variables['containerImage'] ] steps: - - script: ./utils.py ci install-linux - displayName: 'Install' - # There is an issue with Swift 5.4 on Linux which fails the build. See https://bugs.swift.org/browse/SR-14594. - script: | - if [[ $SWIFT_VERSION = '5.4' ]] - then - echo "Skipping Swift 5.4 on linux due to issue with Swift itself." - else - ./utils.py ci script-linux - fi + set -e -o xtrace + swift --version + swift build + swift build -c release # Check Release build just in case. displayName: 'Build SPM Debug & Release' # - stage: Deploy # dependsOn: Test From 45c055dc0ce67c1d3f35591c64dbdd0c64a9ecd1 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 27 May 2021 16:40:17 +0300 Subject: [PATCH 44/97] utils.py: remove install-linux and script-linux sub-subcommands They are no longer used, since we can't use them when we use docker containers for linux ci. --- utils.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/utils.py b/utils.py index e934593a..c3257fb2 100755 --- a/utils.py +++ b/utils.py @@ -28,9 +28,6 @@ def _ci_install_macos(): _sprun_shell(script) _sprun(["git", "lfs", "install"]) -def _ci_install_linux(): - _sprun_shell("eval \"$(curl -sL https://swiftenv.fuller.li/install.sh)\"") - def _ci_script_macos(): _sprun_shell("xcodebuild -version") _sprun(["swift", "--version"]) @@ -45,25 +42,13 @@ def _ci_script_macos(): # If xcodebuild is not run inside shell, then destination parameters are ignored for some reason. _sprun_shell(" ".join(xcodebuild_command)) -def _ci_script_linux(): - env = os.environ.copy() - env["SWIFTENV_ROOT"] = env["HOME"] +"/.swiftenv" - env["PATH"] = env["SWIFTENV_ROOT"] + "/bin:" + env["SWIFTENV_ROOT"] + "/shims:"+ env["PATH"] - _sprun(["swift", "--version"], env=env) - _sprun(["swift", "build"], env=env) - _sprun(["swift", "build", "-c", "release"], env=env) - def action_ci(args): if args.cmd == "before-deploy": _ci_before_deploy() elif args.cmd == "install-macos": _ci_install_macos() - elif args.cmd == "install-linux": - _ci_install_linux() elif args.cmd == "script-macos": _ci_script_macos() - elif args.cmd == "script-linux": - _ci_script_linux() else: raise Exception("Unknown CI command") @@ -107,7 +92,7 @@ subparsers = parser.add_subparsers(title="commands", help="a command to perform" # Parser for 'ci' command. parser_ci = subparsers.add_parser("ci", help="a subset of commands used by CI", description="a subset of commands used by CI") -parser_ci.add_argument("cmd", choices=["before-deploy", "install-macos", "install-linux", "script-macos", "script-linux"], +parser_ci.add_argument("cmd", choices=["before-deploy", "install-macos", "script-macos"], help="a command to perform on CI", metavar="CI_CMD") parser_ci.add_argument("--new-watchos-simulator", action="store_true", dest="new_watchos_simulator", help="use the newest watchos simulator which is necessary for xcode 12+ \ From 1ae8873e4cc9ba26e35b77f85160a654dd5e5f41 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sun, 27 Jun 2021 15:31:09 +0300 Subject: [PATCH 45/97] README: fix link to SPM docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 66acac23..8a1da6b4 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ let package = Package( ) ``` -More details you can find in [Swift Package Manager's Documentation](https://github.com/apple/swift-package-manager/tree/master/Documentation). +More details you can find in [Swift Package Manager's Documentation](https://github.com/apple/swift-package-manager/tree/main/Documentation). ### CocoaPods From b05383e0cd1fe635f99ab2107d47bac77d76bdba Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 17 Jul 2021 11:13:24 +0300 Subject: [PATCH 46/97] CI: use swift 5.4.2 on linux and windows --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ca1d8c68..24a89f58 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -74,7 +74,7 @@ stages: containerImage: 'swift:5.3.3-bionic' linuxSwift54: imageName: 'ubuntu-18.04' - containerImage: 'swift:5.4.1-bionic' + containerImage: 'swift:5.4.2-bionic' pool: vmImage: $(imageName) container: $[ variables['containerImage'] ] @@ -90,7 +90,7 @@ stages: matrix: windowsSwift54: imageName: 'windows-2019' - SWIFT_VERSION: '5.4.1' + SWIFT_VERSION: '5.4.2' pool: vmImage: $(imageName) variables: From d3d2cdbac2efdc2e04cea8c264fe8165906b9374 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 17 Jul 2021 11:13:42 +0300 Subject: [PATCH 47/97] utils.py: remove watchos simulator option --- utils.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/utils.py b/utils.py index c3257fb2..b48b2144 100755 --- a/utils.py +++ b/utils.py @@ -94,9 +94,6 @@ parser_ci = subparsers.add_parser("ci", help="a subset of commands used by CI", description="a subset of commands used by CI") parser_ci.add_argument("cmd", choices=["before-deploy", "install-macos", "script-macos"], help="a command to perform on CI", metavar="CI_CMD") -parser_ci.add_argument("--new-watchos-simulator", action="store_true", dest="new_watchos_simulator", - help="use the newest watchos simulator which is necessary for xcode 12+ \ - (used only by 'script-macos' subcommand)") parser_ci.set_defaults(func=action_ci) # Parser for 'cleanup-workspace' command. From aba14af8c58b62fd785e67d5b5fbedea5e0993d6 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 17 Jul 2021 11:14:25 +0300 Subject: [PATCH 48/97] Small changes to code comments --- Sources/GZip/GzipHeader.swift | 2 +- Sources/LZMA/LZMARangeDecoder.swift | 2 +- Sources/TAR/TarContainer.swift | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Sources/GZip/GzipHeader.swift b/Sources/GZip/GzipHeader.swift index 878231c0..b505ead7 100644 --- a/Sources/GZip/GzipHeader.swift +++ b/Sources/GZip/GzipHeader.swift @@ -58,7 +58,7 @@ public struct GzipHeader { } init(_ reader: LsbBitReader) throws { - // Valid GZip header must contain at least 2 bytes of data. + // Valid GZip header must contain at least 10 bytes of data. guard reader.bytesLeft >= 10 else { throw GzipError.wrongMagic } diff --git a/Sources/LZMA/LZMARangeDecoder.swift b/Sources/LZMA/LZMARangeDecoder.swift index 610fffcf..07ca582f 100644 --- a/Sources/LZMA/LZMARangeDecoder.swift +++ b/Sources/LZMA/LZMARangeDecoder.swift @@ -19,7 +19,7 @@ struct LZMARangeDecoder { } init(_ byteReader: LittleEndianByteReader) throws { - // To initialize rande decoder at least 5 bytes are necessary. + // To initialize range decoder at least 5 bytes are necessary. guard byteReader.bytesLeft >= 5 else { throw LZMAError.rangeDecoderInitError } diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index a8ede371..8d998151 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -39,7 +39,6 @@ public class TarContainer: Container { guard data.count >= 512 else { throw TarError.tooSmallFileIsPassed } - /// Object with input data which supports convenient work with bit shifts. var infoProvider = TarEntryInfoProvider(data) var ustarEncountered = false @@ -159,7 +158,6 @@ public class TarContainer: Container { guard data.count >= 512 else { throw TarError.tooSmallFileIsPassed } - /// Object with input data which supports convenient work with bit shifts. var infoProvider = TarEntryInfoProvider(data) var entries = [TarEntryInfo]() From 7646ec34a18a19bc4e20fea4fd1972e625d5e723 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 21 Jul 2021 19:34:48 +0300 Subject: [PATCH 49/97] [TAR] Remove pre-Swift 5.0 crash workaround --- Sources/TAR/TarEntryInfo.swift | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index 3de3a8d9..65450e0a 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -404,21 +404,8 @@ public struct TarEntryInfo: ContainerEntryInfo { // 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. - #if (swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))) || !os(Linux) - let lastPrefixSlashIndex = nameData.prefix(upTo: maxPrefixLength) - .range(of: Data([0x2f]), options: .backwards)?.lowerBound ?? -1 - #else - // TODO: This is a workaround for runtime crash in `Data.prefix(upTo:).range(of:options:)` on Linux with - // Swift 4.1. It seems like it is fixed in 4.2 and master snapshots, so it will be removed when Swift - // 5.0 is released. - var lastPrefixSlashIndex = -1 - for i in stride(from: maxPrefixLength - 1, through: 0, by: -1) { - if nameData[i] == 0x2f { - lastPrefixSlashIndex = i - break - } - } - #endif + let lastPrefixSlashIndex = nameData.prefix(upTo: maxPrefixLength) + .range(of: Data([0x2f]), options: .backwards)?.lowerBound ?? -1 let updatedNameLength = nameData.count - lastPrefixSlashIndex - 1 let prefixLength = lastPrefixSlashIndex From cb730a334d8106bfda91fedb111a75f2c12da434 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 21 Jul 2021 19:47:05 +0300 Subject: [PATCH 50/97] [LZMA] Change LZMAConstants from struct to enum --- Sources/LZMA/LZMAConstants.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/LZMA/LZMAConstants.swift b/Sources/LZMA/LZMAConstants.swift index 8b051662..5e2fe5e7 100644 --- a/Sources/LZMA/LZMAConstants.swift +++ b/Sources/LZMA/LZMAConstants.swift @@ -5,7 +5,8 @@ import Foundation -struct LZMAConstants { +enum LZMAConstants { + static let topValue: UInt32 = 1 << 24 static let numBitModelTotalBits = 11 static let numMoveBits = 5 @@ -19,4 +20,5 @@ struct LZMAConstants { static let numFullDistances = 1 << (endPosModelIndex >> 1) static let matchMinLen = 2 // LZMAConstants.numStates << LZMAConstants.numPosBitsMax = 192 + } From cb8a6738a0b3a25e07328d6e45e7403cacd1129f Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 21 Jul 2021 19:47:30 +0300 Subject: [PATCH 51/97] [Common] Change DeltaFilter from final class to enum --- Sources/Common/DeltaFilter.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Common/DeltaFilter.swift b/Sources/Common/DeltaFilter.swift index 66618723..02198d43 100644 --- a/Sources/Common/DeltaFilter.swift +++ b/Sources/Common/DeltaFilter.swift @@ -6,7 +6,7 @@ import Foundation import BitByteData -final class DeltaFilter { +enum DeltaFilter { static func decode(_ byteReader: LittleEndianByteReader, _ distance: Int) -> Data { var out = [UInt8]() From bc3362c568e20f3bc5a61221726b8711214c63ca Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 21 Jul 2021 20:21:23 +0300 Subject: [PATCH 52/97] [TAR] Add TarHeader struct --- SWCompression.xcodeproj/project.pbxproj | 4 + Sources/TAR/TarHeader.swift | 135 ++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 Sources/TAR/TarHeader.swift diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index cb1511c6..02d51bc4 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -213,6 +213,7 @@ 06F066771FFB763400312A82 /* test8.bz2 in Resources */ = {isa = PBXBuildFile; fileRef = 06F066111FFB763300312A82 /* test8.bz2 */; }; 06F276DF1F2BAB4A00E67335 /* 7zEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06F276DE1F2BAB4900E67335 /* 7zEntry.swift */; }; 06FEAD921F54B9CD00AD016E /* EncodingTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06FEAD911F54B9CD00AD016E /* EncodingTree.swift */; }; + E648151D26A889B8009261F0 /* TarHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = E648151C26A889B8009261F0 /* TarHeader.swift */; }; E652D8F3263D670900FC229B /* test_nonstandard_runlength.bz2 in Resources */ = {isa = PBXBuildFile; fileRef = E652D8F2263D670900FC229B /* test_nonstandard_runlength.bz2 */; }; E652D8F5263D678000FC229B /* test_nonstandard_runlength.answer in Resources */ = {isa = PBXBuildFile; fileRef = E652D8F4263D678000FC229B /* test_nonstandard_runlength.answer */; }; E66F36242538726E00076A6E /* test_empty.lzma in Resources */ = {isa = PBXBuildFile; fileRef = E66F36232538726E00076A6E /* test_empty.lzma */; }; @@ -437,6 +438,7 @@ 06F276DE1F2BAB4900E67335 /* 7zEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 7zEntry.swift; sourceTree = ""; }; 06FEAD911F54B9CD00AD016E /* EncodingTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EncodingTree.swift; path = Sources/Common/CodingTree/EncodingTree.swift; sourceTree = SOURCE_ROOT; }; 06FED40B1DD7717E0013DFB2 /* BZip2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BZip2.swift; sourceTree = ""; }; + E648151C26A889B8009261F0 /* TarHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TarHeader.swift; sourceTree = ""; }; E652D8F2263D670900FC229B /* test_nonstandard_runlength.bz2 */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_nonstandard_runlength.bz2; sourceTree = ""; }; E652D8F4263D678000FC229B /* test_nonstandard_runlength.answer */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_nonstandard_runlength.answer; sourceTree = ""; }; E66F36232538726E00076A6E /* test_empty.lzma */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_empty.lzma; sourceTree = ""; }; @@ -632,6 +634,7 @@ 06ADB2D81EBCEFA60053A188 /* TarContainer.swift */, 061C065B1F0E90E600832F0C /* TarEntry.swift */, 0656B8251F8A960700111605 /* TarEntryInfo.swift */, + E648151C26A889B8009261F0 /* TarHeader.swift */, 062C1D7B1F8FCA9300917968 /* TarExtendedHeader.swift */, 0698B10821048FB800A7C551 /* TarCreateError.swift */, 061C06561F0E90C800832F0C /* TarError.swift */, @@ -1150,6 +1153,7 @@ 061C063D1F0E8AB700832F0C /* ZipError.swift in Sources */, 0606CF8120641209002B6EE9 /* BuiltinExtraFields.swift in Sources */, 0631CB061F81109E00A2E0AB /* Deflate+Constants.swift in Sources */, + E648151D26A889B8009261F0 /* TarHeader.swift in Sources */, 06D95AC11F4C54E0006B46AC /* BZip2+Compress.swift in Sources */, 06912BD21F5C8F3D0070BB60 /* Deflate+Lengths.swift in Sources */, 06A9606A1F1E7E0D0078E6D1 /* 7zSubstreamInfo.swift in Sources */, diff --git a/Sources/TAR/TarHeader.swift b/Sources/TAR/TarHeader.swift new file mode 100644 index 00000000..599ee413 --- /dev/null +++ b/Sources/TAR/TarHeader.swift @@ -0,0 +1,135 @@ +// Copyright (c) 2021 Timofey Solomko +// Licensed under MIT License +// +// See LICENSE for license information + +import Foundation +import BitByteData + +struct TarHeader { + + enum HeaderEntryType { + case normal(ContainerEntryType) + case special(SpecialEntryType) + } + + enum SpecialEntryType: UInt8 { + case longName = 76 + case longLinkName = 75 + case globalExtendedHeader = 103 + case localExtendedHeader = 120 + // Sun were the first to use extended headers. Their headers are mostly compatible with PAX ones, but differ in + // the typeflag used ("X" instead of "x"). + case sunExtendedHeader = 88 + } + + let name: String + private(set) var prefix: String? + let size: Int + let type: HeaderEntryType + private(set) var atime: Date? + private(set) var ctime: Date? + private(set) var mtime: Date? + let permissions: Permissions? + let ownerID: Int? + let groupID: Int? + private(set) var ownerUserName: String? + private(set) var ownerGroupName: String? + private(set) var deviceMajorNumber: Int? + private(set) var deviceMinorNumber: Int? + let linkName: String + + let format: TarContainer.Format + + let blockStartIndex: Int + + init(_ reader: LittleEndianByteReader) throws { + self.blockStartIndex = reader.offset + self.name = reader.tarCString(maxLength: 100) + + if let posixAttributes = reader.tarInt(maxLength: 8) { + // Sometimes file mode field also contains unix type, so we need to filter it out. + self.permissions = Permissions(rawValue: UInt32(truncatingIfNeeded: posixAttributes) & 0xFFF) + } else { + self.permissions = nil + } + + self.ownerID = reader.tarInt(maxLength: 8) + self.groupID = reader.tarInt(maxLength: 8) + + guard let size = reader.tarInt(maxLength: 12) + else { throw TarError.wrongField } + self.size = size + + if let mtime = reader.tarInt(maxLength: 12) { + self.mtime = Date(timeIntervalSince1970: TimeInterval(mtime)) + } + + // Checksum + guard let checksum = reader.tarInt(maxLength: 8) + else { throw TarError.wrongHeaderChecksum } + + let currentIndex = reader.offset + reader.offset = blockStartIndex + var headerBytesForChecksum = reader.bytes(count: 512) + headerBytesForChecksum.replaceSubrange(148..<156, with: Array(repeating: 0x20, count: 8)) + reader.offset = currentIndex + + // Some implementations treat bytes as signed integers, but some don't. + // So we check both cases, equality in one of them will pass the checksum test. + let unsignedOurChecksum = headerBytesForChecksum.reduce(0 as UInt) { $0 + UInt(truncatingIfNeeded: $1) } + let signedOurChecksum = headerBytesForChecksum.reduce(0 as Int) { $0 + $1.toInt() } + guard unsignedOurChecksum == UInt(truncatingIfNeeded: checksum) || signedOurChecksum == checksum + else { throw TarError.wrongHeaderChecksum } + + let fileTypeIndicator = reader.byte() + if let specialEntryType = SpecialEntryType(rawValue: fileTypeIndicator) { + self.type = .special(specialEntryType) + } else { + self.type = .normal(ContainerEntryType(fileTypeIndicator)) + } + + self.linkName = reader.tarCString(maxLength: 100) + + // There are two different formats utilizing this section of TAR header: GNU format and POSIX (aka "ustar"; + // PAX containers can also be considered as POSIX). They differ in the value of magic field as well as what + // comes after deviceMinorNumber field. While "ustar" format may contain prefix for file name, GNU format + // uses this place for storing atime/ctime and fields related to sparse-files. In practice, these fields are + // rarely used by GNU tar and only present if "incremental backups" options were used. Thus, GNU format TAR + // container can often be incorrectly considered as having prefix field containing only NULLs. + let magic = reader.uint64() + + if magic == 0x0020207261747375 || magic == 0x3030007261747375 || magic == 0x3030207261747375 { + self.ownerUserName = reader.tarCString(maxLength: 32) + self.ownerGroupName = reader.tarCString(maxLength: 32) + self.deviceMajorNumber = reader.tarInt(maxLength: 8) + self.deviceMinorNumber = reader.tarInt(maxLength: 8) + + if magic == 0x00_20_20_72_61_74_73_75 { // GNU format. + // GNU format mostly is identical to POSIX format and in the common situations can be considered as + // having prefix containing only NULLs. However, in the case of incremental backups produced by GNU tar + // this part of the TAR header is used for storing a lot of different properties. For now, we are only + // reading atime and ctime. + + if let atime = reader.tarInt(maxLength: 12) { + self.atime = Date(timeIntervalSince1970: TimeInterval(atime)) + } + + if let ctime = reader.tarInt(maxLength: 12) { + self.ctime = Date(timeIntervalSince1970: TimeInterval(ctime)) + } + } else { + self.prefix = reader.tarCString(maxLength: 155) + } + } + + if magic == 0x0020207261747375 { + self.format = .gnu + } else if magic == 0x3030007261747375 || magic == 0x3030207261747375 { + self.format = .ustar + } else { + self.format = .prePosix + } + } + +} From 64a85690a35e80c99eff50dfd1f6324d8021a3ff Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 21 Jul 2021 20:22:55 +0300 Subject: [PATCH 53/97] [XZ] Remove wrong doc comment for a private processPadding function --- Sources/XZ/XZArchive.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/XZ/XZArchive.swift b/Sources/XZ/XZArchive.swift index 5ca1ad15..77ce765b 100644 --- a/Sources/XZ/XZArchive.swift +++ b/Sources/XZ/XZArchive.swift @@ -191,7 +191,6 @@ public class XZArchive: Archive { else { throw XZError.wrongMagic } } - /// Returns `true` if end of archive is reached, `false` otherwise. private static func processPadding(_ byteReader: LittleEndianByteReader) throws { guard !byteReader.isFinished else { return } From 0815fee187e0312cbda2cc7ab752544f81f5ed96 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 22 Jul 2021 23:08:19 +0300 Subject: [PATCH 54/97] [TAR] Rename TarEntryInfoProvider.byteReader to reader --- Sources/TAR/TarEntryInfoProvider.swift | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Sources/TAR/TarEntryInfoProvider.swift b/Sources/TAR/TarEntryInfoProvider.swift index b8687085..79ef6af4 100644 --- a/Sources/TAR/TarEntryInfoProvider.swift +++ b/Sources/TAR/TarEntryInfoProvider.swift @@ -10,22 +10,22 @@ import BitByteData // impossible to do so, since `TarEntryInfo.init(...)` is throwing and `IteratorProtocol.next()` cannot be throwing. struct TarEntryInfoProvider { - private let byteReader: LittleEndianByteReader + private let reader: LittleEndianByteReader private var lastGlobalExtendedHeader: TarExtendedHeader? private var lastLocalExtendedHeader: TarExtendedHeader? private var longLinkName: String? private var longName: String? init(_ data: Data) { - self.byteReader = LittleEndianByteReader(data: data) + self.reader = LittleEndianByteReader(data: data) } mutating func next() throws -> TarEntryInfo? { - guard byteReader.bytesLeft >= 1024, - byteReader.data[byteReader.offset..= 1024, + reader.data[reader.offset.. Date: Thu, 22 Jul 2021 23:49:47 +0300 Subject: [PATCH 55/97] [TAR] Update TarEntryInfo.init and TarEntryInfoProvider to use TarHeader Temporarily we had to leave the code that is being moved to TarHeader (such as TarEntryInfo.specialEntryType and blockStartIndex properties), because the format and create functionalities of TAR currently rely on it being present in TarEntryInfo to work. However, we were able to remove TarEntryInfo.SpecialEntryType enum, and use the TarHeader's version of it. --- Sources/TAR/TarEntryInfo.swift | 153 +++++++------------------ Sources/TAR/TarEntryInfoProvider.swift | 20 ++-- 2 files changed, 53 insertions(+), 120 deletions(-) diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index 65450e0a..5136db1e 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -9,16 +9,6 @@ import BitByteData /// Provides access to information about an entry from the TAR container. public struct TarEntryInfo: ContainerEntryInfo { - enum SpecialEntryType: UInt8 { - case longName = 76 - case longLinkName = 75 - case globalExtendedHeader = 103 - case localExtendedHeader = 120 - // Sun were the first to use extended headers. Their headers are mostly compatible with PAX ones, but differ in - // the typeflag used ("X" instead of "x"). - case sunExtendedHeader = 88 - } - // MARK: ContainerEntryInfo /** @@ -177,9 +167,12 @@ public struct TarEntryInfo: ContainerEntryInfo { */ public var unknownExtendedHeaderRecords: [String: String]? - var specialEntryType: SpecialEntryType? + // TODO: Remove + var specialEntryType: TarHeader.SpecialEntryType? + let format: TarContainer.Format + // TODO: Remove let blockStartIndex: Int /** @@ -199,13 +192,10 @@ public struct TarEntryInfo: ContainerEntryInfo { self.blockStartIndex = 0 } - init(_ byteReader: LittleEndianByteReader, _ global: TarExtendedHeader?, _ local: TarExtendedHeader?, + init(_ header: TarHeader, _ global: TarExtendedHeader?, _ local: TarExtendedHeader?, _ longName: String?, _ longLinkName: String?) throws { - self.blockStartIndex = byteReader.offset - - // File name - var name = byteReader.tarCString(maxLength: 100) - + // TODO: Remove + self.blockStartIndex = header.blockStartIndex // General notes for all the properties processing below: // 1. There might be a corresponding field in either global or local extended PAX header. // 2. We still need to read general TAR fields so we can't eliminate auxiliary local let-variables. @@ -214,124 +204,67 @@ public struct TarEntryInfo: ContainerEntryInfo { // Corruption of the container should be detected by checksum comparison, so we decided to ignore them here; // the alternative, which was used in previous versions, is to throw an error. - if let posixAttributes = byteReader.tarInt(maxLength: 8) { - // Sometimes file mode field also contains unix type, so we need to filter it out. - self.permissions = Permissions(rawValue: UInt32(truncatingIfNeeded: posixAttributes) & 0xFFF) - } else { - self.permissions = nil - } - - let ownerAccountID = byteReader.tarInt(maxLength: 8) - self.ownerID = (local?.uid ?? global?.uid) ?? ownerAccountID - - let groupAccountID = byteReader.tarInt(maxLength: 8) - self.groupID = (local?.gid ?? global?.gid) ?? groupAccountID - - guard let fileSize = byteReader.tarInt(maxLength: 12) - else { throw TarError.wrongField } - self.size = (local?.size ?? global?.size) ?? fileSize - - let mtime = byteReader.tarInt(maxLength: 12) + self.permissions = header.permissions + self.ownerID = (local?.uid ?? global?.uid) ?? header.ownerID + self.groupID = (local?.gid ?? global?.gid) ?? header.groupID + self.size = (local?.size ?? global?.size) ?? header.size if let paxMtime = local?.mtime ?? global?.mtime { self.modificationTime = Date(timeIntervalSince1970: paxMtime) - } else if let mtime = mtime { - self.modificationTime = Date(timeIntervalSince1970: TimeInterval(mtime)) + } else { + self.modificationTime = header.mtime } - // Checksum - guard let checksum = byteReader.tarInt(maxLength: 8) - else { throw TarError.wrongHeaderChecksum } - - let currentIndex = byteReader.offset - byteReader.offset = blockStartIndex - var headerBytesForChecksum = byteReader.bytes(count: 512) - headerBytesForChecksum.replaceSubrange(148..<156, with: Array(repeating: 0x20, count: 8)) - byteReader.offset = currentIndex - - // Some implementations treat bytes as signed integers, but some don't. - // So we check both cases, equality in one of them will pass the checksum test. - let unsignedOurChecksum = headerBytesForChecksum.reduce(0 as UInt) { $0 + UInt(truncatingIfNeeded: $1) } - let signedOurChecksum = headerBytesForChecksum.reduce(0 as Int) { $0 + $1.toInt() } - guard unsignedOurChecksum == UInt(truncatingIfNeeded: checksum) || signedOurChecksum == checksum - else { throw TarError.wrongHeaderChecksum } - // File type - let fileTypeIndicator = byteReader.byte() - self.specialEntryType = SpecialEntryType(rawValue: fileTypeIndicator) - self.type = ContainerEntryType(fileTypeIndicator) - - // Linked file name - let linkName = byteReader.tarCString(maxLength: 100) - - // There are two different formats utilizing this section of TAR header: GNU format and POSIX (aka "ustar"; - // PAX containers can also be considered as POSIX). They differ in the value of magic field as well as what - // comes after deviceMinorNumber field. While "ustar" format may contain prefix for file name, GNU format - // uses this place for storing atime/ctime and fields related to sparse-files. In practice, these fields are - // rarely used by GNU tar and only present if "incremental backups" options were used. Thus, GNU format TAR - // container can often be incorrectly considered as having prefix field containing only NULLs. - let magic = byteReader.uint64() - - var gnuAtime: Int? - var gnuCtime: Int? - - if magic == 0x0020207261747375 || magic == 0x3030007261747375 || magic == 0x3030207261747375 { - let uname = byteReader.tarCString(maxLength: 32) - self.ownerUserName = (local?.uname ?? global?.uname) ?? uname - - let gname = byteReader.tarCString(maxLength: 32) - self.ownerGroupName = (local?.gname ?? global?.gname) ?? gname - - self.deviceMajorNumber = byteReader.tarInt(maxLength: 8) - self.deviceMinorNumber = byteReader.tarInt(maxLength: 8) - - if magic == 0x00_20_20_72_61_74_73_75 { // GNU format. - // GNU format mostly is identical to POSIX format and in the common situations can be considered as - // having prefix containing only NULLs. However, in the case of incremental backups produced by GNU tar - // this part of the TAR header is used for storing a lot of different properties. For now, we are only - // reading atime and ctime. - - gnuAtime = byteReader.tarInt(maxLength: 12) - gnuCtime = byteReader.tarInt(maxLength: 12) - } else { - let prefix = byteReader.tarCString(maxLength: 155) - if prefix != "" { - if prefix.last == "/" { - name = prefix + name - } else { - name = prefix + "/" + name - } - } - } - } else { - self.ownerUserName = local?.uname ?? global?.uname - self.ownerGroupName = local?.gname ?? global?.gname + // TODO: +// guard case .normal(let entryType) = header.type +// else { fatalError("TarEntryInfo.init: unexpected TarHeader.type, \(header.type)") } +// self.type = entryType + switch header.type { + case .special(let specialType): + self.specialEntryType = specialType + self.type = .unknown + case .normal(let normalType): + self.type = normalType } + self.ownerUserName = (local?.uname ?? global?.uname) ?? header.ownerUserName + self.ownerGroupName = (local?.gname ?? global?.gname) ?? header.ownerGroupName + self.deviceMajorNumber = header.deviceMajorNumber + self.deviceMinorNumber = header.deviceMinorNumber + if local != nil || global != nil { self.format = .pax - } else if magic == 0x0020207261747375 || longName != nil || longLinkName != nil { + } else if header.format == .gnu || longName != nil || longLinkName != nil { self.format = .gnu - } else if magic == 0x3030007261747375 || magic == 0x3030207261747375 { + } 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 != "" { + if prefix.last == "/" { + name = prefix + name + } else { + name = prefix + "/" + name + } + } self.name = ((local?.path ?? global?.path) ?? longName) ?? name - self.linkName = ((local?.linkpath ?? global?.linkpath) ?? longLinkName) ?? linkName + self.linkName = ((local?.linkpath ?? global?.linkpath) ?? longLinkName) ?? header.linkName // Set additional properties from PAX extended headers. if let atime = local?.atime ?? global?.atime { self.accessTime = Date(timeIntervalSince1970: atime) - } else if let gnuAtime = gnuAtime { - self.accessTime = Date(timeIntervalSince1970: TimeInterval(gnuAtime)) + } else { + self.accessTime = header.atime } if let ctime = local?.ctime ?? global?.ctime { self.creationTime = Date(timeIntervalSince1970: ctime) - } else if let gnuCtime = gnuCtime { - self.creationTime = Date(timeIntervalSince1970: TimeInterval(gnuCtime)) + } else { + self.creationTime = header.ctime } self.charset = local?.charset ?? global?.charset diff --git a/Sources/TAR/TarEntryInfoProvider.swift b/Sources/TAR/TarEntryInfoProvider.swift index 79ef6af4..cc02935e 100644 --- a/Sources/TAR/TarEntryInfoProvider.swift +++ b/Sources/TAR/TarEntryInfoProvider.swift @@ -25,31 +25,31 @@ struct TarEntryInfoProvider { reader.data[reader.offset.. Date: Thu, 22 Jul 2021 23:52:54 +0300 Subject: [PATCH 56/97] [TAR] Rename several properties of TarHeader for consistency --- Sources/TAR/TarEntryInfo.swift | 8 ++++---- Sources/TAR/TarHeader.swift | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index 5136db1e..69de5edd 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -205,8 +205,8 @@ public struct TarEntryInfo: ContainerEntryInfo { // the alternative, which was used in previous versions, is to throw an error. self.permissions = header.permissions - self.ownerID = (local?.uid ?? global?.uid) ?? header.ownerID - self.groupID = (local?.gid ?? global?.gid) ?? header.groupID + self.ownerID = (local?.uid ?? global?.uid) ?? header.uid + self.groupID = (local?.gid ?? global?.gid) ?? header.gid self.size = (local?.size ?? global?.size) ?? header.size if let paxMtime = local?.mtime ?? global?.mtime { self.modificationTime = Date(timeIntervalSince1970: paxMtime) @@ -227,8 +227,8 @@ public struct TarEntryInfo: ContainerEntryInfo { self.type = normalType } - self.ownerUserName = (local?.uname ?? global?.uname) ?? header.ownerUserName - self.ownerGroupName = (local?.gname ?? global?.gname) ?? header.ownerGroupName + self.ownerUserName = (local?.uname ?? global?.uname) ?? header.uname + self.ownerGroupName = (local?.gname ?? global?.gname) ?? header.gname self.deviceMajorNumber = header.deviceMajorNumber self.deviceMinorNumber = header.deviceMinorNumber diff --git a/Sources/TAR/TarHeader.swift b/Sources/TAR/TarHeader.swift index 599ee413..a54ea811 100644 --- a/Sources/TAR/TarHeader.swift +++ b/Sources/TAR/TarHeader.swift @@ -6,6 +6,7 @@ import Foundation import BitByteData +/// This type represents the low-level header structure of the TAR format. struct TarHeader { enum HeaderEntryType { @@ -31,16 +32,15 @@ struct TarHeader { private(set) var ctime: Date? private(set) var mtime: Date? let permissions: Permissions? - let ownerID: Int? - let groupID: Int? - private(set) var ownerUserName: String? - private(set) var ownerGroupName: String? + let uid: Int? + let gid: Int? + private(set) var uname: String? + private(set) var gname: String? private(set) var deviceMajorNumber: Int? private(set) var deviceMinorNumber: Int? let linkName: String let format: TarContainer.Format - let blockStartIndex: Int init(_ reader: LittleEndianByteReader) throws { @@ -54,8 +54,8 @@ struct TarHeader { self.permissions = nil } - self.ownerID = reader.tarInt(maxLength: 8) - self.groupID = reader.tarInt(maxLength: 8) + self.uid = reader.tarInt(maxLength: 8) + self.gid = reader.tarInt(maxLength: 8) guard let size = reader.tarInt(maxLength: 12) else { throw TarError.wrongField } @@ -100,13 +100,13 @@ struct TarHeader { let magic = reader.uint64() if magic == 0x0020207261747375 || magic == 0x3030007261747375 || magic == 0x3030207261747375 { - self.ownerUserName = reader.tarCString(maxLength: 32) - self.ownerGroupName = reader.tarCString(maxLength: 32) + self.uname = reader.tarCString(maxLength: 32) + self.gname = reader.tarCString(maxLength: 32) self.deviceMajorNumber = reader.tarInt(maxLength: 8) self.deviceMinorNumber = reader.tarInt(maxLength: 8) if magic == 0x00_20_20_72_61_74_73_75 { // GNU format. - // GNU format mostly is identical to POSIX format and in the common situations can be considered as + // GNU format is mostly identical to POSIX format and in the common situations can be considered as // having prefix containing only NULLs. However, in the case of incremental backups produced by GNU tar // this part of the TAR header is used for storing a lot of different properties. For now, we are only // reading atime and ctime. From 1730eabc1ce37a5a0195f99d02b864a098734c90 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Thu, 22 Jul 2021 23:55:51 +0300 Subject: [PATCH 57/97] [TAR] TarEntryInfo (internal) init is no longer throwing --- Sources/TAR/TarEntryInfo.swift | 5 ++--- Sources/TAR/TarEntryInfoProvider.swift | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index 69de5edd..9a4587de 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -4,7 +4,6 @@ // See LICENSE for license information import Foundation -import BitByteData /// Provides access to information about an entry from the TAR container. public struct TarEntryInfo: ContainerEntryInfo { @@ -193,7 +192,7 @@ public struct TarEntryInfo: ContainerEntryInfo { } init(_ header: TarHeader, _ global: TarExtendedHeader?, _ local: TarExtendedHeader?, - _ longName: String?, _ longLinkName: String?) throws { + _ longName: String?, _ longLinkName: String?) { // TODO: Remove self.blockStartIndex = header.blockStartIndex // General notes for all the properties processing below: @@ -287,7 +286,7 @@ public struct TarEntryInfo: ContainerEntryInfo { // - crash with fatalError, etc. // - throw an error. // - ignore the problem, and just write NULLs. - // The last option is, obviously, is not ideal. Overall, it seems like using UTF-8 instead of ASCII is the most + // The last option is, obviously, not ideal. Overall, it seems like using UTF-8 instead of ASCII is the most // viable option. var out = Data() diff --git a/Sources/TAR/TarEntryInfoProvider.swift b/Sources/TAR/TarEntryInfoProvider.swift index cc02935e..8debb64d 100644 --- a/Sources/TAR/TarEntryInfoProvider.swift +++ b/Sources/TAR/TarEntryInfoProvider.swift @@ -26,7 +26,7 @@ struct TarEntryInfoProvider { else { return nil } let header = try TarHeader(reader) - let info = try TarEntryInfo(header, lastGlobalExtendedHeader, lastLocalExtendedHeader, longName, longLinkName) + let info = TarEntryInfo(header, lastGlobalExtendedHeader, lastLocalExtendedHeader, longName, longLinkName) let dataStartIndex = header.blockStartIndex + 512 if case .special(let specialEntryType) = header.type { From bdf22b2cc59e2e8972ff5f4bafb84ea66be5e934 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Fri, 23 Jul 2021 16:40:21 +0300 Subject: [PATCH 58/97] [TAR] Add a Data extension function which pads to 512 bytes and appends --- SWCompression.xcodeproj/project.pbxproj | 4 ++++ Sources/TAR/Data+Tar.swift | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 Sources/TAR/Data+Tar.swift diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index 02d51bc4..906a91a1 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -214,6 +214,7 @@ 06F276DF1F2BAB4A00E67335 /* 7zEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06F276DE1F2BAB4900E67335 /* 7zEntry.swift */; }; 06FEAD921F54B9CD00AD016E /* EncodingTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06FEAD911F54B9CD00AD016E /* EncodingTree.swift */; }; E648151D26A889B8009261F0 /* TarHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = E648151C26A889B8009261F0 /* TarHeader.swift */; }; + E64F71BC26AAFD6A008BB308 /* Data+Tar.swift in Sources */ = {isa = PBXBuildFile; fileRef = E64F71BB26AAFD6A008BB308 /* Data+Tar.swift */; }; E652D8F3263D670900FC229B /* test_nonstandard_runlength.bz2 in Resources */ = {isa = PBXBuildFile; fileRef = E652D8F2263D670900FC229B /* test_nonstandard_runlength.bz2 */; }; E652D8F5263D678000FC229B /* test_nonstandard_runlength.answer in Resources */ = {isa = PBXBuildFile; fileRef = E652D8F4263D678000FC229B /* test_nonstandard_runlength.answer */; }; E66F36242538726E00076A6E /* test_empty.lzma in Resources */ = {isa = PBXBuildFile; fileRef = E66F36232538726E00076A6E /* test_empty.lzma */; }; @@ -439,6 +440,7 @@ 06FEAD911F54B9CD00AD016E /* EncodingTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EncodingTree.swift; path = Sources/Common/CodingTree/EncodingTree.swift; sourceTree = SOURCE_ROOT; }; 06FED40B1DD7717E0013DFB2 /* BZip2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BZip2.swift; sourceTree = ""; }; E648151C26A889B8009261F0 /* TarHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TarHeader.swift; sourceTree = ""; }; + E64F71BB26AAFD6A008BB308 /* Data+Tar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+Tar.swift"; sourceTree = ""; }; E652D8F2263D670900FC229B /* test_nonstandard_runlength.bz2 */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_nonstandard_runlength.bz2; sourceTree = ""; }; E652D8F4263D678000FC229B /* test_nonstandard_runlength.answer */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_nonstandard_runlength.answer; sourceTree = ""; }; E66F36232538726E00076A6E /* test_empty.lzma */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_empty.lzma; sourceTree = ""; }; @@ -641,6 +643,7 @@ 0651FEC11F8E2E9100C49646 /* ContainerEntryType+Tar.swift */, 0656B82A1F8A979A00111605 /* ByteReader+Tar.swift */, 06CFF6B12078C5A5003B8375 /* TarEntryInfoProvider.swift */, + E64F71BB26AAFD6A008BB308 /* Data+Tar.swift */, ); path = TAR; sourceTree = ""; @@ -1112,6 +1115,7 @@ buildActionMask = 2147483647; files = ( 061C06521F0E904600832F0C /* ZipEndOfCentralDirectory.swift in Sources */, + E64F71BC26AAFD6A008BB308 /* Data+Tar.swift in Sources */, 06BB8F301E0C2C720079FB9E /* LZMA2.swift in Sources */, 0620F4C31F8E24B6001C9B7A /* CompressionAlgorithm.swift in Sources */, 06955E491F65C761004D5D79 /* BZip2+Lengths.swift in Sources */, diff --git a/Sources/TAR/Data+Tar.swift b/Sources/TAR/Data+Tar.swift new file mode 100644 index 00000000..c6b4f289 --- /dev/null +++ b/Sources/TAR/Data+Tar.swift @@ -0,0 +1,17 @@ +// Copyright (c) 2021 Timofey Solomko +// Licensed under MIT License +// +// See LICENSE for license information + +import Foundation + +extension Data { + + @inline(__always) + mutating func appendAsTarBlock(_ data: Data) { + self.append(data) + let paddingSize = data.count.roundTo512() - data.count + self.append(Data(count: paddingSize)) + } + +} From 0bc1987500c6fb5ce2a0500c36c6de141865d728 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Fri, 23 Jul 2021 16:52:42 +0300 Subject: [PATCH 59/97] [TAR] Add two new initializers to TarHeader One creates a header based on TarEntryInfo, and the second one creates a header for special entries like pax headers. --- Sources/TAR/TarHeader.swift | 50 +++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/Sources/TAR/TarHeader.swift b/Sources/TAR/TarHeader.swift index a54ea811..dd92fdec 100644 --- a/Sources/TAR/TarHeader.swift +++ b/Sources/TAR/TarHeader.swift @@ -110,26 +110,60 @@ struct TarHeader { // having prefix containing only NULLs. However, in the case of incremental backups produced by GNU tar // this part of the TAR header is used for storing a lot of different properties. For now, we are only // reading atime and ctime. - if let atime = reader.tarInt(maxLength: 12) { self.atime = Date(timeIntervalSince1970: TimeInterval(atime)) } - if let ctime = reader.tarInt(maxLength: 12) { self.ctime = Date(timeIntervalSince1970: TimeInterval(ctime)) } + self.format = .gnu } else { self.prefix = reader.tarCString(maxLength: 155) + self.format = .ustar } - } - - if magic == 0x0020207261747375 { - self.format = .gnu - } else if magic == 0x3030007261747375 || magic == 0x3030207261747375 { - self.format = .ustar } else { self.format = .prePosix } } + init(specialName: String, specialType: SpecialEntryType, size: Int, uid: Int?, gid: Int?) { + self.name = specialName + self.type = .special(specialType) + self.size = size + self.permissions = Permissions(rawValue: 420) + self.uid = uid + self.gid = gid + self.mtime = Date() + self.linkName = "" + if specialType == .longName || specialType == .longLinkName { + self.format = .gnu + } else if specialType == .globalExtendedHeader || specialType == .localExtendedHeader { + self.format = .pax + } else { + self.format = .prePosix + } + // Unused if header was created using this initializer. + self.blockStartIndex = -1 + } + + 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.atime = info.accessTime + self.ctime = info.creationTime + self.mtime = info.modificationTime + self.permissions = info.permissions + self.uid = info.ownerID + self.gid = info.groupID + self.uname = info.ownerUserName + self.gname = info.ownerGroupName + 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`. + // Unused if header was created using this initializer. + self.blockStartIndex = -1 + } + } From 11a2054498d3a0ddc1ff9673d75d4696655ee192 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 13:56:52 +0300 Subject: [PATCH 60/97] [TAR] Move Data extensions from TarEntryInfo into separate file In addition Data.append(tarString:maxLength:) has been modified to not be throwing. --- Sources/TAR/Data+Tar.swift | 42 +++++++++++++++++++++++++++++ Sources/TAR/TarEntryInfo.swift | 48 ---------------------------------- 2 files changed, 42 insertions(+), 48 deletions(-) diff --git a/Sources/TAR/Data+Tar.swift b/Sources/TAR/Data+Tar.swift index c6b4f289..489c713d 100644 --- a/Sources/TAR/Data+Tar.swift +++ b/Sources/TAR/Data+Tar.swift @@ -14,4 +14,46 @@ extension Data { self.append(Data(count: paddingSize)) } + mutating func append(tarInt value: Int?, maxLength: Int) { + guard var value = value else { + // No value; fill field with NULLs. + self.append(Data(count: maxLength)) + return + } + + let maxOctalValue = (1 << (maxLength * 3)) - 1 + guard value > maxOctalValue || value < 0 else { + // Normal octal encoding. + self.append(Data(String(value, radix: 8).utf8).zeroPad(maxLength)) + return + } + + // Base-256 encoding. + 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) + value >>= 8 + } + buffer[0] |= 0x80 // Highest bit indicates base-256 encoding. + self.append(Data(buffer)) + } + + mutating func append(tarString string: String?, maxLength: Int) { + guard let string = string else { + // No value; fill field with NULLs. + self.append(Data(count: maxLength)) + return + } + self.append(Data(string.utf8).zeroPad(maxLength)) + } + + /// 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 + } + } diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index 9a4587de..7be5ee60 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -367,51 +367,3 @@ public struct TarEntryInfo: ContainerEntryInfo { } } - -fileprivate 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 { - var out = length < self.count ? self.prefix(upTo: length) : self - out.append(Data(count: length - out.count)) - return out - } - - mutating func append(tarInt value: Int?, maxLength: Int) { - guard var value = value else { - // No value; fill field with NULLs. - self.append(Data(count: maxLength)) - return - } - - let maxOctalValue = (1 << (maxLength * 3)) - 1 - guard value > maxOctalValue || value < 0 else { - // Normal octal encoding. - self.append(String(value, radix: 8).data(using: .utf8)!.zeroPad(maxLength)) - return - } - - // Base-256 encoding. - 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) - value >>= 8 - } - buffer[0] |= 0x80 // Highest bit indicates base-256 encoding. - self.append(Data(buffer)) - } - - mutating func append(tarString string: String?, maxLength: Int) throws { - guard let string = string else { - // No value; fill field with NULLs. - self.append(Data(count: maxLength)) - return - } - - guard let stringData = string.data(using: .utf8)?.zeroPad(maxLength) - else { throw TarCreateError.utf8NonEncodable } - self.append(stringData) - } - -} From 082aaf5092b342f7fc7d9f90cc0fad05a69d08ff Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 14:09:34 +0300 Subject: [PATCH 61/97] [TAR] Reorder and comment properties of TarHeader to clarify used formats --- Sources/TAR/TarHeader.swift | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Sources/TAR/TarHeader.swift b/Sources/TAR/TarHeader.swift index dd92fdec..73ae9563 100644 --- a/Sources/TAR/TarHeader.swift +++ b/Sources/TAR/TarHeader.swift @@ -24,21 +24,29 @@ struct TarHeader { case sunExtendedHeader = 88 } + // These fields are present in all formats. let name: String - private(set) var prefix: String? - let size: Int - let type: HeaderEntryType - private(set) var atime: Date? - private(set) var ctime: Date? - private(set) var mtime: Date? let permissions: Permissions? let uid: Int? let gid: Int? + let size: Int + private(set) var mtime: Date? + // - checksum + let type: HeaderEntryType + let linkName: String + + // Ustar only + // - magic private(set) var uname: String? private(set) var gname: String? private(set) var deviceMajorNumber: Int? private(set) var deviceMinorNumber: Int? - let linkName: String + private(set) var prefix: String? + + // These fields are present in gnu and star formats. + // - magic + private(set) var atime: Date? + private(set) var ctime: Date? let format: TarContainer.Format let blockStartIndex: Int From 7c54d2b9912c6f9f9f342aa737d905f26aacf4bf Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 14:10:04 +0300 Subject: [PATCH 62/97] [TAR] Implement TarHeader.generateContainerData --- Sources/TAR/TarHeader.swift | 101 ++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/Sources/TAR/TarHeader.swift b/Sources/TAR/TarHeader.swift index 73ae9563..efe73f91 100644 --- a/Sources/TAR/TarHeader.swift +++ b/Sources/TAR/TarHeader.swift @@ -174,4 +174,105 @@ struct TarHeader { self.blockStartIndex = -1 } + /// This function overrides the value stored in the `format` property. + func generateContainerData(_ format: TarContainer.Format) -> Data { + // It is not possible to encode non-english characters with ASCII (expectedly), so we are using UTF-8. + // While this contradicts format specification, in case of ustar and basic TAR format our other options in + // situation when it is not possible to encode with ASCII are: + // - crash with fatalError, etc. + // - throw an error. + // - ignore the problem, and just write NULLs. + // The last option is, obviously, not ideal. Overall, it seems like using UTF-8 instead of ASCII is the most + // viable option. + + var out = Data() + + out.append(tarString: self.name, maxLength: 100) + + out.append(tarInt: self.permissions?.rawValue.toInt(), maxLength: 8) + out.append(tarInt: self.uid, maxLength: 8) + out.append(tarInt: self.gid, maxLength: 8) + out.append(tarInt: self.size, maxLength: 12) + + if let mtime = self.mtime?.timeIntervalSince1970 { + out.append(tarInt: Int(mtime), maxLength: 12) + } else { + out.append(tarInt: nil, maxLength: 12) + } + + // Checksum is calculated based on the complete header with spaces instead of checksum. + out.append(contentsOf: Array(repeating: 0x20, count: 8)) + + let fileTypeIndicator: UInt8 + switch self.type { + case .normal(let entryType): + fileTypeIndicator = entryType.fileTypeIndicator + case .special(let specialType): + fileTypeIndicator = specialType.rawValue + } + out.append(fileTypeIndicator) + + out.append(tarString: self.linkName, maxLength: 100) + + // For prePosix format there is no additional fields. + + if format == .ustar || format == .pax { + // The header layouts for these two formats are identical. + out.append(contentsOf: [0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30]) // "ustar\000" + // In theory, user/group name is not guaranteed to have only ASCII characters, so the same disclaimer as for + // file name field applies here. + out.append(tarString: self.uname, maxLength: 32) + out.append(tarString: self.gname, maxLength: 32) + out.append(tarInt: self.deviceMajorNumber, maxLength: 8) + out.append(tarInt: self.deviceMinorNumber, maxLength: 8) + + // 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 + if maxPrefixLength > 156 { + // We can set actual maximum possible length of prefix equal to 156 and not 155, because it may + // include trailing slash which will be removed during splitting. + maxPrefixLength = 156 + } else if nameData[maxPrefixLength - 1] == 0x2F { + // Skip trailing slash. + maxPrefixLength -= 1 + } + + // 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. + let lastPrefixSlashIndex = nameData.prefix(upTo: maxPrefixLength) + .range(of: Data([0x2f]), options: .backwards)?.lowerBound ?? -1 + let updatedNameLength = nameData.count - lastPrefixSlashIndex - 1 + let prefixLength = lastPrefixSlashIndex + + if lastPrefixSlashIndex <= 0 || updatedNameLength > 100 || updatedNameLength == 0 || prefixLength > 155 { + // Unsplittable name. + out.append(Data(count: 155)) + } else { + // Add prefix data to output. + out.append(nameData.prefix(upTo: lastPrefixSlashIndex)) + // Update name field data in output. + var newNameData = nameData.suffix(from: lastPrefixSlashIndex + 1) + newNameData.append(Data(count: 100 - newNameData.count)) + out.replaceSubrange(0..<100, with: newNameData) + } + } else { + out.append(Data(count: 155)) // Empty prefix + } + } else if format == .gnu { + // TODO: + } + + // Checksum calculation. + // First, we pad header data to 512 bytes. + out.append(Data(count: 512 - out.count)) + let checksum = out.reduce(0 as Int) { $0 + $1.toInt() } + let checksumString = String(format: "%06o", checksum).appending("\0 ") + out.replaceSubrange(148..<156, with: checksumString.data(using: .ascii)!) + + return out + } + } From 017afa06b805482154815a6ffcd19424cedc0a4d Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 14:15:35 +0300 Subject: [PATCH 63/97] [TAR] Add TarContainer.create(from:force:) function which can be used to specify tar format In addition use this new function in the old TarContainer.create(from:) function with .pax format. --- Sources/TAR/TarContainer.swift | 66 ++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 8d998151..741a2481 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -77,26 +77,64 @@ public class TarContainer: Container { format used during container creation. */ public static func create(from entries: [TarEntry]) throws -> Data { + try create(from: entries, force: .pax) + } + + public static func create(from entries: [TarEntry], force format: TarContainer.Format) throws -> 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 TarHeader. + // 3. For each TarHeader we generate binary data, and the append it with the content of the special entry to + // the output. + // 4. Perform the previous two steps for the entry itself. + // Every time we append something to the output we also make sure that the data is padded to 512 byte-long blocks. + + // TODO: Add counters for special entries. Check if overflow. var out = Data() - var extHeadersCount = 0 for entry in entries { - let extHeader = TarExtendedHeader(entry.info) - let extHeaderData = try extHeader.generateContainerData() - if !extHeaderData.isEmpty { - var extHeaderInfo = TarEntryInfo(name: "SWC_PaxHeader_\(extHeadersCount)", type: .unknown) - extHeaderInfo.specialEntryType = .localExtendedHeader - extHeaderInfo.permissions = Permissions(rawValue: 420) - extHeaderInfo.ownerID = entry.info.ownerID - extHeaderInfo.groupID = entry.info.groupID - extHeaderInfo.modificationTime = Date() + if format == .gnu { + if entry.info.name.utf8.count > 100 { + guard let nameData = entry.info.name.data(using: .utf8) + else { throw TarCreateError.utf8NonEncodable } + let longNameHeader = TarHeader(specialName: "SWC_LongName", specialType: .longName, + size: nameData.count, uid: entry.info.ownerID, + gid: entry.info.groupID) + out.append(longNameHeader.generateContainerData(.gnu)) + assert(out.count % 512 == 0) + out.appendAsTarBlock(nameData) + } - let extHeaderEntry = TarEntry(info: extHeaderInfo, data: extHeaderData) - try out.append(extHeaderEntry.generateContainerData()) + if entry.info.linkName.utf8.count > 100 { + guard let linkNameData = entry.info.linkName.data(using: .utf8) + else { throw TarCreateError.utf8NonEncodable } + let longLinkNameHeader = TarHeader(specialName: "SWC_LongLinkName", specialType: .longLinkName, + size: linkNameData.count, uid: entry.info.ownerID, + gid: entry.info.groupID) + out.append(longLinkNameHeader.generateContainerData(.gnu)) + assert(out.count % 512 == 0) + out.appendAsTarBlock(linkNameData) + } + } else if format == .pax { + let extHeader = TarExtendedHeader(entry.info) + let extHeaderData = try extHeader.generateContainerData() + if !extHeaderData.isEmpty { + let extHeaderHeader = TarHeader(specialName: "SWC_LocalPaxHeader", specialType: .localExtendedHeader, + size: extHeaderData.count, uid: entry.info.ownerID, + gid: entry.info.groupID) + out.append(extHeaderHeader.generateContainerData(.pax)) + assert(out.count % 512 == 0) + out.appendAsTarBlock(extHeaderData) + } + } - extHeadersCount += 1 + let header = TarHeader(entry.info) + out.append(header.generateContainerData(format)) + assert(out.count % 512 == 0) + if let data = entry.data { + out.appendAsTarBlock(data) } - try out.append(entry.generateContainerData()) } + // Two 512-byte blocks consisting of zeros as an EOF marker. out.append(Data(count: 1024)) return out } From c87e8bece78e1de4da4988fb989d9b2b3d8f8871 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 14:16:15 +0300 Subject: [PATCH 64/97] [TAR] Remove unused generateContainerData function from TarEntry[Info] --- Sources/TAR/TarEntry.swift | 10 ---- Sources/TAR/TarEntryInfo.swift | 87 ---------------------------------- 2 files changed, 97 deletions(-) diff --git a/Sources/TAR/TarEntry.swift b/Sources/TAR/TarEntry.swift index 20918f01..a3da7ee1 100644 --- a/Sources/TAR/TarEntry.swift +++ b/Sources/TAR/TarEntry.swift @@ -35,14 +35,4 @@ public struct TarEntry: ContainerEntry { self.data = data } - func generateContainerData() throws -> Data { - var out = try self.info.generateContainerData() - guard let data = self.data - else { return out } - out.append(data) - let paddingSize = data.count.roundTo512() - data.count - out.append(Data(count: paddingSize)) - return out - } - } diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index 7be5ee60..f6075bc3 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -279,91 +279,4 @@ public struct TarEntryInfo: ContainerEntryInfo { } } - func generateContainerData() throws -> Data { - // It is not possible to encode non-english characters with ASCII (expectedly), so we are using UTF-8. - // While this contradicts format specification, in case of ustar and basic TAR format our other options in - // situation when it is not possible to encode with ASCII are: - // - crash with fatalError, etc. - // - throw an error. - // - ignore the problem, and just write NULLs. - // The last option is, obviously, not ideal. Overall, it seems like using UTF-8 instead of ASCII is the most - // viable option. - - var out = Data() - - try out.append(tarString: self.name, maxLength: 100) - - out.append(tarInt: self.permissions?.rawValue.toInt(), maxLength: 8) - out.append(tarInt: self.ownerID, maxLength: 8) - out.append(tarInt: self.groupID, maxLength: 8) - out.append(tarInt: self.size, maxLength: 12) - - if let mtime = self.modificationTime?.timeIntervalSince1970 { - out.append(tarInt: Int(mtime), maxLength: 12) - } else { - out.append(tarInt: nil, maxLength: 12) - } - - // Checksum is calculated based on the complete header with spaces instead of checksum. - out.append(contentsOf: Array(repeating: 0x20, count: 8)) - - let fileTypeIndicator = self.specialEntryType?.rawValue ?? self.type.fileTypeIndicator - out.append(fileTypeIndicator) - - try out.append(tarString: self.linkName, maxLength: 100) - - out.append(contentsOf: [0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30]) // "ustar\000" - // In theory, user/group name is not guaranteed to have only ASCII characters, so the same disclaimer as for - // file name field applies here. - try out.append(tarString: self.ownerUserName, maxLength: 32) - try out.append(tarString: self.ownerGroupName, maxLength: 32) - out.append(tarInt: self.deviceMajorNumber, maxLength: 8) - out.append(tarInt: self.deviceMinorNumber, maxLength: 8) - - guard let nameData = self.name.data(using: .utf8) - else { throw TarCreateError.utf8NonEncodable } - - if nameData.count > 100 { - var maxPrefixLength = nameData.count - if maxPrefixLength > 156 { - // We can set actual maximum possible length of prefix equal to 156 and not 155, because it may - // include trailing slash which will be removed during splitting. - maxPrefixLength = 156 - } else if nameData[maxPrefixLength - 1] == 0x2F { - // Skip trailing slash. - maxPrefixLength -= 1 - } - - // 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. - let lastPrefixSlashIndex = nameData.prefix(upTo: maxPrefixLength) - .range(of: Data([0x2f]), options: .backwards)?.lowerBound ?? -1 - let updatedNameLength = nameData.count - lastPrefixSlashIndex - 1 - let prefixLength = lastPrefixSlashIndex - - if lastPrefixSlashIndex <= 0 || updatedNameLength > 100 || updatedNameLength == 0 || prefixLength > 155 { - // Unsplittable name. - out.append(Data(count: 155)) - } else { - // Add prefix data to output. - out.append(nameData.prefix(upTo: lastPrefixSlashIndex)) - // Update name field data in output. - var newNameData = nameData.suffix(from: lastPrefixSlashIndex + 1) - newNameData.append(Data(count: 100 - newNameData.count)) - out.replaceSubrange(0..<100, with: newNameData) - } - } else { - out.append(Data(count: 155)) // Empty prefix - } - - // Checksum calculation. - // First, we pad header data to 512 bytes. - out.append(Data(count: 512 - out.count)) - let checksum = out.reduce(0 as Int) { $0 + $1.toInt() } - let checksumString = String(format: "%06o", checksum).appending("\0 ") - out.replaceSubrange(148..<156, with: checksumString.data(using: .ascii)!) - - return out - } - } From 505f35fc2815b2406099bb695de9d4156499c3c3 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 14:21:27 +0300 Subject: [PATCH 65/97] [TAR] Make TarContainer.create non-throwing by removing the usage of TarCreateError.utf8NonEncodable --- Sources/TAR/TarContainer.swift | 14 ++++++------ Sources/TAR/TarExtendedHeader.swift | 33 ++++++++++++++--------------- Tests/TarCreateTests.swift | 18 ++++++++-------- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 741a2481..51f078c9 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -76,11 +76,11 @@ public class TarContainer: Container { - 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]) throws -> Data { - try create(from: entries, force: .pax) + public static func create(from entries: [TarEntry]) -> Data { + create(from: entries, force: .pax) } - public static func create(from entries: [TarEntry], force format: TarContainer.Format) throws -> Data { + 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 TarHeader. @@ -94,8 +94,7 @@ public class TarContainer: Container { for entry in entries { if format == .gnu { if entry.info.name.utf8.count > 100 { - guard let nameData = entry.info.name.data(using: .utf8) - else { throw TarCreateError.utf8NonEncodable } + let nameData = Data(entry.info.name.utf8) let longNameHeader = TarHeader(specialName: "SWC_LongName", specialType: .longName, size: nameData.count, uid: entry.info.ownerID, gid: entry.info.groupID) @@ -105,8 +104,7 @@ public class TarContainer: Container { } if entry.info.linkName.utf8.count > 100 { - guard let linkNameData = entry.info.linkName.data(using: .utf8) - else { throw TarCreateError.utf8NonEncodable } + let linkNameData = Data(entry.info.linkName.utf8) let longLinkNameHeader = TarHeader(specialName: "SWC_LongLinkName", specialType: .longLinkName, size: linkNameData.count, uid: entry.info.ownerID, gid: entry.info.groupID) @@ -116,7 +114,7 @@ public class TarContainer: Container { } } else if format == .pax { let extHeader = TarExtendedHeader(entry.info) - let extHeaderData = try extHeader.generateContainerData() + let extHeaderData = extHeader.generateContainerData() if !extHeaderData.isEmpty { let extHeaderHeader = TarHeader(specialName: "SWC_LocalPaxHeader", specialType: .localExtendedHeader, size: extHeaderData.count, uid: entry.info.ownerID, diff --git a/Sources/TAR/TarExtendedHeader.swift b/Sources/TAR/TarExtendedHeader.swift index d7f23922..7dcc3c73 100644 --- a/Sources/TAR/TarExtendedHeader.swift +++ b/Sources/TAR/TarExtendedHeader.swift @@ -128,66 +128,65 @@ struct TarExtendedHeader { self.unknownRecords = info.unknownExtendedHeaderRecords ?? [:] } - func generateContainerData() throws -> Data { + func generateContainerData() -> Data { var headerString = "" if let atime = self.atime { - headerString += try TarExtendedHeader.generateHeaderString("atime", String(atime)) + headerString += TarExtendedHeader.generateHeaderString("atime", String(atime)) } if let ctime = self.ctime { - headerString += try TarExtendedHeader.generateHeaderString("ctime", String(ctime)) + headerString += TarExtendedHeader.generateHeaderString("ctime", String(ctime)) } if let mtime = self.mtime { - headerString += try TarExtendedHeader.generateHeaderString("mtime", String(mtime)) + headerString += TarExtendedHeader.generateHeaderString("mtime", String(mtime)) } if let size = self.size { - headerString += try TarExtendedHeader.generateHeaderString("size", String(size)) + headerString += TarExtendedHeader.generateHeaderString("size", String(size)) } if let uid = self.uid { - headerString += try TarExtendedHeader.generateHeaderString("uid", String(uid)) + headerString += TarExtendedHeader.generateHeaderString("uid", String(uid)) } if let gid = self.gid { - headerString += try TarExtendedHeader.generateHeaderString("gid", String(gid)) + headerString += TarExtendedHeader.generateHeaderString("gid", String(gid)) } if let uname = self.uname { - headerString += try TarExtendedHeader.generateHeaderString("uname", uname) + headerString += TarExtendedHeader.generateHeaderString("uname", uname) } if let gname = self.gname { - headerString += try TarExtendedHeader.generateHeaderString("gname", gname) + headerString += TarExtendedHeader.generateHeaderString("gname", gname) } if let path = self.path { - headerString += try TarExtendedHeader.generateHeaderString("path", path) + headerString += TarExtendedHeader.generateHeaderString("path", path) } if let linkpath = self.linkpath { - headerString += try TarExtendedHeader.generateHeaderString("linkpath", linkpath) + headerString += TarExtendedHeader.generateHeaderString("linkpath", linkpath) } if let charset = self.charset { - headerString += try TarExtendedHeader.generateHeaderString("charset", charset) + headerString += TarExtendedHeader.generateHeaderString("charset", charset) } if let comment = self.comment { - headerString += try TarExtendedHeader.generateHeaderString("comment", comment) + headerString += TarExtendedHeader.generateHeaderString("comment", comment) } for (key, value) in self.unknownRecords { - headerString += try TarExtendedHeader.generateHeaderString(key, value) + headerString += TarExtendedHeader.generateHeaderString(key, value) } return headerString.data(using: .utf8)! } - private static func generateHeaderString(_ fieldName: String, _ valueString: String) throws -> String { - guard let valueCount = valueString.data(using: .utf8)?.count - else { throw TarCreateError.utf8NonEncodable } + private static func generateHeaderString(_ fieldName: String, _ valueString: String) -> String { + let valueCount = Data(valueString.utf8).count return TarExtendedHeader.calculateCountString(fieldName, valueCount) + " \(fieldName)=\(valueString)\n" } diff --git a/Tests/TarCreateTests.swift b/Tests/TarCreateTests.swift index 4c85bab9..cea0a7eb 100644 --- a/Tests/TarCreateTests.swift +++ b/Tests/TarCreateTests.swift @@ -23,7 +23,7 @@ class TarCreateTests: XCTestCase { let data = "Hello, World!\n".data(using: .utf8)! let entry = TarEntry(info: info, data: data) - let containerData = try TarContainer.create(from: [entry]) + let containerData = TarContainer.create(from: [entry]) let newEntries = try TarContainer.open(container: containerData) XCTAssertEqual(newEntries.count, 1) @@ -62,7 +62,7 @@ class TarCreateTests: XCTestCase { info.linkName = "file" info.unknownExtendedHeaderRecords = dict - let containerData = try TarContainer.create(from: [TarEntry(info: info, data: Data())]) + let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())]) let newInfo = try TarContainer.open(container: containerData)[0].info XCTAssertEqual(newInfo.name, "symbolic-link") @@ -90,7 +90,7 @@ class TarCreateTests: XCTestCase { info.name.append(String(repeating: "readme/", count: 15)) info.name.append("readme.txt") - let containerData = try TarContainer.create(from: [TarEntry(info: info, data: Data())]) + let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())]) let newInfo = try TarContainer.open(container: containerData)[0].info // This name should fit into ustar format using "prefix" field @@ -103,7 +103,7 @@ class TarCreateTests: XCTestCase { info.name.append(String(repeating: "readme/", count: 25)) info.name.append("readme.txt") - let containerData = try TarContainer.create(from: [TarEntry(info: info, data: Data())]) + let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())]) let newInfo = try TarContainer.open(container: containerData)[0].info XCTAssertEqual(newInfo.name, info.name) @@ -115,7 +115,7 @@ class TarCreateTests: XCTestCase { info.name = "path/to/" info.name.append(String(repeating: "readme/", count: 15)) - let containerData = try TarContainer.create(from: [TarEntry(info: info, data: Data())]) + let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())]) let newInfo = try TarContainer.open(container: containerData)[0].info XCTAssertEqual(newInfo.name, info.name) @@ -137,7 +137,7 @@ class TarCreateTests: XCTestCase { info.comment = "комментарий" info.linkName = "путь/к/файлу" - let containerData = try TarContainer.create(from: [TarEntry(info: info, data: Data())]) + 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 @@ -165,7 +165,7 @@ class TarCreateTests: XCTestCase { info.groupID = 20 info.modificationTime = date - let containerData = try TarContainer.create(from: [TarEntry(info: info, data: Data())]) + let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())]) XCTAssertEqual(try TarContainer.formatOf(container: containerData), .ustar) let newInfo = try TarContainer.open(container: containerData)[0].info @@ -189,7 +189,7 @@ class TarCreateTests: XCTestCase { var info = TarEntryInfo(name: "file.txt", type: .regular) info.modificationTime = date - let containerData = try TarContainer.create(from: [TarEntry(info: info, data: Data())]) + 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 @@ -213,7 +213,7 @@ class TarCreateTests: XCTestCase { var info = TarEntryInfo(name: "file.txt", type: .regular) info.ownerID = uid - let containerData = try TarContainer.create(from: [TarEntry(info: info, data: Data())]) + 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 From 3e96a84f6227828590d9e885d92abd5f277b2a41 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 14:23:10 +0300 Subject: [PATCH 66/97] [TAR] Add a docs note to TarCreateError about it being never used --- Sources/TAR/TarCreateError.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Sources/TAR/TarCreateError.swift b/Sources/TAR/TarCreateError.swift index 61312585..15b89d8b 100644 --- a/Sources/TAR/TarCreateError.swift +++ b/Sources/TAR/TarCreateError.swift @@ -6,9 +6,13 @@ /** Represents an error which happened during the creation of a new TAR container. - - Note: This error type is going to be merged with `TarError` in the next major update. + - Note: This error type is never used and will be removed in the next major update. */ public enum TarCreateError: Error { - /// One of the `TarEntryInfo`'s string properties (such as `name`) cannot be encoded with UTF-8 encoding. + /** + One of the `TarEntryInfo`'s string properties (such as `name`) cannot be encoded with UTF-8 encoding. + + - Note: This error is never thrown and will be removed in the next major update. + */ case utf8NonEncodable } From 5de2bc57686768fb6f6a6c50179755eee7d5f493 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 14:26:14 +0300 Subject: [PATCH 67/97] Change conversion of utf8 strings to data without optional unwraps --- Sources/TAR/TarExtendedHeader.swift | 2 +- Tests/Sha256Tests.swift | 14 +++++++------- Tests/TarCreateTests.swift | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Sources/TAR/TarExtendedHeader.swift b/Sources/TAR/TarExtendedHeader.swift index 7dcc3c73..b2443a6e 100644 --- a/Sources/TAR/TarExtendedHeader.swift +++ b/Sources/TAR/TarExtendedHeader.swift @@ -182,7 +182,7 @@ struct TarExtendedHeader { headerString += TarExtendedHeader.generateHeaderString(key, value) } - return headerString.data(using: .utf8)! + return Data(headerString.utf8) } private static func generateHeaderString(_ fieldName: String, _ valueString: String) -> String { diff --git a/Tests/Sha256Tests.swift b/Tests/Sha256Tests.swift index 166552a4..82cd55f2 100644 --- a/Tests/Sha256Tests.swift +++ b/Tests/Sha256Tests.swift @@ -12,14 +12,14 @@ class Sha256Tests: XCTestCase { func test1() { let message = "" let answer = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - let hash = Sha256.hash(data: message.data(using: .utf8)!) + let hash = Sha256.hash(data: Data(message.utf8)) XCTAssertEqual(hash.map { String(format: "%02x", $0) }.joined(), answer) } func test2() { let message = "a" let answer = "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" - let data = message.data(using: .utf8)! + let data = Data(message.utf8) let hash = Sha256.hash(data: data) XCTAssertEqual(hash.map { String(format: "%02x", $0) }.joined(), answer) } @@ -27,7 +27,7 @@ class Sha256Tests: XCTestCase { func test3() { let message = "abc" let answer = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" - let data = message.data(using: .utf8)! + let data = Data(message.utf8) let hash = Sha256.hash(data: data) XCTAssertEqual(hash.map { String(format: "%02x", $0) }.joined(), answer) } @@ -35,7 +35,7 @@ class Sha256Tests: XCTestCase { func test4() { let message = "message digest" let answer = "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650" - let data = message.data(using: .utf8)! + let data = Data(message.utf8) let hash = Sha256.hash(data: data) XCTAssertEqual(hash.map { String(format: "%02x", $0) }.joined(), answer) } @@ -43,7 +43,7 @@ class Sha256Tests: XCTestCase { func test5() { let message = "abcdefghijklmnopqrstuvwxyz" let answer = "71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73" - let data = message.data(using: .utf8)! + let data = Data(message.utf8) let hash = Sha256.hash(data: data) XCTAssertEqual(hash.map { String(format: "%02x", $0) }.joined(), answer) } @@ -51,7 +51,7 @@ class Sha256Tests: XCTestCase { func test6() { let message = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" let answer = "db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0" - let data = message.data(using: .utf8)! + let data = Data(message.utf8) let hash = Sha256.hash(data: data) XCTAssertEqual(hash.map { String(format: "%02x", $0) }.joined(), answer) } @@ -59,7 +59,7 @@ class Sha256Tests: XCTestCase { func test7() { let message = "12345678901234567890123456789012345678901234567890123456789012345678901234567890" let answer = "f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e" - let data = message.data(using: .utf8)! + let data = Data(message.utf8) let hash = Sha256.hash(data: data) XCTAssertEqual(hash.map { String(format: "%02x", $0) }.joined(), answer) } diff --git a/Tests/TarCreateTests.swift b/Tests/TarCreateTests.swift index cea0a7eb..628179be 100644 --- a/Tests/TarCreateTests.swift +++ b/Tests/TarCreateTests.swift @@ -21,7 +21,7 @@ class TarCreateTests: XCTestCase { info.accessTime = date info.comment = "comment" - let data = "Hello, World!\n".data(using: .utf8)! + let data = Data("Hello, World!\n".utf8) let entry = TarEntry(info: info, data: data) let containerData = TarContainer.create(from: [entry]) let newEntries = try TarContainer.open(container: containerData) From 753839f195cd7e895b9bf54c431d382968318d1c Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 14:32:47 +0300 Subject: [PATCH 68/97] [TAR] Implement gnu tar headers fields creation --- Sources/TAR/TarHeader.swift | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Sources/TAR/TarHeader.swift b/Sources/TAR/TarHeader.swift index efe73f91..6e001b2e 100644 --- a/Sources/TAR/TarHeader.swift +++ b/Sources/TAR/TarHeader.swift @@ -36,7 +36,7 @@ struct TarHeader { let linkName: String // Ustar only - // - magic + // - magic "ustar\000" private(set) var uname: String? private(set) var gname: String? private(set) var deviceMajorNumber: Int? @@ -44,7 +44,7 @@ struct TarHeader { private(set) var prefix: String? // These fields are present in gnu and star formats. - // - magic + // - magic ("ustar \0" for [old] gnu) private(set) var atime: Date? private(set) var ctime: Date? @@ -262,7 +262,17 @@ struct TarHeader { out.append(Data(count: 155)) // Empty prefix } } else if format == .gnu { - // TODO: + out.append(contentsOf: [0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00]) // "ustar \0" + if let atime = self.atime?.timeIntervalSince1970 { + out.append(tarInt: Int(atime), maxLength: 12) + } else { + out.append(tarInt: nil, maxLength: 12) + } + if let ctime = self.ctime?.timeIntervalSince1970 { + out.append(tarInt: Int(ctime), maxLength: 12) + } else { + out.append(tarInt: nil, maxLength: 12) + } } // Checksum calculation. From b344fe1f1f55e9a3cff435aeb0322d01fbd7903d Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 15:00:13 +0300 Subject: [PATCH 69/97] [TAR] Write ustar fields also for gnu format for --- Sources/TAR/TarHeader.swift | 99 ++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/Sources/TAR/TarHeader.swift b/Sources/TAR/TarHeader.swift index 6e001b2e..9d151092 100644 --- a/Sources/TAR/TarHeader.swift +++ b/Sources/TAR/TarHeader.swift @@ -216,9 +216,17 @@ struct TarHeader { // For prePosix format there is no additional fields. + // Magic if format == .ustar || format == .pax { - // The header layouts for these two formats are identical. out.append(contentsOf: [0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30]) // "ustar\000" + } else if format == .gnu { + out.append(contentsOf: [0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00]) // "ustar \0" + } + + if format != .prePosix { + // Check in case other formats are added in the future. + assert(format == .ustar || format == .gnu || format == .pax) + // Both ustar, pax, and gnu formats contain the following four fields. // In theory, user/group name is not guaranteed to have only ASCII characters, so the same disclaimer as for // file name field applies here. out.append(tarString: self.uname, maxLength: 32) @@ -226,52 +234,53 @@ struct TarHeader { out.append(tarInt: self.deviceMajorNumber, maxLength: 8) out.append(tarInt: self.deviceMinorNumber, maxLength: 8) - // 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 - if maxPrefixLength > 156 { - // We can set actual maximum possible length of prefix equal to 156 and not 155, because it may - // include trailing slash which will be removed during splitting. - maxPrefixLength = 156 - } else if nameData[maxPrefixLength - 1] == 0x2F { - // Skip trailing slash. - maxPrefixLength -= 1 + // 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 + if maxPrefixLength > 156 { + // We can set actual maximum possible length of prefix equal to 156 and not 155, because it may + // include trailing slash which will be removed during splitting. + maxPrefixLength = 156 + } else if nameData[maxPrefixLength - 1] == 0x2F { + // Skip trailing slash. + maxPrefixLength -= 1 + } + + // 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. + let lastPrefixSlashIndex = nameData.prefix(upTo: maxPrefixLength) + .range(of: Data([0x2f]), options: .backwards)?.lowerBound ?? -1 + let updatedNameLength = nameData.count - lastPrefixSlashIndex - 1 + let prefixLength = lastPrefixSlashIndex + + if lastPrefixSlashIndex <= 0 || updatedNameLength > 100 || updatedNameLength == 0 || prefixLength > 155 { + // Unsplittable name. + out.append(Data(count: 155)) + } else { + // Add prefix data to output. + out.append(nameData.prefix(upTo: lastPrefixSlashIndex)) + // Update name field data in output. + var newNameData = nameData.suffix(from: lastPrefixSlashIndex + 1) + newNameData.append(Data(count: 100 - newNameData.count)) + out.replaceSubrange(0..<100, with: newNameData) + } } - - // 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. - let lastPrefixSlashIndex = nameData.prefix(upTo: maxPrefixLength) - .range(of: Data([0x2f]), options: .backwards)?.lowerBound ?? -1 - let updatedNameLength = nameData.count - lastPrefixSlashIndex - 1 - let prefixLength = lastPrefixSlashIndex - - if lastPrefixSlashIndex <= 0 || updatedNameLength > 100 || updatedNameLength == 0 || prefixLength > 155 { - // Unsplittable name. - out.append(Data(count: 155)) + } else if format == .gnu { + // Gnu format contains atime and ctime instead of a prefix field. + if let atime = self.atime?.timeIntervalSince1970 { + out.append(tarInt: Int(atime), maxLength: 12) } else { - // Add prefix data to output. - out.append(nameData.prefix(upTo: lastPrefixSlashIndex)) - // Update name field data in output. - var newNameData = nameData.suffix(from: lastPrefixSlashIndex + 1) - newNameData.append(Data(count: 100 - newNameData.count)) - out.replaceSubrange(0..<100, with: newNameData) + out.append(tarInt: nil, maxLength: 12) + } + if let ctime = self.ctime?.timeIntervalSince1970 { + out.append(tarInt: Int(ctime), maxLength: 12) + } else { + out.append(tarInt: nil, maxLength: 12) } - } else { - out.append(Data(count: 155)) // Empty prefix - } - } else if format == .gnu { - out.append(contentsOf: [0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00]) // "ustar \0" - if let atime = self.atime?.timeIntervalSince1970 { - out.append(tarInt: Int(atime), maxLength: 12) - } else { - out.append(tarInt: nil, maxLength: 12) - } - if let ctime = self.ctime?.timeIntervalSince1970 { - out.append(tarInt: Int(ctime), maxLength: 12) - } else { - out.append(tarInt: nil, maxLength: 12) } } @@ -282,6 +291,8 @@ struct TarHeader { let checksumString = String(format: "%06o", checksum).appending("\0 ") out.replaceSubrange(148..<156, with: checksumString.data(using: .ascii)!) + assert(out.count == 512) + return out } From f1a635c98f611226d75d226247196469b0321436 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 15:01:30 +0300 Subject: [PATCH 70/97] [Tests] Add tests for creation of gnu TAR containers --- Tests/TarCreateTests.swift | 76 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/Tests/TarCreateTests.swift b/Tests/TarCreateTests.swift index 628179be..a91af2bc 100644 --- a/Tests/TarCreateTests.swift +++ b/Tests/TarCreateTests.swift @@ -232,4 +232,80 @@ class TarCreateTests: XCTestCase { XCTAssertNil(newInfo.comment) } + func testGnuLongName() throws { + var info = TarEntryInfo(name: "", type: .regular) + info.name = "path/to/" + info.name.append(String(repeating: "name/", count: 25)) + info.name.append("name.txt") + + let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())], force: .gnu) + XCTAssertEqual(try TarContainer.formatOf(container: containerData), .gnu) + let newInfo = try TarContainer.open(container: containerData)[0].info + + XCTAssertEqual(newInfo.name, info.name) + } + + func testGnuLongLinkName() throws { + var info = TarEntryInfo(name: "", type: .symbolicLink) + info.name = "link" + info.linkName = "path/to/" + info.linkName.append(String(repeating: "name/", count: 25)) + info.linkName.append("name.txt") + + let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())], force: .gnu) + XCTAssertEqual(try TarContainer.formatOf(container: containerData), .gnu) + let newInfo = try TarContainer.open(container: containerData)[0].info + + XCTAssertEqual(newInfo.name, info.name) + } + + func testGnuBothLongNames() throws { + var info = TarEntryInfo(name: "", type: .symbolicLink) + info.name = "path/to/" + info.name.append(String(repeating: "name/", count: 25)) + info.name.append("name.txt") + info.linkName = "path/to/" + info.linkName.append(String(repeating: "link/", count: 25)) + info.linkName.append("link.txt") + + let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())], force: .gnu) + XCTAssertEqual(try TarContainer.formatOf(container: containerData), .gnu) + let newInfo = try TarContainer.open(container: containerData)[0].info + + XCTAssertEqual(newInfo.name, info.name) + } + + func testGnuTimes() throws { + var info = TarEntryInfo(name: "dir", type: .directory) + info.ownerUserName = "tsolomko" + info.ownerGroupName = "staff" + info.ownerID = 501 + info.groupID = 20 + info.permissions = Permissions(rawValue: 420) + // We have to convert time interval to int, since tar can't store fractional timestamps, so we lose in accuracy. + let intTimeInterval = Int(Date().timeIntervalSince1970) + let date = Date(timeIntervalSince1970: Double(intTimeInterval)) + info.modificationTime = date + info.creationTime = date + info.accessTime = date + + let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())], force: .gnu) + XCTAssertEqual(try TarContainer.formatOf(container: containerData), .gnu) + let newEntries = try TarContainer.open(container: containerData) + + XCTAssertEqual(newEntries.count, 1) + XCTAssertEqual(newEntries[0].info.name, "dir") + XCTAssertEqual(newEntries[0].info.type, .directory) + XCTAssertEqual(newEntries[0].info.size, 0) + XCTAssertEqual(newEntries[0].info.ownerUserName, "tsolomko") + XCTAssertEqual(newEntries[0].info.ownerGroupName, "staff") + XCTAssertEqual(newEntries[0].info.ownerID, 501) + XCTAssertEqual(newEntries[0].info.groupID, 20) + XCTAssertEqual(newEntries[0].info.permissions, Permissions(rawValue: 420)) + XCTAssertEqual(newEntries[0].info.modificationTime, date) + XCTAssertEqual(newEntries[0].info.creationTime, date) + XCTAssertEqual(newEntries[0].info.accessTime, date) + XCTAssertNil(newEntries[0].info.comment) + } + } From d523f6ec32a70d057e40327912a47d1ba270e369 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 15:01:56 +0300 Subject: [PATCH 71/97] [TAR] Adjust old tar creation tests to also check for format --- Tests/TarCreateTests.swift | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Tests/TarCreateTests.swift b/Tests/TarCreateTests.swift index a91af2bc..84dc301c 100644 --- a/Tests/TarCreateTests.swift +++ b/Tests/TarCreateTests.swift @@ -15,7 +15,9 @@ class TarCreateTests: XCTestCase { info.ownerID = 501 info.groupID = 20 info.permissions = Permissions(rawValue: 420) - let date = Date() + // We have to convert time interval to int, since tar can't store fractional timestamps, so we lose in accuracy. + let intTimeInterval = Int(Date().timeIntervalSince1970) + let date = Date(timeIntervalSince1970: Double(intTimeInterval)) info.modificationTime = date info.creationTime = date info.accessTime = date @@ -24,6 +26,7 @@ class TarCreateTests: XCTestCase { let data = Data("Hello, World!\n".utf8) let entry = TarEntry(info: info, data: data) let containerData = TarContainer.create(from: [entry]) + XCTAssertEqual(try TarContainer.formatOf(container: containerData), .pax) let newEntries = try TarContainer.open(container: containerData) XCTAssertEqual(newEntries.count, 1) @@ -35,6 +38,9 @@ class TarCreateTests: XCTestCase { XCTAssertEqual(newEntries[0].info.ownerID, 501) XCTAssertEqual(newEntries[0].info.groupID, 20) XCTAssertEqual(newEntries[0].info.permissions, Permissions(rawValue: 420)) + XCTAssertEqual(newEntries[0].info.modificationTime, date) + XCTAssertEqual(newEntries[0].info.creationTime, date) + XCTAssertEqual(newEntries[0].info.accessTime, date) XCTAssertEqual(newEntries[0].info.comment, "comment") XCTAssertEqual(newEntries[0].data, data) } @@ -63,6 +69,7 @@ class TarCreateTests: XCTestCase { info.unknownExtendedHeaderRecords = dict 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, "symbolic-link") @@ -91,6 +98,7 @@ class TarCreateTests: XCTestCase { info.name.append("readme.txt") 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 // This name should fit into ustar format using "prefix" field @@ -104,6 +112,7 @@ class TarCreateTests: XCTestCase { info.name.append("readme.txt") 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, info.name) @@ -116,6 +125,7 @@ class TarCreateTests: XCTestCase { info.name.append(String(repeating: "readme/", count: 15)) 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, info.name) @@ -165,7 +175,7 @@ class TarCreateTests: XCTestCase { info.groupID = 20 info.modificationTime = date - let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())]) + let containerData = TarContainer.create(from: [TarEntry(info: info, data: Data())], force: .ustar) XCTAssertEqual(try TarContainer.formatOf(container: containerData), .ustar) let newInfo = try TarContainer.open(container: containerData)[0].info From 8415cee9aefce14b70d0676497c969c84fa4120e Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 15:15:29 +0300 Subject: [PATCH 72/97] [TAR] Fix missing return statement in TarContainer.create --- Sources/TAR/TarContainer.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 51f078c9..82b239d0 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -77,7 +77,7 @@ public class TarContainer: Container { format used during container creation. */ public static func create(from entries: [TarEntry]) -> Data { - create(from: entries, force: .pax) + return create(from: entries, force: .pax) } public static func create(from entries: [TarEntry], force format: TarContainer.Format) -> Data { From 5012788be4a60ebcc40654dcfdd2dd0b5aeb90d9 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 15:28:19 +0300 Subject: [PATCH 73/97] [TAR] Rename ByteReader+Tar to LittleEndianByteReader+Tar --- SWCompression.xcodeproj/project.pbxproj | 8 ++++---- ...eReader+Tar.swift => LittleEndianByteReader+Tar.swift} | 0 2 files changed, 4 insertions(+), 4 deletions(-) rename Sources/TAR/{ByteReader+Tar.swift => LittleEndianByteReader+Tar.swift} (100%) diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index 906a91a1..1d13e006 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -54,7 +54,7 @@ 06516B782139505800C9823B /* Sha256Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06516B772139505800C9823B /* Sha256Tests.swift */; }; 0651FEC21F8E2E9100C49646 /* ContainerEntryType+Tar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0651FEC11F8E2E9100C49646 /* ContainerEntryType+Tar.swift */; }; 0656B8261F8A960700111605 /* TarEntryInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0656B8251F8A960700111605 /* TarEntryInfo.swift */; }; - 0656B82B1F8A979A00111605 /* ByteReader+Tar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0656B82A1F8A979A00111605 /* ByteReader+Tar.swift */; }; + 0656B82B1F8A979A00111605 /* LittleEndianByteReader+Tar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0656B82A1F8A979A00111605 /* LittleEndianByteReader+Tar.swift */; }; 06595E0E1F1E8252006501C2 /* 7zFolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06595E0D1F1E8252006501C2 /* 7zFolder.swift */; }; 06595E131F1E90C2006501C2 /* 7zCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06595E121F1E90C2006501C2 /* 7zCoder.swift */; }; 065D0ADC1F2B9D9100CE2DA8 /* 7zEntryInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 065D0ADB1F2B9D9100CE2DA8 /* 7zEntryInfo.swift */; }; @@ -282,7 +282,7 @@ 06516B772139505800C9823B /* Sha256Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sha256Tests.swift; sourceTree = ""; }; 0651FEC11F8E2E9100C49646 /* ContainerEntryType+Tar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContainerEntryType+Tar.swift"; sourceTree = ""; }; 0656B8251F8A960700111605 /* TarEntryInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TarEntryInfo.swift; sourceTree = ""; }; - 0656B82A1F8A979A00111605 /* ByteReader+Tar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ByteReader+Tar.swift"; sourceTree = ""; }; + 0656B82A1F8A979A00111605 /* LittleEndianByteReader+Tar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LittleEndianByteReader+Tar.swift"; sourceTree = ""; }; 06595E0D1F1E8252006501C2 /* 7zFolder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 7zFolder.swift; sourceTree = ""; }; 06595E121F1E90C2006501C2 /* 7zCoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = 7zCoder.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 065D0ADB1F2B9D9100CE2DA8 /* 7zEntryInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 7zEntryInfo.swift; sourceTree = ""; }; @@ -641,7 +641,7 @@ 0698B10821048FB800A7C551 /* TarCreateError.swift */, 061C06561F0E90C800832F0C /* TarError.swift */, 0651FEC11F8E2E9100C49646 /* ContainerEntryType+Tar.swift */, - 0656B82A1F8A979A00111605 /* ByteReader+Tar.swift */, + 0656B82A1F8A979A00111605 /* LittleEndianByteReader+Tar.swift */, 06CFF6B12078C5A5003B8375 /* TarEntryInfoProvider.swift */, E64F71BB26AAFD6A008BB308 /* Data+Tar.swift */, ); @@ -1201,7 +1201,7 @@ 06CDFCAD1F111DBE00292758 /* LZMAError.swift in Sources */, 06E6A6391F5C0FBB00D04856 /* CodeLength.swift in Sources */, 0642998B206017590044BA0C /* ZipExtraField.swift in Sources */, - 0656B82B1F8A979A00111605 /* ByteReader+Tar.swift in Sources */, + 0656B82B1F8A979A00111605 /* LittleEndianByteReader+Tar.swift in Sources */, 06B689581F278815007C9316 /* 7zProperty.swift in Sources */, 0686A63B1FA4C07D00E89C9E /* FileSystemType.swift in Sources */, 06516B76213938B000C9823B /* Sha256.swift in Sources */, diff --git a/Sources/TAR/ByteReader+Tar.swift b/Sources/TAR/LittleEndianByteReader+Tar.swift similarity index 100% rename from Sources/TAR/ByteReader+Tar.swift rename to Sources/TAR/LittleEndianByteReader+Tar.swift From af516f409059e754b8160c7e56d150408c0c0ea0 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Jul 2021 15:28:37 +0300 Subject: [PATCH 74/97] [TAR] Add several asserts to TarEntryInfoProvider.next() --- Sources/TAR/TarEntryInfoProvider.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Sources/TAR/TarEntryInfoProvider.swift b/Sources/TAR/TarEntryInfoProvider.swift index 8debb64d..ed638189 100644 --- a/Sources/TAR/TarEntryInfoProvider.swift +++ b/Sources/TAR/TarEntryInfoProvider.swift @@ -7,7 +7,7 @@ import Foundation import BitByteData // While it is tempting to make Provider conform to `IteratorProtocol` and `Sequence` protocols, it is in fact -// impossible to do so, since `TarEntryInfo.init(...)` is throwing and `IteratorProtocol.next()` cannot be throwing. +// impossible to do so, since `TarHeader.init(...)` is throwing and `IteratorProtocol.next()` cannot be throwing. struct TarEntryInfoProvider { private let reader: LittleEndianByteReader @@ -26,7 +26,11 @@ struct TarEntryInfoProvider { else { return nil } let header = try TarHeader(reader) + // For header we read at most 512 bytes. + assert(reader.offset - header.blockStartIndex <= 512) let info = TarEntryInfo(header, lastGlobalExtendedHeader, lastLocalExtendedHeader, longName, longLinkName) + // Check, just in case, since we use blockStartIndex = -1 when creating TAR containers. + assert(header.blockStartIndex >= 0) let dataStartIndex = header.blockStartIndex + 512 if case .special(let specialEntryType) = header.type { @@ -54,6 +58,8 @@ struct TarEntryInfoProvider { longName = nil longLinkName = nil } + // Parsing must complete at the end of a 512 byte-long block. + assert(reader.bytesRead % 512 == 0) return info } From cc217f8f93ff234bfbf401814b7195c033d1a2fe Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sun, 25 Jul 2021 15:53:53 +0300 Subject: [PATCH 75/97] [TAR] The names of created special entries are now quasi-unique --- Sources/TAR/TarContainer.swift | 41 +++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 82b239d0..42c97de2 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -83,45 +83,60 @@ public class TarContainer: Container { 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 TarHeader. - // 3. For each TarHeader we generate binary data, and the append it with the content of the special entry to + // 2. For each special entry we create a TarHeader. + // 3. For each TarHeader we generate binary data, and then append it with the content of the special entry to // the output. // 4. Perform the previous two steps for the entry itself. // Every time we append something to the output we also make sure that the data is padded to 512 byte-long blocks. - // TODO: Add counters for special entries. Check if overflow. + // 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 + // 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 + // 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 + var out = Data() for entry in entries { if format == .gnu { if entry.info.name.utf8.count > 100 { let nameData = Data(entry.info.name.utf8) - let longNameHeader = TarHeader(specialName: "SWC_LongName", specialType: .longName, - size: nameData.count, uid: entry.info.ownerID, - gid: entry.info.groupID) + let longNameHeader = TarHeader(specialName: "SWC_LongName_\(longNameCounter)", + specialType: .longName, size: nameData.count, + uid: entry.info.ownerID, gid: entry.info.groupID) out.append(longNameHeader.generateContainerData(.gnu)) assert(out.count % 512 == 0) out.appendAsTarBlock(nameData) + longNameCounter &+= 1 } if entry.info.linkName.utf8.count > 100 { let linkNameData = Data(entry.info.linkName.utf8) - let longLinkNameHeader = TarHeader(specialName: "SWC_LongLinkName", specialType: .longLinkName, - size: linkNameData.count, uid: entry.info.ownerID, - gid: entry.info.groupID) + let longLinkNameHeader = TarHeader(specialName: "SWC_LongLinkName_\(longLinkNameCounter)", + specialType: .longLinkName, size: linkNameData.count, + uid: entry.info.ownerID, gid: entry.info.groupID) out.append(longLinkNameHeader.generateContainerData(.gnu)) assert(out.count % 512 == 0) out.appendAsTarBlock(linkNameData) + longLinkNameCounter &+= 1 } } else if format == .pax { let extHeader = TarExtendedHeader(entry.info) let extHeaderData = extHeader.generateContainerData() if !extHeaderData.isEmpty { - let extHeaderHeader = TarHeader(specialName: "SWC_LocalPaxHeader", specialType: .localExtendedHeader, - size: extHeaderData.count, uid: entry.info.ownerID, - gid: entry.info.groupID) + let extHeaderHeader = TarHeader(specialName: "SWC_LocalPaxHeader_\(localPaxHeaderCounter)", + specialType: .localExtendedHeader, size: extHeaderData.count, + uid: entry.info.ownerID, gid: entry.info.groupID) out.append(extHeaderHeader.generateContainerData(.pax)) assert(out.count % 512 == 0) out.appendAsTarBlock(extHeaderData) + localPaxHeaderCounter &+= 1 } } @@ -164,7 +179,7 @@ public class TarContainer: Container { let dataEndIndex = dataStartIndex + entryInfo.size! // Verify that data is not truncated. // The data.startIndex inequality is strict since by this point at least one header (i.e. 512 bytes) - // has been processed. The data.endIndex inequality is strict since there must be a 1024 bytes-long EOF + // has been processed. The data.endIndex inequality is strict since there can be a 1024 bytes-long EOF // marker block which isn't included into any entry. guard dataStartIndex > data.startIndex && dataEndIndex < data.endIndex else { throw TarError.wrongField } From 3d7a4a8fbca85765c1416c298ee15aa49456931d Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sun, 25 Jul 2021 15:54:29 +0300 Subject: [PATCH 76/97] [docs] Remove Throws section from TarContainer.create --- Sources/TAR/TarContainer.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 42c97de2..8dac754c 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -70,9 +70,6 @@ public class TarContainer: Container { - Parameter entries: TAR entries to store in the container. - - Throws: `TarCreateError.utf8NonEncodable` which indicates that one of the `TarEntryInfo`'s string properties - (such as `name`) cannot be encoded with UTF-8 encoding. - - SeeAlso: `TarEntryInfo` properties documenation to see how their values are connected with the specific TAR format used during container creation. */ From a743229456e69d3bc0d1976a1f116e4dbe20717c Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sun, 25 Jul 2021 15:55:31 +0300 Subject: [PATCH 77/97] [docs] Mention format forcing in the docs for TarEntryInfo properties --- Sources/TAR/TarEntryInfo.swift | 61 +++++++++++++++++----------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index f6075bc3..d55ae5aa 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -20,20 +20,21 @@ public struct TarEntryInfo: ContainerEntryInfo { 3. GNU format type "L" (LongName) entry. 4. Default TAR header. - - Note: When new TAR container is created, if `name` cannot be encoded with ASCII or its ASCII byte-representation - is longer than 100 bytes then a PAX extended header will be created to represent this value correctly. - - Note: When creating new TAR container, `name` is always encoded with UTF-8 in basic TAR header. + - Note: When a new TAR container is created, if `name` cannot be encoded with ASCII or its ASCII byte-representation + is longer than 100 bytes then a PAX extended header will be created to represent this value correctly, unless other + format is forced. + - Note: When creating new TAR container, `name` is always encoded with UTF-8 in the basic TAR header. */ public var name: String /** Entry's data size. - - Note: This property cannot be directly modified. Instead it is updated automatically to be equal to its parent + - Note: This property cannot be directly modified. Instead it is updated automatically to be equal to its parent's `entry.data.count`. - - Note: When new TAR container is created, if `size` is bigger than 8589934591 then a PAX extended header will be - created to represent this value correctly. Also, base-256 encoding will be used to encode this value in basic TAR - header. + - Note: When a new TAR container is created, if `size` is bigger than 8589934591 then a PAX extended header will be + created to represent this value correctly, unless other format is forced. In addition, base-256 encoding will be + used to encode this value in the basic TAR header. */ public internal(set) var size: Int? @@ -42,25 +43,25 @@ public struct TarEntryInfo: ContainerEntryInfo { /** Entry's last access time (only available for PAX format; `nil` otherwise). - - Note: When new TAR container is created, if `accessTime` is not `nil` then a PAX extended header will be created - to store this property. + - Note: When a new TAR container is created, if `accessTime` is not `nil` then a PAX extended header will be created + to store this property, unless other format is forced. */ public var accessTime: Date? /** Entry's creation time (only available for PAX format; `nil` otherwise). - - Note: When new TAR container is created, if `creationTime` is not `nil` then a PAX extended header will be - created to store this property. + - Note: When a new TAR container is created, if `creationTime` is not `nil` then a PAX extended header will be + created to store this property, unless other format is forced. */ public var creationTime: Date? /** Entry's last modification time. - - Note: When new TAR container is created, if `modificationTime` is bigger than 8589934591 then a PAX extended - header will be created to represent this value correctly. Also, base-256 encoding will be used to encode this value - in basic TAR header. + - Note: When a new TAR container is created, if `modificationTime` is bigger than 8589934591 then a PAX extended + header will be created to represent this value correctly, unless other format is forced. In addition, base-256 + encoding will be used to encode this value in the basic TAR header. */ public var modificationTime: Date? @@ -68,34 +69,34 @@ public struct TarEntryInfo: ContainerEntryInfo { // MARK: TAR specific - /// Entry's compression method. Always `.copy` for entries of TAR containers. + /// Entry's compression method. Always `.copy` for the entries of TAR containers. public let compressionMethod = CompressionMethod.copy /** ID of entry's owner. - - Note: When new TAR container is created, if `ownerID` is bigger than 2097151 then a PAX extended header will be - created to represent this value correctly. Also, base-256 encoding will be used to encode this value in basic TAR - header. + - Note: When a new TAR container is created, if `ownerID` is bigger than 2097151 then a PAX extended header will be + created to represent this value correctly, unless other format is forced. In addition, base-256 encoding will be + used to encode this value in the basic TAR header. */ public var ownerID: Int? /** ID of the group of entry's owner. - - Note: When new TAR container is created, if `groupID` is bigger than 2097151 then a PAX extended header will be - created to represent this value correctly. Also, base-256 encoding will be used to encode this value in basic TAR - header. + - Note: When a new TAR container is created, if `groupID` is bigger than 2097151 then a PAX extended header will be + created to represent this value correctly, unless other format is forced. In addition, base-256 encoding will be + used to encode this value in the basic TAR header. */ public var groupID: Int? /** User name of entry's owner. - - Note: When new TAR container is created, if `ownerUserName` cannot be encoded with ASCII or its ASCII + - Note: When a new TAR container is created, if `ownerUserName` cannot be encoded with ASCII or its ASCII byte-representation is longer than 32 bytes then a PAX extended header will be created to represent this value - correctly. - - Note: When creating new TAR container, `ownerUserName` is always encoded with UTF-8 in ustar header. + correctly, unless other format is forced. + - Note: When creating new TAR container, `ownerUserName` is always encoded with UTF-8 in the ustar header. */ public var ownerUserName: String? @@ -104,8 +105,8 @@ public struct TarEntryInfo: ContainerEntryInfo { - Note: When new TAR container is created, if `ownerGroupName` cannot be encoded with ASCII or its ASCII byte-representation is longer than 32 bytes then a PAX extended header will be created to represent this value - correctly. - - Note: When creating new TAR container, `ownerGroupName` is always encoded with UTF-8 in ustar header. + correctly, unless other format is forced. + - Note: When creating new TAR container, `ownerGroupName` is always encoded with UTF-8 in the ustar header. */ public var ownerGroupName: String? @@ -129,7 +130,7 @@ public struct TarEntryInfo: ContainerEntryInfo { Name of the character set used to encode entry's data (only available for PAX format; `nil` otherwise). - Note: When new TAR container is created, if `charset` is not `nil` then a PAX extended header will be created to - store this property. + store this property, unless other format is forced. */ public var charset: String? @@ -137,7 +138,7 @@ public struct TarEntryInfo: ContainerEntryInfo { Entry's comment (only available for PAX format; `nil` otherwise). - Note: When new TAR container is created, if `comment` is not `nil` then a PAX extended header will be created to - store this property. + store this property, unless other format is forced. */ public var comment: String? @@ -153,7 +154,7 @@ public struct TarEntryInfo: ContainerEntryInfo { - Note: When new TAR container is created, if `linkName` cannot be encoded with ASCII or its ASCII byte-representation is longer than 100 bytes then a PAX extended header will be created to represent this value - correctly. + correctly, unless other format is forced. - Note: When creating new TAR container, `linkName` is always encoded with UTF-8 in basic TAR header. */ public var linkName: String @@ -162,7 +163,7 @@ public struct TarEntryInfo: ContainerEntryInfo { All custom (unknown) records from global and local PAX extended headers. `nil`, if there were no headers. - Note: When new TAR container is created, if `unknownExtendedHeaderRecords` is not `nil` then a *local* PAX - extended header will be created to store this property. + extended header will be created to store this property, unless other format is forced. */ public var unknownExtendedHeaderRecords: [String: String]? From 49c4adf8e9e95b234f8fdf906c774d1b7c697571 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Mon, 26 Jul 2021 21:13:27 +0300 Subject: [PATCH 78/97] [TAR] Return ParsingResult from TarEntryInfoProvider.next() ParsingResult is a new enum. This allows us to better distinguish between different situtations encounterd during parsing a TAR container. --- Sources/TAR/TarContainer.swift | 43 ++++++++++++++++++++------ Sources/TAR/TarEntryInfoProvider.swift | 27 +++++++++++----- 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 8dac754c..3865e6a5 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -43,12 +43,17 @@ public class TarContainer: Container { var ustarEncountered = false - while let info = try infoProvider.next() { - if info.specialEntryType == .globalExtendedHeader || info.specialEntryType == .localExtendedHeader { - return .pax - } else if info.specialEntryType == .longName || info.specialEntryType == .longLinkName { - return .gnu - } else { + parsingLoop: while true { + let result = try infoProvider.next() + switch result { + case .specialEntry(let specialEntryType): + if specialEntryType == .globalExtendedHeader || specialEntryType == .localExtendedHeader { + return .pax + } 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 .pax: return .pax @@ -59,6 +64,13 @@ public class TarContainer: Container { case .prePosix: break } + case .truncated: + // We don't have an error with a more suitable name. + throw TarError.wrongField + case .finished: + fallthrough + case .eofMarker: + break parsingLoop } } @@ -209,10 +221,21 @@ public class TarContainer: Container { var infoProvider = TarEntryInfoProvider(data) var entries = [TarEntryInfo]() - while let info = try infoProvider.next() { - guard info.specialEntryType == nil - else { continue } - entries.append(info) + parsingLoop: while true { + let result = try infoProvider.next() + switch result { + case .specialEntry: + continue parsingLoop + case .entryInfo(let info): + entries.append(info) + case .truncated: + // We don't have an error with a more suitable name. + throw TarError.wrongField + case .finished: + fallthrough + case .eofMarker: + break parsingLoop + } } return entries diff --git a/Sources/TAR/TarEntryInfoProvider.swift b/Sources/TAR/TarEntryInfoProvider.swift index ed638189..6268a408 100644 --- a/Sources/TAR/TarEntryInfoProvider.swift +++ b/Sources/TAR/TarEntryInfoProvider.swift @@ -10,6 +10,14 @@ import BitByteData // impossible to do so, since `TarHeader.init(...)` is throwing and `IteratorProtocol.next()` cannot be throwing. struct TarEntryInfoProvider { + enum ParsingResult { + case truncated + case eofMarker + case finished + case specialEntry(TarHeader.SpecialEntryType) + case entryInfo(TarEntryInfo) + } + private let reader: LittleEndianByteReader private var lastGlobalExtendedHeader: TarExtendedHeader? private var lastLocalExtendedHeader: TarExtendedHeader? @@ -20,15 +28,18 @@ struct TarEntryInfoProvider { self.reader = LittleEndianByteReader(data: data) } - mutating func next() throws -> TarEntryInfo? { - guard reader.bytesLeft >= 1024, - reader.data[reader.offset.. ParsingResult { + if reader.isFinished { + return .finished + } else if reader.bytesLeft >= 1024 && reader.data[reader.offset..= 0) let dataStartIndex = header.blockStartIndex + 512 @@ -51,16 +62,16 @@ struct TarEntryInfoProvider { longName = reader.tarCString(maxLength: header.size) } reader.offset = dataStartIndex + header.size.roundTo512() + return .specialEntry(specialEntryType) } else { + let info = TarEntryInfo(header, lastGlobalExtendedHeader, lastLocalExtendedHeader, longName, longLinkName) // Skip file data. reader.offset = dataStartIndex + header.size.roundTo512() lastLocalExtendedHeader = nil longName = nil longLinkName = nil + return .entryInfo(info) } - // Parsing must complete at the end of a 512 byte-long block. - assert(reader.bytesRead % 512 == 0) - return info } } From b2f7084a0ec5101d2bcdec49757af7a5372a90ff Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Mon, 26 Jul 2021 21:15:06 +0300 Subject: [PATCH 79/97] [TAR] Rename TarEntryInfoProvider to TarParser --- SWCompression.xcodeproj/project.pbxproj | 8 ++++---- Sources/TAR/TarContainer.swift | 8 ++++---- .../TAR/{TarEntryInfoProvider.swift => TarParser.swift} | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) rename Sources/TAR/{TarEntryInfoProvider.swift => TarParser.swift} (99%) diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index 1d13e006..08fad183 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -102,7 +102,7 @@ 06CDFCA81F111D9700292758 /* DeflateError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06CDFCA71F111D9700292758 /* DeflateError.swift */; }; 06CDFCAD1F111DBE00292758 /* LZMAError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06CDFCAC1F111DBE00292758 /* LZMAError.swift */; }; 06CDFCB21F111DEC00292758 /* LZMA2Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06CDFCB11F111DEC00292758 /* LZMA2Error.swift */; }; - 06CFF6B22078C5A5003B8375 /* TarEntryInfoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06CFF6B12078C5A5003B8375 /* TarEntryInfoProvider.swift */; }; + 06CFF6B22078C5A5003B8375 /* TarParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06CFF6B12078C5A5003B8375 /* TarParser.swift */; }; 06D3802E21E36190008B50C6 /* Code.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06D3802D21E36190008B50C6 /* Code.swift */; }; 06D42DA52067B46800C1A98B /* test_custom_extra_field.zip in Resources */ = {isa = PBXBuildFile; fileRef = 06D42DA42067B46800C1A98B /* test_custom_extra_field.zip */; }; 06D42DA72067B71000C1A98B /* TestZipExtraField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06D42DA62067B71000C1A98B /* TestZipExtraField.swift */; }; @@ -327,7 +327,7 @@ 06CDFCA71F111D9700292758 /* DeflateError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeflateError.swift; sourceTree = ""; }; 06CDFCAC1F111DBE00292758 /* LZMAError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LZMAError.swift; sourceTree = ""; }; 06CDFCB11F111DEC00292758 /* LZMA2Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LZMA2Error.swift; sourceTree = ""; }; - 06CFF6B12078C5A5003B8375 /* TarEntryInfoProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TarEntryInfoProvider.swift; sourceTree = ""; }; + 06CFF6B12078C5A5003B8375 /* TarParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TarParser.swift; sourceTree = ""; }; 06D3802D21E36190008B50C6 /* Code.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Code.swift; sourceTree = ""; }; 06D42DA42067B46800C1A98B /* test_custom_extra_field.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = test_custom_extra_field.zip; sourceTree = ""; }; 06D42DA62067B71000C1A98B /* TestZipExtraField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestZipExtraField.swift; sourceTree = ""; }; @@ -636,13 +636,13 @@ 06ADB2D81EBCEFA60053A188 /* TarContainer.swift */, 061C065B1F0E90E600832F0C /* TarEntry.swift */, 0656B8251F8A960700111605 /* TarEntryInfo.swift */, + 06CFF6B12078C5A5003B8375 /* TarParser.swift */, E648151C26A889B8009261F0 /* TarHeader.swift */, 062C1D7B1F8FCA9300917968 /* TarExtendedHeader.swift */, 0698B10821048FB800A7C551 /* TarCreateError.swift */, 061C06561F0E90C800832F0C /* TarError.swift */, 0651FEC11F8E2E9100C49646 /* ContainerEntryType+Tar.swift */, 0656B82A1F8A979A00111605 /* LittleEndianByteReader+Tar.swift */, - 06CFF6B12078C5A5003B8375 /* TarEntryInfoProvider.swift */, E64F71BB26AAFD6A008BB308 /* Data+Tar.swift */, ); path = TAR; @@ -1179,7 +1179,7 @@ 0686A6451FA4C47300E89C9E /* FileSystemType+Zip.swift in Sources */, 06CDFCA31F111D6C00292758 /* BZip2Error.swift in Sources */, 06D3802E21E36190008B50C6 /* Code.swift in Sources */, - 06CFF6B22078C5A5003B8375 /* TarEntryInfoProvider.swift in Sources */, + 06CFF6B22078C5A5003B8375 /* TarParser.swift in Sources */, 06CC3FE21F8AAF3100BD576D /* ByteReader+XZ.swift in Sources */, 065D0ADC1F2B9D9100CE2DA8 /* 7zEntryInfo.swift in Sources */, 06F276DF1F2BAB4A00E67335 /* 7zEntry.swift in Sources */, diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 3865e6a5..8504677e 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -39,12 +39,12 @@ public class TarContainer: Container { guard data.count >= 512 else { throw TarError.tooSmallFileIsPassed } - var infoProvider = TarEntryInfoProvider(data) + var parser = TarParser(data) var ustarEncountered = false parsingLoop: while true { - let result = try infoProvider.next() + let result = try parser.next() switch result { case .specialEntry(let specialEntryType): if specialEntryType == .globalExtendedHeader || specialEntryType == .localExtendedHeader { @@ -218,11 +218,11 @@ public class TarContainer: Container { guard data.count >= 512 else { throw TarError.tooSmallFileIsPassed } - var infoProvider = TarEntryInfoProvider(data) + var parser = TarParser(data) var entries = [TarEntryInfo]() parsingLoop: while true { - let result = try infoProvider.next() + let result = try parser.next() switch result { case .specialEntry: continue parsingLoop diff --git a/Sources/TAR/TarEntryInfoProvider.swift b/Sources/TAR/TarParser.swift similarity index 99% rename from Sources/TAR/TarEntryInfoProvider.swift rename to Sources/TAR/TarParser.swift index 6268a408..dee5bcd2 100644 --- a/Sources/TAR/TarEntryInfoProvider.swift +++ b/Sources/TAR/TarParser.swift @@ -8,7 +8,7 @@ import BitByteData // While it is tempting to make Provider conform to `IteratorProtocol` and `Sequence` protocols, it is in fact // impossible to do so, since `TarHeader.init(...)` is throwing and `IteratorProtocol.next()` cannot be throwing. -struct TarEntryInfoProvider { +struct TarParser { enum ParsingResult { case truncated From 265191ea055754469b665234cc5d883b0ad17d4e Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Mon, 26 Jul 2021 21:16:48 +0300 Subject: [PATCH 80/97] [TAR] Remove TarEntryInfo.specialEntryType --- Sources/TAR/TarEntryInfo.swift | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index d55ae5aa..7ae20ec3 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -167,9 +167,6 @@ public struct TarEntryInfo: ContainerEntryInfo { */ public var unknownExtendedHeaderRecords: [String: String]? - // TODO: Remove - var specialEntryType: TarHeader.SpecialEntryType? - let format: TarContainer.Format // TODO: Remove @@ -215,17 +212,9 @@ public struct TarEntryInfo: ContainerEntryInfo { } // File type - // TODO: -// guard case .normal(let entryType) = header.type -// else { fatalError("TarEntryInfo.init: unexpected TarHeader.type, \(header.type)") } -// self.type = entryType - switch header.type { - case .special(let specialType): - self.specialEntryType = specialType - self.type = .unknown - case .normal(let normalType): - self.type = normalType - } + guard case .normal(let entryType) = header.type + else { fatalError("TarEntryInfo.init: unexpected TarHeader.type, \(header.type)") } + self.type = entryType self.ownerUserName = (local?.uname ?? global?.uname) ?? header.uname self.ownerGroupName = (local?.gname ?? global?.gname) ?? header.gname From 36f34c4e8f0b606626601b033afc4e12059bb36a Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Mon, 26 Jul 2021 21:22:03 +0300 Subject: [PATCH 81/97] [TAR] Remove TarEntryInfo.blockStartIndex To accomplish this, we added a second associated value to ParsingResult.entryInfo and rewrote TarContainer.open in similar way to TarContainer.info. --- Sources/TAR/TarContainer.swift | 55 ++++++++++++++++++++++------------ Sources/TAR/TarEntryInfo.swift | 6 ---- Sources/TAR/TarParser.swift | 4 +-- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 8504677e..564a4a23 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -52,7 +52,7 @@ public class TarContainer: Container { } else if specialEntryType == .longName || specialEntryType == .longLinkName { return .gnu } - case .entryInfo(let info): + 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 .pax: @@ -175,25 +175,42 @@ public class TarContainer: Container { - Returns: Array of `TarEntry`. */ public static func open(container data: Data) throws -> [TarEntry] { - let infos = try info(container: data) + // TAR container should be at least 512 bytes long (when it contains only one header). + guard data.count >= 512 + else { throw TarError.tooSmallFileIsPassed } + + var parser = TarParser(data) var entries = [TarEntry]() - for entryInfo in infos { - if entryInfo.type == .directory { - var entry = TarEntry(info: entryInfo, data: nil) - entry.info.size = 0 - entries.append(entry) - } else { - let dataStartIndex = entryInfo.blockStartIndex + 512 - let dataEndIndex = dataStartIndex + entryInfo.size! - // Verify that data is not truncated. - // The data.startIndex inequality is strict since by this point at least one header (i.e. 512 bytes) - // has been processed. The data.endIndex inequality is strict since there can be a 1024 bytes-long EOF - // marker block which isn't included into any entry. - guard dataStartIndex > data.startIndex && dataEndIndex < data.endIndex - else { throw TarError.wrongField } - let entryData = data.subdata(in: dataStartIndex.. data.startIndex && dataEndIndex < data.endIndex + else { throw TarError.wrongField } + let entryData = data.subdata(in: dataStartIndex.. Date: Mon, 26 Jul 2021 21:27:13 +0300 Subject: [PATCH 82/97] [TAR] Remove an extra check in TarContainer functions for very small files This situation is already covered by the check in TarParser, which results in ParsingResult.truncated. In addition, we repurposed TarError.tooSmallFileIsPassed for this cases (updated documentation). --- Sources/TAR/TarContainer.swift | 21 ++++----------------- Sources/TAR/TarError.swift | 2 +- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 564a4a23..44155655 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -35,12 +35,7 @@ public class TarContainer: Container { - SeeAlso: `TarContainer.Format` */ public static func formatOf(container data: Data) throws -> Format { - // TAR container should be at least 512 bytes long (when it contains only one header). - guard data.count >= 512 - else { throw TarError.tooSmallFileIsPassed } - var parser = TarParser(data) - var ustarEncountered = false parsingLoop: while true { @@ -66,7 +61,7 @@ public class TarContainer: Container { } case .truncated: // We don't have an error with a more suitable name. - throw TarError.wrongField + throw TarError.tooSmallFileIsPassed case .finished: fallthrough case .eofMarker: @@ -175,10 +170,6 @@ public class TarContainer: Container { - Returns: Array of `TarEntry`. */ public static func open(container data: Data) throws -> [TarEntry] { - // TAR container should be at least 512 bytes long (when it contains only one header). - guard data.count >= 512 - else { throw TarError.tooSmallFileIsPassed } - var parser = TarParser(data) var entries = [TarEntry]() @@ -200,13 +191,13 @@ public class TarContainer: Container { // has been processed. The data.endIndex inequality is strict since there can be a 1024 bytes-long EOF // marker block which isn't included into any entry. guard dataStartIndex > data.startIndex && dataEndIndex < data.endIndex - else { throw TarError.wrongField } + else { throw TarError.tooSmallFileIsPassed } let entryData = data.subdata(in: dataStartIndex.. [TarEntryInfo] { - // TAR container should be at least 512 bytes long (when it contains only one header). - guard data.count >= 512 - else { throw TarError.tooSmallFileIsPassed } - var parser = TarParser(data) var entries = [TarEntryInfo]() @@ -247,7 +234,7 @@ public class TarContainer: Container { entries.append(info) case .truncated: // We don't have an error with a more suitable name. - throw TarError.wrongField + throw TarError.tooSmallFileIsPassed case .finished: fallthrough case .eofMarker: diff --git a/Sources/TAR/TarError.swift b/Sources/TAR/TarError.swift index 4dcbbff2..64d4241d 100644 --- a/Sources/TAR/TarError.swift +++ b/Sources/TAR/TarError.swift @@ -10,7 +10,7 @@ import Foundation It may indicate that either container is damaged or it might not be TAR container at all. */ public enum TarError: Error { - /// Size of data is too small, even to contain only one header. + /// Data is unexpectedly truncated. case tooSmallFileIsPassed /// Failed to process a *required* TAR header's field. case wrongField From 6ca3712e11c7cbf330852bb04e956c153fd1084c Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Mon, 26 Jul 2021 21:41:08 +0300 Subject: [PATCH 83/97] [Tests] Add a test for TAR with only a header (no EOF marker even) This is to verify the checks in TarParser.next(). --- SWCompression.xcodeproj/project.pbxproj | 4 ++++ Tests/TarTests.swift | 22 ++++++++++++++++++++++ Tests/Test Files | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index 08fad183..f22297e5 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -213,6 +213,7 @@ 06F066771FFB763400312A82 /* test8.bz2 in Resources */ = {isa = PBXBuildFile; fileRef = 06F066111FFB763300312A82 /* test8.bz2 */; }; 06F276DF1F2BAB4A00E67335 /* 7zEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06F276DE1F2BAB4900E67335 /* 7zEntry.swift */; }; 06FEAD921F54B9CD00AD016E /* EncodingTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06FEAD911F54B9CD00AD016E /* EncodingTree.swift */; }; + E60CBA8A26AF379200A20130 /* test_only_dir_header.tar in Resources */ = {isa = PBXBuildFile; fileRef = E60CBA8926AF379200A20130 /* test_only_dir_header.tar */; }; E648151D26A889B8009261F0 /* TarHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = E648151C26A889B8009261F0 /* TarHeader.swift */; }; E64F71BC26AAFD6A008BB308 /* Data+Tar.swift in Sources */ = {isa = PBXBuildFile; fileRef = E64F71BB26AAFD6A008BB308 /* Data+Tar.swift */; }; E652D8F3263D670900FC229B /* test_nonstandard_runlength.bz2 in Resources */ = {isa = PBXBuildFile; fileRef = E652D8F2263D670900FC229B /* test_nonstandard_runlength.bz2 */; }; @@ -439,6 +440,7 @@ 06F276DE1F2BAB4900E67335 /* 7zEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 7zEntry.swift; sourceTree = ""; }; 06FEAD911F54B9CD00AD016E /* EncodingTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EncodingTree.swift; path = Sources/Common/CodingTree/EncodingTree.swift; sourceTree = SOURCE_ROOT; }; 06FED40B1DD7717E0013DFB2 /* BZip2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BZip2.swift; sourceTree = ""; }; + E60CBA8926AF379200A20130 /* test_only_dir_header.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = test_only_dir_header.tar; sourceTree = ""; }; E648151C26A889B8009261F0 /* TarHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TarHeader.swift; sourceTree = ""; }; E64F71BB26AAFD6A008BB308 /* Data+Tar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+Tar.swift"; sourceTree = ""; }; E652D8F2263D670900FC229B /* test_nonstandard_runlength.bz2 */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_nonstandard_runlength.bz2; sourceTree = ""; }; @@ -812,6 +814,7 @@ 06F065E01FFB763300312A82 /* test.tar */, 06F065E71FFB763300312A82 /* test_empty_dir.tar */, 06F065EC1FFB763300312A82 /* test_empty_cont.tar */, + E60CBA8926AF379200A20130 /* test_only_dir_header.tar */, 06F065ED1FFB763300312A82 /* SWCompressionSourceCode.tar */, 06F065EE1FFB763300312A82 /* test_empty_file.tar */, 06F065EF1FFB763300312A82 /* full_test.tar */, @@ -1043,6 +1046,7 @@ 06F066481FFB763400312A82 /* SWCompressionSourceCode.zip in Resources */, 06F0665D1FFB763400312A82 /* test8.lzma in Resources */, 06F0664F1FFB763400312A82 /* test_oldgnu.tar in Resources */, + E60CBA8A26AF379200A20130 /* test_only_dir_header.tar in Resources */, 06F066211FFB763300312A82 /* test9.answer in Resources */, 06F066221FFB763300312A82 /* test5.answer in Resources */, 06F0662C1FFB763400312A82 /* test7.gz in Resources */, diff --git a/Tests/TarTests.swift b/Tests/TarTests.swift index a5db96e2..b764390e 100644 --- a/Tests/TarTests.swift +++ b/Tests/TarTests.swift @@ -191,6 +191,28 @@ class TarTests: XCTestCase { XCTAssertEqual(entries[0].data, nil) } + func testOnlyDirectoryHeader() throws { + // This tests the correct handling of the situation when there is nothing in the container but one basic header, + // even no EOF marker (two blocks of zeros). + let testData = try Constants.data(forTest: "test_only_dir_header", withType: TarTests.testType) + + XCTAssertEqual(try TarContainer.formatOf(container: testData), .ustar) + + let entries = try TarContainer.open(container: testData) + + XCTAssertEqual(entries.count, 1) + XCTAssertEqual(entries[0].info.name, "empty_dir/") + XCTAssertEqual(entries[0].info.type, .directory) + XCTAssertEqual(entries[0].info.size, 0) + XCTAssertEqual(entries[0].info.ownerID, 501) + XCTAssertEqual(entries[0].info.groupID, 20) + XCTAssertEqual(entries[0].info.ownerUserName, "timofeysolomko") + XCTAssertEqual(entries[0].info.ownerGroupName, "staff") + XCTAssertEqual(entries[0].info.permissions, Permissions(rawValue: 493)) + XCTAssertNil(entries[0].info.comment) + XCTAssertEqual(entries[0].data, nil) + } + func testEmptyContainer() throws { let testData = try Constants.data(forTest: "test_empty_cont", withType: TarTests.testType) diff --git a/Tests/Test Files b/Tests/Test Files index b11a3090..fe35c32f 160000 --- a/Tests/Test Files +++ b/Tests/Test Files @@ -1 +1 @@ -Subproject commit b11a3090304037141155b6aab01ae49c94ee12bf +Subproject commit fe35c32fdab1aab6becabc1ade18408a42e32113 From ff269e3ffef6ff8d53691a867eaae60fd5c08ff7 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Tue, 27 Jul 2021 16:19:06 +0300 Subject: [PATCH 84/97] [ZIP] Rename ByteReader+Zip to LittleEndianByteReader+Zip --- SWCompression.xcodeproj/project.pbxproj | 8 ++++---- ...eReader+Zip.swift => LittleEndianByteReader+Zip.swift} | 0 2 files changed, 4 insertions(+), 4 deletions(-) rename Sources/ZIP/{ByteReader+Zip.swift => LittleEndianByteReader+Zip.swift} (100%) diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index f22297e5..ac5a4d19 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -108,7 +108,7 @@ 06D42DA72067B71000C1A98B /* TestZipExtraField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06D42DA62067B71000C1A98B /* TestZipExtraField.swift */; }; 06D95AC11F4C54E0006B46AC /* BZip2+Compress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06D95AC01F4C54E0006B46AC /* BZip2+Compress.swift */; }; 06DDB1711F8190D400035BEF /* BZip2+BlockSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06DDB1701F8190D400035BEF /* BZip2+BlockSize.swift */; }; - 06DE29B81FB7024C0098A761 /* ByteReader+Zip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06DE29B71FB7024C0098A761 /* ByteReader+Zip.swift */; }; + 06DE29B81FB7024C0098A761 /* LittleEndianByteReader+Zip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06DE29B71FB7024C0098A761 /* LittleEndianByteReader+Zip.swift */; }; 06E2346C1E068E9600F18798 /* XZArchive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06E2346B1E068E9600F18798 /* XZArchive.swift */; }; 06E234821E06A6C200F18798 /* CheckSums.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06E234811E06A6C200F18798 /* CheckSums.swift */; }; 06E6A6391F5C0FBB00D04856 /* CodeLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06E6A6381F5C0FBB00D04856 /* CodeLength.swift */; }; @@ -334,7 +334,7 @@ 06D42DA62067B71000C1A98B /* TestZipExtraField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestZipExtraField.swift; sourceTree = ""; }; 06D95AC01F4C54E0006B46AC /* BZip2+Compress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BZip2+Compress.swift"; sourceTree = ""; }; 06DDB1701F8190D400035BEF /* BZip2+BlockSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BZip2+BlockSize.swift"; sourceTree = ""; }; - 06DE29B71FB7024C0098A761 /* ByteReader+Zip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ByteReader+Zip.swift"; sourceTree = ""; }; + 06DE29B71FB7024C0098A761 /* LittleEndianByteReader+Zip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LittleEndianByteReader+Zip.swift"; sourceTree = ""; }; 06E2346B1E068E9600F18798 /* XZArchive.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XZArchive.swift; sourceTree = ""; }; 06E234811E06A6C200F18798 /* CheckSums.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheckSums.swift; path = Sources/Common/CheckSums.swift; sourceTree = SOURCE_ROOT; }; 06E6A6381F5C0FBB00D04856 /* CodeLength.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CodeLength.swift; path = Sources/Common/CodingTree/CodeLength.swift; sourceTree = SOURCE_ROOT; }; @@ -626,7 +626,7 @@ 061C06471F0E8FF500832F0C /* ZipCentralDirectoryEntry.swift */, 061C06511F0E904600832F0C /* ZipEndOfCentralDirectory.swift */, 06092A231FA4CC3D00DE9FD5 /* CompressionMethod+Zip.swift */, - 06DE29B71FB7024C0098A761 /* ByteReader+Zip.swift */, + 06DE29B71FB7024C0098A761 /* LittleEndianByteReader+Zip.swift */, 0686A6441FA4C47300E89C9E /* FileSystemType+Zip.swift */, ); path = ZIP; @@ -1146,7 +1146,7 @@ 06A172831FA5D3770048A89C /* LZMA2Decoder.swift in Sources */, 061C06571F0E90C800832F0C /* TarError.swift in Sources */, 06A960561F1E7D0B0078E6D1 /* 7zPackInfo.swift in Sources */, - 06DE29B81FB7024C0098A761 /* ByteReader+Zip.swift in Sources */, + 06DE29B81FB7024C0098A761 /* LittleEndianByteReader+Zip.swift in Sources */, 06BAC5941F8CFF28002443F4 /* ZipEntryInfo.swift in Sources */, 0625C49F1FB4B92F00A52C43 /* CompressionMethod+7z.swift in Sources */, 0620F4B31F8E2477001C9B7A /* ContainerEntry.swift in Sources */, diff --git a/Sources/ZIP/ByteReader+Zip.swift b/Sources/ZIP/LittleEndianByteReader+Zip.swift similarity index 100% rename from Sources/ZIP/ByteReader+Zip.swift rename to Sources/ZIP/LittleEndianByteReader+Zip.swift From 156552594290579f29243f291cff3f05a9833f2c Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 28 Jul 2021 11:13:54 +0300 Subject: [PATCH 85/97] Switch to the 2.0.0-test.2 release of BBD --- Cartfile | 2 +- Package.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cartfile b/Cartfile index da1117b1..00e63398 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1 @@ -github "tsolomko/BitByteData" "develop" +github "tsolomko/BitByteData" "2.0.0-test.2" diff --git a/Package.swift b/Package.swift index 445ff43d..0586a39d 100644 --- a/Package.swift +++ b/Package.swift @@ -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", - .branch("develop")), + from: "2.0.0-test.2"), ], targets: [ // SWCOMP: Uncomment the lines below to build swcomp example program. From e8e7bf1a729c88afa7bfd3cd0f3ab7642b162394 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 28 Jul 2021 11:14:32 +0300 Subject: [PATCH 86/97] [swcomp] Remove extra "try" in TarCommand --- Sources/swcomp/Containers/TarCommand.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/swcomp/Containers/TarCommand.swift b/Sources/swcomp/Containers/TarCommand.swift index acfd2d97..54ec091d 100644 --- a/Sources/swcomp/Containers/TarCommand.swift +++ b/Sources/swcomp/Containers/TarCommand.swift @@ -93,7 +93,7 @@ class TarCommand: Command { print("d = directory, f = file, l = symbolic link") } let entries = try self.createEntries(inputPath, verbose.value) - let containerData = try TarContainer.create(from: entries) + let containerData = TarContainer.create(from: entries) try containerData.write(to: URL(fileURLWithPath: self.archive.value)) } } From 417ef7ded882468c05b774c835879a141a1466a4 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 28 Jul 2021 11:17:49 +0300 Subject: [PATCH 87/97] [TAR] Small code comments changes --- Sources/TAR/LittleEndianByteReader+Tar.swift | 2 -- Sources/TAR/TarExtendedHeader.swift | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Sources/TAR/LittleEndianByteReader+Tar.swift b/Sources/TAR/LittleEndianByteReader+Tar.swift index 9efd476c..d0a83896 100644 --- a/Sources/TAR/LittleEndianByteReader+Tar.swift +++ b/Sources/TAR/LittleEndianByteReader+Tar.swift @@ -35,8 +35,6 @@ extension LittleEndianByteReader { Integers are encoded in TAR as ASCII text. We are treating them as UTF-8 encoded strings since UTF-8 is backwards compatible with ASCII. - - Integers can also be encoded as non-decimal based number. This is controlled by `radix` parameter. */ func tarInt(maxLength: Int) -> Int? { guard maxLength > 0 diff --git a/Sources/TAR/TarExtendedHeader.swift b/Sources/TAR/TarExtendedHeader.swift index b2443a6e..d1b31337 100644 --- a/Sources/TAR/TarExtendedHeader.swift +++ b/Sources/TAR/TarExtendedHeader.swift @@ -5,6 +5,7 @@ import Foundation +/// Also known as PAX header. struct TarExtendedHeader { var unknownRecords = [String: String]() @@ -112,6 +113,11 @@ struct TarExtendedHeader { (mtime < 0 || mtime > Double(maxOctalLengthTwelve)) { self.mtime = mtime } + // The non-asciiness of the (link)name is still a reason to use PAX headers, even though we encode using UTF-8 + // in basic TAR headers anyway, because one can imagine a third-party implementation, that can read PAX headers + // properly, but still expects all string fields in the basic header to be ASCII-only. By using PAX headers we + // can "support" those implementations, though this will work only if they skip (non-ASCII/invalid) string + // fields after encountering a PAX header. let asciiNameData = info.name.data(using: .ascii) if asciiNameData == nil || asciiNameData!.count > 100 { self.path = info.name From e5ddd7e2a37db48dccf9e59987c42cc4a2f8265a Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 28 Jul 2021 11:21:24 +0300 Subject: [PATCH 88/97] Remove swift 4.2 badge from README --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 8a1da6b4..e3beb8f4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # SWCompression -[![Swift 4.2](https://img.shields.io/badge/Swift-4.2-blue.svg)](https://developer.apple.com/swift/) [![Swift 5.X](https://img.shields.io/badge/Swift-5.X-blue.svg)](https://developer.apple.com/swift/) [![GitHub license](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://raw.githubusercontent.com/tsolomko/SWCompression/master/LICENSE) [![Build Status](https://travis-ci.com/tsolomko/SWCompression.svg?branch=develop)](https://travis-ci.com/tsolomko/SWCompression) From fe672f29ddddc203a4600d62325eaacbad000f2c Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 28 Jul 2021 11:21:59 +0300 Subject: [PATCH 89/97] Prepare for the test release of 4.6.0 --- .jazzy.yaml | 4 ++-- SWCompression.podspec | 2 +- SWCompression.xcodeproj/SWCompression.plist | 4 ++-- SWCompression.xcodeproj/TestSWCompression.plist | 4 ++-- SWCompression.xcodeproj/project.pbxproj | 8 ++++---- Sources/swcomp/main.swift | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.jazzy.yaml b/.jazzy.yaml index 247e1986..6c086b54 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -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-test 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-test theme: fullwidth custom_categories: diff --git a/SWCompression.podspec b/SWCompression.podspec index a31fcf18..5506cdd8 100644 --- a/SWCompression.podspec +++ b/SWCompression.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "SWCompression" - s.version = "4.5.11" + s.version = "4.6.0-test" 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." diff --git a/SWCompression.xcodeproj/SWCompression.plist b/SWCompression.xcodeproj/SWCompression.plist index 29025807..4ccd3413 100644 --- a/SWCompression.xcodeproj/SWCompression.plist +++ b/SWCompression.xcodeproj/SWCompression.plist @@ -15,9 +15,9 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 4.5.11 + 4.6.0-test CFBundleVersion - 78 + 79 NSHumanReadableCopyright Copyright © 2021 Timofey Solomko diff --git a/SWCompression.xcodeproj/TestSWCompression.plist b/SWCompression.xcodeproj/TestSWCompression.plist index c6fd15cd..b0f4d15c 100644 --- a/SWCompression.xcodeproj/TestSWCompression.plist +++ b/SWCompression.xcodeproj/TestSWCompression.plist @@ -15,8 +15,8 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 4.5.11 + 4.6.0-test CFBundleVersion - 78 + 79 diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index ac5a4d19..e3db6efb 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -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 = 79; 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 = 79; 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 = 79; 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 = 79; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = SWCompression.xcodeproj/SWCompression.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; diff --git a/Sources/swcomp/main.swift b/Sources/swcomp/main.swift index 1eed34a8..4a31d736 100644 --- a/Sources/swcomp/main.swift +++ b/Sources/swcomp/main.swift @@ -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-test", description: """ swcomp - a small command-line client for SWCompression framework. Serves as an example of SWCompression usage. From 47c15a77cc152a31fc850379fe2a4beaef1600c9 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 31 Jul 2021 12:22:27 +0300 Subject: [PATCH 90/97] [Tests] Adjust one of the TAR creation tests to better check base-256 encoding --- Tests/TarCreateTests.swift | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/Tests/TarCreateTests.swift b/Tests/TarCreateTests.swift index 84dc301c..7cb3114e 100644 --- a/Tests/TarCreateTests.swift +++ b/Tests/TarCreateTests.swift @@ -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 { From d335ed450ef7b3f3f2bdb80defefc43a2789f751 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 31 Jul 2021 12:23:00 +0300 Subject: [PATCH 91/97] [TAR] Counters for special entries are now UInt to prevent overflowing into negatives --- Sources/TAR/TarContainer.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 44155655..727764d5 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -94,17 +94,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 { From 925986b9ed5106f3f42deb7742c776df92d9281c Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 31 Jul 2021 12:23:37 +0300 Subject: [PATCH 92/97] [TAR] Add an assertion that verifies that base-256 encoding will always succeed --- Sources/TAR/Data+Tar.swift | 3 +++ Sources/TAR/TarHeader.swift | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Sources/TAR/Data+Tar.swift b/Sources/TAR/Data+Tar.swift index 489c713d..643c881a 100644 --- a/Sources/TAR/Data+Tar.swift +++ b/Sources/TAR/Data+Tar.swift @@ -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) diff --git a/Sources/TAR/TarHeader.swift b/Sources/TAR/TarHeader.swift index 9d151092..cacd3fe8 100644 --- a/Sources/TAR/TarHeader.swift +++ b/Sources/TAR/TarHeader.swift @@ -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 From 8ca03a83ab8f2ecc794f9496c521538cae44be30 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Tue, 3 Aug 2021 18:27:40 +0300 Subject: [PATCH 93/97] Upgrade BBD to 2.0 --- Cartfile | 2 +- Package.swift | 2 +- SWCompression.podspec | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cartfile b/Cartfile index 00e63398..656bf838 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1 @@ -github "tsolomko/BitByteData" "2.0.0-test.2" +github "tsolomko/BitByteData" ~> 2.0.0 diff --git a/Package.swift b/Package.swift index 0586a39d..e63587cd 100644 --- a/Package.swift +++ b/Package.swift @@ -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. diff --git a/SWCompression.podspec b/SWCompression.podspec index 5506cdd8..208138df 100644 --- a/SWCompression.podspec +++ b/SWCompression.podspec @@ -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" From 4e8be1d4fc28fadf836e62e56267d713fc86c34f Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Tue, 3 Aug 2021 18:39:03 +0300 Subject: [PATCH 94/97] [TAR] Remove TarEntryInfo.format in favor of working with header format directly --- Sources/TAR/TarContainer.swift | 11 +++++------ Sources/TAR/TarEntryInfo.swift | 14 -------------- Sources/TAR/TarHeader.swift | 2 +- Sources/TAR/TarParser.swift | 4 ++-- 4 files changed, 8 insertions(+), 23 deletions(-) diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index 727764d5..d13f24bb 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -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: @@ -178,7 +177,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 +229,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. diff --git a/Sources/TAR/TarEntryInfo.swift b/Sources/TAR/TarEntryInfo.swift index 963bb8c3..c298391f 100644 --- a/Sources/TAR/TarEntryInfo.swift +++ b/Sources/TAR/TarEntryInfo.swift @@ -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 != "" { diff --git a/Sources/TAR/TarHeader.swift b/Sources/TAR/TarHeader.swift index cacd3fe8..3a389808 100644 --- a/Sources/TAR/TarHeader.swift +++ b/Sources/TAR/TarHeader.swift @@ -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 } diff --git a/Sources/TAR/TarParser.swift b/Sources/TAR/TarParser.swift index 5879152b..bd4277d7 100644 --- a/Sources/TAR/TarParser.swift +++ b/Sources/TAR/TarParser.swift @@ -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) } } From 0ac48ae70462256a9e1c03ac908e34b9b2790156 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 4 Aug 2021 10:52:31 +0300 Subject: [PATCH 95/97] [docs] Add documentation for TarContainer.create(from:force:) --- Sources/TAR/Data+Tar.swift | 1 - Sources/TAR/TarContainer.swift | 19 ++++++++++++++++++- Sources/TAR/TarHeader.swift | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Sources/TAR/Data+Tar.swift b/Sources/TAR/Data+Tar.swift index 643c881a..9c9ed4fb 100644 --- a/Sources/TAR/Data+Tar.swift +++ b/Sources/TAR/Data+Tar.swift @@ -53,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 diff --git a/Sources/TAR/TarContainer.swift b/Sources/TAR/TarContainer.swift index d13f24bb..5c28adce 100644 --- a/Sources/TAR/TarContainer.swift +++ b/Sources/TAR/TarContainer.swift @@ -83,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. diff --git a/Sources/TAR/TarHeader.swift b/Sources/TAR/TarHeader.swift index 3a389808..b0c9ea2f 100644 --- a/Sources/TAR/TarHeader.swift +++ b/Sources/TAR/TarHeader.swift @@ -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 From 53a9480cc5216c11bff8dffef521fd869a357d47 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 4 Aug 2021 11:53:35 +0300 Subject: [PATCH 96/97] Small updates to README --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index e3beb8f4..d59f3905 100644 --- a/README.md +++ b/README.md @@ -9,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. @@ -33,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 @@ -46,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( @@ -61,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`. @@ -104,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//` 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//` 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). @@ -164,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 @@ -174,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. From 97323fa76a6adb4cec40274bf522032e42a77222 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Wed, 4 Aug 2021 15:50:55 +0300 Subject: [PATCH 97/97] Prepare for 4.6.0 release --- .jazzy.yaml | 4 ++-- CHANGELOG.md | 21 +++++++++++++++++++ SWCompression.podspec | 2 +- SWCompression.xcodeproj/SWCompression.plist | 4 ++-- .../TestSWCompression.plist | 4 ++-- SWCompression.xcodeproj/project.pbxproj | 8 +++---- Sources/swcomp/main.swift | 2 +- 7 files changed, 33 insertions(+), 12 deletions(-) diff --git a/.jazzy.yaml b/.jazzy.yaml index 6c086b54..9e1d8f58 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -3,11 +3,11 @@ sourcekitten_sourcefile: docs.json clean: false author: Timofey Solomko module: SWCompression -module_version: 4.6.0-test +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.6.0-test +github_file_prefix: https://github.com/tsolomko/SWCompression/tree/4.6.0 theme: fullwidth custom_categories: diff --git a/CHANGELOG.md b/CHANGELOG.md index d47da297..85bb1312 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. diff --git a/SWCompression.podspec b/SWCompression.podspec index 208138df..428d48fe 100644 --- a/SWCompression.podspec +++ b/SWCompression.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "SWCompression" - s.version = "4.6.0-test" + 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." diff --git a/SWCompression.xcodeproj/SWCompression.plist b/SWCompression.xcodeproj/SWCompression.plist index 4ccd3413..f6f8a4ef 100644 --- a/SWCompression.xcodeproj/SWCompression.plist +++ b/SWCompression.xcodeproj/SWCompression.plist @@ -15,9 +15,9 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 4.6.0-test + 4.6.0 CFBundleVersion - 79 + 80 NSHumanReadableCopyright Copyright © 2021 Timofey Solomko diff --git a/SWCompression.xcodeproj/TestSWCompression.plist b/SWCompression.xcodeproj/TestSWCompression.plist index b0f4d15c..95886263 100644 --- a/SWCompression.xcodeproj/TestSWCompression.plist +++ b/SWCompression.xcodeproj/TestSWCompression.plist @@ -15,8 +15,8 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 4.6.0-test + 4.6.0 CFBundleVersion - 79 + 80 diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index e3db6efb..bb016374 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -1270,7 +1270,7 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CURRENT_PROJECT_VERSION = 79; + 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 = 79; + 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 = 79; + 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 = 79; + DYLIB_CURRENT_VERSION = 80; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = SWCompression.xcodeproj/SWCompression.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; diff --git a/Sources/swcomp/main.swift b/Sources/swcomp/main.swift index 4a31d736..4b329857 100644 --- a/Sources/swcomp/main.swift +++ b/Sources/swcomp/main.swift @@ -7,7 +7,7 @@ import Foundation import SWCompression import SwiftCLI -let cli = CLI(name: "swcomp", version: "4.6.0-test", +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.