From be507c82303f47aaa4da89867408c96ca4e2c1ce Mon Sep 17 00:00:00 2001 From: Tomasz Krasnyk Date: Sun, 28 Nov 2010 00:41:27 +0100 Subject: [PATCH] - Added controller 4 stashes, submodules, reset management - Added additional menu for the repository actions - Added action for 'Revealing in Finder' --- Commands/PBRevealWithFinderCommand.h | 17 ++++ Commands/PBRevealWithFinderCommand.m | 31 +++++++ Controller/PBGitResetController.h | 24 +++++ Controller/PBGitResetController.m | 60 ++++++++++++ Controller/PBSubmoduleController.h | 37 ++++++++ Controller/PBSubmoduleController.m | 133 +++++++++++++++++++++++++++ GitX.xcodeproj/project.pbxproj | 60 +++++------- PBGitRepository.h | 16 +++- PBGitRepository.m | 68 ++++++-------- PBGitSidebarController.m | 28 +++--- PBStashController.h | 31 +++++++ PBStashController.m | 110 ++++++++++++++++++++++ 12 files changed, 516 insertions(+), 99 deletions(-) create mode 100644 Commands/PBRevealWithFinderCommand.h create mode 100644 Commands/PBRevealWithFinderCommand.m create mode 100644 Controller/PBGitResetController.h create mode 100644 Controller/PBGitResetController.m create mode 100644 Controller/PBSubmoduleController.h create mode 100644 Controller/PBSubmoduleController.m create mode 100644 PBStashController.h create mode 100644 PBStashController.m diff --git a/Commands/PBRevealWithFinderCommand.h b/Commands/PBRevealWithFinderCommand.h new file mode 100644 index 000000000..a97f6f12d --- /dev/null +++ b/Commands/PBRevealWithFinderCommand.h @@ -0,0 +1,17 @@ +// +// PBRevealWithFinder.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBOpenDocumentCommand.h" + +@interface PBRevealWithFinderCommand : PBOpenDocumentCommand { + +} + + +@end diff --git a/Commands/PBRevealWithFinderCommand.m b/Commands/PBRevealWithFinderCommand.m new file mode 100644 index 000000000..2f94a585b --- /dev/null +++ b/Commands/PBRevealWithFinderCommand.m @@ -0,0 +1,31 @@ +// +// PBRevealWithFinder.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBRevealWithFinderCommand.h" + + +@implementation PBRevealWithFinderCommand + +- (id) initWithDocumentAbsolutePath:(NSString *) path { + if (!path) { + [self autorelease]; + return nil; + } + + if (self = [super initWithDisplayName:@"Reveal in Finder" parameters:nil repository:nil]) { + documentURL = [[NSURL alloc] initWithString:path]; + } + return self; +} + +- (void) invoke { + NSWorkspace *ws = [NSWorkspace sharedWorkspace]; + [ws selectFile:[documentURL absoluteString] inFileViewerRootedAtPath:nil]; +} + +@end diff --git a/Controller/PBGitResetController.h b/Controller/PBGitResetController.h new file mode 100644 index 000000000..b7a8d30a3 --- /dev/null +++ b/Controller/PBGitResetController.h @@ -0,0 +1,24 @@ +// +// PBGitResetController.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + +@class PBGitRepository; + +@interface PBGitResetController : NSObject { + PBGitRepository *repository; +} +- (id) initWithRepository:(PBGitRepository *) repo; + +- (NSArray *) menuItems; + + +// actions +- (void) resetHardToHead; + +@end diff --git a/Controller/PBGitResetController.m b/Controller/PBGitResetController.m new file mode 100644 index 000000000..f0d199a20 --- /dev/null +++ b/Controller/PBGitResetController.m @@ -0,0 +1,60 @@ +// +// PBGitResetController.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBGitResetController.h" +#import "PBGitRepository.h" +#import "PBCommand.h" + +@implementation PBGitResetController + +- (id) initWithRepository:(PBGitRepository *) repo { + if (self = [super init]){ + repository = [repo retain]; + } + return self; +} + +- (void) resetHardToHead { + NSArray *arguments = [NSArray arrayWithObjects:@"reset", @"--hard", @"HEAD", nil]; + PBCommand *cmd = [[PBCommand alloc] initWithDisplayName:@"Reset hard to HEAD" parameters:arguments repository:repository]; + cmd.commandTitle = cmd.displayName; + cmd.commandDescription = @"Reseting head"; + [cmd invoke]; +} + +- (void) reset { + //TODO missing implementation +} + +- (NSArray *) menuItems { + NSMenuItem *resetHeadHardly = [[NSMenuItem alloc] initWithTitle:@"Reset hard to HEAD" action:@selector(resetHardToHead) keyEquivalent:@""]; + [resetHeadHardly setTarget:self]; + + NSMenuItem *reset = [[NSMenuItem alloc] initWithTitle:@"Reset..." action:@selector(reset) keyEquivalent:@""]; + [reset setTarget:self]; + + return [NSArray arrayWithObjects:resetHeadHardly, reset, nil]; +} + +- (BOOL) validateMenuItem:(NSMenuItem *)menuItem { + BOOL shouldBeEnabled = YES; + SEL action = [menuItem action]; + if (action == @selector(reset)) { + shouldBeEnabled = NO; + //TODO missing implementation + } + return shouldBeEnabled; +} + +- (void) dealloc { + [repository release]; + [super dealloc]; +} + + +@end diff --git a/Controller/PBSubmoduleController.h b/Controller/PBSubmoduleController.h new file mode 100644 index 000000000..65294eb9d --- /dev/null +++ b/Controller/PBSubmoduleController.h @@ -0,0 +1,37 @@ +// +// PBSubmoduleController.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBGitSubmodule.h" + +@class PBGitRepository; +@class PBCommand; + +@interface PBSubmoduleController : NSObject { + NSArray *submodules; +@private + PBGitRepository *repository; +} +@property (nonatomic, retain, readonly) NSArray *submodules; + +- (id) initWithRepository:(PBGitRepository *) repo; + +- (void) reload; + +- (NSArray *) menuItems; + + +// actions + +- (void) addNewSubmodule; +- (void) initializeAllSubmodules; +- (void) updateAllSubmodules; + +- (PBCommand *) commandForOpeningSubmodule:(PBGitSubmodule *) submodule; +- (PBCommand *) defaultCommandForSubmodule:(PBGitSubmodule *) submodule; +@end diff --git a/Controller/PBSubmoduleController.m b/Controller/PBSubmoduleController.m new file mode 100644 index 000000000..7da580bcd --- /dev/null +++ b/Controller/PBSubmoduleController.m @@ -0,0 +1,133 @@ +// +// PBSubmoduleController.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBSubmoduleController.h" +#import "PBGitRepository.h" +#import "PBOpenDocumentCommand.h" + +@interface PBSubmoduleController() +@property (nonatomic, retain) NSArray *submodules; +@end + + +@implementation PBSubmoduleController +@synthesize submodules; + +- (id) initWithRepository:(PBGitRepository *) repo { + if (self = [super init]){ + repository = [repo retain]; + } + return self; +} + +- (void)dealloc { + [repository release]; + [submodules release]; + [super dealloc]; +} + +- (void) reload { + NSArray *arguments = [NSArray arrayWithObjects:@"submodule", @"status", @"--recursive", nil]; + NSString *output = [repository outputInWorkdirForArguments:arguments]; + NSArray *lines = [output componentsSeparatedByString:@"\n"]; + + NSMutableArray *loadedSubmodules = [[NSMutableArray alloc] initWithCapacity:[lines count]]; + + for (NSString *submoduleLine in lines) { + if ([submoduleLine length] == 0) + continue; + PBGitSubmodule *submodule = [[PBGitSubmodule alloc] initWithRawSubmoduleStatusString:submoduleLine]; + [loadedSubmodules addObject:submodule]; + } + + NSMutableArray *groupedSubmodules = [[NSMutableArray alloc] init]; + for (PBGitSubmodule *submodule in loadedSubmodules) { + BOOL added = NO; + for (PBGitSubmodule *addedItem in groupedSubmodules) { + if ([[submodule path] hasPrefix:[addedItem path]]) { + [addedItem addSubmodule:submodule]; + added = YES; + } + } + if (!added) { + [groupedSubmodules addObject:submodule]; + } + } + + + self.submodules = loadedSubmodules; +} + +#pragma mark - +#pragma mark Actions + +- (void) addNewSubmodule { + //TODO implement +} + +- (void) initializeAllSubmodules { + NSArray *parameters = [NSArray arrayWithObjects:@"submodule", @"init", nil]; + PBCommand *initializeSubmodules = [[PBCommand alloc] initWithDisplayName:@"Initialize All Submodules" parameters:parameters repository:repository]; + initializeSubmodules.commandTitle = initializeSubmodules.displayName; + initializeSubmodules.commandDescription = @"Initializing submodules"; + [initializeSubmodules invoke]; + [initializeSubmodules release]; +} + +- (void) updateAllSubmodules { + NSArray *parameters = [NSArray arrayWithObjects:@"submodule", @"update", nil]; + PBCommand *initializeSubmodules = [[PBCommand alloc] initWithDisplayName:@"Update All Submodules" parameters:parameters repository:repository]; + initializeSubmodules.commandTitle = initializeSubmodules.displayName; + initializeSubmodules.commandDescription = @"Updating submodules"; + [initializeSubmodules invoke]; + [initializeSubmodules release]; +} + +- (NSArray *) menuItems { + NSMutableArray *items = [[NSMutableArray alloc] init]; + [items addObject:[[NSMenuItem alloc] initWithTitle:@"Add Submodule..." action:@selector(addNewSubmodule) keyEquivalent:@""]]; + [items addObject:[[NSMenuItem alloc] initWithTitle:@"Initialize All Submodules" action:@selector(initializeAllSubmodules) keyEquivalent:@""]]; + [items addObject:[[NSMenuItem alloc] initWithTitle:@"Update All Submodules" action:@selector(updateAllSubmodules) keyEquivalent:@""]]; + + for (NSMenuItem *item in items) { + [item setTarget:self]; + } + + return items; +} + +- (PBCommand *) defaultCommandForSubmodule:(PBGitSubmodule *) submodule { + return [self commandForOpeningSubmodule:submodule]; +} + +- (PBCommand *) commandForOpeningSubmodule:(PBGitSubmodule *) submodule { + if (!([submodule path] && [submodule submoduleState] != PBGitSubmoduleStateNotInitialized)) { + return nil; + } + NSString *repoPath = [repository workingDirectory]; + NSString *path = [repoPath stringByAppendingPathComponent:[submodule path]]; + + PBOpenDocumentCommand *command = [[PBOpenDocumentCommand alloc] initWithDocumentAbsolutePath:path]; + command.commandTitle = command.displayName; + command.commandDescription = @"Opening document"; + return [command autorelease]; +} + +- (BOOL) validateMenuItem:(NSMenuItem *)menuItem { + BOOL shouldBeEnabled = YES; + SEL action = [menuItem action]; + if (action == @selector(addNewSubmodule)) { + shouldBeEnabled = NO; + //TODO implementation missing + } else { + shouldBeEnabled = [self.submodules count] > 0; + } + return shouldBeEnabled; +} + +@end diff --git a/GitX.xcodeproj/project.pbxproj b/GitX.xcodeproj/project.pbxproj index 0d028b14b..3d0cd8300 100644 --- a/GitX.xcodeproj/project.pbxproj +++ b/GitX.xcodeproj/project.pbxproj @@ -26,7 +26,6 @@ 056438B70ED0C40B00985397 /* DetailViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 056438B60ED0C40B00985397 /* DetailViewTemplate.png */; }; 21025C1212947AB200D87200 /* sourceListAction.png in Resources */ = {isa = PBXBuildFile; fileRef = 21025C1012947AB200D87200 /* sourceListAction.png */; }; 21025C1312947AB200D87200 /* sourceListActionOver.png in Resources */ = {isa = PBXBuildFile; fileRef = 21025C1112947AB200D87200 /* sourceListActionOver.png */; }; - 21025CA0129487AC00D87200 /* GTScaledButtonControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 21025C0B12947A6200D87200 /* GTScaledButtonControl.m */; }; 21230CB11284B26A0046E5A1 /* PBGitMenuItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230CB01284B26A0046E5A1 /* PBGitMenuItem.m */; }; 21230D351284C5080046E5A1 /* PBGitStash.m in Sources */ = {isa = PBXBuildFile; fileRef = 21230D341284C5080046E5A1 /* PBGitStash.m */; }; 21230D821284D1CC0046E5A1 /* stash-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 21230D811284D1CC0046E5A1 /* stash-icon.png */; }; @@ -43,14 +42,11 @@ 21231220128735E90046E5A1 /* submodule-empty.png in Resources */ = {isa = PBXBuildFile; fileRef = 2123121D128735E90046E5A1 /* submodule-empty.png */; }; 2123138A128756ED0046E5A1 /* PBRemoteCommandFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 21231389128756ED0046E5A1 /* PBRemoteCommandFactory.m */; }; 212313B5128759C00046E5A1 /* PBOpenDocumentCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 212313B4128759C00046E5A1 /* PBOpenDocumentCommand.m */; }; - 21CF0AE3129C7BE00065B37C /* info-selected.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0ADD129C7BE00065B37C /* info-selected.tiff */; }; - 21CF0AE4129C7BE00065B37C /* info-selected-mouse.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0ADE129C7BE00065B37C /* info-selected-mouse.tiff */; }; - 21CF0AE5129C7BE00065B37C /* info-selected-hovered.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0ADF129C7BE00065B37C /* info-selected-hovered.tiff */; }; - 21CF0AE6129C7BE00065B37C /* info-normal.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0AE0129C7BE00065B37C /* info-normal.tiff */; }; - 21CF0AE7129C7BE00065B37C /* info-normal-mouse.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0AE1129C7BE00065B37C /* info-normal-mouse.tiff */; }; - 21CF0AE8129C7BE00065B37C /* info-normal-hovered.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 21CF0AE2129C7BE00065B37C /* info-normal-hovered.tiff */; }; + 217FF0B912A1CB3300785A65 /* PBStashController.m in Sources */ = {isa = PBXBuildFile; fileRef = 217FF0B312A1CB3300785A65 /* PBStashController.m */; }; + 217FF0BA12A1CB3300785A65 /* PBSubmoduleController.m in Sources */ = {isa = PBXBuildFile; fileRef = 217FF0B512A1CB3300785A65 /* PBSubmoduleController.m */; }; + 217FF0BB12A1CB3300785A65 /* PBGitResetController.m in Sources */ = {isa = PBXBuildFile; fileRef = 217FF0B712A1CB3300785A65 /* PBGitResetController.m */; }; + 217FF0BE12A1CB3E00785A65 /* PBRevealWithFinderCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 217FF0BC12A1CB3E00785A65 /* PBRevealWithFinderCommand.m */; }; 21CF0B24129C7ED90065B37C /* TrackableOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CF0B23129C7ED90065B37C /* TrackableOutlineView.m */; }; - 21E331E4129DBFB100C3BA6F /* GTOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 21E331E3129DBFB100C3BA6F /* GTOutlineView.m */; }; 3BC07F4C0ED5A5C5009A7768 /* HistoryViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BC07F4A0ED5A5C5009A7768 /* HistoryViewTemplate.png */; }; 3BC07F4D0ED5A5C5009A7768 /* CommitViewTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BC07F4B0ED5A5C5009A7768 /* CommitViewTemplate.png */; }; 47DBDB580E94EDE700671A1E /* DBPrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 47DBDB570E94EDE700671A1E /* DBPrefsWindowController.m */; }; @@ -272,8 +268,6 @@ 056438B60ED0C40B00985397 /* DetailViewTemplate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DetailViewTemplate.png; path = Images/DetailViewTemplate.png; sourceTree = ""; }; 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; - 21025C0A12947A6200D87200 /* GTScaledButtonControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTScaledButtonControl.h; sourceTree = ""; }; - 21025C0B12947A6200D87200 /* GTScaledButtonControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTScaledButtonControl.m; sourceTree = ""; }; 21025C1012947AB200D87200 /* sourceListAction.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = sourceListAction.png; sourceTree = ""; }; 21025C1112947AB200D87200 /* sourceListActionOver.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = sourceListActionOver.png; sourceTree = ""; }; 21025CA6129487C200D87200 /* defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = defs.h; sourceTree = ""; }; @@ -306,17 +300,17 @@ 21231389128756ED0046E5A1 /* PBRemoteCommandFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBRemoteCommandFactory.m; sourceTree = ""; }; 212313B3128759C00046E5A1 /* PBOpenDocumentCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBOpenDocumentCommand.h; sourceTree = ""; }; 212313B4128759C00046E5A1 /* PBOpenDocumentCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBOpenDocumentCommand.m; sourceTree = ""; }; - 21CF0ADD129C7BE00065B37C /* info-selected.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-selected.tiff"; sourceTree = ""; }; - 21CF0ADE129C7BE00065B37C /* info-selected-mouse.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-selected-mouse.tiff"; sourceTree = ""; }; - 21CF0ADF129C7BE00065B37C /* info-selected-hovered.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-selected-hovered.tiff"; sourceTree = ""; }; - 21CF0AE0129C7BE00065B37C /* info-normal.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-normal.tiff"; sourceTree = ""; }; - 21CF0AE1129C7BE00065B37C /* info-normal-mouse.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-normal-mouse.tiff"; sourceTree = ""; }; - 21CF0AE2129C7BE00065B37C /* info-normal-hovered.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "info-normal-hovered.tiff"; sourceTree = ""; }; + 217FF0B312A1CB3300785A65 /* PBStashController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBStashController.m; sourceTree = SOURCE_ROOT; }; + 217FF0B412A1CB3300785A65 /* PBStashController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBStashController.h; sourceTree = SOURCE_ROOT; }; + 217FF0B512A1CB3300785A65 /* PBSubmoduleController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBSubmoduleController.m; sourceTree = ""; }; + 217FF0B612A1CB3300785A65 /* PBSubmoduleController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBSubmoduleController.h; sourceTree = ""; }; + 217FF0B712A1CB3300785A65 /* PBGitResetController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitResetController.m; sourceTree = ""; }; + 217FF0B812A1CB3300785A65 /* PBGitResetController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitResetController.h; sourceTree = ""; }; + 217FF0BC12A1CB3E00785A65 /* PBRevealWithFinderCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBRevealWithFinderCommand.m; sourceTree = ""; }; + 217FF0BD12A1CB3E00785A65 /* PBRevealWithFinderCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBRevealWithFinderCommand.h; sourceTree = ""; }; 21CF0B22129C7ED90065B37C /* TrackableOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackableOutlineView.h; sourceTree = ""; }; 21CF0B23129C7ED90065B37C /* TrackableOutlineView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TrackableOutlineView.m; sourceTree = ""; }; 21CF0B36129C80100065B37C /* CellTrackingRect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CellTrackingRect.h; sourceTree = ""; }; - 21E331E2129DBFB100C3BA6F /* GTOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTOutlineView.h; path = /Volumes/CORESYSTEMS/git/gitx/GTOutlineView.h; sourceTree = ""; }; - 21E331E3129DBFB100C3BA6F /* GTOutlineView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTOutlineView.m; path = /Volumes/CORESYSTEMS/git/gitx/GTOutlineView.m; sourceTree = ""; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; @@ -658,6 +652,8 @@ 21230D991285524C0046E5A1 /* Commands */ = { isa = PBXGroup; children = ( + 217FF0BC12A1CB3E00785A65 /* PBRevealWithFinderCommand.m */, + 217FF0BD12A1CB3E00785A65 /* PBRevealWithFinderCommand.h */, 21230D9A128552720046E5A1 /* PBCommand.h */, 21230D9B128552720046E5A1 /* PBCommand.m */, 21230D9D128552FA0046E5A1 /* PBStashCommandFactory.h */, @@ -676,15 +672,7 @@ 21230ED41285ED760046E5A1 /* View */ = { isa = PBXGroup; children = ( - 21CF0ADD129C7BE00065B37C /* info-selected.tiff */, - 21CF0ADE129C7BE00065B37C /* info-selected-mouse.tiff */, - 21CF0ADF129C7BE00065B37C /* info-selected-hovered.tiff */, - 21CF0AE0129C7BE00065B37C /* info-normal.tiff */, - 21CF0AE1129C7BE00065B37C /* info-normal-mouse.tiff */, - 21CF0AE2129C7BE00065B37C /* info-normal-hovered.tiff */, 21025CA6129487C200D87200 /* defs.h */, - 21025C0A12947A6200D87200 /* GTScaledButtonControl.h */, - 21025C0B12947A6200D87200 /* GTScaledButtonControl.m */, 21230ED71285EDAF0046E5A1 /* PBArgumentPicker.h */, 21230ED81285EDAF0046E5A1 /* PBArgumentPicker.m */, 21CF0B22129C7ED90065B37C /* TrackableOutlineView.h */, @@ -697,6 +685,12 @@ 21230EDF1285EF880046E5A1 /* Controller */ = { isa = PBXGroup; children = ( + 217FF0B312A1CB3300785A65 /* PBStashController.m */, + 217FF0B412A1CB3300785A65 /* PBStashController.h */, + 217FF0B512A1CB3300785A65 /* PBSubmoduleController.m */, + 217FF0B612A1CB3300785A65 /* PBSubmoduleController.h */, + 217FF0B712A1CB3300785A65 /* PBGitResetController.m */, + 217FF0B812A1CB3300785A65 /* PBGitResetController.h */, 21230EE01285EFB20046E5A1 /* PBArgumentPickerController.h */, 21230EE11285EFB20046E5A1 /* PBArgumentPickerController.m */, ); @@ -706,8 +700,6 @@ 29B97314FDCFA39411CA2CEA /* GitTest */ = { isa = PBXGroup; children = ( - 21E331E2129DBFB100C3BA6F /* GTOutlineView.h */, - 21E331E3129DBFB100C3BA6F /* GTOutlineView.m */, F5886A080ED5D26B0066E74C /* SpeedTest */, 913D5E420E5563FD00CECEA2 /* cli */, D89E9B4C1218C22A0097A90B /* GitXScripting */, @@ -1344,12 +1336,6 @@ 21231220128735E90046E5A1 /* submodule-empty.png in Resources */, 21025C1212947AB200D87200 /* sourceListAction.png in Resources */, 21025C1312947AB200D87200 /* sourceListActionOver.png in Resources */, - 21CF0AE3129C7BE00065B37C /* info-selected.tiff in Resources */, - 21CF0AE4129C7BE00065B37C /* info-selected-mouse.tiff in Resources */, - 21CF0AE5129C7BE00065B37C /* info-selected-hovered.tiff in Resources */, - 21CF0AE6129C7BE00065B37C /* info-normal.tiff in Resources */, - 21CF0AE7129C7BE00065B37C /* info-normal-mouse.tiff in Resources */, - 21CF0AE8129C7BE00065B37C /* info-normal-hovered.tiff in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1511,9 +1497,11 @@ 212311DD12872BF20046E5A1 /* PBGitSubmodule.m in Sources */, 2123138A128756ED0046E5A1 /* PBRemoteCommandFactory.m in Sources */, 212313B5128759C00046E5A1 /* PBOpenDocumentCommand.m in Sources */, - 21025CA0129487AC00D87200 /* GTScaledButtonControl.m in Sources */, 21CF0B24129C7ED90065B37C /* TrackableOutlineView.m in Sources */, - 21E331E4129DBFB100C3BA6F /* GTOutlineView.m in Sources */, + 217FF0B912A1CB3300785A65 /* PBStashController.m in Sources */, + 217FF0BA12A1CB3300785A65 /* PBSubmoduleController.m in Sources */, + 217FF0BB12A1CB3300785A65 /* PBGitResetController.m in Sources */, + 217FF0BE12A1CB3E00785A65 /* PBRevealWithFinderCommand.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/PBGitRepository.h b/PBGitRepository.h index 85462fd0c..aeef8dfa5 100644 --- a/PBGitRepository.h +++ b/PBGitRepository.h @@ -12,6 +12,10 @@ #import "PBGitConfig.h" #import "PBGitRefish.h" +#import "PBStashController.h" +#import "PBGitResetController.h" +#import "PBSubmoduleController.h" + extern NSString* PBGitRepositoryErrorDomain; typedef enum branchFilterTypes { kGitXAllBranchesFilter = 0, @@ -53,9 +57,13 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { PBGitRevSpecifier *_headRef; // Caching PBGitSHA* _headSha; - NSArray *stashes; - NSArray *submodules; + PBStashController *stashController; + PBSubmoduleController *submoduleController; + PBGitResetController *resetController; } +@property (nonatomic, retain, readonly) PBStashController *stashController; +@property (nonatomic, retain, readonly) PBSubmoduleController *submoduleController; +@property (nonatomic, retain, readonly) PBGitResetController *resetController; - (void) cloneRepositoryToPath:(NSString *)path bare:(BOOL)isBare; - (void) beginAddRemote:(NSString *)remoteName forURL:(NSString *)remoteURL; @@ -93,7 +101,6 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { - (NSString *)gitIgnoreFilename; - (BOOL)isBareRepository; -- (void) reloadStashes; - (void) reloadRefs; - (void) addRef:(PBGitRef *)ref fromParameters:(NSArray *)params; - (void) lazyReload; @@ -132,6 +139,7 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { // for the scripting bridge - (void)findInModeScriptCommand:(NSScriptCommand *)command; +- (NSMenu *) menu; @property (assign) BOOL hasChanged; @property (readonly) PBGitWindowController *windowController; @@ -141,6 +149,4 @@ static NSString * PBStringFromBranchFilterType(PBGitXBranchFilterType type) { @property (assign) PBGitRevSpecifier *currentBranch; @property (assign) NSInteger currentBranchFilter; @property (retain) NSMutableDictionary* refs; -@property (readonly) NSArray *stashes; -@property (readonly) NSArray *submodules; @end diff --git a/PBGitRepository.m b/PBGitRepository.m index 23cc38004..d8f7ea451 100644 --- a/PBGitRepository.m +++ b/PBGitRepository.m @@ -27,18 +27,34 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; @interface PBGitRepository() -@property (nonatomic, retain) NSArray *stashes; -@property (nonatomic, retain) NSArray *submodules; @end @implementation PBGitRepository -@synthesize stashes; -@synthesize submodules; +@synthesize stashController; +@synthesize submoduleController; +@synthesize resetController; @synthesize revisionList, branches, currentBranch, refs, hasChanged, config; @synthesize currentBranchFilter; +- (NSMenu *) menu { + NSMenu *menu = [[NSMenu alloc] init]; + NSMutableArray *items = [[NSMutableArray alloc] init]; + [items addObjectsFromArray:[self.submoduleController menuItems]]; + [items addObject:[NSMenuItem separatorItem]]; + [items addObjectsFromArray:[self.stashController menu]]; + [items addObject:[NSMenuItem separatorItem]]; + [items addObjectsFromArray:[self.resetController menuItems]]; + + for (NSMenuItem *item in items) { + [menu addItem:item]; + } + + [menu setAutoenablesItems:YES]; + return menu; +} + - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError { if (outError) { @@ -146,6 +162,10 @@ - (void) setup [self reloadRefs]; currentBranchFilter = [PBGitDefaults branchFilter]; revisionList = [[PBGitHistoryList alloc] initWithRepository:self]; + + resetController = [[PBGitResetController alloc] initWithRepository:self]; + stashController = [[PBStashController alloc] initWithRepository:self]; + submoduleController = [[PBSubmoduleController alloc] initWithRepository:self]; } - (void)close @@ -258,42 +278,6 @@ - (void) addRef: (PBGitRef *) ref fromParameters: (NSArray *) components [refs setObject:[NSMutableArray arrayWithObject:ref] forKey:sha]; } -- (void) reloadStashes { - NSArray *arguments = [NSArray arrayWithObjects:@"stash", @"list", nil]; - NSString *output = [self outputInWorkdirForArguments:arguments]; - NSArray *lines = [output componentsSeparatedByString:@"\n"]; - - NSMutableArray *loadedStashes = [[NSMutableArray alloc] initWithCapacity:[lines count]]; - - for (NSString *stashLine in lines) { - if ([stashLine length] == 0) - continue; - PBGitStash *stash = [[PBGitStash alloc] initWithRawStashLine:stashLine]; - [loadedStashes addObject:stash]; - [stash release]; - } - - self.stashes = loadedStashes; - [loadedStashes release]; -} - -- (void) reloadSubmodules { - - NSArray *arguments = [NSArray arrayWithObjects:@"submodule", @"status", @"--recursive", nil]; - NSString *output = [self outputInWorkdirForArguments:arguments]; - NSArray *lines = [output componentsSeparatedByString:@"\n"]; - - NSMutableArray *loadedSubmodules = [[NSMutableArray alloc] initWithCapacity:[lines count]]; - - for (NSString *submoduleLine in lines) { - if ([submoduleLine length] == 0) - continue; - PBGitSubmodule *submodule = [[PBGitSubmodule alloc] initWithRawSubmoduleStatusString:submoduleLine]; - [loadedSubmodules addObject:submodule]; - } - self.submodules = loadedSubmodules; -} - - (void) reloadRefs { _headRef = nil; @@ -328,8 +312,8 @@ - (void) reloadRefs [self willChangeValueForKey:@"refs"]; [self didChangeValueForKey:@"refs"]; - [self reloadStashes]; - [self reloadSubmodules]; + [self.stashController reload]; + [self.submoduleController reload]; [[[self windowController] window] setTitle:[self displayName]]; } diff --git a/PBGitSidebarController.m b/PBGitSidebarController.m index daa433747..87f7a7ac1 100644 --- a/PBGitSidebarController.m +++ b/PBGitSidebarController.m @@ -61,8 +61,8 @@ - (void)awakeFromNib [repository addObserver:self forKeyPath:@"currentBranch" options:0 context:@"currentBranchChange"]; [repository addObserver:self forKeyPath:@"branches" options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) context:@"branchesModified"]; - [repository addObserver:self forKeyPath:@"stashes" options:NSKeyValueObservingOptionNew context:kObservingContextStashes]; - [repository addObserver:self forKeyPath:@"submodules" options:NSKeyValueObservingOptionNew context:kObservingContextSubmodules]; + [repository addObserver:self forKeyPath:@"stashController.stashes" options:NSKeyValueObservingOptionNew context:kObservingContextStashes]; + [repository addObserver:self forKeyPath:@"submoduleController.submodules" options:NSKeyValueObservingOptionNew context:kObservingContextSubmodules]; [self menuNeedsUpdate:[actionButton menu]]; @@ -80,8 +80,8 @@ - (void)closeView [repository removeObserver:self forKeyPath:@"currentBranch"]; [repository removeObserver:self forKeyPath:@"branches"]; - [repository removeObserver:self forKeyPath:@"stashes"]; - [repository removeObserver:self forKeyPath:@"submodules"]; + [repository removeObserver:self forKeyPath:@"stashController.stashes"]; + [repository removeObserver:self forKeyPath:@"submoduleController.submodules"]; [super closeView]; } @@ -301,6 +301,7 @@ - (BOOL) outlineView:(NSOutlineView *)outlineView shouldShowOutlineCellForItem:( - (void)populateList { PBSourceViewItem *project = [PBSourceViewItem groupItemWithTitle:[repository projectName]]; + project.showsActionButton = YES; project.isUncollapsible = YES; stage = [PBGitSVStageItem stageItem]; @@ -308,15 +309,11 @@ - (void)populateList branches = [PBSourceViewItem groupItemWithTitle:@"Branches"]; - branches.showsActionButton = YES; remotes = [PBSourceViewItem groupItemWithTitle:@"Remotes"]; - remotes.showsActionButton = YES; tags = [PBSourceViewItem groupItemWithTitle:@"Tags"]; others = [PBSourceViewItem groupItemWithTitle:@"Other"]; stashes = [PBSourceViewItem groupItemWithTitle:@"Stashes"]; - stashes.showsActionButton = YES; submodules = [PBSourceViewItem groupItemWithTitle:@"Submodules"]; - submodules.showsActionButton = YES; for (PBGitRevSpecifier *rev in repository.branches) [self addRevSpec:rev]; @@ -395,12 +392,18 @@ - (NSMenuItem *) actionIconItem - (NSMenu *) menuForRow:(NSInteger)row { + if (row == 0) { + return [historyViewController.repository menu]; + } PBSourceViewItem *viewItem = [sourceView itemAtRow:row]; if ([viewItem isKindOfClass:[PBGitMenuItem class]] || [[viewItem title] isEqualToString:@"STASHES"]) { - PBGitMenuItem *stashItem = nil;//(PBGitMenuItem *) viewItem; + PBGitMenuItem *stashItem = (PBGitMenuItem *) viewItem; NSMutableArray *commands = [[NSMutableArray alloc] init]; [commands addObjectsFromArray:[PBStashCommandFactory commandsForObject:[stashItem sourceObject] repository:historyViewController.repository]]; [commands addObjectsFromArray:[PBRemoteCommandFactory commandsForObject:[stashItem sourceObject] repository:historyViewController.repository]]; + if (!commands) { + return nil; + } NSMenu *menu = [[NSMenu alloc] init]; [menu setAutoenablesItems:NO]; for (PBCommand *command in commands) { @@ -408,13 +411,6 @@ - (NSMenu *) menuForRow:(NSInteger)row [menu addItem:item]; [item release]; } - [menu addItem:[[NSMenuItem alloc] initWithTitle:@"hello" action:@selector(hello:) keyEquivalent:@""]]; - if ([[viewItem title] isEqualToString:@"STASHES"]){ - NSEvent *mouseEvent = [NSEvent mouseEventWithType:NSLeftMouseDown location:[NSEvent mouseLocation] modifierFlags:0 timestamp:[NSDate timeIntervalSinceReferenceDate] windowNumber:0 context:nil eventNumber:0 clickCount:1 pressure:0.1]; - NSPoint conv = [sourceView convertPoint:[mouseEvent locationInWindow] fromView:nil]; - [menu popUpMenuPositioningItem:nil atLocation:conv inView:sourceView]; - return nil; - } return menu; } diff --git a/PBStashController.h b/PBStashController.h new file mode 100644 index 000000000..f6f6a6022 --- /dev/null +++ b/PBStashController.h @@ -0,0 +1,31 @@ +// +// PBStashController.h +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright (c) 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "PBGitStash.h" + +@class PBGitRepository; + +@interface PBStashController : NSObject { + NSArray *stashes; +@private + PBGitRepository *repository; +} +@property (nonatomic, retain, readonly) NSArray *stashes; + +- (id) initWithRepository:(PBGitRepository *) repo; + +- (void) reload; + +- (NSArray *) menu; + +// actions +- (void) stashLocalChanges; +- (void) clearAllStashes; + +@end diff --git a/PBStashController.m b/PBStashController.m new file mode 100644 index 000000000..eccde18c8 --- /dev/null +++ b/PBStashController.m @@ -0,0 +1,110 @@ +// +// PBStashController.m +// GitX +// +// Created by Tomasz Krasnyk on 10-11-27. +// Copyright (c) 2010 __MyCompanyName__. All rights reserved. +// + +#import "PBStashController.h" +#import "PBGitRepository.h" +#import "PBCommand.h" +#import "PBCommandWithParameter.h" + +static NSString * const kCommandName = @"stash"; + +@interface PBStashController() +@property (nonatomic, retain) NSArray *stashes; +@end + + + +@implementation PBStashController +@synthesize stashes; + +- (id) initWithRepository:(PBGitRepository *) repo { + if (self = [super init]){ + repository = [repo retain]; + } + return self; +} + +- (void)dealloc { + [repository release]; + [stashes release]; + [super dealloc]; +} + +- (void) reload { + NSArray *arguments = [NSArray arrayWithObjects:kCommandName, @"list", nil]; + NSString *output = [repository outputInWorkdirForArguments:arguments]; + NSArray *lines = [output componentsSeparatedByString:@"\n"]; + + NSMutableArray *loadedStashes = [[NSMutableArray alloc] initWithCapacity:[lines count]]; + + for (NSString *stashLine in lines) { + if ([stashLine length] == 0) + continue; + PBGitStash *stash = [[PBGitStash alloc] initWithRawStashLine:stashLine]; + [loadedStashes addObject:stash]; + [stash release]; + } + + self.stashes = loadedStashes; + [loadedStashes release]; +} + +#pragma mark Actions + +- (void) stashLocalChanges { + NSArray *args = [NSArray arrayWithObject:kCommandName]; + PBCommand *command = [[PBCommand alloc] initWithDisplayName:@"Stash local changes..." parameters:args repository:repository]; + command.commandTitle = command.displayName; + command.commandDescription = @"Stashing local changes"; + + PBCommandWithParameter *cmd = [[PBCommandWithParameter alloc] initWithCommand:command parameterName:@"save" parameterDisplayName:@"Stash message (optional)"]; + [command release]; + + [cmd invoke]; + [cmd release]; +} + +- (void) clearAllStashes { + PBCommand *command = [[PBCommand alloc] initWithDisplayName:@"Clear stashes" parameters:[NSArray arrayWithObjects:kCommandName, @"clear", nil] repository:repository]; + command.commandTitle = command.displayName; + command.commandDescription = @"Clearing stashes"; + [command invoke]; + [command release]; +} + +#pragma mark Menu + +- (NSArray *) menu { + NSMutableArray *array = [[NSMutableArray alloc] init]; + + NSMenuItem *stashChanges = [[NSMenuItem alloc] initWithTitle:@"Stash local changes..." action:@selector(stashLocalChanges) keyEquivalent:@""]; + [stashChanges setTarget:self]; + NSMenuItem *clearStashes = [[NSMenuItem alloc] initWithTitle:@"Clear stashes" action:@selector(clearAllStashes) keyEquivalent:@""]; + [clearStashes setTarget:self]; + + [array addObject:stashChanges]; + [array addObject:clearStashes]; + + return array; +} + +- (BOOL) validateMenuItem:(NSMenuItem *) item { + SEL action = [item action]; + BOOL shouldBeEnabled = YES; + + if (action == @selector(stashLocalChanges)) { + //TODO: check if we have unstaged changes + } else if (action == @selector(clearAllStashes)) { + shouldBeEnabled = [self.stashes count] > 0; + } + + return shouldBeEnabled; +} + + +@end