Skip to content

FileManager: Fix copyItem(atPath:toPath:) for directories and symlinks. #1515

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

Merged
merged 1 commit into from
Apr 15, 2018

Conversation

spevans
Copy link
Contributor

@spevans spevans commented Apr 14, 2018

  • When copying directories dont recurse into copyItems() just iterate
    through the results of subpathsOfDirectory().

  • Copy the contents of the symlink not the file that it points to,
    creating a new symlink.

Found during testing of #1510

- When copying directories dont recurse into copyItems() just iterate
  through the results of subpathsOfDirectory().

- Copy the contents of the symlink not the file that it points to,
  creating a new symlink.
@spevans
Copy link
Contributor Author

spevans commented Apr 14, 2018

@swift-ci please test

@spevans
Copy link
Contributor Author

spevans commented Apr 14, 2018

@swift-ci please test and merge

1 similar comment
@spevans
Copy link
Contributor Author

spevans commented Apr 15, 2018

@swift-ci please test and merge

@swift-ci swift-ci merged commit c2a4159 into swiftlang:master Apr 15, 2018
let destination = try destinationOfSymbolicLink(atPath: srcPath)
try createSymbolicLink(atPath: dstPath, withDestinationPath: destination)
} else if fileType == .typeRegular {
if createFile(atPath: dstPath, contents: contents(atPath: srcPath), attributes: nil) == false {
Copy link
Contributor

Choose a reason for hiding this comment

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

This works, but a proper copy engine will read then write a limited portion of the source file at a time. For large files, this will result in an extreme high-water mark for memory usage.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, this was how the previous version was doing it but I will create a PR to fix it.

if fileType == .typeDirectory {
try createDirectory(atPath: dstPath, withIntermediateDirectories: false, attributes: nil)
let subpaths = try subpathsOfDirectory(atPath: srcPath)
for subpath in subpaths {
try copyItem(atPath: srcPath + "/" + subpath, toPath: dstPath + "/" + subpath)
let src = srcPath + "/" + subpath
let dst = dstPath + "/" + subpath
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm sorry, I don't recall—Do we not have an equivalent of -stringByAppendingPathComponent: in SCL?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Only on NSString it appears, maybe a helper on String could be added in NSPathUtilities.

let dst = dstPath + "/" + subpath
if let attrs = try? attributesOfItem(atPath: src), let fileType = attrs[.type] as? FileAttributeType {
if fileType == .typeDirectory {
try createDirectory(atPath: dst, withIntermediateDirectories: false, attributes: nil)
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks wrong. No recursion at all means we only go one extra level deep, no? (There should be a test for this.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The original implementation was wrong because it was recursing in every directory and then additional recursing in every sub directory. It now uses subpathsOfDirectory(atPath:) at the top level to get all of the subitems. There is are tests for it at https://github.com/apple/swift-corelibs-foundation/pull/1515/files/3c454b7358312d8d10dcb68a22d577e9ec816b58#diff-fffbc0319b30adac9f635327a750b82fR555

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I see. I misread this as contentsOfDirectory.

Please note that subpathsOfDirectory is very expensive, as it does all the directory enumeration at once and potentially creates a VERY large array. This is a high-water mark issue, similar to the contentsAtPath one. Using an enumerator would be much preferable here, and should be a fairly simple drop-in replacement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants