Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

329 lines (269 sloc) 10.627 kB
//
// PBLabelController.m
// GitX
//
// Created by Pieter de Bie on 21-10-08.
// Copyright 2008 Pieter de Bie. All rights reserved.
//
#import "PBRefController.h"
#import "PBGitRevisionCell.h"
#import "PBRefMenuItem.h"
@implementation PBRefController
- (void)awakeFromNib
{
[commitList registerForDraggedTypes:[NSArray arrayWithObject:@"PBGitRef"]];
[historyController addObserver:self forKeyPath:@"repository.branches" options:0 context:@"branchChange"];
[historyController addObserver:self forKeyPath:@"repository.currentBranch" options:0 context:@"currentBranchChange"];
[self updateBranchMenu];
[self selectCurrentBranch];
}
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([(NSString *)context isEqualToString: @"branchChange"]) {
[self updateBranchMenu];
}
else if ([(NSString *)context isEqualToString:@"currentBranchChange"]) {
[self selectCurrentBranch];
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void) removeRef:(PBRefMenuItem *) sender
{
NSString *ref_desc = [NSString stringWithFormat:@"%@ %@", [[sender ref] type], [[sender ref] shortName]];
NSString *question = [NSString stringWithFormat:@"Are you sure you want to remove the %@?", ref_desc];
int choice = NSRunAlertPanel([NSString stringWithFormat:@"Delete %@?", ref_desc], question, @"Delete", @"Cancel", nil);
// TODO: Use a non-modal alert here, so we don't block all the GitX windows
if(choice) {
int ret = 1;
[historyController.repository outputForArguments:[NSArray arrayWithObjects:@"update-ref", @"-d", [[sender ref] ref], nil] retValue: &ret];
if (ret) {
NSLog(@"Removing ref failed!");
return;
}
[historyController.repository removeBranch:[[PBGitRevSpecifier alloc] initWithRef:[sender ref]]];
[[sender commit] removeRef:[sender ref]];
[commitController rearrangeObjects];
}
}
- (void) checkoutRef:(PBRefMenuItem *)sender
{
int ret = 1;
[historyController.repository outputInWorkdirForArguments:[NSArray arrayWithObjects:@"checkout", [[sender ref] shortName], nil] retValue: &ret];
if (ret) {
[[historyController.repository windowController] showMessageSheet:@"Checking out branch failed" infoText:@"There was an error checking out the branch. Perhaps your working directory is not clean?"];
return;
}
[historyController.repository reloadRefs];
[commitController rearrangeObjects];
}
- (void) tagInfo:(PBRefMenuItem *)sender
{
NSString *message = [NSString stringWithFormat:@"Info for tag: %@", [[sender ref] shortName]];
int ret = 1;
NSString *info = [historyController.repository outputInWorkdirForArguments:[NSArray arrayWithObjects:@"tag", @"-n50", @"-l", [[sender ref] shortName], nil] retValue: &ret];
if (!ret) {
[[historyController.repository windowController] showMessageSheet:message infoText:info];
}
return;
}
- (NSArray *) menuItemsForRef:(PBGitRef *)ref commit:(PBGitCommit *)commit
{
return [PBRefMenuItem defaultMenuItemsForRef:ref commit:commit target:self];
}
# pragma mark Tableview delegate methods
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard
{
NSPoint location = [tv convertPointFromBase:[(PBCommitList *)tv mouseDownPoint]];
int row = [tv rowAtPoint:location];
int column = [tv columnAtPoint:location];
if (column != 0)
return NO;
PBGitRevisionCell *cell = (PBGitRevisionCell *)[tv preparedCellAtColumn:column row:row];
int index = [cell indexAtX:location.x];
if (index == -1)
return NO;
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:[NSArray arrayWithObjects:[NSNumber numberWithInt:row], [NSNumber numberWithInt:index], NULL]];
[pboard declareTypes:[NSArray arrayWithObject:@"PBGitRef"] owner:self];
[pboard setData:data forType:@"PBGitRef"];
return YES;
}
- (NSDragOperation)tableView:(NSTableView*)tv
validateDrop:(id <NSDraggingInfo>)info
proposedRow:(NSInteger)row
proposedDropOperation:(NSTableViewDropOperation)operation
{
if (operation == NSTableViewDropAbove)
return NSDragOperationNone;
NSPasteboard *pboard = [info draggingPasteboard];
if ([pboard dataForType:@"PBGitRef"])
return NSDragOperationMove;
return NSDragOperationNone;
}
- (BOOL)tableView:(NSTableView *)aTableView
acceptDrop:(id <NSDraggingInfo>)info
row:(NSInteger)row
dropOperation:(NSTableViewDropOperation)operation
{
if (operation != NSTableViewDropOn)
return NO;
NSPasteboard *pboard = [info draggingPasteboard];
NSData *data = [pboard dataForType:@"PBGitRef"];
if (!data)
return NO;
NSArray *numbers = [NSKeyedUnarchiver unarchiveObjectWithData:data];
int oldRow = [[numbers objectAtIndex:0] intValue];
int oldRefIndex = [[numbers objectAtIndex:1] intValue];
PBGitCommit *oldCommit = [[commitController arrangedObjects] objectAtIndex: oldRow];
PBGitRef *ref = [[oldCommit refs] objectAtIndex:oldRefIndex];
PBGitCommit *dropCommit = [[commitController arrangedObjects] objectAtIndex:row];
int a = [[NSAlert alertWithMessageText:@"Change branch"
defaultButton:@"Change"
alternateButton:@"Cancel"
otherButton:nil
informativeTextWithFormat:@"Do you want to change branch\n\n\t'%@'\n\n to point to commit\n\n\t'%@'", [ref shortName], [dropCommit subject]] runModal];
if (a != NSAlertDefaultReturn)
return NO;
int retValue = 1;
[historyController.repository outputForArguments:[NSArray arrayWithObjects:@"update-ref", @"-mUpdate from GitX", [ref ref], [dropCommit realSha], NULL] retValue:&retValue];
if (retValue)
return NO;
[dropCommit addRef:ref];
[oldCommit removeRef:ref];
[commitController rearrangeObjects];
[aTableView needsToDrawRect:[aTableView rectOfRow:oldRow]];
return YES;
}
# pragma mark Add ref methods
-(void)addRef:(id)sender
{
[errorMessage setStringValue:@""];
[NSApp beginSheet:newBranchSheet
modalForWindow:[[historyController view] window]
modalDelegate:NULL
didEndSelector:NULL
contextInfo:NULL];
}
-(void)saveSheet:(id) sender
{
NSString *branchName = [@"refs/heads/" stringByAppendingString:[newBranchName stringValue]];
if ([[commitController selectedObjects] count] == 0)
return;
PBGitCommit *commit = [[commitController selectedObjects] objectAtIndex:0];
int retValue = 1;
[historyController.repository outputForArguments:[NSArray arrayWithObjects:@"check-ref-format", branchName, nil] retValue:&retValue];
if (retValue != 0) {
[errorMessage setStringValue:@"Invalid name"];
return;
}
retValue = 1;
[historyController.repository outputForArguments:[NSArray arrayWithObjects:@"update-ref", @"-mCreate branch from GitX", branchName, [commit realSha], @"0000000000000000000000000000000000000000", NULL] retValue:&retValue];
if (retValue)
{
[errorMessage setStringValue:@"Branch exists"];
return;
}
[historyController.repository addBranch:[[PBGitRevSpecifier alloc] initWithRef:[PBGitRef refFromString:branchName]]];
[self closeSheet:sender];
[commit addRef:[PBGitRef refFromString:branchName]];
[commitController rearrangeObjects];
}
-(void)closeSheet:(id) sender
{
[NSApp endSheet:newBranchSheet];
[newBranchName setStringValue:@""];
[newBranchSheet orderOut:self];
}
# pragma mark Branches menu
- (void) updateBranchMenu
{
if (!branchPopUp)
return;
NSMutableArray *localBranches = [NSMutableArray array];
NSMutableArray *remoteBranches = [NSMutableArray array];
NSMutableArray *tags = [NSMutableArray array];
NSMutableArray *other = [NSMutableArray array];
NSMenu *menu = [[NSMenu alloc] initWithTitle:@"Branch menu"];
for (PBGitRevSpecifier *rev in historyController.repository.branches)
{
if (![rev isSimpleRef])
{
[other addObject:rev];
continue;
}
NSString *ref = [rev simpleRef];
if ([ref hasPrefix:@"refs/heads"])
[localBranches addObject:rev];
else if ([ref hasPrefix:@"refs/tags"])
[tags addObject:rev];
else if ([ref hasPrefix:@"refs/remote"])
[remoteBranches addObject:rev];
}
for (PBGitRevSpecifier *rev in localBranches)
{
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[rev description] action:@selector(changeBranch:) keyEquivalent:@""];
[item setRepresentedObject:rev];
[item setTarget:self];
[menu addItem:item];
}
[menu addItem:[NSMenuItem separatorItem]];
// Remotes
NSMenu *remoteMenu = [[NSMenu alloc] initWithTitle:@"Remotes"];
NSMenu *currentMenu = NULL;
for (PBGitRevSpecifier *rev in remoteBranches)
{
NSString *ref = [rev simpleRef];
NSArray *components = [ref componentsSeparatedByString:@"/"];
NSString *remoteName = [components objectAtIndex:2];
NSString *branchName = [[components subarrayWithRange:NSMakeRange(3, [components count] - 3)] componentsJoinedByString:@"/"];
if (![[currentMenu title] isEqualToString:remoteName])
{
currentMenu = [[NSMenu alloc] initWithTitle:remoteName];
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:remoteName action:NULL keyEquivalent:@""];
[item setSubmenu:currentMenu];
[remoteMenu addItem:item];
}
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:branchName action:@selector(changeBranch:) keyEquivalent:@""];
[item setTarget:self];
[item setRepresentedObject:rev];
[currentMenu addItem:item];
}
NSMenuItem *remoteItem = [[NSMenuItem alloc] initWithTitle:@"Remotes" action:NULL keyEquivalent:@""];
[remoteItem setSubmenu:remoteMenu];
[menu addItem:remoteItem];
// Tags
NSMenu *tagMenu = [[NSMenu alloc] initWithTitle:@"Tags"];
for (PBGitRevSpecifier *rev in tags)
{
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[rev description] action:@selector(changeBranch:) keyEquivalent:@""];
[item setTarget:self];
[item setRepresentedObject:rev];
[tagMenu addItem:item];
}
NSMenuItem *tagItem = [[NSMenuItem alloc] initWithTitle:@"Tags" action:NULL keyEquivalent:@""];
[tagItem setSubmenu:tagMenu];
[menu addItem:tagItem];
// Others
[menu addItem:[NSMenuItem separatorItem]];
for (PBGitRevSpecifier *rev in other)
{
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[rev description] action:@selector(changeBranch:) keyEquivalent:@""];
[item setRepresentedObject:rev];
[item setTarget:self];
[menu addItem:item];
}
[[branchPopUp cell] setMenu: menu];
}
- (void) changeBranch:(NSMenuItem *)sender
{
PBGitRevSpecifier *rev = [sender representedObject];
historyController.repository.currentBranch = rev;
}
- (void) selectCurrentBranch
{
PBGitRevSpecifier *rev = historyController.repository.currentBranch;
if (rev)
[branchPopUp setTitle:[rev description]];
}
@end
Jump to Line
Something went wrong with that request. Please try again.