Added checks for volume files#38
Added checks for volume files#38abbeycode merged 67 commits intoabbeycode:multivolumefrom aonez:master
Conversation
|
Here a sample code using some of the functions: NSError *archiveError = nil;
URKArchive *archive = [[URKArchive alloc] initWithPath:rar error:&archiveError];
NSError *error = nil;
if (archive.isVolume) {
NSLog(@"isVolume");
NSLog(@"First volume: %@", [archive firstVolumePath]);
URKArchive *volarchive = [[URKArchive alloc] initWithPath:[archive firstVolumePath] error:&archiveError];
NSArray<NSString*> *paths = [volarchive listVolumePaths:&error];
NSLog(@"List of volumes:");
for (NSString *path in paths) {
NSLog(@"%@", path);
}
}
else
NSLog(@"NOT isVolume");Even if |
|
Just noticed the code does not return Those flags might be needed, but are always returning |
|
Thanks for keeping up on this! It looks like it'll make a good addition to the library. I'll review as soon as I'm able to. |
|
I'm starting to take a look at this now. To give me some context, can you explain how your code is using multi-volume archives, and how each of the methods you defined fits into your use case? Also, have you looked at the RAR spec? It is helpful in figuring out the right way to approach problems like these. |
|
I needed a way to list all the parts of a volume, so I can delete them all after an extraction. Also it is useful when a user tries to extract a volume using all the parts, I can select the first one and dismiss the others. First, this one tells me if the file is a volume part, so I can search for the first one and list all the parts. I'll try - (BOOL)isVolume:(NSURL *)fileURLIf it is a volume, I want to be sure it is the first part. With this function I'll get the first volume path: - (NSString *)firstVolumePath:(NSString *)filePathThen, I can just extract the file using the first path. Also, I can get all the volume paths from the first one, so I can delete them or dismiss them from the extraction process: - (NSArray<NSString*> *)listVolumePaths:(NSError **)errorThis last function maybe can be done in another way. Right now I list the contents of the file so I can get the paths of all (found) volumes. Maybe it can be done using |
|
I'll be using it here: aonez/Keka#8 |
|
Checked again, |
|
Sorry it took me a while to get back to you, but I was getting the code all cleaned up to work with the latest Xcode version, and it took longer than expected. That's great you found a better way to list the volume paths! Can you push an updated commit? Also, I'm curious about why you need the I'll try to keep up on this a little more to get it out the door. I'm going to be pushing a branch I created that'll help us get started on unit tests for these new methods. I'm using the |
|
@abbeycode not hurry at all. Sadly I did not found any other way to get the first part of the volume detected as a volume, nor get a consistent way to detect the next/previous volume existence. So right now the code is as here. The overloads are not necessary for me. I'm using with the opened archive ( Let me know how the tests go! Maybe you get motivated and find the right flag to get the first volume path detected ;) |
|
Just rebased with your master, seems there're too many changes now in the pull request... |
|
That's strange that it's showing all of those as changes. Did you do a |
|
Did a rebase but using the Fork GUI. First rebase for me by the way, so not surprised it got broken... |
|
Interesting... I think it messed it up. Also, regardless of what it did, I think GitHub expects you to just |
|
Sure, I’ll try to fix it right away :)
|
|
Done! Hard reset and a merge did it. |
… a pull request's tests (PR #38)
|
I added the tests and stubbed out methods. I renamed the one method to be a little clearer, and added Also, while I was running the tests with your current implementation, it looks like you're going to want to use this in your
Let me know if you have any other questions! Also, you should probably update the PR to merge into that new |
|
You got it, using |
|
Little busy right now, but I'll get to it! |
|
Hello. It's been a while, and I was wondering if you were still planning on pushing this PR over the finish line. If so, let me know and I'll bring the |
|
Just was thinking about this some days ago. Sure I will! |
|
Ok, so my PR is updated to the current status of the |
|
I updated the |
|
The build failed, but that's because of the unit tests that this PR will fix, so you may proceed! |
|
Should work now, let's see what travis says 😛 |
|
Hmmmm still looks like the new unit tests are failing... |
|
I'll take a look in a few hours...
|
|
Cleaned all my code and failed again. Then I saw your branch failed too. Look at your latest commit travis CI status. I'm mostly sure this is why it failed yesterday. I'm not familiar with travis CI, maybe you'll see whats the problem there. |
abbeycode
left a comment
There was a problem hiding this comment.
Thanks for picking this back up! I'm excited to include this new functionality in the library. I have one incredibly minor nitpick, and one more substantial issue. Please take a look when you can, and we'll get this over the finish line.
Classes/URKArchive.mm
Outdated
| return false; | ||
| } | ||
|
|
||
| return (volumeURLs.count > 1); |
There was a problem hiding this comment.
Very very minor suggestion: No need for the parentheses here.
Classes/URKArchive.mm
Outdated
| @try { | ||
| NSError *firstVolumeError = nil; | ||
|
|
||
| if ([self _unrarOpenFile:firstVolumeURL.path |
There was a problem hiding this comment.
Please take a look at this suggestion. It's the only real thing holding this back. Thanks for hopping back on this request!
| * @return Returns the URL, or nil if there was an error | ||
| */ | ||
| - (nullable NSURL *)firstVolumeURL; | ||
| - (NSURL *)firstVolumeURL:(NSURL *)fileURL; |
There was a problem hiding this comment.
Those will be not nullable, since they will be called after a (!fileURL) check. If no first part, they will return the passed fileURL.
| return false; | ||
| } | ||
|
|
||
| return volumeURLs.count > 1; |
There was a problem hiding this comment.
No extra parenthesis 👍
|
|
||
| - (nullable NSURL *)firstVolumeURL { | ||
| NSString *path = [self firstVolumePath]; | ||
| - (NSURL *)firstVolumeURL:(NSURL *)fileURL { |
There was a problem hiding this comment.
Changed the contents to the NSURL method because init uses NSURL
There was a problem hiding this comment.
I have a few thoughts on this.
- Since we're working with regular expressions in the
firstVolume...method, it makes sense for it to use a path. Let it be true to itself - I think it would be clearer if
firstVolumePathwere a class method that takes a path, since it isn't using any internal state of the class - It only needs to be private. We can get rid of the public
firstVolumeURLandfirstPathURLinstance methods, since all instances are going to represent the first volume. Basically, it will always be true thatfirstVolumeURL == fileURL
| return [NSURL fileURLWithPath:volumePath]; | ||
| } | ||
| else | ||
| URKLogInfo("First volume part %@ not found. Skipping first volume selection", volumePath); |
There was a problem hiding this comment.
Just skip, do not return nil. URKLogInfo, this will get to the final user?
There was a problem hiding this comment.
No, all logging is for the dev to see, not the user.
There was a problem hiding this comment.
Also, look at the README for logging suggestions. This should probably be Debug level
| URKLogInfo("First volume part %@ not found. Skipping first volume selection", volumePath); | ||
| } | ||
|
|
||
| return fileURL; |
There was a problem hiding this comment.
If no match, always return the passed fileURL
| return @[]; | ||
| NSMutableOrderedSet<NSString*> *volumePaths = [NSMutableOrderedSet new]; | ||
|
|
||
| NSArray<URKFileInfo*> *listFileInfo = [self listFileInfo:error]; |
There was a problem hiding this comment.
The NSMutableOrderedSet class doesn't sort members as they're added. You're better off using a regular NSMutableSet and sorting it when you convert to an array.
| } | ||
|
|
||
|
|
||
| fileURL = [self firstVolumeURL:fileURL]; |
There was a problem hiding this comment.
Just added it before (!fileURL) check and [self init], let me know if you think there's a better place
|
|
||
| if (![path length]) { | ||
| return nil; | ||
| URKLogDebug("Checking if the archive is part of a volume..."); |
There was a problem hiding this comment.
Added URKLogDebug trough all the process
|
If the changes are ok for you, the case tests calls to Alse we need to determine what to do with this check: - (void)testMultipleVolume_FirstVolumeMissing;Maybe add an overload to firstVolumeURL to return nil if not found so the developer can forcibly ask for it? |
abbeycode
left a comment
There was a problem hiding this comment.
I appreciate all of your work on this. I still feel like there's some work to be done, but I'll leave it up to you whether you want to continue going through the PR feedback loop or not. I'm fine will pulling your changes into the multivolume branch at this point and making the changes I'm suggesting myself. If you feel like you're getting something out of the review process, though, then we can keep going and bring it over the finish line together. It's your call.
|
|
||
| - (nullable NSURL *)firstVolumeURL { | ||
| NSString *path = [self firstVolumePath]; | ||
| - (NSURL *)firstVolumeURL:(NSURL *)fileURL { |
There was a problem hiding this comment.
I have a few thoughts on this.
- Since we're working with regular expressions in the
firstVolume...method, it makes sense for it to use a path. Let it be true to itself - I think it would be clearer if
firstVolumePathwere a class method that takes a path, since it isn't using any internal state of the class - It only needs to be private. We can get rid of the public
firstVolumeURLandfirstPathURLinstance methods, since all instances are going to represent the first volume. Basically, it will always be true thatfirstVolumeURL == fileURL
| return nil; | ||
| URKLogDebug("Checking if the archive is part of a volume..."); | ||
|
|
||
| __block NSString *volumePath = fileURL.path; |
There was a problem hiding this comment.
This doesn't need to be a __block variable, since it's not modified from inside a block. Also, once we refactor to a single class method (+[URKArchive firstVolumePath:]), it'll be the input argument.
| __block NSString *volumePath = fileURL.path; | ||
| NSTextCheckingResult * match; | ||
|
|
||
| if (volumePath.length) |
There was a problem hiding this comment.
Invert this if and exit early. If volumePath is empty, log an error and return nil. That way we un-nest everything below, and you don't need to check for match twice. You can simplify the rest of the method's conditions.
| return @[]; | ||
| NSMutableOrderedSet<NSString*> *volumePaths = [NSMutableOrderedSet new]; | ||
|
|
||
| NSArray<URKFileInfo*> *listFileInfo = [self listFileInfo:error]; |
There was a problem hiding this comment.
The NSMutableOrderedSet class doesn't sort members as they're added. You're better off using a regular NSMutableSet and sorting it when you convert to an array.
|
Go ahead with the pull. I think now all the elements are working, it's just a matter of "coding" preferences and optimisations that maybe you'll do faster. I'll take a look at the final code once is there 🤓 Obviously if you need anything from my part just ask. |
|
@aonez Thanks again for all your work on this! I'll mention you in the PR I create to merge the |
|
@aonez Take a look at the PR I created (linked above) and let me know what you think. If it looks good, I'll merge to v2.9 and release a second beta soon. |
From pull #36
This one contains various functions to check wether the file is a parted RAR volume, the get the first part path and to get the list of all the parts paths of the volume.