Files
gitx/PBGitRepository.m
T
Ciarán Walsh 12faa4a8f0 Avoid showing .git dirs in the recent documents menu.
Instead (for non-bare repos) add the directory above the .git dir.
2008-08-19 00:16:15 +02:00

206 lines
6.7 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// PBGitRepository.m
// GitTest
//
// Created by Pieter de Bie on 13-06-08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "PBGitRepository.h"
#import "PBGitCommit.h"
#import "PBDetailController.h"
#import "NSFileHandleExt.h"
#import "PBEasyPipe.h"
NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain";
@implementation PBGitRepository
@synthesize revisionList, branches, currentBranch;
static NSString* gitPath;
+ (void) initialize
{
// Try to find the path of the Git binary
char* path = getenv("GIT_PATH");
if (path != nil) {
gitPath = [NSString stringWithCString:path];
return;
}
// No explicit path. Try it with "which"
gitPath = [PBEasyPipe outputForCommand:@"/usr/bin/which" withArgs:[NSArray arrayWithObject:@"git"]];
if (gitPath.length > 0)
return;
// Still no path. Let's try some default locations.
NSArray* locations = [NSArray arrayWithObjects:@"/opt/local/bin/git", @"/sw/bin/git", @"/opt/git/bin/git", nil];
for (NSString* location in locations) {
if ([[NSFileManager defaultManager] fileExistsAtPath:location]) {
gitPath = location;
return;
}
}
NSLog(@"Could not find a git binary!");
}
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
if (outError) {
*outError = [NSError errorWithDomain:PBGitRepositoryErrorDomain
code:0
userInfo:[NSDictionary dictionaryWithObject:@"Reading files is not supported." forKey:NSLocalizedFailureReasonErrorKey]];
}
return NO;
}
+ (NSURL*)gitDirForURL:(NSURL*)repositoryURL;
{
NSString* repositoryPath = [repositoryURL path];
NSURL* gitDirURL = nil;
if ([repositoryPath hasSuffix:@".git"]) {
gitDirURL = [NSURL fileURLWithPath:repositoryPath];
} else {
// Use rev-parse to find the .git dir for the repository being opened
NSString* newPath = [PBEasyPipe outputForCommand:gitPath withArgs:[NSArray arrayWithObjects:@"rev-parse", @"--git-dir", nil] inDir:repositoryPath];
if ([newPath isEqualToString:@".git"]) {
gitDirURL = [NSURL fileURLWithPath:[repositoryPath stringByAppendingPathComponent:@".git"]];
} else if ([newPath length] > 0) {
gitDirURL = [NSURL fileURLWithPath:newPath];
}
}
return gitDirURL;
}
// For a given path inside a repository, return either the .git dir
// (for a bare repo) or the directory above the .git dir otherwise
+ (NSURL*)baseDirForURL:(NSURL*)repositoryURL;
{
NSURL* gitDirURL = [self gitDirForURL:repositoryURL];
NSString* repositoryPath = [gitDirURL path];
if (![[PBEasyPipe outputForCommand:gitPath withArgs:[NSArray arrayWithObjects:@"rev-parse", @"--is-bare-repository", nil] inDir:repositoryPath] isEqualToString:@"true"]) {
repositoryURL = [NSURL fileURLWithPath:[[repositoryURL path] stringByDeletingLastPathComponent]];
}
return repositoryURL;
}
- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError **)outError
{
BOOL success = NO;
if (![fileWrapper isDirectory]) {
if (outError) {
NSDictionary* userInfo = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Reading files is not supported.", [fileWrapper filename]]
forKey:NSLocalizedRecoverySuggestionErrorKey];
*outError = [NSError errorWithDomain:PBGitRepositoryErrorDomain code:0 userInfo:userInfo];
}
} else {
NSURL* gitDirURL = [PBGitRepository gitDirForURL:[self fileURL]];
if (gitDirURL) {
[self setFileURL:gitDirURL];
success = YES;
} else if (outError) {
NSDictionary* userInfo = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"%@ does not appear to be a git repository.", [fileWrapper filename]]
forKey:NSLocalizedRecoverySuggestionErrorKey];
*outError = [NSError errorWithDomain:PBGitRepositoryErrorDomain code:0 userInfo:userInfo];
}
if (success) {
[self readBranches];
[self readCurrentBranch];
revisionList = [[PBGitRevList alloc] initWithRepository:self andRevListParameters:[NSArray array]];
}
}
return success;
}
// The fileURL the document keeps is to the .git dir, but thats pretty
// useless for display in the window title bar, so we show the directory above
- (NSString*)displayName
{
NSString* displayName = self.fileURL.path.lastPathComponent;
if ([displayName isEqualToString:@".git"])
displayName = [self.fileURL.path stringByDeletingLastPathComponent].lastPathComponent;
return displayName;
}
// Overridden to create our custom window controller
- (void)makeWindowControllers
{
PBDetailController* controller = [[PBDetailController alloc] initWithRepository:self];
[self addWindowController:controller];
[controller release];
}
- (void) readBranches
{
NSString* output = [PBEasyPipe outputForCommand:gitPath withArgs:[NSArray arrayWithObjects:@"for-each-ref", @"refs/heads", nil] inDir: self.fileURL.path];
NSArray* lines = [output componentsSeparatedByString:@"\n"];
NSMutableArray* newBranches = [NSMutableArray array];
for (NSString* line in lines) {
NSString* substr = [line substringWithRange: NSMakeRange(40,19)];
if (![substr isEqualToString:@" commit\trefs/heads/"]) {
NSLog(@"Cannot parse branch %@. (%@)", line, substr);
continue;
}
NSString* branch = [line substringFromIndex:59];
[newBranches addObject: branch];
}
self.branches = newBranches;
}
- (void) readCurrentBranch
{
NSString* branch = [self parseSymbolicReference: @"HEAD"];
if (branch && [branch hasPrefix:@"refs/heads/"])
self.currentBranch = [branch substringFromIndex:11];
}
- (NSFileHandle*) handleForArguments:(NSArray *)args
{
NSString* gitDirArg = [@"--git-dir=" stringByAppendingString:self.fileURL.path];
NSMutableArray* arguments = [NSMutableArray arrayWithObject: gitDirArg];
[arguments addObjectsFromArray: args];
return [PBEasyPipe handleForCommand:gitPath withArgs:arguments];
}
- (NSFileHandle*) handleForCommand:(NSString *)cmd
{
NSArray* arguments = [cmd componentsSeparatedByString:@" "];
return [self handleForArguments:arguments];
}
- (NSString*) outputForCommand:(NSString *)cmd
{
NSArray* arguments = [cmd componentsSeparatedByString:@" "];
return [self outputForArguments: arguments];
}
- (NSString*) outputForArguments:(NSArray*) arguments
{
return [PBEasyPipe outputForCommand:gitPath withArgs:arguments inDir: self.fileURL.path];
}
- (NSString*) parseReference:(NSString *)reference
{
return [self outputForArguments:[NSArray arrayWithObjects: @"rev-parse", reference, nil]];
}
- (NSString*) parseSymbolicReference:(NSString*) reference
{
NSString* ref = [self outputForArguments:[NSArray arrayWithObjects: @"symbolic-ref", reference, nil]];
if ([ref hasPrefix:@"refs/"])
return ref;
return nil;
}
@end