Skip to content

Commit cc41a65

Browse files
committed
added an option to specify a path within the folder to restore
1 parent 3bd7f24 commit cc41a65

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

ArqRestoreCommand.m

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ - (BOOL)printTree:(Tree *)theTree repo:(Repo *)theRepo relativePath:(NSString *)
431431
}
432432

433433
- (BOOL)restore:(NSArray *)args error:(NSError **)error {
434-
if ([args count] != 5) {
434+
if ([args count] != 5 && [args count] != 6) {
435435
SETNSERROR([self errorDomain], ERROR_USAGE, @"invalid arguments");
436436
return NO;
437437
}
@@ -489,8 +489,41 @@ - (BOOL)restore:(NSArray *)args error:(NSError **)error {
489489
if (commit == nil) {
490490
return NO;
491491
}
492-
493-
NSString *destinationPath = [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:[[matchingBucket localPath] lastPathComponent]];
492+
493+
BlobKey *treeBlobKey = [commit treeBlobKey];
494+
NSString *nodeName = nil;
495+
if ([args count] == 6) {
496+
NSString *path = [args objectAtIndex:5];
497+
if ([path hasPrefix:@"/"]) {
498+
path = [path substringFromIndex:1];
499+
}
500+
NSArray *pathComponents = [path pathComponents];
501+
for (NSUInteger index = 0; index < [pathComponents count]; index++) {
502+
NSString *component = [pathComponents objectAtIndex:index];
503+
Tree *childTree = [repo treeForBlobKey:treeBlobKey error:error];
504+
if (childTree == nil) {
505+
return NO;
506+
}
507+
Node *childNode = [childTree childNodeWithName:component];
508+
if (childNode == nil) {
509+
SETNSERROR([self errorDomain], ERROR_NOT_FOUND, @"path component '%@' not found", component);
510+
return NO;
511+
}
512+
if (![childNode isTree] && index < ([pathComponents count] - 1)) {
513+
// If it's a directory and we're not at the end of the path, fail.
514+
SETNSERROR([self errorDomain], -1, @"'%@' is not a directory", component);
515+
return NO;
516+
}
517+
if ([childNode isTree]) {
518+
treeBlobKey = [childNode treeBlobKey];
519+
} else {
520+
nodeName = component;
521+
}
522+
}
523+
}
524+
525+
NSString *restoreFileName = [args count] == 6 ? [[args objectAtIndex:5] lastPathComponent] : [[matchingBucket localPath] lastPathComponent];
526+
NSString *destinationPath = [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:restoreFileName];
494527
if ([[NSFileManager defaultManager] fileExistsAtPath:destinationPath]) {
495528
SETNSERROR([self errorDomain], -1, @"%@ already exists", destinationPath);
496529
return NO;
@@ -511,8 +544,9 @@ - (BOOL)restore:(NSArray *)args error:(NSError **)error {
511544
commitBlobKey:commitBlobKey
512545
rootItemName:[[matchingBucket localPath] lastPathComponent]
513546
treeVersion:CURRENT_TREE_VERSION
514-
treeBlobKey:[commit treeBlobKey]
515-
nodeName:nil targetUID:getuid()
547+
treeBlobKey:treeBlobKey
548+
nodeName:nodeName
549+
targetUID:getuid()
516550
targetGID:getgid()
517551
useTargetUIDAndGID:YES
518552
destinationPath:destinationPath
@@ -527,8 +561,8 @@ - (BOOL)restore:(NSArray *)args error:(NSError **)error {
527561
commitBlobKey:commitBlobKey
528562
rootItemName:[[matchingBucket localPath] lastPathComponent]
529563
treeVersion:CURRENT_TREE_VERSION
530-
treeBlobKey:[commit treeBlobKey]
531-
nodeName:nil
564+
treeBlobKey:treeBlobKey
565+
nodeName:nodeName
532566
targetUID:getuid()
533567
targetGID:getgid()
534568
useTargetUIDAndGID:YES
@@ -542,8 +576,8 @@ - (BOOL)restore:(NSArray *)args error:(NSError **)error {
542576
commitBlobKey:commitBlobKey
543577
rootItemName:[[matchingBucket localPath] lastPathComponent]
544578
treeVersion:CURRENT_TREE_VERSION
545-
treeBlobKey:[commit treeBlobKey]
546-
nodeName:nil
579+
treeBlobKey:treeBlobKey
580+
nodeName:nodeName
547581
targetUID:getuid()
548582
targetGID:getgid()
549583
useTargetUIDAndGID:YES

arq_restore.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static void printUsage(const char *exeName) {
4848
fprintf(stderr, "\t%s [-l loglevel] listfolders <target_nickname> <computer_uuid>\n", exeName);
4949
fprintf(stderr, "\t%s [-l loglevel] printplist <target_nickname> <computer_uuid> <folder_uuid>\n", exeName);
5050
fprintf(stderr, "\t%s [-l loglevel] listtree <target_nickname> <computer_uuid> <folder_uuid>\n", exeName);
51-
fprintf(stderr, "\t%s [-l loglevel] restore <target_nickname> <computer_uuid> <folder_uuid>\n", exeName);
51+
fprintf(stderr, "\t%s [-l loglevel] restore <target_nickname> <computer_uuid> <folder_uuid> [relative_path]\n", exeName);
5252
fprintf(stderr, "\t%s [-l loglevel] clearcache <target_nickname>\n", exeName);
5353
fprintf(stderr, "\n");
5454
fprintf(stderr, "log levels: none, error, warn, info, and debug\n");

0 commit comments

Comments
 (0)