@@ -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
0 commit comments