Skip to content

Read archive in chunks when publishing archive to registry #6979

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions Sources/PackageRegistry/RegistryClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1363,10 +1363,10 @@ public final class RegistryClient: Cancellable {
return completion(.failure(RegistryError.invalidURL(registryURL)))
}

// TODO: don't load the entire file in memory
guard let packageArchiveContent: Data = try? fileSystem.readFileContents(packageArchive) else {
guard let packageArchiveContent: Data = fileSystem.readFileInChunks(path: packageArchive) else {
return completion(.failure(RegistryError.failedLoadingPackageArchive(packageArchive)))
}

var metadataContent: String? = .none
if let packageMetadata {
do {
Expand Down Expand Up @@ -2441,3 +2441,35 @@ extension URLComponents {
path += (path.last == "/" ? "" : "/") + components.joined(separator: "/")
}
}

extension FileSystem {
/// Get the contents of a file without loading all of it in memory
///
/// - Returns: The file contents as Data, or nil if missing
func readFileInChunks(path: AbsolutePath, bufferSize: Int = 1024) -> Data? {
Copy link
Contributor

@MaxDesiatov MaxDesiatov Oct 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm not sure I understand what this is trying to achieve. How exactly would this prevent reading the whole file into memory if the resulting Data value contains the whole file in memory due to the fact that all of the chunks are appended to it to form one huge Data buffer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're totally right.
My bad, this is actually far from being ready for review.
Marking it as a draft for now if that's ok.

guard localFileSystem.exists(path) else {
return nil
}
guard let inputStream = InputStream(fileAtPath: path.pathString) else {
return nil
}
inputStream.open()
defer { inputStream.close() }

var data = Data()
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
while inputStream.hasBytesAvailable {
let read = inputStream.read(buffer, maxLength: bufferSize)
if read < 0 {
return nil
} else if read == 0 {
break
} else {
data.append(buffer, count: read)
}
}
buffer.deallocate()

return data
}
}